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,
523 XP_THEME_FONT_MESSAGE,
524 buf, sizeof (buf))) != NULL)
526 if (style->font_desc)
528 pango_font_description_free (style->font_desc);
530 style->font_desc = pango_font_description_from_string(font);
535 sys_color_to_gtk_color(XpThemeClass klazz, int id, GdkColor *pcolor)
539 if (!xp_theme_get_system_color (klazz, id, &color))
540 color = GetSysColor(id);
542 pcolor->pixel = color;
543 pcolor->red = (GetRValue(color) << 8) | GetRValue(color);
544 pcolor->green = (GetGValue(color) << 8) | GetGValue(color);
545 pcolor->blue = (GetBValue(color) << 8) | GetBValue(color);
549 get_system_metric(XpThemeClass klazz, int id)
553 if (!xp_theme_get_system_metric(klazz, id, &rval))
554 rval = GetSystemMetrics (id);
561 setup_default_style (void)
567 GdkColor highlighttext;
577 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNFACE, &btnface);
578 sys_color_to_gtk_color(XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT, &highlight);
579 sys_color_to_gtk_color(XP_THEME_CLASS_WINDOW, COLOR_WINDOW, &window);
580 sys_color_to_gtk_color(XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT, &windowtext);
581 sys_color_to_gtk_color(XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT, &highlighttext);
582 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_GRAYTEXT, &graytext);
583 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT, &btntext);
584 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_3DSHADOW, &dark);
585 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_3DHILIGHT, &light);
587 mid.red = (light.red + dark.red) / 2;
588 mid.green = (light.green + dark.green) / 2;
589 mid.blue = (light.blue + dark.blue) / 2;
591 text_aa[0].red = (windowtext.red + window.red) / 2;
592 text_aa[0].green = (windowtext.green + window.green) / 2;
593 text_aa[0].blue = (windowtext.blue + window.blue) / 2;
594 text_aa[1].red = (highlighttext.red + highlight.red) / 2;
595 text_aa[1].green = (highlighttext.green + highlight.green) / 2;
596 text_aa[1].blue = (highlighttext.blue + highlight.blue) / 2;
598 text_aa[2].red = (graytext.red + btnface.red) / 2;
599 text_aa[2].green = (graytext.green + btnface.green) / 2;
600 text_aa[2].blue = (graytext.blue + btnface.blue) / 2;
602 text_aa[3].red = (btntext.red + btnface.red) / 2;
603 text_aa[3].green = (btntext.green + btnface.green) / 2;
604 text_aa[3].blue = (btntext.blue + btnface.blue) / 2;
606 text_aa[4].red = (windowtext.red + window.red) / 2;
607 text_aa[4].green = (windowtext.green + window.green) / 2;
608 text_aa[4].blue = (windowtext.blue + window.blue) / 2;
610 g_snprintf(buf, sizeof (buf),
611 "style \"msw-base\" = \"msw-default\"\n"
613 "bg[NORMAL] = { %d, %d, %d }\n"
614 "bg[SELECTED] = { %d, %d, %d }\n"
615 "bg[INSENSITIVE] = { %d, %d, %d }\n"
616 "bg[ACTIVE] = { %d, %d, %d }\n"
617 "bg[PRELIGHT] = { %d, %d, %d }\n"
618 "base[NORMAL] = { %d, %d, %d }\n"
619 "base[SELECTED] = { %d, %d, %d }\n"
620 "base[INSENSITIVE] = { %d, %d, %d }\n"
621 "base[ACTIVE] = { %d, %d, %d }\n"
622 "base[PRELIGHT] = { %d, %d, %d }\n"
623 "text[NORMAL] = { %d, %d, %d }\n"
624 "text[SELECTED] = { %d, %d, %d }\n"
625 "text[INSENSITIVE] = { %d, %d, %d }\n"
626 "text[ACTIVE] = { %d, %d, %d }\n"
627 "text[PRELIGHT] = { %d, %d, %d }\n"
628 "fg[NORMAL] = { %d, %d, %d }\n"
629 "fg[SELECTED] = { %d, %d, %d }\n"
630 "fg[INSENSITIVE] = { %d, %d, %d }\n"
631 "fg[ACTIVE] = { %d, %d, %d }\n"
632 "fg[PRELIGHT] = { %d, %d, %d }\n"
633 "dark[NORMAL] = { %d, %d, %d }\n"
634 "dark[SELECTED] = { %d, %d, %d }\n"
635 "dark[INSENSITIVE] = { %d, %d, %d }\n"
636 "dark[ACTIVE] = { %d, %d, %d }\n"
637 "dark[PRELIGHT] = { %d, %d, %d }\n"
638 "light[NORMAL] = { %d, %d, %d }\n"
639 "light[SELECTED] = { %d, %d, %d }\n"
640 "light[INSENSITIVE] = { %d, %d, %d }\n"
641 "light[ACTIVE] = { %d, %d, %d }\n"
642 "light[PRELIGHT] = { %d, %d, %d }\n"
643 "text_aa[NORMAL] = { %d, %d, %d }\n"
644 "text_aa[SELECTED] = { %d, %d, %d }\n"
645 "text_aa[INSENSITIVE] = { %d, %d, %d }\n"
646 "text_aa[ACTIVE] = { %d, %d, %d }\n"
647 "text_aa[PRELIGHT] = { %d, %d, %d }\n"
648 "}widget_class \"*\" style \"msw-base\"\n",
651 btnface.red, btnface.green, btnface.blue,
652 highlight.red, highlight.green, highlight.blue,
653 btnface.red, btnface.green, btnface.blue,
654 btnface.red, btnface.green, btnface.blue,
655 btnface.red, btnface.green, btnface.blue,
658 window.red, window.green, window.blue,
659 highlight.red, highlight.green, highlight.blue,
660 btnface.red, btnface.green, btnface.blue,
661 btnface.red, btnface.green, btnface.blue,
662 window.red, window.green, window.blue,
665 windowtext.red, windowtext.green, windowtext.blue,
666 highlighttext.red, highlighttext.green, highlighttext.blue,
667 graytext.red, graytext.green, graytext.blue,
668 btntext.red, btntext.green, btntext.blue,
669 windowtext.red, windowtext.green, windowtext.blue,
672 btntext.red, btntext.green, btntext.blue,
673 highlighttext.red, highlighttext.green, highlighttext.blue,
674 graytext.red, graytext.green, graytext.blue,
675 btntext.red, btntext.green, btntext.blue,
676 windowtext.red, windowtext.green, windowtext.blue,
679 dark.red, dark.green, dark.blue,
680 dark.red, dark.green, dark.blue,
681 dark.red, dark.green, dark.blue,
682 dark.red, dark.green, dark.blue,
683 dark.red, dark.green, dark.blue,
686 light.red, light.green, light.blue,
687 light.red, light.green, light.blue,
688 light.red, light.green, light.blue,
689 light.red, light.green, light.blue,
690 light.red, light.green, light.blue,
693 text_aa[0].red, text_aa[0].green, text_aa[0].blue,
694 text_aa[1].red, text_aa[1].green, text_aa[1].blue,
695 text_aa[2].red, text_aa[2].green, text_aa[2].blue,
696 text_aa[3].red, text_aa[3].green, text_aa[3].blue,
697 text_aa[4].red, text_aa[4].green, text_aa[4].blue
699 gtk_rc_parse_string(buf);
704 setup_msw_rc_style(void)
707 "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" */
709 char buf[1024], font_buf[256], *font_ptr;
712 GdkColor menu_text_color;
713 GdkColor tooltip_back;
714 GdkColor tooltip_fore;
717 GdkColor progress_back;
719 GdkColor fg_prelight;
720 GdkColor bg_prelight;
721 GdkColor base_prelight;
722 GdkColor text_prelight;
727 sys_color_to_gtk_color(XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT, &fg_prelight);
728 sys_color_to_gtk_color(XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT, &bg_prelight);
729 sys_color_to_gtk_color(XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT, &base_prelight);
730 sys_color_to_gtk_color(XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT, &text_prelight);
732 sys_color_to_gtk_color(XP_THEME_CLASS_MENU, COLOR_MENUTEXT, &menu_text_color);
733 sys_color_to_gtk_color(XP_THEME_CLASS_MENU, COLOR_MENU, &menu_color);
736 sys_color_to_gtk_color(XP_THEME_CLASS_TOOLTIP, COLOR_INFOTEXT, &tooltip_fore);
737 sys_color_to_gtk_color(XP_THEME_CLASS_TOOLTIP, COLOR_INFOBK, &tooltip_back);
739 /* text on push buttons. TODO: button shadows, backgrounds, and highlights */
740 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT, &btn_fore);
741 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNFACE, &btn_face);
743 /* progress bar background color */
744 sys_color_to_gtk_color(XP_THEME_CLASS_PROGRESS, COLOR_HIGHLIGHT, &progress_back);
746 /* Enable coloring for menus. */
747 font_ptr = sys_font_to_pango_font (XP_THEME_CLASS_MENU, XP_THEME_FONT_MENU,font_buf, sizeof (font_buf));
748 g_snprintf(buf, sizeof (buf),
749 "style \"msw-menu\" = \"msw-default\"\n"
751 "fg[PRELIGHT] = { %d, %d, %d }\n"
752 "bg[PRELIGHT] = { %d, %d, %d }\n"
753 "text[PRELIGHT] = { %d, %d, %d }\n"
754 "base[PRELIGHT] = { %d, %d, %d }\n"
755 "fg[NORMAL] = { %d, %d, %d }\n"
756 "bg[NORMAL] = { %d, %d, %d }\n"
758 "}widget_class \"*MenuItem*\" style \"msw-menu\"\n"
759 "widget_class \"*GtkMenu\" style \"msw-menu\"\n"
760 "widget_class \"*GtkMenuShell*\" style \"msw-menu\"\n",
774 menu_text_color.green,
775 menu_text_color.blue,
779 (font_ptr ? "font_name" : "#"),
780 (font_ptr ? font_ptr : " font name should go here"));
781 gtk_rc_parse_string(buf);
783 /* Enable coloring for menu bars. */
784 font_ptr = sys_font_to_pango_font (XP_THEME_CLASS_MENU, XP_THEME_FONT_MENU,font_buf, sizeof (font_buf));
785 g_snprintf(buf, sizeof (buf),
786 "style \"msw-menu-bar\" = \"msw-menu\"\n"
788 "bg[NORMAL] = { %d, %d, %d }\n"
789 "}widget_class \"*MenuBar*\" style \"msw-menu-bar\"\n",
793 gtk_rc_parse_string(buf);
795 /* enable tooltip fonts */
796 font_ptr = sys_font_to_pango_font (XP_THEME_CLASS_STATUS, XP_THEME_FONT_STATUS,font_buf, sizeof (font_buf));
797 g_snprintf(buf, sizeof (buf),
798 "style \"msw-tooltips-caption\" = \"msw-default\"\n"
799 "{fg[NORMAL] = { %d, %d, %d }\n"
801 "}widget \"gtk-tooltips.GtkLabel\" style \"msw-tooltips-caption\"\n",
805 (font_ptr ? "font_name" : "#"),
806 (font_ptr ? font_ptr : " font name should go here"));
807 gtk_rc_parse_string(buf);
809 g_snprintf(buf, sizeof (buf),
810 "style \"msw-tooltips\" = \"msw-default\"\n"
811 "{bg[NORMAL] = { %d, %d, %d }\n"
812 "}widget \"gtk-tooltips*\" style \"msw-tooltips\"\n",
816 gtk_rc_parse_string(buf);
818 /* enable font theming for status bars */
819 font_ptr = sys_font_to_pango_font (XP_THEME_CLASS_STATUS, XP_THEME_FONT_STATUS,font_buf, sizeof (font_buf));
820 g_snprintf(buf, sizeof (buf),
821 "style \"msw-status\" = \"msw-default\"\n"
823 "bg[NORMAL] = { %d, %d, %d }\n"
824 "}widget_class \"*Status*\" style \"msw-status\"\n",
825 (font_ptr ? "font_name" : "#"),
826 (font_ptr ? font_ptr : " font name should go here"),
827 btn_face.red, btn_face.green, btn_face.blue);
828 gtk_rc_parse_string(buf);
830 /* enable coloring for text on buttons
831 TODO: use GetThemeMetric for the border and outside border */
832 g_snprintf(buf, sizeof (buf),
833 "style \"msw-button\" = \"msw-default\"\n"
835 "bg[NORMAL] = { %d, %d, %d }\n"
836 "bg[PRELIGHT] = { %d, %d, %d }\n"
837 "bg[INSENSITIVE] = { %d, %d, %d }\n"
838 "fg[PRELIGHT] = { %d, %d, %d }\n"
839 "GtkButton::default-border = { 1, 1, 1, 1 }\n"
840 "GtkButton::default-outside-border = { 0, 0, 0, 0 }\n"
841 "GtkButton::child-displacement-x = 1\n"
842 "GtkButton::child-displacement-y = 1\n"
843 "}widget_class \"*Button*\" style \"msw-button\"\n",
844 btn_face.red, btn_face.green, btn_face.blue,
845 btn_face.red, btn_face.green, btn_face.blue,
846 btn_face.red, btn_face.green, btn_face.blue,
847 btn_fore.red, btn_fore.green, btn_fore.blue
849 gtk_rc_parse_string(buf);
851 /* enable coloring for progress bars */
852 g_snprintf(buf, sizeof (buf),
853 "style \"msw-progress\" = \"msw-default\"\n"
854 "{bg[PRELIGHT] = { %d, %d, %d }\n"
855 "bg[NORMAL] = { %d, %d, %d }\n"
856 "}widget_class \"*Progress*\" style \"msw-progress\"\n",
860 btn_face.red, btn_face.green, btn_face.blue);
861 gtk_rc_parse_string(buf);
863 /* scrollbar thumb width and height */
864 g_snprintf(buf, sizeof (buf),
865 "style \"msw-vscrollbar\" = \"msw-default\"\n"
866 "{GtkRange::slider-width = %d\n"
867 "GtkRange::stepper-size = %d\n"
868 "GtkRange::stepper-spacing = 0\n"
869 "GtkRange::trough_border = 0\n"
870 "}widget_class \"*VScrollbar*\" style \"msw-vscrollbar\"\n",
871 GetSystemMetrics(SM_CYVTHUMB),
872 get_system_metric(XP_THEME_CLASS_SCROLLBAR, SM_CXVSCROLL));
873 gtk_rc_parse_string(buf);
875 g_snprintf(buf, sizeof (buf),
876 "style \"msw-hscrollbar\" = \"msw-default\"\n"
877 "{GtkRange::slider-width = %d\n"
878 "GtkRange::stepper-size = %d\n"
879 "GtkRange::stepper-spacing = 0\n"
880 "GtkRange::trough_border = 0\n"
881 "}widget_class \"*HScrollbar*\" style \"msw-hscrollbar\"\n",
882 GetSystemMetrics(SM_CXHTHUMB),
883 get_system_metric(XP_THEME_CLASS_SCROLLBAR, SM_CYHSCROLL));
884 gtk_rc_parse_string(buf);
886 /* radio/check button sizes */
887 g_snprintf(buf, sizeof (buf),
888 "style \"msw-checkbutton\" = \"msw-button\"\n"
889 "{GtkCheckButton::indicator-size = 13\n"
890 "}widget_class \"*CheckButton*\" style \"msw-checkbutton\"\n"
891 "widget_class \"*RadioButton*\" style \"msw-checkbutton\"\n");
892 gtk_rc_parse_string(buf);
896 setup_system_styles(GtkStyle *style)
900 /* Default background */
901 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNFACE, &style->bg[GTK_STATE_NORMAL]);
902 sys_color_to_gtk_color(XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT, &style->bg[GTK_STATE_SELECTED]);
903 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNFACE, &style->bg[GTK_STATE_INSENSITIVE]);
904 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNFACE, &style->bg[GTK_STATE_ACTIVE]);
905 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNFACE, &style->bg[GTK_STATE_PRELIGHT]);
908 sys_color_to_gtk_color(XP_THEME_CLASS_WINDOW, COLOR_WINDOW, &style->base[GTK_STATE_NORMAL]);
909 sys_color_to_gtk_color(XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT, &style->base[GTK_STATE_SELECTED]);
910 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNFACE, &style->base[GTK_STATE_INSENSITIVE]);
911 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNFACE, &style->base[GTK_STATE_ACTIVE]);
912 sys_color_to_gtk_color(XP_THEME_CLASS_WINDOW, COLOR_WINDOW, &style->base[GTK_STATE_PRELIGHT]);
915 sys_color_to_gtk_color(XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT, &style->text[GTK_STATE_NORMAL]);
916 sys_color_to_gtk_color(XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT, &style->text[GTK_STATE_SELECTED]);
917 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_GRAYTEXT, &style->text[GTK_STATE_INSENSITIVE]);
918 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT, &style->text[GTK_STATE_ACTIVE]);
919 sys_color_to_gtk_color(XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT, &style->text[GTK_STATE_PRELIGHT]);
921 /* Default forgeground */
922 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT, &style->fg[GTK_STATE_NORMAL]);
923 sys_color_to_gtk_color(XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT, &style->fg[GTK_STATE_SELECTED]);
924 sys_color_to_gtk_color(XP_THEME_CLASS_TEXT, COLOR_GRAYTEXT, &style->fg[GTK_STATE_INSENSITIVE]);
925 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT, &style->fg[GTK_STATE_ACTIVE]);
926 sys_color_to_gtk_color(XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT, &style->fg[GTK_STATE_PRELIGHT]);
928 for (i = 0; i < 5; i++)
930 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_3DSHADOW, &style->dark[i]);
931 sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_3DHILIGHT, &style->light[i]);
933 style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2;
934 style->mid[i].green = (style->light[i].green + style->dark[i].green) / 2;
935 style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2;
937 style->text_aa[i].red = (style->text[i].red + style->base[i].red) / 2;
938 style->text_aa[i].green = (style->text[i].green + style->base[i].green) / 2;
939 style->text_aa[i].blue = (style->text[i].blue + style->base[i].blue) / 2;
944 sanitize_size (GdkWindow *window,
948 gboolean set_bg = FALSE;
950 if ((*width == -1) && (*height == -1))
952 set_bg = GDK_IS_WINDOW (window);
953 gdk_window_get_size (window, width, height);
955 else if (*width == -1)
956 gdk_window_get_size (window, width, NULL);
957 else if (*height == -1)
958 gdk_window_get_size (window, NULL, height);
963 static XpThemeElement
964 map_gtk_progress_bar_to_xp(GtkProgressBar *progress_bar, gboolean trough)
967 switch (progress_bar->orientation)
969 case GTK_PROGRESS_LEFT_TO_RIGHT:
970 case GTK_PROGRESS_RIGHT_TO_LEFT:
972 ? XP_THEME_ELEMENT_PROGRESS_TROUGH_H
973 : XP_THEME_ELEMENT_PROGRESS_BAR_H;
977 ? XP_THEME_ELEMENT_PROGRESS_TROUGH_V
978 : XP_THEME_ELEMENT_PROGRESS_BAR_V;
985 draw_part (GdkDrawable *drawable,
993 gdk_gc_set_clip_rectangle (gc, area);
995 if (!parts[part].bmap)
996 parts[part].bmap = gdk_bitmap_create_from_data (drawable,
998 PART_SIZE, PART_SIZE);
1000 gdk_gc_set_ts_origin (gc, x, y);
1001 gdk_gc_set_stipple (gc, parts[part].bmap);
1002 gdk_gc_set_fill (gc, GDK_STIPPLED);
1004 gdk_draw_rectangle (drawable, gc, TRUE, x, y, PART_SIZE, PART_SIZE);
1006 gdk_gc_set_fill (gc, GDK_SOLID);
1009 gdk_gc_set_clip_rectangle (gc, NULL);
1013 draw_check(GtkStyle *style,
1016 GtkShadowType shadow,
1019 const gchar *detail,
1025 x -= (1 + PART_SIZE - width) / 2;
1026 y -= (1 + PART_SIZE - height) / 2;
1028 if (detail && strcmp (detail, "check") == 0) /* Menu item */
1030 if (shadow == GTK_SHADOW_IN)
1032 draw_part (window, style->black_gc, area, x, y, CHECK_TEXT);
1033 draw_part (window, style->dark_gc[state], area, x, y, CHECK_AA);
1038 if (xp_theme_draw(window, shadow == GTK_SHADOW_IN
1039 ? XP_THEME_ELEMENT_PRESSED_CHECKBOX
1040 : XP_THEME_ELEMENT_CHECKBOX,
1041 style, x, y, width, height, state, area))
1046 draw_part (window, style->black_gc, area, x, y, CHECK_BLACK);
1047 draw_part (window, style->dark_gc[state], area, x, y, CHECK_DARK);
1048 draw_part (window, style->mid_gc[state], area, x, y, CHECK_MID);
1049 draw_part (window, style->light_gc[state], area, x, y, CHECK_LIGHT);
1050 draw_part (window, style->base_gc[state], area, x, y, CHECK_BASE);
1052 if (shadow == GTK_SHADOW_IN)
1054 draw_part (window, style->text_gc[state], area, x, y, CHECK_TEXT);
1055 draw_part (window, style->text_aa_gc[state], area, x, y, CHECK_AA);
1062 draw_expander(GtkStyle *style,
1067 const gchar *detail,
1070 GtkExpanderStyle expander_style)
1073 gint expander_semi_size;
1077 XpThemeElement xp_expander;
1079 gtk_widget_style_get (widget, "expander_size", &expander_size, NULL);
1081 switch (expander_style)
1083 case GTK_EXPANDER_COLLAPSED:
1084 case GTK_EXPANDER_SEMI_COLLAPSED:
1085 xp_expander = XP_THEME_ELEMENT_TREEVIEW_EXPANDER_CLOSED;
1088 xp_expander = XP_THEME_ELEMENT_TREEVIEW_EXPANDER_OPENED;
1092 if ((expander_size % 2) == 0)
1095 if (expander_size > 2)
1099 gdk_gc_set_clip_rectangle (style->fg_gc[state], area);
1101 expander_semi_size = expander_size / 2;
1102 x -= expander_semi_size;
1103 y -= expander_semi_size;
1105 gdk_gc_get_values (style->fg_gc[state], &values);
1107 if (! xp_theme_draw(window, xp_expander, style,
1109 expander_size, expander_size, state, area))
1111 /* RGB values to emulate Windows Classic style */
1112 color.red = color.green = color.blue = 128 << 8;
1114 success = gdk_colormap_alloc_color
1115 (gtk_widget_get_default_colormap (), &color, FALSE, TRUE);
1118 gdk_gc_set_foreground (style->fg_gc[state], &color);
1121 (window, style->fg_gc[state], FALSE, x, y,
1122 expander_size - 1, expander_size - 1);
1125 (window, style->fg_gc[state], x + 2, y + expander_semi_size,
1126 x + expander_size - 2, y + expander_semi_size);
1128 switch (expander_style)
1130 case GTK_EXPANDER_COLLAPSED:
1131 case GTK_EXPANDER_SEMI_COLLAPSED:
1133 (window, style->fg_gc[state], x + expander_semi_size, y + 2,
1134 x + expander_semi_size, y + expander_size - 2);
1139 gdk_gc_set_foreground (style->fg_gc[state], &values.foreground);
1143 gdk_gc_set_clip_rectangle (style->fg_gc[state], NULL);
1147 draw_option(GtkStyle *style,
1150 GtkShadowType shadow,
1153 const gchar *detail,
1159 x -= (1 + PART_SIZE - width) / 2;
1160 y -= (1 + PART_SIZE - height) / 2;
1162 if (detail && strcmp (detail, "option") == 0) /* Menu item */
1164 if (shadow == GTK_SHADOW_IN)
1165 draw_part (window, style->fg_gc[state], area, x, y, RADIO_TEXT);
1169 if (xp_theme_draw (window, shadow == GTK_SHADOW_IN
1170 ? XP_THEME_ELEMENT_PRESSED_RADIO_BUTTON
1171 : XP_THEME_ELEMENT_RADIO_BUTTON,
1172 style, x, y, width, height, state, area))
1177 draw_part (window, style->black_gc, area, x, y, RADIO_BLACK);
1178 draw_part (window, style->dark_gc[state], area, x, y, RADIO_DARK);
1179 draw_part (window, style->mid_gc[state], area, x, y, RADIO_MID);
1180 draw_part (window, style->light_gc[state], area, x, y, RADIO_LIGHT);
1181 draw_part (window, style->base_gc[state], area, x, y, RADIO_BASE);
1183 if (shadow == GTK_SHADOW_IN)
1184 draw_part (window, style->text_gc[state], area, x, y, RADIO_TEXT);
1190 draw_varrow (GdkWindow *window,
1192 GtkShadowType shadow_type,
1194 GtkArrowType arrow_type,
1201 gint y_start, y_increment;
1205 gdk_gc_set_clip_rectangle (gc, area);
1207 width = width + width % 2 - 1; /* Force odd */
1209 steps = 1 + width / 2;
1211 extra = height - steps;
1213 if (arrow_type == GTK_ARROW_DOWN)
1220 y_start = y + height - 1;
1225 for (i = 0; i < extra; i++)
1227 gdk_draw_line (window, gc,
1228 x, y_start + i * y_increment,
1229 x + width - 1, y_start + i * y_increment);
1232 for (i = extra; i < height; i++)
1234 gdk_draw_line (window, gc,
1235 x + (i - extra), y_start + i * y_increment,
1236 x + width - (i - extra) - 1, y_start + i * y_increment);
1241 gdk_gc_set_clip_rectangle (gc, NULL);
1245 draw_harrow (GdkWindow *window,
1247 GtkShadowType shadow_type,
1249 GtkArrowType arrow_type,
1256 gint x_start, x_increment;
1260 gdk_gc_set_clip_rectangle (gc, area);
1262 height = height + height % 2 - 1; /* Force odd */
1264 steps = 1 + height / 2;
1266 extra = width - steps;
1268 if (arrow_type == GTK_ARROW_RIGHT)
1275 x_start = x + width - 1;
1280 for (i = 0; i < extra; i++)
1282 gdk_draw_line (window, gc,
1283 x_start + i * x_increment, y,
1284 x_start + i * x_increment, y + height - 1);
1287 for (i = extra; i < width; i++)
1289 gdk_draw_line (window, gc,
1290 x_start + i * x_increment, y + (i - extra),
1291 x_start + i * x_increment, y + height - (i - extra) - 1);
1296 gdk_gc_set_clip_rectangle (gc, NULL);
1299 /* This function makes up for some brokeness in gtkrange.c
1300 * where we never get the full arrow of the stepper button
1301 * and the type of button in a single drawing function.
1303 * It doesn't work correctly when the scrollbar is squished
1304 * to the point we don't have room for full-sized steppers.
1307 reverse_engineer_stepper_box (GtkWidget *range,
1308 GtkArrowType arrow_type,
1314 gint slider_width = 14, stepper_size = 14;
1320 gtk_widget_style_get (range,
1321 "slider_width", &slider_width,
1322 "stepper_size", &stepper_size,
1326 if (arrow_type == GTK_ARROW_UP || arrow_type == GTK_ARROW_DOWN)
1328 box_width = slider_width;
1329 box_height = stepper_size;
1333 box_width = stepper_size;
1334 box_height = slider_width;
1337 *x = *x - (box_width - *width) / 2;
1338 *y = *y - (box_height - *height) / 2;
1340 *height = box_height;
1344 draw_arrow (GtkStyle *style,
1347 GtkShadowType shadow,
1350 const gchar *detail,
1351 GtkArrowType arrow_type,
1360 name = gtk_widget_get_name (widget);
1362 sanitize_size (window, &width, &height);
1364 if (detail && strcmp (detail, "spinbutton") == 0)
1366 if (xp_theme_is_drawable(XP_THEME_ELEMENT_SPIN_BUTTON_UP))
1372 x += (width - 7) / 2;
1374 if (arrow_type == GTK_ARROW_UP)
1375 y += (height - 4) / 2;
1377 y += (1 + height - 4) / 2;
1378 draw_varrow (window, style->fg_gc[state], shadow, area, arrow_type,
1382 else if (detail && (!strcmp (detail, "vscrollbar")
1383 || !strcmp (detail, "hscrollbar")))
1387 gint box_width = width;
1388 gint box_height = height;
1389 XpThemeElement xp_arrow;
1390 reverse_engineer_stepper_box (widget, arrow_type,
1391 &box_x, &box_y, &box_width, &box_height);
1396 xp_arrow = XP_THEME_ELEMENT_ARROW_UP;
1398 case GTK_ARROW_DOWN:
1399 xp_arrow = XP_THEME_ELEMENT_ARROW_DOWN;
1401 case GTK_ARROW_LEFT:
1402 xp_arrow = XP_THEME_ELEMENT_ARROW_LEFT;
1405 xp_arrow = XP_THEME_ELEMENT_ARROW_RIGHT;
1408 if (xp_theme_draw(window, xp_arrow, style, box_x, box_y, box_width, box_height, state, area))
1411 else if (arrow_type == GTK_ARROW_UP || arrow_type == GTK_ARROW_DOWN)
1413 x += (width - 7) / 2;
1414 y += (height - 5) / 2;
1416 draw_varrow (window, style->fg_gc[state], shadow, area, arrow_type,
1421 y += (height - 7) / 2;
1422 x += (width - 5) / 2;
1424 draw_harrow (window, style->fg_gc[state], shadow, area, arrow_type,
1430 /* draw the toolbar chevrons - waiting for GTK 2.4 */
1431 if (name && !strcmp (name, "gtk-toolbar-arrow"))
1433 if (xp_theme_draw(window, XP_THEME_ELEMENT_REBAR_CHEVRON, style, x, y, width, height, state, area))
1437 if (arrow_type == GTK_ARROW_UP || arrow_type == GTK_ARROW_DOWN)
1439 x += (width - 7) / 2;
1440 y += (height - 5) / 2;
1442 draw_varrow (window, style->fg_gc[state], shadow, area, arrow_type,
1447 x += (width - 5) / 2;
1448 y += (height - 7) / 2;
1450 draw_harrow (window, style->fg_gc[state], shadow, area, arrow_type,
1457 option_menu_get_props (GtkWidget *widget,
1458 GtkRequisition *indicator_size,
1459 GtkBorder *indicator_spacing)
1461 GtkRequisition *tmp_size = NULL;
1462 GtkBorder *tmp_spacing = NULL;
1465 gtk_widget_style_get (widget,
1466 "indicator_size", &tmp_size,
1467 "indicator_spacing", &tmp_spacing,
1472 *indicator_size = *tmp_size;
1476 *indicator_size = default_option_indicator_size;
1480 *indicator_spacing = *tmp_spacing;
1481 g_free (tmp_spacing);
1484 *indicator_spacing = default_option_indicator_spacing;
1487 static gboolean is_toolbar_child(GtkWidget * wid)
1491 if(GTK_IS_TOOLBAR(wid))
1501 draw_box (GtkStyle *style,
1503 GtkStateType state_type,
1504 GtkShadowType shadow_type,
1507 const gchar *detail,
1514 (!strcmp (detail, "button") ||
1515 !strcmp (detail, "buttondefault")))
1517 if (GTK_IS_TREE_VIEW (widget->parent) || GTK_IS_CLIST (widget->parent))
1519 if (xp_theme_draw(window, XP_THEME_ELEMENT_LIST_HEADER, style, x, y,
1520 width, height, state_type, area))
1523 else if (is_toolbar_child (widget->parent))
1525 if (xp_theme_draw(window, XP_THEME_ELEMENT_TOOLBAR_BUTTON, style, x, y,
1526 width, height, state_type, area))
1531 gboolean is_default = !strcmp (detail, "buttondefault");
1532 if (xp_theme_draw(window, is_default ? XP_THEME_ELEMENT_DEFAULT_BUTTON
1533 : XP_THEME_ELEMENT_BUTTON, style, x, y,
1534 width, height, state_type, area))
1538 else if (detail && !strcmp (detail, "spinbutton"))
1540 if (xp_theme_is_drawable(XP_THEME_ELEMENT_SPIN_BUTTON_UP))
1545 else if (detail && (!strcmp (detail, "spinbutton_up")
1546 || !strcmp (detail, "spinbutton_down")))
1548 if (xp_theme_draw(window,
1549 (! strcmp (detail, "spinbutton_up"))
1550 ? XP_THEME_ELEMENT_SPIN_BUTTON_UP
1551 : XP_THEME_ELEMENT_SPIN_BUTTON_DOWN,
1552 style, x, y, width, height, state_type, area))
1558 else if (detail && !strcmp (detail, "slider"))
1560 if (GTK_IS_SCROLLBAR(widget))
1562 GtkScrollbar * scrollbar = GTK_SCROLLBAR(widget);
1563 gboolean is_v = GTK_IS_VSCROLLBAR(widget);
1564 if (xp_theme_draw(window,
1566 ? XP_THEME_ELEMENT_SCROLLBAR_V
1567 : XP_THEME_ELEMENT_SCROLLBAR_H,
1568 style, x, y, width, height, state_type, area))
1570 XpThemeElement gripper = (is_v ? XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V : XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H);
1572 /* Do not display grippers on tiny scroll bars, the limit imposed
1573 is rather arbitrary, perhaps we can fetch the gripper geometry
1574 from somewhere and use that... */
1575 if ((gripper == XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H && width < 16)
1576 || (gripper == XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V && height < 16))
1581 xp_theme_draw(window, gripper, style, x, y, width, height, state_type, area);
1586 else if (detail && !strcmp (detail, "bar"))
1588 if (widget && GTK_IS_PROGRESS_BAR (widget))
1590 GtkProgressBar *progress_bar = GTK_PROGRESS_BAR(widget);
1591 XpThemeElement xp_progress_bar = map_gtk_progress_bar_to_xp (progress_bar, FALSE);
1592 if (xp_theme_draw (window, xp_progress_bar,
1593 style, x, y, width, height, state_type, area))
1599 else if (detail && !strcmp (detail, "handlebox_bin")) {
1600 if (xp_theme_draw (window, XP_THEME_ELEMENT_REBAR, style, x, y, width, height, state_type, area))
1605 else if (detail && strcmp (detail, "menuitem") == 0) {
1606 shadow_type = GTK_SHADOW_NONE;
1607 if (xp_theme_draw (window, XP_THEME_ELEMENT_MENU_ITEM, style, x, y, width, height, state_type, area))
1612 else if (detail && !strcmp (detail, "trough"))
1614 if (widget && GTK_IS_PROGRESS_BAR (widget))
1616 GtkProgressBar *progress_bar = GTK_PROGRESS_BAR(widget);
1617 XpThemeElement xp_progress_bar = map_gtk_progress_bar_to_xp (progress_bar, TRUE);
1618 if (xp_theme_draw (window, xp_progress_bar,
1619 style, x, y, width, height, state_type, area))
1625 /* Blank in classic Windows */
1628 else if (widget && GTK_IS_SCROLLBAR(widget))
1630 gboolean is_vertical = GTK_IS_VSCROLLBAR(widget);
1632 if (GTK_IS_RANGE(widget)
1633 && xp_theme_draw(window,
1635 ? XP_THEME_ELEMENT_TROUGH_V
1636 : XP_THEME_ELEMENT_TROUGH_H,
1638 x, y, width, height, state_type, area))
1644 GdkGCValues gc_values;
1648 sanitize_size (window, &width, &height);
1650 pixmap = gdk_pixmap_new (window, 2, 2, -1);
1652 gdk_draw_point (pixmap, style->bg_gc[GTK_STATE_NORMAL], 0, 0);
1653 gdk_draw_point (pixmap, style->bg_gc[GTK_STATE_NORMAL], 1, 1);
1654 gdk_draw_point (pixmap, style->light_gc[GTK_STATE_NORMAL], 1, 0);
1655 gdk_draw_point (pixmap, style->light_gc[GTK_STATE_NORMAL], 0, 1);
1657 gc_values.fill = GDK_TILED;
1658 gc_values.tile = pixmap;
1659 gc_values.ts_x_origin = x;
1660 gc_values.ts_y_origin = y;
1661 gc = gdk_gc_new_with_values (window, &gc_values,
1662 GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN | GDK_GC_FILL | GDK_GC_TILE);
1665 gdk_gc_set_clip_rectangle (gc, area);
1667 gdk_draw_rectangle (window, gc, TRUE, x, y, width, height);
1670 gdk_pixmap_unref (pixmap);
1675 else if (widget && GTK_IS_SCALE(widget))
1677 gboolean is_vertical = GTK_IS_VSCALE(widget);
1679 parent_class->draw_box (style, window, state_type, GTK_SHADOW_NONE, area,
1680 widget, detail, x, y, width, height);
1683 parent_class->draw_box(style, window, state_type, GTK_SHADOW_ETCHED_IN, area, NULL, NULL, (2 * x + width)/2, y, 1, height);
1685 parent_class->draw_box(style, window, state_type, GTK_SHADOW_ETCHED_IN, area, NULL, NULL, x, (2 * y + height)/2, width, 1);
1690 else if (detail && strcmp (detail, "optionmenu") == 0)
1692 if (xp_theme_draw(window, XP_THEME_ELEMENT_EDIT_TEXT,
1693 style, x, y, width, height, state_type, area))
1698 else if (detail && (strcmp (detail, "vscrollbar") == 0 || strcmp (detail, "hscrollbar") == 0))
1700 if (shadow_type == GTK_SHADOW_IN)
1701 shadow_type = GTK_SHADOW_ETCHED_IN;
1705 const gchar * name = gtk_widget_get_name (widget);
1707 if (name && !strcmp (name, "gtk-tooltips")) {
1708 if (xp_theme_draw (window, XP_THEME_ELEMENT_TOOLTIP, style, x, y, width, height, state_type, area))
1715 parent_class->draw_box (style, window, state_type, shadow_type, area,
1716 widget, detail, x, y, width, height);
1718 if (detail && strcmp (detail, "optionmenu") == 0)
1720 GtkRequisition indicator_size;
1721 GtkBorder indicator_spacing;
1724 option_menu_get_props (widget, &indicator_size, &indicator_spacing);
1726 sanitize_size (window, &width, &height);
1728 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
1729 vline_x = x + indicator_size.width + indicator_spacing.left + indicator_spacing.right;
1731 vline_x = x + width - (indicator_size.width + indicator_spacing.left + indicator_spacing.right) - style->xthickness;
1733 parent_class->draw_vline (style, window, state_type, area, widget,
1735 y + style->ythickness + 1,
1736 y + height - style->ythickness - 3,
1742 draw_tab (GtkStyle *style,
1745 GtkShadowType shadow,
1748 const gchar *detail,
1754 GtkRequisition indicator_size;
1755 GtkBorder indicator_spacing;
1759 g_return_if_fail (style != NULL);
1760 g_return_if_fail (window != NULL);
1762 if (detail && ! strcmp (detail, "optionmenutab"))
1764 if (xp_theme_draw(window, XP_THEME_ELEMENT_COMBOBUTTON,
1765 style, x-5, widget->allocation.y+1,
1766 width+10, widget->allocation.height-2, state, area))
1773 gtk_widget_style_get (widget, "indicator_size", &indicator_size, NULL);
1775 option_menu_get_props (widget, &indicator_size, &indicator_spacing);
1777 x += (width - indicator_size.width) / 2;
1778 arrow_height = (indicator_size.width + 1) / 2;
1780 y += (height - arrow_height) / 2;
1782 draw_varrow (window, style->black_gc, shadow, area, GTK_ARROW_DOWN,
1783 x, y, indicator_size.width, arrow_height);
1786 /* this is an undefined magic value that, according to the mozilla folks,
1787 worked for all the various themes that they tried */
1788 #define XP_EDGE_SIZE 2
1791 draw_extension(GtkStyle *style,
1793 GtkStateType state_type,
1794 GtkShadowType shadow_type,
1797 const gchar *detail,
1802 GtkPositionType gap_side)
1804 if (detail && !strcmp(detail, "tab"))
1806 GtkNotebook *notebook = GTK_NOTEBOOK(widget);
1807 GtkPositionType pos_type = gtk_notebook_get_tab_pos(notebook);
1809 if (pos_type == GTK_POS_TOP && state_type == GTK_STATE_NORMAL)
1810 height += XP_EDGE_SIZE;
1813 /* FIXME: pos != TOP to be implemented */
1814 else if (pos_type == GTK_POS_BOTTOM)
1816 else if (pos_type == GTK_POS_RIGHT)
1817 width += XP_EDGE_SIZE;
1818 else if (pos_type == GTK_POS_LEFT)
1819 height -= XP_EDGE_SIZE;
1822 if (pos_type == GTK_POS_TOP
1824 (window, gtk_notebook_get_current_page(notebook)==0
1825 ? XP_THEME_ELEMENT_TAB_ITEM_LEFT_EDGE
1826 : XP_THEME_ELEMENT_TAB_ITEM,
1827 style, x, y, width, height, state_type, area))
1832 parent_class->draw_extension
1833 (style, window, state_type, shadow_type, area, widget, detail,
1834 x, y, width, height, gap_side);
1838 draw_box_gap (GtkStyle *style, GdkWindow *window, GtkStateType state_type,
1839 GtkShadowType shadow_type, GdkRectangle *area,
1840 GtkWidget *widget, const gchar *detail, gint x,
1841 gint y, gint width, gint height, GtkPositionType gap_side,
1842 gint gap_x, gint gap_width)
1844 if (detail && !strcmp(detail, "notebook"))
1846 GtkNotebook *notebook = GTK_NOTEBOOK(widget);
1848 /* FIXME: pos != TOP to be implemented */
1849 if (gtk_notebook_get_tab_pos(notebook) == GTK_POS_TOP && xp_theme_draw(window, XP_THEME_ELEMENT_TAB_PANE, style, x, y, width, height,
1855 parent_class->draw_box_gap(style, window, state_type, shadow_type,
1856 area, widget, detail, x, y, width, height,
1857 gap_side, gap_x, gap_width);
1861 draw_flat_box (GtkStyle *style, GdkWindow *window,
1862 GtkStateType state_type, GtkShadowType shadow_type,
1863 GdkRectangle *area, GtkWidget *widget,
1864 const gchar *detail, gint x, gint y,
1865 gint width, gint height)
1867 if (detail && ! strcmp (detail, "checkbutton"))
1869 if (state_type == GTK_STATE_PRELIGHT)
1875 parent_class->draw_flat_box(style, window, state_type, shadow_type,
1876 area, widget, detail, x, y, width, height);
1880 draw_shadow (GtkStyle *style,
1882 GtkStateType state_type,
1883 GtkShadowType shadow_type,
1886 const gchar *detail,
1892 if(detail && ! strcmp(detail, "entry"))
1894 if (xp_theme_draw(window, XP_THEME_ELEMENT_EDIT_TEXT, style,
1895 x, y, width, height, state_type, area))
1900 parent_class->draw_shadow (style, window, state_type, shadow_type, area, widget,
1901 detail, x, y, width, height);
1905 draw_hline (GtkStyle *style,
1907 GtkStateType state_type,
1910 const gchar *detail,
1916 if (detail && !strcmp(detail, "menuitem")) {
1917 if (xp_theme_draw(window, XP_THEME_ELEMENT_MENU_SEPARATOR, style,
1918 x1, y, x2, style->ythickness, state_type, area)) {
1923 parent_class->draw_hline (style, window, state_type, area, widget,
1928 draw_vline (GtkStyle *style,
1930 GtkStateType state_type,
1933 const gchar *detail,
1938 parent_class->draw_vline (style, window, state_type, area, widget,
1943 draw_resize_grip (GtkStyle *style,
1945 GtkStateType state_type,
1948 const gchar *detail,
1955 if (detail && !strcmp(detail, "statusbar")) {
1956 if (!xp_theme_draw(window, XP_THEME_ELEMENT_STATUS_GRIPPER, style, x, y, width, height,
1961 parent_class->draw_resize_grip (style, window, state_type, area,
1962 widget, detail, edge, x, y, width, height);
1966 draw_handle (GtkStyle *style,
1968 GtkStateType state_type,
1969 GtkShadowType shadow_type,
1972 const gchar *detail,
1977 GtkOrientation orientation)
1979 if (! GTK_IS_HANDLE_BOX (widget))
1981 XpThemeElement hndl;
1983 sanitize_size (window, &width, &height);
1985 if (orientation == GTK_ORIENTATION_VERTICAL)
1986 hndl = XP_THEME_ELEMENT_REBAR_GRIPPER_V;
1988 hndl = XP_THEME_ELEMENT_REBAR_GRIPPER_H;
1990 if (xp_theme_draw (window, hndl, style, x, y, width, height,
1995 /* grippers are just flat boxes when they're not a toolbar */
1996 parent_class->draw_box (style, window, state_type, shadow_type,
1997 area, widget, detail, x, y, width, height);
2001 /* TODO: Draw handle boxes as double lines: || */
2002 parent_class->draw_handle (style, window, state_type, shadow_type,
2003 area, widget, detail, x, y, width, height,
2009 msw_style_init_from_rc (GtkStyle * style, GtkRcStyle * rc_style)
2011 setup_system_font (style);
2012 setup_menu_settings ();
2013 setup_system_styles (style);
2014 parent_class->init_from_rc(style, rc_style);
2018 msw_style_class_init (MswStyleClass *klass)
2020 GtkStyleClass *style_class = GTK_STYLE_CLASS (klass);
2022 parent_class = g_type_class_peek_parent (klass);
2024 style_class->init_from_rc = msw_style_init_from_rc;
2025 style_class->draw_arrow = draw_arrow;
2026 style_class->draw_box = draw_box;
2027 style_class->draw_check = draw_check;
2028 style_class->draw_option = draw_option;
2029 style_class->draw_tab = draw_tab;
2030 style_class->draw_flat_box = draw_flat_box;
2031 style_class->draw_expander = draw_expander;
2032 style_class->draw_extension = draw_extension;
2033 style_class->draw_box_gap = draw_box_gap;
2034 style_class->draw_shadow = draw_shadow;
2035 style_class->draw_hline = draw_hline;
2036 style_class->draw_vline = draw_vline;
2037 style_class->draw_handle = draw_handle;
2038 style_class->draw_resize_grip = draw_resize_grip;
2041 GType msw_type_style = 0;
2044 msw_style_register_type (GTypeModule *module)
2046 static const GTypeInfo object_info =
2048 sizeof (MswStyleClass),
2049 (GBaseInitFunc) NULL,
2050 (GBaseFinalizeFunc) NULL,
2051 (GClassInitFunc) msw_style_class_init,
2052 NULL, /* class_finalize */
2053 NULL, /* class_data */
2055 0, /* n_preallocs */
2056 (GInstanceInitFunc) NULL,
2059 msw_type_style = g_type_module_register_type (module,
2066 msw_style_init (void)
2069 msw_style_setup_system_settings ();
2070 setup_msw_rc_style ();