* </refsect2>
*/
+/* Add flags here that should not be propagated to children. By default,
+ * all flags will be set on children (think prelight or active), but we
+ * might want to not do this for some.
+ */
+#define GTK_STATE_FLAGS_DONT_PROPAGATE (GTK_STATE_FLAG_FOCUSED)
+#define GTK_STATE_FLAGS_DO_PROPAGATE (~GTK_STATE_FLAGS_DONT_PROPAGATE)
+
#define WIDGET_CLASS(w) GTK_WIDGET_GET_CLASS (w)
#define INIT_PATH_SIZE (512)
guint mapped : 1;
guint visible : 1;
guint sensitive : 1;
- guint parent_sensitive : 1;
guint can_focus : 1;
guint has_focus : 1;
guint can_default : 1;
{
guint flags : 6;
guint operation : 2;
- guint parent_sensitive : 1;
guint use_forall : 1;
};
priv->parent = NULL;
priv->sensitive = TRUE;
- priv->parent_sensitive = TRUE;
priv->composite_child = composite_child_stack != 0;
priv->double_buffered = TRUE;
priv->redraw_on_alloc = TRUE;
* Since: 3.0
**/
void
-gtk_widget_queue_draw_region (GtkWidget *widget,
- cairo_region_t *region)
+gtk_widget_queue_draw_region (GtkWidget *widget,
+ const cairo_region_t *region)
{
GtkWidgetPrivate *priv;
GtkWidget *w;
}
}
+/* translate initial/final into start/end */
+static GtkAlign
+effective_align (GtkAlign align,
+ GtkTextDirection direction)
+{
+ switch (align)
+ {
+ case GTK_ALIGN_START:
+ return direction == GTK_TEXT_DIR_RTL ? GTK_ALIGN_END : GTK_ALIGN_START;
+ case GTK_ALIGN_END:
+ return direction == GTK_TEXT_DIR_RTL ? GTK_ALIGN_START : GTK_ALIGN_END;
+ default:
+ return align;
+ }
+}
+
static void
-adjust_for_align(GtkAlign align,
- gint *natural_size,
- gint *allocated_pos,
- gint *allocated_size)
+adjust_for_align (GtkAlign align,
+ gint *natural_size,
+ gint *allocated_pos,
+ gint *allocated_size)
{
switch (align)
{
{
adjust_for_margin (aux_info->margin.left,
aux_info->margin.right,
- minimum_size, natural_size,
- allocated_pos, allocated_size);
- adjust_for_align (aux_info->halign,
+ minimum_size, natural_size,
+ allocated_pos, allocated_size);
+ adjust_for_align (effective_align (aux_info->halign, gtk_widget_get_direction (widget)),
natural_size, allocated_pos, allocated_size);
}
else
{
adjust_for_margin (aux_info->margin.top,
aux_info->margin.bottom,
- minimum_size, natural_size,
- allocated_pos, allocated_size);
- adjust_for_align (aux_info->valign,
+ minimum_size, natural_size,
+ allocated_pos, allocated_size);
+ adjust_for_align (effective_align (aux_info->valign, GTK_TEXT_DIR_NONE),
natural_size, allocated_pos, allocated_size);
}
}
static void
gtk_widget_real_style_updated (GtkWidget *widget)
{
- if (gtk_widget_get_realized (widget))
+ GtkWidgetPrivate *priv = widget->priv;
+
+ if (priv->style != NULL &&
+ priv->style != gtk_widget_get_default_style ())
{
/* Trigger ::style-set for old
* widgets not listening to this
if (widget->priv->context)
{
- gtk_style_context_invalidate (widget->priv->context);
-
if (gtk_widget_get_realized (widget) &&
gtk_widget_get_has_window (widget))
gtk_style_context_set_background (widget->priv->context,
g_free (priv->name);
priv->name = new_name;
- if (priv->path)
- {
- guint pos;
-
- pos = gtk_widget_path_length (priv->path) - 1;
- gtk_widget_path_iter_set_name (priv->path, pos,
- priv->name);
- }
-
- if (priv->context)
- gtk_style_context_set_path (priv->context, priv->path);
+ gtk_widget_reset_style (widget);
g_object_notify (G_OBJECT (widget), "name");
}
data.operation = operation;
data.use_forall = FALSE;
- if (priv->parent)
- data.parent_sensitive = (gtk_widget_is_sensitive (priv->parent) != FALSE);
- else
- data.parent_sensitive = TRUE;
-
gtk_widget_propagate_state (widget, &data);
gtk_widget_queue_resize (widget);
flags = widget->priv->state_flags;
- if (!gtk_widget_is_sensitive (widget))
- flags |= GTK_STATE_FLAG_INSENSITIVE;
-
if (gtk_widget_has_focus (widget))
flags |= GTK_STATE_FLAG_FOCUSED;
data.use_forall = TRUE;
- if (priv->parent)
- data.parent_sensitive = gtk_widget_is_sensitive (priv->parent);
- else
- data.parent_sensitive = TRUE;
-
gtk_widget_propagate_state (widget, &data);
gtk_widget_queue_resize (widget);
* @widget: a #GtkWidget
*
* Returns the widget's effective sensitivity, which means
- * it is sensitive itself and also its parent widget is sensntive
+ * it is sensitive itself and also its parent widget is sensitive
*
* Returns: %TRUE if the widget is effectively sensitive
*
{
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
- return widget->priv->sensitive && widget->priv->parent_sensitive;
+ return !(widget->priv->state_flags & GTK_STATE_FLAG_INSENSITIVE);
}
static void
parent_flags = gtk_widget_get_state_flags (parent);
/* Merge both old state and current parent state,
- * We don't want the insensitive flag to propagate
- * to the new child though */
- data.flags = parent_flags & ~GTK_STATE_FLAG_INSENSITIVE;
+ * making sure to only propagate the right states */
+ data.flags = parent_flags & GTK_STATE_FLAGS_DO_PROPAGATE;
data.flags |= priv->state_flags;
data.operation = STATE_CHANGE_REPLACE;
- data.parent_sensitive = (gtk_widget_is_sensitive (parent) != FALSE);
data.use_forall = gtk_widget_is_sensitive (parent) != gtk_widget_is_sensitive (widget);
gtk_widget_propagate_state (widget, &data);
- gtk_widget_reset_rc_styles (widget);
+ gtk_widget_reset_style (widget);
g_signal_emit (widget, widget_signals[PARENT_SET], 0, NULL);
if (priv->parent->priv->anchored)
gtk_widget_queue_compute_expand (parent);
}
- if (widget->priv->context)
- {
- GdkScreen *screen;
-
- _gtk_widget_update_path (widget);
- gtk_style_context_set_path (widget->priv->context, widget->priv->path);
-
- screen = gtk_widget_get_screen (widget);
-
- if (screen)
- gtk_style_context_set_screen (widget->priv->context, screen);
- }
-
gtk_widget_pop_verify_invariants (widget);
}
void
gtk_widget_style_attach (GtkWidget *widget)
{
- GtkWidgetPrivate *priv;
-
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (gtk_widget_get_realized (widget));
-
- priv = widget->priv;
-
- priv->style = gtk_style_attach (priv->style, priv->window);
}
/**
* of a previous call to gtk_widget_set_style() and go back to
* the default style
*
- * Sets the #GtkStyle for a widget (@widget->style).
- *
- * You probably don't want to use this function; it interacts
- * badly with themes, because themes work by replacing the #GtkStyle.
- * Instead, use gtk_widget_modify_style().
+ * Used to set the #GtkStyle for a widget (@widget->style). Since
+ * GTK 3, this function does nothing, the passed in style is ignored.
*
* Deprecated:3.0: Use #GtkStyleContext instead
*/
void
gtk_widget_ensure_style (GtkWidget *widget)
{
- g_return_if_fail (GTK_IS_WIDGET (widget));
+ GtkWidgetPrivate *priv;
- if (!widget->priv->style ||
- widget->priv->style == gtk_widget_get_default_style ())
- {
- GtkStyle *style;
+ g_return_if_fail (GTK_IS_WIDGET (widget));
- if (widget->priv->style)
- g_object_unref (widget->priv->style);
+ priv = widget->priv;
- style = g_object_new (GTK_TYPE_STYLE,
- "context", gtk_widget_get_style_context (widget),
- NULL);
+ if (priv->style == gtk_widget_get_default_style ())
+ {
+ g_object_unref (priv->style);
- widget->priv->style = g_object_ref (style);
+ priv->style = NULL;
g_signal_emit (widget,
widget_signals[STYLE_SET],
0, NULL);
-
- g_object_unref (style);
}
}
GtkStyle*
gtk_widget_get_style (GtkWidget *widget)
{
+ GtkWidgetPrivate *priv;
+
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
- return widget->priv->style;
+ priv = widget->priv;
+
+ if (priv->style == NULL)
+ {
+ priv->style = g_object_new (GTK_TYPE_STYLE,
+ "context", gtk_widget_get_style_context (widget),
+ NULL);
+
+ }
+
+ return priv->style;
}
/**
{
if (old_screen != new_screen)
{
- GtkStyleContext *context;
+ GtkWidgetPrivate *priv = widget->priv;
if (old_screen)
{
_gtk_tooltip_hide (widget);
- context = gtk_widget_get_style_context (widget);
- gtk_style_context_set_screen (context, gtk_widget_get_screen (widget));
+ if (new_screen && priv->context)
+ gtk_style_context_set_screen (priv->context, new_screen);
g_signal_emit (widget, widget_signals[SCREEN_CHANGED], 0, old_screen);
}
static void
reset_style_recurse (GtkWidget *widget, gpointer data)
{
- if (widget->priv->context)
- {
- _gtk_widget_update_path (widget);
- gtk_style_context_set_path (widget->priv->context,
- widget->priv->path);
- }
+ _gtk_widget_update_path (widget);
if (GTK_IS_CONTAINER (widget))
gtk_container_forall (GTK_CONTAINER (widget),
GtkIconSize size,
const gchar *detail)
{
+ gtk_widget_ensure_style (widget);
+
return gtk_widget_render_icon_pixbuf (widget, stock_id, size);
}
gtk_grab_remove (widget);
- g_object_unref (priv->style);
+ if (priv->style)
+ g_object_unref (priv->style);
priv->style = gtk_widget_get_default_style ();
g_object_ref (priv->style);
}
if (priv->context)
g_object_unref (priv->context);
+ _gtk_widget_free_cached_sizes (widget);
+
if (g_object_is_floating (object))
g_warning ("A floating object was finalized. This means that someone\n"
"called g_object_unref() on an object that had only a floating\n"
priv->window = gtk_widget_get_parent_window (widget);
g_object_ref (priv->window);
}
- priv->style = gtk_style_attach (priv->style, priv->window);
}
/*****************************************
(GtkCallback) gtk_widget_unrealize,
NULL);
- gtk_style_detach (priv->style);
if (gtk_widget_get_has_window (widget))
{
gdk_window_set_user_data (priv->window, NULL);
old_state = gtk_widget_get_state (widget);
- if (!priv->parent_sensitive)
- old_flags |= GTK_STATE_FLAG_INSENSITIVE;
-
- priv->parent_sensitive = data->parent_sensitive;
-
switch (data->operation)
{
case STATE_CHANGE_REPLACE:
break;
}
+ /* make insensitivity unoverridable */
+ if (!priv->sensitive)
+ priv->state_flags |= GTK_STATE_FLAG_INSENSITIVE;
+
if (gtk_widget_is_focus (widget) && !gtk_widget_is_sensitive (widget))
{
GtkWidget *window;
gtk_window_set_focus (GTK_WINDOW (window), NULL);
}
- new_flags = gtk_widget_get_state_flags (widget);
+ new_flags = priv->state_flags;
if (old_flags != new_flags)
{
if (GTK_IS_CONTAINER (widget))
{
- data->parent_sensitive = gtk_widget_is_sensitive (widget);
+ GtkStateData child_data = *data;
- /* Do not propagate focused state further */
- data->flags &= ~GTK_STATE_FLAG_FOCUSED;
+ /* Make sure to only propate the right states further */
+ child_data.flags &= GTK_STATE_FLAGS_DO_PROPAGATE;
- if (data->use_forall)
+ if (child_data.use_forall)
gtk_container_forall (GTK_CONTAINER (widget),
(GtkCallback) gtk_widget_propagate_state,
- data);
+ &child_data);
else
gtk_container_foreach (GTK_CONTAINER (widget),
(GtkCallback) gtk_widget_propagate_state,
- data);
+ &child_data);
}
/* Trigger state change transitions for the widget */
static GtkSizeRequestMode
gtk_widget_real_get_request_mode (GtkWidget *widget)
{
- /* By default widgets are height-for-width. */
- return GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
+ /* By default widgets dont trade size at all. */
+ return GTK_SIZE_REQUEST_CONSTANT_SIZE;
}
static void
GtkStyleContext *
gtk_widget_get_style_context (GtkWidget *widget)
{
+ GtkWidgetPrivate *priv;
+ GtkWidgetPath *path;
+
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
- if (G_UNLIKELY (!widget->priv->context))
+ priv = widget->priv;
+
+ /* updates style context if it exists already */
+ path = gtk_widget_get_path (widget);
+
+ if (G_UNLIKELY (priv->context == NULL))
{
GdkScreen *screen;
- widget->priv->context = g_object_new (GTK_TYPE_STYLE_CONTEXT,
- "direction", gtk_widget_get_direction (widget),
- NULL);
+ priv->context = g_object_new (GTK_TYPE_STYLE_CONTEXT,
+ "direction", gtk_widget_get_direction (widget),
+ NULL);
g_signal_connect (widget->priv->context, "changed",
G_CALLBACK (style_context_changed), widget);
screen = gtk_widget_get_screen (widget);
if (screen)
- gtk_style_context_set_screen (widget->priv->context, screen);
+ gtk_style_context_set_screen (priv->context, screen);
- _gtk_widget_update_path (widget);
- gtk_style_context_set_path (widget->priv->context,
- widget->priv->path);
- }
- else
- {
- /* Force widget path regeneration if needed, the
- * context will be updated within this function.
- */
- gtk_widget_get_path (widget);
+ gtk_style_context_set_path (priv->context, path);
}
return widget->priv->context;