gdi32: Introduce user_callbacks.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2021-09-29 14:08:05 +02:00 committed by Alexandre Julliard
parent 8ebd516f9b
commit cdfcafafa1
9 changed files with 245 additions and 80 deletions

View File

@ -54,7 +54,8 @@ C_SRCS = \
uniscribe/shaping.c \
uniscribe/usp10.c \
vertical.c \
vulkan.c
vulkan.c \
wrappers.c
RC_SRCS = gdi32.rc

View File

@ -65,14 +65,6 @@ static CRITICAL_SECTION_DEBUG critsect_debug =
};
static CRITICAL_SECTION driver_section = { &critsect_debug, -1, 0, 0, 0, 0 };
static BOOL (WINAPI *pEnumDisplayMonitors)(HDC, LPRECT, MONITORENUMPROC, LPARAM);
static BOOL (WINAPI *pEnumDisplaySettingsW)(LPCWSTR, DWORD, LPDEVMODEW);
static HWND (WINAPI *pGetDesktopWindow)(void);
static BOOL (WINAPI *pGetMonitorInfoW)(HMONITOR, LPMONITORINFO);
static INT (WINAPI *pGetSystemMetrics)(INT);
static DPI_AWARENESS_CONTEXT (WINAPI *pSetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
/**********************************************************************
* get_display_driver
*
@ -82,10 +74,7 @@ const struct gdi_dc_funcs *get_display_driver(void)
{
if (!driver_funcs)
{
HMODULE user32 = LoadLibraryA( "user32.dll" );
pGetDesktopWindow = (void *)GetProcAddress( user32, "GetDesktopWindow" );
if (!pGetDesktopWindow() || !driver_funcs)
if (!user_callbacks || !user_callbacks->pGetDesktopWindow() || !driver_funcs)
{
static struct gdi_dc_funcs empty_funcs;
WARN( "failed to load the display driver, falling back to null driver\n" );
@ -95,7 +84,6 @@ const struct gdi_dc_funcs *get_display_driver(void)
return driver_funcs;
}
/***********************************************************************
* __wine_set_display_driver (win32u.@)
*/
@ -103,7 +91,6 @@ void CDECL __wine_set_display_driver( HMODULE module )
{
const struct gdi_dc_funcs * (CDECL *wine_get_gdi_driver)( unsigned int );
const struct gdi_dc_funcs *funcs = NULL;
HMODULE user32;
wine_get_gdi_driver = (void *)GetProcAddress( module, "wine_get_gdi_driver" );
if (wine_get_gdi_driver) funcs = wine_get_gdi_driver( WINE_GDI_DRIVER_VERSION );
@ -113,13 +100,6 @@ void CDECL __wine_set_display_driver( HMODULE module )
NtTerminateProcess( GetCurrentThread(), 1 );
}
InterlockedExchangePointer( (void **)&driver_funcs, (void *)funcs );
user32 = LoadLibraryA( "user32.dll" );
pGetMonitorInfoW = (void *)GetProcAddress( user32, "GetMonitorInfoW" );
pGetSystemMetrics = (void *)GetProcAddress( user32, "GetSystemMetrics" );
pEnumDisplayMonitors = (void *)GetProcAddress( user32, "EnumDisplayMonitors" );
pEnumDisplaySettingsW = (void *)GetProcAddress( user32, "EnumDisplaySettingsW" );
pSetThreadDpiAwarenessContext = (void *)GetProcAddress( user32, "SetThreadDpiAwarenessContext" );
}
struct monitor_info
@ -134,8 +114,8 @@ static BOOL CALLBACK monitor_enum_proc( HMONITOR monitor, HDC hdc, LPRECT rect,
MONITORINFOEXW mi;
mi.cbSize = sizeof(mi);
pGetMonitorInfoW( monitor, (MONITORINFO *)&mi );
if (!lstrcmpiW( info->name, mi.szDevice ))
user_callbacks->pGetMonitorInfoW( monitor, (MONITORINFO *)&mi );
if (!wcsicmp( info->name, mi.szDevice ))
{
info->rect = mi.rcMonitor;
return FALSE;
@ -264,33 +244,41 @@ static INT CDECL nulldrv_GetDeviceCaps( PHYSDEV dev, INT cap )
{
DC *dc = get_nulldrv_dc( dev );
struct monitor_info info;
int ret;
if (dc->display[0] && pEnumDisplayMonitors && pGetMonitorInfoW)
if (!user_callbacks) return 640;
if (dc->display[0])
{
info.name = dc->display;
SetRectEmpty( &info.rect );
pEnumDisplayMonitors( NULL, NULL, monitor_enum_proc, (LPARAM)&info );
user_callbacks->pEnumDisplayMonitors( NULL, NULL, monitor_enum_proc, (LPARAM)&info );
if (!IsRectEmpty( &info.rect ))
return info.rect.right - info.rect.left;
}
return pGetSystemMetrics ? pGetSystemMetrics( SM_CXSCREEN ) : 640;
ret = user_callbacks->pGetSystemMetrics( SM_CXSCREEN );
return ret ? ret : 640;
}
case VERTRES:
{
DC *dc = get_nulldrv_dc( dev );
struct monitor_info info;
int ret;
if (dc->display[0] && pEnumDisplayMonitors && pGetMonitorInfoW)
if (!user_callbacks) return 480;
if (dc->display[0] && user_callbacks)
{
info.name = dc->display;
SetRectEmpty( &info.rect );
pEnumDisplayMonitors( NULL, NULL, monitor_enum_proc, (LPARAM)&info );
user_callbacks->pEnumDisplayMonitors( NULL, NULL, monitor_enum_proc, (LPARAM)&info );
if (!IsRectEmpty( &info.rect ))
return info.rect.bottom - info.rect.top;
}
return pGetSystemMetrics ? pGetSystemMetrics( SM_CYSCREEN ) : 480;
ret = user_callbacks->pGetSystemMetrics( SM_CYSCREEN );
return ret ? ret : 480;
}
case BITSPIXEL:
{
@ -298,13 +286,13 @@ static INT CDECL nulldrv_GetDeviceCaps( PHYSDEV dev, INT cap )
WCHAR *display;
DC *dc;
if (NtGdiGetDeviceCaps( dev->hdc, TECHNOLOGY ) == DT_RASDISPLAY && pEnumDisplaySettingsW)
if (NtGdiGetDeviceCaps( dev->hdc, TECHNOLOGY ) == DT_RASDISPLAY && user_callbacks)
{
dc = get_nulldrv_dc( dev );
display = dc->display[0] ? dc->display : NULL;
memset( &devmode, 0, sizeof(devmode) );
devmode.dmSize = sizeof(devmode);
if (pEnumDisplaySettingsW( display, ENUM_CURRENT_SETTINGS, &devmode )
if (user_callbacks->pEnumDisplaySettingsW( display, ENUM_CURRENT_SETTINGS, &devmode )
&& devmode.dmFields & DM_BITSPERPEL && devmode.dmBitsPerPel)
return devmode.dmBitsPerPel;
}
@ -351,39 +339,39 @@ static INT CDECL nulldrv_GetDeviceCaps( PHYSDEV dev, INT cap )
if (NtGdiGetDeviceCaps( dev->hdc, TECHNOLOGY ) != DT_RASDISPLAY)
return 0;
if (pEnumDisplaySettingsW)
if (user_callbacks)
{
dc = get_nulldrv_dc( dev );
memset( &devmode, 0, sizeof(devmode) );
devmode.dmSize = sizeof(devmode);
display = dc->display[0] ? dc->display : NULL;
if (pEnumDisplaySettingsW( display, ENUM_CURRENT_SETTINGS, &devmode ))
if (user_callbacks->pEnumDisplaySettingsW( display, ENUM_CURRENT_SETTINGS, &devmode ))
return devmode.dmDisplayFrequency ? devmode.dmDisplayFrequency : 1;
}
return 1;
}
case DESKTOPHORZRES:
if (NtGdiGetDeviceCaps( dev->hdc, TECHNOLOGY ) == DT_RASDISPLAY && pGetSystemMetrics)
if (NtGdiGetDeviceCaps( dev->hdc, TECHNOLOGY ) == DT_RASDISPLAY && user_callbacks)
{
DPI_AWARENESS_CONTEXT context;
UINT ret;
context = pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE );
ret = pGetSystemMetrics( SM_CXVIRTUALSCREEN );
pSetThreadDpiAwarenessContext( context );
return ret;
context = user_callbacks->pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE );
ret = user_callbacks->pGetSystemMetrics( SM_CXVIRTUALSCREEN );
user_callbacks->pSetThreadDpiAwarenessContext( context );
if (ret) return ret;
}
return NtGdiGetDeviceCaps( dev->hdc, HORZRES );
case DESKTOPVERTRES:
if (NtGdiGetDeviceCaps( dev->hdc, TECHNOLOGY ) == DT_RASDISPLAY && pGetSystemMetrics)
if (NtGdiGetDeviceCaps( dev->hdc, TECHNOLOGY ) == DT_RASDISPLAY && user_callbacks)
{
DPI_AWARENESS_CONTEXT context;
UINT ret;
context = pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE );
ret = pGetSystemMetrics( SM_CYVIRTUALSCREEN );
pSetThreadDpiAwarenessContext( context );
return ret;
context = user_callbacks->pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE );
ret = user_callbacks->pGetSystemMetrics( SM_CYVIRTUALSCREEN );
user_callbacks->pSetThreadDpiAwarenessContext( context );
if (ret) return ret;
}
return NtGdiGetDeviceCaps( dev->hdc, VERTRES );
case BLTALIGNMENT: return 0;

View File

@ -45,21 +45,30 @@
#ifdef HAVE_CARBON_CARBON_H
#define LoadResource __carbon_LoadResource
#define CheckMenuItem __carbon_CheckMenuItem
#define CompareString __carbon_CompareString
#define GetCurrentThread __carbon_GetCurrentThread
#define GetCurrentProcess __carbon_GetCurrentProcess
#define AnimatePalette __carbon_AnimatePalette
#define DeleteMenu __carbon_DeleteMenu
#define DrawMenu __carbon_DrawMenu
#define DrawMenuBar __carbon_DrawMenuBar
#define EnableMenuItem __carbon_EnableMenuItem
#define EqualRgn __carbon_EqualRgn
#define FillRgn __carbon_FillRgn
#define FrameRgn __carbon_FrameRgn
#define GetMenu __carbon_GetMenu
#define GetPixel __carbon_GetPixel
#define InvertRgn __carbon_InvertRgn
#define IsWindowVisible __carbon_IsWindowVisible
#define LineTo __carbon_LineTo
#define MoveWindow __carbon_MoveWindow
#define OffsetRgn __carbon_OffsetRgn
#define PaintRgn __carbon_PaintRgn
#define Polygon __carbon_Polygon
#define ResizePalette __carbon_ResizePalette
#define SetRectRgn __carbon_SetRectRgn
#define ShowWindow __carbon_ShowWindow
#include <Carbon/Carbon.h>
#undef LoadResource
#undef CompareString
@ -67,17 +76,26 @@
#undef _CDECL
#undef GetCurrentProcess
#undef AnimatePalette
#undef CheckMenuItem
#undef DeleteMenu
#undef DrawMenu
#undef DrawMenuBar
#undef EnableMenuItem
#undef EqualRgn
#undef FillRgn
#undef FrameRgn
#undef GetMenu
#undef GetPixel
#undef InvertRgn
#undef IsWindowVisible
#undef LineTo
#undef MoveWindow
#undef OffsetRgn
#undef PaintRgn
#undef Polygon
#undef ResizePalette
#undef SetRectRgn
#undef ShowWindow
#endif /* HAVE_CARBON_CARBON_H */
#ifdef HAVE_FT2BUILD_H

View File

@ -579,14 +579,7 @@ BOOL GDI_dec_ref_count( HGDIOBJ handle )
*/
DWORD get_system_dpi(void)
{
static UINT (WINAPI *pGetDpiForSystem)(void);
if (!pGetDpiForSystem)
{
HMODULE user = GetModuleHandleW( L"user32.dll" );
if (user) pGetDpiForSystem = (void *)GetProcAddress( user, "GetDpiForSystem" );
}
return pGetDpiForSystem ? pGetDpiForSystem() : 96;
return user_callbacks ? user_callbacks->pGetDpiForSystem() : 96;
}
static HFONT create_font( const LOGFONTW *deffont )

View File

@ -28,7 +28,7 @@
#include "windef.h"
#include "winbase.h"
#include "ntgdi.h"
#include "wine/gdi_driver.h"
#include "win32u_private.h"
/* extra stock object: default 1x1 bitmap for memory DCs */
#define DEFAULT_BITMAP (STOCK_LAST+1)
@ -649,5 +649,6 @@ void set_gdi_client_ptr( HGDIOBJ handle, void *ptr ) DECLSPEC_HIDDEN;
extern HMODULE gdi32_module DECLSPEC_HIDDEN;
extern SYSTEM_BASIC_INFORMATION system_info DECLSPEC_HIDDEN;
extern const struct user_callbacks *user_callbacks DECLSPEC_HIDDEN;
#endif /* __WINE_NTGDI_PRIVATE_H */

View File

@ -580,29 +580,18 @@ typedef BOOL (WINAPI *RedrawWindow_funcptr)( HWND, const RECT *, HRGN, UINT );
*/
BOOL WINAPI NtGdiUpdateColors( HDC hDC )
{
HMODULE mod;
int size = NtGdiGetDeviceCaps( hDC, SIZEPALETTE );
HWND hwnd;
if (!size) return FALSE;
if (!user_callbacks) return TRUE;
mod = GetModuleHandleA("user32.dll");
if (mod)
{
WindowFromDC_funcptr pWindowFromDC = (WindowFromDC_funcptr)GetProcAddress(mod,"WindowFromDC");
if (pWindowFromDC)
{
HWND hWnd = pWindowFromDC( hDC );
hwnd = user_callbacks->pWindowFromDC( hDC );
/* Docs say that we have to remap current drawable pixel by pixel
* but it would take forever given the speed of XGet/PutPixel.
*/
if (hWnd && size)
{
RedrawWindow_funcptr pRedrawWindow = (void *)GetProcAddress( mod, "RedrawWindow" );
if (pRedrawWindow) pRedrawWindow( hWnd, NULL, 0, RDW_INVALIDATE );
}
}
}
/* Docs say that we have to remap current drawable pixel by pixel
* but it would take forever given the speed of XGet/PutPixel.
*/
if (hwnd && size) user_callbacks->pRedrawWindow( hwnd, NULL, 0, RDW_INVALIDATE );
return TRUE;
}

View File

@ -1375,17 +1375,10 @@ INT mirror_region( HRGN dst, HRGN src, INT width )
*/
BOOL WINAPI MirrorRgn( HWND hwnd, HRGN hrgn )
{
static BOOL (WINAPI *pGetWindowRect)( HWND hwnd, LPRECT rect );
RECT rect;
/* yes, a HWND in gdi32, don't ask */
if (!pGetWindowRect)
{
HMODULE user32 = GetModuleHandleW(L"user32.dll");
if (!user32) return FALSE;
if (!(pGetWindowRect = (void *)GetProcAddress( user32, "GetWindowRect" ))) return FALSE;
}
pGetWindowRect( hwnd, &rect );
if (!user_callbacks) return FALSE;
user_callbacks->pGetWindowRect( hwnd, &rect );
return mirror_region( hrgn, hrgn, rect.right - rect.left ) != ERROR;
}

View File

@ -0,0 +1,41 @@
/*
* Unix call wrappers
*
* Copyright 2021 Jacek Caban for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __WINE_WIN32U_PRIVATE
#define __WINE_WIN32U_PRIVATE
#include "wine/gdi_driver.h"
#include "winuser.h"
struct user_callbacks
{
HWND (WINAPI *pGetDesktopWindow)(void);
UINT (WINAPI *pGetDpiForSystem)(void);
BOOL (WINAPI *pGetMonitorInfoW)( HMONITOR, LPMONITORINFO );
INT (WINAPI *pGetSystemMetrics)(INT);
BOOL (WINAPI *pGetWindowRect)( HWND hwnd, LPRECT rect );
BOOL (WINAPI *pEnumDisplayMonitors)( HDC, LPRECT, MONITORENUMPROC, LPARAM );
BOOL (WINAPI *pEnumDisplaySettingsW)(LPCWSTR, DWORD, LPDEVMODEW );
BOOL (WINAPI *pRedrawWindow)( HWND, const RECT*, HRGN, UINT );
DPI_AWARENESS_CONTEXT (WINAPI *pSetThreadDpiAwarenessContext)( DPI_AWARENESS_CONTEXT );
HWND (WINAPI *pWindowFromDC)( HDC );
};
#endif /* __WINE_WIN32U_PRIVATE */

141
dlls/gdi32/wrappers.c Normal file
View File

@ -0,0 +1,141 @@
/*
* Unix call wrappers
*
* Copyright 2021 Jacek Caban for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "gdi_private.h"
#include "win32u_private.h"
static void *get_user_proc( const char *name, BOOL force_load )
{
ANSI_STRING name_str;
FARPROC proc = NULL;
static HMODULE user32;
if (!user32)
{
UNICODE_STRING str;
NTSTATUS status;
RtlInitUnicodeString( &str, L"user32.dll" );
status = force_load
? LdrLoadDll( NULL, 0, &str, &user32 )
: LdrGetDllHandle( NULL, 0, &str, &user32 );
if (status < 0) return NULL;
}
RtlInitAnsiString( &name_str, name );
LdrGetProcedureAddress( user32, &name_str, 0, (void**)&proc );
return proc;
}
static HWND WINAPI call_GetDesktopWindow(void)
{
static HWND (WINAPI *pGetDesktopWindow)(void);
if (!pGetDesktopWindow)
pGetDesktopWindow = get_user_proc( "GetDesktopWindow", TRUE );
return pGetDesktopWindow ? pGetDesktopWindow() : NULL;
}
static UINT WINAPI call_GetDpiForSystem(void)
{
static UINT (WINAPI *pGetDpiForSystem)(void);
if (!pGetDpiForSystem)
pGetDpiForSystem = get_user_proc( "GetDpiForSystem", FALSE );
return pGetDpiForSystem ? pGetDpiForSystem() : 96;
}
static BOOL WINAPI call_GetMonitorInfoW( HMONITOR monitor, MONITORINFO *info )
{
static BOOL (WINAPI *pGetMonitorInfoW)( HMONITOR, LPMONITORINFO );
if (!pGetMonitorInfoW)
pGetMonitorInfoW = get_user_proc( "GetMonitorInfoW", FALSE );
return pGetMonitorInfoW && pGetMonitorInfoW( monitor, info );
}
static INT WINAPI call_GetSystemMetrics( INT metric )
{
static INT (WINAPI *pGetSystemMetrics)(INT);
if (!pGetSystemMetrics)
pGetSystemMetrics = get_user_proc( "GetSystemMetrics", FALSE );
return pGetSystemMetrics ? pGetSystemMetrics( metric ) : 0;
}
static BOOL WINAPI call_GetWindowRect( HWND hwnd, LPRECT rect )
{
static BOOL (WINAPI *pGetWindowRect)( HWND hwnd, LPRECT rect );
if (!pGetWindowRect)
pGetWindowRect = get_user_proc( "GetWindowRect", FALSE );
return pGetWindowRect && pGetWindowRect( hwnd, rect );
}
static BOOL WINAPI call_EnumDisplayMonitors( HDC hdc, RECT *rect, MONITORENUMPROC proc,
LPARAM lparam )
{
static BOOL (WINAPI *pEnumDisplayMonitors)( HDC, LPRECT, MONITORENUMPROC, LPARAM );
if (!pEnumDisplayMonitors)
pEnumDisplayMonitors = get_user_proc( "EnumDisplayMonitors", FALSE );
return pEnumDisplayMonitors && pEnumDisplayMonitors( hdc, rect, proc, lparam );
}
static BOOL WINAPI call_EnumDisplaySettingsW( const WCHAR *device, DWORD mode, DEVMODEW *devmode )
{
static BOOL (WINAPI *pEnumDisplaySettingsW)(LPCWSTR, DWORD, LPDEVMODEW );
if (!pEnumDisplaySettingsW)
pEnumDisplaySettingsW = get_user_proc( "EnumDisplaySettingsW", FALSE );
return pEnumDisplaySettingsW && pEnumDisplaySettingsW( device, mode, devmode );
}
static BOOL WINAPI call_RedrawWindow( HWND hwnd, const RECT *rect, HRGN rgn, UINT flags )
{
static BOOL (WINAPI *pRedrawWindow)( HWND, const RECT*, HRGN, UINT );
if (!pRedrawWindow)
pRedrawWindow = get_user_proc( "RedrawWindow", FALSE );
return pRedrawWindow && pRedrawWindow( hwnd, rect, rgn, flags );
}
static DPI_AWARENESS_CONTEXT WINAPI call_SetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT ctx )
{
static DPI_AWARENESS_CONTEXT (WINAPI *pSetThreadDpiAwarenessContext)( DPI_AWARENESS_CONTEXT );
if (!pSetThreadDpiAwarenessContext)
pSetThreadDpiAwarenessContext = get_user_proc( "SetThreadDpiAwarenessContext", FALSE );
return pSetThreadDpiAwarenessContext ? pSetThreadDpiAwarenessContext( ctx ) : 0;
}
static HWND WINAPI call_WindowFromDC( HDC hdc )
{
static HWND (WINAPI *pWindowFromDC)( HDC );
if (!pWindowFromDC)
pWindowFromDC = get_user_proc( "WindowFromDC", FALSE );
return pWindowFromDC ? pWindowFromDC( hdc ) : NULL;
}
static const struct user_callbacks callbacks =
{
call_GetDesktopWindow,
call_GetDpiForSystem,
call_GetMonitorInfoW,
call_GetSystemMetrics,
call_GetWindowRect,
call_EnumDisplayMonitors,
call_EnumDisplaySettingsW,
call_RedrawWindow,
call_SetThreadDpiAwarenessContext,
call_WindowFromDC,
};
const struct user_callbacks *user_callbacks = &callbacks;