1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

Minimize invalidation on window position changes

This commit is contained in:
narzoul 2016-02-21 12:03:31 +01:00
parent 0244c8c022
commit 1ab496cbf5
4 changed files with 69 additions and 8 deletions

View File

@ -602,7 +602,7 @@ HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface<TSurface>::Restore(TSurface* T
result = RealPrimarySurface::restore(); result = RealPrimarySurface::restore();
if (wasLost) if (wasLost)
{ {
CompatGdi::invalidate(); CompatGdi::invalidate(nullptr);
} }
} }
} }

View File

@ -58,14 +58,33 @@ namespace
return nullptr; return nullptr;
} }
BOOL CALLBACK invalidateWindow(HWND hwnd, LPARAM /*lParam*/) BOOL CALLBACK invalidateWindow(HWND hwnd, LPARAM lParam)
{ {
if (!IsWindowVisible(hwnd))
{
return TRUE;
}
DWORD processId = 0; DWORD processId = 0;
GetWindowThreadProcessId(hwnd, &processId); GetWindowThreadProcessId(hwnd, &processId);
if (processId == GetCurrentProcessId()) if (processId != GetCurrentProcessId())
{
return TRUE;
}
if (lParam)
{
POINT origin = {};
ClientToScreen(hwnd, &origin);
RECT rect = *reinterpret_cast<const RECT*>(lParam);
OffsetRect(&rect, -origin.x, -origin.y);
RedrawWindow(hwnd, &rect, nullptr, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
}
else
{ {
RedrawWindow(hwnd, nullptr, nullptr, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN); RedrawWindow(hwnd, nullptr, nullptr, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
} }
return TRUE; return TRUE;
} }
@ -237,9 +256,9 @@ namespace CompatGdi
} }
} }
void invalidate() void invalidate(const RECT* rect)
{ {
EnumWindows(&invalidateWindow, 0); EnumWindows(&invalidateWindow, reinterpret_cast<LPARAM>(rect));
} }
void updatePalette() void updatePalette()
@ -257,7 +276,7 @@ namespace CompatGdi
if (0 != memcmp(usedPaletteEntries, g_usedPaletteEntries, sizeof(usedPaletteEntries))) if (0 != memcmp(usedPaletteEntries, g_usedPaletteEntries, sizeof(usedPaletteEntries)))
{ {
invalidate(); invalidate(nullptr);
} }
} }
} }

View File

@ -45,6 +45,6 @@ namespace CompatGdi
} }
void installHooks(); void installHooks();
void invalidate(); void invalidate(const RECT* rect);
void updatePalette(); void updatePalette();
}; };

View File

@ -1,5 +1,7 @@
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <unordered_map>
#include <dwmapi.h> #include <dwmapi.h>
#include <Windows.h> #include <Windows.h>
@ -12,9 +14,13 @@
namespace namespace
{ {
std::unordered_map<HWND, RECT> g_prevWindowRect;
void disableDwmAttributes(HWND hwnd); void disableDwmAttributes(HWND hwnd);
void eraseBackground(HWND hwnd, HDC dc); void eraseBackground(HWND hwnd, HDC dc);
void ncPaint(HWND hwnd); void ncPaint(HWND hwnd);
void onWindowPosChanged(HWND hwnd);
void removeDropShadow(HWND hwnd);
void updateScrolledWindow(HWND hwnd); void updateScrolledWindow(HWND hwnd);
LRESULT CALLBACK callWndRetProc(int nCode, WPARAM wParam, LPARAM lParam) LRESULT CALLBACK callWndRetProc(int nCode, WPARAM wParam, LPARAM lParam)
@ -25,6 +31,12 @@ namespace
if (WM_CREATE == ret->message) if (WM_CREATE == ret->message)
{ {
disableDwmAttributes(ret->hwnd); disableDwmAttributes(ret->hwnd);
removeDropShadow(ret->hwnd);
}
else if (WM_DESTROY == ret->message)
{
CompatGdi::GdiScopedThreadLock lock;
g_prevWindowRect.erase(ret->hwnd);
} }
else if (WM_ERASEBKGND == ret->message) else if (WM_ERASEBKGND == ret->message)
{ {
@ -42,7 +54,7 @@ namespace
} }
else if (WM_WINDOWPOSCHANGED == ret->message) else if (WM_WINDOWPOSCHANGED == ret->message)
{ {
CompatGdi::invalidate(); onWindowPosChanged(ret->hwnd);
} }
else if (WM_VSCROLL == ret->message || WM_HSCROLL == ret->message) else if (WM_VSCROLL == ret->message || WM_HSCROLL == ret->message)
{ {
@ -201,6 +213,36 @@ namespace
} }
} }
void onWindowPosChanged(HWND hwnd)
{
CompatGdi::GdiScopedThreadLock lock;
const auto it = g_prevWindowRect.find(hwnd);
if (it != g_prevWindowRect.end())
{
CompatGdi::invalidate(&it->second);
}
if (IsWindowVisible(hwnd))
{
GetWindowRect(hwnd, it != g_prevWindowRect.end() ? &it->second : &g_prevWindowRect[hwnd]);
RedrawWindow(hwnd, nullptr, nullptr, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
}
else if (it != g_prevWindowRect.end())
{
g_prevWindowRect.erase(it);
}
}
void removeDropShadow(HWND hwnd)
{
const auto style = GetClassLongPtr(hwnd, GCL_STYLE);
if (style & CS_DROPSHADOW)
{
SetClassLongPtr(hwnd, GCL_STYLE, style ^ CS_DROPSHADOW);
}
}
void updateScrolledWindow(HWND hwnd) void updateScrolledWindow(HWND hwnd)
{ {
RedrawWindow(hwnd, nullptr, nullptr, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE); RedrawWindow(hwnd, nullptr, nullptr, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE);