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 <utility>
|
||||||
|
|
||||||
#include "Gdi/Region.h"
|
#include <Common/Hook.h>
|
||||||
|
#include <Gdi/Region.h>
|
||||||
|
|
||||||
namespace
|
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()
|
Region::~Region()
|
||||||
{
|
{
|
||||||
if (m_region)
|
if (m_region)
|
||||||
|
@ -9,6 +9,7 @@ namespace Gdi
|
|||||||
public:
|
public:
|
||||||
Region(HRGN rgn);
|
Region(HRGN rgn);
|
||||||
Region(const RECT& rect = RECT{ 0, 0, 0, 0 });
|
Region(const RECT& rect = RECT{ 0, 0, 0, 0 });
|
||||||
|
Region(HWND hwnd);
|
||||||
~Region();
|
~Region();
|
||||||
Region(const Region& other);
|
Region(const Region& other);
|
||||||
Region(Region&& other);
|
Region(Region&& other);
|
||||||
|
@ -3,23 +3,33 @@
|
|||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
#include "Common/Hook.h"
|
#include <Common/Hook.h>
|
||||||
#include "Common/Log.h"
|
#include <Common/Log.h>
|
||||||
#include "Common/ScopedCriticalSection.h"
|
#include <Common/ScopedCriticalSection.h>
|
||||||
#include "Gdi/AccessGuard.h"
|
#include <Gdi/AccessGuard.h>
|
||||||
#include "Gdi/Dc.h"
|
#include <Gdi/Dc.h>
|
||||||
#include "Win32/DisplayMode.h"
|
#include <Win32/DisplayMode.h>
|
||||||
#include "Gdi/PaintHandlers.h"
|
#include <Gdi/PaintHandlers.h>
|
||||||
#include "Gdi/ScrollBar.h"
|
#include <Gdi/ScrollBar.h>
|
||||||
#include "Gdi/ScrollFunctions.h"
|
#include <Gdi/ScrollFunctions.h>
|
||||||
#include "Gdi/TitleBar.h"
|
#include <Gdi/TitleBar.h>
|
||||||
#include "Gdi/Window.h"
|
#include <Gdi/Window.h>
|
||||||
#include "Gdi/WinProc.h"
|
#include <Gdi/WinProc.h>
|
||||||
|
|
||||||
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
const char* PROP_DDRAWCOMPAT = "DDrawCompat";
|
||||||
|
|
||||||
|
struct ChildWindowInfo
|
||||||
|
{
|
||||||
|
RECT rect;
|
||||||
|
Gdi::Region visibleRegion;
|
||||||
|
|
||||||
|
ChildWindowInfo() : rect{} {}
|
||||||
|
};
|
||||||
|
|
||||||
std::multimap<DWORD, HHOOK> g_threadIdToHook;
|
std::multimap<DWORD, HHOOK> g_threadIdToHook;
|
||||||
Compat::CriticalSection g_threadIdToHookCs;
|
Compat::CriticalSection g_threadIdToHookCs;
|
||||||
HWINEVENTHOOK g_objectCreateEventHook = nullptr;
|
HWINEVENTHOOK g_objectCreateEventHook = nullptr;
|
||||||
@ -30,6 +40,7 @@ namespace
|
|||||||
void onCreateWindow(HWND hwnd);
|
void onCreateWindow(HWND hwnd);
|
||||||
void onDestroyWindow(HWND hwnd);
|
void onDestroyWindow(HWND hwnd);
|
||||||
void onWindowPosChanged(HWND hwnd);
|
void onWindowPosChanged(HWND hwnd);
|
||||||
|
void onWindowPosChanging(HWND hwnd, const WINDOWPOS& wp);
|
||||||
|
|
||||||
LRESULT CALLBACK callWndRetProc(int nCode, WPARAM wParam, LPARAM lParam)
|
LRESULT CALLBACK callWndRetProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
@ -68,6 +79,10 @@ namespace
|
|||||||
case WM_WINDOWPOSCHANGED:
|
case WM_WINDOWPOSCHANGED:
|
||||||
onWindowPosChanged(ret->hwnd);
|
onWindowPosChanged(ret->hwnd);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case WM_WINDOWPOSCHANGING:
|
||||||
|
onWindowPosChanging(ret->hwnd, *reinterpret_cast<WINDOWPOS*>(ret->lParam));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,6 +205,7 @@ namespace
|
|||||||
void onDestroyWindow(HWND hwnd)
|
void onDestroyWindow(HWND hwnd)
|
||||||
{
|
{
|
||||||
Gdi::Window::remove(hwnd);
|
Gdi::Window::remove(hwnd);
|
||||||
|
delete reinterpret_cast<ChildWindowInfo*>(RemoveProp(hwnd, PROP_DDRAWCOMPAT));
|
||||||
}
|
}
|
||||||
|
|
||||||
void onWindowPosChanged(HWND hwnd)
|
void onWindowPosChanged(HWND hwnd)
|
||||||
@ -209,10 +225,71 @@ namespace
|
|||||||
notifyFunc();
|
notifyFunc();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Gdi::Window::get(hwnd) || Gdi::Window::add(hwnd))
|
if (Gdi::Window::isTopLevelWindow(hwnd))
|
||||||
{
|
{
|
||||||
|
Gdi::Window::add(hwnd);
|
||||||
Gdi::Window::updateAll();
|
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()
|
void installHooks()
|
||||||
{
|
{
|
||||||
|
HOOK_FUNCTION(user32, SetWindowPos, setWindowPos);
|
||||||
|
|
||||||
g_objectCreateEventHook = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE,
|
g_objectCreateEventHook = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE,
|
||||||
reinterpret_cast<HMODULE>(&__ImageBase), &objectCreateEvent,
|
reinterpret_cast<HMODULE>(&__ImageBase), &objectCreateEvent,
|
||||||
GetCurrentProcessId(), 0, WINEVENT_INCONTEXT);
|
GetCurrentProcessId(), 0, WINEVENT_INCONTEXT);
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
#include <dwmapi.h>
|
#include <dwmapi.h>
|
||||||
|
|
||||||
#include "Common/Hook.h"
|
#include <Common/Hook.h>
|
||||||
#include "Common/Log.h"
|
#include <Common/Log.h>
|
||||||
#include "D3dDdi/ScopedCriticalSection.h"
|
#include <D3dDdi/ScopedCriticalSection.h>
|
||||||
#include "DDraw/RealPrimarySurface.h"
|
#include <DDraw/RealPrimarySurface.h>
|
||||||
#include "Gdi/Gdi.h"
|
#include <Gdi/Gdi.h>
|
||||||
#include "Gdi/Window.h"
|
#include <Gdi/Window.h>
|
||||||
|
|
||||||
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
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);
|
HRGN rgn = CreateRectRgn(0, 0, 0, 0);
|
||||||
if (ERROR != GetWindowRgn(owner, rgn))
|
if (ERROR != GetWindowRgn(owner, rgn))
|
||||||
@ -271,7 +272,7 @@ namespace Gdi
|
|||||||
oldWindowRect.right - oldWindowRect.left, oldWindowRect.bottom - oldWindowRect.top,
|
oldWindowRect.right - oldWindowRect.left, oldWindowRect.bottom - oldWindowRect.top,
|
||||||
screenDc, oldWindowRect.left, oldWindowRect.top, SRCCOPY);
|
screenDc, oldWindowRect.left, oldWindowRect.top, SRCCOPY);
|
||||||
SelectClipRgn(screenDc, nullptr);
|
SelectClipRgn(screenDc, nullptr);
|
||||||
ReleaseDC(nullptr, screenDc);
|
CALL_ORIG_FUNC(ReleaseDC)(nullptr, screenDc);
|
||||||
}
|
}
|
||||||
m_invalidatedRegion -= preservedRegion;
|
m_invalidatedRegion -= preservedRegion;
|
||||||
}
|
}
|
||||||
@ -423,9 +424,7 @@ namespace Gdi
|
|||||||
GetWindowRect(m_hwnd, &newWindowRect);
|
GetWindowRect(m_hwnd, &newWindowRect);
|
||||||
if (!IsRectEmpty(&newWindowRect) && !m_isLayered)
|
if (!IsRectEmpty(&newWindowRect) && !m_isLayered)
|
||||||
{
|
{
|
||||||
HDC windowDc = GetWindowDC(m_hwnd);
|
newVisibleRegion = m_hwnd;
|
||||||
GetRandomRgn(windowDc, newVisibleRegion, SYSRGN);
|
|
||||||
CALL_ORIG_FUNC(ReleaseDC)(m_hwnd, windowDc);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user