Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--configure.in5
-rw-r--r--gtk-engine/Makefile.am1
-rw-r--r--gtk-engine/src/Makefile.am27
-rw-r--r--gtk-engine/src/cairo-support.c454
-rw-r--r--gtk-engine/src/cairo-support.h81
-rw-r--r--gtk-engine/src/ge-support.h9
-rw-r--r--gtk-engine/src/general-support.h35
-rw-r--r--gtk-engine/src/olpc_main.c23
-rw-r--r--gtk-engine/src/olpc_misc.c325
-rw-r--r--gtk-engine/src/olpc_misc.h39
-rw-r--r--gtk-engine/src/olpc_rc_style.c398
-rw-r--r--gtk-engine/src/olpc_rc_style.h93
-rw-r--r--gtk-engine/src/olpc_style.h29
-rw-r--r--gtk-engine/src/olpc_theme_draw.c1478
-rw-r--r--gtk-engine/src/widget-information.c331
-rw-r--r--gtk-engine/src/widget-information.h104
-rw-r--r--gtk-engine/theme/Makefile.am5
-rw-r--r--gtk-engine/theme/gtkrc102
-rw-r--r--gtkrc2-default1
-rwxr-xr-xsetup-user-theme.py38
-rwxr-xr-xtest/gtk-engine-test.py54
22 files changed, 3633 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index d74ad4b..b043bfd 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = art po matchbox
+SUBDIRS = art gtk-engine po matchbox
intltool_extra = intltool-extract.in intltool-merge.in intltool-update.in
diff --git a/configure.in b/configure.in
index e42db42..2ccb498 100644
--- a/configure.in
+++ b/configure.in
@@ -24,6 +24,8 @@ GDK_PIXBUF2_LIBS=`$PKG_CONFIG --libs gdk-pixbuf-2.0`
AC_SUBST(GDK_PIXBUF2_CFLAGS)
AC_SUBST(GDK_PIXBUF2_LIBS)
+PKG_CHECK_MODULES(ENGINE, gtk+-2.0 >= 2.0 gobject-2.0 >= 2.0 cairo >= 0.1.1)
+
dnl ===========================================================================
dnl Use lots of warning flags with GCC
@@ -53,6 +55,9 @@ art/icon-theme/scalable/control/Makefile
art/icon-theme/scalable/device/Makefile
art/icon-theme/scalable/stock/Makefile
art/icon-theme/scalable/object/Makefile
+gtk-engine/Makefile
+gtk-engine/src/Makefile
+gtk-engine/theme/Makefile
matchbox/Makefile
po/Makefile.in
])
diff --git a/gtk-engine/Makefile.am b/gtk-engine/Makefile.am
new file mode 100644
index 0000000..e5b32d9
--- /dev/null
+++ b/gtk-engine/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = src theme
diff --git a/gtk-engine/src/Makefile.am b/gtk-engine/src/Makefile.am
new file mode 100644
index 0000000..abda93e
--- /dev/null
+++ b/gtk-engine/src/Makefile.am
@@ -0,0 +1,27 @@
+INCLUDES = \
+ -DGTK_DISABLE_DEPRECATED \
+ -DGDK_DISABLE_DEPRECATED \
+ -DG_DISABLE_DEPRECATED \
+ $(ENGINE_CFLAGS) $(WARN_CFLAGS)
+
+enginedir = $(libdir)/gtk-2.0/$(GTK_VERSION)/engines
+engine_LTLIBRARIES = libolpc.la
+
+libolpc_la_SOURCES = \
+ cairo-support.c \
+ cairo-support.h \
+ general-support.h \
+ ge-support.h \
+ olpc_main.c \
+ olpc_misc.c \
+ olpc_misc.h \
+ olpc_rc_style.c \
+ olpc_rc_style.h \
+ olpc_style.h \
+ olpc_theme_draw.c \
+ widget-information.c \
+ widget-information.h
+
+libolpc_la_LDFLAGS = \
+ -avoid-version -no-undefined -module \
+ $(ENGINE_LIBS)
diff --git a/gtk-engine/src/cairo-support.c b/gtk-engine/src/cairo-support.c
new file mode 100644
index 0000000..5c90547
--- /dev/null
+++ b/gtk-engine/src/cairo-support.c
@@ -0,0 +1,454 @@
+#include "general-support.h"
+#include "cairo-support.h"
+
+/***********************************************
+ * ge_hsb_from_color -
+ *
+ * Get HSB values from RGB values.
+ *
+ * Modified from Smooth but originated in GTK+
+ ***********************************************/
+void
+ge_hsb_from_color (const CairoColor *color,
+ gdouble *hue,
+ gdouble *saturation,
+ gdouble *brightness)
+{
+ gdouble min, max, delta;
+ gdouble red, green, blue;
+
+ red = color->r;
+ green = color->g;
+ blue = color->b;
+
+ if (red > green)
+ {
+ max = MAX(red, blue);
+ min = MIN(green, blue);
+ }
+ else
+ {
+ max = MAX(green, blue);
+ min = MIN(red, blue);
+ }
+
+ *brightness = (max + min) / 2;
+
+ if (max == min)
+ {
+ *hue = 0;
+ *saturation = 0;
+ }
+ else
+ {
+ if (*brightness <= 0.5)
+ *saturation = (max - min) / (max + min);
+ else
+ *saturation = (max - min) / (2 - max - min);
+
+ delta = max -min;
+
+ if (red == max)
+ *hue = (green - blue) / delta;
+ else if (green == max)
+ *hue = 2 + (blue - red) / delta;
+ else if (blue == max)
+ *hue = 4 + (red - green) / delta;
+
+ *hue *= 60;
+ if (*hue < 0.0)
+ *hue += 360;
+ }
+}
+
+/***********************************************
+ * ge_color_from_hsb -
+ *
+ * Get RGB values from HSB values.
+ *
+ * Modified from Smooth but originated in GTK+
+ ***********************************************/
+#define MODULA(number, divisor) (((gint)number % divisor) + (number - (gint)number))
+void
+ge_color_from_hsb (gdouble hue,
+ gdouble saturation,
+ gdouble brightness,
+ CairoColor *color)
+{
+ gint i;
+ gdouble hue_shift[3], color_shift[3];
+ gdouble m1, m2, m3;
+
+ if (!color) return;
+
+ if (brightness <= 0.5)
+ m2 = brightness * (1 + saturation);
+ else
+ m2 = brightness + saturation - brightness * saturation;
+
+ m1 = 2 * brightness - m2;
+
+ hue_shift[0] = hue + 120;
+ hue_shift[1] = hue;
+ hue_shift[2] = hue - 120;
+
+ color_shift[0] = color_shift[1] = color_shift[2] = brightness;
+
+ i = (saturation == 0)?3:0;
+
+ for (; i < 3; i++)
+ {
+ m3 = hue_shift[i];
+
+ if (m3 > 360)
+ m3 = MODULA(m3, 360);
+ else if (m3 < 0)
+ m3 = 360 - MODULA(ABS(m3), 360);
+
+ if (m3 < 60)
+ color_shift[i] = m1 + (m2 - m1) * m3 / 60;
+ else if (m3 < 180)
+ color_shift[i] = m2;
+ else if (m3 < 240)
+ color_shift[i] = m1 + (m2 - m1) * (240 - m3) / 60;
+ else
+ color_shift[i] = m1;
+ }
+
+ color->r = color_shift[0];
+ color->g = color_shift[1];
+ color->b = color_shift[2];
+ color->a = 1.0;
+}
+
+void
+ge_gdk_color_to_cairo (GdkColor *c, CairoColor *cc)
+{
+ gdouble r, g, b;
+
+ g_return_if_fail (c && cc);
+
+ r = c->red / 65536.0;
+ g = c->green / 65536.0;
+ b = c->blue / 65536.0;
+
+ cc->r = r;
+ cc->g = g;
+ cc->b = b;
+ cc->a = 1.0;
+}
+
+void
+ge_cairo_color_to_gtk (CairoColor *cc, GdkColor *c)
+{
+ gdouble r, g, b;
+
+ g_return_if_fail (c && cc);
+
+ r = cc->r * 65536.0;
+ g = cc->g * 65536.0;
+ b = cc->b * 65536.0;
+
+ c->red = r;
+ c->green = g;
+ c->blue = b;
+}
+
+void
+ge_gtk_style_to_cairo_color_cube (GtkStyle * style, CairoColorCube *cube)
+{
+ int i;
+
+ g_return_if_fail (style && cube);
+
+ for (i = 0; i < 5; i++)
+ {
+ ge_gdk_color_to_cairo (&style->bg[i], &cube->bg[i]);
+ ge_gdk_color_to_cairo (&style->fg[i], &cube->fg[i]);
+
+ ge_gdk_color_to_cairo (&style->dark[i], &cube->dark[i]);
+ ge_gdk_color_to_cairo (&style->light[i], &cube->light[i]);
+ ge_gdk_color_to_cairo (&style->mid[i], &cube->mid[i]);
+
+ ge_gdk_color_to_cairo (&style->base[i], &cube->base[i]);
+ ge_gdk_color_to_cairo (&style->text[i], &cube->text[i]);
+ ge_gdk_color_to_cairo (&style->text_aa[i], &cube->text_aa[i]);
+ }
+
+ cube->black.r = cube->black.g = cube->black.b = 0;
+ cube->black.a = 1;
+
+ cube->white.r = cube->white.g = cube->white.b = 1;
+ cube->white.a = 1;
+}
+
+void
+ge_shade_color(const CairoColor *base, gdouble shade_ratio, CairoColor *composite)
+{
+ gdouble hue = 0;
+ gdouble saturation = 0;
+ gdouble brightness = 0;
+
+ g_return_if_fail (base && composite);
+
+ ge_hsb_from_color (base, &hue, &saturation, &brightness);
+
+ brightness = MIN(brightness*shade_ratio, 1.0);
+ brightness = MAX(brightness, 0.0);
+
+ saturation = MIN(saturation*shade_ratio, 1.0);
+ saturation = MAX(saturation, 0.0);
+
+ ge_color_from_hsb (hue, saturation, brightness, composite);
+ composite->a = base->a;
+}
+
+void
+ge_saturate_color (const CairoColor * base, gdouble saturate_level, CairoColor *composite)
+{
+ gdouble hue = 0;
+ gdouble saturation = 0;
+ gdouble brightness = 0;
+
+ g_return_if_fail (base && composite);
+
+ ge_hsb_from_color (base, &hue, &saturation, &brightness);
+
+ saturation = MIN(saturation*saturate_level, 1.0);
+ saturation = MAX(saturation, 0.0);
+
+ ge_color_from_hsb (hue, saturation, brightness, composite);
+ composite->a = base->a;
+}
+
+cairo_t *
+ge_gdk_drawable_to_cairo (GdkDrawable *window, GdkRectangle *area)
+{
+ cairo_t *cr;
+
+ g_return_val_if_fail (window != NULL, NULL);
+
+ cr = (cairo_t*) gdk_cairo_create (window);
+ cairo_set_line_width (cr, 1.0);
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
+ cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER);
+
+ if (area)
+ {
+ cairo_rectangle (cr, area->x, area->y, area->width, area->height);
+ cairo_clip_preserve (cr);
+ cairo_new_path (cr);
+ }
+
+ return cr;
+}
+
+void
+ge_cairo_set_color (cairo_t *cr, CairoColor *color)
+{
+ g_return_if_fail (cr && color);
+
+ cairo_set_source_rgba (cr, color->r, color->g, color->b, color->a);
+}
+
+void
+ge_cairo_pattern_add_color_stop_color (cairo_pattern_t *pattern, gfloat offset, CairoColor *color)
+{
+ g_return_if_fail (pattern && color);
+
+ cairo_pattern_add_color_stop_rgba (pattern, offset, color->r, color->g, color->b, color->a);
+}
+
+void
+ge_cairo_rounded_rectangle (cairo_t *cr,
+ double x, double y, double w, double h,
+ double radius, CairoCorners corners)
+{
+ g_return_if_fail (cr != NULL);
+
+ if (radius < 0.0001)
+ {
+ cairo_rectangle (cr, x, y, w, h);
+ return;
+ }
+
+ if (corners & CR_CORNER_TOPLEFT)
+ cairo_move_to (cr, x+radius, y);
+ else
+ cairo_move_to (cr, x, y);
+
+ if (corners & CR_CORNER_TOPRIGHT)
+ cairo_arc (cr, x+w-radius, y+radius, radius, M_PI * 1.5, M_PI * 2);
+ else
+ cairo_line_to (cr, x+w, y);
+
+ if (corners & CR_CORNER_BOTTOMRIGHT)
+ cairo_arc (cr, x+w-radius, y+h-radius, radius, 0, M_PI * 0.5);
+ else
+ cairo_line_to (cr, x+w, y+h);
+
+ if (corners & CR_CORNER_BOTTOMLEFT)
+ cairo_arc (cr, x+radius, y+h-radius, radius, M_PI * 0.5, M_PI);
+ else
+ cairo_line_to (cr, x, y+h);
+
+ if (corners & CR_CORNER_TOPLEFT)
+ cairo_arc (cr, x+radius, y+radius, radius, M_PI, M_PI * 1.5);
+ else
+ cairo_line_to (cr, x, y);
+}
+
+/***********************************************
+ * ge_cairo_simple_border -
+ *
+ * A simple routine to draw thin squared
+ * borders with a topleft and bottomright color.
+ *
+ * It originated in Smooth-Engine.
+ ***********************************************/
+void
+ge_cairo_simple_border (cairo_t *cr,
+ CairoColor * tl, CairoColor * br,
+ gint x, gint y, gint width, gint height,
+ gboolean topleft_overlap)
+{
+ gboolean solid_color;
+
+ g_return_if_fail (cr != NULL);
+ g_return_if_fail (tl != NULL);
+ g_return_if_fail (br != NULL);
+
+
+ solid_color = (tl == br) || ((tl->r == br->r) && (tl->g == br->g) && (tl->b == br->b) && (tl->a == br->a));
+
+ topleft_overlap &= !solid_color;
+
+ cairo_save(cr);
+
+ cairo_set_line_width (cr, 1);
+
+ if (topleft_overlap)
+ {
+ ge_cairo_set_color(cr, br);
+
+ cairo_move_to(cr, x + 0.5, y + height - 0.5);
+ cairo_line_to(cr, x + width - 0.5, y + height - 0.5);
+ cairo_line_to(cr, x + width - 0.5, y + 0.5);
+
+ cairo_stroke(cr);
+ }
+
+ ge_cairo_set_color(cr, tl);
+
+ cairo_move_to(cr, x + 0.5, y + height - 0.5);
+ cairo_line_to(cr, x + 0.5, y + 0.5);
+ cairo_line_to(cr, x + width - 0.5, y + 0.5);
+
+ if (!topleft_overlap)
+ {
+ if (!solid_color)
+ {
+ cairo_stroke(cr);
+ ge_cairo_set_color(cr, br);
+ }
+
+ cairo_move_to(cr, x + 0.5, y + height - 0.5);
+ cairo_line_to(cr, x + width - 0.5, y + height - 0.5);
+ cairo_line_to(cr, x + width - 0.5, y + 0.5);
+ }
+
+ cairo_stroke(cr);
+
+ cairo_restore(cr);
+}
+
+void ge_cairo_polygon (cairo_t *cr,
+ CairoColor *color,
+ GdkPoint *points,
+ gint npoints)
+{
+ int i = 0;
+
+ cairo_save(cr);
+
+ ge_cairo_set_color(cr, color);
+ cairo_move_to(cr, points[0].x, points[0].y);
+
+ for (i = 1; i < npoints; i++)
+ {
+ if (!((points[i].x == points[i + 1].x) &&
+ (points[i].y == points[i + 1].y)))
+ {
+ cairo_line_to(cr, points[i].x, points[i].y);
+ }
+ }
+
+ if ((points[npoints-1].x != points[0].y) ||
+ (points[npoints-1].y != points[0].y))
+ {
+ cairo_line_to(cr, points[0].x, points[0].y);
+ }
+
+ cairo_fill(cr);
+
+ cairo_restore(cr);
+}
+
+void ge_cairo_line (cairo_t *cr,
+ CairoColor *color,
+ gint x1,
+ gint y1,
+ gint x2,
+ gint y2)
+{
+ cairo_save(cr);
+
+ ge_cairo_set_color(cr, color);
+ cairo_set_line_width (cr, 1);
+
+ cairo_move_to(cr, x1 + 0.5, y1 + 0.5);
+ cairo_line_to(cr, x2 + 0.5, y2 + 0.5);
+
+ cairo_stroke(cr);
+
+ cairo_restore(cr);
+}
+
+void
+ge_cairo_mirror (cairo_t *cr,
+ CairoMirror mirror,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height)
+{
+ cairo_matrix_t matrix;
+
+ cairo_matrix_init_identity (&matrix);
+
+ if (mirror & CR_MIRROR_HORIZONTAL)
+ {
+ cairo_matrix_scale (&matrix, -1, 1);
+ cairo_matrix_translate (&matrix, *width, 0);
+ }
+ if (mirror & CR_MIRROR_VERTICAL)
+ {
+ cairo_matrix_scale (&matrix, 1, -1);
+ cairo_matrix_translate (&matrix, 0, *height);
+ }
+
+ cairo_transform (cr, &matrix);
+}
+
+/* The following function will be called by GTK+ when the module
+ * is loaded and checks to see if we are compatible with the
+ * version of GTK+ that loads us.
+ */
+G_MODULE_EXPORT const gchar* g_module_check_init (GModule *module);
+const gchar*
+g_module_check_init (GModule *module)
+{
+ return gtk_check_version (GTK_MAJOR_VERSION,
+ GTK_MINOR_VERSION,
+ GTK_MICRO_VERSION - GTK_INTERFACE_AGE);
+}
diff --git a/gtk-engine/src/cairo-support.h b/gtk-engine/src/cairo-support.h
new file mode 100644
index 0000000..2094688
--- /dev/null
+++ b/gtk-engine/src/cairo-support.h
@@ -0,0 +1,81 @@
+/* Helpful functions when dealing with cairo in gtk engines */
+
+#include <gtk/gtk.h>
+#include <math.h>
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+#ifndef M_PI_2
+#define M_PI_2 1.57079632679489661923
+#endif
+
+#ifndef M_PI_4
+#define M_PI_4 0.78539816339744830962
+#endif
+
+typedef struct
+{
+ gdouble r;
+ gdouble g;
+ gdouble b;
+ gdouble a;
+} CairoColor;
+
+typedef struct
+{
+ CairoColor bg[5];
+ CairoColor fg[5];
+
+ CairoColor dark[5];
+ CairoColor light[5];
+ CairoColor mid[5];
+
+ CairoColor base[5];
+ CairoColor text[5];
+ CairoColor text_aa[5];
+
+ CairoColor black;
+ CairoColor white;
+} CairoColorCube;
+
+typedef enum
+{
+ CR_CORNER_NONE = 0,
+ CR_CORNER_TOPLEFT = 1,
+ CR_CORNER_TOPRIGHT = 2,
+ CR_CORNER_BOTTOMLEFT = 4,
+ CR_CORNER_BOTTOMRIGHT = 8,
+ CR_CORNER_ALL = 15
+} CairoCorners;
+
+typedef enum
+{
+ CR_MIRROR_NONE = 0,
+ CR_MIRROR_HORIZONTAL = 1 << 0,
+ CR_MIRROR_VERTICAL = 1 << 1
+} CairoMirror;
+
+GE_INTERNAL void ge_hsb_from_color (const CairoColor *color, gdouble *hue, gdouble *saturation, gdouble *brightness);
+GE_INTERNAL void ge_color_from_hsb (gdouble hue, gdouble saturation, gdouble brightness, CairoColor *color);
+
+GE_INTERNAL void ge_gdk_color_to_cairo (GdkColor * gc, CairoColor * cc);
+GE_INTERNAL void ge_cairo_color_to_gtk (CairoColor *cc, GdkColor *c);
+GE_INTERNAL void ge_gtk_style_to_cairo_color_cube (GtkStyle * style, CairoColorCube *cube);
+
+GE_INTERNAL void ge_shade_color(const CairoColor *base, gdouble shade_ratio, CairoColor *composite);
+GE_INTERNAL void ge_saturate_color (const CairoColor * base, gdouble saturate_level, CairoColor *composite);
+
+GE_INTERNAL cairo_t * ge_gdk_drawable_to_cairo (GdkDrawable *window, GdkRectangle *area);
+GE_INTERNAL void ge_cairo_set_color (cairo_t *cr, CairoColor *color);
+GE_INTERNAL void ge_cairo_pattern_add_color_stop_color (cairo_pattern_t *pattern, gfloat offset, CairoColor *color);
+
+GE_INTERNAL void ge_cairo_rounded_rectangle (cairo_t *cr, double x, double y, double w, double h, double radius, CairoCorners corners);
+
+GE_INTERNAL void ge_cairo_simple_border (cairo_t *cr, CairoColor * tl, CairoColor * br, gint x, gint y, gint width, gint height, gboolean topleft_overlap);
+
+GE_INTERNAL void ge_cairo_line (cairo_t *cr, CairoColor *color, gint x1, gint y1, gint x2, gint y2);
+GE_INTERNAL void ge_cairo_polygon (cairo_t *cr, CairoColor *color, GdkPoint *points, gint npoints);
+
+GE_INTERNAL void ge_cairo_mirror (cairo_t *cr, CairoMirror mirror, gint *x, gint *y, gint *width, gint *height);
diff --git a/gtk-engine/src/ge-support.h b/gtk-engine/src/ge-support.h
new file mode 100644
index 0000000..e0a42b6
--- /dev/null
+++ b/gtk-engine/src/ge-support.h
@@ -0,0 +1,9 @@
+#ifndef GE_SUPPORT_H
+#define GE_SUPPORT_H
+
+#include "general-support.h"
+#include "cairo-support.h"
+#include "widget-information.h"
+
+
+#endif /* GE_SUPPORT_H */
diff --git a/gtk-engine/src/general-support.h b/gtk-engine/src/general-support.h
new file mode 100644
index 0000000..d03abde
--- /dev/null
+++ b/gtk-engine/src/general-support.h
@@ -0,0 +1,35 @@
+
+#include <glib.h>
+
+/* macros to make sure that things are sane ... */
+
+#define CHECK_DETAIL(detail, value) ((detail) && (!strcmp(value, detail)))
+
+#define CHECK_ARGS \
+ g_return_if_fail (window != NULL); \
+ g_return_if_fail (style != NULL);
+
+#define SANITIZE_SIZE \
+ g_return_if_fail (width >= -1); \
+ g_return_if_fail (height >= -1); \
+ \
+ if ((width == -1) && (height == -1)) \
+ gdk_drawable_get_size (window, &width, &height); \
+ else if (width == -1) \
+ gdk_drawable_get_size (window, &width, NULL); \
+ else if (height == -1) \
+ gdk_drawable_get_size (window, NULL, &height);
+
+#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__)
+# define GE_EXPORT __attribute__((__visibility__("default")))
+# define GE_HIDDEN __attribute__((__visibility__("hidden")))
+# define GE_INTERNAL __attribute__((__visibility__("internal")))
+#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
+# define GE_EXPORT __global
+# define GE_HIDDEN __hidden
+# define GE_INTERNAL __hidden
+#else /* not gcc >= 3.3 and not Sun Studio >= 8 */
+# define GE_EXPORT
+# define GE_HIDDEN
+# define GE_INTERNAL
+#endif
diff --git a/gtk-engine/src/olpc_main.c b/gtk-engine/src/olpc_main.c
new file mode 100644
index 0000000..0cbfc76
--- /dev/null
+++ b/gtk-engine/src/olpc_main.c
@@ -0,0 +1,23 @@
+#include <gmodule.h>
+#include "olpc_rc_style.h"
+#include "olpc_style.h"
+
+G_MODULE_EXPORT void
+theme_init (GTypeModule *module)
+{
+ olpc_rc_style_register_type (module);
+ olpc_style_register_type (module);
+}
+
+G_MODULE_EXPORT void
+theme_exit (void)
+{
+}
+
+G_MODULE_EXPORT GtkRcStyle *
+theme_create_rc_style (void)
+{
+ void *ptr;
+ ptr = GTK_RC_STYLE (g_object_new (OLPC_TYPE_RC_STYLE, NULL));
+ return (GtkRcStyle *)ptr;
+}
diff --git a/gtk-engine/src/olpc_misc.c b/gtk-engine/src/olpc_misc.c
new file mode 100644
index 0000000..831a736
--- /dev/null
+++ b/gtk-engine/src/olpc_misc.c
@@ -0,0 +1,325 @@
+#include <math.h>
+#include <string.h>
+#include <gtk/gtknotebook.h>
+
+#include "olpc_style.h"
+#include "olpc_rc_style.h"
+#include "olpc_misc.h"
+
+GtkShadowType
+olpc_shadow_type (GtkStyle *style, const char *detail, GtkShadowType requested)
+{
+ GtkShadowType retval = GTK_SHADOW_NONE;
+
+ if (requested != GTK_SHADOW_NONE) {
+ retval = GTK_SHADOW_ETCHED_IN;
+ }
+
+ if (CHECK_DETAIL (detail, "dockitem") || CHECK_DETAIL (detail, "handlebox_bin") || CHECK_DETAIL (detail, "spinbutton_up") || CHECK_DETAIL (detail, "spinbutton_down")) {
+ retval = GTK_SHADOW_NONE;
+ } else if (CHECK_DETAIL (detail, "button") || CHECK_DETAIL (detail, "togglebutton") || CHECK_DETAIL (detail, "notebook") || CHECK_DETAIL (detail, "optionmenu")) {
+ retval = requested;
+ } else if (CHECK_DETAIL (detail, "menu")) {
+ retval = GTK_SHADOW_ETCHED_IN;
+ }
+
+ return retval;
+}
+
+/***********************************************
+ * olpc_arrow-
+ *
+ * borrowed from redmond till shareable
+ ***********************************************/
+void olpc_arrow (cairo_t *canvas,
+ CairoColor * color,
+ GtkArrowType arrow_type,
+ gboolean fill,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ gint aw = width, ah = height;
+ GdkPoint points[3];
+
+ switch (arrow_type)
+ {
+ case GTK_ARROW_UP:
+ case GTK_ARROW_DOWN:
+ {
+ gdouble tmp=((aw+1)/2) - ((height%2)?1:0);
+
+ if (tmp > ah)
+ {
+ aw = 2*ah - 1 - ((height%2)?1:0);
+ ah = (aw+1)/2;
+ }
+ else
+ {
+ ah = (gint) tmp;
+ aw = 2*ah - 1;
+ }
+
+ if ((aw < 5) || (ah < 3))
+ {
+ aw = 5;
+ ah = 3;
+ }
+
+ x += (width - aw) / 2 ;
+ y += (height - ah) / 2;
+ width = aw;
+ height = ah;
+
+ width += width % 2 - 1;
+
+ points[0].x = x;
+ points[1].x = x + width - 1;
+ points[2].x = x + ((height - 1) - (height - (1 + width / 2)));
+
+ points[0].y = points[1].y = y;
+ points[2].y = y + height - 1;
+
+ if (arrow_type == GTK_ARROW_UP)
+ {
+ gint flip = points[1].y;
+
+ points[0].y = points[1].y = points[2].y;
+ points[2].y = flip;
+ }
+ }
+ break;
+
+ case GTK_ARROW_LEFT:
+ case GTK_ARROW_RIGHT:
+ {
+ gdouble tmp=((ah+1)/2) - ((width%2)?1:0);
+
+ if (tmp > aw)
+ {
+ ah = 2*aw - 1 - ((width%2)?1:0);
+ aw = (ah+1)/2;
+ }
+ else
+ {
+ aw = (gint) tmp;
+ ah = 2*aw - 1;
+ }
+
+ if ((ah < 5) || (aw < 3))
+ {
+ ah = 5;
+ aw = 3;
+ }
+
+ x += (width - aw) / 2 ;
+ y += (height - ah) / 2;
+ width = aw;
+ height = ah;
+
+ height += height % 2 - 1;
+
+ points[0].y = y;
+ points[1].y = y + height - 1;
+ points[2].y = y + ((width - 1) - (width - (1 + height / 2)));
+
+ points[0].x = points[1].x = x;
+ points[2].x = x + width - 1;
+
+ if (arrow_type == GTK_ARROW_LEFT)
+ {
+ gint flip = points[0].x;
+
+ points[0].x = points[1].x = points[2].x;
+ points[2].x = flip;
+ }
+ }
+ break;
+
+ default:
+ {
+ return;
+ }
+ }
+
+ cairo_save(canvas);
+
+ ge_cairo_set_color(canvas, color);
+ cairo_set_line_width (canvas, 0.5);
+
+ cairo_move_to(canvas, points[0].x + 0.5, points[0].y + 0.5);
+ cairo_line_to(canvas, points[1].x + 0.5, points[1].y + 0.5);
+ cairo_line_to(canvas, points[2].x + 0.5, points[2].y + 0.5);
+ cairo_line_to(canvas, points[0].x + 0.5, points[0].y + 0.5);
+
+ if (fill)
+ {
+ cairo_stroke_preserve(canvas);
+
+ cairo_fill(canvas);
+ }
+ else
+ {
+ cairo_stroke(canvas);
+ }
+
+ cairo_restore(canvas);
+}
+
+void
+olpc_slash_two(cairo_t *cr,
+ CairoColor *color1,
+ CairoColor *color2,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ gdouble centerx, centery, thick;
+ gint ax1=0,ax2=0,ay1=0,ay2=0;
+
+ centerx = width/2 + x + 0.5;
+ centery = height/2 + y + 0.5;
+ if (width > height)
+ {
+ ax1 = -2; ax2 = 1;
+ }
+ else
+ {
+ ay1 = -2; ay2 = 1;
+ }
+
+ thick = ((width < height?width-1:height-1) >> 1) - 1.5;
+
+ cairo_set_line_width (cr, 1);
+
+ ge_cairo_set_color(cr, color2);
+ cairo_move_to(cr, centerx - thick + ax1, centery + thick + ay1);
+ cairo_line_to(cr, centerx + thick + ax1, centery - thick + ay1);
+ cairo_stroke(cr);
+
+ ge_cairo_set_color(cr, color1);
+ cairo_move_to(cr, centerx - thick + ax1 + ax2, centery + thick + ay1 + ay2);
+ cairo_line_to(cr, centerx + thick + ax1 + ax2, centery - thick + ay1 + ay2);
+ cairo_stroke(cr);
+
+ if (width > height)
+ {
+ ax1 = 2; /* ax2 = 1; */
+ }
+ else
+ {
+ ay1 = 2; /* ay2 = 1; */
+ }
+
+ cairo_set_line_width (cr, 1);
+
+ ge_cairo_set_color(cr, color2);
+ cairo_move_to(cr, centerx - thick + ax1, centery + thick + ay1);
+ cairo_line_to(cr, centerx + thick + ax1, centery - thick + ay1);
+ cairo_stroke(cr);
+
+ ge_cairo_set_color(cr, color1);
+ cairo_move_to(cr, centerx - thick + ax1 + ax2, centery + thick + ay1 + ay2);
+ cairo_line_to(cr, centerx + thick + ax1 + ax2, centery - thick + ay1 + ay2);
+ cairo_stroke(cr);
+}
+
+
+void
+olpc_slash_one(cairo_t *cr,
+ CairoColor *color1,
+ CairoColor *color2,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ gint centerx, centery, thick;
+
+ centerx = width/2 + x + 0.5;
+ centery = height/2 + y + 0.5;
+
+ thick = ((width < height?width:height) >> 1) - 1.5;
+
+ cairo_set_line_width (cr, 1);
+
+ ge_cairo_set_color(cr, color2);
+ cairo_move_to(cr, centerx - thick, centery + thick);
+ cairo_line_to(cr, centerx + thick, centery - thick);
+ cairo_stroke(cr);
+
+ ge_cairo_set_color(cr, color2);
+ cairo_move_to(cr, centerx - thick, centery + thick - 1);
+ cairo_line_to(cr, centerx + thick - 1, centery - thick);
+ cairo_stroke(cr);
+}
+
+void
+olpc_dot(cairo_t *cr,
+ CairoColor *color1,
+ CairoColor *color2,
+ gint x,
+ gint y)
+{
+ cairo_save(cr);
+
+ cairo_set_line_width (cr, 0.5);
+ cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
+
+ ge_cairo_set_color(cr, color2);
+
+ cairo_rectangle (cr, x - 1, y, 0.5, 0.5);
+ cairo_rectangle (cr, x - 1, y - 1, 0.5, 0.5);
+ cairo_rectangle (cr, x, y - 1, 0.5, 0.5);
+
+ cairo_stroke(cr);
+
+ ge_cairo_set_color(cr, color1);
+
+ cairo_rectangle (cr, x + 1, y, 0.5, 0.5);
+ cairo_rectangle (cr, x + 1, y + 1, 0.5, 0.5);
+ cairo_rectangle (cr, x, y + 1, 0.5, 0.5);
+
+ cairo_stroke(cr);
+
+ cairo_restore(cr);
+}
+
+
+void
+olpc_draw_separator(cairo_t *cr, gboolean horizontal,
+ int x, int y, int width, int height)
+{
+ if (horizontal)
+ {
+ cairo_set_line_width (cr, 1.0);
+ cairo_translate (cr, x, y+0.5);
+
+ cairo_move_to (cr, 0.0, 0.0);
+ cairo_line_to (cr, width+1, 0.0);
+ cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.2);
+ cairo_stroke (cr);
+
+ cairo_move_to (cr, 0.0, 1.0);
+ cairo_line_to (cr, width, 1.0);
+ cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.8);
+ cairo_stroke (cr);
+ }
+ else
+ {
+ cairo_set_line_width (cr, 1.0);
+ cairo_translate (cr, x+0.5, y);
+
+ cairo_move_to (cr, 0.0, 0.0);
+ cairo_line_to (cr, 0.0, height);
+ cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.2);
+ cairo_stroke (cr);
+
+ cairo_move_to (cr, 1.0, 0.0);
+ cairo_line_to (cr, 1.0, height);
+ cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.8);
+ cairo_stroke (cr);
+ }
+}
diff --git a/gtk-engine/src/olpc_misc.h b/gtk-engine/src/olpc_misc.h
new file mode 100644
index 0000000..478a485
--- /dev/null
+++ b/gtk-engine/src/olpc_misc.h
@@ -0,0 +1,39 @@
+GtkShadowType
+GE_INTERNAL olpc_shadow_type (GtkStyle *style, const char *detail, GtkShadowType requested);
+
+GE_INTERNAL void
+olpc_slash_two(cairo_t *cr,
+ CairoColor *color1,
+ CairoColor *color2,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+
+GE_INTERNAL void
+olpc_slash_one(cairo_t *cr,
+ CairoColor *color1,
+ CairoColor *color2,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+
+GE_INTERNAL void
+olpc_dot(cairo_t *cr,
+ CairoColor *color1,
+ CairoColor *color2,
+ gint x,
+ gint y);
+
+GE_INTERNAL void olpc_arrow (cairo_t *canvas,
+ CairoColor *color,
+ GtkArrowType arrow_type,
+ gboolean fill,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+
+GE_INTERNAL void olpc_draw_separator(cairo_t *cr, gboolean horizontal,
+ int x, int y, int width, int height);
diff --git a/gtk-engine/src/olpc_rc_style.c b/gtk-engine/src/olpc_rc_style.c
new file mode 100644
index 0000000..8601bdd
--- /dev/null
+++ b/gtk-engine/src/olpc_rc_style.c
@@ -0,0 +1,398 @@
+#include "olpc_rc_style.h"
+#include "olpc_style.h"
+
+static void olpc_rc_style_init (OlpcRcStyle *style);
+static void olpc_rc_style_class_init (OlpcRcStyleClass *klass);
+static guint olpc_rc_style_parse (GtkRcStyle *rc_style,
+ GtkSettings *settings,
+ GScanner *scanner);
+static void olpc_rc_style_merge (GtkRcStyle *dest,
+ GtkRcStyle *src);
+
+static GtkStyle *olpc_rc_style_create_style (GtkRcStyle *rc_style);
+
+
+static struct
+ {
+ gchar *name;
+ guint token;
+ }
+olpc_rc_symbols[] =
+{
+ { "rect_scrollbar", TOKEN_RECTSCROLLBAR },
+ { "scrollbar_marks", TOKEN_SCROLLBARMARKS },
+ { "scroll_button_marks", TOKEN_SCROLLBUTTONMARKS },
+ { "handlebox_marks", TOKEN_HANDLEBOXMARKS },
+ { "mark_type1", TOKEN_MARKTYPE1 },
+ { "mark_type2", TOKEN_MARKTYPE2 },
+ { "paned_dots", TOKEN_PANEDDOTS },
+
+ { "TRUE", TOKEN_TRUE },
+ { "FALSE", TOKEN_FALSE },
+
+ { "NOTHING", TOKEN_NOTHING },
+ { "SLASH", TOKEN_SLASH },
+ { "INVSLASH", TOKEN_INVSLASH },
+ { "DOT", TOKEN_DOT },
+ { "INVDOT", TOKEN_INVDOT },
+ { "ARROW", TOKEN_ARROW },
+
+ { "FULL", TOKEN_FULL },
+ { "SOME", TOKEN_SOME },
+ { "NONE", TOKEN_NONE },
+
+};
+
+static guint n_olpc_rc_symbols = sizeof(olpc_rc_symbols) / sizeof(olpc_rc_symbols[0]);
+
+static GtkRcStyleClass *olpc_parent_rc_style_class;
+
+GType olpc_type_rc_style = 0;
+
+void
+olpc_rc_style_register_type (GTypeModule *module)
+{
+ static const GTypeInfo object_info =
+ {
+ sizeof (OlpcRcStyleClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) olpc_rc_style_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (OlpcRcStyle),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) olpc_rc_style_init,
+ };
+
+ olpc_type_rc_style = g_type_module_register_type (module,
+ GTK_TYPE_RC_STYLE,
+ "OlpcRcStyle",
+ &object_info, 0);
+}
+
+static void
+olpc_rc_style_init (OlpcRcStyle *style)
+{
+}
+
+static void
+olpc_rc_style_class_init (OlpcRcStyleClass *klass)
+{
+ GtkRcStyleClass *rc_style_class = GTK_RC_STYLE_CLASS (klass);
+
+ olpc_parent_rc_style_class = g_type_class_peek_parent (klass);
+
+ rc_style_class->parse = olpc_rc_style_parse;
+ rc_style_class->merge = olpc_rc_style_merge;
+ rc_style_class->create_style = olpc_rc_style_create_style;
+}
+
+#if 0
+static guint
+olpc_rc_parse_int(GScanner *scanner,
+ GTokenType wanted_token,
+ guint *retval)
+{
+ guint token;
+
+ token = g_scanner_get_next_token(scanner);
+ if (token != wanted_token)
+ return wanted_token;
+
+ token = g_scanner_get_next_token(scanner);
+ if (token != G_TOKEN_EQUAL_SIGN)
+ return wanted_token;
+
+ token = g_scanner_get_next_token(scanner);
+ if (token != G_TOKEN_INT)
+ return G_TOKEN_INT;
+
+ *retval = g_scanner_cur_value(scanner).v_int;
+
+ return G_TOKEN_NONE;
+}
+#endif
+
+static guint
+olpc_rc_parse_boolean(GScanner *scanner,
+ GTokenType wanted_token,
+ guint *retval)
+{
+ guint token;
+
+ token = g_scanner_get_next_token(scanner);
+ if (token != wanted_token)
+ return wanted_token;
+
+ token = g_scanner_get_next_token(scanner);
+ if (token != G_TOKEN_EQUAL_SIGN)
+ return G_TOKEN_EQUAL_SIGN;
+
+ token = g_scanner_get_next_token(scanner);
+ if (token == TOKEN_TRUE)
+ *retval = TRUE;
+ else if (token == TOKEN_FALSE)
+ *retval = FALSE;
+ else
+ return TOKEN_TRUE;
+
+ return G_TOKEN_NONE;
+}
+
+static guint
+olpc_rc_parse_marktype(GScanner *scanner,
+ GTokenType wanted_token,
+ guint *retval)
+{
+ guint token;
+
+ token = g_scanner_get_next_token(scanner);
+ if (token != wanted_token)
+ return wanted_token;
+
+ token = g_scanner_get_next_token(scanner);
+ if (token != G_TOKEN_EQUAL_SIGN)
+ return G_TOKEN_EQUAL_SIGN;
+
+ token = g_scanner_get_next_token(scanner);
+ switch (token)
+ {
+ case TOKEN_NOTHING:
+ *retval = MARKS_NOTHING;
+ break;
+ case TOKEN_SLASH:
+ *retval = MARKS_SLASH;
+ break;
+ case TOKEN_INVSLASH:
+ *retval = MARKS_INVSLASH;
+ break;
+ case TOKEN_DOT:
+ *retval = MARKS_DOT;
+ break;
+ case TOKEN_INVDOT:
+ *retval = MARKS_INVDOT;
+ break;
+ case TOKEN_ARROW:
+ *retval = MARKS_ARROW;
+ break;
+ default:
+ return TOKEN_NOTHING;
+ }
+
+ return G_TOKEN_NONE;
+}
+
+static guint
+olpc_rc_parse_paned(GScanner *scanner,
+ GTokenType wanted_token,
+ guint *retval)
+{
+ guint token;
+
+ token = g_scanner_get_next_token(scanner);
+ if (token != wanted_token)
+ return wanted_token;
+
+ token = g_scanner_get_next_token(scanner);
+ if (token != G_TOKEN_EQUAL_SIGN)
+ return G_TOKEN_EQUAL_SIGN;
+
+ token = g_scanner_get_next_token(scanner);
+ switch (token)
+ {
+ case TOKEN_NONE:
+ *retval = PANED_DOTSNONE;
+ break;
+ case TOKEN_SOME:
+ *retval = PANED_DOTSSOME;
+ break;
+ case TOKEN_FULL:
+ *retval = PANED_DOTSFULL;
+ break;
+ default:
+ return TOKEN_NOTHING;
+ }
+
+ return G_TOKEN_NONE;
+}
+
+static guint
+olpc_rc_style_parse (GtkRcStyle *rc_style,
+ GtkSettings *settings,
+ GScanner *scanner)
+{
+ static GQuark scope_id = 0;
+ OlpcRcStyle *theme_data = OLPC_RC_STYLE (rc_style);
+ guint old_scope;
+ guint token;
+ guint i;
+
+ /* Set up a new scope in this scanner. */
+
+ /*
+ g_print("olpc_rc_parse_rc_style(\"%s\")\n", rc_style->name);
+ */
+ if (!scope_id)
+ scope_id = g_quark_from_string("theme_engine");
+
+ /* If we bail out due to errors, we *don't* reset the scope, so the
+ * error messaging code can make sense of our tokens.
+ */
+ old_scope = g_scanner_set_scope(scanner, scope_id);
+
+ /* Now check if we already added our symbols to this scope
+ * (in some previous call to olpc_rc_parse_rc_style for the
+ * same scanner.
+ */
+
+ if (!g_scanner_lookup_symbol(scanner, olpc_rc_symbols[0].name))
+ {
+ for (i = 0; i < n_olpc_rc_symbols; i++)
+ {
+ g_scanner_scope_add_symbol(scanner, scope_id,
+ olpc_rc_symbols[i].name,
+ GINT_TO_POINTER(olpc_rc_symbols[i].token));
+ }
+ }
+
+ /* We're ready to go, now parse the top level */
+
+ /* theme_data = g_new0(OlpcRcStyle, 1); */
+ theme_data->scrollbar_type = DEFAULT_SCROLLSHAPE;
+ theme_data->scrollbar_marks = DEFAULT_SCROLLBARMARKS;
+ theme_data->scroll_button_marks = DEFAULT_SCROLLBUTTONMARKS;
+ theme_data->handlebox_marks = DEFAULT_HANDLEBOXMARKS;
+ theme_data->mark_type1 = DEFAULT_MARKTYPE1;
+ theme_data->mark_type2 = DEFAULT_MARKTYPE2;
+
+ token = g_scanner_peek_next_token(scanner);
+ while (token != G_TOKEN_RIGHT_CURLY)
+ {
+ switch (token)
+ {
+ case TOKEN_RECTSCROLLBAR:
+ token = olpc_rc_parse_boolean(scanner, TOKEN_RECTSCROLLBAR, &i);
+ if (token != G_TOKEN_NONE)
+ break;
+ if (i == FALSE)
+ theme_data->scrollbar_type = SCROLL_SHAPED;
+ else
+ theme_data->scrollbar_type = SCROLL_RECT;
+ break;
+
+ case TOKEN_SCROLLBUTTONMARKS:
+ token = olpc_rc_parse_boolean(scanner, TOKEN_SCROLLBUTTONMARKS, &i);
+ if (token != G_TOKEN_NONE)
+ break;
+ if (i == TRUE)
+ theme_data->mark_type2 = MARKS_SLASH;
+ else
+ theme_data->mark_type2 = MARKS_NOTHING;
+ /*
+ if (i == TRUE)
+ theme_data->scroll_button_marks = MARKS_ON;
+ else
+ theme_data->scroll_button_marks = MARKS_OFF;
+ */
+ break;
+
+ case TOKEN_SCROLLBARMARKS:
+ token = olpc_rc_parse_boolean(scanner, TOKEN_SCROLLBARMARKS, &i);
+ if (token != G_TOKEN_NONE)
+ break;
+ if (i == TRUE)
+ theme_data->mark_type1 = MARKS_SLASH;
+ else
+ theme_data->mark_type1 = MARKS_NOTHING;
+ /*
+ if (i == TRUE)
+ theme_data->scrollbar_marks = MARKS_ON;
+ else
+ theme_data->scrollbar_marks = MARKS_OFF;
+ */
+ break;
+
+ case TOKEN_HANDLEBOXMARKS:
+ token = olpc_rc_parse_boolean(scanner, TOKEN_HANDLEBOXMARKS, &i);
+ if (token != G_TOKEN_NONE)
+ break;
+ if (i == TRUE)
+ theme_data->handlebox_marks = MARKS_ON;
+ else
+ theme_data->handlebox_marks = MARKS_OFF;
+ break;
+
+ case TOKEN_MARKTYPE1:
+ token = olpc_rc_parse_marktype(scanner, TOKEN_MARKTYPE1, &i);
+ if (token != G_TOKEN_NONE)
+ break;
+ theme_data->mark_type1 = i;
+ break;
+
+ case TOKEN_MARKTYPE2:
+ token = olpc_rc_parse_marktype(scanner, TOKEN_MARKTYPE2, &i);
+ if (token != G_TOKEN_NONE)
+ break;
+ theme_data->mark_type2 = i;
+ break;
+
+ case TOKEN_PANEDDOTS:
+ token = olpc_rc_parse_paned(scanner, TOKEN_PANEDDOTS, &i);
+ if (token != G_TOKEN_NONE)
+ break;
+ theme_data->paned_dots = i;
+ break;
+
+ default:
+ g_scanner_get_next_token(scanner);
+ token = G_TOKEN_RIGHT_CURLY;
+ break;
+ }
+
+ if (token != G_TOKEN_NONE)
+ {
+// g_free(theme_data);
+ return token;
+ }
+ token = g_scanner_peek_next_token(scanner);
+ }
+
+ g_scanner_get_next_token(scanner);
+
+ g_scanner_set_scope(scanner, old_scope);
+
+ return G_TOKEN_NONE;
+}
+
+static void
+olpc_rc_style_merge (GtkRcStyle * dest,
+ GtkRcStyle * src)
+{
+ if (OLPC_IS_RC_STYLE (src)) {
+ OlpcRcStyle *src_data = OLPC_RC_STYLE (src);
+ OlpcRcStyle *dest_data = OLPC_RC_STYLE (dest);
+
+ /*
+ g_print("theme_merge_rc_style(\"%s\", \"%s\")\n", dest->name, src->name);
+ */
+
+ dest_data->scrollbar_type = src_data->scrollbar_type;
+ dest_data->scrollbar_marks = src_data->scrollbar_marks;
+ dest_data->scroll_button_marks = src_data->scroll_button_marks;
+ dest_data->handlebox_marks = src_data->handlebox_marks;
+ dest_data->mark_type1 = src_data->mark_type1;
+ dest_data->mark_type2 = src_data->mark_type2;
+ dest_data->paned_dots = src_data->paned_dots;
+ }
+
+ olpc_parent_rc_style_class->merge (dest, src);
+}
+
+/* Create an empty style suitable to this RC style
+ */
+static GtkStyle *
+olpc_rc_style_create_style (GtkRcStyle *rc_style)
+{
+ return GTK_STYLE (g_object_new (OLPC_TYPE_STYLE, NULL));
+}
diff --git a/gtk-engine/src/olpc_rc_style.h b/gtk-engine/src/olpc_rc_style.h
new file mode 100644
index 0000000..6813533
--- /dev/null
+++ b/gtk-engine/src/olpc_rc_style.h
@@ -0,0 +1,93 @@
+#include <gtk/gtkrc.h>
+#include "ge-support.h"
+
+typedef struct _OlpcRcStyle OlpcRcStyle;
+typedef struct _OlpcRcStyleClass OlpcRcStyleClass;
+
+GE_INTERNAL extern GType olpc_type_rc_style;
+
+#define OLPC_TYPE_RC_STYLE olpc_type_rc_style
+#define OLPC_RC_STYLE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), OLPC_TYPE_RC_STYLE, OlpcRcStyle))
+#define OLPC_RC_STYLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), OLPC_TYPE_RC_STYLE, OlpcRcStyleClass))
+#define OLPC_IS_RC_STYLE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), OLPC_TYPE_RC_STYLE))
+#define OLPC_IS_RC_STYLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OLPC_TYPE_RC_STYLE))
+#define OLPC_RC_STYLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OLPC_TYPE_RC_STYLE, OlpcRcStyleClass))
+
+struct _OlpcRcStyle
+{
+ GtkRcStyle parent_instance;
+
+ guint scrollbar_type:1;
+ guint scrollbar_marks:1;
+ guint scroll_button_marks:1;
+ guint handlebox_marks:1;
+ guint mark_type1;
+ guint mark_type2;
+ guint paned_dots;
+};
+
+struct _OlpcRcStyleClass
+{
+ GtkRcStyleClass parent_class;
+};
+
+GE_INTERNAL void olpc_rc_style_register_type (GTypeModule *module);
+
+/* Default stuff */
+#define DEFAULT_SCROLLSHAPE SCROLL_SHAPED
+#define DEFAULT_SCROLLBARMARKS MARKS_ON
+#define DEFAULT_SCROLLBUTTONMARKS MARKS_ON
+#define DEFAULT_HANDLEBOXMARKS MARKS_ON
+#define DEFAULT_MARKTYPE1 MARKS_SLASH
+#define DEFAULT_MARKTYPE2 MARKS_INVSLASH
+#define DEFAULT_PANEDDOTS PANED_DOTSFULL
+
+#define DEFAULT_SCROLLTHUMB_SIZE 12
+#define DEFAULT_MIN_SLIDER_SIZE 9
+#define SMALLEST_HANDLE 17
+
+enum
+ {
+ TOKEN_RECTSCROLLBAR = G_TOKEN_LAST + 1,
+ TOKEN_SCROLLBARMARKS,
+ TOKEN_SCROLLBUTTONMARKS,
+ TOKEN_HANDLEBOXMARKS,
+ TOKEN_MARKTYPE1,
+ TOKEN_MARKTYPE2,
+ TOKEN_PANEDDOTS,
+
+ TOKEN_TRUE,
+ TOKEN_FALSE,
+
+ TOKEN_NOTHING,
+ TOKEN_SLASH,
+ TOKEN_INVSLASH,
+ TOKEN_DOT,
+ TOKEN_INVDOT,
+ TOKEN_ARROW,
+
+ TOKEN_FULL,
+ TOKEN_SOME,
+ TOKEN_NONE
+ };
+
+enum
+ {
+ SCROLL_RECT = 0,
+ SCROLL_SHAPED = 1,
+
+ MARKS_OFF = 0,
+ MARKS_ON = 1,
+
+ MARKS_NOTHING = 0,
+ MARKS_SLASH = 1,
+ MARKS_INVSLASH = 2,
+ MARKS_DOT = 3,
+ MARKS_INVDOT = 4,
+ MARKS_ARROW = 5,
+
+ PANED_DOTSFULL = 0,
+ PANED_DOTSSOME = 1,
+ PANED_DOTSNONE = 2
+ };
+
diff --git a/gtk-engine/src/olpc_style.h b/gtk-engine/src/olpc_style.h
new file mode 100644
index 0000000..83addf7
--- /dev/null
+++ b/gtk-engine/src/olpc_style.h
@@ -0,0 +1,29 @@
+#include <gtk/gtkstyle.h>
+#include "ge-support.h"
+
+typedef struct _OlpcStyle OlpcStyle;
+typedef struct _OlpcStyleClass OlpcStyleClass;
+
+GE_INTERNAL extern GType olpc_type_style;
+
+#define OLPC_TYPE_STYLE olpc_type_style
+#define OLPC_STYLE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), OLPC_TYPE_STYLE, OlpcStyle))
+#define OLPC_STYLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), OLPC_TYPE_STYLE, OlpcStyleClass))
+#define OLPC_IS_STYLE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), OLPC_TYPE_STYLE))
+#define OLPC_IS_STYLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OLPC_TYPE_STYLE))
+#define OLPC_STYLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OLPC_TYPE_STYLE, OlpcStyleClass))
+
+struct _OlpcStyle
+{
+ GtkStyle parent_instance;
+ CairoColorCube color_cube;
+};
+
+struct _OlpcStyleClass
+{
+ GtkStyleClass parent_class;
+};
+
+GE_INTERNAL void olpc_style_register_type (GTypeModule *module);
+
+
diff --git a/gtk-engine/src/olpc_theme_draw.c b/gtk-engine/src/olpc_theme_draw.c
new file mode 100644
index 0000000..7f347a7
--- /dev/null
+++ b/gtk-engine/src/olpc_theme_draw.c
@@ -0,0 +1,1478 @@
+/* Olpc theme for gtk, based on raster's Motif theme and the Metal theme.
+Authors: Tim Gerla <timg@rrv.net>
+Tomas Ögren <stric@ing.umu.se>
+ */
+/* #define DEBUG 1 */
+
+#include <math.h>
+#include <string.h>
+#include <gtk/gtknotebook.h>
+
+#include "olpc_style.h"
+#include "olpc_rc_style.h"
+#include "olpc_misc.h"
+
+#ifndef max
+#define max(x,y) ((x)>=(y)?(x):(y))
+#endif
+#ifndef min
+#define min(x,y) ((x)<=(y)?(x):(y))
+#endif
+
+#define DRAW_ARGS GtkStyle *style, \
+ GdkWindow *window, \
+ GtkStateType state_type, \
+ GtkShadowType shadow_type, \
+ GdkRectangle *area, \
+ GtkWidget *widget, \
+ const gchar *detail, \
+ gint x, \
+ gint y, \
+ gint width, \
+ gint height
+
+#define DRAW_VARS style, window, state_type, shadow_type, area, widget, detail, x, y, width, height
+
+static void olpc_style_init (OlpcStyle *style);
+static void olpc_style_class_init (OlpcStyleClass *klass);
+
+static void
+olpc_tab(GtkStyle * style,
+ GdkWindow * window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ GdkRectangle * area,
+ GtkWidget * widget,
+ const gchar *detail,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ gint orientation);
+
+static GtkStyleClass *olpc_parent_style_class = NULL;
+
+static void
+olpc_style_draw_hline(GtkStyle * style,
+ GdkWindow * window,
+ GtkStateType state_type,
+ GdkRectangle * area,
+ GtkWidget * widget,
+ const gchar *detail,
+ gint x1,
+ gint x2,
+ gint y)
+{
+ cairo_t *cr;
+
+ CHECK_ARGS
+
+ cr = ge_gdk_drawable_to_cairo (window, area);
+
+ olpc_draw_separator(cr, TRUE, x1, y, x2-x1, 2);
+ cairo_destroy (cr);
+}
+
+static void
+olpc_style_draw_vline(GtkStyle * style,
+ GdkWindow * window,
+ GtkStateType state_type,
+ GdkRectangle * area,
+ GtkWidget * widget,
+ const gchar *detail,
+ gint y1,
+ gint y2,
+ gint x)
+{
+ cairo_t *cr;
+
+ CHECK_ARGS
+
+ if (ge_is_combo_box(widget, FALSE) && (!ge_is_combo_box_entry(widget)))
+ return;
+
+ cr = ge_gdk_drawable_to_cairo (window, area);
+
+ olpc_draw_separator(cr, FALSE, x, y1, 2, y2-y1);
+
+ cairo_destroy (cr);
+}
+
+static void
+olpc_style_draw_shadow(GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ GdkRectangle *area,
+ GtkWidget *widget,
+ const gchar *detail,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ OlpcStyle *olpc_style = OLPC_STYLE (style);
+
+ CairoColor *color1 = NULL;
+ CairoColor *color2 = NULL;
+ cairo_t *cr;
+
+ CHECK_ARGS
+
+ SANITIZE_SIZE
+
+ switch (shadow_type)
+ {
+ case GTK_SHADOW_NONE:
+ return;
+ case GTK_SHADOW_IN:
+ if (((x == 1) || (y == 1)) && (CHECK_DETAIL (detail, "entry") || CHECK_DETAIL (detail, "text")))
+ {
+ color1 = color2 = &olpc_style->color_cube.base[state_type];
+ break;
+ }
+ case GTK_SHADOW_ETCHED_IN:
+ color1 = &olpc_style->color_cube.light[state_type];
+ color2 = &olpc_style->color_cube.dark[state_type];
+ break;
+ case GTK_SHADOW_OUT:
+ case GTK_SHADOW_ETCHED_OUT:
+ color1 = &olpc_style->color_cube.dark[state_type];
+ color2 = &olpc_style->color_cube.light[state_type];
+ break;
+ }
+
+ if (CHECK_DETAIL (detail, "entry"))
+ {
+ cr = ge_gdk_drawable_to_cairo (window, area);
+
+ ge_cairo_set_color(cr, &olpc_style->color_cube.bg[state_type]);
+ cairo_rectangle(cr, x, y, width, height);
+ cairo_fill(cr);
+
+ ge_cairo_set_color(cr, &olpc_style->color_cube.base[state_type]);
+ ge_cairo_rounded_rectangle (cr, x, y, width, height, 12, CR_CORNER_ALL);
+ cairo_fill(cr);
+
+ cairo_destroy(cr);
+
+ return;
+ }
+
+ cr = ge_gdk_drawable_to_cairo (window, area);
+
+ switch (shadow_type)
+ {
+ case GTK_SHADOW_NONE:
+ break;
+
+ case GTK_SHADOW_ETCHED_IN:
+ case GTK_SHADOW_ETCHED_OUT:
+ ge_cairo_set_color(cr, color1);
+ cairo_rectangle(cr, x + 1.5, y + 1.5, width - 3, height - 3);
+ cairo_stroke(cr);
+
+ ge_cairo_set_color(cr, color2);
+ cairo_rectangle(cr, x + 0.5, y + 0.5, width - 3, height - 3);
+ cairo_stroke(cr);
+ break;
+
+ case GTK_SHADOW_IN:
+ case GTK_SHADOW_OUT:
+ ge_cairo_simple_border (cr, color2, color1, x, y, width, height, FALSE);
+ break;
+ }
+
+ cairo_destroy(cr);
+}
+
+static void
+olpc_style_draw_polygon(GtkStyle * style,
+ GdkWindow * window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ GdkRectangle * area,
+ GtkWidget * widget,
+ const gchar *detail,
+ GdkPoint * points,
+ gint npoints,
+ gint fill)
+{
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif /* M_PI */
+#ifndef M_PI_4
+#define M_PI_4 0.78539816339744830962
+#endif /* M_PI_4 */
+
+ static const gdouble pi_over_4 = M_PI_4;
+ static const gdouble pi_3_over_4 = M_PI_4 * 3;
+
+ OlpcStyle *olpc_style = OLPC_STYLE (style);
+
+ CairoColor *color1 = NULL;
+ CairoColor *color2 = NULL;
+ CairoColor *color3 = NULL;
+ CairoColor *color4 = NULL;
+ cairo_t *cr;
+
+ gdouble angle;
+ gint xadjust;
+ gint yadjust;
+ gint i;
+
+ CHECK_ARGS
+ g_return_if_fail(points != NULL);
+
+ switch (shadow_type)
+ {
+ case GTK_SHADOW_IN:
+ color1 = &olpc_style->color_cube.light[state_type];
+ color2 = &olpc_style->color_cube.dark[state_type];
+ color3 = &olpc_style->color_cube.light[state_type];
+ color4 = &olpc_style->color_cube.dark[state_type];
+ break;
+ case GTK_SHADOW_ETCHED_IN:
+ color1 = &olpc_style->color_cube.light[state_type];
+ color2 = &olpc_style->color_cube.dark[state_type];
+ color3 = &olpc_style->color_cube.dark[state_type];
+ color4 = &olpc_style->color_cube.light[state_type];
+ break;
+ case GTK_SHADOW_OUT:
+ color1 = &olpc_style->color_cube.dark[state_type];
+ color2 = &olpc_style->color_cube.light[state_type];
+ color3 = &olpc_style->color_cube.dark[state_type];
+ color4 = &olpc_style->color_cube.light[state_type];
+ break;
+ case GTK_SHADOW_ETCHED_OUT:
+ color1 = &olpc_style->color_cube.dark[state_type];
+ color2 = &olpc_style->color_cube.light[state_type];
+ color3 = &olpc_style->color_cube.light[state_type];
+ color4 = &olpc_style->color_cube.dark[state_type];
+ break;
+ default:
+ return;
+ }
+
+ cr = ge_gdk_drawable_to_cairo (window, area);
+
+ if (fill)
+ ge_cairo_polygon(cr, &olpc_style->color_cube.bg[state_type], points, npoints);
+
+ npoints--;
+
+ for (i = 0; i < npoints; i++)
+ {
+ if ((points[i].x == points[i + 1].x) &&
+ (points[i].y == points[i + 1].y))
+ {
+ angle = 0;
+ }
+ else
+ {
+ angle = atan2(points[i + 1].y - points[i].y,
+ points[i + 1].x - points[i].x);
+ }
+
+ if ((angle > -pi_3_over_4) && (angle < pi_over_4))
+ {
+ if (angle > -pi_over_4)
+ {
+ xadjust = 0;
+ yadjust = 1;
+ }
+ else
+ {
+ xadjust = 1;
+ yadjust = 0;
+ }
+
+ ge_cairo_line(cr, color1,
+ points[i].x - xadjust, points[i].y - yadjust,
+ points[i + 1].x - xadjust, points[i + 1].y - yadjust);
+ ge_cairo_line(cr, color3,
+ points[i].x, points[i].y,
+ points[i + 1].x, points[i + 1].y);
+ }
+ else
+ {
+ if ((angle < -pi_3_over_4) || (angle > pi_3_over_4))
+ {
+ xadjust = 0;
+ yadjust = 1;
+ }
+ else
+ {
+ xadjust = 1;
+ yadjust = 0;
+ }
+
+ ge_cairo_line(cr, color4,
+ points[i].x + xadjust, points[i].y + yadjust,
+ points[i + 1].x + xadjust, points[i + 1].y + yadjust);
+ ge_cairo_line(cr, color2,
+ points[i].x, points[i].y,
+ points[i + 1].x, points[i + 1].y);
+ }
+ }
+
+ cairo_destroy(cr);
+}
+
+static void
+olpc_style_draw_arrow(GtkStyle * style,
+ GdkWindow * window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ GdkRectangle * area,
+ GtkWidget * widget,
+ const gchar *detail,
+ GtkArrowType arrow_type,
+ gint fill, gint x, gint y, gint width, gint height)
+{
+ OlpcStyle *olpc_style = OLPC_STYLE (style);
+
+ CairoColor *color1, *color2, *color3=NULL,*color4=NULL;
+ gint half_width, half_height;
+ cairo_t *cr;
+
+ CHECK_ARGS
+
+ if (ge_is_combo_box(widget, FALSE) && (!ge_is_combo_box_entry(widget)))
+ return;
+
+ SANITIZE_SIZE
+
+ half_width = width / 2;
+ half_height = height / 2;
+
+ switch (shadow_type)
+ {
+ case GTK_SHADOW_IN:
+ color1 = &olpc_style->color_cube.bg[state_type];
+ color2 = &olpc_style->color_cube.dark[state_type];
+ color3 = &olpc_style->color_cube.light[state_type];
+ color4 = &olpc_style->color_cube.black;
+ break;
+
+ case GTK_SHADOW_OUT:
+ color1 = &olpc_style->color_cube.dark[state_type];
+ color2 = &olpc_style->color_cube.light[state_type];
+ color3 = &olpc_style->color_cube.black;
+ color4 = &olpc_style->color_cube.bg[state_type];
+ break;
+
+ case GTK_SHADOW_ETCHED_IN:
+ color2 = &olpc_style->color_cube.light[state_type];
+ color1 = &olpc_style->color_cube.dark[state_type];
+ break;
+
+ case GTK_SHADOW_ETCHED_OUT:
+ color1 = &olpc_style->color_cube.dark[state_type];
+ color2 = &olpc_style->color_cube.light[state_type];
+ break;
+
+ case GTK_SHADOW_NONE:
+ color1 = &olpc_style->color_cube.bg[state_type];
+ color2 = &olpc_style->color_cube.bg[state_type];
+ break;
+
+ default:
+ return;
+ }
+
+ cr = ge_gdk_drawable_to_cairo (window, area);
+
+ if (CHECK_DETAIL (detail, "vscrollbar") || CHECK_DETAIL (detail, "hscrollbar"))
+ {
+ switch (OLPC_RC_STYLE (style->rc_style)->mark_type2)
+ {
+ case MARKS_NOTHING:
+ break;
+
+ case MARKS_INVSLASH:
+ olpc_slash_one(cr, color2, color1, x, y, width, height);
+ break;
+
+ case MARKS_DOT:
+ olpc_dot(cr, color2, color1, x + half_width, y + half_height);
+ break;
+
+ case MARKS_INVDOT:
+ olpc_dot(cr, color1, color2, x + half_width, y + half_height);
+ break;
+
+ case MARKS_ARROW:
+ if (state_type == GTK_STATE_INSENSITIVE)
+ olpc_arrow (cr, &olpc_style->color_cube.white, arrow_type, TRUE, x+1, y+1, width, height);
+ olpc_arrow (cr, &olpc_style->color_cube.fg[state_type], arrow_type, TRUE, x, y, width, height);
+ break;
+
+ case MARKS_SLASH:
+ default:
+ olpc_slash_one(cr, color1, color2, x, y, width - 1, height - 1);
+ break;
+ }
+ }
+ else
+ {
+ if (state_type == GTK_STATE_INSENSITIVE)
+ olpc_arrow (cr, &olpc_style->color_cube.white, arrow_type, TRUE, x+1, y+1, width, height);
+ olpc_arrow (cr, &olpc_style->color_cube.fg[state_type], arrow_type, TRUE, x, y, width, height);
+ }
+
+ cairo_destroy(cr);
+}
+
+static void
+olpc_style_draw_diamond(GtkStyle * style,
+ GdkWindow * window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ GdkRectangle * area,
+ GtkWidget * widget,
+ const gchar *detail,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ OlpcStyle *olpc_style = OLPC_STYLE (style);
+ gint half_width;
+ gint half_height;
+ cairo_t *cr;
+
+ CHECK_ARGS
+
+ SANITIZE_SIZE
+
+ half_width = width / 2;
+ half_height = height / 2;
+
+ cr = ge_gdk_drawable_to_cairo (window, area);
+
+ switch (shadow_type)
+ {
+ case GTK_SHADOW_IN:
+ ge_cairo_line(cr, &olpc_style->color_cube.light[state_type],
+ x + 2, y + half_height,
+ x + half_width, y + height - 2);
+ ge_cairo_line(cr, &olpc_style->color_cube.light[state_type],
+ x + half_width, y + height - 2,
+ x + width - 2, y + half_height);
+ ge_cairo_line(cr, &olpc_style->color_cube.light[state_type],
+ x + 1, y + half_height,
+ x + half_width, y + height - 1);
+ ge_cairo_line(cr, &olpc_style->color_cube.light[state_type],
+ x + half_width, y + height - 1,
+ x + width - 1, y + half_height);
+ ge_cairo_line(cr, &olpc_style->color_cube.light[state_type],
+ x, y + half_height,
+ x + half_width, y + height);
+ ge_cairo_line(cr, &olpc_style->color_cube.light[state_type],
+ x + half_width, y + height,
+ x + width, y + half_height);
+
+ ge_cairo_line(cr, &olpc_style->color_cube.dark[state_type],
+ x + 2, y + half_height,
+ x + half_width, y + 2);
+ ge_cairo_line(cr, &olpc_style->color_cube.dark[state_type],
+ x + half_width, y + 2,
+ x + width - 2, y + half_height);
+ ge_cairo_line(cr, &olpc_style->color_cube.dark[state_type],
+ x + 1, y + half_height,
+ x + half_width, y + 1);
+ ge_cairo_line(cr, &olpc_style->color_cube.dark[state_type],
+ x + half_width, y + 1,
+ x + width - 1, y + half_height);
+ ge_cairo_line(cr, &olpc_style->color_cube.dark[state_type],
+ x, y + half_height,
+ x + half_width, y);
+ ge_cairo_line(cr, &olpc_style->color_cube.dark[state_type],
+ x + half_width, y,
+ x + width, y + half_height);
+ break;
+ case GTK_SHADOW_OUT:
+ ge_cairo_line(cr, &olpc_style->color_cube.dark[state_type],
+ x + 2, y + half_height,
+ x + half_width, y + height - 2);
+ ge_cairo_line(cr, &olpc_style->color_cube.dark[state_type],
+ x + half_width, y + height - 2,
+ x + width - 2, y + half_height);
+ ge_cairo_line(cr, &olpc_style->color_cube.dark[state_type],
+ x + 1, y + half_height,
+ x + half_width, y + height - 1);
+ ge_cairo_line(cr, &olpc_style->color_cube.dark[state_type],
+ x + half_width, y + height - 1,
+ x + width - 1, y + half_height);
+ ge_cairo_line(cr, &olpc_style->color_cube.dark[state_type],
+ x, y + half_height,
+ x + half_width, y + height);
+ ge_cairo_line(cr, &olpc_style->color_cube.dark[state_type],
+ x + half_width, y + height,
+ x + width, y + half_height);
+
+ ge_cairo_line(cr, &olpc_style->color_cube.light[state_type],
+ x + 2, y + half_height,
+ x + half_width, y + 2);
+ ge_cairo_line(cr, &olpc_style->color_cube.light[state_type],
+ x + half_width, y + 2,
+ x + width - 2, y + half_height);
+ ge_cairo_line(cr, &olpc_style->color_cube.light[state_type],
+ x + 1, y + half_height,
+ x + half_width, y + 1);
+ ge_cairo_line(cr, &olpc_style->color_cube.light[state_type],
+ x + half_width, y + 1,
+ x + width - 1, y + half_height);
+ ge_cairo_line(cr, &olpc_style->color_cube.light[state_type],
+ x, y + half_height,
+ x + half_width, y);
+ ge_cairo_line(cr, &olpc_style->color_cube.light[state_type],
+ x + half_width, y,
+ x + width, y + half_height);
+ break;
+ default:
+ break;
+ }
+
+ cairo_destroy(cr);
+}
+
+static void
+olpc_style_draw_box(GtkStyle * style,
+ GdkWindow * window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ GdkRectangle * area,
+ GtkWidget * widget,
+ const gchar *detail,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ OlpcStyle *olpc_style = OLPC_STYLE (style);
+ cairo_t *canvas;
+ gboolean draw_border = TRUE;
+
+ /***********************************************/
+ /* GTK Sanity Checks */
+ /***********************************************/
+ CHECK_ARGS
+ SANITIZE_SIZE
+
+
+ /***********************************************/
+ /* GTK Special Cases - Ignored Widgets */
+ /***********************************************/
+ if ((CHECK_DETAIL(detail, "optionmenutab")) ||
+ (CHECK_DETAIL (detail, "vscrollbar")) ||
+ (CHECK_DETAIL (detail, "hscrollbar")) ||
+ (CHECK_DETAIL (detail, "slider")) ||
+ (CHECK_DETAIL (detail, "buttondefault")) ||
+ (CHECK_DETAIL (detail, "bar") &&
+ ((height < 1) && (width < 1))))
+ {
+ return;
+ }
+
+
+ /***********************************************/
+ /* GTK Special Cases - adjust Size/Offset */
+ /***********************************************/
+ if ((CHECK_DETAIL (detail, "bar")))
+ {
+ x += 1;
+ y += 1;
+ width -= 2;
+ height -= 2;
+
+ draw_border=FALSE;
+ }
+ else if (CHECK_DETAIL (detail, "handlebox_bin"))
+ {
+ draw_border=FALSE;
+ }
+ else if (CHECK_DETAIL (detail, "trough"))
+ {
+ draw_border = FALSE;
+ }
+
+
+ /***********************************************/
+ /* Fill Box */
+ /***********************************************/
+ if ((!style->bg_pixmap[state_type]) || GDK_IS_PIXMAP(window))
+ {
+ canvas = ge_gdk_drawable_to_cairo (window, area);
+
+ ge_cairo_set_color(canvas, &olpc_style->color_cube.bg[state_type]);
+
+ cairo_rectangle(canvas, x, y, width, height);
+
+ cairo_fill(canvas);
+
+ cairo_destroy(canvas);
+ }
+ else
+ {
+ gtk_style_apply_default_background(style, window,
+ widget && !GTK_WIDGET_NO_WINDOW(widget),
+ state_type, area,
+ x, y, width, height);
+ }
+
+ /***********************************************/
+ /* Draw Box Border */
+ /***********************************************/
+ if (draw_border)
+ {
+ olpc_style_draw_shadow(style, window, state_type, shadow_type, area, widget,
+ detail, x, y, width, height);
+ }
+
+ /***********************************************/
+ /* Draw Widget Specific Sub-Parts */
+ /***********************************************/
+ if (CHECK_DETAIL (detail, "button"))
+ {
+ /* Paint a triangle here instead of in "buttondefault"
+ which is drawn _behind_ the current button */
+ if (widget && GE_WIDGET_HAS_DEFAULT (widget))
+ {
+ canvas = ge_gdk_drawable_to_cairo (window, area);
+
+ ge_cairo_set_color(canvas, &olpc_style->color_cube.bg[GTK_STATE_SELECTED]);
+ cairo_move_to(canvas, x+2.5, y+2.5);
+ cairo_line_to(canvas, x+10.5, y+2.5);
+ cairo_line_to(canvas, x+2.5, y+10.5);
+ cairo_line_to(canvas, x+2.5, y+2.5);
+ cairo_fill(canvas);
+
+ ge_cairo_set_color(canvas, &olpc_style->color_cube.dark[state_type]);
+ cairo_move_to(canvas, x + 2.5, y + 11);
+ cairo_line_to(canvas, x + 2.5, y + 2.5);
+ cairo_line_to(canvas, x + 11, y + 2.5);
+ cairo_stroke(canvas);
+
+ cairo_set_line_width (canvas, 0.5);
+ ge_cairo_set_color(canvas, &olpc_style->color_cube.light[state_type]);
+ cairo_move_to(canvas, x+11, y+3);
+ cairo_line_to(canvas, x+3, y+11);
+ cairo_stroke(canvas);
+
+ cairo_destroy(canvas);
+ }
+ }
+
+ /* Draw Option Menus and Combo Box "Tab" The Same Way Here */
+ if (CHECK_DETAIL(detail, "optionmenu") || (CHECK_DETAIL(detail, "button") &&
+ (ge_is_combo_box(widget, FALSE)) && !(ge_is_combo_box_entry(widget))))
+ {
+ GtkRequisition indicator_size;
+ GtkBorder indicator_spacing;
+ gint vline_x;
+
+ if (state_type != GTK_STATE_INSENSITIVE)
+ state_type = GTK_STATE_NORMAL;
+
+ ge_option_menu_get_props (widget, &indicator_size, &indicator_spacing);
+
+ if ((!widget) || (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL))
+ vline_x = x + indicator_size.width + indicator_spacing.left + indicator_spacing.right;
+ else
+ vline_x = x + width - (indicator_size.width + indicator_spacing.left +
+ indicator_spacing.right) - style->xthickness;
+
+ canvas = ge_gdk_drawable_to_cairo (window, area);
+
+ olpc_draw_separator(canvas, FALSE, vline_x, y + style->ythickness + 1, style->xthickness, height - 2*style->ythickness - 2);
+
+ cairo_destroy(canvas);
+
+ if ((widget) && (gtk_widget_get_direction (GTK_WIDGET (widget)) == GTK_TEXT_DIR_RTL))
+ x += indicator_spacing.right + style->xthickness;
+ else
+ x += width - indicator_size.width - indicator_spacing.right - style->xthickness;
+
+ y += ((height - indicator_size.height) / 2) + 1;
+
+ width = indicator_size.width;
+ height = indicator_size.height;
+
+ olpc_style_draw_arrow (style, window, state_type, shadow_type, area, NULL, "optionmenu",
+ GTK_ARROW_DOWN, TRUE, x, y, width, height);
+ }
+}
+
+static void
+olpc_style_draw_check(GtkStyle * style,
+ GdkWindow * window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ GdkRectangle * area,
+ GtkWidget * widget,
+ const gchar *detail,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ OlpcStyle *olpc_style = OLPC_STYLE (style);
+
+ CairoColor *color1 = NULL;
+ cairo_t *cr;
+
+ CHECK_ARGS
+ SANITIZE_SIZE
+
+ if (shadow_type == GTK_SHADOW_IN)
+ {
+ color1 = &olpc_style->color_cube.bg[GTK_STATE_ACTIVE];
+ }
+
+ cr = ge_gdk_drawable_to_cairo (window, area);
+
+ if (state_type == GTK_STATE_INSENSITIVE)
+ {
+ ge_cairo_set_color(cr, &olpc_style->color_cube.dark[state_type]);
+
+ cairo_rectangle(cr, x + 0.5, y + 0.5, width - 1, height - 1);
+
+ cairo_stroke(cr);
+ }
+ else
+ {
+ olpc_style_draw_box(style, window, state_type, shadow_type, area, widget,
+ detail, x, y, width, height);
+ if (color1)
+ {
+ ge_cairo_set_color(cr, color1);
+
+ cairo_rectangle(cr, x+1, y+1, width-2, height-2);
+
+ cairo_fill(cr);
+ }
+ }
+
+ cairo_destroy(cr);
+}
+
+
+/* Thanks to Evan Lawrence */
+static void
+olpc_style_draw_option(GtkStyle * style,
+ GdkWindow * window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ GdkRectangle * area,
+ GtkWidget * widget,
+ const gchar *detail,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ OlpcStyle *olpc_style = OLPC_STYLE (style);
+
+ CairoColor *color1 = NULL, *color2 = NULL, *color3 = NULL;
+ cairo_t *cr;
+
+ gint centerX;
+ gint centerY;
+ gint radius;
+
+ CHECK_ARGS
+ SANITIZE_SIZE
+
+ if (shadow_type == GTK_SHADOW_IN ||
+ shadow_type == GTK_SHADOW_ETCHED_IN)
+ {
+ color1 = &olpc_style->color_cube.dark[state_type];
+ color2 = &olpc_style->color_cube.light[state_type];
+ color3 = &olpc_style->color_cube.bg[GTK_STATE_ACTIVE];
+ }
+ else
+ {
+ color1 = &olpc_style->color_cube.light[state_type];
+ color2 = &olpc_style->color_cube.dark[state_type];
+ color3 = &olpc_style->color_cube.bg[state_type];
+ }
+
+ cr = ge_gdk_drawable_to_cairo (window, area);
+ cairo_set_line_width (cr, 0.5);
+
+ centerX = x + floor(width/2);
+ centerY = y + floor(height/2);
+ radius = floor(MIN(width, height)/2) - 0.5;
+
+ switch (shadow_type)
+ {
+ case GTK_SHADOW_ETCHED_IN:
+ ge_cairo_set_color(cr, color2);
+ cairo_arc(cr, centerX + 1, centerY + 1, radius + 1, 0, 2 * M_PI);
+ cairo_stroke(cr);
+
+ ge_cairo_set_color(cr, color1);
+ cairo_arc(cr, centerX, centerY, radius + 1, 0, 2 * M_PI);
+ cairo_stroke(cr);
+
+ break;
+ case GTK_SHADOW_ETCHED_OUT:
+ ge_cairo_set_color(cr, color1);
+ cairo_arc(cr, centerX - 1, centerY - 1, radius + 1, 0, 2 * M_PI);
+ cairo_stroke(cr);
+
+ ge_cairo_set_color(cr, color2);
+ cairo_arc(cr, centerX, centerY, radius + 1, 0, 2 * M_PI);
+ cairo_stroke(cr);
+
+ break;
+ default:
+ cairo_set_line_width (cr, 0.5);
+
+ cairo_new_path (cr);
+
+ cairo_move_to(cr, centerX + (radius + 2), centerY + (radius + 2));
+ cairo_line_to(cr, centerX + (radius + 2)*sin(M_PI/4.0), centerY - (radius + 2)*cos(M_PI/4.0));
+ cairo_line_to(cr, centerX - (radius + 2)*sin(M_PI/4.0), centerY + (radius + 2)*cos(M_PI/4.0));
+ cairo_line_to(cr, centerX + (radius + 2), centerY + (radius + 2));
+
+ cairo_close_path (cr);
+
+ cairo_save(cr);
+ cairo_clip (cr);
+
+ ge_cairo_set_color(cr, color2);
+ cairo_arc(cr, centerX, centerY, radius + 1, 0, 2*M_PI);
+ cairo_fill(cr);
+
+ cairo_restore(cr);
+
+ cairo_new_path (cr);
+
+ cairo_move_to(cr, centerX - (radius + 2), centerY - (radius + 2));
+ cairo_line_to(cr, centerX + (radius + 2)*sin(M_PI/4.0), centerY - (radius + 2)*cos(M_PI/4.0));
+ cairo_line_to(cr, centerX - (radius + 2)*sin(M_PI/4.0), centerY + (radius + 2)*cos(M_PI/4.0));
+ cairo_line_to(cr, centerX - (radius + 2), centerY - (radius + 2));
+
+ cairo_close_path (cr);
+
+ cairo_save(cr);
+
+ cairo_clip (cr);
+
+ ge_cairo_set_color(cr, color1);
+ cairo_arc(cr, centerX, centerY, radius + 1, 0, 2*M_PI);
+ cairo_fill(cr);
+
+ cairo_restore(cr);
+
+ ge_cairo_set_color(cr, color3);
+ cairo_arc(cr, centerX, centerY, radius, 0, 2 * M_PI);
+ cairo_fill(cr);
+
+ break;
+ }
+
+ cairo_destroy(cr);
+}
+
+static void
+olpc_style_draw_shadow_gap(GtkStyle * style,
+ GdkWindow * window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ GdkRectangle * area,
+ GtkWidget * widget,
+ const gchar *detail,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ GtkPositionType gap_side,
+ gint gap_x,
+ gint gap_width)
+{
+ OlpcStyle *olpc_style = OLPC_STYLE (style);
+
+ CairoColor *color1 = NULL, *color2 = NULL;
+ cairo_t *cr;
+
+ CHECK_ARGS
+ SANITIZE_SIZE
+
+ shadow_type = olpc_shadow_type (style, detail, shadow_type);
+
+ switch (shadow_type) {
+ case GTK_SHADOW_NONE:
+ return;
+ case GTK_SHADOW_IN:
+ color1 = &olpc_style->color_cube.dark[state_type];
+ color2 = &olpc_style->color_cube.light[state_type];
+ break;
+ case GTK_SHADOW_OUT:
+ color1 = &olpc_style->color_cube.light[state_type];
+ color2 = &olpc_style->color_cube.dark[state_type];
+ break;
+ case GTK_SHADOW_ETCHED_IN:
+ case GTK_SHADOW_ETCHED_OUT:
+ color1 = &olpc_style->color_cube.dark[state_type];
+ color2 = &olpc_style->color_cube.dark[state_type];
+ }
+
+ cr = ge_gdk_drawable_to_cairo (window, area);
+
+ switch (gap_side) {
+ case GTK_POS_TOP:
+ if (gap_x > 0) {
+ ge_cairo_line (cr, color1,
+ x, y,
+ x + gap_x, y);
+ }
+ if ((width - (gap_x + gap_width)) > 0) {
+ ge_cairo_line (cr, color1,
+ x + gap_x + gap_width - 1, y,
+ x + width - 1, y);
+ }
+ ge_cairo_line (cr, color1,
+ x, y,
+ x, y + height - 1);
+ ge_cairo_line (cr, color2,
+ x + width - 1, y,
+ x + width - 1, y + height - 1);
+ ge_cairo_line (cr, color2,
+ x, y + height - 1,
+ x + width - 1, y + height - 1);
+ break;
+ case GTK_POS_BOTTOM:
+ ge_cairo_line (cr, color1,
+ x, y,
+ x + width - 1, y);
+ ge_cairo_line (cr, color1,
+ x, y,
+ x, y + height - 1);
+ ge_cairo_line (cr, color2,
+ x + width - 1, y,
+ x + width - 1, y + height - 1);
+
+ if (gap_x > 0) {
+ ge_cairo_line (cr, color2,
+ x, y + height - 1,
+ x + gap_x, y + height - 1);
+ }
+ if ((width - (gap_x + gap_width)) > 0) {
+ ge_cairo_line (cr, color2,
+ x + gap_x + gap_width - 1, y + height - 1,
+ x + width - 1, y + height - 1);
+ }
+
+ break;
+ case GTK_POS_LEFT:
+ ge_cairo_line (cr, color1,
+ x, y,
+ x + width - 1, y);
+ if (gap_x > 0) {
+ ge_cairo_line (cr, color1,
+ x, y,
+ x, y + gap_x);
+ }
+ if ((height - (gap_x + gap_width)) > 0) {
+ ge_cairo_line (cr, color1,
+ x, y + gap_x + gap_width - 1,
+ x, y + height - 1);
+ }
+
+ ge_cairo_line (cr, color2,
+ x + width - 1, y,
+ x + width - 1, y + height - 1);
+ ge_cairo_line (cr, color2,
+ x, y + height - 1,
+ x + width - 1, y + height - 1);
+ break;
+ case GTK_POS_RIGHT:
+ ge_cairo_line (cr, color1,
+ x, y,
+ x + width - 1, y);
+ ge_cairo_line (cr, color1,
+ x, y,
+ x, y + height - 1);
+
+
+ if (gap_x > 0) {
+ ge_cairo_line (cr, color2,
+ x + width - 1, y,
+ x + width - 1, y + gap_x);
+ }
+ if ((height - (gap_x + gap_width)) > 0) {
+ ge_cairo_line (cr, color2,
+ x + width - 1, y + gap_x + gap_width - 1,
+ x + width - 1, y + height - 1);
+ }
+
+ ge_cairo_line (cr, color2,
+ x, y + height - 1,
+ x + width - 1, y + height - 1);
+
+ }
+
+ cairo_destroy(cr);
+}
+
+
+static void
+olpc_style_draw_box_gap(GtkStyle * style,
+ GdkWindow * window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ GdkRectangle * area,
+ GtkWidget * widget,
+ const gchar *detail,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ GtkPositionType gap_side,
+ gint gap_x,
+ gint gap_width)
+{
+ SANITIZE_SIZE
+
+ gtk_style_apply_default_background(style, window,
+ widget && !GTK_WIDGET_NO_WINDOW(widget),
+ state_type, area,
+ x, y, width, height);
+ olpc_style_draw_shadow_gap (style, window, state_type, shadow_type,
+ area, widget, detail, x, y, width, height,
+ gap_side, gap_x, gap_width);
+}
+
+
+static void
+olpc_style_draw_extension(DRAW_ARGS, GtkPositionType gap_side)
+{
+ switch (gap_side)
+ {
+ case GTK_POS_TOP: gap_side = GTK_POS_BOTTOM; break;
+ case GTK_POS_BOTTOM: gap_side = GTK_POS_TOP; break;
+ case GTK_POS_LEFT: gap_side = GTK_POS_RIGHT; break;
+ case GTK_POS_RIGHT: gap_side = GTK_POS_LEFT; break;
+ }
+
+ olpc_tab(DRAW_VARS, gap_side);
+}
+
+static void
+olpc_style_draw_slider(GtkStyle * style,
+ GdkWindow * window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ GdkRectangle * area,
+ GtkWidget * widget,
+ const gchar *detail,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ GtkOrientation orientation)
+{
+ OlpcStyle *olpc_style = OLPC_STYLE (style);
+
+ GdkPoint pointsh[7];
+ gint midlines = MARKS_SLASH;
+ gint modx, mody;
+ cairo_t *cr;
+
+ CHECK_ARGS
+
+ SANITIZE_SIZE
+
+#ifdef DEBUG
+ printf("draw_slider(%s, %d, %d, %d)\n", detail, x, y, orientation);
+#endif
+
+#ifdef DEBUG
+ printf("Slider... x,y=%d,%d width = %d, height = %d (%d)\n",x,y,width,height, state_type);
+#endif
+ midlines = OLPC_RC_STYLE (style->rc_style)->mark_type1;
+#ifdef DEBUG
+ printf("Midlines = %d\n", midlines);
+#endif
+
+ pointsh[0].x = x; pointsh[0].y = y;
+ pointsh[1].x = x + width - 1; pointsh[1].y = y;
+ pointsh[2].x = x + width - 1; pointsh[2].y = y + height - 1;
+ pointsh[3].x = x; pointsh[3].y = y + height - 1;
+ pointsh[4].x = x; pointsh[4].y = y;
+
+ cr = ge_gdk_drawable_to_cairo (window, area);
+
+ ge_cairo_set_color(cr, &olpc_style->color_cube.bg[state_type]);
+
+ ge_cairo_rounded_rectangle(cr, x + 3, y + 3, width - 6, height - 6, 2, CR_CORNER_ALL);
+
+ cairo_fill(cr);
+
+ //olpc_style_draw_shadow(style, window, state_type, shadow_type, area,
+ // widget, detail, x, y, width, height);
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ { modx = 4; mody = 0; }
+ else
+ { modx = 0; mody = 4; }
+
+ switch (midlines)
+ {
+ case MARKS_NOTHING:
+ break;
+ case MARKS_INVSLASH: /* Inverse //:es */
+ olpc_slash_two(cr,
+ &olpc_style->color_cube.dark[state_type],
+ &olpc_style->color_cube.light[state_type],
+ x, y, width, height);
+ break;
+ case MARKS_DOT:
+ olpc_dot(cr,
+ &olpc_style->color_cube.light[state_type],
+ &olpc_style->color_cube.dark[state_type],
+ x + width / 2 - modx,
+ y + height / 2 - mody);
+ olpc_dot(cr,
+ &olpc_style->color_cube.light[state_type],
+ &olpc_style->color_cube.dark[state_type],
+ x + width / 2,
+ y + height / 2);
+ olpc_dot(cr,
+ &olpc_style->color_cube.light[state_type],
+ &olpc_style->color_cube.dark[state_type],
+ x + width / 2 + modx,
+ y + height / 2 + mody);
+ break;
+ case MARKS_INVDOT: /* Inverted */
+ olpc_dot(cr,
+ &olpc_style->color_cube.dark[state_type],
+ &olpc_style->color_cube.light[state_type],
+ x + width / 2 - modx,
+ y + height / 2 - mody);
+ olpc_dot(cr,
+ &olpc_style->color_cube.dark[state_type],
+ &olpc_style->color_cube.light[state_type],
+ x + width / 2,
+ y + height / 2);
+ olpc_dot(cr,
+ &olpc_style->color_cube.dark[state_type],
+ &olpc_style->color_cube.light[state_type],
+ x + width / 2 + modx,
+ y + height / 2 + mody);
+ break;
+ case MARKS_SLASH:
+ default:
+ olpc_slash_two(cr,
+ &olpc_style->color_cube.light[state_type],
+ &olpc_style->color_cube.dark[state_type],
+ x, y, width, height);
+ break;
+ }
+
+ cairo_destroy(cr);
+
+}
+
+static void
+olpc_style_draw_handle(GtkStyle * style,
+ GdkWindow * window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ GdkRectangle * area,
+ GtkWidget * widget,
+ const gchar *detail,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ GtkOrientation orientation)
+{
+ OlpcStyle *olpc_style = OLPC_STYLE (style);
+
+ cairo_t *cr;
+ CairoColor *light=NULL, *dark=NULL;
+ GdkRectangle dest;
+ gint modx, mody;
+
+ CHECK_ARGS
+
+#ifdef DEBUG
+ printf("draw_handle(state=%d, shadow=%d, detail=%s, [%d,%d]@[%d,%d]\n",
+ state_type, shadow_type, detail?detail:"nul",width,height,x,y);
+#endif
+ SANITIZE_SIZE
+
+ cr = ge_gdk_drawable_to_cairo (window, area);
+
+ if (CHECK_DETAIL (detail, "paned"))
+ {
+ int i, w;
+ int start_i, end_i;
+
+ dest.x = x;
+ dest.y = y;
+ dest.width = width;
+ dest.height = height;
+
+ light = &olpc_style->color_cube.light[state_type];
+ dark = &olpc_style->color_cube.dark[state_type];
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ w = width;
+ else
+ w = height;
+ switch (OLPC_RC_STYLE (style->rc_style)->paned_dots) {
+ default:
+ case PANED_DOTSFULL:
+ start_i = 5;
+ end_i = w - 5;
+ break;
+ case PANED_DOTSSOME:
+ start_i = w/2 - 16;
+ end_i = w/2 + 16;
+ break;
+ case PANED_DOTSNONE:
+ start_i = w;
+ end_i = 0;
+ break;
+ }
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ for (i=x + start_i; i <= x + end_i; i+=8)
+ {
+ olpc_dot(cr, light, dark, i, y + height / 2);
+ }
+ }
+ else
+ {
+ for (i=y + start_i; i <= y + end_i; i+=8)
+ {
+ olpc_dot(cr, light, dark, x + width / 2, i);
+ }
+ }
+
+ cairo_destroy(cr);
+
+ return;
+ }
+
+ olpc_style_draw_box(style, window, state_type, shadow_type, area, widget,
+ detail, x, y, width, height);
+
+ ge_cairo_line(cr, &olpc_style->color_cube.light[state_type],
+ x + width, y, x + width, y + height - 2);
+
+ /* Draw something in the box if so wanted */
+ if (OLPC_RC_STYLE (style->rc_style)->mark_type1 != MARKS_NOTHING)
+ {
+ light = &olpc_style->color_cube.light[state_type];
+ dark = &olpc_style->color_cube.dark[state_type];
+
+ orientation = GTK_ORIENTATION_HORIZONTAL;
+ if (height > width)
+ orientation = GTK_ORIENTATION_VERTICAL;
+
+ dest.x = x + style->xthickness;
+ dest.y = y + style->ythickness;
+ dest.width = width - (style->xthickness * 2);
+ dest.height = height - (style->ythickness * 2);
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ { modx = 4; mody = 0; }
+ else
+ { modx = 0; mody = 4; }
+
+ switch (OLPC_RC_STYLE (style->rc_style)->mark_type1)
+ {
+ case MARKS_INVSLASH: /* Inverse //:es */
+ olpc_slash_two(cr, dark, light,
+ x, y, width, height);
+ break;
+ case MARKS_DOT: /* Dots */
+ olpc_dot(cr, light, dark,
+ x + width / 2 - modx,
+ y + height / 2 - mody);
+ olpc_dot(cr, light, dark,
+ x + width / 2,
+ y + height / 2);
+ olpc_dot(cr, light, dark,
+ x + width / 2 + modx,
+ y + height / 2 + mody);
+ break;
+ case MARKS_INVDOT: /* Inverted dots */
+ olpc_dot(cr, dark, light,
+ x + width / 2 - modx,
+ y + height / 2 - mody);
+ olpc_dot(cr, dark, light,
+ x + width / 2,
+ y + height / 2);
+ olpc_dot(cr, dark, light,
+ x + width / 2 + modx,
+ y + height / 2 + mody);
+ break;
+ case MARKS_SLASH:
+ default:
+ olpc_slash_two(cr, light, dark,
+ x, y, width, height);
+ break;
+ }
+ }
+
+ cairo_destroy(cr);
+}
+
+static void
+olpc_tab(DRAW_ARGS, gint orientation)
+{
+ OlpcStyle *olpc_style = OLPC_STYLE (style);
+
+ CairoColor *light, *dark;
+ cairo_t *cr;
+
+ CHECK_ARGS
+
+ SANITIZE_SIZE
+
+ light = &olpc_style->color_cube.light[state_type];
+ dark = &olpc_style->color_cube.dark[state_type];
+
+ cr = ge_gdk_drawable_to_cairo (window, area);
+
+ if ((!style->bg_pixmap[state_type]) || GDK_IS_PIXMAP(window))
+ {
+ ge_cairo_set_color(cr, &olpc_style->color_cube.bg[state_type]);
+
+ cairo_rectangle(cr, x, y, width - 1, height - 1);
+
+ cairo_fill(cr);
+ }
+ else
+ {
+ gtk_style_apply_default_background(style, window,
+ widget && !GTK_WIDGET_NO_WINDOW(widget),
+ state_type, area, x, y, width, height);
+ }
+
+ switch(orientation)
+ {
+ case GTK_POS_TOP:
+ ge_cairo_line(cr, light,
+ x, y + height, x, y);
+ ge_cairo_line(cr, light,
+ x, y, x + width - 2, y);
+ ge_cairo_line(cr, dark,
+ x + width - 2, y, x + width - 2, y + height - 1);
+ break;
+ case GTK_POS_BOTTOM:
+ ge_cairo_line(cr, light,
+ x, y - 1, x, y + height - 1);
+ ge_cairo_line(cr, dark,
+ x, y + height - 1, x + width - 2, y + height - 1);
+ ge_cairo_line(cr, dark,
+ x + width - 2, y + height - 1, x + width - 2, y);
+ break;
+ case GTK_POS_LEFT:
+ ge_cairo_line(cr, light,
+ x, y + height - 1, x, y);
+ ge_cairo_line(cr, light,
+ x, y, x + width, y);
+ ge_cairo_line(cr, dark,
+ x, y + height - 1, x + width - 1, y + height - 1);
+ break;
+ case GTK_POS_RIGHT:
+ ge_cairo_line(cr, light,
+ x - 1, y, x + width - 1, y);
+ ge_cairo_line(cr, dark,
+ x + width - 1, y, x + width - 1, y + height - 1);
+ ge_cairo_line(cr, dark,
+ x, y + height - 1, x + width - 1, y + height - 1);
+ break;
+ }
+
+ cairo_destroy(cr);
+}
+
+GType olpc_type_style = 0;
+
+void
+olpc_style_register_type (GTypeModule *module)
+{
+ static const GTypeInfo object_info =
+ {
+ sizeof (OlpcStyleClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) olpc_style_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (OlpcStyle),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) olpc_style_init,
+ };
+
+ olpc_type_style = g_type_module_register_type (module,
+ GTK_TYPE_STYLE,
+ "OlpcStyle",
+ &object_info, 0);
+}
+
+static void
+olpc_style_init (OlpcStyle *style)
+{
+}
+
+static void
+olpc_style_realize (GtkStyle * style)
+{
+ OlpcStyle *olpc_style = OLPC_STYLE (style);
+
+ olpc_parent_style_class->realize (style);
+
+ ge_gtk_style_to_cairo_color_cube (style, &olpc_style->color_cube);
+}
+
+static void
+olpc_style_class_init (OlpcStyleClass *klass)
+{
+ GtkStyleClass *style_class = GTK_STYLE_CLASS (klass);
+
+ olpc_parent_style_class = g_type_class_peek_parent (klass);
+
+ style_class->realize = olpc_style_realize;
+
+ style_class->draw_hline = olpc_style_draw_hline;
+ style_class->draw_vline = olpc_style_draw_vline;
+ style_class->draw_shadow = olpc_style_draw_shadow;
+ style_class->draw_polygon = olpc_style_draw_polygon;
+ style_class->draw_arrow = olpc_style_draw_arrow;
+ style_class->draw_diamond = olpc_style_draw_diamond;
+ style_class->draw_box = olpc_style_draw_box;
+ style_class->draw_tab = olpc_style_draw_box;
+
+ style_class->draw_check = olpc_style_draw_check;
+ style_class->draw_option = olpc_style_draw_option;
+ style_class->draw_shadow_gap = olpc_style_draw_shadow_gap;
+ style_class->draw_box_gap = olpc_style_draw_box_gap;
+ style_class->draw_extension = olpc_style_draw_extension;
+ style_class->draw_slider = olpc_style_draw_slider;
+ style_class->draw_handle = olpc_style_draw_handle;
+}
+
+
+/*
+FIXME: file/font selector background OK
+FIXME: radioknappar varierar storlek rätt bra.. OK
+FIXME: scrollbars OK
+FIXME: inconsistent-radioknappar OK
+FIXME: paned-pluttarna OK
+FIXME: spinbuttons, vid max OK
+
+FIXME: Blå triangeln vid RTL, WONTFIX?
+*/
+
diff --git a/gtk-engine/src/widget-information.c b/gtk-engine/src/widget-information.c
new file mode 100644
index 0000000..55d260f
--- /dev/null
+++ b/gtk-engine/src/widget-information.c
@@ -0,0 +1,331 @@
+#include <gtk/gtk.h>
+
+#include "general-support.h"
+#include "widget-information.h"
+#include <math.h>
+#include <string.h>
+
+/* Widget Type Lookups/Macros
+
+ Based on/modified from functions in
+ Smooth-Engine.
+*/
+gboolean
+ge_object_is_a (const GObject * object, const gchar * type_name)
+{
+ gboolean result = FALSE;
+
+ if ((object))
+ {
+ GType tmp = g_type_from_name (type_name);
+
+ if (tmp)
+ result = g_type_check_instance_is_a ((GTypeInstance *) object, tmp);
+ }
+
+ return result;
+}
+
+gboolean
+ge_is_combo_box_entry (GtkWidget * widget)
+{
+ gboolean result = FALSE;
+
+ if ((widget) && (widget->parent))
+ {
+ if (GE_IS_COMBO_BOX_ENTRY (widget->parent))
+ result = TRUE;
+ else
+ result = ge_is_combo_box_entry (widget->parent);
+ }
+ return result;
+}
+
+gboolean
+ge_combo_box_is_using_list (GtkWidget * widget)
+{
+ gboolean result = FALSE;
+
+ if ((widget) && (GE_IS_COMBO_BOX (widget->parent)))
+ {
+ gboolean *tmp = NULL;
+
+ gtk_widget_style_get (widget->parent, "appears-as-list", &result, NULL);
+
+ if (tmp)
+ result = *tmp;
+ }
+
+ return result;
+}
+
+gboolean
+ge_is_combo_box (GtkWidget * widget, gboolean as_list)
+{
+ gboolean result = FALSE;
+
+ if ((widget) && (widget->parent))
+ {
+ if (GE_IS_COMBO_BOX (widget->parent))
+ {
+ if (as_list)
+ result = (ge_combo_box_is_using_list(widget->parent));
+ else
+ result = (!ge_combo_box_is_using_list(widget->parent));
+ }
+ else
+ result = ge_is_combo_box (widget->parent, as_list);
+ }
+ return result;
+}
+
+gboolean
+ge_is_combo (GtkWidget * widget)
+{
+ gboolean result = FALSE;
+
+ if ((widget) && (widget->parent))
+ {
+ if (GE_IS_COMBO (widget->parent))
+ result = TRUE;
+ else
+ result = ge_is_combo (widget->parent);
+ }
+ return result;
+}
+
+gboolean
+ge_is_in_combo_box (GtkWidget * widget)
+{
+ return ((ge_is_combo (widget) || ge_is_combo_box (widget, TRUE) || ge_is_combo_box_entry (widget)));
+}
+
+gboolean
+ge_is_toolbar_item (GtkWidget * widget)
+{
+ gboolean result = FALSE;
+
+ if ((widget) && (widget->parent)) {
+ if ((GE_IS_BONOBO_TOOLBAR (widget->parent))
+ || (GE_IS_BONOBO_DOCK_ITEM (widget->parent))
+ || (GE_IS_EGG_TOOLBAR (widget->parent))
+ || (GE_IS_TOOLBAR (widget->parent))
+ || (GE_IS_HANDLE_BOX (widget->parent)))
+ result = TRUE;
+ else
+ result = ge_is_toolbar_item (widget->parent);
+ }
+ return result;
+}
+
+gboolean
+ge_is_panel_widget_item (GtkWidget * widget)
+{
+ gboolean result = FALSE;
+
+ if ((widget) && (widget->parent))
+ {
+ if (GE_IS_PANEL_WIDGET (widget->parent))
+ result = TRUE;
+ else
+ result = ge_is_panel_widget_item (widget->parent);
+ }
+ return result;
+}
+
+gboolean
+ge_is_bonobo_dock_item (GtkWidget * widget)
+{
+ gboolean result = FALSE;
+
+ if ((widget))
+ {
+ if (GE_IS_BONOBO_DOCK_ITEM(widget) || GE_IS_BONOBO_DOCK_ITEM (widget->parent))
+ result = TRUE;
+ else if (GE_IS_BOX(widget) || GE_IS_BOX(widget->parent))
+ {
+ GtkContainer *box = GE_IS_BOX(widget)?GTK_CONTAINER(widget):GTK_CONTAINER(widget->parent);
+ GList *children = NULL, *child = NULL;
+
+ children = gtk_container_get_children(box);
+
+ for (child = g_list_first(children); child; child = g_list_next(child))
+ {
+ if (GE_IS_BONOBO_DOCK_ITEM_GRIP(child->data))
+ {
+ result = TRUE;
+ child = NULL;
+ }
+ }
+
+ if (children)
+ g_list_free(children);
+ }
+ }
+ return result;
+}
+
+static GtkWidget *
+ge_find_combo_box_entry_widget (GtkWidget * widget)
+{
+ GtkWidget *result = NULL;
+
+ if (widget)
+ {
+ if (GE_IS_COMBO_BOX_ENTRY (widget))
+ result = widget;
+ else
+ result = ge_find_combo_box_entry_widget (widget->parent);
+ }
+
+ return result;
+}
+
+static GtkWidget *
+ge_find_combo_box_widget (GtkWidget * widget, gboolean as_list)
+{
+ GtkWidget *result = NULL;
+
+ if (widget)
+ {
+ if (GE_IS_COMBO_BOX (widget))
+ {
+ if (as_list)
+ result = (ge_combo_box_is_using_list(widget))?widget:NULL;
+ else
+ result = (!ge_combo_box_is_using_list(widget))?widget:NULL;
+ }
+ else
+ result = ge_find_combo_box_widget (widget->parent, as_list);
+ }
+ return result;
+}
+
+static GtkWidget *
+ge_find_combo_widget (GtkWidget * widget)
+{
+ GtkWidget *result = NULL;
+
+ if (widget)
+ {
+ if (GE_IS_COMBO (widget))
+ result = widget;
+ else
+ result = ge_find_combo_widget(widget->parent);
+ }
+ return result;
+}
+
+GtkWidget*
+ge_find_combo_box_widget_parent (GtkWidget * widget)
+{
+ GtkWidget *result = NULL;
+
+ if (!result)
+ result = ge_find_combo_widget(widget);
+
+ if (!result)
+ result = ge_find_combo_box_widget(widget, TRUE);
+
+ if (!result)
+ result = ge_find_combo_box_entry_widget(widget);
+
+ return result;
+}
+
+gboolean
+ge_cell_renderer_toggle_get_inconsistent (GtkWidget * widget)
+{
+ gboolean result = FALSE;
+
+ g_object_get (widget, "inconsistent", &result, NULL);
+
+ return result;
+}
+
+gboolean
+ge_toggle_get_inconsistent (GtkWidget * widget, const gchar *detail, GtkShadowType shadow_type)
+{
+ return (GE_IS_TOGGLE_BUTTON(widget) && gtk_toggle_button_get_inconsistent(TOGGLE_BUTTON(widget)))
+ | (GE_IS_CELL_RENDERER_TOGGLE(widget) && ge_cell_renderer_toggle_get_inconsistent (widget))
+ | (CHECK_DETAIL(detail, "cellcheck") && (shadow_type == GTK_SHADOW_ETCHED_IN))
+ | (CHECK_DETAIL(detail, "cellradio") && (shadow_type == GTK_SHADOW_ETCHED_IN));
+}
+
+/***********************************************
+ * option_menu_get_props -
+ *
+ * Find Option Menu Size and Spacing
+ *
+ * Taken from Smooth
+ ***********************************************/
+void
+ge_option_menu_get_props (GtkWidget * widget,
+ GtkRequisition * indicator_size,
+ GtkBorder * indicator_spacing)
+{
+ GtkRequisition default_size = { 9, 5 };
+ GtkBorder default_spacing = { 7, 5, 2, 2 };
+ GtkRequisition *tmp_size = NULL;
+ GtkBorder *tmp_spacing = NULL;
+
+ if ((widget) && GE_IS_OPTION_MENU(widget))
+ gtk_widget_style_get (widget,
+ "indicator_size", &tmp_size,
+ "indicator_spacing", &tmp_spacing, NULL);
+
+ if (tmp_size)
+ {
+ *indicator_size = *tmp_size;
+ g_free (tmp_size);
+ }
+ else
+ *indicator_size = default_size;
+
+ if (tmp_spacing)
+ {
+ *indicator_spacing = *tmp_spacing;
+ g_free (tmp_spacing);
+ }
+ else
+ *indicator_spacing = default_spacing;
+}
+
+void
+ge_button_get_default_border (GtkWidget *widget,
+ GtkBorder *border)
+{
+ GtkBorder default_border = {1, 1, 1, 1};
+ GtkBorder *tmp_border = NULL;
+
+ if (widget && GE_IS_BUTTON (widget))
+ gtk_widget_style_get (widget, "default-border", &tmp_border, NULL);
+
+ if (tmp_border)
+ {
+ *border = *tmp_border;
+ g_free (tmp_border);
+ }
+ else
+ {
+ *border = default_border;
+ }
+}
+
+
+gboolean
+ge_widget_is_ltr (GtkWidget *widget)
+{
+ GtkTextDirection dir = GTK_TEXT_DIR_NONE;
+
+ if (GE_IS_WIDGET (widget))
+ dir = gtk_widget_get_direction (widget);
+
+ if (dir == GTK_TEXT_DIR_NONE)
+ dir = gtk_widget_get_default_direction ();
+
+ if (dir == GTK_TEXT_DIR_RTL)
+ return FALSE;
+ else
+ return TRUE;
+}
diff --git a/gtk-engine/src/widget-information.h b/gtk-engine/src/widget-information.h
new file mode 100644
index 0000000..db1d449
--- /dev/null
+++ b/gtk-engine/src/widget-information.h
@@ -0,0 +1,104 @@
+
+/* Object Type Lookups/Macros
+
+ Based on/modified from functions in
+ Smooth-Engine.
+*/
+#define GE_IS_WIDGET(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkWidget"))
+#define GE_IS_CONTAINER(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkContainer"))
+#define GE_IS_BIN(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkBin"))
+
+#define GE_IS_ARROW(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkArrow"))
+
+#define GE_IS_SEPARATOR(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkSeparator"))
+#define GE_IS_VSEPARATOR(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkVSeparator"))
+#define GE_IS_HSEPARATOR(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkHSeparator"))
+
+#define GE_IS_HANDLE_BOX(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkHandleBox"))
+#define GE_IS_HANDLE_BOX_ITEM(object) ((object) && GE_IS_HANDLE_BOX(object->parent))
+#define GE_IS_BONOBO_DOCK_ITEM(object) ((object) && ge_object_is_a ((GObject*)(object), "BonoboDockItem"))
+#define GE_IS_BONOBO_DOCK_ITEM_GRIP(object) ((object) && ge_object_is_a ((GObject*)(object), "BonoboDockItemGrip"))
+#define GE_IS_BONOBO_TOOLBAR(object) ((object) && ge_object_is_a ((GObject*)(object), "BonoboUIToolbar"))
+#define GE_IS_EGG_TOOLBAR(object) ((object) && ge_object_is_a ((GObject*)(object), "Toolbar"))
+#define GE_IS_TOOLBAR(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkToolbar"))
+#define GE_IS_PANEL_WIDGET(object) ((object) && (ge_object_is_a ((GObject*)(object), "PanelWidget") || ge_object_is_a ((GObject*)(object), "PanelApplet")))
+
+#define GE_IS_COMBO_BOX_ENTRY(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkComboBoxEntry"))
+#define GE_IS_COMBO_BOX(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkComboBox"))
+#define GE_IS_COMBO(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkCombo"))
+#define GE_IS_OPTION_MENU(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkOptionMenu"))
+
+#define GE_IS_TOGGLE_BUTTON(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkToggleButton"))
+#define GE_IS_CHECK_BUTTON(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkCheckButton"))
+#define GE_IS_SPIN_BUTTON(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkSpinButton"))
+
+#define GE_IS_STATUSBAR(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkStatusbar"))
+#define GE_IS_PROGRESS_BAR(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkProgressBar"))
+
+#define GE_IS_MENU_SHELL(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkMenuShell"))
+#define GE_IS_MENU(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkMenu"))
+#define GE_IS_MENU_BAR(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkMenuBar"))
+#define GE_IS_MENU_ITEM(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkMenuItem"))
+
+#define GE_IS_CHECK_MENU_ITEM(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkCheckMenuItem"))
+
+#define GE_IS_RANGE(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkRange"))
+
+#define GE_IS_SCROLLBAR(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkScrollbar"))
+#define GE_IS_VSCROLLBAR(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkVScrollbar"))
+#define GE_IS_HSCROLLBAR(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkHScrollbar"))
+
+#define GE_IS_SCALE(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkScale"))
+#define GE_IS_VSCALE(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkVScale"))
+#define GE_IS_HSCALE(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkHScale"))
+
+#define GE_IS_PANED(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkPaned"))
+#define GE_IS_VPANED(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkVPaned"))
+#define GE_IS_HPANED(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkHPaned"))
+
+#define GE_IS_BOX(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkBox"))
+#define GE_IS_VBOX(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkVBox"))
+#define GE_IS_HBOX(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkHBox"))
+
+#define GE_IS_CLIST(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkCList"))
+#define GE_IS_TREE_VIEW(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkTreeView"))
+#define GE_IS_ENTRY(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkEntry"))
+#define GE_IS_BUTTON(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkButton"))
+#define GE_IS_FIXED(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkFixed"))
+
+#define TOGGLE_BUTTON(object) (GE_IS_TOGGLE_BUTTON(object)?(GtkToggleButton *)object:NULL)
+
+#define GE_IS_NOTEBOOK(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkNotebook"))
+#define GE_IS_CELL_RENDERER_TOGGLE(object) ((object) && ge_object_is_a ((GObject*)(object), "GtkCellRendererToggle"))
+
+#define GE_WIDGET_HAS_DEFAULT(object) ((object) && GE_IS_WIDGET(object) && GTK_WIDGET_HAS_DEFAULT(object))
+
+GE_INTERNAL gboolean ge_object_is_a (const GObject * object, const gchar * type_name);
+
+GE_INTERNAL gboolean ge_combo_box_is_using_list (GtkWidget * widget);
+
+GE_INTERNAL gboolean ge_is_combo_box_entry (GtkWidget * widget);
+GE_INTERNAL gboolean ge_is_combo_box (GtkWidget * widget, gboolean as_list);
+GE_INTERNAL gboolean ge_is_combo (GtkWidget * widget);
+GE_INTERNAL gboolean ge_is_in_combo_box (GtkWidget * widget);
+
+GE_INTERNAL gboolean ge_is_toolbar_item (GtkWidget * widget);
+
+GE_INTERNAL gboolean ge_is_panel_widget_item (GtkWidget * widget);
+
+GE_INTERNAL gboolean ge_is_bonobo_dock_item (GtkWidget * widget);
+
+GE_INTERNAL GtkWidget *ge_find_combo_box_widget_parent (GtkWidget * widget);
+
+GE_INTERNAL gboolean ge_cell_renderer_toggle_get_inconsistent (GtkWidget * widget);
+GE_INTERNAL gboolean ge_toggle_get_inconsistent (GtkWidget * widget, const gchar *detail, GtkShadowType shadow_type);
+
+GE_INTERNAL void ge_option_menu_get_props (GtkWidget * widget,
+ GtkRequisition * indicator_size,
+ GtkBorder * indicator_spacing);
+
+GE_INTERNAL void ge_button_get_default_border (GtkWidget *widget,
+ GtkBorder *border);
+
+GE_INTERNAL gboolean ge_widget_is_ltr (GtkWidget *widget);
+
diff --git a/gtk-engine/theme/Makefile.am b/gtk-engine/theme/Makefile.am
new file mode 100644
index 0000000..1da5d18
--- /dev/null
+++ b/gtk-engine/theme/Makefile.am
@@ -0,0 +1,5 @@
+themedir = $(datadir)/themes/olpc/gtk-2.0
+theme_DATA = gtkrc
+
+EXTRA_DIST = \
+ $(theme_DATA)
diff --git a/gtk-engine/theme/gtkrc b/gtk-engine/theme/gtkrc
new file mode 100644
index 0000000..5cac2ec
--- /dev/null
+++ b/gtk-engine/theme/gtkrc
@@ -0,0 +1,102 @@
+style "default"
+{
+ GtkOptionMenu::indicator_spacing = { 3, 2, 1, 1 }
+ GtkCheckButton::indicator_size = 10
+ GtkCheckMenuItem::indicator_size = 10
+ GtkButton::default_border = { 0, 0, 0, 0 }
+
+ fg[NORMAL] = "#000000"
+ fg[ACTIVE] = "#000000"
+ fg[PRELIGHT] = "#000000"
+ fg[SELECTED] = "#FFFFFF"
+ fg[INSENSITIVE] = "#747474"
+ bg[NORMAL] = "#D3D3DD"
+ bg[ACTIVE] = "#C1C1CC"
+ bg[PRELIGHT] = "#E5E5F7"
+ bg[SELECTED] = "#336699"
+ bg[INSENSITIVE] = "#D3D3DD"
+ base[NORMAL] = "#E5E5F7"
+ base[ACTIVE] = "#808080"
+ base[PRELIGHT] = "#E5E5F7"
+ base[SELECTED] = "#336699"
+ base[INSENSITIVE] = "#E5E5F7"
+ text[NORMAL] = "#000000"
+ text[ACTIVE] = "#FFFFFF"
+ text[PRELIGHT] = "#000000"
+ text[SELECTED] = "#FFFFFF"
+ text[INSENSITIVE] = "#747474"
+
+ engine "olpc"
+ {
+ mark_type1 = NOTHING
+ mark_type2 = NOTHING
+ }
+}
+
+style "scrollbar" = "default"
+{
+ GtkRange::slider_width = 12
+ GtkRange::stepper_size = 1
+ GtkRange::trough-border = 0
+
+ bg[ACTIVE] = "#E6E6E6"
+ bg[NORMAL] = "#414141"
+ bg[PRELIGHT] = "#414141"
+}
+
+style "dark-default" = "default"
+{
+ fg[NORMAL] = "#FFFFFF"
+ fg[ACTIVE] = "#FFFFFF"
+ fg[PRELIGHT] = "#FFFFFF"
+ fg[SELECTED] = "#FFFFFF"
+ fg[INSENSITIVE] = "#FFFFFF"
+ bg[NORMAL] = "#414141"
+ bg[ACTIVE] = "#000000"
+ bg[PRELIGHT] = "#000000"
+ bg[SELECTED] = "#414141"
+ bg[INSENSITIVE] = "#D3D3DD"
+ base[NORMAL] = "#646464"
+ base[ACTIVE] = "#808080"
+ base[PRELIGHT] = "#E5E5F7"
+ base[SELECTED] = "#336699"
+ base[INSENSITIVE] = "#E5E5F7"
+ text[NORMAL] = "#FFFFFF"
+ text[ACTIVE] = "#FFFFFF"
+ text[PRELIGHT] = "#000000"
+ text[SELECTED] = "#FFFFFF"
+ text[INSENSITIVE] = "#747474"
+}
+
+style "toolbar" = "dark-default"
+{
+ GtkToolbar::internal_padding = 0
+ GtkToolbar::shadow_type = 0
+}
+
+style "toolbar-button" = "dark-default"
+{
+ GtkButton::default_border = { 0, 0, 0, 0 }
+ GtkButton::default_outsideborder = { 0, 0, 0, 0 }
+ GtkButton::inner_border = { 0, 0, 0, 0 }
+ GtkButton::focus_line_width = 0
+ GtkButton::focus_padding = 0
+ xthickness = 0
+ ythickness = 0
+}
+
+style "toolbar-entry" = "dark-default"
+{
+ GtkWidget::cursor_color = "#FFFFFF"
+ xthickness = 12
+ ythickness = 3
+ font_name = 'Sans 14'
+}
+
+class "GtkWidget" style "default"
+class "GtkScrollbar" style "scrollbar"
+class "GtkToolbar" style "toolbar"
+class "GtkSocket" style "dark-default"
+
+widget_class "*.GtkToolbar.*.<GtkButton>" style "toolbar-button"
+widget_class "*.GtkToolbar.*.<GtkEntry>" style "toolbar-entry"
diff --git a/gtkrc2-default b/gtkrc2-default
index b517c0f..7397047 100644
--- a/gtkrc2-default
+++ b/gtkrc2-default
@@ -1,3 +1,4 @@
+gtk-theme-name = "olpc"
gtk-icon-theme-name = "olpc"
gtk-cursor-theme-name = "olpc"
gtk-cursor-theme-size = 48
diff --git a/setup-user-theme.py b/setup-user-theme.py
new file mode 100755
index 0000000..bc5bfe7
--- /dev/null
+++ b/setup-user-theme.py
@@ -0,0 +1,38 @@
+#!/usr/bin/python
+
+# FIXME Need to handle the case when symlinks already exists
+
+import os
+
+theme_dir = os.path.expanduser('~/.themes/olpc/gtk-2.0')
+gtkrc_dest = os.path.join(theme_dir, 'gtkrc')
+
+engine_dir = os.path.expanduser('~/.gtk-2.0/engines')
+engine_dest = os.path.join(engine_dir, 'libolpc.so')
+
+src_dir = os.path.abspath(os.path.dirname(__file__))
+
+if not os.path.exists(theme_dir):
+ try:
+ os.makedirs(theme_dir)
+ except OSError, exc:
+ if exc[0] == 17: # File exists
+ pass
+try:
+ os.unlink(gtkrc_dest)
+except OSError, exc:
+ pass
+os.symlink(os.path.join(src_dir, 'gtk-engine/theme/gtkrc'), gtkrc_dest)
+
+if not os.path.exists(engine_dest):
+ try:
+ os.makedirs(engine_dir)
+ except OSError, exc:
+ if exc[0] == 17: # File exists
+ pass
+engine_src = os.path.join(src_dir, 'gtk-engine/src/.libs/libolpc.so')
+try:
+ os.unlink(engine_dest)
+except OSError, exc:
+ pass
+os.symlink(engine_src, engine_dest)
diff --git a/test/gtk-engine-test.py b/test/gtk-engine-test.py
new file mode 100755
index 0000000..4487002
--- /dev/null
+++ b/test/gtk-engine-test.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python
+
+import pygtk
+pygtk.require('2.0')
+import gtk
+
+class Base:
+ def __init__(self):
+ window = gtk.Window(gtk.WINDOW_TOPLEVEL)
+ window.set_default_size(300, 200)
+
+ vbox = gtk.VBox(False, 12)
+ vbox.set_border_width(12)
+
+ hbox = gtk.HBox(False, 12)
+
+ button = gtk.Button("Button")
+ hbox.pack_start(button, False)
+ button.show()
+
+ entry = gtk.Entry()
+ hbox.pack_start(entry, False)
+ entry.show()
+
+ vbox.pack_start(hbox, False)
+ hbox.show()
+
+
+ sw = gtk.ScrolledWindow()
+ sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
+ sw.set_size_request(150, 120)
+
+ text_view = gtk.TextView()
+ sw.add(text_view)
+ text_view.show()
+
+ vbox.pack_start(sw, False)
+ sw.show()
+
+ window.add(vbox)
+ vbox.show()
+
+ window.show()
+
+ def main(self):
+ gtk.main()
+
+settings = gtk.settings_get_default()
+
+if settings.get_property('gtk-theme-name') != 'olpc':
+ settings.set_string_property('gtk-theme-name', 'olpc', '')
+
+base = Base()
+base.main()