1 /* MS-Windows Engine (aka GTK-Wimp)
3 * Copyright (C) 2003, 2004 Raymond Penners <raymond@dotsphinx.com>
4 * Copyright (C) 2006 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
5 * Includes code adapted from redmond95 by Owen Taylor, and
6 * gtk-nativewin by Evan Martin
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
27 * http://lxr.mozilla.org/seamonkey/source/widget/src/windows/nsNativeThemeWin.cpp
28 * http://lxr.mozilla.org/seamonkey/source/widget/src/windows/nsLookAndFeel.cpp
29 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/userex/functions/drawthemebackground.asp
30 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/pantdraw_4b3g.asp
33 #include "msw_style.h"
43 /* #include <gdk/gdkwin32.h> */
45 #include "gdk/win32/gdkwin32.h"
47 static HDC get_window_dc (GtkStyle *style, GdkWindow *window,
48 GtkStateType state_type, gint x, gint y, gint width,
49 gint height, RECT *rect);
50 static void release_window_dc (GtkStyle *style, GdkWindow *window,
51 GtkStateType state_type);
54 /* Default values, not normally used
56 static const GtkRequisition default_option_indicator_size = { 9, 8 };
57 static const GtkBorder default_option_indicator_spacing = { 7, 5, 2, 2 };
59 static GtkStyleClass *parent_class;
60 static HBRUSH g_dither_brush = NULL;
62 static HPEN g_light_pen = NULL;
63 static HPEN g_dark_pen = NULL;
85 static const guint8 check_aa_bits[] = {
86 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
90 static const guint8 check_base_bits[] = {
91 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xfc, 0x07, 0xfc, 0x07, 0xfc, 0x07,
93 0x07, 0xfc, 0x07, 0xfc, 0x07, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00
95 static const guint8 check_black_bits[] = {
96 0x00, 0x00, 0xfe, 0x0f, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00,
98 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00
100 static const guint8 check_dark_bits[] = {
101 0xff, 0x1f, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
103 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00
105 static const guint8 check_light_bits[] = {
106 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10,
108 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0xfe, 0x1f
110 static const guint8 check_mid_bits[] = {
111 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08,
113 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0xfc, 0x0f, 0x00, 0x00
115 static const guint8 check_text_bits[] = {
116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x88, 0x03,
118 0x00, 0x70, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
120 static const char check_inconsistent_bits[] = {
121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
123 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
125 static const guint8 radio_base_bits[] = {
126 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0xf8, 0x03, 0xfc, 0x07, 0xfc, 0x07,
128 0x07, 0xfc, 0x07, 0xf8, 0x03, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00
130 static const guint8 radio_black_bits[] = {
131 0x00, 0x00, 0xf0, 0x01, 0x0c, 0x02, 0x04, 0x00, 0x02, 0x00, 0x02, 0x00,
133 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
135 static const guint8 radio_dark_bits[] = {
136 0xf0, 0x01, 0x0c, 0x06, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00,
138 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
140 static const guint8 radio_light_bits[] = {
141 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x10, 0x00, 0x10,
143 0x10, 0x00, 0x10, 0x00, 0x08, 0x00, 0x08, 0x0c, 0x06, 0xf0, 0x01
145 static const guint8 radio_mid_bits[] = {
146 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08,
148 0x08, 0x00, 0x08, 0x00, 0x04, 0x0c, 0x06, 0xf0, 0x01, 0x00, 0x00
150 static const guint8 radio_text_bits[] = {
151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xf0, 0x01,
153 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
161 { check_aa_bits, NULL },
162 { check_base_bits, NULL },
163 { check_black_bits, NULL },
164 { check_dark_bits, NULL },
165 { check_light_bits, NULL },
166 { check_mid_bits, NULL },
167 { check_text_bits, NULL },
168 { check_inconsistent_bits, NULL },
169 { radio_base_bits, NULL },
170 { radio_black_bits, NULL },
171 { radio_dark_bits, NULL },
172 { radio_light_bits, NULL },
173 { radio_mid_bits, NULL },
174 { radio_text_bits, NULL }
178 get_system_font (XpThemeClass klazz, XpThemeFont type, LOGFONT *out_lf)
181 /* TODO: this causes crashes later because the font name is in UCS2, and
182 the pango fns don't deal with that gracefully */
183 if (xp_theme_get_system_font (klazz, type, out_lf))
190 NONCLIENTMETRICS ncm;
192 ncm.cbSize = sizeof (NONCLIENTMETRICS);
194 if (SystemParametersInfo (SPI_GETNONCLIENTMETRICS,
195 sizeof (NONCLIENTMETRICS), &ncm, 0))
197 if (type == XP_THEME_FONT_CAPTION)
198 *out_lf = ncm.lfCaptionFont;
199 else if (type == XP_THEME_FONT_MENU)
200 *out_lf = ncm.lfMenuFont;
201 else if (type == XP_THEME_FONT_STATUS)
202 *out_lf = ncm.lfStatusFont;
204 *out_lf = ncm.lfMessageFont;
213 /***************************** BEGIN STOLEN FROM PANGO *****************************/
216 This code is stolen from Pango 1.4. It attempts to address the following problems:
218 http://bugzilla.gnome.org/show_bug.cgi?id=135098
219 http://sourceforge.net/tracker/index.php?func=detail&aid=895762&group_id=76416&atid=547655
221 As Owen suggested in bug 135098, once Pango 1.6 is released, we need to get rid of this code.
224 #define PING(printlist)
226 /* TrueType defines: */
228 #define MAKE_TT_TABLE_NAME(c1, c2, c3, c4) \
229 (((guint32)c4) << 24 | ((guint32)c3) << 16 | ((guint32)c2) << 8 | ((guint32)c1))
231 #define CMAP (MAKE_TT_TABLE_NAME('c','m','a','p'))
232 #define CMAP_HEADER_SIZE 4
234 #define NAME (MAKE_TT_TABLE_NAME('n','a','m','e'))
235 #define NAME_HEADER_SIZE 6
237 #define ENCODING_TABLE_SIZE 8
239 #define APPLE_UNICODE_PLATFORM_ID 0
240 #define MACINTOSH_PLATFORM_ID 1
241 #define ISO_PLATFORM_ID 2
242 #define MICROSOFT_PLATFORM_ID 3
244 #define SYMBOL_ENCODING_ID 0
245 #define UNICODE_ENCODING_ID 1
246 #define UCS4_ENCODING_ID 10
250 guint16 format_selector;
252 guint16 string_storage_offset;
261 guint16 string_length;
262 guint16 string_offset;
266 pango_win32_get_name_header (HDC hdc, struct name_header *header)
268 if (GetFontData (hdc, NAME, 0, header, sizeof (*header)) != sizeof (*header))
271 header->num_records = GUINT16_FROM_BE (header->num_records);
272 header->string_storage_offset = GUINT16_FROM_BE (header->string_storage_offset);
278 pango_win32_get_name_record (HDC hdc, gint i, struct name_record *record)
280 if (GetFontData (hdc, NAME, 6 + i * sizeof (*record),
281 record, sizeof (*record)) != sizeof (*record))
286 record->platform_id = GUINT16_FROM_BE (record->platform_id);
287 record->encoding_id = GUINT16_FROM_BE (record->encoding_id);
288 record->language_id = GUINT16_FROM_BE (record->language_id);
289 record->name_id = GUINT16_FROM_BE (record->name_id);
290 record->string_length = GUINT16_FROM_BE (record->string_length);
291 record->string_offset = GUINT16_FROM_BE (record->string_offset);
297 get_family_name (LOGFONT *lfp, HDC pango_win32_hdc)
302 struct name_header header;
303 struct name_record record;
305 gint unicode_ix = -1, mac_ix = -1, microsoft_ix = -1;
309 gchar *string = NULL;
314 /* If lfFaceName is ASCII, assume it is the common (English) name for the
315 font. Is this valid? Do some TrueType fonts have different names in
316 French, German, etc, and does the system return these if the locale is
317 set to use French, German, etc? */
318 l = strlen (lfp->lfFaceName);
319 for (i = 0; i < l; i++)
321 if (lfp->lfFaceName[i] < ' ' || lfp->lfFaceName[i] > '~')
328 return g_strdup (lfp->lfFaceName);
330 if ((hfont = CreateFontIndirect (lfp)) == NULL)
333 if ((oldhfont = (HFONT) SelectObject (pango_win32_hdc, hfont)) == NULL)
336 if (!pango_win32_get_name_header (pango_win32_hdc, &header))
339 PING (("%d name records", header.num_records));
341 for (i = 0; i < header.num_records; i++)
343 if (!pango_win32_get_name_record (pango_win32_hdc, i, &record))
346 if ((record.name_id != 1 && record.name_id != 16) || record.string_length <= 0)
349 PING (("platform:%d encoding:%d language:%04x name_id:%d",
350 record.platform_id, record.encoding_id, record.language_id,
353 if (record.platform_id == APPLE_UNICODE_PLATFORM_ID ||
354 record.platform_id == ISO_PLATFORM_ID)
358 else if (record.platform_id == MACINTOSH_PLATFORM_ID && record.encoding_id == 0 && /* Roman
360 record.language_id == 0) /* English */
364 else if (record.platform_id == MICROSOFT_PLATFORM_ID)
366 if ((microsoft_ix == -1 ||
367 PRIMARYLANGID (record.language_id) == LANG_ENGLISH) &&
368 (record.encoding_id == SYMBOL_ENCODING_ID ||
369 record.encoding_id == UNICODE_ENCODING_ID ||
370 record.encoding_id == UCS4_ENCODING_ID))
377 if (microsoft_ix >= 0)
378 name_ix = microsoft_ix;
379 else if (mac_ix >= 0)
381 else if (unicode_ix >= 0)
382 name_ix = unicode_ix;
386 if (!pango_win32_get_name_record (pango_win32_hdc, name_ix, &record))
389 string = g_malloc (record.string_length + 1);
390 if (GetFontData (pango_win32_hdc, NAME,
391 header.string_storage_offset + record.string_offset,
392 string, record.string_length) != record.string_length)
395 string[record.string_length] = '\0';
397 if (name_ix == microsoft_ix)
399 if (record.encoding_id == SYMBOL_ENCODING_ID ||
400 record.encoding_id == UNICODE_ENCODING_ID)
402 codeset = "UTF-16BE";
409 else if (name_ix == mac_ix)
411 codeset = "MacRoman";
413 else /* name_ix == unicode_ix */
419 name = g_convert (string, record.string_length, "UTF-8", codeset, NULL,
428 SelectObject (pango_win32_hdc, oldhfont);
429 DeleteObject (hfont);
435 SelectObject (pango_win32_hdc, oldhfont);
438 DeleteObject (hfont);
441 return g_locale_to_utf8 (lfp->lfFaceName, -1, NULL, NULL, NULL);
444 /***************************** END STOLEN FROM PANGO *****************************/
447 sys_font_to_pango_font (XpThemeClass klazz, XpThemeFont type, char *buf,
458 if (get_system_font (klazz, type, &lf))
464 weight = "Ultra-Light";
476 weight = "Semi-Bold";
480 weight = "Ultra-Bold";
497 hwnd = GetDesktopWindow ();
501 pt_size = -MulDiv (lf.lfHeight, 72,
502 GetDeviceCaps (hDC, LOGPIXELSY));
509 font = get_family_name (&lf, hDC);
512 ReleaseDC (hwnd, hDC);
514 if (!(font && *font))
517 g_snprintf (buf, bufsiz, "%s %s %s %d", font, style, weight, pt_size);
526 /* missing from ms's header files */
527 #ifndef SPI_GETMENUSHOWDELAY
528 #define SPI_GETMENUSHOWDELAY 106
531 /* I don't know the proper XP theme class for things like
532 HIGHLIGHTTEXT, so we'll just define it to be "BUTTON"
534 #define XP_THEME_CLASS_TEXT XP_THEME_CLASS_BUTTON
537 setup_menu_settings (GtkSettings *settings)
540 gboolean win95 = FALSE;
541 OSVERSIONINFOEX osvi;
542 GObjectClass *klazz = G_OBJECT_GET_CLASS (G_OBJECT (settings));
544 ZeroMemory (&osvi, sizeof (OSVERSIONINFOEX));
545 osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
547 if (!GetVersionEx ((OSVERSIONINFO *) & osvi))
548 win95 = TRUE; /* assume the worst */
550 if (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
552 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
560 if (SystemParametersInfo (SPI_GETMENUSHOWDELAY, 0, &menu_delay, 0))
564 if (g_object_class_find_property
565 (klazz, "gtk-menu-bar-popup-delay"))
567 g_object_set (settings,
568 "gtk-menu-bar-popup-delay", 0, NULL);
570 if (g_object_class_find_property
571 (klazz, "gtk-menu-popup-delay"))
573 g_object_set (settings,
574 "gtk-menu-popup-delay", menu_delay, NULL);
576 if (g_object_class_find_property
577 (klazz, "gtk-menu-popdown-delay"))
579 g_object_set (settings,
580 "gtk-menu-popdown-delay", menu_delay, NULL);
588 msw_style_setup_system_settings (void)
590 GtkSettings *settings;
591 int cursor_blink_time;
593 settings = gtk_settings_get_default ();
597 cursor_blink_time = GetCaretBlinkTime ();
598 g_object_set (settings, "gtk-cursor-blink", cursor_blink_time > 0, NULL);
600 if (cursor_blink_time > 0)
602 g_object_set (settings, "gtk-cursor-blink-time",
603 2 * cursor_blink_time, NULL);
606 g_object_set (settings, "gtk-double-click-distance",
607 GetSystemMetrics (SM_CXDOUBLECLK), NULL);
608 g_object_set (settings, "gtk-double-click-time", GetDoubleClickTime (),
610 g_object_set (settings, "gtk-dnd-drag-threshold",
611 GetSystemMetrics (SM_CXDRAG), NULL);
613 setup_menu_settings (settings);
616 http://developer.gnome.org/doc/API/2.0/gtk/GtkSettings.html
617 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/systemparametersinfo.asp
618 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/getsystemmetrics.asp */
622 setup_system_font (GtkStyle *style)
624 char buf[256], *font; /* It's okay, lfFaceName is smaller than 32
627 if ((font = sys_font_to_pango_font (XP_THEME_CLASS_TEXT,
628 XP_THEME_FONT_MESSAGE,
629 buf, sizeof (buf))) != NULL)
631 if (style->font_desc)
633 pango_font_description_free (style->font_desc);
636 style->font_desc = pango_font_description_from_string (font);
641 sys_color_to_gtk_color (XpThemeClass klazz, int id, GdkColor * pcolor)
645 if (!xp_theme_get_system_color (klazz, id, &color))
646 color = GetSysColor (id);
648 pcolor->pixel = color;
649 pcolor->red = (GetRValue (color) << 8) | GetRValue (color);
650 pcolor->green = (GetGValue (color) << 8) | GetGValue (color);
651 pcolor->blue = (GetBValue (color) << 8) | GetBValue (color);
655 get_system_metric (XpThemeClass klazz, int id)
659 if (!xp_theme_get_system_metric (klazz, id, &rval))
660 rval = GetSystemMetrics (id);
666 setup_msw_rc_style (void)
668 char buf[1024], font_buf[256], *font_ptr;
669 char menu_bar_prelight_str[128];
672 GdkColor menu_text_color;
673 GdkColor tooltip_back;
674 GdkColor tooltip_fore;
677 GdkColor progress_back;
679 GdkColor fg_prelight;
680 GdkColor bg_prelight;
681 GdkColor base_prelight;
682 GdkColor text_prelight;
685 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT,
687 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT, &bg_prelight);
688 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT,
690 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT,
693 sys_color_to_gtk_color (XP_THEME_CLASS_MENU, COLOR_MENUTEXT,
695 sys_color_to_gtk_color (XP_THEME_CLASS_MENU, COLOR_MENU, &menu_color);
698 sys_color_to_gtk_color (XP_THEME_CLASS_TOOLTIP, COLOR_INFOTEXT,
700 sys_color_to_gtk_color (XP_THEME_CLASS_TOOLTIP, COLOR_INFOBK,
703 /* text on push buttons. TODO: button shadows, backgrounds, and
705 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT, &btn_fore);
706 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE, &btn_face);
708 /* progress bar background color */
709 sys_color_to_gtk_color (XP_THEME_CLASS_PROGRESS, COLOR_HIGHLIGHT,
712 /* Enable coloring for menus. */
714 sys_font_to_pango_font (XP_THEME_CLASS_MENU, XP_THEME_FONT_MENU,
715 font_buf, sizeof (font_buf));
716 g_snprintf (buf, sizeof (buf),
717 "style \"msw-menu\" = \"msw-default\"\n" "{\n"
718 "GtkMenuItem::toggle-spacing = 8\n"
719 "fg[PRELIGHT] = { %d, %d, %d }\n"
720 "bg[PRELIGHT] = { %d, %d, %d }\n"
721 "text[PRELIGHT] = { %d, %d, %d }\n"
722 "base[PRELIGHT] = { %d, %d, %d }\n"
723 "fg[NORMAL] = { %d, %d, %d }\n"
724 "bg[NORMAL] = { %d, %d, %d }\n" "%s = \"%s\"\n"
725 "}widget_class \"*MenuItem*\" style \"msw-menu\"\n"
726 "widget_class \"*GtkMenu\" style \"msw-menu\"\n"
727 "widget_class \"*GtkMenuShell*\" style \"msw-menu\"\n",
728 fg_prelight.red, fg_prelight.green, fg_prelight.blue,
729 bg_prelight.red, bg_prelight.green, bg_prelight.blue,
730 text_prelight.red, text_prelight.green, text_prelight.blue,
731 base_prelight.red, base_prelight.green, base_prelight.blue,
732 menu_text_color.red, menu_text_color.green,
733 menu_text_color.blue, menu_color.red, menu_color.green,
734 menu_color.blue, (font_ptr ? "font_name" : "#"),
735 (font_ptr ? font_ptr : " font name should go here"));
736 gtk_rc_parse_string (buf);
738 if (xp_theme_is_active ())
740 *menu_bar_prelight_str = '\0';
744 g_snprintf (menu_bar_prelight_str, sizeof (menu_bar_prelight_str),
745 "fg[PRELIGHT] = { %d, %d, %d }\n",
746 menu_text_color.red, menu_text_color.green,
747 menu_text_color.blue);
750 /* Enable coloring for menu bars. */
751 g_snprintf (buf, sizeof (buf),
752 "style \"msw-menu-bar\" = \"msw-menu\"\n"
754 "bg[NORMAL] = { %d, %d, %d }\n"
755 "%s" "GtkMenuBar::shadow-type = %d\n"
757 FIXME: This should be enabled once gtk+ support
758 GtkMenuBar::prelight-item style property.
760 /* "GtkMenuBar::prelight-item = 1\n" */
761 "}widget_class \"*MenuBar*\" style \"msw-menu-bar\"\n",
762 btn_face.red, btn_face.green, btn_face.blue,
763 menu_bar_prelight_str, xp_theme_is_active ()? 0 : 2);
764 gtk_rc_parse_string (buf);
766 g_snprintf (buf, sizeof (buf),
767 "style \"msw-toolbar\" = \"msw-default\"\n"
769 "GtkHandleBox::shadow-type = %s\n"
770 "GtkToolbar::shadow-type = %s\n"
771 "}widget_class \"*HandleBox*\" style \"msw-toolbar\"\n",
772 "etched-in", "etched-in");
773 gtk_rc_parse_string (buf);
775 /* enable tooltip fonts */
776 font_ptr = sys_font_to_pango_font (XP_THEME_CLASS_STATUS, XP_THEME_FONT_STATUS,
777 font_buf, sizeof (font_buf));
778 g_snprintf (buf, sizeof (buf),
779 "style \"msw-tooltips-caption\" = \"msw-default\"\n"
780 "{fg[NORMAL] = { %d, %d, %d }\n" "%s = \"%s\"\n"
781 "}widget \"gtk-tooltips.GtkLabel\" style \"msw-tooltips-caption\"\n",
782 tooltip_fore.red, tooltip_fore.green, tooltip_fore.blue,
783 (font_ptr ? "font_name" : "#"),
784 (font_ptr ? font_ptr : " font name should go here"));
785 gtk_rc_parse_string (buf);
787 g_snprintf (buf, sizeof (buf),
788 "style \"msw-tooltips\" = \"msw-default\"\n"
789 "{bg[NORMAL] = { %d, %d, %d }\n"
790 "}widget \"gtk-tooltips*\" style \"msw-tooltips\"\n",
791 tooltip_back.red, tooltip_back.green, tooltip_back.blue);
792 gtk_rc_parse_string (buf);
794 /* enable font theming for status bars */
795 font_ptr = sys_font_to_pango_font (XP_THEME_CLASS_STATUS, XP_THEME_FONT_STATUS,
796 font_buf, sizeof (font_buf));
797 g_snprintf (buf, sizeof (buf),
798 "style \"msw-status\" = \"msw-default\"\n" "{%s = \"%s\"\n"
799 "bg[NORMAL] = { %d, %d, %d }\n"
800 "}widget_class \"*Status*\" style \"msw-status\"\n",
801 (font_ptr ? "font_name" : "#"),
802 (font_ptr ? font_ptr : " font name should go here"),
803 btn_face.red, btn_face.green, btn_face.blue);
804 gtk_rc_parse_string (buf);
806 /* enable coloring for text on buttons TODO: use GetThemeMetric for the
807 border and outside border */
808 g_snprintf (buf, sizeof (buf),
809 "style \"msw-button\" = \"msw-default\"\n"
811 "bg[NORMAL] = { %d, %d, %d }\n"
812 "bg[PRELIGHT] = { %d, %d, %d }\n"
813 "bg[INSENSITIVE] = { %d, %d, %d }\n"
814 "fg[PRELIGHT] = { %d, %d, %d }\n"
815 "GtkButton::default-border = { 0, 0, 0, 0 }\n"
816 "GtkButton::default-outside-border = { 0, 0, 0, 0 }\n"
817 "GtkButton::child-displacement-x = 1\n"
818 "GtkButton::child-displacement-y = 1\n"
819 "GtkButton::focus-padding = %d\n"
820 "}widget_class \"*Button*\" style \"msw-button\"\n",
821 btn_face.red, btn_face.green, btn_face.blue,
822 btn_face.red, btn_face.green, btn_face.blue,
823 btn_face.red, btn_face.green, btn_face.blue,
824 btn_fore.red, btn_fore.green, btn_fore.blue,
825 xp_theme_is_active ()? 1 : 2);
826 gtk_rc_parse_string (buf);
828 /* enable coloring for progress bars */
829 g_snprintf (buf, sizeof (buf),
830 "style \"msw-progress\" = \"msw-default\"\n"
831 "{bg[PRELIGHT] = { %d, %d, %d }\n"
832 "bg[NORMAL] = { %d, %d, %d }\n"
833 "}widget_class \"*Progress*\" style \"msw-progress\"\n",
837 btn_face.red, btn_face.green, btn_face.blue);
838 gtk_rc_parse_string (buf);
840 /* scrollbar thumb width and height */
841 g_snprintf (buf, sizeof (buf),
842 "style \"msw-vscrollbar\" = \"msw-default\"\n"
843 "{GtkRange::slider-width = %d\n"
844 "GtkRange::stepper-size = %d\n"
845 "GtkRange::stepper-spacing = 0\n"
846 "GtkRange::trough_border = 0\n"
847 "GtkScale::slider-length = %d\n"
848 "GtkScrollbar::min-slider-length = 8\n"
849 "}widget_class \"*VScrollbar*\" style \"msw-vscrollbar\"\n"
850 "widget_class \"*VScale*\" style \"msw-vscrollbar\"\n",
851 GetSystemMetrics (SM_CYVTHUMB),
852 get_system_metric (XP_THEME_CLASS_SCROLLBAR, SM_CXVSCROLL), 11);
853 gtk_rc_parse_string (buf);
855 g_snprintf (buf, sizeof (buf),
856 "style \"msw-hscrollbar\" = \"msw-default\"\n"
857 "{GtkRange::slider-width = %d\n"
858 "GtkRange::stepper-size = %d\n"
859 "GtkRange::stepper-spacing = 0\n"
860 "GtkRange::trough_border = 0\n"
861 "GtkScale::slider-length = %d\n"
862 "GtkScrollbar::min-slider-length = 8\n"
863 "}widget_class \"*HScrollbar*\" style \"msw-hscrollbar\"\n"
864 "widget_class \"*HScale*\" style \"msw-hscrollbar\"\n",
865 GetSystemMetrics (SM_CXHTHUMB),
866 get_system_metric (XP_THEME_CLASS_SCROLLBAR, SM_CYHSCROLL), 11);
867 gtk_rc_parse_string (buf);
869 gtk_rc_parse_string ("style \"msw-scrolled-window\" = \"msw-default\"\n"
870 "{GtkScrolledWindow::scrollbars-within-bevel = 1}\n"
871 "class \"GtkScrolledWindow\" style \"msw-scrolled-window\"\n");
873 /* radio/check button sizes */
874 g_snprintf (buf, sizeof (buf),
875 "style \"msw-checkbutton\" = \"msw-button\"\n"
876 "{GtkCheckButton::indicator-size = 13\n"
877 "}widget_class \"*CheckButton*\" style \"msw-checkbutton\"\n"
878 "widget_class \"*RadioButton*\" style \"msw-checkbutton\"\n");
879 gtk_rc_parse_string (buf);
881 /* size of combo box toggle button */
882 g_snprintf (buf, sizeof (buf),
883 "style \"msw-combobox-button\" = \"msw-default\"\n"
887 "GtkButton::default-border = { 0, 0, 0, 0 }\n"
888 "GtkButton::default-outside-border = { 0, 0, 0, 0 }\n"
889 "GtkButton::child-displacement-x = 0\n"
890 "GtkButton::child-displacement-y = 0\n"
891 "GtkWidget::focus-padding = 0\n"
892 "GtkWidget::focus-line-width = 0\n"
894 "widget_class \"*ComboBox*ToggleButton*\" style \"msw-combobox-button\"\n");
895 gtk_rc_parse_string (buf);
897 g_snprintf (buf, sizeof (buf),
898 "style \"msw-combobox\" = \"msw-default\"\n"
900 "GtkComboBox::shadow-type = in\n"
904 "class \"GtkComboBox\" style \"msw-combobox\"\n",
905 GetSystemMetrics (SM_CXEDGE), GetSystemMetrics (SM_CYEDGE));
906 gtk_rc_parse_string (buf);
908 /* size of tree view header */
909 g_snprintf (buf, sizeof (buf),
910 "style \"msw-header-button\" = \"msw-default\"\n"
914 "GtkButton::default-border = { 0, 0, 0, 0 }\n"
915 "GtkButton::default-outside-border = { 0, 0, 0, 0 }\n"
916 "GtkButton::child-displacement-x = 1\n"
917 "GtkButton::child-displacement-y = 1\n"
918 "GtkWidget::focus-padding = 0\n"
919 "GtkWidget::focus-line-width = 0\n"
921 "widget_class \"*TreeView*Button*\" style \"msw-header-button\"\n",
922 xp_theme_is_active ()? 2 : 0);
923 gtk_rc_parse_string (buf);
925 /* FIXME: This should be enabled once gtk+ support GtkNotebok::prelight-tab */
926 /* enable prelight tab of GtkNotebook */
928 g_snprintf (buf, sizeof (buf),
929 "style \"msw-notebook\" = \"msw-default\"\n"
930 "{GtkNotebook::prelight-tab=1\n"
931 "}widget_class \"*Notebook*\" style \"msw-notebook\"\n");
932 gtk_rc_parse_string (buf);
935 /* FIXME: This should be enabled once gtk+ support GtkTreeView::full-row-focus */
937 g_snprintf (buf, sizeof (buf),
938 "style \"msw-treeview\" = \"msw-default\"\n"
939 "{GtkTreeView::full-row-focus=0\n"
940 "}widget_class \"*TreeView*\" style \"msw-treeview\"\n");
941 gtk_rc_parse_string (buf);
946 setup_system_styles (GtkStyle *style)
950 /* Default background */
951 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
952 &style->bg[GTK_STATE_NORMAL]);
953 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT,
954 &style->bg[GTK_STATE_SELECTED]);
955 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
956 &style->bg[GTK_STATE_INSENSITIVE]);
957 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
958 &style->bg[GTK_STATE_ACTIVE]);
959 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
960 &style->bg[GTK_STATE_PRELIGHT]);
963 sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOW,
964 &style->base[GTK_STATE_NORMAL]);
965 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT,
966 &style->base[GTK_STATE_SELECTED]);
967 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
968 &style->base[GTK_STATE_INSENSITIVE]);
969 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
970 &style->base[GTK_STATE_ACTIVE]);
971 sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOW,
972 &style->base[GTK_STATE_PRELIGHT]);
975 sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT,
976 &style->text[GTK_STATE_NORMAL]);
977 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT,
978 &style->text[GTK_STATE_SELECTED]);
979 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_GRAYTEXT,
980 &style->text[GTK_STATE_INSENSITIVE]);
981 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT,
982 &style->text[GTK_STATE_ACTIVE]);
983 sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT,
984 &style->text[GTK_STATE_PRELIGHT]);
986 /* Default foreground */
987 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT,
988 &style->fg[GTK_STATE_NORMAL]);
989 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT,
990 &style->fg[GTK_STATE_SELECTED]);
991 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_GRAYTEXT,
992 &style->fg[GTK_STATE_INSENSITIVE]);
993 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT,
994 &style->fg[GTK_STATE_ACTIVE]);
995 sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT,
996 &style->fg[GTK_STATE_PRELIGHT]);
998 for (i = 0; i < 5; i++)
1000 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_3DSHADOW,
1002 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_3DHILIGHT,
1005 style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2;
1006 style->mid[i].green =
1007 (style->light[i].green + style->dark[i].green) / 2;
1008 style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2;
1010 style->text_aa[i].red = (style->text[i].red + style->base[i].red) / 2;
1011 style->text_aa[i].green =
1012 (style->text[i].green + style->base[i].green) / 2;
1013 style->text_aa[i].blue =
1014 (style->text[i].blue + style->base[i].blue) / 2;
1019 sanitize_size (GdkWindow *window, gint *width, gint *height)
1021 gboolean set_bg = FALSE;
1023 if ((*width == -1) && (*height == -1))
1025 set_bg = GDK_IS_WINDOW (window);
1026 gdk_drawable_get_size (window, width, height);
1028 else if (*width == -1)
1030 gdk_drawable_get_size (window, width, NULL);
1032 else if (*height == -1)
1034 gdk_drawable_get_size (window, NULL, height);
1040 static XpThemeElement
1041 map_gtk_progress_bar_to_xp (GtkProgressBar *progress_bar, gboolean trough)
1045 switch (progress_bar->orientation)
1047 case GTK_PROGRESS_LEFT_TO_RIGHT:
1048 case GTK_PROGRESS_RIGHT_TO_LEFT:
1050 ? XP_THEME_ELEMENT_PROGRESS_TROUGH_H
1051 : XP_THEME_ELEMENT_PROGRESS_BAR_H;
1056 ? XP_THEME_ELEMENT_PROGRESS_TROUGH_V
1057 : XP_THEME_ELEMENT_PROGRESS_BAR_V;
1065 is_combo_box_child (GtkWidget *w)
1072 for (tmp = w->parent; tmp; tmp = tmp->parent)
1074 if (GTK_IS_COMBO_BOX (tmp))
1082 combo_box_draw_arrow (GtkStyle *style,
1085 GdkRectangle *area, GtkWidget *widget)
1087 if (xp_theme_is_active ())
1090 if (widget && GTK_IS_TOGGLE_BUTTON (widget->parent))
1096 dc = get_window_dc (style, window, state, area->x, area->y, area->width,
1097 area->height, &rect);
1098 border = (GTK_TOGGLE_BUTTON (widget->parent)->
1099 active ? DFCS_PUSHED | DFCS_FLAT : 0);
1101 InflateRect (&rect, 1, 1);
1102 DrawFrameControl (dc, &rect, DFC_SCROLL, DFCS_SCROLLDOWN | border);
1104 release_window_dc (style, window, state);
1113 draw_part (GdkDrawable *drawable,
1114 GdkGC *gc, GdkRectangle *area, gint x, gint y, Part part)
1117 gdk_gc_set_clip_rectangle (gc, area);
1119 if (!parts[part].bmap)
1121 parts[part].bmap = gdk_bitmap_create_from_data (drawable,
1123 PART_SIZE, PART_SIZE);
1126 gdk_gc_set_ts_origin (gc, x, y);
1127 gdk_gc_set_stipple (gc, parts[part].bmap);
1128 gdk_gc_set_fill (gc, GDK_STIPPLED);
1130 gdk_draw_rectangle (drawable, gc, TRUE, x, y, PART_SIZE, PART_SIZE);
1132 gdk_gc_set_fill (gc, GDK_SOLID);
1135 gdk_gc_set_clip_rectangle (gc, NULL);
1139 draw_check (GtkStyle *style,
1142 GtkShadowType shadow,
1145 const gchar *detail, gint x, gint y, gint width, gint height)
1147 x -= (1 + PART_SIZE - width) / 2;
1148 y -= (1 + PART_SIZE - height) / 2;
1150 if (detail && strcmp (detail, "check") == 0) /* Menu item */
1152 if (shadow == GTK_SHADOW_IN)
1154 draw_part (window, style->black_gc, area, x, y, CHECK_TEXT);
1155 draw_part (window, style->dark_gc[state], area, x, y, CHECK_AA);
1160 XpThemeElement theme_elt = XP_THEME_ELEMENT_CHECKBOX;
1163 case GTK_SHADOW_ETCHED_IN:
1164 theme_elt = XP_THEME_ELEMENT_INCONSISTENT_CHECKBOX;
1168 theme_elt = XP_THEME_ELEMENT_PRESSED_CHECKBOX;
1175 if (!xp_theme_draw (window, theme_elt,
1176 style, x, y, width, height, state, area))
1178 if (detail && !strcmp (detail, "cellcheck"))
1179 state = GTK_STATE_NORMAL;
1181 draw_part (window, style->black_gc, area, x, y, CHECK_BLACK);
1182 draw_part (window, style->dark_gc[state], area, x, y, CHECK_DARK);
1183 draw_part (window, style->mid_gc[state], area, x, y, CHECK_MID);
1184 draw_part (window, style->light_gc[state], area, x, y, CHECK_LIGHT);
1185 draw_part (window, style->base_gc[state], area, x, y, CHECK_BASE);
1187 if (shadow == GTK_SHADOW_IN)
1189 draw_part (window, style->text_gc[state], area, x,
1191 draw_part (window, style->text_aa_gc[state], area,
1194 else if (shadow == GTK_SHADOW_ETCHED_IN)
1196 draw_part (window, style->text_gc[state], area, x, y,
1197 CHECK_INCONSISTENT);
1198 draw_part (window, style->text_aa_gc[state], area, x, y,
1206 draw_expander (GtkStyle *style,
1211 const gchar *detail,
1212 gint x, gint y, GtkExpanderStyle expander_style)
1215 gint expander_semi_size;
1216 XpThemeElement xp_expander;
1218 gtk_widget_style_get (widget, "expander_size", &expander_size, NULL);
1220 switch (expander_style)
1222 case GTK_EXPANDER_COLLAPSED:
1223 case GTK_EXPANDER_SEMI_COLLAPSED:
1224 xp_expander = XP_THEME_ELEMENT_TREEVIEW_EXPANDER_CLOSED;
1228 xp_expander = XP_THEME_ELEMENT_TREEVIEW_EXPANDER_OPENED;
1232 if ((expander_size % 2) == 0)
1235 if (expander_size > 2)
1239 gdk_gc_set_clip_rectangle (style->fg_gc[state], area);
1241 expander_semi_size = expander_size / 2;
1242 x -= expander_semi_size;
1243 y -= expander_semi_size;
1245 if (!xp_theme_draw (window, xp_expander, style,
1246 x, y, expander_size, expander_size, state, area))
1253 dc = get_window_dc (style, window, state, x, y, expander_size,
1254 expander_size, &rect);
1255 FrameRect (dc, &rect, GetSysColorBrush (COLOR_GRAYTEXT));
1256 InflateRect (&rect, -1, -1);
1257 FillRect (dc, &rect,
1258 GetSysColorBrush (state ==
1259 GTK_STATE_INSENSITIVE ? COLOR_BTNFACE :
1262 InflateRect (&rect, -1, -1);
1264 pen = CreatePen (PS_SOLID, 1, GetSysColor (COLOR_WINDOWTEXT));
1265 old_pen = SelectObject (dc, pen);
1267 MoveToEx (dc, rect.left, rect.top - 2 + expander_semi_size, NULL);
1268 LineTo (dc, rect.right, rect.top - 2 + expander_semi_size);
1270 if (expander_style == GTK_EXPANDER_COLLAPSED ||
1271 expander_style == GTK_EXPANDER_SEMI_COLLAPSED)
1273 MoveToEx (dc, rect.left - 2 + expander_semi_size, rect.top, NULL);
1274 LineTo (dc, rect.left - 2 + expander_semi_size, rect.bottom);
1277 SelectObject (dc, old_pen);
1279 release_window_dc (style, window, state);
1283 gdk_gc_set_clip_rectangle (style->fg_gc[state], NULL);
1287 draw_option (GtkStyle *style,
1290 GtkShadowType shadow,
1293 const gchar *detail, gint x, gint y, gint width, gint height)
1295 x -= (1 + PART_SIZE - width) / 2;
1296 y -= (1 + PART_SIZE - height) / 2;
1298 if (detail && strcmp (detail, "option") == 0) /* Menu item */
1300 if (shadow == GTK_SHADOW_IN)
1302 draw_part (window, style->fg_gc[state], area, x, y, RADIO_TEXT);
1307 if (xp_theme_draw (window, shadow == GTK_SHADOW_IN
1308 ? XP_THEME_ELEMENT_PRESSED_RADIO_BUTTON
1309 : XP_THEME_ELEMENT_RADIO_BUTTON,
1310 style, x, y, width, height, state, area))
1315 if (detail && !strcmp (detail, "cellradio"))
1316 state = GTK_STATE_NORMAL;
1318 draw_part (window, style->black_gc, area, x, y, RADIO_BLACK);
1319 draw_part (window, style->dark_gc[state], area, x, y, RADIO_DARK);
1320 draw_part (window, style->mid_gc[state], area, x, y, RADIO_MID);
1321 draw_part (window, style->light_gc[state], area, x, y, RADIO_LIGHT);
1322 draw_part (window, style->base_gc[state], area, x, y, RADIO_BASE);
1324 if (shadow == GTK_SHADOW_IN)
1325 draw_part (window, style->text_gc[state], area, x, y, RADIO_TEXT);
1331 draw_varrow (GdkWindow *window,
1333 GtkShadowType shadow_type,
1335 GtkArrowType arrow_type, gint x, gint y, gint width, gint height)
1338 gint y_start, y_increment;
1342 gdk_gc_set_clip_rectangle (gc, area);
1344 width = width + width % 2 - 1; /* Force odd */
1345 steps = 1 + width / 2;
1346 extra = height - steps;
1348 if (arrow_type == GTK_ARROW_DOWN)
1355 y_start = y + height - 1;
1359 for (i = extra; i < height; i++)
1361 gdk_draw_line (window, gc,
1362 x + (i - extra), y_start + i * y_increment,
1363 x + width - (i - extra) - 1, y_start + i * y_increment);
1367 gdk_gc_set_clip_rectangle (gc, NULL);
1371 draw_harrow (GdkWindow *window,
1373 GtkShadowType shadow_type,
1375 GtkArrowType arrow_type, gint x, gint y, gint width, gint height)
1378 gint x_start, x_increment;
1382 gdk_gc_set_clip_rectangle (gc, area);
1384 height = height + height % 2 - 1; /* Force odd */
1385 steps = 1 + height / 2;
1386 extra = width - steps;
1388 if (arrow_type == GTK_ARROW_RIGHT)
1395 x_start = x + width - 1;
1399 for (i = extra; i < width; i++)
1401 gdk_draw_line (window, gc,
1402 x_start + i * x_increment, y + (i - extra),
1403 x_start + i * x_increment, y + height - (i - extra) - 1);
1408 gdk_gc_set_clip_rectangle (gc, NULL);
1411 /* This function makes up for some brokeness in gtkrange.c
1412 * where we never get the full arrow of the stepper button
1413 * and the type of button in a single drawing function.
1415 * It doesn't work correctly when the scrollbar is squished
1416 * to the point we don't have room for full-sized steppers.
1419 reverse_engineer_stepper_box (GtkWidget *range,
1420 GtkArrowType arrow_type,
1421 gint *x, gint *y, gint *width, gint *height)
1423 gint slider_width = 14, stepper_size = 14;
1429 gtk_widget_style_get (range,
1430 "slider_width", &slider_width,
1431 "stepper_size", &stepper_size, NULL);
1434 if (arrow_type == GTK_ARROW_UP || arrow_type == GTK_ARROW_DOWN)
1436 box_width = slider_width;
1437 box_height = stepper_size;
1441 box_width = stepper_size;
1442 box_height = slider_width;
1445 *x = *x - (box_width - *width) / 2;
1446 *y = *y - (box_height - *height) / 2;
1448 *height = box_height;
1451 static XpThemeElement
1452 to_xp_arrow (GtkArrowType arrow_type)
1454 XpThemeElement xp_arrow;
1459 xp_arrow = XP_THEME_ELEMENT_ARROW_UP;
1462 case GTK_ARROW_DOWN:
1463 xp_arrow = XP_THEME_ELEMENT_ARROW_DOWN;
1466 case GTK_ARROW_LEFT:
1467 xp_arrow = XP_THEME_ELEMENT_ARROW_LEFT;
1471 xp_arrow = XP_THEME_ELEMENT_ARROW_RIGHT;
1479 draw_arrow (GtkStyle *style,
1482 GtkShadowType shadow,
1485 const gchar *detail,
1486 GtkArrowType arrow_type,
1487 gboolean fill, gint x, gint y, gint width, gint height)
1493 name = gtk_widget_get_name (widget);
1495 sanitize_size (window, &width, &height);
1497 if (GTK_IS_ARROW (widget) && is_combo_box_child (widget))
1499 if (combo_box_draw_arrow (style, window, state, area, widget))
1505 if (detail && strcmp (detail, "spinbutton") == 0)
1507 if (xp_theme_is_drawable (XP_THEME_ELEMENT_SPIN_BUTTON_UP))
1514 if (arrow_type == GTK_ARROW_DOWN)
1518 if (state == GTK_STATE_ACTIVE)
1524 draw_varrow (window, style->fg_gc[state], shadow, area,
1525 arrow_type, x, y, width, height);
1529 else if (detail && (!strcmp (detail, "vscrollbar")
1530 || !strcmp (detail, "hscrollbar")))
1532 gboolean is_disabled = FALSE;
1534 GtkScrollbar *scrollbar = GTK_SCROLLBAR (widget);
1538 gint box_width = width;
1539 gint box_height = height;
1541 reverse_engineer_stepper_box (widget, arrow_type,
1542 &box_x, &box_y, &box_width, &box_height);
1544 if (scrollbar->range.adjustment->page_size >=
1545 (scrollbar->range.adjustment->upper -
1546 scrollbar->range.adjustment->lower))
1551 if (xp_theme_draw (window, to_xp_arrow (arrow_type), style, box_x, box_y,
1552 box_width, box_height, state, area))
1560 btn_type = DFCS_SCROLLUP;
1563 case GTK_ARROW_DOWN:
1564 btn_type = DFCS_SCROLLDOWN;
1567 case GTK_ARROW_LEFT:
1568 btn_type = DFCS_SCROLLLEFT;
1571 case GTK_ARROW_RIGHT:
1572 btn_type = DFCS_SCROLLRIGHT;
1575 case GTK_ARROW_NONE:
1579 if (state == GTK_STATE_INSENSITIVE)
1581 btn_type |= DFCS_INACTIVE;
1586 sanitize_size (window, &width, &height);
1588 dc = get_window_dc (style, window, state,
1589 box_x, box_y, box_width, box_height, &rect);
1590 DrawFrameControl (dc, &rect, DFC_SCROLL,
1591 btn_type | (shadow ==
1592 GTK_SHADOW_IN ? (DFCS_PUSHED |
1594 release_window_dc (style, window, state);
1600 /* draw the toolbar chevrons - waiting for GTK 2.4 */
1601 if (name && !strcmp (name, "gtk-toolbar-arrow"))
1604 (window, XP_THEME_ELEMENT_REBAR_CHEVRON, style, x, y,
1605 width, height, state, area))
1610 /* probably a gtk combo box on a toolbar */
1611 else if (0 /* widget->parent && GTK_IS_BUTTON
1612 (widget->parent) */ )
1615 (window, XP_THEME_ELEMENT_COMBOBUTTON, style, x - 3,
1616 widget->allocation.y + 1, width + 5,
1617 widget->allocation.height - 4, state, area))
1623 if (arrow_type == GTK_ARROW_UP || arrow_type == GTK_ARROW_DOWN)
1625 x += (width - 7) / 2;
1626 y += (height - 5) / 2;
1628 draw_varrow (window, style->fg_gc[state], shadow, area,
1629 arrow_type, x, y, 7, 5);
1633 x += (width - 5) / 2;
1634 y += (height - 7) / 2;
1636 draw_harrow (window, style->fg_gc[state], shadow, area,
1637 arrow_type, x, y, 5, 7);
1643 option_menu_get_props (GtkWidget *widget,
1644 GtkRequisition *indicator_size,
1645 GtkBorder *indicator_spacing)
1647 GtkRequisition *tmp_size = NULL;
1648 GtkBorder *tmp_spacing = NULL;
1651 gtk_widget_style_get (widget,
1652 "indicator_size", &tmp_size,
1653 "indicator_spacing", &tmp_spacing, NULL);
1657 *indicator_size = *tmp_size;
1658 gtk_requisition_free (tmp_size);
1662 *indicator_size = default_option_indicator_size;
1667 *indicator_spacing = *tmp_spacing;
1668 gtk_border_free (tmp_spacing);
1672 *indicator_spacing = default_option_indicator_spacing;
1677 is_toolbar_child (GtkWidget *wid)
1681 if (GTK_IS_TOOLBAR (wid) || GTK_IS_HANDLE_BOX (wid))
1691 is_menu_tool_button_child (GtkWidget *wid)
1695 if (GTK_IS_MENU_TOOL_BUTTON (wid))
1704 get_window_dc (GtkStyle *style, GdkWindow *window, GtkStateType state_type,
1705 gint x, gint y, gint width, gint height, RECT *rect)
1708 GdkDrawable *drawable;
1710 if (!GDK_IS_WINDOW (window))
1718 gdk_window_get_internal_paint_info (window, &drawable, &xoff, &yoff);
1721 rect->left = x - xoff;
1722 rect->top = y - yoff;
1723 rect->right = rect->left + width;
1724 rect->bottom = rect->top + height;
1726 return gdk_win32_hdc_get (drawable, style->dark_gc[state_type], 0);
1730 release_window_dc (GtkStyle *style, GdkWindow *window,
1731 GtkStateType state_type)
1733 GdkDrawable *drawable;
1735 if (!GDK_IS_WINDOW (window))
1741 gdk_window_get_internal_paint_info (window, &drawable, NULL, NULL);
1744 gdk_win32_hdc_release (drawable, style->dark_gc[state_type], 0);
1752 g_light_pen = CreatePen (PS_SOLID | PS_INSIDEFRAME, 1,
1753 GetSysColor (COLOR_BTNHIGHLIGHT));
1764 g_dark_pen = CreatePen (PS_SOLID | PS_INSIDEFRAME, 1,
1765 GetSysColor (COLOR_BTNSHADOW));
1772 draw_3d_border (HDC hdc, RECT *rc, gboolean sunken)
1779 pen1 = get_dark_pen ();
1780 pen2 = get_light_pen ();
1784 pen1 = get_light_pen ();
1785 pen2 = get_dark_pen ();
1788 MoveToEx (hdc, rc->left, rc->bottom - 1, NULL);
1790 old_pen = SelectObject (hdc, pen1);
1791 LineTo (hdc, rc->left, rc->top);
1792 LineTo (hdc, rc->right - 1, rc->top);
1793 SelectObject (hdc, old_pen);
1795 old_pen = SelectObject (hdc, pen2);
1796 LineTo (hdc, rc->right - 1, rc->bottom - 1);
1797 LineTo (hdc, rc->left, rc->bottom - 1);
1798 SelectObject (hdc, old_pen);
1802 draw_menu_item (GdkWindow *window, GtkWidget *widget, GtkStyle *style,
1803 gint x, gint y, gint width, gint height,
1804 GtkStateType state_type, GdkRectangle *area)
1811 if ((parent = gtk_widget_get_parent (widget))
1812 && GTK_IS_MENU_BAR (parent) && !xp_theme_is_active ())
1814 bar = GTK_MENU_SHELL (parent);
1816 dc = get_window_dc (style, window, state_type, x, y, width, height, &rect);
1818 if (state_type == GTK_STATE_PRELIGHT)
1820 draw_3d_border (dc, &rect, bar->active);
1823 release_window_dc (style, window, state_type);
1832 get_dither_brush (void)
1835 HBITMAP pattern_bmp;
1839 return g_dither_brush;
1841 for (i = 0; i < 8; i++)
1843 pattern[i] = (WORD) (0x5555 << (i & 1));
1846 pattern_bmp = CreateBitmap (8, 8, 1, 1, &pattern);
1850 g_dither_brush = CreatePatternBrush (pattern_bmp);
1851 DeleteObject (pattern_bmp);
1854 return g_dither_brush;
1858 draw_tool_button (GdkWindow *window, GtkWidget *widget, GtkStyle *style,
1859 gint x, gint y, gint width, gint height,
1860 GtkStateType state_type, GdkRectangle *area)
1864 gboolean is_toggled = FALSE;
1866 if (xp_theme_is_active ())
1868 return (xp_theme_draw (window, XP_THEME_ELEMENT_TOOLBAR_BUTTON, style,
1869 x, y, width, height, state_type, area));
1872 if (GTK_IS_TOGGLE_BUTTON (widget))
1874 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
1880 if (state_type != GTK_STATE_PRELIGHT
1881 && state_type != GTK_STATE_ACTIVE && !is_toggled)
1886 dc = get_window_dc (style, window, state_type, x, y, width, height, &rect);
1887 if (state_type == GTK_STATE_PRELIGHT)
1891 FillRect (dc, &rect, GetSysColorBrush (COLOR_BTNFACE));
1894 draw_3d_border (dc, &rect, is_toggled);
1896 else if (state_type == GTK_STATE_ACTIVE)
1898 if (is_toggled && !is_menu_tool_button_child (widget->parent))
1900 SetTextColor (dc, GetSysColor (COLOR_3DHILIGHT));
1901 SetBkColor (dc, GetSysColor (COLOR_BTNFACE));
1902 FillRect (dc, &rect, get_dither_brush ());
1905 draw_3d_border (dc, &rect, TRUE);
1908 release_window_dc (style, window, state_type);
1914 draw_push_button (GdkWindow *window, GtkWidget *widget, GtkStyle *style,
1915 gint x, gint y, gint width, gint height,
1916 GtkStateType state_type, gboolean is_default)
1921 dc = get_window_dc (style, window, state_type, x, y, width, height, &rect);
1923 if (GTK_IS_TOGGLE_BUTTON (widget))
1925 if (state_type == GTK_STATE_PRELIGHT &&
1926 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
1928 state_type = GTK_STATE_ACTIVE;
1932 if (state_type == GTK_STATE_ACTIVE)
1934 if (GTK_IS_TOGGLE_BUTTON (widget))
1936 DrawEdge (dc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1937 SetTextColor (dc, GetSysColor (COLOR_3DHILIGHT));
1938 SetBkColor (dc, GetSysColor (COLOR_BTNFACE));
1939 FillRect (dc, &rect, get_dither_brush ());
1943 FrameRect (dc, &rect, GetSysColorBrush (COLOR_WINDOWFRAME));
1944 InflateRect (&rect, -1, -1);
1945 FrameRect (dc, &rect, GetSysColorBrush (COLOR_BTNSHADOW));
1946 InflateRect (&rect, -1, -1);
1947 FillRect (dc, &rect, GetSysColorBrush (COLOR_BTNFACE));
1952 if (is_default || GTK_WIDGET_HAS_FOCUS (widget))
1954 FrameRect (dc, &rect, GetSysColorBrush (COLOR_WINDOWFRAME));
1955 InflateRect (&rect, -1, -1);
1958 DrawFrameControl (dc, &rect, DFC_BUTTON, DFCS_BUTTONPUSH);
1961 release_window_dc (style, window, state_type);
1965 draw_box (GtkStyle *style,
1967 GtkStateType state_type,
1968 GtkShadowType shadow_type,
1971 const gchar *detail, gint x, gint y, gint width, gint height)
1973 if (is_combo_box_child (widget) && detail && !strcmp (detail, "button"))
1979 dc = get_window_dc (style, window, state_type, x, y, width - cx, height, &rect);
1980 FillRect (dc, &rect, GetSysColorBrush (COLOR_WINDOW));
1981 release_window_dc (style, window, state_type);
1983 cx = 2 * GetSystemMetrics (SM_CXEDGE) + 16; /* TODO evaluate arrow width */
1987 if (xp_theme_is_active ()
1988 && xp_theme_draw (window, XP_THEME_ELEMENT_COMBOBUTTON, style, x, y,
1989 width, height, state_type, area))
1996 (!strcmp (detail, "button") || !strcmp (detail, "buttondefault")))
1998 if (GTK_IS_TREE_VIEW (widget->parent) || GTK_IS_CLIST (widget->parent))
2001 (window, XP_THEME_ELEMENT_LIST_HEADER, style, x, y,
2002 width, height, state_type, area))
2010 dc = get_window_dc (style, window, state_type, x, y, width, height, &rect);
2012 DrawFrameControl (dc, &rect, DFC_BUTTON, DFCS_BUTTONPUSH |
2014 GTK_STATE_ACTIVE ? (DFCS_PUSHED | DFCS_FLAT)
2016 release_window_dc (style, window, state_type);
2019 else if (is_toolbar_child (widget->parent)
2020 || (!GTK_IS_BUTTON (widget) ||
2021 (GTK_RELIEF_NONE == gtk_button_get_relief (GTK_BUTTON (widget)))))
2023 if (draw_tool_button (window, widget, style, x, y,
2024 width, height, state_type, area))
2031 gboolean is_default = GTK_WIDGET_HAS_DEFAULT (widget);
2034 is_default ? XP_THEME_ELEMENT_DEFAULT_BUTTON :
2035 XP_THEME_ELEMENT_BUTTON, style, x, y, width, height,
2041 draw_push_button (window, widget, style,
2042 x, y, width, height, state_type, is_default);
2049 else if (detail && !strcmp (detail, "spinbutton"))
2051 if (xp_theme_is_drawable (XP_THEME_ELEMENT_SPIN_BUTTON_UP))
2056 else if (detail && (!strcmp (detail, "spinbutton_up")
2057 || !strcmp (detail, "spinbutton_down")))
2059 if (!xp_theme_draw (window,
2060 (!strcmp (detail, "spinbutton_up"))
2061 ? XP_THEME_ELEMENT_SPIN_BUTTON_UP
2062 : XP_THEME_ELEMENT_SPIN_BUTTON_DOWN,
2063 style, x, y, width, height, state_type, area))
2068 dc = get_window_dc (style, window, state_type,
2069 x, y, width, height, &rect);
2070 DrawEdge (dc, &rect,
2072 GTK_STATE_ACTIVE ? EDGE_SUNKEN : EDGE_RAISED, BF_RECT);
2073 release_window_dc (style, window, state_type);
2077 else if (detail && !strcmp (detail, "slider"))
2079 if (GTK_IS_SCROLLBAR (widget))
2081 GtkScrollbar *scrollbar = GTK_SCROLLBAR (widget);
2082 gboolean is_v = GTK_IS_VSCROLLBAR (widget);
2084 if (xp_theme_draw (window,
2086 ? XP_THEME_ELEMENT_SCROLLBAR_V
2087 : XP_THEME_ELEMENT_SCROLLBAR_H,
2088 style, x, y, width, height, state_type, area))
2090 XpThemeElement gripper =
2091 (is_v ? XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V :
2092 XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H);
2094 /* Do not display grippers on tiny scroll bars,
2095 the limit imposed is rather arbitrary, perhaps
2096 we can fetch the gripper geometry from
2097 somewhere and use that... */
2099 XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H
2102 XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V && height < 16))
2107 xp_theme_draw (window, gripper, style, x, y,
2108 width, height, state_type, area);
2113 if (scrollbar->range.adjustment->page_size >=
2114 (scrollbar->range.adjustment->upper -
2115 scrollbar->range.adjustment->lower))
2122 else if (detail && !strcmp (detail, "bar"))
2124 if (widget && GTK_IS_PROGRESS_BAR (widget))
2126 GtkProgressBar *progress_bar = GTK_PROGRESS_BAR (widget);
2127 XpThemeElement xp_progress_bar =
2128 map_gtk_progress_bar_to_xp (progress_bar, FALSE);
2130 if (xp_theme_draw (window, xp_progress_bar, style, x, y,
2131 width, height, state_type, area))
2136 shadow_type = GTK_SHADOW_NONE;
2139 else if (detail && strcmp (detail, "menuitem") == 0)
2141 shadow_type = GTK_SHADOW_NONE;
2142 if (draw_menu_item (window, widget, style,
2143 x, y, width, height, state_type, area))
2148 else if (detail && !strcmp (detail, "trough"))
2150 if (widget && GTK_IS_PROGRESS_BAR (widget))
2152 GtkProgressBar *progress_bar = GTK_PROGRESS_BAR (widget);
2153 XpThemeElement xp_progress_bar =
2154 map_gtk_progress_bar_to_xp (progress_bar, TRUE);
2156 (window, xp_progress_bar, style, x, y, width, height,
2163 /* Blank in classic Windows */
2166 else if (widget && GTK_IS_SCROLLBAR (widget))
2168 gboolean is_vertical = GTK_IS_VSCROLLBAR (widget);
2170 if (xp_theme_draw (window,
2172 ? XP_THEME_ELEMENT_TROUGH_V
2173 : XP_THEME_ELEMENT_TROUGH_H,
2174 style, x, y, width, height, state_type, area))
2183 sanitize_size (window, &width, &height);
2184 dc = get_window_dc (style, window, state_type, x, y, width, height, &rect);
2186 SetTextColor (dc, GetSysColor (COLOR_3DHILIGHT));
2187 SetBkColor (dc, GetSysColor (COLOR_BTNFACE));
2188 FillRect (dc, &rect, get_dither_brush ());
2190 release_window_dc (style, window, state_type);
2195 else if (widget && GTK_IS_SCALE (widget))
2197 gboolean is_vertical = GTK_IS_VSCALE (widget);
2199 if (!xp_theme_is_active ())
2201 parent_class->draw_box (style, window, state_type,
2202 GTK_SHADOW_NONE, area,
2203 widget, detail, x, y, width, height);
2209 (window, XP_THEME_ELEMENT_SCALE_TROUGH_V,
2210 style, (2 * x + width) / 2, y, 2, height,
2216 parent_class->draw_box (style, window, state_type,
2217 GTK_SHADOW_ETCHED_IN,
2219 (2 * x + width) / 2, y, 1, height);
2224 (window, XP_THEME_ELEMENT_SCALE_TROUGH_H,
2225 style, x, (2 * y + height) / 2, width, 2,
2231 parent_class->draw_box (style, window, state_type,
2232 GTK_SHADOW_ETCHED_IN,
2233 area, NULL, NULL, x,
2234 (2 * y + height) / 2, width, 1);
2240 else if (detail && strcmp (detail, "optionmenu") == 0)
2242 if (xp_theme_draw (window, XP_THEME_ELEMENT_EDIT_TEXT,
2243 style, x, y, width, height, state_type, area))
2249 && (strcmp (detail, "vscrollbar") == 0
2250 || strcmp (detail, "hscrollbar") == 0))
2255 && (strcmp (detail, "handlebox_bin") == 0
2256 || strcmp (detail, "toolbar") == 0
2257 || strcmp (detail, "menubar") == 0))
2259 sanitize_size (window, &width, &height);
2260 if (xp_theme_draw (window, XP_THEME_ELEMENT_REBAR,
2261 style, x, y, width, height, state_type, area))
2266 else if (detail && (!strcmp (detail, "handlebox"))) /* grip */
2268 if (!xp_theme_is_active ())
2273 else if (detail && !strcmp (detail, "notebook") && GTK_IS_NOTEBOOK (widget))
2275 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2277 if (xp_theme_draw (window, XP_THEME_ELEMENT_TAB_PANE, style,
2278 x, y, width, height, state_type, area))
2286 const gchar *name = gtk_widget_get_name (widget);
2288 if (name && !strcmp (name, "gtk-tooltips"))
2291 (window, XP_THEME_ELEMENT_TOOLTIP, style, x, y, width,
2292 height, state_type, area))
2302 hdc = get_window_dc (style, window, state_type, x, y, width, height, &rect);
2304 brush = GetSysColorBrush (COLOR_3DDKSHADOW);
2308 FrameRect (hdc, &rect, brush);
2311 InflateRect (&rect, -1, -1);
2312 FillRect (hdc, &rect, (HBRUSH) (COLOR_INFOBK + 1));
2314 release_window_dc (style, window, state_type);
2321 parent_class->draw_box (style, window, state_type, shadow_type, area,
2322 widget, detail, x, y, width, height);
2324 if (detail && strcmp (detail, "optionmenu") == 0)
2326 GtkRequisition indicator_size;
2327 GtkBorder indicator_spacing;
2330 option_menu_get_props (widget, &indicator_size, &indicator_spacing);
2332 sanitize_size (window, &width, &height);
2334 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
2337 x + indicator_size.width + indicator_spacing.left +
2338 indicator_spacing.right;
2342 vline_x = x + width - (indicator_size.width +
2343 indicator_spacing.left +
2344 indicator_spacing.right) - style->xthickness;
2346 parent_class->draw_vline (style, window, state_type, area, widget,
2348 y + style->ythickness + 1,
2349 y + height - style->ythickness - 3, vline_x);
2355 draw_tab (GtkStyle *style,
2358 GtkShadowType shadow,
2361 const gchar *detail, gint x, gint y, gint width, gint height)
2363 GtkRequisition indicator_size;
2364 GtkBorder indicator_spacing;
2368 g_return_if_fail (style != NULL);
2369 g_return_if_fail (window != NULL);
2371 if (detail && !strcmp (detail, "optionmenutab"))
2373 if (xp_theme_draw (window, XP_THEME_ELEMENT_COMBOBUTTON,
2374 style, x - 5, widget->allocation.y + 1,
2375 width + 10, widget->allocation.height - 2,
2382 option_menu_get_props (widget, &indicator_size, &indicator_spacing);
2384 x += (width - indicator_size.width) / 2;
2385 arrow_height = (indicator_size.width + 1) / 2;
2387 y += (height - arrow_height) / 2;
2389 draw_varrow (window, style->black_gc, shadow, area, GTK_ARROW_DOWN,
2390 x, y, indicator_size.width, arrow_height);
2393 /* Draw classic Windows tab - thanks Mozilla!
2394 (no system API for this, but DrawEdge can draw all the parts of a tab) */
2396 DrawTab (HDC hdc, const RECT R, gint32 aPosition, gboolean aSelected,
2397 gboolean aDrawLeft, gboolean aDrawRight)
2399 gint32 leftFlag, topFlag, rightFlag, lightFlag, shadeFlag;
2400 RECT topRect, sideRect, bottomRect, lightRect, shadeRect;
2401 gint32 selectedOffset, lOffset, rOffset;
2403 selectedOffset = aSelected ? 1 : 0;
2404 lOffset = aDrawLeft ? 2 : 0;
2405 rOffset = aDrawRight ? 2 : 0;
2407 /* Get info for tab orientation/position (Left, Top, Right, Bottom) */
2413 rightFlag = BF_BOTTOM;
2414 lightFlag = BF_DIAGONAL_ENDTOPRIGHT;
2415 shadeFlag = BF_DIAGONAL_ENDBOTTOMRIGHT;
2417 SetRect (&topRect, R.left, R.top + lOffset, R.right,
2418 R.bottom - rOffset);
2419 SetRect (&sideRect, R.left + 2, R.top, R.right - 2 + selectedOffset,
2421 SetRect (&bottomRect, R.right - 2, R.top, R.right, R.bottom);
2422 SetRect (&lightRect, R.left, R.top, R.left + 3, R.top + 3);
2423 SetRect (&shadeRect, R.left + 1, R.bottom - 2, R.left + 2,
2430 rightFlag = BF_RIGHT;
2431 lightFlag = BF_DIAGONAL_ENDTOPRIGHT;
2432 shadeFlag = BF_DIAGONAL_ENDBOTTOMRIGHT;
2434 SetRect (&topRect, R.left + lOffset, R.top, R.right - rOffset,
2436 SetRect (&sideRect, R.left, R.top + 2, R.right,
2437 R.bottom - 1 + selectedOffset);
2438 SetRect (&bottomRect, R.left, R.bottom - 1, R.right, R.bottom);
2439 SetRect (&lightRect, R.left, R.top, R.left + 3, R.top + 3);
2440 SetRect (&shadeRect, R.right - 2, R.top + 1, R.right - 1, R.top + 2);
2446 rightFlag = BF_BOTTOM;
2447 lightFlag = BF_DIAGONAL_ENDTOPLEFT;
2448 shadeFlag = BF_DIAGONAL_ENDBOTTOMLEFT;
2450 SetRect (&topRect, R.left, R.top + lOffset, R.right,
2451 R.bottom - rOffset);
2452 SetRect (&sideRect, R.left + 2 - selectedOffset, R.top, R.right - 2,
2454 SetRect (&bottomRect, R.left, R.top, R.left + 2, R.bottom);
2455 SetRect (&lightRect, R.right - 3, R.top, R.right - 1, R.top + 2);
2456 SetRect (&shadeRect, R.right - 2, R.bottom - 3, R.right, R.bottom - 1);
2461 topFlag = BF_BOTTOM;
2462 rightFlag = BF_RIGHT;
2463 lightFlag = BF_DIAGONAL_ENDTOPLEFT;
2464 shadeFlag = BF_DIAGONAL_ENDBOTTOMLEFT;
2466 SetRect (&topRect, R.left + lOffset, R.top, R.right - rOffset,
2468 SetRect (&sideRect, R.left, R.top + 2 - selectedOffset, R.right,
2470 SetRect (&bottomRect, R.left, R.top, R.right, R.top + 2);
2471 SetRect (&lightRect, R.left, R.bottom - 3, R.left + 2, R.bottom - 1);
2472 SetRect (&shadeRect, R.right - 2, R.bottom - 3, R.right, R.bottom - 1);
2476 g_return_if_reached ();
2480 FillRect (hdc, &R, (HBRUSH) (COLOR_3DFACE + 1));
2483 DrawEdge (hdc, &topRect, EDGE_RAISED, BF_SOFT | topFlag);
2487 DrawEdge (hdc, &bottomRect, EDGE_RAISED, BF_SOFT | topFlag);
2495 DrawEdge (hdc, &sideRect, EDGE_RAISED, BF_SOFT | leftFlag | rightFlag);
2497 /* Tab Diagonal Corners */
2499 DrawEdge (hdc, &lightRect, EDGE_RAISED, BF_SOFT | lightFlag);
2502 DrawEdge (hdc, &shadeRect, EDGE_RAISED, BF_SOFT | shadeFlag);
2506 draw_themed_tab_button (GtkStyle *style,
2508 GtkStateType state_type,
2509 GtkNotebook *notebook,
2511 gint width, gint height, gint gap_side)
2513 GdkPixmap *pixmap = NULL;
2515 gtk_container_get_border_width (GTK_CONTAINER (notebook));
2516 GtkWidget *widget = GTK_WIDGET (notebook);
2517 GdkRectangle draw_rect, clip_rect;
2518 GdkPixbufRotation rotation = GDK_PIXBUF_ROTATE_NONE;
2520 if (gap_side == GTK_POS_TOP)
2524 if (state_type == GTK_STATE_NORMAL)
2528 draw_rect.width = width + 2;
2529 draw_rect.height = height;
2531 clip_rect = draw_rect;
2536 draw_rect.x = x + 2;
2538 draw_rect.width = width - 2;
2539 draw_rect.height = height - 2;
2540 clip_rect = draw_rect;
2543 /* If we are currently drawing the right-most tab, and if that tab is the selected tab... */
2544 widget_right = widget->allocation.x + widget->allocation.width - border_width - 2;
2546 if (draw_rect.x + draw_rect.width >= widget_right)
2548 draw_rect.width = clip_rect.width = widget_right - draw_rect.x;
2551 if (gap_side == GTK_POS_BOTTOM)
2555 if (state_type == GTK_STATE_NORMAL)
2559 draw_rect.width = width + 2;
2560 draw_rect.height = height;
2562 clip_rect = draw_rect;
2566 draw_rect.x = x + 2;
2567 draw_rect.y = y + 2;
2568 draw_rect.width = width - 2;
2569 draw_rect.height = height - 2;
2570 clip_rect = draw_rect;
2573 /* If we are currently drawing the right-most tab, and if that tab is the selected tab... */
2574 widget_right = widget->allocation.x + widget->allocation.width - border_width - 2;
2576 if (draw_rect.x + draw_rect.width >= widget_right)
2578 draw_rect.width = clip_rect.width = widget_right - draw_rect.x;
2581 rotation = GDK_PIXBUF_ROTATE_UPSIDEDOWN;
2583 else if (gap_side == GTK_POS_LEFT)
2587 if (state_type == GTK_STATE_NORMAL)
2591 draw_rect.width = width;
2592 draw_rect.height = height + 2;
2594 clip_rect = draw_rect;
2600 draw_rect.y = y + 2;
2601 draw_rect.width = width - 2;
2602 draw_rect.height = height - 2;
2603 clip_rect = draw_rect;
2606 /* If we are currently drawing the bottom-most tab, and if that tab is the selected tab... */
2607 widget_bottom = widget->allocation.x + widget->allocation.height - border_width - 2;
2609 if (draw_rect.y + draw_rect.height >= widget_bottom)
2611 draw_rect.height = clip_rect.height = widget_bottom - draw_rect.y;
2614 rotation = GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE;
2616 else if (gap_side == GTK_POS_RIGHT)
2620 if (state_type == GTK_STATE_NORMAL)
2622 draw_rect.x = x + 1;
2624 draw_rect.width = width;
2625 draw_rect.height = height + 2;
2627 clip_rect = draw_rect;
2632 draw_rect.x = x + 2;
2633 draw_rect.y = y + 2;
2634 draw_rect.width = width - 2;
2635 draw_rect.height = height - 2;
2636 clip_rect = draw_rect;
2639 /* If we are currently drawing the bottom-most tab, and if that tab is the selected tab... */
2640 widget_bottom = widget->allocation.x + widget->allocation.height - border_width - 2;
2642 if (draw_rect.y + draw_rect.height >= widget_bottom)
2644 draw_rect.height = clip_rect.height = widget_bottom - draw_rect.y;
2647 rotation = GDK_PIXBUF_ROTATE_CLOCKWISE;
2650 if (gap_side == GTK_POS_TOP)
2652 if (!xp_theme_draw (window, XP_THEME_ELEMENT_TAB_ITEM, style,
2653 draw_rect.x, draw_rect.y,
2654 draw_rect.width, draw_rect.height,
2655 state_type, &clip_rect))
2665 if (gap_side == GTK_POS_LEFT || gap_side == GTK_POS_RIGHT)
2667 pixmap = gdk_pixmap_new (window, clip_rect.height, clip_rect.width, -1);
2669 if (!xp_theme_draw (pixmap, XP_THEME_ELEMENT_TAB_ITEM, style,
2670 draw_rect.y - clip_rect.y, draw_rect.x - clip_rect.x,
2671 draw_rect.height, draw_rect.width, state_type, 0))
2673 g_object_unref (pixmap);
2677 pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap, NULL, 0, 0, 0, 0,
2678 clip_rect.height, clip_rect.width);
2679 g_object_unref (pixmap);
2683 pixmap = gdk_pixmap_new (window, clip_rect.width, clip_rect.height, -1);
2685 if (!xp_theme_draw (pixmap, XP_THEME_ELEMENT_TAB_ITEM, style,
2686 draw_rect.x - clip_rect.x, draw_rect.y - clip_rect.y,
2687 draw_rect.width, draw_rect.height, state_type, 0))
2689 g_object_unref (pixmap);
2693 pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap, NULL, 0, 0, 0, 0,
2694 clip_rect.width, clip_rect.height);
2695 g_object_unref (pixmap);
2698 rotated = gdk_pixbuf_rotate_simple (pixbuf, rotation);
2699 g_object_unref (pixbuf);
2702 // XXX - This is really hacky and evil. When we're drawing the left-most tab
2703 // while it is active on a bottom-oriented notebook, there is one white
2704 // pixel at the top. There may be a better solution than this if someone
2705 // has time to discover it.
2706 if (gap_side == GTK_POS_BOTTOM && state_type == GTK_STATE_NORMAL
2707 && x == widget->allocation.x)
2709 int rowstride = gdk_pixbuf_get_rowstride (pixbuf);
2710 int n_channels = gdk_pixbuf_get_n_channels (pixbuf);
2713 guchar *pixels = gdk_pixbuf_get_pixels (pixbuf);
2714 guchar *p = pixels + rowstride;
2716 for (psub = 0; psub < n_channels; psub++)
2718 pixels[psub] = p[psub];
2722 gdk_draw_pixbuf (window, NULL, pixbuf, 0, 0, clip_rect.x, clip_rect.y,
2723 clip_rect.width, clip_rect.height, GDK_RGB_DITHER_NONE,
2725 g_object_unref (pixbuf);
2732 draw_tab_button (GtkStyle *style,
2734 GtkStateType state_type,
2735 GtkShadowType shadow_type,
2738 const gchar *detail,
2739 gint x, gint y, gint width, gint height, gint gap_side)
2741 if (gap_side == GTK_POS_TOP || gap_side == GTK_POS_BOTTOM)
2743 /* experimental tab-drawing code from mozilla */
2748 dc = get_window_dc (style, window, state_type, x, y, width, height, &rect);
2750 if (gap_side == GTK_POS_TOP)
2752 else if (gap_side == GTK_POS_BOTTOM)
2753 aPosition = BF_BOTTOM;
2754 else if (gap_side == GTK_POS_LEFT)
2755 aPosition = BF_LEFT;
2757 aPosition = BF_RIGHT;
2759 if (state_type == GTK_STATE_PRELIGHT)
2760 state_type = GTK_STATE_NORMAL;
2762 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
2764 DrawTab (dc, rect, aPosition,
2765 state_type != GTK_STATE_PRELIGHT,
2766 (gap_side != GTK_POS_LEFT), (gap_side != GTK_POS_RIGHT));
2769 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
2771 release_window_dc (style, window, state_type);
2779 draw_extension (GtkStyle *style,
2781 GtkStateType state_type,
2782 GtkShadowType shadow_type,
2785 const gchar *detail,
2787 gint width, gint height, GtkPositionType gap_side)
2789 if (widget && GTK_IS_NOTEBOOK (widget) && detail && !strcmp (detail, "tab"))
2791 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2793 /* Why this differs from gap_side, I have no idea.. */
2794 int real_gap_side = gtk_notebook_get_tab_pos (notebook);
2796 if (!draw_themed_tab_button (style, window, state_type,
2797 GTK_NOTEBOOK (widget), x, y,
2798 width, height, real_gap_side))
2800 if (!draw_tab_button (style, window, state_type,
2801 shadow_type, area, widget,
2802 detail, x, y, width, height, real_gap_side))
2804 parent_class->draw_extension (style, window, state_type,
2805 shadow_type, area, widget, detail,
2806 x, y, width, height,
2814 draw_box_gap (GtkStyle *style, GdkWindow *window, GtkStateType state_type,
2815 GtkShadowType shadow_type, GdkRectangle *area,
2816 GtkWidget *widget, const gchar *detail, gint x,
2817 gint y, gint width, gint height, GtkPositionType gap_side,
2818 gint gap_x, gint gap_width)
2820 if (GTK_IS_NOTEBOOK (widget) && detail && !strcmp (detail, "notebook"))
2822 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2823 int side = gtk_notebook_get_tab_pos (notebook);
2824 int x2 = x, y2 = y, w2 = width, h2 = height;
2826 if (side == GTK_POS_TOP)
2829 y2 = y - notebook->tab_vborder;
2831 h2 = height + notebook->tab_vborder * 2;
2833 else if (side == GTK_POS_BOTTOM)
2838 h2 = height + notebook->tab_vborder * 2;
2840 else if (side == GTK_POS_LEFT)
2842 x2 = x - notebook->tab_hborder;
2844 w2 = width + notebook->tab_hborder;
2847 else if (side == GTK_POS_RIGHT)
2851 w2 = width + notebook->tab_hborder * 2;
2855 if (xp_theme_draw (window, XP_THEME_ELEMENT_TAB_PANE, style,
2856 x2, y2, w2, h2, state_type, area))
2862 parent_class->draw_box_gap (style, window, state_type, shadow_type,
2863 area, widget, detail, x, y, width, height,
2864 gap_side, gap_x, gap_width);
2868 is_popup_window_child (GtkWidget *widget)
2871 GtkWindowType type = -1;
2873 top = gtk_widget_get_toplevel (widget);
2875 if (top && GTK_IS_WINDOW (top))
2877 g_object_get (top, "type", &type, NULL);
2879 if (type == GTK_WINDOW_POPUP)
2880 { /* Hack for combo boxes */
2889 draw_flat_box (GtkStyle *style, GdkWindow *window,
2890 GtkStateType state_type, GtkShadowType shadow_type,
2891 GdkRectangle *area, GtkWidget *widget,
2892 const gchar *detail, gint x, gint y, gint width, gint height)
2896 if (!strcmp (detail, "checkbutton"))
2898 if (state_type == GTK_STATE_PRELIGHT)
2905 parent_class->draw_flat_box (style, window, state_type, shadow_type,
2906 area, widget, detail, x, y, width, height);
2910 draw_menu_border (GdkWindow *win, GtkStyle *style,
2911 gint x, gint y, gint width, gint height)
2916 dc = get_window_dc (style, win, GTK_STATE_NORMAL, x, y, width, height, &rect);
2921 if (xp_theme_is_active ())
2923 FrameRect (dc, &rect, GetSysColorBrush (COLOR_3DSHADOW));
2927 DrawEdge (dc, &rect, EDGE_RAISED, BF_RECT);
2930 release_window_dc (style, win, GTK_STATE_NORMAL);
2936 draw_shadow (GtkStyle *style,
2938 GtkStateType state_type,
2939 GtkShadowType shadow_type,
2942 const gchar *detail, gint x, gint y, gint width, gint height)
2944 gboolean is_handlebox;
2945 gboolean is_toolbar;
2947 if (detail && !strcmp (detail, "frame"))
2951 dc = get_window_dc (style, window, state_type, x, y, width, height, &rect);
2953 if (is_popup_window_child (widget))
2955 FrameRect (dc, &rect, GetSysColorBrush (COLOR_WINDOWFRAME));
2959 switch (shadow_type)
2962 draw_3d_border (dc, &rect, TRUE);
2965 case GTK_SHADOW_OUT:
2966 draw_3d_border (dc, &rect, FALSE);
2969 case GTK_SHADOW_ETCHED_IN:
2970 draw_3d_border (dc, &rect, TRUE);
2971 InflateRect (&rect, -1, -1);
2972 draw_3d_border (dc, &rect, FALSE);
2975 case GTK_SHADOW_ETCHED_OUT:
2976 draw_3d_border (dc, &rect, FALSE);
2977 InflateRect (&rect, -1, -1);
2978 draw_3d_border (dc, &rect, TRUE);
2981 case GTK_SHADOW_NONE:
2986 release_window_dc (style, window, state_type);
2990 if (detail && (!strcmp (detail, "entry") || !strcmp (detail, "combobox")))
2992 if (shadow_type != GTK_SHADOW_IN)
2995 if (!xp_theme_draw (window, XP_THEME_ELEMENT_EDIT_TEXT, style,
2996 x, y, width, height, state_type, area))
3001 dc = get_window_dc (style, window, state_type,
3002 x, y, width, height, &rect);
3004 DrawEdge (dc, &rect, EDGE_SUNKEN, BF_RECT);
3005 release_window_dc (style, window, state_type);
3011 if (detail && !strcmp (detail, "scrolled_window") &&
3012 xp_theme_draw (window, XP_THEME_ELEMENT_EDIT_TEXT, style,
3013 x, y, width, height, state_type, area))
3018 if (detail && !strcmp (detail, "spinbutton"))
3021 if (detail && !strcmp (detail, "menu"))
3023 if (draw_menu_border (window, style, x, y, width, height))
3029 if (detail && !strcmp (detail, "handlebox"))
3032 is_handlebox = (detail && !strcmp (detail, "handlebox_bin"));
3033 is_toolbar = (detail
3034 && (!strcmp (detail, "toolbar")
3035 || !strcmp (detail, "menubar")));
3037 if (is_toolbar || is_handlebox)
3039 if (shadow_type == GTK_SHADOW_NONE)
3048 HGDIOBJ old_pen = NULL;
3049 GtkPositionType pos;
3051 sanitize_size (window, &width, &height);
3055 pos = gtk_handle_box_get_handle_position (GTK_HANDLE_BOX (widget));
3057 If the handle box is at left side,
3058 we shouldn't draw its right border.
3059 The same holds true for top, right, and bottom.
3064 pos = GTK_POS_RIGHT;
3072 pos = GTK_POS_BOTTOM;
3075 case GTK_POS_BOTTOM:
3082 GtkWidget *parent = gtk_widget_get_parent (widget);
3084 /* Dirty hack for toolbars contained in handle boxes */
3085 if (GTK_IS_HANDLE_BOX (parent))
3087 pos = gtk_handle_box_get_handle_position (GTK_HANDLE_BOX (parent));
3093 Make pos != all legal enum vaules of GtkPositionType.
3094 So every border will be draw.
3096 pos = (GtkPositionType) - 1;
3100 dc = get_window_dc (style, window, state_type, x, y, width, height, &rect);
3102 if (pos != GTK_POS_LEFT)
3104 old_pen = SelectObject (dc, get_light_pen ());
3105 MoveToEx (dc, rect.left, rect.top, NULL);
3106 LineTo (dc, rect.left, rect.bottom);
3108 if (pos != GTK_POS_TOP)
3110 old_pen = SelectObject (dc, get_light_pen ());
3111 MoveToEx (dc, rect.left, rect.top, NULL);
3112 LineTo (dc, rect.right, rect.top);
3114 if (pos != GTK_POS_RIGHT)
3116 old_pen = SelectObject (dc, get_dark_pen ());
3117 MoveToEx (dc, rect.right - 1, rect.top, NULL);
3118 LineTo (dc, rect.right - 1, rect.bottom);
3120 if (pos != GTK_POS_BOTTOM)
3122 old_pen = SelectObject (dc, get_dark_pen ());
3123 MoveToEx (dc, rect.left, rect.bottom - 1, NULL);
3124 LineTo (dc, rect.right, rect.bottom - 1);
3127 SelectObject (dc, old_pen);
3128 release_window_dc (style, window, state_type);
3134 if (detail && !strcmp (detail, "statusbar"))
3139 parent_class->draw_shadow (style, window, state_type, shadow_type, area,
3140 widget, detail, x, y, width, height);
3144 draw_hline (GtkStyle *style,
3146 GtkStateType state_type,
3149 const gchar *detail, gint x1, gint x2, gint y)
3151 if (xp_theme_is_active () && detail && !strcmp (detail, "menuitem"))
3154 (window, XP_THEME_ELEMENT_MENU_SEPARATOR, style, x1, y, x2, 1,
3163 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
3166 gdk_draw_line (window, style->dark_gc[state_type], x1, y, x2, y);
3170 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
3176 if (style->ythickness == 2)
3180 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
3181 gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
3184 gdk_draw_line (window, style->dark_gc[state_type], x1, y, x2, y);
3186 gdk_draw_line (window, style->light_gc[state_type], x1, y, x2, y);
3190 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
3191 gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
3196 parent_class->draw_hline (style, window, state_type, area, widget,
3203 draw_vline (GtkStyle *style,
3205 GtkStateType state_type,
3208 const gchar *detail, gint y1, gint y2, gint x)
3210 if (style->xthickness == 2)
3214 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
3215 gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
3218 gdk_draw_line (window, style->dark_gc[state_type], x, y1, x, y2);
3220 gdk_draw_line (window, style->light_gc[state_type], x, y1, x, y2);
3224 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
3225 gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
3230 parent_class->draw_vline (style, window, state_type, area, widget,
3236 draw_slider (GtkStyle *style,
3238 GtkStateType state_type,
3239 GtkShadowType shadow_type,
3242 const gchar *detail,
3244 gint y, gint width, gint height, GtkOrientation orientation)
3246 if (GTK_IS_SCALE (widget) &&
3247 xp_theme_draw (window, ((orientation == GTK_ORIENTATION_VERTICAL) ?
3248 XP_THEME_ELEMENT_SCALE_SLIDER_V :
3249 XP_THEME_ELEMENT_SCALE_SLIDER_H), style, x, y, width,
3250 height, state_type, area))
3255 parent_class->draw_slider (style, window, state_type, shadow_type, area,
3256 widget, detail, x, y, width, height,
3261 draw_resize_grip (GtkStyle *style,
3263 GtkStateType state_type,
3266 const gchar *detail,
3267 GdkWindowEdge edge, gint x, gint y, gint width, gint height)
3269 if (detail && !strcmp (detail, "statusbar"))
3272 (window, XP_THEME_ELEMENT_STATUS_GRIPPER, style, x, y, width,
3273 height, state_type, area))
3280 HDC dc = get_window_dc (style, window, state_type, x, y, width, height, &rect);
3283 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
3285 DrawFrameControl (dc, &rect, DFC_SCROLL, DFCS_SCROLLSIZEGRIP);
3286 release_window_dc (style, window, state_type);
3289 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
3295 parent_class->draw_resize_grip (style, window, state_type, area,
3296 widget, detail, edge, x, y, width, height);
3300 draw_handle (GtkStyle *style,
3302 GtkStateType state_type,
3303 GtkShadowType shadow_type,
3306 const gchar *detail,
3308 gint y, gint width, gint height, GtkOrientation orientation)
3313 if (is_toolbar_child (widget))
3315 XpThemeElement hndl;
3317 sanitize_size (window, &width, &height);
3319 if (GTK_IS_HANDLE_BOX (widget))
3321 GtkPositionType pos;
3322 pos = gtk_handle_box_get_handle_position (GTK_HANDLE_BOX (widget));
3324 if (pos == GTK_POS_TOP || pos == GTK_POS_BOTTOM)
3326 orientation = GTK_ORIENTATION_HORIZONTAL;
3330 orientation = GTK_ORIENTATION_VERTICAL;
3334 if (orientation == GTK_ORIENTATION_VERTICAL)
3335 hndl = XP_THEME_ELEMENT_REBAR_GRIPPER_V;
3337 hndl = XP_THEME_ELEMENT_REBAR_GRIPPER_H;
3339 if (xp_theme_draw (window, hndl, style, x, y, width, height,
3345 dc = get_window_dc (style, window, state_type, x, y, width, height, &rect);
3347 if (orientation == GTK_ORIENTATION_VERTICAL)
3350 rect.right = rect.left + 3;
3357 rect.bottom = rect.top + 3;
3362 draw_3d_border (dc, &rect, FALSE);
3363 release_window_dc (style, window, state_type);
3367 if (!GTK_IS_PANED (widget))
3369 gint xthick, ythick;
3370 GdkGC *light_gc, *dark_gc, *shadow_gc;
3373 sanitize_size (window, &width, &height);
3375 gtk_paint_box (style, window, state_type, shadow_type, area,
3376 widget, detail, x, y, width, height);
3378 light_gc = style->light_gc[state_type];
3379 dark_gc = style->dark_gc[state_type];
3380 shadow_gc = style->mid_gc[state_type];
3382 xthick = style->xthickness;
3383 ythick = style->ythickness;
3385 dest.x = x + xthick;
3386 dest.y = y + ythick;
3387 dest.width = width - (xthick * 2);
3388 dest.height = height - (ythick * 2);
3390 if (dest.width < dest.height)
3395 gdk_gc_set_clip_rectangle (light_gc, &dest);
3396 gdk_gc_set_clip_rectangle (dark_gc, &dest);
3397 gdk_gc_set_clip_rectangle (shadow_gc, &dest);
3399 if (dest.width < dest.height)
3401 gdk_draw_line (window, light_gc, dest.x, dest.y, dest.x,
3403 gdk_draw_line (window, dark_gc, dest.x + (dest.width / 2),
3404 dest.y, dest.x + (dest.width / 2), dest.height);
3405 gdk_draw_line (window, shadow_gc, dest.x + dest.width,
3406 dest.y, dest.x + dest.width, dest.height);
3410 gdk_draw_line (window, light_gc, dest.x, dest.y,
3411 dest.x + dest.width, dest.y);
3412 gdk_draw_line (window, dark_gc, dest.x,
3413 dest.y + (dest.height / 2),
3414 dest.x + dest.width, dest.y + (dest.height / 2));
3415 gdk_draw_line (window, shadow_gc, dest.x,
3416 dest.y + dest.height, dest.x + dest.width,
3417 dest.y + dest.height);
3420 gdk_gc_set_clip_rectangle (shadow_gc, NULL);
3421 gdk_gc_set_clip_rectangle (light_gc, NULL);
3422 gdk_gc_set_clip_rectangle (dark_gc, NULL);
3427 draw_focus (GtkStyle *style,
3429 GtkStateType state_type,
3432 const gchar *detail, gint x, gint y, gint width, gint height)
3437 if (!GTK_WIDGET_CAN_FOCUS (widget))
3442 if (is_combo_box_child (widget)
3443 && (GTK_IS_ARROW (widget) || GTK_IS_BUTTON (widget)))
3447 if (GTK_IS_TREE_VIEW (widget->parent) /* list view bheader */
3448 || GTK_IS_CLIST (widget->parent))
3453 dc = get_window_dc (style, window, state_type, x, y, width, height, &rect);
3454 DrawFocusRect (dc, &rect);
3455 release_window_dc (style, window, state_type);
3457 parent_class->draw_focus (style, window, state_type,
3458 area, widget, detail, x, y, width, height);
3463 draw_layout (GtkStyle *style,
3465 GtkStateType state_type,
3469 const gchar *detail,
3470 gint old_x, gint old_y, PangoLayout *layout)
3472 GtkNotebook *notebook = NULL;
3476 /* In the XP theme, labels don't appear correctly centered inside
3477 * notebook tabs, so we give them a gentle nudge two pixels to the
3478 * right. A little hackish, but what are 'ya gonna do? -- Cody
3480 if (xp_theme_is_active () && detail && !strcmp (detail, "label"))
3482 if (widget->parent != NULL)
3484 if (GTK_IS_NOTEBOOK (widget->parent))
3486 notebook = GTK_NOTEBOOK (widget->parent);
3487 int side = gtk_notebook_get_tab_pos (notebook);
3489 if (side == GTK_POS_TOP || side == GTK_POS_BOTTOM)
3497 parent_class->draw_layout (style, window, state_type,
3498 use_text, area, widget, detail, x, y, layout);
3502 msw_style_init_from_rc (GtkStyle *style, GtkRcStyle *rc_style)
3504 setup_system_font (style);
3505 setup_menu_settings (gtk_settings_get_default ());
3506 setup_system_styles (style);
3507 parent_class->init_from_rc (style, rc_style);
3511 load_bg_image (GdkColormap *colormap,
3512 GdkColor *bg_color, const gchar *filename)
3514 if (strcmp (filename, "<parent>") == 0)
3516 return (GdkPixmap *) GDK_PARENT_RELATIVE;
3520 return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL,
3521 bg_color, filename);
3526 msw_style_realize (GtkStyle *style)
3528 GdkGCValues gc_values;
3529 GdkGCValuesMask gc_values_mask;
3533 for (i = 0; i < 5; i++)
3535 style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2;
3536 style->mid[i].green =
3537 (style->light[i].green + style->dark[i].green) / 2;
3538 style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2;
3540 style->text_aa[i].red = (style->text[i].red + style->base[i].red) / 2;
3541 style->text_aa[i].green =
3542 (style->text[i].green + style->base[i].green) / 2;
3543 style->text_aa[i].blue =
3544 (style->text[i].blue + style->base[i].blue) / 2;
3547 style->black.red = 0x0000;
3548 style->black.green = 0x0000;
3549 style->black.blue = 0x0000;
3550 gdk_colormap_alloc_color (style->colormap, &style->black, FALSE, TRUE);
3552 style->white.red = 0xffff;
3553 style->white.green = 0xffff;
3554 style->white.blue = 0xffff;
3555 gdk_colormap_alloc_color (style->colormap, &style->white, FALSE, TRUE);
3557 gc_values_mask = GDK_GC_FOREGROUND | GDK_GC_BACKGROUND;
3559 gc_values.foreground = style->black;
3560 gc_values.background = style->white;
3562 gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3564 gc_values.foreground = style->white;
3565 gc_values.background = style->black;
3567 gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3569 gc_values_mask = GDK_GC_FOREGROUND;
3571 for (i = 0; i < 5; i++)
3573 if (style->rc_style && style->rc_style->bg_pixmap_name[i])
3575 style->bg_pixmap[i] = load_bg_image (style->colormap,
3581 if (!gdk_colormap_alloc_color (style->colormap, &style->fg[i], FALSE, TRUE))
3583 g_warning ("unable to allocate color: ( %d %d %d )", style->fg[i].red,
3584 style->fg[i].green, style->fg[i].blue);
3587 if (!gdk_colormap_alloc_color (style->colormap, &style->bg[i], FALSE, TRUE))
3589 g_warning ("unable to allocate color: ( %d %d %d )", style->bg[i].red,
3590 style->bg[i].green, style->bg[i].blue);
3593 if (!gdk_colormap_alloc_color (style->colormap, &style->light[i], FALSE, TRUE))
3595 g_warning ("unable to allocate color: ( %d %d %d )",
3596 style->light[i].red, style->light[i].green,
3597 style->light[i].blue);
3600 if (!gdk_colormap_alloc_color (style->colormap, &style->dark[i], FALSE, TRUE))
3602 g_warning ("unable to allocate color: ( %d %d %d )",
3603 style->dark[i].red, style->dark[i].green,
3604 style->dark[i].blue);
3607 if (!gdk_colormap_alloc_color (style->colormap, &style->mid[i], FALSE, TRUE))
3609 g_warning ("unable to allocate color: ( %d %d %d )",
3610 style->mid[i].red, style->mid[i].green,
3611 style->mid[i].blue);
3614 if (!gdk_colormap_alloc_color (style->colormap, &style->text[i], FALSE, TRUE))
3616 g_warning ("unable to allocate color: ( %d %d %d )",
3617 style->text[i].red, style->text[i].green,
3618 style->text[i].blue);
3621 if (!gdk_colormap_alloc_color (style->colormap, &style->base[i], FALSE, TRUE))
3623 g_warning ("unable to allocate color: ( %d %d %d )",
3624 style->base[i].red, style->base[i].green,
3625 style->base[i].blue);
3628 if (!gdk_colormap_alloc_color (style->colormap, &style->text_aa[i], FALSE, TRUE))
3630 g_warning ("unable to allocate color: ( %d %d %d )",
3631 style->text_aa[i].red, style->text_aa[i].green,
3632 style->text_aa[i].blue);
3635 gc_values.foreground = style->fg[i];
3636 style->fg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3638 gc_values.foreground = style->bg[i];
3639 style->bg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3641 gc_values.foreground = style->light[i];
3642 style->light_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3644 gc_values.foreground = style->dark[i];
3645 style->dark_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3647 gc_values.foreground = style->mid[i];
3648 style->mid_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3650 gc_values.foreground = style->text[i];
3651 style->text_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3653 gc_values.foreground = style->base[i];
3654 style->base_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3656 gc_values.foreground = style->text_aa[i];
3657 style->text_aa_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3662 msw_style_unrealize (GtkStyle *style)
3664 parent_class->unrealize (style);
3668 msw_style_class_init (MswStyleClass *klass)
3670 GtkStyleClass *style_class = GTK_STYLE_CLASS (klass);
3672 parent_class = g_type_class_peek_parent (klass);
3674 style_class->init_from_rc = msw_style_init_from_rc;
3675 style_class->draw_arrow = draw_arrow;
3676 style_class->draw_box = draw_box;
3677 style_class->draw_check = draw_check;
3678 style_class->draw_option = draw_option;
3679 style_class->draw_tab = draw_tab;
3680 style_class->draw_flat_box = draw_flat_box;
3681 style_class->draw_expander = draw_expander;
3682 style_class->draw_extension = draw_extension;
3683 style_class->draw_box_gap = draw_box_gap;
3684 style_class->draw_shadow = draw_shadow;
3685 style_class->draw_hline = draw_hline;
3686 style_class->draw_vline = draw_vline;
3687 style_class->draw_handle = draw_handle;
3688 style_class->draw_resize_grip = draw_resize_grip;
3689 style_class->draw_slider = draw_slider;
3690 style_class->draw_focus = draw_focus;
3691 style_class->draw_layout = draw_layout;
3693 style_class->realize = msw_style_realize;
3694 style_class->unrealize = msw_style_unrealize;
3697 GType msw_type_style = 0;
3700 msw_style_register_type (GTypeModule *module)
3702 static const GTypeInfo object_info = {
3703 sizeof (MswStyleClass),
3704 (GBaseInitFunc) NULL,
3705 (GBaseFinalizeFunc) NULL,
3706 (GClassInitFunc) msw_style_class_init,
3707 NULL, /* class_finalize */
3708 NULL, /* class_data */
3710 0, /* n_preallocs */
3711 (GInstanceInitFunc) NULL,
3714 msw_type_style = g_type_module_register_type (module,
3716 "MswStyle", &object_info, 0);
3720 msw_style_init (void)
3723 msw_style_setup_system_settings ();
3724 setup_msw_rc_style ();
3728 DeleteObject (g_light_pen);
3734 DeleteObject (g_dark_pen);
3740 msw_style_finalize (void)
3744 DeleteObject (g_dither_brush);
3749 DeleteObject (g_light_pen);
3754 DeleteObject (g_dark_pen);