mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Handle child window position changes
Fixes Loyalty window getting clipped while dragging it in Star Wars Rebellion.
This commit is contained in:
parent
4d46189aa8
commit
4eb28cc596
@ -1,6 +1,7 @@
|
||||
#include <utility>
|
||||
|
||||
#include "Gdi/Region.h"
|
||||
#include <Common/Hook.h>
|
||||
#include <Gdi/Region.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -24,6 +25,14 @@ namespace Gdi
|
||||
{
|
||||
}
|
||||
|
||||
Region::Region(HWND hwnd)
|
||||
: m_region(CreateRectRgn(0, 0, 0, 0))
|
||||
{
|
||||
HDC dc = GetWindowDC(hwnd);
|
||||
GetRandomRgn(dc, m_region, SYSRGN);
|
||||
CALL_ORIG_FUNC(ReleaseDC)(hwnd, dc);
|
||||
}
|
||||
|
||||
Region::~Region()
|
||||
{
|
||||
if (m_region)
|
||||
|
@ -9,6 +9,7 @@ namespace Gdi
|
||||
public:
|
||||
Region(HRGN rgn);
|
||||
Region(const RECT& rect = RECT{ 0, 0, 0, 0 });
|
||||
Region(HWND hwnd);
|
||||
~Region();
|
||||
Region(const Region& other);
|
||||
Region(Region&& other);
|
||||
|
@ -3,23 +3,33 @@
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include "Common/Hook.h"
|
||||
#include "Common/Log.h"
|
||||
#include "Common/ScopedCriticalSection.h"
|
||||
#include "Gdi/AccessGuard.h"
|
||||
#include "Gdi/Dc.h"
|
||||
#include "Win32/DisplayMode.h"
|
||||
#include "Gdi/PaintHandlers.h"
|
||||
#include "Gdi/ScrollBar.h"
|
||||
#include "Gdi/ScrollFunctions.h"
|
||||
#include "Gdi/TitleBar.h"
|
||||
#include "Gdi/Window.h"
|
||||
#include "Gdi/WinProc.h"
|
||||
#include <Common/Hook.h>
|
||||
#include <Common/Log.h>
|
||||
#include <Common/ScopedCriticalSection.h>
|
||||
#include <Gdi/AccessGuard.h>
|
||||
#include <Gdi/Dc.h>
|
||||
#include <Win32/DisplayMode.h>
|
||||
#include <Gdi/PaintHandlers.h>
|
||||
#include <Gdi/ScrollBar.h>
|
||||
#include <Gdi/ScrollFunctions.h>
|
||||
#include <Gdi/TitleBar.h>
|
||||
#include <Gdi/Window.h>
|
||||
#include <Gdi/WinProc.h>
|
||||
|
||||
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
||||
|
||||
namespace
|
||||
{
|
||||
const char* PROP_DDRAWCOMPAT = "DDrawCompat";
|
||||
|
||||
struct ChildWindowInfo
|
||||
{
|
||||
RECT rect;
|
||||
Gdi::Region visibleRegion;
|
||||
|
||||
ChildWindowInfo() : rect{} {}
|
||||
};
|
||||
|
||||
std::multimap<DWORD, HHOOK> g_threadIdToHook;
|
||||
Compat::CriticalSection g_threadIdToHookCs;
|
||||
HWINEVENTHOOK g_objectCreateEventHook = nullptr;
|
||||
@ -30,6 +40,7 @@ namespace
|
||||
void onCreateWindow(HWND hwnd);
|
||||
void onDestroyWindow(HWND hwnd);
|
||||
void onWindowPosChanged(HWND hwnd);
|
||||
void onWindowPosChanging(HWND hwnd, const WINDOWPOS& wp);
|
||||
|
||||
LRESULT CALLBACK callWndRetProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
@ -68,6 +79,10 @@ namespace
|
||||
case WM_WINDOWPOSCHANGED:
|
||||
onWindowPosChanged(ret->hwnd);
|
||||
break;
|
||||
|
||||
case WM_WINDOWPOSCHANGING:
|
||||
onWindowPosChanging(ret->hwnd, *reinterpret_cast<WINDOWPOS*>(ret->lParam));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,6 +205,7 @@ namespace
|
||||
void onDestroyWindow(HWND hwnd)
|
||||
{
|
||||
Gdi::Window::remove(hwnd);
|
||||
delete reinterpret_cast<ChildWindowInfo*>(RemoveProp(hwnd, PROP_DDRAWCOMPAT));
|
||||
}
|
||||
|
||||
void onWindowPosChanged(HWND hwnd)
|
||||
@ -209,10 +225,71 @@ namespace
|
||||
notifyFunc();
|
||||
}
|
||||
|
||||
if (Gdi::Window::get(hwnd) || Gdi::Window::add(hwnd))
|
||||
if (Gdi::Window::isTopLevelWindow(hwnd))
|
||||
{
|
||||
Gdi::Window::add(hwnd);
|
||||
Gdi::Window::updateAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::unique_ptr<ChildWindowInfo> cwi(reinterpret_cast<ChildWindowInfo*>(RemoveProp(hwnd, PROP_DDRAWCOMPAT)));
|
||||
if (cwi && IsWindowVisible(hwnd) && !IsIconic(GetAncestor(hwnd, GA_ROOT)))
|
||||
{
|
||||
RECT rect = {};
|
||||
GetWindowRect(hwnd, &rect);
|
||||
if (rect.left != cwi->rect.left || rect.top != cwi->rect.top)
|
||||
{
|
||||
Gdi::Region clipRegion(hwnd);
|
||||
cwi->visibleRegion.offset(rect.left - cwi->rect.left, rect.top - cwi->rect.top);
|
||||
clipRegion &= cwi->visibleRegion;
|
||||
|
||||
HDC screenDc = GetDC(nullptr);
|
||||
SelectClipRgn(screenDc, clipRegion);
|
||||
BitBlt(screenDc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
|
||||
screenDc, cwi->rect.left, cwi->rect.top, SRCCOPY);
|
||||
SelectClipRgn(screenDc, nullptr);
|
||||
CALL_ORIG_FUNC(ReleaseDC)(nullptr, screenDc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void onWindowPosChanging(HWND hwnd, const WINDOWPOS& wp)
|
||||
{
|
||||
if (!Gdi::Window::isTopLevelWindow(hwnd))
|
||||
{
|
||||
std::unique_ptr<ChildWindowInfo> cwi(reinterpret_cast<ChildWindowInfo*>(RemoveProp(hwnd, PROP_DDRAWCOMPAT)));
|
||||
if (!(wp.flags & SWP_NOMOVE) && IsWindowVisible(hwnd) && !IsIconic(GetAncestor(hwnd, GA_ROOT)))
|
||||
{
|
||||
cwi.reset(new ChildWindowInfo());
|
||||
GetWindowRect(hwnd, &cwi->rect);
|
||||
cwi->visibleRegion = hwnd;
|
||||
if (!cwi->visibleRegion.isEmpty())
|
||||
{
|
||||
SetProp(hwnd, PROP_DDRAWCOMPAT, cwi.release());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL WINAPI setWindowPos(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags)
|
||||
{
|
||||
LOG_FUNC("SetWindowPos", hWnd, hWndInsertAfter, X, Y, cx, cy, Compat::hex(uFlags));
|
||||
if (uFlags & SWP_NOSENDCHANGING)
|
||||
{
|
||||
WINDOWPOS wp = {};
|
||||
wp.hwnd = hWnd;
|
||||
wp.hwndInsertAfter = hWndInsertAfter;
|
||||
wp.x = X;
|
||||
wp.y = Y;
|
||||
wp.cx = cx;
|
||||
wp.cy = cy;
|
||||
wp.flags = uFlags;
|
||||
onWindowPosChanging(hWnd, wp);
|
||||
}
|
||||
BOOL result = CALL_ORIG_FUNC(SetWindowPos)(hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
|
||||
delete reinterpret_cast<ChildWindowInfo*>(RemoveProp(hWnd, PROP_DDRAWCOMPAT));
|
||||
return LOG_RESULT(result);
|
||||
}
|
||||
}
|
||||
|
||||
@ -236,6 +313,8 @@ namespace Gdi
|
||||
|
||||
void installHooks()
|
||||
{
|
||||
HOOK_FUNCTION(user32, SetWindowPos, setWindowPos);
|
||||
|
||||
g_objectCreateEventHook = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE,
|
||||
reinterpret_cast<HMODULE>(&__ImageBase), &objectCreateEvent,
|
||||
GetCurrentProcessId(), 0, WINEVENT_INCONTEXT);
|
||||
|
@ -1,11 +1,11 @@
|
||||
#include <dwmapi.h>
|
||||
|
||||
#include "Common/Hook.h"
|
||||
#include "Common/Log.h"
|
||||
#include "D3dDdi/ScopedCriticalSection.h"
|
||||
#include "DDraw/RealPrimarySurface.h"
|
||||
#include "Gdi/Gdi.h"
|
||||
#include "Gdi/Window.h"
|
||||
#include <Common/Hook.h>
|
||||
#include <Common/Log.h>
|
||||
#include <D3dDdi/ScopedCriticalSection.h>
|
||||
#include <DDraw/RealPrimarySurface.h>
|
||||
#include <Gdi/Gdi.h>
|
||||
#include <Gdi/Window.h>
|
||||
|
||||
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
||||
|
||||
@ -101,7 +101,8 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
SetWindowPos(hwnd, insertAfter, wr.left, wr.top, wr.right - wr.left, wr.bottom - wr.top, flags);
|
||||
CALL_ORIG_FUNC(SetWindowPos)(
|
||||
hwnd, insertAfter, wr.left, wr.top, wr.right - wr.left, wr.bottom - wr.top, flags);
|
||||
|
||||
HRGN rgn = CreateRectRgn(0, 0, 0, 0);
|
||||
if (ERROR != GetWindowRgn(owner, rgn))
|
||||
@ -271,7 +272,7 @@ namespace Gdi
|
||||
oldWindowRect.right - oldWindowRect.left, oldWindowRect.bottom - oldWindowRect.top,
|
||||
screenDc, oldWindowRect.left, oldWindowRect.top, SRCCOPY);
|
||||
SelectClipRgn(screenDc, nullptr);
|
||||
ReleaseDC(nullptr, screenDc);
|
||||
CALL_ORIG_FUNC(ReleaseDC)(nullptr, screenDc);
|
||||
}
|
||||
m_invalidatedRegion -= preservedRegion;
|
||||
}
|
||||
@ -423,9 +424,7 @@ namespace Gdi
|
||||
GetWindowRect(m_hwnd, &newWindowRect);
|
||||
if (!IsRectEmpty(&newWindowRect) && !m_isLayered)
|
||||
{
|
||||
HDC windowDc = GetWindowDC(m_hwnd);
|
||||
GetRandomRgn(windowDc, newVisibleRegion, SYSRGN);
|
||||
CALL_ORIG_FUNC(ReleaseDC)(m_hwnd, windowDc);
|
||||
newVisibleRegion = m_hwnd;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user