1/* $Id$
2 */
3
4#ifdef _MSC_VER
5#define WIN32_LEAN_AND_MEAN
6#endif
7
8#include <tkWinInt.h>
9#include "ttk/ttkTheme.h"
10
11#if !defined(WM_THEMECHANGED)
12#define WM_THEMECHANGED 0x031A
13#endif
14
15static LRESULT WINAPI WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
16
17/*
18 * RegisterSystemColors --
19 *	Register all known Windows system colors (as per GetSysColor) as Tk
20 *	named colors.
21 */
22
23typedef struct {
24    const char *name;
25    int index;
26} SystemColorEntry;
27
28static SystemColorEntry sysColors[] = {
29	{ "System3dDarkShadow",		COLOR_3DDKSHADOW },
30	{ "System3dLight",		COLOR_3DLIGHT },
31	{ "SystemActiveBorder",		COLOR_ACTIVEBORDER },
32	{ "SystemActiveCaption",	COLOR_ACTIVECAPTION },
33	{ "SystemAppWorkspace",		COLOR_APPWORKSPACE },
34	{ "SystemBackground",		COLOR_BACKGROUND },
35	{ "SystemButtonFace",		COLOR_BTNFACE },
36	{ "SystemButtonHighlight",	COLOR_BTNHIGHLIGHT },
37	{ "SystemButtonShadow",		COLOR_BTNSHADOW },
38	{ "SystemButtonText",		COLOR_BTNTEXT },
39	{ "SystemCaptionText",		COLOR_CAPTIONTEXT },
40	{ "SystemDisabledText",		COLOR_GRAYTEXT },
41	{ "SystemGrayText",		COLOR_GRAYTEXT },
42	{ "SystemHighlight",		COLOR_HIGHLIGHT },
43	{ "SystemHighlightText",	COLOR_HIGHLIGHTTEXT },
44	{ "SystemInactiveBorder",	COLOR_INACTIVEBORDER },
45	{ "SystemInactiveCaption",	COLOR_INACTIVECAPTION },
46	{ "SystemInactiveCaptionText",	COLOR_INACTIVECAPTIONTEXT },
47	{ "SystemInfoBackground",	COLOR_INFOBK },
48	{ "SystemInfoText",		COLOR_INFOTEXT },
49	{ "SystemMenu",			COLOR_MENU },
50	{ "SystemMenuText",		COLOR_MENUTEXT },
51	{ "SystemScrollbar",		COLOR_SCROLLBAR },
52	{ "SystemWindow",		COLOR_WINDOW },
53	{ "SystemWindowFrame",		COLOR_WINDOWFRAME },
54	{ "SystemWindowText",		COLOR_WINDOWTEXT },
55	{ NULL, 0 }
56};
57
58static void RegisterSystemColors(Tcl_Interp *interp)
59{
60    Ttk_ResourceCache cache = Ttk_GetResourceCache(interp);
61    SystemColorEntry *sysColor;
62
63    for (sysColor = sysColors; sysColor->name; ++sysColor) {
64	DWORD pixel = GetSysColor(sysColor->index);
65	XColor colorSpec;
66	colorSpec.red = GetRValue(pixel) * 257;
67	colorSpec.green = GetGValue(pixel) * 257;
68	colorSpec.blue = GetBValue(pixel) * 257;
69	Ttk_RegisterNamedColor(cache, sysColor->name, &colorSpec);
70    }
71}
72
73static HWND
74CreateThemeMonitorWindow(HINSTANCE hinst, Tcl_Interp *interp)
75{
76    WNDCLASSEX wc;
77    HWND       hwnd = NULL;
78    TCHAR      title[32] = TEXT("TtkMonitorWindow");
79    TCHAR      name[32] = TEXT("TtkMonitorClass");
80
81    wc.cbSize        = sizeof(WNDCLASSEX);
82    wc.style         = CS_HREDRAW | CS_VREDRAW;
83    wc.lpfnWndProc   = (WNDPROC)WndProc;
84    wc.cbClsExtra    = 0;
85    wc.cbWndExtra    = 0;
86    wc.hInstance     = hinst;
87    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
88    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
89    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
90    wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
91    wc.lpszMenuName  = name;
92    wc.lpszClassName = name;
93
94    if (RegisterClassEx(&wc)) {
95	hwnd = CreateWindow( name, title, WS_OVERLAPPEDWINDOW,
96	    CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
97	    NULL, NULL, hinst, NULL );
98	SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG)interp);
99	ShowWindow(hwnd, SW_HIDE);
100	UpdateWindow(hwnd);
101    }
102    return hwnd;
103}
104
105static void
106DestroyThemeMonitorWindow(void *clientData)
107{
108    HWND hwnd = (HWND)clientData;
109    DestroyWindow(hwnd);
110}
111
112static LRESULT WINAPI
113WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
114{
115    Tcl_Interp *interp = (Tcl_Interp *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
116    Ttk_Theme theme;
117
118    switch (msg) {
119    case WM_DESTROY:
120	break;
121
122    case WM_SYSCOLORCHANGE:
123	RegisterSystemColors(interp);
124	break;
125
126    case WM_THEMECHANGED:
127	/*
128	 * Reset the application theme to 'xpnative' if present,
129	 * which will in turn fall back to 'winnative' if XP theming
130	 * is disabled.
131	 */
132
133	theme = Ttk_GetTheme(interp, "xpnative");
134	if (theme) {
135	    Ttk_UseTheme(interp, theme);
136	    /* @@@ What to do about errors here? */
137	}
138	break;
139    }
140    return DefWindowProc(hwnd, msg, wp, lp);
141}
142
143/*
144 * Windows-specific platform initialization:
145 */
146
147MODULE_SCOPE int TtkWinTheme_Init(Tcl_Interp *, HWND hwnd);
148MODULE_SCOPE int TtkXPTheme_Init(Tcl_Interp *, HWND hwnd);
149
150MODULE_SCOPE int Ttk_WinPlatformInit(Tcl_Interp *interp)
151{
152    HWND hwnd;
153
154    hwnd = CreateThemeMonitorWindow(Tk_GetHINSTANCE(), interp);
155    Ttk_RegisterCleanup(interp, (ClientData)hwnd, DestroyThemeMonitorWindow);
156
157    TtkWinTheme_Init(interp, hwnd);
158    TtkXPTheme_Init(interp, hwnd);
159
160    return TCL_OK;
161}
162