1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2016 Benjamin Otte <otte@gnome.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <config.h>
19 
20 #include "gtkwin32drawprivate.h"
21 
22 typedef enum {
23   ICON_CLOSE,
24   ICON_MINIMIZE,
25   ICON_MAXIMIZE,
26   ICON_RESTORE
27 } Icon;
28 
29 const guchar icon_close_pixels[] = {
30   0x00, 0x00, 0x00, 0x00,
31   0x00, 0x00, 0x00, 0x00,
32   0x0c, 0x06, 0x00, 0x00,
33   0x1c, 0x07, 0x00, 0x00,
34   0xb8, 0x03, 0x00, 0x00,
35   0xf0, 0x01, 0x00, 0x00,
36   0xe0, 0x00, 0x00, 0x00,
37   0xf0, 0x01, 0x00, 0x00,
38   0xb8, 0x03, 0x00, 0x00,
39   0x1c, 0x07, 0x00, 0x00,
40   0x0c, 0x06, 0x00, 0x00,
41   0x00, 0x00, 0x00, 0x00,
42   0x00, 0x00, 0x00, 0x00
43 };
44 
45 const guchar icon_minimize_pixels[] = {
46   0x00, 0x00, 0x00, 0x00,
47   0x00, 0x00, 0x00, 0x00,
48   0x00, 0x00, 0x00, 0x00,
49   0x00, 0x00, 0x00, 0x00,
50   0x00, 0x00, 0x00, 0x00,
51   0x00, 0x00, 0x00, 0x00,
52   0x00, 0x00, 0x00, 0x00,
53   0x00, 0x00, 0x00, 0x00,
54   0x00, 0x00, 0x00, 0x00,
55   0x00, 0x00, 0x00, 0x00,
56   0xfc, 0x00, 0x00, 0x00,
57   0x00, 0x00, 0x00, 0x00,
58   0x00, 0x00, 0x00, 0x00
59 };
60 
61 const guchar icon_maximize_pixels[] = {
62   0x00, 0x00, 0x00, 0x00,
63   0x00, 0x00, 0x00, 0x00,
64   0xfe, 0x07, 0x00, 0x00,
65   0xfe, 0x07, 0x00, 0x00,
66   0x02, 0x04, 0x00, 0x00,
67   0x02, 0x04, 0x00, 0x00,
68   0x02, 0x04, 0x00, 0x00,
69   0x02, 0x04, 0x00, 0x00,
70   0x02, 0x04, 0x00, 0x00,
71   0x02, 0x04, 0x00, 0x00,
72   0xfe, 0x07, 0x00, 0x00,
73   0x00, 0x00, 0x00, 0x00,
74   0x00, 0x00, 0x00, 0x00
75 };
76 
77 const guchar icon_restore_pixels[] = {
78   0x00, 0x00, 0x00, 0x00,
79   0x00, 0x00, 0x00, 0x00,
80   0xf8, 0x07, 0x00, 0x00,
81   0xf8, 0x07, 0x00, 0x00,
82   0x08, 0x04, 0x00, 0x00,
83   0x08, 0x04, 0x00, 0x00,
84   0xfe, 0x04, 0x00, 0x00,
85   0x82, 0x07, 0x00, 0x00,
86   0x82, 0x00, 0x00, 0x00,
87   0x82, 0x00, 0x00, 0x00,
88   0xfe, 0x00, 0x00, 0x00,
89   0x00, 0x00, 0x00, 0x00,
90   0x00, 0x00, 0x00, 0x00
91 };
92 
93 static struct {
94   int width;
95   int height;
96   gsize pixels_size;
97   const guchar *pixels;
98 } icon_masks[] = {
99   { 13, 13, sizeof (icon_close_pixels), icon_close_pixels },
100   { 13, 13, sizeof (icon_minimize_pixels), icon_minimize_pixels },
101   { 13, 13, sizeof (icon_maximize_pixels), icon_maximize_pixels },
102   { 13, 13, sizeof (icon_restore_pixels), icon_restore_pixels }
103 };
104 
105 static void
mask_icon(cairo_t * cr,Icon icon,double x,double y,double width,double height)106 mask_icon (cairo_t *cr,
107            Icon     icon,
108            double   x,
109            double   y,
110            double   width,
111            double   height)
112 {
113   cairo_surface_t *surface;
114 
115   surface = cairo_image_surface_create_for_data ((guchar *) icon_masks[icon].pixels,
116                                                  CAIRO_FORMAT_A1,
117                                                  icon_masks[icon].width,
118                                                  icon_masks[icon].height,
119                                                  icon_masks[icon].pixels_size / icon_masks[icon].height);
120   cairo_mask_surface (cr,
121                       surface,
122                       x + (width - icon_masks[icon].width) / 2,
123                       y + (height - icon_masks[icon].height) / 2);
124   cairo_surface_destroy (surface);
125 }
126 
127 static void
gtk_cairo_set_source_sys_color(cairo_t * cr,gint id)128 gtk_cairo_set_source_sys_color (cairo_t *cr,
129                                 gint     id)
130 {
131   GdkRGBA rgba;
132 
133   gtk_win32_get_sys_color (id, &rgba);
134   gdk_cairo_set_source_rgba (cr, &rgba);
135 }
136 
137 static void
draw_outline(cairo_t * cr,int top_color_id,int bottom_color_id,int x,int y,int width,int height)138 draw_outline (cairo_t *cr,
139               int      top_color_id,
140               int      bottom_color_id,
141               int      x,
142               int      y,
143               int      width,
144               int      height)
145 {
146   gtk_cairo_set_source_sys_color (cr, top_color_id);
147   cairo_rectangle (cr, x, y,     width, 1);
148   cairo_rectangle (cr, x, y,     1,     height);
149   cairo_fill (cr);
150 
151   gtk_cairo_set_source_sys_color (cr, bottom_color_id);
152   cairo_rectangle (cr, x + width, y + height, -1,     -height);
153   cairo_rectangle (cr, x + width, y + height, -width, -1);
154   cairo_fill (cr);
155 }
156 
157 typedef enum {
158   EDGE_RAISED_OUTER = 1 << 0,
159   EDGE_SUNKEN_OUTER = 1 << 1,
160   EDGE_RAISED_INNER = 1 << 2,
161   EDGE_SUNKEN_INNER = 1 << 3,
162   EDGE_RAISED       = (EDGE_RAISED_OUTER | EDGE_RAISED_INNER),
163   EDGE_SUNKEN       = (EDGE_SUNKEN_OUTER | EDGE_SUNKEN_INNER),
164   EDGE_ETCHED       = (EDGE_SUNKEN_OUTER | EDGE_RAISED_INNER),
165   EDGE_BUMP         = (EDGE_RAISED_OUTER | EDGE_SUNKEN_INNER)
166 } GtkWin32Edge;
167 
168 static void
draw_edge(cairo_t * cr,GtkWin32Edge edge,gboolean soft,int x,int y,int width,int height)169 draw_edge (cairo_t      *cr,
170            GtkWin32Edge  edge,
171            gboolean      soft,
172            int           x,
173            int           y,
174            int           width,
175            int           height)
176 {
177   switch (edge & (EDGE_RAISED_OUTER | EDGE_SUNKEN_OUTER))
178     {
179     case EDGE_RAISED_OUTER:
180       draw_outline (cr,
181                     soft ? GTK_WIN32_SYS_COLOR_BTNHIGHLIGHT : GTK_WIN32_SYS_COLOR_3DLIGHT,
182                     GTK_WIN32_SYS_COLOR_3DDKSHADOW,
183                     x, y, width, height);
184       break;
185     case EDGE_SUNKEN_OUTER:
186       draw_outline (cr,
187                     soft ? GTK_WIN32_SYS_COLOR_3DDKSHADOW : GTK_WIN32_SYS_COLOR_BTNSHADOW,
188                     GTK_WIN32_SYS_COLOR_BTNHIGHLIGHT,
189                     x, y, width, height);
190       break;
191     case (EDGE_RAISED_OUTER | EDGE_SUNKEN_OUTER):
192       return;
193     default:
194       break;
195     }
196 
197   x += 1;
198   y += 1;
199   width -= 2;
200   height -= 2;
201 
202   switch (edge & (EDGE_RAISED_INNER | EDGE_SUNKEN_INNER))
203     {
204     case EDGE_RAISED_INNER:
205       draw_outline (cr,
206                     soft ? GTK_WIN32_SYS_COLOR_3DLIGHT : GTK_WIN32_SYS_COLOR_BTNHIGHLIGHT,
207                     GTK_WIN32_SYS_COLOR_BTNSHADOW,
208                     x, y, width, height);
209       break;
210     case EDGE_SUNKEN_INNER:
211       draw_outline (cr,
212                     soft ? GTK_WIN32_SYS_COLOR_BTNSHADOW : GTK_WIN32_SYS_COLOR_3DDKSHADOW,
213                     GTK_WIN32_SYS_COLOR_3DLIGHT,
214                     x, y, width, height);
215       break;
216     case (EDGE_RAISED_INNER | EDGE_SUNKEN_INNER):
217       return;
218     default:
219       break;
220     }
221 }
222 
223 static void
draw_button(cairo_t * cr,int part,int state,int width,int height)224 draw_button (cairo_t *cr,
225              int      part,
226              int      state,
227              int      width,
228              int      height)
229 {
230   draw_edge (cr, state == 3 ? EDGE_SUNKEN : EDGE_RAISED, TRUE, 0, 0, width, height);
231 
232   gtk_cairo_set_source_sys_color (cr, GTK_WIN32_SYS_COLOR_BTNFACE);
233   cairo_rectangle (cr, 2, 2, width - 4, height - 4);
234   cairo_fill (cr);
235 }
236 
237 static void
draw_frame(cairo_t * cr,int part,int state,int width,int height)238 draw_frame (cairo_t *cr,
239             int      part,
240             int      state,
241             int      width,
242             int      height)
243 {
244   draw_edge (cr, EDGE_ETCHED, FALSE, 0, 0, width, height);
245 
246   gtk_cairo_set_source_sys_color (cr, GTK_WIN32_SYS_COLOR_BTNFACE);
247   cairo_rectangle (cr, 2, 2, width - 4, height - 4);
248   cairo_fill (cr);
249 }
250 
251 static void
draw_check(cairo_t * cr,int part,int state,int width,int height)252 draw_check (cairo_t *cr,
253             int      part,
254             int      state,
255             int      width,
256             int      height)
257 {
258   gtk_cairo_set_source_sys_color (cr, GTK_WIN32_SYS_COLOR_BTNHIGHLIGHT);
259   cairo_set_line_width (cr, 1.0);
260   cairo_rectangle (cr, 0.5, 0.5, width - 1.0, height - 1.0);
261   cairo_stroke (cr);
262 }
263 
264 static void
draw_radio(cairo_t * cr,int part,int state,int width,int height)265 draw_radio (cairo_t *cr,
266             int      part,
267             int      state,
268             int      width,
269             int      height)
270 {
271   gtk_cairo_set_source_sys_color (cr, GTK_WIN32_SYS_COLOR_BTNHIGHLIGHT);
272   cairo_set_line_width (cr, 1.0);
273   cairo_arc (cr, width / 2.0, height / 2.0, MIN (width, height) / 2.0 - 0.5, 0, G_PI * 2);
274   cairo_stroke (cr);
275 }
276 
277 static void
draw_edit(cairo_t * cr,int part,int state,int width,int height)278 draw_edit (cairo_t *cr,
279            int      part,
280            int      state,
281            int      width,
282            int      height)
283 {
284   int xborder = gtk_win32_get_sys_metric (GTK_WIN32_SYS_METRIC_CXBORDER);
285   int yborder = gtk_win32_get_sys_metric (GTK_WIN32_SYS_METRIC_CYBORDER);
286 
287   cairo_rectangle (cr, 0, 0, width, height);
288   gtk_cairo_set_source_sys_color (cr, (state == 6 || state == 4) ? GTK_WIN32_SYS_COLOR_BTNFACE
289                                                                  : GTK_WIN32_SYS_COLOR_WINDOW);
290   cairo_fill_preserve (cr);
291 
292   cairo_rectangle (cr, width - xborder, yborder,
293                    - (width - 2 * xborder), height - 2 * yborder);
294   gtk_cairo_set_source_sys_color (cr, GTK_WIN32_SYS_COLOR_WINDOWFRAME);
295   cairo_fill (cr);
296 }
297 
298 static void
draw_edit_noborder(cairo_t * cr,int part,int state,int width,int height)299 draw_edit_noborder (cairo_t *cr,
300                     int      part,
301                     int      state,
302                     int      width,
303                     int      height)
304 {
305 
306   cairo_rectangle (cr, 0, 0, width, height);
307   gtk_cairo_set_source_sys_color (cr, (state == 6 || state == 4) ? GTK_WIN32_SYS_COLOR_BTNFACE
308                                                                  : GTK_WIN32_SYS_COLOR_WINDOW);
309   cairo_fill (cr);
310 }
311 
312 static void
draw_window(cairo_t * cr,int part,int state,int width,int height)313 draw_window (cairo_t *cr,
314              int      part,
315              int      state,
316              int      width,
317              int      height)
318 {
319   draw_edge (cr, EDGE_RAISED, TRUE, 0, 0, width, height + 2);
320 
321   gtk_cairo_set_source_sys_color (cr, state == 2 ? GTK_WIN32_SYS_COLOR_INACTIVECAPTION
322                                                  : GTK_WIN32_SYS_COLOR_ACTIVECAPTION);
323   cairo_rectangle (cr, 2, 2, width - 4, height - 2);
324   cairo_fill (cr);
325 }
326 
327 static void
draw_window_left(cairo_t * cr,int part,int state,int width,int height)328 draw_window_left (cairo_t *cr,
329                   int      part,
330                   int      state,
331                   int      width,
332                   int      height)
333 {
334   draw_edge (cr, EDGE_RAISED, TRUE, 0, -2, width + 2, height + 4);
335 
336   gtk_cairo_set_source_sys_color (cr, GTK_WIN32_SYS_COLOR_BTNFACE);
337   cairo_rectangle (cr, 2, 0, width - 2, height);
338   cairo_fill (cr);
339 }
340 
341 static void
draw_window_right(cairo_t * cr,int part,int state,int width,int height)342 draw_window_right (cairo_t *cr,
343                    int      part,
344                    int      state,
345                    int      width,
346                    int      height)
347 {
348   draw_edge (cr, EDGE_RAISED, TRUE, -2, -2, width + 2, height + 4);
349 
350   gtk_cairo_set_source_sys_color (cr, GTK_WIN32_SYS_COLOR_BTNFACE);
351   cairo_rectangle (cr, 0, 0, width - 2, height);
352   cairo_fill (cr);
353 }
354 
355 static void
draw_window_bottom(cairo_t * cr,int part,int state,int width,int height)356 draw_window_bottom (cairo_t *cr,
357                     int      part,
358                     int      state,
359                     int      width,
360                     int      height)
361 {
362   draw_edge (cr, EDGE_RAISED, TRUE, 0, -2, width, height + 2);
363 
364   gtk_cairo_set_source_sys_color (cr, GTK_WIN32_SYS_COLOR_BTNFACE);
365   cairo_rectangle (cr, 2, 0, width - 4, height - 2);
366   cairo_fill (cr);
367 }
368 
369 static void
draw_window_button(cairo_t * cr,int part,int state,int width,int height)370 draw_window_button (cairo_t *cr,
371                     int      part,
372                     int      state,
373                     int      width,
374                     int      height)
375 {
376   Icon icon;
377 
378 
379   switch (part)
380     {
381     case 15: /* minimize */
382       icon = ICON_MINIMIZE;
383       break;
384     case 17: /* maximize */
385       icon = ICON_MAXIMIZE;
386       break;
387     default:
388       g_assert_not_reached ();
389     case 18: /* close */
390       icon = ICON_CLOSE;
391       break;
392     case 21: /* restore */
393       icon = ICON_RESTORE;
394       break;
395     }
396 
397   draw_button (cr, 0, state, width, height);
398 
399   gtk_cairo_set_source_sys_color (cr, state == 4 ? GTK_WIN32_SYS_COLOR_BTNSHADOW
400                                                  : GTK_WIN32_SYS_COLOR_BTNTEXT);
401   mask_icon (cr, icon, 1, 1, width - 2, height - 2);
402 }
403 
404 static void
draw_tab_item(cairo_t * cr,int part,int state,int width,int height)405 draw_tab_item (cairo_t *cr,
406                int      part,
407                int      state,
408                int      width,
409                int      height)
410 {
411   draw_edge (cr, EDGE_RAISED, TRUE, 0, 0, width, height + 2);
412 
413   gtk_cairo_set_source_sys_color (cr, GTK_WIN32_SYS_COLOR_BTNFACE);
414   cairo_rectangle (cr, 2, 2, width - 4, height - 2);
415   cairo_fill (cr);
416 }
417 
418 static void
draw_tab_pane(cairo_t * cr,int part,int state,int width,int height)419 draw_tab_pane (cairo_t *cr,
420                int      part,
421                int      state,
422                int      width,
423                int      height)
424 {
425   draw_edge (cr, EDGE_RAISED, TRUE, 0, 0, width, height);
426 
427   gtk_cairo_set_source_sys_color (cr, GTK_WIN32_SYS_COLOR_BTNFACE);
428   cairo_rectangle (cr, 2, 2, width - 4, height - 4);
429   cairo_fill (cr);
430 }
431 
432 static void
draw_tooltip(cairo_t * cr,int part,int state,int width,int height)433 draw_tooltip (cairo_t *cr,
434               int      part,
435               int      state,
436               int      width,
437               int      height)
438 {
439   int xborder = gtk_win32_get_sys_metric (GTK_WIN32_SYS_METRIC_CXDLGFRAME) -
440                 gtk_win32_get_sys_metric (GTK_WIN32_SYS_METRIC_CXEDGE);
441   int yborder = gtk_win32_get_sys_metric (GTK_WIN32_SYS_METRIC_CYDLGFRAME) -
442                 gtk_win32_get_sys_metric (GTK_WIN32_SYS_METRIC_CYEDGE);
443 
444   cairo_rectangle (cr, 0, 0, width, height);
445   cairo_rectangle (cr, width - xborder, yborder,
446                    - (width - 2 * xborder), height - 2 * yborder);
447   gtk_cairo_set_source_sys_color (cr, GTK_WIN32_SYS_COLOR_WINDOWFRAME);
448   cairo_fill (cr);
449 }
450 
451 typedef struct _GtkWin32ThemePart GtkWin32ThemePart;
452 struct _GtkWin32ThemePart {
453   const char *class_name;
454   gint        part;
455   gint        size;
456   GtkBorder   margins;
457   void        (* draw_func)             (cairo_t        *cr,
458                                          int             part,
459                                          int             state,
460                                          int             width,
461                                          int             height);
462 };
463 
464 static GtkWin32ThemePart theme_parts[] = {
465   { "button",  1,  0, { 3, 3, 3, 3 }, draw_button },
466   { "button",  2, 13, { 0, 0, 0, 0 }, draw_radio },
467   { "button",  3, 13, { 0, 0, 0, 0 }, draw_check },
468   { "button",  4,  0, { 3, 3, 3, 3 }, draw_frame },
469   { "edit",    1,  0, { 0, 0, 0, 0 }, draw_edit },
470   { "edit",    3,  0, { 0, 0, 0, 0 }, draw_edit_noborder },
471   { "edit",    6,  0, { 0, 0, 0, 0 }, draw_edit },
472   { "edit",    7,  0, { 0, 0, 0, 0 }, draw_edit },
473   { "edit",    8,  0, { 0, 0, 0, 0 }, draw_edit },
474   { "edit",    9,  0, { 0, 0, 0, 0 }, draw_edit },
475   { "tab",     1,  0, { 0, 0, 0, 0 }, draw_tab_item },
476   { "tab",     2,  0, { 0, 0, 0, 0 }, draw_tab_item },
477   { "tab",     3,  0, { 0, 0, 0, 0 }, draw_tab_item },
478   { "tab",     4,  0, { 0, 0, 0, 0 }, draw_tab_item },
479   { "tab",     5,  0, { 0, 0, 0, 0 }, draw_tab_item },
480   { "tab",     6,  0, { 0, 0, 0, 0 }, draw_tab_item },
481   { "tab",     7,  0, { 0, 0, 0, 0 }, draw_tab_item },
482   { "tab",     8,  0, { 0, 0, 0, 0 }, draw_tab_item },
483   { "tab",     9,  0, { 0, 0, 0, 0 }, draw_tab_pane },
484   { "tooltip", 1,  0, { 0, 0, 0, 0 }, draw_tooltip },
485   { "window",  1,  0, { 0, 0, 0, 0 }, draw_window },
486   { "window",  7,  0, { 0, 0, 0, 0 }, draw_window_left },
487   { "window",  8,  0, { 0, 0, 0, 0 }, draw_window_right },
488   { "window",  9,  0, { 0, 0, 0, 0 }, draw_window_bottom },
489   { "window", 15,  0, { 0, 0, 0, 0 }, draw_window_button },
490   { "window", 17,  0, { 0, 0, 0, 0 }, draw_window_button },
491   { "window", 18,  0, { 0, 0, 0, 0 }, draw_window_button },
492   { "window", 21,  0, { 0, 0, 0, 0 }, draw_window_button }
493 };
494 
495 static const GtkWin32ThemePart *
get_theme_part(const char * class_name,gint part)496 get_theme_part (const char *class_name,
497                 gint        part)
498 {
499   gsize i;
500 
501   for (i = 0; i < G_N_ELEMENTS (theme_parts); i++)
502     {
503       if (g_str_equal (theme_parts[i].class_name, class_name) &&
504           theme_parts[i].part == part)
505         return &theme_parts[i];
506     }
507 
508   return NULL;
509 }
510 
511 void
gtk_win32_draw_theme_background(cairo_t * cr,const char * class_name,int part,int state,int width,int height)512 gtk_win32_draw_theme_background (cairo_t    *cr,
513                                  const char *class_name,
514                                  int         part,
515                                  int         state,
516                                  int         width,
517                                  int         height)
518 {
519   const GtkWin32ThemePart *theme_part;
520 
521   theme_part = get_theme_part (class_name, part);
522 
523   if (theme_part)
524     {
525       theme_part->draw_func (cr, part, state, width, height);
526     }
527   else
528     {
529       g_warning ("No fallback code to draw background for class \"%s\", part %d", class_name, part);
530     }
531 }
532 
533 void
gtk_win32_get_theme_part_size(const char * class_name,int part,int state,int * width,int * height)534 gtk_win32_get_theme_part_size (const char *class_name,
535                                int          part,
536                                int          state,
537                                int         *width,
538                                int         *height)
539 {
540   const GtkWin32ThemePart *theme_part;
541 
542   theme_part = get_theme_part (class_name, part);
543 
544   if (theme_part)
545     {
546       if (width)
547         *width = theme_part->size;
548       if (height)
549         *height = theme_part->size;
550     }
551   else
552     {
553       if (width)
554         *width = 1;
555       if (height)
556         *height = 1;
557     }
558 }
559 
560 void
gtk_win32_get_theme_margins(const char * class_name,int part,int state,GtkBorder * out_margins)561 gtk_win32_get_theme_margins (const char     *class_name,
562                              int             part,
563                              int             state,
564                              GtkBorder      *out_margins)
565 {
566   const GtkWin32ThemePart *theme_part;
567 
568   theme_part = get_theme_part (class_name, part);
569 
570   if (theme_part)
571     {
572       *out_margins = theme_part->margins;
573     }
574   else
575     {
576       out_margins->top = out_margins->bottom = out_margins->left = out_margins->right = 0;
577     }
578 }
579 
580 static int
FIXME_IMPLEMENT(int id)581 FIXME_IMPLEMENT (int id)
582 {
583   g_warning ("win32 sys metric %d not implemented", id);
584   return 0;
585 }
586 
587 static struct {
588   const char *name;
589   int         value;
590   int         (* get_value) (int id);
591 } win32_default_metrics[] = {
592   { "cxscreen",            0, FIXME_IMPLEMENT },
593   { "cyscreen",            0, FIXME_IMPLEMENT },
594   { "cxvscroll",          16, NULL },
595   { "cyhscroll",          16, NULL },
596   { "cycaption",          16, NULL },
597   { "cxborder",            1, NULL },
598   { "cyborder",            1, NULL },
599   { "cxdlgframe",          3, NULL },
600   { "cydlgframe",          3, NULL },
601   { "cyvthumb",           16, NULL },
602   { "cxhthumb",           16, NULL },
603   { "cxicon",             32, NULL },
604   { "cyicon",             32, NULL },
605   { "cxcursor",           32, NULL },
606   { "cycursor",           32, NULL },
607   { "cymenu",             19, NULL },
608   { "cxfullscreen", 0, FIXME_IMPLEMENT },
609   { "cyfullscreen", 0, FIXME_IMPLEMENT },
610   { "cykanjiwindow",       0, NULL },
611   { "mousepresent",        1, NULL },
612   { "cyvscroll",          16, NULL },
613   { "cxhscroll",          16, NULL },
614   { "debug",               0, NULL },
615   { "swapbutton",          0, NULL },
616   { "reserved1",           0, NULL },
617   { "reserved2",           0, NULL },
618   { "reserved3",           0, NULL },
619   { "reserved4",           0, NULL },
620   { "cxmin",             112, NULL },
621   { "cymin",              24, NULL },
622   { "cxsize",             18, NULL },
623   { "cysize",             15, NULL },
624   { "cxframe",             4, NULL },
625   { "cyframe",             4, NULL },
626   { "cxmintrack",        112, NULL },
627   { "cymintrack",         24, NULL },
628   { "cxdoubleclk",         0, FIXME_IMPLEMENT },
629   { "cydoubleclk",         0, FIXME_IMPLEMENT },
630   { "cxiconspacing",      75, NULL },
631   { "cyiconspacing",      75, NULL },
632   { "menudropalignment",   0, NULL },
633   { "penwindows",          0, NULL },
634   { "dbcsenabled",         1, NULL },
635   { "cmousebuttons",       3, NULL },
636   { "secure",              0, NULL },
637   { "cxedge",              2, NULL },
638   { "cyedge",              2, NULL },
639   { "cxminspacing",      160, NULL },
640   { "cyminspacing",       21, NULL },
641   { "cxsmicon",           16, NULL },
642   { "cysmicon",           16, NULL },
643   { "cysmcaption",        16, NULL },
644   { "cxsmsize",           15, NULL },
645   { "cysmsize",           15, NULL },
646   { "cxmenusize",         18, NULL },
647   { "cymenusize",         18, NULL },
648   { "arrange",             8, NULL },
649   { "cxminimized",       160, NULL },
650   { "cyminimized",        21, NULL },
651   { "cxmaxtrack", 0, FIXME_IMPLEMENT },
652   { "cymaxtrack", 0, FIXME_IMPLEMENT },
653   { "cxmaximized", 0, FIXME_IMPLEMENT },
654   { "cymaximized", 0, FIXME_IMPLEMENT },
655   { "network",             3, NULL },
656   { NULL,                  0, NULL },
657   { NULL,                  0, NULL },
658   { NULL,                  0, NULL },
659   { "cleanboot",           0, NULL },
660   { "cxdrag",              4, NULL },
661   { "cydrag",              4, NULL },
662   { "showsounds",          0, NULL },
663   { "cxmenucheck",        13, NULL },
664   { "cymenucheck",        13, NULL },
665   { "slowmachine",         0, NULL },
666   { "mideastenabled",      0, NULL },
667   { "mousewheelpresent",   1, NULL },
668   { "xvirtualscreen", 0, FIXME_IMPLEMENT },
669   { "yvirtualscreen", 0, FIXME_IMPLEMENT },
670   { "cxvirtualscreen", 0, FIXME_IMPLEMENT },
671   { "cyvirtualscreen", 0, FIXME_IMPLEMENT },
672   { "cmonitors", 0, FIXME_IMPLEMENT },
673   { "samedisplayformat",   1, NULL },
674   { "immenabled",          1, NULL },
675   { "cxfocusborder",       1, NULL },
676   { "cyfocusborder",       1, NULL },
677   { NULL,                  0, NULL },
678   { "tabletpc",            0, NULL },
679   { "mediacenter",         0, NULL },
680   { "starter",             0, NULL },
681   { "serverr2",            0, NULL },
682   { "cmetrics",           90, NULL },
683   { "mousehorizontalwheelpresent", 0, NULL },
684   { "cxpaddedborder",      0, NULL }
685 };
686 
687 const char *
gtk_win32_get_sys_metric_name_for_id(gint id)688 gtk_win32_get_sys_metric_name_for_id (gint id)
689 {
690   if (id >= 0 && id < G_N_ELEMENTS (win32_default_metrics))
691     return win32_default_metrics[id].name;
692   else
693     return NULL;
694 }
695 
696 int
gtk_win32_get_sys_metric_id_for_name(const char * name)697 gtk_win32_get_sys_metric_id_for_name (const char *name)
698 {
699   int i;
700 
701   g_return_val_if_fail (name != NULL, -1);
702 
703   for (i = 0; i < G_N_ELEMENTS (win32_default_metrics); i++)
704     {
705       if (win32_default_metrics[i].name == NULL)
706         continue;
707 
708       if (g_str_equal (name, win32_default_metrics[i].name))
709         return i;
710     }
711 
712   return -1;
713 }
714 
715 int
gtk_win32_get_sys_metric(gint id)716 gtk_win32_get_sys_metric (gint id)
717 {
718   if (id < 0 || id >= G_N_ELEMENTS (win32_default_metrics))
719     return 0;
720 
721   if (win32_default_metrics[id].get_value)
722     return win32_default_metrics[id].get_value (id);
723 
724   return win32_default_metrics[id].value;
725 }
726 
727 static struct {
728   const char *name;
729   GdkRGBA rgba;
730 } win32_default_colors[] = {
731 #define RGB(r, g, b) { (r)/255.0, (g)/255.0, (b)/255., 1.0 }
732   { "scrollbar", RGB(212, 208, 200) },
733   { "background", RGB(58, 110, 165) },
734   { "activecaption", RGB(10, 36, 106) },
735   { "inactivecaption", RGB(128, 128, 128) },
736   { "menu", RGB(212, 208, 200) },
737   { "window", RGB(255, 255, 255) },
738   { "windowframe", RGB(0, 0, 0) },
739   { "menutext", RGB(0, 0, 0) },
740   { "windowtext", RGB(0, 0, 0) },
741   { "captiontext", RGB(255, 255, 255) },
742   { "activeborder", RGB(212, 208, 200) },
743   { "inactiveborder", RGB(212, 208, 200) },
744   { "appworkspace", RGB(128, 128, 128) },
745   { "highlight", RGB(10, 36, 106) },
746   { "highlighttext", RGB(255, 255, 255) },
747   { "btnface", RGB(212, 208, 200) },
748   { "btnshadow", RGB(128, 128, 128) },
749   { "graytext", RGB(128, 128, 128) },
750   { "btntext", RGB(0, 0, 0) },
751   { "inactivecaptiontext", RGB(212, 208, 200) },
752   { "btnhighlight", RGB(255, 255, 255) },
753   { "3ddkshadow", RGB(64, 64, 64) },
754   { "3dlight", RGB(212, 208, 200) },
755   { "infotext", RGB(0, 0, 0) },
756   { "infobk", RGB(255, 255, 225) },
757   { "alternatebtnface", RGB(181, 181, 181) },
758   { "hotlight", RGB(0, 0, 200) },
759   { "gradientactivecaption", RGB(166, 202, 240) },
760   { "gradientinactivecaption", RGB(192, 192, 192) },
761   { "menuhilight", RGB(10, 36, 106) },
762   { "menubar", RGB(212, 208, 200) }
763 #undef RGB
764 };
765 
766 const char *
gtk_win32_get_sys_color_name_for_id(gint id)767 gtk_win32_get_sys_color_name_for_id (gint id)
768 {
769   if (id >= 0 && id < G_N_ELEMENTS (win32_default_colors))
770     return win32_default_colors[id].name;
771   else
772     return NULL;
773 }
774 
775 int
gtk_win32_get_sys_color_id_for_name(const char * name)776 gtk_win32_get_sys_color_id_for_name (const char *name)
777 {
778   int i;
779 
780   g_return_val_if_fail (name != NULL, -1);
781 
782   for (i = 0; i < G_N_ELEMENTS (win32_default_colors); i++)
783     {
784       if (g_str_equal (name, win32_default_colors[i].name))
785         return i;
786     }
787 
788   return -1;
789 }
790 
791 void
gtk_win32_get_sys_color(gint id,GdkRGBA * color)792 gtk_win32_get_sys_color (gint     id,
793                          GdkRGBA *color)
794 {
795   if (id < 0 || id >= G_N_ELEMENTS (win32_default_colors))
796     {
797       gdk_rgba_parse (color, "black");
798       return;
799     }
800 
801   *color = win32_default_colors[id].rgba;
802 }
803 
804