win-capture: Use DPI context for window BitBlt

Fixes GetClientRect and cursor position for windows unaware of DPI.

Only works on Windows 10 1607 and above.
This commit is contained in:
jpark37 2021-09-01 23:12:32 -07:00 committed by Jim
parent 9d6ecc8beb
commit 3706a21327

View File

@ -61,6 +61,11 @@ enum window_capture_method {
METHOD_WGC,
};
typedef DPI_AWARENESS_CONTEXT(WINAPI *PFN_SetThreadDpiAwarenessContext)(
DPI_AWARENESS_CONTEXT);
typedef DPI_AWARENESS_CONTEXT(WINAPI *PFN_GetThreadDpiAwarenessContext)(VOID);
typedef DPI_AWARENESS_CONTEXT(WINAPI *PFN_GetWindowDpiAwarenessContext)(HWND);
struct window_capture {
obs_source_t *source;
@ -89,6 +94,10 @@ struct window_capture {
HWND window;
RECT last_rect;
PFN_SetThreadDpiAwarenessContext set_thread_dpi_awareness_context;
PFN_GetThreadDpiAwarenessContext get_thread_dpi_awareness_context;
PFN_GetWindowDpiAwarenessContext get_window_dpi_awareness_context;
};
static const char *wgc_partial_match_classes[] = {
@ -254,6 +263,35 @@ static void *wc_create(obs_data_t *settings, obs_source_t *source)
}
}
const HMODULE hModuleUser32 = GetModuleHandle(L"User32.dll");
if (hModuleUser32) {
PFN_SetThreadDpiAwarenessContext
set_thread_dpi_awareness_context =
(PFN_SetThreadDpiAwarenessContext)GetProcAddress(
hModuleUser32,
"SetThreadDpiAwarenessContext");
PFN_GetThreadDpiAwarenessContext
get_thread_dpi_awareness_context =
(PFN_GetThreadDpiAwarenessContext)GetProcAddress(
hModuleUser32,
"GetThreadDpiAwarenessContext");
PFN_GetWindowDpiAwarenessContext
get_window_dpi_awareness_context =
(PFN_GetWindowDpiAwarenessContext)GetProcAddress(
hModuleUser32,
"GetWindowDpiAwarenessContext");
if (set_thread_dpi_awareness_context &&
get_thread_dpi_awareness_context &&
get_window_dpi_awareness_context) {
wc->set_thread_dpi_awareness_context =
set_thread_dpi_awareness_context;
wc->get_thread_dpi_awareness_context =
get_thread_dpi_awareness_context;
wc->get_window_dpi_awareness_context =
get_window_dpi_awareness_context;
}
}
update_settings(wc, settings);
log_settings(wc, settings);
return wc;
@ -523,6 +561,15 @@ static void wc_tick(void *data, float seconds)
obs_enter_graphics();
if (wc->method == METHOD_BITBLT) {
DPI_AWARENESS_CONTEXT previous = NULL;
if (wc->get_window_dpi_awareness_context != NULL) {
const DPI_AWARENESS_CONTEXT context =
wc->get_window_dpi_awareness_context(
wc->window);
previous =
wc->set_thread_dpi_awareness_context(context);
}
GetClientRect(wc->window, &rect);
if (!reset_capture) {
@ -552,6 +599,9 @@ static void wc_tick(void *data, float seconds)
}
dc_capture_capture(&wc->capture, wc->window);
if (previous)
wc->set_thread_dpi_awareness_context(previous);
} else if (wc->method == METHOD_WGC) {
if (wc->window && (wc->capture_winrt == NULL)) {
if (!wc->previously_failed) {