mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-18 17:30:10 +00:00
1165 lines
26 KiB
C
Executable File
1165 lines
26 KiB
C
Executable File
/* MS-Windows Engine (aka GTK-Wimp)
|
|
*
|
|
* Copyright (C) 2003, 2004 Raymond Penners <raymond@dotsphinx.com>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#define _WIN32_WINNT 0x0501
|
|
|
|
#include "xp_theme.h"
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <windows.h>
|
|
#include <math.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
#ifdef BUILDING_STANDALONE
|
|
#include "gdk/gdkwin32.h"
|
|
#else
|
|
#include "gdk/win32/gdkwin32.h"
|
|
#endif
|
|
|
|
#include <cairo-win32.h>
|
|
#include <gdk/gdk.h>
|
|
|
|
#include "xp_theme_defs.h"
|
|
|
|
#ifndef TMT_CAPTIONFONT
|
|
|
|
/* These aren't in mingw's "w32api" headers, nor in the Platform SDK
|
|
* headers.
|
|
*/
|
|
#define TMT_CAPTIONFONT 801
|
|
#define TMT_MENUFONT 803
|
|
#define TMT_STATUSFONT 804
|
|
#define TMT_MSGBOXFONT 805
|
|
#endif
|
|
|
|
#define GP_LINEHORZ 2
|
|
#define GP_LINEVERT 3
|
|
#define TP_SEPARATOR 5
|
|
#define TP_SEPARATORVERT 6
|
|
|
|
/* GLOBALS LINEHORZ states */
|
|
#define LHS_FLAT 1
|
|
#define LHS_RAISED 2
|
|
#define LHS_SUNKEN 3
|
|
|
|
/* GLOBAL LINEVERT states */
|
|
#define LVS_FLAT 1
|
|
#define LVS_RAISED 2
|
|
#define LVS_SUNKEN 3
|
|
|
|
/* TRACKBAR parts */
|
|
#define TKP_TRACK 1
|
|
#define TKP_TRACKVERT 2
|
|
#define TKP_THUMB 3
|
|
#define TKP_THUMBBOTTOM 4
|
|
#define TKP_THUMBTOP 5
|
|
#define TKP_THUMBVERT 6
|
|
#define TKP_THUMBLEFT 7
|
|
#define TKP_THUMBRIGHT 8
|
|
#define TKP_TICS 9
|
|
#define TKP_TICSVERT 10
|
|
|
|
#define TRS_NORMAL 1
|
|
|
|
#define MBI_NORMAL 1
|
|
#define MBI_HOT 2
|
|
#define MBI_PUSHED 3
|
|
#define MBI_DISABLED 4
|
|
#define MBI_DISABLEDHOT 5
|
|
#define MBI_DISABLEDPUSHED 6
|
|
|
|
#define MENU_POPUPGUTTER 13
|
|
#define MENU_POPUPITEM 14
|
|
#define MENU_POPUPSEPARATOR 15
|
|
|
|
static const LPCWSTR class_descriptors[] = {
|
|
L"Scrollbar", /* XP_THEME_CLASS_SCROLLBAR */
|
|
L"Button", /* XP_THEME_CLASS_BUTTON */
|
|
L"Header", /* XP_THEME_CLASS_HEADER */
|
|
L"ComboBox", /* XP_THEME_CLASS_COMBOBOX */
|
|
L"Tab", /* XP_THEME_CLASS_TAB */
|
|
L"Edit", /* XP_THEME_CLASS_EDIT */
|
|
L"TreeView", /* XP_THEME_CLASS_TREEVIEW */
|
|
L"Spin", /* XP_THEME_CLASS_SPIN */
|
|
L"Progress", /* XP_THEME_CLASS_PROGRESS */
|
|
L"Tooltip", /* XP_THEME_CLASS_TOOLTIP */
|
|
L"Rebar", /* XP_THEME_CLASS_REBAR */
|
|
L"Toolbar", /* XP_THEME_CLASS_TOOLBAR */
|
|
L"Globals", /* XP_THEME_CLASS_GLOBALS */
|
|
L"Menu", /* XP_THEME_CLASS_MENU */
|
|
L"Window", /* XP_THEME_CLASS_WINDOW */
|
|
L"Status", /* XP_THEME_CLASS_STATUS */
|
|
L"Trackbar" /* XP_THEME_CLASS_TRACKBAR */
|
|
};
|
|
|
|
static const short element_part_map[XP_THEME_ELEMENT__SIZEOF] = {
|
|
BP_CHECKBOX,
|
|
BP_CHECKBOX,
|
|
BP_CHECKBOX,
|
|
BP_PUSHBUTTON,
|
|
HP_HEADERITEM,
|
|
CP_DROPDOWNBUTTON,
|
|
TABP_BODY,
|
|
TABP_TABITEM,
|
|
TABP_TABITEMLEFTEDGE,
|
|
TABP_TABITEMRIGHTEDGE,
|
|
TABP_PANE,
|
|
SBP_THUMBBTNHORZ,
|
|
SBP_THUMBBTNVERT,
|
|
SBP_ARROWBTN,
|
|
SBP_ARROWBTN,
|
|
SBP_ARROWBTN,
|
|
SBP_ARROWBTN,
|
|
SBP_GRIPPERHORZ,
|
|
SBP_GRIPPERVERT,
|
|
SBP_LOWERTRACKHORZ,
|
|
SBP_LOWERTRACKVERT,
|
|
EP_EDITTEXT,
|
|
BP_PUSHBUTTON,
|
|
SPNP_UP,
|
|
SPNP_DOWN,
|
|
BP_RADIOBUTTON,
|
|
BP_RADIOBUTTON,
|
|
TVP_GLYPH,
|
|
TVP_GLYPH,
|
|
PP_CHUNK,
|
|
PP_CHUNKVERT,
|
|
PP_BAR,
|
|
PP_BARVERT,
|
|
TTP_STANDARD,
|
|
0 /* RP_BAND */ ,
|
|
RP_GRIPPER,
|
|
RP_GRIPPERVERT,
|
|
RP_CHEVRON,
|
|
TP_BUTTON,
|
|
MENU_POPUPITEM, /*MP_MENUITEM,*/
|
|
MENU_POPUPSEPARATOR, /*MP_SEPARATOR,*/
|
|
SP_GRIPPER,
|
|
SP_PANE,
|
|
GP_LINEHORZ,
|
|
GP_LINEVERT,
|
|
TP_SEPARATOR,
|
|
TP_SEPARATORVERT,
|
|
TKP_TRACK,
|
|
TKP_TRACKVERT,
|
|
TKP_THUMB,
|
|
TKP_THUMBVERT,
|
|
TKP_TICS,
|
|
TKP_TICSVERT
|
|
};
|
|
|
|
#define UXTHEME_DLL "uxtheme.dll"
|
|
|
|
static HINSTANCE uxtheme_dll = NULL;
|
|
static HTHEME open_themes[XP_THEME_CLASS__SIZEOF];
|
|
static gboolean use_xp_theme = FALSE;
|
|
|
|
typedef HRESULT (FAR PASCAL *GetThemeSysFontFunc) (HTHEME hTheme, int iFontID, OUT LOGFONTW *plf);
|
|
typedef int (FAR PASCAL *GetThemeSysSizeFunc) (HTHEME hTheme, int iSizeId);
|
|
typedef COLORREF (FAR PASCAL *GetThemeSysColorFunc) (HTHEME hTheme,
|
|
int iColorID);
|
|
typedef HTHEME (FAR PASCAL *OpenThemeDataFunc) (HWND hwnd,
|
|
LPCWSTR pszClassList);
|
|
typedef HRESULT (FAR PASCAL *CloseThemeDataFunc) (HTHEME theme);
|
|
typedef HRESULT (FAR PASCAL *DrawThemeBackgroundFunc) (HTHEME hTheme, HDC hdc, int iPartId, int iStateId,
|
|
const RECT *pRect, const RECT *pClipRect);
|
|
typedef HRESULT (FAR PASCAL *EnableThemeDialogTextureFunc) (HWND hwnd,
|
|
DWORD dwFlags);
|
|
typedef BOOL (FAR PASCAL *IsThemeActiveFunc) (VOID);
|
|
typedef BOOL (FAR PASCAL *IsAppThemedFunc) (VOID);
|
|
typedef BOOL (FAR PASCAL *IsThemeBackgroundPartiallyTransparentFunc) (HTHEME hTheme,
|
|
int iPartId,
|
|
int iStateId);
|
|
typedef HRESULT (FAR PASCAL *DrawThemeParentBackgroundFunc) (HWND hwnd,
|
|
HDC hdc,
|
|
RECT *prc);
|
|
typedef HRESULT (FAR PASCAL *GetThemePartSizeFunc) (HTHEME hTheme,
|
|
HDC hdc,
|
|
int iPartId,
|
|
int iStateId,
|
|
RECT *prc,
|
|
int eSize,
|
|
SIZE *psz);
|
|
|
|
static GetThemeSysFontFunc get_theme_sys_font_func = NULL;
|
|
static GetThemeSysColorFunc get_theme_sys_color_func = NULL;
|
|
static GetThemeSysSizeFunc get_theme_sys_metric_func = NULL;
|
|
static OpenThemeDataFunc open_theme_data_func = NULL;
|
|
static CloseThemeDataFunc close_theme_data_func = NULL;
|
|
static DrawThemeBackgroundFunc draw_theme_background_func = NULL;
|
|
static EnableThemeDialogTextureFunc enable_theme_dialog_texture_func = NULL;
|
|
static IsThemeActiveFunc is_theme_active_func = NULL;
|
|
static IsAppThemedFunc is_app_themed_func = NULL;
|
|
static IsThemeBackgroundPartiallyTransparentFunc is_theme_partially_transparent_func = NULL;
|
|
static DrawThemeParentBackgroundFunc draw_theme_parent_background_func = NULL;
|
|
static GetThemePartSizeFunc get_theme_part_size_func = NULL;
|
|
|
|
static void
|
|
xp_theme_close_open_handles (void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < XP_THEME_CLASS__SIZEOF; i++)
|
|
{
|
|
if (open_themes[i])
|
|
{
|
|
close_theme_data_func (open_themes[i]);
|
|
open_themes[i] = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
xp_theme_init (void)
|
|
{
|
|
char *buf;
|
|
char dummy;
|
|
int n, k;
|
|
|
|
if (uxtheme_dll)
|
|
return;
|
|
|
|
memset (open_themes, 0, sizeof (open_themes));
|
|
|
|
n = GetSystemDirectory (&dummy, 0);
|
|
|
|
if (n <= 0)
|
|
return;
|
|
|
|
buf = g_malloc (n + 1 + strlen (UXTHEME_DLL));
|
|
k = GetSystemDirectory (buf, n);
|
|
|
|
if (k == 0 || k > n)
|
|
{
|
|
g_free (buf);
|
|
return;
|
|
}
|
|
|
|
if (!G_IS_DIR_SEPARATOR (buf[strlen (buf) -1]))
|
|
strcat (buf, G_DIR_SEPARATOR_S);
|
|
strcat (buf, UXTHEME_DLL);
|
|
|
|
uxtheme_dll = LoadLibrary (buf);
|
|
g_free (buf);
|
|
|
|
if (!uxtheme_dll)
|
|
return;
|
|
|
|
is_app_themed_func = (IsAppThemedFunc) GetProcAddress (uxtheme_dll, "IsAppThemed");
|
|
|
|
if (is_app_themed_func)
|
|
{
|
|
is_theme_active_func = (IsThemeActiveFunc) GetProcAddress (uxtheme_dll, "IsThemeActive");
|
|
open_theme_data_func = (OpenThemeDataFunc) GetProcAddress (uxtheme_dll, "OpenThemeData");
|
|
close_theme_data_func = (CloseThemeDataFunc) GetProcAddress (uxtheme_dll, "CloseThemeData");
|
|
draw_theme_background_func = (DrawThemeBackgroundFunc) GetProcAddress (uxtheme_dll, "DrawThemeBackground");
|
|
enable_theme_dialog_texture_func = (EnableThemeDialogTextureFunc) GetProcAddress (uxtheme_dll, "EnableThemeDialogTexture");
|
|
get_theme_sys_font_func = (GetThemeSysFontFunc) GetProcAddress (uxtheme_dll, "GetThemeSysFont");
|
|
get_theme_sys_color_func = (GetThemeSysColorFunc) GetProcAddress (uxtheme_dll, "GetThemeSysColor");
|
|
get_theme_sys_metric_func = (GetThemeSysSizeFunc) GetProcAddress (uxtheme_dll, "GetThemeSysSize");
|
|
is_theme_partially_transparent_func = (IsThemeBackgroundPartiallyTransparentFunc) GetProcAddress (uxtheme_dll, "IsThemeBackgroundPartiallyTransparent");
|
|
draw_theme_parent_background_func = (DrawThemeParentBackgroundFunc) GetProcAddress (uxtheme_dll, "DrawThemeParentBackground");
|
|
get_theme_part_size_func = (GetThemePartSizeFunc) GetProcAddress (uxtheme_dll, "GetThemePartSize");
|
|
}
|
|
|
|
if (is_app_themed_func && is_theme_active_func)
|
|
{
|
|
use_xp_theme = (is_app_themed_func () && is_theme_active_func ());
|
|
}
|
|
else
|
|
{
|
|
use_xp_theme = FALSE;
|
|
}
|
|
}
|
|
|
|
void
|
|
xp_theme_reset (void)
|
|
{
|
|
xp_theme_close_open_handles ();
|
|
|
|
if (is_app_themed_func && is_theme_active_func)
|
|
{
|
|
use_xp_theme = (is_app_themed_func () && is_theme_active_func ());
|
|
}
|
|
else
|
|
{
|
|
use_xp_theme = FALSE;
|
|
}
|
|
}
|
|
|
|
void
|
|
xp_theme_exit (void)
|
|
{
|
|
if (!uxtheme_dll)
|
|
return;
|
|
|
|
xp_theme_close_open_handles ();
|
|
|
|
FreeLibrary (uxtheme_dll);
|
|
uxtheme_dll = NULL;
|
|
use_xp_theme = FALSE;
|
|
|
|
is_app_themed_func = NULL;
|
|
is_theme_active_func = NULL;
|
|
open_theme_data_func = NULL;
|
|
close_theme_data_func = NULL;
|
|
draw_theme_background_func = NULL;
|
|
enable_theme_dialog_texture_func = NULL;
|
|
get_theme_sys_font_func = NULL;
|
|
get_theme_sys_color_func = NULL;
|
|
get_theme_sys_metric_func = NULL;
|
|
is_theme_partially_transparent_func = NULL;
|
|
draw_theme_parent_background_func = NULL;
|
|
get_theme_part_size_func = NULL;
|
|
}
|
|
|
|
static HTHEME
|
|
xp_theme_get_handle_by_class (XpThemeClass klazz)
|
|
{
|
|
if (!open_themes[klazz] && open_theme_data_func)
|
|
{
|
|
open_themes[klazz] = open_theme_data_func (NULL, class_descriptors[klazz]);
|
|
}
|
|
|
|
return open_themes[klazz];
|
|
}
|
|
|
|
static HTHEME
|
|
xp_theme_get_handle_by_element (XpThemeElement element)
|
|
{
|
|
HTHEME ret = NULL;
|
|
XpThemeClass klazz = XP_THEME_CLASS__SIZEOF;
|
|
|
|
switch (element)
|
|
{
|
|
case XP_THEME_ELEMENT_TOOLTIP:
|
|
klazz = XP_THEME_CLASS_TOOLTIP;
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_REBAR:
|
|
case XP_THEME_ELEMENT_REBAR_GRIPPER_H:
|
|
case XP_THEME_ELEMENT_REBAR_GRIPPER_V:
|
|
case XP_THEME_ELEMENT_REBAR_CHEVRON:
|
|
klazz = XP_THEME_CLASS_REBAR;
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_SCALE_TROUGH_H:
|
|
case XP_THEME_ELEMENT_SCALE_TROUGH_V:
|
|
case XP_THEME_ELEMENT_SCALE_SLIDER_H:
|
|
case XP_THEME_ELEMENT_SCALE_SLIDER_V:
|
|
case XP_THEME_ELEMENT_SCALE_TICS_H:
|
|
case XP_THEME_ELEMENT_SCALE_TICS_V:
|
|
klazz = XP_THEME_CLASS_TRACKBAR;
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_STATUS_GRIPPER:
|
|
case XP_THEME_ELEMENT_STATUS_PANE:
|
|
klazz = XP_THEME_CLASS_STATUS;
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_TOOLBAR_BUTTON:
|
|
case XP_THEME_ELEMENT_TOOLBAR_SEPARATOR_H:
|
|
case XP_THEME_ELEMENT_TOOLBAR_SEPARATOR_V:
|
|
klazz = XP_THEME_CLASS_TOOLBAR;
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_MENU_ITEM:
|
|
case XP_THEME_ELEMENT_MENU_SEPARATOR:
|
|
klazz = XP_THEME_CLASS_MENU;
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_PRESSED_CHECKBOX:
|
|
case XP_THEME_ELEMENT_INCONSISTENT_CHECKBOX:
|
|
case XP_THEME_ELEMENT_CHECKBOX:
|
|
case XP_THEME_ELEMENT_BUTTON:
|
|
case XP_THEME_ELEMENT_DEFAULT_BUTTON:
|
|
case XP_THEME_ELEMENT_PRESSED_RADIO_BUTTON:
|
|
case XP_THEME_ELEMENT_RADIO_BUTTON:
|
|
klazz = XP_THEME_CLASS_BUTTON;
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_LIST_HEADER:
|
|
klazz = XP_THEME_CLASS_HEADER;
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_COMBOBUTTON:
|
|
klazz = XP_THEME_CLASS_COMBOBOX;
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_BODY:
|
|
case XP_THEME_ELEMENT_TAB_ITEM:
|
|
case XP_THEME_ELEMENT_TAB_ITEM_LEFT_EDGE:
|
|
case XP_THEME_ELEMENT_TAB_ITEM_RIGHT_EDGE:
|
|
case XP_THEME_ELEMENT_TAB_PANE:
|
|
klazz = XP_THEME_CLASS_TAB;
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_SCROLLBAR_V:
|
|
case XP_THEME_ELEMENT_SCROLLBAR_H:
|
|
case XP_THEME_ELEMENT_ARROW_UP:
|
|
case XP_THEME_ELEMENT_ARROW_DOWN:
|
|
case XP_THEME_ELEMENT_ARROW_LEFT:
|
|
case XP_THEME_ELEMENT_ARROW_RIGHT:
|
|
case XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V:
|
|
case XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H:
|
|
case XP_THEME_ELEMENT_TROUGH_V:
|
|
case XP_THEME_ELEMENT_TROUGH_H:
|
|
klazz = XP_THEME_CLASS_SCROLLBAR;
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_EDIT_TEXT:
|
|
klazz = XP_THEME_CLASS_EDIT;
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_SPIN_BUTTON_UP:
|
|
case XP_THEME_ELEMENT_SPIN_BUTTON_DOWN:
|
|
klazz = XP_THEME_CLASS_SPIN;
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_PROGRESS_BAR_H:
|
|
case XP_THEME_ELEMENT_PROGRESS_BAR_V:
|
|
case XP_THEME_ELEMENT_PROGRESS_TROUGH_H:
|
|
case XP_THEME_ELEMENT_PROGRESS_TROUGH_V:
|
|
klazz = XP_THEME_CLASS_PROGRESS;
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_TREEVIEW_EXPANDER_OPENED:
|
|
case XP_THEME_ELEMENT_TREEVIEW_EXPANDER_CLOSED:
|
|
klazz = XP_THEME_CLASS_TREEVIEW;
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_LINE_H:
|
|
case XP_THEME_ELEMENT_LINE_V:
|
|
klazz = XP_THEME_CLASS_GLOBALS;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (klazz != XP_THEME_CLASS__SIZEOF)
|
|
{
|
|
ret = xp_theme_get_handle_by_class (klazz);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int
|
|
xp_theme_map_gtk_state (XpThemeElement element, GtkStateType state)
|
|
{
|
|
int ret = 0;
|
|
|
|
switch (element)
|
|
{
|
|
case XP_THEME_ELEMENT_TOOLTIP:
|
|
ret = TTSS_NORMAL;
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_REBAR:
|
|
ret = 0;
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_REBAR_GRIPPER_H:
|
|
case XP_THEME_ELEMENT_REBAR_GRIPPER_V:
|
|
ret = 0;
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_STATUS_GRIPPER:
|
|
case XP_THEME_ELEMENT_STATUS_PANE:
|
|
ret = 1;
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_REBAR_CHEVRON:
|
|
switch (state)
|
|
{
|
|
case GTK_STATE_PRELIGHT:
|
|
ret = CHEVS_HOT;
|
|
break;
|
|
|
|
case GTK_STATE_SELECTED:
|
|
case GTK_STATE_ACTIVE:
|
|
ret = CHEVS_PRESSED;
|
|
break;
|
|
|
|
default:
|
|
ret = CHEVS_NORMAL;
|
|
}
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_TOOLBAR_SEPARATOR_H:
|
|
case XP_THEME_ELEMENT_TOOLBAR_SEPARATOR_V:
|
|
ret = TS_NORMAL;
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_TOOLBAR_BUTTON:
|
|
switch (state)
|
|
{
|
|
case GTK_STATE_ACTIVE:
|
|
ret = TS_PRESSED;
|
|
break;
|
|
|
|
case GTK_STATE_PRELIGHT:
|
|
ret = TS_HOT;
|
|
break;
|
|
|
|
case GTK_STATE_INSENSITIVE:
|
|
ret = TS_DISABLED;
|
|
break;
|
|
|
|
default:
|
|
ret = TS_NORMAL;
|
|
}
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_TAB_PANE:
|
|
ret = 1;
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_TAB_ITEM_LEFT_EDGE:
|
|
case XP_THEME_ELEMENT_TAB_ITEM_RIGHT_EDGE:
|
|
case XP_THEME_ELEMENT_TAB_ITEM:
|
|
switch (state)
|
|
{
|
|
case GTK_STATE_PRELIGHT:
|
|
ret = TIS_HOT;
|
|
break;
|
|
|
|
case GTK_STATE_INSENSITIVE:
|
|
ret = TIS_DISABLED;
|
|
break;
|
|
|
|
case GTK_STATE_SELECTED:
|
|
case GTK_STATE_ACTIVE:
|
|
ret = TIS_NORMAL;
|
|
break;
|
|
|
|
default:
|
|
ret = TIS_SELECTED;
|
|
}
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_EDIT_TEXT:
|
|
switch (state)
|
|
{
|
|
case GTK_STATE_PRELIGHT:
|
|
ret = ETS_FOCUSED;
|
|
break;
|
|
|
|
case GTK_STATE_INSENSITIVE:
|
|
ret = ETS_READONLY;
|
|
break;
|
|
|
|
case GTK_STATE_SELECTED:
|
|
case GTK_STATE_ACTIVE:
|
|
default:
|
|
ret = ETS_NORMAL;
|
|
}
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_TROUGH_H:
|
|
case XP_THEME_ELEMENT_TROUGH_V:
|
|
ret = SCRBS_NORMAL;
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_SCROLLBAR_H:
|
|
case XP_THEME_ELEMENT_SCROLLBAR_V:
|
|
switch (state)
|
|
{
|
|
case GTK_STATE_SELECTED:
|
|
case GTK_STATE_ACTIVE:
|
|
ret = SCRBS_PRESSED;
|
|
break;
|
|
|
|
case GTK_STATE_PRELIGHT:
|
|
ret = SCRBS_HOT;
|
|
break;
|
|
|
|
case GTK_STATE_INSENSITIVE:
|
|
ret = SCRBS_DISABLED;
|
|
break;
|
|
|
|
default:
|
|
ret = SCRBS_NORMAL;
|
|
}
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_ARROW_DOWN:
|
|
switch (state)
|
|
{
|
|
case GTK_STATE_ACTIVE:
|
|
ret = ABS_DOWNPRESSED;
|
|
break;
|
|
|
|
case GTK_STATE_PRELIGHT:
|
|
ret = ABS_DOWNHOT;
|
|
break;
|
|
|
|
case GTK_STATE_INSENSITIVE:
|
|
ret = ABS_DOWNDISABLED;
|
|
break;
|
|
|
|
default:
|
|
ret = ABS_DOWNNORMAL;
|
|
}
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_ARROW_UP:
|
|
switch (state)
|
|
{
|
|
case GTK_STATE_ACTIVE:
|
|
ret = ABS_UPPRESSED;
|
|
break;
|
|
|
|
case GTK_STATE_PRELIGHT:
|
|
ret = ABS_UPHOT;
|
|
break;
|
|
|
|
case GTK_STATE_INSENSITIVE:
|
|
ret = ABS_UPDISABLED;
|
|
break;
|
|
|
|
default:
|
|
ret = ABS_UPNORMAL;
|
|
}
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_ARROW_LEFT:
|
|
switch (state)
|
|
{
|
|
case GTK_STATE_ACTIVE:
|
|
ret = ABS_LEFTPRESSED;
|
|
break;
|
|
|
|
case GTK_STATE_PRELIGHT:
|
|
ret = ABS_LEFTHOT;
|
|
break;
|
|
|
|
case GTK_STATE_INSENSITIVE:
|
|
ret = ABS_LEFTDISABLED;
|
|
break;
|
|
|
|
default:
|
|
ret = ABS_LEFTNORMAL;
|
|
}
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_ARROW_RIGHT:
|
|
switch (state)
|
|
{
|
|
case GTK_STATE_ACTIVE:
|
|
ret = ABS_RIGHTPRESSED;
|
|
break;
|
|
|
|
case GTK_STATE_PRELIGHT:
|
|
ret = ABS_RIGHTHOT;
|
|
break;
|
|
|
|
case GTK_STATE_INSENSITIVE:
|
|
ret = ABS_RIGHTDISABLED;
|
|
break;
|
|
|
|
default:
|
|
ret = ABS_RIGHTNORMAL;
|
|
}
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_CHECKBOX:
|
|
case XP_THEME_ELEMENT_RADIO_BUTTON:
|
|
switch (state)
|
|
{
|
|
case GTK_STATE_SELECTED:
|
|
ret = CBS_UNCHECKEDPRESSED;
|
|
break;
|
|
|
|
case GTK_STATE_PRELIGHT:
|
|
ret = CBS_UNCHECKEDHOT;
|
|
break;
|
|
|
|
case GTK_STATE_INSENSITIVE:
|
|
ret = CBS_UNCHECKEDDISABLED;
|
|
break;
|
|
|
|
default:
|
|
ret = CBS_UNCHECKEDNORMAL;
|
|
}
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_INCONSISTENT_CHECKBOX:
|
|
switch (state)
|
|
{
|
|
case GTK_STATE_SELECTED:
|
|
ret = CBS_MIXEDPRESSED;
|
|
break;
|
|
|
|
case GTK_STATE_PRELIGHT:
|
|
ret = CBS_MIXEDHOT;
|
|
break;
|
|
|
|
case GTK_STATE_INSENSITIVE:
|
|
ret = CBS_MIXEDDISABLED;
|
|
break;
|
|
|
|
default:
|
|
ret = CBS_MIXEDNORMAL;
|
|
}
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_PRESSED_CHECKBOX:
|
|
case XP_THEME_ELEMENT_PRESSED_RADIO_BUTTON:
|
|
switch (state)
|
|
{
|
|
case GTK_STATE_SELECTED:
|
|
ret = CBS_CHECKEDPRESSED;
|
|
break;
|
|
|
|
case GTK_STATE_PRELIGHT:
|
|
ret = CBS_CHECKEDHOT;
|
|
break;
|
|
|
|
case GTK_STATE_INSENSITIVE:
|
|
ret = CBS_CHECKEDDISABLED;
|
|
break;
|
|
|
|
default:
|
|
ret = CBS_CHECKEDNORMAL;
|
|
}
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_DEFAULT_BUTTON:
|
|
switch (state)
|
|
{
|
|
case GTK_STATE_ACTIVE:
|
|
ret = PBS_PRESSED;
|
|
break;
|
|
|
|
case GTK_STATE_PRELIGHT:
|
|
ret = PBS_HOT;
|
|
break;
|
|
|
|
case GTK_STATE_INSENSITIVE:
|
|
ret = PBS_DISABLED;
|
|
break;
|
|
|
|
default:
|
|
ret = PBS_DEFAULTED;
|
|
}
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_SPIN_BUTTON_DOWN:
|
|
switch (state)
|
|
{
|
|
case GTK_STATE_ACTIVE:
|
|
ret = DNS_PRESSED;
|
|
break;
|
|
|
|
case GTK_STATE_PRELIGHT:
|
|
ret = DNS_HOT;
|
|
break;
|
|
|
|
case GTK_STATE_INSENSITIVE:
|
|
ret = DNS_DISABLED;
|
|
break;
|
|
|
|
default:
|
|
ret = DNS_NORMAL;
|
|
}
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_SPIN_BUTTON_UP:
|
|
switch (state)
|
|
{
|
|
case GTK_STATE_ACTIVE:
|
|
ret = UPS_PRESSED;
|
|
break;
|
|
|
|
case GTK_STATE_PRELIGHT:
|
|
ret = UPS_HOT;
|
|
break;
|
|
|
|
case GTK_STATE_INSENSITIVE:
|
|
ret = UPS_DISABLED;
|
|
break;
|
|
|
|
default:
|
|
ret = UPS_NORMAL;
|
|
}
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_TREEVIEW_EXPANDER_OPENED:
|
|
ret = GLPS_OPENED;
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_TREEVIEW_EXPANDER_CLOSED:
|
|
ret = GLPS_CLOSED;
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_PROGRESS_BAR_H:
|
|
case XP_THEME_ELEMENT_PROGRESS_BAR_V:
|
|
case XP_THEME_ELEMENT_PROGRESS_TROUGH_H:
|
|
case XP_THEME_ELEMENT_PROGRESS_TROUGH_V:
|
|
ret = 1;
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_MENU_SEPARATOR:
|
|
ret = TS_NORMAL;
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_MENU_ITEM:
|
|
switch (state)
|
|
{
|
|
case GTK_STATE_SELECTED:
|
|
ret = MS_SELECTED;
|
|
break;
|
|
|
|
case GTK_STATE_PRELIGHT:
|
|
ret = MBI_HOT;
|
|
break;
|
|
|
|
case GTK_STATE_INSENSITIVE:
|
|
ret = MBI_DISABLED;
|
|
break;
|
|
|
|
default:
|
|
ret = MBI_NORMAL;
|
|
}
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_LINE_H:
|
|
switch (state)
|
|
{
|
|
/* LHS_FLAT, LHS_RAISED, LHS_SUNKEN */
|
|
ret = LHS_RAISED;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_LINE_V:
|
|
switch (state)
|
|
{
|
|
/* LVS_FLAT, LVS_RAISED, LVS_SUNKEN */
|
|
ret = LVS_RAISED;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case XP_THEME_ELEMENT_SCALE_TROUGH_H:
|
|
case XP_THEME_ELEMENT_SCALE_TROUGH_V:
|
|
ret = TRS_NORMAL;
|
|
break;
|
|
|
|
default:
|
|
switch (state)
|
|
{
|
|
case GTK_STATE_ACTIVE:
|
|
ret = PBS_PRESSED;
|
|
break;
|
|
|
|
case GTK_STATE_PRELIGHT:
|
|
ret = PBS_HOT;
|
|
break;
|
|
|
|
case GTK_STATE_INSENSITIVE:
|
|
ret = PBS_DISABLED;
|
|
break;
|
|
|
|
default:
|
|
ret = PBS_NORMAL;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
HDC
|
|
get_window_dc (GtkStyle *style,
|
|
cairo_t *cr,
|
|
GtkStateType state_type,
|
|
XpDCInfo *dc_info_out,
|
|
gint x, gint y, gint width, gint height,
|
|
RECT *rect_out)
|
|
{
|
|
HDC hDC, hTempDC;
|
|
HBITMAP hBitmap, hOldBitmap;
|
|
cairo_surface_t *sourceCS, *tempCS;
|
|
cairo_t *tempCR;
|
|
double x_off = 0, y_off = 0;
|
|
|
|
dc_info_out->hdc = NULL;
|
|
|
|
hDC = GetDC(NULL);
|
|
hTempDC = CreateCompatibleDC(hDC);
|
|
hBitmap = CreateCompatibleBitmap(hDC, x + width, y + height);
|
|
hOldBitmap = (HBITMAP)SelectObject(hTempDC, hBitmap);
|
|
ReleaseDC(NULL, hDC);
|
|
|
|
tempCS = cairo_win32_surface_create (hTempDC);
|
|
if (!tempCS)
|
|
return NULL;
|
|
|
|
sourceCS = cairo_get_target (cr);
|
|
tempCR = cairo_create (tempCS);
|
|
|
|
/* FIXME: I am missing something here - why is it needed to have device
|
|
* for cairo_set_source_surface() ? */
|
|
cairo_surface_get_device_offset (sourceCS, &x_off, &y_off);
|
|
cairo_set_source_surface (tempCR, sourceCS, x_off, y_off);
|
|
cairo_set_operator (tempCR, CAIRO_OPERATOR_OVER);
|
|
/* FIXME: Something is not quit right here - seems the CR or SURFACE do
|
|
* not always have the correct data. Hovering on a GtkToolbar from
|
|
* left to right draws the previous button over the next for ex. */
|
|
cairo_rectangle (tempCR, x, y, width, height);
|
|
cairo_fill (tempCR);
|
|
|
|
cairo_destroy (tempCR);
|
|
|
|
cairo_surface_flush (tempCS);
|
|
cairo_surface_destroy (tempCS);
|
|
|
|
rect_out->left = x;
|
|
rect_out->top = y;
|
|
rect_out->right = rect_out->left + width;
|
|
rect_out->bottom = rect_out->top + height;
|
|
|
|
dc_info_out->hdc = hTempDC;
|
|
dc_info_out->hBitmap = hBitmap;
|
|
dc_info_out->hOldBitmap = hOldBitmap;
|
|
dc_info_out->cr = cr;
|
|
dc_info_out->x = x;
|
|
dc_info_out->y = y;
|
|
dc_info_out->width = width;
|
|
dc_info_out->height = height;
|
|
|
|
return hTempDC;
|
|
}
|
|
|
|
void
|
|
release_window_dc (XpDCInfo *dc_info)
|
|
{
|
|
cairo_surface_t *tempCS, *target;
|
|
|
|
if (!dc_info->hdc)
|
|
return;
|
|
|
|
tempCS = cairo_win32_surface_create (dc_info->hdc);
|
|
target = cairo_get_target (dc_info->cr);
|
|
|
|
cairo_save (dc_info->cr);
|
|
|
|
cairo_set_source_surface (dc_info->cr, tempCS, 0, 0);
|
|
cairo_set_operator (dc_info->cr, CAIRO_OPERATOR_OVER);
|
|
cairo_rectangle (dc_info->cr, dc_info->x, dc_info->y, dc_info->width, dc_info->height);
|
|
cairo_fill (dc_info->cr);
|
|
|
|
cairo_restore (dc_info->cr);
|
|
|
|
cairo_surface_destroy (tempCS);
|
|
|
|
SelectObject(dc_info->hdc, dc_info->hOldBitmap);
|
|
DeleteDC(dc_info->hdc);
|
|
DeleteObject(dc_info->hBitmap);
|
|
|
|
dc_info->hdc = NULL;
|
|
}
|
|
|
|
gboolean
|
|
xp_theme_draw (cairo_t *cr, XpThemeElement element, GtkStyle *style,
|
|
int x, int y, int width, int height,
|
|
GtkStateType state_type)
|
|
{
|
|
HTHEME theme;
|
|
RECT rect;
|
|
HDC dc;
|
|
XpDCInfo dc_info;
|
|
int part_state;
|
|
|
|
if (!xp_theme_is_drawable (element))
|
|
return FALSE;
|
|
|
|
theme = xp_theme_get_handle_by_element (element);
|
|
if (!theme)
|
|
return FALSE;
|
|
|
|
/* FIXME: Recheck its function */
|
|
// if (GDK_IS_WINDOW (win) && gdk_win32_window_is_win32 (win))
|
|
// enable_theme_dialog_texture_func (GDK_WINDOW_HWND (win), ETDT_ENABLETAB);
|
|
|
|
dc = get_window_dc (style, cr, state_type, &dc_info,
|
|
x, y, width, height,
|
|
&rect);
|
|
if (!dc)
|
|
return FALSE;
|
|
|
|
part_state = xp_theme_map_gtk_state (element, state_type);
|
|
|
|
/* Support transparency */
|
|
// if (is_theme_partially_transparent_func (theme, element_part_map[element], part_state))
|
|
// draw_theme_parent_background_func (GDK_WINDOW_HWND (win), dc, pClip);
|
|
|
|
/* FIXME: Should we get and handle clipping (check it on the CR?) ? */
|
|
draw_theme_background_func (theme, dc, element_part_map[element],
|
|
part_state, &rect, NULL);
|
|
|
|
release_window_dc (&dc_info);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
gboolean
|
|
xp_theme_is_active (void)
|
|
{
|
|
return use_xp_theme;
|
|
}
|
|
|
|
gboolean
|
|
xp_theme_is_drawable (XpThemeElement element)
|
|
{
|
|
if (xp_theme_is_active ())
|
|
return (xp_theme_get_handle_by_element (element) != NULL);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
gboolean
|
|
xp_theme_get_element_dimensions (XpThemeElement element,
|
|
GtkStateType state_type,
|
|
gint *cx, gint *cy)
|
|
{
|
|
HTHEME theme;
|
|
SIZE part_size;
|
|
int part_state;
|
|
|
|
if (!xp_theme_is_active ())
|
|
return FALSE;
|
|
|
|
theme = xp_theme_get_handle_by_element (element);
|
|
if (!theme)
|
|
return FALSE;
|
|
|
|
part_state = xp_theme_map_gtk_state (element, state_type);
|
|
|
|
get_theme_part_size_func (theme,
|
|
NULL,
|
|
element_part_map[element],
|
|
part_state,
|
|
NULL,
|
|
TS_MIN,
|
|
&part_size);
|
|
|
|
*cx = part_size.cx;
|
|
*cy = part_size.cy;
|
|
|
|
if (element == XP_THEME_ELEMENT_MENU_ITEM ||
|
|
element == XP_THEME_ELEMENT_MENU_SEPARATOR)
|
|
{
|
|
SIZE gutter_size;
|
|
|
|
get_theme_part_size_func (theme,
|
|
NULL,
|
|
MENU_POPUPGUTTER,
|
|
0,
|
|
NULL,
|
|
TS_MIN,
|
|
&gutter_size);
|
|
|
|
*cx += gutter_size.cx * 2;
|
|
*cy += gutter_size.cy * 2;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
gboolean
|
|
xp_theme_get_system_font (XpThemeClass klazz, XpThemeFont fontId,
|
|
OUT LOGFONTW *lf)
|
|
{
|
|
if (xp_theme_is_active () && get_theme_sys_font_func != NULL)
|
|
{
|
|
HTHEME theme = xp_theme_get_handle_by_class (klazz);
|
|
int themeFont;
|
|
|
|
if (!theme)
|
|
return FALSE;
|
|
|
|
switch (fontId)
|
|
{
|
|
case XP_THEME_FONT_CAPTION:
|
|
themeFont = TMT_CAPTIONFONT;
|
|
break;
|
|
|
|
case XP_THEME_FONT_MENU:
|
|
themeFont = TMT_MENUFONT;
|
|
break;
|
|
|
|
case XP_THEME_FONT_STATUS:
|
|
themeFont = TMT_STATUSFONT;
|
|
break;
|
|
|
|
case XP_THEME_FONT_MESSAGE:
|
|
default:
|
|
themeFont = TMT_MSGBOXFONT;
|
|
break;
|
|
}
|
|
|
|
/* if theme is NULL, it will just return the GetSystemFont()
|
|
value */
|
|
return ((*get_theme_sys_font_func) (theme, themeFont, lf) == S_OK);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
gboolean
|
|
xp_theme_get_system_color (XpThemeClass klazz, int colorId,
|
|
OUT DWORD *pColor)
|
|
{
|
|
if (xp_theme_is_active () && get_theme_sys_color_func != NULL)
|
|
{
|
|
HTHEME theme = xp_theme_get_handle_by_class (klazz);
|
|
|
|
/* if theme is NULL, it will just return the GetSystemColor()
|
|
value */
|
|
*pColor = (*get_theme_sys_color_func) (theme, colorId);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
gboolean
|
|
xp_theme_get_system_metric (XpThemeClass klazz, int metricId, OUT int *pVal)
|
|
{
|
|
if (xp_theme_is_active () && get_theme_sys_metric_func != NULL)
|
|
{
|
|
HTHEME theme = xp_theme_get_handle_by_class (klazz);
|
|
|
|
/* if theme is NULL, it will just return the GetSystemMetrics()
|
|
value */
|
|
*pVal = (*get_theme_sys_metric_func) (theme, metricId);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|