Author: gadamopoulos
Date: Fri Jan 17 17:52:58 2014
New Revision: 61654
URL:
http://svn.reactos.org/svn/reactos?rev=61654&view=rev
Log:
[uxtheme]
- Greatly reduce needless repaints in the non client area but remembering the last hittest
of the mouse events to redraw it only when it is needed
- Do not reset the theme region every time we move a window, also make sure we try to set
a theme region only when it is needed
- Do not use OpenThemeData but use MSSTYLES_OpenThemeClass directly
- Do not reload the active theme every time we get a WM_THEMECHANGED message, make sure to
see if the active theme was already loaded before trying to load it again
- See CORE-7775
Modified:
trunk/reactos/dll/win32/uxtheme/nonclient.c
trunk/reactos/dll/win32/uxtheme/system.c
trunk/reactos/dll/win32/uxtheme/themehooks.c
trunk/reactos/dll/win32/uxtheme/uxthemep.h
Modified: trunk/reactos/dll/win32/uxtheme/nonclient.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/uxtheme/nonclien…
==============================================================================
--- trunk/reactos/dll/win32/uxtheme/nonclient.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/uxtheme/nonclient.c [iso-8859-1] Fri Jan 17 17:52:58 2014
@@ -155,9 +155,8 @@
GetWindowInfo(hWnd, &pcontext->wi);
pcontext->hWnd = hWnd;
pcontext->Active = IsWindowActive(hWnd, pcontext->wi.dwExStyle);
- pcontext->hPrevTheme = GetPropW(hWnd, (LPCWSTR)MAKEINTATOM(atWindowTheme));
- pcontext->theme = OpenThemeData(pcontext->hWnd, L"WINDOW");
- pcontext->scrolltheme = OpenThemeData(pcontext->hWnd,
L"SCROLLBAR");
+ pcontext->theme = MSSTYLES_OpenThemeClass(ActiveThemeFile, NULL,
L"WINDOW");
+ pcontext->scrolltheme = MSSTYLES_OpenThemeClass(ActiveThemeFile, NULL,
L"SCROLLBAR");
pcontext->CaptionHeight = pcontext->wi.cyWindowBorders;
pcontext->CaptionHeight += GetSystemMetrics(pcontext->wi.dwExStyle &
WS_EX_TOOLWINDOW ? SM_CYSMCAPTION : SM_CYCAPTION );
@@ -178,8 +177,6 @@
CloseThemeData (pcontext->theme);
CloseThemeData (pcontext->scrolltheme);
-
- SetPropW(pcontext->hWnd, (LPCWSTR)MAKEINTATOM(atWindowTheme),
pcontext->hPrevTheme);
if(pcontext->hRgn != NULL)
{
@@ -289,10 +286,7 @@
{
RECT rcCurrent;
- /* Check if the window has caption buttons */
- if (!((pcontext->wi.dwStyle & WS_CAPTION) && (pcontext->wi.dwStyle
& WS_SYSMENU)))
- return ;
-
+ /* Calculate the area of the caption */
rcCurrent.top = rcCurrent.left = 0;
rcCurrent.right = pcontext->wi.rcWindow.right - pcontext->wi.rcWindow.left;
rcCurrent.bottom = pcontext->CaptionHeight;
@@ -336,7 +330,7 @@
/* Draw the caption background*/
rcPart = *prcCurrent;
- rcPart.bottom = pcontext->CaptionHeight;
+ rcPart.bottom = rcPart.top + pcontext->CaptionHeight;
prcCurrent->top = rcPart.bottom;
DrawThemeBackground(pcontext->theme,
pcontext->hDC,iPart,iState,&rcPart,NULL);
@@ -400,7 +394,7 @@
/* Draw the left border */
rcPart = *prcCurrent;
- rcPart.right = pcontext->wi.cxWindowBorders ;
+ rcPart.right = rcPart.left + pcontext->wi.cxWindowBorders ;
prcCurrent->left = rcPart.right;
DrawThemeBackground(pcontext->theme, pcontext->hDC,WP_FRAMELEFT, iState,
&rcPart, NULL);
@@ -684,28 +678,56 @@
{
DRAW_CONTEXT context;
TRACKMOUSEEVENT tme;
-
+ DWORD style;
+ PWND_CONTEXT pcontext;
+
+ /* First of all check if we have something to do here */
+ style = GetWindowLongW(hWnd, GWL_STYLE);
+ if((style & (WS_CAPTION|WS_HSCROLL|WS_VSCROLL))==0)
+ return 0;
+
+ /* Get theme data for this window */
+ pcontext = ThemeGetWndContext(hWnd);
+ if (pcontext == NULL)
+ return 0;
+
+ /* Begin tracking in the non client area if we are not tracking yet */
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_QUERY;
tme.hwndTrack = hWnd;
TrackMouseEvent(&tme);
- if (tme.dwFlags != (TME_LEAVE | TME_NONCLIENT))
+ if (tme.dwFlags != (TME_LEAVE | TME_NONCLIENT))
{
tme.hwndTrack = hWnd;
tme.dwFlags = TME_LEAVE | TME_NONCLIENT;
TrackMouseEvent(&tme);
}
+ /* Dont do any drawing if the hit test wasn't changed */
+ if (ht == pcontext->lastHitTest)
+ return 0;
+
ThemeInitDrawContext(&context, hWnd, 0);
- ThemeDrawCaptionButtons(&context, ht, 0);
-
- if(context.wi.dwStyle & WS_HSCROLL)
- ThemeDrawScrollBar(&context, SB_HORZ , ht == HTHSCROLL ? pt : NULL);
-
- if(context.wi.dwStyle & WS_VSCROLL)
- ThemeDrawScrollBar(&context, SB_VERT, ht == HTVSCROLL ? pt : NULL);
-
+ if (context.wi.dwStyle & WS_SYSMENU)
+ {
+ if (HT_ISBUTTON(ht) || HT_ISBUTTON(pcontext->lastHitTest))
+ ThemeDrawCaptionButtons(&context, ht, 0);
+ }
+
+ if (context.wi.dwStyle & WS_HSCROLL)
+ {
+ if (ht == HTHSCROLL || pcontext->lastHitTest == HTHSCROLL)
+ ThemeDrawScrollBar(&context, SB_HORZ , ht == HTHSCROLL ? pt : NULL);
+ }
+
+ if (context.wi.dwStyle & WS_VSCROLL)
+ {
+ if (ht == HTVSCROLL || pcontext->lastHitTest == HTVSCROLL)
+ ThemeDrawScrollBar(&context, SB_VERT, ht == HTVSCROLL ? pt : NULL);
+ }
ThemeCleanupDrawContext(&context);
+
+ pcontext->lastHitTest = ht;
return 0;
}
@@ -714,17 +736,32 @@
ThemeHandleNcMouseLeave(HWND hWnd)
{
DRAW_CONTEXT context;
+ DWORD style;
+ PWND_CONTEXT pWndContext;
+
+ /* First of all check if we have something to do here */
+ style = GetWindowLongW(hWnd, GWL_STYLE);
+ if((style & (WS_CAPTION|WS_HSCROLL|WS_VSCROLL))==0)
+ return 0;
+
+ /* Get theme data for this window */
+ pWndContext = ThemeGetWndContext(hWnd);
+ if (pWndContext == NULL)
+ return 0;
ThemeInitDrawContext(&context, hWnd, 0);
- ThemeDrawCaptionButtons(&context, 0, 0);
-
- if(context.wi.dwStyle & WS_HSCROLL)
- ThemeDrawScrollBar(&context, SB_HORZ, NULL);
-
- if(context.wi.dwStyle & WS_VSCROLL)
+ if (context.wi.dwStyle & WS_SYSMENU &&
HT_ISBUTTON(pWndContext->lastHitTest))
+ ThemeDrawCaptionButtons(&context, 0, 0);
+
+ if (context.wi.dwStyle & WS_HSCROLL && pWndContext->lastHitTest ==
HTHSCROLL)
+ ThemeDrawScrollBar(&context, SB_HORZ, NULL);
+
+ if (context.wi.dwStyle & WS_VSCROLL && pWndContext->lastHitTest ==
HTVSCROLL)
ThemeDrawScrollBar(&context, SB_VERT, NULL);
ThemeCleanupDrawContext(&context);
+
+ pWndContext->lastHitTest = HTNOWHERE;
return 0;
}
@@ -733,17 +770,19 @@
ThemeHandleButton(HWND hWnd, WPARAM wParam)
{
MSG Msg;
- BOOL Pressed = TRUE; // , OldState;
+ BOOL Pressed = TRUE;
WPARAM SCMsg, ht;
ULONG Style;
DRAW_CONTEXT context;
+ PWND_CONTEXT pWndContext;
Style = GetWindowLongW(hWnd, GWL_STYLE);
+ if (!((Style & WS_CAPTION) && (Style & WS_SYSMENU)))
+ return ;
+
switch (wParam)
{
case HTCLOSE:
- if (!(Style & WS_SYSMENU))
- return;
SCMsg = SC_CLOSE;
break;
case HTMINBUTTON:
@@ -760,8 +799,14 @@
return;
}
+ /* Get theme data for this window */
+ pWndContext = ThemeGetWndContext(hWnd);
+ if (pWndContext == NULL)
+ return;
+
ThemeInitDrawContext(&context, hWnd, 0);
ThemeDrawCaptionButtons(&context, 0, wParam);
+ pWndContext->lastHitTest = wParam;
SetCapture(hWnd);
@@ -776,14 +821,19 @@
if (Msg.message != WM_MOUSEMOVE)
continue;
- //OldState = Pressed;
ht = SendMessage(hWnd, WM_NCHITTEST, 0, MAKELPARAM(Msg.pt.x, Msg.pt.y));
Pressed = (ht == wParam);
- ThemeDrawCaptionButtons(&context, 0, Pressed ? wParam: 0);
- }
-
- ThemeDrawCaptionButtons(&context, 0, 0);
+ /* Only draw the buttons if the hit test changed */
+ if (ht != pWndContext->lastHitTest &&
+ (HT_ISBUTTON(ht) || HT_ISBUTTON(pWndContext->lastHitTest)))
+ {
+ ThemeDrawCaptionButtons(&context, 0, Pressed ? wParam: 0);
+ pWndContext->lastHitTest = ht;
+ }
+ }
+
+ ThemeDrawCaptionButtons(&context, ht, 0);
ThemeCleanupDrawContext(&context);
ReleaseCapture();
Modified: trunk/reactos/dll/win32/uxtheme/system.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/uxtheme/system.c…
==============================================================================
--- trunk/reactos/dll/win32/uxtheme/system.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/uxtheme/system.c [iso-8859-1] Fri Jan 17 17:52:58 2014
@@ -50,7 +50,7 @@
static ATOM atSubIdList;
ATOM atWndContrext;
-static PTHEME_FILE ActiveThemeFile;
+PTHEME_FILE ActiveThemeFile;
/***********************************************************************/
@@ -136,6 +136,39 @@
MSSTYLES_ParseThemeIni(ActiveThemeFile);
}
return S_OK;
+}
+
+static BOOL bIsThemeActive(LPCWSTR pszTheme, LPCWSTR pszColor, LPCWSTR pszSize)
+{
+ if (ActiveThemeFile == NULL)
+ return FALSE;
+
+ if (wcscmp(pszTheme, ActiveThemeFile->szThemeFile) != 0)
+ return FALSE;
+
+ if (!pszColor[0])
+ {
+ if (ActiveThemeFile->pszAvailColors != ActiveThemeFile->pszSelectedColor)
+ return FALSE;
+ }
+ else
+ {
+ if (wcscmp(pszColor, ActiveThemeFile->pszSelectedColor) != 0)
+ return FALSE;
+ }
+
+ if (!pszSize[0])
+ {
+ if (ActiveThemeFile->pszAvailSizes != ActiveThemeFile->pszSelectedSize)
+ return FALSE;
+ }
+ else
+ {
+ if (wcscmp(pszSize, ActiveThemeFile->pszSelectedSize) != 0)
+ return FALSE;
+ }
+
+ return TRUE;
}
/***********************************************************************
@@ -186,7 +219,14 @@
bThemeActive = FALSE;
}
- if(bThemeActive) {
+ if(bThemeActive)
+ {
+ if( bIsThemeActive(szCurrentTheme, szCurrentColor, szCurrentSize) )
+ {
+ TRACE("Tried to load active theme again\n");
+ return;
+ }
+
/* Make sure the theme requested is actually valid */
hr = MSSTYLES_OpenThemeFile(szCurrentTheme,
szCurrentColor[0]?szCurrentColor:NULL,
@@ -471,6 +511,8 @@
WCHAR tmp[2];
HRESULT hr;
+ TRACE("UXTHEME_ApplyTheme\n");
+
if (tf && !ActiveThemeFile)
{
UXTHEME_BackupSystemMetrics();
@@ -562,7 +604,7 @@
WCHAR tmp[10];
DWORD buffsize;
- TRACE("\n");
+ TRACE("IsThemeActive\n");
SetLastError(ERROR_SUCCESS);
if (ActiveThemeFile)
Modified: trunk/reactos/dll/win32/uxtheme/themehooks.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/uxtheme/themehoo…
==============================================================================
--- trunk/reactos/dll/win32/uxtheme/themehooks.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/uxtheme/themehooks.c [iso-8859-1] Fri Jan 17 17:52:58 2014
@@ -83,7 +83,7 @@
return TRUE;
}
-void SetThemeRegion(HWND hWnd, PWND_CONTEXT pcontext)
+void SetThemeRegion(HWND hWnd)
{
HTHEME hTheme;
RECT rcWindow;
@@ -91,24 +91,10 @@
int CaptionHeight, iPart;
WINDOWINFO wi;
- if(!IsAppThemed())
- {
- if(pcontext->HasThemeRgn)
- {
- pcontext->HasThemeRgn = FALSE;
- user32ApiHook.SetWindowRgn(hWnd, 0, TRUE);
- }
- return;
- }
+ TRACE("SetThemeRegion %d\n", hWnd);
wi.cbSize = sizeof(wi);
-
GetWindowInfo(hWnd, &wi);
-
- if((wi.dwStyle & WS_CAPTION)!=WS_CAPTION)
- {
- return;
- }
/* Get the caption part id */
if (wi.dwExStyle & WS_EX_TOOLWINDOW)
@@ -118,8 +104,6 @@
else
iPart = WP_CAPTION;
- pcontext->HasThemeRgn = TRUE;
-
CaptionHeight = wi.cyWindowBorders;
CaptionHeight += GetSystemMetrics(wi.dwExStyle & WS_EX_TOOLWINDOW ?
SM_CYSMCAPTION : SM_CYCAPTION );
@@ -129,10 +113,8 @@
rcWindow.top = 0;
rcWindow.left = 0;
- hTheme = OpenThemeData (hWnd, L"WINDOW");
-
+ hTheme = MSSTYLES_OpenThemeClass(ActiveThemeFile, NULL, L"WINDOW");
GetThemeBackgroundRegion(hTheme, 0, iPart, FS_ACTIVE, &rcWindow, &hrgn);
-
CloseThemeData(hTheme);
GetWindowRect(hWnd, &rcWindow);
@@ -149,21 +131,51 @@
user32ApiHook.SetWindowRgn(hWnd, hrgn, TRUE);
}
-int OnPostWinPosChanged(HWND hWnd)
-{
- PWND_CONTEXT pcontext = ThemeGetWndContext(hWnd);
-
- if(pcontext &&
- pcontext->HasAppDefinedRgn == FALSE &&
- pcontext->UpdatingRgn == FALSE)
- {
- pcontext->UpdatingRgn = TRUE;
- SetThemeRegion(hWnd, pcontext);
- pcontext = ThemeGetWndContext(hWnd);
- pcontext->UpdatingRgn = FALSE;
- }
- return 0;
-}
+int OnPostWinPosChanged(HWND hWnd, WINDOWPOS* pWinPos)
+{
+ PWND_CONTEXT pcontext;
+ DWORD style;
+
+ /* We only proceed to change the window shape if it has a caption */
+ style = GetWindowLongW(hWnd, GWL_STYLE);
+ if((style & WS_CAPTION)!=WS_CAPTION)
+ return 0;
+
+ /* Get theme data for this window */
+ pcontext = ThemeGetWndContext(hWnd);
+ if (pcontext == NULL)
+ return 0;
+
+ /* Do not change the region of the window if its size wasn't changed */
+ if ((pWinPos->flags & SWP_NOSIZE) != 0 &&
pcontext->DirtyThemeRegion == FALSE)
+ return 0;
+
+ /* We don't touch the shape of the window if the application sets it on its own
*/
+ if (pcontext->HasAppDefinedRgn == TRUE)
+ return 0;
+
+ /* Calling SetWindowRgn will call SetWindowPos again so we need to avoid this
recursion */
+ if (pcontext->UpdatingRgn == TRUE)
+ return 0;
+
+ if(!IsAppThemed())
+ {
+ if(pcontext->HasThemeRgn)
+ {
+ pcontext->HasThemeRgn = FALSE;
+ user32ApiHook.SetWindowRgn(hWnd, 0, TRUE);
+ }
+ return 0;
+ }
+
+ pcontext->DirtyThemeRegion = FALSE;
+ pcontext->HasThemeRgn = TRUE;
+ pcontext->UpdatingRgn = TRUE;
+ SetThemeRegion(hWnd);
+ pcontext->UpdatingRgn = FALSE;
+
+ return 0;
+ }
/**********************************************************************
* Hook Functions
@@ -172,7 +184,7 @@
static LRESULT CALLBACK
ThemeDefWindowProcW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
- if(!IsThemeActive())
+ if(!IsAppThemed())
{
return user32ApiHook.DefWindowProcW(hWnd,
Msg,
@@ -190,7 +202,7 @@
static LRESULT CALLBACK
ThemeDefWindowProcA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
- if(!IsThemeActive())
+ if(!IsAppThemed())
{
return user32ApiHook.DefWindowProcA(hWnd,
Msg,
@@ -211,8 +223,15 @@
switch(Msg)
{
case WM_THEMECHANGED:
- UXTHEME_LoadTheme(TRUE);
- return 0;
+ if (GetAncestor(hWnd, GA_PARENT) == GetDesktopWindow())
+ UXTHEME_LoadTheme(TRUE);
+ case WM_NCCREATE:
+ {
+ PWND_CONTEXT pcontext = ThemeGetWndContext(hWnd);
+ if (pcontext == NULL)
+ return 0;
+ pcontext->DirtyThemeRegion = TRUE;
+ }
}
return 0;
@@ -226,7 +245,7 @@
{
case WM_WINDOWPOSCHANGED:
{
- return OnPostWinPosChanged(hWnd);
+ return OnPostWinPosChanged(hWnd, (WINDOWPOS*)lParam);
}
case WM_DESTROY:
{
Modified: trunk/reactos/dll/win32/uxtheme/uxthemep.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/uxtheme/uxthemep…
==============================================================================
--- trunk/reactos/dll/win32/uxtheme/uxthemep.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/uxtheme/uxthemep.h [iso-8859-1] Fri Jan 17 17:52:58 2014
@@ -8,6 +8,7 @@
#include <windowsx.h>
#include <undocuser.h>
#include <uxtheme.h>
+#include <uxundoc.h>
#include <vfwmsgs.h>
#include <tmschema.h>
@@ -111,14 +112,17 @@
BOOL UXINI_FindValue(PUXINI_FILE uf, LPCWSTR lpName, LPCWSTR *lpValue, DWORD
*dwValueLen);
-
+/* The window context stores data for the window needed through the life of the window
*/
typedef struct _WND_CONTEXT
{
+ UINT lastHitTest;
BOOL HasAppDefinedRgn;
BOOL HasThemeRgn;
BOOL UpdatingRgn;
+ BOOL DirtyThemeRegion;
} WND_CONTEXT, *PWND_CONTEXT;
+/* The draw context stores data that are needed by the drawing operations in the non
client area of the window */
typedef struct _DRAW_CONTEXT
{
HWND hWnd;
@@ -168,6 +172,8 @@
SCROLL_BOTTOM_ARROW /* Bottom or right arrow */
};
+#define HT_ISBUTTON(ht) ((ht) == HTMINBUTTON || (ht) == HTMAXBUTTON || (ht) == HTCLOSE ||
(ht) == HTHELP)
+
#define HASSIZEGRIP(Style, ExStyle, ParentStyle, WindowRect, ParentClientRect) \
((!(Style & WS_CHILD) && (Style & WS_THICKFRAME) &&
!(Style & WS_MAXIMIZE)) || \
((Style & WS_CHILD) && (ParentStyle & WS_THICKFRAME)
&& !(ParentStyle & WS_MAXIMIZE) && \
@@ -208,6 +214,7 @@
extern ATOM atWindowTheme;
extern ATOM atWndContrext;
extern BOOL gbThemeHooksActive;
+extern PTHEME_FILE ActiveThemeFile;
void UXTHEME_InitSystem(HINSTANCE hInst);
void UXTHEME_LoadTheme(BOOL bLoad);