1 /* MS-Windows Engine (aka GTK-Wimp)
3 * Copyright (C) 2003, 2004 Raymond Penners <raymond@dotsphinx.com>
4 * Includes code adapted from redmond95 by Owen Taylor, and
5 * gtk-nativewin by Evan Martin
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
23 #include "msw_style.h"
31 #include <gdk/gdkwin32.h>
35 /* Default values, not normally used
37 static const GtkRequisition default_option_indicator_size = { 9, 8 };
38 static const GtkBorder default_option_indicator_spacing = { 7, 5, 2, 2 };
40 static GtkStyleClass *parent_class;
60 static const char check_aa_bits[] = {
61 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
62 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
63 static const char check_base_bits[] = {
64 0x00,0x00,0x00,0x00,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc,
65 0x07,0xfc,0x07,0xfc,0x07,0xfc,0x07,0x00,0x00,0x00,0x00};
66 static const char check_black_bits[] = {
67 0x00,0x00,0xfe,0x0f,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,
68 0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00};
69 static const char check_dark_bits[] = {
70 0xff,0x1f,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
71 0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00};
72 static const char check_light_bits[] = {
73 0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,
74 0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0xfe,0x1f};
75 static const char check_mid_bits[] = {
76 0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,
77 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0xfc,0x0f,0x00,0x00};
78 static const char check_text_bits[] = {
79 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x03,0x88,0x03,0xd8,0x01,0xf8,
80 0x00,0x70,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
81 static const char radio_base_bits[] = {
82 0x00,0x00,0x00,0x00,0xf0,0x01,0xf8,0x03,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc,
83 0x07,0xfc,0x07,0xf8,0x03,0xf0,0x01,0x00,0x00,0x00,0x00};
84 static const char radio_black_bits[] = {
85 0x00,0x00,0xf0,0x01,0x0c,0x02,0x04,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,
86 0x00,0x02,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
87 static const char radio_dark_bits[] = {
88 0xf0,0x01,0x0c,0x06,0x02,0x00,0x02,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
89 0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00};
90 static const char radio_light_bits[] = {
91 0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0x10,0x00,0x10,0x00,
92 0x10,0x00,0x10,0x00,0x08,0x00,0x08,0x0c,0x06,0xf0,0x01};
93 static const char radio_mid_bits[] = {
94 0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x08,0x00,
95 0x08,0x00,0x08,0x00,0x04,0x0c,0x06,0xf0,0x01,0x00,0x00};
96 static const char radio_text_bits[] = {
97 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0xf0,0x01,0xf0,0x01,0xf0,
98 0x01,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
104 { check_aa_bits, NULL },
105 { check_base_bits, NULL },
106 { check_black_bits, NULL },
107 { check_dark_bits, NULL },
108 { check_light_bits, NULL },
109 { check_mid_bits, NULL },
110 { check_text_bits, NULL },
111 { radio_base_bits, NULL },
112 { radio_black_bits, NULL },
113 { radio_dark_bits, NULL },
114 { radio_light_bits, NULL },
115 { radio_mid_bits, NULL },
116 { radio_text_bits, NULL }
120 get_system_font(XpThemeClass klazz, XpThemeFont type, LOGFONT *out_lf)
123 /* TODO: this crashes. need to figure out why and how to fix it */
124 if (xp_theme_get_system_font(klazz, type, out_lf)) {
129 NONCLIENTMETRICS ncm;
130 ncm.cbSize = sizeof(NONCLIENTMETRICS);
132 if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
133 sizeof(NONCLIENTMETRICS), &ncm, 0))
135 if (type == XP_THEME_FONT_CAPTION)
136 *out_lf = ncm.lfCaptionFont;
137 else if (type == XP_THEME_FONT_MENU)
138 *out_lf = ncm.lfMenuFont;
139 else if (type == XP_THEME_FONT_STATUS)
140 *out_lf = ncm.lfStatusFont;
142 *out_lf = ncm.lfMessageFont;
150 /***************************** STOLEN FROM PANGO *****************************/
153 This code is stolen from Pango 1.4. It attempts to address the following problems:
155 http://bugzilla.gnome.org/show_bug.cgi?id=135098
156 http://sourceforge.net/tracker/index.php?func=detail&aid=895762&group_id=76416&atid=547655
158 As Owen suggested in bug 135098, once Pango 1.6 is released, we need to get rid of this code.
161 #define PING(printlist)
163 /* TrueType defines: */
165 #define MAKE_TT_TABLE_NAME(c1, c2, c3, c4) \
166 (((guint32)c4) << 24 | ((guint32)c3) << 16 | ((guint32)c2) << 8 | ((guint32)c1))
168 #define CMAP (MAKE_TT_TABLE_NAME('c','m','a','p'))
169 #define CMAP_HEADER_SIZE 4
171 #define NAME (MAKE_TT_TABLE_NAME('n','a','m','e'))
172 #define NAME_HEADER_SIZE 6
174 #define ENCODING_TABLE_SIZE 8
176 #define APPLE_UNICODE_PLATFORM_ID 0
177 #define MACINTOSH_PLATFORM_ID 1
178 #define ISO_PLATFORM_ID 2
179 #define MICROSOFT_PLATFORM_ID 3
181 #define SYMBOL_ENCODING_ID 0
182 #define UNICODE_ENCODING_ID 1
183 #define UCS4_ENCODING_ID 10
187 guint16 format_selector;
189 guint16 string_storage_offset;
198 guint16 string_length;
199 guint16 string_offset;
203 pango_win32_get_name_header (HDC hdc,
204 struct name_header *header)
206 if (GetFontData (hdc, NAME, 0, header, sizeof (*header)) != sizeof (*header))
209 header->num_records = GUINT16_FROM_BE (header->num_records);
210 header->string_storage_offset = GUINT16_FROM_BE (header->string_storage_offset);
216 pango_win32_get_name_record (HDC hdc,
218 struct name_record *record)
220 if (GetFontData (hdc, NAME, 6 + i * sizeof (*record),
221 record, sizeof (*record)) != sizeof (*record))
224 record->platform_id = GUINT16_FROM_BE (record->platform_id);
225 record->encoding_id = GUINT16_FROM_BE (record->encoding_id);
226 record->language_id = GUINT16_FROM_BE (record->language_id);
227 record->name_id = GUINT16_FROM_BE (record->name_id);
228 record->string_length = GUINT16_FROM_BE (record->string_length);
229 record->string_offset = GUINT16_FROM_BE (record->string_offset);
235 get_family_name (LOGFONT *lfp, HDC pango_win32_hdc)
240 struct name_header header;
241 struct name_record record;
243 gint unicode_ix = -1, mac_ix = -1, microsoft_ix = -1;
247 gchar *string = NULL;
253 /* If lfFaceName is ASCII, assume it is the common (English) name
254 * for the font. Is this valid? Do some TrueType fonts have
255 * different names in French, German, etc, and does the system
256 * return these if the locale is set to use French, German, etc?
258 l = strlen (lfp->lfFaceName);
259 for (i = 0; i < l; i++)
260 if (lfp->lfFaceName[i] < ' ' || lfp->lfFaceName[i] > '~')
264 return g_strdup (lfp->lfFaceName);
266 if ((hfont = CreateFontIndirect (lfp)) == NULL)
269 if ((oldhfont = SelectObject (pango_win32_hdc, hfont)) == NULL)
272 if (!pango_win32_get_name_header (pango_win32_hdc, &header))
275 PING (("%d name records", header.num_records));
277 for (i = 0; i < header.num_records; i++)
279 if (!pango_win32_get_name_record (pango_win32_hdc, i, &record))
282 if ((record.name_id != 1 && record.name_id != 16) || record.string_length <= 0)
285 PING(("platform:%d encoding:%d language:%04x name_id:%d",
286 record.platform_id, record.encoding_id, record.language_id, record.name_id));
288 if (record.platform_id == APPLE_UNICODE_PLATFORM_ID ||
289 record.platform_id == ISO_PLATFORM_ID)
291 else if (record.platform_id == MACINTOSH_PLATFORM_ID &&
292 record.encoding_id == 0 && /* Roman */
293 record.language_id == 0) /* English */
295 else if (record.platform_id == MICROSOFT_PLATFORM_ID)
296 if ((microsoft_ix == -1 ||
297 PRIMARYLANGID (record.language_id) == LANG_ENGLISH) &&
298 (record.encoding_id == SYMBOL_ENCODING_ID ||
299 record.encoding_id == UNICODE_ENCODING_ID ||
300 record.encoding_id == UCS4_ENCODING_ID))
304 if (microsoft_ix >= 0)
305 name_ix = microsoft_ix;
306 else if (mac_ix >= 0)
308 else if (unicode_ix >= 0)
309 name_ix = unicode_ix;
313 if (!pango_win32_get_name_record (pango_win32_hdc, name_ix, &record))
316 string = g_malloc (record.string_length + 1);
317 if (GetFontData (pango_win32_hdc, NAME,
318 header.string_storage_offset + record.string_offset,
319 string, record.string_length) != record.string_length)
322 string[record.string_length] = '\0';
324 if (name_ix == microsoft_ix)
325 if (record.encoding_id == SYMBOL_ENCODING_ID ||
326 record.encoding_id == UNICODE_ENCODING_ID)
327 codeset = "UTF-16BE";
330 else if (name_ix == mac_ix)
331 codeset = "MacRoman";
332 else /* name_ix == unicode_ix */
335 name = g_convert (string, record.string_length, "UTF-8", codeset, NULL, &nbytes, NULL);
342 SelectObject (pango_win32_hdc, oldhfont);
343 DeleteObject (hfont);
349 SelectObject (pango_win32_hdc, oldhfont);
352 DeleteObject (hfont);
355 return g_locale_to_utf8 (lfp->lfFaceName, -1, NULL, NULL, NULL);
358 /***************************** STOLEN FROM PANGO *****************************/
361 sys_font_to_pango_font (XpThemeClass klazz, XpThemeFont type, char * buf, size_t bufsiz)
371 if (get_system_font(klazz, type, &lf))
373 switch (lf.lfWeight) {
376 weight = "Ultra-Light";
388 weight = "Semi-Bold";
392 weight = "Ultra-Bold";
409 hwnd = GetDesktopWindow();
412 pt_size = -MulDiv(lf.lfHeight, 72,
413 GetDeviceCaps(hDC,LOGPIXELSY));
414 ReleaseDC(hwnd, hDC);
418 font = get_family_name(&lf, hDC);
419 g_snprintf(buf, bufsiz, "%s %s %s %d", font, style, weight, pt_size);
428 /* missing from ms's header files */
429 #ifndef SPI_GETMENUSHOWDELAY
430 #define SPI_GETMENUSHOWDELAY 106
433 /* I don't know the proper XP theme class for things like
434 HIGHLIGHTTEXT, so we'll just define it to be "BUTTON"
436 #define XP_THEME_CLASS_TEXT XP_THEME_CLASS_BUTTON
439 setup_menu_settings (void)
442 gboolean win95 = FALSE;
444 GtkSettings * settings;
445 OSVERSIONINFOEX osvi;
447 settings = gtk_settings_get_default ();
451 ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
452 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
454 if (!GetVersionEx ( (OSVERSIONINFO *) &osvi))
455 win95 = TRUE; /* assume the worst */
457 if (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
458 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
462 if (SystemParametersInfo (SPI_GETMENUSHOWDELAY, 0, &menu_delay, 0)) {
463 GObjectClass * klazz = G_OBJECT_GET_CLASS(G_OBJECT(settings));
466 if (g_object_class_find_property (klazz, "gtk-menu-bar-popup-delay")) {
467 g_object_set (G_OBJECT (settings), "gtk-menu-bar-popup-delay",
470 if (g_object_class_find_property (klazz, "gtk-menu-popup-delay")) {
471 g_object_set (G_OBJECT (settings), "gtk-menu-popup-delay",
474 if (g_object_class_find_property (klazz, "gtk-menu-popdown-delay")) {
475 g_object_set (G_OBJECT (settings), "gtk-menu-popdown-delay",
484 msw_style_setup_system_settings (void)
486 GtkSettings * settings;
487 int cursor_blink_time;
489 settings = gtk_settings_get_default ();
493 cursor_blink_time = GetCaretBlinkTime ();
494 g_object_set (G_OBJECT (settings), "gtk-cursor-blink",
495 cursor_blink_time > 0, NULL);
497 if (cursor_blink_time > 0)
499 g_object_set (G_OBJECT (settings), "gtk-cursor-blink-time",
500 2*cursor_blink_time, NULL);
503 g_object_set (G_OBJECT (settings), "gtk-double-click-time",
504 GetDoubleClickTime(), NULL);
505 g_object_set (G_OBJECT (settings), "gtk-dnd-drag-threshold",
506 GetSystemMetrics(SM_CXDRAG), NULL);
508 setup_menu_settings ();
511 http://developer.gnome.org/doc/API/2.0/gtk/GtkSettings.html
512 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/systemparametersinfo.asp
513 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/getsystemmetrics.asp
518 setup_system_font(GtkStyle *style)
520 char buf[256], * font; /* It's okay, lfFaceName is smaller than 32 chars */
522 if ((font = sys_font_to_pango_font(XP_THEME_CLASS_TEXT, XP_THEME_FONT_MESSAGE, buf, sizeof (buf))) != NULL)
523 style->font_desc = pango_font_description_from_string(font);
527 sys_color_to_gtk_color(XpThemeClass klazz, int id, GdkColor *pcolor)
531 if (!xp_theme_get_system_color (klazz, id, &color))
532 color = GetSysColor(id);
534 pcolor->pixel = color;
535 pcolor->red = (GetRValue(color) << 8) | GetRValue(color);
536 pcolor->green = (GetGValue(color) << 8) | GetGValue(color);
537 pcolor->blue = (GetBValue(color) << 8) | GetBValue(color);
541 get_system_metric(XpThemeClass klazz, int id)
545 if (!xp_theme_get_system_metric(klazz, id, &rval))
546 rval = GetSystemMetrics (id);
553 setup_default_style (void)
559 GdkColor highlighttext;
569 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNFACE, &btnface);
570 sys_color_to_gtk_color(XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT, &highlight);
571 sys_color_to_gtk_color(XP_THEME_CLASS_WINDOW, COLOR_WINDOW, &window);
572 sys_color_to_gtk_color(XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT, &windowtext);
573 sys_color_to_gtk_color(XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT, &highlighttext);
574 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_GRAYTEXT, &graytext);
575 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT, &btntext);
576 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_3DSHADOW, &dark);
577 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_3DHILIGHT, &light);
579 mid.red = (light.red + dark.red) / 2;
580 mid.green = (light.green + dark.green) / 2;
581 mid.blue = (light.blue + dark.blue) / 2;
583 text_aa[0].red = (windowtext.red + window.red) / 2;
584 text_aa[0].green = (windowtext.green + window.green) / 2;
585 text_aa[0].blue = (windowtext.blue + window.blue) / 2;
586 text_aa[1].red = (highlighttext.red + highlight.red) / 2;
587 text_aa[1].green = (highlighttext.green + highlight.green) / 2;
588 text_aa[1].blue = (highlighttext.blue + highlight.blue) / 2;
590 text_aa[2].red = (graytext.red + btnface.red) / 2;
591 text_aa[2].green = (graytext.green + btnface.green) / 2;
592 text_aa[2].blue = (graytext.blue + btnface.blue) / 2;
594 text_aa[3].red = (btntext.red + btnface.red) / 2;
595 text_aa[3].green = (btntext.green + btnface.green) / 2;
596 text_aa[3].blue = (btntext.blue + btnface.blue) / 2;
598 text_aa[4].red = (windowtext.red + window.red) / 2;
599 text_aa[4].green = (windowtext.green + window.green) / 2;
600 text_aa[4].blue = (windowtext.blue + window.blue) / 2;
602 g_snprintf(buf, sizeof (buf),
603 "style \"msw-base\" = \"msw-default\"\n"
605 "bg[NORMAL] = { %d, %d, %d }\n"
606 "bg[SELECTED] = { %d, %d, %d }\n"
607 "bg[INSENSITIVE] = { %d, %d, %d }\n"
608 "bg[ACTIVE] = { %d, %d, %d }\n"
609 "bg[PRELIGHT] = { %d, %d, %d }\n"
610 "base[NORMAL] = { %d, %d, %d }\n"
611 "base[SELECTED] = { %d, %d, %d }\n"
612 "base[INSENSITIVE] = { %d, %d, %d }\n"
613 "base[ACTIVE] = { %d, %d, %d }\n"
614 "base[PRELIGHT] = { %d, %d, %d }\n"
615 "text[NORMAL] = { %d, %d, %d }\n"
616 "text[SELECTED] = { %d, %d, %d }\n"
617 "text[INSENSITIVE] = { %d, %d, %d }\n"
618 "text[ACTIVE] = { %d, %d, %d }\n"
619 "text[PRELIGHT] = { %d, %d, %d }\n"
620 "fg[NORMAL] = { %d, %d, %d }\n"
621 "fg[SELECTED] = { %d, %d, %d }\n"
622 "fg[INSENSITIVE] = { %d, %d, %d }\n"
623 "fg[ACTIVE] = { %d, %d, %d }\n"
624 "fg[PRELIGHT] = { %d, %d, %d }\n"
625 "dark[NORMAL] = { %d, %d, %d }\n"
626 "dark[SELECTED] = { %d, %d, %d }\n"
627 "dark[INSENSITIVE] = { %d, %d, %d }\n"
628 "dark[ACTIVE] = { %d, %d, %d }\n"
629 "dark[PRELIGHT] = { %d, %d, %d }\n"
630 "light[NORMAL] = { %d, %d, %d }\n"
631 "light[SELECTED] = { %d, %d, %d }\n"
632 "light[INSENSITIVE] = { %d, %d, %d }\n"
633 "light[ACTIVE] = { %d, %d, %d }\n"
634 "light[PRELIGHT] = { %d, %d, %d }\n"
635 "text_aa[NORMAL] = { %d, %d, %d }\n"
636 "text_aa[SELECTED] = { %d, %d, %d }\n"
637 "text_aa[INSENSITIVE] = { %d, %d, %d }\n"
638 "text_aa[ACTIVE] = { %d, %d, %d }\n"
639 "text_aa[PRELIGHT] = { %d, %d, %d }\n"
640 "}widget_class \"*\" style \"msw-base\"\n",
643 btnface.red, btnface.green, btnface.blue,
644 highlight.red, highlight.green, highlight.blue,
645 btnface.red, btnface.green, btnface.blue,
646 btnface.red, btnface.green, btnface.blue,
647 btnface.red, btnface.green, btnface.blue,
650 window.red, window.green, window.blue,
651 highlight.red, highlight.green, highlight.blue,
652 btnface.red, btnface.green, btnface.blue,
653 btnface.red, btnface.green, btnface.blue,
654 window.red, window.green, window.blue,
657 windowtext.red, windowtext.green, windowtext.blue,
658 highlighttext.red, highlighttext.green, highlighttext.blue,
659 graytext.red, graytext.green, graytext.blue,
660 btntext.red, btntext.green, btntext.blue,
661 windowtext.red, windowtext.green, windowtext.blue,
664 btntext.red, btntext.green, btntext.blue,
665 highlighttext.red, highlighttext.green, highlighttext.blue,
666 graytext.red, graytext.green, graytext.blue,
667 btntext.red, btntext.green, btntext.blue,
668 windowtext.red, windowtext.green, windowtext.blue,
671 dark.red, dark.green, dark.blue,
672 dark.red, dark.green, dark.blue,
673 dark.red, dark.green, dark.blue,
674 dark.red, dark.green, dark.blue,
675 dark.red, dark.green, dark.blue,
678 light.red, light.green, light.blue,
679 light.red, light.green, light.blue,
680 light.red, light.green, light.blue,
681 light.red, light.green, light.blue,
682 light.red, light.green, light.blue,
685 text_aa[0].red, text_aa[0].green, text_aa[0].blue,
686 text_aa[1].red, text_aa[1].green, text_aa[1].blue,
687 text_aa[2].red, text_aa[2].green, text_aa[2].blue,
688 text_aa[3].red, text_aa[3].green, text_aa[3].blue,
689 text_aa[4].red, text_aa[4].green, text_aa[4].blue
691 gtk_rc_parse_string(buf);
696 setup_msw_rc_style(void)
699 "If your setup_system_styles() function called gtk_rc_parse_string(), then you are just piling a new set of strings on top each time the theme changes .. the old ones won't be removed" */
701 char buf[1024], font_buf[256], *font_ptr;
704 GdkColor menu_text_color;
705 GdkColor tooltip_back;
706 GdkColor tooltip_fore;
709 GdkColor progress_back;
711 GdkColor fg_prelight;
712 GdkColor bg_prelight;
713 GdkColor base_prelight;
714 GdkColor text_prelight;
719 sys_color_to_gtk_color(XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT, &fg_prelight);
720 sys_color_to_gtk_color(XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT, &bg_prelight);
721 sys_color_to_gtk_color(XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT, &base_prelight);
722 sys_color_to_gtk_color(XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT, &text_prelight);
724 sys_color_to_gtk_color(XP_THEME_CLASS_MENU, COLOR_MENUTEXT, &menu_text_color);
725 sys_color_to_gtk_color(XP_THEME_CLASS_MENU, COLOR_MENU, &menu_color);
728 sys_color_to_gtk_color(XP_THEME_CLASS_TOOLTIP, COLOR_INFOTEXT, &tooltip_fore);
729 sys_color_to_gtk_color(XP_THEME_CLASS_TOOLTIP, COLOR_INFOBK, &tooltip_back);
731 /* text on push buttons. TODO: button shadows, backgrounds, and highlights */
732 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT, &btn_fore);
733 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNFACE, &btn_face);
735 /* progress bar background color */
736 sys_color_to_gtk_color(XP_THEME_CLASS_PROGRESS, COLOR_HIGHLIGHT, &progress_back);
738 /* Enable coloring for menus. */
739 font_ptr = sys_font_to_pango_font (XP_THEME_CLASS_MENU, XP_THEME_FONT_MENU,font_buf, sizeof (font_buf));
740 g_snprintf(buf, sizeof (buf),
741 "style \"msw-menu\" = \"msw-default\"\n"
743 "fg[PRELIGHT] = { %d, %d, %d }\n"
744 "bg[PRELIGHT] = { %d, %d, %d }\n"
745 "text[PRELIGHT] = { %d, %d, %d }\n"
746 "base[PRELIGHT] = { %d, %d, %d }\n"
747 "fg[NORMAL] = { %d, %d, %d }\n"
748 "bg[NORMAL] = { %d, %d, %d }\n"
750 "}widget_class \"*MenuItem*\" style \"msw-menu\"\n"
751 "widget_class \"*GtkMenu\" style \"msw-menu\"\n"
752 "widget_class \"*GtkMenuShell*\" style \"msw-menu\"\n",
766 menu_text_color.green,
767 menu_text_color.blue,
771 (font_ptr ? "font_name" : "#"),
772 (font_ptr ? font_ptr : " font name should go here"));
773 gtk_rc_parse_string(buf);
775 /* Enable coloring for menu bars. */
776 font_ptr = sys_font_to_pango_font (XP_THEME_CLASS_MENU, XP_THEME_FONT_MENU,font_buf, sizeof (font_buf));
777 g_snprintf(buf, sizeof (buf),
778 "style \"msw-menu-bar\" = \"msw-menu\"\n"
780 "bg[NORMAL] = { %d, %d, %d }\n"
781 "}widget_class \"*MenuBar*\" style \"msw-menu-bar\"\n",
785 gtk_rc_parse_string(buf);
787 /* enable tooltip fonts */
788 font_ptr = sys_font_to_pango_font (XP_THEME_CLASS_STATUS, XP_THEME_FONT_STATUS,font_buf, sizeof (font_buf));
789 g_snprintf(buf, sizeof (buf),
790 "style \"msw-tooltips-caption\" = \"msw-default\"\n"
791 "{fg[NORMAL] = { %d, %d, %d }\n"
793 "}widget \"gtk-tooltips.GtkLabel\" style \"msw-tooltips-caption\"\n",
797 (font_ptr ? "font_name" : "#"),
798 (font_ptr ? font_ptr : " font name should go here"));
799 gtk_rc_parse_string(buf);
801 g_snprintf(buf, sizeof (buf),
802 "style \"msw-tooltips\" = \"msw-default\"\n"
803 "{bg[NORMAL] = { %d, %d, %d }\n"
804 "}widget \"gtk-tooltips*\" style \"msw-tooltips\"\n",
808 gtk_rc_parse_string(buf);
810 /* enable font theming for status bars */
811 font_ptr = sys_font_to_pango_font (XP_THEME_CLASS_STATUS, XP_THEME_FONT_STATUS,font_buf, sizeof (font_buf));
812 g_snprintf(buf, sizeof (buf),
813 "style \"msw-status\" = \"msw-default\"\n"
815 "bg[NORMAL] = { %d, %d, %d }\n"
816 "}widget_class \"*Status*\" style \"msw-status\"\n",
817 (font_ptr ? "font_name" : "#"),
818 (font_ptr ? font_ptr : " font name should go here"),
819 btn_face.red, btn_face.green, btn_face.blue);
820 gtk_rc_parse_string(buf);
822 /* enable coloring for text on buttons
823 TODO: use GetThemeMetric for the border and outside border */
824 g_snprintf(buf, sizeof (buf),
825 "style \"msw-button\" = \"msw-default\"\n"
827 "bg[NORMAL] = { %d, %d, %d }\n"
828 "bg[PRELIGHT] = { %d, %d, %d }\n"
829 "bg[INSENSITIVE] = { %d, %d, %d }\n"
830 "fg[PRELIGHT] = { %d, %d, %d }\n"
831 "GtkButton::default-border = { 1, 1, 1, 1 }\n"
832 "GtkButton::default-outside-border = { 0, 0, 0, 0 }\n"
833 "GtkButton::child-displacement-x = 1\n"
834 "GtkButton::child-displacement-y = 1\n"
835 "}widget_class \"*Button*\" style \"msw-button\"\n",
836 btn_face.red, btn_face.green, btn_face.blue,
837 btn_face.red, btn_face.green, btn_face.blue,
838 btn_face.red, btn_face.green, btn_face.blue,
839 btn_fore.red, btn_fore.green, btn_fore.blue
841 gtk_rc_parse_string(buf);
843 /* enable coloring for progress bars */
844 g_snprintf(buf, sizeof (buf),
845 "style \"msw-progress\" = \"msw-default\"\n"
846 "{bg[PRELIGHT] = { %d, %d, %d }\n"
847 "bg[NORMAL] = { %d, %d, %d }\n"
848 "}widget_class \"*Progress*\" style \"msw-progress\"\n",
852 btn_face.red, btn_face.green, btn_face.blue);
853 gtk_rc_parse_string(buf);
855 /* scrollbar thumb width and height */
856 g_snprintf(buf, sizeof (buf),
857 "style \"msw-vscrollbar\" = \"msw-default\"\n"
858 "{GtkRange::slider-width = %d\n"
859 "GtkRange::stepper-size = %d\n"
860 "GtkRange::stepper-spacing = 0\n"
861 "GtkRange::trough_border = 0\n"
862 "}widget_class \"*VScrollbar*\" style \"msw-vscrollbar\"\n",
863 GetSystemMetrics(SM_CYVTHUMB),
864 get_system_metric(XP_THEME_CLASS_SCROLLBAR, SM_CXVSCROLL));
865 gtk_rc_parse_string(buf);
867 g_snprintf(buf, sizeof (buf),
868 "style \"msw-hscrollbar\" = \"msw-default\"\n"
869 "{GtkRange::slider-width = %d\n"
870 "GtkRange::stepper-size = %d\n"
871 "GtkRange::stepper-spacing = 0\n"
872 "GtkRange::trough_border = 0\n"
873 "}widget_class \"*HScrollbar*\" style \"msw-hscrollbar\"\n",
874 GetSystemMetrics(SM_CXHTHUMB),
875 get_system_metric(XP_THEME_CLASS_SCROLLBAR, SM_CYHSCROLL));
876 gtk_rc_parse_string(buf);
878 /* radio/check button sizes */
879 g_snprintf(buf, sizeof (buf),
880 "style \"msw-checkbutton\" = \"msw-button\"\n"
881 "{GtkCheckButton::indicator-size = 13\n"
882 "}widget_class \"*CheckButton*\" style \"msw-checkbutton\"\n"
883 "widget_class \"*RadioButton*\" style \"msw-checkbutton\"\n");
884 gtk_rc_parse_string(buf);
888 setup_system_styles(GtkStyle *style)
892 /* Default background */
893 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNFACE, &style->bg[GTK_STATE_NORMAL]);
894 sys_color_to_gtk_color(XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT, &style->bg[GTK_STATE_SELECTED]);
895 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNFACE, &style->bg[GTK_STATE_INSENSITIVE]);
896 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNFACE, &style->bg[GTK_STATE_ACTIVE]);
897 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNFACE, &style->bg[GTK_STATE_PRELIGHT]);
900 sys_color_to_gtk_color(XP_THEME_CLASS_WINDOW, COLOR_WINDOW, &style->base[GTK_STATE_NORMAL]);
901 sys_color_to_gtk_color(XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT, &style->base[GTK_STATE_SELECTED]);
902 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNFACE, &style->base[GTK_STATE_INSENSITIVE]);
903 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNFACE, &style->base[GTK_STATE_ACTIVE]);
904 sys_color_to_gtk_color(XP_THEME_CLASS_WINDOW, COLOR_WINDOW, &style->base[GTK_STATE_PRELIGHT]);
907 sys_color_to_gtk_color(XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT, &style->text[GTK_STATE_NORMAL]);
908 sys_color_to_gtk_color(XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT, &style->text[GTK_STATE_SELECTED]);
909 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_GRAYTEXT, &style->text[GTK_STATE_INSENSITIVE]);
910 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT, &style->text[GTK_STATE_ACTIVE]);
911 sys_color_to_gtk_color(XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT, &style->text[GTK_STATE_PRELIGHT]);
913 /* Default forgeground */
914 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT, &style->fg[GTK_STATE_NORMAL]);
915 sys_color_to_gtk_color(XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT, &style->fg[GTK_STATE_SELECTED]);
916 sys_color_to_gtk_color(XP_THEME_CLASS_TEXT, COLOR_GRAYTEXT, &style->fg[GTK_STATE_INSENSITIVE]);
917 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT, &style->fg[GTK_STATE_ACTIVE]);
918 sys_color_to_gtk_color(XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT, &style->fg[GTK_STATE_PRELIGHT]);
920 for (i = 0; i < 5; i++)
922 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_3DSHADOW, &style->dark[i]);
923 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_3DHILIGHT, &style->light[i]);
925 style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2;
926 style->mid[i].green = (style->light[i].green + style->dark[i].green) / 2;
927 style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2;
929 style->text_aa[i].red = (style->text[i].red + style->base[i].red) / 2;
930 style->text_aa[i].green = (style->text[i].green + style->base[i].green) / 2;
931 style->text_aa[i].blue = (style->text[i].blue + style->base[i].blue) / 2;
936 sanitize_size (GdkWindow *window,
940 gboolean set_bg = FALSE;
942 if ((*width == -1) && (*height == -1))
944 set_bg = GDK_IS_WINDOW (window);
945 gdk_window_get_size (window, width, height);
947 else if (*width == -1)
948 gdk_window_get_size (window, width, NULL);
949 else if (*height == -1)
950 gdk_window_get_size (window, NULL, height);
955 static XpThemeElement
956 map_gtk_progress_bar_to_xp(GtkProgressBar *progress_bar, gboolean trough)
959 switch (progress_bar->orientation)
961 case GTK_PROGRESS_LEFT_TO_RIGHT:
962 case GTK_PROGRESS_RIGHT_TO_LEFT:
964 ? XP_THEME_ELEMENT_PROGRESS_TROUGH_H
965 : XP_THEME_ELEMENT_PROGRESS_BAR_H;
969 ? XP_THEME_ELEMENT_PROGRESS_TROUGH_V
970 : XP_THEME_ELEMENT_PROGRESS_BAR_V;
977 draw_part (GdkDrawable *drawable,
985 gdk_gc_set_clip_rectangle (gc, area);
987 if (!parts[part].bmap)
988 parts[part].bmap = gdk_bitmap_create_from_data (drawable,
990 PART_SIZE, PART_SIZE);
992 gdk_gc_set_ts_origin (gc, x, y);
993 gdk_gc_set_stipple (gc, parts[part].bmap);
994 gdk_gc_set_fill (gc, GDK_STIPPLED);
996 gdk_draw_rectangle (drawable, gc, TRUE, x, y, PART_SIZE, PART_SIZE);
998 gdk_gc_set_fill (gc, GDK_SOLID);
1001 gdk_gc_set_clip_rectangle (gc, NULL);
1005 draw_check(GtkStyle *style,
1008 GtkShadowType shadow,
1011 const gchar *detail,
1017 x -= (1 + PART_SIZE - width) / 2;
1018 y -= (1 + PART_SIZE - height) / 2;
1020 if (detail && strcmp (detail, "check") == 0) /* Menu item */
1022 if (shadow == GTK_SHADOW_IN)
1024 draw_part (window, style->black_gc, area, x, y, CHECK_TEXT);
1025 draw_part (window, style->dark_gc[state], area, x, y, CHECK_AA);
1030 if (xp_theme_draw(window, shadow == GTK_SHADOW_IN
1031 ? XP_THEME_ELEMENT_PRESSED_CHECKBOX
1032 : XP_THEME_ELEMENT_CHECKBOX,
1033 style, x, y, width, height, state, area))
1038 draw_part (window, style->black_gc, area, x, y, CHECK_BLACK);
1039 draw_part (window, style->dark_gc[state], area, x, y, CHECK_DARK);
1040 draw_part (window, style->mid_gc[state], area, x, y, CHECK_MID);
1041 draw_part (window, style->light_gc[state], area, x, y, CHECK_LIGHT);
1042 draw_part (window, style->base_gc[state], area, x, y, CHECK_BASE);
1044 if (shadow == GTK_SHADOW_IN)
1046 draw_part (window, style->text_gc[state], area, x, y, CHECK_TEXT);
1047 draw_part (window, style->text_aa_gc[state], area, x, y, CHECK_AA);
1054 draw_expander(GtkStyle *style,
1059 const gchar *detail,
1062 GtkExpanderStyle expander_style)
1065 gint expander_semi_size;
1069 XpThemeElement xp_expander;
1071 gtk_widget_style_get (widget, "expander_size", &expander_size, NULL);
1073 switch (expander_style)
1075 case GTK_EXPANDER_COLLAPSED:
1076 case GTK_EXPANDER_SEMI_COLLAPSED:
1077 xp_expander = XP_THEME_ELEMENT_TREEVIEW_EXPANDER_CLOSED;
1080 xp_expander = XP_THEME_ELEMENT_TREEVIEW_EXPANDER_OPENED;
1084 if ((expander_size % 2) == 0)
1087 if (expander_size > 2)
1091 gdk_gc_set_clip_rectangle (style->fg_gc[state], area);
1093 expander_semi_size = expander_size / 2;
1094 x -= expander_semi_size;
1095 y -= expander_semi_size;
1097 gdk_gc_get_values (style->fg_gc[state], &values);
1099 if (! xp_theme_draw(window, xp_expander, style,
1101 expander_size, expander_size, state, area))
1103 /* RGB values to emulate Windows Classic style */
1104 color.red = color.green = color.blue = 128 << 8;
1106 success = gdk_colormap_alloc_color
1107 (gtk_widget_get_default_colormap (), &color, FALSE, TRUE);
1110 gdk_gc_set_foreground (style->fg_gc[state], &color);
1113 (window, style->fg_gc[state], FALSE, x, y,
1114 expander_size - 1, expander_size - 1);
1117 (window, style->fg_gc[state], x + 2, y + expander_semi_size,
1118 x + expander_size - 2, y + expander_semi_size);
1120 switch (expander_style)
1122 case GTK_EXPANDER_COLLAPSED:
1123 case GTK_EXPANDER_SEMI_COLLAPSED:
1125 (window, style->fg_gc[state], x + expander_semi_size, y + 2,
1126 x + expander_semi_size, y + expander_size - 2);
1131 gdk_gc_set_foreground (style->fg_gc[state], &values.foreground);
1135 gdk_gc_set_clip_rectangle (style->fg_gc[state], NULL);
1139 draw_option(GtkStyle *style,
1142 GtkShadowType shadow,
1145 const gchar *detail,
1151 x -= (1 + PART_SIZE - width) / 2;
1152 y -= (1 + PART_SIZE - height) / 2;
1154 if (detail && strcmp (detail, "option") == 0) /* Menu item */
1156 if (shadow == GTK_SHADOW_IN)
1157 draw_part (window, style->fg_gc[state], area, x, y, RADIO_TEXT);
1161 if (xp_theme_draw (window, shadow == GTK_SHADOW_IN
1162 ? XP_THEME_ELEMENT_PRESSED_RADIO_BUTTON
1163 : XP_THEME_ELEMENT_RADIO_BUTTON,
1164 style, x, y, width, height, state, area))
1169 draw_part (window, style->black_gc, area, x, y, RADIO_BLACK);
1170 draw_part (window, style->dark_gc[state], area, x, y, RADIO_DARK);
1171 draw_part (window, style->mid_gc[state], area, x, y, RADIO_MID);
1172 draw_part (window, style->light_gc[state], area, x, y, RADIO_LIGHT);
1173 draw_part (window, style->base_gc[state], area, x, y, RADIO_BASE);
1175 if (shadow == GTK_SHADOW_IN)
1176 draw_part (window, style->text_gc[state], area, x, y, RADIO_TEXT);
1182 draw_varrow (GdkWindow *window,
1184 GtkShadowType shadow_type,
1186 GtkArrowType arrow_type,
1193 gint y_start, y_increment;
1197 gdk_gc_set_clip_rectangle (gc, area);
1199 width = width + width % 2 - 1; /* Force odd */
1201 steps = 1 + width / 2;
1203 extra = height - steps;
1205 if (arrow_type == GTK_ARROW_DOWN)
1212 y_start = y + height - 1;
1217 for (i = 0; i < extra; i++)
1219 gdk_draw_line (window, gc,
1220 x, y_start + i * y_increment,
1221 x + width - 1, y_start + i * y_increment);
1224 for (i = extra; i < height; i++)
1226 gdk_draw_line (window, gc,
1227 x + (i - extra), y_start + i * y_increment,
1228 x + width - (i - extra) - 1, y_start + i * y_increment);
1233 gdk_gc_set_clip_rectangle (gc, NULL);
1237 draw_harrow (GdkWindow *window,
1239 GtkShadowType shadow_type,
1241 GtkArrowType arrow_type,
1248 gint x_start, x_increment;
1252 gdk_gc_set_clip_rectangle (gc, area);
1254 height = height + height % 2 - 1; /* Force odd */
1256 steps = 1 + height / 2;
1258 extra = width - steps;
1260 if (arrow_type == GTK_ARROW_RIGHT)
1267 x_start = x + width - 1;
1272 for (i = 0; i < extra; i++)
1274 gdk_draw_line (window, gc,
1275 x_start + i * x_increment, y,
1276 x_start + i * x_increment, y + height - 1);
1279 for (i = extra; i < width; i++)
1281 gdk_draw_line (window, gc,
1282 x_start + i * x_increment, y + (i - extra),
1283 x_start + i * x_increment, y + height - (i - extra) - 1);
1288 gdk_gc_set_clip_rectangle (gc, NULL);
1291 /* This function makes up for some brokeness in gtkrange.c
1292 * where we never get the full arrow of the stepper button
1293 * and the type of button in a single drawing function.
1295 * It doesn't work correctly when the scrollbar is squished
1296 * to the point we don't have room for full-sized steppers.
1299 reverse_engineer_stepper_box (GtkWidget *range,
1300 GtkArrowType arrow_type,
1306 gint slider_width = 14, stepper_size = 14;
1312 gtk_widget_style_get (range,
1313 "slider_width", &slider_width,
1314 "stepper_size", &stepper_size,
1318 if (arrow_type == GTK_ARROW_UP || arrow_type == GTK_ARROW_DOWN)
1320 box_width = slider_width;
1321 box_height = stepper_size;
1325 box_width = stepper_size;
1326 box_height = slider_width;
1329 *x = *x - (box_width - *width) / 2;
1330 *y = *y - (box_height - *height) / 2;
1332 *height = box_height;
1336 draw_arrow (GtkStyle *style,
1339 GtkShadowType shadow,
1342 const gchar *detail,
1343 GtkArrowType arrow_type,
1352 name = gtk_widget_get_name (widget);
1354 sanitize_size (window, &width, &height);
1356 if (detail && strcmp (detail, "spinbutton") == 0)
1358 if (xp_theme_is_drawable(XP_THEME_ELEMENT_SPIN_BUTTON_UP))
1364 x += (width - 7) / 2;
1366 if (arrow_type == GTK_ARROW_UP)
1367 y += (height - 4) / 2;
1369 y += (1 + height - 4) / 2;
1370 draw_varrow (window, style->fg_gc[state], shadow, area, arrow_type,
1374 else if (detail && (!strcmp (detail, "vscrollbar")
1375 || !strcmp (detail, "hscrollbar")))
1379 gint box_width = width;
1380 gint box_height = height;
1381 XpThemeElement xp_arrow;
1382 reverse_engineer_stepper_box (widget, arrow_type,
1383 &box_x, &box_y, &box_width, &box_height);
1388 xp_arrow = XP_THEME_ELEMENT_ARROW_UP;
1390 case GTK_ARROW_DOWN:
1391 xp_arrow = XP_THEME_ELEMENT_ARROW_DOWN;
1393 case GTK_ARROW_LEFT:
1394 xp_arrow = XP_THEME_ELEMENT_ARROW_LEFT;
1397 xp_arrow = XP_THEME_ELEMENT_ARROW_RIGHT;
1400 if (xp_theme_draw(window, xp_arrow, style, box_x, box_y, box_width, box_height, state, area))
1403 else if (arrow_type == GTK_ARROW_UP || arrow_type == GTK_ARROW_DOWN)
1405 x += (width - 7) / 2;
1406 y += (height - 5) / 2;
1408 draw_varrow (window, style->fg_gc[state], shadow, area, arrow_type,
1413 y += (height - 7) / 2;
1414 x += (width - 5) / 2;
1416 draw_harrow (window, style->fg_gc[state], shadow, area, arrow_type,
1422 /* draw the toolbar chevrons - waiting for GTK 2.4 */
1423 if (name && !strcmp (name, "gtk-toolbar-arrow"))
1425 if (xp_theme_draw(window, XP_THEME_ELEMENT_REBAR_CHEVRON, style, x, y, width, height, state, area))
1429 if (arrow_type == GTK_ARROW_UP || arrow_type == GTK_ARROW_DOWN)
1431 x += (width - 7) / 2;
1432 y += (height - 5) / 2;
1434 draw_varrow (window, style->fg_gc[state], shadow, area, arrow_type,
1439 x += (width - 5) / 2;
1440 y += (height - 7) / 2;
1442 draw_harrow (window, style->fg_gc[state], shadow, area, arrow_type,
1449 option_menu_get_props (GtkWidget *widget,
1450 GtkRequisition *indicator_size,
1451 GtkBorder *indicator_spacing)
1453 GtkRequisition *tmp_size = NULL;
1454 GtkBorder *tmp_spacing = NULL;
1457 gtk_widget_style_get (widget,
1458 "indicator_size", &tmp_size,
1459 "indicator_spacing", &tmp_spacing,
1464 *indicator_size = *tmp_size;
1468 *indicator_size = default_option_indicator_size;
1472 *indicator_spacing = *tmp_spacing;
1473 g_free (tmp_spacing);
1476 *indicator_spacing = default_option_indicator_spacing;
1480 draw_box (GtkStyle *style,
1482 GtkStateType state_type,
1483 GtkShadowType shadow_type,
1486 const gchar *detail,
1493 (!strcmp (detail, "button") ||
1494 !strcmp (detail, "buttondefault")))
1496 if (GTK_IS_TREE_VIEW (widget->parent) || GTK_IS_CLIST (widget->parent))
1498 if (xp_theme_draw(window, XP_THEME_ELEMENT_LIST_HEADER, style, x, y,
1499 width, height, state_type, area))
1502 else if (GTK_IS_TOOLBAR (widget->parent))
1504 if (xp_theme_draw(window, XP_THEME_ELEMENT_TOOLBAR_BUTTON, style, x, y,
1505 width, height, state_type, area))
1510 gboolean is_default = !strcmp (detail, "buttondefault");
1511 if (xp_theme_draw(window, is_default ? XP_THEME_ELEMENT_DEFAULT_BUTTON
1512 : XP_THEME_ELEMENT_BUTTON, style, x, y,
1513 width, height, state_type, area))
1517 else if (detail && !strcmp (detail, "spinbutton"))
1519 if (xp_theme_is_drawable(XP_THEME_ELEMENT_SPIN_BUTTON_UP))
1524 else if (detail && (!strcmp (detail, "spinbutton_up")
1525 || !strcmp (detail, "spinbutton_down")))
1527 if (xp_theme_draw(window,
1528 (! strcmp (detail, "spinbutton_up"))
1529 ? XP_THEME_ELEMENT_SPIN_BUTTON_UP
1530 : XP_THEME_ELEMENT_SPIN_BUTTON_DOWN,
1531 style, x, y, width, height, state_type, area))
1537 else if (detail && !strcmp (detail, "slider"))
1539 if (GTK_IS_SCROLLBAR(widget))
1541 GtkScrollbar * scrollbar = GTK_SCROLLBAR(widget);
1542 gboolean is_v = GTK_IS_VSCROLLBAR(widget);
1543 if (xp_theme_draw(window,
1545 ? XP_THEME_ELEMENT_SCROLLBAR_V
1546 : XP_THEME_ELEMENT_SCROLLBAR_H,
1547 style, x, y, width, height, state_type, area))
1549 XpThemeElement gripper = (is_v ? XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V : XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H);
1551 /* Do not display grippers on tiny scroll bars, the limit imposed
1552 is rather arbitrary, perhaps we can fetch the gripper geometry
1553 from somewhere and use that... */
1554 if ((gripper == XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H && width < 16)
1555 || (gripper == XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V && height < 16))
1560 xp_theme_draw(window, gripper, style, x, y, width, height, state_type, area);
1565 else if (detail && !strcmp (detail, "bar"))
1567 if (widget && GTK_IS_PROGRESS_BAR (widget))
1569 GtkProgressBar *progress_bar = GTK_PROGRESS_BAR(widget);
1570 XpThemeElement xp_progress_bar = map_gtk_progress_bar_to_xp (progress_bar, FALSE);
1571 if (xp_theme_draw (window, xp_progress_bar,
1572 style, x, y, width, height, state_type, area))
1578 else if (detail && !strcmp (detail, "handlebox_bin")) {
1579 if (xp_theme_draw (window, XP_THEME_ELEMENT_REBAR, style, x, y, width, height, state_type, area))
1584 else if (detail && strcmp (detail, "menuitem") == 0) {
1585 shadow_type = GTK_SHADOW_NONE;
1586 if (xp_theme_draw (window, XP_THEME_ELEMENT_MENU_ITEM, style, x, y, width, height, state_type, area))
1591 else if (detail && !strcmp (detail, "trough"))
1593 if (widget && GTK_IS_PROGRESS_BAR (widget))
1595 GtkProgressBar *progress_bar = GTK_PROGRESS_BAR(widget);
1596 XpThemeElement xp_progress_bar = map_gtk_progress_bar_to_xp (progress_bar, TRUE);
1597 if (xp_theme_draw (window, xp_progress_bar,
1598 style, x, y, width, height, state_type, area))
1604 /* Blank in classic Windows */
1607 else if (widget && GTK_IS_SCROLLBAR(widget))
1609 gboolean is_vertical = GTK_IS_VSCROLLBAR(widget);
1611 if (GTK_IS_RANGE(widget)
1612 && xp_theme_draw(window,
1614 ? XP_THEME_ELEMENT_TROUGH_V
1615 : XP_THEME_ELEMENT_TROUGH_H,
1617 x, y, width, height, state_type, area))
1623 GdkGCValues gc_values;
1627 sanitize_size (window, &width, &height);
1629 pixmap = gdk_pixmap_new (window, 2, 2, -1);
1631 gdk_draw_point (pixmap, style->bg_gc[GTK_STATE_NORMAL], 0, 0);
1632 gdk_draw_point (pixmap, style->bg_gc[GTK_STATE_NORMAL], 1, 1);
1633 gdk_draw_point (pixmap, style->light_gc[GTK_STATE_NORMAL], 1, 0);
1634 gdk_draw_point (pixmap, style->light_gc[GTK_STATE_NORMAL], 0, 1);
1636 gc_values.fill = GDK_TILED;
1637 gc_values.tile = pixmap;
1638 gc_values.ts_x_origin = x;
1639 gc_values.ts_y_origin = y;
1640 gc = gdk_gc_new_with_values (window, &gc_values,
1641 GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN | GDK_GC_FILL | GDK_GC_TILE);
1644 gdk_gc_set_clip_rectangle (gc, area);
1646 gdk_draw_rectangle (window, gc, TRUE, x, y, width, height);
1649 gdk_pixmap_unref (pixmap);
1654 else if (widget && GTK_IS_SCALE(widget))
1656 gboolean is_vertical = GTK_IS_VSCALE(widget);
1658 parent_class->draw_box (style, window, state_type, GTK_SHADOW_NONE, area,
1659 widget, detail, x, y, width, height);
1662 parent_class->draw_box(style, window, state_type, GTK_SHADOW_ETCHED_IN, area, NULL, NULL, (2 * x + width)/2, y, 1, height);
1664 parent_class->draw_box(style, window, state_type, GTK_SHADOW_ETCHED_IN, area, NULL, NULL, x, (2 * y + height)/2, width, 1);
1669 else if (detail && strcmp (detail, "optionmenu") == 0)
1671 if (xp_theme_draw(window, XP_THEME_ELEMENT_EDIT_TEXT,
1672 style, x, y, width, height, state_type, area))
1677 else if (detail && (strcmp (detail, "vscrollbar") == 0 || strcmp (detail, "hscrollbar") == 0))
1679 if (shadow_type == GTK_SHADOW_IN)
1680 shadow_type = GTK_SHADOW_ETCHED_IN;
1684 const gchar * name = gtk_widget_get_name (widget);
1686 if (name && !strcmp (name, "gtk-tooltips")) {
1687 if (xp_theme_draw (window, XP_THEME_ELEMENT_TOOLTIP, style, x, y, width, height, state_type, area))
1694 parent_class->draw_box (style, window, state_type, shadow_type, area,
1695 widget, detail, x, y, width, height);
1697 if (detail && strcmp (detail, "optionmenu") == 0)
1699 GtkRequisition indicator_size;
1700 GtkBorder indicator_spacing;
1703 option_menu_get_props (widget, &indicator_size, &indicator_spacing);
1705 sanitize_size (window, &width, &height);
1707 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
1708 vline_x = x + indicator_size.width + indicator_spacing.left + indicator_spacing.right;
1710 vline_x = x + width - (indicator_size.width + indicator_spacing.left + indicator_spacing.right) - style->xthickness;
1712 parent_class->draw_vline (style, window, state_type, area, widget,
1714 y + style->ythickness + 1,
1715 y + height - style->ythickness - 3,
1721 draw_tab (GtkStyle *style,
1724 GtkShadowType shadow,
1727 const gchar *detail,
1733 GtkRequisition indicator_size;
1734 GtkBorder indicator_spacing;
1738 g_return_if_fail (style != NULL);
1739 g_return_if_fail (window != NULL);
1741 if (detail && ! strcmp (detail, "optionmenutab"))
1743 if (xp_theme_draw(window, XP_THEME_ELEMENT_COMBOBUTTON,
1744 style, x-5, widget->allocation.y+1,
1745 width+10, widget->allocation.height-2, state, area))
1752 gtk_widget_style_get (widget, "indicator_size", &indicator_size, NULL);
1754 option_menu_get_props (widget, &indicator_size, &indicator_spacing);
1756 x += (width - indicator_size.width) / 2;
1757 arrow_height = (indicator_size.width + 1) / 2;
1759 y += (height - arrow_height) / 2;
1761 draw_varrow (window, style->black_gc, shadow, area, GTK_ARROW_DOWN,
1762 x, y, indicator_size.width, arrow_height);
1765 /* this is an undefined magic value that, according to the mozilla folks,
1766 worked for all the various themes that they tried */
1767 #define XP_EDGE_SIZE 2
1770 draw_extension(GtkStyle *style,
1772 GtkStateType state_type,
1773 GtkShadowType shadow_type,
1776 const gchar *detail,
1781 GtkPositionType gap_side)
1783 if (detail && !strcmp(detail, "tab"))
1785 GtkNotebook *notebook = GTK_NOTEBOOK(widget);
1786 GtkPositionType pos_type = gtk_notebook_get_tab_pos(notebook);
1788 if (pos_type == GTK_POS_TOP && state_type == GTK_STATE_NORMAL)
1789 height += XP_EDGE_SIZE;
1792 /* FIXME: pos != TOP to be implemented */
1793 else if (pos_type == GTK_POS_BOTTOM)
1795 else if (pos_type == GTK_POS_RIGHT)
1796 width += XP_EDGE_SIZE;
1797 else if (pos_type == GTK_POS_LEFT)
1798 height -= XP_EDGE_SIZE;
1801 if (pos_type == GTK_POS_TOP
1803 (window, gtk_notebook_get_current_page(notebook)==0
1804 ? XP_THEME_ELEMENT_TAB_ITEM_LEFT_EDGE
1805 : XP_THEME_ELEMENT_TAB_ITEM,
1806 style, x, y, width, height, state_type, area))
1811 parent_class->draw_extension
1812 (style, window, state_type, shadow_type, area, widget, detail,
1813 x, y, width, height, gap_side);
1817 draw_box_gap (GtkStyle *style, GdkWindow *window, GtkStateType state_type,
1818 GtkShadowType shadow_type, GdkRectangle *area,
1819 GtkWidget *widget, const gchar *detail, gint x,
1820 gint y, gint width, gint height, GtkPositionType gap_side,
1821 gint gap_x, gint gap_width)
1823 if (detail && !strcmp(detail, "notebook"))
1825 GtkNotebook *notebook = GTK_NOTEBOOK(widget);
1827 /* FIXME: pos != TOP to be implemented */
1828 if (gtk_notebook_get_tab_pos(notebook) == GTK_POS_TOP && xp_theme_draw(window, XP_THEME_ELEMENT_TAB_PANE, style, x, y, width, height,
1834 parent_class->draw_box_gap(style, window, state_type, shadow_type,
1835 area, widget, detail, x, y, width, height,
1836 gap_side, gap_x, gap_width);
1840 draw_flat_box (GtkStyle *style, GdkWindow *window,
1841 GtkStateType state_type, GtkShadowType shadow_type,
1842 GdkRectangle *area, GtkWidget *widget,
1843 const gchar *detail, gint x, gint y,
1844 gint width, gint height)
1846 if (detail && ! strcmp (detail, "checkbutton"))
1848 if (state_type == GTK_STATE_PRELIGHT)
1854 parent_class->draw_flat_box(style, window, state_type, shadow_type,
1855 area, widget, detail, x, y, width, height);
1859 draw_shadow (GtkStyle *style,
1861 GtkStateType state_type,
1862 GtkShadowType shadow_type,
1865 const gchar *detail,
1871 if(detail && ! strcmp(detail, "entry"))
1873 if (xp_theme_draw(window, XP_THEME_ELEMENT_EDIT_TEXT, style,
1874 x, y, width, height, state_type, area))
1879 parent_class->draw_shadow (style, window, state_type, shadow_type, area, widget,
1880 detail, x, y, width, height);
1884 draw_hline (GtkStyle *style,
1886 GtkStateType state_type,
1889 const gchar *detail,
1895 if (detail && !strcmp(detail, "menuitem")) {
1896 if (xp_theme_draw(window, XP_THEME_ELEMENT_MENU_SEPARATOR, style,
1897 x1, y, x2, style->ythickness, state_type, area)) {
1902 parent_class->draw_hline (style, window, state_type, area, widget,
1907 draw_vline (GtkStyle *style,
1909 GtkStateType state_type,
1912 const gchar *detail,
1917 parent_class->draw_vline (style, window, state_type, area, widget,
1922 draw_resize_grip (GtkStyle *style,
1924 GtkStateType state_type,
1927 const gchar *detail,
1934 if (detail && !strcmp(detail, "statusbar")) {
1935 if (!xp_theme_draw(window, XP_THEME_ELEMENT_STATUS_GRIPPER, style, x, y, width, height,
1940 parent_class->draw_resize_grip (style, window, state_type, area,
1941 widget, detail, edge, x, y, width, height);
1945 draw_handle (GtkStyle *style,
1947 GtkStateType state_type,
1948 GtkShadowType shadow_type,
1951 const gchar *detail,
1956 GtkOrientation orientation)
1958 if (! GTK_IS_HANDLE_BOX (widget))
1960 XpThemeElement hndl;
1962 sanitize_size (window, &width, &height);
1964 if (orientation == GTK_ORIENTATION_VERTICAL)
1965 hndl = XP_THEME_ELEMENT_REBAR_GRIPPER_V;
1967 hndl = XP_THEME_ELEMENT_REBAR_GRIPPER_H;
1969 if (xp_theme_draw (window, hndl, style, x, y, width, height,
1974 /* grippers are just flat boxes when they're not a toolbar */
1975 parent_class->draw_box (style, window, state_type, shadow_type,
1976 area, widget, detail, x, y, width, height);
1980 /* TODO: Draw handle boxes as double lines: || */
1981 parent_class->draw_handle (style, window, state_type, shadow_type,
1982 area, widget, detail, x, y, width, height,
1988 msw_style_init_from_rc (GtkStyle * style, GtkRcStyle * rc_style)
1990 setup_system_font (style);
1991 setup_menu_settings ();
1992 setup_system_styles (style);
1993 parent_class->init_from_rc(style, rc_style);
1997 msw_style_class_init (MswStyleClass *klass)
1999 GtkStyleClass *style_class = GTK_STYLE_CLASS (klass);
2001 parent_class = g_type_class_peek_parent (klass);
2003 style_class->init_from_rc = msw_style_init_from_rc;
2004 style_class->draw_arrow = draw_arrow;
2005 style_class->draw_box = draw_box;
2006 style_class->draw_check = draw_check;
2007 style_class->draw_option = draw_option;
2008 style_class->draw_tab = draw_tab;
2009 style_class->draw_flat_box = draw_flat_box;
2010 style_class->draw_expander = draw_expander;
2011 style_class->draw_extension = draw_extension;
2012 style_class->draw_box_gap = draw_box_gap;
2013 style_class->draw_shadow = draw_shadow;
2014 style_class->draw_hline = draw_hline;
2015 style_class->draw_vline = draw_vline;
2016 style_class->draw_handle = draw_handle;
2017 style_class->draw_resize_grip = draw_resize_grip;
2020 GType msw_type_style = 0;
2023 msw_style_register_type (GTypeModule *module)
2025 static const GTypeInfo object_info =
2027 sizeof (MswStyleClass),
2028 (GBaseInitFunc) NULL,
2029 (GBaseFinalizeFunc) NULL,
2030 (GClassInitFunc) msw_style_class_init,
2031 NULL, /* class_finalize */
2032 NULL, /* class_data */
2034 0, /* n_preallocs */
2035 (GInstanceInitFunc) NULL,
2038 msw_type_style = g_type_module_register_type (module,
2045 msw_style_init (void)
2048 msw_style_setup_system_settings ();
2049 setup_msw_rc_style ();