804 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			804 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* GTK - The GIMP Toolkit
 | 
						|
 * Copyright (C) 2016 Benjamin Otte <otte@gnome.org>
 | 
						|
 *
 | 
						|
 * This library is free software; you can redistribute it and/or
 | 
						|
 * modify it under the terms of the GNU Lesser General Public
 | 
						|
 * License as published by the Free Software Foundation; either
 | 
						|
 * version 2 of the License, or (at your option) any later version.
 | 
						|
 *
 | 
						|
 * This library is distributed in the hope that it will be useful,
 | 
						|
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
 * Lesser General Public License for more details.
 | 
						|
 *
 | 
						|
 * You should have received a copy of the GNU Lesser General Public
 | 
						|
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 | 
						|
 */
 | 
						|
 | 
						|
#include <config.h>
 | 
						|
 | 
						|
#include "gtkwin32drawprivate.h"
 | 
						|
 | 
						|
typedef enum {
 | 
						|
  ICON_CLOSE,
 | 
						|
  ICON_MINIMIZE,
 | 
						|
  ICON_MAXIMIZE,
 | 
						|
  ICON_RESTORE
 | 
						|
} Icon;
 | 
						|
 | 
						|
const guchar icon_close_pixels[] = {
 | 
						|
  0x00, 0x00, 0x00, 0x00,
 | 
						|
  0x00, 0x00, 0x00, 0x00,
 | 
						|
  0x0c, 0x06, 0x00, 0x00,
 | 
						|
  0x1c, 0x07, 0x00, 0x00,
 | 
						|
  0xb8, 0x03, 0x00, 0x00,
 | 
						|
  0xf0, 0x01, 0x00, 0x00,
 | 
						|
  0xe0, 0x00, 0x00, 0x00,
 | 
						|
  0xf0, 0x01, 0x00, 0x00,
 | 
						|
  0xb8, 0x03, 0x00, 0x00,
 | 
						|
  0x1c, 0x07, 0x00, 0x00,
 | 
						|
  0x0c, 0x06, 0x00, 0x00,
 | 
						|
  0x00, 0x00, 0x00, 0x00,
 | 
						|
  0x00, 0x00, 0x00, 0x00
 | 
						|
};
 | 
						|
 | 
						|
const guchar icon_minimize_pixels[] = {
 | 
						|
  0x00, 0x00, 0x00, 0x00,
 | 
						|
  0x00, 0x00, 0x00, 0x00,
 | 
						|
  0x00, 0x00, 0x00, 0x00,
 | 
						|
  0x00, 0x00, 0x00, 0x00,
 | 
						|
  0x00, 0x00, 0x00, 0x00,
 | 
						|
  0x00, 0x00, 0x00, 0x00,
 | 
						|
  0x00, 0x00, 0x00, 0x00,
 | 
						|
  0x00, 0x00, 0x00, 0x00,
 | 
						|
  0x00, 0x00, 0x00, 0x00,
 | 
						|
  0x00, 0x00, 0x00, 0x00,
 | 
						|
  0xfc, 0x00, 0x00, 0x00,
 | 
						|
  0x00, 0x00, 0x00, 0x00,
 | 
						|
  0x00, 0x00, 0x00, 0x00
 | 
						|
};
 | 
						|
 | 
						|
const guchar icon_maximize_pixels[] = {
 | 
						|
  0x00, 0x00, 0x00, 0x00,
 | 
						|
  0x00, 0x00, 0x00, 0x00,
 | 
						|
  0xfe, 0x07, 0x00, 0x00,
 | 
						|
  0xfe, 0x07, 0x00, 0x00,
 | 
						|
  0x02, 0x04, 0x00, 0x00,
 | 
						|
  0x02, 0x04, 0x00, 0x00,
 | 
						|
  0x02, 0x04, 0x00, 0x00,
 | 
						|
  0x02, 0x04, 0x00, 0x00,
 | 
						|
  0x02, 0x04, 0x00, 0x00,
 | 
						|
  0x02, 0x04, 0x00, 0x00,
 | 
						|
  0xfe, 0x07, 0x00, 0x00,
 | 
						|
  0x00, 0x00, 0x00, 0x00,
 | 
						|
  0x00, 0x00, 0x00, 0x00
 | 
						|
};
 | 
						|
 | 
						|
const guchar icon_restore_pixels[] = {
 | 
						|
  0x00, 0x00, 0x00, 0x00,
 | 
						|
  0x00, 0x00, 0x00, 0x00,
 | 
						|
  0xf8, 0x07, 0x00, 0x00,
 | 
						|
  0xf8, 0x07, 0x00, 0x00,
 | 
						|
  0x08, 0x04, 0x00, 0x00,
 | 
						|
  0x08, 0x04, 0x00, 0x00,
 | 
						|
  0xfe, 0x04, 0x00, 0x00,
 | 
						|
  0x82, 0x07, 0x00, 0x00,
 | 
						|
  0x82, 0x00, 0x00, 0x00,
 | 
						|
  0x82, 0x00, 0x00, 0x00,
 | 
						|
  0xfe, 0x00, 0x00, 0x00,
 | 
						|
  0x00, 0x00, 0x00, 0x00,
 | 
						|
  0x00, 0x00, 0x00, 0x00
 | 
						|
};
 | 
						|
 | 
						|
static struct {
 | 
						|
  int width;
 | 
						|
  int height;
 | 
						|
  gsize pixels_size;
 | 
						|
  const guchar *pixels;
 | 
						|
} icon_masks[] = {
 | 
						|
  { 13, 13, sizeof (icon_close_pixels), icon_close_pixels },
 | 
						|
  { 13, 13, sizeof (icon_minimize_pixels), icon_minimize_pixels },
 | 
						|
  { 13, 13, sizeof (icon_maximize_pixels), icon_maximize_pixels },
 | 
						|
  { 13, 13, sizeof (icon_restore_pixels), icon_restore_pixels }
 | 
						|
};
 | 
						|
 | 
						|
static void
 | 
						|
mask_icon (cairo_t *cr,
 | 
						|
           Icon     icon,
 | 
						|
           double   x,
 | 
						|
           double   y,
 | 
						|
           double   width,
 | 
						|
           double   height)
 | 
						|
{
 | 
						|
  cairo_surface_t *surface;
 | 
						|
 | 
						|
  surface = cairo_image_surface_create_for_data ((guchar *) icon_masks[icon].pixels,
 | 
						|
                                                 CAIRO_FORMAT_A1,
 | 
						|
                                                 icon_masks[icon].width,
 | 
						|
                                                 icon_masks[icon].height,
 | 
						|
                                                 icon_masks[icon].pixels_size / icon_masks[icon].height);
 | 
						|
  cairo_mask_surface (cr,
 | 
						|
                      surface,
 | 
						|
                      x + (width - icon_masks[icon].width) / 2,
 | 
						|
                      y + (height - icon_masks[icon].height) / 2);
 | 
						|
  cairo_surface_destroy (surface);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
gtk_cairo_set_source_sys_color (cairo_t *cr,
 | 
						|
                                gint     id)
 | 
						|
{
 | 
						|
  GdkRGBA rgba;
 | 
						|
 | 
						|
  gtk_win32_get_sys_color (id, &rgba);
 | 
						|
  gdk_cairo_set_source_rgba (cr, &rgba);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
draw_outline (cairo_t *cr,
 | 
						|
              int      top_color_id,
 | 
						|
              int      bottom_color_id,
 | 
						|
              int      x,
 | 
						|
              int      y,
 | 
						|
              int      width,
 | 
						|
              int      height)
 | 
						|
{
 | 
						|
  gtk_cairo_set_source_sys_color (cr, top_color_id);
 | 
						|
  cairo_rectangle (cr, x, y,     width, 1);
 | 
						|
  cairo_rectangle (cr, x, y,     1,     height);
 | 
						|
  cairo_fill (cr);
 | 
						|
 | 
						|
  gtk_cairo_set_source_sys_color (cr, bottom_color_id);
 | 
						|
  cairo_rectangle (cr, x + width, y + height, -1,     -height);
 | 
						|
  cairo_rectangle (cr, x + width, y + height, -width, -1);
 | 
						|
  cairo_fill (cr);
 | 
						|
}
 | 
						|
 | 
						|
typedef enum {
 | 
						|
  EDGE_RAISED_OUTER = 1 << 0,
 | 
						|
  EDGE_SUNKEN_OUTER = 1 << 1,
 | 
						|
  EDGE_RAISED_INNER = 1 << 2,
 | 
						|
  EDGE_SUNKEN_INNER = 1 << 3,
 | 
						|
  EDGE_RAISED       = (EDGE_RAISED_OUTER | EDGE_RAISED_INNER),
 | 
						|
  EDGE_SUNKEN       = (EDGE_SUNKEN_OUTER | EDGE_SUNKEN_INNER),
 | 
						|
  EDGE_ETCHED       = (EDGE_SUNKEN_OUTER | EDGE_RAISED_INNER),
 | 
						|
  EDGE_BUMP         = (EDGE_RAISED_OUTER | EDGE_SUNKEN_INNER)
 | 
						|
} GtkWin32Edge;
 | 
						|
 | 
						|
static void
 | 
						|
draw_edge (cairo_t      *cr,
 | 
						|
           GtkWin32Edge  edge,
 | 
						|
           gboolean      soft,
 | 
						|
           int           x,
 | 
						|
           int           y,
 | 
						|
           int           width,
 | 
						|
           int           height)
 | 
						|
{
 | 
						|
  switch (edge & (EDGE_RAISED_OUTER | EDGE_SUNKEN_OUTER))
 | 
						|
    {
 | 
						|
    case EDGE_RAISED_OUTER:
 | 
						|
      draw_outline (cr,
 | 
						|
                    soft ? GTK_WIN32_SYS_COLOR_BTNHIGHLIGHT : GTK_WIN32_SYS_COLOR_3DLIGHT,
 | 
						|
                    GTK_WIN32_SYS_COLOR_3DDKSHADOW,
 | 
						|
                    x, y, width, height);
 | 
						|
      break;
 | 
						|
    case EDGE_SUNKEN_OUTER:
 | 
						|
      draw_outline (cr,
 | 
						|
                    soft ? GTK_WIN32_SYS_COLOR_3DDKSHADOW : GTK_WIN32_SYS_COLOR_BTNSHADOW,
 | 
						|
                    GTK_WIN32_SYS_COLOR_BTNHIGHLIGHT,
 | 
						|
                    x, y, width, height);
 | 
						|
      break;
 | 
						|
    case (EDGE_RAISED_OUTER | EDGE_SUNKEN_OUTER):
 | 
						|
      return;
 | 
						|
    default:
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
  x += 1;
 | 
						|
  y += 1;
 | 
						|
  width -= 2;
 | 
						|
  height -= 2;
 | 
						|
 | 
						|
  switch (edge & (EDGE_RAISED_INNER | EDGE_SUNKEN_INNER))
 | 
						|
    {
 | 
						|
    case EDGE_RAISED_INNER:
 | 
						|
      draw_outline (cr,
 | 
						|
                    soft ? GTK_WIN32_SYS_COLOR_3DLIGHT : GTK_WIN32_SYS_COLOR_BTNHIGHLIGHT,
 | 
						|
                    GTK_WIN32_SYS_COLOR_BTNSHADOW,
 | 
						|
                    x, y, width, height);
 | 
						|
      break;
 | 
						|
    case EDGE_SUNKEN_INNER:
 | 
						|
      draw_outline (cr,
 | 
						|
                    soft ? GTK_WIN32_SYS_COLOR_BTNSHADOW : GTK_WIN32_SYS_COLOR_3DDKSHADOW,
 | 
						|
                    GTK_WIN32_SYS_COLOR_3DLIGHT,
 | 
						|
                    x, y, width, height);
 | 
						|
      break;
 | 
						|
    case (EDGE_RAISED_INNER | EDGE_SUNKEN_INNER):
 | 
						|
      return;
 | 
						|
    default:
 | 
						|
      break;
 | 
						|
    }
 | 
						|
}
 | 
						|
           
 | 
						|
static void
 | 
						|
draw_button (cairo_t *cr,
 | 
						|
             int      part,
 | 
						|
             int      state,
 | 
						|
             int      width,
 | 
						|
             int      height)
 | 
						|
{
 | 
						|
  draw_edge (cr, state == 3 ? EDGE_SUNKEN : EDGE_RAISED, TRUE, 0, 0, width, height);
 | 
						|
 | 
						|
  gtk_cairo_set_source_sys_color (cr, GTK_WIN32_SYS_COLOR_BTNFACE);
 | 
						|
  cairo_rectangle (cr, 2, 2, width - 4, height - 4);
 | 
						|
  cairo_fill (cr);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
draw_frame (cairo_t *cr,
 | 
						|
            int      part,
 | 
						|
            int      state,
 | 
						|
            int      width,
 | 
						|
            int      height)
 | 
						|
{
 | 
						|
  draw_edge (cr, EDGE_ETCHED, FALSE, 0, 0, width, height);
 | 
						|
 | 
						|
  gtk_cairo_set_source_sys_color (cr, GTK_WIN32_SYS_COLOR_BTNFACE);
 | 
						|
  cairo_rectangle (cr, 2, 2, width - 4, height - 4);
 | 
						|
  cairo_fill (cr);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
draw_check (cairo_t *cr,
 | 
						|
            int      part,
 | 
						|
            int      state,
 | 
						|
            int      width,
 | 
						|
            int      height)
 | 
						|
{
 | 
						|
  gtk_cairo_set_source_sys_color (cr, GTK_WIN32_SYS_COLOR_BTNHIGHLIGHT);
 | 
						|
  cairo_set_line_width (cr, 1.0);
 | 
						|
  cairo_rectangle (cr, 0.5, 0.5, width - 1.0, height - 1.0);
 | 
						|
  cairo_stroke (cr);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
draw_radio (cairo_t *cr,
 | 
						|
            int      part,
 | 
						|
            int      state,
 | 
						|
            int      width,
 | 
						|
            int      height)
 | 
						|
{
 | 
						|
  gtk_cairo_set_source_sys_color (cr, GTK_WIN32_SYS_COLOR_BTNHIGHLIGHT);
 | 
						|
  cairo_set_line_width (cr, 1.0);
 | 
						|
  cairo_arc (cr, width / 2.0, height / 2.0, MIN (width, height) / 2.0 - 0.5, 0, G_PI * 2);
 | 
						|
  cairo_stroke (cr);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
draw_edit (cairo_t *cr,
 | 
						|
           int      part,
 | 
						|
           int      state,
 | 
						|
           int      width,
 | 
						|
           int      height)
 | 
						|
{
 | 
						|
  int xborder = gtk_win32_get_sys_metric (GTK_WIN32_SYS_METRIC_CXBORDER);
 | 
						|
  int yborder = gtk_win32_get_sys_metric (GTK_WIN32_SYS_METRIC_CYBORDER);
 | 
						|
 | 
						|
  cairo_rectangle (cr, 0, 0, width, height);
 | 
						|
  gtk_cairo_set_source_sys_color (cr, (state == 6 || state == 4) ? GTK_WIN32_SYS_COLOR_BTNFACE
 | 
						|
                                                                 : GTK_WIN32_SYS_COLOR_WINDOW);
 | 
						|
  cairo_fill_preserve (cr);
 | 
						|
 | 
						|
  cairo_rectangle (cr, width - xborder, yborder,
 | 
						|
                   - (width - 2 * xborder), height - 2 * yborder);
 | 
						|
  gtk_cairo_set_source_sys_color (cr, GTK_WIN32_SYS_COLOR_WINDOWFRAME);
 | 
						|
  cairo_fill (cr);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
draw_edit_noborder (cairo_t *cr,
 | 
						|
                    int      part,
 | 
						|
                    int      state,
 | 
						|
                    int      width,
 | 
						|
                    int      height)
 | 
						|
{
 | 
						|
 | 
						|
  cairo_rectangle (cr, 0, 0, width, height);
 | 
						|
  gtk_cairo_set_source_sys_color (cr, (state == 6 || state == 4) ? GTK_WIN32_SYS_COLOR_BTNFACE
 | 
						|
                                                                 : GTK_WIN32_SYS_COLOR_WINDOW);
 | 
						|
  cairo_fill (cr);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
draw_window (cairo_t *cr,
 | 
						|
             int      part,
 | 
						|
             int      state,
 | 
						|
             int      width,
 | 
						|
             int      height)
 | 
						|
{
 | 
						|
  draw_edge (cr, EDGE_RAISED, TRUE, 0, 0, width, height + 2);
 | 
						|
 | 
						|
  gtk_cairo_set_source_sys_color (cr, state == 2 ? GTK_WIN32_SYS_COLOR_INACTIVECAPTION
 | 
						|
                                                 : GTK_WIN32_SYS_COLOR_ACTIVECAPTION);
 | 
						|
  cairo_rectangle (cr, 2, 2, width - 4, height - 2);
 | 
						|
  cairo_fill (cr);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
draw_window_left (cairo_t *cr,
 | 
						|
                  int      part,
 | 
						|
                  int      state,
 | 
						|
                  int      width,
 | 
						|
                  int      height)
 | 
						|
{
 | 
						|
  draw_edge (cr, EDGE_RAISED, TRUE, 0, -2, width + 2, height + 4);
 | 
						|
 | 
						|
  gtk_cairo_set_source_sys_color (cr, GTK_WIN32_SYS_COLOR_BTNFACE);
 | 
						|
  cairo_rectangle (cr, 2, 0, width - 2, height);
 | 
						|
  cairo_fill (cr);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
draw_window_right (cairo_t *cr,
 | 
						|
                   int      part,
 | 
						|
                   int      state,
 | 
						|
                   int      width,
 | 
						|
                   int      height)
 | 
						|
{
 | 
						|
  draw_edge (cr, EDGE_RAISED, TRUE, -2, -2, width + 2, height + 4);
 | 
						|
 | 
						|
  gtk_cairo_set_source_sys_color (cr, GTK_WIN32_SYS_COLOR_BTNFACE);
 | 
						|
  cairo_rectangle (cr, 0, 0, width - 2, height);
 | 
						|
  cairo_fill (cr);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
draw_window_bottom (cairo_t *cr,
 | 
						|
                    int      part,
 | 
						|
                    int      state,
 | 
						|
                    int      width,
 | 
						|
                    int      height)
 | 
						|
{
 | 
						|
  draw_edge (cr, EDGE_RAISED, TRUE, 0, -2, width, height + 2);
 | 
						|
 | 
						|
  gtk_cairo_set_source_sys_color (cr, GTK_WIN32_SYS_COLOR_BTNFACE);
 | 
						|
  cairo_rectangle (cr, 2, 0, width - 4, height - 2);
 | 
						|
  cairo_fill (cr);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
draw_window_button (cairo_t *cr,
 | 
						|
                    int      part,
 | 
						|
                    int      state,
 | 
						|
                    int      width,
 | 
						|
                    int      height)
 | 
						|
{
 | 
						|
  Icon icon;
 | 
						|
 | 
						|
 | 
						|
  switch (part)
 | 
						|
    {
 | 
						|
    case 15: /* minimize */
 | 
						|
      icon = ICON_MINIMIZE;
 | 
						|
      break;
 | 
						|
    case 17: /* maximize */
 | 
						|
      icon = ICON_MAXIMIZE;
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      g_assert_not_reached ();
 | 
						|
    case 18: /* close */
 | 
						|
      icon = ICON_CLOSE;
 | 
						|
      break;
 | 
						|
    case 21: /* restore */
 | 
						|
      icon = ICON_RESTORE;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
  draw_button (cr, 0, state, width, height);
 | 
						|
 | 
						|
  gtk_cairo_set_source_sys_color (cr, state == 4 ? GTK_WIN32_SYS_COLOR_BTNSHADOW
 | 
						|
                                                 : GTK_WIN32_SYS_COLOR_BTNTEXT);
 | 
						|
  mask_icon (cr, icon, 1, 1, width - 2, height - 2);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
draw_tab_item (cairo_t *cr,
 | 
						|
               int      part,
 | 
						|
               int      state,
 | 
						|
               int      width,
 | 
						|
               int      height)
 | 
						|
{
 | 
						|
  draw_edge (cr, EDGE_RAISED, TRUE, 0, 0, width, height + 2);
 | 
						|
 | 
						|
  gtk_cairo_set_source_sys_color (cr, GTK_WIN32_SYS_COLOR_BTNFACE);
 | 
						|
  cairo_rectangle (cr, 2, 2, width - 4, height - 2);
 | 
						|
  cairo_fill (cr);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
draw_tab_pane (cairo_t *cr,
 | 
						|
               int      part,
 | 
						|
               int      state,
 | 
						|
               int      width,
 | 
						|
               int      height)
 | 
						|
{
 | 
						|
  draw_edge (cr, EDGE_RAISED, TRUE, 0, 0, width, height);
 | 
						|
 | 
						|
  gtk_cairo_set_source_sys_color (cr, GTK_WIN32_SYS_COLOR_BTNFACE);
 | 
						|
  cairo_rectangle (cr, 2, 2, width - 4, height - 4);
 | 
						|
  cairo_fill (cr);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
draw_tooltip (cairo_t *cr,
 | 
						|
              int      part,
 | 
						|
              int      state,
 | 
						|
              int      width,
 | 
						|
              int      height)
 | 
						|
{
 | 
						|
  int xborder = gtk_win32_get_sys_metric (GTK_WIN32_SYS_METRIC_CXDLGFRAME) -
 | 
						|
                gtk_win32_get_sys_metric (GTK_WIN32_SYS_METRIC_CXEDGE);
 | 
						|
  int yborder = gtk_win32_get_sys_metric (GTK_WIN32_SYS_METRIC_CYDLGFRAME) -
 | 
						|
                gtk_win32_get_sys_metric (GTK_WIN32_SYS_METRIC_CYEDGE);
 | 
						|
 | 
						|
  cairo_rectangle (cr, 0, 0, width, height);
 | 
						|
  cairo_rectangle (cr, width - xborder, yborder,
 | 
						|
                   - (width - 2 * xborder), height - 2 * yborder);
 | 
						|
  gtk_cairo_set_source_sys_color (cr, GTK_WIN32_SYS_COLOR_WINDOWFRAME);
 | 
						|
  cairo_fill (cr);
 | 
						|
}
 | 
						|
 | 
						|
typedef struct _GtkWin32ThemePart GtkWin32ThemePart;
 | 
						|
struct _GtkWin32ThemePart {
 | 
						|
  const char *class_name;
 | 
						|
  gint        part;
 | 
						|
  gint        size;
 | 
						|
  GtkBorder   margins;
 | 
						|
  void        (* draw_func)             (cairo_t        *cr,
 | 
						|
                                         int             part,
 | 
						|
                                         int             state,
 | 
						|
                                         int             width,
 | 
						|
                                         int             height);
 | 
						|
};
 | 
						|
 | 
						|
static GtkWin32ThemePart theme_parts[] = {
 | 
						|
  { "button",  1,  0, { 3, 3, 3, 3 }, draw_button },
 | 
						|
  { "button",  2, 13, { 0, 0, 0, 0 }, draw_radio },
 | 
						|
  { "button",  3, 13, { 0, 0, 0, 0 }, draw_check },
 | 
						|
  { "button",  4,  0, { 3, 3, 3, 3 }, draw_frame },
 | 
						|
  { "edit",    1,  0, { 0, 0, 0, 0 }, draw_edit },
 | 
						|
  { "edit",    3,  0, { 0, 0, 0, 0 }, draw_edit_noborder },
 | 
						|
  { "edit",    6,  0, { 0, 0, 0, 0 }, draw_edit },
 | 
						|
  { "edit",    7,  0, { 0, 0, 0, 0 }, draw_edit },
 | 
						|
  { "edit",    8,  0, { 0, 0, 0, 0 }, draw_edit },
 | 
						|
  { "edit",    9,  0, { 0, 0, 0, 0 }, draw_edit },
 | 
						|
  { "tab",     1,  0, { 0, 0, 0, 0 }, draw_tab_item },
 | 
						|
  { "tab",     2,  0, { 0, 0, 0, 0 }, draw_tab_item },
 | 
						|
  { "tab",     3,  0, { 0, 0, 0, 0 }, draw_tab_item },
 | 
						|
  { "tab",     4,  0, { 0, 0, 0, 0 }, draw_tab_item },
 | 
						|
  { "tab",     5,  0, { 0, 0, 0, 0 }, draw_tab_item },
 | 
						|
  { "tab",     6,  0, { 0, 0, 0, 0 }, draw_tab_item },
 | 
						|
  { "tab",     7,  0, { 0, 0, 0, 0 }, draw_tab_item },
 | 
						|
  { "tab",     8,  0, { 0, 0, 0, 0 }, draw_tab_item },
 | 
						|
  { "tab",     9,  0, { 0, 0, 0, 0 }, draw_tab_pane },
 | 
						|
  { "tooltip", 1,  0, { 0, 0, 0, 0 }, draw_tooltip },
 | 
						|
  { "window",  1,  0, { 0, 0, 0, 0 }, draw_window },
 | 
						|
  { "window",  7,  0, { 0, 0, 0, 0 }, draw_window_left },
 | 
						|
  { "window",  8,  0, { 0, 0, 0, 0 }, draw_window_right },
 | 
						|
  { "window",  9,  0, { 0, 0, 0, 0 }, draw_window_bottom },
 | 
						|
  { "window", 15,  0, { 0, 0, 0, 0 }, draw_window_button },
 | 
						|
  { "window", 17,  0, { 0, 0, 0, 0 }, draw_window_button },
 | 
						|
  { "window", 18,  0, { 0, 0, 0, 0 }, draw_window_button },
 | 
						|
  { "window", 21,  0, { 0, 0, 0, 0 }, draw_window_button }
 | 
						|
};
 | 
						|
 | 
						|
static const GtkWin32ThemePart *
 | 
						|
get_theme_part (const char *class_name,
 | 
						|
                gint        part)
 | 
						|
{
 | 
						|
  gsize i;
 | 
						|
 | 
						|
  for (i = 0; i < G_N_ELEMENTS (theme_parts); i++)
 | 
						|
    {
 | 
						|
      if (g_str_equal (theme_parts[i].class_name, class_name) &&
 | 
						|
          theme_parts[i].part == part)
 | 
						|
        return &theme_parts[i];
 | 
						|
    }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
gtk_win32_draw_theme_background (cairo_t    *cr,
 | 
						|
                                 const char *class_name,
 | 
						|
                                 int         part,
 | 
						|
                                 int         state,
 | 
						|
                                 int         width,
 | 
						|
                                 int         height)
 | 
						|
{
 | 
						|
  const GtkWin32ThemePart *theme_part;
 | 
						|
 | 
						|
  theme_part = get_theme_part (class_name, part);
 | 
						|
 | 
						|
  if (theme_part)
 | 
						|
    {
 | 
						|
      theme_part->draw_func (cr, part, state, width, height);
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      g_warning ("No fallback code to draw background for class \"%s\", part %d", class_name, part);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
gtk_win32_get_theme_part_size (const char *class_name,
 | 
						|
                               int          part,
 | 
						|
                               int          state,
 | 
						|
                               int         *width,
 | 
						|
                               int         *height)
 | 
						|
{
 | 
						|
  const GtkWin32ThemePart *theme_part;
 | 
						|
 | 
						|
  theme_part = get_theme_part (class_name, part);
 | 
						|
 | 
						|
  if (theme_part)
 | 
						|
    {
 | 
						|
      if (width)
 | 
						|
        *width = theme_part->size;
 | 
						|
      if (height)
 | 
						|
        *height = theme_part->size;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      if (width)
 | 
						|
        *width = 1;
 | 
						|
      if (height)
 | 
						|
        *height = 1;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
gtk_win32_get_theme_margins (const char     *class_name,
 | 
						|
                             int             part,
 | 
						|
                             int             state,
 | 
						|
                             GtkBorder      *out_margins)
 | 
						|
{
 | 
						|
  const GtkWin32ThemePart *theme_part;
 | 
						|
 | 
						|
  theme_part = get_theme_part (class_name, part);
 | 
						|
 | 
						|
  if (theme_part)
 | 
						|
    {
 | 
						|
      *out_margins = theme_part->margins;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      out_margins->top = out_margins->bottom = out_margins->left = out_margins->right = 0;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
FIXME_IMPLEMENT (int id)
 | 
						|
{
 | 
						|
  g_warning ("win32 sys metric %d not implemented", id);
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
static struct {
 | 
						|
  const char *name;
 | 
						|
  int         value;
 | 
						|
  int         (* get_value) (int id);
 | 
						|
} win32_default_metrics[] = {
 | 
						|
  { "cxscreen",            0, FIXME_IMPLEMENT },
 | 
						|
  { "cyscreen",            0, FIXME_IMPLEMENT },
 | 
						|
  { "cxvscroll",          16, NULL },
 | 
						|
  { "cyhscroll",          16, NULL },
 | 
						|
  { "cycaption",          16, NULL },
 | 
						|
  { "cxborder",            1, NULL },
 | 
						|
  { "cyborder",            1, NULL },
 | 
						|
  { "cxdlgframe",          3, NULL },
 | 
						|
  { "cydlgframe",          3, NULL },
 | 
						|
  { "cyvthumb",           16, NULL },
 | 
						|
  { "cxhthumb",           16, NULL },
 | 
						|
  { "cxicon",             32, NULL },
 | 
						|
  { "cyicon",             32, NULL },
 | 
						|
  { "cxcursor",           32, NULL },
 | 
						|
  { "cycursor",           32, NULL },
 | 
						|
  { "cymenu",             19, NULL },
 | 
						|
  { "cxfullscreen", 0, FIXME_IMPLEMENT },
 | 
						|
  { "cyfullscreen", 0, FIXME_IMPLEMENT },
 | 
						|
  { "cykanjiwindow",       0, NULL },
 | 
						|
  { "mousepresent",        1, NULL },
 | 
						|
  { "cyvscroll",          16, NULL },
 | 
						|
  { "cxhscroll",          16, NULL },
 | 
						|
  { "debug",               0, NULL },
 | 
						|
  { "swapbutton",          0, NULL },
 | 
						|
  { "reserved1",           0, NULL },
 | 
						|
  { "reserved2",           0, NULL },
 | 
						|
  { "reserved3",           0, NULL },
 | 
						|
  { "reserved4",           0, NULL },
 | 
						|
  { "cxmin",             112, NULL },
 | 
						|
  { "cymin",              24, NULL },
 | 
						|
  { "cxsize",             18, NULL },
 | 
						|
  { "cysize",             15, NULL },
 | 
						|
  { "cxframe",             4, NULL },
 | 
						|
  { "cyframe",             4, NULL },
 | 
						|
  { "cxmintrack",        112, NULL },
 | 
						|
  { "cymintrack",         24, NULL },
 | 
						|
  { "cxdoubleclk",         0, FIXME_IMPLEMENT },
 | 
						|
  { "cydoubleclk",         0, FIXME_IMPLEMENT },
 | 
						|
  { "cxiconspacing",      75, NULL },
 | 
						|
  { "cyiconspacing",      75, NULL },
 | 
						|
  { "menudropalignment",   0, NULL },
 | 
						|
  { "penwindows",          0, NULL },
 | 
						|
  { "dbcsenabled",         1, NULL },
 | 
						|
  { "cmousebuttons",       3, NULL },
 | 
						|
  { "secure",              0, NULL },
 | 
						|
  { "cxedge",              2, NULL },
 | 
						|
  { "cyedge",              2, NULL },
 | 
						|
  { "cxminspacing",      160, NULL },
 | 
						|
  { "cyminspacing",       21, NULL },
 | 
						|
  { "cxsmicon",           16, NULL },
 | 
						|
  { "cysmicon",           16, NULL },
 | 
						|
  { "cysmcaption",        16, NULL },
 | 
						|
  { "cxsmsize",           15, NULL },
 | 
						|
  { "cysmsize",           15, NULL },
 | 
						|
  { "cxmenusize",         18, NULL },
 | 
						|
  { "cymenusize",         18, NULL },
 | 
						|
  { "arrange",             8, NULL },
 | 
						|
  { "cxminimized",       160, NULL },
 | 
						|
  { "cyminimized",        21, NULL },
 | 
						|
  { "cxmaxtrack", 0, FIXME_IMPLEMENT },
 | 
						|
  { "cymaxtrack", 0, FIXME_IMPLEMENT },
 | 
						|
  { "cxmaximized", 0, FIXME_IMPLEMENT },
 | 
						|
  { "cymaximized", 0, FIXME_IMPLEMENT },
 | 
						|
  { "network",             3, NULL },
 | 
						|
  { NULL,                  0, NULL },
 | 
						|
  { NULL,                  0, NULL },
 | 
						|
  { NULL,                  0, NULL },
 | 
						|
  { "cleanboot",           0, NULL },
 | 
						|
  { "cxdrag",              4, NULL },
 | 
						|
  { "cydrag",              4, NULL },
 | 
						|
  { "showsounds",          0, NULL },
 | 
						|
  { "cxmenucheck",        13, NULL },
 | 
						|
  { "cymenucheck",        13, NULL },
 | 
						|
  { "slowmachine",         0, NULL },
 | 
						|
  { "mideastenabled",      0, NULL },
 | 
						|
  { "mousewheelpresent",   1, NULL },
 | 
						|
  { "xvirtualscreen", 0, FIXME_IMPLEMENT },
 | 
						|
  { "yvirtualscreen", 0, FIXME_IMPLEMENT },
 | 
						|
  { "cxvirtualscreen", 0, FIXME_IMPLEMENT },
 | 
						|
  { "cyvirtualscreen", 0, FIXME_IMPLEMENT },
 | 
						|
  { "cmonitors", 0, FIXME_IMPLEMENT },
 | 
						|
  { "samedisplayformat",   1, NULL },
 | 
						|
  { "immenabled",          1, NULL },
 | 
						|
  { "cxfocusborder",       1, NULL },
 | 
						|
  { "cyfocusborder",       1, NULL },
 | 
						|
  { NULL,                  0, NULL },
 | 
						|
  { "tabletpc",            0, NULL },
 | 
						|
  { "mediacenter",         0, NULL },
 | 
						|
  { "starter",             0, NULL },
 | 
						|
  { "serverr2",            0, NULL },
 | 
						|
  { "cmetrics",           90, NULL },
 | 
						|
  { "mousehorizontalwheelpresent", 0, NULL },
 | 
						|
  { "cxpaddedborder",      0, NULL }
 | 
						|
};
 | 
						|
 | 
						|
const char *
 | 
						|
gtk_win32_get_sys_metric_name_for_id (gint id)
 | 
						|
{
 | 
						|
  if (id >= 0 && id < G_N_ELEMENTS (win32_default_metrics))
 | 
						|
    return win32_default_metrics[id].name;
 | 
						|
  else
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
gtk_win32_get_sys_metric_id_for_name (const char *name)
 | 
						|
{
 | 
						|
  int i;
 | 
						|
 | 
						|
  g_return_val_if_fail (name != NULL, -1);
 | 
						|
 | 
						|
  for (i = 0; i < G_N_ELEMENTS (win32_default_metrics); i++)
 | 
						|
    {
 | 
						|
      if (win32_default_metrics[i].name == NULL)
 | 
						|
        continue;
 | 
						|
 | 
						|
      if (g_str_equal (name, win32_default_metrics[i].name))
 | 
						|
        return i;
 | 
						|
    }
 | 
						|
 | 
						|
  return -1;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
gtk_win32_get_sys_metric (gint id)
 | 
						|
{
 | 
						|
  if (id < 0 || id >= G_N_ELEMENTS (win32_default_metrics))
 | 
						|
    return 0;
 | 
						|
 | 
						|
  if (win32_default_metrics[id].get_value)
 | 
						|
    return win32_default_metrics[id].get_value (id);
 | 
						|
 | 
						|
  return win32_default_metrics[id].value;
 | 
						|
}
 | 
						|
 | 
						|
static struct {
 | 
						|
  const char *name;
 | 
						|
  GdkRGBA rgba;
 | 
						|
} win32_default_colors[] = {
 | 
						|
#define RGB(r, g, b) { (r)/255.0, (g)/255.0, (b)/255., 1.0 }
 | 
						|
  { "scrollbar", RGB(212, 208, 200) },
 | 
						|
  { "background", RGB(58, 110, 165) },
 | 
						|
  { "activecaption", RGB(10, 36, 106) },
 | 
						|
  { "inactivecaption", RGB(128, 128, 128) },
 | 
						|
  { "menu", RGB(212, 208, 200) },
 | 
						|
  { "window", RGB(255, 255, 255) },
 | 
						|
  { "windowframe", RGB(0, 0, 0) },
 | 
						|
  { "menutext", RGB(0, 0, 0) },
 | 
						|
  { "windowtext", RGB(0, 0, 0) },
 | 
						|
  { "captiontext", RGB(255, 255, 255) },
 | 
						|
  { "activeborder", RGB(212, 208, 200) },
 | 
						|
  { "inactiveborder", RGB(212, 208, 200) },
 | 
						|
  { "appworkspace", RGB(128, 128, 128) },
 | 
						|
  { "highlight", RGB(10, 36, 106) },
 | 
						|
  { "highlighttext", RGB(255, 255, 255) },
 | 
						|
  { "btnface", RGB(212, 208, 200) },
 | 
						|
  { "btnshadow", RGB(128, 128, 128) },
 | 
						|
  { "graytext", RGB(128, 128, 128) },
 | 
						|
  { "btntext", RGB(0, 0, 0) },
 | 
						|
  { "inactivecaptiontext", RGB(212, 208, 200) },
 | 
						|
  { "btnhighlight", RGB(255, 255, 255) },
 | 
						|
  { "3ddkshadow", RGB(64, 64, 64) },
 | 
						|
  { "3dlight", RGB(212, 208, 200) },
 | 
						|
  { "infotext", RGB(0, 0, 0) },
 | 
						|
  { "infobk", RGB(255, 255, 225) },
 | 
						|
  { "alternatebtnface", RGB(181, 181, 181) },
 | 
						|
  { "hotlight", RGB(0, 0, 200) },
 | 
						|
  { "gradientactivecaption", RGB(166, 202, 240) },
 | 
						|
  { "gradientinactivecaption", RGB(192, 192, 192) },
 | 
						|
  { "menuhilight", RGB(10, 36, 106) },
 | 
						|
  { "menubar", RGB(212, 208, 200) }
 | 
						|
#undef RGB
 | 
						|
};
 | 
						|
 | 
						|
const char *
 | 
						|
gtk_win32_get_sys_color_name_for_id (gint id)
 | 
						|
{
 | 
						|
  if (id >= 0 && id < G_N_ELEMENTS (win32_default_colors))
 | 
						|
    return win32_default_colors[id].name;
 | 
						|
  else
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
gtk_win32_get_sys_color_id_for_name (const char *name)
 | 
						|
{
 | 
						|
  int i;
 | 
						|
 | 
						|
  g_return_val_if_fail (name != NULL, -1);
 | 
						|
 | 
						|
  for (i = 0; i < G_N_ELEMENTS (win32_default_colors); i++)
 | 
						|
    {
 | 
						|
      if (g_str_equal (name, win32_default_colors[i].name))
 | 
						|
        return i;
 | 
						|
    }
 | 
						|
 | 
						|
  return -1;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
gtk_win32_get_sys_color (gint     id,
 | 
						|
                         GdkRGBA *color)
 | 
						|
{
 | 
						|
  if (id < 0 || id >= G_N_ELEMENTS (win32_default_colors))
 | 
						|
    {
 | 
						|
      gdk_rgba_parse (color, "black");
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
  *color = win32_default_colors[id].rgba;
 | 
						|
}
 | 
						|
 |