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"
50 static HDC get_window_dc (GtkStyle *style, GdkWindow *window,
51 GtkStateType state_type, gint x, gint y, gint width,
52 gint height, RECT *rect);
53 static void release_window_dc (GtkStyle *style, GdkWindow *window,
54 GtkStateType state_type);
57 /* Default values, not normally used
59 static const GtkRequisition default_option_indicator_size = { 9, 8 };
60 static const GtkBorder default_option_indicator_spacing = { 7, 5, 2, 2 };
62 static GtkStyleClass *parent_class;
63 static HBRUSH g_dither_brush = NULL;
65 static HPEN g_light_pen = NULL;
66 static HPEN g_dark_pen = NULL;
88 static const guint8 check_aa_bits[] = {
89 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
93 static const guint8 check_base_bits[] = {
94 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xfc, 0x07, 0xfc, 0x07, 0xfc, 0x07,
96 0x07, 0xfc, 0x07, 0xfc, 0x07, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00
98 static const guint8 check_black_bits[] = {
99 0x00, 0x00, 0xfe, 0x0f, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00,
101 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00
103 static const guint8 check_dark_bits[] = {
104 0xff, 0x1f, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
106 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00
108 static const guint8 check_light_bits[] = {
109 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10,
111 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0xfe, 0x1f
113 static const guint8 check_mid_bits[] = {
114 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08,
116 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0xfc, 0x0f, 0x00, 0x00
118 static const guint8 check_text_bits[] = {
119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x88, 0x03,
121 0x00, 0x70, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
123 static const char check_inconsistent_bits[] = {
124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
128 static const guint8 radio_base_bits[] = {
129 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0xf8, 0x03, 0xfc, 0x07, 0xfc, 0x07,
131 0x07, 0xfc, 0x07, 0xf8, 0x03, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00
133 static const guint8 radio_black_bits[] = {
134 0x00, 0x00, 0xf0, 0x01, 0x0c, 0x02, 0x04, 0x00, 0x02, 0x00, 0x02, 0x00,
136 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
138 static const guint8 radio_dark_bits[] = {
139 0xf0, 0x01, 0x0c, 0x06, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00,
141 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
143 static const guint8 radio_light_bits[] = {
144 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x10, 0x00, 0x10,
146 0x10, 0x00, 0x10, 0x00, 0x08, 0x00, 0x08, 0x0c, 0x06, 0xf0, 0x01
148 static const guint8 radio_mid_bits[] = {
149 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08,
151 0x08, 0x00, 0x08, 0x00, 0x04, 0x0c, 0x06, 0xf0, 0x01, 0x00, 0x00
153 static const guint8 radio_text_bits[] = {
154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xf0, 0x01,
156 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
164 { check_aa_bits, NULL },
165 { check_base_bits, NULL },
166 { check_black_bits, NULL },
167 { check_dark_bits, NULL },
168 { check_light_bits, NULL },
169 { check_mid_bits, NULL },
170 { check_text_bits, NULL },
171 { check_inconsistent_bits, NULL },
172 { radio_base_bits, NULL },
173 { radio_black_bits, NULL },
174 { radio_dark_bits, NULL },
175 { radio_light_bits, NULL },
176 { radio_mid_bits, NULL },
177 { radio_text_bits, NULL }
181 get_system_font (XpThemeClass klazz, XpThemeFont type, LOGFONT *out_lf)
184 /* TODO: this causes crashes later because the font name is in UCS2, and
185 the pango fns don't deal with that gracefully */
186 if (xp_theme_get_system_font (klazz, type, out_lf))
193 NONCLIENTMETRICS ncm;
195 ncm.cbSize = sizeof (NONCLIENTMETRICS);
197 if (SystemParametersInfo (SPI_GETNONCLIENTMETRICS,
198 sizeof (NONCLIENTMETRICS), &ncm, 0))
200 if (type == XP_THEME_FONT_CAPTION)
201 *out_lf = ncm.lfCaptionFont;
202 else if (type == XP_THEME_FONT_MENU)
203 *out_lf = ncm.lfMenuFont;
204 else if (type == XP_THEME_FONT_STATUS)
205 *out_lf = ncm.lfStatusFont;
207 *out_lf = ncm.lfMessageFont;
216 /***************************** BEGIN STOLEN FROM PANGO *****************************/
219 This code is stolen from Pango 1.4. It attempts to address the following problems:
221 http://bugzilla.gnome.org/show_bug.cgi?id=135098
222 http://sourceforge.net/tracker/index.php?func=detail&aid=895762&group_id=76416&atid=547655
224 As Owen suggested in bug 135098, once Pango 1.6 is released, we need to get rid of this code.
227 #define PING(printlist)
229 /* TrueType defines: */
231 #define MAKE_TT_TABLE_NAME(c1, c2, c3, c4) \
232 (((guint32)c4) << 24 | ((guint32)c3) << 16 | ((guint32)c2) << 8 | ((guint32)c1))
234 #define CMAP (MAKE_TT_TABLE_NAME('c','m','a','p'))
235 #define CMAP_HEADER_SIZE 4
237 #define NAME (MAKE_TT_TABLE_NAME('n','a','m','e'))
238 #define NAME_HEADER_SIZE 6
240 #define ENCODING_TABLE_SIZE 8
242 #define APPLE_UNICODE_PLATFORM_ID 0
243 #define MACINTOSH_PLATFORM_ID 1
244 #define ISO_PLATFORM_ID 2
245 #define MICROSOFT_PLATFORM_ID 3
247 #define SYMBOL_ENCODING_ID 0
248 #define UNICODE_ENCODING_ID 1
249 #define UCS4_ENCODING_ID 10
253 guint16 format_selector;
255 guint16 string_storage_offset;
264 guint16 string_length;
265 guint16 string_offset;
269 pango_win32_get_name_header (HDC hdc, struct name_header *header)
271 if (GetFontData (hdc, NAME, 0, header, sizeof (*header)) != sizeof (*header))
274 header->num_records = GUINT16_FROM_BE (header->num_records);
275 header->string_storage_offset = GUINT16_FROM_BE (header->string_storage_offset);
281 pango_win32_get_name_record (HDC hdc, gint i, struct name_record *record)
283 if (GetFontData (hdc, NAME, 6 + i * sizeof (*record),
284 record, sizeof (*record)) != sizeof (*record))
289 record->platform_id = GUINT16_FROM_BE (record->platform_id);
290 record->encoding_id = GUINT16_FROM_BE (record->encoding_id);
291 record->language_id = GUINT16_FROM_BE (record->language_id);
292 record->name_id = GUINT16_FROM_BE (record->name_id);
293 record->string_length = GUINT16_FROM_BE (record->string_length);
294 record->string_offset = GUINT16_FROM_BE (record->string_offset);
300 get_family_name (LOGFONT *lfp, HDC pango_win32_hdc)
305 struct name_header header;
306 struct name_record record;
308 gint unicode_ix = -1, mac_ix = -1, microsoft_ix = -1;
312 gchar *string = NULL;
317 /* If lfFaceName is ASCII, assume it is the common (English) name for the
318 font. Is this valid? Do some TrueType fonts have different names in
319 French, German, etc, and does the system return these if the locale is
320 set to use French, German, etc? */
321 l = strlen (lfp->lfFaceName);
322 for (i = 0; i < l; i++)
324 if (lfp->lfFaceName[i] < ' ' || lfp->lfFaceName[i] > '~')
331 return g_strdup (lfp->lfFaceName);
333 if ((hfont = CreateFontIndirect (lfp)) == NULL)
336 if ((oldhfont = (HFONT) SelectObject (pango_win32_hdc, hfont)) == NULL)
339 if (!pango_win32_get_name_header (pango_win32_hdc, &header))
342 PING (("%d name records", header.num_records));
344 for (i = 0; i < header.num_records; i++)
346 if (!pango_win32_get_name_record (pango_win32_hdc, i, &record))
349 if ((record.name_id != 1 && record.name_id != 16) || record.string_length <= 0)
352 PING (("platform:%d encoding:%d language:%04x name_id:%d",
353 record.platform_id, record.encoding_id, record.language_id,
356 if (record.platform_id == APPLE_UNICODE_PLATFORM_ID ||
357 record.platform_id == ISO_PLATFORM_ID)
361 else if (record.platform_id == MACINTOSH_PLATFORM_ID && record.encoding_id == 0 && /* Roman
363 record.language_id == 0) /* English */
367 else if (record.platform_id == MICROSOFT_PLATFORM_ID)
369 if ((microsoft_ix == -1 ||
370 PRIMARYLANGID (record.language_id) == LANG_ENGLISH) &&
371 (record.encoding_id == SYMBOL_ENCODING_ID ||
372 record.encoding_id == UNICODE_ENCODING_ID ||
373 record.encoding_id == UCS4_ENCODING_ID))
380 if (microsoft_ix >= 0)
381 name_ix = microsoft_ix;
382 else if (mac_ix >= 0)
384 else if (unicode_ix >= 0)
385 name_ix = unicode_ix;
389 if (!pango_win32_get_name_record (pango_win32_hdc, name_ix, &record))
392 string = g_malloc (record.string_length + 1);
393 if (GetFontData (pango_win32_hdc, NAME,
394 header.string_storage_offset + record.string_offset,
395 string, record.string_length) != record.string_length)
398 string[record.string_length] = '\0';
400 if (name_ix == microsoft_ix)
402 if (record.encoding_id == SYMBOL_ENCODING_ID ||
403 record.encoding_id == UNICODE_ENCODING_ID)
405 codeset = "UTF-16BE";
412 else if (name_ix == mac_ix)
414 codeset = "MacRoman";
416 else /* name_ix == unicode_ix */
422 name = g_convert (string, record.string_length, "UTF-8", codeset, NULL,
431 SelectObject (pango_win32_hdc, oldhfont);
432 DeleteObject (hfont);
438 SelectObject (pango_win32_hdc, oldhfont);
441 DeleteObject (hfont);
444 return g_locale_to_utf8 (lfp->lfFaceName, -1, NULL, NULL, NULL);
447 /***************************** END STOLEN FROM PANGO *****************************/
450 sys_font_to_pango_font (XpThemeClass klazz, XpThemeFont type, char *buf,
461 if (get_system_font (klazz, type, &lf))
467 weight = "Ultra-Light";
479 weight = "Semi-Bold";
483 weight = "Ultra-Bold";
500 hwnd = GetDesktopWindow ();
504 pt_size = -MulDiv (lf.lfHeight, 72,
505 GetDeviceCaps (hDC, LOGPIXELSY));
512 font = get_family_name (&lf, hDC);
515 ReleaseDC (hwnd, hDC);
517 if (!(font && *font))
520 g_snprintf (buf, bufsiz, "%s %s %s %d", font, style, weight, pt_size);
529 /* missing from ms's header files */
530 #ifndef SPI_GETMENUSHOWDELAY
531 #define SPI_GETMENUSHOWDELAY 106
534 /* I don't know the proper XP theme class for things like
535 HIGHLIGHTTEXT, so we'll just define it to be "BUTTON"
537 #define XP_THEME_CLASS_TEXT XP_THEME_CLASS_BUTTON
539 #define WIN95_VERSION 0x400
540 #define WIN2K_VERSION 0x500
541 #define WINXP_VERSION 0x501
542 #define WIN2K3_VERSION 0x502
543 #define VISTA_VERSION 0x600
546 get_windows_version ()
548 static gint32 version = 0;
549 static gboolean have_version = FALSE;
553 OSVERSIONINFOEX osvi;
556 ZeroMemory (&osvi, sizeof (OSVERSIONINFOEX));
557 osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
559 GetVersionEx((OSVERSIONINFO*) &osvi);
561 version = (osvi.dwMajorVersion & 0xff) << 8 | (osvi.dwMinorVersion & 0xff);
568 setup_menu_settings (GtkSettings *settings)
571 OSVERSIONINFOEX osvi;
572 GObjectClass *klazz = G_OBJECT_GET_CLASS (G_OBJECT (settings));
574 if (get_windows_version () > WIN95_VERSION)
576 if (SystemParametersInfo (SPI_GETMENUSHOWDELAY, 0, &menu_delay, 0))
580 if (g_object_class_find_property
581 (klazz, "gtk-menu-bar-popup-delay"))
583 g_object_set (settings,
584 "gtk-menu-bar-popup-delay", 0, NULL);
586 if (g_object_class_find_property
587 (klazz, "gtk-menu-popup-delay"))
589 g_object_set (settings,
590 "gtk-menu-popup-delay", menu_delay, NULL);
592 if (g_object_class_find_property
593 (klazz, "gtk-menu-popdown-delay"))
595 g_object_set (settings,
596 "gtk-menu-popdown-delay", menu_delay, NULL);
604 msw_style_setup_system_settings (void)
606 GtkSettings *settings;
607 int cursor_blink_time;
609 settings = gtk_settings_get_default ();
613 cursor_blink_time = GetCaretBlinkTime ();
614 g_object_set (settings, "gtk-cursor-blink", cursor_blink_time > 0, NULL);
616 if (cursor_blink_time > 0)
618 g_object_set (settings, "gtk-cursor-blink-time",
619 2 * cursor_blink_time, NULL);
622 g_object_set (settings, "gtk-double-click-distance",
623 GetSystemMetrics (SM_CXDOUBLECLK), NULL);
624 g_object_set (settings, "gtk-double-click-time", GetDoubleClickTime (),
626 g_object_set (settings, "gtk-dnd-drag-threshold",
627 GetSystemMetrics (SM_CXDRAG), NULL);
629 setup_menu_settings (settings);
632 http://developer.gnome.org/doc/API/2.0/gtk/GtkSettings.html
633 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/systemparametersinfo.asp
634 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/getsystemmetrics.asp */
638 setup_system_font (GtkStyle *style)
640 char buf[256], *font; /* It's okay, lfFaceName is smaller than 32
643 if ((font = sys_font_to_pango_font (XP_THEME_CLASS_TEXT,
644 XP_THEME_FONT_MESSAGE,
645 buf, sizeof (buf))) != NULL)
647 if (style->font_desc)
649 pango_font_description_free (style->font_desc);
652 style->font_desc = pango_font_description_from_string (font);
657 sys_color_to_gtk_color (XpThemeClass klazz, int id, GdkColor * pcolor)
661 if (!xp_theme_get_system_color (klazz, id, &color))
662 color = GetSysColor (id);
664 pcolor->pixel = color;
665 pcolor->red = (GetRValue (color) << 8) | GetRValue (color);
666 pcolor->green = (GetGValue (color) << 8) | GetGValue (color);
667 pcolor->blue = (GetBValue (color) << 8) | GetBValue (color);
671 get_system_metric (XpThemeClass klazz, int id)
675 if (!xp_theme_get_system_metric (klazz, id, &rval))
676 rval = GetSystemMetrics (id);
682 setup_msw_rc_style (void)
684 char buf[1024], font_buf[256], *font_ptr;
685 char menu_bar_prelight_str[128];
688 GdkColor menu_text_color;
689 GdkColor tooltip_back;
690 GdkColor tooltip_fore;
693 GdkColor progress_back;
695 GdkColor fg_prelight;
696 GdkColor bg_prelight;
697 GdkColor base_prelight;
698 GdkColor text_prelight;
701 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT,
702 get_windows_version () == VISTA_VERSION ? COLOR_MENUTEXT : COLOR_HIGHLIGHTTEXT,
704 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT, &bg_prelight);
705 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT,
707 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT,
710 sys_color_to_gtk_color (XP_THEME_CLASS_MENU, COLOR_MENUTEXT,
712 sys_color_to_gtk_color (XP_THEME_CLASS_MENU, COLOR_MENU, &menu_color);
715 sys_color_to_gtk_color (XP_THEME_CLASS_TOOLTIP, COLOR_INFOTEXT,
717 sys_color_to_gtk_color (XP_THEME_CLASS_TOOLTIP, COLOR_INFOBK,
720 /* text on push buttons. TODO: button shadows, backgrounds, and
722 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT, &btn_fore);
723 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE, &btn_face);
725 /* progress bar background color */
726 sys_color_to_gtk_color (XP_THEME_CLASS_PROGRESS, COLOR_HIGHLIGHT,
729 /* Enable coloring for menus. */
731 sys_font_to_pango_font (XP_THEME_CLASS_MENU, XP_THEME_FONT_MENU,
732 font_buf, sizeof (font_buf));
733 g_snprintf (buf, sizeof (buf),
734 "style \"msw-menu\" = \"msw-default\"\n" "{\n"
735 "GtkMenuItem::toggle-spacing = 8\n"
736 "fg[PRELIGHT] = { %d, %d, %d }\n"
737 "bg[PRELIGHT] = { %d, %d, %d }\n"
738 "text[PRELIGHT] = { %d, %d, %d }\n"
739 "base[PRELIGHT] = { %d, %d, %d }\n"
740 "fg[NORMAL] = { %d, %d, %d }\n"
741 "bg[NORMAL] = { %d, %d, %d }\n" "%s = \"%s\"\n"
742 "}widget_class \"*MenuItem*\" style \"msw-menu\"\n"
743 "widget_class \"*GtkMenu\" style \"msw-menu\"\n"
744 "widget_class \"*GtkMenuShell*\" style \"msw-menu\"\n",
745 fg_prelight.red, fg_prelight.green, fg_prelight.blue,
746 bg_prelight.red, bg_prelight.green, bg_prelight.blue,
747 text_prelight.red, text_prelight.green, text_prelight.blue,
748 base_prelight.red, base_prelight.green, base_prelight.blue,
749 menu_text_color.red, menu_text_color.green,
750 menu_text_color.blue, menu_color.red, menu_color.green,
751 menu_color.blue, (font_ptr ? "font_name" : "#"),
752 (font_ptr ? font_ptr : " font name should go here"));
753 gtk_rc_parse_string (buf);
755 if (xp_theme_is_active ())
757 *menu_bar_prelight_str = '\0';
761 g_snprintf (menu_bar_prelight_str, sizeof (menu_bar_prelight_str),
762 "fg[PRELIGHT] = { %d, %d, %d }\n",
763 menu_text_color.red, menu_text_color.green,
764 menu_text_color.blue);
767 /* Enable coloring for menu bars. */
768 g_snprintf (buf, sizeof (buf),
769 "style \"msw-menu-bar\" = \"msw-menu\"\n"
771 "bg[NORMAL] = { %d, %d, %d }\n"
772 "%s" "GtkMenuBar::shadow-type = %d\n"
774 FIXME: This should be enabled once gtk+ support
775 GtkMenuBar::prelight-item style property.
777 /* "GtkMenuBar::prelight-item = 1\n" */
778 "}widget_class \"*MenuBar*\" style \"msw-menu-bar\"\n",
779 btn_face.red, btn_face.green, btn_face.blue,
780 menu_bar_prelight_str, xp_theme_is_active ()? 0 : 2);
781 gtk_rc_parse_string (buf);
783 g_snprintf (buf, sizeof (buf),
784 "style \"msw-toolbar\" = \"msw-default\"\n"
786 "GtkHandleBox::shadow-type = %s\n"
787 "GtkToolbar::shadow-type = %s\n"
788 "}widget_class \"*HandleBox*\" style \"msw-toolbar\"\n",
789 "etched-in", "etched-in");
790 gtk_rc_parse_string (buf);
792 /* enable tooltip fonts */
793 font_ptr = sys_font_to_pango_font (XP_THEME_CLASS_STATUS, XP_THEME_FONT_STATUS,
794 font_buf, sizeof (font_buf));
795 g_snprintf (buf, sizeof (buf),
796 "style \"msw-tooltips-caption\" = \"msw-default\"\n"
797 "{fg[NORMAL] = { %d, %d, %d }\n" "%s = \"%s\"\n"
798 "}widget \"gtk-tooltips.GtkLabel\" style \"msw-tooltips-caption\"\n"
799 "widget \"gtk-tooltip.GtkLabel\" style \"msw-tooltips-caption\"\n",
800 tooltip_fore.red, tooltip_fore.green, tooltip_fore.blue,
801 (font_ptr ? "font_name" : "#"),
802 (font_ptr ? font_ptr : " font name should go here"));
803 gtk_rc_parse_string (buf);
805 g_snprintf (buf, sizeof (buf),
806 "style \"msw-tooltips\" = \"msw-default\"\n"
807 "{bg[NORMAL] = { %d, %d, %d }\n"
808 "}widget \"gtk-tooltips*\" style \"msw-tooltips\"\n"
809 "widget \"gtk-tooltip*\" style \"msw-tooltips\"\n",
810 tooltip_back.red, tooltip_back.green, tooltip_back.blue);
811 gtk_rc_parse_string (buf);
813 /* enable font theming for status bars */
814 font_ptr = sys_font_to_pango_font (XP_THEME_CLASS_STATUS, XP_THEME_FONT_STATUS,
815 font_buf, sizeof (font_buf));
816 g_snprintf (buf, sizeof (buf),
817 "style \"msw-status\" = \"msw-default\"\n" "{%s = \"%s\"\n"
818 "bg[NORMAL] = { %d, %d, %d }\n"
819 "}widget_class \"*Status*\" style \"msw-status\"\n",
820 (font_ptr ? "font_name" : "#"),
821 (font_ptr ? font_ptr : " font name should go here"),
822 btn_face.red, btn_face.green, btn_face.blue);
823 gtk_rc_parse_string (buf);
825 /* enable coloring for text on buttons TODO: use GetThemeMetric for the
826 border and outside border */
827 g_snprintf (buf, sizeof (buf),
828 "style \"msw-button\" = \"msw-default\"\n"
830 "bg[NORMAL] = { %d, %d, %d }\n"
831 "bg[PRELIGHT] = { %d, %d, %d }\n"
832 "bg[INSENSITIVE] = { %d, %d, %d }\n"
833 "fg[PRELIGHT] = { %d, %d, %d }\n"
834 "GtkButton::default-border = { 0, 0, 0, 0 }\n"
835 "GtkButton::default-outside-border = { 0, 0, 0, 0 }\n"
836 "GtkButton::child-displacement-x = 1\n"
837 "GtkButton::child-displacement-y = 1\n"
838 "GtkButton::focus-padding = %d\n"
839 "}widget_class \"*Button*\" style \"msw-button\"\n",
840 btn_face.red, btn_face.green, btn_face.blue,
841 btn_face.red, btn_face.green, btn_face.blue,
842 btn_face.red, btn_face.green, btn_face.blue,
843 btn_fore.red, btn_fore.green, btn_fore.blue,
844 xp_theme_is_active ()? 1 : 2);
845 gtk_rc_parse_string (buf);
847 /* enable coloring for progress bars */
848 g_snprintf (buf, sizeof (buf),
849 "style \"msw-progress\" = \"msw-default\"\n"
850 "{bg[PRELIGHT] = { %d, %d, %d }\n"
851 "bg[NORMAL] = { %d, %d, %d }\n"
852 "}widget_class \"*Progress*\" style \"msw-progress\"\n",
856 btn_face.red, btn_face.green, btn_face.blue);
857 gtk_rc_parse_string (buf);
859 /* scrollbar thumb width and height */
860 g_snprintf (buf, sizeof (buf),
861 "style \"msw-vscrollbar\" = \"msw-default\"\n"
862 "{GtkRange::slider-width = %d\n"
863 "GtkRange::stepper-size = %d\n"
864 "GtkRange::stepper-spacing = 0\n"
865 "GtkRange::trough_border = 0\n"
866 "GtkScale::slider-length = %d\n"
867 "GtkScrollbar::min-slider-length = 8\n"
868 "}widget_class \"*VScrollbar*\" style \"msw-vscrollbar\"\n"
869 "widget_class \"*VScale*\" style \"msw-vscrollbar\"\n",
870 GetSystemMetrics (SM_CYVTHUMB),
871 get_system_metric (XP_THEME_CLASS_SCROLLBAR, SM_CXVSCROLL), 11);
872 gtk_rc_parse_string (buf);
874 g_snprintf (buf, sizeof (buf),
875 "style \"msw-hscrollbar\" = \"msw-default\"\n"
876 "{GtkRange::slider-width = %d\n"
877 "GtkRange::stepper-size = %d\n"
878 "GtkRange::stepper-spacing = 0\n"
879 "GtkRange::trough_border = 0\n"
880 "GtkScale::slider-length = %d\n"
881 "GtkScrollbar::min-slider-length = 8\n"
882 "}widget_class \"*HScrollbar*\" style \"msw-hscrollbar\"\n"
883 "widget_class \"*HScale*\" style \"msw-hscrollbar\"\n",
884 GetSystemMetrics (SM_CXHTHUMB),
885 get_system_metric (XP_THEME_CLASS_SCROLLBAR, SM_CYHSCROLL), 11);
886 gtk_rc_parse_string (buf);
888 gtk_rc_parse_string ("style \"msw-scrolled-window\" = \"msw-default\"\n"
889 "{GtkScrolledWindow::scrollbars-within-bevel = 1}\n"
890 "class \"GtkScrolledWindow\" style \"msw-scrolled-window\"\n");
892 /* radio/check button sizes */
893 g_snprintf (buf, sizeof (buf),
894 "style \"msw-checkbutton\" = \"msw-button\"\n"
895 "{GtkCheckButton::indicator-size = 13\n"
896 "}widget_class \"*CheckButton*\" style \"msw-checkbutton\"\n"
897 "widget_class \"*RadioButton*\" style \"msw-checkbutton\"\n");
898 gtk_rc_parse_string (buf);
900 /* size of combo box toggle button */
901 g_snprintf (buf, sizeof (buf),
902 "style \"msw-combobox-button\" = \"msw-default\"\n"
906 "GtkButton::default-border = { 0, 0, 0, 0 }\n"
907 "GtkButton::default-outside-border = { 0, 0, 0, 0 }\n"
908 "GtkButton::child-displacement-x = 0\n"
909 "GtkButton::child-displacement-y = 0\n"
910 "GtkWidget::focus-padding = 0\n"
911 "GtkWidget::focus-line-width = 0\n"
913 "widget_class \"*ComboBox*ToggleButton*\" style \"msw-combobox-button\"\n");
914 gtk_rc_parse_string (buf);
916 g_snprintf (buf, sizeof (buf),
917 "style \"msw-combobox\" = \"msw-default\"\n"
919 "GtkComboBox::shadow-type = in\n"
923 "class \"GtkComboBox\" style \"msw-combobox\"\n",
924 xp_theme_is_active()? 1 : GetSystemMetrics (SM_CXEDGE),
925 xp_theme_is_active()? 1 : GetSystemMetrics (SM_CYEDGE));
926 gtk_rc_parse_string (buf);
928 /* size of tree view header */
929 g_snprintf (buf, sizeof (buf),
930 "style \"msw-header-button\" = \"msw-default\"\n"
934 "GtkWidget::draw-border = {0, 0, 0, 0}\n"
935 "GtkButton::default-border = { 0, 0, 0, 0 }\n"
936 "GtkButton::default-outside-border = { 0, 0, 0, 0 }\n"
937 "GtkButton::child-displacement-x = 0\n"
938 "GtkButton::child-displacement-y = 0\n"
939 "GtkWidget::focus-padding = 0\n"
940 "GtkWidget::focus-line-width = 0\n"
942 "widget_class \"*TreeView*Button*\" style \"msw-header-button\"\n");
943 gtk_rc_parse_string (buf);
945 /* FIXME: This should be enabled once gtk+ support GtkNotebok::prelight-tab */
946 /* enable prelight tab of GtkNotebook */
948 g_snprintf (buf, sizeof (buf),
949 "style \"msw-notebook\" = \"msw-default\"\n"
950 "{GtkNotebook::prelight-tab=1\n"
951 "}widget_class \"*Notebook*\" style \"msw-notebook\"\n");
952 gtk_rc_parse_string (buf);
955 /* FIXME: This should be enabled once gtk+ support GtkTreeView::full-row-focus */
957 g_snprintf (buf, sizeof (buf),
958 "style \"msw-treeview\" = \"msw-default\"\n"
959 "{GtkTreeView::full-row-focus=0\n"
960 "}widget_class \"*TreeView*\" style \"msw-treeview\"\n");
961 gtk_rc_parse_string (buf);
966 setup_system_styles (GtkStyle *style)
970 /* Default background */
971 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
972 &style->bg[GTK_STATE_NORMAL]);
973 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT,
974 &style->bg[GTK_STATE_SELECTED]);
975 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
976 &style->bg[GTK_STATE_INSENSITIVE]);
977 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
978 &style->bg[GTK_STATE_ACTIVE]);
979 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
980 &style->bg[GTK_STATE_PRELIGHT]);
983 sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOW,
984 &style->base[GTK_STATE_NORMAL]);
985 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT,
986 &style->base[GTK_STATE_SELECTED]);
987 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
988 &style->base[GTK_STATE_INSENSITIVE]);
989 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
990 &style->base[GTK_STATE_ACTIVE]);
991 sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOW,
992 &style->base[GTK_STATE_PRELIGHT]);
995 sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT,
996 &style->text[GTK_STATE_NORMAL]);
997 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT,
998 &style->text[GTK_STATE_SELECTED]);
999 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_GRAYTEXT,
1000 &style->text[GTK_STATE_INSENSITIVE]);
1001 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT,
1002 &style->text[GTK_STATE_ACTIVE]);
1003 sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT,
1004 &style->text[GTK_STATE_PRELIGHT]);
1006 /* Default foreground */
1007 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT,
1008 &style->fg[GTK_STATE_NORMAL]);
1009 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT,
1010 &style->fg[GTK_STATE_SELECTED]);
1011 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_GRAYTEXT,
1012 &style->fg[GTK_STATE_INSENSITIVE]);
1013 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT,
1014 &style->fg[GTK_STATE_ACTIVE]);
1015 sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT,
1016 &style->fg[GTK_STATE_PRELIGHT]);
1018 for (i = 0; i < 5; i++)
1020 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_3DSHADOW,
1022 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_3DHILIGHT,
1025 style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2;
1026 style->mid[i].green =
1027 (style->light[i].green + style->dark[i].green) / 2;
1028 style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2;
1030 style->text_aa[i].red = (style->text[i].red + style->base[i].red) / 2;
1031 style->text_aa[i].green =
1032 (style->text[i].green + style->base[i].green) / 2;
1033 style->text_aa[i].blue =
1034 (style->text[i].blue + style->base[i].blue) / 2;
1039 sanitize_size (GdkWindow *window, gint *width, gint *height)
1041 gboolean set_bg = FALSE;
1043 if ((*width == -1) && (*height == -1))
1045 set_bg = GDK_IS_WINDOW (window);
1046 gdk_drawable_get_size (window, width, height);
1048 else if (*width == -1)
1050 gdk_drawable_get_size (window, width, NULL);
1052 else if (*height == -1)
1054 gdk_drawable_get_size (window, NULL, height);
1060 static XpThemeElement
1061 map_gtk_progress_bar_to_xp (GtkProgressBar *progress_bar, gboolean trough)
1065 switch (progress_bar->orientation)
1067 case GTK_PROGRESS_LEFT_TO_RIGHT:
1068 case GTK_PROGRESS_RIGHT_TO_LEFT:
1070 ? XP_THEME_ELEMENT_PROGRESS_TROUGH_H
1071 : XP_THEME_ELEMENT_PROGRESS_BAR_H;
1076 ? XP_THEME_ELEMENT_PROGRESS_TROUGH_V
1077 : XP_THEME_ELEMENT_PROGRESS_BAR_V;
1085 is_combo_box_child (GtkWidget *w)
1092 for (tmp = w->parent; tmp; tmp = tmp->parent)
1094 if (GTK_IS_COMBO_BOX (tmp))
1101 /* This function is not needed anymore */
1103 combo_box_draw_arrow (GtkStyle *style,
1106 GdkRectangle *area, GtkWidget *widget)
1108 if (xp_theme_is_active ())
1111 if (widget && GTK_IS_TOGGLE_BUTTON (widget->parent))
1117 dc = get_window_dc (style, window, state, area->x, area->y, area->width,
1118 area->height, &rect);
1119 border = (GTK_TOGGLE_BUTTON (widget->parent)->
1120 active ? DFCS_PUSHED | DFCS_FLAT : 0);
1122 InflateRect (&rect, 1, 1);
1123 DrawFrameControl (dc, &rect, DFC_SCROLL, DFCS_SCROLLDOWN | border);
1125 release_window_dc (style, window, state);
1134 draw_part (GdkDrawable *drawable,
1135 GdkGC *gc, GdkRectangle *area, gint x, gint y, Part part)
1138 gdk_gc_set_clip_rectangle (gc, area);
1140 if (!parts[part].bmap)
1142 parts[part].bmap = gdk_bitmap_create_from_data (drawable,
1144 PART_SIZE, PART_SIZE);
1147 gdk_gc_set_ts_origin (gc, x, y);
1148 gdk_gc_set_stipple (gc, parts[part].bmap);
1149 gdk_gc_set_fill (gc, GDK_STIPPLED);
1151 gdk_draw_rectangle (drawable, gc, TRUE, x, y, PART_SIZE, PART_SIZE);
1153 gdk_gc_set_fill (gc, GDK_SOLID);
1156 gdk_gc_set_clip_rectangle (gc, NULL);
1160 draw_check (GtkStyle *style,
1163 GtkShadowType shadow,
1166 const gchar *detail, gint x, gint y, gint width, gint height)
1168 x -= (1 + PART_SIZE - width) / 2;
1169 y -= (1 + PART_SIZE - height) / 2;
1171 if (detail && strcmp (detail, "check") == 0) /* Menu item */
1173 if (shadow == GTK_SHADOW_IN)
1175 draw_part (window, style->black_gc, area, x, y, CHECK_TEXT);
1176 draw_part (window, style->dark_gc[state], area, x, y, CHECK_AA);
1181 XpThemeElement theme_elt = XP_THEME_ELEMENT_CHECKBOX;
1184 case GTK_SHADOW_ETCHED_IN:
1185 theme_elt = XP_THEME_ELEMENT_INCONSISTENT_CHECKBOX;
1189 theme_elt = XP_THEME_ELEMENT_PRESSED_CHECKBOX;
1196 if (!xp_theme_draw (window, theme_elt,
1197 style, x, y, width, height, state, area))
1199 if (detail && !strcmp (detail, "cellcheck"))
1200 state = GTK_STATE_NORMAL;
1202 draw_part (window, style->black_gc, area, x, y, CHECK_BLACK);
1203 draw_part (window, style->dark_gc[state], area, x, y, CHECK_DARK);
1204 draw_part (window, style->mid_gc[state], area, x, y, CHECK_MID);
1205 draw_part (window, style->light_gc[state], area, x, y, CHECK_LIGHT);
1206 draw_part (window, style->base_gc[state], area, x, y, CHECK_BASE);
1208 if (shadow == GTK_SHADOW_IN)
1210 draw_part (window, style->text_gc[state], area, x,
1212 draw_part (window, style->text_aa_gc[state], area,
1215 else if (shadow == GTK_SHADOW_ETCHED_IN)
1217 draw_part (window, style->text_gc[state], area, x, y,
1218 CHECK_INCONSISTENT);
1219 draw_part (window, style->text_aa_gc[state], area, x, y,
1227 draw_expander (GtkStyle *style,
1232 const gchar *detail,
1233 gint x, gint y, GtkExpanderStyle expander_style)
1236 gint expander_semi_size;
1237 XpThemeElement xp_expander;
1239 gtk_widget_style_get (widget, "expander_size", &expander_size, NULL);
1241 switch (expander_style)
1243 case GTK_EXPANDER_COLLAPSED:
1244 case GTK_EXPANDER_SEMI_COLLAPSED:
1245 xp_expander = XP_THEME_ELEMENT_TREEVIEW_EXPANDER_CLOSED;
1249 xp_expander = XP_THEME_ELEMENT_TREEVIEW_EXPANDER_OPENED;
1253 if ((expander_size % 2) == 0)
1256 if (expander_size > 2)
1260 gdk_gc_set_clip_rectangle (style->fg_gc[state], area);
1262 expander_semi_size = expander_size / 2;
1263 x -= expander_semi_size;
1264 y -= expander_semi_size;
1266 if (!xp_theme_draw (window, xp_expander, style,
1267 x, y, expander_size, expander_size, state, area))
1274 dc = get_window_dc (style, window, state, x, y, expander_size,
1275 expander_size, &rect);
1276 FrameRect (dc, &rect, GetSysColorBrush (COLOR_GRAYTEXT));
1277 InflateRect (&rect, -1, -1);
1278 FillRect (dc, &rect,
1279 GetSysColorBrush (state ==
1280 GTK_STATE_INSENSITIVE ? COLOR_BTNFACE :
1283 InflateRect (&rect, -1, -1);
1285 pen = CreatePen (PS_SOLID, 1, GetSysColor (COLOR_WINDOWTEXT));
1286 old_pen = SelectObject (dc, pen);
1288 MoveToEx (dc, rect.left, rect.top - 2 + expander_semi_size, NULL);
1289 LineTo (dc, rect.right, rect.top - 2 + expander_semi_size);
1291 if (expander_style == GTK_EXPANDER_COLLAPSED ||
1292 expander_style == GTK_EXPANDER_SEMI_COLLAPSED)
1294 MoveToEx (dc, rect.left - 2 + expander_semi_size, rect.top, NULL);
1295 LineTo (dc, rect.left - 2 + expander_semi_size, rect.bottom);
1298 SelectObject (dc, old_pen);
1300 release_window_dc (style, window, state);
1304 gdk_gc_set_clip_rectangle (style->fg_gc[state], NULL);
1308 draw_option (GtkStyle *style,
1311 GtkShadowType shadow,
1314 const gchar *detail, gint x, gint y, gint width, gint height)
1316 x -= (1 + PART_SIZE - width) / 2;
1317 y -= (1 + PART_SIZE - height) / 2;
1319 if (detail && strcmp (detail, "option") == 0) /* Menu item */
1321 if (shadow == GTK_SHADOW_IN)
1323 draw_part (window, style->fg_gc[state], area, x, y, RADIO_TEXT);
1328 if (xp_theme_draw (window, shadow == GTK_SHADOW_IN
1329 ? XP_THEME_ELEMENT_PRESSED_RADIO_BUTTON
1330 : XP_THEME_ELEMENT_RADIO_BUTTON,
1331 style, x, y, width, height, state, area))
1336 if (detail && !strcmp (detail, "cellradio"))
1337 state = GTK_STATE_NORMAL;
1339 draw_part (window, style->black_gc, area, x, y, RADIO_BLACK);
1340 draw_part (window, style->dark_gc[state], area, x, y, RADIO_DARK);
1341 draw_part (window, style->mid_gc[state], area, x, y, RADIO_MID);
1342 draw_part (window, style->light_gc[state], area, x, y, RADIO_LIGHT);
1343 draw_part (window, style->base_gc[state], area, x, y, RADIO_BASE);
1345 if (shadow == GTK_SHADOW_IN)
1346 draw_part (window, style->text_gc[state], area, x, y, RADIO_TEXT);
1352 draw_varrow (GdkWindow *window,
1354 GtkShadowType shadow_type,
1356 GtkArrowType arrow_type, gint x, gint y, gint width, gint height)
1359 gint y_start, y_increment;
1363 gdk_gc_set_clip_rectangle (gc, area);
1365 width = width + width % 2 - 1; /* Force odd */
1366 steps = 1 + width / 2;
1367 extra = height - steps;
1369 if (arrow_type == GTK_ARROW_DOWN)
1376 y_start = y + height - 1;
1380 for (i = extra; i < height; i++)
1382 gdk_draw_line (window, gc,
1383 x + (i - extra), y_start + i * y_increment,
1384 x + width - (i - extra) - 1, y_start + i * y_increment);
1388 gdk_gc_set_clip_rectangle (gc, NULL);
1392 draw_harrow (GdkWindow *window,
1394 GtkShadowType shadow_type,
1396 GtkArrowType arrow_type, gint x, gint y, gint width, gint height)
1399 gint x_start, x_increment;
1403 gdk_gc_set_clip_rectangle (gc, area);
1405 height = height + height % 2 - 1; /* Force odd */
1406 steps = 1 + height / 2;
1407 extra = width - steps;
1409 if (arrow_type == GTK_ARROW_RIGHT)
1416 x_start = x + width - 1;
1420 for (i = extra; i < width; i++)
1422 gdk_draw_line (window, gc,
1423 x_start + i * x_increment, y + (i - extra),
1424 x_start + i * x_increment, y + height - (i - extra) - 1);
1429 gdk_gc_set_clip_rectangle (gc, NULL);
1432 /* This function makes up for some brokeness in gtkrange.c
1433 * where we never get the full arrow of the stepper button
1434 * and the type of button in a single drawing function.
1436 * It doesn't work correctly when the scrollbar is squished
1437 * to the point we don't have room for full-sized steppers.
1440 reverse_engineer_stepper_box (GtkWidget *range,
1441 GtkArrowType arrow_type,
1442 gint *x, gint *y, gint *width, gint *height)
1444 gint slider_width = 14, stepper_size = 14;
1450 gtk_widget_style_get (range,
1451 "slider_width", &slider_width,
1452 "stepper_size", &stepper_size, NULL);
1455 if (arrow_type == GTK_ARROW_UP || arrow_type == GTK_ARROW_DOWN)
1457 box_width = slider_width;
1458 box_height = stepper_size;
1462 box_width = stepper_size;
1463 box_height = slider_width;
1466 *x = *x - (box_width - *width) / 2;
1467 *y = *y - (box_height - *height) / 2;
1469 *height = box_height;
1472 static XpThemeElement
1473 to_xp_arrow (GtkArrowType arrow_type)
1475 XpThemeElement xp_arrow;
1480 xp_arrow = XP_THEME_ELEMENT_ARROW_UP;
1483 case GTK_ARROW_DOWN:
1484 xp_arrow = XP_THEME_ELEMENT_ARROW_DOWN;
1487 case GTK_ARROW_LEFT:
1488 xp_arrow = XP_THEME_ELEMENT_ARROW_LEFT;
1492 xp_arrow = XP_THEME_ELEMENT_ARROW_RIGHT;
1500 draw_arrow (GtkStyle *style,
1503 GtkShadowType shadow,
1506 const gchar *detail,
1507 GtkArrowType arrow_type,
1508 gboolean fill, gint x, gint y, gint width, gint height)
1514 name = gtk_widget_get_name (widget);
1516 sanitize_size (window, &width, &height);
1518 if (GTK_IS_ARROW (widget) && is_combo_box_child (widget) && xp_theme_is_active ())
1521 if (detail && strcmp (detail, "spinbutton") == 0)
1523 if (xp_theme_is_drawable (XP_THEME_ELEMENT_SPIN_BUTTON_UP))
1530 if (arrow_type == GTK_ARROW_DOWN)
1534 if (state == GTK_STATE_ACTIVE)
1540 draw_varrow (window, style->fg_gc[state], shadow, area,
1541 arrow_type, x, y, width, height);
1545 else if (detail && (!strcmp (detail, "vscrollbar")
1546 || !strcmp (detail, "hscrollbar")))
1548 gboolean is_disabled = FALSE;
1550 GtkScrollbar *scrollbar = GTK_SCROLLBAR (widget);
1554 gint box_width = width;
1555 gint box_height = height;
1557 reverse_engineer_stepper_box (widget, arrow_type,
1558 &box_x, &box_y, &box_width, &box_height);
1560 if (scrollbar->range.adjustment->page_size >=
1561 (scrollbar->range.adjustment->upper -
1562 scrollbar->range.adjustment->lower))
1567 if (xp_theme_draw (window, to_xp_arrow (arrow_type), style, box_x, box_y,
1568 box_width, box_height, state, area))
1576 btn_type = DFCS_SCROLLUP;
1579 case GTK_ARROW_DOWN:
1580 btn_type = DFCS_SCROLLDOWN;
1583 case GTK_ARROW_LEFT:
1584 btn_type = DFCS_SCROLLLEFT;
1587 case GTK_ARROW_RIGHT:
1588 btn_type = DFCS_SCROLLRIGHT;
1591 case GTK_ARROW_NONE:
1595 if (state == GTK_STATE_INSENSITIVE)
1597 btn_type |= DFCS_INACTIVE;
1602 sanitize_size (window, &width, &height);
1604 dc = get_window_dc (style, window, state,
1605 box_x, box_y, box_width, box_height, &rect);
1606 DrawFrameControl (dc, &rect, DFC_SCROLL,
1607 btn_type | (shadow ==
1608 GTK_SHADOW_IN ? (DFCS_PUSHED |
1610 release_window_dc (style, window, state);
1616 /* draw the toolbar chevrons - waiting for GTK 2.4 */
1617 if (name && !strcmp (name, "gtk-toolbar-arrow"))
1620 (window, XP_THEME_ELEMENT_REBAR_CHEVRON, style, x, y,
1621 width, height, state, area))
1626 /* probably a gtk combo box on a toolbar */
1627 else if (0 /* widget->parent && GTK_IS_BUTTON
1628 (widget->parent) */ )
1631 (window, XP_THEME_ELEMENT_COMBOBUTTON, style, x - 3,
1632 widget->allocation.y + 1, width + 5,
1633 widget->allocation.height - 4, state, area))
1639 if (arrow_type == GTK_ARROW_UP || arrow_type == GTK_ARROW_DOWN)
1641 x += (width - 7) / 2;
1642 y += (height - 5) / 2;
1644 draw_varrow (window, style->fg_gc[state], shadow, area,
1645 arrow_type, x, y, 7, 5);
1649 x += (width - 5) / 2;
1650 y += (height - 7) / 2;
1652 draw_harrow (window, style->fg_gc[state], shadow, area,
1653 arrow_type, x, y, 5, 7);
1659 option_menu_get_props (GtkWidget *widget,
1660 GtkRequisition *indicator_size,
1661 GtkBorder *indicator_spacing)
1663 GtkRequisition *tmp_size = NULL;
1664 GtkBorder *tmp_spacing = NULL;
1667 gtk_widget_style_get (widget,
1668 "indicator_size", &tmp_size,
1669 "indicator_spacing", &tmp_spacing, NULL);
1673 *indicator_size = *tmp_size;
1674 gtk_requisition_free (tmp_size);
1678 *indicator_size = default_option_indicator_size;
1683 *indicator_spacing = *tmp_spacing;
1684 gtk_border_free (tmp_spacing);
1688 *indicator_spacing = default_option_indicator_spacing;
1693 is_toolbar_child (GtkWidget *wid)
1697 if (GTK_IS_TOOLBAR (wid) || GTK_IS_HANDLE_BOX (wid))
1707 is_menu_tool_button_child (GtkWidget *wid)
1711 if (GTK_IS_MENU_TOOL_BUTTON (wid))
1720 get_window_dc (GtkStyle *style, GdkWindow *window, GtkStateType state_type,
1721 gint x, gint y, gint width, gint height, RECT *rect)
1724 GdkDrawable *drawable;
1726 if (!GDK_IS_WINDOW (window))
1734 gdk_window_get_internal_paint_info (window, &drawable, &xoff, &yoff);
1737 rect->left = x - xoff;
1738 rect->top = y - yoff;
1739 rect->right = rect->left + width;
1740 rect->bottom = rect->top + height;
1742 return gdk_win32_hdc_get (drawable, style->dark_gc[state_type], 0);
1746 release_window_dc (GtkStyle *style, GdkWindow *window,
1747 GtkStateType state_type)
1749 GdkDrawable *drawable;
1751 if (!GDK_IS_WINDOW (window))
1757 gdk_window_get_internal_paint_info (window, &drawable, NULL, NULL);
1760 gdk_win32_hdc_release (drawable, style->dark_gc[state_type], 0);
1768 g_light_pen = CreatePen (PS_SOLID | PS_INSIDEFRAME, 1,
1769 GetSysColor (COLOR_BTNHIGHLIGHT));
1780 g_dark_pen = CreatePen (PS_SOLID | PS_INSIDEFRAME, 1,
1781 GetSysColor (COLOR_BTNSHADOW));
1788 draw_3d_border (HDC hdc, RECT *rc, gboolean sunken)
1795 pen1 = get_dark_pen ();
1796 pen2 = get_light_pen ();
1800 pen1 = get_light_pen ();
1801 pen2 = get_dark_pen ();
1804 MoveToEx (hdc, rc->left, rc->bottom - 1, NULL);
1806 old_pen = SelectObject (hdc, pen1);
1807 LineTo (hdc, rc->left, rc->top);
1808 LineTo (hdc, rc->right - 1, rc->top);
1809 SelectObject (hdc, old_pen);
1811 old_pen = SelectObject (hdc, pen2);
1812 LineTo (hdc, rc->right - 1, rc->bottom - 1);
1813 LineTo (hdc, rc->left, rc->bottom - 1);
1814 SelectObject (hdc, old_pen);
1818 draw_menu_item (GdkWindow *window, GtkWidget *widget, GtkStyle *style,
1819 gint x, gint y, gint width, gint height,
1820 GtkStateType state_type, GdkRectangle *area)
1827 if (xp_theme_is_active ())
1829 return (xp_theme_draw (window, XP_THEME_ELEMENT_MENU_ITEM, style,
1830 x, y, width, height, state_type, area));
1833 if ((parent = gtk_widget_get_parent (widget))
1834 && GTK_IS_MENU_BAR (parent) && !xp_theme_is_active ())
1836 bar = GTK_MENU_SHELL (parent);
1838 dc = get_window_dc (style, window, state_type, x, y, width, height, &rect);
1840 if (state_type == GTK_STATE_PRELIGHT)
1842 draw_3d_border (dc, &rect, bar->active);
1845 release_window_dc (style, window, state_type);
1854 get_dither_brush (void)
1857 HBITMAP pattern_bmp;
1861 return g_dither_brush;
1863 for (i = 0; i < 8; i++)
1865 pattern[i] = (WORD) (0x5555 << (i & 1));
1868 pattern_bmp = CreateBitmap (8, 8, 1, 1, &pattern);
1872 g_dither_brush = CreatePatternBrush (pattern_bmp);
1873 DeleteObject (pattern_bmp);
1876 return g_dither_brush;
1880 draw_tool_button (GdkWindow *window, GtkWidget *widget, GtkStyle *style,
1881 gint x, gint y, gint width, gint height,
1882 GtkStateType state_type, GdkRectangle *area)
1886 gboolean is_toggled = FALSE;
1888 if (xp_theme_is_active ())
1890 return (xp_theme_draw (window, XP_THEME_ELEMENT_TOOLBAR_BUTTON, style,
1891 x, y, width, height, state_type, area));
1894 if (GTK_IS_TOGGLE_BUTTON (widget))
1896 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
1902 if (state_type != GTK_STATE_PRELIGHT
1903 && state_type != GTK_STATE_ACTIVE && !is_toggled)
1908 dc = get_window_dc (style, window, state_type, x, y, width, height, &rect);
1909 if (state_type == GTK_STATE_PRELIGHT)
1913 FillRect (dc, &rect, GetSysColorBrush (COLOR_BTNFACE));
1916 draw_3d_border (dc, &rect, is_toggled);
1918 else if (state_type == GTK_STATE_ACTIVE)
1920 if (is_toggled && !is_menu_tool_button_child (widget->parent))
1922 SetTextColor (dc, GetSysColor (COLOR_3DHILIGHT));
1923 SetBkColor (dc, GetSysColor (COLOR_BTNFACE));
1924 FillRect (dc, &rect, get_dither_brush ());
1927 draw_3d_border (dc, &rect, TRUE);
1930 release_window_dc (style, window, state_type);
1936 draw_push_button (GdkWindow *window, GtkWidget *widget, GtkStyle *style,
1937 gint x, gint y, gint width, gint height,
1938 GtkStateType state_type, gboolean is_default)
1943 dc = get_window_dc (style, window, state_type, x, y, width, height, &rect);
1945 if (GTK_IS_TOGGLE_BUTTON (widget))
1947 if (state_type == GTK_STATE_PRELIGHT &&
1948 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
1950 state_type = GTK_STATE_ACTIVE;
1954 if (state_type == GTK_STATE_ACTIVE)
1956 if (GTK_IS_TOGGLE_BUTTON (widget))
1958 DrawEdge (dc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1959 SetTextColor (dc, GetSysColor (COLOR_3DHILIGHT));
1960 SetBkColor (dc, GetSysColor (COLOR_BTNFACE));
1961 FillRect (dc, &rect, get_dither_brush ());
1965 FrameRect (dc, &rect, GetSysColorBrush (COLOR_WINDOWFRAME));
1966 InflateRect (&rect, -1, -1);
1967 FrameRect (dc, &rect, GetSysColorBrush (COLOR_BTNSHADOW));
1968 InflateRect (&rect, -1, -1);
1969 FillRect (dc, &rect, GetSysColorBrush (COLOR_BTNFACE));
1974 if (is_default || GTK_WIDGET_HAS_FOCUS (widget))
1976 FrameRect (dc, &rect, GetSysColorBrush (COLOR_WINDOWFRAME));
1977 InflateRect (&rect, -1, -1);
1980 DrawFrameControl (dc, &rect, DFC_BUTTON, DFCS_BUTTONPUSH);
1983 release_window_dc (style, window, state_type);
1987 draw_box (GtkStyle *style,
1989 GtkStateType state_type,
1990 GtkShadowType shadow_type,
1993 const gchar *detail, gint x, gint y, gint width, gint height)
1995 if (is_combo_box_child (widget) && detail && !strcmp (detail, "button"))
2002 border = (GTK_TOGGLE_BUTTON (widget)->active ? DFCS_PUSHED | DFCS_FLAT : 0);
2004 dc = get_window_dc (style, window, state_type, x, y, width, height, &rect);
2005 DrawFrameControl (dc, &rect, DFC_SCROLL, DFCS_SCROLLDOWN | border);
2006 release_window_dc (style, window, state_type);
2008 if (xp_theme_is_active ()
2009 && xp_theme_draw (window, XP_THEME_ELEMENT_COMBOBUTTON, style, x, y,
2010 width, height, state_type, area))
2012 cx = GetSystemMetrics(SM_CXVSCROLL);
2017 dc = get_window_dc (style, window, state_type, x, y, width - cx, height, &rect);
2018 FillRect (dc, &rect, GetSysColorBrush (COLOR_WINDOW));
2019 release_window_dc (style, window, state_type);
2025 (!strcmp (detail, "button") || !strcmp (detail, "buttondefault")))
2027 if (GTK_IS_TREE_VIEW (widget->parent) || GTK_IS_CLIST (widget->parent))
2030 (window, XP_THEME_ELEMENT_LIST_HEADER, style, x, y,
2031 width, height, state_type, area))
2039 dc = get_window_dc (style, window, state_type, x, y, width, height, &rect);
2041 DrawFrameControl (dc, &rect, DFC_BUTTON, DFCS_BUTTONPUSH |
2043 GTK_STATE_ACTIVE ? (DFCS_PUSHED | DFCS_FLAT)
2045 release_window_dc (style, window, state_type);
2048 else if (is_toolbar_child (widget->parent)
2049 || (!GTK_IS_BUTTON (widget) ||
2050 (GTK_RELIEF_NONE == gtk_button_get_relief (GTK_BUTTON (widget)))))
2052 if (draw_tool_button (window, widget, style, x, y,
2053 width, height, state_type, area))
2060 gboolean is_default = GTK_WIDGET_HAS_DEFAULT (widget);
2063 is_default ? XP_THEME_ELEMENT_DEFAULT_BUTTON :
2064 XP_THEME_ELEMENT_BUTTON, style, x, y, width, height,
2070 draw_push_button (window, widget, style,
2071 x, y, width, height, state_type, is_default);
2078 else if (detail && !strcmp (detail, "spinbutton"))
2080 if (xp_theme_is_drawable (XP_THEME_ELEMENT_SPIN_BUTTON_UP))
2085 else if (detail && (!strcmp (detail, "spinbutton_up")
2086 || !strcmp (detail, "spinbutton_down")))
2088 if (!xp_theme_draw (window,
2089 (!strcmp (detail, "spinbutton_up"))
2090 ? XP_THEME_ELEMENT_SPIN_BUTTON_UP
2091 : XP_THEME_ELEMENT_SPIN_BUTTON_DOWN,
2092 style, x, y, width, height, state_type, area))
2097 dc = get_window_dc (style, window, state_type,
2098 x, y, width, height, &rect);
2099 DrawEdge (dc, &rect,
2101 GTK_STATE_ACTIVE ? EDGE_SUNKEN : EDGE_RAISED, BF_RECT);
2102 release_window_dc (style, window, state_type);
2106 else if (detail && !strcmp (detail, "slider"))
2108 if (GTK_IS_SCROLLBAR (widget))
2110 GtkScrollbar *scrollbar = GTK_SCROLLBAR (widget);
2111 gboolean is_v = GTK_IS_VSCROLLBAR (widget);
2113 if (xp_theme_draw (window,
2115 ? XP_THEME_ELEMENT_SCROLLBAR_V
2116 : XP_THEME_ELEMENT_SCROLLBAR_H,
2117 style, x, y, width, height, state_type, area))
2119 XpThemeElement gripper =
2120 (is_v ? XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V :
2121 XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H);
2123 /* Do not display grippers on tiny scroll bars,
2124 the limit imposed is rather arbitrary, perhaps
2125 we can fetch the gripper geometry from
2126 somewhere and use that... */
2128 XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H
2131 XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V && height < 16))
2136 xp_theme_draw (window, gripper, style, x, y,
2137 width, height, state_type, area);
2142 if (scrollbar->range.adjustment->page_size >=
2143 (scrollbar->range.adjustment->upper -
2144 scrollbar->range.adjustment->lower))
2151 else if (detail && !strcmp (detail, "bar"))
2153 if (widget && GTK_IS_PROGRESS_BAR (widget))
2155 GtkProgressBar *progress_bar = GTK_PROGRESS_BAR (widget);
2156 XpThemeElement xp_progress_bar =
2157 map_gtk_progress_bar_to_xp (progress_bar, FALSE);
2159 if (xp_theme_draw (window, xp_progress_bar, style, x, y,
2160 width, height, state_type, area))
2165 shadow_type = GTK_SHADOW_NONE;
2168 else if (detail && strcmp (detail, "menuitem") == 0)
2170 shadow_type = GTK_SHADOW_NONE;
2171 if (draw_menu_item (window, widget, style,
2172 x, y, width, height, state_type, area))
2177 else if (detail && !strcmp (detail, "trough"))
2179 if (widget && GTK_IS_PROGRESS_BAR (widget))
2181 GtkProgressBar *progress_bar = GTK_PROGRESS_BAR (widget);
2182 XpThemeElement xp_progress_bar =
2183 map_gtk_progress_bar_to_xp (progress_bar, TRUE);
2185 (window, xp_progress_bar, style, x, y, width, height,
2192 /* Blank in classic Windows */
2195 else if (widget && GTK_IS_SCROLLBAR (widget))
2197 gboolean is_vertical = GTK_IS_VSCROLLBAR (widget);
2199 if (xp_theme_draw (window,
2201 ? XP_THEME_ELEMENT_TROUGH_V
2202 : XP_THEME_ELEMENT_TROUGH_H,
2203 style, x, y, width, height, state_type, area))
2212 sanitize_size (window, &width, &height);
2213 dc = get_window_dc (style, window, state_type, x, y, width, height, &rect);
2215 SetTextColor (dc, GetSysColor (COLOR_3DHILIGHT));
2216 SetBkColor (dc, GetSysColor (COLOR_BTNFACE));
2217 FillRect (dc, &rect, get_dither_brush ());
2219 release_window_dc (style, window, state_type);
2224 else if (widget && GTK_IS_SCALE (widget))
2226 gboolean is_vertical = GTK_IS_VSCALE (widget);
2228 if (!xp_theme_is_active ())
2230 parent_class->draw_box (style, window, state_type,
2231 GTK_SHADOW_NONE, area,
2232 widget, detail, x, y, width, height);
2238 (window, XP_THEME_ELEMENT_SCALE_TROUGH_V,
2239 style, (2 * x + width) / 2, y, 2, height,
2245 parent_class->draw_box (style, window, state_type,
2246 GTK_SHADOW_ETCHED_IN,
2248 (2 * x + width) / 2, y, 1, height);
2253 (window, XP_THEME_ELEMENT_SCALE_TROUGH_H,
2254 style, x, (2 * y + height) / 2, width, 2,
2260 parent_class->draw_box (style, window, state_type,
2261 GTK_SHADOW_ETCHED_IN,
2262 area, NULL, NULL, x,
2263 (2 * y + height) / 2, width, 1);
2269 else if (detail && strcmp (detail, "optionmenu") == 0)
2271 if (xp_theme_draw (window, XP_THEME_ELEMENT_EDIT_TEXT,
2272 style, x, y, width, height, state_type, area))
2278 && (strcmp (detail, "vscrollbar") == 0
2279 || strcmp (detail, "hscrollbar") == 0))
2284 && (strcmp (detail, "handlebox_bin") == 0
2285 || strcmp (detail, "toolbar") == 0
2286 || strcmp (detail, "menubar") == 0))
2288 sanitize_size (window, &width, &height);
2289 if (xp_theme_draw (window, XP_THEME_ELEMENT_REBAR,
2290 style, x, y, width, height, state_type, area))
2295 else if (detail && (!strcmp (detail, "handlebox"))) /* grip */
2297 if (!xp_theme_is_active ())
2302 else if (detail && !strcmp (detail, "notebook") && GTK_IS_NOTEBOOK (widget))
2304 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2306 if (xp_theme_draw (window, XP_THEME_ELEMENT_TAB_PANE, style,
2307 x, y, width, height, state_type, area))
2315 const gchar *name = gtk_widget_get_name (widget);
2317 if (name && !strcmp (name, "gtk-tooltips"))
2320 (window, XP_THEME_ELEMENT_TOOLTIP, style, x, y, width,
2321 height, state_type, area))
2331 hdc = get_window_dc (style, window, state_type, x, y, width, height, &rect);
2333 brush = GetSysColorBrush (COLOR_3DDKSHADOW);
2337 FrameRect (hdc, &rect, brush);
2340 InflateRect (&rect, -1, -1);
2341 FillRect (hdc, &rect, (HBRUSH) (COLOR_INFOBK + 1));
2343 release_window_dc (style, window, state_type);
2350 parent_class->draw_box (style, window, state_type, shadow_type, area,
2351 widget, detail, x, y, width, height);
2353 if (detail && strcmp (detail, "optionmenu") == 0)
2355 GtkRequisition indicator_size;
2356 GtkBorder indicator_spacing;
2359 option_menu_get_props (widget, &indicator_size, &indicator_spacing);
2361 sanitize_size (window, &width, &height);
2363 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
2366 x + indicator_size.width + indicator_spacing.left +
2367 indicator_spacing.right;
2371 vline_x = x + width - (indicator_size.width +
2372 indicator_spacing.left +
2373 indicator_spacing.right) - style->xthickness;
2375 parent_class->draw_vline (style, window, state_type, area, widget,
2377 y + style->ythickness + 1,
2378 y + height - style->ythickness - 3, vline_x);
2384 draw_tab (GtkStyle *style,
2387 GtkShadowType shadow,
2390 const gchar *detail, gint x, gint y, gint width, gint height)
2392 GtkRequisition indicator_size;
2393 GtkBorder indicator_spacing;
2397 g_return_if_fail (style != NULL);
2398 g_return_if_fail (window != NULL);
2400 if (detail && !strcmp (detail, "optionmenutab"))
2402 if (xp_theme_draw (window, XP_THEME_ELEMENT_COMBOBUTTON,
2403 style, x - 5, widget->allocation.y + 1,
2404 width + 10, widget->allocation.height - 2,
2411 option_menu_get_props (widget, &indicator_size, &indicator_spacing);
2413 x += (width - indicator_size.width) / 2;
2414 arrow_height = (indicator_size.width + 1) / 2;
2416 y += (height - arrow_height) / 2;
2418 draw_varrow (window, style->black_gc, shadow, area, GTK_ARROW_DOWN,
2419 x, y, indicator_size.width, arrow_height);
2422 /* Draw classic Windows tab - thanks Mozilla!
2423 (no system API for this, but DrawEdge can draw all the parts of a tab) */
2425 DrawTab (HDC hdc, const RECT R, gint32 aPosition, gboolean aSelected,
2426 gboolean aDrawLeft, gboolean aDrawRight)
2428 gint32 leftFlag, topFlag, rightFlag, lightFlag, shadeFlag;
2429 RECT topRect, sideRect, bottomRect, lightRect, shadeRect;
2430 gint32 selectedOffset, lOffset, rOffset;
2432 selectedOffset = aSelected ? 1 : 0;
2433 lOffset = aDrawLeft ? 2 : 0;
2434 rOffset = aDrawRight ? 2 : 0;
2436 /* Get info for tab orientation/position (Left, Top, Right, Bottom) */
2442 rightFlag = BF_BOTTOM;
2443 lightFlag = BF_DIAGONAL_ENDTOPRIGHT;
2444 shadeFlag = BF_DIAGONAL_ENDBOTTOMRIGHT;
2446 SetRect (&topRect, R.left, R.top + lOffset, R.right,
2447 R.bottom - rOffset);
2448 SetRect (&sideRect, R.left + 2, R.top, R.right - 2 + selectedOffset,
2450 SetRect (&bottomRect, R.right - 2, R.top, R.right, R.bottom);
2451 SetRect (&lightRect, R.left, R.top, R.left + 3, R.top + 3);
2452 SetRect (&shadeRect, R.left + 1, R.bottom - 2, R.left + 2,
2459 rightFlag = BF_RIGHT;
2460 lightFlag = BF_DIAGONAL_ENDTOPRIGHT;
2461 shadeFlag = BF_DIAGONAL_ENDBOTTOMRIGHT;
2463 SetRect (&topRect, R.left + lOffset, R.top, R.right - rOffset,
2465 SetRect (&sideRect, R.left, R.top + 2, R.right,
2466 R.bottom - 1 + selectedOffset);
2467 SetRect (&bottomRect, R.left, R.bottom - 1, R.right, R.bottom);
2468 SetRect (&lightRect, R.left, R.top, R.left + 3, R.top + 3);
2469 SetRect (&shadeRect, R.right - 2, R.top + 1, R.right - 1, R.top + 2);
2475 rightFlag = BF_BOTTOM;
2476 lightFlag = BF_DIAGONAL_ENDTOPLEFT;
2477 shadeFlag = BF_DIAGONAL_ENDBOTTOMLEFT;
2479 SetRect (&topRect, R.left, R.top + lOffset, R.right,
2480 R.bottom - rOffset);
2481 SetRect (&sideRect, R.left + 2 - selectedOffset, R.top, R.right - 2,
2483 SetRect (&bottomRect, R.left, R.top, R.left + 2, R.bottom);
2484 SetRect (&lightRect, R.right - 3, R.top, R.right - 1, R.top + 2);
2485 SetRect (&shadeRect, R.right - 2, R.bottom - 3, R.right, R.bottom - 1);
2490 topFlag = BF_BOTTOM;
2491 rightFlag = BF_RIGHT;
2492 lightFlag = BF_DIAGONAL_ENDTOPLEFT;
2493 shadeFlag = BF_DIAGONAL_ENDBOTTOMLEFT;
2495 SetRect (&topRect, R.left + lOffset, R.top, R.right - rOffset,
2497 SetRect (&sideRect, R.left, R.top + 2 - selectedOffset, R.right,
2499 SetRect (&bottomRect, R.left, R.top, R.right, R.top + 2);
2500 SetRect (&lightRect, R.left, R.bottom - 3, R.left + 2, R.bottom - 1);
2501 SetRect (&shadeRect, R.right - 2, R.bottom - 3, R.right, R.bottom - 1);
2505 g_return_if_reached ();
2509 FillRect (hdc, &R, (HBRUSH) (COLOR_3DFACE + 1));
2512 DrawEdge (hdc, &topRect, EDGE_RAISED, BF_SOFT | topFlag);
2516 DrawEdge (hdc, &bottomRect, EDGE_RAISED, BF_SOFT | topFlag);
2524 DrawEdge (hdc, &sideRect, EDGE_RAISED, BF_SOFT | leftFlag | rightFlag);
2526 /* Tab Diagonal Corners */
2528 DrawEdge (hdc, &lightRect, EDGE_RAISED, BF_SOFT | lightFlag);
2531 DrawEdge (hdc, &shadeRect, EDGE_RAISED, BF_SOFT | shadeFlag);
2535 draw_themed_tab_button (GtkStyle *style,
2537 GtkStateType state_type,
2538 GtkNotebook *notebook,
2540 gint width, gint height, gint gap_side)
2542 GdkPixmap *pixmap = NULL;
2544 gtk_container_get_border_width (GTK_CONTAINER (notebook));
2545 GtkWidget *widget = GTK_WIDGET (notebook);
2546 GdkRectangle draw_rect, clip_rect;
2547 GdkPixbufRotation rotation = GDK_PIXBUF_ROTATE_NONE;
2549 if (gap_side == GTK_POS_TOP)
2553 if (state_type == GTK_STATE_NORMAL)
2557 draw_rect.width = width + 2;
2558 draw_rect.height = height;
2560 clip_rect = draw_rect;
2565 draw_rect.x = x + 2;
2567 draw_rect.width = width - 2;
2568 draw_rect.height = height - 2;
2569 clip_rect = draw_rect;
2572 /* If we are currently drawing the right-most tab, and if that tab is the selected tab... */
2573 widget_right = widget->allocation.x + widget->allocation.width - border_width - 2;
2575 if (draw_rect.x + draw_rect.width >= widget_right)
2577 draw_rect.width = clip_rect.width = widget_right - draw_rect.x;
2580 if (gap_side == GTK_POS_BOTTOM)
2584 if (state_type == GTK_STATE_NORMAL)
2588 draw_rect.width = width + 2;
2589 draw_rect.height = height;
2591 clip_rect = draw_rect;
2595 draw_rect.x = x + 2;
2596 draw_rect.y = y + 2;
2597 draw_rect.width = width - 2;
2598 draw_rect.height = height - 2;
2599 clip_rect = draw_rect;
2602 /* If we are currently drawing the right-most tab, and if that tab is the selected tab... */
2603 widget_right = widget->allocation.x + widget->allocation.width - border_width - 2;
2605 if (draw_rect.x + draw_rect.width >= widget_right)
2607 draw_rect.width = clip_rect.width = widget_right - draw_rect.x;
2610 rotation = GDK_PIXBUF_ROTATE_UPSIDEDOWN;
2612 else if (gap_side == GTK_POS_LEFT)
2616 if (state_type == GTK_STATE_NORMAL)
2620 draw_rect.width = width;
2621 draw_rect.height = height + 2;
2623 clip_rect = draw_rect;
2629 draw_rect.y = y + 2;
2630 draw_rect.width = width - 2;
2631 draw_rect.height = height - 2;
2632 clip_rect = draw_rect;
2635 /* If we are currently drawing the bottom-most tab, and if that tab is the selected tab... */
2636 widget_bottom = widget->allocation.x + widget->allocation.height - border_width - 2;
2638 if (draw_rect.y + draw_rect.height >= widget_bottom)
2640 draw_rect.height = clip_rect.height = widget_bottom - draw_rect.y;
2643 rotation = GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE;
2645 else if (gap_side == GTK_POS_RIGHT)
2649 if (state_type == GTK_STATE_NORMAL)
2651 draw_rect.x = x + 1;
2653 draw_rect.width = width;
2654 draw_rect.height = height + 2;
2656 clip_rect = draw_rect;
2661 draw_rect.x = x + 2;
2662 draw_rect.y = y + 2;
2663 draw_rect.width = width - 2;
2664 draw_rect.height = height - 2;
2665 clip_rect = draw_rect;
2668 /* If we are currently drawing the bottom-most tab, and if that tab is the selected tab... */
2669 widget_bottom = widget->allocation.x + widget->allocation.height - border_width - 2;
2671 if (draw_rect.y + draw_rect.height >= widget_bottom)
2673 draw_rect.height = clip_rect.height = widget_bottom - draw_rect.y;
2676 rotation = GDK_PIXBUF_ROTATE_CLOCKWISE;
2679 if (gap_side == GTK_POS_TOP)
2681 if (!xp_theme_draw (window, XP_THEME_ELEMENT_TAB_ITEM, style,
2682 draw_rect.x, draw_rect.y,
2683 draw_rect.width, draw_rect.height,
2684 state_type, &clip_rect))
2694 if (gap_side == GTK_POS_LEFT || gap_side == GTK_POS_RIGHT)
2696 pixmap = gdk_pixmap_new (window, clip_rect.height, clip_rect.width, -1);
2698 if (!xp_theme_draw (pixmap, XP_THEME_ELEMENT_TAB_ITEM, style,
2699 draw_rect.y - clip_rect.y, draw_rect.x - clip_rect.x,
2700 draw_rect.height, draw_rect.width, state_type, 0))
2702 g_object_unref (pixmap);
2706 pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap, NULL, 0, 0, 0, 0,
2707 clip_rect.height, clip_rect.width);
2708 g_object_unref (pixmap);
2712 pixmap = gdk_pixmap_new (window, clip_rect.width, clip_rect.height, -1);
2714 if (!xp_theme_draw (pixmap, XP_THEME_ELEMENT_TAB_ITEM, style,
2715 draw_rect.x - clip_rect.x, draw_rect.y - clip_rect.y,
2716 draw_rect.width, draw_rect.height, state_type, 0))
2718 g_object_unref (pixmap);
2722 pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap, NULL, 0, 0, 0, 0,
2723 clip_rect.width, clip_rect.height);
2724 g_object_unref (pixmap);
2727 rotated = gdk_pixbuf_rotate_simple (pixbuf, rotation);
2728 g_object_unref (pixbuf);
2731 // XXX - This is really hacky and evil. When we're drawing the left-most tab
2732 // while it is active on a bottom-oriented notebook, there is one white
2733 // pixel at the top. There may be a better solution than this if someone
2734 // has time to discover it.
2735 if (gap_side == GTK_POS_BOTTOM && state_type == GTK_STATE_NORMAL
2736 && x == widget->allocation.x)
2738 int rowstride = gdk_pixbuf_get_rowstride (pixbuf);
2739 int n_channels = gdk_pixbuf_get_n_channels (pixbuf);
2742 guchar *pixels = gdk_pixbuf_get_pixels (pixbuf);
2743 guchar *p = pixels + rowstride;
2745 for (psub = 0; psub < n_channels; psub++)
2747 pixels[psub] = p[psub];
2751 gdk_draw_pixbuf (window, NULL, pixbuf, 0, 0, clip_rect.x, clip_rect.y,
2752 clip_rect.width, clip_rect.height, GDK_RGB_DITHER_NONE,
2754 g_object_unref (pixbuf);
2761 draw_tab_button (GtkStyle *style,
2763 GtkStateType state_type,
2764 GtkShadowType shadow_type,
2767 const gchar *detail,
2768 gint x, gint y, gint width, gint height, gint gap_side)
2770 if (gap_side == GTK_POS_TOP || gap_side == GTK_POS_BOTTOM)
2772 /* experimental tab-drawing code from mozilla */
2777 dc = get_window_dc (style, window, state_type, x, y, width, height, &rect);
2779 if (gap_side == GTK_POS_TOP)
2781 else if (gap_side == GTK_POS_BOTTOM)
2782 aPosition = BF_BOTTOM;
2783 else if (gap_side == GTK_POS_LEFT)
2784 aPosition = BF_LEFT;
2786 aPosition = BF_RIGHT;
2788 if (state_type == GTK_STATE_PRELIGHT)
2789 state_type = GTK_STATE_NORMAL;
2791 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
2793 DrawTab (dc, rect, aPosition,
2794 state_type != GTK_STATE_PRELIGHT,
2795 (gap_side != GTK_POS_LEFT), (gap_side != GTK_POS_RIGHT));
2798 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
2800 release_window_dc (style, window, state_type);
2808 draw_extension (GtkStyle *style,
2810 GtkStateType state_type,
2811 GtkShadowType shadow_type,
2814 const gchar *detail,
2816 gint width, gint height, GtkPositionType gap_side)
2818 if (widget && GTK_IS_NOTEBOOK (widget) && detail && !strcmp (detail, "tab"))
2820 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2822 /* Why this differs from gap_side, I have no idea.. */
2823 int real_gap_side = gtk_notebook_get_tab_pos (notebook);
2825 if (!draw_themed_tab_button (style, window, state_type,
2826 GTK_NOTEBOOK (widget), x, y,
2827 width, height, real_gap_side))
2829 if (!draw_tab_button (style, window, state_type,
2830 shadow_type, area, widget,
2831 detail, x, y, width, height, real_gap_side))
2833 parent_class->draw_extension (style, window, state_type,
2834 shadow_type, area, widget, detail,
2835 x, y, width, height,
2843 draw_box_gap (GtkStyle *style, GdkWindow *window, GtkStateType state_type,
2844 GtkShadowType shadow_type, GdkRectangle *area,
2845 GtkWidget *widget, const gchar *detail, gint x,
2846 gint y, gint width, gint height, GtkPositionType gap_side,
2847 gint gap_x, gint gap_width)
2849 if (GTK_IS_NOTEBOOK (widget) && detail && !strcmp (detail, "notebook"))
2851 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2852 int side = gtk_notebook_get_tab_pos (notebook);
2853 int x2 = x, y2 = y, w2 = width, h2 = height;
2855 if (side == GTK_POS_TOP)
2858 y2 = y - notebook->tab_vborder;
2860 h2 = height + notebook->tab_vborder * 2;
2862 else if (side == GTK_POS_BOTTOM)
2867 h2 = height + notebook->tab_vborder * 2;
2869 else if (side == GTK_POS_LEFT)
2871 x2 = x - notebook->tab_hborder;
2873 w2 = width + notebook->tab_hborder;
2876 else if (side == GTK_POS_RIGHT)
2880 w2 = width + notebook->tab_hborder * 2;
2884 if (xp_theme_draw (window, XP_THEME_ELEMENT_TAB_PANE, style,
2885 x2, y2, w2, h2, state_type, area))
2891 parent_class->draw_box_gap (style, window, state_type, shadow_type,
2892 area, widget, detail, x, y, width, height,
2893 gap_side, gap_x, gap_width);
2897 is_popup_window_child (GtkWidget *widget)
2900 GtkWindowType type = -1;
2902 top = gtk_widget_get_toplevel (widget);
2904 if (top && GTK_IS_WINDOW (top))
2906 g_object_get (top, "type", &type, NULL);
2908 if (type == GTK_WINDOW_POPUP)
2909 { /* Hack for combo boxes */
2918 draw_flat_box (GtkStyle *style, GdkWindow *window,
2919 GtkStateType state_type, GtkShadowType shadow_type,
2920 GdkRectangle *area, GtkWidget *widget,
2921 const gchar *detail, gint x, gint y, gint width, gint height)
2925 if (state_type == GTK_STATE_SELECTED &&
2926 (!strncmp ("cell_even", detail, 9) || !strncmp ("cell_odd", detail, 8)))
2928 GdkGC *gc = GTK_WIDGET_HAS_FOCUS (widget) ? style->base_gc[state_type] : style->base_gc[GTK_STATE_ACTIVE];
2930 gdk_draw_rectangle (window, gc, TRUE, x, y, width, height);
2934 else if (!strcmp (detail, "checkbutton"))
2936 if (state_type == GTK_STATE_PRELIGHT)
2943 parent_class->draw_flat_box (style, window, state_type, shadow_type,
2944 area, widget, detail, x, y, width, height);
2948 draw_menu_border (GdkWindow *win, GtkStyle *style,
2949 gint x, gint y, gint width, gint height)
2954 dc = get_window_dc (style, win, GTK_STATE_NORMAL, x, y, width, height, &rect);
2959 if (xp_theme_is_active ())
2961 FrameRect (dc, &rect, GetSysColorBrush (COLOR_3DSHADOW));
2965 DrawEdge (dc, &rect, EDGE_RAISED, BF_RECT);
2968 release_window_dc (style, win, GTK_STATE_NORMAL);
2974 draw_shadow (GtkStyle *style,
2976 GtkStateType state_type,
2977 GtkShadowType shadow_type,
2980 const gchar *detail, gint x, gint y, gint width, gint height)
2982 gboolean is_handlebox;
2983 gboolean is_toolbar;
2985 if (detail && !strcmp (detail, "frame"))
2993 dc = get_window_dc (style, window, state_type, x, y, width, height, &rect);
2994 if (is_combo_box_child (widget))
2996 FillRect (dc, &rect, GetSysColorBrush (COLOR_WINDOW));
2998 else if (is_popup_window_child (widget))
3000 FrameRect (dc, &rect, GetSysColorBrush (COLOR_WINDOWFRAME));
3004 switch (shadow_type)
3007 draw_3d_border (dc, &rect, TRUE);
3010 case GTK_SHADOW_OUT:
3011 draw_3d_border (dc, &rect, FALSE);
3014 case GTK_SHADOW_ETCHED_IN:
3015 draw_3d_border (dc, &rect, TRUE);
3016 InflateRect (&rect, -1, -1);
3017 draw_3d_border (dc, &rect, FALSE);
3020 case GTK_SHADOW_ETCHED_OUT:
3021 draw_3d_border (dc, &rect, FALSE);
3022 InflateRect (&rect, -1, -1);
3023 draw_3d_border (dc, &rect, TRUE);
3026 case GTK_SHADOW_NONE:
3031 release_window_dc (style, window, state_type);
3035 if (detail && (!strcmp (detail, "entry") || !strcmp (detail, "combobox")))
3037 if (shadow_type != GTK_SHADOW_IN)
3040 if (!xp_theme_draw (window, XP_THEME_ELEMENT_EDIT_TEXT, style,
3041 x, y, width, height, state_type, area))
3046 dc = get_window_dc (style, window, state_type,
3047 x, y, width, height, &rect);
3049 DrawEdge (dc, &rect, EDGE_SUNKEN, BF_RECT);
3050 release_window_dc (style, window, state_type);
3056 if (detail && !strcmp (detail, "scrolled_window") &&
3057 xp_theme_draw (window, XP_THEME_ELEMENT_EDIT_TEXT, style,
3058 x, y, width, height, state_type, area))
3063 if (detail && !strcmp (detail, "spinbutton"))
3066 if (detail && !strcmp (detail, "menu"))
3068 if (draw_menu_border (window, style, x, y, width, height))
3074 if (detail && !strcmp (detail, "handlebox"))
3077 is_handlebox = (detail && !strcmp (detail, "handlebox_bin"));
3078 is_toolbar = (detail
3079 && (!strcmp (detail, "toolbar")
3080 || !strcmp (detail, "menubar")));
3082 if (is_toolbar || is_handlebox)
3084 if (shadow_type == GTK_SHADOW_NONE)
3093 HGDIOBJ old_pen = NULL;
3094 GtkPositionType pos;
3096 sanitize_size (window, &width, &height);
3100 pos = gtk_handle_box_get_handle_position (GTK_HANDLE_BOX (widget));
3102 If the handle box is at left side,
3103 we shouldn't draw its right border.
3104 The same holds true for top, right, and bottom.
3109 pos = GTK_POS_RIGHT;
3117 pos = GTK_POS_BOTTOM;
3120 case GTK_POS_BOTTOM:
3127 GtkWidget *parent = gtk_widget_get_parent (widget);
3129 /* Dirty hack for toolbars contained in handle boxes */
3130 if (GTK_IS_HANDLE_BOX (parent))
3132 pos = gtk_handle_box_get_handle_position (GTK_HANDLE_BOX (parent));
3138 Make pos != all legal enum vaules of GtkPositionType.
3139 So every border will be draw.
3141 pos = (GtkPositionType) - 1;
3145 dc = get_window_dc (style, window, state_type, x, y, width, height, &rect);
3147 if (pos != GTK_POS_LEFT)
3149 old_pen = SelectObject (dc, get_light_pen ());
3150 MoveToEx (dc, rect.left, rect.top, NULL);
3151 LineTo (dc, rect.left, rect.bottom);
3153 if (pos != GTK_POS_TOP)
3155 old_pen = SelectObject (dc, get_light_pen ());
3156 MoveToEx (dc, rect.left, rect.top, NULL);
3157 LineTo (dc, rect.right, rect.top);
3159 if (pos != GTK_POS_RIGHT)
3161 old_pen = SelectObject (dc, get_dark_pen ());
3162 MoveToEx (dc, rect.right - 1, rect.top, NULL);
3163 LineTo (dc, rect.right - 1, rect.bottom);
3165 if (pos != GTK_POS_BOTTOM)
3167 old_pen = SelectObject (dc, get_dark_pen ());
3168 MoveToEx (dc, rect.left, rect.bottom - 1, NULL);
3169 LineTo (dc, rect.right, rect.bottom - 1);
3172 SelectObject (dc, old_pen);
3173 release_window_dc (style, window, state_type);
3179 if (detail && !strcmp (detail, "statusbar"))
3184 parent_class->draw_shadow (style, window, state_type, shadow_type, area,
3185 widget, detail, x, y, width, height);
3189 draw_hline (GtkStyle *style,
3191 GtkStateType state_type,
3194 const gchar *detail, gint x1, gint x2, gint y)
3196 if (xp_theme_is_active () && detail && !strcmp (detail, "menuitem"))
3199 (window, XP_THEME_ELEMENT_MENU_SEPARATOR, style, x1, y, x2, 1,
3208 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
3211 gdk_draw_line (window, style->dark_gc[state_type], x1, y, x2, y);
3215 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
3221 if (style->ythickness == 2)
3225 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
3226 gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
3229 gdk_draw_line (window, style->dark_gc[state_type], x1, y, x2, y);
3231 gdk_draw_line (window, style->light_gc[state_type], x1, y, x2, y);
3235 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
3236 gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
3241 parent_class->draw_hline (style, window, state_type, area, widget,
3248 draw_vline (GtkStyle *style,
3250 GtkStateType state_type,
3253 const gchar *detail, gint y1, gint y2, gint x)
3255 if (style->xthickness == 2)
3259 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
3260 gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
3263 gdk_draw_line (window, style->dark_gc[state_type], x, y1, x, y2);
3265 gdk_draw_line (window, style->light_gc[state_type], x, y1, x, y2);
3269 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
3270 gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
3275 parent_class->draw_vline (style, window, state_type, area, widget,
3281 draw_slider (GtkStyle *style,
3283 GtkStateType state_type,
3284 GtkShadowType shadow_type,
3287 const gchar *detail,
3289 gint y, gint width, gint height, GtkOrientation orientation)
3291 if (GTK_IS_SCALE (widget) &&
3292 xp_theme_draw (window, ((orientation == GTK_ORIENTATION_VERTICAL) ?
3293 XP_THEME_ELEMENT_SCALE_SLIDER_V :
3294 XP_THEME_ELEMENT_SCALE_SLIDER_H), style, x, y, width,
3295 height, state_type, area))
3300 parent_class->draw_slider (style, window, state_type, shadow_type, area,
3301 widget, detail, x, y, width, height,
3306 draw_resize_grip (GtkStyle *style,
3308 GtkStateType state_type,
3311 const gchar *detail,
3312 GdkWindowEdge edge, gint x, gint y, gint width, gint height)
3314 if (detail && !strcmp (detail, "statusbar"))
3317 (window, XP_THEME_ELEMENT_STATUS_GRIPPER, style, x, y, width,
3318 height, state_type, area))
3325 HDC dc = get_window_dc (style, window, state_type, x, y, width, height, &rect);
3328 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
3330 DrawFrameControl (dc, &rect, DFC_SCROLL, DFCS_SCROLLSIZEGRIP);
3331 release_window_dc (style, window, state_type);
3334 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
3340 parent_class->draw_resize_grip (style, window, state_type, area,
3341 widget, detail, edge, x, y, width, height);
3345 draw_handle (GtkStyle *style,
3347 GtkStateType state_type,
3348 GtkShadowType shadow_type,
3351 const gchar *detail,
3353 gint y, gint width, gint height, GtkOrientation orientation)
3358 if (is_toolbar_child (widget))
3360 XpThemeElement hndl;
3362 sanitize_size (window, &width, &height);
3364 if (GTK_IS_HANDLE_BOX (widget))
3366 GtkPositionType pos;
3367 pos = gtk_handle_box_get_handle_position (GTK_HANDLE_BOX (widget));
3369 if (pos == GTK_POS_TOP || pos == GTK_POS_BOTTOM)
3371 orientation = GTK_ORIENTATION_HORIZONTAL;
3375 orientation = GTK_ORIENTATION_VERTICAL;
3379 if (orientation == GTK_ORIENTATION_VERTICAL)
3380 hndl = XP_THEME_ELEMENT_REBAR_GRIPPER_V;
3382 hndl = XP_THEME_ELEMENT_REBAR_GRIPPER_H;
3384 if (xp_theme_draw (window, hndl, style, x, y, width, height,
3390 dc = get_window_dc (style, window, state_type, x, y, width, height, &rect);
3392 if (orientation == GTK_ORIENTATION_VERTICAL)
3395 rect.right = rect.left + 3;
3402 rect.bottom = rect.top + 3;
3407 draw_3d_border (dc, &rect, FALSE);
3408 release_window_dc (style, window, state_type);
3412 if (!GTK_IS_PANED (widget))
3414 gint xthick, ythick;
3415 GdkGC *light_gc, *dark_gc, *shadow_gc;
3418 sanitize_size (window, &width, &height);
3420 gtk_paint_box (style, window, state_type, shadow_type, area,
3421 widget, detail, x, y, width, height);
3423 light_gc = style->light_gc[state_type];
3424 dark_gc = style->dark_gc[state_type];
3425 shadow_gc = style->mid_gc[state_type];
3427 xthick = style->xthickness;
3428 ythick = style->ythickness;
3430 dest.x = x + xthick;
3431 dest.y = y + ythick;
3432 dest.width = width - (xthick * 2);
3433 dest.height = height - (ythick * 2);
3435 if (dest.width < dest.height)
3440 gdk_gc_set_clip_rectangle (light_gc, &dest);
3441 gdk_gc_set_clip_rectangle (dark_gc, &dest);
3442 gdk_gc_set_clip_rectangle (shadow_gc, &dest);
3444 if (dest.width < dest.height)
3446 gdk_draw_line (window, light_gc, dest.x, dest.y, dest.x,
3448 gdk_draw_line (window, dark_gc, dest.x + (dest.width / 2),
3449 dest.y, dest.x + (dest.width / 2), dest.height);
3450 gdk_draw_line (window, shadow_gc, dest.x + dest.width,
3451 dest.y, dest.x + dest.width, dest.height);
3455 gdk_draw_line (window, light_gc, dest.x, dest.y,
3456 dest.x + dest.width, dest.y);
3457 gdk_draw_line (window, dark_gc, dest.x,
3458 dest.y + (dest.height / 2),
3459 dest.x + dest.width, dest.y + (dest.height / 2));
3460 gdk_draw_line (window, shadow_gc, dest.x,
3461 dest.y + dest.height, dest.x + dest.width,
3462 dest.y + dest.height);
3465 gdk_gc_set_clip_rectangle (shadow_gc, NULL);
3466 gdk_gc_set_clip_rectangle (light_gc, NULL);
3467 gdk_gc_set_clip_rectangle (dark_gc, NULL);
3472 draw_focus (GtkStyle *style,
3474 GtkStateType state_type,
3477 const gchar *detail, gint x, gint y, gint width, gint height)
3482 if (!GTK_WIDGET_CAN_FOCUS (widget))
3487 if (is_combo_box_child (widget)
3488 && (GTK_IS_ARROW (widget) || GTK_IS_BUTTON (widget)))
3492 if (GTK_IS_TREE_VIEW (widget->parent) /* list view bheader */
3493 || GTK_IS_CLIST (widget->parent))
3498 dc = get_window_dc (style, window, state_type, x, y, width, height, &rect);
3499 DrawFocusRect (dc, &rect);
3500 release_window_dc (style, window, state_type);
3502 parent_class->draw_focus (style, window, state_type,
3503 area, widget, detail, x, y, width, height);
3508 draw_layout (GtkStyle *style,
3510 GtkStateType state_type,
3514 const gchar *detail,
3515 gint old_x, gint old_y, PangoLayout *layout)
3517 GtkNotebook *notebook = NULL;
3521 /* In the XP theme, labels don't appear correctly centered inside
3522 * notebook tabs, so we give them a gentle nudge two pixels to the
3523 * right. A little hackish, but what are 'ya gonna do? -- Cody
3525 if (xp_theme_is_active () && detail && !strcmp (detail, "label"))
3527 if (widget->parent != NULL)
3529 if (GTK_IS_NOTEBOOK (widget->parent))
3532 notebook = GTK_NOTEBOOK (widget->parent);
3533 side = gtk_notebook_get_tab_pos (notebook);
3535 if (side == GTK_POS_TOP || side == GTK_POS_BOTTOM)
3543 parent_class->draw_layout (style, window, state_type,
3544 use_text, area, widget, detail, x, y, layout);
3548 msw_style_init_from_rc (GtkStyle *style, GtkRcStyle *rc_style)
3550 setup_system_font (style);
3551 setup_menu_settings (gtk_settings_get_default ());
3552 setup_system_styles (style);
3553 parent_class->init_from_rc (style, rc_style);
3557 load_bg_image (GdkColormap *colormap,
3558 GdkColor *bg_color, const gchar *filename)
3560 if (strcmp (filename, "<parent>") == 0)
3562 return (GdkPixmap *) GDK_PARENT_RELATIVE;
3566 return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL,
3567 bg_color, filename);
3572 msw_style_realize (GtkStyle *style)
3574 GdkGCValues gc_values;
3575 GdkGCValuesMask gc_values_mask;
3579 for (i = 0; i < 5; i++)
3581 style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2;
3582 style->mid[i].green =
3583 (style->light[i].green + style->dark[i].green) / 2;
3584 style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2;
3586 style->text_aa[i].red = (style->text[i].red + style->base[i].red) / 2;
3587 style->text_aa[i].green =
3588 (style->text[i].green + style->base[i].green) / 2;
3589 style->text_aa[i].blue =
3590 (style->text[i].blue + style->base[i].blue) / 2;
3593 style->black.red = 0x0000;
3594 style->black.green = 0x0000;
3595 style->black.blue = 0x0000;
3596 gdk_colormap_alloc_color (style->colormap, &style->black, FALSE, TRUE);
3598 style->white.red = 0xffff;
3599 style->white.green = 0xffff;
3600 style->white.blue = 0xffff;
3601 gdk_colormap_alloc_color (style->colormap, &style->white, FALSE, TRUE);
3603 gc_values_mask = GDK_GC_FOREGROUND | GDK_GC_BACKGROUND;
3605 gc_values.foreground = style->black;
3606 gc_values.background = style->white;
3608 gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3610 gc_values.foreground = style->white;
3611 gc_values.background = style->black;
3613 gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3615 gc_values_mask = GDK_GC_FOREGROUND;
3617 for (i = 0; i < 5; i++)
3619 if (style->rc_style && style->rc_style->bg_pixmap_name[i])
3621 style->bg_pixmap[i] = load_bg_image (style->colormap,
3627 if (!gdk_colormap_alloc_color (style->colormap, &style->fg[i], FALSE, TRUE))
3629 g_warning ("unable to allocate color: ( %d %d %d )", style->fg[i].red,
3630 style->fg[i].green, style->fg[i].blue);
3633 if (!gdk_colormap_alloc_color (style->colormap, &style->bg[i], FALSE, TRUE))
3635 g_warning ("unable to allocate color: ( %d %d %d )", style->bg[i].red,
3636 style->bg[i].green, style->bg[i].blue);
3639 if (!gdk_colormap_alloc_color (style->colormap, &style->light[i], FALSE, TRUE))
3641 g_warning ("unable to allocate color: ( %d %d %d )",
3642 style->light[i].red, style->light[i].green,
3643 style->light[i].blue);
3646 if (!gdk_colormap_alloc_color (style->colormap, &style->dark[i], FALSE, TRUE))
3648 g_warning ("unable to allocate color: ( %d %d %d )",
3649 style->dark[i].red, style->dark[i].green,
3650 style->dark[i].blue);
3653 if (!gdk_colormap_alloc_color (style->colormap, &style->mid[i], FALSE, TRUE))
3655 g_warning ("unable to allocate color: ( %d %d %d )",
3656 style->mid[i].red, style->mid[i].green,
3657 style->mid[i].blue);
3660 if (!gdk_colormap_alloc_color (style->colormap, &style->text[i], FALSE, TRUE))
3662 g_warning ("unable to allocate color: ( %d %d %d )",
3663 style->text[i].red, style->text[i].green,
3664 style->text[i].blue);
3667 if (!gdk_colormap_alloc_color (style->colormap, &style->base[i], FALSE, TRUE))
3669 g_warning ("unable to allocate color: ( %d %d %d )",
3670 style->base[i].red, style->base[i].green,
3671 style->base[i].blue);
3674 if (!gdk_colormap_alloc_color (style->colormap, &style->text_aa[i], FALSE, TRUE))
3676 g_warning ("unable to allocate color: ( %d %d %d )",
3677 style->text_aa[i].red, style->text_aa[i].green,
3678 style->text_aa[i].blue);
3681 gc_values.foreground = style->fg[i];
3682 style->fg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3684 gc_values.foreground = style->bg[i];
3685 style->bg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3687 gc_values.foreground = style->light[i];
3688 style->light_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3690 gc_values.foreground = style->dark[i];
3691 style->dark_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3693 gc_values.foreground = style->mid[i];
3694 style->mid_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3696 gc_values.foreground = style->text[i];
3697 style->text_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3699 gc_values.foreground = style->base[i];
3700 style->base_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3702 gc_values.foreground = style->text_aa[i];
3703 style->text_aa_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3708 msw_style_unrealize (GtkStyle *style)
3710 parent_class->unrealize (style);
3714 msw_style_class_init (MswStyleClass *klass)
3716 GtkStyleClass *style_class = GTK_STYLE_CLASS (klass);
3718 parent_class = g_type_class_peek_parent (klass);
3720 style_class->init_from_rc = msw_style_init_from_rc;
3721 style_class->draw_arrow = draw_arrow;
3722 style_class->draw_box = draw_box;
3723 style_class->draw_check = draw_check;
3724 style_class->draw_option = draw_option;
3725 style_class->draw_tab = draw_tab;
3726 style_class->draw_flat_box = draw_flat_box;
3727 style_class->draw_expander = draw_expander;
3728 style_class->draw_extension = draw_extension;
3729 style_class->draw_box_gap = draw_box_gap;
3730 style_class->draw_shadow = draw_shadow;
3731 style_class->draw_hline = draw_hline;
3732 style_class->draw_vline = draw_vline;
3733 style_class->draw_handle = draw_handle;
3734 style_class->draw_resize_grip = draw_resize_grip;
3735 style_class->draw_slider = draw_slider;
3736 style_class->draw_focus = draw_focus;
3737 style_class->draw_layout = draw_layout;
3739 style_class->realize = msw_style_realize;
3740 style_class->unrealize = msw_style_unrealize;
3743 GType msw_type_style = 0;
3746 msw_style_register_type (GTypeModule *module)
3748 const GTypeInfo object_info = {
3749 sizeof (MswStyleClass),
3750 (GBaseInitFunc) NULL,
3751 (GBaseFinalizeFunc) NULL,
3752 (GClassInitFunc) msw_style_class_init,
3753 NULL, /* class_finalize */
3754 NULL, /* class_data */
3756 0, /* n_preallocs */
3757 (GInstanceInitFunc) NULL,
3760 msw_type_style = g_type_module_register_type (module,
3762 "MswStyle", &object_info, 0);
3766 msw_style_init (void)
3769 msw_style_setup_system_settings ();
3770 setup_msw_rc_style ();
3774 DeleteObject (g_light_pen);
3780 DeleteObject (g_dark_pen);
3786 msw_style_finalize (void)
3790 DeleteObject (g_dither_brush);
3795 DeleteObject (g_light_pen);
3800 DeleteObject (g_dark_pen);