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"
44 #ifdef BUILDING_STANDALONE
45 #include "gdk/gdkwin32.h"
47 #include "gdk/win32/gdkwin32.h"
51 /* Default values, not normally used
53 static const GtkRequisition default_option_indicator_size = { 9, 8 };
54 static const GtkBorder default_option_indicator_spacing = { 7, 5, 2, 2 };
56 static GtkStyleClass *parent_class;
57 static HBRUSH g_dither_brush = NULL;
59 static HPEN g_light_pen = NULL;
60 static HPEN g_dark_pen = NULL;
82 static const gchar check_aa_bits[] = {
83 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
87 static const gchar check_base_bits[] = {
88 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xfc, 0x07, 0xfc, 0x07, 0xfc, 0x07,
90 0x07, 0xfc, 0x07, 0xfc, 0x07, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00
92 static const gchar check_black_bits[] = {
93 0x00, 0x00, 0xfe, 0x0f, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00,
95 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00
97 static const gchar check_dark_bits[] = {
98 0xff, 0x1f, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
100 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00
102 static const gchar check_light_bits[] = {
103 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10,
105 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0xfe, 0x1f
107 static const gchar check_mid_bits[] = {
108 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08,
110 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0xfc, 0x0f, 0x00, 0x00
112 static const gchar check_text_bits[] = {
113 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x88, 0x03,
115 0x00, 0x70, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
117 static const gchar check_inconsistent_bits[] = {
118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
120 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
122 static const gchar radio_base_bits[] = {
123 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0xf8, 0x03, 0xfc, 0x07, 0xfc, 0x07,
125 0x07, 0xfc, 0x07, 0xf8, 0x03, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00
127 static const gchar radio_black_bits[] = {
128 0x00, 0x00, 0xf0, 0x01, 0x0c, 0x02, 0x04, 0x00, 0x02, 0x00, 0x02, 0x00,
130 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
132 static const gchar radio_dark_bits[] = {
133 0xf0, 0x01, 0x0c, 0x06, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00,
135 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
137 static const gchar radio_light_bits[] = {
138 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x10, 0x00, 0x10,
140 0x10, 0x00, 0x10, 0x00, 0x08, 0x00, 0x08, 0x0c, 0x06, 0xf0, 0x01
142 static const gchar radio_mid_bits[] = {
143 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08,
145 0x08, 0x00, 0x08, 0x00, 0x04, 0x0c, 0x06, 0xf0, 0x01, 0x00, 0x00
147 static const gchar radio_text_bits[] = {
148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xf0, 0x01,
150 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
158 { check_aa_bits, NULL },
159 { check_base_bits, NULL },
160 { check_black_bits, NULL },
161 { check_dark_bits, NULL },
162 { check_light_bits, NULL },
163 { check_mid_bits, NULL },
164 { check_text_bits, NULL },
165 { check_inconsistent_bits, NULL },
166 { radio_base_bits, NULL },
167 { radio_black_bits, NULL },
168 { radio_dark_bits, NULL },
169 { radio_light_bits, NULL },
170 { radio_mid_bits, NULL },
171 { radio_text_bits, NULL }
175 get_system_font (XpThemeClass klazz, XpThemeFont type, LOGFONT *out_lf)
178 /* TODO: this causes crashes later because the font name is in UCS2, and
179 the pango fns don't deal with that gracefully */
180 if (xp_theme_get_system_font (klazz, type, out_lf))
187 NONCLIENTMETRICS ncm;
189 ncm.cbSize = sizeof (NONCLIENTMETRICS);
191 if (SystemParametersInfo (SPI_GETNONCLIENTMETRICS,
192 sizeof (NONCLIENTMETRICS), &ncm, 0))
194 if (type == XP_THEME_FONT_CAPTION)
195 *out_lf = ncm.lfCaptionFont;
196 else if (type == XP_THEME_FONT_MENU)
197 *out_lf = ncm.lfMenuFont;
198 else if (type == XP_THEME_FONT_STATUS)
199 *out_lf = ncm.lfStatusFont;
201 *out_lf = ncm.lfMessageFont;
210 /***************************** BEGIN STOLEN FROM PANGO *****************************/
213 This code is stolen from Pango 1.4. It attempts to address the following problems:
215 http://bugzilla.gnome.org/show_bug.cgi?id=135098
216 http://sourceforge.net/tracker/index.php?func=detail&aid=895762&group_id=76416&atid=547655
218 As Owen suggested in bug 135098, once Pango 1.6 is released, we need to get rid of this code.
221 #define PING(printlist)
223 /* TrueType defines: */
225 #define MAKE_TT_TABLE_NAME(c1, c2, c3, c4) \
226 (((guint32)c4) << 24 | ((guint32)c3) << 16 | ((guint32)c2) << 8 | ((guint32)c1))
228 #define CMAP (MAKE_TT_TABLE_NAME('c','m','a','p'))
229 #define CMAP_HEADER_SIZE 4
231 #define NAME (MAKE_TT_TABLE_NAME('n','a','m','e'))
232 #define NAME_HEADER_SIZE 6
234 #define ENCODING_TABLE_SIZE 8
236 #define APPLE_UNICODE_PLATFORM_ID 0
237 #define MACINTOSH_PLATFORM_ID 1
238 #define ISO_PLATFORM_ID 2
239 #define MICROSOFT_PLATFORM_ID 3
241 #define SYMBOL_ENCODING_ID 0
242 #define UNICODE_ENCODING_ID 1
243 #define UCS4_ENCODING_ID 10
247 guint16 format_selector;
249 guint16 string_storage_offset;
258 guint16 string_length;
259 guint16 string_offset;
263 pango_win32_get_name_header (HDC hdc, struct name_header *header)
265 if (GetFontData (hdc, NAME, 0, header, sizeof (*header)) != sizeof (*header))
268 header->num_records = GUINT16_FROM_BE (header->num_records);
269 header->string_storage_offset = GUINT16_FROM_BE (header->string_storage_offset);
275 pango_win32_get_name_record (HDC hdc, gint i, struct name_record *record)
277 if (GetFontData (hdc, NAME, 6 + i * sizeof (*record),
278 record, sizeof (*record)) != sizeof (*record))
283 record->platform_id = GUINT16_FROM_BE (record->platform_id);
284 record->encoding_id = GUINT16_FROM_BE (record->encoding_id);
285 record->language_id = GUINT16_FROM_BE (record->language_id);
286 record->name_id = GUINT16_FROM_BE (record->name_id);
287 record->string_length = GUINT16_FROM_BE (record->string_length);
288 record->string_offset = GUINT16_FROM_BE (record->string_offset);
294 get_family_name (LOGFONT *lfp, HDC pango_win32_hdc)
299 struct name_header header;
300 struct name_record record;
302 gint unicode_ix = -1, mac_ix = -1, microsoft_ix = -1;
306 gchar *string = NULL;
311 /* If lfFaceName is ASCII, assume it is the common (English) name for the
312 font. Is this valid? Do some TrueType fonts have different names in
313 French, German, etc, and does the system return these if the locale is
314 set to use French, German, etc? */
315 l = strlen (lfp->lfFaceName);
316 for (i = 0; i < l; i++)
318 if (lfp->lfFaceName[i] < ' ' || lfp->lfFaceName[i] > '~')
325 return g_strdup (lfp->lfFaceName);
327 if ((hfont = CreateFontIndirect (lfp)) == NULL)
330 if ((oldhfont = (HFONT) SelectObject (pango_win32_hdc, hfont)) == NULL)
333 if (!pango_win32_get_name_header (pango_win32_hdc, &header))
336 PING (("%d name records", header.num_records));
338 for (i = 0; i < header.num_records; i++)
340 if (!pango_win32_get_name_record (pango_win32_hdc, i, &record))
343 if ((record.name_id != 1 && record.name_id != 16) || record.string_length <= 0)
346 PING (("platform:%d encoding:%d language:%04x name_id:%d",
347 record.platform_id, record.encoding_id, record.language_id,
350 if (record.platform_id == APPLE_UNICODE_PLATFORM_ID ||
351 record.platform_id == ISO_PLATFORM_ID)
355 else if (record.platform_id == MACINTOSH_PLATFORM_ID && record.encoding_id == 0 && /* Roman
357 record.language_id == 0) /* English */
361 else if (record.platform_id == MICROSOFT_PLATFORM_ID)
363 if ((microsoft_ix == -1 ||
364 PRIMARYLANGID (record.language_id) == LANG_ENGLISH) &&
365 (record.encoding_id == SYMBOL_ENCODING_ID ||
366 record.encoding_id == UNICODE_ENCODING_ID ||
367 record.encoding_id == UCS4_ENCODING_ID))
374 if (microsoft_ix >= 0)
375 name_ix = microsoft_ix;
376 else if (mac_ix >= 0)
378 else if (unicode_ix >= 0)
379 name_ix = unicode_ix;
383 if (!pango_win32_get_name_record (pango_win32_hdc, name_ix, &record))
386 string = g_malloc (record.string_length + 1);
387 if (GetFontData (pango_win32_hdc, NAME,
388 header.string_storage_offset + record.string_offset,
389 string, record.string_length) != record.string_length)
392 string[record.string_length] = '\0';
394 if (name_ix == microsoft_ix)
396 if (record.encoding_id == SYMBOL_ENCODING_ID ||
397 record.encoding_id == UNICODE_ENCODING_ID)
399 codeset = "UTF-16BE";
406 else if (name_ix == mac_ix)
408 codeset = "MacRoman";
410 else /* name_ix == unicode_ix */
416 name = g_convert (string, record.string_length, "UTF-8", codeset, NULL,
425 SelectObject (pango_win32_hdc, oldhfont);
426 DeleteObject (hfont);
432 SelectObject (pango_win32_hdc, oldhfont);
435 DeleteObject (hfont);
438 return g_locale_to_utf8 (lfp->lfFaceName, -1, NULL, NULL, NULL);
441 /***************************** END STOLEN FROM PANGO *****************************/
444 sys_font_to_pango_font (XpThemeClass klazz, XpThemeFont type, char *buf,
455 if (get_system_font (klazz, type, &lf))
461 weight = "Ultra-Light";
473 weight = "Semi-Bold";
477 weight = "Ultra-Bold";
494 hwnd = GetDesktopWindow ();
498 pt_size = -MulDiv (lf.lfHeight, 72,
499 GetDeviceCaps (hDC, LOGPIXELSY));
506 font = get_family_name (&lf, hDC);
509 ReleaseDC (hwnd, hDC);
511 if (!(font && *font))
514 g_snprintf (buf, bufsiz, "%s %s %s %d", font, style, weight, pt_size);
523 /* missing from ms's header files */
524 #ifndef SPI_GETMENUSHOWDELAY
525 #define SPI_GETMENUSHOWDELAY 106
528 /* I don't know the proper XP theme class for things like
529 HIGHLIGHTTEXT, so we'll just define it to be "BUTTON"
531 #define XP_THEME_CLASS_TEXT XP_THEME_CLASS_BUTTON
533 #define WIN95_VERSION 0x400
534 #define WIN2K_VERSION 0x500
535 #define WINXP_VERSION 0x501
536 #define WIN2K3_VERSION 0x502
537 #define VISTA_VERSION 0x600
540 get_windows_version ()
542 static gint32 version = 0;
543 static gboolean have_version = FALSE;
547 OSVERSIONINFOEX osvi;
550 ZeroMemory (&osvi, sizeof (OSVERSIONINFOEX));
551 osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
553 GetVersionEx((OSVERSIONINFO*) &osvi);
555 version = (osvi.dwMajorVersion & 0xff) << 8 | (osvi.dwMinorVersion & 0xff);
562 setup_menu_settings (GtkSettings *settings)
565 GObjectClass *klazz = G_OBJECT_GET_CLASS (G_OBJECT (settings));
567 if (get_windows_version () > WIN95_VERSION)
569 if (SystemParametersInfo (SPI_GETMENUSHOWDELAY, 0, &menu_delay, 0))
573 if (g_object_class_find_property
574 (klazz, "gtk-menu-bar-popup-delay"))
576 g_object_set (settings,
577 "gtk-menu-bar-popup-delay", 0, NULL);
579 if (g_object_class_find_property
580 (klazz, "gtk-menu-popup-delay"))
582 g_object_set (settings,
583 "gtk-menu-popup-delay", menu_delay, NULL);
585 if (g_object_class_find_property
586 (klazz, "gtk-menu-popdown-delay"))
588 g_object_set (settings,
589 "gtk-menu-popdown-delay", menu_delay, NULL);
597 msw_style_setup_system_settings (void)
599 GtkSettings *settings;
600 int cursor_blink_time;
602 settings = gtk_settings_get_default ();
606 cursor_blink_time = GetCaretBlinkTime ();
607 g_object_set (settings, "gtk-cursor-blink", cursor_blink_time > 0, NULL);
609 if (cursor_blink_time > 0)
611 g_object_set (settings, "gtk-cursor-blink-time",
612 2 * cursor_blink_time, NULL);
615 g_object_set (settings, "gtk-double-click-distance",
616 GetSystemMetrics (SM_CXDOUBLECLK), NULL);
617 g_object_set (settings, "gtk-double-click-time", GetDoubleClickTime (),
619 g_object_set (settings, "gtk-dnd-drag-threshold",
620 GetSystemMetrics (SM_CXDRAG), NULL);
622 setup_menu_settings (settings);
625 http://developer.gnome.org/doc/API/2.0/gtk/GtkSettings.html
626 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/systemparametersinfo.asp
627 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/getsystemmetrics.asp */
631 setup_system_font (GtkStyle *style)
633 char buf[256], *font; /* It's okay, lfFaceName is smaller than 32
636 if ((font = sys_font_to_pango_font (XP_THEME_CLASS_TEXT,
637 XP_THEME_FONT_MESSAGE,
638 buf, sizeof (buf))) != NULL)
640 if (style->font_desc)
642 pango_font_description_free (style->font_desc);
645 style->font_desc = pango_font_description_from_string (font);
650 sys_color_to_gtk_color (XpThemeClass klazz, int id, GdkColor * pcolor)
654 if (!xp_theme_get_system_color (klazz, id, &color))
655 color = GetSysColor (id);
657 pcolor->pixel = color;
658 pcolor->red = (GetRValue (color) << 8) | GetRValue (color);
659 pcolor->green = (GetGValue (color) << 8) | GetGValue (color);
660 pcolor->blue = (GetBValue (color) << 8) | GetBValue (color);
664 get_system_metric (XpThemeClass klazz, int id)
668 if (!xp_theme_get_system_metric (klazz, id, &rval))
669 rval = GetSystemMetrics (id);
675 setup_msw_rc_style (void)
677 char buf[1024], font_buf[256], *font_ptr;
678 char menu_bar_prelight_str[128];
681 GdkColor menu_text_color;
682 GdkColor tooltip_back;
683 GdkColor tooltip_fore;
686 GdkColor progress_back;
688 GdkColor fg_prelight;
689 GdkColor bg_prelight;
690 GdkColor base_prelight;
691 GdkColor text_prelight;
694 sys_color_to_gtk_color (get_windows_version () >= VISTA_VERSION ? XP_THEME_CLASS_MENU : XP_THEME_CLASS_TEXT,
695 get_windows_version () >= VISTA_VERSION ? COLOR_MENUTEXT : COLOR_HIGHLIGHTTEXT,
697 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT, &bg_prelight);
698 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT,
700 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT,
703 sys_color_to_gtk_color (XP_THEME_CLASS_MENU, COLOR_MENUTEXT,
705 sys_color_to_gtk_color (XP_THEME_CLASS_MENU, COLOR_MENU, &menu_color);
708 sys_color_to_gtk_color (XP_THEME_CLASS_TOOLTIP, COLOR_INFOTEXT,
710 sys_color_to_gtk_color (XP_THEME_CLASS_TOOLTIP, COLOR_INFOBK,
713 /* text on push buttons. TODO: button shadows, backgrounds, and
715 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT, &btn_fore);
716 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE, &btn_face);
718 /* progress bar background color */
719 sys_color_to_gtk_color (XP_THEME_CLASS_PROGRESS, COLOR_HIGHLIGHT,
722 /* Enable coloring for menus. */
724 sys_font_to_pango_font (XP_THEME_CLASS_MENU, XP_THEME_FONT_MENU,
725 font_buf, sizeof (font_buf));
726 g_snprintf (buf, sizeof (buf),
727 "style \"msw-menu\" = \"msw-default\"\n" "{\n"
728 "GtkMenuItem::toggle-spacing = 8\n"
729 "fg[PRELIGHT] = { %d, %d, %d }\n"
730 "bg[PRELIGHT] = { %d, %d, %d }\n"
731 "text[PRELIGHT] = { %d, %d, %d }\n"
732 "base[PRELIGHT] = { %d, %d, %d }\n"
733 "fg[NORMAL] = { %d, %d, %d }\n"
734 "bg[NORMAL] = { %d, %d, %d }\n" "%s = \"%s\"\n"
735 "}widget_class \"*MenuItem*\" style \"msw-menu\"\n"
736 "widget_class \"*GtkMenu\" style \"msw-menu\"\n"
737 "widget_class \"*GtkMenuShell*\" style \"msw-menu\"\n",
738 fg_prelight.red, fg_prelight.green, fg_prelight.blue,
739 bg_prelight.red, bg_prelight.green, bg_prelight.blue,
740 text_prelight.red, text_prelight.green, text_prelight.blue,
741 base_prelight.red, base_prelight.green, base_prelight.blue,
742 menu_text_color.red, menu_text_color.green,
743 menu_text_color.blue, menu_color.red, menu_color.green,
744 menu_color.blue, (font_ptr ? "font_name" : "#"),
745 (font_ptr ? font_ptr : " font name should go here"));
746 gtk_rc_parse_string (buf);
748 if (xp_theme_is_active ())
750 *menu_bar_prelight_str = '\0';
754 g_snprintf (menu_bar_prelight_str, sizeof (menu_bar_prelight_str),
755 "fg[PRELIGHT] = { %d, %d, %d }\n",
756 menu_text_color.red, menu_text_color.green,
757 menu_text_color.blue);
760 /* Enable coloring for menu bars. */
761 g_snprintf (buf, sizeof (buf),
762 "style \"msw-menu-bar\" = \"msw-menu\"\n"
764 "bg[NORMAL] = { %d, %d, %d }\n"
765 "%s" "GtkMenuBar::shadow-type = %d\n"
767 FIXME: This should be enabled once gtk+ support
768 GtkMenuBar::prelight-item style property.
770 /* "GtkMenuBar::prelight-item = 1\n" */
771 "}widget_class \"*MenuBar*\" style \"msw-menu-bar\"\n",
772 btn_face.red, btn_face.green, btn_face.blue,
773 menu_bar_prelight_str, xp_theme_is_active ()? 0 : 2);
774 gtk_rc_parse_string (buf);
776 g_snprintf (buf, sizeof (buf),
777 "style \"msw-toolbar\" = \"msw-default\"\n"
779 "GtkHandleBox::shadow-type = %s\n"
780 "GtkToolbar::shadow-type = %s\n"
781 "}widget_class \"*HandleBox*\" style \"msw-toolbar\"\n",
782 "etched-in", "etched-in");
783 gtk_rc_parse_string (buf);
785 /* enable tooltip fonts */
786 font_ptr = sys_font_to_pango_font (XP_THEME_CLASS_STATUS, XP_THEME_FONT_STATUS,
787 font_buf, sizeof (font_buf));
788 g_snprintf (buf, sizeof (buf),
789 "style \"msw-tooltips-caption\" = \"msw-default\"\n"
790 "{fg[NORMAL] = { %d, %d, %d }\n" "%s = \"%s\"\n"
791 "}widget \"gtk-tooltips.GtkLabel\" style \"msw-tooltips-caption\"\n"
792 "widget \"gtk-tooltip.GtkLabel\" style \"msw-tooltips-caption\"\n",
793 tooltip_fore.red, tooltip_fore.green, tooltip_fore.blue,
794 (font_ptr ? "font_name" : "#"),
795 (font_ptr ? font_ptr : " font name should go here"));
796 gtk_rc_parse_string (buf);
798 g_snprintf (buf, sizeof (buf),
799 "style \"msw-tooltips\" = \"msw-default\"\n"
800 "{bg[NORMAL] = { %d, %d, %d }\n"
801 "}widget \"gtk-tooltips*\" style \"msw-tooltips\"\n"
802 "widget \"gtk-tooltip*\" style \"msw-tooltips\"\n",
803 tooltip_back.red, tooltip_back.green, tooltip_back.blue);
804 gtk_rc_parse_string (buf);
806 /* enable font theming for status bars */
807 font_ptr = sys_font_to_pango_font (XP_THEME_CLASS_STATUS, XP_THEME_FONT_STATUS,
808 font_buf, sizeof (font_buf));
809 g_snprintf (buf, sizeof (buf),
810 "style \"msw-status\" = \"msw-default\"\n" "{%s = \"%s\"\n"
811 "bg[NORMAL] = { %d, %d, %d }\n"
812 "}widget_class \"*Status*\" style \"msw-status\"\n",
813 (font_ptr ? "font_name" : "#"),
814 (font_ptr ? font_ptr : " font name should go here"),
815 btn_face.red, btn_face.green, btn_face.blue);
816 gtk_rc_parse_string (buf);
818 /* enable coloring for text on buttons TODO: use GetThemeMetric for the
819 border and outside border */
820 g_snprintf (buf, sizeof (buf),
821 "style \"msw-button\" = \"msw-default\"\n"
823 "bg[NORMAL] = { %d, %d, %d }\n"
824 "bg[PRELIGHT] = { %d, %d, %d }\n"
825 "bg[INSENSITIVE] = { %d, %d, %d }\n"
826 "fg[PRELIGHT] = { %d, %d, %d }\n"
827 "GtkButton::default-border = { 0, 0, 0, 0 }\n"
828 "GtkButton::default-outside-border = { 0, 0, 0, 0 }\n"
829 "GtkButton::child-displacement-x = 1\n"
830 "GtkButton::child-displacement-y = 1\n"
831 "GtkButton::focus-padding = %d\n"
832 "}widget_class \"*Button*\" style \"msw-button\"\n",
833 btn_face.red, btn_face.green, btn_face.blue,
834 btn_face.red, btn_face.green, btn_face.blue,
835 btn_face.red, btn_face.green, btn_face.blue,
836 btn_fore.red, btn_fore.green, btn_fore.blue,
837 xp_theme_is_active ()? 1 : 2);
838 gtk_rc_parse_string (buf);
840 /* enable coloring for progress bars */
841 g_snprintf (buf, sizeof (buf),
842 "style \"msw-progress\" = \"msw-default\"\n"
843 "{bg[PRELIGHT] = { %d, %d, %d }\n"
844 "bg[NORMAL] = { %d, %d, %d }\n"
845 "}widget_class \"*Progress*\" style \"msw-progress\"\n",
849 btn_face.red, btn_face.green, btn_face.blue);
850 gtk_rc_parse_string (buf);
852 /* scrollbar thumb width and height */
853 g_snprintf (buf, sizeof (buf),
854 "style \"msw-vscrollbar\" = \"msw-default\"\n"
855 "{GtkRange::slider-width = %d\n"
856 "GtkRange::stepper-size = %d\n"
857 "GtkRange::stepper-spacing = 0\n"
858 "GtkRange::trough_border = 0\n"
859 "GtkScale::slider-length = %d\n"
860 "GtkScrollbar::min-slider-length = 8\n"
861 "}widget_class \"*VScrollbar*\" style \"msw-vscrollbar\"\n"
862 "widget_class \"*VScale*\" style \"msw-vscrollbar\"\n",
863 GetSystemMetrics (SM_CYVTHUMB),
864 get_system_metric (XP_THEME_CLASS_SCROLLBAR, SM_CXVSCROLL), 11);
865 gtk_rc_parse_string (buf);
867 g_snprintf (buf, sizeof (buf),
868 "style \"msw-hscrollbar\" = \"msw-default\"\n"
869 "{GtkRange::slider-width = %d\n"
870 "GtkRange::stepper-size = %d\n"
871 "GtkRange::stepper-spacing = 0\n"
872 "GtkRange::trough_border = 0\n"
873 "GtkScale::slider-length = %d\n"
874 "GtkScrollbar::min-slider-length = 8\n"
875 "}widget_class \"*HScrollbar*\" style \"msw-hscrollbar\"\n"
876 "widget_class \"*HScale*\" style \"msw-hscrollbar\"\n",
877 GetSystemMetrics (SM_CXHTHUMB),
878 get_system_metric (XP_THEME_CLASS_SCROLLBAR, SM_CYHSCROLL), 11);
879 gtk_rc_parse_string (buf);
881 gtk_rc_parse_string ("style \"msw-scrolled-window\" = \"msw-default\"\n"
882 "{GtkScrolledWindow::scrollbars-within-bevel = 1}\n"
883 "class \"GtkScrolledWindow\" style \"msw-scrolled-window\"\n");
885 /* radio/check button sizes */
886 g_snprintf (buf, sizeof (buf),
887 "style \"msw-checkbutton\" = \"msw-button\"\n"
888 "{GtkCheckButton::indicator-size = 13\n"
889 "}widget_class \"*CheckButton*\" style \"msw-checkbutton\"\n"
890 "widget_class \"*RadioButton*\" style \"msw-checkbutton\"\n");
891 gtk_rc_parse_string (buf);
893 /* size of combo box toggle button */
894 g_snprintf (buf, sizeof (buf),
895 "style \"msw-combobox-button\" = \"msw-default\"\n"
899 "GtkButton::default-border = { 0, 0, 0, 0 }\n"
900 "GtkButton::default-outside-border = { 0, 0, 0, 0 }\n"
901 "GtkButton::child-displacement-x = 0\n"
902 "GtkButton::child-displacement-y = 0\n"
903 "GtkWidget::focus-padding = 0\n"
904 "GtkWidget::focus-line-width = 0\n"
906 "widget_class \"*ComboBox*ToggleButton*\" style \"msw-combobox-button\"\n");
907 gtk_rc_parse_string (buf);
909 g_snprintf (buf, sizeof (buf),
910 "style \"msw-combobox\" = \"msw-default\"\n"
912 "GtkComboBox::shadow-type = in\n"
916 "class \"GtkComboBox\" style \"msw-combobox\"\n",
917 xp_theme_is_active()? 1 : GetSystemMetrics (SM_CXEDGE),
918 xp_theme_is_active()? 1 : GetSystemMetrics (SM_CYEDGE));
919 gtk_rc_parse_string (buf);
921 /* size of tree view header */
922 g_snprintf (buf, sizeof (buf),
923 "style \"msw-header-button\" = \"msw-default\"\n"
927 "GtkWidget::draw-border = {0, 0, 0, 0}\n"
928 "GtkButton::default-border = { 0, 0, 0, 0 }\n"
929 "GtkButton::default-outside-border = { 0, 0, 0, 0 }\n"
930 "GtkButton::child-displacement-x = 0\n"
931 "GtkButton::child-displacement-y = 0\n"
932 "GtkWidget::focus-padding = 0\n"
933 "GtkWidget::focus-line-width = 0\n"
935 "widget_class \"*TreeView*Button*\" style \"msw-header-button\"\n");
936 gtk_rc_parse_string (buf);
938 /* FIXME: This should be enabled once gtk+ support GtkNotebok::prelight-tab */
939 /* enable prelight tab of GtkNotebook */
941 g_snprintf (buf, sizeof (buf),
942 "style \"msw-notebook\" = \"msw-default\"\n"
943 "{GtkNotebook::prelight-tab=1\n"
944 "}widget_class \"*Notebook*\" style \"msw-notebook\"\n");
945 gtk_rc_parse_string (buf);
948 /* FIXME: This should be enabled once gtk+ support GtkTreeView::full-row-focus */
950 g_snprintf (buf, sizeof (buf),
951 "style \"msw-treeview\" = \"msw-default\"\n"
952 "{GtkTreeView::full-row-focus=0\n"
953 "}widget_class \"*TreeView*\" style \"msw-treeview\"\n");
954 gtk_rc_parse_string (buf);
959 setup_system_styles (GtkStyle *style)
963 /* Default background */
964 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
965 &style->bg[GTK_STATE_NORMAL]);
966 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT,
967 &style->bg[GTK_STATE_SELECTED]);
968 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
969 &style->bg[GTK_STATE_INSENSITIVE]);
970 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
971 &style->bg[GTK_STATE_ACTIVE]);
972 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
973 &style->bg[GTK_STATE_PRELIGHT]);
976 sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOW,
977 &style->base[GTK_STATE_NORMAL]);
978 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT,
979 &style->base[GTK_STATE_SELECTED]);
980 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
981 &style->base[GTK_STATE_INSENSITIVE]);
982 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
983 &style->base[GTK_STATE_ACTIVE]);
984 sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOW,
985 &style->base[GTK_STATE_PRELIGHT]);
988 sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT,
989 &style->text[GTK_STATE_NORMAL]);
990 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT,
991 &style->text[GTK_STATE_SELECTED]);
992 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_GRAYTEXT,
993 &style->text[GTK_STATE_INSENSITIVE]);
994 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT,
995 &style->text[GTK_STATE_ACTIVE]);
996 sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT,
997 &style->text[GTK_STATE_PRELIGHT]);
999 /* Default foreground */
1000 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT,
1001 &style->fg[GTK_STATE_NORMAL]);
1002 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT,
1003 &style->fg[GTK_STATE_SELECTED]);
1004 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_GRAYTEXT,
1005 &style->fg[GTK_STATE_INSENSITIVE]);
1006 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT,
1007 &style->fg[GTK_STATE_ACTIVE]);
1008 sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT,
1009 &style->fg[GTK_STATE_PRELIGHT]);
1011 for (i = 0; i < 5; i++)
1013 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_3DSHADOW,
1015 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_3DHILIGHT,
1018 style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2;
1019 style->mid[i].green =
1020 (style->light[i].green + style->dark[i].green) / 2;
1021 style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2;
1023 style->text_aa[i].red = (style->text[i].red + style->base[i].red) / 2;
1024 style->text_aa[i].green =
1025 (style->text[i].green + style->base[i].green) / 2;
1026 style->text_aa[i].blue =
1027 (style->text[i].blue + style->base[i].blue) / 2;
1032 sanitize_size (GdkWindow *window, gint *width, gint *height)
1034 gboolean set_bg = FALSE;
1036 if ((*width == -1) && (*height == -1))
1038 set_bg = GDK_IS_WINDOW (window);
1039 gdk_drawable_get_size (window, width, height);
1041 else if (*width == -1)
1043 gdk_drawable_get_size (window, width, NULL);
1045 else if (*height == -1)
1047 gdk_drawable_get_size (window, NULL, height);
1053 static XpThemeElement
1054 map_gtk_progress_bar_to_xp (GtkProgressBar *progress_bar, gboolean trough)
1058 switch (gtk_progress_bar_get_orientation (progress_bar))
1060 case GTK_PROGRESS_LEFT_TO_RIGHT:
1061 case GTK_PROGRESS_RIGHT_TO_LEFT:
1063 ? XP_THEME_ELEMENT_PROGRESS_TROUGH_H
1064 : XP_THEME_ELEMENT_PROGRESS_BAR_H;
1069 ? XP_THEME_ELEMENT_PROGRESS_TROUGH_V
1070 : XP_THEME_ELEMENT_PROGRESS_BAR_V;
1078 is_combo_box_child (GtkWidget *w)
1085 for (tmp = w->parent; tmp; tmp = tmp->parent)
1087 if (GTK_IS_COMBO_BOX (tmp))
1094 /* This function is not needed anymore */
1096 combo_box_draw_arrow (GtkStyle *style,
1099 GdkRectangle *area, GtkWidget *widget)
1101 if (xp_theme_is_active ())
1104 if (widget && GTK_IS_TOGGLE_BUTTON (widget->parent))
1111 dc = get_window_dc (style, window, state, &dc_info, area->x, area->y, area->width,
1112 area->height, &rect);
1113 border = (GTK_TOGGLE_BUTTON (widget->parent)->
1114 active ? DFCS_PUSHED | DFCS_FLAT : 0);
1116 InflateRect (&rect, 1, 1);
1117 DrawFrameControl (dc, &rect, DFC_SCROLL, DFCS_SCROLLDOWN | border);
1119 release_window_dc (&dc_info);
1128 draw_part (GdkDrawable *drawable,
1129 GdkGC *gc, GdkRectangle *area, gint x, gint y, Part part)
1132 gdk_gc_set_clip_rectangle (gc, area);
1134 if (!parts[part].bmap)
1136 parts[part].bmap = gdk_bitmap_create_from_data (drawable,
1138 PART_SIZE, PART_SIZE);
1141 gdk_gc_set_ts_origin (gc, x, y);
1142 gdk_gc_set_stipple (gc, parts[part].bmap);
1143 gdk_gc_set_fill (gc, GDK_STIPPLED);
1145 gdk_draw_rectangle (drawable, gc, TRUE, x, y, PART_SIZE, PART_SIZE);
1147 gdk_gc_set_fill (gc, GDK_SOLID);
1150 gdk_gc_set_clip_rectangle (gc, NULL);
1154 draw_check (GtkStyle *style,
1157 GtkShadowType shadow,
1160 const gchar *detail, gint x, gint y, gint width, gint height)
1162 x -= (1 + PART_SIZE - width) / 2;
1163 y -= (1 + PART_SIZE - height) / 2;
1165 if (detail && strcmp (detail, "check") == 0) /* Menu item */
1167 if (shadow == GTK_SHADOW_IN)
1169 draw_part (window, style->black_gc, area, x, y, CHECK_TEXT);
1170 draw_part (window, style->dark_gc[state], area, x, y, CHECK_AA);
1175 XpThemeElement theme_elt = XP_THEME_ELEMENT_CHECKBOX;
1178 case GTK_SHADOW_ETCHED_IN:
1179 theme_elt = XP_THEME_ELEMENT_INCONSISTENT_CHECKBOX;
1183 theme_elt = XP_THEME_ELEMENT_PRESSED_CHECKBOX;
1190 if (!xp_theme_draw (window, theme_elt,
1191 style, x, y, width, height, state, area))
1193 if (detail && !strcmp (detail, "cellcheck"))
1194 state = GTK_STATE_NORMAL;
1196 draw_part (window, style->black_gc, area, x, y, CHECK_BLACK);
1197 draw_part (window, style->dark_gc[state], area, x, y, CHECK_DARK);
1198 draw_part (window, style->mid_gc[state], area, x, y, CHECK_MID);
1199 draw_part (window, style->light_gc[state], area, x, y, CHECK_LIGHT);
1200 draw_part (window, style->base_gc[state], area, x, y, CHECK_BASE);
1202 if (shadow == GTK_SHADOW_IN)
1204 draw_part (window, style->text_gc[state], area, x,
1206 draw_part (window, style->text_aa_gc[state], area,
1209 else if (shadow == GTK_SHADOW_ETCHED_IN)
1211 draw_part (window, style->text_gc[state], area, x, y,
1212 CHECK_INCONSISTENT);
1213 draw_part (window, style->text_aa_gc[state], area, x, y,
1221 draw_expander (GtkStyle *style,
1226 const gchar *detail,
1227 gint x, gint y, GtkExpanderStyle expander_style)
1230 gint expander_semi_size;
1231 XpThemeElement xp_expander;
1233 gtk_widget_style_get (widget, "expander_size", &expander_size, NULL);
1235 switch (expander_style)
1237 case GTK_EXPANDER_COLLAPSED:
1238 case GTK_EXPANDER_SEMI_COLLAPSED:
1239 xp_expander = XP_THEME_ELEMENT_TREEVIEW_EXPANDER_CLOSED;
1243 xp_expander = XP_THEME_ELEMENT_TREEVIEW_EXPANDER_OPENED;
1247 if ((expander_size % 2) == 0)
1250 if (expander_size > 2)
1254 gdk_gc_set_clip_rectangle (style->fg_gc[state], area);
1256 expander_semi_size = expander_size / 2;
1257 x -= expander_semi_size;
1258 y -= expander_semi_size;
1260 if (!xp_theme_draw (window, xp_expander, style,
1261 x, y, expander_size, expander_size, state, area))
1269 dc = get_window_dc (style, window, state, &dc_info, x, y, expander_size,
1270 expander_size, &rect);
1271 FrameRect (dc, &rect, GetSysColorBrush (COLOR_GRAYTEXT));
1272 InflateRect (&rect, -1, -1);
1273 FillRect (dc, &rect,
1274 GetSysColorBrush (state ==
1275 GTK_STATE_INSENSITIVE ? COLOR_BTNFACE :
1278 InflateRect (&rect, -1, -1);
1280 pen = CreatePen (PS_SOLID, 1, GetSysColor (COLOR_WINDOWTEXT));
1281 old_pen = SelectObject (dc, pen);
1283 MoveToEx (dc, rect.left, rect.top - 2 + expander_semi_size, NULL);
1284 LineTo (dc, rect.right, rect.top - 2 + expander_semi_size);
1286 if (expander_style == GTK_EXPANDER_COLLAPSED ||
1287 expander_style == GTK_EXPANDER_SEMI_COLLAPSED)
1289 MoveToEx (dc, rect.left - 2 + expander_semi_size, rect.top, NULL);
1290 LineTo (dc, rect.left - 2 + expander_semi_size, rect.bottom);
1293 SelectObject (dc, old_pen);
1295 release_window_dc (&dc_info);
1299 gdk_gc_set_clip_rectangle (style->fg_gc[state], NULL);
1303 draw_option (GtkStyle *style,
1306 GtkShadowType shadow,
1309 const gchar *detail, gint x, gint y, gint width, gint height)
1311 x -= (1 + PART_SIZE - width) / 2;
1312 y -= (1 + PART_SIZE - height) / 2;
1314 if (detail && strcmp (detail, "option") == 0) /* Menu item */
1316 if (shadow == GTK_SHADOW_IN)
1318 draw_part (window, style->fg_gc[state], area, x, y, RADIO_TEXT);
1323 if (xp_theme_draw (window, shadow == GTK_SHADOW_IN
1324 ? XP_THEME_ELEMENT_PRESSED_RADIO_BUTTON
1325 : XP_THEME_ELEMENT_RADIO_BUTTON,
1326 style, x, y, width, height, state, area))
1331 if (detail && !strcmp (detail, "cellradio"))
1332 state = GTK_STATE_NORMAL;
1334 draw_part (window, style->black_gc, area, x, y, RADIO_BLACK);
1335 draw_part (window, style->dark_gc[state], area, x, y, RADIO_DARK);
1336 draw_part (window, style->mid_gc[state], area, x, y, RADIO_MID);
1337 draw_part (window, style->light_gc[state], area, x, y, RADIO_LIGHT);
1338 draw_part (window, style->base_gc[state], area, x, y, RADIO_BASE);
1340 if (shadow == GTK_SHADOW_IN)
1341 draw_part (window, style->text_gc[state], area, x, y, RADIO_TEXT);
1347 draw_varrow (GdkWindow *window,
1349 GtkShadowType shadow_type,
1351 GtkArrowType arrow_type, gint x, gint y, gint width, gint height)
1354 gint y_start, y_increment;
1358 gdk_gc_set_clip_rectangle (gc, area);
1360 width = width + width % 2 - 1; /* Force odd */
1361 steps = 1 + width / 2;
1362 extra = height - steps;
1364 if (arrow_type == GTK_ARROW_DOWN)
1371 y_start = y + height - 1;
1375 for (i = extra; i < height; i++)
1377 gdk_draw_line (window, gc,
1378 x + (i - extra), y_start + i * y_increment,
1379 x + width - (i - extra) - 1, y_start + i * y_increment);
1383 gdk_gc_set_clip_rectangle (gc, NULL);
1387 draw_harrow (GdkWindow *window,
1389 GtkShadowType shadow_type,
1391 GtkArrowType arrow_type, gint x, gint y, gint width, gint height)
1394 gint x_start, x_increment;
1398 gdk_gc_set_clip_rectangle (gc, area);
1400 height = height + height % 2 - 1; /* Force odd */
1401 steps = 1 + height / 2;
1402 extra = width - steps;
1404 if (arrow_type == GTK_ARROW_RIGHT)
1411 x_start = x + width - 1;
1415 for (i = extra; i < width; i++)
1417 gdk_draw_line (window, gc,
1418 x_start + i * x_increment, y + (i - extra),
1419 x_start + i * x_increment, y + height - (i - extra) - 1);
1424 gdk_gc_set_clip_rectangle (gc, NULL);
1427 /* This function makes up for some brokeness in gtkrange.c
1428 * where we never get the full arrow of the stepper button
1429 * and the type of button in a single drawing function.
1431 * It doesn't work correctly when the scrollbar is squished
1432 * to the point we don't have room for full-sized steppers.
1435 reverse_engineer_stepper_box (GtkWidget *range,
1436 GtkArrowType arrow_type,
1437 gint *x, gint *y, gint *width, gint *height)
1439 gint slider_width = 14, stepper_size = 14;
1445 gtk_widget_style_get (range,
1446 "slider_width", &slider_width,
1447 "stepper_size", &stepper_size, NULL);
1450 if (arrow_type == GTK_ARROW_UP || arrow_type == GTK_ARROW_DOWN)
1452 box_width = slider_width;
1453 box_height = stepper_size;
1457 box_width = stepper_size;
1458 box_height = slider_width;
1461 *x = *x - (box_width - *width) / 2;
1462 *y = *y - (box_height - *height) / 2;
1464 *height = box_height;
1467 static XpThemeElement
1468 to_xp_arrow (GtkArrowType arrow_type)
1470 XpThemeElement xp_arrow;
1475 xp_arrow = XP_THEME_ELEMENT_ARROW_UP;
1478 case GTK_ARROW_DOWN:
1479 xp_arrow = XP_THEME_ELEMENT_ARROW_DOWN;
1482 case GTK_ARROW_LEFT:
1483 xp_arrow = XP_THEME_ELEMENT_ARROW_LEFT;
1487 xp_arrow = XP_THEME_ELEMENT_ARROW_RIGHT;
1495 draw_arrow (GtkStyle *style,
1498 GtkShadowType shadow,
1501 const gchar *detail,
1502 GtkArrowType arrow_type,
1503 gboolean fill, gint x, gint y, gint width, gint height)
1510 name = gtk_widget_get_name (widget);
1512 sanitize_size (window, &width, &height);
1514 if (GTK_IS_ARROW (widget) && is_combo_box_child (widget) && xp_theme_is_active ())
1517 if (detail && strcmp (detail, "spinbutton") == 0)
1519 if (xp_theme_is_drawable (XP_THEME_ELEMENT_SPIN_BUTTON_UP))
1526 if (arrow_type == GTK_ARROW_DOWN)
1530 if (state == GTK_STATE_ACTIVE)
1536 draw_varrow (window, style->fg_gc[state], shadow, area,
1537 arrow_type, x, y, width, height);
1541 else if (detail && (!strcmp (detail, "vscrollbar")
1542 || !strcmp (detail, "hscrollbar")))
1544 gboolean is_disabled = FALSE;
1546 GtkScrollbar *scrollbar = GTK_SCROLLBAR (widget);
1550 gint box_width = width;
1551 gint box_height = height;
1553 reverse_engineer_stepper_box (widget, arrow_type,
1554 &box_x, &box_y, &box_width, &box_height);
1556 if (scrollbar->range.adjustment->page_size >=
1557 (scrollbar->range.adjustment->upper -
1558 scrollbar->range.adjustment->lower))
1563 if (xp_theme_draw (window, to_xp_arrow (arrow_type), style, box_x, box_y,
1564 box_width, box_height, state, area))
1572 btn_type = DFCS_SCROLLUP;
1575 case GTK_ARROW_DOWN:
1576 btn_type = DFCS_SCROLLDOWN;
1579 case GTK_ARROW_LEFT:
1580 btn_type = DFCS_SCROLLLEFT;
1583 case GTK_ARROW_RIGHT:
1584 btn_type = DFCS_SCROLLRIGHT;
1587 case GTK_ARROW_NONE:
1591 if (state == GTK_STATE_INSENSITIVE)
1593 btn_type |= DFCS_INACTIVE;
1598 sanitize_size (window, &width, &height);
1600 dc = get_window_dc (style, window, state, &dc_info,
1601 box_x, box_y, box_width, box_height, &rect);
1602 DrawFrameControl (dc, &rect, DFC_SCROLL,
1603 btn_type | (shadow ==
1604 GTK_SHADOW_IN ? (DFCS_PUSHED |
1606 release_window_dc (&dc_info);
1612 /* draw the toolbar chevrons - waiting for GTK 2.4 */
1613 if (name && !strcmp (name, "gtk-toolbar-arrow"))
1616 (window, XP_THEME_ELEMENT_REBAR_CHEVRON, style, x, y,
1617 width, height, state, area))
1622 /* probably a gtk combo box on a toolbar */
1623 else if (0 /* widget->parent && GTK_IS_BUTTON
1624 (widget->parent) */ )
1627 (window, XP_THEME_ELEMENT_COMBOBUTTON, style, x - 3,
1628 widget->allocation.y + 1, width + 5,
1629 widget->allocation.height - 4, state, area))
1635 if (arrow_type == GTK_ARROW_UP || arrow_type == GTK_ARROW_DOWN)
1637 x += (width - 7) / 2;
1638 y += (height - 5) / 2;
1640 draw_varrow (window, style->fg_gc[state], shadow, area,
1641 arrow_type, x, y, 7, 5);
1645 x += (width - 5) / 2;
1646 y += (height - 7) / 2;
1648 draw_harrow (window, style->fg_gc[state], shadow, area,
1649 arrow_type, x, y, 5, 7);
1655 option_menu_get_props (GtkWidget *widget,
1656 GtkRequisition *indicator_size,
1657 GtkBorder *indicator_spacing)
1659 GtkRequisition *tmp_size = NULL;
1660 GtkBorder *tmp_spacing = NULL;
1663 gtk_widget_style_get (widget,
1664 "indicator_size", &tmp_size,
1665 "indicator_spacing", &tmp_spacing, NULL);
1669 *indicator_size = *tmp_size;
1670 gtk_requisition_free (tmp_size);
1674 *indicator_size = default_option_indicator_size;
1679 *indicator_spacing = *tmp_spacing;
1680 gtk_border_free (tmp_spacing);
1684 *indicator_spacing = default_option_indicator_spacing;
1689 is_toolbar_child (GtkWidget *wid)
1693 if (GTK_IS_TOOLBAR (wid) || GTK_IS_HANDLE_BOX (wid))
1703 is_menu_tool_button_child (GtkWidget *wid)
1707 if (GTK_IS_MENU_TOOL_BUTTON (wid))
1720 g_light_pen = CreatePen (PS_SOLID | PS_INSIDEFRAME, 1,
1721 GetSysColor (COLOR_BTNHIGHLIGHT));
1732 g_dark_pen = CreatePen (PS_SOLID | PS_INSIDEFRAME, 1,
1733 GetSysColor (COLOR_BTNSHADOW));
1740 draw_3d_border (HDC hdc, RECT *rc, gboolean sunken)
1747 pen1 = get_dark_pen ();
1748 pen2 = get_light_pen ();
1752 pen1 = get_light_pen ();
1753 pen2 = get_dark_pen ();
1756 MoveToEx (hdc, rc->left, rc->bottom - 1, NULL);
1758 old_pen = SelectObject (hdc, pen1);
1759 LineTo (hdc, rc->left, rc->top);
1760 LineTo (hdc, rc->right - 1, rc->top);
1761 SelectObject (hdc, old_pen);
1763 old_pen = SelectObject (hdc, pen2);
1764 LineTo (hdc, rc->right - 1, rc->bottom - 1);
1765 LineTo (hdc, rc->left, rc->bottom - 1);
1766 SelectObject (hdc, old_pen);
1770 draw_menu_item (GdkWindow *window, GtkWidget *widget, GtkStyle *style,
1771 gint x, gint y, gint width, gint height,
1772 GtkStateType state_type, GdkRectangle *area)
1780 if (xp_theme_is_active ())
1782 return (xp_theme_draw (window, XP_THEME_ELEMENT_MENU_ITEM, style,
1783 x, y, width, height, state_type, area));
1786 if ((parent = gtk_widget_get_parent (widget))
1787 && GTK_IS_MENU_BAR (parent) && !xp_theme_is_active ())
1789 bar = GTK_MENU_SHELL (parent);
1791 dc = get_window_dc (style, window, state_type, &dc_info, x, y, width, height, &rect);
1793 if (state_type == GTK_STATE_PRELIGHT)
1795 draw_3d_border (dc, &rect, bar->active);
1798 release_window_dc (&dc_info);
1807 get_dither_brush (void)
1810 HBITMAP pattern_bmp;
1814 return g_dither_brush;
1816 for (i = 0; i < 8; i++)
1818 pattern[i] = (WORD) (0x5555 << (i & 1));
1821 pattern_bmp = CreateBitmap (8, 8, 1, 1, &pattern);
1825 g_dither_brush = CreatePatternBrush (pattern_bmp);
1826 DeleteObject (pattern_bmp);
1829 return g_dither_brush;
1833 draw_tool_button (GdkWindow *window, GtkWidget *widget, GtkStyle *style,
1834 gint x, gint y, gint width, gint height,
1835 GtkStateType state_type, GdkRectangle *area)
1840 gboolean is_toggled = FALSE;
1842 if (xp_theme_is_active ())
1844 return (xp_theme_draw (window, XP_THEME_ELEMENT_TOOLBAR_BUTTON, style,
1845 x, y, width, height, state_type, area));
1848 if (GTK_IS_TOGGLE_BUTTON (widget))
1850 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
1856 if (state_type != GTK_STATE_PRELIGHT
1857 && state_type != GTK_STATE_ACTIVE && !is_toggled)
1862 dc = get_window_dc (style, window, state_type, &dc_info, x, y, width, height, &rect);
1863 if (state_type == GTK_STATE_PRELIGHT)
1867 FillRect (dc, &rect, GetSysColorBrush (COLOR_BTNFACE));
1870 draw_3d_border (dc, &rect, is_toggled);
1872 else if (state_type == GTK_STATE_ACTIVE)
1874 if (is_toggled && !is_menu_tool_button_child (widget->parent))
1876 SetTextColor (dc, GetSysColor (COLOR_3DHILIGHT));
1877 SetBkColor (dc, GetSysColor (COLOR_BTNFACE));
1878 FillRect (dc, &rect, get_dither_brush ());
1881 draw_3d_border (dc, &rect, TRUE);
1884 release_window_dc (&dc_info);
1890 draw_push_button (GdkWindow *window, GtkWidget *widget, GtkStyle *style,
1891 gint x, gint y, gint width, gint height,
1892 GtkStateType state_type, gboolean is_default)
1898 dc = get_window_dc (style, window, state_type, &dc_info, x, y, width, height, &rect);
1900 if (GTK_IS_TOGGLE_BUTTON (widget))
1902 if (state_type == GTK_STATE_PRELIGHT &&
1903 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
1905 state_type = GTK_STATE_ACTIVE;
1909 if (state_type == GTK_STATE_ACTIVE)
1911 if (GTK_IS_TOGGLE_BUTTON (widget))
1913 DrawEdge (dc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1914 SetTextColor (dc, GetSysColor (COLOR_3DHILIGHT));
1915 SetBkColor (dc, GetSysColor (COLOR_BTNFACE));
1916 FillRect (dc, &rect, get_dither_brush ());
1920 FrameRect (dc, &rect, GetSysColorBrush (COLOR_WINDOWFRAME));
1921 InflateRect (&rect, -1, -1);
1922 FrameRect (dc, &rect, GetSysColorBrush (COLOR_BTNSHADOW));
1923 InflateRect (&rect, -1, -1);
1924 FillRect (dc, &rect, GetSysColorBrush (COLOR_BTNFACE));
1929 if (is_default || gtk_widget_has_focus (widget))
1931 FrameRect (dc, &rect, GetSysColorBrush (COLOR_WINDOWFRAME));
1932 InflateRect (&rect, -1, -1);
1935 DrawFrameControl (dc, &rect, DFC_BUTTON, DFCS_BUTTONPUSH);
1938 release_window_dc (&dc_info);
1942 draw_box (GtkStyle *style,
1944 GtkStateType state_type,
1945 GtkShadowType shadow_type,
1948 const gchar *detail, gint x, gint y, gint width, gint height)
1950 if (is_combo_box_child (widget) && detail && !strcmp (detail, "button"))
1958 border = (GTK_TOGGLE_BUTTON (widget)->active ? DFCS_PUSHED | DFCS_FLAT : 0);
1960 dc = get_window_dc (style, window, state_type, &dc_info, x, y, width, height, &rect);
1961 DrawFrameControl (dc, &rect, DFC_SCROLL, DFCS_SCROLLDOWN | border);
1962 release_window_dc (&dc_info);
1964 if (xp_theme_is_active ()
1965 && xp_theme_draw (window, XP_THEME_ELEMENT_COMBOBUTTON, style, x, y,
1966 width, height, state_type, area))
1968 cx = GetSystemMetrics(SM_CXVSCROLL);
1973 dc = get_window_dc (style, window, state_type, &dc_info, x, y, width - cx, height, &rect);
1974 FillRect (dc, &rect, GetSysColorBrush (COLOR_WINDOW));
1975 release_window_dc (&dc_info);
1981 (!strcmp (detail, "button") || !strcmp (detail, "buttondefault")))
1983 if (GTK_IS_TREE_VIEW (widget->parent))
1986 (window, XP_THEME_ELEMENT_LIST_HEADER, style, x, y,
1987 width, height, state_type, area))
1996 dc = get_window_dc (style, window, state_type, &dc_info, x, y, width, height, &rect);
1998 DrawFrameControl (dc, &rect, DFC_BUTTON, DFCS_BUTTONPUSH |
2000 GTK_STATE_ACTIVE ? (DFCS_PUSHED | DFCS_FLAT)
2002 release_window_dc (&dc_info);
2005 else if (is_toolbar_child (widget->parent)
2006 || (!GTK_IS_BUTTON (widget) ||
2007 (GTK_RELIEF_NONE == gtk_button_get_relief (GTK_BUTTON (widget)))))
2009 if (draw_tool_button (window, widget, style, x, y,
2010 width, height, state_type, area))
2017 gboolean is_default = gtk_widget_has_default (widget);
2020 is_default ? XP_THEME_ELEMENT_DEFAULT_BUTTON :
2021 XP_THEME_ELEMENT_BUTTON, style, x, y, width, height,
2027 draw_push_button (window, widget, style,
2028 x, y, width, height, state_type, is_default);
2035 else if (detail && !strcmp (detail, "spinbutton"))
2037 if (xp_theme_is_drawable (XP_THEME_ELEMENT_SPIN_BUTTON_UP))
2042 else if (detail && (!strcmp (detail, "spinbutton_up")
2043 || !strcmp (detail, "spinbutton_down")))
2045 if (!xp_theme_draw (window,
2046 (!strcmp (detail, "spinbutton_up"))
2047 ? XP_THEME_ELEMENT_SPIN_BUTTON_UP
2048 : XP_THEME_ELEMENT_SPIN_BUTTON_DOWN,
2049 style, x, y, width, height, state_type, area))
2055 dc = get_window_dc (style, window, state_type, &dc_info,
2056 x, y, width, height, &rect);
2057 DrawEdge (dc, &rect,
2059 GTK_STATE_ACTIVE ? EDGE_SUNKEN : EDGE_RAISED, BF_RECT);
2060 release_window_dc (&dc_info);
2064 else if (detail && !strcmp (detail, "slider"))
2066 if (GTK_IS_SCROLLBAR (widget))
2068 GtkScrollbar *scrollbar = GTK_SCROLLBAR (widget);
2069 gboolean is_v = GTK_IS_VSCROLLBAR (widget);
2071 if (xp_theme_draw (window,
2073 ? XP_THEME_ELEMENT_SCROLLBAR_V
2074 : XP_THEME_ELEMENT_SCROLLBAR_H,
2075 style, x, y, width, height, state_type, area))
2077 XpThemeElement gripper =
2078 (is_v ? XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V :
2079 XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H);
2081 /* Do not display grippers on tiny scroll bars,
2082 the limit imposed is rather arbitrary, perhaps
2083 we can fetch the gripper geometry from
2084 somewhere and use that... */
2086 XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H
2089 XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V && height < 16))
2094 xp_theme_draw (window, gripper, style, x, y,
2095 width, height, state_type, area);
2100 if (scrollbar->range.adjustment->page_size >=
2101 (scrollbar->range.adjustment->upper -
2102 scrollbar->range.adjustment->lower))
2109 else if (detail && !strcmp (detail, "bar"))
2111 if (widget && GTK_IS_PROGRESS_BAR (widget))
2113 GtkProgressBar *progress_bar = GTK_PROGRESS_BAR (widget);
2114 XpThemeElement xp_progress_bar =
2115 map_gtk_progress_bar_to_xp (progress_bar, FALSE);
2117 if (xp_theme_draw (window, xp_progress_bar, style, x, y,
2118 width, height, state_type, area))
2123 shadow_type = GTK_SHADOW_NONE;
2126 else if (detail && strcmp (detail, "menuitem") == 0)
2128 shadow_type = GTK_SHADOW_NONE;
2129 if (draw_menu_item (window, widget, style,
2130 x, y, width, height, state_type, area))
2135 else if (detail && !strcmp (detail, "trough"))
2137 if (widget && GTK_IS_PROGRESS_BAR (widget))
2139 GtkProgressBar *progress_bar = GTK_PROGRESS_BAR (widget);
2140 XpThemeElement xp_progress_bar =
2141 map_gtk_progress_bar_to_xp (progress_bar, TRUE);
2143 (window, xp_progress_bar, style, x, y, width, height,
2150 /* Blank in classic Windows */
2153 else if (widget && GTK_IS_SCROLLBAR (widget))
2155 gboolean is_vertical = GTK_IS_VSCROLLBAR (widget);
2157 if (xp_theme_draw (window,
2159 ? XP_THEME_ELEMENT_TROUGH_V
2160 : XP_THEME_ELEMENT_TROUGH_H,
2161 style, x, y, width, height, state_type, area))
2171 sanitize_size (window, &width, &height);
2172 dc = get_window_dc (style, window, state_type, &dc_info, x, y, width, height, &rect);
2174 SetTextColor (dc, GetSysColor (COLOR_3DHILIGHT));
2175 SetBkColor (dc, GetSysColor (COLOR_BTNFACE));
2176 FillRect (dc, &rect, get_dither_brush ());
2178 release_window_dc (&dc_info);
2183 else if (widget && GTK_IS_SCALE (widget))
2185 gboolean is_vertical = GTK_IS_VSCALE (widget);
2187 if (!xp_theme_is_active ())
2189 parent_class->draw_box (style, window, state_type,
2190 GTK_SHADOW_NONE, area,
2191 widget, detail, x, y, width, height);
2197 (window, XP_THEME_ELEMENT_SCALE_TROUGH_V,
2198 style, (2 * x + width) / 2, y, 2, height,
2204 parent_class->draw_box (style, window, state_type,
2205 GTK_SHADOW_ETCHED_IN,
2207 (2 * x + width) / 2, y, 1, height);
2212 (window, XP_THEME_ELEMENT_SCALE_TROUGH_H,
2213 style, x, (2 * y + height) / 2, width, 2,
2219 parent_class->draw_box (style, window, state_type,
2220 GTK_SHADOW_ETCHED_IN,
2221 area, NULL, NULL, x,
2222 (2 * y + height) / 2, width, 1);
2228 else if (detail && strcmp (detail, "optionmenu") == 0)
2230 if (xp_theme_draw (window, XP_THEME_ELEMENT_EDIT_TEXT,
2231 style, x, y, width, height, state_type, area))
2237 && (strcmp (detail, "vscrollbar") == 0
2238 || strcmp (detail, "hscrollbar") == 0))
2243 && (strcmp (detail, "handlebox_bin") == 0
2244 || strcmp (detail, "toolbar") == 0
2245 || strcmp (detail, "menubar") == 0))
2247 sanitize_size (window, &width, &height);
2248 if (xp_theme_draw (window, XP_THEME_ELEMENT_REBAR,
2249 style, x, y, width, height, state_type, area))
2254 else if (detail && (!strcmp (detail, "handlebox"))) /* grip */
2256 if (!xp_theme_is_active ())
2261 else if (detail && !strcmp (detail, "notebook") && GTK_IS_NOTEBOOK (widget))
2263 if (xp_theme_draw (window, XP_THEME_ELEMENT_TAB_PANE, style,
2264 x, y, width, height, state_type, area))
2272 const gchar *name = gtk_widget_get_name (widget);
2274 if (name && !strcmp (name, "gtk-tooltips"))
2277 (window, XP_THEME_ELEMENT_TOOLTIP, style, x, y, width,
2278 height, state_type, area))
2289 hdc = get_window_dc (style, window, state_type, &dc_info, x, y, width, height, &rect);
2291 brush = GetSysColorBrush (COLOR_3DDKSHADOW);
2295 FrameRect (hdc, &rect, brush);
2298 InflateRect (&rect, -1, -1);
2299 FillRect (hdc, &rect, (HBRUSH) (COLOR_INFOBK + 1));
2301 release_window_dc (&dc_info);
2308 parent_class->draw_box (style, window, state_type, shadow_type, area,
2309 widget, detail, x, y, width, height);
2311 if (detail && strcmp (detail, "optionmenu") == 0)
2313 GtkRequisition indicator_size;
2314 GtkBorder indicator_spacing;
2317 option_menu_get_props (widget, &indicator_size, &indicator_spacing);
2319 sanitize_size (window, &width, &height);
2321 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
2324 x + indicator_size.width + indicator_spacing.left +
2325 indicator_spacing.right;
2329 vline_x = x + width - (indicator_size.width +
2330 indicator_spacing.left +
2331 indicator_spacing.right) - style->xthickness;
2333 parent_class->draw_vline (style, window, state_type, area, widget,
2335 y + style->ythickness + 1,
2336 y + height - style->ythickness - 3, vline_x);
2342 draw_tab (GtkStyle *style,
2345 GtkShadowType shadow,
2348 const gchar *detail, gint x, gint y, gint width, gint height)
2350 GtkRequisition indicator_size;
2351 GtkBorder indicator_spacing;
2355 g_return_if_fail (style != NULL);
2356 g_return_if_fail (window != NULL);
2358 if (detail && !strcmp (detail, "optionmenutab"))
2360 if (xp_theme_draw (window, XP_THEME_ELEMENT_COMBOBUTTON,
2361 style, x - 5, widget->allocation.y + 1,
2362 width + 10, widget->allocation.height - 2,
2369 option_menu_get_props (widget, &indicator_size, &indicator_spacing);
2371 x += (width - indicator_size.width) / 2;
2372 arrow_height = (indicator_size.width + 1) / 2;
2374 y += (height - arrow_height) / 2;
2376 draw_varrow (window, style->black_gc, shadow, area, GTK_ARROW_DOWN,
2377 x, y, indicator_size.width, arrow_height);
2380 /* Draw classic Windows tab - thanks Mozilla!
2381 (no system API for this, but DrawEdge can draw all the parts of a tab) */
2383 DrawTab (HDC hdc, const RECT R, gint32 aPosition, gboolean aSelected,
2384 gboolean aDrawLeft, gboolean aDrawRight)
2386 gint32 leftFlag, topFlag, rightFlag, lightFlag, shadeFlag;
2387 RECT topRect, sideRect, bottomRect, lightRect, shadeRect;
2388 gint32 selectedOffset, lOffset, rOffset;
2390 selectedOffset = aSelected ? 1 : 0;
2391 lOffset = aDrawLeft ? 2 : 0;
2392 rOffset = aDrawRight ? 2 : 0;
2394 /* Get info for tab orientation/position (Left, Top, Right, Bottom) */
2400 rightFlag = BF_BOTTOM;
2401 lightFlag = BF_DIAGONAL_ENDTOPRIGHT;
2402 shadeFlag = BF_DIAGONAL_ENDBOTTOMRIGHT;
2404 SetRect (&topRect, R.left, R.top + lOffset, R.right,
2405 R.bottom - rOffset);
2406 SetRect (&sideRect, R.left + 2, R.top, R.right - 2 + selectedOffset,
2408 SetRect (&bottomRect, R.right - 2, R.top, R.right, R.bottom);
2409 SetRect (&lightRect, R.left, R.top, R.left + 3, R.top + 3);
2410 SetRect (&shadeRect, R.left + 1, R.bottom - 2, R.left + 2,
2417 rightFlag = BF_RIGHT;
2418 lightFlag = BF_DIAGONAL_ENDTOPRIGHT;
2419 shadeFlag = BF_DIAGONAL_ENDBOTTOMRIGHT;
2421 SetRect (&topRect, R.left + lOffset, R.top, R.right - rOffset,
2423 SetRect (&sideRect, R.left, R.top + 2, R.right,
2424 R.bottom - 1 + selectedOffset);
2425 SetRect (&bottomRect, R.left, R.bottom - 1, R.right, R.bottom);
2426 SetRect (&lightRect, R.left, R.top, R.left + 3, R.top + 3);
2427 SetRect (&shadeRect, R.right - 2, R.top + 1, R.right - 1, R.top + 2);
2433 rightFlag = BF_BOTTOM;
2434 lightFlag = BF_DIAGONAL_ENDTOPLEFT;
2435 shadeFlag = BF_DIAGONAL_ENDBOTTOMLEFT;
2437 SetRect (&topRect, R.left, R.top + lOffset, R.right,
2438 R.bottom - rOffset);
2439 SetRect (&sideRect, R.left + 2 - selectedOffset, R.top, R.right - 2,
2441 SetRect (&bottomRect, R.left, R.top, R.left + 2, R.bottom);
2442 SetRect (&lightRect, R.right - 3, R.top, R.right - 1, R.top + 2);
2443 SetRect (&shadeRect, R.right - 2, R.bottom - 3, R.right, R.bottom - 1);
2448 topFlag = BF_BOTTOM;
2449 rightFlag = BF_RIGHT;
2450 lightFlag = BF_DIAGONAL_ENDTOPLEFT;
2451 shadeFlag = BF_DIAGONAL_ENDBOTTOMLEFT;
2453 SetRect (&topRect, R.left + lOffset, R.top, R.right - rOffset,
2455 SetRect (&sideRect, R.left, R.top + 2 - selectedOffset, R.right,
2457 SetRect (&bottomRect, R.left, R.top, R.right, R.top + 2);
2458 SetRect (&lightRect, R.left, R.bottom - 3, R.left + 2, R.bottom - 1);
2459 SetRect (&shadeRect, R.right - 2, R.bottom - 3, R.right, R.bottom - 1);
2463 g_return_if_reached ();
2467 FillRect (hdc, &R, (HBRUSH) (COLOR_3DFACE + 1));
2470 DrawEdge (hdc, &topRect, EDGE_RAISED, BF_SOFT | topFlag);
2474 DrawEdge (hdc, &bottomRect, EDGE_RAISED, BF_SOFT | topFlag);
2482 DrawEdge (hdc, &sideRect, EDGE_RAISED, BF_SOFT | leftFlag | rightFlag);
2484 /* Tab Diagonal Corners */
2486 DrawEdge (hdc, &lightRect, EDGE_RAISED, BF_SOFT | lightFlag);
2489 DrawEdge (hdc, &shadeRect, EDGE_RAISED, BF_SOFT | shadeFlag);
2493 draw_themed_tab_button (GtkStyle *style,
2495 GtkStateType state_type,
2496 GtkNotebook *notebook,
2498 gint width, gint height, gint gap_side)
2500 GdkPixmap *pixmap = NULL;
2502 gtk_container_get_border_width (GTK_CONTAINER (notebook));
2503 GtkWidget *widget = GTK_WIDGET (notebook);
2504 GdkRectangle draw_rect, clip_rect;
2505 GdkPixbufRotation rotation = GDK_PIXBUF_ROTATE_NONE;
2507 if (gap_side == GTK_POS_TOP)
2511 if (state_type == GTK_STATE_NORMAL)
2515 draw_rect.width = width + 2;
2516 draw_rect.height = height;
2518 clip_rect = draw_rect;
2523 draw_rect.x = x + 2;
2525 draw_rect.width = width - 2;
2526 draw_rect.height = height - 2;
2527 clip_rect = draw_rect;
2530 /* If we are currently drawing the right-most tab, and if that tab is the selected tab... */
2531 widget_right = widget->allocation.x + widget->allocation.width - border_width - 2;
2533 if (draw_rect.x + draw_rect.width >= widget_right)
2535 draw_rect.width = clip_rect.width = widget_right - draw_rect.x;
2538 if (gap_side == GTK_POS_BOTTOM)
2542 if (state_type == GTK_STATE_NORMAL)
2546 draw_rect.width = width + 2;
2547 draw_rect.height = height;
2549 clip_rect = draw_rect;
2553 draw_rect.x = x + 2;
2554 draw_rect.y = y + 2;
2555 draw_rect.width = width - 2;
2556 draw_rect.height = height - 2;
2557 clip_rect = draw_rect;
2560 /* If we are currently drawing the right-most tab, and if that tab is the selected tab... */
2561 widget_right = widget->allocation.x + widget->allocation.width - border_width - 2;
2563 if (draw_rect.x + draw_rect.width >= widget_right)
2565 draw_rect.width = clip_rect.width = widget_right - draw_rect.x;
2568 rotation = GDK_PIXBUF_ROTATE_UPSIDEDOWN;
2570 else if (gap_side == GTK_POS_LEFT)
2574 if (state_type == GTK_STATE_NORMAL)
2578 draw_rect.width = width;
2579 draw_rect.height = height + 2;
2581 clip_rect = draw_rect;
2587 draw_rect.y = y + 2;
2588 draw_rect.width = width - 2;
2589 draw_rect.height = height - 2;
2590 clip_rect = draw_rect;
2593 /* If we are currently drawing the bottom-most tab, and if that tab is the selected tab... */
2594 widget_bottom = widget->allocation.x + widget->allocation.height - border_width - 2;
2596 if (draw_rect.y + draw_rect.height >= widget_bottom)
2598 draw_rect.height = clip_rect.height = widget_bottom - draw_rect.y;
2601 rotation = GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE;
2603 else if (gap_side == GTK_POS_RIGHT)
2607 if (state_type == GTK_STATE_NORMAL)
2609 draw_rect.x = x + 1;
2611 draw_rect.width = width;
2612 draw_rect.height = height + 2;
2614 clip_rect = draw_rect;
2619 draw_rect.x = x + 2;
2620 draw_rect.y = y + 2;
2621 draw_rect.width = width - 2;
2622 draw_rect.height = height - 2;
2623 clip_rect = draw_rect;
2626 /* If we are currently drawing the bottom-most tab, and if that tab is the selected tab... */
2627 widget_bottom = widget->allocation.x + widget->allocation.height - border_width - 2;
2629 if (draw_rect.y + draw_rect.height >= widget_bottom)
2631 draw_rect.height = clip_rect.height = widget_bottom - draw_rect.y;
2634 rotation = GDK_PIXBUF_ROTATE_CLOCKWISE;
2637 if (gap_side == GTK_POS_TOP)
2639 if (!xp_theme_draw (window, XP_THEME_ELEMENT_TAB_ITEM, style,
2640 draw_rect.x, draw_rect.y,
2641 draw_rect.width, draw_rect.height,
2642 state_type, &clip_rect))
2652 if (gap_side == GTK_POS_LEFT || gap_side == GTK_POS_RIGHT)
2654 pixmap = gdk_pixmap_new (window, clip_rect.height, clip_rect.width, -1);
2656 if (!xp_theme_draw (pixmap, XP_THEME_ELEMENT_TAB_ITEM, style,
2657 draw_rect.y - clip_rect.y, draw_rect.x - clip_rect.x,
2658 draw_rect.height, draw_rect.width, state_type, 0))
2660 g_object_unref (pixmap);
2664 pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap, NULL, 0, 0, 0, 0,
2665 clip_rect.height, clip_rect.width);
2666 g_object_unref (pixmap);
2670 pixmap = gdk_pixmap_new (window, clip_rect.width, clip_rect.height, -1);
2672 if (!xp_theme_draw (pixmap, XP_THEME_ELEMENT_TAB_ITEM, style,
2673 draw_rect.x - clip_rect.x, draw_rect.y - clip_rect.y,
2674 draw_rect.width, draw_rect.height, state_type, 0))
2676 g_object_unref (pixmap);
2680 pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap, NULL, 0, 0, 0, 0,
2681 clip_rect.width, clip_rect.height);
2682 g_object_unref (pixmap);
2685 rotated = gdk_pixbuf_rotate_simple (pixbuf, rotation);
2686 g_object_unref (pixbuf);
2689 // XXX - This is really hacky and evil. When we're drawing the left-most tab
2690 // while it is active on a bottom-oriented notebook, there is one white
2691 // pixel at the top. There may be a better solution than this if someone
2692 // has time to discover it.
2693 if (gap_side == GTK_POS_BOTTOM && state_type == GTK_STATE_NORMAL
2694 && x == widget->allocation.x)
2696 int rowstride = gdk_pixbuf_get_rowstride (pixbuf);
2697 int n_channels = gdk_pixbuf_get_n_channels (pixbuf);
2700 guchar *pixels = gdk_pixbuf_get_pixels (pixbuf);
2701 guchar *p = pixels + rowstride;
2703 for (psub = 0; psub < n_channels; psub++)
2705 pixels[psub] = p[psub];
2709 gdk_draw_pixbuf (window, NULL, pixbuf, 0, 0, clip_rect.x, clip_rect.y,
2710 clip_rect.width, clip_rect.height, GDK_RGB_DITHER_NONE,
2712 g_object_unref (pixbuf);
2719 draw_tab_button (GtkStyle *style,
2721 GtkStateType state_type,
2722 GtkShadowType shadow_type,
2725 const gchar *detail,
2726 gint x, gint y, gint width, gint height, gint gap_side)
2728 if (gap_side == GTK_POS_TOP || gap_side == GTK_POS_BOTTOM)
2730 /* experimental tab-drawing code from mozilla */
2736 dc = get_window_dc (style, window, state_type, &dc_info, x, y, width, height, &rect);
2738 if (gap_side == GTK_POS_TOP)
2740 else if (gap_side == GTK_POS_BOTTOM)
2741 aPosition = BF_BOTTOM;
2742 else if (gap_side == GTK_POS_LEFT)
2743 aPosition = BF_LEFT;
2745 aPosition = BF_RIGHT;
2747 if (state_type == GTK_STATE_PRELIGHT)
2748 state_type = GTK_STATE_NORMAL;
2750 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
2752 DrawTab (dc, rect, aPosition,
2753 state_type != GTK_STATE_PRELIGHT,
2754 (gap_side != GTK_POS_LEFT), (gap_side != GTK_POS_RIGHT));
2757 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
2759 release_window_dc (&dc_info);
2767 draw_extension (GtkStyle *style,
2769 GtkStateType state_type,
2770 GtkShadowType shadow_type,
2773 const gchar *detail,
2775 gint width, gint height, GtkPositionType gap_side)
2777 if (widget && GTK_IS_NOTEBOOK (widget) && detail && !strcmp (detail, "tab"))
2779 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2781 /* Why this differs from gap_side, I have no idea.. */
2782 int real_gap_side = gtk_notebook_get_tab_pos (notebook);
2784 if (!draw_themed_tab_button (style, window, state_type,
2785 GTK_NOTEBOOK (widget), x, y,
2786 width, height, real_gap_side))
2788 if (!draw_tab_button (style, window, state_type,
2789 shadow_type, area, widget,
2790 detail, x, y, width, height, real_gap_side))
2792 parent_class->draw_extension (style, window, state_type,
2793 shadow_type, area, widget, detail,
2794 x, y, width, height,
2802 draw_box_gap (GtkStyle *style, GdkWindow *window, GtkStateType state_type,
2803 GtkShadowType shadow_type, GdkRectangle *area,
2804 GtkWidget *widget, const gchar *detail, gint x,
2805 gint y, gint width, gint height, GtkPositionType gap_side,
2806 gint gap_x, gint gap_width)
2808 if (GTK_IS_NOTEBOOK (widget) && detail && !strcmp (detail, "notebook"))
2810 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2811 int side = gtk_notebook_get_tab_pos (notebook);
2812 int x2 = x, y2 = y, w2 = width, h2 = height;
2814 if (side == GTK_POS_TOP)
2817 y2 = y - gtk_notebook_get_tab_vborder (notebook);
2819 h2 = height + gtk_notebook_get_tab_vborder (notebook) * 2;
2821 else if (side == GTK_POS_BOTTOM)
2826 h2 = height + gtk_notebook_get_tab_vborder (notebook) * 2;
2828 else if (side == GTK_POS_LEFT)
2830 x2 = x - gtk_notebook_get_tab_hborder (notebook);
2832 w2 = width + gtk_notebook_get_tab_hborder (notebook);
2835 else if (side == GTK_POS_RIGHT)
2839 w2 = width + gtk_notebook_get_tab_hborder (notebook) * 2;
2843 if (xp_theme_draw (window, XP_THEME_ELEMENT_TAB_PANE, style,
2844 x2, y2, w2, h2, state_type, area))
2850 parent_class->draw_box_gap (style, window, state_type, shadow_type,
2851 area, widget, detail, x, y, width, height,
2852 gap_side, gap_x, gap_width);
2856 is_popup_window_child (GtkWidget *widget)
2859 GtkWindowType type = -1;
2861 top = gtk_widget_get_toplevel (widget);
2863 if (top && GTK_IS_WINDOW (top))
2865 g_object_get (top, "type", &type, NULL);
2867 if (type == GTK_WINDOW_POPUP)
2868 { /* Hack for combo boxes */
2877 draw_flat_box (GtkStyle *style, GdkWindow *window,
2878 GtkStateType state_type, GtkShadowType shadow_type,
2879 GdkRectangle *area, GtkWidget *widget,
2880 const gchar *detail, gint x, gint y, gint width, gint height)
2884 if (state_type == GTK_STATE_SELECTED &&
2885 (!strncmp ("cell_even", detail, 9) || !strncmp ("cell_odd", detail, 8)))
2887 GdkGC *gc = gtk_widget_has_focus (widget) ? style->base_gc[state_type] : style->base_gc[GTK_STATE_ACTIVE];
2889 gdk_draw_rectangle (window, gc, TRUE, x, y, width, height);
2893 else if (!strcmp (detail, "checkbutton"))
2895 if (state_type == GTK_STATE_PRELIGHT)
2902 parent_class->draw_flat_box (style, window, state_type, shadow_type,
2903 area, widget, detail, x, y, width, height);
2907 draw_menu_border (GdkWindow *win, GtkStyle *style,
2908 gint x, gint y, gint width, gint height)
2914 dc = get_window_dc (style, win, GTK_STATE_NORMAL, &dc_info, x, y, width, height, &rect);
2919 if (xp_theme_is_active ())
2921 FrameRect (dc, &rect, GetSysColorBrush (COLOR_3DSHADOW));
2925 DrawEdge (dc, &rect, EDGE_RAISED, BF_RECT);
2928 release_window_dc (&dc_info);
2934 draw_shadow (GtkStyle *style,
2936 GtkStateType state_type,
2937 GtkShadowType shadow_type,
2940 const gchar *detail, gint x, gint y, gint width, gint height)
2942 gboolean is_handlebox;
2943 gboolean is_toolbar;
2945 if (detail && !strcmp (detail, "frame"))
2954 dc = get_window_dc (style, window, state_type, &dc_info, x, y, width, height, &rect);
2955 if (is_combo_box_child (widget))
2957 FillRect (dc, &rect, GetSysColorBrush (COLOR_WINDOW));
2959 else if (is_popup_window_child (widget))
2961 FrameRect (dc, &rect, GetSysColorBrush (COLOR_WINDOWFRAME));
2965 switch (shadow_type)
2968 draw_3d_border (dc, &rect, TRUE);
2971 case GTK_SHADOW_OUT:
2972 draw_3d_border (dc, &rect, FALSE);
2975 case GTK_SHADOW_ETCHED_IN:
2976 draw_3d_border (dc, &rect, TRUE);
2977 InflateRect (&rect, -1, -1);
2978 draw_3d_border (dc, &rect, FALSE);
2981 case GTK_SHADOW_ETCHED_OUT:
2982 draw_3d_border (dc, &rect, FALSE);
2983 InflateRect (&rect, -1, -1);
2984 draw_3d_border (dc, &rect, TRUE);
2987 case GTK_SHADOW_NONE:
2992 release_window_dc (&dc_info);
2996 if (detail && (!strcmp (detail, "entry") || !strcmp (detail, "combobox")))
2998 if (shadow_type != GTK_SHADOW_IN)
3001 if (!xp_theme_draw (window, XP_THEME_ELEMENT_EDIT_TEXT, style,
3002 x, y, width, height, state_type, area))
3008 dc = get_window_dc (style, window, state_type, &dc_info,
3009 x, y, width, height, &rect);
3011 DrawEdge (dc, &rect, EDGE_SUNKEN, BF_RECT);
3012 release_window_dc (&dc_info);
3018 if (detail && !strcmp (detail, "scrolled_window") &&
3019 xp_theme_draw (window, XP_THEME_ELEMENT_EDIT_TEXT, style,
3020 x, y, width, height, state_type, area))
3025 if (detail && !strcmp (detail, "spinbutton"))
3028 if (detail && !strcmp (detail, "menu"))
3030 if (draw_menu_border (window, style, x, y, width, height))
3036 if (detail && !strcmp (detail, "handlebox"))
3039 is_handlebox = (detail && !strcmp (detail, "handlebox_bin"));
3040 is_toolbar = (detail
3041 && (!strcmp (detail, "toolbar")
3042 || !strcmp (detail, "menubar")));
3044 if (is_toolbar || is_handlebox)
3046 if (shadow_type == GTK_SHADOW_NONE)
3056 HGDIOBJ old_pen = NULL;
3057 GtkPositionType pos;
3059 sanitize_size (window, &width, &height);
3063 pos = gtk_handle_box_get_handle_position (GTK_HANDLE_BOX (widget));
3065 If the handle box is at left side,
3066 we shouldn't draw its right border.
3067 The same holds true for top, right, and bottom.
3072 pos = GTK_POS_RIGHT;
3080 pos = GTK_POS_BOTTOM;
3083 case GTK_POS_BOTTOM:
3090 GtkWidget *parent = gtk_widget_get_parent (widget);
3092 /* Dirty hack for toolbars contained in handle boxes */
3093 if (GTK_IS_HANDLE_BOX (parent))
3095 pos = gtk_handle_box_get_handle_position (GTK_HANDLE_BOX (parent));
3101 Make pos != all legal enum vaules of GtkPositionType.
3102 So every border will be draw.
3104 pos = (GtkPositionType) - 1;
3108 dc = get_window_dc (style, window, state_type, &dc_info, x, y, width, height, &rect);
3110 if (pos != GTK_POS_LEFT)
3112 old_pen = SelectObject (dc, get_light_pen ());
3113 MoveToEx (dc, rect.left, rect.top, NULL);
3114 LineTo (dc, rect.left, rect.bottom);
3116 if (pos != GTK_POS_TOP)
3118 old_pen = SelectObject (dc, get_light_pen ());
3119 MoveToEx (dc, rect.left, rect.top, NULL);
3120 LineTo (dc, rect.right, rect.top);
3122 if (pos != GTK_POS_RIGHT)
3124 old_pen = SelectObject (dc, get_dark_pen ());
3125 MoveToEx (dc, rect.right - 1, rect.top, NULL);
3126 LineTo (dc, rect.right - 1, rect.bottom);
3128 if (pos != GTK_POS_BOTTOM)
3130 old_pen = SelectObject (dc, get_dark_pen ());
3131 MoveToEx (dc, rect.left, rect.bottom - 1, NULL);
3132 LineTo (dc, rect.right, rect.bottom - 1);
3135 SelectObject (dc, old_pen);
3136 release_window_dc (&dc_info);
3142 if (detail && !strcmp (detail, "statusbar"))
3147 parent_class->draw_shadow (style, window, state_type, shadow_type, area,
3148 widget, detail, x, y, width, height);
3152 draw_hline (GtkStyle *style,
3154 GtkStateType state_type,
3157 const gchar *detail, gint x1, gint x2, gint y)
3159 if (xp_theme_is_active () && detail && !strcmp (detail, "menuitem"))
3162 (window, XP_THEME_ELEMENT_MENU_SEPARATOR, style, x1, y, x2, 1,
3171 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
3174 gdk_draw_line (window, style->dark_gc[state_type], x1, y, x2, y);
3178 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
3184 if (style->ythickness == 2)
3188 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
3189 gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
3192 gdk_draw_line (window, style->dark_gc[state_type], x1, y, x2, y);
3194 gdk_draw_line (window, style->light_gc[state_type], x1, y, x2, y);
3198 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
3199 gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
3204 parent_class->draw_hline (style, window, state_type, area, widget,
3211 draw_vline (GtkStyle *style,
3213 GtkStateType state_type,
3216 const gchar *detail, gint y1, gint y2, gint x)
3218 if (style->xthickness == 2)
3222 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
3223 gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
3226 gdk_draw_line (window, style->dark_gc[state_type], x, y1, x, y2);
3228 gdk_draw_line (window, style->light_gc[state_type], x, y1, x, y2);
3232 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
3233 gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
3238 parent_class->draw_vline (style, window, state_type, area, widget,
3244 draw_slider (GtkStyle *style,
3246 GtkStateType state_type,
3247 GtkShadowType shadow_type,
3250 const gchar *detail,
3252 gint y, gint width, gint height, GtkOrientation orientation)
3254 if (GTK_IS_SCALE (widget) &&
3255 xp_theme_draw (window, ((orientation == GTK_ORIENTATION_VERTICAL) ?
3256 XP_THEME_ELEMENT_SCALE_SLIDER_V :
3257 XP_THEME_ELEMENT_SCALE_SLIDER_H), style, x, y, width,
3258 height, state_type, area))
3263 parent_class->draw_slider (style, window, state_type, shadow_type, area,
3264 widget, detail, x, y, width, height,
3269 draw_resize_grip (GtkStyle *style,
3271 GtkStateType state_type,
3274 const gchar *detail,
3275 GdkWindowEdge edge, gint x, gint y, gint width, gint height)
3277 if (detail && !strcmp (detail, "statusbar"))
3280 (window, XP_THEME_ELEMENT_STATUS_GRIPPER, style, x, y, width,
3281 height, state_type, area))
3289 HDC dc = get_window_dc (style, window, state_type, &dc_info, x, y, width, height, &rect);
3292 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
3294 DrawFrameControl (dc, &rect, DFC_SCROLL, DFCS_SCROLLSIZEGRIP);
3295 release_window_dc (&dc_info);
3298 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
3304 parent_class->draw_resize_grip (style, window, state_type, area,
3305 widget, detail, edge, x, y, width, height);
3309 draw_handle (GtkStyle *style,
3311 GtkStateType state_type,
3312 GtkShadowType shadow_type,
3315 const gchar *detail,
3317 gint y, gint width, gint height, GtkOrientation orientation)
3323 if (is_toolbar_child (widget))
3325 XpThemeElement hndl;
3327 sanitize_size (window, &width, &height);
3329 if (GTK_IS_HANDLE_BOX (widget))
3331 GtkPositionType pos;
3332 pos = gtk_handle_box_get_handle_position (GTK_HANDLE_BOX (widget));
3334 if (pos == GTK_POS_TOP || pos == GTK_POS_BOTTOM)
3336 orientation = GTK_ORIENTATION_HORIZONTAL;
3340 orientation = GTK_ORIENTATION_VERTICAL;
3344 if (orientation == GTK_ORIENTATION_VERTICAL)
3345 hndl = XP_THEME_ELEMENT_REBAR_GRIPPER_V;
3347 hndl = XP_THEME_ELEMENT_REBAR_GRIPPER_H;
3349 if (xp_theme_draw (window, hndl, style, x, y, width, height,
3355 dc = get_window_dc (style, window, state_type, &dc_info, x, y, width, height, &rect);
3357 if (orientation == GTK_ORIENTATION_VERTICAL)
3360 rect.right = rect.left + 3;
3367 rect.bottom = rect.top + 3;
3372 draw_3d_border (dc, &rect, FALSE);
3373 release_window_dc (&dc_info);
3377 if (!GTK_IS_PANED (widget))
3379 gint xthick, ythick;
3380 GdkGC *light_gc, *dark_gc, *shadow_gc;
3383 sanitize_size (window, &width, &height);
3385 gtk_paint_box (style, window, state_type, shadow_type, area,
3386 widget, detail, x, y, width, height);
3388 light_gc = style->light_gc[state_type];
3389 dark_gc = style->dark_gc[state_type];
3390 shadow_gc = style->mid_gc[state_type];
3392 xthick = style->xthickness;
3393 ythick = style->ythickness;
3395 dest.x = x + xthick;
3396 dest.y = y + ythick;
3397 dest.width = width - (xthick * 2);
3398 dest.height = height - (ythick * 2);
3400 if (dest.width < dest.height)
3405 gdk_gc_set_clip_rectangle (light_gc, &dest);
3406 gdk_gc_set_clip_rectangle (dark_gc, &dest);
3407 gdk_gc_set_clip_rectangle (shadow_gc, &dest);
3409 if (dest.width < dest.height)
3411 gdk_draw_line (window, light_gc, dest.x, dest.y, dest.x,
3413 gdk_draw_line (window, dark_gc, dest.x + (dest.width / 2),
3414 dest.y, dest.x + (dest.width / 2), dest.height);
3415 gdk_draw_line (window, shadow_gc, dest.x + dest.width,
3416 dest.y, dest.x + dest.width, dest.height);
3420 gdk_draw_line (window, light_gc, dest.x, dest.y,
3421 dest.x + dest.width, dest.y);
3422 gdk_draw_line (window, dark_gc, dest.x,
3423 dest.y + (dest.height / 2),
3424 dest.x + dest.width, dest.y + (dest.height / 2));
3425 gdk_draw_line (window, shadow_gc, dest.x,
3426 dest.y + dest.height, dest.x + dest.width,
3427 dest.y + dest.height);
3430 gdk_gc_set_clip_rectangle (shadow_gc, NULL);
3431 gdk_gc_set_clip_rectangle (light_gc, NULL);
3432 gdk_gc_set_clip_rectangle (dark_gc, NULL);
3437 draw_focus (GtkStyle *style,
3439 GtkStateType state_type,
3442 const gchar *detail, gint x, gint y, gint width, gint height)
3448 if (!gtk_widget_get_can_focus (widget))
3453 if (is_combo_box_child (widget)
3454 && (GTK_IS_ARROW (widget) || GTK_IS_BUTTON (widget)))
3458 if (GTK_IS_TREE_VIEW (widget->parent) /* list view bheader */)
3463 dc = get_window_dc (style, window, state_type, &dc_info, x, y, width, height, &rect);
3464 DrawFocusRect (dc, &rect);
3465 release_window_dc (&dc_info);
3467 parent_class->draw_focus (style, window, state_type,
3468 area, widget, detail, x, y, width, height);
3473 draw_layout (GtkStyle *style,
3475 GtkStateType state_type,
3479 const gchar *detail,
3480 gint old_x, gint old_y, PangoLayout *layout)
3482 GtkNotebook *notebook = NULL;
3486 /* In the XP theme, labels don't appear correctly centered inside
3487 * notebook tabs, so we give them a gentle nudge two pixels to the
3488 * right. A little hackish, but what are 'ya gonna do? -- Cody
3490 if (xp_theme_is_active () && detail && !strcmp (detail, "label"))
3492 if (widget->parent != NULL)
3494 if (GTK_IS_NOTEBOOK (widget->parent))
3497 notebook = GTK_NOTEBOOK (widget->parent);
3498 side = gtk_notebook_get_tab_pos (notebook);
3500 if (side == GTK_POS_TOP || side == GTK_POS_BOTTOM)
3508 parent_class->draw_layout (style, window, state_type,
3509 use_text, area, widget, detail, x, y, layout);
3513 msw_style_init_from_rc (GtkStyle *style, GtkRcStyle *rc_style)
3515 setup_system_font (style);
3516 setup_menu_settings (gtk_settings_get_default ());
3517 setup_system_styles (style);
3518 parent_class->init_from_rc (style, rc_style);
3522 load_bg_image (GdkColormap *colormap,
3523 GdkColor *bg_color, const gchar *filename)
3525 if (strcmp (filename, "<parent>") == 0)
3527 return (GdkPixmap *) GDK_PARENT_RELATIVE;
3531 return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL,
3532 bg_color, filename);
3537 msw_style_realize (GtkStyle *style)
3539 GdkGCValues gc_values;
3540 GdkGCValuesMask gc_values_mask;
3544 for (i = 0; i < 5; i++)
3546 style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2;
3547 style->mid[i].green =
3548 (style->light[i].green + style->dark[i].green) / 2;
3549 style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2;
3551 style->text_aa[i].red = (style->text[i].red + style->base[i].red) / 2;
3552 style->text_aa[i].green =
3553 (style->text[i].green + style->base[i].green) / 2;
3554 style->text_aa[i].blue =
3555 (style->text[i].blue + style->base[i].blue) / 2;
3558 style->black.red = 0x0000;
3559 style->black.green = 0x0000;
3560 style->black.blue = 0x0000;
3561 gdk_colormap_alloc_color (style->colormap, &style->black, FALSE, TRUE);
3563 style->white.red = 0xffff;
3564 style->white.green = 0xffff;
3565 style->white.blue = 0xffff;
3566 gdk_colormap_alloc_color (style->colormap, &style->white, FALSE, TRUE);
3568 gc_values_mask = GDK_GC_FOREGROUND | GDK_GC_BACKGROUND;
3570 gc_values.foreground = style->black;
3571 gc_values.background = style->white;
3573 gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3575 gc_values.foreground = style->white;
3576 gc_values.background = style->black;
3578 gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3580 gc_values_mask = GDK_GC_FOREGROUND;
3582 for (i = 0; i < 5; i++)
3584 if (style->rc_style && style->rc_style->bg_pixmap_name[i])
3586 style->bg_pixmap[i] = load_bg_image (style->colormap,
3592 if (!gdk_colormap_alloc_color (style->colormap, &style->fg[i], FALSE, TRUE))
3594 g_warning ("unable to allocate color: ( %d %d %d )", style->fg[i].red,
3595 style->fg[i].green, style->fg[i].blue);
3598 if (!gdk_colormap_alloc_color (style->colormap, &style->bg[i], FALSE, TRUE))
3600 g_warning ("unable to allocate color: ( %d %d %d )", style->bg[i].red,
3601 style->bg[i].green, style->bg[i].blue);
3604 if (!gdk_colormap_alloc_color (style->colormap, &style->light[i], FALSE, TRUE))
3606 g_warning ("unable to allocate color: ( %d %d %d )",
3607 style->light[i].red, style->light[i].green,
3608 style->light[i].blue);
3611 if (!gdk_colormap_alloc_color (style->colormap, &style->dark[i], FALSE, TRUE))
3613 g_warning ("unable to allocate color: ( %d %d %d )",
3614 style->dark[i].red, style->dark[i].green,
3615 style->dark[i].blue);
3618 if (!gdk_colormap_alloc_color (style->colormap, &style->mid[i], FALSE, TRUE))
3620 g_warning ("unable to allocate color: ( %d %d %d )",
3621 style->mid[i].red, style->mid[i].green,
3622 style->mid[i].blue);
3625 if (!gdk_colormap_alloc_color (style->colormap, &style->text[i], FALSE, TRUE))
3627 g_warning ("unable to allocate color: ( %d %d %d )",
3628 style->text[i].red, style->text[i].green,
3629 style->text[i].blue);
3632 if (!gdk_colormap_alloc_color (style->colormap, &style->base[i], FALSE, TRUE))
3634 g_warning ("unable to allocate color: ( %d %d %d )",
3635 style->base[i].red, style->base[i].green,
3636 style->base[i].blue);
3639 if (!gdk_colormap_alloc_color (style->colormap, &style->text_aa[i], FALSE, TRUE))
3641 g_warning ("unable to allocate color: ( %d %d %d )",
3642 style->text_aa[i].red, style->text_aa[i].green,
3643 style->text_aa[i].blue);
3646 gc_values.foreground = style->fg[i];
3647 style->fg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3649 gc_values.foreground = style->bg[i];
3650 style->bg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3652 gc_values.foreground = style->light[i];
3653 style->light_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3655 gc_values.foreground = style->dark[i];
3656 style->dark_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3658 gc_values.foreground = style->mid[i];
3659 style->mid_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3661 gc_values.foreground = style->text[i];
3662 style->text_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3664 gc_values.foreground = style->base[i];
3665 style->base_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3667 gc_values.foreground = style->text_aa[i];
3668 style->text_aa_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3673 msw_style_unrealize (GtkStyle *style)
3675 parent_class->unrealize (style);
3679 msw_style_class_init (MswStyleClass *klass)
3681 GtkStyleClass *style_class = GTK_STYLE_CLASS (klass);
3683 parent_class = g_type_class_peek_parent (klass);
3685 style_class->init_from_rc = msw_style_init_from_rc;
3686 style_class->draw_arrow = draw_arrow;
3687 style_class->draw_box = draw_box;
3688 style_class->draw_check = draw_check;
3689 style_class->draw_option = draw_option;
3690 style_class->draw_tab = draw_tab;
3691 style_class->draw_flat_box = draw_flat_box;
3692 style_class->draw_expander = draw_expander;
3693 style_class->draw_extension = draw_extension;
3694 style_class->draw_box_gap = draw_box_gap;
3695 style_class->draw_shadow = draw_shadow;
3696 style_class->draw_hline = draw_hline;
3697 style_class->draw_vline = draw_vline;
3698 style_class->draw_handle = draw_handle;
3699 style_class->draw_resize_grip = draw_resize_grip;
3700 style_class->draw_slider = draw_slider;
3701 style_class->draw_focus = draw_focus;
3702 style_class->draw_layout = draw_layout;
3704 style_class->realize = msw_style_realize;
3705 style_class->unrealize = msw_style_unrealize;
3708 GType msw_type_style = 0;
3711 msw_style_register_type (GTypeModule *module)
3713 const GTypeInfo object_info = {
3714 sizeof (MswStyleClass),
3715 (GBaseInitFunc) NULL,
3716 (GBaseFinalizeFunc) NULL,
3717 (GClassInitFunc) msw_style_class_init,
3718 NULL, /* class_finalize */
3719 NULL, /* class_data */
3721 0, /* n_preallocs */
3722 (GInstanceInitFunc) NULL,
3725 msw_type_style = g_type_module_register_type (module,
3727 "MswStyle", &object_info, 0);
3731 msw_style_init (void)
3734 msw_style_setup_system_settings ();
3735 setup_msw_rc_style ();
3739 DeleteObject (g_light_pen);
3745 DeleteObject (g_dark_pen);
3751 msw_style_finalize (void)
3755 DeleteObject (g_dither_brush);
3760 DeleteObject (g_light_pen);
3765 DeleteObject (g_dark_pen);