win32u: Move NtUserCreateWindowEx implementation from user32.
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:
parent
f2f07d5ba7
commit
d765edc411
|
@ -42,8 +42,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(class);
|
|||
|
||||
static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
|
||||
|
||||
#define CLASS_OTHER_PROCESS ((CLASS *)1)
|
||||
|
||||
static inline const char *debugstr_us( const UNICODE_STRING *us )
|
||||
{
|
||||
if (!us) return "<null>";
|
||||
|
@ -351,15 +349,6 @@ void register_desktop_class(void)
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* get_class_winproc
|
||||
*/
|
||||
WNDPROC get_class_winproc( CLASS *class )
|
||||
{
|
||||
return class->winproc;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* RegisterClassA (USER32.@)
|
||||
*
|
||||
|
|
|
@ -114,7 +114,6 @@ struct tagWND;
|
|||
extern ATOM get_int_atom_value( UNICODE_STRING *name ) DECLSPEC_HIDDEN;
|
||||
extern void register_builtin_classes(void) DECLSPEC_HIDDEN;
|
||||
extern void register_desktop_class(void) DECLSPEC_HIDDEN;
|
||||
extern WNDPROC get_class_winproc( struct tagCLASS *class ) DECLSPEC_HIDDEN;
|
||||
|
||||
/* defwnd proc */
|
||||
extern HBRUSH DEFWND_ControlColor( HDC hDC, UINT ctlType ) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -74,11 +74,6 @@ static void CDECL nulldrv_UpdateClipboard(void)
|
|||
{
|
||||
}
|
||||
|
||||
static BOOL CDECL nulldrv_CreateWindow( HWND hwnd )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static DWORD CDECL nulldrv_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles, DWORD timeout,
|
||||
DWORD mask, DWORD flags )
|
||||
{
|
||||
|
@ -132,11 +127,6 @@ static void CDECL loaderdrv_UpdateClipboard(void)
|
|||
load_driver()->pUpdateClipboard();
|
||||
}
|
||||
|
||||
static BOOL CDECL loaderdrv_CreateWindow( HWND hwnd )
|
||||
{
|
||||
return load_driver()->pCreateWindow( hwnd );
|
||||
}
|
||||
|
||||
static struct user_driver_funcs lazy_load_driver =
|
||||
{
|
||||
{ NULL },
|
||||
|
@ -164,7 +154,7 @@ static struct user_driver_funcs lazy_load_driver =
|
|||
NULL,
|
||||
/* windowing functions */
|
||||
NULL,
|
||||
loaderdrv_CreateWindow,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
|
@ -213,7 +203,6 @@ void CDECL __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT v
|
|||
|
||||
SET_USER_FUNC(SetCursorPos);
|
||||
SET_USER_FUNC(UpdateClipboard);
|
||||
SET_USER_FUNC(CreateWindow);
|
||||
SET_USER_FUNC(MsgWaitForMultipleObjectsEx);
|
||||
SET_USER_FUNC(SetWindowIcon);
|
||||
SET_USER_FUNC(SetWindowText);
|
||||
|
|
|
@ -140,7 +140,12 @@ static void CDECL notify_ime( HWND hwnd, UINT param )
|
|||
if (ime_default) SendMessageW( ime_default, WM_IME_INTERNAL, param, HandleToUlong(hwnd) );
|
||||
}
|
||||
|
||||
void WINAPI unregister_imm( HWND hwnd )
|
||||
static BOOL WINAPI register_imm( HWND hwnd )
|
||||
{
|
||||
return imm_register_window( hwnd );
|
||||
}
|
||||
|
||||
static void WINAPI unregister_imm( HWND hwnd )
|
||||
{
|
||||
imm_unregister_window( hwnd );
|
||||
}
|
||||
|
@ -149,7 +154,6 @@ static void CDECL free_win_ptr( WND *win )
|
|||
{
|
||||
HeapFree( GetProcessHeap(), 0, win->text );
|
||||
HeapFree( GetProcessHeap(), 0, win->pScroll );
|
||||
HeapFree( GetProcessHeap(), 0, win );
|
||||
}
|
||||
|
||||
static const struct user_callbacks user_funcs =
|
||||
|
@ -163,8 +167,10 @@ static const struct user_callbacks user_funcs =
|
|||
PostMessageW,
|
||||
SendInput,
|
||||
SendMessageTimeoutW,
|
||||
SendMessageA,
|
||||
SendMessageW,
|
||||
SendNotifyMessageW,
|
||||
SetSystemMenu,
|
||||
ShowCaret,
|
||||
WaitForInputIdle,
|
||||
free_win_ptr,
|
||||
|
@ -172,9 +178,11 @@ static const struct user_callbacks user_funcs =
|
|||
notify_ime,
|
||||
register_builtin_classes,
|
||||
MSG_SendInternalMessageTimeout,
|
||||
MENU_SetMenu,
|
||||
SCROLL_SetStandardScrollPainted,
|
||||
(void *)__wine_set_user_driver,
|
||||
set_window_pos,
|
||||
register_imm,
|
||||
unregister_imm,
|
||||
};
|
||||
|
||||
|
|
|
@ -128,9 +128,6 @@ extern BOOL USER_IsExitingThread( DWORD tid ) DECLSPEC_HIDDEN;
|
|||
typedef LRESULT (*winproc_callback_t)( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
|
||||
LRESULT *result, void *arg );
|
||||
|
||||
extern WNDPROC WINPROC_GetProc( WNDPROC proc, BOOL unicode ) DECLSPEC_HIDDEN;
|
||||
extern BOOL WINPROC_IsUnicode( WNDPROC proc, BOOL def_val ) DECLSPEC_HIDDEN;
|
||||
|
||||
extern LRESULT WINPROC_CallProcAtoW( winproc_callback_t callback, HWND hwnd, UINT msg,
|
||||
WPARAM wParam, LPARAM lParam, LRESULT *result, void *arg,
|
||||
enum wm_char_mapping mapping ) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -76,124 +76,6 @@ void *free_user_handle( HANDLE handle, unsigned int type )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* create_window_handle
|
||||
*
|
||||
* Create a window handle with the server.
|
||||
*/
|
||||
static WND *create_window_handle( HWND parent, HWND owner, UNICODE_STRING *name,
|
||||
HINSTANCE instance, BOOL unicode,
|
||||
DWORD style, DWORD ex_style )
|
||||
{
|
||||
WND *win;
|
||||
HWND handle = 0, full_parent = 0, full_owner = 0;
|
||||
struct tagCLASS *class = NULL;
|
||||
int extra_bytes = 0;
|
||||
DPI_AWARENESS awareness = GetAwarenessFromDpiAwarenessContext( GetThreadDpiAwarenessContext() );
|
||||
UINT dpi = 0;
|
||||
|
||||
SERVER_START_REQ( create_window )
|
||||
{
|
||||
req->parent = wine_server_user_handle( parent );
|
||||
req->owner = wine_server_user_handle( owner );
|
||||
req->instance = wine_server_client_ptr( instance );
|
||||
req->dpi = GetDpiForSystem();
|
||||
req->awareness = awareness;
|
||||
req->style = style;
|
||||
req->ex_style = ex_style;
|
||||
if (!(req->atom = get_int_atom_value( name )) && name->Length)
|
||||
wine_server_add_data( req, name->Buffer, name->Length );
|
||||
if (!wine_server_call_err( req ))
|
||||
{
|
||||
handle = wine_server_ptr_handle( reply->handle );
|
||||
full_parent = wine_server_ptr_handle( reply->parent );
|
||||
full_owner = wine_server_ptr_handle( reply->owner );
|
||||
extra_bytes = reply->extra;
|
||||
dpi = reply->dpi;
|
||||
awareness = reply->awareness;
|
||||
class = wine_server_get_ptr( reply->class_ptr );
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
if (!handle)
|
||||
{
|
||||
WARN( "error %d creating window\n", GetLastError() );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(win = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||
sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
|
||||
{
|
||||
SERVER_START_REQ( destroy_window )
|
||||
{
|
||||
req->handle = wine_server_user_handle( handle );
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!parent) /* if parent is 0 we don't have a desktop window yet */
|
||||
{
|
||||
struct user_thread_info *thread_info = get_user_thread_info();
|
||||
|
||||
if (name->Buffer == (LPCWSTR)DESKTOP_CLASS_ATOM)
|
||||
{
|
||||
if (!thread_info->top_window) thread_info->top_window = full_parent ? full_parent : handle;
|
||||
else assert( full_parent == thread_info->top_window );
|
||||
if (full_parent && !NtUserCallHwnd( thread_info->top_window, NtUserCreateDesktopWindow ))
|
||||
ERR( "failed to create desktop window\n" );
|
||||
register_builtin_classes();
|
||||
}
|
||||
else /* HWND_MESSAGE parent */
|
||||
{
|
||||
if (!thread_info->msg_window && !full_parent) thread_info->msg_window = handle;
|
||||
}
|
||||
}
|
||||
|
||||
USER_Lock();
|
||||
|
||||
win->obj.handle = handle;
|
||||
win->obj.type = NTUSER_OBJ_WINDOW;
|
||||
win->parent = full_parent;
|
||||
win->owner = full_owner;
|
||||
win->class = class;
|
||||
win->winproc = get_class_winproc( class );
|
||||
win->cbWndExtra = extra_bytes;
|
||||
win->dpi = dpi;
|
||||
win->dpi_awareness = awareness;
|
||||
NtUserCallTwoParam( HandleToUlong(handle), (UINT_PTR)win, NtUserSetHandlePtr );
|
||||
if (WINPROC_IsUnicode( win->winproc, unicode )) win->flags |= WIN_ISUNICODE;
|
||||
return win;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* free_window_handle
|
||||
*
|
||||
* Free a window handle.
|
||||
*/
|
||||
static void free_window_handle( HWND hwnd )
|
||||
{
|
||||
struct user_object *ptr;
|
||||
|
||||
if ((ptr = get_user_handle_ptr( hwnd, NTUSER_OBJ_WINDOW )) && ptr != OBJ_OTHER_PROCESS)
|
||||
{
|
||||
SERVER_START_REQ( destroy_window )
|
||||
{
|
||||
req->handle = wine_server_user_handle( hwnd );
|
||||
wine_server_call( req );
|
||||
NtUserCallTwoParam( HandleToUlong(hwnd), 0, NtUserSetHandlePtr );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
USER_Unlock();
|
||||
HeapFree( GetProcessHeap(), 0, ptr );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* list_window_children
|
||||
*
|
||||
|
@ -242,22 +124,6 @@ static HWND *list_window_children( HDESK desktop, HWND hwnd, UNICODE_STRING *cla
|
|||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* send_parent_notify
|
||||
*/
|
||||
static void send_parent_notify( HWND hwnd, UINT msg )
|
||||
{
|
||||
if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
|
||||
!(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
|
||||
{
|
||||
HWND parent = GetParent(hwnd);
|
||||
if (parent && parent != GetDesktopWindow())
|
||||
SendMessageW( parent, WM_PARENTNOTIFY,
|
||||
MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* get_hwnd_message_parent
|
||||
*
|
||||
|
@ -707,66 +573,6 @@ other_process:
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* WIN_FixCoordinates
|
||||
*
|
||||
* Fix the coordinates - Helper for WIN_CreateWindowEx.
|
||||
* returns default show mode in sw.
|
||||
*/
|
||||
static void WIN_FixCoordinates( CREATESTRUCTW *cs, INT *sw)
|
||||
{
|
||||
#define IS_DEFAULT(x) ((x) == CW_USEDEFAULT || (x) == (SHORT)0x8000)
|
||||
if (cs->style & (WS_CHILD | WS_POPUP))
|
||||
{
|
||||
if (IS_DEFAULT(cs->x)) cs->x = cs->y = 0;
|
||||
if (IS_DEFAULT(cs->cx)) cs->cx = cs->cy = 0;
|
||||
}
|
||||
else /* overlapped window */
|
||||
{
|
||||
HMONITOR monitor;
|
||||
MONITORINFO mon_info;
|
||||
STARTUPINFOW info;
|
||||
|
||||
if (!IS_DEFAULT(cs->x) && !IS_DEFAULT(cs->cx) && !IS_DEFAULT(cs->cy)) return;
|
||||
|
||||
monitor = MonitorFromWindow( cs->hwndParent, MONITOR_DEFAULTTOPRIMARY );
|
||||
mon_info.cbSize = sizeof(mon_info);
|
||||
GetMonitorInfoW( monitor, &mon_info );
|
||||
GetStartupInfoW( &info );
|
||||
|
||||
if (IS_DEFAULT(cs->x))
|
||||
{
|
||||
if (!IS_DEFAULT(cs->y)) *sw = cs->y;
|
||||
cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : mon_info.rcWork.left;
|
||||
cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : mon_info.rcWork.top;
|
||||
}
|
||||
|
||||
if (IS_DEFAULT(cs->cx))
|
||||
{
|
||||
if (info.dwFlags & STARTF_USESIZE)
|
||||
{
|
||||
cs->cx = info.dwXSize;
|
||||
cs->cy = info.dwYSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
cs->cx = (mon_info.rcWork.right - mon_info.rcWork.left) * 3 / 4 - cs->x;
|
||||
cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
|
||||
}
|
||||
}
|
||||
/* neither x nor cx are default. Check the y values .
|
||||
* In the trace we see Outlook and Outlook Express using
|
||||
* cy set to CW_USEDEFAULT when opening the address book.
|
||||
*/
|
||||
else if (IS_DEFAULT(cs->cy))
|
||||
{
|
||||
FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
|
||||
cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
|
||||
}
|
||||
}
|
||||
#undef IS_DEFAULT
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* dump_window_styles
|
||||
*/
|
||||
|
@ -885,40 +691,6 @@ static BOOL is_default_coord( int x )
|
|||
return x == CW_USEDEFAULT || x == 0x8000;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* map_dpi_create_struct
|
||||
*/
|
||||
static void map_dpi_create_struct( CREATESTRUCTW *cs, UINT dpi_from, UINT dpi_to )
|
||||
{
|
||||
if (!dpi_from && !dpi_to) return;
|
||||
if (!dpi_from || !dpi_to)
|
||||
{
|
||||
POINT pt = { cs->x, cs->y };
|
||||
UINT mon_dpi = get_monitor_dpi( MonitorFromPoint( pt, MONITOR_DEFAULTTONEAREST ));
|
||||
if (!dpi_from) dpi_from = mon_dpi;
|
||||
else dpi_to = mon_dpi;
|
||||
}
|
||||
if (dpi_from == dpi_to) return;
|
||||
cs->x = MulDiv( cs->x, dpi_to, dpi_from );
|
||||
cs->y = MulDiv( cs->y, dpi_to, dpi_from );
|
||||
cs->cx = MulDiv( cs->cx, dpi_to, dpi_from );
|
||||
cs->cy = MulDiv( cs->cy, dpi_to, dpi_from );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* fix_exstyle
|
||||
*/
|
||||
static DWORD fix_exstyle( DWORD style, DWORD exstyle )
|
||||
{
|
||||
if ((exstyle & WS_EX_DLGMODALFRAME) ||
|
||||
(!(exstyle & WS_EX_STATICEDGE) &&
|
||||
(style & (WS_DLGFRAME | WS_THICKFRAME))))
|
||||
exstyle |= WS_EX_WINDOWEDGE;
|
||||
else
|
||||
exstyle &= ~WS_EX_WINDOWEDGE;
|
||||
return exstyle;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* WIN_CreateWindowEx
|
||||
*
|
||||
|
@ -926,19 +698,14 @@ static DWORD fix_exstyle( DWORD style, DWORD exstyle )
|
|||
*/
|
||||
HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module, BOOL unicode )
|
||||
{
|
||||
INT cx, cy, style, ex_style, sw = SW_SHOW;
|
||||
LRESULT result;
|
||||
RECT rect;
|
||||
WND *wndPtr;
|
||||
HWND hwnd, parent, owner, top_child = 0;
|
||||
UINT win_dpi, thread_dpi = get_thread_dpi();
|
||||
DPI_AWARENESS_CONTEXT context;
|
||||
HWND hwnd, top_child = 0;
|
||||
MDICREATESTRUCTW mdi_cs;
|
||||
UNICODE_STRING class;
|
||||
CBT_CREATEWNDW cbtc;
|
||||
CREATESTRUCTW cbcs;
|
||||
WNDCLASSEXW info;
|
||||
HMENU menu;
|
||||
|
||||
if (!get_class_info( module, className, NULL, &class, FALSE )) return FALSE;
|
||||
if (!get_class_info( module, className, &info, &class, FALSE )) return FALSE;
|
||||
|
||||
TRACE("%s %s%s%s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
|
||||
unicode ? debugstr_w(cs->lpszName) : debugstr_a((LPCSTR)cs->lpszName),
|
||||
|
@ -1030,300 +797,25 @@ HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module,
|
|||
}
|
||||
}
|
||||
|
||||
/* Find the parent window */
|
||||
|
||||
parent = cs->hwndParent;
|
||||
owner = 0;
|
||||
|
||||
if (cs->hwndParent == HWND_MESSAGE)
|
||||
{
|
||||
cs->hwndParent = parent = get_hwnd_message_parent();
|
||||
}
|
||||
else if (cs->hwndParent)
|
||||
{
|
||||
if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
|
||||
{
|
||||
parent = GetDesktopWindow();
|
||||
owner = cs->hwndParent;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD parent_style = GetWindowLongW( parent, GWL_EXSTYLE );
|
||||
if ((parent_style & WS_EX_LAYOUTRTL) && !(parent_style & WS_EX_NOINHERITLAYOUT))
|
||||
cs->dwExStyle |= WS_EX_LAYOUTRTL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
|
||||
{
|
||||
WARN("No parent for child window\n" );
|
||||
SetLastError(ERROR_TLW_WITH_WSCHILD);
|
||||
return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
|
||||
}
|
||||
|
||||
/* are we creating the desktop or HWND_MESSAGE parent itself? */
|
||||
if (className != (LPCWSTR)DESKTOP_CLASS_ATOM &&
|
||||
/* FIXME: move to win32u */
|
||||
if (!cs->hwndParent && className != (const WCHAR *)DESKTOP_CLASS_ATOM &&
|
||||
(IS_INTRESOURCE(className) || wcsicmp( className, L"Message" )))
|
||||
{
|
||||
DWORD layout;
|
||||
GetProcessDefaultLayout( &layout );
|
||||
if (layout & LAYOUT_RTL) cs->dwExStyle |= WS_EX_LAYOUTRTL;
|
||||
parent = GetDesktopWindow();
|
||||
}
|
||||
}
|
||||
|
||||
WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
|
||||
cs->dwExStyle = fix_exstyle(cs->style, cs->dwExStyle);
|
||||
menu = cs->hMenu;
|
||||
if (!menu && info.lpszMenuName && (cs->style & (WS_CHILD | WS_POPUP)) != WS_CHILD)
|
||||
menu = LoadMenuW( cs->hInstance, info.lpszMenuName );
|
||||
|
||||
/* Create the window structure */
|
||||
|
||||
style = cs->style & ~WS_VISIBLE;
|
||||
ex_style = cs->dwExStyle & ~WS_EX_LAYERED;
|
||||
if (!(wndPtr = create_window_handle( parent, owner, &class, module,
|
||||
unicode, style, ex_style )))
|
||||
return 0;
|
||||
hwnd = wndPtr->obj.handle;
|
||||
|
||||
/* Fill the window structure */
|
||||
|
||||
wndPtr->tid = GetCurrentThreadId();
|
||||
wndPtr->hInstance = cs->hInstance;
|
||||
wndPtr->text = NULL;
|
||||
wndPtr->dwStyle = style;
|
||||
wndPtr->dwExStyle = ex_style;
|
||||
wndPtr->wIDmenu = 0;
|
||||
wndPtr->helpContext = 0;
|
||||
wndPtr->pScroll = NULL;
|
||||
wndPtr->userdata = 0;
|
||||
wndPtr->hIcon = 0;
|
||||
wndPtr->hIconSmall = 0;
|
||||
wndPtr->hIconSmall2 = 0;
|
||||
wndPtr->hSysMenu = 0;
|
||||
|
||||
wndPtr->min_pos.x = wndPtr->min_pos.y = -1;
|
||||
wndPtr->max_pos.x = wndPtr->max_pos.y = -1;
|
||||
SetRect( &wndPtr->normal_rect, cs->x, cs->y, cs->x + cs->cx, cs->y + cs->cy );
|
||||
|
||||
if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
|
||||
|
||||
/* call the WH_CBT hook */
|
||||
|
||||
WIN_ReleasePtr( wndPtr );
|
||||
cbcs = *cs;
|
||||
cbtc.lpcs = &cbcs;
|
||||
cbtc.hwndInsertAfter = HWND_TOP;
|
||||
if (HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, (WPARAM)hwnd, (LPARAM)&cbtc, unicode ) ||
|
||||
!(wndPtr = WIN_GetPtr( hwnd )))
|
||||
{
|
||||
free_window_handle( hwnd );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Correct the window styles.
|
||||
*
|
||||
* It affects only the style loaded into the WIN structure.
|
||||
*/
|
||||
|
||||
if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
|
||||
{
|
||||
wndPtr->dwStyle |= WS_CLIPSIBLINGS;
|
||||
if (!(wndPtr->dwStyle & WS_POPUP))
|
||||
wndPtr->dwStyle |= WS_CAPTION;
|
||||
}
|
||||
|
||||
wndPtr->dwExStyle = cs->dwExStyle;
|
||||
/* WS_EX_WINDOWEDGE depends on some other styles */
|
||||
if ((wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)) &&
|
||||
!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
|
||||
wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
|
||||
|
||||
if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
|
||||
wndPtr->flags |= WIN_NEED_SIZE;
|
||||
|
||||
SERVER_START_REQ( set_window_info )
|
||||
{
|
||||
req->handle = wine_server_user_handle( hwnd );
|
||||
req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
|
||||
req->style = wndPtr->dwStyle;
|
||||
req->ex_style = wndPtr->dwExStyle;
|
||||
req->instance = wine_server_client_ptr( wndPtr->hInstance );
|
||||
req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
|
||||
req->extra_offset = -1;
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
/* Set the window menu */
|
||||
|
||||
if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
|
||||
{
|
||||
if (cs->hMenu)
|
||||
{
|
||||
if (!MENU_SetMenu(hwnd, cs->hMenu))
|
||||
{
|
||||
WIN_ReleasePtr( wndPtr );
|
||||
free_window_handle( hwnd );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LPCWSTR menuName = (LPCWSTR)GetClassLongPtrW( hwnd, GCLP_MENUNAME );
|
||||
if (menuName)
|
||||
{
|
||||
cs->hMenu = LoadMenuW( cs->hInstance, menuName );
|
||||
if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
|
||||
}
|
||||
}
|
||||
}
|
||||
else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
|
||||
|
||||
win_dpi = wndPtr->dpi;
|
||||
WIN_ReleasePtr( wndPtr );
|
||||
|
||||
if (parent) map_dpi_create_struct( cs, thread_dpi, win_dpi );
|
||||
|
||||
context = SetThreadDpiAwarenessContext( GetWindowDpiAwarenessContext( hwnd ));
|
||||
|
||||
/* send the WM_GETMINMAXINFO message and fix the size if needed */
|
||||
|
||||
cx = cs->cx;
|
||||
cy = cs->cy;
|
||||
if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
|
||||
{
|
||||
MINMAXINFO info = WINPOS_GetMinMaxInfo( hwnd );
|
||||
cx = max( min( cx, info.ptMaxTrackSize.x ), info.ptMinTrackSize.x );
|
||||
cy = max( min( cy, info.ptMaxTrackSize.y ), info.ptMinTrackSize.y );
|
||||
}
|
||||
|
||||
if (cx < 0) cx = 0;
|
||||
if (cy < 0) cy = 0;
|
||||
SetRect( &rect, cs->x, cs->y, cs->x + cx, cs->y + cy );
|
||||
/* check for wraparound */
|
||||
if (cs->x > 0x7fffffff - cx) rect.right = 0x7fffffff;
|
||||
if (cs->y > 0x7fffffff - cy) rect.bottom = 0x7fffffff;
|
||||
if (!set_window_pos( hwnd, 0, SWP_NOZORDER | SWP_NOACTIVATE, &rect, &rect, NULL )) goto failed;
|
||||
|
||||
/* send WM_NCCREATE */
|
||||
|
||||
TRACE( "hwnd %p cs %d,%d %dx%d %s\n", hwnd, cs->x, cs->y, cs->cx, cs->cy, wine_dbgstr_rect(&rect) );
|
||||
if (unicode)
|
||||
result = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
|
||||
else
|
||||
result = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
|
||||
if (!result)
|
||||
{
|
||||
WARN( "%p: aborted by WM_NCCREATE\n", hwnd );
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* create default IME window */
|
||||
|
||||
if (imm_register_window && !is_desktop_window( hwnd ) &&
|
||||
parent != get_hwnd_message_parent() && imm_register_window( hwnd ))
|
||||
{
|
||||
TRACE("register IME window for %p\n", hwnd);
|
||||
win_set_flags( hwnd, WIN_HAS_IME_WIN, 0 );
|
||||
}
|
||||
|
||||
/* send WM_NCCALCSIZE */
|
||||
|
||||
if (WIN_GetRectangles( hwnd, COORDS_PARENT, &rect, NULL ))
|
||||
{
|
||||
/* yes, even if the CBT hook was called with HWND_TOP */
|
||||
HWND insert_after = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
|
||||
RECT client_rect = rect;
|
||||
|
||||
/* the rectangle is in screen coords for WM_NCCALCSIZE when wparam is FALSE */
|
||||
MapWindowPoints( parent, 0, (POINT *)&client_rect, 2 );
|
||||
SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&client_rect );
|
||||
MapWindowPoints( 0, parent, (POINT *)&client_rect, 2 );
|
||||
set_window_pos( hwnd, insert_after, SWP_NOACTIVATE, &rect, &client_rect, NULL );
|
||||
}
|
||||
else goto failed;
|
||||
|
||||
/* send WM_CREATE */
|
||||
|
||||
if (unicode)
|
||||
result = SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs );
|
||||
else
|
||||
result = SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs );
|
||||
if (result == -1) goto failed;
|
||||
|
||||
/* call the driver */
|
||||
|
||||
if (!USER_Driver->pCreateWindow( hwnd )) goto failed;
|
||||
|
||||
NtUserNotifyWinEvent( EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0 );
|
||||
|
||||
/* send the size messages */
|
||||
|
||||
if (!(win_get_flags( hwnd ) & WIN_NEED_SIZE))
|
||||
{
|
||||
WIN_GetRectangles( hwnd, COORDS_PARENT, NULL, &rect );
|
||||
SendMessageW( hwnd, WM_SIZE, SIZE_RESTORED,
|
||||
MAKELONG(rect.right-rect.left, rect.bottom-rect.top));
|
||||
SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( rect.left, rect.top ) );
|
||||
}
|
||||
|
||||
/* Show the window, maximizing or minimizing if needed */
|
||||
|
||||
style = WIN_SetStyle( hwnd, 0, WS_MAXIMIZE | WS_MINIMIZE );
|
||||
if (style & (WS_MINIMIZE | WS_MAXIMIZE))
|
||||
{
|
||||
RECT newPos;
|
||||
UINT swFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
|
||||
|
||||
swFlag = WINPOS_MinMaximize( hwnd, swFlag, &newPos );
|
||||
swFlag |= SWP_FRAMECHANGED; /* Frame always gets changed */
|
||||
if (!(style & WS_VISIBLE) || (style & WS_CHILD) || GetActiveWindow()) swFlag |= SWP_NOACTIVATE;
|
||||
NtUserSetWindowPos( hwnd, 0, newPos.left, newPos.top, newPos.right - newPos.left,
|
||||
newPos.bottom - newPos.top, swFlag );
|
||||
}
|
||||
|
||||
/* Notify the parent window only */
|
||||
|
||||
send_parent_notify( hwnd, WM_CREATE );
|
||||
if (!IsWindow( hwnd ))
|
||||
{
|
||||
SetThreadDpiAwarenessContext( context );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (parent == GetDesktopWindow())
|
||||
PostMessageW( parent, WM_PARENTNOTIFY, WM_CREATE, (LPARAM)hwnd );
|
||||
|
||||
if (cs->style & WS_VISIBLE)
|
||||
{
|
||||
if (cs->style & WS_MAXIMIZE)
|
||||
sw = SW_SHOW;
|
||||
else if (cs->style & WS_MINIMIZE)
|
||||
sw = SW_SHOWMINIMIZED;
|
||||
|
||||
NtUserShowWindow( hwnd, sw );
|
||||
if (cs->dwExStyle & WS_EX_MDICHILD)
|
||||
{
|
||||
SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
|
||||
/* ShowWindow won't activate child windows */
|
||||
NtUserSetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
|
||||
}
|
||||
}
|
||||
|
||||
/* Call WH_SHELL hook */
|
||||
|
||||
if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
|
||||
HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
|
||||
|
||||
TRACE("created window %p\n", hwnd);
|
||||
SetThreadDpiAwarenessContext( context );
|
||||
cbtc.lpcs = cs;
|
||||
hwnd = NtUserCreateWindowEx( cs->dwExStyle, &class, NULL, NULL, cs->style, cs->x, cs->y,
|
||||
cs->cx, cs->cy, cs->hwndParent, menu, module,
|
||||
cs->lpCreateParams, 0, &cbtc, 0, !unicode );
|
||||
if (!hwnd && menu && menu != cs->hMenu) DestroyMenu( menu );
|
||||
return hwnd;
|
||||
|
||||
failed:
|
||||
NtUserCallHwnd( hwnd, NtUserDestroyWindowHandle );
|
||||
SetThreadDpiAwarenessContext( context );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -66,7 +66,6 @@ extern MINMAXINFO WINPOS_GetMinMaxInfo( HWND hwnd ) DECLSPEC_HIDDEN;
|
|||
extern LONG WINPOS_HandleWindowPosChanging(HWND hwnd, WINDOWPOS *winpos) DECLSPEC_HIDDEN;
|
||||
extern HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest ) DECLSPEC_HIDDEN;
|
||||
extern void WINPOS_ActivateOtherWindow( HWND hwnd ) DECLSPEC_HIDDEN;
|
||||
extern UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect ) DECLSPEC_HIDDEN;
|
||||
extern void WINPOS_SysCommandSizeMove( HWND hwnd, WPARAM wParam ) DECLSPEC_HIDDEN;
|
||||
|
||||
extern UINT get_monitor_dpi( HMONITOR monitor ) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -622,182 +622,6 @@ static void get_next_minimized_child_pos( const RECT *parent, const MINIMIZEDMET
|
|||
}
|
||||
}
|
||||
|
||||
static POINT get_minimized_pos( HWND hwnd, POINT pt )
|
||||
{
|
||||
RECT rect, rectParent;
|
||||
HWND parent, child;
|
||||
HRGN hrgn, tmp;
|
||||
MINIMIZEDMETRICS metrics;
|
||||
int width, height;
|
||||
|
||||
parent = NtUserGetAncestor( hwnd, GA_PARENT );
|
||||
if (parent == GetDesktopWindow())
|
||||
{
|
||||
MONITORINFO mon_info;
|
||||
HMONITOR monitor = MonitorFromWindow( hwnd, MONITOR_DEFAULTTOPRIMARY );
|
||||
|
||||
mon_info.cbSize = sizeof( mon_info );
|
||||
GetMonitorInfoW( monitor, &mon_info );
|
||||
rectParent = mon_info.rcWork;
|
||||
}
|
||||
else GetClientRect( parent, &rectParent );
|
||||
|
||||
if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics( SM_CXMINIMIZED ) < rectParent.right) &&
|
||||
(pt.y >= rectParent.top) && (pt.y + GetSystemMetrics( SM_CYMINIMIZED ) < rectParent.bottom))
|
||||
return pt; /* The icon already has a suitable position */
|
||||
|
||||
width = GetSystemMetrics( SM_CXMINIMIZED );
|
||||
height = GetSystemMetrics( SM_CYMINIMIZED );
|
||||
|
||||
metrics.cbSize = sizeof(metrics);
|
||||
SystemParametersInfoW( SPI_GETMINIMIZEDMETRICS, sizeof(metrics), &metrics, 0 );
|
||||
|
||||
/* Check if another icon already occupies this spot */
|
||||
/* FIXME: this is completely inefficient */
|
||||
|
||||
hrgn = CreateRectRgn( 0, 0, 0, 0 );
|
||||
tmp = CreateRectRgn( 0, 0, 0, 0 );
|
||||
for (child = GetWindow( parent, GW_CHILD ); child; child = GetWindow( child, GW_HWNDNEXT ))
|
||||
{
|
||||
if (child == hwnd) continue;
|
||||
if ((GetWindowLongW( child, GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != (WS_VISIBLE|WS_MINIMIZE))
|
||||
continue;
|
||||
if (WIN_GetRectangles( child, COORDS_PARENT, &rect, NULL ))
|
||||
{
|
||||
SetRectRgn( tmp, rect.left, rect.top, rect.right, rect.bottom );
|
||||
CombineRgn( hrgn, hrgn, tmp, RGN_OR );
|
||||
}
|
||||
}
|
||||
DeleteObject( tmp );
|
||||
|
||||
pt = get_first_minimized_child_pos( &rectParent, &metrics, width, height );
|
||||
for (;;)
|
||||
{
|
||||
SetRect( &rect, pt.x, pt.y, pt.x + width, pt.y + height );
|
||||
if (!RectInRegion( hrgn, &rect ))
|
||||
break;
|
||||
|
||||
get_next_minimized_child_pos( &rectParent, &metrics, width, height, &pt );
|
||||
}
|
||||
|
||||
DeleteObject( hrgn );
|
||||
return pt;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* WINPOS_MinMaximize
|
||||
*/
|
||||
UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect )
|
||||
{
|
||||
UINT swpFlags = 0;
|
||||
LONG old_style;
|
||||
MINMAXINFO minmax;
|
||||
WINDOWPLACEMENT wpl;
|
||||
|
||||
TRACE("%p %u\n", hwnd, cmd );
|
||||
|
||||
wpl.length = sizeof(wpl);
|
||||
GetWindowPlacement( hwnd, &wpl );
|
||||
|
||||
if (HOOK_CallHooks( WH_CBT, HCBT_MINMAX, (WPARAM)hwnd, cmd, TRUE ))
|
||||
return SWP_NOSIZE | SWP_NOMOVE;
|
||||
|
||||
if (IsIconic( hwnd ))
|
||||
{
|
||||
switch (cmd)
|
||||
{
|
||||
case SW_SHOWMINNOACTIVE:
|
||||
case SW_SHOWMINIMIZED:
|
||||
case SW_FORCEMINIMIZE:
|
||||
case SW_MINIMIZE:
|
||||
wpl.ptMinPosition = get_minimized_pos( hwnd, wpl.ptMinPosition );
|
||||
|
||||
SetRect( rect, wpl.ptMinPosition.x, wpl.ptMinPosition.y,
|
||||
wpl.ptMinPosition.x + GetSystemMetrics(SM_CXMINIMIZED),
|
||||
wpl.ptMinPosition.y + GetSystemMetrics(SM_CYMINIMIZED) );
|
||||
return SWP_NOSIZE | SWP_NOMOVE;
|
||||
}
|
||||
if (!SendMessageW( hwnd, WM_QUERYOPEN, 0, 0 )) return SWP_NOSIZE | SWP_NOMOVE;
|
||||
swpFlags |= SWP_NOCOPYBITS;
|
||||
}
|
||||
|
||||
switch( cmd )
|
||||
{
|
||||
case SW_SHOWMINNOACTIVE:
|
||||
case SW_SHOWMINIMIZED:
|
||||
case SW_FORCEMINIMIZE:
|
||||
case SW_MINIMIZE:
|
||||
if (IsZoomed( hwnd )) win_set_flags( hwnd, WIN_RESTORE_MAX, 0 );
|
||||
else win_set_flags( hwnd, 0, WIN_RESTORE_MAX );
|
||||
|
||||
if (GetFocus() == hwnd)
|
||||
{
|
||||
if (GetWindowLongW(hwnd, GWL_STYLE) & WS_CHILD)
|
||||
NtUserSetFocus( NtUserGetAncestor( hwnd, GA_PARENT ));
|
||||
else
|
||||
NtUserSetFocus( 0 );
|
||||
}
|
||||
|
||||
old_style = WIN_SetStyle( hwnd, WS_MINIMIZE, WS_MAXIMIZE );
|
||||
|
||||
wpl.ptMinPosition = get_minimized_pos( hwnd, wpl.ptMinPosition );
|
||||
|
||||
if (!(old_style & WS_MINIMIZE)) swpFlags |= SWP_STATECHANGED;
|
||||
SetRect( rect, wpl.ptMinPosition.x, wpl.ptMinPosition.y,
|
||||
wpl.ptMinPosition.x + GetSystemMetrics(SM_CXMINIMIZED),
|
||||
wpl.ptMinPosition.y + GetSystemMetrics(SM_CYMINIMIZED) );
|
||||
swpFlags |= SWP_NOCOPYBITS;
|
||||
break;
|
||||
|
||||
case SW_MAXIMIZE:
|
||||
old_style = GetWindowLongW( hwnd, GWL_STYLE );
|
||||
if ((old_style & WS_MAXIMIZE) && (old_style & WS_VISIBLE)) return SWP_NOSIZE | SWP_NOMOVE;
|
||||
|
||||
minmax = WINPOS_GetMinMaxInfo( hwnd );
|
||||
|
||||
old_style = WIN_SetStyle( hwnd, WS_MAXIMIZE, WS_MINIMIZE );
|
||||
if (old_style & WS_MINIMIZE)
|
||||
win_set_flags( hwnd, WIN_RESTORE_MAX, 0 );
|
||||
|
||||
if (!(old_style & WS_MAXIMIZE)) swpFlags |= SWP_STATECHANGED;
|
||||
SetRect( rect, minmax.ptMaxPosition.x, minmax.ptMaxPosition.y,
|
||||
minmax.ptMaxPosition.x + minmax.ptMaxSize.x, minmax.ptMaxPosition.y + minmax.ptMaxSize.y );
|
||||
break;
|
||||
|
||||
case SW_SHOWNOACTIVATE:
|
||||
win_set_flags( hwnd, 0, WIN_RESTORE_MAX );
|
||||
/* fall through */
|
||||
case SW_SHOWNORMAL:
|
||||
case SW_RESTORE:
|
||||
case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
|
||||
old_style = WIN_SetStyle( hwnd, 0, WS_MINIMIZE | WS_MAXIMIZE );
|
||||
if (old_style & WS_MINIMIZE)
|
||||
{
|
||||
if (win_get_flags( hwnd ) & WIN_RESTORE_MAX)
|
||||
{
|
||||
/* Restore to maximized position */
|
||||
minmax = WINPOS_GetMinMaxInfo( hwnd );
|
||||
WIN_SetStyle( hwnd, WS_MAXIMIZE, 0 );
|
||||
swpFlags |= SWP_STATECHANGED;
|
||||
SetRect( rect, minmax.ptMaxPosition.x, minmax.ptMaxPosition.y,
|
||||
minmax.ptMaxPosition.x + minmax.ptMaxSize.x, minmax.ptMaxPosition.y + minmax.ptMaxSize.y );
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (!(old_style & WS_MAXIMIZE)) break;
|
||||
|
||||
swpFlags |= SWP_STATECHANGED;
|
||||
|
||||
/* Restore to normal position */
|
||||
|
||||
*rect = wpl.rcNormalPosition;
|
||||
break;
|
||||
}
|
||||
|
||||
return swpFlags;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetInternalWindowPos (USER32.@)
|
||||
|
|
|
@ -161,29 +161,6 @@ static LRESULT call_dialog_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp, LRES
|
|||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* WINPROC_GetProc
|
||||
*
|
||||
* Get a window procedure pointer that can be passed to the Windows program.
|
||||
*/
|
||||
WNDPROC WINPROC_GetProc( WNDPROC proc, BOOL unicode )
|
||||
{
|
||||
WINDOWPROC *ptr = handle_to_proc( proc );
|
||||
|
||||
if (!ptr || ptr == WINPROC_PROC16) return proc;
|
||||
if (unicode)
|
||||
{
|
||||
if (ptr->procW) return ptr->procW;
|
||||
return proc;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ptr->procA) return ptr->procA;
|
||||
return proc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* WINPROC_AllocProc
|
||||
*
|
||||
|
@ -199,22 +176,6 @@ static WNDPROC WINPROC_AllocProc( WNDPROC func, BOOL unicode )
|
|||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* WINPROC_IsUnicode
|
||||
*
|
||||
* Return the window procedure type, or the default value if not a winproc handle.
|
||||
*/
|
||||
BOOL WINPROC_IsUnicode( WNDPROC proc, BOOL def_val )
|
||||
{
|
||||
WINDOWPROC *ptr = handle_to_proc( proc );
|
||||
|
||||
if (!ptr) return def_val;
|
||||
if (ptr == WINPROC_PROC16) return FALSE; /* 16-bit is always A */
|
||||
if (ptr->procA && ptr->procW) return def_val; /* can be both */
|
||||
return (ptr->procW != NULL);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* WINPROC_TestLBForStr
|
||||
*
|
||||
|
|
|
@ -39,6 +39,27 @@ WINE_DECLARE_DEBUG_CHANNEL(win);
|
|||
#define MAX_WINPROCS 4096
|
||||
#define WINPROC_PROC16 ((WINDOWPROC *)1) /* placeholder for 16-bit window procs */
|
||||
|
||||
typedef struct tagCLASS
|
||||
{
|
||||
struct list entry; /* Entry in class list */
|
||||
UINT style; /* Class style */
|
||||
BOOL local; /* Local class? */
|
||||
WNDPROC winproc; /* Window procedure */
|
||||
INT cbClsExtra; /* Class extra bytes */
|
||||
INT cbWndExtra; /* Window extra bytes */
|
||||
struct dce *dce; /* Opaque pointer to class DCE */
|
||||
UINT_PTR instance; /* Module that created the task */
|
||||
HICON hIcon; /* Default icon */
|
||||
HICON hIconSm; /* Default small icon */
|
||||
HICON hIconSmIntern; /* Internal small icon, derived from hIcon */
|
||||
HCURSOR hCursor; /* Default cursor */
|
||||
HBRUSH hbrBackground; /* Default background */
|
||||
ATOM atomName; /* Name of the class */
|
||||
WCHAR name[MAX_ATOM_LEN + 1];
|
||||
WCHAR *basename; /* Base name for redirected classes, pointer within 'name'. */
|
||||
struct client_menu_name menu_name; /* Default menu name */
|
||||
} CLASS;
|
||||
|
||||
static WINDOWPROC winproc_array[MAX_WINPROCS];
|
||||
static UINT winproc_used = NB_BUILTIN_WINPROCS;
|
||||
static pthread_mutex_t winproc_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
@ -283,6 +304,14 @@ static CLASS *find_class( HINSTANCE module, UNICODE_STRING *name )
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* get_class_winproc
|
||||
*/
|
||||
WNDPROC get_class_winproc( CLASS *class )
|
||||
{
|
||||
return class->winproc;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* get_class_dce
|
||||
*/
|
||||
|
|
|
@ -34,6 +34,17 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(win);
|
||||
|
||||
struct dce
|
||||
{
|
||||
struct list entry; /* entry in global DCE list */
|
||||
HDC hdc;
|
||||
HWND hwnd;
|
||||
HRGN clip_rgn;
|
||||
DWORD flags;
|
||||
LONG count; /* usage count; 0 or 1 for cache DCEs, always 1 for window DCEs,
|
||||
always >= 1 for class DCEs */
|
||||
};
|
||||
|
||||
static struct list dce_list = LIST_INIT(dce_list);
|
||||
|
||||
#define DCE_CACHE_SIZE 64
|
||||
|
|
|
@ -1132,6 +1132,11 @@ static BOOL CDECL loaderdrv_CreateDesktopWindow( HWND hwnd )
|
|||
return load_driver()->pCreateDesktopWindow( hwnd );
|
||||
}
|
||||
|
||||
static BOOL CDECL loaderdrv_CreateWindow( HWND hwnd )
|
||||
{
|
||||
return load_driver()->pCreateWindow( hwnd );
|
||||
}
|
||||
|
||||
static void CDECL loaderdrv_GetDC( HDC hdc, HWND hwnd, HWND top_win, const RECT *win_rect,
|
||||
const RECT *top_rect, DWORD flags )
|
||||
{
|
||||
|
@ -1190,6 +1195,7 @@ static const struct user_driver_funcs lazy_load_driver =
|
|||
.pUpdateDisplayDevices = loaderdrv_UpdateDisplayDevices,
|
||||
/* windowing functions */
|
||||
.pCreateDesktopWindow = loaderdrv_CreateDesktopWindow,
|
||||
.pCreateWindow = loaderdrv_CreateWindow,
|
||||
.pDestroyWindow = nulldrv_DestroyWindow,
|
||||
.pFlashWindowEx = loaderdrv_FlashWindowEx,
|
||||
.pGetDC = loaderdrv_GetDC,
|
||||
|
|
|
@ -1160,6 +1160,7 @@ static struct unix_funcs unix_funcs =
|
|||
NtUserChangeDisplaySettings,
|
||||
NtUserClipCursor,
|
||||
NtUserCountClipboardFormats,
|
||||
NtUserCreateWindowEx,
|
||||
NtUserDeferWindowPosAndBand,
|
||||
NtUserDestroyCursor,
|
||||
NtUserDestroyWindow,
|
||||
|
|
|
@ -119,3 +119,11 @@ BOOL WINAPI NtUserDestroyMenu( HMENU menu )
|
|||
{
|
||||
return user_callbacks && user_callbacks->pDestroyMenu( menu );
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* NtUserSetSystemMenu (win32u.@)
|
||||
*/
|
||||
BOOL WINAPI NtUserSetSystemMenu( HWND hwnd, HMENU menu )
|
||||
{
|
||||
return user_callbacks && user_callbacks->pSetSystemMenu( hwnd, menu );
|
||||
}
|
||||
|
|
|
@ -231,12 +231,23 @@ BOOL kill_system_timer( HWND hwnd, UINT_PTR id )
|
|||
return ret;
|
||||
}
|
||||
|
||||
static BOOL send_window_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam,
|
||||
LRESULT *result, BOOL ansi )
|
||||
{
|
||||
/* FIXME: move implementation from user32 */
|
||||
if (!user_callbacks) return FALSE;
|
||||
*result = ansi
|
||||
? user_callbacks->pSendMessageA( hwnd, msg, wparam, lparam )
|
||||
: user_callbacks->pSendMessageW( hwnd, msg, wparam, lparam );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* see SendMessageW */
|
||||
LRESULT send_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
|
||||
{
|
||||
/* FIXME: move implementation from user32 */
|
||||
if (!user_callbacks) return 0;
|
||||
return user_callbacks->pSendMessageW( hwnd, msg, wparam, lparam );
|
||||
LRESULT result = 0;
|
||||
send_window_message( hwnd, msg, wparam, lparam, &result, FALSE );
|
||||
return result;
|
||||
}
|
||||
|
||||
/* see SendNotifyMessageW */
|
||||
|
@ -258,6 +269,8 @@ BOOL WINAPI NtUserMessageCall( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam
|
|||
{
|
||||
switch (type)
|
||||
{
|
||||
case FNID_SENDMESSAGE:
|
||||
return send_window_message( hwnd, msg, wparam, lparam, (LRESULT *)result_info, ansi );
|
||||
case FNID_SENDNOTIFYMESSAGE:
|
||||
return send_notify_message( hwnd, msg, wparam, lparam, ansi );
|
||||
default:
|
||||
|
|
|
@ -39,8 +39,10 @@ struct user_callbacks
|
|||
BOOL (WINAPI *pPostMessageW)( HWND, UINT, WPARAM, LPARAM );
|
||||
UINT (WINAPI *pSendInput)( UINT count, INPUT *inputs, int size );
|
||||
LRESULT (WINAPI *pSendMessageTimeoutW)( HWND, UINT, WPARAM, LPARAM, UINT, UINT, PDWORD_PTR );
|
||||
LRESULT (WINAPI *pSendMessageA)( HWND, UINT, WPARAM, LPARAM );
|
||||
LRESULT (WINAPI *pSendMessageW)( HWND, UINT, WPARAM, LPARAM );
|
||||
BOOL (WINAPI *pSendNotifyMessageW)( HWND, UINT, WPARAM, LPARAM );
|
||||
BOOL (WINAPI *pSetSystemMenu)( HWND hwnd, HMENU menu );
|
||||
BOOL (WINAPI *pShowCaret)( HWND hwnd );
|
||||
DWORD (WINAPI *pWaitForInputIdle)( HANDLE, DWORD );
|
||||
void (CDECL *free_win_ptr)( struct tagWND *win );
|
||||
|
@ -48,11 +50,13 @@ struct user_callbacks
|
|||
void (CDECL *notify_ime)( HWND hwnd, UINT param );
|
||||
void (CDECL *register_builtin_classes)(void);
|
||||
LRESULT (WINAPI *send_ll_message)( DWORD, DWORD, UINT, WPARAM, LPARAM, UINT, UINT, PDWORD_PTR );
|
||||
BOOL (CDECL *set_menu)( HWND hwnd, HMENU menu );
|
||||
void (WINAPI *set_standard_scroll_painted)( HWND hwnd, INT bar, BOOL visible );
|
||||
void (CDECL *set_user_driver)( void *, UINT );
|
||||
BOOL (CDECL *set_window_pos)( HWND hwnd, HWND insert_after, UINT swp_flags,
|
||||
const RECT *window_rect, const RECT *client_rect,
|
||||
const RECT *valid_rects );
|
||||
BOOL (WINAPI *register_imm)( HWND hwnd );
|
||||
void (WINAPI *unregister_imm)( HWND hwnd );
|
||||
};
|
||||
|
||||
|
@ -69,7 +73,6 @@ struct user_object
|
|||
|
||||
HANDLE alloc_user_handle( struct user_object *ptr, unsigned int type ) DECLSPEC_HIDDEN;
|
||||
void *get_user_handle_ptr( HANDLE handle, unsigned int type ) DECLSPEC_HIDDEN;
|
||||
void set_user_handle_ptr( HANDLE handle, struct user_object *ptr ) DECLSPEC_HIDDEN;
|
||||
void release_user_handle_ptr( void *ptr ) DECLSPEC_HIDDEN;
|
||||
void *free_user_handle( HANDLE handle, unsigned int type ) DECLSPEC_HIDDEN;
|
||||
|
||||
|
@ -210,18 +213,6 @@ typedef struct tagWINDOWPROC
|
|||
|
||||
#define MAX_ATOM_LEN 255
|
||||
|
||||
/* FIXME: make it private to dce.c */
|
||||
struct dce
|
||||
{
|
||||
struct list entry; /* entry in global DCE list */
|
||||
HDC hdc;
|
||||
HWND hwnd;
|
||||
HRGN clip_rgn;
|
||||
DWORD flags;
|
||||
LONG count; /* usage count; 0 or 1 for cache DCEs, always 1 for window DCEs,
|
||||
always >= 1 for class DCEs */
|
||||
};
|
||||
|
||||
/* Built-in class names (see _Undocumented_Windows_ p.418) */
|
||||
#define POPUPMENU_CLASS_ATOM MAKEINTATOM(32768) /* PopupMenu */
|
||||
#define DESKTOP_CLASS_ATOM MAKEINTATOM(32769) /* Desktop */
|
||||
|
@ -229,32 +220,12 @@ struct dce
|
|||
#define WINSWITCH_CLASS_ATOM MAKEINTATOM(32771) /* WinSwitch */
|
||||
#define ICONTITLE_CLASS_ATOM MAKEINTATOM(32772) /* IconTitle */
|
||||
|
||||
typedef struct tagCLASS
|
||||
{
|
||||
struct list entry; /* Entry in class list */
|
||||
UINT style; /* Class style */
|
||||
BOOL local; /* Local class? */
|
||||
WNDPROC winproc; /* Window procedure */
|
||||
INT cbClsExtra; /* Class extra bytes */
|
||||
INT cbWndExtra; /* Window extra bytes */
|
||||
struct client_menu_name menu_name; /* Default menu name */
|
||||
struct dce *dce; /* Opaque pointer to class DCE */
|
||||
UINT_PTR instance; /* Module that created the task */
|
||||
HICON hIcon; /* Default icon */
|
||||
HICON hIconSm; /* Default small icon */
|
||||
HICON hIconSmIntern; /* Internal small icon, derived from hIcon */
|
||||
HCURSOR hCursor; /* Default cursor */
|
||||
HBRUSH hbrBackground; /* Default background */
|
||||
ATOM atomName; /* Name of the class */
|
||||
WCHAR name[MAX_ATOM_LEN + 1];
|
||||
WCHAR *basename; /* Base name for redirected classes, pointer within 'name'. */
|
||||
} CLASS;
|
||||
|
||||
/* class.c */
|
||||
WNDPROC alloc_winproc( WNDPROC func, BOOL ansi ) DECLSPEC_HIDDEN;
|
||||
WINDOWPROC *get_winproc_ptr( WNDPROC handle ) DECLSPEC_HIDDEN;
|
||||
BOOL is_winproc_unicode( WNDPROC proc, BOOL def_val ) DECLSPEC_HIDDEN;
|
||||
DWORD get_class_long( HWND hwnd, INT offset, BOOL ansi ) DECLSPEC_HIDDEN;
|
||||
WNDPROC get_class_winproc( struct tagCLASS *class ) DECLSPEC_HIDDEN;
|
||||
ULONG_PTR get_class_long_ptr( HWND hwnd, INT offset, BOOL ansi ) DECLSPEC_HIDDEN;
|
||||
WORD get_class_word( HWND hwnd, INT offset ) DECLSPEC_HIDDEN;
|
||||
ATOM get_int_atom_value( UNICODE_STRING *name ) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -1391,7 +1391,7 @@ UINT get_win_monitor_dpi( HWND hwnd )
|
|||
/**********************************************************************
|
||||
* get_thread_dpi_awareness
|
||||
*/
|
||||
static DPI_AWARENESS get_thread_dpi_awareness(void)
|
||||
DPI_AWARENESS get_thread_dpi_awareness(void)
|
||||
{
|
||||
struct user_thread_info *info = get_user_thread_info();
|
||||
ULONG_PTR context = info->dpi_awareness;
|
||||
|
@ -4749,9 +4749,6 @@ ULONG_PTR WINAPI NtUserCallTwoParam( ULONG_PTR arg1, ULONG_PTR arg2, ULONG code
|
|||
case NtUserRegisterWindowSurface:
|
||||
register_window_surface( (struct window_surface *)arg1, (struct window_surface *)arg2 );
|
||||
return 0;
|
||||
case NtUserSetHandlePtr:
|
||||
set_user_handle_ptr( UlongToHandle(arg1), (struct user_object *)arg2 );
|
||||
return 0;
|
||||
default:
|
||||
FIXME( "invalid code %u\n", code );
|
||||
return 0;
|
||||
|
|
|
@ -814,7 +814,7 @@
|
|||
@ stub NtUserCreateInputContext
|
||||
@ stub NtUserCreateLocalMemHandle
|
||||
@ stub NtUserCreatePalmRejectionDelayZone
|
||||
@ stub NtUserCreateWindowEx
|
||||
@ stdcall NtUserCreateWindowEx(long ptr ptr ptr long long long long long long long long ptr long long long long)
|
||||
@ stub NtUserCreateWindowGroup
|
||||
@ stdcall -syscall NtUserCreateWindowStation(ptr long long long long long long)
|
||||
@ stub NtUserCtxDisplayIOCtl
|
||||
|
|
|
@ -195,6 +195,11 @@ struct unix_funcs
|
|||
DWORD flags, void *lparam );
|
||||
BOOL (WINAPI *pNtUserClipCursor)( const RECT *rect );
|
||||
INT (WINAPI *pNtUserCountClipboardFormats)(void);
|
||||
HWND (WINAPI *pNtUserCreateWindowEx)( DWORD ex_style, UNICODE_STRING *class_name,
|
||||
UNICODE_STRING *version, UNICODE_STRING *window_name,
|
||||
DWORD style, INT x, INT y, INT width, INT height,
|
||||
HWND parent, HMENU menu, HINSTANCE instance, void *params,
|
||||
DWORD flags, CBT_CREATEWNDW *cbtc, DWORD unk, BOOL ansi );
|
||||
HDWP (WINAPI *pNtUserDeferWindowPosAndBand)( HDWP hdwp, HWND hwnd, HWND after,
|
||||
INT x, INT y, INT cx, INT cy,
|
||||
UINT flags, UINT unk1, UINT unk2 );
|
||||
|
@ -300,6 +305,7 @@ extern ULONG_PTR set_icon_param( HICON handle, ULONG_PTR param ) DECLSPEC_HIDDEN
|
|||
|
||||
/* dce.c */
|
||||
extern struct window_surface dummy_surface DECLSPEC_HIDDEN;
|
||||
extern void erase_now( HWND hwnd, UINT rdw_flags ) DECLSPEC_HIDDEN;
|
||||
extern void flush_window_surfaces( BOOL idle ) DECLSPEC_HIDDEN;
|
||||
extern void register_window_surface( struct window_surface *old,
|
||||
struct window_surface *new ) DECLSPEC_HIDDEN;
|
||||
|
@ -336,6 +342,7 @@ extern RECT get_primary_monitor_rect( UINT dpi ) DECLSPEC_HIDDEN;
|
|||
extern UINT get_system_dpi(void) DECLSPEC_HIDDEN;
|
||||
extern int get_system_metrics( int index ) DECLSPEC_HIDDEN;
|
||||
extern UINT get_thread_dpi(void) DECLSPEC_HIDDEN;
|
||||
extern DPI_AWARENESS get_thread_dpi_awareness(void) DECLSPEC_HIDDEN;
|
||||
extern RECT get_virtual_screen_rect( UINT dpi ) DECLSPEC_HIDDEN;
|
||||
extern BOOL is_exiting_thread( DWORD tid ) DECLSPEC_HIDDEN;
|
||||
extern POINT map_dpi_point( POINT pt, UINT dpi_from, UINT dpi_to ) DECLSPEC_HIDDEN;
|
||||
|
@ -348,9 +355,6 @@ extern void user_lock(void) DECLSPEC_HIDDEN;
|
|||
extern void user_unlock(void) DECLSPEC_HIDDEN;
|
||||
extern void user_check_not_lock(void) DECLSPEC_HIDDEN;
|
||||
|
||||
/* windc.c */
|
||||
extern void erase_now( HWND hwnd, UINT rdw_flags ) DECLSPEC_HIDDEN;
|
||||
|
||||
/* window.c */
|
||||
struct tagWND;
|
||||
extern HDWP begin_defer_window_pos( INT count ) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -100,7 +100,7 @@ void *get_user_handle_ptr( HANDLE handle, unsigned int type )
|
|||
/***********************************************************************
|
||||
* set_user_handle_ptr
|
||||
*/
|
||||
void set_user_handle_ptr( HANDLE handle, struct user_object *ptr )
|
||||
static void set_user_handle_ptr( HANDLE handle, struct user_object *ptr )
|
||||
{
|
||||
WORD index = USER_HANDLE_TO_INDEX(handle);
|
||||
assert( index < NB_USER_HANDLES );
|
||||
|
@ -3990,6 +3990,7 @@ static void free_window_handle( HWND hwnd )
|
|||
SERVER_END_REQ;
|
||||
user_unlock();
|
||||
if (user_callbacks) user_callbacks->free_win_ptr( win );
|
||||
free( win );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4192,9 +4193,490 @@ void destroy_thread_windows(void)
|
|||
window_surface_release( win->surface );
|
||||
}
|
||||
if (user_callbacks) user_callbacks->free_win_ptr( win );
|
||||
free( win );
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* create_window_handle
|
||||
*
|
||||
* Create a window handle with the server.
|
||||
*/
|
||||
static WND *create_window_handle( HWND parent, HWND owner, UNICODE_STRING *name,
|
||||
HINSTANCE instance, BOOL ansi,
|
||||
DWORD style, DWORD ex_style )
|
||||
{
|
||||
DPI_AWARENESS awareness = get_thread_dpi_awareness();
|
||||
HWND handle = 0, full_parent = 0, full_owner = 0;
|
||||
struct tagCLASS *class = NULL;
|
||||
int extra_bytes = 0;
|
||||
UINT dpi = 0;
|
||||
WND *win;
|
||||
|
||||
SERVER_START_REQ( create_window )
|
||||
{
|
||||
req->parent = wine_server_user_handle( parent );
|
||||
req->owner = wine_server_user_handle( owner );
|
||||
req->instance = wine_server_client_ptr( instance );
|
||||
req->dpi = get_system_dpi();
|
||||
req->awareness = awareness;
|
||||
req->style = style;
|
||||
req->ex_style = ex_style;
|
||||
if (!(req->atom = get_int_atom_value( name )) && name->Length)
|
||||
wine_server_add_data( req, name->Buffer, name->Length );
|
||||
if (!wine_server_call_err( req ))
|
||||
{
|
||||
handle = wine_server_ptr_handle( reply->handle );
|
||||
full_parent = wine_server_ptr_handle( reply->parent );
|
||||
full_owner = wine_server_ptr_handle( reply->owner );
|
||||
extra_bytes = reply->extra;
|
||||
dpi = reply->dpi;
|
||||
awareness = reply->awareness;
|
||||
class = wine_server_get_ptr( reply->class_ptr );
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
if (!handle)
|
||||
{
|
||||
WARN( "error %d creating window\n", GetLastError() );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(win = calloc( 1, FIELD_OFFSET(WND, wExtra) + extra_bytes )))
|
||||
{
|
||||
SERVER_START_REQ( destroy_window )
|
||||
{
|
||||
req->handle = wine_server_user_handle( handle );
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!parent) /* if parent is 0 we don't have a desktop window yet */
|
||||
{
|
||||
struct user_thread_info *thread_info = get_user_thread_info();
|
||||
|
||||
if (name->Buffer == (const WCHAR *)DESKTOP_CLASS_ATOM)
|
||||
{
|
||||
if (!thread_info->top_window) thread_info->top_window = full_parent ? full_parent : handle;
|
||||
else assert( full_parent == thread_info->top_window );
|
||||
if (full_parent && !user_driver->pCreateDesktopWindow( thread_info->top_window ))
|
||||
ERR( "failed to create desktop window\n" );
|
||||
if (user_callbacks) user_callbacks->register_builtin_classes();
|
||||
}
|
||||
else /* HWND_MESSAGE parent */
|
||||
{
|
||||
if (!thread_info->msg_window && !full_parent) thread_info->msg_window = handle;
|
||||
}
|
||||
}
|
||||
|
||||
user_lock();
|
||||
|
||||
win->obj.handle = handle;
|
||||
win->obj.type = NTUSER_OBJ_WINDOW;
|
||||
win->parent = full_parent;
|
||||
win->owner = full_owner;
|
||||
win->class = class;
|
||||
win->winproc = get_class_winproc( class );
|
||||
win->cbWndExtra = extra_bytes;
|
||||
win->dpi = dpi;
|
||||
win->dpi_awareness = awareness;
|
||||
set_user_handle_ptr( handle, &win->obj );
|
||||
if (is_winproc_unicode( win->winproc, !ansi )) win->flags |= WIN_ISUNICODE;
|
||||
return win;
|
||||
}
|
||||
|
||||
static BOOL is_default_coord( int x )
|
||||
{
|
||||
return x == CW_USEDEFAULT || x == 0x8000;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* fix_cs_coordinates
|
||||
*
|
||||
* Fix the coordinates and return default show mode in sw.
|
||||
*/
|
||||
static void fix_cs_coordinates( CREATESTRUCTW *cs, INT *sw )
|
||||
{
|
||||
if (cs->style & (WS_CHILD | WS_POPUP))
|
||||
{
|
||||
if (is_default_coord(cs->x)) cs->x = cs->y = 0;
|
||||
if (is_default_coord(cs->cx)) cs->cx = cs->cy = 0;
|
||||
}
|
||||
else /* overlapped window */
|
||||
{
|
||||
RTL_USER_PROCESS_PARAMETERS *params = NtCurrentTeb()->Peb->ProcessParameters;
|
||||
HMONITOR monitor;
|
||||
MONITORINFO mon_info;
|
||||
|
||||
if (!is_default_coord( cs->x ) && !is_default_coord( cs->cx ) && !is_default_coord( cs->cy ))
|
||||
return;
|
||||
|
||||
monitor = monitor_from_window( cs->hwndParent, MONITOR_DEFAULTTOPRIMARY, get_thread_dpi() );
|
||||
mon_info.cbSize = sizeof(mon_info);
|
||||
get_monitor_info( monitor, &mon_info );
|
||||
|
||||
if (is_default_coord( cs->x ))
|
||||
{
|
||||
if (!is_default_coord( cs->y )) *sw = cs->y;
|
||||
cs->x = (params->dwFlags & STARTF_USEPOSITION) ? params->dwX : mon_info.rcWork.left;
|
||||
cs->y = (params->dwFlags & STARTF_USEPOSITION) ? params->dwY : mon_info.rcWork.top;
|
||||
}
|
||||
|
||||
if (is_default_coord( cs->cx ))
|
||||
{
|
||||
if (params->dwFlags & STARTF_USESIZE)
|
||||
{
|
||||
cs->cx = params->dwXSize;
|
||||
cs->cy = params->dwYSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
cs->cx = (mon_info.rcWork.right - mon_info.rcWork.left) * 3 / 4 - cs->x;
|
||||
cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
|
||||
}
|
||||
}
|
||||
/* neither x nor cx are default. Check the y values.
|
||||
* In the trace we see Outlook and Outlook Express using
|
||||
* cy set to CW_USEDEFAULT when opening the address book.
|
||||
*/
|
||||
else if (is_default_coord( cs->cy ))
|
||||
{
|
||||
FIXME( "Strange use of CW_USEDEFAULT in cy\n" );
|
||||
cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* map_dpi_create_struct
|
||||
*/
|
||||
static void map_dpi_create_struct( CREATESTRUCTW *cs, UINT dpi_from, UINT dpi_to )
|
||||
{
|
||||
if (!dpi_from && !dpi_to) return;
|
||||
if (!dpi_from || !dpi_to)
|
||||
{
|
||||
POINT pt = { cs->x, cs->y };
|
||||
UINT mon_dpi = get_monitor_dpi( monitor_from_point( pt, MONITOR_DEFAULTTONEAREST, dpi_from ));
|
||||
if (!dpi_from) dpi_from = mon_dpi;
|
||||
else dpi_to = mon_dpi;
|
||||
}
|
||||
if (dpi_from == dpi_to) return;
|
||||
cs->x = muldiv( cs->x, dpi_to, dpi_from );
|
||||
cs->y = muldiv( cs->y, dpi_to, dpi_from );
|
||||
cs->cx = muldiv( cs->cx, dpi_to, dpi_from );
|
||||
cs->cy = muldiv( cs->cy, dpi_to, dpi_from );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* NtUserCreateWindowEx (win32u.@)
|
||||
*/
|
||||
HWND WINAPI NtUserCreateWindowEx( DWORD ex_style, UNICODE_STRING *class_name,
|
||||
UNICODE_STRING *version, UNICODE_STRING *window_name,
|
||||
DWORD style, INT x, INT y, INT cx, INT cy,
|
||||
HWND parent, HMENU menu, HINSTANCE instance, void *params,
|
||||
DWORD flags, CBT_CREATEWNDW *cbtc, DWORD unk, BOOL ansi )
|
||||
{
|
||||
CREATESTRUCTW cs, *client_cs = cbtc->lpcs;
|
||||
UINT win_dpi, thread_dpi = get_thread_dpi();
|
||||
DPI_AWARENESS_CONTEXT context;
|
||||
HWND hwnd, owner = 0;
|
||||
INT sw = SW_SHOW;
|
||||
LRESULT result;
|
||||
RECT rect;
|
||||
WND *win;
|
||||
|
||||
static const WCHAR messageW[] = {'M','e','s','s','a','g','e'};
|
||||
|
||||
cs.lpCreateParams = params;
|
||||
cs.hInstance = client_cs->hInstance; /* may be different than instance for win16 */
|
||||
cs.hMenu = menu;
|
||||
cs.hwndParent = parent;
|
||||
cs.style = style;
|
||||
cs.dwExStyle = ex_style;
|
||||
cs.x = x;
|
||||
cs.y = y;
|
||||
cs.cx = cx;
|
||||
cs.cy = cy;
|
||||
/* We use client_cs to pass original class and name pointers,
|
||||
* that's probably not how native handles it. */
|
||||
cs.lpszName = client_cs->lpszName;
|
||||
cs.lpszClass = client_cs->lpszClass;
|
||||
|
||||
/* Find the parent window */
|
||||
if (parent == HWND_MESSAGE)
|
||||
{
|
||||
cs.hwndParent = parent = get_hwnd_message_parent();
|
||||
}
|
||||
else if (parent)
|
||||
{
|
||||
if ((cs.style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
|
||||
{
|
||||
owner = parent;
|
||||
parent = get_desktop_window();
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD parent_style = get_window_long( parent, GWL_EXSTYLE );
|
||||
if ((parent_style & WS_EX_LAYOUTRTL) && !(parent_style & WS_EX_NOINHERITLAYOUT))
|
||||
cs.dwExStyle |= WS_EX_LAYOUTRTL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((cs.style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
|
||||
{
|
||||
WARN( "No parent for child window\n" );
|
||||
SetLastError( ERROR_TLW_WITH_WSCHILD );
|
||||
return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
|
||||
}
|
||||
|
||||
/* are we creating the desktop or HWND_MESSAGE parent itself? */
|
||||
if (class_name->Buffer != (LPCWSTR)DESKTOP_CLASS_ATOM &&
|
||||
(class_name->Length != sizeof(messageW) ||
|
||||
wcsnicmp( class_name->Buffer, messageW, ARRAYSIZE(messageW) )))
|
||||
{
|
||||
parent = get_desktop_window();
|
||||
}
|
||||
}
|
||||
|
||||
fix_cs_coordinates( &cs, &sw );
|
||||
cs.dwExStyle = fix_exstyle( cs.style, cs.dwExStyle );
|
||||
|
||||
/* Create the window structure */
|
||||
|
||||
style = cs.style & ~WS_VISIBLE;
|
||||
ex_style = cs.dwExStyle & ~WS_EX_LAYERED;
|
||||
if (!(win = create_window_handle( parent, owner, class_name, instance, ansi, style, ex_style )))
|
||||
return 0;
|
||||
hwnd = win->obj.handle;
|
||||
|
||||
/* Fill the window structure */
|
||||
|
||||
win->tid = GetCurrentThreadId();
|
||||
win->hInstance = cs.hInstance;
|
||||
win->text = NULL;
|
||||
win->dwStyle = style;
|
||||
win->dwExStyle = ex_style;
|
||||
win->wIDmenu = 0;
|
||||
win->helpContext = 0;
|
||||
win->pScroll = NULL;
|
||||
win->userdata = 0;
|
||||
win->hIcon = 0;
|
||||
win->hIconSmall = 0;
|
||||
win->hIconSmall2 = 0;
|
||||
win->hSysMenu = 0;
|
||||
|
||||
win->min_pos.x = win->min_pos.y = -1;
|
||||
win->max_pos.x = win->max_pos.y = -1;
|
||||
SetRect( &win->normal_rect, cs.x, cs.y, cs.x + cs.cx, cs.y + cs.cy );
|
||||
|
||||
if (win->dwStyle & WS_SYSMENU) NtUserSetSystemMenu( hwnd, 0 );
|
||||
|
||||
/* call the WH_CBT hook */
|
||||
|
||||
release_win_ptr( win );
|
||||
*client_cs = cs;
|
||||
cbtc->hwndInsertAfter = HWND_TOP;
|
||||
if (call_hooks( WH_CBT, HCBT_CREATEWND, (WPARAM)hwnd, (LPARAM)cbtc, !ansi ))
|
||||
{
|
||||
free_window_handle( hwnd );
|
||||
return 0;
|
||||
}
|
||||
if (!(win = get_win_ptr( hwnd ))) return 0;
|
||||
|
||||
/*
|
||||
* Correct the window styles.
|
||||
*
|
||||
* It affects only the style loaded into the WND structure.
|
||||
*/
|
||||
|
||||
if ((win->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
|
||||
{
|
||||
win->dwStyle |= WS_CLIPSIBLINGS;
|
||||
if (!(win->dwStyle & WS_POPUP)) win->dwStyle |= WS_CAPTION;
|
||||
}
|
||||
|
||||
win->dwExStyle = cs.dwExStyle;
|
||||
/* WS_EX_WINDOWEDGE depends on some other styles */
|
||||
if ((win->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)) &&
|
||||
!(win->dwStyle & (WS_CHILD | WS_POPUP)))
|
||||
win->dwExStyle |= WS_EX_WINDOWEDGE;
|
||||
|
||||
if (!(win->dwStyle & (WS_CHILD | WS_POPUP))) win->flags |= WIN_NEED_SIZE;
|
||||
|
||||
SERVER_START_REQ( set_window_info )
|
||||
{
|
||||
req->handle = wine_server_user_handle( hwnd );
|
||||
req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
|
||||
req->style = win->dwStyle;
|
||||
req->ex_style = win->dwExStyle;
|
||||
req->instance = wine_server_client_ptr( win->hInstance );
|
||||
req->is_unicode = (win->flags & WIN_ISUNICODE) != 0;
|
||||
req->extra_offset = -1;
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
/* Set the window menu */
|
||||
|
||||
if ((win->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
|
||||
{
|
||||
if (cs.hMenu && user_callbacks && !user_callbacks->set_menu( hwnd, cs.hMenu ))
|
||||
{
|
||||
release_win_ptr( win );
|
||||
free_window_handle( hwnd );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else NtUserSetWindowLongPtr( hwnd, GWLP_ID, (ULONG_PTR)cs.hMenu, FALSE );
|
||||
|
||||
win_dpi = win->dpi;
|
||||
release_win_ptr( win );
|
||||
|
||||
if (parent) map_dpi_create_struct( &cs, thread_dpi, win_dpi );
|
||||
|
||||
context = set_thread_dpi_awareness_context( get_window_dpi_awareness_context( hwnd ));
|
||||
|
||||
/* send the WM_GETMINMAXINFO message and fix the size if needed */
|
||||
|
||||
cx = cs.cx;
|
||||
cy = cs.cy;
|
||||
if ((cs.style & WS_THICKFRAME) || !(cs.style & (WS_POPUP | WS_CHILD)))
|
||||
{
|
||||
MINMAXINFO info = get_min_max_info( hwnd );
|
||||
cx = max( min( cx, info.ptMaxTrackSize.x ), info.ptMinTrackSize.x );
|
||||
cy = max( min( cy, info.ptMaxTrackSize.y ), info.ptMinTrackSize.y );
|
||||
}
|
||||
|
||||
if (cx < 0) cx = 0;
|
||||
if (cy < 0) cy = 0;
|
||||
set_rect( &rect, cs.x, cs.y, cs.x + cx, cs.y + cy );
|
||||
/* check for wraparound */
|
||||
if (cs.x > 0x7fffffff - cx) rect.right = 0x7fffffff;
|
||||
if (cs.y > 0x7fffffff - cy) rect.bottom = 0x7fffffff;
|
||||
if (user_callbacks && !user_callbacks->set_window_pos( hwnd, 0, SWP_NOZORDER | SWP_NOACTIVATE,
|
||||
&rect, &rect, NULL )) goto failed;
|
||||
|
||||
/* send WM_NCCREATE */
|
||||
|
||||
TRACE( "hwnd %p cs %d,%d %dx%d %s\n", hwnd, cs.x, cs.y, cs.cx, cs.cy, wine_dbgstr_rect(&rect) );
|
||||
*client_cs = cs;
|
||||
if (!NtUserMessageCall( hwnd, WM_NCCREATE, 0, (LPARAM)client_cs, (ULONG_PTR)&result,
|
||||
FNID_SENDMESSAGE, ansi ) || !result)
|
||||
{
|
||||
WARN( "%p: aborted by WM_NCCREATE\n", hwnd );
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* create default IME window */
|
||||
|
||||
if (!is_desktop_window( hwnd ) && parent != get_hwnd_message_parent() &&
|
||||
user_callbacks && user_callbacks->register_imm( hwnd ))
|
||||
{
|
||||
TRACE( "register IME window for %p\n", hwnd );
|
||||
win_set_flags( hwnd, WIN_HAS_IME_WIN, 0 );
|
||||
}
|
||||
|
||||
/* send WM_NCCALCSIZE */
|
||||
|
||||
if (get_window_rects( hwnd, COORDS_PARENT, &rect, NULL, win_dpi ))
|
||||
{
|
||||
/* yes, even if the CBT hook was called with HWND_TOP */
|
||||
HWND insert_after = (get_window_long( hwnd, GWL_STYLE ) & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
|
||||
RECT client_rect = rect;
|
||||
|
||||
/* the rectangle is in screen coords for WM_NCCALCSIZE when wparam is FALSE */
|
||||
map_window_points( parent, 0, (POINT *)&client_rect, 2, win_dpi );
|
||||
send_message( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&client_rect );
|
||||
map_window_points( 0, parent, (POINT *)&client_rect, 2, win_dpi );
|
||||
user_callbacks->set_window_pos( hwnd, insert_after, SWP_NOACTIVATE, &rect, &client_rect, NULL );
|
||||
}
|
||||
else goto failed;
|
||||
|
||||
/* send WM_CREATE */
|
||||
if (!NtUserMessageCall( hwnd, WM_CREATE, 0, (LPARAM)client_cs, (ULONG_PTR)&result,
|
||||
FNID_SENDMESSAGE, ansi ) || result == -1) goto failed;
|
||||
cs = *client_cs;
|
||||
|
||||
/* call the driver */
|
||||
|
||||
if (!user_driver->pCreateWindow( hwnd )) goto failed;
|
||||
|
||||
NtUserNotifyWinEvent( EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0 );
|
||||
|
||||
/* send the size messages */
|
||||
|
||||
if (!(win_get_flags( hwnd ) & WIN_NEED_SIZE))
|
||||
{
|
||||
get_window_rects( hwnd, COORDS_PARENT, NULL, &rect, win_dpi );
|
||||
send_message( hwnd, WM_SIZE, SIZE_RESTORED,
|
||||
MAKELONG(rect.right-rect.left, rect.bottom-rect.top));
|
||||
send_message( hwnd, WM_MOVE, 0, MAKELONG( rect.left, rect.top ) );
|
||||
}
|
||||
|
||||
/* Show the window, maximizing or minimizing if needed */
|
||||
|
||||
style = set_window_style( hwnd, 0, WS_MAXIMIZE | WS_MINIMIZE );
|
||||
if (style & (WS_MINIMIZE | WS_MAXIMIZE))
|
||||
{
|
||||
RECT new_pos;
|
||||
UINT sw_flags = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
|
||||
|
||||
sw_flags = window_min_maximize( hwnd, sw_flags, &new_pos );
|
||||
sw_flags |= SWP_FRAMECHANGED; /* Frame always gets changed */
|
||||
if (!(style & WS_VISIBLE) || (style & WS_CHILD) || get_active_window())
|
||||
sw_flags |= SWP_NOACTIVATE;
|
||||
NtUserSetWindowPos( hwnd, 0, new_pos.left, new_pos.top, new_pos.right - new_pos.left,
|
||||
new_pos.bottom - new_pos.top, sw_flags );
|
||||
}
|
||||
|
||||
/* Notify the parent window only */
|
||||
|
||||
send_parent_notify( hwnd, WM_CREATE );
|
||||
if (!is_window( hwnd ))
|
||||
{
|
||||
set_thread_dpi_awareness_context( context );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (parent == get_desktop_window())
|
||||
post_message( parent, WM_PARENTNOTIFY, WM_CREATE, (LPARAM)hwnd );
|
||||
|
||||
if (cs.style & WS_VISIBLE)
|
||||
{
|
||||
if (cs.style & WS_MAXIMIZE)
|
||||
sw = SW_SHOW;
|
||||
else if (cs.style & WS_MINIMIZE)
|
||||
sw = SW_SHOWMINIMIZED;
|
||||
|
||||
NtUserShowWindow( hwnd, sw );
|
||||
if (cs.dwExStyle & WS_EX_MDICHILD)
|
||||
{
|
||||
send_message( cs.hwndParent, WM_MDIREFRESHMENU, 0, 0 );
|
||||
/* ShowWindow won't activate child windows */
|
||||
NtUserSetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
|
||||
}
|
||||
}
|
||||
|
||||
/* Call WH_SHELL hook */
|
||||
|
||||
if (!(get_window_long( hwnd, GWL_STYLE ) & WS_CHILD) && !get_window_relative( hwnd, GW_OWNER ))
|
||||
call_hooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
|
||||
|
||||
TRACE( "created window %p\n", hwnd );
|
||||
set_thread_dpi_awareness_context( context );
|
||||
return hwnd;
|
||||
|
||||
failed:
|
||||
destroy_window( hwnd );
|
||||
set_thread_dpi_awareness_context( context );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* NtUserCallHwnd (win32u.@)
|
||||
*/
|
||||
|
@ -4219,10 +4701,6 @@ ULONG_PTR WINAPI NtUserCallHwnd( HWND hwnd, DWORD code )
|
|||
case NtUserIsWindowVisible:
|
||||
return is_window_visible( hwnd );
|
||||
/* temporary exports */
|
||||
case NtUserCreateDesktopWindow:
|
||||
return user_driver->pCreateDesktopWindow( hwnd );
|
||||
case NtUserDestroyWindowHandle:
|
||||
return destroy_window( hwnd );
|
||||
case NtUserGetDummySurface:
|
||||
return (UINT_PTR)&dummy_surface;
|
||||
default:
|
||||
|
|
|
@ -768,6 +768,18 @@ INT WINAPI NtUserCountClipboardFormats(void)
|
|||
return unix_funcs->pNtUserCountClipboardFormats();
|
||||
}
|
||||
|
||||
HWND WINAPI NtUserCreateWindowEx( DWORD ex_style, UNICODE_STRING *class_name,
|
||||
UNICODE_STRING *version, UNICODE_STRING *window_name,
|
||||
DWORD style, INT x, INT y, INT width, INT height,
|
||||
HWND parent, HMENU menu, HINSTANCE instance, void *params,
|
||||
DWORD flags, CBT_CREATEWNDW *cbtc, DWORD unk, BOOL ansi )
|
||||
{
|
||||
if (!unix_funcs) return 0;
|
||||
return unix_funcs->pNtUserCreateWindowEx( ex_style, class_name, version, window_name,
|
||||
style, x, y, width, height, parent, menu,
|
||||
instance, params, flags, cbtc, unk, ansi );
|
||||
}
|
||||
|
||||
HDWP WINAPI NtUserDeferWindowPosAndBand( HDWP hdwp, HWND hwnd, HWND after,
|
||||
INT x, INT y, INT cx, INT cy,
|
||||
UINT flags, UINT unk1, UINT unk2 )
|
||||
|
|
|
@ -139,7 +139,6 @@ enum
|
|||
NtUserGetHandlePtr,
|
||||
NtUserInvalidateDCE,
|
||||
NtUserRegisterWindowSurface,
|
||||
NtUserSetHandlePtr,
|
||||
};
|
||||
|
||||
/* NtUserCallHwnd codes, not compatible with Windows */
|
||||
|
@ -154,8 +153,6 @@ enum
|
|||
NtUserIsWindowUnicode,
|
||||
NtUserIsWindowVisible,
|
||||
/* temporary exports */
|
||||
NtUserCreateDesktopWindow,
|
||||
NtUserDestroyWindowHandle,
|
||||
NtUserGetDummySurface,
|
||||
};
|
||||
|
||||
|
@ -193,6 +190,7 @@ enum
|
|||
/* NtUserMessageCall codes */
|
||||
enum
|
||||
{
|
||||
FNID_SENDMESSAGE = 0x02b1,
|
||||
FNID_SENDNOTIFYMESSAGE = 0x02b7,
|
||||
};
|
||||
|
||||
|
@ -298,6 +296,11 @@ HACCEL WINAPI NtUserCreateAcceleratorTable( ACCEL *table, INT count );
|
|||
HDESK WINAPI NtUserCreateDesktopEx( OBJECT_ATTRIBUTES *attr, UNICODE_STRING *device,
|
||||
DEVMODEW *devmode, DWORD flags, ACCESS_MASK access,
|
||||
ULONG heap_size );
|
||||
HWND WINAPI NtUserCreateWindowEx( DWORD ex_style, UNICODE_STRING *class_name,
|
||||
UNICODE_STRING *version, UNICODE_STRING *window_name,
|
||||
DWORD style, INT x, INT y, INT cx, INT cy,
|
||||
HWND parent, HMENU menu, HINSTANCE instance, void *params,
|
||||
DWORD flags, CBT_CREATEWNDW *cbtc, DWORD unk, BOOL ansi );
|
||||
HWINSTA WINAPI NtUserCreateWindowStation( OBJECT_ATTRIBUTES *attr, ACCESS_MASK mask, ULONG arg3,
|
||||
ULONG arg4, ULONG arg5, ULONG arg6, ULONG arg7 );
|
||||
HDWP WINAPI NtUserDeferWindowPosAndBand( HDWP hdwp, HWND hwnd, HWND after, INT x, INT y,
|
||||
|
@ -408,6 +411,7 @@ BOOL WINAPI NtUserSetProcessDpiAwarenessContext( ULONG awareness, ULONG unkno
|
|||
BOOL WINAPI NtUserSetProcessWindowStation( HWINSTA handle );
|
||||
BOOL WINAPI NtUserSetProp( HWND hwnd, const WCHAR *str, HANDLE handle );
|
||||
BOOL WINAPI NtUserSetSysColors( INT count, const INT *colors, const COLORREF *values );
|
||||
BOOL WINAPI NtUserSetSystemMenu( HWND hwnd, HMENU menu );
|
||||
UINT_PTR WINAPI NtUserSetSystemTimer( HWND hwnd, UINT_PTR id, UINT timeout, TIMERPROC proc );
|
||||
BOOL WINAPI NtUserSetThreadDesktop( HDESK handle );
|
||||
UINT_PTR WINAPI NtUserSetTimer( HWND hwnd, UINT_PTR id, UINT timeout, TIMERPROC proc, ULONG tolerance );
|
||||
|
|
Loading…
Reference in New Issue