1 /* MS-Windows Engine (aka GTK-Wimp)
3 * Copyright (C) 2003, 2004 Raymond Penners <raymond@dotsphinx.com>
4 * Copyright (C) 2006 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
5 * Includes code adapted from redmond95 by Owen Taylor, and
6 * gtk-nativewin by Evan Martin
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
27 * http://lxr.mozilla.org/seamonkey/source/widget/src/windows/nsNativeThemeWin.cpp
28 * http://lxr.mozilla.org/seamonkey/source/widget/src/windows/nsLookAndFeel.cpp
29 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/userex/functions/drawthemebackground.asp
30 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/pantdraw_4b3g.asp
33 #include "msw_style.h"
43 /* #include <gdk/gdkwin32.h> */
45 #include "gdk/win32/gdkwin32.h"
47 static HDC get_window_dc(GtkStyle * style, GdkWindow * window, GtkStateType state_type, gint x, gint y, gint width, gint height, RECT *rect);
48 static void release_window_dc(GtkStyle * style, GdkWindow * window, GtkStateType state_type);
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 guint8 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 guint8 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 guint8 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 guint8 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 guint8 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 guint8 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 guint8 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 char check_inconsistent_bits[] = {
118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0xf0,
119 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
121 static const guint8 radio_base_bits[] = {
122 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0xf8, 0x03, 0xfc, 0x07, 0xfc, 0x07,
124 0x07, 0xfc, 0x07, 0xf8, 0x03, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00
126 static const guint8 radio_black_bits[] = {
127 0x00, 0x00, 0xf0, 0x01, 0x0c, 0x02, 0x04, 0x00, 0x02, 0x00, 0x02, 0x00,
129 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
131 static const guint8 radio_dark_bits[] = {
132 0xf0, 0x01, 0x0c, 0x06, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00,
134 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
136 static const guint8 radio_light_bits[] = {
137 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x10, 0x00, 0x10,
139 0x10, 0x00, 0x10, 0x00, 0x08, 0x00, 0x08, 0x0c, 0x06, 0xf0, 0x01
141 static const guint8 radio_mid_bits[] = {
142 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08,
144 0x08, 0x00, 0x08, 0x00, 0x04, 0x0c, 0x06, 0xf0, 0x01, 0x00, 0x00
146 static const guint8 radio_text_bits[] = {
147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xf0, 0x01,
149 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))
185 NONCLIENTMETRICS ncm;
187 ncm.cbSize = sizeof (NONCLIENTMETRICS);
189 if (SystemParametersInfo (SPI_GETNONCLIENTMETRICS,
190 sizeof (NONCLIENTMETRICS), &ncm, 0))
192 if (type == XP_THEME_FONT_CAPTION)
193 *out_lf = ncm.lfCaptionFont;
194 else if (type == XP_THEME_FONT_MENU)
195 *out_lf = ncm.lfMenuFont;
196 else if (type == XP_THEME_FONT_STATUS)
197 *out_lf = ncm.lfStatusFont;
199 *out_lf = ncm.lfMessageFont;
207 /***************************** BEGIN STOLEN FROM PANGO *****************************/
210 This code is stolen from Pango 1.4. It attempts to address the following problems:
212 http://bugzilla.gnome.org/show_bug.cgi?id=135098
213 http://sourceforge.net/tracker/index.php?func=detail&aid=895762&group_id=76416&atid=547655
215 As Owen suggested in bug 135098, once Pango 1.6 is released, we need to get rid of this code.
218 #define PING(printlist)
220 /* TrueType defines: */
222 #define MAKE_TT_TABLE_NAME(c1, c2, c3, c4) \
223 (((guint32)c4) << 24 | ((guint32)c3) << 16 | ((guint32)c2) << 8 | ((guint32)c1))
225 #define CMAP (MAKE_TT_TABLE_NAME('c','m','a','p'))
226 #define CMAP_HEADER_SIZE 4
228 #define NAME (MAKE_TT_TABLE_NAME('n','a','m','e'))
229 #define NAME_HEADER_SIZE 6
231 #define ENCODING_TABLE_SIZE 8
233 #define APPLE_UNICODE_PLATFORM_ID 0
234 #define MACINTOSH_PLATFORM_ID 1
235 #define ISO_PLATFORM_ID 2
236 #define MICROSOFT_PLATFORM_ID 3
238 #define SYMBOL_ENCODING_ID 0
239 #define UNICODE_ENCODING_ID 1
240 #define UCS4_ENCODING_ID 10
244 guint16 format_selector;
246 guint16 string_storage_offset;
255 guint16 string_length;
256 guint16 string_offset;
260 pango_win32_get_name_header (HDC hdc, struct name_header *header)
262 if (GetFontData (hdc, NAME, 0, header, sizeof (*header)) !=
266 header->num_records = GUINT16_FROM_BE (header->num_records);
267 header->string_storage_offset =
268 GUINT16_FROM_BE (header->string_storage_offset);
274 pango_win32_get_name_record (HDC hdc, gint i, struct name_record *record)
276 if (GetFontData (hdc, NAME, 6 + i * sizeof (*record),
277 record, sizeof (*record)) != sizeof (*record))
280 record->platform_id = GUINT16_FROM_BE (record->platform_id);
281 record->encoding_id = GUINT16_FROM_BE (record->encoding_id);
282 record->language_id = GUINT16_FROM_BE (record->language_id);
283 record->name_id = GUINT16_FROM_BE (record->name_id);
284 record->string_length = GUINT16_FROM_BE (record->string_length);
285 record->string_offset = GUINT16_FROM_BE (record->string_offset);
291 get_family_name (LOGFONT * lfp, HDC pango_win32_hdc)
296 struct name_header header;
297 struct name_record record;
299 gint unicode_ix = -1, mac_ix = -1, microsoft_ix = -1;
303 gchar *string = NULL;
308 /* If lfFaceName is ASCII, assume it is the common (English) name for the
309 font. Is this valid? Do some TrueType fonts have different names in
310 French, German, etc, and does the system return these if the locale is
311 set to use French, German, etc? */
312 l = strlen (lfp->lfFaceName);
313 for (i = 0; i < l; i++)
314 if (lfp->lfFaceName[i] < ' ' || lfp->lfFaceName[i] > '~')
318 return g_strdup (lfp->lfFaceName);
320 if ((hfont = CreateFontIndirect (lfp)) == NULL)
323 if ((oldhfont = (HFONT) SelectObject (pango_win32_hdc, hfont)) == NULL)
326 if (!pango_win32_get_name_header (pango_win32_hdc, &header))
329 PING (("%d name records", header.num_records));
331 for (i = 0; i < header.num_records; i++)
333 if (!pango_win32_get_name_record (pango_win32_hdc, i, &record))
336 if ((record.name_id != 1 && record.name_id != 16)
337 || record.string_length <= 0)
340 PING (("platform:%d encoding:%d language:%04x name_id:%d",
341 record.platform_id, record.encoding_id, record.language_id,
344 if (record.platform_id == APPLE_UNICODE_PLATFORM_ID ||
345 record.platform_id == ISO_PLATFORM_ID)
347 else if (record.platform_id == MACINTOSH_PLATFORM_ID && record.encoding_id == 0 && /* Roman
349 record.language_id == 0) /* English */
351 else if (record.platform_id == MICROSOFT_PLATFORM_ID)
352 if ((microsoft_ix == -1 ||
353 PRIMARYLANGID (record.language_id) == LANG_ENGLISH) &&
354 (record.encoding_id == SYMBOL_ENCODING_ID ||
355 record.encoding_id == UNICODE_ENCODING_ID ||
356 record.encoding_id == UCS4_ENCODING_ID))
360 if (microsoft_ix >= 0)
361 name_ix = microsoft_ix;
362 else if (mac_ix >= 0)
364 else if (unicode_ix >= 0)
365 name_ix = unicode_ix;
369 if (!pango_win32_get_name_record (pango_win32_hdc, name_ix, &record))
372 string = g_malloc (record.string_length + 1);
373 if (GetFontData (pango_win32_hdc, NAME,
374 header.string_storage_offset + record.string_offset,
375 string, record.string_length) != record.string_length)
378 string[record.string_length] = '\0';
380 if (name_ix == microsoft_ix)
381 if (record.encoding_id == SYMBOL_ENCODING_ID ||
382 record.encoding_id == UNICODE_ENCODING_ID)
383 codeset = "UTF-16BE";
386 else if (name_ix == mac_ix)
387 codeset = "MacRoman";
388 else /* name_ix == unicode_ix */
392 g_convert (string, record.string_length, "UTF-8", codeset, NULL,
400 SelectObject (pango_win32_hdc, oldhfont);
401 DeleteObject (hfont);
407 SelectObject (pango_win32_hdc, oldhfont);
410 DeleteObject (hfont);
413 return g_locale_to_utf8 (lfp->lfFaceName, -1, NULL, NULL, NULL);
416 /***************************** END STOLEN FROM PANGO *****************************/
419 sys_font_to_pango_font (XpThemeClass klazz, XpThemeFont type, char *buf,
430 if (get_system_font (klazz, type, &lf))
436 weight = "Ultra-Light";
448 weight = "Semi-Bold";
452 weight = "Ultra-Bold";
469 hwnd = GetDesktopWindow ();
473 pt_size = -MulDiv (lf.lfHeight, 72,
474 GetDeviceCaps (hDC, LOGPIXELSY));
479 font = get_family_name (&lf, hDC);
482 ReleaseDC (hwnd, hDC);
487 g_snprintf (buf, bufsiz, "%s %s %s %d", font, style, weight, pt_size);
496 /* missing from ms's header files */
497 #ifndef SPI_GETMENUSHOWDELAY
498 #define SPI_GETMENUSHOWDELAY 106
501 /* I don't know the proper XP theme class for things like
502 HIGHLIGHTTEXT, so we'll just define it to be "BUTTON"
504 #define XP_THEME_CLASS_TEXT XP_THEME_CLASS_BUTTON
507 setup_menu_settings (GtkSettings * settings)
510 gboolean win95 = FALSE;
511 OSVERSIONINFOEX osvi;
512 GObjectClass *klazz = G_OBJECT_GET_CLASS (G_OBJECT (settings));
514 ZeroMemory (&osvi, sizeof (OSVERSIONINFOEX));
515 osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
517 if (!GetVersionEx ((OSVERSIONINFO *) & osvi))
518 win95 = TRUE; /* assume the worst */
520 if (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
521 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
526 if (SystemParametersInfo
527 (SPI_GETMENUSHOWDELAY, 0, &menu_delay, 0))
531 if (g_object_class_find_property
532 (klazz, "gtk-menu-bar-popup-delay"))
534 g_object_set (settings,
535 "gtk-menu-bar-popup-delay",
538 if (g_object_class_find_property
539 (klazz, "gtk-menu-popup-delay"))
541 g_object_set (settings,
542 "gtk-menu-popup-delay",
545 if (g_object_class_find_property
546 (klazz, "gtk-menu-popdown-delay"))
548 g_object_set (settings,
549 "gtk-menu-popdown-delay",
558 msw_style_setup_system_settings (void)
560 GtkSettings *settings;
561 int cursor_blink_time;
563 settings = gtk_settings_get_default ();
567 cursor_blink_time = GetCaretBlinkTime ();
568 g_object_set (settings, "gtk-cursor-blink", cursor_blink_time > 0, NULL);
570 if (cursor_blink_time > 0)
571 g_object_set (settings, "gtk-cursor-blink-time",
572 2 * cursor_blink_time, NULL);
574 g_object_set (settings, "gtk-double-click-distance",
575 GetSystemMetrics (SM_CXDOUBLECLK), NULL);
576 g_object_set (settings, "gtk-double-click-time", GetDoubleClickTime (),
578 g_object_set (settings, "gtk-dnd-drag-threshold",
579 GetSystemMetrics (SM_CXDRAG), NULL);
581 setup_menu_settings (settings);
584 http://developer.gnome.org/doc/API/2.0/gtk/GtkSettings.html
585 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/systemparametersinfo.asp
586 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/getsystemmetrics.asp */
590 setup_system_font (GtkStyle * style)
592 char buf[256], *font; /* It's okay, lfFaceName is smaller than 32
595 if ((font = sys_font_to_pango_font (XP_THEME_CLASS_TEXT,
596 XP_THEME_FONT_MESSAGE,
597 buf, sizeof (buf))) != NULL)
599 if (style->font_desc)
600 pango_font_description_free (style->font_desc);
602 style->font_desc = pango_font_description_from_string (font);
607 sys_color_to_gtk_color (XpThemeClass klazz, int id, GdkColor * pcolor)
611 if (!xp_theme_get_system_color (klazz, id, &color))
612 color = GetSysColor (id);
614 pcolor->pixel = color;
615 pcolor->red = (GetRValue (color) << 8) | GetRValue (color);
616 pcolor->green = (GetGValue (color) << 8) | GetGValue (color);
617 pcolor->blue = (GetBValue (color) << 8) | GetBValue (color);
621 get_system_metric (XpThemeClass klazz, int id)
625 if (!xp_theme_get_system_metric (klazz, id, &rval))
626 rval = GetSystemMetrics (id);
632 setup_msw_rc_style (void)
634 char buf[1024], font_buf[256], *font_ptr;
635 char menu_bar_prelight_str[128];
638 GdkColor menu_text_color;
639 GdkColor tooltip_back;
640 GdkColor tooltip_fore;
643 GdkColor progress_back;
645 GdkColor fg_prelight;
646 GdkColor bg_prelight;
647 GdkColor base_prelight;
648 GdkColor text_prelight;
651 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT,
653 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT,
655 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT,
657 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT,
660 sys_color_to_gtk_color (XP_THEME_CLASS_MENU, COLOR_MENUTEXT,
662 sys_color_to_gtk_color (XP_THEME_CLASS_MENU, COLOR_MENU, &menu_color);
665 sys_color_to_gtk_color (XP_THEME_CLASS_TOOLTIP, COLOR_INFOTEXT,
667 sys_color_to_gtk_color (XP_THEME_CLASS_TOOLTIP, COLOR_INFOBK,
670 /* text on push buttons. TODO: button shadows, backgrounds, and
672 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT, &btn_fore);
673 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE, &btn_face);
675 /* progress bar background color */
676 sys_color_to_gtk_color (XP_THEME_CLASS_PROGRESS, COLOR_HIGHLIGHT,
679 /* Enable coloring for menus. */
681 sys_font_to_pango_font (XP_THEME_CLASS_MENU, XP_THEME_FONT_MENU,
682 font_buf, sizeof (font_buf));
683 g_snprintf (buf, sizeof (buf),
684 "style \"msw-menu\" = \"msw-default\"\n" "{\n"
685 "GtkMenuItem::toggle-spacing = 8\n"
686 "fg[PRELIGHT] = { %d, %d, %d }\n"
687 "bg[PRELIGHT] = { %d, %d, %d }\n"
688 "text[PRELIGHT] = { %d, %d, %d }\n"
689 "base[PRELIGHT] = { %d, %d, %d }\n"
690 "fg[NORMAL] = { %d, %d, %d }\n"
691 "bg[NORMAL] = { %d, %d, %d }\n" "%s = \"%s\"\n"
692 "}widget_class \"*MenuItem*\" style \"msw-menu\"\n"
693 "widget_class \"*GtkMenu\" style \"msw-menu\"\n"
694 "widget_class \"*GtkMenuShell*\" style \"msw-menu\"\n",
695 fg_prelight.red, fg_prelight.green, fg_prelight.blue,
696 bg_prelight.red, bg_prelight.green, bg_prelight.blue,
697 text_prelight.red, text_prelight.green, text_prelight.blue,
698 base_prelight.red, base_prelight.green, base_prelight.blue,
699 menu_text_color.red, menu_text_color.green,
700 menu_text_color.blue, menu_color.red, menu_color.green,
701 menu_color.blue, (font_ptr ? "font_name" : "#"),
702 (font_ptr ? font_ptr : " font name should go here"));
703 gtk_rc_parse_string (buf);
705 if( xp_theme_is_active() ) {
706 *menu_bar_prelight_str = '\0';
709 g_snprintf(menu_bar_prelight_str, sizeof(menu_bar_prelight_str),
710 "fg[PRELIGHT] = { %d, %d, %d }\n",
711 menu_text_color.red, menu_text_color.green, menu_text_color.blue);
714 /* Enable coloring for menu bars. */
715 g_snprintf (buf, sizeof (buf),
716 "style \"msw-menu-bar\" = \"msw-menu\"\n"
718 "bg[NORMAL] = { %d, %d, %d }\n"
720 "GtkMenuBar::shadow-type = %d\n"
722 FIXME: This should be enabled once gtk+ support
723 GtkMenuBar::prelight-item style property.
725 /* "GtkMenuBar::prelight-item = 1\n" */
726 "}widget_class \"*MenuBar*\" style \"msw-menu-bar\"\n",
727 btn_face.red, btn_face.green, btn_face.blue,
728 menu_bar_prelight_str,
729 xp_theme_is_active() ? 0 : 2 );
730 gtk_rc_parse_string (buf);
732 g_snprintf (buf, sizeof (buf),
733 "style \"msw-toolbar\" = \"msw-default\"\n"
735 "GtkHandleBox::shadow-type = %s\n"
736 "GtkToolbar::shadow-type = %s\n"
737 "}widget_class \"*HandleBox*\" style \"msw-toolbar\"\n",
738 "etched-in", "etched-in");
739 gtk_rc_parse_string (buf);
741 /* enable tooltip fonts */
743 sys_font_to_pango_font (XP_THEME_CLASS_STATUS, XP_THEME_FONT_STATUS,
744 font_buf, sizeof (font_buf));
745 g_snprintf (buf, sizeof (buf),
746 "style \"msw-tooltips-caption\" = \"msw-default\"\n"
747 "{fg[NORMAL] = { %d, %d, %d }\n" "%s = \"%s\"\n"
748 "}widget \"gtk-tooltips.GtkLabel\" style \"msw-tooltips-caption\"\n",
749 tooltip_fore.red, tooltip_fore.green, tooltip_fore.blue,
750 (font_ptr ? "font_name" : "#"),
751 (font_ptr ? font_ptr : " font name should go here"));
752 gtk_rc_parse_string (buf);
754 g_snprintf (buf, sizeof (buf),
755 "style \"msw-tooltips\" = \"msw-default\"\n"
756 "{bg[NORMAL] = { %d, %d, %d }\n"
757 "}widget \"gtk-tooltips*\" style \"msw-tooltips\"\n",
758 tooltip_back.red, tooltip_back.green, tooltip_back.blue);
759 gtk_rc_parse_string (buf);
761 /* enable font theming for status bars */
763 sys_font_to_pango_font (XP_THEME_CLASS_STATUS, XP_THEME_FONT_STATUS,
764 font_buf, sizeof (font_buf));
765 g_snprintf (buf, sizeof (buf),
766 "style \"msw-status\" = \"msw-default\"\n" "{%s = \"%s\"\n"
767 "bg[NORMAL] = { %d, %d, %d }\n"
768 "}widget_class \"*Status*\" style \"msw-status\"\n",
769 (font_ptr ? "font_name" : "#"),
770 (font_ptr ? font_ptr : " font name should go here"),
771 btn_face.red, btn_face.green, btn_face.blue);
772 gtk_rc_parse_string (buf);
774 /* enable coloring for text on buttons TODO: use GetThemeMetric for the
775 border and outside border */
776 g_snprintf (buf, sizeof (buf),
777 "style \"msw-button\" = \"msw-default\"\n"
779 "bg[NORMAL] = { %d, %d, %d }\n"
780 "bg[PRELIGHT] = { %d, %d, %d }\n"
781 "bg[INSENSITIVE] = { %d, %d, %d }\n"
782 "fg[PRELIGHT] = { %d, %d, %d }\n"
783 "GtkButton::default-border = { 0, 0, 0, 0 }\n"
784 "GtkButton::default-outside-border = { 0, 0, 0, 0 }\n"
785 "GtkButton::child-displacement-x = 1\n"
786 "GtkButton::child-displacement-y = 1\n"
787 "GtkButton::focus-padding = %d\n"
788 "}widget_class \"*Button*\" style \"msw-button\"\n",
789 btn_face.red, btn_face.green, btn_face.blue,
790 btn_face.red, btn_face.green, btn_face.blue,
791 btn_face.red, btn_face.green, btn_face.blue,
792 btn_fore.red, btn_fore.green, btn_fore.blue,
793 xp_theme_is_active() ? 1 : 2 );
794 gtk_rc_parse_string (buf);
796 /* enable coloring for progress bars */
797 g_snprintf (buf, sizeof (buf),
798 "style \"msw-progress\" = \"msw-default\"\n"
799 "{bg[PRELIGHT] = { %d, %d, %d }\n"
800 "bg[NORMAL] = { %d, %d, %d }\n"
801 "}widget_class \"*Progress*\" style \"msw-progress\"\n",
805 btn_face.red, btn_face.green, btn_face.blue);
806 gtk_rc_parse_string (buf);
808 /* scrollbar thumb width and height */
809 g_snprintf (buf, sizeof (buf),
810 "style \"msw-vscrollbar\" = \"msw-default\"\n"
811 "{GtkRange::slider-width = %d\n"
812 "GtkRange::stepper-size = %d\n"
813 "GtkRange::stepper-spacing = 0\n"
814 "GtkRange::trough_border = 0\n"
815 "GtkScale::slider-length = %d\n"
816 "GtkScrollbar::min-slider-length = 8\n"
817 "}widget_class \"*VScrollbar*\" style \"msw-vscrollbar\"\n"
818 "widget_class \"*VScale*\" style \"msw-vscrollbar\"\n",
819 GetSystemMetrics (SM_CYVTHUMB),
820 get_system_metric (XP_THEME_CLASS_SCROLLBAR, SM_CXVSCROLL),
822 gtk_rc_parse_string (buf);
824 g_snprintf (buf, sizeof (buf),
825 "style \"msw-hscrollbar\" = \"msw-default\"\n"
826 "{GtkRange::slider-width = %d\n"
827 "GtkRange::stepper-size = %d\n"
828 "GtkRange::stepper-spacing = 0\n"
829 "GtkRange::trough_border = 0\n"
830 "GtkScale::slider-length = %d\n"
831 "GtkScrollbar::min-slider-length = 8\n"
832 "}widget_class \"*HScrollbar*\" style \"msw-hscrollbar\"\n"
833 "widget_class \"*HScale*\" style \"msw-hscrollbar\"\n",
834 GetSystemMetrics (SM_CXHTHUMB),
835 get_system_metric (XP_THEME_CLASS_SCROLLBAR, SM_CYHSCROLL),
837 gtk_rc_parse_string (buf);
839 gtk_rc_parse_string (
840 "style \"msw-scrolled-window\" = \"msw-default\"\n"
841 "{GtkScrolledWindow::scrollbars-within-bevel = 1}\n"
842 "class \"GtkScrolledWindow\" style \"msw-scrolled-window\"\n");
844 /* radio/check button sizes */
845 g_snprintf (buf, sizeof (buf),
846 "style \"msw-checkbutton\" = \"msw-button\"\n"
847 "{GtkCheckButton::indicator-size = 13\n"
848 "}widget_class \"*CheckButton*\" style \"msw-checkbutton\"\n"
849 "widget_class \"*RadioButton*\" style \"msw-checkbutton\"\n");
850 gtk_rc_parse_string (buf);
852 /* size of combo box toggle button */
853 g_snprintf (buf, sizeof(buf),
854 "style \"msw-combobox-button\" = \"msw-default\"\n"
858 "GtkButton::default-border = { 0, 0, 0, 0 }\n"
859 "GtkButton::default-outside-border = { 0, 0, 0, 0 }\n"
860 "GtkButton::child-displacement-x = 0\n"
861 "GtkButton::child-displacement-y = 0\n"
862 "GtkWidget::focus-padding = 0\n"
863 "GtkWidget::focus-line-width = 0\n"
865 "widget_class \"*ComboBox*ToggleButton*\" style \"msw-combobox-button\"\n");
866 gtk_rc_parse_string (buf);
868 g_snprintf (buf, sizeof(buf),
869 "style \"msw-combobox\" = \"msw-default\"\n"
871 "GtkComboBox::shadow-type = in\n"
875 "class \"GtkComboBox\" style \"msw-combobox\"\n",
876 GetSystemMetrics (SM_CXEDGE),
877 GetSystemMetrics (SM_CYEDGE));
878 gtk_rc_parse_string (buf);
880 /* size of tree view header */
881 g_snprintf (buf, sizeof(buf),
882 "style \"msw-header-button\" = \"msw-default\"\n"
886 "GtkButton::default-border = { 0, 0, 0, 0 }\n"
887 "GtkButton::default-outside-border = { 0, 0, 0, 0 }\n"
888 "GtkButton::child-displacement-x = 1\n"
889 "GtkButton::child-displacement-y = 1\n"
890 "GtkWidget::focus-padding = 0\n"
891 "GtkWidget::focus-line-width = 0\n"
893 "widget_class \"*TreeView*Button*\" style \"msw-header-button\"\n",
894 xp_theme_is_active() ? 2 : 0 );
895 gtk_rc_parse_string (buf);
897 /* FIXME: This should be enabled once gtk+ support GtkNotebok::prelight-tab */
898 /* enable prelight tab of GtkNotebook */
900 g_snprintf (buf, sizeof (buf),
901 "style \"msw-notebook\" = \"msw-default\"\n"
902 "{GtkNotebook::prelight-tab=1\n"
903 "}widget_class \"*Notebook*\" style \"msw-notebook\"\n");
904 gtk_rc_parse_string (buf);
907 /* FIXME: This should be enabled once gtk+ support GtkTreeView::full-row-focus */
909 g_snprintf (buf, sizeof (buf),
910 "style \"msw-treeview\" = \"msw-default\"\n"
911 "{GtkTreeView::full-row-focus=0\n"
912 "}widget_class \"*TreeView*\" style \"msw-treeview\"\n");
913 gtk_rc_parse_string (buf);
918 setup_system_styles (GtkStyle * style)
922 /* Default background */
923 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
924 &style->bg[GTK_STATE_NORMAL]);
925 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT,
926 &style->bg[GTK_STATE_SELECTED]);
927 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
928 &style->bg[GTK_STATE_INSENSITIVE]);
929 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
930 &style->bg[GTK_STATE_ACTIVE]);
931 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
932 &style->bg[GTK_STATE_PRELIGHT]);
935 sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOW,
936 &style->base[GTK_STATE_NORMAL]);
937 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT,
938 &style->base[GTK_STATE_SELECTED]);
939 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
940 &style->base[GTK_STATE_INSENSITIVE]);
941 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
942 &style->base[GTK_STATE_ACTIVE]);
943 sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOW,
944 &style->base[GTK_STATE_PRELIGHT]);
947 sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT,
948 &style->text[GTK_STATE_NORMAL]);
949 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT,
950 &style->text[GTK_STATE_SELECTED]);
951 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_GRAYTEXT,
952 &style->text[GTK_STATE_INSENSITIVE]);
953 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT,
954 &style->text[GTK_STATE_ACTIVE]);
955 sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT,
956 &style->text[GTK_STATE_PRELIGHT]);
958 /* Default foreground */
959 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT,
960 &style->fg[GTK_STATE_NORMAL]);
961 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT,
962 &style->fg[GTK_STATE_SELECTED]);
963 sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_GRAYTEXT,
964 &style->fg[GTK_STATE_INSENSITIVE]);
965 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT,
966 &style->fg[GTK_STATE_ACTIVE]);
967 sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT,
968 &style->fg[GTK_STATE_PRELIGHT]);
970 for (i = 0; i < 5; i++)
972 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_3DSHADOW,
974 sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_3DHILIGHT,
978 (style->light[i].red + style->dark[i].red) / 2;
979 style->mid[i].green =
980 (style->light[i].green + style->dark[i].green) / 2;
982 (style->light[i].blue + style->dark[i].blue) / 2;
984 style->text_aa[i].red =
985 (style->text[i].red + style->base[i].red) / 2;
986 style->text_aa[i].green =
987 (style->text[i].green + style->base[i].green) / 2;
988 style->text_aa[i].blue =
989 (style->text[i].blue + style->base[i].blue) / 2;
994 sanitize_size (GdkWindow * window, gint * width, gint * height)
996 gboolean set_bg = FALSE;
998 if ((*width == -1) && (*height == -1))
1000 set_bg = GDK_IS_WINDOW (window);
1001 gdk_drawable_get_size (window, width, height);
1003 else if (*width == -1)
1004 gdk_drawable_get_size (window, width, NULL);
1005 else if (*height == -1)
1006 gdk_drawable_get_size (window, NULL, height);
1011 static XpThemeElement
1012 map_gtk_progress_bar_to_xp (GtkProgressBar * progress_bar, gboolean trough)
1016 switch (progress_bar->orientation)
1018 case GTK_PROGRESS_LEFT_TO_RIGHT:
1019 case GTK_PROGRESS_RIGHT_TO_LEFT:
1021 ? XP_THEME_ELEMENT_PROGRESS_TROUGH_H
1022 : XP_THEME_ELEMENT_PROGRESS_BAR_H;
1026 ? XP_THEME_ELEMENT_PROGRESS_TROUGH_V
1027 : XP_THEME_ELEMENT_PROGRESS_BAR_V;
1034 is_combo_box_child (GtkWidget* w)
1041 for (tmp = w->parent; tmp; tmp = tmp->parent)
1043 if (GTK_IS_COMBO_BOX(tmp))
1051 combo_box_draw_arrow (GtkStyle * style,
1054 GdkRectangle * area,
1057 if (xp_theme_is_active ())
1060 if (widget && GTK_IS_TOGGLE_BUTTON(widget->parent) )
1066 dc = get_window_dc( style, window, state, area->x, area->y, area->width, area->height, &rect );
1067 border = (GTK_TOGGLE_BUTTON(widget->parent)->active ? DFCS_PUSHED|DFCS_FLAT : 0);
1069 InflateRect( &rect, 1, 1 );
1070 DrawFrameControl (dc, &rect, DFC_SCROLL, DFCS_SCROLLDOWN | border);
1072 release_window_dc( style, window, state );
1080 draw_part (GdkDrawable * drawable,
1081 GdkGC * gc, GdkRectangle * area, gint x, gint y, Part part)
1084 gdk_gc_set_clip_rectangle (gc, area);
1086 if (!parts[part].bmap)
1087 parts[part].bmap = gdk_bitmap_create_from_data (drawable,
1089 PART_SIZE, PART_SIZE);
1091 gdk_gc_set_ts_origin (gc, x, y);
1092 gdk_gc_set_stipple (gc, parts[part].bmap);
1093 gdk_gc_set_fill (gc, GDK_STIPPLED);
1095 gdk_draw_rectangle (drawable, gc, TRUE, x, y, PART_SIZE, PART_SIZE);
1097 gdk_gc_set_fill (gc, GDK_SOLID);
1100 gdk_gc_set_clip_rectangle (gc, NULL);
1104 draw_check (GtkStyle * style,
1107 GtkShadowType shadow,
1108 GdkRectangle * area,
1110 const gchar * detail, gint x, gint y, gint width, gint height)
1112 x -= (1 + PART_SIZE - width) / 2;
1113 y -= (1 + PART_SIZE - height) / 2;
1115 if (detail && strcmp (detail, "check") == 0) /* Menu item */
1117 if (shadow == GTK_SHADOW_IN)
1119 draw_part (window, style->black_gc, area, x, y,
1121 draw_part (window, style->dark_gc[state], area, x, y,
1127 XpThemeElement theme_elt = XP_THEME_ELEMENT_CHECKBOX;
1130 case GTK_SHADOW_ETCHED_IN:
1131 theme_elt = XP_THEME_ELEMENT_INCONSISTENT_CHECKBOX;
1135 theme_elt = XP_THEME_ELEMENT_PRESSED_CHECKBOX;
1142 if (!xp_theme_draw (window, theme_elt,
1143 style, x, y, width, height, state, area))
1145 if( detail && !strcmp(detail, "cellcheck") )
1146 state = GTK_STATE_NORMAL;
1148 draw_part (window, style->black_gc, area, x, y,
1150 draw_part (window, style->dark_gc[state], area, x, y,
1152 draw_part (window, style->mid_gc[state], area, x, y,
1154 draw_part (window, style->light_gc[state], area, x, y,
1156 draw_part (window, style->base_gc[state], area, x, y,
1159 if (shadow == GTK_SHADOW_IN)
1161 draw_part (window, style->text_gc[state], area, x,
1163 draw_part (window, style->text_aa_gc[state], area,
1166 else if (shadow == GTK_SHADOW_ETCHED_IN)
1168 draw_part (window, style->text_gc[state], area, x, y, CHECK_INCONSISTENT);
1169 draw_part (window, style->text_aa_gc[state], area, x, y, CHECK_AA);
1176 draw_expander (GtkStyle * style,
1179 GdkRectangle * area,
1181 const gchar * detail,
1182 gint x, gint y, GtkExpanderStyle expander_style)
1185 gint expander_semi_size;
1186 XpThemeElement xp_expander;
1188 gtk_widget_style_get (widget, "expander_size", &expander_size, NULL);
1190 switch (expander_style)
1192 case GTK_EXPANDER_COLLAPSED:
1193 case GTK_EXPANDER_SEMI_COLLAPSED:
1194 xp_expander = XP_THEME_ELEMENT_TREEVIEW_EXPANDER_CLOSED;
1197 xp_expander = XP_THEME_ELEMENT_TREEVIEW_EXPANDER_OPENED;
1201 if ((expander_size % 2) == 0)
1204 if (expander_size > 2)
1208 gdk_gc_set_clip_rectangle (style->fg_gc[state], area);
1210 expander_semi_size = expander_size / 2;
1211 x -= expander_semi_size;
1212 y -= expander_semi_size;
1214 if (!xp_theme_draw (window, xp_expander, style,
1215 x, y, expander_size, expander_size, state, area))
1222 dc = get_window_dc( style, window, state, x, y, expander_size, expander_size, &rect );
1223 FrameRect( dc, &rect, GetSysColorBrush(COLOR_GRAYTEXT) );
1224 InflateRect( &rect, -1, -1 );
1225 FillRect( dc, &rect, GetSysColorBrush(state == GTK_STATE_INSENSITIVE ? COLOR_BTNFACE : COLOR_WINDOW) );
1227 InflateRect( &rect, -1, -1 );
1229 pen = CreatePen( PS_SOLID, 1, GetSysColor(COLOR_WINDOWTEXT) );
1230 old_pen = SelectObject( dc, pen );
1232 MoveToEx( dc, rect.left, rect.top - 2 + expander_semi_size, NULL );
1233 LineTo( dc, rect.right, rect.top - 2 + expander_semi_size );
1235 if( expander_style == GTK_EXPANDER_COLLAPSED ||
1236 expander_style == GTK_EXPANDER_SEMI_COLLAPSED )
1238 MoveToEx( dc, rect.left - 2 + expander_semi_size, rect.top, NULL );
1239 LineTo( dc, rect.left - 2 + expander_semi_size, rect.bottom );
1242 SelectObject( dc, old_pen );
1243 DeleteObject( pen );
1244 release_window_dc( style, window, state );
1248 gdk_gc_set_clip_rectangle (style->fg_gc[state], NULL);
1252 draw_option (GtkStyle * style,
1255 GtkShadowType shadow,
1256 GdkRectangle * area,
1258 const gchar * detail, gint x, gint y, gint width, gint height)
1260 x -= (1 + PART_SIZE - width) / 2;
1261 y -= (1 + PART_SIZE - height) / 2;
1263 if (detail && strcmp (detail, "option") == 0) /* Menu item */
1265 if (shadow == GTK_SHADOW_IN)
1266 draw_part (window, style->fg_gc[state], area, x, y,
1271 if (xp_theme_draw (window, shadow == GTK_SHADOW_IN
1272 ? XP_THEME_ELEMENT_PRESSED_RADIO_BUTTON
1273 : XP_THEME_ELEMENT_RADIO_BUTTON,
1274 style, x, y, width, height, state, area))
1279 if( detail && !strcmp(detail, "cellradio") )
1280 state = GTK_STATE_NORMAL;
1282 draw_part (window, style->black_gc, area, x, y,
1284 draw_part (window, style->dark_gc[state], area, x, y,
1286 draw_part (window, style->mid_gc[state], area, x, y,
1288 draw_part (window, style->light_gc[state], area, x, y,
1290 draw_part (window, style->base_gc[state], area, x, y,
1293 if (shadow == GTK_SHADOW_IN)
1294 draw_part (window, style->text_gc[state], area, x, y,
1301 draw_varrow (GdkWindow * window,
1303 GtkShadowType shadow_type,
1304 GdkRectangle * area,
1305 GtkArrowType arrow_type, gint x, gint y, gint width, gint height)
1308 gint y_start, y_increment;
1312 gdk_gc_set_clip_rectangle (gc, area);
1314 width = width + width % 2 - 1; /* Force odd */
1315 steps = 1 + width / 2;
1316 extra = height - steps;
1318 if (arrow_type == GTK_ARROW_DOWN)
1325 y_start = y + height - 1;
1329 for (i = extra; i < height; i++)
1331 gdk_draw_line (window, gc,
1332 x + (i - extra), y_start + i * y_increment,
1333 x + width - (i - extra) - 1,
1334 y_start + i * y_increment);
1338 gdk_gc_set_clip_rectangle (gc, NULL);
1342 draw_harrow (GdkWindow * window,
1344 GtkShadowType shadow_type,
1345 GdkRectangle * area,
1346 GtkArrowType arrow_type, gint x, gint y, gint width, gint height)
1349 gint x_start, x_increment;
1353 gdk_gc_set_clip_rectangle (gc, area);
1355 height = height + height % 2 - 1; /* Force odd */
1356 steps = 1 + height / 2;
1357 extra = width - steps;
1359 if (arrow_type == GTK_ARROW_RIGHT)
1366 x_start = x + width - 1;
1370 for (i = extra; i < width; i++)
1372 gdk_draw_line (window, gc,
1373 x_start + i * x_increment, y + (i - extra),
1374 x_start + i * x_increment,
1375 y + height - (i - extra) - 1);
1380 gdk_gc_set_clip_rectangle (gc, NULL);
1383 /* This function makes up for some brokeness in gtkrange.c
1384 * where we never get the full arrow of the stepper button
1385 * and the type of button in a single drawing function.
1387 * It doesn't work correctly when the scrollbar is squished
1388 * to the point we don't have room for full-sized steppers.
1391 reverse_engineer_stepper_box (GtkWidget * range,
1392 GtkArrowType arrow_type,
1393 gint * x, gint * y, gint * width, gint * height)
1395 gint slider_width = 14, stepper_size = 14;
1401 gtk_widget_style_get (range,
1402 "slider_width", &slider_width,
1403 "stepper_size", &stepper_size, NULL);
1406 if (arrow_type == GTK_ARROW_UP || arrow_type == GTK_ARROW_DOWN)
1408 box_width = slider_width;
1409 box_height = stepper_size;
1413 box_width = stepper_size;
1414 box_height = slider_width;
1417 *x = *x - (box_width - *width) / 2;
1418 *y = *y - (box_height - *height) / 2;
1420 *height = box_height;
1423 static XpThemeElement
1424 to_xp_arrow (GtkArrowType arrow_type)
1426 XpThemeElement xp_arrow;
1431 xp_arrow = XP_THEME_ELEMENT_ARROW_UP;
1433 case GTK_ARROW_DOWN:
1434 xp_arrow = XP_THEME_ELEMENT_ARROW_DOWN;
1436 case GTK_ARROW_LEFT:
1437 xp_arrow = XP_THEME_ELEMENT_ARROW_LEFT;
1440 xp_arrow = XP_THEME_ELEMENT_ARROW_RIGHT;
1448 draw_arrow (GtkStyle * style,
1451 GtkShadowType shadow,
1452 GdkRectangle * area,
1454 const gchar * detail,
1455 GtkArrowType arrow_type,
1456 gboolean fill, gint x, gint y, gint width, gint height)
1462 name = gtk_widget_get_name (widget);
1464 sanitize_size (window, &width, &height);
1466 if (GTK_IS_ARROW(widget) && is_combo_box_child(widget))
1468 if (combo_box_draw_arrow (style, window, state, area, widget))
1474 if (detail && strcmp (detail, "spinbutton") == 0)
1476 if (xp_theme_is_drawable (XP_THEME_ELEMENT_SPIN_BUTTON_UP))
1483 if( arrow_type == GTK_ARROW_DOWN )
1487 if( state == GTK_STATE_ACTIVE ) {
1491 draw_varrow (window, style->fg_gc[state], shadow, area,
1492 arrow_type, x, y, width, height);
1495 else if (detail && (!strcmp (detail, "vscrollbar")
1496 || !strcmp (detail, "hscrollbar")))
1498 gboolean is_disabled = FALSE;
1500 GtkScrollbar *scrollbar = GTK_SCROLLBAR (widget);
1504 gint box_width = width;
1505 gint box_height = height;
1507 reverse_engineer_stepper_box (widget, arrow_type,
1508 &box_x, &box_y, &box_width,
1511 if (scrollbar->range.adjustment->page_size >=
1512 (scrollbar->range.adjustment->upper -
1513 scrollbar->range.adjustment->lower))
1517 (window, to_xp_arrow (arrow_type), style, box_x, box_y,
1518 box_width, box_height, state, area))
1526 btn_type = DFCS_SCROLLUP;
1528 case GTK_ARROW_DOWN:
1529 btn_type = DFCS_SCROLLDOWN;
1531 case GTK_ARROW_LEFT:
1532 btn_type = DFCS_SCROLLLEFT;
1534 case GTK_ARROW_RIGHT:
1535 btn_type = DFCS_SCROLLRIGHT;
1537 case GTK_ARROW_NONE:
1540 if( state == GTK_STATE_INSENSITIVE )
1541 btn_type |= DFCS_INACTIVE;
1543 sanitize_size (window, &width, &height);
1545 dc = get_window_dc( style, window, state,
1546 box_x, box_y, box_width, box_height, &rect );
1547 DrawFrameControl( dc, &rect, DFC_SCROLL,
1548 btn_type|(shadow == GTK_SHADOW_IN ? (DFCS_PUSHED|DFCS_FLAT) : 0) );
1549 release_window_dc( style, window, state );
1555 /* draw the toolbar chevrons - waiting for GTK 2.4 */
1556 if (name && !strcmp (name, "gtk-toolbar-arrow"))
1559 (window, XP_THEME_ELEMENT_REBAR_CHEVRON, style, x, y,
1560 width, height, state, area))
1563 /* probably a gtk combo box on a toolbar */
1564 else if (0 /* widget->parent && GTK_IS_BUTTON
1565 (widget->parent) */ )
1568 (window, XP_THEME_ELEMENT_COMBOBUTTON, style, x - 3,
1569 widget->allocation.y + 1, width + 5,
1570 widget->allocation.height - 4, state, area))
1574 if (arrow_type == GTK_ARROW_UP || arrow_type == GTK_ARROW_DOWN)
1576 x += (width - 7) / 2;
1577 y += (height - 5) / 2;
1579 draw_varrow (window, style->fg_gc[state], shadow, area,
1580 arrow_type, x, y, 7, 5);
1584 x += (width - 5) / 2;
1585 y += (height - 7) / 2;
1587 draw_harrow (window, style->fg_gc[state], shadow, area,
1588 arrow_type, x, y, 5, 7);
1594 option_menu_get_props (GtkWidget * widget,
1595 GtkRequisition * indicator_size,
1596 GtkBorder * indicator_spacing)
1598 GtkRequisition *tmp_size = NULL;
1599 GtkBorder *tmp_spacing = NULL;
1602 gtk_widget_style_get (widget,
1603 "indicator_size", &tmp_size,
1604 "indicator_spacing", &tmp_spacing, NULL);
1608 *indicator_size = *tmp_size;
1609 gtk_requisition_free (tmp_size);
1612 *indicator_size = default_option_indicator_size;
1616 *indicator_spacing = *tmp_spacing;
1617 gtk_border_free (tmp_spacing);
1620 *indicator_spacing = default_option_indicator_spacing;
1624 is_toolbar_child (GtkWidget * wid)
1628 if (GTK_IS_TOOLBAR (wid) || GTK_IS_HANDLE_BOX (wid))
1638 is_menu_tool_button_child (GtkWidget * wid)
1642 if (GTK_IS_MENU_TOOL_BUTTON (wid) )
1650 HDC get_window_dc(GtkStyle * style, GdkWindow * window, GtkStateType state_type, gint x, gint y, gint width, gint height, RECT *rect)
1653 GdkDrawable *drawable;
1655 if (!GDK_IS_WINDOW (window))
1663 gdk_window_get_internal_paint_info (window, &drawable, &xoff, &yoff);
1666 rect->left = x - xoff;
1667 rect->top = y - yoff;
1668 rect->right = rect->left + width;
1669 rect->bottom = rect->top + height;
1671 return gdk_win32_hdc_get (drawable, style->dark_gc[state_type], 0);
1674 void release_window_dc(GtkStyle * style, GdkWindow * window, GtkStateType state_type)
1676 GdkDrawable *drawable;
1678 if (!GDK_IS_WINDOW (window))
1684 gdk_window_get_internal_paint_info (window, &drawable, NULL, NULL);
1687 gdk_win32_hdc_release (drawable, style->dark_gc[state_type], 0);
1690 static HPEN get_light_pen()
1692 if( ! g_light_pen ) {
1693 g_light_pen = CreatePen( PS_SOLID|PS_INSIDEFRAME, 1, GetSysColor(COLOR_BTNHIGHLIGHT) );
1698 static HPEN get_dark_pen()
1700 if( ! g_dark_pen ) {
1701 g_dark_pen = CreatePen( PS_SOLID|PS_INSIDEFRAME, 1, GetSysColor(COLOR_BTNSHADOW) );
1707 draw_3d_border( HDC hdc, RECT* rc, gboolean sunken )
1713 pen1 = get_dark_pen();
1714 pen2 = get_light_pen();
1717 pen1 = get_light_pen();
1718 pen2 = get_dark_pen();
1721 MoveToEx( hdc, rc->left, rc->bottom - 1, NULL);
1723 old_pen = SelectObject( hdc, pen1 );
1724 LineTo( hdc, rc->left, rc->top );
1725 LineTo( hdc, rc->right-1, rc->top );
1726 SelectObject( hdc, old_pen );
1728 old_pen = SelectObject( hdc, pen2 );
1729 LineTo( hdc, rc->right-1, rc->bottom-1 );
1730 LineTo( hdc, rc->left, rc->bottom-1 );
1731 SelectObject( hdc, old_pen );
1735 draw_menu_item(GdkWindow* window, GtkWidget* widget, GtkStyle* style,
1736 gint x, gint y, gint width, gint height,
1737 GtkStateType state_type, GdkRectangle* area )
1744 if( (parent = gtk_widget_get_parent(widget))
1745 && GTK_IS_MENU_BAR(parent)
1746 && !xp_theme_is_active() )
1748 bar = GTK_MENU_SHELL(parent);
1750 dc = get_window_dc( style, window, state_type, x, y, width, height, &rect );
1751 if( state_type == GTK_STATE_PRELIGHT ){
1752 draw_3d_border( dc, &rect, bar->active );
1754 release_window_dc( style, window, state_type );
1761 get_dither_brush( void )
1764 HBITMAP pattern_bmp;
1767 if( g_dither_brush )
1768 return g_dither_brush;
1769 for ( i = 0; i < 8; i++ )
1770 pattern[i] = (WORD)(0x5555 << (i & 1));
1771 pattern_bmp = CreateBitmap(8, 8, 1, 1, &pattern);
1773 g_dither_brush = CreatePatternBrush(pattern_bmp);
1774 DeleteObject(pattern_bmp);
1776 return g_dither_brush;
1780 draw_tool_button(GdkWindow* window, GtkWidget* widget, GtkStyle* style,
1781 gint x, gint y, gint width, gint height,
1782 GtkStateType state_type, GdkRectangle* area )
1786 gboolean is_toggled = FALSE;
1788 if ( xp_theme_is_active() ) {
1789 return (xp_theme_draw (window, XP_THEME_ELEMENT_TOOLBAR_BUTTON, style,
1790 x, y, width, height, state_type, area) );
1793 if( GTK_IS_TOGGLE_BUTTON(widget) ){
1794 if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) ) {
1799 if( state_type != GTK_STATE_PRELIGHT
1800 && state_type != GTK_STATE_ACTIVE && !is_toggled )
1803 dc = get_window_dc( style, window, state_type, x, y, width, height, &rect );
1804 if( state_type == GTK_STATE_PRELIGHT ){
1806 FillRect( dc, &rect, GetSysColorBrush(COLOR_BTNFACE));
1808 draw_3d_border( dc, &rect, is_toggled);
1810 else if ( state_type == GTK_STATE_ACTIVE ){
1811 if( is_toggled && ! is_menu_tool_button_child(widget->parent) ){
1812 SetTextColor( dc, GetSysColor(COLOR_3DHILIGHT) );
1813 SetBkColor( dc, GetSysColor(COLOR_BTNFACE) );
1814 FillRect( dc, &rect, get_dither_brush() );
1816 draw_3d_border( dc, &rect, TRUE );
1818 release_window_dc( style, window, state_type );
1823 draw_push_button( GdkWindow* window, GtkWidget* widget, GtkStyle* style, gint x, gint y,
1824 gint width, gint height,
1825 GtkStateType state_type, gboolean is_default )
1830 dc = get_window_dc( style, window, state_type,
1831 x, y, width, height, &rect );
1832 if( GTK_IS_TOGGLE_BUTTON(widget) ) {
1833 if( state_type == GTK_STATE_PRELIGHT &&
1834 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) )
1836 state_type = GTK_STATE_ACTIVE;
1840 if( state_type == GTK_STATE_ACTIVE ) {
1841 if( GTK_IS_TOGGLE_BUTTON(widget) ) {
1842 DrawEdge( dc, &rect, EDGE_SUNKEN, BF_RECT|BF_ADJUST);
1843 SetTextColor( dc, GetSysColor(COLOR_3DHILIGHT) );
1844 SetBkColor( dc, GetSysColor(COLOR_BTNFACE) );
1845 FillRect( dc, &rect, get_dither_brush() );
1848 FrameRect( dc, &rect, GetSysColorBrush(COLOR_WINDOWFRAME) );
1849 InflateRect( &rect, -1, -1 );
1850 FrameRect( dc, &rect, GetSysColorBrush(COLOR_BTNSHADOW) );
1851 InflateRect( &rect, -1, -1 );
1852 FillRect( dc, &rect, GetSysColorBrush(COLOR_BTNFACE) );
1856 if( is_default || GTK_WIDGET_HAS_FOCUS(widget) ) {
1857 FrameRect( dc, &rect, GetSysColorBrush(COLOR_WINDOWFRAME) );
1858 InflateRect( &rect, -1, -1 );
1860 DrawFrameControl( dc, &rect, DFC_BUTTON, DFCS_BUTTONPUSH );
1862 release_window_dc(style, window, state_type);
1866 draw_box (GtkStyle * style,
1868 GtkStateType state_type,
1869 GtkShadowType shadow_type,
1870 GdkRectangle * area,
1872 const gchar * detail, gint x, gint y, gint width, gint height)
1874 if (is_combo_box_child (widget) && detail && !strcmp (detail, "button")) {
1879 dc = get_window_dc (style, window, state_type, x, y, width - cx, height, &rect);
1880 FillRect (dc, &rect, GetSysColorBrush(COLOR_WINDOW));
1881 release_window_dc (style, window, state_type);
1883 cx = 2 * GetSystemMetrics (SM_CXEDGE) + 16; /* TODO evaluate arrow width */
1887 if (xp_theme_is_active () && xp_theme_draw (
1888 window, XP_THEME_ELEMENT_COMBOBUTTON, style,
1889 x, y, width, height, state_type, area))
1894 (!strcmp (detail, "button") || !strcmp (detail, "buttondefault")))
1896 if (GTK_IS_TREE_VIEW (widget->parent)
1897 || GTK_IS_CLIST (widget->parent))
1900 (window, XP_THEME_ELEMENT_LIST_HEADER, style, x, y,
1901 width, height, state_type, area))
1906 dc = get_window_dc( style, window, state_type, x, y, width, height, &rect );
1908 DrawFrameControl( dc, &rect, DFC_BUTTON, DFCS_BUTTONPUSH |
1909 (state_type == GTK_STATE_ACTIVE ? (DFCS_PUSHED|DFCS_FLAT) : 0 ) );
1910 release_window_dc( style, window, state_type );
1913 else if (is_toolbar_child (widget->parent)
1914 || (GTK_RELIEF_NONE == gtk_button_get_relief(GTK_BUTTON(widget)) ) )
1916 if( draw_tool_button( window, widget, style, x, y,
1917 width, height, state_type, area ) )
1924 gboolean is_default = GTK_WIDGET_HAS_DEFAULT(widget);
1927 is_default ? XP_THEME_ELEMENT_DEFAULT_BUTTON :
1928 XP_THEME_ELEMENT_BUTTON, style, x, y, width, height,
1933 draw_push_button( window, widget, style,
1934 x, y, width, height, state_type, is_default );
1939 else if (detail && !strcmp (detail, "spinbutton"))
1941 if (xp_theme_is_drawable (XP_THEME_ELEMENT_SPIN_BUTTON_UP))
1946 else if (detail && (!strcmp (detail, "spinbutton_up")
1947 || !strcmp (detail, "spinbutton_down")))
1949 if ( ! xp_theme_draw ( window,
1950 (!strcmp (detail, "spinbutton_up"))
1951 ? XP_THEME_ELEMENT_SPIN_BUTTON_UP
1952 : XP_THEME_ELEMENT_SPIN_BUTTON_DOWN,
1953 style, x, y, width, height, state_type, area))
1958 dc = get_window_dc( style, window, state_type,
1959 x, y, width, height, &rect );
1960 DrawEdge( dc, &rect,
1961 state_type == GTK_STATE_ACTIVE ? EDGE_SUNKEN : EDGE_RAISED, BF_RECT );
1962 release_window_dc( style, window, state_type );
1966 else if (detail && !strcmp (detail, "slider"))
1968 if (GTK_IS_SCROLLBAR (widget))
1970 GtkScrollbar *scrollbar = GTK_SCROLLBAR (widget);
1971 gboolean is_v = GTK_IS_VSCROLLBAR (widget);
1973 if (xp_theme_draw (window,
1975 ? XP_THEME_ELEMENT_SCROLLBAR_V
1976 : XP_THEME_ELEMENT_SCROLLBAR_H,
1977 style, x, y, width, height, state_type,
1980 XpThemeElement gripper =
1981 (is_v ? XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V :
1982 XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H);
1984 /* Do not display grippers on tiny scroll bars,
1985 the limit imposed is rather arbitrary, perhaps
1986 we can fetch the gripper geometry from
1987 somewhere and use that... */
1989 XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H
1992 XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V
1998 xp_theme_draw (window, gripper, style, x, y,
1999 width, height, state_type, area);
2004 if (scrollbar->range.adjustment->page_size >=
2005 (scrollbar->range.adjustment->upper -
2006 scrollbar->range.adjustment->lower))
2011 else if (detail && !strcmp (detail, "bar"))
2013 if (widget && GTK_IS_PROGRESS_BAR (widget))
2015 GtkProgressBar *progress_bar = GTK_PROGRESS_BAR (widget);
2016 XpThemeElement xp_progress_bar =
2017 map_gtk_progress_bar_to_xp (progress_bar, FALSE);
2019 if (xp_theme_draw (window, xp_progress_bar, style, x, y,
2020 width, height, state_type, area))
2025 shadow_type = GTK_SHADOW_NONE;
2028 else if (detail && strcmp (detail, "menuitem") == 0)
2030 shadow_type = GTK_SHADOW_NONE;
2031 if( draw_menu_item(window, widget, style,
2032 x, y, width, height, state_type, area ) )
2037 else if (detail && !strcmp (detail, "trough"))
2039 if (widget && GTK_IS_PROGRESS_BAR (widget))
2041 GtkProgressBar *progress_bar = GTK_PROGRESS_BAR (widget);
2042 XpThemeElement xp_progress_bar =
2043 map_gtk_progress_bar_to_xp (progress_bar, TRUE);
2045 (window, xp_progress_bar, style, x, y, width, height,
2052 /* Blank in classic Windows */
2055 else if (widget && GTK_IS_SCROLLBAR (widget))
2057 gboolean is_vertical = GTK_IS_VSCROLLBAR (widget);
2059 if (xp_theme_draw (window,
2061 ? XP_THEME_ELEMENT_TROUGH_V
2062 : XP_THEME_ELEMENT_TROUGH_H,
2064 x, y, width, height, state_type, area))
2073 sanitize_size (window, &width, &height);
2074 dc = get_window_dc( style, window, state_type, x, y, width, height, &rect );
2075 SetTextColor( dc, GetSysColor(COLOR_3DHILIGHT) );
2076 SetBkColor( dc, GetSysColor(COLOR_BTNFACE) );
2077 FillRect( dc, &rect, get_dither_brush() );
2078 release_window_dc( style, window, state_type );
2083 else if (widget && GTK_IS_SCALE (widget))
2085 gboolean is_vertical = GTK_IS_VSCALE (widget);
2087 if (!xp_theme_is_active ())
2089 parent_class->draw_box (style, window, state_type,
2090 GTK_SHADOW_NONE, area,
2091 widget, detail, x, y,
2098 (window, XP_THEME_ELEMENT_SCALE_TROUGH_V,
2099 style, (2 * x + width) / 2, y, 2, height,
2103 parent_class->draw_box (style, window, state_type,
2104 GTK_SHADOW_ETCHED_IN,
2106 (2 * x + width) / 2, y, 1,
2112 (window, XP_THEME_ELEMENT_SCALE_TROUGH_H,
2113 style, x, (2 * y + height) / 2, width, 2,
2117 parent_class->draw_box (style, window, state_type,
2118 GTK_SHADOW_ETCHED_IN,
2119 area, NULL, NULL, x,
2120 (2 * y + height) / 2,
2126 else if (detail && strcmp (detail, "optionmenu") == 0)
2128 if (xp_theme_draw (window, XP_THEME_ELEMENT_EDIT_TEXT,
2129 style, x, y, width, height, state_type, area))
2135 && (strcmp (detail, "vscrollbar") == 0
2136 || strcmp (detail, "hscrollbar") == 0))
2141 && (strcmp (detail, "handlebox_bin") == 0
2142 || strcmp (detail, "toolbar") == 0
2143 || strcmp (detail, "menubar") == 0))
2145 sanitize_size( window, &width, &height );
2146 if (xp_theme_draw (window, XP_THEME_ELEMENT_REBAR,
2147 style, x, y, width, height, state_type, area))
2152 else if (detail && (!strcmp (detail, "handlebox"))) /* grip */
2154 if( !xp_theme_is_active() ) {
2158 else if (detail && !strcmp (detail, "notebook") && GTK_IS_NOTEBOOK (widget))
2160 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2162 if (xp_theme_draw (window, XP_THEME_ELEMENT_TAB_PANE, style,
2163 x, y, width, height, state_type, area))
2171 const gchar *name = gtk_widget_get_name (widget);
2173 if (name && !strcmp (name, "gtk-tooltips"))
2176 (window, XP_THEME_ELEMENT_TOOLTIP, style, x, y, width,
2177 height, state_type, area))
2187 hdc = get_window_dc(style, window, state_type, x, y, width, height, &rect);
2189 brush = GetSysColorBrush (COLOR_3DDKSHADOW);
2191 FrameRect (hdc, &rect, brush);
2192 InflateRect (&rect, -1, -1);
2193 FillRect (hdc, &rect,
2194 (HBRUSH) (COLOR_INFOBK + 1));
2196 release_window_dc (style, window, state_type);
2204 parent_class->draw_box (style, window, state_type, shadow_type, area,
2205 widget, detail, x, y, width, height);
2207 if (detail && strcmp (detail, "optionmenu") == 0)
2209 GtkRequisition indicator_size;
2210 GtkBorder indicator_spacing;
2213 option_menu_get_props (widget, &indicator_size,
2214 &indicator_spacing);
2216 sanitize_size (window, &width, &height);
2218 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
2220 x + indicator_size.width + indicator_spacing.left +
2221 indicator_spacing.right;
2224 x + width - (indicator_size.width +
2225 indicator_spacing.left +
2226 indicator_spacing.right) - style->xthickness;
2228 parent_class->draw_vline (style, window, state_type, area, widget,
2230 y + style->ythickness + 1,
2231 y + height - style->ythickness - 3,
2237 draw_tab (GtkStyle * style,
2240 GtkShadowType shadow,
2241 GdkRectangle * area,
2243 const gchar * detail, gint x, gint y, gint width, gint height)
2245 GtkRequisition indicator_size;
2246 GtkBorder indicator_spacing;
2250 g_return_if_fail (style != NULL);
2251 g_return_if_fail (window != NULL);
2253 if (detail && !strcmp (detail, "optionmenutab"))
2255 if (xp_theme_draw (window, XP_THEME_ELEMENT_COMBOBUTTON,
2256 style, x - 5, widget->allocation.y + 1,
2257 width + 10, widget->allocation.height - 2,
2264 option_menu_get_props (widget, &indicator_size, &indicator_spacing);
2266 x += (width - indicator_size.width) / 2;
2267 arrow_height = (indicator_size.width + 1) / 2;
2269 y += (height - arrow_height) / 2;
2271 draw_varrow (window, style->black_gc, shadow, area, GTK_ARROW_DOWN,
2272 x, y, indicator_size.width, arrow_height);
2275 /* Draw classic Windows tab - thanks Mozilla!
2276 (no system API for this, but DrawEdge can draw all the parts of a tab) */
2277 static void DrawTab(HDC hdc, const RECT R, gint32 aPosition, gboolean aSelected,
2278 gboolean aDrawLeft, gboolean aDrawRight)
2280 gint32 leftFlag, topFlag, rightFlag, lightFlag, shadeFlag;
2281 RECT topRect, sideRect, bottomRect, lightRect, shadeRect;
2282 gint32 selectedOffset, lOffset, rOffset;
2284 selectedOffset = aSelected ? 1 : 0;
2285 lOffset = aDrawLeft ? 2 : 0;
2286 rOffset = aDrawRight ? 2 : 0;
2288 /* Get info for tab orientation/position (Left, Top, Right, Bottom) */
2292 leftFlag = BF_TOP; topFlag = BF_LEFT;
2293 rightFlag = BF_BOTTOM;
2294 lightFlag = BF_DIAGONAL_ENDTOPRIGHT;
2295 shadeFlag = BF_DIAGONAL_ENDBOTTOMRIGHT;
2297 SetRect(&topRect, R.left, R.top+lOffset, R.right, R.bottom-rOffset);
2298 SetRect(&sideRect, R.left+2, R.top, R.right-2+selectedOffset, R.bottom);
2299 SetRect(&bottomRect, R.right-2, R.top, R.right, R.bottom);
2300 SetRect(&lightRect, R.left, R.top, R.left+3, R.top+3);
2301 SetRect(&shadeRect, R.left+1, R.bottom-2, R.left+2, R.bottom-1);
2305 leftFlag = BF_LEFT; topFlag = BF_TOP;
2306 rightFlag = BF_RIGHT;
2307 lightFlag = BF_DIAGONAL_ENDTOPRIGHT;
2308 shadeFlag = BF_DIAGONAL_ENDBOTTOMRIGHT;
2310 SetRect(&topRect, R.left+lOffset, R.top, R.right-rOffset, R.bottom);
2311 SetRect(&sideRect, R.left, R.top+2, R.right, R.bottom-1+selectedOffset);
2312 SetRect(&bottomRect, R.left, R.bottom-1, R.right, R.bottom);
2313 SetRect(&lightRect, R.left, R.top, R.left+3, R.top+3);
2314 SetRect(&shadeRect, R.right-2, R.top+1, R.right-1, R.top+2);
2317 leftFlag = BF_TOP; topFlag = BF_RIGHT;
2318 rightFlag = BF_BOTTOM;
2319 lightFlag = BF_DIAGONAL_ENDTOPLEFT;
2320 shadeFlag = BF_DIAGONAL_ENDBOTTOMLEFT;
2322 SetRect(&topRect, R.left, R.top+lOffset, R.right, R.bottom-rOffset);
2323 SetRect(&sideRect, R.left+2-selectedOffset, R.top, R.right-2, R.bottom);
2324 SetRect(&bottomRect, R.left, R.top, R.left+2, R.bottom);
2325 SetRect(&lightRect, R.right-3, R.top, R.right-1, R.top+2);
2326 SetRect(&shadeRect, R.right-2, R.bottom-3, R.right, R.bottom-1);
2330 leftFlag = BF_LEFT; topFlag = BF_BOTTOM;
2331 rightFlag = BF_RIGHT;
2332 lightFlag = BF_DIAGONAL_ENDTOPLEFT;
2333 shadeFlag = BF_DIAGONAL_ENDBOTTOMLEFT;
2335 SetRect(&topRect, R.left+lOffset, R.top, R.right-rOffset, R.bottom);
2336 SetRect(&sideRect, R.left, R.top+2-selectedOffset, R.right, R.bottom-2);
2337 SetRect(&bottomRect, R.left, R.top, R.right, R.top+2);
2338 SetRect(&lightRect, R.left, R.bottom-3, R.left+2, R.bottom-1);
2339 SetRect(&shadeRect, R.right-2, R.bottom-3, R.right, R.bottom-1);
2343 g_return_if_reached();
2347 FillRect(hdc, &R, (HBRUSH) (COLOR_3DFACE+1) );
2350 DrawEdge(hdc, &topRect, EDGE_RAISED, BF_SOFT | topFlag);
2354 DrawEdge(hdc, &bottomRect, EDGE_RAISED, BF_SOFT | topFlag);
2361 DrawEdge(hdc, &sideRect, EDGE_RAISED, BF_SOFT | leftFlag | rightFlag);
2363 /* Tab Diagonal Corners */
2365 DrawEdge(hdc, &lightRect, EDGE_RAISED, BF_SOFT | lightFlag);
2368 DrawEdge(hdc, &shadeRect, EDGE_RAISED, BF_SOFT | shadeFlag);
2372 draw_themed_tab_button (GtkStyle *style,
2374 GtkStateType state_type,
2375 GtkNotebook *notebook,
2377 gint width, gint height,
2380 GdkPixmap *pixmap = NULL;
2381 gint border_width = gtk_container_get_border_width (GTK_CONTAINER (notebook));
2382 GtkWidget *widget = GTK_WIDGET (notebook);
2383 GdkRectangle draw_rect, clip_rect;
2384 GdkPixbufRotation rotation = GDK_PIXBUF_ROTATE_NONE;
2386 if (gap_side == GTK_POS_TOP)
2390 if (state_type == GTK_STATE_NORMAL)
2394 draw_rect.width = width + 2;
2395 draw_rect.height = height;
2397 clip_rect = draw_rect;
2402 draw_rect.x = x + 2;
2404 draw_rect.width = width - 2;
2405 draw_rect.height = height - 2;
2406 clip_rect = draw_rect;
2409 /* If we are currently drawing the right-most tab, and if that tab is the selected tab... */
2410 widget_right = widget->allocation.x + widget->allocation.width - border_width - 2;
2411 if (draw_rect.x + draw_rect.width >= widget_right)
2413 draw_rect.width = clip_rect.width = widget_right - draw_rect.x;
2416 if (gap_side == GTK_POS_BOTTOM)
2420 if (state_type == GTK_STATE_NORMAL)
2424 draw_rect.width = width + 2;
2425 draw_rect.height = height;
2427 clip_rect = draw_rect;
2431 draw_rect.x = x + 2;
2432 draw_rect.y = y + 2;
2433 draw_rect.width = width - 2;
2434 draw_rect.height = height - 2;
2435 clip_rect = draw_rect;
2438 /* If we are currently drawing the right-most tab, and if that tab is the selected tab... */
2439 widget_right = widget->allocation.x + widget->allocation.width - border_width - 2;
2440 if (draw_rect.x + draw_rect.width >= widget_right)
2442 draw_rect.width = clip_rect.width = widget_right - draw_rect.x;
2445 rotation = GDK_PIXBUF_ROTATE_UPSIDEDOWN;
2447 else if (gap_side == GTK_POS_LEFT)
2451 if (state_type == GTK_STATE_NORMAL)
2455 draw_rect.width = width;
2456 draw_rect.height = height + 2;
2458 clip_rect = draw_rect;
2464 draw_rect.y = y + 2;
2465 draw_rect.width = width - 2;
2466 draw_rect.height = height - 2;
2467 clip_rect = draw_rect;
2470 /* If we are currently drawing the bottom-most tab, and if that tab is the selected tab... */
2471 widget_bottom = widget->allocation.x + widget->allocation.height - border_width - 2;
2472 if (draw_rect.y + draw_rect.height >= widget_bottom)
2474 draw_rect.height = clip_rect.height = widget_bottom - draw_rect.y;
2477 rotation = GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE;
2479 else if (gap_side == GTK_POS_RIGHT)
2483 if (state_type == GTK_STATE_NORMAL)
2485 draw_rect.x = x + 1;
2487 draw_rect.width = width;
2488 draw_rect.height = height + 2;
2490 clip_rect = draw_rect;
2495 draw_rect.x = x + 2;
2496 draw_rect.y = y + 2;
2497 draw_rect.width = width - 2;
2498 draw_rect.height = height - 2;
2499 clip_rect = draw_rect;
2502 /* If we are currently drawing the bottom-most tab, and if that tab is the selected tab... */
2503 widget_bottom = widget->allocation.x + widget->allocation.height - border_width - 2;
2504 if (draw_rect.y + draw_rect.height >= widget_bottom)
2506 draw_rect.height = clip_rect.height = widget_bottom - draw_rect.y;
2509 rotation = GDK_PIXBUF_ROTATE_CLOCKWISE;
2512 if (gap_side == GTK_POS_TOP)
2514 if (!xp_theme_draw (window, XP_THEME_ELEMENT_TAB_ITEM, style,
2515 draw_rect.x, draw_rect.y,
2516 draw_rect.width,draw_rect.height,
2517 state_type, &clip_rect))
2527 if (gap_side == GTK_POS_LEFT || gap_side == GTK_POS_RIGHT)
2529 pixmap = gdk_pixmap_new (window, clip_rect.height, clip_rect.width, -1);
2530 if (!xp_theme_draw (pixmap, XP_THEME_ELEMENT_TAB_ITEM, style,
2531 draw_rect.y - clip_rect.y, draw_rect.x - clip_rect.x,
2532 draw_rect.height, draw_rect.width, state_type, 0))
2534 g_object_unref (pixmap);
2538 pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap, NULL, 0, 0, 0, 0,
2539 clip_rect.height, clip_rect.width);
2540 g_object_unref (pixmap);
2544 pixmap = gdk_pixmap_new (window, clip_rect.width, clip_rect.height, -1);
2545 if (!xp_theme_draw (pixmap, XP_THEME_ELEMENT_TAB_ITEM, style,
2546 draw_rect.x - clip_rect.x, draw_rect.y - clip_rect.y,
2547 draw_rect.width, draw_rect.height, state_type, 0))
2549 g_object_unref (pixmap);
2553 pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap, NULL, 0, 0, 0, 0,
2554 clip_rect.width, clip_rect.height);
2555 g_object_unref (pixmap);
2558 rotated = gdk_pixbuf_rotate_simple (pixbuf, rotation);
2559 g_object_unref (pixbuf);
2562 // XXX - This is really hacky and evil. When we're drawing the left-most tab
2563 // while it is active on a bottom-oriented notebook, there is one white
2564 // pixel at the top. There may be a better solution than this if someone
2565 // has time to discover it.
2566 if (gap_side == GTK_POS_BOTTOM && state_type == GTK_STATE_NORMAL && x == widget->allocation.x)
2568 int rowstride = gdk_pixbuf_get_rowstride (pixbuf);
2569 int n_channels = gdk_pixbuf_get_n_channels (pixbuf);
2572 guchar *pixels = gdk_pixbuf_get_pixels (pixbuf);
2573 guchar *p = pixels + rowstride;
2575 for (psub = 0; psub < n_channels; psub++)
2577 pixels[psub] = p[psub];
2581 gdk_draw_pixbuf (window, NULL, pixbuf, 0, 0, clip_rect.x, clip_rect.y,
2582 clip_rect.width, clip_rect.height, GDK_RGB_DITHER_NONE, 0, 0);
2583 g_object_unref (pixbuf);
2590 draw_tab_button (GtkStyle *style,
2592 GtkStateType state_type,
2593 GtkShadowType shadow_type,
2596 const gchar *detail,
2598 gint width, gint height,
2601 if (gap_side == GTK_POS_TOP || gap_side == GTK_POS_BOTTOM)
2603 /* experimental tab-drawing code from mozilla */
2608 dc = get_window_dc (style, window, state_type, x, y, width, height, &rect);
2610 if (gap_side == GTK_POS_TOP)
2612 else if (gap_side == GTK_POS_BOTTOM)
2613 aPosition = BF_BOTTOM;
2614 else if (gap_side == GTK_POS_LEFT)
2615 aPosition = BF_LEFT;
2617 aPosition = BF_RIGHT;
2619 if(state_type == GTK_STATE_PRELIGHT)
2620 state_type = GTK_STATE_NORMAL;
2622 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
2624 DrawTab (dc, rect, aPosition,
2625 state_type != GTK_STATE_PRELIGHT,
2626 (gap_side != GTK_POS_LEFT),
2627 (gap_side != GTK_POS_RIGHT));
2629 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
2631 release_window_dc (style, window, state_type);
2639 draw_extension (GtkStyle *style,
2641 GtkStateType state_type,
2642 GtkShadowType shadow_type,
2645 const gchar *detail,
2647 gint width, gint height,
2648 GtkPositionType gap_side)
2650 if (widget && GTK_IS_NOTEBOOK (widget) && detail && !strcmp (detail, "tab"))
2652 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2654 /* Why this differs from gap_side, I have no idea.. */
2655 int real_gap_side = gtk_notebook_get_tab_pos (notebook);
2657 if (!draw_themed_tab_button (style, window, state_type,
2658 GTK_NOTEBOOK (widget), x, y,
2659 width, height, real_gap_side))
2661 if (!draw_tab_button (style, window, state_type,
2662 shadow_type, area, widget,
2664 x, y, width, height, real_gap_side))
2666 parent_class->draw_extension (style, window, state_type,
2667 shadow_type, area, widget, detail,
2668 x, y, width, height, real_gap_side);
2675 draw_box_gap (GtkStyle * style, GdkWindow * window, GtkStateType state_type,
2676 GtkShadowType shadow_type, GdkRectangle * area,
2677 GtkWidget * widget, const gchar * detail, gint x,
2678 gint y, gint width, gint height, GtkPositionType gap_side,
2679 gint gap_x, gint gap_width)
2681 if (GTK_IS_NOTEBOOK (widget) && detail && !strcmp (detail, "notebook"))
2683 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2684 int side = gtk_notebook_get_tab_pos (notebook);
2685 int x2 = x, y2 = y, w2 = width, h2 = height;
2687 if (side == GTK_POS_TOP)
2690 y2 = y - notebook->tab_vborder;
2692 h2 = height + notebook->tab_vborder * 2;
2694 else if (side == GTK_POS_BOTTOM)
2699 h2 = height + notebook->tab_vborder * 2;
2701 else if (side == GTK_POS_LEFT)
2703 x2 = x - notebook->tab_hborder;
2705 w2 = width + notebook->tab_hborder;
2708 else if (side == GTK_POS_RIGHT)
2712 w2 = width + notebook->tab_hborder * 2;
2716 if (xp_theme_draw (window, XP_THEME_ELEMENT_TAB_PANE, style,
2717 x2, y2, w2, h2, state_type, area))
2723 parent_class->draw_box_gap (style, window, state_type, shadow_type,
2724 area, widget, detail, x, y, width, height,
2725 gap_side, gap_x, gap_width);
2728 static gboolean is_popup_window_child( GtkWidget* widget )
2731 GtkWindowType type = -1;
2733 top = gtk_widget_get_toplevel( widget );
2734 if( top && GTK_IS_WINDOW(top) ) {
2735 g_object_get(top, "type", &type, NULL );
2736 if( type == GTK_WINDOW_POPUP ) { /* Hack for combo boxes */
2744 draw_flat_box (GtkStyle * style, GdkWindow * window,
2745 GtkStateType state_type, GtkShadowType shadow_type,
2746 GdkRectangle * area, GtkWidget * widget,
2747 const gchar * detail, gint x, gint y, gint width, gint height)
2750 if ( !strcmp (detail, "checkbutton") )
2752 if (state_type == GTK_STATE_PRELIGHT)
2759 parent_class->draw_flat_box (style, window, state_type, shadow_type,
2760 area, widget, detail, x, y, width, height);
2764 draw_menu_border ( GdkWindow* win, GtkStyle* style,
2765 gint x, gint y, gint width, gint height )
2770 dc = get_window_dc (style, win, GTK_STATE_NORMAL, x, y, width, height, &rect );
2773 if( xp_theme_is_active() ) {
2774 FrameRect( dc, &rect, GetSysColorBrush(COLOR_3DSHADOW) );
2777 DrawEdge( dc, &rect, EDGE_RAISED, BF_RECT );
2779 release_window_dc( style, win, GTK_STATE_NORMAL );
2784 draw_shadow (GtkStyle * style,
2786 GtkStateType state_type,
2787 GtkShadowType shadow_type,
2788 GdkRectangle * area,
2790 const gchar * detail, gint x, gint y, gint width, gint height)
2792 gboolean is_handlebox;
2793 gboolean is_toolbar;
2795 if( detail && !strcmp( detail, "frame") )
2799 dc = get_window_dc( style, window, state_type, x, y, width, height, &rect );
2800 if( is_popup_window_child(widget) ) {
2801 FrameRect( dc, &rect, GetSysColorBrush( COLOR_WINDOWFRAME ) );
2804 switch( shadow_type ){
2806 draw_3d_border(dc, &rect, TRUE);
2808 case GTK_SHADOW_OUT:
2809 draw_3d_border(dc, &rect, FALSE);
2811 case GTK_SHADOW_ETCHED_IN:
2812 draw_3d_border(dc, &rect, TRUE);
2813 InflateRect( &rect, -1, -1 );
2814 draw_3d_border(dc, &rect, FALSE);
2816 case GTK_SHADOW_ETCHED_OUT:
2817 draw_3d_border(dc, &rect, FALSE);
2818 InflateRect( &rect, -1, -1 );
2819 draw_3d_border(dc, &rect, TRUE);
2821 case GTK_SHADOW_NONE:
2825 release_window_dc( style, window, state_type );
2828 if (detail && (!strcmp (detail, "entry") || !strcmp (detail, "combobox")) )
2830 if( shadow_type != GTK_SHADOW_IN )
2833 if ( !xp_theme_draw (window, XP_THEME_ELEMENT_EDIT_TEXT, style,
2834 x, y, width, height, state_type, area))
2839 dc = get_window_dc (style, window, state_type,
2840 x, y, width, height, &rect);
2841 DrawEdge (dc, &rect, EDGE_SUNKEN, BF_RECT);
2842 release_window_dc (style, window, state_type);
2848 if (detail && !strcmp (detail, "scrolled_window") &&
2849 xp_theme_draw (window, XP_THEME_ELEMENT_EDIT_TEXT, style,
2850 x, y, width, height, state_type, area))
2853 if (detail && !strcmp (detail, "spinbutton"))
2856 if (detail && !strcmp (detail, "menu"))
2858 if ( draw_menu_border ( window, style, x, y, width, height ) ) {
2863 if (detail && !strcmp (detail, "handlebox"))
2866 is_handlebox = (detail && !strcmp (detail, "handlebox_bin"));
2867 is_toolbar = (detail && (!strcmp (detail, "toolbar") || !strcmp(detail, "menubar")));
2869 if ( is_toolbar || is_handlebox )
2871 if( shadow_type == GTK_SHADOW_NONE )
2877 HGDIOBJ old_pen = NULL;
2878 GtkPositionType pos;
2880 sanitize_size (window, &width, &height);
2882 if( is_handlebox ) {
2883 pos = gtk_handle_box_get_handle_position(GTK_HANDLE_BOX(widget));
2885 If the handle box is at left side,
2886 we shouldn't draw its right border.
2887 The same holds true for top, right, and bottom.
2891 pos = GTK_POS_RIGHT; break;
2893 pos = GTK_POS_LEFT; break;
2895 pos = GTK_POS_BOTTOM; break;
2896 case GTK_POS_BOTTOM:
2897 pos = GTK_POS_TOP; break;
2901 GtkWidget* parent = gtk_widget_get_parent(widget);
2902 /* Dirty hack for toolbars contained in handle boxes */
2903 if( GTK_IS_HANDLE_BOX( parent ) ) {
2904 pos = gtk_handle_box_get_handle_position( GTK_HANDLE_BOX( parent ) );
2909 Make pos != all legal enum vaules of GtkPositionType.
2910 So every border will be draw.
2912 pos = (GtkPositionType)-1;
2916 dc = get_window_dc( style, window, state_type, x, y, width, height, &rect );
2917 if( pos != GTK_POS_LEFT ) {
2918 old_pen = SelectObject( dc, get_light_pen() );
2919 MoveToEx( dc, rect.left, rect.top, NULL );
2920 LineTo( dc, rect.left, rect.bottom );
2922 if( pos != GTK_POS_TOP ) {
2923 old_pen = SelectObject( dc, get_light_pen() );
2924 MoveToEx( dc, rect.left, rect.top, NULL );
2925 LineTo( dc, rect.right, rect.top );
2927 if( pos != GTK_POS_RIGHT ) {
2928 old_pen = SelectObject( dc, get_dark_pen() );
2929 MoveToEx( dc, rect.right-1, rect.top, NULL );
2930 LineTo( dc, rect.right-1, rect.bottom );
2932 if( pos != GTK_POS_BOTTOM ) {
2933 old_pen = SelectObject( dc, get_dark_pen() );
2934 MoveToEx( dc, rect.left, rect.bottom-1, NULL );
2935 LineTo( dc, rect.right, rect.bottom-1 );
2938 SelectObject( dc, old_pen );
2939 release_window_dc( style, window, state_type );
2944 if (detail && !strcmp (detail, "statusbar")) {
2948 parent_class->draw_shadow (style, window, state_type, shadow_type, area,
2949 widget, detail, x, y, width, height);
2953 draw_hline (GtkStyle * style,
2955 GtkStateType state_type,
2956 GdkRectangle * area,
2958 const gchar * detail, gint x1, gint x2, gint y)
2960 if (xp_theme_is_active () && detail && !strcmp(detail, "menuitem")) {
2961 if(xp_theme_draw (window, XP_THEME_ELEMENT_MENU_SEPARATOR, style, x1, y, x2, 1, state_type, area))
2965 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
2967 gdk_draw_line (window, style->dark_gc[state_type], x1, y, x2, y);
2970 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
2973 if( style->ythickness == 2 )
2977 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
2978 gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
2980 gdk_draw_line (window, style->dark_gc[state_type], x1, y, x2, y);
2982 gdk_draw_line (window, style->light_gc[state_type], x1, y, x2, y);
2985 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
2986 gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
2991 parent_class->draw_hline (style, window, state_type, area, widget,
2998 draw_vline (GtkStyle * style,
3000 GtkStateType state_type,
3001 GdkRectangle * area,
3003 const gchar * detail, gint y1, gint y2, gint x)
3005 if( style->xthickness == 2 )
3009 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
3010 gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
3012 gdk_draw_line (window, style->dark_gc[state_type], x, y1, x, y2);
3014 gdk_draw_line (window, style->light_gc[state_type], x, y1, x, y2);
3017 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
3018 gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
3023 parent_class->draw_vline (style, window, state_type, area, widget,
3029 draw_slider (GtkStyle * style,
3031 GtkStateType state_type,
3032 GtkShadowType shadow_type,
3033 GdkRectangle * area,
3035 const gchar * detail,
3037 gint y, gint width, gint height, GtkOrientation orientation)
3039 if (GTK_IS_SCALE (widget) &&
3040 xp_theme_draw (window,
3042 GTK_ORIENTATION_VERTICAL) ?
3043 XP_THEME_ELEMENT_SCALE_SLIDER_V :
3044 XP_THEME_ELEMENT_SCALE_SLIDER_H), style, x, y, width,
3045 height, state_type, area))
3050 parent_class->draw_slider (style, window, state_type, shadow_type, area,
3051 widget, detail, x, y, width, height,
3056 draw_resize_grip (GtkStyle * style,
3058 GtkStateType state_type,
3059 GdkRectangle * area,
3061 const gchar * detail,
3062 GdkWindowEdge edge, gint x, gint y, gint width, gint height)
3064 if (detail && !strcmp (detail, "statusbar"))
3067 (window, XP_THEME_ELEMENT_STATUS_GRIPPER, style, x, y, width,
3068 height, state_type, area))
3072 HDC dc = get_window_dc(style, window, state_type, x, y, width, height, &rect);
3075 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
3076 DrawFrameControl(dc, &rect, DFC_SCROLL, DFCS_SCROLLSIZEGRIP);
3077 release_window_dc(style, window, state_type);
3079 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
3084 parent_class->draw_resize_grip (style, window, state_type, area,
3085 widget, detail, edge, x, y, width,
3090 draw_handle (GtkStyle * style,
3092 GtkStateType state_type,
3093 GtkShadowType shadow_type,
3094 GdkRectangle * area,
3096 const gchar * detail,
3098 gint y, gint width, gint height, GtkOrientation orientation)
3103 if (is_toolbar_child (widget))
3105 XpThemeElement hndl;
3107 sanitize_size (window, &width, &height);
3109 if( GTK_IS_HANDLE_BOX(widget) ) {
3110 GtkPositionType pos;
3111 pos = gtk_handle_box_get_handle_position(GTK_HANDLE_BOX(widget));
3112 if( pos == GTK_POS_TOP || pos == GTK_POS_BOTTOM ) {
3113 orientation = GTK_ORIENTATION_HORIZONTAL;
3116 orientation = GTK_ORIENTATION_VERTICAL;
3120 if ( orientation == GTK_ORIENTATION_VERTICAL )
3121 hndl = XP_THEME_ELEMENT_REBAR_GRIPPER_V;
3123 hndl = XP_THEME_ELEMENT_REBAR_GRIPPER_H;
3125 if (xp_theme_draw (window, hndl, style, x, y, width, height,
3131 dc = get_window_dc( style, window, state_type, x, y, width, height, &rect );
3132 if ( orientation == GTK_ORIENTATION_VERTICAL ) {
3134 rect.right = rect.left + 3;
3140 rect.bottom = rect.top + 3;
3144 draw_3d_border( dc, &rect, FALSE );
3145 release_window_dc( style, window, state_type );
3149 if (!GTK_IS_PANED (widget))
3151 gint xthick, ythick;
3152 GdkGC *light_gc, *dark_gc, *shadow_gc;
3155 sanitize_size (window, &width, &height);
3157 gtk_paint_box (style, window, state_type, shadow_type, area,
3158 widget, detail, x, y, width, height);
3160 light_gc = style->light_gc[state_type];
3161 dark_gc = style->dark_gc[state_type];
3162 shadow_gc = style->mid_gc[state_type];
3164 xthick = style->xthickness;
3165 ythick = style->ythickness;
3167 dest.x = x + xthick;
3168 dest.y = y + ythick;
3169 dest.width = width - (xthick * 2);
3170 dest.height = height - (ythick * 2);
3172 if (dest.width < dest.height)
3177 gdk_gc_set_clip_rectangle (light_gc, &dest);
3178 gdk_gc_set_clip_rectangle (dark_gc, &dest);
3179 gdk_gc_set_clip_rectangle (shadow_gc, &dest);
3181 if (dest.width < dest.height)
3183 gdk_draw_line (window, light_gc, dest.x, dest.y, dest.x,
3185 gdk_draw_line (window, dark_gc, dest.x + (dest.width / 2),
3186 dest.y, dest.x + (dest.width / 2),
3188 gdk_draw_line (window, shadow_gc, dest.x + dest.width,
3189 dest.y, dest.x + dest.width, dest.height);
3193 gdk_draw_line (window, light_gc, dest.x, dest.y,
3194 dest.x + dest.width, dest.y);
3195 gdk_draw_line (window, dark_gc, dest.x,
3196 dest.y + (dest.height / 2),
3197 dest.x + dest.width,
3198 dest.y + (dest.height / 2));
3199 gdk_draw_line (window, shadow_gc, dest.x,
3200 dest.y + dest.height, dest.x + dest.width,
3201 dest.y + dest.height);
3204 gdk_gc_set_clip_rectangle (shadow_gc, NULL);
3205 gdk_gc_set_clip_rectangle (light_gc, NULL);
3206 gdk_gc_set_clip_rectangle (dark_gc, NULL);
3211 draw_focus ( GtkStyle *style,
3213 GtkStateType state_type,
3216 const gchar *detail,
3224 if( !GTK_WIDGET_CAN_FOCUS(widget) ) {
3227 if( detail && 0 == strcmp(detail, "button")
3228 && GTK_RELIEF_NONE == gtk_button_get_relief( GTK_BUTTON(widget) ) )
3232 if ( is_combo_box_child(widget)
3233 && (GTK_IS_ARROW(widget) || GTK_IS_BUTTON(widget)) ) {
3236 if (GTK_IS_TREE_VIEW (widget->parent) /* list view bheader */
3237 || GTK_IS_CLIST (widget->parent)) {
3241 dc = get_window_dc( style, window, state_type, x, y, width, height, &rect );
3242 DrawFocusRect(dc, &rect);
3243 release_window_dc( style, window, state_type );
3245 parent_class->draw_focus (style, window, state_type,
3246 area, widget, detail, x, y, width, height);
3251 draw_layout (GtkStyle *style,
3253 GtkStateType state_type,
3257 const gchar *detail,
3260 PangoLayout *layout)
3262 GtkNotebook *notebook = NULL;
3266 /* In the XP theme, labels don't appear correctly centered inside
3267 * notebook tabs, so we give them a gentle nudge two pixels to the
3268 * right. A little hackish, but what are 'ya gonna do? -- Cody
3270 if (xp_theme_is_active () && detail && !strcmp (detail, "label"))
3272 if (widget->parent != NULL)
3274 if (GTK_IS_NOTEBOOK (widget->parent))
3276 notebook = GTK_NOTEBOOK (widget->parent);
3277 int side = gtk_notebook_get_tab_pos (notebook);
3279 if (side == GTK_POS_TOP || side == GTK_POS_BOTTOM)
3287 parent_class->draw_layout (style, window, state_type,
3288 use_text, area, widget,
3289 detail, x, y, layout);
3293 msw_style_init_from_rc (GtkStyle * style, GtkRcStyle * rc_style)
3295 setup_system_font (style);
3296 setup_menu_settings (gtk_settings_get_default ());
3297 setup_system_styles (style);
3298 parent_class->init_from_rc (style, rc_style);
3302 load_bg_image (GdkColormap *colormap,
3304 const gchar *filename)
3306 if (strcmp (filename, "<parent>") == 0)
3307 return (GdkPixmap*) GDK_PARENT_RELATIVE;
3310 return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL,
3317 msw_style_realize (GtkStyle * style)
3319 GdkGCValues gc_values;
3320 GdkGCValuesMask gc_values_mask;
3324 for (i = 0; i < 5; i++)
3326 style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2;
3327 style->mid[i].green = (style->light[i].green + style->dark[i].green) / 2;
3328 style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2;
3330 style->text_aa[i].red = (style->text[i].red + style->base[i].red) / 2;
3331 style->text_aa[i].green = (style->text[i].green + style->base[i].green) / 2;
3332 style->text_aa[i].blue = (style->text[i].blue + style->base[i].blue) / 2;
3335 style->black.red = 0x0000;
3336 style->black.green = 0x0000;
3337 style->black.blue = 0x0000;
3338 gdk_colormap_alloc_color (style->colormap, &style->black, FALSE, TRUE);
3340 style->white.red = 0xffff;
3341 style->white.green = 0xffff;
3342 style->white.blue = 0xffff;
3343 gdk_colormap_alloc_color (style->colormap, &style->white, FALSE, TRUE);
3345 gc_values_mask = GDK_GC_FOREGROUND | GDK_GC_BACKGROUND;
3347 gc_values.foreground = style->black;
3348 gc_values.background = style->white;
3349 style->black_gc = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3351 gc_values.foreground = style->white;
3352 gc_values.background = style->black;
3353 style->white_gc = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3355 gc_values_mask = GDK_GC_FOREGROUND;
3357 for (i = 0; i < 5; i++)
3359 if (style->rc_style && style->rc_style->bg_pixmap_name[i])
3360 style->bg_pixmap[i] = load_bg_image (style->colormap,
3362 style->rc_style->bg_pixmap_name[i]);
3364 if (!gdk_colormap_alloc_color (style->colormap, &style->fg[i], FALSE, TRUE))
3365 g_warning ("unable to allocate color: ( %d %d %d )",
3366 style->fg[i].red, style->fg[i].green, style->fg[i].blue);
3367 if (!gdk_colormap_alloc_color (style->colormap, &style->bg[i], FALSE, TRUE))
3368 g_warning ("unable to allocate color: ( %d %d %d )",
3369 style->bg[i].red, style->bg[i].green, style->bg[i].blue);
3370 if (!gdk_colormap_alloc_color (style->colormap, &style->light[i], FALSE, TRUE))
3371 g_warning ("unable to allocate color: ( %d %d %d )",
3372 style->light[i].red, style->light[i].green, style->light[i].blue);
3373 if (!gdk_colormap_alloc_color (style->colormap, &style->dark[i], FALSE, TRUE))
3374 g_warning ("unable to allocate color: ( %d %d %d )",
3375 style->dark[i].red, style->dark[i].green, style->dark[i].blue);
3376 if (!gdk_colormap_alloc_color (style->colormap, &style->mid[i], FALSE, TRUE))
3377 g_warning ("unable to allocate color: ( %d %d %d )",
3378 style->mid[i].red, style->mid[i].green, style->mid[i].blue);
3379 if (!gdk_colormap_alloc_color (style->colormap, &style->text[i], FALSE, TRUE))
3380 g_warning ("unable to allocate color: ( %d %d %d )",
3381 style->text[i].red, style->text[i].green, style->text[i].blue);
3382 if (!gdk_colormap_alloc_color (style->colormap, &style->base[i], FALSE, TRUE))
3383 g_warning ("unable to allocate color: ( %d %d %d )",
3384 style->base[i].red, style->base[i].green, style->base[i].blue);
3385 if (!gdk_colormap_alloc_color (style->colormap, &style->text_aa[i], FALSE, TRUE))
3386 g_warning ("unable to allocate color: ( %d %d %d )",
3387 style->text_aa[i].red, style->text_aa[i].green, style->text_aa[i].blue);
3389 gc_values.foreground = style->fg[i];
3390 style->fg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3392 gc_values.foreground = style->bg[i];
3393 style->bg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3395 gc_values.foreground = style->light[i];
3396 style->light_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3398 gc_values.foreground = style->dark[i];
3399 style->dark_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3401 gc_values.foreground = style->mid[i];
3402 style->mid_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3404 gc_values.foreground = style->text[i];
3405 style->text_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3407 gc_values.foreground = style->base[i];
3408 style->base_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3410 gc_values.foreground = style->text_aa[i];
3411 style->text_aa_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3416 msw_style_unrealize (GtkStyle * style)
3418 parent_class->unrealize (style);
3422 msw_style_class_init (MswStyleClass * klass)
3424 GtkStyleClass *style_class = GTK_STYLE_CLASS (klass);
3426 parent_class = g_type_class_peek_parent (klass);
3428 style_class->init_from_rc = msw_style_init_from_rc;
3429 style_class->draw_arrow = draw_arrow;
3430 style_class->draw_box = draw_box;
3431 style_class->draw_check = draw_check;
3432 style_class->draw_option = draw_option;
3433 style_class->draw_tab = draw_tab;
3434 style_class->draw_flat_box = draw_flat_box;
3435 style_class->draw_expander = draw_expander;
3436 style_class->draw_extension = draw_extension;
3437 style_class->draw_box_gap = draw_box_gap;
3438 style_class->draw_shadow = draw_shadow;
3439 style_class->draw_hline = draw_hline;
3440 style_class->draw_vline = draw_vline;
3441 style_class->draw_handle = draw_handle;
3442 style_class->draw_resize_grip = draw_resize_grip;
3443 style_class->draw_slider = draw_slider;
3444 style_class->draw_focus = draw_focus;
3445 style_class->draw_layout = draw_layout;
3447 style_class->realize = msw_style_realize;
3448 style_class->unrealize = msw_style_unrealize;
3451 GType msw_type_style = 0;
3454 msw_style_register_type (GTypeModule * module)
3456 static const GTypeInfo object_info = {
3457 sizeof (MswStyleClass),
3458 (GBaseInitFunc) NULL,
3459 (GBaseFinalizeFunc) NULL,
3460 (GClassInitFunc) msw_style_class_init,
3461 NULL, /* class_finalize */
3462 NULL, /* class_data */
3464 0, /* n_preallocs */
3465 (GInstanceInitFunc) NULL,
3468 msw_type_style = g_type_module_register_type (module,
3475 msw_style_init (void)
3478 msw_style_setup_system_settings ();
3479 setup_msw_rc_style ();
3482 DeleteObject( g_light_pen );
3486 DeleteObject( g_dark_pen );
3491 void msw_style_finalize(void)
3493 if( g_dither_brush ){
3494 DeleteObject( g_dither_brush );
3497 DeleteObject( g_light_pen );
3500 DeleteObject( g_dark_pen );