1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
31 #include <gobject/gvaluecollector.h>
32 #include "gtkmarshalers.h"
35 #include "gtkspinbutton.h"
37 #include "gtkwidget.h"
38 #include "gtkthemes.h"
39 #include "gtkiconfactory.h"
40 #include "gtksettings.h" /* _gtk_settings_parse_convert() */
42 #include "gtkspinner.h"
47 * @Short_description: An object that hold style information for widgets
50 * A #GtkStyle object encapsulates the information that provides the look and
51 * feel for a widget. Each #GtkWidget has an associated #GTkStyle object that
52 * is used when rendering that widget. Also, a #GtkStyle holds information for
53 * the five possible widget states though not every widget supports all five
54 * states; see #GtkStateType.
56 * Usually the #GtkStyle for a widget is the same as the default style that is
57 * set by GTK+ and modified the theme engine.
59 * Usually applications should not need to use or modify the #GtkStyle of their
64 #define LIGHTNESS_MULT 1.3
65 #define DARKNESS_MULT 0.7
67 /* --- typedefs & structures --- */
74 #define GTK_STYLE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_STYLE, GtkStylePrivate))
76 typedef struct _GtkStylePrivate GtkStylePrivate;
78 struct _GtkStylePrivate {
82 /* --- prototypes --- */
83 static void gtk_style_finalize (GObject *object);
84 static void gtk_style_realize (GtkStyle *style,
85 GdkColormap *colormap);
86 static void gtk_style_real_realize (GtkStyle *style);
87 static void gtk_style_real_unrealize (GtkStyle *style);
88 static void gtk_style_real_copy (GtkStyle *style,
90 static void gtk_style_real_set_background (GtkStyle *style,
92 GtkStateType state_type);
93 static GtkStyle *gtk_style_real_clone (GtkStyle *style);
94 static void gtk_style_real_init_from_rc (GtkStyle *style,
95 GtkRcStyle *rc_style);
96 static GdkPixbuf *gtk_default_render_icon (GtkStyle *style,
97 const GtkIconSource *source,
98 GtkTextDirection direction,
102 const gchar *detail);
103 static void gtk_default_draw_hline (GtkStyle *style,
105 GtkStateType state_type,
111 static void gtk_default_draw_vline (GtkStyle *style,
113 GtkStateType state_type,
120 static void gtk_default_draw_shadow (GtkStyle *style,
122 GtkStateType state_type,
123 GtkShadowType shadow_type,
131 static void gtk_default_draw_arrow (GtkStyle *style,
133 GtkStateType state_type,
134 GtkShadowType shadow_type,
138 GtkArrowType arrow_type,
144 static void gtk_default_draw_diamond (GtkStyle *style,
146 GtkStateType state_type,
147 GtkShadowType shadow_type,
155 static void gtk_default_draw_box (GtkStyle *style,
157 GtkStateType state_type,
158 GtkShadowType shadow_type,
166 static void gtk_default_draw_flat_box (GtkStyle *style,
168 GtkStateType state_type,
169 GtkShadowType shadow_type,
177 static void gtk_default_draw_check (GtkStyle *style,
179 GtkStateType state_type,
180 GtkShadowType shadow_type,
188 static void gtk_default_draw_option (GtkStyle *style,
190 GtkStateType state_type,
191 GtkShadowType shadow_type,
199 static void gtk_default_draw_tab (GtkStyle *style,
201 GtkStateType state_type,
202 GtkShadowType shadow_type,
210 static void gtk_default_draw_shadow_gap (GtkStyle *style,
212 GtkStateType state_type,
213 GtkShadowType shadow_type,
221 GtkPositionType gap_side,
224 static void gtk_default_draw_box_gap (GtkStyle *style,
226 GtkStateType state_type,
227 GtkShadowType shadow_type,
235 GtkPositionType gap_side,
238 static void gtk_default_draw_extension (GtkStyle *style,
240 GtkStateType state_type,
241 GtkShadowType shadow_type,
249 GtkPositionType gap_side);
250 static void gtk_default_draw_focus (GtkStyle *style,
252 GtkStateType state_type,
260 static void gtk_default_draw_slider (GtkStyle *style,
262 GtkStateType state_type,
263 GtkShadowType shadow_type,
271 GtkOrientation orientation);
272 static void gtk_default_draw_handle (GtkStyle *style,
274 GtkStateType state_type,
275 GtkShadowType shadow_type,
283 GtkOrientation orientation);
284 static void gtk_default_draw_expander (GtkStyle *style,
286 GtkStateType state_type,
292 GtkExpanderStyle expander_style);
293 static void gtk_default_draw_layout (GtkStyle *style,
295 GtkStateType state_type,
302 PangoLayout *layout);
303 static void gtk_default_draw_resize_grip (GtkStyle *style,
305 GtkStateType state_type,
314 static void gtk_default_draw_spinner (GtkStyle *style,
316 GtkStateType state_type,
326 static void rgb_to_hls (gdouble *r,
329 static void hls_to_rgb (gdouble *h,
333 static void style_unrealize_cursors (GtkStyle *style);
336 * Data for default check and radio buttons
339 static const GtkRequisition default_option_indicator_size = { 7, 13 };
340 static const GtkBorder default_option_indicator_spacing = { 7, 5, 2, 2 };
342 #define GTK_GRAY 0xdcdc, 0xdada, 0xd5d5
343 #define GTK_DARK_GRAY 0xc4c4, 0xc2c2, 0xbdbd
344 #define GTK_LIGHT_GRAY 0xeeee, 0xebeb, 0xe7e7
345 #define GTK_WHITE 0xffff, 0xffff, 0xffff
346 #define GTK_BLUE 0x4b4b, 0x6969, 0x8383
347 #define GTK_VERY_DARK_GRAY 0x9c9c, 0x9a9a, 0x9494
348 #define GTK_BLACK 0x0000, 0x0000, 0x0000
349 #define GTK_WEAK_GRAY 0x7530, 0x7530, 0x7530
351 /* --- variables --- */
352 static const GdkColor gtk_default_normal_fg = { 0, GTK_BLACK };
353 static const GdkColor gtk_default_active_fg = { 0, GTK_BLACK };
354 static const GdkColor gtk_default_prelight_fg = { 0, GTK_BLACK };
355 static const GdkColor gtk_default_selected_fg = { 0, GTK_WHITE };
356 static const GdkColor gtk_default_insensitive_fg = { 0, GTK_WEAK_GRAY };
358 static const GdkColor gtk_default_normal_bg = { 0, GTK_GRAY };
359 static const GdkColor gtk_default_active_bg = { 0, GTK_DARK_GRAY };
360 static const GdkColor gtk_default_prelight_bg = { 0, GTK_LIGHT_GRAY };
361 static const GdkColor gtk_default_selected_bg = { 0, GTK_BLUE };
362 static const GdkColor gtk_default_insensitive_bg = { 0, GTK_GRAY };
363 static const GdkColor gtk_default_selected_base = { 0, GTK_BLUE };
364 static const GdkColor gtk_default_active_base = { 0, GTK_VERY_DARK_GRAY };
366 /* --- signals --- */
367 static guint realize_signal = 0;
368 static guint unrealize_signal = 0;
370 G_DEFINE_TYPE (GtkStyle, gtk_style, G_TYPE_OBJECT)
372 /* --- functions --- */
375 * _gtk_style_init_for_settings:
376 * @style: a #GtkStyle
377 * @settings: a #GtkSettings
379 * Initializes the font description in @style according to the default
380 * font name of @settings. This is called for gtk_style_new() with
381 * the settings for the default screen (if any); if we are creating
382 * a style for a particular screen, we then call it again in a
383 * location where we know the correct settings.
384 * The reason for this is that gtk_rc_style_create_style() doesn't
385 * take the screen for an argument.
388 _gtk_style_init_for_settings (GtkStyle *style,
389 GtkSettings *settings)
391 const gchar *font_name = _gtk_rc_context_get_default_font_name (settings);
393 if (style->font_desc)
394 pango_font_description_free (style->font_desc);
396 style->font_desc = pango_font_description_from_string (font_name);
398 if (!pango_font_description_get_family (style->font_desc))
400 g_warning ("Default font does not have a family set");
401 pango_font_description_set_family (style->font_desc, "Sans");
403 if (pango_font_description_get_size (style->font_desc) <= 0)
405 g_warning ("Default font does not have a positive size");
406 pango_font_description_set_size (style->font_desc, 10 * PANGO_SCALE);
411 gtk_style_init (GtkStyle *style)
415 GtkSettings *settings = gtk_settings_get_default ();
418 _gtk_style_init_for_settings (style, settings);
420 style->font_desc = pango_font_description_from_string ("Sans 10");
422 style->attach_count = 0;
423 style->colormap = NULL;
426 style->black.red = 0;
427 style->black.green = 0;
428 style->black.blue = 0;
430 style->white.red = 65535;
431 style->white.green = 65535;
432 style->white.blue = 65535;
434 style->fg[GTK_STATE_NORMAL] = gtk_default_normal_fg;
435 style->fg[GTK_STATE_ACTIVE] = gtk_default_active_fg;
436 style->fg[GTK_STATE_PRELIGHT] = gtk_default_prelight_fg;
437 style->fg[GTK_STATE_SELECTED] = gtk_default_selected_fg;
438 style->fg[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_fg;
440 style->bg[GTK_STATE_NORMAL] = gtk_default_normal_bg;
441 style->bg[GTK_STATE_ACTIVE] = gtk_default_active_bg;
442 style->bg[GTK_STATE_PRELIGHT] = gtk_default_prelight_bg;
443 style->bg[GTK_STATE_SELECTED] = gtk_default_selected_bg;
444 style->bg[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_bg;
446 for (i = 0; i < 4; i++)
448 style->text[i] = style->fg[i];
449 style->base[i] = style->white;
452 style->base[GTK_STATE_SELECTED] = gtk_default_selected_base;
453 style->text[GTK_STATE_SELECTED] = style->white;
454 style->base[GTK_STATE_ACTIVE] = gtk_default_active_base;
455 style->text[GTK_STATE_ACTIVE] = style->white;
456 style->base[GTK_STATE_INSENSITIVE] = gtk_default_prelight_bg;
457 style->text[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_fg;
459 for (i = 0; i < 5; i++)
460 style->bg_pixmap[i] = NULL;
462 style->rc_style = NULL;
464 style->xthickness = 2;
465 style->ythickness = 2;
467 style->property_cache = NULL;
471 gtk_style_class_init (GtkStyleClass *klass)
473 GObjectClass *object_class = G_OBJECT_CLASS (klass);
475 object_class->finalize = gtk_style_finalize;
477 klass->clone = gtk_style_real_clone;
478 klass->copy = gtk_style_real_copy;
479 klass->init_from_rc = gtk_style_real_init_from_rc;
480 klass->realize = gtk_style_real_realize;
481 klass->unrealize = gtk_style_real_unrealize;
482 klass->set_background = gtk_style_real_set_background;
483 klass->render_icon = gtk_default_render_icon;
485 klass->draw_hline = gtk_default_draw_hline;
486 klass->draw_vline = gtk_default_draw_vline;
487 klass->draw_shadow = gtk_default_draw_shadow;
488 klass->draw_arrow = gtk_default_draw_arrow;
489 klass->draw_diamond = gtk_default_draw_diamond;
490 klass->draw_box = gtk_default_draw_box;
491 klass->draw_flat_box = gtk_default_draw_flat_box;
492 klass->draw_check = gtk_default_draw_check;
493 klass->draw_option = gtk_default_draw_option;
494 klass->draw_tab = gtk_default_draw_tab;
495 klass->draw_shadow_gap = gtk_default_draw_shadow_gap;
496 klass->draw_box_gap = gtk_default_draw_box_gap;
497 klass->draw_extension = gtk_default_draw_extension;
498 klass->draw_focus = gtk_default_draw_focus;
499 klass->draw_slider = gtk_default_draw_slider;
500 klass->draw_handle = gtk_default_draw_handle;
501 klass->draw_expander = gtk_default_draw_expander;
502 klass->draw_layout = gtk_default_draw_layout;
503 klass->draw_resize_grip = gtk_default_draw_resize_grip;
504 klass->draw_spinner = gtk_default_draw_spinner;
506 g_type_class_add_private (object_class, sizeof (GtkStylePrivate));
510 * @style: the object which received the signal
512 * Emitted when the style has been initialized for a particular
513 * colormap and depth. Connecting to this signal is probably seldom
514 * useful since most of the time applications and widgets only
515 * deal with styles that have been already realized.
519 realize_signal = g_signal_new (I_("realize"),
520 G_TYPE_FROM_CLASS (object_class),
522 G_STRUCT_OFFSET (GtkStyleClass, realize),
524 _gtk_marshal_VOID__VOID,
527 * GtkStyle::unrealize:
528 * @style: the object which received the signal
530 * Emitted when the aspects of the style specific to a particular colormap
531 * and depth are being cleaned up. A connection to this signal can be useful
532 * if a widget wants to cache objects as object data on #GtkStyle.
533 * This signal provides a convenient place to free such cached objects.
537 unrealize_signal = g_signal_new (I_("unrealize"),
538 G_TYPE_FROM_CLASS (object_class),
540 G_STRUCT_OFFSET (GtkStyleClass, unrealize),
542 _gtk_marshal_VOID__VOID,
547 clear_property_cache (GtkStyle *style)
549 if (style->property_cache)
553 for (i = 0; i < style->property_cache->len; i++)
555 PropertyValue *node = &g_array_index (style->property_cache, PropertyValue, i);
557 g_param_spec_unref (node->pspec);
558 g_value_unset (&node->value);
560 g_array_free (style->property_cache, TRUE);
561 style->property_cache = NULL;
566 gtk_style_finalize (GObject *object)
568 GtkStyle *style = GTK_STYLE (object);
569 GtkStylePrivate *priv = GTK_STYLE_GET_PRIVATE (style);
571 g_return_if_fail (style->attach_count == 0);
573 clear_property_cache (style);
575 /* All the styles in the list have the same
576 * style->styles pointer. If we delete the
577 * *first* style from the list, we need to update
578 * the style->styles pointers from all the styles.
579 * Otherwise we simply remove the node from
584 if (style->styles->data != style)
585 style->styles = g_slist_remove (style->styles, style);
588 GSList *tmp_list = style->styles->next;
592 GTK_STYLE (tmp_list->data)->styles = style->styles->next;
593 tmp_list = tmp_list->next;
595 g_slist_free_1 (style->styles);
599 g_slist_foreach (style->icon_factories, (GFunc) g_object_unref, NULL);
600 g_slist_free (style->icon_factories);
602 g_slist_foreach (priv->color_hashes, (GFunc) g_hash_table_unref, NULL);
603 g_slist_free (priv->color_hashes);
605 pango_font_description_free (style->font_desc);
607 if (style->private_font_desc)
608 pango_font_description_free (style->private_font_desc);
611 g_object_unref (style->rc_style);
613 G_OBJECT_CLASS (gtk_style_parent_class)->finalize (object);
619 * @style: a #GtkStyle
621 * Creates a copy of the passed in #GtkStyle object.
623 * Returns: (transfer full): a copy of @style
626 gtk_style_copy (GtkStyle *style)
630 g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
632 new_style = GTK_STYLE_GET_CLASS (style)->clone (style);
633 GTK_STYLE_GET_CLASS (style)->copy (new_style, style);
639 gtk_style_duplicate (GtkStyle *style)
643 g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
645 new_style = gtk_style_copy (style);
647 /* All the styles in the list have the same
648 * style->styles pointer. When we insert a new
649 * style, we append it to the list to avoid having
650 * to update the existing ones.
652 style->styles = g_slist_append (style->styles, new_style);
653 new_style->styles = style->styles;
660 * @returns: a new #GtkStyle.
662 * Creates a new #GtkStyle.
669 style = g_object_new (GTK_TYPE_STYLE, NULL);
676 * @style: a #GtkStyle.
677 * @window: a #GdkWindow.
679 * Attaches a style to a window; this process allocates the
680 * colors and creates the GC's for the style - it specializes
681 * it to a particular visual and colormap. The process may
682 * involve the creation of a new style if the style has already
683 * been attached to a window with a different style and colormap.
685 * Since this function may return a new object, you have to use it
686 * in the following way:
687 * <literal>style = gtk_style_attach (style, window)</literal>
689 * Returns: Either @style, or a newly-created #GtkStyle.
690 * If the style is newly created, the style parameter
691 * will be unref'ed, and the new style will have
692 * a reference count belonging to the caller.
695 gtk_style_attach (GtkStyle *style,
699 GtkStyle *new_style = NULL;
700 GdkColormap *colormap;
702 g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
703 g_return_val_if_fail (window != NULL, NULL);
705 colormap = gdk_drawable_get_colormap (window);
708 style->styles = g_slist_append (NULL, style);
710 styles = style->styles;
713 new_style = styles->data;
715 if (new_style->colormap == colormap)
719 styles = styles->next;
724 styles = style->styles;
728 new_style = styles->data;
730 if (new_style->attach_count == 0)
732 gtk_style_realize (new_style, colormap);
737 styles = styles->next;
743 new_style = gtk_style_duplicate (style);
744 gtk_style_realize (new_style, colormap);
747 /* A style gets a refcount from being attached */
748 if (new_style->attach_count == 0)
749 g_object_ref (new_style);
751 /* Another refcount belongs to the parent */
752 if (style != new_style)
754 g_object_unref (style);
755 g_object_ref (new_style);
758 new_style->attach_count++;
765 * @style: a #GtkStyle
767 * Detaches a style from a window. If the style is not attached
768 * to any windows anymore, it is unrealized. See gtk_style_attach().
772 gtk_style_detach (GtkStyle *style)
774 g_return_if_fail (GTK_IS_STYLE (style));
775 g_return_if_fail (style->attach_count > 0);
777 style->attach_count -= 1;
778 if (style->attach_count == 0)
780 g_signal_emit (style, unrealize_signal, 0);
782 g_object_unref (style->colormap);
783 style->colormap = NULL;
785 if (style->private_font_desc)
787 pango_font_description_free (style->private_font_desc);
788 style->private_font_desc = NULL;
791 g_object_unref (style);
796 gtk_style_realize (GtkStyle *style,
797 GdkColormap *colormap)
799 style->colormap = g_object_ref (colormap);
800 style->depth = gdk_colormap_get_visual (colormap)->depth;
802 g_signal_emit (style, realize_signal, 0);
806 * gtk_style_lookup_icon_set:
807 * @style: a #GtkStyle
808 * @stock_id: an icon name
810 * Looks up @stock_id in the icon factories associated with @style
811 * and the default icon factory, returning an icon set if found,
814 * Return value: icon set of @stock_id
817 gtk_style_lookup_icon_set (GtkStyle *style,
818 const char *stock_id)
822 g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
823 g_return_val_if_fail (stock_id != NULL, NULL);
825 iter = style->icon_factories;
828 GtkIconSet *icon_set = gtk_icon_factory_lookup (GTK_ICON_FACTORY (iter->data),
833 iter = g_slist_next (iter);
836 return gtk_icon_factory_lookup_default (stock_id);
840 * gtk_style_lookup_color:
841 * @style: a #GtkStyle
842 * @color_name: the name of the logical color to look up
843 * @color: the #GdkColor to fill in
845 * Looks up @color_name in the style's logical color mappings,
846 * filling in @color and returning %TRUE if found, otherwise
847 * returning %FALSE. Do not cache the found mapping, because
848 * it depends on the #GtkStyle and might change when a theme
851 * Return value: %TRUE if the mapping was found.
856 gtk_style_lookup_color (GtkStyle *style,
857 const char *color_name,
860 GtkStylePrivate *priv;
863 g_return_val_if_fail (GTK_IS_STYLE (style), FALSE);
864 g_return_val_if_fail (color_name != NULL, FALSE);
865 g_return_val_if_fail (color != NULL, FALSE);
867 priv = GTK_STYLE_GET_PRIVATE (style);
869 for (iter = priv->color_hashes; iter != NULL; iter = iter->next)
871 GHashTable *hash = iter->data;
872 GdkColor *mapping = g_hash_table_lookup (hash, color_name);
876 color->red = mapping->red;
877 color->green = mapping->green;
878 color->blue = mapping->blue;
887 * gtk_style_set_background:
888 * @style: a #GtkStyle
889 * @window: a #GdkWindow
890 * @state_type: a state
892 * Sets the background of @window to the background color or pixmap
893 * specified by @style for the given state.
896 gtk_style_set_background (GtkStyle *style,
898 GtkStateType state_type)
900 g_return_if_fail (GTK_IS_STYLE (style));
901 g_return_if_fail (window != NULL);
903 GTK_STYLE_GET_CLASS (style)->set_background (style, window, state_type);
906 /* Default functions */
908 gtk_style_real_clone (GtkStyle *style)
910 return g_object_new (G_OBJECT_TYPE (style), NULL);
914 gtk_style_real_copy (GtkStyle *style,
917 GtkStylePrivate *priv = GTK_STYLE_GET_PRIVATE (style);
918 GtkStylePrivate *src_priv = GTK_STYLE_GET_PRIVATE (src);
921 for (i = 0; i < 5; i++)
923 style->fg[i] = src->fg[i];
924 style->bg[i] = src->bg[i];
925 style->text[i] = src->text[i];
926 style->base[i] = src->base[i];
928 if (style->bg_pixmap[i])
929 g_object_unref (style->bg_pixmap[i]),
930 style->bg_pixmap[i] = src->bg_pixmap[i];
931 if (style->bg_pixmap[i])
932 g_object_ref (style->bg_pixmap[i]);
935 if (style->font_desc)
936 pango_font_description_free (style->font_desc);
938 style->font_desc = pango_font_description_copy (src->font_desc);
940 style->font_desc = NULL;
942 style->xthickness = src->xthickness;
943 style->ythickness = src->ythickness;
946 g_object_unref (style->rc_style);
947 style->rc_style = src->rc_style;
949 g_object_ref (src->rc_style);
951 g_slist_foreach (style->icon_factories, (GFunc) g_object_unref, NULL);
952 g_slist_free (style->icon_factories);
953 style->icon_factories = g_slist_copy (src->icon_factories);
954 g_slist_foreach (style->icon_factories, (GFunc) g_object_ref, NULL);
956 g_slist_foreach (priv->color_hashes, (GFunc) g_hash_table_unref, NULL);
957 g_slist_free (priv->color_hashes);
958 priv->color_hashes = g_slist_copy (src_priv->color_hashes);
959 g_slist_foreach (priv->color_hashes, (GFunc) g_hash_table_ref, NULL);
961 /* don't copy, just clear cache */
962 clear_property_cache (style);
966 gtk_style_real_init_from_rc (GtkStyle *style,
967 GtkRcStyle *rc_style)
969 GtkStylePrivate *priv = GTK_STYLE_GET_PRIVATE (style);
972 /* cache _should_ be still empty */
973 clear_property_cache (style);
975 if (rc_style->font_desc)
976 pango_font_description_merge (style->font_desc, rc_style->font_desc, TRUE);
978 for (i = 0; i < 5; i++)
980 if (rc_style->color_flags[i] & GTK_RC_FG)
981 style->fg[i] = rc_style->fg[i];
982 if (rc_style->color_flags[i] & GTK_RC_BG)
983 style->bg[i] = rc_style->bg[i];
984 if (rc_style->color_flags[i] & GTK_RC_TEXT)
985 style->text[i] = rc_style->text[i];
986 if (rc_style->color_flags[i] & GTK_RC_BASE)
987 style->base[i] = rc_style->base[i];
990 if (rc_style->xthickness >= 0)
991 style->xthickness = rc_style->xthickness;
992 if (rc_style->ythickness >= 0)
993 style->ythickness = rc_style->ythickness;
995 style->icon_factories = g_slist_copy (rc_style->icon_factories);
996 g_slist_foreach (style->icon_factories, (GFunc) g_object_ref, NULL);
998 priv->color_hashes = g_slist_copy (_gtk_rc_style_get_color_hashes (rc_style));
999 g_slist_foreach (priv->color_hashes, (GFunc) g_hash_table_ref, NULL);
1003 style_property_values_cmp (gconstpointer bsearch_node1,
1004 gconstpointer bsearch_node2)
1006 const PropertyValue *val1 = bsearch_node1;
1007 const PropertyValue *val2 = bsearch_node2;
1009 if (val1->widget_type == val2->widget_type)
1010 return val1->pspec < val2->pspec ? -1 : val1->pspec == val2->pspec ? 0 : 1;
1012 return val1->widget_type < val2->widget_type ? -1 : 1;
1016 * gtk_style_get_style_property:
1017 * @style: a #GtkStyle
1018 * @widget_type: the #GType of a descendant of #GtkWidget
1019 * @property_name: the name of the style property to get
1020 * @value: a #GValue where the value of the property being
1021 * queried will be stored
1023 * Queries the value of a style property corresponding to a
1024 * widget class is in the given style.
1029 gtk_style_get_style_property (GtkStyle *style,
1031 const gchar *property_name,
1034 GtkWidgetClass *klass;
1036 GtkRcPropertyParser parser;
1037 const GValue *peek_value;
1039 klass = g_type_class_ref (widget_type);
1040 pspec = gtk_widget_class_find_style_property (klass, property_name);
1041 g_type_class_unref (klass);
1045 g_warning ("%s: widget class `%s' has no property named `%s'",
1047 g_type_name (widget_type),
1052 parser = g_param_spec_get_qdata (pspec,
1053 g_quark_from_static_string ("gtk-rc-property-parser"));
1055 peek_value = _gtk_style_peek_property_value (style, widget_type, pspec, parser);
1057 if (G_VALUE_TYPE (value) == G_PARAM_SPEC_VALUE_TYPE (pspec))
1058 g_value_copy (peek_value, value);
1059 else if (g_value_type_transformable (G_PARAM_SPEC_VALUE_TYPE (pspec), G_VALUE_TYPE (value)))
1060 g_value_transform (peek_value, value);
1062 g_warning ("can't retrieve style property `%s' of type `%s' as value of type `%s'",
1064 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
1065 G_VALUE_TYPE_NAME (value));
1069 * gtk_style_get_valist:
1070 * @style: a #GtkStyle
1071 * @widget_type: the #GType of a descendant of #GtkWidget
1072 * @first_property_name: the name of the first style property to get
1073 * @var_args: a <type>va_list</type> of pairs of property names and
1074 * locations to return the property values, starting with the
1075 * location for @first_property_name.
1077 * Non-vararg variant of gtk_style_get().
1078 * Used primarily by language bindings.
1083 gtk_style_get_valist (GtkStyle *style,
1085 const gchar *first_property_name,
1088 const char *property_name;
1089 GtkWidgetClass *klass;
1091 g_return_if_fail (GTK_IS_STYLE (style));
1093 klass = g_type_class_ref (widget_type);
1095 property_name = first_property_name;
1096 while (property_name)
1099 GtkRcPropertyParser parser;
1100 const GValue *peek_value;
1103 pspec = gtk_widget_class_find_style_property (klass, property_name);
1107 g_warning ("%s: widget class `%s' has no property named `%s'",
1109 g_type_name (widget_type),
1114 parser = g_param_spec_get_qdata (pspec,
1115 g_quark_from_static_string ("gtk-rc-property-parser"));
1117 peek_value = _gtk_style_peek_property_value (style, widget_type, pspec, parser);
1118 G_VALUE_LCOPY (peek_value, var_args, 0, &error);
1121 g_warning ("%s: %s", G_STRLOC, error);
1126 property_name = va_arg (var_args, gchar*);
1129 g_type_class_unref (klass);
1134 * @style: a #GtkStyle
1135 * @widget_type: the #GType of a descendant of #GtkWidget
1136 * @first_property_name: the name of the first style property to get
1137 * @Varargs: pairs of property names and locations to
1138 * return the property values, starting with the location for
1139 * @first_property_name, terminated by %NULL.
1141 * Gets the values of a multiple style properties for @widget_type
1147 gtk_style_get (GtkStyle *style,
1149 const gchar *first_property_name,
1154 va_start (var_args, first_property_name);
1155 gtk_style_get_valist (style, widget_type, first_property_name, var_args);
1160 _gtk_style_peek_property_value (GtkStyle *style,
1163 GtkRcPropertyParser parser)
1165 PropertyValue *pcache, key = { 0, NULL, { 0, } };
1166 const GtkRcProperty *rcprop = NULL;
1169 g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
1170 g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
1171 g_return_val_if_fail (g_type_is_a (pspec->owner_type, GTK_TYPE_WIDGET), NULL);
1172 g_return_val_if_fail (g_type_is_a (widget_type, pspec->owner_type), NULL);
1174 key.widget_type = widget_type;
1177 /* need value cache array */
1178 if (!style->property_cache)
1179 style->property_cache = g_array_new (FALSE, FALSE, sizeof (PropertyValue));
1182 pcache = bsearch (&key,
1183 style->property_cache->data, style->property_cache->len,
1184 sizeof (PropertyValue), style_property_values_cmp);
1186 return &pcache->value;
1190 while (i < style->property_cache->len &&
1191 style_property_values_cmp (&key, &g_array_index (style->property_cache, PropertyValue, i)) >= 0)
1194 g_array_insert_val (style->property_cache, i, key);
1195 pcache = &g_array_index (style->property_cache, PropertyValue, i);
1197 /* cache miss, initialize value type, then set contents */
1198 g_param_spec_ref (pcache->pspec);
1199 g_value_init (&pcache->value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1201 /* value provided by rc style? */
1202 if (style->rc_style)
1204 GQuark prop_quark = g_quark_from_string (pspec->name);
1208 rcprop = _gtk_rc_style_lookup_rc_property (style->rc_style,
1209 g_type_qname (widget_type),
1213 widget_type = g_type_parent (widget_type);
1215 while (g_type_is_a (widget_type, pspec->owner_type));
1218 /* when supplied by rc style, we need to convert */
1219 if (rcprop && !_gtk_settings_parse_convert (parser, &rcprop->value,
1220 pspec, &pcache->value))
1222 gchar *contents = g_strdup_value_contents (&rcprop->value);
1224 g_message ("%s: failed to retrieve property `%s::%s' of type `%s' from rc file value \"%s\" of type `%s'",
1225 rcprop->origin ? rcprop->origin : "(for origin information, set GTK_DEBUG)",
1226 g_type_name (pspec->owner_type), pspec->name,
1227 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
1229 G_VALUE_TYPE_NAME (&rcprop->value));
1231 rcprop = NULL; /* needs default */
1234 /* not supplied by rc style (or conversion failed), revert to default */
1236 g_param_value_set_default (pspec, &pcache->value);
1238 return &pcache->value;
1242 load_bg_image (GdkColormap *colormap,
1244 const gchar *filename)
1246 if (strcmp (filename, "<parent>") == 0)
1247 return (GdkPixmap*) GDK_PARENT_RELATIVE;
1253 GdkScreen *screen = gdk_colormap_get_screen (colormap);
1255 pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
1259 pixmap = gdk_pixmap_new (gdk_screen_get_root_window (screen),
1260 gdk_pixbuf_get_width (pixbuf),
1261 gdk_pixbuf_get_height (pixbuf),
1262 gdk_colormap_get_visual (colormap)->depth);
1263 gdk_drawable_set_colormap (pixmap, colormap);
1265 cr = gdk_cairo_create (pixmap);
1267 gdk_cairo_set_source_color (cr, bg_color);
1270 gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
1274 g_object_unref (pixbuf);
1281 gtk_style_real_realize (GtkStyle *style)
1285 for (i = 0; i < 5; i++)
1287 _gtk_style_shade (&style->bg[i], &style->light[i], LIGHTNESS_MULT);
1288 _gtk_style_shade (&style->bg[i], &style->dark[i], DARKNESS_MULT);
1290 style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2;
1291 style->mid[i].green = (style->light[i].green + style->dark[i].green) / 2;
1292 style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2;
1294 style->text_aa[i].red = (style->text[i].red + style->base[i].red) / 2;
1295 style->text_aa[i].green = (style->text[i].green + style->base[i].green) / 2;
1296 style->text_aa[i].blue = (style->text[i].blue + style->base[i].blue) / 2;
1299 style->black.red = 0x0000;
1300 style->black.green = 0x0000;
1301 style->black.blue = 0x0000;
1303 style->white.red = 0xffff;
1304 style->white.green = 0xffff;
1305 style->white.blue = 0xffff;
1307 for (i = 0; i < 5; i++)
1309 if (style->rc_style && style->rc_style->bg_pixmap_name[i])
1310 style->bg_pixmap[i] = load_bg_image (style->colormap,
1312 style->rc_style->bg_pixmap_name[i]);
1317 gtk_style_real_unrealize (GtkStyle *style)
1321 for (i = 0; i < 5; i++)
1323 if (style->bg_pixmap[i] && style->bg_pixmap[i] != (GdkPixmap*) GDK_PARENT_RELATIVE)
1325 g_object_unref (style->bg_pixmap[i]);
1326 style->bg_pixmap[i] = NULL;
1331 style_unrealize_cursors (style);
1335 gtk_style_real_set_background (GtkStyle *style,
1337 GtkStateType state_type)
1340 gint parent_relative;
1342 if (style->bg_pixmap[state_type])
1344 if (style->bg_pixmap[state_type] == (GdkPixmap*) GDK_PARENT_RELATIVE)
1347 parent_relative = TRUE;
1351 pixmap = style->bg_pixmap[state_type];
1352 parent_relative = FALSE;
1355 gdk_window_set_back_pixmap (window, pixmap, parent_relative);
1358 gdk_window_set_background (window, &style->bg[state_type]);
1362 * gtk_style_render_icon:
1363 * @style: a #GtkStyle
1364 * @source: the #GtkIconSource specifying the icon to render
1365 * @direction: a text direction
1367 * @size: (type int): the size to render the icon at. A size of
1368 * (GtkIconSize)-1 means render at the size of the source and
1370 * @widget: (allow-none): the widget
1371 * @detail: (allow-none): a style detail
1373 * Renders the icon specified by @source at the given @size
1374 * according to the given parameters and returns the result in a
1377 * Return value: (transfer full): a newly-created #GdkPixbuf
1378 * containing the rendered icon
1381 gtk_style_render_icon (GtkStyle *style,
1382 const GtkIconSource *source,
1383 GtkTextDirection direction,
1387 const gchar *detail)
1391 g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
1392 g_return_val_if_fail (GTK_STYLE_GET_CLASS (style)->render_icon != NULL, NULL);
1394 pixbuf = GTK_STYLE_GET_CLASS (style)->render_icon (style, source, direction, state,
1395 size, widget, detail);
1397 g_return_val_if_fail (pixbuf != NULL, NULL);
1402 /* Default functions */
1405 * gtk_style_apply_default_background:
1411 * @area: (allow-none):
1418 gtk_style_apply_default_background (GtkStyle *style,
1421 GtkStateType state_type,
1429 if (style->bg_pixmap[state_type] == (GdkPixmap*) GDK_PARENT_RELATIVE)
1431 GdkWindow *parent = gdk_window_get_parent (window);
1432 int x_offset, y_offset;
1436 gdk_window_get_position (window, &x_offset, &y_offset);
1437 cairo_translate (cr, -x_offset, -y_offset);
1438 gtk_style_apply_default_background (style, cr,
1440 x + x_offset, y + y_offset,
1445 gdk_cairo_set_source_color (cr, &style->bg[state_type]);
1447 else if (style->bg_pixmap[state_type])
1449 gdk_cairo_set_source_pixmap (cr, style->bg_pixmap[state_type], 0, 0);
1450 cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
1453 gdk_cairo_set_source_color (cr, &style->bg[state_type]);
1455 cairo_rectangle (cr, x, y, width, height);
1463 scale_or_ref (GdkPixbuf *src,
1467 if (width == gdk_pixbuf_get_width (src) &&
1468 height == gdk_pixbuf_get_height (src))
1470 return g_object_ref (src);
1474 return gdk_pixbuf_scale_simple (src,
1476 GDK_INTERP_BILINEAR);
1481 lookup_icon_size (GtkStyle *style,
1488 GtkSettings *settings;
1490 if (widget && gtk_widget_has_screen (widget))
1492 screen = gtk_widget_get_screen (widget);
1493 settings = gtk_settings_get_for_screen (screen);
1495 else if (style && style->colormap)
1497 screen = gdk_colormap_get_screen (style->colormap);
1498 settings = gtk_settings_get_for_screen (screen);
1502 settings = gtk_settings_get_default ();
1503 GTK_NOTE (MULTIHEAD,
1504 g_warning ("Using the default screen for gtk_default_render_icon()"));
1507 return gtk_icon_size_lookup_for_settings (settings, size, width, height);
1511 gtk_default_render_icon (GtkStyle *style,
1512 const GtkIconSource *source,
1513 GtkTextDirection direction,
1517 const gchar *detail)
1523 GdkPixbuf *base_pixbuf;
1525 /* Oddly, style can be NULL in this function, because
1526 * GtkIconSet can be used without a style and if so
1527 * it uses this function.
1530 base_pixbuf = gtk_icon_source_get_pixbuf (source);
1532 g_return_val_if_fail (base_pixbuf != NULL, NULL);
1534 if (size != (GtkIconSize) -1 && !lookup_icon_size(style, widget, size, &width, &height))
1536 g_warning (G_STRLOC ": invalid icon size '%d'", size);
1540 /* If the size was wildcarded, and we're allowed to scale, then scale; otherwise,
1543 if (size != (GtkIconSize)-1 && gtk_icon_source_get_size_wildcarded (source))
1544 scaled = scale_or_ref (base_pixbuf, width, height);
1546 scaled = g_object_ref (base_pixbuf);
1548 /* If the state was wildcarded, then generate a state. */
1549 if (gtk_icon_source_get_state_wildcarded (source))
1551 if (state == GTK_STATE_INSENSITIVE)
1553 stated = gdk_pixbuf_copy (scaled);
1555 gdk_pixbuf_saturate_and_pixelate (scaled, stated,
1558 g_object_unref (scaled);
1560 else if (state == GTK_STATE_PRELIGHT)
1562 stated = gdk_pixbuf_copy (scaled);
1564 gdk_pixbuf_saturate_and_pixelate (scaled, stated,
1567 g_object_unref (scaled);
1581 sanitize_size (GdkWindow *window,
1585 if ((*width == -1) && (*height == -1))
1586 gdk_drawable_get_size (window, width, height);
1587 else if (*width == -1)
1588 gdk_drawable_get_size (window, width, NULL);
1589 else if (*height == -1)
1590 gdk_drawable_get_size (window, NULL, height);
1594 _cairo_draw_line (cairo_t *cr,
1603 gdk_cairo_set_source_color (cr, color);
1604 cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
1606 cairo_move_to (cr, x1 + 0.5, y1 + 0.5);
1607 cairo_line_to (cr, x2 + 0.5, y2 + 0.5);
1614 _cairo_draw_rectangle (cairo_t *cr,
1622 gdk_cairo_set_source_color (cr, color);
1626 cairo_rectangle (cr, x, y, width, height);
1631 cairo_rectangle (cr, x + 0.5, y + 0.5, width, height);
1637 _cairo_draw_point (cairo_t *cr,
1642 gdk_cairo_set_source_color (cr, color);
1643 cairo_rectangle (cr, x, y, 1, 1);
1648 gtk_default_draw_hline (GtkStyle *style,
1650 GtkStateType state_type,
1652 const gchar *detail,
1657 gint thickness_light;
1658 gint thickness_dark;
1661 thickness_light = style->ythickness / 2;
1662 thickness_dark = style->ythickness - thickness_light;
1664 cairo_set_line_width (cr, 1.0);
1666 if (detail && !strcmp (detail, "label"))
1668 if (state_type == GTK_STATE_INSENSITIVE)
1669 _cairo_draw_line (cr, &style->white, x1 + 1, y + 1, x2 + 1, y + 1);
1670 _cairo_draw_line (cr, &style->fg[state_type], x1, y, x2, y);
1674 for (i = 0; i < thickness_dark; i++)
1676 _cairo_draw_line (cr, &style->dark[state_type], x1, y + i, x2 - i - 1, y + i);
1677 _cairo_draw_line (cr, &style->light[state_type], x2 - i, y + i, x2, y + i);
1680 y += thickness_dark;
1681 for (i = 0; i < thickness_light; i++)
1683 _cairo_draw_line (cr, &style->dark[state_type], x1, y + i, x1 + thickness_light - i - 1, y + i);
1684 _cairo_draw_line (cr, &style->light[state_type], x1 + thickness_light - i, y + i, x2, y + i);
1691 gtk_default_draw_vline (GtkStyle *style,
1693 GtkStateType state_type,
1696 const gchar *detail,
1702 gint thickness_light;
1703 gint thickness_dark;
1706 thickness_light = style->xthickness / 2;
1707 thickness_dark = style->xthickness - thickness_light;
1709 cr = gdk_cairo_create (window);
1710 cairo_set_line_width (cr, 1.0);
1714 gdk_cairo_rectangle (cr, area);
1718 for (i = 0; i < thickness_dark; i++)
1720 _cairo_draw_line (cr, &style->dark[state_type],
1721 x + i, y1, x + i, y2 - i - 1);
1722 _cairo_draw_line (cr, &style->light[state_type],
1723 x + i, y2 - i, x + i, y2);
1726 x += thickness_dark;
1727 for (i = 0; i < thickness_light; i++)
1729 _cairo_draw_line (cr, &style->dark[state_type],
1730 x + i, y1, x + i, y1 + thickness_light - i - 1);
1731 _cairo_draw_line (cr, &style->light[state_type],
1732 x + i, y1 + thickness_light - i, x + i, y2);
1739 draw_thin_shadow (GtkStyle *style,
1748 GdkColor *gc1, *gc2;
1750 gc1 = &style->light[state];
1751 gc2 = &style->dark[state];
1753 _cairo_draw_line (cr, gc1,
1754 x, y + height - 1, x + width - 1, y + height - 1);
1755 _cairo_draw_line (cr, gc1,
1756 x + width - 1, y, x + width - 1, y + height - 1);
1758 _cairo_draw_line (cr, gc2,
1759 x, y, x + width - 2, y);
1760 _cairo_draw_line (cr, gc2,
1761 x, y, x, y + height - 2);
1765 draw_spinbutton_shadow (GtkStyle *style,
1768 GtkTextDirection direction,
1776 if (direction == GTK_TEXT_DIR_LTR)
1778 _cairo_draw_line (cr, &style->dark[state],
1779 x, y, x + width - 1, y);
1780 _cairo_draw_line (cr, &style->black,
1781 x, y + 1, x + width - 2, y + 1);
1782 _cairo_draw_line (cr, &style->black,
1783 x + width - 2, y + 2, x + width - 2, y + height - 3);
1784 _cairo_draw_line (cr, &style->light[state],
1785 x + width - 1, y + 1, x + width - 1, y + height - 2);
1786 _cairo_draw_line (cr, &style->light[state],
1787 x, y + height - 1, x + width - 1, y + height - 1);
1788 _cairo_draw_line (cr, &style->bg[state],
1789 x, y + height - 2, x + width - 2, y + height - 2);
1790 _cairo_draw_line (cr, &style->black,
1791 x, y + 2, x, y + height - 3);
1795 _cairo_draw_line (cr, &style->dark[state],
1796 x, y, x + width - 1, y);
1797 _cairo_draw_line (cr, &style->dark[state],
1798 x, y + 1, x, y + height - 1);
1799 _cairo_draw_line (cr, &style->black,
1800 x + 1, y + 1, x + width - 1, y + 1);
1801 _cairo_draw_line (cr, &style->black,
1802 x + 1, y + 2, x + 1, y + height - 2);
1803 _cairo_draw_line (cr, &style->black,
1804 x + width - 1, y + 2, x + width - 1, y + height - 3);
1805 _cairo_draw_line (cr, &style->light[state],
1806 x + 1, y + height - 1, x + width - 1, y + height - 1);
1807 _cairo_draw_line (cr, &style->bg[state],
1808 x + 2, y + height - 2, x + width - 1, y + height - 2);
1813 draw_menu_shadow (GtkStyle *style,
1822 if (style->ythickness > 0)
1824 if (style->ythickness > 1)
1826 _cairo_draw_line (cr, &style->dark[state],
1827 x + 1, y + height - 2,
1828 x + width - 2, y + height - 2);
1829 _cairo_draw_line (cr, &style->black,
1830 x, y + height - 1, x + width - 1, y + height - 1);
1834 _cairo_draw_line (cr, &style->dark[state],
1835 x + 1, y + height - 1, x + width - 1, y + height - 1);
1839 if (style->xthickness > 0)
1841 if (style->xthickness > 1)
1843 _cairo_draw_line (cr, &style->dark[state],
1844 x + width - 2, y + 1,
1845 x + width - 2, y + height - 2);
1847 _cairo_draw_line (cr, &style->black,
1848 x + width - 1, y, x + width - 1, y + height - 1);
1852 _cairo_draw_line (cr, &style->dark[state],
1853 x + width - 1, y + 1, x + width - 1, y + height - 1);
1857 /* Light around top and left */
1859 if (style->ythickness > 0)
1860 _cairo_draw_line (cr, &style->black,
1861 x, y, x + width - 2, y);
1862 if (style->xthickness > 0)
1863 _cairo_draw_line (cr, &style->black,
1864 x, y, x, y + height - 2);
1866 if (style->ythickness > 1)
1867 _cairo_draw_line (cr, &style->light[state],
1868 x + 1, y + 1, x + width - 3, y + 1);
1869 if (style->xthickness > 1)
1870 _cairo_draw_line (cr, &style->light[state],
1871 x + 1, y + 1, x + 1, y + height - 3);
1874 static GtkTextDirection
1875 get_direction (GtkWidget *widget)
1877 GtkTextDirection dir;
1880 dir = gtk_widget_get_direction (widget);
1882 dir = GTK_TEXT_DIR_LTR;
1889 gtk_default_draw_shadow (GtkStyle *style,
1891 GtkStateType state_type,
1892 GtkShadowType shadow_type,
1895 const gchar *detail,
1902 GdkColor *gc1 = NULL;
1903 GdkColor *gc2 = NULL;
1904 gint thickness_light;
1905 gint thickness_dark;
1908 sanitize_size (window, &width, &height);
1910 cr = gdk_cairo_create (window);
1911 cairo_set_line_width (cr, 1.0);
1915 gdk_cairo_rectangle (cr, area);
1919 if (shadow_type == GTK_SHADOW_IN)
1921 if (detail && strcmp (detail, "buttondefault") == 0)
1923 _cairo_draw_rectangle (cr, &style->black, FALSE,
1924 x, y, width - 1, height - 1);
1929 if (detail && strcmp (detail, "trough") == 0)
1931 draw_thin_shadow (style, cr, state_type, area,
1932 x, y, width, height);
1937 if (GTK_IS_SPIN_BUTTON (widget) &&
1938 detail && strcmp (detail, "spinbutton") == 0)
1940 draw_spinbutton_shadow (style, cr, state_type,
1941 get_direction (widget), area, x, y, width, height);
1948 if (shadow_type == GTK_SHADOW_OUT && detail && strcmp (detail, "menu") == 0)
1950 draw_menu_shadow (style, cr, state_type, area, x, y, width, height);
1955 switch (shadow_type)
1957 case GTK_SHADOW_NONE:
1961 case GTK_SHADOW_ETCHED_IN:
1962 gc1 = &style->light[state_type];
1963 gc2 = &style->dark[state_type];
1965 case GTK_SHADOW_OUT:
1966 case GTK_SHADOW_ETCHED_OUT:
1967 gc1 = &style->dark[state_type];
1968 gc2 = &style->light[state_type];
1972 switch (shadow_type)
1974 case GTK_SHADOW_NONE:
1978 /* Light around right and bottom edge */
1980 if (style->ythickness > 0)
1981 _cairo_draw_line (cr, gc1,
1982 x, y + height - 1, x + width - 1, y + height - 1);
1983 if (style->xthickness > 0)
1984 _cairo_draw_line (cr, gc1,
1985 x + width - 1, y, x + width - 1, y + height - 1);
1987 if (style->ythickness > 1)
1988 _cairo_draw_line (cr, &style->bg[state_type],
1989 x + 1, y + height - 2, x + width - 2, y + height - 2);
1990 if (style->xthickness > 1)
1991 _cairo_draw_line (cr, &style->bg[state_type],
1992 x + width - 2, y + 1, x + width - 2, y + height - 2);
1994 /* Dark around left and top */
1996 if (style->ythickness > 1)
1997 _cairo_draw_line (cr, &style->black,
1998 x + 1, y + 1, x + width - 2, y + 1);
1999 if (style->xthickness > 1)
2000 _cairo_draw_line (cr, &style->black,
2001 x + 1, y + 1, x + 1, y + height - 2);
2003 if (style->ythickness > 0)
2004 _cairo_draw_line (cr, gc2,
2005 x, y, x + width - 1, y);
2006 if (style->xthickness > 0)
2007 _cairo_draw_line (cr, gc2,
2008 x, y, x, y + height - 1);
2011 case GTK_SHADOW_OUT:
2012 /* Dark around right and bottom edge */
2014 if (style->ythickness > 0)
2016 if (style->ythickness > 1)
2018 _cairo_draw_line (cr, gc1,
2019 x + 1, y + height - 2, x + width - 2, y + height - 2);
2020 _cairo_draw_line (cr, &style->black,
2021 x, y + height - 1, x + width - 1, y + height - 1);
2025 _cairo_draw_line (cr, gc1,
2026 x + 1, y + height - 1, x + width - 1, y + height - 1);
2030 if (style->xthickness > 0)
2032 if (style->xthickness > 1)
2034 _cairo_draw_line (cr, gc1,
2035 x + width - 2, y + 1, x + width - 2, y + height - 2);
2037 _cairo_draw_line (cr, &style->black,
2038 x + width - 1, y, x + width - 1, y + height - 1);
2042 _cairo_draw_line (cr, gc1,
2043 x + width - 1, y + 1, x + width - 1, y + height - 1);
2047 /* Light around top and left */
2049 if (style->ythickness > 0)
2050 _cairo_draw_line (cr, gc2,
2051 x, y, x + width - 2, y);
2052 if (style->xthickness > 0)
2053 _cairo_draw_line (cr, gc2,
2054 x, y, x, y + height - 2);
2056 if (style->ythickness > 1)
2057 _cairo_draw_line (cr, &style->bg[state_type],
2058 x + 1, y + 1, x + width - 3, y + 1);
2059 if (style->xthickness > 1)
2060 _cairo_draw_line (cr, &style->bg[state_type],
2061 x + 1, y + 1, x + 1, y + height - 3);
2064 case GTK_SHADOW_ETCHED_IN:
2065 case GTK_SHADOW_ETCHED_OUT:
2066 if (style->xthickness > 0)
2068 if (style->xthickness > 1)
2070 thickness_light = 1;
2073 for (i = 0; i < thickness_dark; i++)
2075 _cairo_draw_line (cr, gc1,
2079 y + height - i - 1);
2080 _cairo_draw_line (cr, gc2,
2084 y + height - i - 2);
2087 for (i = 0; i < thickness_light; i++)
2089 _cairo_draw_line (cr, gc1,
2090 x + thickness_dark + i,
2091 y + thickness_dark + i,
2092 x + thickness_dark + i,
2093 y + height - thickness_dark - i - 1);
2094 _cairo_draw_line (cr, gc2,
2095 x + width - thickness_light - i - 1,
2096 y + thickness_dark + i,
2097 x + width - thickness_light - i - 1,
2098 y + height - thickness_light - 1);
2103 _cairo_draw_line (cr,
2104 &style->dark[state_type],
2105 x, y, x, y + height);
2106 _cairo_draw_line (cr,
2107 &style->dark[state_type],
2108 x + width, y, x + width, y + height);
2112 if (style->ythickness > 0)
2114 if (style->ythickness > 1)
2116 thickness_light = 1;
2119 for (i = 0; i < thickness_dark; i++)
2121 _cairo_draw_line (cr, gc1,
2125 y + height - i - 1);
2127 _cairo_draw_line (cr, gc2,
2134 for (i = 0; i < thickness_light; i++)
2136 _cairo_draw_line (cr, gc1,
2137 x + thickness_dark + i,
2138 y + thickness_dark + i,
2139 x + width - thickness_dark - i - 2,
2140 y + thickness_dark + i);
2142 _cairo_draw_line (cr, gc2,
2143 x + thickness_dark + i,
2144 y + height - thickness_light - i - 1,
2145 x + width - thickness_light - 1,
2146 y + height - thickness_light - i - 1);
2151 _cairo_draw_line (cr,
2152 &style->dark[state_type],
2153 x, y, x + width, y);
2154 _cairo_draw_line (cr,
2155 &style->dark[state_type],
2156 x, y + height, x + width, y + height);
2163 if (shadow_type == GTK_SHADOW_IN &&
2164 GTK_IS_SPIN_BUTTON (widget) &&
2165 detail && strcmp (detail, "entry") == 0)
2167 if (get_direction (widget) == GTK_TEXT_DIR_LTR)
2169 _cairo_draw_line (cr,
2170 &style->base[state_type],
2171 x + width - 1, y + 2,
2172 x + width - 1, y + height - 3);
2173 _cairo_draw_line (cr,
2174 &style->base[state_type],
2175 x + width - 2, y + 2,
2176 x + width - 2, y + height - 3);
2178 _cairo_draw_point (cr,
2180 x + width - 1, y + 1);
2181 _cairo_draw_point (cr,
2182 &style->bg[state_type],
2183 x + width - 1, y + height - 2);
2187 _cairo_draw_line (cr,
2188 &style->base[state_type],
2191 _cairo_draw_line (cr,
2192 &style->base[state_type],
2194 x + 1, y + height - 3);
2196 _cairo_draw_point (cr,
2200 _cairo_draw_line (cr,
2201 &style->bg[state_type],
2203 x + 1, y + height - 2);
2204 _cairo_draw_point (cr,
2205 &style->light[state_type],
2215 draw_arrow (cairo_t *cr,
2217 GtkArrowType arrow_type,
2223 gdk_cairo_set_source_color (cr, color);
2226 if (arrow_type == GTK_ARROW_DOWN)
2228 cairo_move_to (cr, x, y);
2229 cairo_line_to (cr, x + width, y);
2230 cairo_line_to (cr, x + width / 2., y + height);
2232 else if (arrow_type == GTK_ARROW_UP)
2234 cairo_move_to (cr, x, y + height);
2235 cairo_line_to (cr, x + width / 2., y);
2236 cairo_line_to (cr, x + width, y + height);
2238 else if (arrow_type == GTK_ARROW_LEFT)
2240 cairo_move_to (cr, x + width, y);
2241 cairo_line_to (cr, x + width, y + height);
2242 cairo_line_to (cr, x, y + height / 2.);
2244 else if (arrow_type == GTK_ARROW_RIGHT)
2246 cairo_move_to (cr, x, y);
2247 cairo_line_to (cr, x + width, y + height / 2.);
2248 cairo_line_to (cr, x, y + height);
2251 cairo_close_path (cr);
2258 calculate_arrow_geometry (GtkArrowType arrow_type,
2270 case GTK_ARROW_DOWN:
2280 if (arrow_type == GTK_ARROW_DOWN)
2282 if (*height % 2 == 1 || h % 2 == 0)
2287 if (*height % 2 == 0 || h % 2 == 0)
2292 case GTK_ARROW_RIGHT:
2293 case GTK_ARROW_LEFT:
2303 if (arrow_type == GTK_ARROW_RIGHT)
2305 if (*width % 2 == 1 || w % 2 == 0)
2310 if (*width % 2 == 0 || w % 2 == 0)
2316 /* should not be reached */
2320 *x += (*width - w) / 2;
2321 *y += (*height - h) / 2;
2327 gtk_default_draw_arrow (GtkStyle *style,
2330 GtkShadowType shadow,
2333 const gchar *detail,
2334 GtkArrowType arrow_type,
2343 sanitize_size (window, &width, &height);
2345 calculate_arrow_geometry (arrow_type, &x, &y, &width, &height);
2347 if (detail && strcmp (detail, "menu_scroll_arrow_up") == 0)
2350 cr = gdk_cairo_create (window);
2354 gdk_cairo_rectangle (cr, area);
2358 if (state == GTK_STATE_INSENSITIVE)
2359 draw_arrow (cr, &style->white, arrow_type,
2360 x + 1, y + 1, width, height);
2361 draw_arrow (cr, &style->fg[state], arrow_type,
2362 x, y, width, height);
2368 gtk_default_draw_diamond (GtkStyle *style,
2370 GtkStateType state_type,
2371 GtkShadowType shadow_type,
2374 const gchar *detail,
2382 GdkColor *outer_nw = NULL;
2383 GdkColor *outer_ne = NULL;
2384 GdkColor *outer_sw = NULL;
2385 GdkColor *outer_se = NULL;
2386 GdkColor *middle_nw = NULL;
2387 GdkColor *middle_ne = NULL;
2388 GdkColor *middle_sw = NULL;
2389 GdkColor *middle_se = NULL;
2390 GdkColor *inner_nw = NULL;
2391 GdkColor *inner_ne = NULL;
2392 GdkColor *inner_sw = NULL;
2393 GdkColor *inner_se = NULL;
2396 sanitize_size (window, &width, &height);
2398 half_width = width / 2;
2399 half_height = height / 2;
2401 switch (shadow_type)
2404 inner_sw = inner_se = &style->bg[state_type];
2405 middle_sw = middle_se = &style->light[state_type];
2406 outer_sw = outer_se = &style->light[state_type];
2407 inner_nw = inner_ne = &style->black;
2408 middle_nw = middle_ne = &style->dark[state_type];
2409 outer_nw = outer_ne = &style->dark[state_type];
2412 case GTK_SHADOW_OUT:
2413 inner_sw = inner_se = &style->dark[state_type];
2414 middle_sw = middle_se = &style->dark[state_type];
2415 outer_sw = outer_se = &style->black;
2416 inner_nw = inner_ne = &style->bg[state_type];
2417 middle_nw = middle_ne = &style->light[state_type];
2418 outer_nw = outer_ne = &style->light[state_type];
2421 case GTK_SHADOW_ETCHED_IN:
2422 inner_sw = inner_se = &style->bg[state_type];
2423 middle_sw = middle_se = &style->dark[state_type];
2424 outer_sw = outer_se = &style->light[state_type];
2425 inner_nw = inner_ne = &style->bg[state_type];
2426 middle_nw = middle_ne = &style->light[state_type];
2427 outer_nw = outer_ne = &style->dark[state_type];
2430 case GTK_SHADOW_ETCHED_OUT:
2431 inner_sw = inner_se = &style->bg[state_type];
2432 middle_sw = middle_se = &style->light[state_type];
2433 outer_sw = outer_se = &style->dark[state_type];
2434 inner_nw = inner_ne = &style->bg[state_type];
2435 middle_nw = middle_ne = &style->dark[state_type];
2436 outer_nw = outer_ne = &style->light[state_type];
2444 cr = gdk_cairo_create (window);
2447 gdk_cairo_rectangle (cr, area);
2453 _cairo_draw_line (cr, inner_sw,
2454 x + 2, y + half_height,
2455 x + half_width, y + height - 2);
2456 _cairo_draw_line (cr, inner_se,
2457 x + half_width, y + height - 2,
2458 x + width - 2, y + half_height);
2459 _cairo_draw_line (cr, middle_sw,
2460 x + 1, y + half_height,
2461 x + half_width, y + height - 1);
2462 _cairo_draw_line (cr, middle_se,
2463 x + half_width, y + height - 1,
2464 x + width - 1, y + half_height);
2465 _cairo_draw_line (cr, outer_sw,
2467 x + half_width, y + height);
2468 _cairo_draw_line (cr, outer_se,
2469 x + half_width, y + height,
2470 x + width, y + half_height);
2472 _cairo_draw_line (cr, inner_nw,
2473 x + 2, y + half_height,
2474 x + half_width, y + 2);
2475 _cairo_draw_line (cr, inner_ne,
2476 x + half_width, y + 2,
2477 x + width - 2, y + half_height);
2478 _cairo_draw_line (cr, middle_nw,
2479 x + 1, y + half_height,
2480 x + half_width, y + 1);
2481 _cairo_draw_line (cr, middle_ne,
2482 x + half_width, y + 1,
2483 x + width - 1, y + half_height);
2484 _cairo_draw_line (cr, outer_nw,
2487 _cairo_draw_line (cr, outer_ne,
2489 x + width, y + half_height);
2496 option_menu_get_props (GtkWidget *widget,
2497 GtkRequisition *indicator_size,
2498 GtkBorder *indicator_spacing)
2500 GtkRequisition *tmp_size = NULL;
2501 GtkBorder *tmp_spacing = NULL;
2505 *indicator_size = *tmp_size;
2506 gtk_requisition_free (tmp_size);
2509 *indicator_size = default_option_indicator_size;
2513 *indicator_spacing = *tmp_spacing;
2514 gtk_border_free (tmp_spacing);
2517 *indicator_spacing = default_option_indicator_spacing;
2521 gtk_default_draw_box (GtkStyle *style,
2523 GtkStateType state_type,
2524 GtkShadowType shadow_type,
2527 const gchar *detail,
2534 gboolean is_spinbutton_box = FALSE;
2536 sanitize_size (window, &width, &height);
2538 if (GTK_IS_SPIN_BUTTON (widget) && detail)
2540 if (strcmp (detail, "spinbutton_up") == 0)
2546 if (get_direction (widget) == GTK_TEXT_DIR_RTL)
2551 is_spinbutton_box = TRUE;
2553 else if (strcmp (detail, "spinbutton_down") == 0)
2558 if (get_direction (widget) == GTK_TEXT_DIR_RTL)
2563 is_spinbutton_box = TRUE;
2567 cr = gdk_cairo_create (window);
2571 gdk_cairo_rectangle (cr, area);
2575 if (!style->bg_pixmap[state_type] ||
2576 GDK_IS_PIXMAP (window))
2578 GdkColor *gc = &style->bg[state_type];
2580 if (state_type == GTK_STATE_SELECTED && detail && strcmp (detail, "paned") == 0)
2582 if (widget && !gtk_widget_has_focus (widget))
2583 gc = &style->base[GTK_STATE_ACTIVE];
2586 _cairo_draw_rectangle (cr, gc, TRUE,
2587 x, y, width, height);
2590 gtk_style_apply_default_background (style, cr, window,
2591 state_type, x, y, width, height);
2594 if (is_spinbutton_box)
2599 lower = &style->dark[state_type];
2600 if (shadow_type == GTK_SHADOW_OUT)
2601 upper = &style->light[state_type];
2603 upper = &style->dark[state_type];
2607 gdk_cairo_rectangle (cr, area);
2611 _cairo_draw_line (cr, upper, x, y, x + width - 1, y);
2612 _cairo_draw_line (cr, lower, x, y + height - 1, x + width - 1, y + height - 1);
2620 gtk_paint_shadow (style, window, state_type, shadow_type, area, widget, detail,
2621 x, y, width, height);
2623 if (detail && strcmp (detail, "optionmenu") == 0)
2625 GtkRequisition indicator_size;
2626 GtkBorder indicator_spacing;
2629 option_menu_get_props (widget, &indicator_size, &indicator_spacing);
2631 sanitize_size (window, &width, &height);
2633 if (get_direction (widget) == GTK_TEXT_DIR_RTL)
2634 vline_x = x + indicator_size.width + indicator_spacing.left + indicator_spacing.right;
2636 vline_x = x + width - (indicator_size.width + indicator_spacing.left + indicator_spacing.right) - style->xthickness;
2638 gtk_paint_vline (style, window, state_type, area, widget,
2640 y + style->ythickness + 1,
2641 y + height - style->ythickness - 3,
2647 get_darkened (const GdkColor *color,
2650 GdkColor src = *color;
2651 GdkColor shaded = *color;
2653 while (darken_count)
2655 _gtk_style_shade (&src, &shaded, 0.93);
2660 return gdk_color_copy (&shaded);
2664 gtk_default_draw_flat_box (GtkStyle *style,
2666 GtkStateType state_type,
2667 GtkShadowType shadow_type,
2670 const gchar *detail,
2678 GdkColor *freeme = NULL;
2680 sanitize_size (window, &width, &height);
2682 cr = gdk_cairo_create (window);
2684 cairo_set_line_width (cr, 1.0);
2688 gdk_cairo_rectangle (cr, area);
2694 int trimmed_len = strlen (detail);
2696 if (g_str_has_prefix (detail, "cell_"))
2698 if (g_str_has_suffix (detail, "_start"))
2700 else if (g_str_has_suffix (detail, "_middle"))
2702 else if (g_str_has_suffix (detail, "_end"))
2706 if (state_type == GTK_STATE_SELECTED)
2708 if (!strcmp ("text", detail))
2709 gc1 = &style->bg[GTK_STATE_SELECTED];
2710 else if (!strncmp ("cell_even", detail, trimmed_len) ||
2711 !strncmp ("cell_odd", detail, trimmed_len) ||
2712 !strncmp ("cell_even_ruled", detail, trimmed_len) ||
2713 !strncmp ("cell_even_ruled_sorted", detail, trimmed_len))
2715 /* This has to be really broken; alex made me do it. -jrb */
2716 if (widget && gtk_widget_has_focus (widget))
2717 gc1 = &style->base[state_type];
2719 gc1 = &style->base[GTK_STATE_ACTIVE];
2721 else if (!strncmp ("cell_odd_ruled", detail, trimmed_len) ||
2722 !strncmp ("cell_odd_ruled_sorted", detail, trimmed_len))
2724 if (widget && gtk_widget_has_focus (widget))
2725 freeme = get_darkened (&style->base[state_type], 1);
2727 freeme = get_darkened (&style->base[GTK_STATE_ACTIVE], 1);
2732 gc1 = &style->bg[state_type];
2737 if (!strcmp ("viewportbin", detail))
2738 gc1 = &style->bg[GTK_STATE_NORMAL];
2739 else if (!strcmp ("entry_bg", detail))
2740 gc1 = &style->base[gtk_widget_get_state (widget)];
2742 /* For trees: even rows are base color, odd rows are a shade of
2743 * the base color, the sort column is a shade of the original color
2747 else if (!strncmp ("cell_even", detail, trimmed_len) ||
2748 !strncmp ("cell_odd", detail, trimmed_len) ||
2749 !strncmp ("cell_even_ruled", detail, trimmed_len))
2751 GdkColor *color = NULL;
2753 gtk_widget_style_get (widget,
2754 "even-row-color", &color,
2759 freeme = get_darkened (color, 0);
2762 gdk_color_free (color);
2765 gc1 = &style->base[state_type];
2767 else if (!strncmp ("cell_odd_ruled", detail, trimmed_len))
2769 GdkColor *color = NULL;
2771 gtk_widget_style_get (widget,
2772 "odd-row-color", &color,
2777 freeme = get_darkened (color, 0);
2780 gdk_color_free (color);
2784 gtk_widget_style_get (widget,
2785 "even-row-color", &color,
2790 freeme = get_darkened (color, 1);
2791 gdk_color_free (color);
2794 freeme = get_darkened (&style->base[state_type], 1);
2798 else if (!strncmp ("cell_even_sorted", detail, trimmed_len) ||
2799 !strncmp ("cell_odd_sorted", detail, trimmed_len) ||
2800 !strncmp ("cell_even_ruled_sorted", detail, trimmed_len))
2802 GdkColor *color = NULL;
2804 if (!strncmp ("cell_odd_sorted", detail, trimmed_len))
2805 gtk_widget_style_get (widget,
2806 "odd-row-color", &color,
2809 gtk_widget_style_get (widget,
2810 "even-row-color", &color,
2815 freeme = get_darkened (color, 1);
2818 gdk_color_free (color);
2822 freeme = get_darkened (&style->base[state_type], 1);
2826 else if (!strncmp ("cell_odd_ruled_sorted", detail, trimmed_len))
2828 GdkColor *color = NULL;
2830 gtk_widget_style_get (widget,
2831 "odd-row-color", &color,
2836 freeme = get_darkened (color, 1);
2839 gdk_color_free (color);
2843 gtk_widget_style_get (widget,
2844 "even-row-color", &color,
2849 freeme = get_darkened (color, 2);
2850 gdk_color_free (color);
2853 freeme = get_darkened (&style->base[state_type], 2);
2858 gc1 = &style->bg[state_type];
2862 gc1 = &style->bg[state_type];
2864 if (!style->bg_pixmap[state_type] || gc1 != &style->bg[state_type] ||
2865 GDK_IS_PIXMAP (window))
2867 _cairo_draw_rectangle (cr, gc1, TRUE,
2868 x, y, width, height);
2870 if (detail && !strcmp ("tooltip", detail))
2871 _cairo_draw_rectangle (cr, &style->black, FALSE,
2872 x, y, width - 1, height - 1);
2875 gtk_style_apply_default_background (style, cr, window,
2876 state_type, x, y, width, height);
2882 gdk_color_free (freeme);
2886 gtk_default_draw_check (GtkStyle *style,
2888 GtkStateType state_type,
2889 GtkShadowType shadow_type,
2892 const gchar *detail,
2898 cairo_t *cr = gdk_cairo_create (window);
2899 enum { BUTTON, MENU, CELL } type = BUTTON;
2906 if (strcmp (detail, "cellcheck") == 0)
2908 else if (strcmp (detail, "check") == 0)
2914 gdk_cairo_rectangle (cr, area);
2918 exterior_size = MIN (width, height);
2919 if (exterior_size % 2 == 0) /* Ensure odd */
2922 pad = style->xthickness + MAX (1, (exterior_size - 2 * style->xthickness) / 9);
2923 interior_size = MAX (1, exterior_size - 2 * pad);
2925 if (interior_size < 7)
2928 pad = MAX (0, (exterior_size - interior_size) / 2);
2931 x -= (1 + exterior_size - width) / 2;
2932 y -= (1 + exterior_size - height) / 2;
2939 gdk_cairo_set_source_color (cr, &style->fg[state_type]);
2941 gdk_cairo_set_source_color (cr, &style->text[state_type]);
2943 cairo_set_line_width (cr, 1.0);
2944 cairo_rectangle (cr, x + 0.5, y + 0.5, exterior_size - 1, exterior_size - 1);
2947 gdk_cairo_set_source_color (cr, &style->base[state_type]);
2948 cairo_rectangle (cr, x + 1, y + 1, exterior_size - 2, exterior_size - 2);
2960 gdk_cairo_set_source_color (cr, &style->text[state_type]);
2963 gdk_cairo_set_source_color (cr, &style->fg[state_type]);
2967 if (shadow_type == GTK_SHADOW_IN)
2969 cairo_translate (cr,
2972 cairo_scale (cr, interior_size / 7., interior_size / 7.);
2974 cairo_move_to (cr, 7.0, 0.0);
2975 cairo_line_to (cr, 7.5, 1.0);
2976 cairo_curve_to (cr, 5.3, 2.0,
2979 cairo_curve_to (cr, 3.0, 5.7,
2982 cairo_line_to (cr, 0.2, 3.5);
2983 cairo_curve_to (cr, 1.1, 3.5,
2986 cairo_curve_to (cr, 1.0, 3.9,
2989 cairo_curve_to (cr, 3.5, 3.1,
2995 else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */
2997 int line_thickness = MAX (1, (3 + interior_size * 2) / 7);
2999 cairo_rectangle (cr,
3001 y + pad + (1 + interior_size - line_thickness) / 2,
3011 gtk_default_draw_option (GtkStyle *style,
3013 GtkStateType state_type,
3014 GtkShadowType shadow_type,
3017 const gchar *detail,
3023 cairo_t *cr = gdk_cairo_create (window);
3024 enum { BUTTON, MENU, CELL } type = BUTTON;
3029 if (strcmp (detail, "radio") == 0)
3031 else if (strcmp (detail, "option") == 0)
3037 gdk_cairo_rectangle (cr, area);
3041 exterior_size = MIN (width, height);
3042 if (exterior_size % 2 == 0) /* Ensure odd */
3045 x -= (1 + exterior_size - width) / 2;
3046 y -= (1 + exterior_size - height) / 2;
3052 gdk_cairo_set_source_color (cr, &style->base[state_type]);
3055 x + exterior_size / 2.,
3056 y + exterior_size / 2.,
3057 (exterior_size - 1) / 2.,
3060 cairo_fill_preserve (cr);
3063 gdk_cairo_set_source_color (cr, &style->fg[state_type]);
3065 gdk_cairo_set_source_color (cr, &style->text[state_type]);
3067 cairo_set_line_width (cr, 1.);
3078 gdk_cairo_set_source_color (cr, &style->text[state_type]);
3083 gdk_cairo_set_source_color (cr, &style->fg[state_type]);
3087 if (shadow_type == GTK_SHADOW_IN)
3089 int pad = style->xthickness + MAX (1, 2 * (exterior_size - 2 * style->xthickness) / 9);
3090 int interior_size = MAX (1, exterior_size - 2 * pad);
3092 if (interior_size < 5)
3095 pad = MAX (0, (exterior_size - interior_size) / 2);
3099 x + pad + interior_size / 2.,
3100 y + pad + interior_size / 2.,
3105 else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */
3107 int pad = style->xthickness + MAX (1, (exterior_size - 2 * style->xthickness) / 9);
3108 int interior_size = MAX (1, exterior_size - 2 * pad);
3111 if (interior_size < 7)
3114 pad = MAX (0, (exterior_size - interior_size) / 2);
3117 line_thickness = MAX (1, (3 + interior_size * 2) / 7);
3119 cairo_rectangle (cr,
3121 y + pad + (interior_size - line_thickness) / 2.,
3131 gtk_default_draw_tab (GtkStyle *style,
3133 GtkStateType state_type,
3134 GtkShadowType shadow_type,
3137 const gchar *detail,
3143 #define ARROW_SPACE 4
3146 GtkRequisition indicator_size;
3147 GtkBorder indicator_spacing;
3150 cr = gdk_cairo_create (window);
3154 gdk_cairo_rectangle (cr, area);
3158 option_menu_get_props (widget, &indicator_size, &indicator_spacing);
3160 indicator_size.width += (indicator_size.width % 2) - 1;
3161 arrow_height = indicator_size.width / 2 + 1;
3163 x += (width - indicator_size.width) / 2;
3164 y += (height - (2 * arrow_height + ARROW_SPACE)) / 2;
3166 if (state_type == GTK_STATE_INSENSITIVE)
3168 draw_arrow (cr, &style->white,
3169 GTK_ARROW_UP, x + 1, y + 1,
3170 indicator_size.width, arrow_height);
3172 draw_arrow (cr, &style->white,
3173 GTK_ARROW_DOWN, x + 1, y + arrow_height + ARROW_SPACE + 1,
3174 indicator_size.width, arrow_height);
3177 draw_arrow (cr, &style->fg[state_type],
3179 indicator_size.width, arrow_height);
3182 draw_arrow (cr, &style->fg[state_type],
3183 GTK_ARROW_DOWN, x, y + arrow_height + ARROW_SPACE,
3184 indicator_size.width, arrow_height);
3190 gtk_default_draw_shadow_gap (GtkStyle *style,
3192 GtkStateType state_type,
3193 GtkShadowType shadow_type,
3196 const gchar *detail,
3201 GtkPositionType gap_side,
3205 GdkColor *color1 = NULL;
3206 GdkColor *color2 = NULL;
3207 GdkColor *color3 = NULL;
3208 GdkColor *color4 = NULL;
3211 sanitize_size (window, &width, &height);
3213 switch (shadow_type)
3215 case GTK_SHADOW_NONE:
3219 color1 = &style->dark[state_type];
3220 color2 = &style->black;
3221 color3 = &style->bg[state_type];
3222 color4 = &style->light[state_type];
3224 case GTK_SHADOW_ETCHED_IN:
3225 color1 = &style->dark[state_type];
3226 color2 = &style->light[state_type];
3227 color3 = &style->dark[state_type];
3228 color4 = &style->light[state_type];
3230 case GTK_SHADOW_OUT:
3231 color1 = &style->light[state_type];
3232 color2 = &style->bg[state_type];
3233 color3 = &style->dark[state_type];
3234 color4 = &style->black;
3236 case GTK_SHADOW_ETCHED_OUT:
3237 color1 = &style->light[state_type];
3238 color2 = &style->dark[state_type];
3239 color3 = &style->light[state_type];
3240 color4 = &style->dark[state_type];
3244 cr = gdk_cairo_create (window);
3247 gdk_cairo_rectangle (cr, area);
3251 switch (shadow_type)
3253 case GTK_SHADOW_NONE:
3255 case GTK_SHADOW_OUT:
3256 case GTK_SHADOW_ETCHED_IN:
3257 case GTK_SHADOW_ETCHED_OUT:
3261 _cairo_draw_line (cr, color1,
3262 x, y, x, y + height - 1);
3263 _cairo_draw_line (cr, color2,
3264 x + 1, y, x + 1, y + height - 2);
3266 _cairo_draw_line (cr, color3,
3267 x + 1, y + height - 2, x + width - 2, y + height - 2);
3268 _cairo_draw_line (cr, color3,
3269 x + width - 2, y, x + width - 2, y + height - 2);
3270 _cairo_draw_line (cr, color4,
3271 x, y + height - 1, x + width - 1, y + height - 1);
3272 _cairo_draw_line (cr, color4,
3273 x + width - 1, y, x + width - 1, y + height - 1);
3276 _cairo_draw_line (cr, color1,
3277 x, y, x + gap_x - 1, y);
3278 _cairo_draw_line (cr, color2,
3279 x + 1, y + 1, x + gap_x - 1, y + 1);
3280 _cairo_draw_line (cr, color2,
3281 x + gap_x, y, x + gap_x, y);
3283 if ((width - (gap_x + gap_width)) > 0)
3285 _cairo_draw_line (cr, color1,
3286 x + gap_x + gap_width, y, x + width - 2, y);
3287 _cairo_draw_line (cr, color2,
3288 x + gap_x + gap_width, y + 1, x + width - 3, y + 1);
3289 _cairo_draw_line (cr, color2,
3290 x + gap_x + gap_width - 1, y, x + gap_x + gap_width - 1, y);
3293 case GTK_POS_BOTTOM:
3294 _cairo_draw_line (cr, color1,
3295 x, y, x + width - 1, y);
3296 _cairo_draw_line (cr, color1,
3297 x, y, x, y + height - 1);
3298 _cairo_draw_line (cr, color2,
3299 x + 1, y + 1, x + width - 2, y + 1);
3300 _cairo_draw_line (cr, color2,
3301 x + 1, y + 1, x + 1, y + height - 1);
3303 _cairo_draw_line (cr, color3,
3304 x + width - 2, y + 1, x + width - 2, y + height - 1);
3305 _cairo_draw_line (cr, color4,
3306 x + width - 1, y, x + width - 1, y + height - 1);
3309 _cairo_draw_line (cr, color4,
3310 x, y + height - 1, x + gap_x - 1, y + height - 1);
3311 _cairo_draw_line (cr, color3,
3312 x + 1, y + height - 2, x + gap_x - 1, y + height - 2);
3313 _cairo_draw_line (cr, color3,
3314 x + gap_x, y + height - 1, x + gap_x, y + height - 1);
3316 if ((width - (gap_x + gap_width)) > 0)
3318 _cairo_draw_line (cr, color4,
3319 x + gap_x + gap_width, y + height - 1, x + width - 2, y + height - 1);
3320 _cairo_draw_line (cr, color3,
3321 x + gap_x + gap_width, y + height - 2, x + width - 2, y + height - 2);
3322 _cairo_draw_line (cr, color3,
3323 x + gap_x + gap_width - 1, y + height - 1, x + gap_x + gap_width - 1, y + height - 1);
3327 _cairo_draw_line (cr, color1,
3328 x, y, x + width - 1, y);
3329 _cairo_draw_line (cr, color2,
3330 x, y + 1, x + width - 2, y + 1);
3332 _cairo_draw_line (cr, color3,
3333 x, y + height - 2, x + width - 2, y + height - 2);
3334 _cairo_draw_line (cr, color3,
3335 x + width - 2, y + 1, x + width - 2, y + height - 2);
3336 _cairo_draw_line (cr, color4,
3337 x, y + height - 1, x + width - 1, y + height - 1);
3338 _cairo_draw_line (cr, color4,
3339 x + width - 1, y, x + width - 1, y + height - 1);
3342 _cairo_draw_line (cr, color1,
3343 x, y, x, y + gap_x - 1);
3344 _cairo_draw_line (cr, color2,
3345 x + 1, y + 1, x + 1, y + gap_x - 1);
3346 _cairo_draw_line (cr, color2,
3347 x, y + gap_x, x, y + gap_x);
3349 if ((width - (gap_x + gap_width)) > 0)
3351 _cairo_draw_line (cr, color1,
3352 x, y + gap_x + gap_width, x, y + height - 2);
3353 _cairo_draw_line (cr, color2,
3354 x + 1, y + gap_x + gap_width, x + 1, y + height - 2);
3355 _cairo_draw_line (cr, color2,
3356 x, y + gap_x + gap_width - 1, x, y + gap_x + gap_width - 1);
3360 _cairo_draw_line (cr, color1,
3361 x, y, x + width - 1, y);
3362 _cairo_draw_line (cr, color1,
3363 x, y, x, y + height - 1);
3364 _cairo_draw_line (cr, color2,
3365 x + 1, y + 1, x + width - 1, y + 1);
3366 _cairo_draw_line (cr, color2,
3367 x + 1, y + 1, x + 1, y + height - 2);
3369 _cairo_draw_line (cr, color3,
3370 x + 1, y + height - 2, x + width - 1, y + height - 2);
3371 _cairo_draw_line (cr, color4,
3372 x, y + height - 1, x + width - 1, y + height - 1);
3375 _cairo_draw_line (cr, color4,
3376 x + width - 1, y, x + width - 1, y + gap_x - 1);
3377 _cairo_draw_line (cr, color3,
3378 x + width - 2, y + 1, x + width - 2, y + gap_x - 1);
3379 _cairo_draw_line (cr, color3,
3380 x + width - 1, y + gap_x, x + width - 1, y + gap_x);
3382 if ((width - (gap_x + gap_width)) > 0)
3384 _cairo_draw_line (cr, color4,
3385 x + width - 1, y + gap_x + gap_width, x + width - 1, y + height - 2);
3386 _cairo_draw_line (cr, color3,
3387 x + width - 2, y + gap_x + gap_width, x + width - 2, y + height - 2);
3388 _cairo_draw_line (cr, color3,
3389 x + width - 1, y + gap_x + gap_width - 1, x + width - 1, y + gap_x + gap_width - 1);
3399 gtk_default_draw_box_gap (GtkStyle *style,
3401 GtkStateType state_type,
3402 GtkShadowType shadow_type,
3405 const gchar *detail,
3410 GtkPositionType gap_side,
3420 sanitize_size (window, &width, &height);
3422 cr = gdk_cairo_create (window);
3425 gdk_cairo_rectangle (cr, area);
3429 gtk_style_apply_default_background (style, cr, window,
3430 state_type, x, y, width, height);
3432 switch (shadow_type)
3434 case GTK_SHADOW_NONE:
3438 color1 = style->dark[state_type];
3439 color2 = style->black;
3440 color3 = style->bg[state_type];
3441 color4 = style->light[state_type];
3443 case GTK_SHADOW_ETCHED_IN:
3444 color1 = style->dark[state_type];
3445 color2 = style->light[state_type];
3446 color3 = style->dark[state_type];
3447 color4 = style->light[state_type];
3449 case GTK_SHADOW_OUT:
3450 color1 = style->light[state_type];
3451 color2 = style->bg[state_type];
3452 color3 = style->dark[state_type];
3453 color4 = style->black;
3455 case GTK_SHADOW_ETCHED_OUT:
3456 color1 = style->light[state_type];
3457 color2 = style->dark[state_type];
3458 color3 = style->light[state_type];
3459 color4 = style->dark[state_type];
3463 cairo_set_line_width (cr, 1.0);
3465 switch (shadow_type)
3467 case GTK_SHADOW_NONE:
3469 case GTK_SHADOW_OUT:
3470 case GTK_SHADOW_ETCHED_IN:
3471 case GTK_SHADOW_ETCHED_OUT:
3475 _cairo_draw_line (cr, &color1,
3476 x, y, x, y + height - 1);
3477 _cairo_draw_line (cr, &color2,
3478 x + 1, y, x + 1, y + height - 2);
3480 _cairo_draw_line (cr, &color3,
3481 x + 1, y + height - 2, x + width - 2, y + height - 2);
3482 _cairo_draw_line (cr, &color3,
3483 x + width - 2, y, x + width - 2, y + height - 2);
3484 _cairo_draw_line (cr, &color4,
3485 x, y + height - 1, x + width - 1, y + height - 1);
3486 _cairo_draw_line (cr, &color4,
3487 x + width - 1, y, x + width - 1, y + height - 1);
3490 _cairo_draw_line (cr, &color1,
3491 x, y, x + gap_x - 1, y);
3492 _cairo_draw_line (cr, &color2,
3493 x + 1, y + 1, x + gap_x - 1, y + 1);
3494 _cairo_draw_line (cr, &color2,
3495 x + gap_x, y, x + gap_x, y);
3497 if ((width - (gap_x + gap_width)) > 0)
3499 _cairo_draw_line (cr, &color1,
3500 x + gap_x + gap_width, y, x + width - 2, y);
3501 _cairo_draw_line (cr, &color2,
3502 x + gap_x + gap_width, y + 1, x + width - 2, y + 1);
3503 _cairo_draw_line (cr, &color2,
3504 x + gap_x + gap_width - 1, y, x + gap_x + gap_width - 1, y);
3507 case GTK_POS_BOTTOM:
3508 _cairo_draw_line (cr, &color1,
3509 x, y, x + width - 1, y);
3510 _cairo_draw_line (cr, &color1,
3511 x, y, x, y + height - 1);
3512 _cairo_draw_line (cr, &color2,
3513 x + 1, y + 1, x + width - 2, y + 1);
3514 _cairo_draw_line (cr, &color2,
3515 x + 1, y + 1, x + 1, y + height - 1);
3517 _cairo_draw_line (cr, &color3,
3518 x + width - 2, y + 1, x + width - 2, y + height - 1);
3519 _cairo_draw_line (cr, &color4,
3520 x + width - 1, y, x + width - 1, y + height - 1);
3523 _cairo_draw_line (cr, &color4,
3524 x, y + height - 1, x + gap_x - 1, y + height - 1);
3525 _cairo_draw_line (cr, &color3,
3526 x + 1, y + height - 2, x + gap_x - 1, y + height - 2);
3527 _cairo_draw_line (cr, &color3,
3528 x + gap_x, y + height - 1, x + gap_x, y + height - 1);
3530 if ((width - (gap_x + gap_width)) > 0)
3532 _cairo_draw_line (cr, &color4,
3533 x + gap_x + gap_width, y + height - 1, x + width - 2, y + height - 1);
3534 _cairo_draw_line (cr, &color3,
3535 x + gap_x + gap_width, y + height - 2, x + width - 2, y + height - 2);
3536 _cairo_draw_line (cr, &color3,
3537 x + gap_x + gap_width - 1, y + height - 1, x + gap_x + gap_width - 1, y + height - 1);
3541 _cairo_draw_line (cr, &color1,
3542 x, y, x + width - 1, y);
3543 _cairo_draw_line (cr, &color2,
3544 x, y + 1, x + width - 2, y + 1);
3546 _cairo_draw_line (cr, &color3,
3547 x, y + height - 2, x + width - 2, y + height - 2);
3548 _cairo_draw_line (cr, &color3,
3549 x + width - 2, y + 1, x + width - 2, y + height - 2);
3550 _cairo_draw_line (cr, &color4,
3551 x, y + height - 1, x + width - 1, y + height - 1);
3552 _cairo_draw_line (cr, &color4,
3553 x + width - 1, y, x + width - 1, y + height - 1);
3556 _cairo_draw_line (cr, &color1,
3557 x, y, x, y + gap_x - 1);
3558 _cairo_draw_line (cr, &color2,
3559 x + 1, y + 1, x + 1, y + gap_x - 1);
3560 _cairo_draw_line (cr, &color2,
3561 x, y + gap_x, x, y + gap_x);
3563 if ((height - (gap_x + gap_width)) > 0)
3565 _cairo_draw_line (cr, &color1,
3566 x, y + gap_x + gap_width, x, y + height - 2);
3567 _cairo_draw_line (cr, &color2,
3568 x + 1, y + gap_x + gap_width, x + 1, y + height - 2);
3569 _cairo_draw_line (cr, &color2,
3570 x, y + gap_x + gap_width - 1, x, y + gap_x + gap_width - 1);
3574 _cairo_draw_line (cr, &color1,
3575 x, y, x + width - 1, y);
3576 _cairo_draw_line (cr, &color1,
3577 x, y, x, y + height - 1);
3578 _cairo_draw_line (cr, &color2,
3579 x + 1, y + 1, x + width - 1, y + 1);
3580 _cairo_draw_line (cr, &color2,
3581 x + 1, y + 1, x + 1, y + height - 2);
3583 _cairo_draw_line (cr, &color3,
3584 x + 1, y + height - 2, x + width - 1, y + height - 2);
3585 _cairo_draw_line (cr, &color4,
3586 x, y + height - 1, x + width - 1, y + height - 1);
3589 _cairo_draw_line (cr, &color4,
3590 x + width - 1, y, x + width - 1, y + gap_x - 1);
3591 _cairo_draw_line (cr, &color3,
3592 x + width - 2, y + 1, x + width - 2, y + gap_x - 1);
3593 _cairo_draw_line (cr, &color3,
3594 x + width - 1, y + gap_x, x + width - 1, y + gap_x);
3596 if ((height - (gap_x + gap_width)) > 0)
3598 _cairo_draw_line (cr, &color4,
3599 x + width - 1, y + gap_x + gap_width, x + width - 1, y + height - 2);
3600 _cairo_draw_line (cr, &color3,
3601 x + width - 2, y + gap_x + gap_width, x + width - 2, y + height - 2);
3602 _cairo_draw_line (cr, &color3,
3603 x + width - 1, y + gap_x + gap_width - 1, x + width - 1, y + gap_x + gap_width - 1);
3614 gtk_default_draw_extension (GtkStyle *style,
3616 GtkStateType state_type,
3617 GtkShadowType shadow_type,
3620 const gchar *detail,
3625 GtkPositionType gap_side)
3633 sanitize_size (window, &width, &height);
3635 cr = gdk_cairo_create (window);
3638 gdk_cairo_rectangle (cr, area);
3645 gtk_style_apply_default_background (style, cr, window,
3652 case GTK_POS_BOTTOM:
3653 gtk_style_apply_default_background (style, cr, window,
3661 gtk_style_apply_default_background (style, cr, window,
3669 gtk_style_apply_default_background (style, cr, window,
3678 switch (shadow_type)
3680 case GTK_SHADOW_NONE:
3684 color1 = style->dark[state_type];
3685 color2 = style->black;
3686 color3 = style->bg[state_type];
3687 color4 = style->light[state_type];
3689 case GTK_SHADOW_ETCHED_IN:
3690 color1 = style->dark[state_type];
3691 color2 = style->light[state_type];
3692 color3 = style->dark[state_type];
3693 color4 = style->light[state_type];
3695 case GTK_SHADOW_OUT:
3696 color1 = style->light[state_type];
3697 color2 = style->bg[state_type];
3698 color3 = style->dark[state_type];
3699 color4 = style->black;
3701 case GTK_SHADOW_ETCHED_OUT:
3702 color1 = style->light[state_type];
3703 color2 = style->dark[state_type];
3704 color3 = style->light[state_type];
3705 color4 = style->dark[state_type];
3709 cairo_set_line_width (cr, 1.0);
3711 switch (shadow_type)
3713 case GTK_SHADOW_NONE:
3715 case GTK_SHADOW_OUT:
3716 case GTK_SHADOW_ETCHED_IN:
3717 case GTK_SHADOW_ETCHED_OUT:
3721 _cairo_draw_line (cr, &color1,
3722 x, y, x, y + height - 2);
3723 _cairo_draw_line (cr, &color2,
3724 x + 1, y, x + 1, y + height - 2);
3726 _cairo_draw_line (cr, &color3,
3727 x + 2, y + height - 2, x + width - 2, y + height - 2);
3728 _cairo_draw_line (cr, &color3,
3729 x + width - 2, y, x + width - 2, y + height - 2);
3730 _cairo_draw_line (cr, &color4,
3731 x + 1, y + height - 1, x + width - 2, y + height - 1);
3732 _cairo_draw_line (cr, &color4,
3733 x + width - 1, y, x + width - 1, y + height - 2);
3735 case GTK_POS_BOTTOM:
3736 _cairo_draw_line (cr, &color1,
3737 x + 1, y, x + width - 2, y);
3738 _cairo_draw_line (cr, &color1,
3739 x, y + 1, x, y + height - 1);
3740 _cairo_draw_line (cr, &color2,
3741 x + 1, y + 1, x + width - 2, y + 1);
3742 _cairo_draw_line (cr, &color2,
3743 x + 1, y + 1, x + 1, y + height - 1);
3745 _cairo_draw_line (cr, &color3,
3746 x + width - 2, y + 2, x + width - 2, y + height - 1);
3747 _cairo_draw_line (cr, &color4,
3748 x + width - 1, y + 1, x + width - 1, y + height - 1);
3751 _cairo_draw_line (cr, &color1,
3752 x, y, x + width - 2, y);
3753 _cairo_draw_line (cr, &color2,
3754 x + 1, y + 1, x + width - 2, y + 1);
3756 _cairo_draw_line (cr, &color3,
3757 x, y + height - 2, x + width - 2, y + height - 2);
3758 _cairo_draw_line (cr, &color3,
3759 x + width - 2, y + 2, x + width - 2, y + height - 2);
3760 _cairo_draw_line (cr, &color4,
3761 x, y + height - 1, x + width - 2, y + height - 1);
3762 _cairo_draw_line (cr, &color4,
3763 x + width - 1, y + 1, x + width - 1, y + height - 2);
3766 _cairo_draw_line (cr, &color1,
3767 x + 1, y, x + width - 1, y);
3768 _cairo_draw_line (cr, &color1,
3769 x, y + 1, x, y + height - 2);
3770 _cairo_draw_line (cr, &color2,
3771 x + 1, y + 1, x + width - 1, y + 1);
3772 _cairo_draw_line (cr, &color2,
3773 x + 1, y + 1, x + 1, y + height - 2);
3775 _cairo_draw_line (cr, &color3,
3776 x + 2, y + height - 2, x + width - 1, y + height - 2);
3777 _cairo_draw_line (cr, &color4,
3778 x + 1, y + height - 1, x + width - 1, y + height - 1);
3787 gtk_default_draw_focus (GtkStyle *style,
3789 GtkStateType state_type,
3792 const gchar *detail,
3799 gboolean free_dash_list = FALSE;
3800 gint line_width = 1;
3801 gint8 *dash_list = (gint8 *) "\1\1";
3805 gtk_widget_style_get (widget,
3806 "focus-line-width", &line_width,
3807 "focus-line-pattern", (gchar *)&dash_list,
3810 free_dash_list = TRUE;
3813 if (detail && !strcmp (detail, "add-mode"))
3818 dash_list = (gint8 *) "\4\4";
3819 free_dash_list = FALSE;
3822 sanitize_size (window, &width, &height);
3824 cr = gdk_cairo_create (window);
3826 if (detail && !strcmp (detail, "colorwheel_light"))
3827 cairo_set_source_rgb (cr, 0., 0., 0.);
3828 else if (detail && !strcmp (detail, "colorwheel_dark"))
3829 cairo_set_source_rgb (cr, 1., 1., 1.);
3831 gdk_cairo_set_source_color (cr, &style->fg[state_type]);
3833 cairo_set_line_width (cr, line_width);
3837 gint n_dashes = strlen ((const gchar *) dash_list);
3838 gdouble *dashes = g_new (gdouble, n_dashes);
3839 gdouble total_length = 0;
3840 gdouble dash_offset;
3843 for (i = 0; i < n_dashes; i++)
3845 dashes[i] = dash_list[i];
3846 total_length += dash_list[i];
3849 /* The dash offset here aligns the pattern to integer pixels
3850 * by starting the dash at the right side of the left border
3851 * Negative dash offsets in cairo don't work
3852 * (https://bugs.freedesktop.org/show_bug.cgi?id=2729)
3854 dash_offset = - line_width / 2.;
3855 while (dash_offset < 0)
3856 dash_offset += total_length;
3858 cairo_set_dash (cr, dashes, n_dashes, dash_offset);
3864 gdk_cairo_rectangle (cr, area);
3868 cairo_rectangle (cr,
3869 x + line_width / 2.,
3870 y + line_width / 2.,
3872 height - line_width);
3881 gtk_default_draw_slider (GtkStyle *style,
3883 GtkStateType state_type,
3884 GtkShadowType shadow_type,
3887 const gchar *detail,
3892 GtkOrientation orientation)
3894 sanitize_size (window, &width, &height);
3896 gtk_paint_box (style, window, state_type, shadow_type,
3897 area, widget, detail, x, y, width, height);
3900 (strcmp ("hscale", detail) == 0 ||
3901 strcmp ("vscale", detail) == 0))
3903 if (orientation == GTK_ORIENTATION_HORIZONTAL)
3904 gtk_paint_vline (style, window, state_type, area, widget, detail,
3905 y + style->ythickness,
3906 y + height - style->ythickness - 1, x + width / 2);
3908 gtk_paint_hline (style, window, state_type, area, widget, detail,
3909 x + style->xthickness,
3910 x + width - style->xthickness - 1, y + height / 2);
3915 draw_dot (cairo_t *cr,
3922 size = CLAMP (size, 2, 3);
3926 _cairo_draw_point (cr, light, x, y);
3927 _cairo_draw_point (cr, light, x+1, y+1);
3931 _cairo_draw_point (cr, light, x, y);
3932 _cairo_draw_point (cr, light, x+1, y);
3933 _cairo_draw_point (cr, light, x, y+1);
3934 _cairo_draw_point (cr, dark, x+1, y+2);
3935 _cairo_draw_point (cr, dark, x+2, y+1);
3936 _cairo_draw_point (cr, dark, x+2, y+2);
3941 gtk_default_draw_handle (GtkStyle *style,
3943 GtkStateType state_type,
3944 GtkShadowType shadow_type,
3947 const gchar *detail,
3952 GtkOrientation orientation)
3955 gint xthick, ythick;
3956 GdkColor light, dark;
3959 sanitize_size (window, &width, &height);
3961 gtk_paint_box (style, window, state_type, shadow_type, area, widget,
3962 detail, x, y, width, height);
3964 cr = gdk_cairo_create (window);
3967 gdk_cairo_rectangle (cr, area);
3971 if (detail && !strcmp (detail, "paned"))
3973 /* we want to ignore the shadow border in paned widgets */
3977 if (state_type == GTK_STATE_SELECTED && widget && !gtk_widget_has_focus (widget))
3978 _gtk_style_shade (&style->base[GTK_STATE_ACTIVE], &light,
3981 light = style->light[state_type];
3983 dark = style->black;
3987 xthick = style->xthickness;
3988 ythick = style->ythickness;
3990 light = style->light[state_type];
3991 dark = style->dark[state_type];
3994 cairo_rectangle(cr, x + xthick, y + ythick,
3995 width - (xthick * 2), height - (ythick * 2));
3998 if (detail && !strcmp (detail, "paned"))
4000 if (orientation == GTK_ORIENTATION_HORIZONTAL)
4001 for (xx = x + width/2 - 15; xx <= x + width/2 + 15; xx += 5)
4002 draw_dot (cr, &light, &dark, xx, y + height/2 - 1, 3);
4004 for (yy = y + height/2 - 15; yy <= y + height/2 + 15; yy += 5)
4005 draw_dot (cr, &light, &dark, x + width/2 - 1, yy, 3);
4009 for (yy = y + ythick; yy < (y + height - ythick); yy += 3)
4010 for (xx = x + xthick; xx < (x + width - xthick); xx += 6)
4012 draw_dot (cr, &light, &dark, xx, yy, 2);
4013 draw_dot (cr, &light, &dark, xx + 3, yy + 1, 2);
4021 gtk_default_draw_expander (GtkStyle *style,
4023 GtkStateType state_type,
4026 const gchar *detail,
4029 GtkExpanderStyle expander_style)
4031 #define DEFAULT_EXPANDER_SIZE 12
4035 double vertical_overshoot;
4038 double interp; /* interpolation factor for center position */
4039 double x_double_horz, y_double_horz;
4040 double x_double_vert, y_double_vert;
4041 double x_double, y_double;
4044 cairo_t *cr = gdk_cairo_create (window);
4048 gdk_cairo_rectangle (cr, area);
4053 gtk_widget_class_find_style_property (GTK_WIDGET_GET_CLASS (widget),
4056 gtk_widget_style_get (widget,
4057 "expander-size", &expander_size,
4061 expander_size = DEFAULT_EXPANDER_SIZE;
4063 line_width = MAX (1, expander_size/9);
4065 switch (expander_style)
4067 case GTK_EXPANDER_COLLAPSED:
4068 degrees = (get_direction (widget) == GTK_TEXT_DIR_RTL) ? 180 : 0;
4071 case GTK_EXPANDER_SEMI_COLLAPSED:
4072 degrees = (get_direction (widget) == GTK_TEXT_DIR_RTL) ? 150 : 30;
4075 case GTK_EXPANDER_SEMI_EXPANDED:
4076 degrees = (get_direction (widget) == GTK_TEXT_DIR_RTL) ? 120 : 60;
4079 case GTK_EXPANDER_EXPANDED:
4084 g_assert_not_reached ();
4087 /* Compute distance that the stroke extends beyonds the end
4088 * of the triangle we draw.
4090 vertical_overshoot = line_width / 2.0 * (1. / tan (G_PI / 8));
4092 /* For odd line widths, we end the vertical line of the triangle
4093 * at a half pixel, so we round differently.
4095 if (line_width % 2 == 1)
4096 vertical_overshoot = ceil (0.5 + vertical_overshoot) - 0.5;
4098 vertical_overshoot = ceil (vertical_overshoot);
4100 /* Adjust the size of the triangle we draw so that the entire stroke fits
4102 diameter = MAX (3, expander_size - 2 * vertical_overshoot);
4104 /* If the line width is odd, we want the diameter to be even,
4105 * and vice versa, so force the sum to be odd. This relationship
4106 * makes the point of the triangle look right.
4108 diameter -= (1 - (diameter + line_width) % 2);
4110 radius = diameter / 2.;
4112 /* Adjust the center so that the stroke is properly aligned with
4113 * the pixel grid. The center adjustment is different for the
4114 * horizontal and vertical orientations. For intermediate positions
4115 * we interpolate between the two.
4117 x_double_vert = floor (x - (radius + line_width) / 2.) + (radius + line_width) / 2.;
4118 y_double_vert = y - 0.5;
4120 x_double_horz = x - 0.5;
4121 y_double_horz = floor (y - (radius + line_width) / 2.) + (radius + line_width) / 2.;
4123 x_double = x_double_vert * (1 - interp) + x_double_horz * interp;
4124 y_double = y_double_vert * (1 - interp) + y_double_horz * interp;
4126 cairo_translate (cr, x_double, y_double);
4127 cairo_rotate (cr, degrees * G_PI / 180);
4129 cairo_move_to (cr, - radius / 2., - radius);
4130 cairo_line_to (cr, radius / 2., 0);
4131 cairo_line_to (cr, - radius / 2., radius);
4132 cairo_close_path (cr);
4134 cairo_set_line_width (cr, line_width);
4136 if (state_type == GTK_STATE_PRELIGHT)
4137 gdk_cairo_set_source_color (cr,
4138 &style->fg[GTK_STATE_PRELIGHT]);
4139 else if (state_type == GTK_STATE_ACTIVE)
4140 gdk_cairo_set_source_color (cr,
4141 &style->light[GTK_STATE_ACTIVE]);
4143 gdk_cairo_set_source_color (cr,
4144 &style->base[GTK_STATE_NORMAL]);
4146 cairo_fill_preserve (cr);
4148 gdk_cairo_set_source_color (cr, &style->fg[state_type]);
4155 gtk_default_draw_layout (GtkStyle *style,
4157 GtkStateType state_type,
4161 const gchar *detail,
4164 PangoLayout *layout)
4168 const PangoMatrix *matrix;
4170 cr = gdk_cairo_create (window);
4174 gdk_cairo_rectangle (cr, area);
4178 matrix = pango_context_get_matrix (pango_layout_get_context (layout));
4181 cairo_matrix_t cairo_matrix;
4182 PangoMatrix tmp_matrix;
4183 PangoRectangle rect;
4185 cairo_matrix_init (&cairo_matrix,
4186 matrix->xx, matrix->yx,
4187 matrix->xy, matrix->yy,
4188 matrix->x0, matrix->y0);
4190 pango_layout_get_extents (layout, NULL, &rect);
4191 pango_matrix_transform_rectangle (matrix, &rect);
4192 pango_extents_to_pixels (&rect, NULL);
4194 tmp_matrix = *matrix;
4195 cairo_matrix.x0 += x - rect.x;
4196 cairo_matrix.y0 += y - rect.y;
4198 cairo_set_matrix (cr, &cairo_matrix);
4201 cairo_translate (cr, x, y);
4203 cairo_new_path (cr);
4205 if (state_type == GTK_STATE_INSENSITIVE)
4207 gdk_cairo_set_source_color (cr, &style->white);
4208 cairo_move_to (cr, 1, 1);
4209 _gtk_pango_fill_layout (cr, layout);
4210 cairo_new_path (cr);
4213 gc = use_text ? &style->text[state_type] : &style->fg[state_type];
4215 gdk_cairo_set_source_color (cr, gc);
4217 pango_cairo_show_layout (cr, layout);
4223 gtk_default_draw_resize_grip (GtkStyle *style,
4225 GtkStateType state_type,
4228 const gchar *detail,
4238 cr = gdk_cairo_create (window);
4239 cairo_rectangle (cr, x, y, width, height);
4243 gdk_cairo_rectangle (cr, area);
4247 cairo_set_line_width (cr, 1.0);
4252 case GDK_WINDOW_EDGE_NORTH_WEST:
4253 /* make it square */
4256 else if (height < width)
4260 case GDK_WINDOW_EDGE_NORTH:
4264 case GDK_WINDOW_EDGE_NORTH_EAST:
4265 /* make it square, aligning to top right */
4268 else if (height < width)
4270 x += (width - height);
4275 case GDK_WINDOW_EDGE_WEST:
4279 case GDK_WINDOW_EDGE_EAST:
4280 /* aligning to right */
4283 x += (width - height);
4287 case GDK_WINDOW_EDGE_SOUTH_WEST:
4288 /* make it square, aligning to bottom left */
4291 y += (height - width);
4294 else if (height < width)
4298 case GDK_WINDOW_EDGE_SOUTH:
4299 /* align to bottom */
4302 y += (height - width);
4306 case GDK_WINDOW_EDGE_SOUTH_EAST:
4307 /* make it square, aligning to bottom right */
4310 y += (height - width);
4313 else if (height < width)
4315 x += (width - height);
4321 g_assert_not_reached ();
4326 case GDK_WINDOW_EDGE_WEST:
4327 case GDK_WINDOW_EDGE_EAST:
4333 while (xi < x + width)
4335 _cairo_draw_line (cr,
4336 &style->light[state_type],
4341 _cairo_draw_line (cr,
4342 &style->dark[state_type],
4350 case GDK_WINDOW_EDGE_NORTH:
4351 case GDK_WINDOW_EDGE_SOUTH:
4357 while (yi < y + height)
4359 _cairo_draw_line (cr,
4360 &style->light[state_type],
4365 _cairo_draw_line (cr,
4366 &style->dark[state_type],
4374 case GDK_WINDOW_EDGE_NORTH_WEST:
4383 _cairo_draw_line (cr,
4384 &style->dark[state_type],
4391 _cairo_draw_line (cr,
4392 &style->dark[state_type],
4399 _cairo_draw_line (cr,
4400 &style->light[state_type],
4410 case GDK_WINDOW_EDGE_NORTH_EAST:
4417 while (xi < (x + width - 3))
4419 _cairo_draw_line (cr,
4420 &style->light[state_type],
4427 _cairo_draw_line (cr,
4428 &style->dark[state_type],
4435 _cairo_draw_line (cr,
4436 &style->dark[state_type],
4445 case GDK_WINDOW_EDGE_SOUTH_WEST:
4454 _cairo_draw_line (cr,
4455 &style->dark[state_type],
4462 _cairo_draw_line (cr,
4463 &style->dark[state_type],
4470 _cairo_draw_line (cr,
4471 &style->light[state_type],
4481 case GDK_WINDOW_EDGE_SOUTH_EAST:
4488 while (xi < (x + width - 3))
4490 _cairo_draw_line (cr,
4491 &style->light[state_type],
4498 _cairo_draw_line (cr,
4499 &style->dark[state_type],
4506 _cairo_draw_line (cr,
4507 &style->dark[state_type],
4517 g_assert_not_reached ();
4525 gtk_default_draw_spinner (GtkStyle *style,
4527 GtkStateType state_type,
4530 const gchar *detail,
4546 gtk_style_get (style, GTK_TYPE_SPINNER,
4547 "num-steps", &num_steps,
4549 real_step = step % num_steps;
4551 /* get cairo context */
4552 cr = gdk_cairo_create (window);
4554 /* set a clip region for the expose event */
4555 cairo_rectangle (cr, x, y, width, height);
4558 cairo_translate (cr, x, y);
4560 /* draw clip region */
4561 cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
4563 color = &style->fg[state_type];
4566 radius = MIN (width / 2, height / 2);
4567 half = num_steps / 2;
4569 for (i = 0; i < num_steps; i++)
4571 gint inset = 0.7 * radius;
4573 /* transparency is a function of time and intial value */
4574 gdouble t = (gdouble) ((i + num_steps - real_step)
4575 % num_steps) / num_steps;
4579 cairo_set_source_rgba (cr,
4580 color->red / 65535.,
4581 color->green / 65535.,
4582 color->blue / 65535.,
4585 cairo_set_line_width (cr, 2.0);
4587 dx + (radius - inset) * cos (i * G_PI / half),
4588 dy + (radius - inset) * sin (i * G_PI / half));
4590 dx + radius * cos (i * G_PI / half),
4591 dy + radius * sin (i * G_PI / half));
4602 _gtk_style_shade (const GdkColor *a,
4610 red = (gdouble) a->red / 65535.0;
4611 green = (gdouble) a->green / 65535.0;
4612 blue = (gdouble) a->blue / 65535.0;
4614 rgb_to_hls (&red, &green, &blue);
4619 else if (green < 0.0)
4625 else if (blue < 0.0)
4628 hls_to_rgb (&red, &green, &blue);
4630 b->red = red * 65535.0;
4631 b->green = green * 65535.0;
4632 b->blue = blue * 65535.0;
4636 rgb_to_hls (gdouble *r,
4677 l = (max + min) / 2;
4684 s = (max - min) / (max + min);
4686 s = (max - min) / (2 - max - min);
4690 h = (green - blue) / delta;
4691 else if (green == max)
4692 h = 2 + (blue - red) / delta;
4693 else if (blue == max)
4694 h = 4 + (red - green) / delta;
4707 hls_to_rgb (gdouble *h,
4720 if (lightness <= 0.5)
4721 m2 = lightness * (1 + saturation);
4723 m2 = lightness + saturation - lightness * saturation;
4724 m1 = 2 * lightness - m2;
4726 if (saturation == 0)
4741 r = m1 + (m2 - m1) * hue / 60;
4745 r = m1 + (m2 - m1) * (240 - hue) / 60;
4756 g = m1 + (m2 - m1) * hue / 60;
4760 g = m1 + (m2 - m1) * (240 - hue) / 60;
4771 b = m1 + (m2 - m1) * hue / 60;
4775 b = m1 + (m2 - m1) * (240 - hue) / 60;
4787 gtk_style_cairo_create (GdkWindow *window, const GdkRectangle *area)
4791 cr = gdk_cairo_create (window);
4795 gdk_cairo_rectangle (cr, area);
4804 * @style: a #GtkStyle
4805 * @window: a #GdkWindow
4806 * @state_type: a state
4807 * @area: (allow-none): rectangle to which the output is clipped, or %NULL if the
4808 * output should not be clipped
4809 * @widget: (allow-none): the widget
4810 * @detail: (allow-none): a style detail
4811 * @x1: the starting x coordinate
4812 * @x2: the ending x coordinate
4813 * @y: the y coordinate
4815 * Draws a horizontal line from (@x1, @y) to (@x2, @y) in @window
4816 * using the given style and state.
4819 gtk_paint_hline (GtkStyle *style,
4821 GtkStateType state_type,
4822 const GdkRectangle *area,
4824 const gchar *detail,
4831 g_return_if_fail (GTK_IS_STYLE (style));
4832 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_hline != NULL);
4833 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
4835 cr = gtk_style_cairo_create (window, area);
4837 gtk_cairo_paint_hline (style, cr, state_type,
4845 * gtk_cairo_paint_hline:
4846 * @style: a #GtkStyle
4848 * @state_type: a state
4849 * @widget: (allow-none): the widget
4850 * @detail: (allow-none): a style detail
4851 * @x1: the starting x coordinate
4852 * @x2: the ending x coordinate
4853 * @y: the y coordinate
4855 * Draws a horizontal line from (@x1, @y) to (@x2, @y) in @cr
4856 * using the given style and state.
4859 gtk_cairo_paint_hline (GtkStyle *style,
4861 GtkStateType state_type,
4863 const gchar *detail,
4868 g_return_if_fail (GTK_IS_STYLE (style));
4869 g_return_if_fail (cr != NULL);
4870 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_hline != NULL);
4874 GTK_STYLE_GET_CLASS (style)->draw_hline (style, cr, state_type,
4883 * @style: a #GtkStyle
4884 * @window: a #GdkWindow
4885 * @state_type: a state
4886 * @area: (allow-none): rectangle to which the output is clipped, or %NULL if the
4887 * output should not be clipped
4888 * @widget: (allow-none): the widget
4889 * @detail: (allow-none): a style detail
4890 * @y1_: the starting y coordinate
4891 * @y2_: the ending y coordinate
4892 * @x: the x coordinate
4894 * Draws a vertical line from (@x, @y1_) to (@x, @y2_) in @window
4895 * using the given style and state.
4898 gtk_paint_vline (GtkStyle *style,
4900 GtkStateType state_type,
4901 const GdkRectangle *area,
4903 const gchar *detail,
4908 g_return_if_fail (GTK_IS_STYLE (style));
4909 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_vline != NULL);
4910 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
4912 GTK_STYLE_GET_CLASS (style)->draw_vline (style, window, state_type,
4913 (GdkRectangle *) area, widget, detail,
4919 * @style: a #GtkStyle
4920 * @window: a #GdkWindow
4921 * @state_type: a state
4922 * @shadow_type: type of shadow to draw
4923 * @area: (allow-none): clip rectangle or %NULL if the
4924 * output should not be clipped
4925 * @widget: (allow-none): the widget
4926 * @detail: (allow-none): a style detail
4927 * @x: x origin of the rectangle
4928 * @y: y origin of the rectangle
4929 * @width: width of the rectangle
4930 * @height: width of the rectangle
4932 * Draws a shadow around the given rectangle in @window
4933 * using the given style and state and shadow type.
4936 gtk_paint_shadow (GtkStyle *style,
4938 GtkStateType state_type,
4939 GtkShadowType shadow_type,
4940 const GdkRectangle *area,
4942 const gchar *detail,
4948 g_return_if_fail (GTK_IS_STYLE (style));
4949 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow != NULL);
4950 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
4952 GTK_STYLE_GET_CLASS (style)->draw_shadow (style, window, state_type, shadow_type,
4953 (GdkRectangle *) area, widget, detail,
4954 x, y, width, height);
4959 * @style: a #GtkStyle
4960 * @window: a #GdkWindow
4961 * @state_type: a state
4962 * @shadow_type: the type of shadow to draw
4963 * @area: (allow-none): clip rectangle, or %NULL if the
4964 * output should not be clipped
4965 * @widget: (allow-none): the widget
4966 * @detail: (allow-none): a style detail
4967 * @arrow_type: the type of arrow to draw
4968 * @fill: %TRUE if the arrow tip should be filled
4969 * @x: x origin of the rectangle to draw the arrow in
4970 * @y: y origin of the rectangle to draw the arrow in
4971 * @width: width of the rectangle to draw the arrow in
4972 * @height: height of the rectangle to draw the arrow in
4974 * Draws an arrow in the given rectangle on @window using the given
4975 * parameters. @arrow_type determines the direction of the arrow.
4978 gtk_paint_arrow (GtkStyle *style,
4980 GtkStateType state_type,
4981 GtkShadowType shadow_type,
4982 const GdkRectangle *area,
4984 const gchar *detail,
4985 GtkArrowType arrow_type,
4992 g_return_if_fail (GTK_IS_STYLE (style));
4993 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_arrow != NULL);
4994 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
4996 GTK_STYLE_GET_CLASS (style)->draw_arrow (style, window, state_type, shadow_type,
4997 (GdkRectangle *) area, widget, detail,
4998 arrow_type, fill, x, y, width, height);
5002 * gtk_paint_diamond:
5003 * @style: a #GtkStyle
5004 * @window: a #GdkWindow
5005 * @state_type: a state
5006 * @shadow_type: the type of shadow to draw
5007 * @area: (allow-none): clip rectangle, or %NULL if the
5008 * output should not be clipped
5009 * @widget: (allow-none): the widget
5010 * @detail: (allow-none): a style detail
5011 * @x: x origin of the rectangle to draw the diamond in
5012 * @y: y origin of the rectangle to draw the diamond in
5013 * @width: width of the rectangle to draw the diamond in
5014 * @height: height of the rectangle to draw the diamond in
5016 * Draws a diamond in the given rectangle on @window using the given
5020 gtk_paint_diamond (GtkStyle *style,
5022 GtkStateType state_type,
5023 GtkShadowType shadow_type,
5024 const GdkRectangle *area,
5026 const gchar *detail,
5032 g_return_if_fail (GTK_IS_STYLE (style));
5033 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_diamond != NULL);
5034 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5036 GTK_STYLE_GET_CLASS (style)->draw_diamond (style, window, state_type, shadow_type,
5037 (GdkRectangle *) area, widget, detail,
5038 x, y, width, height);
5043 * @style: a #GtkStyle
5044 * @window: a #GdkWindow
5045 * @state_type: a state
5046 * @shadow_type: the type of shadow to draw
5047 * @area: (allow-none): clip rectangle, or %NULL if the
5048 * output should not be clipped
5049 * @widget: (allow-none): the widget
5050 * @detail: (allow-none): a style detail
5051 * @x: x origin of the box
5052 * @y: y origin of the box
5053 * @width: the width of the box
5054 * @height: the height of the box
5056 * Draws a box on @window with the given parameters.
5059 gtk_paint_box (GtkStyle *style,
5061 GtkStateType state_type,
5062 GtkShadowType shadow_type,
5063 const GdkRectangle *area,
5065 const gchar *detail,
5071 g_return_if_fail (GTK_IS_STYLE (style));
5072 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box != NULL);
5073 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5075 GTK_STYLE_GET_CLASS (style)->draw_box (style, window, state_type, shadow_type,
5076 (GdkRectangle *) area, widget, detail,
5077 x, y, width, height);
5081 * gtk_paint_flat_box:
5082 * @style: a #GtkStyle
5083 * @window: a #GdkWindow
5084 * @state_type: a state
5085 * @shadow_type: the type of shadow to draw
5086 * @area: (allow-none): clip rectangle, or %NULL if the
5087 * output should not be clipped
5088 * @widget: (allow-none): the widget
5089 * @detail: (allow-none): a style detail
5090 * @x: x origin of the box
5091 * @y: y origin of the box
5092 * @width: the width of the box
5093 * @height: the height of the box
5095 * Draws a flat box on @window with the given parameters.
5098 gtk_paint_flat_box (GtkStyle *style,
5100 GtkStateType state_type,
5101 GtkShadowType shadow_type,
5102 const GdkRectangle *area,
5104 const gchar *detail,
5110 g_return_if_fail (GTK_IS_STYLE (style));
5111 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_flat_box != NULL);
5112 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5114 GTK_STYLE_GET_CLASS (style)->draw_flat_box (style, window, state_type, shadow_type,
5115 (GdkRectangle *) area, widget, detail,
5116 x, y, width, height);
5121 * @style: a #GtkStyle
5122 * @window: a #GdkWindow
5123 * @state_type: a state
5124 * @shadow_type: the type of shadow to draw
5125 * @area: (allow-none): clip rectangle, or %NULL if the
5126 * output should not be clipped
5127 * @widget: (allow-none): the widget
5128 * @detail: (allow-none): a style detail
5129 * @x: x origin of the rectangle to draw the check in
5130 * @y: y origin of the rectangle to draw the check in
5131 * @width: the width of the rectangle to draw the check in
5132 * @height: the height of the rectangle to draw the check in
5134 * Draws a check button indicator in the given rectangle on @window with
5135 * the given parameters.
5138 gtk_paint_check (GtkStyle *style,
5140 GtkStateType state_type,
5141 GtkShadowType shadow_type,
5142 const GdkRectangle *area,
5144 const gchar *detail,
5150 g_return_if_fail (GTK_IS_STYLE (style));
5151 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_check != NULL);
5152 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5154 GTK_STYLE_GET_CLASS (style)->draw_check (style, window, state_type, shadow_type,
5155 (GdkRectangle *) area, widget, detail,
5156 x, y, width, height);
5161 * @style: a #GtkStyle
5162 * @window: a #GdkWindow
5163 * @state_type: a state
5164 * @shadow_type: the type of shadow to draw
5165 * @area: (allow-none): clip rectangle, or %NULL if the
5166 * output should not be clipped
5167 * @widget: (allow-none): the widget
5168 * @detail: (allow-none): a style detail
5169 * @x: x origin of the rectangle to draw the option in
5170 * @y: y origin of the rectangle to draw the option in
5171 * @width: the width of the rectangle to draw the option in
5172 * @height: the height of the rectangle to draw the option in
5174 * Draws a radio button indicator in the given rectangle on @window with
5175 * the given parameters.
5178 gtk_paint_option (GtkStyle *style,
5180 GtkStateType state_type,
5181 GtkShadowType shadow_type,
5182 const GdkRectangle *area,
5184 const gchar *detail,
5190 g_return_if_fail (GTK_IS_STYLE (style));
5191 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_option != NULL);
5192 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5194 GTK_STYLE_GET_CLASS (style)->draw_option (style, window, state_type, shadow_type,
5195 (GdkRectangle *) area, widget, detail,
5196 x, y, width, height);
5201 * @style: a #GtkStyle
5202 * @window: a #GdkWindow
5203 * @state_type: a state
5204 * @shadow_type: the type of shadow to draw
5205 * @area: (allow-none): clip rectangle, or %NULL if the
5206 * output should not be clipped
5207 * @widget: (allow-none): the widget
5208 * @detail: (allow-none): a style detail
5209 * @x: x origin of the rectangle to draw the tab in
5210 * @y: y origin of the rectangle to draw the tab in
5211 * @width: the width of the rectangle to draw the tab in
5212 * @height: the height of the rectangle to draw the tab in
5214 * Draws an option menu tab (i.e. the up and down pointing arrows)
5215 * in the given rectangle on @window using the given parameters.
5218 gtk_paint_tab (GtkStyle *style,
5220 GtkStateType state_type,
5221 GtkShadowType shadow_type,
5222 const GdkRectangle *area,
5224 const gchar *detail,
5230 g_return_if_fail (GTK_IS_STYLE (style));
5231 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_tab != NULL);
5232 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5234 GTK_STYLE_GET_CLASS (style)->draw_tab (style, window, state_type, shadow_type,
5235 (GdkRectangle *) area, widget, detail,
5236 x, y, width, height);
5240 * gtk_paint_shadow_gap:
5241 * @style: a #GtkStyle
5242 * @window: a #GdkWindow
5243 * @state_type: a state
5244 * @shadow_type: type of shadow to draw
5245 * @area: (allow-none): clip rectangle, or %NULL if the
5246 * output should not be clipped
5247 * @widget: (allow-none): the widget
5248 * @detail: (allow-none): a style detail
5249 * @x: x origin of the rectangle
5250 * @y: y origin of the rectangle
5251 * @width: width of the rectangle
5252 * @height: width of the rectangle
5253 * @gap_side: side in which to leave the gap
5254 * @gap_x: starting position of the gap
5255 * @gap_width: width of the gap
5257 * Draws a shadow around the given rectangle in @window
5258 * using the given style and state and shadow type, leaving a
5262 gtk_paint_shadow_gap (GtkStyle *style,
5264 GtkStateType state_type,
5265 GtkShadowType shadow_type,
5266 const GdkRectangle *area,
5268 const gchar *detail,
5273 GtkPositionType gap_side,
5277 g_return_if_fail (GTK_IS_STYLE (style));
5278 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow_gap != NULL);
5279 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5281 GTK_STYLE_GET_CLASS (style)->draw_shadow_gap (style, window, state_type, shadow_type,
5282 (GdkRectangle *) area, widget, detail,
5283 x, y, width, height, gap_side, gap_x, gap_width);
5288 * gtk_paint_box_gap:
5289 * @style: a #GtkStyle
5290 * @window: a #GdkWindow
5291 * @state_type: a state
5292 * @shadow_type: type of shadow to draw
5293 * @area: (allow-none): clip rectangle, or %NULL if the
5294 * output should not be clipped
5295 * @widget: (allow-none): the widget
5296 * @detail: (allow-none): a style detail
5297 * @x: x origin of the rectangle
5298 * @y: y origin of the rectangle
5299 * @width: width of the rectangle
5300 * @height: width of the rectangle
5301 * @gap_side: side in which to leave the gap
5302 * @gap_x: starting position of the gap
5303 * @gap_width: width of the gap
5305 * Draws a box in @window using the given style and state and shadow type,
5306 * leaving a gap in one side.
5309 gtk_paint_box_gap (GtkStyle *style,
5311 GtkStateType state_type,
5312 GtkShadowType shadow_type,
5313 const GdkRectangle *area,
5315 const gchar *detail,
5320 GtkPositionType gap_side,
5324 g_return_if_fail (GTK_IS_STYLE (style));
5325 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box_gap != NULL);
5326 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5328 GTK_STYLE_GET_CLASS (style)->draw_box_gap (style, window, state_type, shadow_type,
5329 (GdkRectangle *) area, widget, detail,
5330 x, y, width, height, gap_side, gap_x, gap_width);
5334 * gtk_paint_extension:
5335 * @style: a #GtkStyle
5336 * @window: a #GdkWindow
5337 * @state_type: a state
5338 * @shadow_type: type of shadow to draw
5339 * @area: (allow-none): clip rectangle, or %NULL if the
5340 * output should not be clipped
5341 * @widget: (allow-none): the widget
5342 * @detail: (allow-none): a style detail
5343 * @x: x origin of the extension
5344 * @y: y origin of the extension
5345 * @width: width of the extension
5346 * @height: width of the extension
5347 * @gap_side: the side on to which the extension is attached
5349 * Draws an extension, i.e. a notebook tab.
5352 gtk_paint_extension (GtkStyle *style,
5354 GtkStateType state_type,
5355 GtkShadowType shadow_type,
5356 const GdkRectangle *area,
5358 const gchar *detail,
5363 GtkPositionType gap_side)
5365 g_return_if_fail (GTK_IS_STYLE (style));
5366 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_extension != NULL);
5367 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5369 GTK_STYLE_GET_CLASS (style)->draw_extension (style, window, state_type, shadow_type,
5370 (GdkRectangle *) area, widget, detail,
5371 x, y, width, height, gap_side);
5376 * @style: a #GtkStyle
5377 * @window: a #GdkWindow
5378 * @state_type: a state
5379 * @area: (allow-none): clip rectangle, or %NULL if the
5380 * output should not be clipped
5381 * @widget: (allow-none): the widget
5382 * @detail: (allow-none): a style detail
5383 * @x: the x origin of the rectangle around which to draw a focus indicator
5384 * @y: the y origin of the rectangle around which to draw a focus indicator
5385 * @width: the width of the rectangle around which to draw a focus indicator
5386 * @height: the height of the rectangle around which to draw a focus indicator
5388 * Draws a focus indicator around the given rectangle on @window using the
5392 gtk_paint_focus (GtkStyle *style,
5394 GtkStateType state_type,
5395 const GdkRectangle *area,
5397 const gchar *detail,
5403 g_return_if_fail (GTK_IS_STYLE (style));
5404 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_focus != NULL);
5405 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5407 GTK_STYLE_GET_CLASS (style)->draw_focus (style, window, state_type,
5408 (GdkRectangle *) area, widget, detail,
5409 x, y, width, height);
5414 * @style: a #GtkStyle
5415 * @window: a #GdkWindow
5416 * @state_type: a state
5417 * @shadow_type: a shadow
5418 * @area: (allow-none): clip rectangle, or %NULL if the
5419 * output should not be clipped
5420 * @widget: (allow-none): the widget
5421 * @detail: (allow-none): a style detail
5422 * @x: the x origin of the rectangle in which to draw a slider
5423 * @y: the y origin of the rectangle in which to draw a slider
5424 * @width: the width of the rectangle in which to draw a slider
5425 * @height: the height of the rectangle in which to draw a slider
5426 * @orientation: the orientation to be used
5428 * Draws a slider in the given rectangle on @window using the
5429 * given style and orientation.
5432 gtk_paint_slider (GtkStyle *style,
5434 GtkStateType state_type,
5435 GtkShadowType shadow_type,
5436 const GdkRectangle *area,
5438 const gchar *detail,
5443 GtkOrientation orientation)
5445 g_return_if_fail (GTK_IS_STYLE (style));
5446 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_slider != NULL);
5447 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5449 GTK_STYLE_GET_CLASS (style)->draw_slider (style, window, state_type, shadow_type,
5450 (GdkRectangle *) area, widget, detail,
5451 x, y, width, height, orientation);
5456 * @style: a #GtkStyle
5457 * @window: a #GdkWindow
5458 * @state_type: a state
5459 * @shadow_type: type of shadow to draw
5460 * @area: (allow-none): clip rectangle, or %NULL if the
5461 * output should not be clipped
5462 * @widget: (allow-none): the widget
5463 * @detail: (allow-none): a style detail
5464 * @x: x origin of the handle
5465 * @y: y origin of the handle
5466 * @width: with of the handle
5467 * @height: height of the handle
5468 * @orientation: the orientation of the handle
5470 * Draws a handle as used in #GtkHandleBox and #GtkPaned.
5473 gtk_paint_handle (GtkStyle *style,
5475 GtkStateType state_type,
5476 GtkShadowType shadow_type,
5477 const GdkRectangle *area,
5479 const gchar *detail,
5484 GtkOrientation orientation)
5486 g_return_if_fail (GTK_IS_STYLE (style));
5487 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_handle != NULL);
5488 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5490 GTK_STYLE_GET_CLASS (style)->draw_handle (style, window, state_type, shadow_type,
5491 (GdkRectangle *) area, widget, detail,
5492 x, y, width, height, orientation);
5496 * gtk_paint_expander:
5497 * @style: a #GtkStyle
5498 * @window: a #GdkWindow
5499 * @state_type: a state
5500 * @area: (allow-none): clip rectangle, or %NULL if the
5501 * output should not be clipped
5502 * @widget: (allow-none): the widget
5503 * @detail: (allow-none): a style detail
5504 * @x: the x position to draw the expander at
5505 * @y: the y position to draw the expander at
5506 * @expander_style: the style to draw the expander in; determines
5507 * whether the expander is collapsed, expanded, or in an
5508 * intermediate state.
5510 * Draws an expander as used in #GtkTreeView. @x and @y specify the
5511 * center the expander. The size of the expander is determined by the
5512 * "expander-size" style property of @widget. (If widget is not
5513 * specified or doesn't have an "expander-size" property, an
5514 * unspecified default size will be used, since the caller doesn't
5515 * have sufficient information to position the expander, this is
5516 * likely not useful.) The expander is expander_size pixels tall
5517 * in the collapsed position and expander_size pixels wide in the
5518 * expanded position.
5521 gtk_paint_expander (GtkStyle *style,
5523 GtkStateType state_type,
5524 const GdkRectangle *area,
5526 const gchar *detail,
5529 GtkExpanderStyle expander_style)
5531 g_return_if_fail (GTK_IS_STYLE (style));
5532 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_expander != NULL);
5533 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5535 GTK_STYLE_GET_CLASS (style)->draw_expander (style, window, state_type,
5536 (GdkRectangle *) area, widget, detail,
5537 x, y, expander_style);
5542 * @style: a #GtkStyle
5543 * @window: a #GdkWindow
5544 * @state_type: a state
5545 * @use_text: whether to use the text or foreground
5546 * graphics context of @style
5547 * @area: (allow-none): clip rectangle, or %NULL if the
5548 * output should not be clipped
5549 * @widget: (allow-none): the widget
5550 * @detail: (allow-none): a style detail
5553 * @layout: the layout to draw
5555 * Draws a layout on @window using the given parameters.
5558 gtk_paint_layout (GtkStyle *style,
5560 GtkStateType state_type,
5562 const GdkRectangle *area,
5564 const gchar *detail,
5567 PangoLayout *layout)
5569 g_return_if_fail (GTK_IS_STYLE (style));
5570 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_layout != NULL);
5571 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5573 GTK_STYLE_GET_CLASS (style)->draw_layout (style, window, state_type, use_text,
5574 (GdkRectangle *) area, widget, detail,
5579 * gtk_paint_resize_grip:
5580 * @style: a #GtkStyle
5581 * @window: a #GdkWindow
5582 * @state_type: a state
5583 * @area: (allow-none): clip rectangle, or %NULL if the
5584 * output should not be clipped
5585 * @widget: (allow-none): the widget
5586 * @detail: (allow-none): a style detail
5587 * @edge: the edge in which to draw the resize grip
5588 * @x: the x origin of the rectangle in which to draw the resize grip
5589 * @y: the y origin of the rectangle in which to draw the resize grip
5590 * @width: the width of the rectangle in which to draw the resize grip
5591 * @height: the height of the rectangle in which to draw the resize grip
5593 * Draws a resize grip in the given rectangle on @window using the given
5597 gtk_paint_resize_grip (GtkStyle *style,
5599 GtkStateType state_type,
5600 const GdkRectangle *area,
5602 const gchar *detail,
5610 g_return_if_fail (GTK_IS_STYLE (style));
5611 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_resize_grip != NULL);
5612 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5614 GTK_STYLE_GET_CLASS (style)->draw_resize_grip (style, window, state_type,
5615 (GdkRectangle *) area, widget, detail,
5616 edge, x, y, width, height);
5620 * gtk_paint_spinner:
5621 * @style: a #GtkStyle
5622 * @window: a #GdkWindow
5623 * @state_type: a state
5624 * @area: (allow-none): clip rectangle, or %NULL if the
5625 * output should not be clipped
5626 * @widget: (allow-none): the widget (may be %NULL)
5627 * @detail: (allow-none): a style detail (may be %NULL)
5628 * @step: the nth step, a value between 0 and #GtkSpinner:num-steps
5629 * @x: the x origin of the rectangle in which to draw the spinner
5630 * @y: the y origin of the rectangle in which to draw the spinner
5631 * @width: the width of the rectangle in which to draw the spinner
5632 * @height: the height of the rectangle in which to draw the spinner
5634 * Draws a spinner on @window using the given parameters.
5639 gtk_paint_spinner (GtkStyle *style,
5641 GtkStateType state_type,
5642 const GdkRectangle *area,
5644 const gchar *detail,
5651 g_return_if_fail (GTK_IS_STYLE (style));
5652 g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_spinner != NULL);
5653 g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5655 GTK_STYLE_GET_CLASS (style)->draw_spinner (style, window, state_type,
5656 (GdkRectangle *)area, widget, detail,
5657 step, x, y, width, height);
5663 * Allocates a new #GtkBorder structure and initializes its elements to zero.
5665 * Returns: a new empty #GtkBorder. The newly allocated #GtkBorder should be
5666 * freed with gtk_border_free()
5671 gtk_border_new (void)
5673 return g_slice_new0 (GtkBorder);
5678 * @border_: a #GtkBorder.
5679 * @returns: a copy of @border_.
5681 * Copies a #GtkBorder structure.
5684 gtk_border_copy (const GtkBorder *border)
5686 g_return_val_if_fail (border != NULL, NULL);
5688 return g_slice_dup (GtkBorder, border);
5693 * @border_: a #GtkBorder.
5695 * Frees a #GtkBorder structure.
5698 gtk_border_free (GtkBorder *border)
5700 g_slice_free (GtkBorder, border);
5703 G_DEFINE_BOXED_TYPE (GtkBorder, gtk_border,
5707 typedef struct _CursorInfo CursorInfo;
5717 style_unrealize_cursors (GtkStyle *style)
5721 cursor_info = g_object_get_data (G_OBJECT (style), "gtk-style-cursor-info");
5724 g_free (cursor_info);
5725 g_object_set_data (G_OBJECT (style), I_("gtk-style-cursor-info"), NULL);
5729 static const GdkColor *
5730 get_insertion_cursor_color (GtkWidget *widget,
5731 gboolean is_primary)
5733 CursorInfo *cursor_info;
5735 GdkColor *cursor_color;
5737 style = gtk_widget_get_style (widget);
5739 cursor_info = g_object_get_data (G_OBJECT (style), "gtk-style-cursor-info");
5742 cursor_info = g_new0 (CursorInfo, 1);
5743 g_object_set_data (G_OBJECT (style), I_("gtk-style-cursor-info"), cursor_info);
5744 cursor_info->for_type = G_TYPE_INVALID;
5747 /* We have to keep track of the type because gtk_widget_style_get()
5748 * can return different results when called on the same property and
5749 * same style but for different widgets. :-(. That is,
5750 * GtkEntry::cursor-color = "red" in a style will modify the cursor
5751 * color for entries but not for text view.
5753 if (cursor_info->for_type != G_OBJECT_TYPE (widget))
5755 cursor_info->for_type = G_OBJECT_TYPE (widget);
5757 /* Cursors in text widgets are drawn only in NORMAL state,
5758 * so we can use text[GTK_STATE_NORMAL] as text color here */
5759 gtk_widget_style_get (widget, "cursor-color", &cursor_color, NULL);
5762 cursor_info->primary = *cursor_color;
5763 gdk_color_free (cursor_color);
5767 cursor_info->primary = style->text[GTK_STATE_NORMAL];
5770 gtk_widget_style_get (widget, "secondary-cursor-color", &cursor_color, NULL);
5773 cursor_info->secondary = *cursor_color;
5774 gdk_color_free (cursor_color);
5778 /* text_aa is the average of text and base colors,
5779 * in usual black-on-white case it's grey. */
5780 cursor_info->secondary = style->text_aa[GTK_STATE_NORMAL];
5785 return &cursor_info->primary;
5787 return &cursor_info->secondary;
5791 _gtk_widget_get_cursor_color (GtkWidget *widget,
5794 GdkColor *style_color;
5796 g_return_if_fail (GTK_IS_WIDGET (widget));
5797 g_return_if_fail (color != NULL);
5799 gtk_widget_style_get (widget, "cursor-color", &style_color, NULL);
5803 *color = *style_color;
5804 gdk_color_free (style_color);
5807 *color = gtk_widget_get_style (widget)->text[GTK_STATE_NORMAL];
5811 draw_insertion_cursor (GtkWidget *widget,
5813 const GdkRectangle *location,
5814 GtkTextDirection direction,
5815 gboolean draw_arrow)
5820 gfloat cursor_aspect_ratio;
5823 /* When changing the shape or size of the cursor here,
5824 * propagate the changes to gtktextview.c:text_window_invalidate_cursors().
5827 gtk_widget_style_get (widget, "cursor-aspect-ratio", &cursor_aspect_ratio, NULL);
5829 stem_width = location->height * cursor_aspect_ratio + 1;
5830 arrow_width = stem_width + 1;
5832 /* put (stem_width % 2) on the proper side of the cursor */
5833 if (direction == GTK_TEXT_DIR_LTR)
5834 offset = stem_width / 2;
5836 offset = stem_width - stem_width / 2;
5838 cairo_rectangle (cr,
5839 location->x - offset, location->y,
5840 stem_width, location->height);
5845 if (direction == GTK_TEXT_DIR_RTL)
5847 x = location->x - offset - 1;
5848 y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
5850 cairo_move_to (cr, x, y + 1);
5851 cairo_line_to (cr, x - arrow_width, y + arrow_width);
5852 cairo_line_to (cr, x, y + 2 * arrow_width);
5855 else if (direction == GTK_TEXT_DIR_LTR)
5857 x = location->x + stem_width - offset;
5858 y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
5860 cairo_move_to (cr, x, y + 1);
5861 cairo_line_to (cr, x + arrow_width, y + arrow_width);
5862 cairo_line_to (cr, x, y + 2 * arrow_width);
5869 * gtk_draw_insertion_cursor:
5870 * @widget: a #GtkWidget
5871 * @drawable: a #GdkDrawable
5872 * @area: (allow-none): rectangle to which the output is clipped, or %NULL if the
5873 * output should not be clipped
5874 * @location: location where to draw the cursor (@location->width is ignored)
5875 * @is_primary: if the cursor should be the primary cursor color.
5876 * @direction: whether the cursor is left-to-right or
5877 * right-to-left. Should never be #GTK_TEXT_DIR_NONE
5878 * @draw_arrow: %TRUE to draw a directional arrow on the
5879 * cursor. Should be %FALSE unless the cursor is split.
5881 * Draws a text caret on @drawable at @location. This is not a style function
5882 * but merely a convenience function for drawing the standard cursor shape.
5887 gtk_draw_insertion_cursor (GtkWidget *widget,
5888 GdkDrawable *drawable,
5889 const GdkRectangle *area,
5890 const GdkRectangle *location,
5891 gboolean is_primary,
5892 GtkTextDirection direction,
5893 gboolean draw_arrow)
5897 g_return_if_fail (GTK_IS_WIDGET (widget));
5898 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
5899 g_return_if_fail (location != NULL);
5900 g_return_if_fail (direction != GTK_TEXT_DIR_NONE);
5902 cr = gdk_cairo_create (drawable);
5905 gdk_cairo_rectangle (cr, area);
5909 gdk_cairo_set_source_color (cr, get_insertion_cursor_color (widget, is_primary));
5910 draw_insertion_cursor (widget, cr, location, direction, draw_arrow);