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.
26 * http://lxr.mozilla.org/mozilla/source/gfx/src/windows/nsNativeThemeWin.cpp
27 * http://lxr.mozilla.org/seamonkey/source/widget/src/windows/nsLookAndFeel.cpp
28 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/userex/functions/drawthemebackground.asp
31 #include "msw_style.h"
41 /* #include <gdk/gdkwin32.h> */
43 #include "gdk/win32/gdkwin32.h"
46 /* Default values, not normally used
48 static const GtkRequisition default_option_indicator_size = { 9, 8 };
49 static const GtkBorder default_option_indicator_spacing = { 7, 5, 2, 2 };
51 static GtkStyleClass *parent_class;
72 static const guint8 check_aa_bits[] = {
73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
77 static const guint8 check_base_bits[] = {
78 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xfc, 0x07, 0xfc, 0x07, 0xfc, 0x07,
80 0x07, 0xfc, 0x07, 0xfc, 0x07, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00
82 static const guint8 check_black_bits[] = {
83 0x00, 0x00, 0xfe, 0x0f, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00,
85 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00
87 static const guint8 check_dark_bits[] = {
88 0xff, 0x1f, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
90 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00
92 static const guint8 check_light_bits[] = {
93 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10,
95 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0xfe, 0x1f
97 static const guint8 check_mid_bits[] = {
98 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08,
100 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0xfc, 0x0f, 0x00, 0x00
102 static const guint8 check_text_bits[] = {
103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x88, 0x03,
105 0x00, 0x70, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
107 static const guint8 radio_base_bits[] = {
108 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0xf8, 0x03, 0xfc, 0x07, 0xfc, 0x07,
110 0x07, 0xfc, 0x07, 0xf8, 0x03, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00
112 static const guint8 radio_black_bits[] = {
113 0x00, 0x00, 0xf0, 0x01, 0x0c, 0x02, 0x04, 0x00, 0x02, 0x00, 0x02, 0x00,
115 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
117 static const guint8 radio_dark_bits[] = {
118 0xf0, 0x01, 0x0c, 0x06, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00,
120 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
122 static const guint8 radio_light_bits[] = {
123 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x10, 0x00, 0x10,
125 0x10, 0x00, 0x10, 0x00, 0x08, 0x00, 0x08, 0x0c, 0x06, 0xf0, 0x01
127 static const guint8 radio_mid_bits[] = {
128 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08,
130 0x08, 0x00, 0x08, 0x00, 0x04, 0x0c, 0x06, 0xf0, 0x01, 0x00, 0x00
132 static const guint8 radio_text_bits[] = {
133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xf0, 0x01,
135 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
144 {check_aa_bits, NULL},
145 {check_base_bits, NULL},
146 {check_black_bits, NULL},
147 {check_dark_bits, NULL},
148 {check_light_bits, NULL},
149 {check_mid_bits, NULL},
150 {check_text_bits, NULL},
151 {radio_base_bits, NULL},
152 {radio_black_bits, NULL},
153 {radio_dark_bits, NULL},
154 {radio_light_bits, NULL},
155 {radio_mid_bits, NULL},
156 {radio_text_bits, NULL}
160 get_system_font (XpThemeClass klazz, XpThemeFont type, LOGFONT * out_lf)
163 /* TODO: this causes crashes later because the font name is in UCS2, and
164 the pango fns don't deal with that gracefully */
165 if (xp_theme_get_system_font (klazz, type, out_lf))
170 NONCLIENTMETRICS ncm;
172 ncm.cbSize = sizeof (NONCLIENTMETRICS);
174 if (SystemParametersInfo (SPI_GETNONCLIENTMETRICS,
175 sizeof (NONCLIENTMETRICS), &ncm, 0))
177 if (type == XP_THEME_FONT_CAPTION)
178 *out_lf = ncm.lfCaptionFont;
179 else if (type == XP_THEME_FONT_MENU)
180 *out_lf = ncm.lfMenuFont;
181 else if (type == XP_THEME_FONT_STATUS)
182 *out_lf = ncm.lfStatusFont;
184 *out_lf = ncm.lfMessageFont;
192 /***************************** BEGIN STOLEN FROM PANGO *****************************/
195 This code is stolen from Pango 1.4. It attempts to address the following problems:
197 http://bugzilla.gnome.org/show_bug.cgi?id=135098
198 http://sourceforge.net/tracker/index.php?func=detail&aid=895762&group_id=76416&atid=547655
200 As Owen suggested in bug 135098, once Pango 1.6 is released, we need to get rid of this code.
203 #define PING(printlist)
205 /* TrueType defines: */
207 #define MAKE_TT_TABLE_NAME(c1, c2, c3, c4) \
208 (((guint32)c4) << 24 | ((guint32)c3) << 16 | ((guint32)c2) << 8 | ((guint32)c1))
210 #define CMAP (MAKE_TT_TABLE_NAME('c','m','a','p'))
211 #define CMAP_HEADER_SIZE 4
213 #define NAME (MAKE_TT_TABLE_NAME('n','a','m','e'))
214 #define NAME_HEADER_SIZE 6
216 #define ENCODING_TABLE_SIZE 8
218 #define APPLE_UNICODE_PLATFORM_ID 0
219 #define MACINTOSH_PLATFORM_ID 1
220 #define ISO_PLATFORM_ID 2
221 #define MICROSOFT_PLATFORM_ID 3
223 #define SYMBOL_ENCODING_ID 0
224 #define UNICODE_ENCODING_ID 1
225 #define UCS4_ENCODING_ID 10
229 guint16 format_selector;
231 guint16 string_storage_offset;
240 guint16 string_length;
241 guint16 string_offset;
245 pango_win32_get_name_header (HDC hdc, struct name_header *header)
247 if (GetFontData (hdc, NAME, 0, header, sizeof (*header)) !=
251 header->num_records = GUINT16_FROM_BE (header->num_records);
252 header->string_storage_offset =
253 GUINT16_FROM_BE (header->string_storage_offset);
259 pango_win32_get_name_record (HDC hdc, gint i, struct name_record *record)
261 if (GetFontData (hdc, NAME, 6 + i * sizeof (*record),
262 record, sizeof (*record)) != sizeof (*record))
265 record->platform_id = GUINT16_FROM_BE (record->platform_id);
266 record->encoding_id = GUINT16_FROM_BE (record->encoding_id);
267 record->language_id = GUINT16_FROM_BE (record->language_id);
268 record->name_id = GUINT16_FROM_BE (record->name_id);
269 record->string_length = GUINT16_FROM_BE (record->string_length);
270 record->string_offset = GUINT16_FROM_BE (record->string_offset);
276 get_family_name (LOGFONT * lfp, HDC pango_win32_hdc)
281 struct name_header header;
282 struct name_record record;
284 gint unicode_ix = -1, mac_ix = -1, microsoft_ix = -1;
288 gchar *string = NULL;
293 /* If lfFaceName is ASCII, assume it is the common (English) name for the
294 font. Is this valid? Do some TrueType fonts have different names in
295 French, German, etc, and does the system return these if the locale is
296 set to use French, German, etc? */
297 l = strlen (lfp->lfFaceName);
298 for (i = 0; i < l; i++)
299 if (lfp->lfFaceName[i] < ' ' || lfp->lfFaceName[i] > '~')
303 return g_strdup (lfp->lfFaceName);
305 if ((hfont = CreateFontIndirect (lfp)) == NULL)
308 if ((oldhfont = (HFONT) SelectObject (pango_win32_hdc, hfont)) == NULL)
311 if (!pango_win32_get_name_header (pango_win32_hdc, &header))
314 PING (("%d name records", header.num_records));
316 for (i = 0; i < header.num_records; i++)
318 if (!pango_win32_get_name_record (pango_win32_hdc, i, &record))
321 if ((record.name_id != 1 && record.name_id != 16)
322 || record.string_length <= 0)
325 PING (("platform:%d encoding:%d language:%04x name_id:%d",
326 record.platform_id, record.encoding_id, record.language_id,
329 if (record.platform_id == APPLE_UNICODE_PLATFORM_ID ||
330 record.platform_id == ISO_PLATFORM_ID)
332 else if (record.platform_id == MACINTOSH_PLATFORM_ID && record.encoding_id == 0 && /* Roman
334 record.language_id == 0) /* English */
336 else if (record.platform_id == MICROSOFT_PLATFORM_ID)
337 if ((microsoft_ix == -1 ||
338 PRIMARYLANGID (record.language_id) == LANG_ENGLISH) &&
339 (record.encoding_id == SYMBOL_ENCODING_ID ||
340 record.encoding_id == UNICODE_ENCODING_ID ||
341 record.encoding_id == UCS4_ENCODING_ID))
345 if (microsoft_ix >= 0)
346 name_ix = microsoft_ix;
347 else if (mac_ix >= 0)
349 else if (unicode_ix >= 0)
350 name_ix = unicode_ix;
354 if (!pango_win32_get_name_record (pango_win32_hdc, name_ix, &record))
357 string = g_malloc (record.string_length + 1);
358 if (GetFontData (pango_win32_hdc, NAME,
359 header.string_storage_offset + record.string_offset,
360 string, record.string_length) != record.string_length)
363 string[record.string_length] = '\0';
365 if (name_ix == microsoft_ix)
366 if (record.encoding_id == SYMBOL_ENCODING_ID ||
367 record.encoding_id == UNICODE_ENCODING_ID)
368 codeset = "UTF-16BE";
371 else if (name_ix == mac_ix)
372 codeset = "MacRoman";
373 else /* name_ix == unicode_ix */
377 g_convert (string, record.string_length, "UTF-8", codeset, NULL,
385 SelectObject (pango_win32_hdc, oldhfont);
386 DeleteObject (hfont);
392 SelectObject (pango_win32_hdc, oldhfont);
395 DeleteObject (hfont);
398 return g_locale_to_utf8 (lfp->lfFaceName, -1, NULL, NULL, NULL);
401 /***************************** END STOLEN FROM PANGO *****************************/
404 sys_font_to_pango_font (XpThemeClass klazz, XpThemeFont type, char *buf,
415 if (get_system_font (klazz, type, &lf))
421 weight = "Ultra-Light";
433 weight = "Semi-Bold";
437 weight = "Ultra-Bold";
454 hwnd = GetDesktopWindow ();
458 pt_size = -MulDiv (lf.lfHeight, 72,
459 GetDeviceCaps (hDC, LOGPIXELSY));
460 ReleaseDC (hwnd, hDC);
465 font = get_family_name (&lf, hDC);
466 g_snprintf (buf, bufsiz, "%s %s %s %d", font, style, weight,
476 /* missing from ms's header files */
477 #ifndef SPI_GETMENUSHOWDELAY
478 #define SPI_GETMENUSHOWDELAY 106
481 /* I don't know the proper XP theme class for things like
482 HIGHLIGHTTEXT, so we'll just define it to be "BUTTON"
484 #define XP_THEME_CLASS_TEXT XP_THEME_CLASS_BUTTON
487 setup_menu_settings (GtkSettings * settings)
490 gboolean win95 = FALSE;
491 OSVERSIONINFOEX osvi;
492 GObjectClass *klazz = G_OBJECT_GET_CLASS (G_OBJECT (settings));
494 ZeroMemory (&osvi, sizeof (OSVERSIONINFOEX));
495 osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
497 if (!GetVersionEx ((OSVERSIONINFO *) & osvi))
498 win95 = TRUE; /* assume the worst */
500 if (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
501 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
506 if (SystemParametersInfo
507 (SPI_GETMENUSHOWDELAY, 0, &menu_delay, 0))
511 if (g_object_class_find_property
512 (klazz, "gtk-menu-bar-popup-delay"))
514 g_object_set (settings,
515 "gtk-menu-bar-popup-delay",
518 if (g_object_class_find_property
519 (klazz, "gtk-menu-popup-delay"))
521 g_object_set (settings,
522 "gtk-menu-popup-delay",
525 if (g_object_class_find_property
526 (klazz, "gtk-menu-popdown-delay"))
528 g_object_set (settings,
529 "gtk-menu-popdown-delay",
538 msw_style_setup_system_settings (void)
540 GtkSettings *settings;
541 int cursor_blink_time;
543 settings = gtk_settings_get_default ();
547 cursor_blink_time = GetCaretBlinkTime ();
548 g_object_set (settings, "gtk-cursor-blink", cursor_blink_time > 0, NULL);
550 if (cursor_blink_time > 0)
551 g_object_set (settings, "gtk-cursor-blink-time",
552 2 * cursor_blink_time, NULL);
554 g_object_set (settings, "gtk-double-click-distance",
555 GetSystemMetrics (SM_CXDOUBLECLK), NULL);
556 g_object_set (settings, "gtk-double-click-time", GetDoubleClickTime (),
558 g_object_set (settings, "gtk-dnd-drag-threshold",
559 GetSystemMetrics (SM_CXDRAG), NULL);
561 setup_menu_settings (settings);
564 http://developer.gnome.org/doc/API/2.0/gtk/GtkSettings.html
565 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/systemparametersinfo.asp
566 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/getsystemmetrics.asp */
570 setup_system_font (GtkStyle * style)
572 char buf[256], *font; /* It's okay, lfFaceName is smaller than 32
575 if ((font = sys_font_to_pango_font (XP_THEME_CLASS_TEXT,
576 XP_THEME_FONT_MESSAGE,
577 buf, sizeof (buf))) != NULL)
579 if (style->font_desc)
580 pango_font_description_free (style->font_desc);
582 style->font_desc = pango_font_description_from_string (font);
587 sys_color_to_gtk_color (XpThemeClass klazz, int id, GdkColor * pcolor)
591 if (!xp_theme_get_system_color (klazz, id, &color))
592 color = GetSysColor (id);
594 pcolor->pixel = color;
595 pcolor->red = (GetRValue (color) << 8) | GetRValue (color);
596 pcolor->green = (GetGValue (color) << 8) | GetGValue (color);
597 pcolor->blue = (GetBValue (color) << 8) | GetBValue (color);
601 get_system_metric (XpThemeClass klazz, int id)
605 if (!xp_theme_get_system_metric (klazz, id, &rval))
606 rval = GetSystemMetrics (id);
612 setup_msw_rc_style (void)
614 char buf[1024], font_buf[256], *font_ptr;
617 GdkColor menu_text_color;
618 GdkColor tooltip_back;
619 GdkColor tooltip_fore;
622 GdkColor progress_back;
624 GdkColor fg_prelight;
625 GdkColor bg_prelight;
626 GdkColor base_prelight;
627 GdkColor text_prelight;
630 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT,
632 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT,
634 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT,
636 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT,
639 sys_color_to_gtk_color (XP_THEME_CLASS_MENU, COLOR_MENUTEXT,
641 sys_color_to_gtk_color (XP_THEME_CLASS_MENU, COLOR_MENU, &menu_color);
644 sys_color_to_gtk_color (XP_THEME_CLASS_TOOLTIP, COLOR_INFOTEXT,
646 sys_color_to_gtk_color (XP_THEME_CLASS_TOOLTIP, COLOR_INFOBK,
649 /* text on push buttons. TODO: button shadows, backgrounds, and
651 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT, &btn_fore);
652 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE, &btn_face);
654 /* progress bar background color */
655 sys_color_to_gtk_color (XP_THEME_CLASS_PROGRESS, COLOR_HIGHLIGHT,
658 /* Enable coloring for menus. */
660 sys_font_to_pango_font (XP_THEME_CLASS_MENU, XP_THEME_FONT_MENU,
661 font_buf, sizeof (font_buf));
662 g_snprintf (buf, sizeof (buf),
663 "style \"msw-menu\" = \"msw-default\"\n" "{\n"
664 "fg[PRELIGHT] = { %d, %d, %d }\n"
665 "bg[PRELIGHT] = { %d, %d, %d }\n"
666 "text[PRELIGHT] = { %d, %d, %d }\n"
667 "base[PRELIGHT] = { %d, %d, %d }\n"
668 "fg[NORMAL] = { %d, %d, %d }\n"
669 "bg[NORMAL] = { %d, %d, %d }\n" "%s = \"%s\"\n"
670 "}widget_class \"*MenuItem*\" style \"msw-menu\"\n"
671 "widget_class \"*GtkMenu\" style \"msw-menu\"\n"
672 "widget_class \"*GtkMenuShell*\" style \"msw-menu\"\n",
673 fg_prelight.red, fg_prelight.green, fg_prelight.blue,
674 bg_prelight.red, bg_prelight.green, bg_prelight.blue,
675 text_prelight.red, text_prelight.green, text_prelight.blue,
676 base_prelight.red, base_prelight.green, base_prelight.blue,
677 menu_text_color.red, menu_text_color.green,
678 menu_text_color.blue, menu_color.red, menu_color.green,
679 menu_color.blue, (font_ptr ? "font_name" : "#"),
680 (font_ptr ? font_ptr : " font name should go here"));
681 gtk_rc_parse_string (buf);
683 /* Enable coloring for menu bars. */
684 g_snprintf (buf, sizeof (buf),
685 "style \"msw-menu-bar\" = \"msw-menu\"\n"
687 "bg[NORMAL] = { %d, %d, %d }\n"
688 "GtkMenuBar::shadow-type = %s\n"
689 "}widget_class \"*MenuBar*\" style \"msw-menu-bar\"\n",
690 btn_face.red, btn_face.green, btn_face.blue, "etched-in");
691 gtk_rc_parse_string (buf);
693 g_snprintf (buf, sizeof (buf),
694 "style \"msw-toolbar\" = \"msw-default\"\n"
696 "GtkHandleBox::shadow-type = %s\n"
697 "GtkToolbar::shadow-type = %s\n"
698 "}widget_class \"*HandleBox*\" style \"msw-toolbar\"\n",
699 "etched-in", "etched-in");
700 gtk_rc_parse_string (buf);
702 /* enable tooltip fonts */
704 sys_font_to_pango_font (XP_THEME_CLASS_STATUS, XP_THEME_FONT_STATUS,
705 font_buf, sizeof (font_buf));
706 g_snprintf (buf, sizeof (buf),
707 "style \"msw-tooltips-caption\" = \"msw-default\"\n"
708 "{fg[NORMAL] = { %d, %d, %d }\n" "%s = \"%s\"\n"
709 "}widget \"gtk-tooltips.GtkLabel\" style \"msw-tooltips-caption\"\n",
710 tooltip_fore.red, tooltip_fore.green, tooltip_fore.blue,
711 (font_ptr ? "font_name" : "#"),
712 (font_ptr ? font_ptr : " font name should go here"));
713 gtk_rc_parse_string (buf);
715 g_snprintf (buf, sizeof (buf),
716 "style \"msw-tooltips\" = \"msw-default\"\n"
717 "{bg[NORMAL] = { %d, %d, %d }\n"
718 "}widget \"gtk-tooltips*\" style \"msw-tooltips\"\n",
719 tooltip_back.red, tooltip_back.green, tooltip_back.blue);
720 gtk_rc_parse_string (buf);
722 /* enable font theming for status bars */
724 sys_font_to_pango_font (XP_THEME_CLASS_STATUS, XP_THEME_FONT_STATUS,
725 font_buf, sizeof (font_buf));
726 g_snprintf (buf, sizeof (buf),
727 "style \"msw-status\" = \"msw-default\"\n" "{%s = \"%s\"\n"
728 "bg[NORMAL] = { %d, %d, %d }\n"
729 "}widget_class \"*Status*\" style \"msw-status\"\n",
730 (font_ptr ? "font_name" : "#"),
731 (font_ptr ? font_ptr : " font name should go here"),
732 btn_face.red, btn_face.green, btn_face.blue);
733 gtk_rc_parse_string (buf);
735 /* enable coloring for text on buttons TODO: use GetThemeMetric for the
736 border and outside border */
737 g_snprintf (buf, sizeof (buf),
738 "style \"msw-button\" = \"msw-default\"\n"
740 "bg[NORMAL] = { %d, %d, %d }\n"
741 "bg[PRELIGHT] = { %d, %d, %d }\n"
742 "bg[INSENSITIVE] = { %d, %d, %d }\n"
743 "fg[PRELIGHT] = { %d, %d, %d }\n"
744 "GtkButton::default-border = { 1, 1, 1, 1 }\n"
745 "GtkButton::default-outside-border = { 0, 0, 0, 0 }\n"
746 "GtkButton::child-displacement-x = 1\n"
747 "GtkButton::child-displacement-y = 1\n"
748 "}widget_class \"*Button*\" style \"msw-button\"\n",
749 btn_face.red, btn_face.green, btn_face.blue,
750 btn_face.red, btn_face.green, btn_face.blue,
751 btn_face.red, btn_face.green, btn_face.blue,
752 btn_fore.red, btn_fore.green, btn_fore.blue);
753 gtk_rc_parse_string (buf);
755 /* enable coloring for progress bars */
756 g_snprintf (buf, sizeof (buf),
757 "style \"msw-progress\" = \"msw-default\"\n"
758 "{bg[PRELIGHT] = { %d, %d, %d }\n"
759 "bg[NORMAL] = { %d, %d, %d }\n"
760 "}widget_class \"*Progress*\" style \"msw-progress\"\n",
764 btn_face.red, btn_face.green, btn_face.blue);
765 gtk_rc_parse_string (buf);
767 /* scrollbar thumb width and height */
768 g_snprintf (buf, sizeof (buf),
769 "style \"msw-vscrollbar\" = \"msw-default\"\n"
770 "{GtkRange::slider-width = %d\n"
771 "GtkRange::stepper-size = %d\n"
772 "GtkRange::stepper-spacing = 0\n"
773 "GtkRange::trough_border = 0\n"
774 "GtkScale::slider-length = %d\n"
775 "GtkScrollbar::min-slider-length = 8\n"
776 "}widget_class \"*VScrollbar*\" style \"msw-vscrollbar\"\n"
777 "widget_class \"*VScale*\" style \"msw-vscrollbar\"\n",
778 GetSystemMetrics (SM_CYVTHUMB),
779 get_system_metric (XP_THEME_CLASS_SCROLLBAR, SM_CXVSCROLL),
781 gtk_rc_parse_string (buf);
783 g_snprintf (buf, sizeof (buf),
784 "style \"msw-hscrollbar\" = \"msw-default\"\n"
785 "{GtkRange::slider-width = %d\n"
786 "GtkRange::stepper-size = %d\n"
787 "GtkRange::stepper-spacing = 0\n"
788 "GtkRange::trough_border = 0\n"
789 "GtkScale::slider-length = %d\n"
790 "GtkScrollbar::min-slider-length = 8\n"
791 "}widget_class \"*HScrollbar*\" style \"msw-hscrollbar\"\n"
792 "widget_class \"*HScale*\" style \"msw-hscrollbar\"\n",
793 GetSystemMetrics (SM_CXHTHUMB),
794 get_system_metric (XP_THEME_CLASS_SCROLLBAR, SM_CYHSCROLL),
796 gtk_rc_parse_string (buf);
798 /* radio/check button sizes */
799 g_snprintf (buf, sizeof (buf),
800 "style \"msw-checkbutton\" = \"msw-button\"\n"
801 "{GtkCheckButton::indicator-size = 13\n"
802 "}widget_class \"*CheckButton*\" style \"msw-checkbutton\"\n"
803 "widget_class \"*RadioButton*\" style \"msw-checkbutton\"\n");
804 gtk_rc_parse_string (buf);
808 setup_system_styles (GtkStyle * style)
812 /* Default background */
813 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
814 &style->bg[GTK_STATE_NORMAL]);
815 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT,
816 &style->bg[GTK_STATE_SELECTED]);
817 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
818 &style->bg[GTK_STATE_INSENSITIVE]);
819 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
820 &style->bg[GTK_STATE_ACTIVE]);
821 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
822 &style->bg[GTK_STATE_PRELIGHT]);
825 sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOW,
826 &style->base[GTK_STATE_NORMAL]);
827 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT,
828 &style->base[GTK_STATE_SELECTED]);
829 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
830 &style->base[GTK_STATE_INSENSITIVE]);
831 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
832 &style->base[GTK_STATE_ACTIVE]);
833 sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOW,
834 &style->base[GTK_STATE_PRELIGHT]);
837 sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT,
838 &style->text[GTK_STATE_NORMAL]);
839 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT,
840 &style->text[GTK_STATE_SELECTED]);
841 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_GRAYTEXT,
842 &style->text[GTK_STATE_INSENSITIVE]);
843 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT,
844 &style->text[GTK_STATE_ACTIVE]);
845 sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT,
846 &style->text[GTK_STATE_PRELIGHT]);
848 /* Default foreground */
849 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT,
850 &style->fg[GTK_STATE_NORMAL]);
851 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT,
852 &style->fg[GTK_STATE_SELECTED]);
853 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_GRAYTEXT,
854 &style->fg[GTK_STATE_INSENSITIVE]);
855 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT,
856 &style->fg[GTK_STATE_ACTIVE]);
857 sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT,
858 &style->fg[GTK_STATE_PRELIGHT]);
860 for (i = 0; i < 5; i++)
862 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_3DSHADOW,
864 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_3DHILIGHT,
868 (style->light[i].red + style->dark[i].red) / 2;
869 style->mid[i].green =
870 (style->light[i].green + style->dark[i].green) / 2;
872 (style->light[i].blue + style->dark[i].blue) / 2;
874 style->text_aa[i].red =
875 (style->text[i].red + style->base[i].red) / 2;
876 style->text_aa[i].green =
877 (style->text[i].green + style->base[i].green) / 2;
878 style->text_aa[i].blue =
879 (style->text[i].blue + style->base[i].blue) / 2;
884 sanitize_size (GdkWindow * window, gint * width, gint * height)
886 gboolean set_bg = FALSE;
888 if ((*width == -1) && (*height == -1))
890 set_bg = GDK_IS_WINDOW (window);
891 gdk_drawable_get_size (window, width, height);
893 else if (*width == -1)
894 gdk_drawable_get_size (window, width, NULL);
895 else if (*height == -1)
896 gdk_drawable_get_size (window, NULL, height);
901 static XpThemeElement
902 map_gtk_progress_bar_to_xp (GtkProgressBar * progress_bar, gboolean trough)
906 switch (progress_bar->orientation)
908 case GTK_PROGRESS_LEFT_TO_RIGHT:
909 case GTK_PROGRESS_RIGHT_TO_LEFT:
911 ? XP_THEME_ELEMENT_PROGRESS_TROUGH_H
912 : XP_THEME_ELEMENT_PROGRESS_BAR_H;
916 ? XP_THEME_ELEMENT_PROGRESS_TROUGH_V
917 : XP_THEME_ELEMENT_PROGRESS_BAR_V;
924 draw_part (GdkDrawable * drawable,
925 GdkGC * gc, GdkRectangle * area, gint x, gint y, Part part)
928 gdk_gc_set_clip_rectangle (gc, area);
930 if (!parts[part].bmap)
931 parts[part].bmap = gdk_bitmap_create_from_data (drawable,
933 PART_SIZE, PART_SIZE);
935 gdk_gc_set_ts_origin (gc, x, y);
936 gdk_gc_set_stipple (gc, parts[part].bmap);
937 gdk_gc_set_fill (gc, GDK_STIPPLED);
939 gdk_draw_rectangle (drawable, gc, TRUE, x, y, PART_SIZE, PART_SIZE);
941 gdk_gc_set_fill (gc, GDK_SOLID);
944 gdk_gc_set_clip_rectangle (gc, NULL);
948 draw_check (GtkStyle * style,
951 GtkShadowType shadow,
954 const gchar * detail, gint x, gint y, gint width, gint height)
956 x -= (1 + PART_SIZE - width) / 2;
957 y -= (1 + PART_SIZE - height) / 2;
959 if (detail && strcmp (detail, "check") == 0) /* Menu item */
961 if (shadow == GTK_SHADOW_IN)
963 draw_part (window, style->black_gc, area, x, y,
965 draw_part (window, style->dark_gc[state], area, x, y,
971 if (!xp_theme_draw (window, shadow == GTK_SHADOW_IN
972 ? XP_THEME_ELEMENT_PRESSED_CHECKBOX
973 : XP_THEME_ELEMENT_CHECKBOX,
974 style, x, y, width, height, state, area))
976 draw_part (window, style->black_gc, area, x, y,
978 draw_part (window, style->dark_gc[state], area, x, y,
980 draw_part (window, style->mid_gc[state], area, x, y,
982 draw_part (window, style->light_gc[state], area, x, y,
984 draw_part (window, style->base_gc[state], area, x, y,
987 if (shadow == GTK_SHADOW_IN)
989 draw_part (window, style->text_gc[state], area, x,
991 draw_part (window, style->text_aa_gc[state], area,
999 draw_expander (GtkStyle * style,
1002 GdkRectangle * area,
1004 const gchar * detail,
1005 gint x, gint y, GtkExpanderStyle expander_style)
1008 gint expander_semi_size;
1012 XpThemeElement xp_expander;
1014 gtk_widget_style_get (widget, "expander_size", &expander_size, NULL);
1016 switch (expander_style)
1018 case GTK_EXPANDER_COLLAPSED:
1019 case GTK_EXPANDER_SEMI_COLLAPSED:
1020 xp_expander = XP_THEME_ELEMENT_TREEVIEW_EXPANDER_CLOSED;
1023 xp_expander = XP_THEME_ELEMENT_TREEVIEW_EXPANDER_OPENED;
1027 if ((expander_size % 2) == 0)
1030 if (expander_size > 2)
1034 gdk_gc_set_clip_rectangle (style->fg_gc[state], area);
1036 expander_semi_size = expander_size / 2;
1037 x -= expander_semi_size;
1038 y -= expander_semi_size;
1040 gdk_gc_get_values (style->fg_gc[state], &values);
1042 if (!xp_theme_draw (window, xp_expander, style,
1043 x, y, expander_size, expander_size, state, area))
1045 /* RGB values to emulate Windows Classic style */
1046 color.red = color.green = color.blue = 128 << 8;
1048 success = gdk_colormap_alloc_color
1049 (gtk_widget_get_default_colormap (), &color, FALSE, TRUE);
1052 gdk_gc_set_foreground (style->fg_gc[state], &color);
1055 (window, style->fg_gc[state], FALSE, x, y,
1056 expander_size - 1, expander_size - 1);
1059 (window, style->fg_gc[state], x + 2, y + expander_semi_size,
1060 x + expander_size - 2, y + expander_semi_size);
1062 switch (expander_style)
1064 case GTK_EXPANDER_COLLAPSED:
1065 case GTK_EXPANDER_SEMI_COLLAPSED:
1067 (window, style->fg_gc[state], x + expander_semi_size,
1068 y + 2, x + expander_semi_size,
1069 y + expander_size - 2);
1077 gdk_gc_set_foreground (style->fg_gc[state],
1078 &values.foreground);
1082 gdk_gc_set_clip_rectangle (style->fg_gc[state], NULL);
1086 draw_option (GtkStyle * style,
1089 GtkShadowType shadow,
1090 GdkRectangle * area,
1092 const gchar * detail, gint x, gint y, gint width, gint height)
1094 x -= (1 + PART_SIZE - width) / 2;
1095 y -= (1 + PART_SIZE - height) / 2;
1097 if (detail && strcmp (detail, "option") == 0) /* Menu item */
1099 if (shadow == GTK_SHADOW_IN)
1100 draw_part (window, style->fg_gc[state], area, x, y,
1105 if (xp_theme_draw (window, shadow == GTK_SHADOW_IN
1106 ? XP_THEME_ELEMENT_PRESSED_RADIO_BUTTON
1107 : XP_THEME_ELEMENT_RADIO_BUTTON,
1108 style, x, y, width, height, state, area))
1113 draw_part (window, style->black_gc, area, x, y,
1115 draw_part (window, style->dark_gc[state], area, x, y,
1117 draw_part (window, style->mid_gc[state], area, x, y,
1119 draw_part (window, style->light_gc[state], area, x, y,
1121 draw_part (window, style->base_gc[state], area, x, y,
1124 if (shadow == GTK_SHADOW_IN)
1125 draw_part (window, style->text_gc[state], area, x, y,
1132 draw_varrow (GdkWindow * window,
1134 GtkShadowType shadow_type,
1135 GdkRectangle * area,
1136 GtkArrowType arrow_type, gint x, gint y, gint width, gint height)
1139 gint y_start, y_increment;
1143 gdk_gc_set_clip_rectangle (gc, area);
1145 width = width + width % 2 - 1; /* Force odd */
1146 steps = 1 + width / 2;
1147 extra = height - steps;
1149 if (arrow_type == GTK_ARROW_DOWN)
1156 y_start = y + height - 1;
1160 for (i = extra; i < height; i++)
1162 gdk_draw_line (window, gc,
1163 x + (i - extra), y_start + i * y_increment,
1164 x + width - (i - extra) - 1,
1165 y_start + i * y_increment);
1169 gdk_gc_set_clip_rectangle (gc, NULL);
1173 draw_harrow (GdkWindow * window,
1175 GtkShadowType shadow_type,
1176 GdkRectangle * area,
1177 GtkArrowType arrow_type, gint x, gint y, gint width, gint height)
1180 gint x_start, x_increment;
1184 gdk_gc_set_clip_rectangle (gc, area);
1186 height = height + height % 2 - 1; /* Force odd */
1187 steps = 1 + height / 2;
1188 extra = width - steps;
1190 if (arrow_type == GTK_ARROW_RIGHT)
1197 x_start = x + width - 1;
1201 for (i = extra; i < width; i++)
1203 gdk_draw_line (window, gc,
1204 x_start + i * x_increment, y + (i - extra),
1205 x_start + i * x_increment,
1206 y + height - (i - extra) - 1);
1211 gdk_gc_set_clip_rectangle (gc, NULL);
1214 /* This function makes up for some brokeness in gtkrange.c
1215 * where we never get the full arrow of the stepper button
1216 * and the type of button in a single drawing function.
1218 * It doesn't work correctly when the scrollbar is squished
1219 * to the point we don't have room for full-sized steppers.
1222 reverse_engineer_stepper_box (GtkWidget * range,
1223 GtkArrowType arrow_type,
1224 gint * x, gint * y, gint * width, gint * height)
1226 gint slider_width = 14, stepper_size = 14;
1232 gtk_widget_style_get (range,
1233 "slider_width", &slider_width,
1234 "stepper_size", &stepper_size, NULL);
1237 if (arrow_type == GTK_ARROW_UP || arrow_type == GTK_ARROW_DOWN)
1239 box_width = slider_width;
1240 box_height = stepper_size;
1244 box_width = stepper_size;
1245 box_height = slider_width;
1248 *x = *x - (box_width - *width) / 2;
1249 *y = *y - (box_height - *height) / 2;
1251 *height = box_height;
1254 static XpThemeElement
1255 to_xp_arrow (GtkArrowType arrow_type)
1257 XpThemeElement xp_arrow;
1262 xp_arrow = XP_THEME_ELEMENT_ARROW_UP;
1264 case GTK_ARROW_DOWN:
1265 xp_arrow = XP_THEME_ELEMENT_ARROW_DOWN;
1267 case GTK_ARROW_LEFT:
1268 xp_arrow = XP_THEME_ELEMENT_ARROW_LEFT;
1271 xp_arrow = XP_THEME_ELEMENT_ARROW_RIGHT;
1279 draw_arrow (GtkStyle * style,
1282 GtkShadowType shadow,
1283 GdkRectangle * area,
1285 const gchar * detail,
1286 GtkArrowType arrow_type,
1287 gboolean fill, gint x, gint y, gint width, gint height)
1291 name = gtk_widget_get_name (widget);
1293 sanitize_size (window, &width, &height);
1295 if (detail && strcmp (detail, "spinbutton") == 0)
1297 if (xp_theme_is_drawable (XP_THEME_ELEMENT_SPIN_BUTTON_UP))
1303 x += (width - 7) / 2;
1305 if (arrow_type == GTK_ARROW_UP)
1306 y += (height - 4) / 2;
1308 y += (1 + height - 4) / 2;
1309 draw_varrow (window, style->fg_gc[state], shadow, area,
1310 arrow_type, x, y, 7, 4);
1313 else if (detail && (!strcmp (detail, "vscrollbar")
1314 || !strcmp (detail, "hscrollbar")))
1316 gboolean is_disabled = FALSE;
1317 GtkScrollbar *scrollbar = GTK_SCROLLBAR (widget);
1320 gint box_width = width;
1321 gint box_height = height;
1323 reverse_engineer_stepper_box (widget, arrow_type,
1324 &box_x, &box_y, &box_width,
1327 if (scrollbar->range.adjustment->page_size >=
1328 (scrollbar->range.adjustment->upper -
1329 scrollbar->range.adjustment->lower))
1333 (window, to_xp_arrow (arrow_type), style, box_x, box_y,
1334 box_width, box_height, state, area))
1337 else if (arrow_type == GTK_ARROW_UP
1338 || arrow_type == GTK_ARROW_DOWN)
1340 x += (width - 7) / 2;
1341 y += (height - 5) / 2;
1343 draw_varrow (window,
1344 is_disabled ? style->
1345 text_aa_gc[state] : style->fg_gc[state],
1346 shadow, area, arrow_type, x, y, 7, 5);
1350 y += (height - 7) / 2;
1351 x += (width - 5) / 2;
1353 draw_harrow (window,
1354 is_disabled ? style->
1355 text_aa_gc[state] : style->fg_gc[state],
1356 shadow, area, arrow_type, x, y, 5, 7);
1361 /* draw the toolbar chevrons - waiting for GTK 2.4 */
1362 if (name && !strcmp (name, "gtk-toolbar-arrow"))
1365 (window, XP_THEME_ELEMENT_REBAR_CHEVRON, style, x, y,
1366 width, height, state, area))
1369 /* probably a gtk combo box on a toolbar */
1370 else if (0 /* widget->parent && GTK_IS_BUTTON
1371 (widget->parent) */ )
1374 (window, XP_THEME_ELEMENT_COMBOBUTTON, style, x - 3,
1375 widget->allocation.y + 1, width + 5,
1376 widget->allocation.height - 4, state, area))
1380 if (arrow_type == GTK_ARROW_UP || arrow_type == GTK_ARROW_DOWN)
1382 x += (width - 7) / 2;
1383 y += (height - 5) / 2;
1385 draw_varrow (window, style->fg_gc[state], shadow, area,
1386 arrow_type, x, y, 7, 5);
1390 x += (width - 5) / 2;
1391 y += (height - 7) / 2;
1393 draw_harrow (window, style->fg_gc[state], shadow, area,
1394 arrow_type, x, y, 5, 7);
1400 option_menu_get_props (GtkWidget * widget,
1401 GtkRequisition * indicator_size,
1402 GtkBorder * indicator_spacing)
1404 GtkRequisition *tmp_size = NULL;
1405 GtkBorder *tmp_spacing = NULL;
1408 gtk_widget_style_get (widget,
1409 "indicator_size", &tmp_size,
1410 "indicator_spacing", &tmp_spacing, NULL);
1414 *indicator_size = *tmp_size;
1418 *indicator_size = default_option_indicator_size;
1422 *indicator_spacing = *tmp_spacing;
1423 g_free (tmp_spacing);
1426 *indicator_spacing = default_option_indicator_spacing;
1430 is_toolbar_child (GtkWidget * wid)
1434 if (GTK_IS_TOOLBAR (wid) || GTK_IS_HANDLE_BOX (wid))
1444 draw_box (GtkStyle * style,
1446 GtkStateType state_type,
1447 GtkShadowType shadow_type,
1448 GdkRectangle * area,
1450 const gchar * detail, gint x, gint y, gint width, gint height)
1453 (!strcmp (detail, "button") || !strcmp (detail, "buttondefault")))
1455 if (GTK_IS_TREE_VIEW (widget->parent)
1456 || GTK_IS_CLIST (widget->parent))
1459 (window, XP_THEME_ELEMENT_LIST_HEADER, style, x, y,
1460 width, height, state_type, area))
1463 else if (is_toolbar_child (widget->parent))
1466 (window, XP_THEME_ELEMENT_TOOLBAR_BUTTON, style, x, y,
1467 width, height, state_type, area))
1472 gboolean is_default = !strcmp (detail, "buttondefault");
1476 is_default ? XP_THEME_ELEMENT_DEFAULT_BUTTON :
1477 XP_THEME_ELEMENT_BUTTON, style, x, y, width, height,
1482 else if (detail && !strcmp (detail, "spinbutton"))
1484 if (xp_theme_is_drawable (XP_THEME_ELEMENT_SPIN_BUTTON_UP))
1489 else if (detail && (!strcmp (detail, "spinbutton_up")
1490 || !strcmp (detail, "spinbutton_down")))
1492 if (xp_theme_draw (window,
1493 (!strcmp (detail, "spinbutton_up"))
1494 ? XP_THEME_ELEMENT_SPIN_BUTTON_UP
1495 : XP_THEME_ELEMENT_SPIN_BUTTON_DOWN,
1496 style, x, y, width, height, state_type, area))
1501 else if (detail && !strcmp (detail, "slider"))
1503 if (GTK_IS_SCROLLBAR (widget))
1505 GtkScrollbar *scrollbar = GTK_SCROLLBAR (widget);
1506 gboolean is_v = GTK_IS_VSCROLLBAR (widget);
1508 if (xp_theme_draw (window,
1510 ? XP_THEME_ELEMENT_SCROLLBAR_V
1511 : XP_THEME_ELEMENT_SCROLLBAR_H,
1512 style, x, y, width, height, state_type,
1515 XpThemeElement gripper =
1516 (is_v ? XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V :
1517 XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H);
1519 /* Do not display grippers on tiny scroll bars,
1520 the limit imposed is rather arbitrary, perhaps
1521 we can fetch the gripper geometry from
1522 somewhere and use that... */
1524 XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H
1527 XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V
1533 xp_theme_draw (window, gripper, style, x, y,
1534 width, height, state_type, area);
1539 if (scrollbar->range.adjustment->page_size >=
1540 (scrollbar->range.adjustment->upper -
1541 scrollbar->range.adjustment->lower))
1546 else if (detail && !strcmp (detail, "bar"))
1548 if (widget && GTK_IS_PROGRESS_BAR (widget))
1550 GtkProgressBar *progress_bar = GTK_PROGRESS_BAR (widget);
1551 XpThemeElement xp_progress_bar =
1552 map_gtk_progress_bar_to_xp (progress_bar, FALSE);
1554 (window, xp_progress_bar, style, x, y, width, height,
1561 else if (detail && strcmp (detail, "menuitem") == 0)
1563 shadow_type = GTK_SHADOW_NONE;
1565 (window, XP_THEME_ELEMENT_MENU_ITEM, style, x, y, width,
1566 height, state_type, area))
1571 else if (detail && !strcmp (detail, "trough"))
1573 if (widget && GTK_IS_PROGRESS_BAR (widget))
1575 GtkProgressBar *progress_bar = GTK_PROGRESS_BAR (widget);
1576 XpThemeElement xp_progress_bar =
1577 map_gtk_progress_bar_to_xp (progress_bar, TRUE);
1579 (window, xp_progress_bar, style, x, y, width, height,
1586 /* Blank in classic Windows */
1589 else if (widget && GTK_IS_SCROLLBAR (widget))
1591 gboolean is_vertical = GTK_IS_VSCROLLBAR (widget);
1593 if (xp_theme_draw (window,
1595 ? XP_THEME_ELEMENT_TROUGH_V
1596 : XP_THEME_ELEMENT_TROUGH_H,
1598 x, y, width, height, state_type, area))
1604 GdkGCValues gc_values;
1608 sanitize_size (window, &width, &height);
1610 pixmap = gdk_pixmap_new (window, 2, 2, -1);
1612 gdk_draw_point (pixmap,
1613 style->bg_gc[GTK_STATE_NORMAL], 0,
1615 gdk_draw_point (pixmap,
1616 style->bg_gc[GTK_STATE_NORMAL], 1,
1618 gdk_draw_point (pixmap,
1619 style->light_gc[GTK_STATE_NORMAL],
1621 gdk_draw_point (pixmap,
1622 style->light_gc[GTK_STATE_NORMAL],
1625 gc_values.fill = GDK_TILED;
1626 gc_values.tile = pixmap;
1627 gc_values.ts_x_origin = x;
1628 gc_values.ts_y_origin = y;
1629 gc = gdk_gc_new_with_values (window, &gc_values,
1630 GDK_GC_TS_X_ORIGIN |
1631 GDK_GC_TS_Y_ORIGIN |
1636 gdk_gc_set_clip_rectangle (gc, area);
1638 gdk_draw_rectangle (window, gc, TRUE, x, y, width,
1641 g_object_unref (gc);
1642 g_object_unref (pixmap);
1647 else if (widget && GTK_IS_SCALE (widget))
1649 gboolean is_vertical = GTK_IS_VSCALE (widget);
1651 if (!xp_theme_is_active ())
1653 parent_class->draw_box (style, window, state_type,
1654 GTK_SHADOW_NONE, area,
1655 widget, detail, x, y,
1662 (window, XP_THEME_ELEMENT_SCALE_TROUGH_V,
1663 style, (2 * x + width) / 2, y, 2, height,
1667 parent_class->draw_box (style, window, state_type,
1668 GTK_SHADOW_ETCHED_IN,
1670 (2 * x + width) / 2, y, 1,
1676 (window, XP_THEME_ELEMENT_SCALE_TROUGH_H,
1677 style, x, (2 * y + height) / 2, width, 2,
1681 parent_class->draw_box (style, window, state_type,
1682 GTK_SHADOW_ETCHED_IN,
1683 area, NULL, NULL, x,
1684 (2 * y + height) / 2,
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))
1699 && (strcmp (detail, "vscrollbar") == 0
1700 || strcmp (detail, "hscrollbar") == 0))
1702 GtkScrollbar *scrollbar = GTK_SCROLLBAR (widget);
1704 if (shadow_type == GTK_SHADOW_IN)
1705 shadow_type = GTK_SHADOW_ETCHED_IN;
1706 if (scrollbar->range.adjustment->page_size >=
1707 (scrollbar->range.adjustment->upper -
1708 scrollbar->range.adjustment->lower))
1709 shadow_type = GTK_SHADOW_OUT;
1712 && (strcmp (detail, "handlebox_bin") == 0
1713 || strcmp (detail, "toolbar") == 0
1714 || strcmp (detail, "menubar") == 0))
1716 if (xp_theme_draw (window, XP_THEME_ELEMENT_REBAR,
1717 style, x, y, width, height, state_type, area))
1722 else if (detail && (!strcmp (detail, "handlebox"))) /* grip */
1727 const gchar *name = gtk_widget_get_name (widget);
1729 if (name && !strcmp (name, "gtk-tooltips"))
1732 (window, XP_THEME_ELEMENT_TOOLTIP, style, x, y, width,
1733 height, state_type, area))
1741 GdkDrawable *drawable;
1745 if (!GDK_IS_WINDOW (window))
1753 gdk_window_get_internal_paint_info
1754 (window, &drawable, &xoff, &yoff);
1757 rect.left = x - xoff;
1758 rect.top = y - yoff;
1759 rect.right = rect.left + width;
1760 rect.bottom = rect.top + height;
1763 gdk_win32_hdc_get (window,
1764 style->dark_gc[state_type],
1766 brush = GetSysColorBrush (COLOR_3DDKSHADOW);
1768 FrameRect (hdc, &rect, brush);
1769 InflateRect (&rect, -1, -1);
1770 FillRect (hdc, &rect,
1771 (HBRUSH) (COLOR_INFOBK + 1));
1779 parent_class->draw_box (style, window, state_type, shadow_type, area,
1780 widget, detail, x, y, width, height);
1782 if (detail && strcmp (detail, "optionmenu") == 0)
1784 GtkRequisition indicator_size;
1785 GtkBorder indicator_spacing;
1788 option_menu_get_props (widget, &indicator_size,
1789 &indicator_spacing);
1791 sanitize_size (window, &width, &height);
1793 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
1795 x + indicator_size.width + indicator_spacing.left +
1796 indicator_spacing.right;
1799 x + width - (indicator_size.width +
1800 indicator_spacing.left +
1801 indicator_spacing.right) - style->xthickness;
1803 parent_class->draw_vline (style, window, state_type, area, widget,
1805 y + style->ythickness + 1,
1806 y + height - style->ythickness - 3,
1812 draw_tab (GtkStyle * style,
1815 GtkShadowType shadow,
1816 GdkRectangle * area,
1818 const gchar * detail, gint x, gint y, gint width, gint height)
1820 GtkRequisition indicator_size;
1821 GtkBorder indicator_spacing;
1825 g_return_if_fail (style != NULL);
1826 g_return_if_fail (window != NULL);
1828 if (detail && !strcmp (detail, "optionmenutab"))
1830 if (xp_theme_draw (window, XP_THEME_ELEMENT_COMBOBUTTON,
1831 style, x - 5, widget->allocation.y + 1,
1832 width + 10, widget->allocation.height - 2,
1840 gtk_widget_style_get (widget, "indicator_size", &indicator_size,
1843 option_menu_get_props (widget, &indicator_size, &indicator_spacing);
1845 x += (width - indicator_size.width) / 2;
1846 arrow_height = (indicator_size.width + 1) / 2;
1848 y += (height - arrow_height) / 2;
1850 draw_varrow (window, style->black_gc, shadow, area, GTK_ARROW_DOWN,
1851 x, y, indicator_size.width, arrow_height);
1854 /* this is an undefined magic value that, according to the mozilla folks,
1855 worked for all the various themes that they tried */
1856 #define XP_EDGE_SIZE 2
1859 draw_extension (GtkStyle * style,
1861 GtkStateType state_type,
1862 GtkShadowType shadow_type,
1863 GdkRectangle * area,
1865 const gchar * detail,
1867 gint y, gint width, gint height, GtkPositionType gap_side)
1869 if (GTK_IS_NOTEBOOK (widget) && detail && !strcmp (detail, "tab"))
1871 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1872 gint x2, y2, w2, h2;
1878 if (gap_side == GTK_POS_TOP && state_type == GTK_STATE_NORMAL)
1880 /* h2 += XP_EDGE_SIZE; */
1882 else if (gap_side == GTK_POS_BOTTOM
1883 && state_type == GTK_STATE_NORMAL)
1885 /* h2 += XP_EDGE_SIZE; */
1887 else if (gap_side == GTK_POS_LEFT
1888 && state_type == GTK_STATE_NORMAL)
1893 else if (gap_side == GTK_POS_RIGHT
1894 && state_type == GTK_STATE_NORMAL)
1896 w2 -= (XP_EDGE_SIZE + 1);
1900 (window, gtk_notebook_get_current_page (notebook) == 0
1901 ? XP_THEME_ELEMENT_TAB_ITEM_LEFT_EDGE
1902 : XP_THEME_ELEMENT_TAB_ITEM,
1903 style, x2, y2, w2, h2, state_type, area))
1908 parent_class->draw_extension
1909 (style, window, state_type, shadow_type, area, widget, detail,
1910 x, y, width, height, gap_side);
1914 draw_box_gap (GtkStyle * style, GdkWindow * window, GtkStateType state_type,
1915 GtkShadowType shadow_type, GdkRectangle * area,
1916 GtkWidget * widget, const gchar * detail, gint x,
1917 gint y, gint width, gint height, GtkPositionType gap_side,
1918 gint gap_x, gint gap_width)
1920 if (GTK_IS_NOTEBOOK (widget) && detail && !strcmp (detail, "notebook"))
1922 /* FIXME: pos != TOP to be implemented */
1923 if (gap_side == GTK_POS_TOP
1924 && xp_theme_draw (window, XP_THEME_ELEMENT_TAB_PANE, style, x,
1925 y, width, height, state_type, area))
1930 parent_class->draw_box_gap (style, window, state_type, shadow_type,
1931 area, widget, detail, x, y, width, height,
1932 gap_side, gap_x, gap_width);
1936 draw_flat_box (GtkStyle * style, GdkWindow * window,
1937 GtkStateType state_type, GtkShadowType shadow_type,
1938 GdkRectangle * area, GtkWidget * widget,
1939 const gchar * detail, gint x, gint y, gint width, gint height)
1941 if (detail && !strcmp (detail, "checkbutton"))
1943 if (state_type == GTK_STATE_PRELIGHT)
1949 parent_class->draw_flat_box (style, window, state_type, shadow_type,
1950 area, widget, detail, x, y, width, height);
1954 draw_shadow (GtkStyle * style,
1956 GtkStateType state_type,
1957 GtkShadowType shadow_type,
1958 GdkRectangle * area,
1960 const gchar * detail, gint x, gint y, gint width, gint height)
1962 gboolean is_handlebox_grippie = (detail && !strcmp (detail, "handlebox"));
1964 if (detail && !strcmp (detail, "entry"))
1966 if (xp_theme_draw (window, XP_THEME_ELEMENT_EDIT_TEXT, style,
1967 x, y, width, height, state_type, area))
1973 if (is_handlebox_grippie
1974 || (widget && (shadow_type == GTK_SHADOW_ETCHED_IN)
1975 && (GTK_IS_MENU_BAR (widget) || GTK_IS_TOOLBAR (widget)
1976 || GTK_IS_HANDLE_BOX (widget))))
1980 gint thickness_light;
1981 gint thickness_dark;
1984 gc1 = style->light_gc[state_type];
1985 gc2 = style->dark_gc[state_type];
1987 sanitize_size (window, &width, &height);
1991 gdk_gc_set_clip_rectangle (gc1, area);
1992 gdk_gc_set_clip_rectangle (gc2, area);
1993 if (shadow_type == GTK_SHADOW_IN ||
1994 shadow_type == GTK_SHADOW_OUT)
1996 gdk_gc_set_clip_rectangle (style->black_gc, area);
1997 gdk_gc_set_clip_rectangle (style->
2003 if (style->xthickness > 0)
2005 if (style->xthickness > 1)
2007 thickness_light = 1;
2010 for (i = 0; i < thickness_dark; i++)
2012 if (!is_handlebox_grippie)
2013 gdk_draw_line (window, gc1,
2017 y + height - i - 1);
2018 if (is_handlebox_grippie
2020 && GTK_IS_MENU_BAR (widget)))
2021 gdk_draw_line (window, gc2, x + i,
2023 y + height - i - 1);
2026 for (i = 0; i < thickness_light; i++)
2028 if (is_handlebox_grippie
2030 && GTK_IS_MENU_BAR (widget)))
2031 gdk_draw_line (window, gc1,
2032 x + thickness_dark + i,
2033 y + thickness_dark + i,
2034 x + thickness_dark + i,
2036 thickness_dark - i -
2038 if (!is_handlebox_grippie)
2039 gdk_draw_line (window, gc2,
2041 thickness_light - i -
2043 y + thickness_dark + i,
2045 thickness_light - i -
2048 thickness_light - 1);
2053 gdk_draw_line (window,
2054 style->dark_gc[state_type],
2055 x, y, x, y + height);
2056 gdk_draw_line (window,
2057 style->dark_gc[state_type],
2058 x + width, y, x + width,
2063 if (style->ythickness > 0)
2065 if (style->ythickness > 1)
2067 thickness_light = 1;
2070 for (i = 0; i < thickness_dark; i++)
2072 gdk_draw_line (window, gc1,
2076 y + height - i - 1);
2078 if (widget && GTK_IS_MENU_BAR (widget))
2079 gdk_draw_line (window, gc2,
2086 for (i = 0; i < thickness_light; i++)
2088 gdk_draw_line (window, gc2,
2089 x + thickness_dark + i,
2091 thickness_light - i - 1,
2093 thickness_light - 1,
2095 thickness_light - i - 1);
2097 if (widget && GTK_IS_MENU_BAR (widget))
2098 gdk_draw_line (window, gc1,
2099 x + thickness_dark + i,
2100 y + thickness_dark + i,
2102 thickness_dark - i - 2,
2103 y + thickness_dark +
2109 gdk_draw_line (window,
2110 style->dark_gc[state_type],
2111 x, y, x + width, y);
2113 gdk_draw_line (window,
2114 style->dark_gc[state_type],
2115 x, y + height, x + width,
2123 gdk_gc_set_clip_rectangle (gc1, NULL);
2124 gdk_gc_set_clip_rectangle (gc2, NULL);
2125 if (shadow_type == GTK_SHADOW_IN ||
2126 shadow_type == GTK_SHADOW_OUT)
2128 gdk_gc_set_clip_rectangle (style->black_gc, NULL);
2129 gdk_gc_set_clip_rectangle (style->
2137 parent_class->draw_shadow (style, window, state_type, shadow_type, area,
2138 widget, detail, x, y, width, height);
2142 draw_hline (GtkStyle * style,
2144 GtkStateType state_type,
2145 GdkRectangle * area,
2147 const gchar * detail, gint x1, gint x2, gint y)
2149 parent_class->draw_hline (style, window, state_type, area, widget,
2154 draw_vline (GtkStyle * style,
2156 GtkStateType state_type,
2157 GdkRectangle * area,
2159 const gchar * detail, gint y1, gint y2, gint x)
2161 parent_class->draw_vline (style, window, state_type, area, widget,
2166 draw_slider (GtkStyle * style,
2168 GtkStateType state_type,
2169 GtkShadowType shadow_type,
2170 GdkRectangle * area,
2172 const gchar * detail,
2174 gint y, gint width, gint height, GtkOrientation orientation)
2176 if (GTK_IS_SCALE (widget) &&
2177 xp_theme_draw (window,
2179 GTK_ORIENTATION_VERTICAL) ?
2180 XP_THEME_ELEMENT_SCALE_SLIDER_V :
2181 XP_THEME_ELEMENT_SCALE_SLIDER_H), style, x, y, width,
2182 height, state_type, area))
2187 parent_class->draw_slider (style, window, state_type, shadow_type, area,
2188 widget, detail, x, y, width, height,
2193 draw_resize_grip (GtkStyle * style,
2195 GtkStateType state_type,
2196 GdkRectangle * area,
2198 const gchar * detail,
2199 GdkWindowEdge edge, gint x, gint y, gint width, gint height)
2201 if (detail && !strcmp (detail, "statusbar"))
2204 (window, XP_THEME_ELEMENT_STATUS_GRIPPER, style, x, y, width,
2205 height, state_type, area))
2209 parent_class->draw_resize_grip (style, window, state_type, area,
2210 widget, detail, edge, x, y, width,
2215 draw_handle (GtkStyle * style,
2217 GtkStateType state_type,
2218 GtkShadowType shadow_type,
2219 GdkRectangle * area,
2221 const gchar * detail,
2223 gint y, gint width, gint height, GtkOrientation orientation)
2225 if (is_toolbar_child (widget))
2227 XpThemeElement hndl;
2229 sanitize_size (window, &width, &height);
2231 if (orientation == GTK_ORIENTATION_VERTICAL)
2232 hndl = XP_THEME_ELEMENT_REBAR_GRIPPER_V;
2234 hndl = XP_THEME_ELEMENT_REBAR_GRIPPER_H;
2236 if (xp_theme_draw (window, hndl, style, x, y, width, height,
2243 if (!GTK_IS_PANED (widget))
2245 gint xthick, ythick;
2246 GdkGC *light_gc, *dark_gc, *shadow_gc;
2249 sanitize_size (window, &width, &height);
2251 gtk_paint_box (style, window, state_type, shadow_type, area,
2252 widget, detail, x, y, width, height);
2254 light_gc = style->light_gc[state_type];
2255 dark_gc = style->dark_gc[state_type];
2256 shadow_gc = style->mid_gc[state_type];
2258 xthick = style->xthickness;
2259 ythick = style->ythickness;
2261 dest.x = x + xthick;
2262 dest.y = y + ythick;
2263 dest.width = width - (xthick * 2);
2264 dest.height = height - (ythick * 2);
2266 if (dest.width < dest.height)
2271 gdk_gc_set_clip_rectangle (light_gc, &dest);
2272 gdk_gc_set_clip_rectangle (dark_gc, &dest);
2273 gdk_gc_set_clip_rectangle (shadow_gc, &dest);
2275 if (dest.width < dest.height)
2277 gdk_draw_line (window, light_gc, dest.x, dest.y, dest.x,
2279 gdk_draw_line (window, dark_gc, dest.x + (dest.width / 2),
2280 dest.y, dest.x + (dest.width / 2),
2282 gdk_draw_line (window, shadow_gc, dest.x + dest.width,
2283 dest.y, dest.x + dest.width, dest.height);
2287 gdk_draw_line (window, light_gc, dest.x, dest.y,
2288 dest.x + dest.width, dest.y);
2289 gdk_draw_line (window, dark_gc, dest.x,
2290 dest.y + (dest.height / 2),
2291 dest.x + dest.width,
2292 dest.y + (dest.height / 2));
2293 gdk_draw_line (window, shadow_gc, dest.x,
2294 dest.y + dest.height, dest.x + dest.width,
2295 dest.y + dest.height);
2298 gdk_gc_set_clip_rectangle (shadow_gc, NULL);
2299 gdk_gc_set_clip_rectangle (light_gc, NULL);
2300 gdk_gc_set_clip_rectangle (dark_gc, NULL);
2305 msw_style_init_from_rc (GtkStyle * style, GtkRcStyle * rc_style)
2307 setup_system_font (style);
2308 setup_menu_settings (gtk_settings_get_default ());
2309 setup_system_styles (style);
2310 parent_class->init_from_rc (style, rc_style);
2314 msw_style_class_init (MswStyleClass * klass)
2316 GtkStyleClass *style_class = GTK_STYLE_CLASS (klass);
2318 parent_class = g_type_class_peek_parent (klass);
2320 style_class->init_from_rc = msw_style_init_from_rc;
2321 style_class->draw_arrow = draw_arrow;
2322 style_class->draw_box = draw_box;
2323 style_class->draw_check = draw_check;
2324 style_class->draw_option = draw_option;
2325 style_class->draw_tab = draw_tab;
2326 style_class->draw_flat_box = draw_flat_box;
2327 style_class->draw_expander = draw_expander;
2328 style_class->draw_extension = draw_extension;
2329 style_class->draw_box_gap = draw_box_gap;
2330 style_class->draw_shadow = draw_shadow;
2331 style_class->draw_hline = draw_hline;
2332 style_class->draw_vline = draw_vline;
2333 style_class->draw_handle = draw_handle;
2334 style_class->draw_resize_grip = draw_resize_grip;
2335 style_class->draw_slider = draw_slider;
2338 GType msw_type_style = 0;
2341 msw_style_register_type (GTypeModule * module)
2343 static const GTypeInfo object_info = {
2344 sizeof (MswStyleClass),
2345 (GBaseInitFunc) NULL,
2346 (GBaseFinalizeFunc) NULL,
2347 (GClassInitFunc) msw_style_class_init,
2348 NULL, /* class_finalize */
2349 NULL, /* class_data */
2351 0, /* n_preallocs */
2352 (GInstanceInitFunc) NULL,
2355 msw_type_style = g_type_module_register_type (module,
2362 msw_style_init (void)
2365 msw_style_setup_system_settings ();
2366 setup_msw_rc_style ();