Wine-devel
Threads by month
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
April 2022
- 87 participants
- 938 discussions
[PATCH v2 12/12] win32u: Use user mode callback for registering builtin classes.
by Huw Davies 26 Apr '22
by Huw Davies 26 Apr '22
26 Apr '22
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/user32/class.c | 15 ++-------------
dlls/user32/controls.h | 1 -
dlls/user32/user_main.c | 2 +-
dlls/user32/user_private.h | 1 +
dlls/win32u/class.c | 16 ++++++++++++++++
dlls/win32u/ntuser_private.h | 2 +-
dlls/win32u/window.c | 2 +-
dlls/win32u/winstation.c | 2 +-
include/ntuser.h | 1 +
9 files changed, 24 insertions(+), 18 deletions(-)
diff --git a/dlls/user32/class.c b/dlls/user32/class.c
index aaa8f75bebe..620477f1b14 100644
--- a/dlls/user32/class.c
+++ b/dlls/user32/class.c
@@ -40,8 +40,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(class);
#define MAX_ATOM_LEN 255 /* from dlls/kernel32/atom.c */
-static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
-
static inline const char *debugstr_us( const UNICODE_STRING *us )
{
if (!us) return "<null>";
@@ -307,9 +305,9 @@ static void load_uxtheme(void)
}
/***********************************************************************
- * register_builtins
+ * User32RegisterBuiltinClasses
*/
-static BOOL WINAPI register_builtins( INIT_ONCE *once, void *param, void **context )
+BOOL WINAPI User32RegisterBuiltinClasses( const struct win_hook_params *params, ULONG size )
{
register_builtin( &BUTTON_builtin_class );
register_builtin( &COMBO_builtin_class );
@@ -330,15 +328,6 @@ static BOOL WINAPI register_builtins( INIT_ONCE *once, void *param, void **conte
}
-/***********************************************************************
- * register_builtin_classes
- */
-void register_builtin_classes(void)
-{
- InitOnceExecuteOnce( &init_once, register_builtins, NULL, NULL );
-}
-
-
/***********************************************************************
* register_desktop_class
*/
diff --git a/dlls/user32/controls.h b/dlls/user32/controls.h
index a410bf27460..5dcdd9bb935 100644
--- a/dlls/user32/controls.h
+++ b/dlls/user32/controls.h
@@ -104,7 +104,6 @@ extern LRESULT StaticWndProc_common(HWND,UINT,WPARAM,LPARAM,BOOL) DECLSPEC_HIDDE
struct tagCLASS; /* opaque structure */
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;
/* defwnd proc */
diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c
index 1258181c88a..1400597eb5d 100644
--- a/dlls/user32/user_main.c
+++ b/dlls/user32/user_main.c
@@ -172,7 +172,6 @@ static const struct user_callbacks user_funcs =
post_dde_message,
process_rawinput_message,
rawinput_device_get_usages,
- register_builtin_classes,
SCROLL_SetStandardScrollPainted,
unpack_dde_message,
register_imm,
@@ -207,6 +206,7 @@ static const void *kernel_callback_table[NtUserCallCount] =
User32CallWindowsHook,
User32FreeCachedClipboardData,
User32LoadDriver,
+ User32RegisterBuiltinClasses,
User32RenderSsynthesizedFormat,
};
diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h
index f28fc66bbf2..aa3e1565bfa 100644
--- a/dlls/user32/user_private.h
+++ b/dlls/user32/user_private.h
@@ -124,6 +124,7 @@ BOOL WINAPI User32CallSendAsyncCallback( const struct send_async_params *params,
BOOL WINAPI User32CallWinEventHook( const struct win_event_hook_params *params, ULONG size );
BOOL WINAPI User32CallWindowProc( struct win_proc_params *params, ULONG size );
BOOL WINAPI User32CallWindowsHook( const struct win_hook_params *params, ULONG size );
+BOOL WINAPI User32RegisterBuiltinClasses( const struct win_hook_params *params, ULONG size );
/* message spy definitions */
diff --git a/dlls/win32u/class.c b/dlls/win32u/class.c
index ba60794ccd7..c52fcad6025 100644
--- a/dlls/win32u/class.c
+++ b/dlls/win32u/class.c
@@ -972,3 +972,19 @@ WORD get_class_word( HWND hwnd, INT offset )
release_class_ptr( class );
return retvalue;
}
+
+static void register_builtins(void)
+{
+ void *ret_ptr;
+ ULONG ret_len;
+ KeUserModeCallback( NtUserRegisterBuiltinClasses, NULL, 0, &ret_ptr, &ret_len );
+}
+
+/***********************************************************************
+ * register_builtin_classes
+ */
+void register_builtin_classes(void)
+{
+ static pthread_once_t init_once = PTHREAD_ONCE_INIT;
+ pthread_once( &init_once, register_builtins );
+}
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h
index 632cb16d23a..fe9d7e18bc9 100644
--- a/dlls/win32u/ntuser_private.h
+++ b/dlls/win32u/ntuser_private.h
@@ -46,7 +46,6 @@ struct user_callbacks
DWORD type );
BOOL (CDECL *process_rawinput_message)( MSG *msg, UINT hw_id, const struct hardware_msg_data *msg_data );
BOOL (CDECL *rawinput_device_get_usages)(HANDLE handle, USHORT *usage_page, USHORT *usage);
- void (CDECL *register_builtin_classes)(void);
void (WINAPI *set_standard_scroll_painted)( HWND hwnd, INT bar, BOOL visible );
BOOL (CDECL *unpack_dde_message)( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lparam,
void **buffer, size_t size );
@@ -303,6 +302,7 @@ WNDPROC get_winproc( WNDPROC proc, BOOL ansi ) DECLSPEC_HIDDEN;
void get_winproc_params( struct win_proc_params *params ) DECLSPEC_HIDDEN;
struct dce *get_class_dce( struct tagCLASS *class ) DECLSPEC_HIDDEN;
struct dce *set_class_dce( struct tagCLASS *class, struct dce *dce ) DECLSPEC_HIDDEN;
+extern void register_builtin_classes(void) DECLSPEC_HIDDEN;
/* cursoricon.c */
HICON alloc_cursoricon_handle( BOOL is_icon ) DECLSPEC_HIDDEN;
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c
index e206881e596..edafc522d14 100644
--- a/dlls/win32u/window.c
+++ b/dlls/win32u/window.c
@@ -4732,7 +4732,7 @@ static WND *create_window_handle( HWND parent, HWND owner, UNICODE_STRING *name,
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();
+ register_builtin_classes();
}
else /* HWND_MESSAGE parent */
{
diff --git a/dlls/win32u/winstation.c b/dlls/win32u/winstation.c
index 4cd223750c2..0f6fb66a2b2 100644
--- a/dlls/win32u/winstation.c
+++ b/dlls/win32u/winstation.c
@@ -499,7 +499,7 @@ HWND get_desktop_window(void)
if (!thread_info->top_window || !user_driver->pCreateDesktopWindow( thread_info->top_window ))
ERR_(win)( "failed to create desktop window\n" );
- if (user_callbacks) user_callbacks->register_builtin_classes();
+ register_builtin_classes();
return thread_info->top_window;
}
diff --git a/include/ntuser.h b/include/ntuser.h
index cad90b91882..58486fcfcb0 100644
--- a/include/ntuser.h
+++ b/include/ntuser.h
@@ -34,6 +34,7 @@ enum
NtUserCallWindowsHook,
NtUserFreeCachedClipboardData,
NtUserLoadDriver,
+ NtUserRegisterBuiltinClasses,
NtUserRenderSynthesizedFormat,
/* win16 hooks */
NtUserCallFreeIcon,
--
2.25.1
1
0
[PATCH v2 11/12] winex11: Directly use win32u and ntdll in a few more places.
by Huw Davies 26 Apr '22
by Huw Davies 26 Apr '22
26 Apr '22
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winex11.drv/clipboard.c | 27 ++++++++++++++++++---------
1 file changed, 18 insertions(+), 9 deletions(-)
diff --git a/dlls/winex11.drv/clipboard.c b/dlls/winex11.drv/clipboard.c
index eb357ed4643..a0ccc3ebc96 100644
--- a/dlls/winex11.drv/clipboard.c
+++ b/dlls/winex11.drv/clipboard.c
@@ -203,7 +203,7 @@ static const char *debugstr_format( UINT id )
{
WCHAR buffer[256];
- if (GetClipboardFormatNameW( id, buffer, 256 ))
+ if (NtUserGetClipboardFormatName( id, buffer, ARRAYSIZE(buffer) ))
return wine_dbg_sprintf( "%04x %s", id, debugstr_w(buffer) );
switch (id)
@@ -349,7 +349,8 @@ static void register_win32_formats( const UINT *ids, UINT size )
for (count = 0; count < 256 && size; ids++, size--)
{
if (find_win32_format( *ids )) continue; /* it already exists */
- if (!GetClipboardFormatNameW( *ids, buffer, 256 )) continue; /* not a named format */
+ if (!NtUserGetClipboardFormatName( *ids, buffer, ARRAYSIZE(buffer) ))
+ continue; /* not a named format */
if (!(len = WideCharToMultiByte( CP_UNIXCP, 0, buffer, -1, NULL, 0, NULL, NULL ))) continue;
if (!(names[count] = malloc( len ))) continue;
WideCharToMultiByte( CP_UNIXCP, 0, buffer, -1, names[count], len, NULL, NULL );
@@ -434,6 +435,14 @@ static void put_property( Display *display, Window win, Atom prop, Atom type, in
}
+static void selection_sleep(void)
+{
+ LARGE_INTEGER timeout;
+ timeout.QuadPart = (ULONGLONG)SELECTION_WAIT * -10000;
+ NtDelayExecution( FALSE, &timeout );
+}
+
+
/**************************************************************************
* convert_selection
*/
@@ -455,7 +464,7 @@ static BOOL convert_selection( Display *display, Window win, Atom selection,
Bool res = XCheckTypedWindowEvent( display, win, SelectionNotify, &event );
if (res && event.xselection.selection == selection && event.xselection.target == format->atom)
return read_property( display, win, event.xselection.property, type, data, size );
- Sleep( SELECTION_WAIT );
+ selection_sleep();
}
ERR( "Timed out waiting for SelectionNotify event\n" );
return FALSE;
@@ -1414,7 +1423,7 @@ static UINT *get_clipboard_formats( UINT *size )
for (;;)
{
if (!(ids = malloc( *size * sizeof(*ids) ))) return NULL;
- if (GetUpdatedClipboardFormats( ids, *size, size )) break;
+ if (NtUserGetUpdatedClipboardFormats( ids, *size, size )) break;
free( ids );
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return NULL;
}
@@ -1706,7 +1715,7 @@ static BOOL read_property( Display *display, Window w, Atom prop,
if (res && xe.xproperty.atom == prop &&
xe.xproperty.state == PropertyNewValue)
break;
- Sleep(SELECTION_WAIT);
+ selection_sleep();
}
if (i >= SELECTION_RETRIES ||
@@ -1863,14 +1872,14 @@ static BOOL request_selection_contents( Display *display, BOOL changed )
last_size != size ||
memcmp( last_data, data, size ));
- if (!changed || !OpenClipboard( clipboard_hwnd ))
+ if (!changed || !NtUserOpenClipboard( clipboard_hwnd, 0 ))
{
free( data );
return FALSE;
}
TRACE( "selection changed, importing\n" );
- EmptyClipboard();
+ NtUserEmptyClipboard();
is_clipboard_owner = TRUE;
rendered_formats = 0;
@@ -1884,9 +1893,9 @@ static BOOL request_selection_contents( Display *display, BOOL changed )
last_data = data;
last_size = size;
last_clipboard_update = GetTickCount64();
- CloseClipboard();
+ NtUserCloseClipboard();
if (!use_xfixes)
- SetTimer( clipboard_hwnd, 1, SELECTION_UPDATE_DELAY, NULL );
+ NtUserSetTimer( clipboard_hwnd, 1, SELECTION_UPDATE_DELAY, NULL, TIMERV_DEFAULT_COALESCING );
return TRUE;
}
--
2.25.1
1
0
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winex11.drv/clipboard.c | 33 ++++++++++++++++++++++++++++-----
1 file changed, 28 insertions(+), 5 deletions(-)
diff --git a/dlls/winex11.drv/clipboard.c b/dlls/winex11.drv/clipboard.c
index ec0392f3ec8..eb357ed4643 100644
--- a/dlls/winex11.drv/clipboard.c
+++ b/dlls/winex11.drv/clipboard.c
@@ -569,6 +569,29 @@ static HGLOBAL create_dib_from_bitmap(HBITMAP hBmp)
}
+/* based on wine_get_dos_file_name */
+static WCHAR *get_dos_file_name( const char *path )
+{
+ ULONG len = strlen( path ) + 9; /* \??\unix prefix */
+ WCHAR *ret;
+
+ if (!(ret = malloc( len * sizeof(WCHAR) ))) return NULL;
+ if (wine_unix_to_nt_file_name( path, ret, &len ))
+ {
+ free( ret );
+ return NULL;
+ }
+
+ if (ret[5] == ':')
+ {
+ /* get rid of the \??\ prefix */
+ memmove( ret, ret + 4, (len - 4) * sizeof(WCHAR) );
+ }
+ else ret[1] = '\\';
+ return ret;
+}
+
+
/***********************************************************************
* uri_to_dos
*
@@ -616,7 +639,7 @@ static WCHAR* uri_to_dos(char *encodedURI)
if (uri[7] == '/')
{
/* file:///path/to/file (nautilus, thunar) */
- ret = wine_get_dos_file_name(&uri[7]);
+ ret = get_dos_file_name( &uri[7] );
}
else if (uri[7])
{
@@ -629,14 +652,14 @@ static WCHAR* uri_to_dos(char *encodedURI)
if (strcmp(&uri[7], "localhost") == 0)
{
*path = '/';
- ret = wine_get_dos_file_name(path);
+ ret = get_dos_file_name( path );
}
else if (gethostname(hostname, sizeof(hostname)) == 0)
{
if (strcmp(hostname, &uri[7]) == 0)
{
*path = '/';
- ret = wine_get_dos_file_name(path);
+ ret = get_dos_file_name( path );
}
}
}
@@ -645,7 +668,7 @@ static WCHAR* uri_to_dos(char *encodedURI)
else if (uri[6])
{
/* file:/path/to/file (konqueror) */
- ret = wine_get_dos_file_name(&uri[5]);
+ ret = get_dos_file_name( &uri[5] );
}
}
free( uri );
@@ -938,7 +961,7 @@ static HANDLE import_text_uri_list( Atom type, const void *data, size_t size )
memcpy(&out[total], path, pathSize * sizeof(WCHAR));
total += pathSize;
done:
- HeapFree( GetProcessHeap(), 0, path );
+ free( path );
if (out == NULL)
break;
}
--
2.25.1
1
0
[PATCH v2 09/12] winex11: Use data-only NtUserGetClipboardData to export clipboard data.
by Huw Davies 26 Apr '22
by Huw Davies 26 Apr '22
26 Apr '22
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winex11.drv/clipboard.c | 167 ++++++++++++++++-------------------
1 file changed, 75 insertions(+), 92 deletions(-)
diff --git a/dlls/winex11.drv/clipboard.c b/dlls/winex11.drv/clipboard.c
index 02456ef3870..ec0392f3ec8 100644
--- a/dlls/winex11.drv/clipboard.c
+++ b/dlls/winex11.drv/clipboard.c
@@ -97,7 +97,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(clipboard);
#define SELECTION_UPDATE_DELAY 2000 /* delay between checks of the X11 selection */
-typedef BOOL (*EXPORTFUNC)( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
+typedef BOOL (*EXPORTFUNC)( Display *display, Window win, Atom prop, Atom target, void *data, size_t size );
typedef HANDLE (*IMPORTFUNC)( Atom type, const void *data, size_t size );
struct clipboard_format
@@ -121,19 +121,18 @@ static HANDLE import_text_html( Atom type, const void *data, size_t size );
static HANDLE import_text_uri_list( Atom type, const void *data, size_t size );
static HANDLE import_targets( Atom type, const void *data, size_t size );
-static BOOL export_data( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
-static BOOL export_string( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
-static BOOL export_utf8_string( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
-static BOOL export_text( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
-static BOOL export_compound_text( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
-static BOOL export_pixmap( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
-static BOOL export_image_bmp( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
-static BOOL export_enhmetafile( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
-static BOOL export_text_html( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
-static BOOL export_hdrop( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
-static BOOL export_targets( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
-static BOOL export_multiple( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
-static BOOL export_timestamp( Display *display, Window win, Atom prop, Atom target, HANDLE handle );
+static BOOL export_data( Display *display, Window win, Atom prop, Atom target, void *data, size_t size );
+static BOOL export_string( Display *display, Window win, Atom prop, Atom target, void *data, size_t size );
+static BOOL export_utf8_string( Display *display, Window win, Atom prop, Atom target, void *data, size_t size );
+static BOOL export_text( Display *display, Window win, Atom prop, Atom target, void *data, size_t size );
+static BOOL export_compound_text( Display *display, Window win, Atom prop, Atom target, void *data, size_t size );
+static BOOL export_pixmap( Display *display, Window win, Atom prop, Atom target, void *data, size_t size );
+static BOOL export_image_bmp( Display *display, Window win, Atom prop, Atom target, void *data, size_t size );
+static BOOL export_text_html( Display *display, Window win, Atom prop, Atom target, void *data, size_t size );
+static BOOL export_hdrop( Display *display, Window win, Atom prop, Atom target, void *data, size_t size );
+static BOOL export_targets( Display *display, Window win, Atom prop, Atom target, void *data, size_t size );
+static BOOL export_multiple( Display *display, Window win, Atom prop, Atom target, void *data, size_t size );
+static BOOL export_timestamp( Display *display, Window win, Atom prop, Atom target, void *data, size_t size );
static BOOL read_property( Display *display, Window w, Atom prop,
Atom *type, unsigned char **data, unsigned long *datasize );
@@ -167,7 +166,7 @@ static const struct
{ 0, CF_PENDATA, XATOM_WCF_PENDATA, import_data, export_data },
{ 0, CF_RIFF, XATOM_WCF_RIFF, import_data, export_data },
{ 0, CF_WAVE, XATOM_WCF_WAVE, import_data, export_data },
- { 0, CF_ENHMETAFILE, XATOM_WCF_ENHMETAFILE, import_enhmetafile, export_enhmetafile },
+ { 0, CF_ENHMETAFILE, XATOM_WCF_ENHMETAFILE, import_enhmetafile, export_data },
{ 0, CF_HDROP, XATOM_text_uri_list, import_text_uri_list, export_hdrop },
{ 0, CF_DIB, XATOM_image_bmp, import_image_bmp, export_image_bmp },
{ RichTextFormatW, 0, XATOM_text_rtf, import_data, export_data },
@@ -1099,13 +1098,9 @@ static HANDLE render_format( UINT id )
*
* Generic export clipboard data routine.
*/
-static BOOL export_data( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
+static BOOL export_data( Display *display, Window win, Atom prop, Atom target, void *data, size_t size )
{
- void *ptr = GlobalLock( handle );
-
- if (!ptr) return FALSE;
- put_property( display, win, prop, target, 8, ptr, GlobalSize( handle ));
- GlobalUnlock( handle );
+ put_property( display, win, prop, target, 8, data, size );
return TRUE;
}
@@ -1115,18 +1110,19 @@ static BOOL export_data( Display *display, Window win, Atom prop, Atom target, H
*
* Convert CF_UNICODETEXT data to a string in the specified codepage.
*/
-static char *string_from_unicode_text( UINT codepage, HANDLE handle, UINT *size )
+static char *string_from_unicode_text( UINT codepage, const WCHAR *string, size_t string_size, size_t *size )
{
UINT i, j;
char *str;
- WCHAR *strW = GlobalLock( handle );
- UINT lenW = GlobalSize( handle ) / sizeof(WCHAR);
- DWORD len = WideCharToMultiByte( codepage, 0, strW, lenW, NULL, 0, NULL, NULL );
+ UINT lenW = string_size / sizeof(WCHAR);
+ DWORD len;
+
+ if (!string_size) return NULL;
+ len = WideCharToMultiByte( codepage, 0, string, lenW, NULL, 0, NULL, NULL );
if ((str = malloc( len )))
{
- WideCharToMultiByte( codepage, 0, strW, lenW, str, len, NULL, NULL);
- GlobalUnlock( handle );
+ WideCharToMultiByte( codepage, 0, string, lenW, str, len, NULL, NULL);
/* remove carriage returns */
for (i = j = 0; i < len; i++)
@@ -1138,7 +1134,6 @@ static char *string_from_unicode_text( UINT codepage, HANDLE handle, UINT *size
*size = j;
TRACE( "returning %s\n", debugstr_an( str, j ));
}
- GlobalUnlock( handle );
return str;
}
@@ -1148,15 +1143,13 @@ static char *string_from_unicode_text( UINT codepage, HANDLE handle, UINT *size
*
* Export CF_UNICODETEXT converting the string to XA_STRING.
*/
-static BOOL export_string( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
+static BOOL export_string( Display *display, Window win, Atom prop, Atom target, void *data, size_t size )
{
- UINT size;
- char *text = string_from_unicode_text( 28591, handle, &size );
+ char *text = string_from_unicode_text( 28591, data, size, &size );
if (!text) return FALSE;
put_property( display, win, prop, target, 8, text, size );
free( text );
- GlobalUnlock( handle );
return TRUE;
}
@@ -1166,15 +1159,14 @@ static BOOL export_string( Display *display, Window win, Atom prop, Atom target,
*
* Export CF_UNICODE converting the string to UTF8.
*/
-static BOOL export_utf8_string( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
+static BOOL export_utf8_string( Display *display, Window win, Atom prop, Atom target,
+ void *data, size_t size )
{
- UINT size;
- char *text = string_from_unicode_text( CP_UTF8, handle, &size );
+ char *text = string_from_unicode_text( CP_UTF8, data, size, &size );
if (!text) return FALSE;
put_property( display, win, prop, target, 8, text, size );
free( text );
- GlobalUnlock( handle );
return TRUE;
}
@@ -1184,9 +1176,9 @@ static BOOL export_utf8_string( Display *display, Window win, Atom prop, Atom ta
*
* Export CF_UNICODE to the polymorphic TEXT type, using UTF8.
*/
-static BOOL export_text( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
+static BOOL export_text( Display *display, Window win, Atom prop, Atom target, void *data, size_t size )
{
- return export_utf8_string( display, win, prop, x11drv_atom(UTF8_STRING), handle );
+ return export_utf8_string( display, win, prop, x11drv_atom(UTF8_STRING), data, size );
}
@@ -1195,12 +1187,12 @@ static BOOL export_text( Display *display, Window win, Atom prop, Atom target, H
*
* Export CF_UNICODE to COMPOUND_TEXT
*/
-static BOOL export_compound_text( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
+static BOOL export_compound_text( Display *display, Window win, Atom prop, Atom target,
+ void *data, size_t size )
{
XTextProperty textprop;
XICCEncodingStyle style;
- UINT size;
- char *text = string_from_unicode_text( CP_UNIXCP, handle, &size );
+ char *text = string_from_unicode_text( CP_UNIXCP, data, size, &size );
if (!text) return FALSE;
if (target == x11drv_atom(COMPOUND_TEXT))
@@ -1225,18 +1217,16 @@ static BOOL export_compound_text( Display *display, Window win, Atom prop, Atom
*
* Export CF_DIB to XA_PIXMAP.
*/
-static BOOL export_pixmap( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
+static BOOL export_pixmap( Display *display, Window win, Atom prop, Atom target, void *data, size_t size )
{
Pixmap pixmap;
- BITMAPINFO *pbmi;
+ BITMAPINFO *pbmi = data;
struct gdi_image_bits bits;
- pbmi = GlobalLock( handle );
bits.ptr = (LPBYTE)pbmi + bitmap_info_size( pbmi, DIB_RGB_COLORS );
bits.free = NULL;
bits.is_copy = FALSE;
pixmap = create_pixmap_from_image( 0, &default_visual, pbmi, &bits, DIB_RGB_COLORS );
- GlobalUnlock( handle );
put_property( display, win, prop, target, 32, &pixmap, 1 );
/* FIXME: free the pixmap when the property is deleted */
@@ -1249,13 +1239,13 @@ static BOOL export_pixmap( Display *display, Window win, Atom prop, Atom target,
*
* Export CF_DIB to image/bmp.
*/
-static BOOL export_image_bmp( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
+static BOOL export_image_bmp( Display *display, Window win, Atom prop, Atom target, void *data, size_t size )
{
- LPBYTE dibdata = GlobalLock( handle );
+ LPBYTE dibdata = data;
UINT bmpsize;
BITMAPFILEHEADER *bfh;
- bmpsize = sizeof(BITMAPFILEHEADER) + GlobalSize( handle );
+ bmpsize = sizeof(BITMAPFILEHEADER) + size;
bfh = malloc( bmpsize );
if (bfh)
{
@@ -1269,33 +1259,12 @@ static BOOL export_image_bmp( Display *display, Window win, Atom prop, Atom targ
/* rest of bitmap is the same as the packed dib */
memcpy(bfh+1, dibdata, bmpsize-sizeof(BITMAPFILEHEADER));
}
- GlobalUnlock( handle );
put_property( display, win, prop, target, 8, bfh, bmpsize );
free( bfh );
return TRUE;
}
-/**************************************************************************
- * export_enhmetafile
- *
- * Export EnhMetaFile.
- */
-static BOOL export_enhmetafile( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
-{
- unsigned int size;
- void *ptr;
-
- if (!(size = GetEnhMetaFileBits( handle, 0, NULL ))) return FALSE;
- if (!(ptr = malloc( size ))) return FALSE;
-
- GetEnhMetaFileBits( handle, size, ptr );
- put_property( display, win, prop, target, 8, ptr, size );
- free( ptr );
- return TRUE;
-}
-
-
/**************************************************************************
* export_text_html
*
@@ -1303,14 +1272,12 @@ static BOOL export_enhmetafile( Display *display, Window win, Atom prop, Atom ta
*
* FIXME: We should attempt to add an <a base> tag and convert windows paths.
*/
-static BOOL export_text_html( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
+static BOOL export_text_html( Display *display, Window win, Atom prop, Atom target, void *data, size_t size )
{
- const char *p, *data;
+ const char *p;
UINT start = 0, end = 0;
BOOL ret = TRUE;
- if (!(data = GlobalLock( handle ))) return FALSE;
-
p = data;
while (*p && *p != '<')
{
@@ -1319,12 +1286,11 @@ static BOOL export_text_html( Display *display, Window win, Atom prop, Atom targ
if (!(p = strpbrk( p, "\r\n" ))) break;
while (*p == '\r' || *p == '\n') p++;
}
- if (start && start < end && end <= GlobalSize( handle ))
- put_property( display, win, prop, target, 8, data + start, end - start );
+ if (start && start < end && end <= size)
+ put_property( display, win, prop, target, 8, (char *)data + start, end - start );
else
ret = FALSE;
- GlobalUnlock( handle );
return ret;
}
@@ -1334,14 +1300,13 @@ static BOOL export_text_html( Display *display, Window win, Atom prop, Atom targ
*
* Export CF_HDROP format to text/uri-list.
*/
-static BOOL export_hdrop( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
+static BOOL export_hdrop( Display *display, Window win, Atom prop, Atom target, void *data, size_t size )
{
char *textUriList = NULL;
UINT textUriListSize = 32;
UINT next = 0;
const WCHAR *ptr;
WCHAR *unicode_data = NULL;
- void *data = GlobalLock( handle );
DROPFILES *drop_files = data;
if (!drop_files->fWide)
@@ -1406,7 +1371,6 @@ static BOOL export_hdrop( Display *display, Window win, Atom prop, Atom target,
return TRUE;
failed:
- GlobalUnlock( handle );
free( unicode_data );
free( textUriList );
return FALSE;
@@ -1454,7 +1418,7 @@ static BOOL is_format_available( UINT format, const UINT *ids, unsigned int coun
*
* Service a TARGETS selection request event
*/
-static BOOL export_targets( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
+static BOOL export_targets( Display *display, Window win, Atom prop, Atom target, void *data, size_t size )
{
struct clipboard_format *format;
UINT pos, count, *formats;
@@ -1493,9 +1457,10 @@ static BOOL export_targets( Display *display, Window win, Atom prop, Atom target
*/
static BOOL export_selection( Display *display, Window win, Atom prop, Atom target )
{
+ struct get_clipboard_params params = { .data_only = TRUE };
struct clipboard_format *format;
- HANDLE handle = 0;
BOOL open = FALSE, ret = FALSE;
+ size_t buffer_size = 0;
LIST_FOR_EACH_ENTRY( format, &format_list, struct clipboard_format, entry )
{
@@ -1504,26 +1469,44 @@ static BOOL export_selection( Display *display, Window win, Atom prop, Atom targ
if (!format->id)
{
TRACE( "win %lx prop %s target %s\n", win, debugstr_xatom( prop ), debugstr_xatom( target ));
- ret = format->export( display, win, prop, target, 0 );
+ ret = format->export( display, win, prop, target, NULL, 0 );
break;
}
- if (!open && !(open = OpenClipboard( clipboard_hwnd )))
+ if (!open && !(open = NtUserOpenClipboard( clipboard_hwnd, 0 )))
{
ERR( "failed to open clipboard for %s\n", debugstr_xatom( target ));
return FALSE;
}
- if ((handle = GetClipboardData( format->id )))
+
+ if (!buffer_size)
{
- TRACE( "win %lx prop %s target %s exporting %s %p\n",
- win, debugstr_xatom( prop ), debugstr_xatom( target ),
- debugstr_format( format->id ), handle );
+ buffer_size = 1024;
+ if (!(params.data = malloc( buffer_size ))) break;
+ }
- ret = format->export( display, win, prop, target, handle );
- break;
+ for (;;)
+ {
+ params.size = buffer_size;
+ if (NtUserGetClipboardData( format->id, ¶ms ))
+ {
+ TRACE( "win %lx prop %s target %s exporting %s\n",
+ win, debugstr_xatom( prop ), debugstr_xatom( target ),
+ debugstr_format( format->id ) );
+
+ ret = format->export( display, win, prop, target, params.data, params.size );
+ goto done;
+ }
+ if (!params.data_size) break;
+ free( params.data );
+ if (!(params.data = malloc( params.data_size ))) goto done;
+ buffer_size = params.data_size;
+ params.data_size = 0;
}
/* keep looking for another Win32 format mapping to the same target */
}
- if (open) CloseClipboard();
+done:
+ free( params.data );
+ if (open) NtUserCloseClipboard();
return ret;
}
@@ -1541,7 +1524,7 @@ static BOOL export_selection( Display *display, Window win, Atom prop, Atom targ
* 2. If we fail to convert the target named by an atom in the MULTIPLE property,
* we replace the atom in the property by None.
*/
-static BOOL export_multiple( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
+static BOOL export_multiple( Display *display, Window win, Atom prop, Atom target, void *data, size_t size )
{
Atom atype;
int aformat;
@@ -1587,7 +1570,7 @@ static BOOL export_multiple( Display *display, Window win, Atom prop, Atom targe
*
* Export the timestamp that was used to acquire the selection
*/
-static BOOL export_timestamp( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
+static BOOL export_timestamp( Display *display, Window win, Atom prop, Atom target, void *data, size_t size )
{
Time time = CurrentTime; /* FIXME */
put_property( display, win, prop, XA_INTEGER, 32, &time, 1 );
--
2.25.1
1
0
26 Apr '22
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winex11.drv/clipboard.c | 41 +++++++++++++++++++++++-------------
1 file changed, 26 insertions(+), 15 deletions(-)
diff --git a/dlls/winex11.drv/clipboard.c b/dlls/winex11.drv/clipboard.c
index d677aad034b..02456ef3870 100644
--- a/dlls/winex11.drv/clipboard.c
+++ b/dlls/winex11.drv/clipboard.c
@@ -1336,30 +1336,39 @@ static BOOL export_text_html( Display *display, Window win, Atom prop, Atom targ
*/
static BOOL export_hdrop( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
{
- UINT i;
- UINT numFiles;
- char *textUriList;
+ char *textUriList = NULL;
UINT textUriListSize = 32;
UINT next = 0;
+ const WCHAR *ptr;
+ WCHAR *unicode_data = NULL;
+ void *data = GlobalLock( handle );
+ DROPFILES *drop_files = data;
- textUriList = malloc( textUriListSize );
- if (!textUriList) return FALSE;
- numFiles = DragQueryFileW( handle, 0xFFFFFFFF, NULL, 0 );
- for (i = 0; i < numFiles; i++)
+ if (!drop_files->fWide)
+ {
+ char *p, *files = (char *)data + drop_files->pFiles;
+ p = files;
+ while (*p) p += strlen( p ) + 1;
+ p++;
+
+ if (!(unicode_data = malloc( (p - files) * sizeof(WCHAR) ))) goto failed;
+ MultiByteToWideChar( CP_ACP, 0, files, p - files, unicode_data, p - files );
+ ptr = unicode_data;
+ }
+ else ptr = (const WCHAR *)((char *)data + drop_files->pFiles);
+
+ if (!(textUriList = malloc( textUriListSize ))) goto failed;
+
+ while (*ptr)
{
- UINT dosFilenameSize;
- WCHAR *dosFilename = NULL;
char *unixFilename = NULL;
UINT uriSize;
UINT u;
- dosFilenameSize = 1 + DragQueryFileW( handle, i, NULL, 0 );
- dosFilename = malloc( dosFilenameSize * sizeof(WCHAR) );
- if (dosFilename == NULL) goto failed;
- DragQueryFileW( handle, i, dosFilename, dosFilenameSize );
- unixFilename = wine_get_unix_file_name(dosFilename);
- free( dosFilename );
+ unixFilename = wine_get_unix_file_name( ptr );
if (unixFilename == NULL) goto failed;
+ ptr += lstrlenW( ptr ) + 1;
+
uriSize = 8 + /* file:/// */
3 * (lstrlenA(unixFilename) - 1) + /* "%xy" per char except first '/' */
2; /* \r\n */
@@ -1397,6 +1406,8 @@ static BOOL export_hdrop( Display *display, Window win, Atom prop, Atom target,
return TRUE;
failed:
+ GlobalUnlock( handle );
+ free( unicode_data );
free( textUriList );
return FALSE;
}
--
2.25.1
1
0
[PATCH v2 07/12] win32u: Introduce data-only mode in NtUserGetClipboardData.
by Huw Davies 26 Apr '22
by Huw Davies 26 Apr '22
26 Apr '22
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/win32u/clipboard.c | 19 +++++++++++++++----
include/ntuser.h | 1 +
2 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/dlls/win32u/clipboard.c b/dlls/win32u/clipboard.c
index 63306702b1c..67bdd0ba391 100644
--- a/dlls/win32u/clipboard.c
+++ b/dlls/win32u/clipboard.c
@@ -631,7 +631,7 @@ done:
*/
HANDLE WINAPI NtUserGetClipboardData( UINT format, struct get_clipboard_params *params )
{
- struct cached_format *cache;
+ struct cached_format *cache = NULL;
NTSTATUS status;
UINT from, data_seqno;
size_t size;
@@ -642,7 +642,7 @@ HANDLE WINAPI NtUserGetClipboardData( UINT format, struct get_clipboard_params *
{
pthread_mutex_lock( &clipboard_mutex );
- cache = get_cached_format( format );
+ if (!params->data_only) cache = get_cached_format( format );
SERVER_START_REQ( get_clipboard_data )
{
@@ -662,6 +662,8 @@ HANDLE WINAPI NtUserGetClipboardData( UINT format, struct get_clipboard_params *
}
SERVER_END_REQ;
+ params->size = size;
+
if (!status && size)
{
if (cache)
@@ -679,8 +681,18 @@ HANDLE WINAPI NtUserGetClipboardData( UINT format, struct get_clipboard_params *
list_add_tail( &formats_to_free, &cache->entry );
}
+ if (params->data_only)
+ {
+ pthread_mutex_unlock( &clipboard_mutex );
+ return params->data;
+ }
+
/* allocate new cache entry */
- if (!(cache = malloc( sizeof(*cache) ))) return 0;
+ if (!(cache = malloc( sizeof(*cache) )))
+ {
+ pthread_mutex_unlock( &clipboard_mutex );
+ return 0;
+ }
cache->format = format;
cache->seqno = data_seqno;
@@ -690,7 +702,6 @@ HANDLE WINAPI NtUserGetClipboardData( UINT format, struct get_clipboard_params *
pthread_mutex_unlock( &clipboard_mutex );
TRACE( "%s needs unmarshaling\n", debugstr_format( format ) );
params->data_size = ~0;
- params->size = size;
return 0;
}
pthread_mutex_unlock( &clipboard_mutex );
diff --git a/include/ntuser.h b/include/ntuser.h
index f49c9bc7723..cad90b91882 100644
--- a/include/ntuser.h
+++ b/include/ntuser.h
@@ -257,6 +257,7 @@ struct get_clipboard_params
size_t size;
size_t data_size;
UINT seqno;
+ BOOL data_only;
};
/* NtUserSetClipboardData params, not compatible with Windows */
--
2.25.1
1
0
From: Zebediah Figura <zfigura(a)codeweavers.com>
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/user32/Makefile.in | 1 -
dlls/user32/caret.c | 58 -----------------------------------------
dlls/user32/input.c | 27 +++++++++++++++++++
3 files changed, 27 insertions(+), 59 deletions(-)
delete mode 100644 dlls/user32/caret.c
diff --git a/dlls/user32/Makefile.in b/dlls/user32/Makefile.in
index dd83ecec5cf..92d5c1ec1d9 100644
--- a/dlls/user32/Makefile.in
+++ b/dlls/user32/Makefile.in
@@ -7,7 +7,6 @@ DELAYIMPORTS = hid setupapi imm32
C_SRCS = \
button.c \
- caret.c \
class.c \
clipboard.c \
combo.c \
diff --git a/dlls/user32/caret.c b/dlls/user32/caret.c
deleted file mode 100644
index 9e0ff5ca48c..00000000000
--- a/dlls/user32/caret.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Caret functions
- *
- * Copyright 1993 David Metcalfe
- * Copyright 1996 Frans van Dorsselaer
- * Copyright 2001 Eric Pouech
- * Copyright 2002 Alexandre Julliard
- *
- * 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 <stdarg.h>
-
-#include "windef.h"
-#include "winbase.h"
-#include "wingdi.h"
-#include "ntuser.h"
-#include "user_private.h"
-#include "wine/server.h"
-#include "wine/debug.h"
-
-/*****************************************************************
- * DestroyCaret (USER32.@)
- */
-BOOL WINAPI DestroyCaret(void)
-{
- return NtUserDestroyCaret();
-}
-
-
-/*****************************************************************
- * SetCaretPos (USER32.@)
- */
-BOOL WINAPI SetCaretPos( INT x, INT y )
-{
- return NtUserSetCaretPos( x, y );
-}
-
-
-/*****************************************************************
- * SetCaretBlinkTime (USER32.@)
- */
-BOOL WINAPI SetCaretBlinkTime( unsigned int time )
-{
- return NtUserSetCaretBlinkTime( time );
-}
diff --git a/dlls/user32/input.c b/dlls/user32/input.c
index dcb46df22b5..06756b5551e 100644
--- a/dlls/user32/input.c
+++ b/dlls/user32/input.c
@@ -162,6 +162,33 @@ HWND WINAPI GetCapture(void)
}
+/*****************************************************************
+ * DestroyCaret (USER32.@)
+ */
+BOOL WINAPI DestroyCaret(void)
+{
+ return NtUserDestroyCaret();
+}
+
+
+/*****************************************************************
+ * SetCaretPos (USER32.@)
+ */
+BOOL WINAPI SetCaretPos( int x, int y )
+{
+ return NtUserSetCaretPos( x, y );
+}
+
+
+/*****************************************************************
+ * SetCaretBlinkTime (USER32.@)
+ */
+BOOL WINAPI SetCaretBlinkTime( unsigned int time )
+{
+ return NtUserSetCaretBlinkTime( time );
+}
+
+
/***********************************************************************
* GetInputState (USER32.@)
*/
--
2.25.1
1
0
From: Zebediah Figura <zfigura(a)codeweavers.com>
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/user32/caret.c | 371 +--------------------------------
dlls/user32/edit.c | 8 +-
dlls/user32/menu.c | 4 +-
dlls/user32/painting.c | 4 +-
dlls/user32/scroll.c | 20 +-
dlls/user32/user32.spec | 10 +-
dlls/user32/user_main.c | 4 -
dlls/user32/user_private.h | 1 -
dlls/win32u/dce.c | 4 +-
dlls/win32u/gdiobj.c | 3 +
dlls/win32u/input.c | 384 +++++++++++++++++++++++++++++++++++
dlls/win32u/message.c | 3 +-
dlls/win32u/ntuser_private.h | 4 -
dlls/win32u/syscall.c | 2 +
dlls/win32u/sysparams.c | 9 +
dlls/win32u/win32u.spec | 10 +-
dlls/win32u/win32u_private.h | 7 +
dlls/win32u/window.c | 13 +-
dlls/win32u/wrappers.c | 18 ++
dlls/wow64win/syscall.h | 2 +
dlls/wow64win/user.c | 12 ++
include/ntuser.h | 23 +++
22 files changed, 500 insertions(+), 416 deletions(-)
diff --git a/dlls/user32/caret.c b/dlls/user32/caret.c
index 7b21e03c764..9e0ff5ca48c 100644
--- a/dlls/user32/caret.c
+++ b/dlls/user32/caret.c
@@ -31,222 +31,12 @@
#include "wine/server.h"
#include "wine/debug.h"
-WINE_DEFAULT_DEBUG_CHANNEL(caret);
-
-typedef struct
-{
- HBITMAP hBmp;
- UINT timeout;
-} CARET;
-
-static CARET Caret = { 0, 500 };
-
-
-/*****************************************************************
- * CARET_DisplayCaret
- */
-static void CARET_DisplayCaret( HWND hwnd, const RECT *r )
-{
- HDC hdc;
- HDC hCompDC;
-
- /* do not use DCX_CACHE here, for x,y,width,height are in logical units */
- if (!(hdc = NtUserGetDCEx( hwnd, 0, DCX_USESTYLE /*| DCX_CACHE*/ ))) return;
- hCompDC = CreateCompatibleDC(hdc);
- if (hCompDC)
- {
- HBITMAP hPrevBmp;
-
- hPrevBmp = SelectObject(hCompDC, Caret.hBmp);
- BitBlt(hdc, r->left, r->top, r->right-r->left, r->bottom-r->top, hCompDC, 0, 0, SRCINVERT);
- SelectObject(hCompDC, hPrevBmp);
- DeleteDC(hCompDC);
- }
- NtUserReleaseDC( hwnd, hdc );
-}
-
-
-void CDECL toggle_caret( HWND hwnd )
-{
- BOOL ret;
- RECT r;
- int hidden = 0;
-
- SERVER_START_REQ( set_caret_info )
- {
- req->flags = SET_CARET_STATE;
- req->handle = wine_server_user_handle( hwnd );
- req->x = 0;
- req->y = 0;
- req->hide = 0;
- req->state = CARET_STATE_TOGGLE;
- if ((ret = !wine_server_call( req )))
- {
- hwnd = wine_server_ptr_handle( reply->full_handle );
- r.left = reply->old_rect.left;
- r.top = reply->old_rect.top;
- r.right = reply->old_rect.right;
- r.bottom = reply->old_rect.bottom;
- hidden = reply->old_hide;
- }
- }
- SERVER_END_REQ;
-
- if (ret && !hidden) CARET_DisplayCaret( hwnd, &r );
-}
-
-
-static unsigned int get_caret_registry_timeout(void)
-{
- unsigned int ret = 500;
- WCHAR value[11];
- DWORD size;
- HKEY key;
-
- if (RegOpenKeyExW( HKEY_CURRENT_USER, L"Control Panel\\Desktop", 0, KEY_READ, &key ))
- return ret;
-
- size = sizeof(value);
- if (!RegQueryValueExW( key, L"CursorBlinkRate", NULL, NULL, (BYTE *)value, &size ))
- ret = wcstoul( value, NULL, 10 );
- RegCloseKey( key );
- return ret;
-}
-
-
-/*****************************************************************
- * CreateCaret (USER32.@)
- */
-BOOL WINAPI CreateCaret( HWND hwnd, HBITMAP bitmap, INT width, INT height )
-{
- BOOL ret;
- RECT r;
- int old_state = 0;
- int hidden = 0;
- HBITMAP hBmp = 0;
- HWND prev = 0;
-
- TRACE("hwnd=%p\n", hwnd);
-
- if (!hwnd) return FALSE;
-
- if (bitmap && (bitmap != (HBITMAP)1))
- {
- BITMAP bmp;
- if (!GetObjectA( bitmap, sizeof(bmp), &bmp )) return FALSE;
- width = bmp.bmWidth;
- height = bmp.bmHeight;
- bmp.bmBits = NULL;
- hBmp = CreateBitmapIndirect(&bmp);
- if (hBmp)
- {
- /* copy the bitmap */
- LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, bmp.bmWidthBytes * bmp.bmHeight);
- GetBitmapBits(bitmap, bmp.bmWidthBytes * bmp.bmHeight, buf);
- SetBitmapBits(hBmp, bmp.bmWidthBytes * bmp.bmHeight, buf);
- HeapFree(GetProcessHeap(), 0, buf);
- }
- }
- else
- {
- HDC hdc;
-
- if (!width) width = GetSystemMetrics(SM_CXBORDER);
- if (!height) height = GetSystemMetrics(SM_CYBORDER);
-
- /* create the uniform bitmap on the fly */
- hdc = GetDC(hwnd);
- if (hdc)
- {
- HDC hMemDC = CreateCompatibleDC(hdc);
- if (hMemDC)
- {
- if ((hBmp = CreateCompatibleBitmap(hMemDC, width, height )))
- {
- HBITMAP hPrevBmp = SelectObject(hMemDC, hBmp);
- SetRect( &r, 0, 0, width, height );
- FillRect(hMemDC, &r, bitmap ? GetStockObject(GRAY_BRUSH) : GetStockObject(WHITE_BRUSH));
- SelectObject(hMemDC, hPrevBmp);
- }
- DeleteDC(hMemDC);
- }
- NtUserReleaseDC(hwnd, hdc);
- }
- }
- if (!hBmp) return FALSE;
-
- SERVER_START_REQ( set_caret_window )
- {
- req->handle = wine_server_user_handle( hwnd );
- req->width = width;
- req->height = height;
- if ((ret = !wine_server_call_err( req )))
- {
- prev = wine_server_ptr_handle( reply->previous );
- r.left = reply->old_rect.left;
- r.top = reply->old_rect.top;
- r.right = reply->old_rect.right;
- r.bottom = reply->old_rect.bottom;
- old_state = reply->old_state;
- hidden = reply->old_hide;
- }
- }
- SERVER_END_REQ;
- if (!ret) return FALSE;
-
- if (prev && !hidden) /* hide the previous one */
- {
- /* FIXME: won't work if prev belongs to a different process */
- KillSystemTimer( prev, SYSTEM_TIMER_CARET );
- if (old_state) CARET_DisplayCaret( prev, &r );
- }
-
- if (Caret.hBmp) DeleteObject( Caret.hBmp );
- Caret.hBmp = hBmp;
-
- Caret.timeout = get_caret_registry_timeout();
- return TRUE;
-}
-
-
/*****************************************************************
* DestroyCaret (USER32.@)
*/
BOOL WINAPI DestroyCaret(void)
{
- BOOL ret;
- HWND prev = 0;
- RECT r;
- int old_state = 0;
- int hidden = 0;
-
- SERVER_START_REQ( set_caret_window )
- {
- req->handle = 0;
- req->width = 0;
- req->height = 0;
- if ((ret = !wine_server_call_err( req )))
- {
- prev = wine_server_ptr_handle( reply->previous );
- r.left = reply->old_rect.left;
- r.top = reply->old_rect.top;
- r.right = reply->old_rect.right;
- r.bottom = reply->old_rect.bottom;
- old_state = reply->old_state;
- hidden = reply->old_hide;
- }
- }
- SERVER_END_REQ;
-
- if (ret && prev && !hidden)
- {
- /* FIXME: won't work if prev belongs to a different process */
- KillSystemTimer( prev, SYSTEM_TIMER_CARET );
- if (old_state) CARET_DisplayCaret( prev, &r );
- }
- if (Caret.hBmp) DeleteObject( Caret.hBmp );
- Caret.hBmp = 0;
- return ret;
+ return NtUserDestroyCaret();
}
@@ -255,167 +45,14 @@ BOOL WINAPI DestroyCaret(void)
*/
BOOL WINAPI SetCaretPos( INT x, INT y )
{
- BOOL ret;
- HWND hwnd = 0;
- RECT r;
- int old_state = 0;
- int hidden = 0;
-
- SERVER_START_REQ( set_caret_info )
- {
- req->flags = SET_CARET_POS|SET_CARET_STATE;
- req->handle = 0;
- req->x = x;
- req->y = y;
- req->hide = 0;
- req->state = CARET_STATE_ON_IF_MOVED;
- if ((ret = !wine_server_call_err( req )))
- {
- hwnd = wine_server_ptr_handle( reply->full_handle );
- r.left = reply->old_rect.left;
- r.top = reply->old_rect.top;
- r.right = reply->old_rect.right;
- r.bottom = reply->old_rect.bottom;
- old_state = reply->old_state;
- hidden = reply->old_hide;
- }
- }
- SERVER_END_REQ;
- if (ret && !hidden && (x != r.left || y != r.top))
- {
- if (old_state) CARET_DisplayCaret( hwnd, &r );
- r.right += x - r.left;
- r.bottom += y - r.top;
- r.left = x;
- r.top = y;
- CARET_DisplayCaret( hwnd, &r );
- NtUserSetSystemTimer( hwnd, SYSTEM_TIMER_CARET, Caret.timeout );
- }
- return ret;
-}
-
-
-/*****************************************************************
- * HideCaret (USER32.@)
- */
-BOOL WINAPI HideCaret( HWND hwnd )
-{
- BOOL ret;
- RECT r;
- int old_state = 0;
- int hidden = 0;
-
- SERVER_START_REQ( set_caret_info )
- {
- req->flags = SET_CARET_HIDE|SET_CARET_STATE;
- req->handle = wine_server_user_handle( hwnd );
- req->x = 0;
- req->y = 0;
- req->hide = 1;
- req->state = CARET_STATE_OFF;
- if ((ret = !wine_server_call_err( req )))
- {
- hwnd = wine_server_ptr_handle( reply->full_handle );
- r.left = reply->old_rect.left;
- r.top = reply->old_rect.top;
- r.right = reply->old_rect.right;
- r.bottom = reply->old_rect.bottom;
- old_state = reply->old_state;
- hidden = reply->old_hide;
- }
- }
- SERVER_END_REQ;
-
- if (ret && !hidden)
- {
- if (old_state) CARET_DisplayCaret( hwnd, &r );
- KillSystemTimer( hwnd, SYSTEM_TIMER_CARET );
- }
- return ret;
-}
-
-
-/*****************************************************************
- * ShowCaret (USER32.@)
- */
-BOOL WINAPI ShowCaret( HWND hwnd )
-{
- BOOL ret;
- RECT r;
- int hidden = 0;
-
- SERVER_START_REQ( set_caret_info )
- {
- req->flags = SET_CARET_HIDE|SET_CARET_STATE;
- req->handle = wine_server_user_handle( hwnd );
- req->x = 0;
- req->y = 0;
- req->hide = -1;
- req->state = CARET_STATE_ON;
- if ((ret = !wine_server_call_err( req )))
- {
- hwnd = wine_server_ptr_handle( reply->full_handle );
- r.left = reply->old_rect.left;
- r.top = reply->old_rect.top;
- r.right = reply->old_rect.right;
- r.bottom = reply->old_rect.bottom;
- hidden = reply->old_hide;
- }
- }
- SERVER_END_REQ;
-
- if (ret && (hidden == 1)) /* hidden was 1 so it's now 0 */
- {
- CARET_DisplayCaret( hwnd, &r );
- NtUserSetSystemTimer( hwnd, SYSTEM_TIMER_CARET, Caret.timeout );
- }
- return ret;
-}
-
-
-/*****************************************************************
- * GetCaretPos (USER32.@)
- */
-BOOL WINAPI GetCaretPos( LPPOINT pt )
-{
- BOOL ret;
-
- SERVER_START_REQ( set_caret_info )
- {
- req->flags = 0; /* don't set anything */
- req->handle = 0;
- req->x = 0;
- req->y = 0;
- req->hide = 0;
- req->state = 0;
- if ((ret = !wine_server_call_err( req )))
- {
- pt->x = reply->old_rect.left;
- pt->y = reply->old_rect.top;
- }
- }
- SERVER_END_REQ;
- return ret;
+ return NtUserSetCaretPos( x, y );
}
/*****************************************************************
* SetCaretBlinkTime (USER32.@)
*/
-BOOL WINAPI SetCaretBlinkTime( UINT msecs )
-{
- TRACE("msecs=%d\n", msecs);
-
- Caret.timeout = msecs;
-/* if (Caret.hwnd) CARET_SetTimer(); FIXME */
- return TRUE;
-}
-
-
-/*****************************************************************
- * GetCaretBlinkTime (USER32.@)
- */
-UINT WINAPI GetCaretBlinkTime(void)
+BOOL WINAPI SetCaretBlinkTime( unsigned int time )
{
- return Caret.timeout;
+ return NtUserSetCaretBlinkTime( time );
}
diff --git a/dlls/user32/edit.c b/dlls/user32/edit.c
index f15c4c8e550..4e32a59df48 100644
--- a/dlls/user32/edit.c
+++ b/dlls/user32/edit.c
@@ -3807,10 +3807,10 @@ static void EDIT_WM_SetFocus(EDITSTATE *es)
NtUserReleaseDC( es->hwndSelf, hdc );
}
- CreateCaret(es->hwndSelf, 0, 1, es->line_height);
+ NtUserCreateCaret( es->hwndSelf, 0, 1, es->line_height );
EDIT_SetCaretPos(es, es->selection_end,
es->flags & EF_AFTER_WRAP);
- ShowCaret(es->hwndSelf);
+ NtUserShowCaret( es->hwndSelf );
EDIT_NOTIFY_PARENT(es, EN_SETFOCUS);
}
@@ -3890,10 +3890,10 @@ static void EDIT_WM_SetFont(EDITSTATE *es, HFONT font, BOOL redraw)
EDIT_UpdateText(es, NULL, TRUE);
if (es->flags & EF_FOCUSED) {
DestroyCaret();
- CreateCaret(es->hwndSelf, 0, 1, es->line_height);
+ NtUserCreateCaret( es->hwndSelf, 0, 1, es->line_height );
EDIT_SetCaretPos(es, es->selection_end,
es->flags & EF_AFTER_WRAP);
- ShowCaret(es->hwndSelf);
+ NtUserShowCaret( es->hwndSelf );
}
}
diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c
index 6fb9422cf9d..cc6c5c953e9 100644
--- a/dlls/user32/menu.c
+++ b/dlls/user32/menu.c
@@ -3300,7 +3300,7 @@ static BOOL MENU_InitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT wFlags)
TRACE("hwnd=%p hmenu=%p\n", hWnd, hMenu);
- HideCaret(0);
+ NtUserHideCaret( 0 );
if (!(menu = MENU_GetMenu( hMenu ))) return FALSE;
@@ -3342,7 +3342,7 @@ static BOOL MENU_ExitTracking(HWND hWnd, BOOL bPopup)
TRACE("hwnd=%p\n", hWnd);
SendMessageW( hWnd, WM_EXITMENULOOP, bPopup, 0 );
- ShowCaret(0);
+ NtUserShowCaret( 0 );
top_popup = 0;
top_popup_hmenu = NULL;
return TRUE;
diff --git a/dlls/user32/painting.c b/dlls/user32/painting.c
index 94e462605dd..29450e6e984 100644
--- a/dlls/user32/painting.c
+++ b/dlls/user32/painting.c
@@ -285,7 +285,7 @@ static INT scroll_window( HWND hwnd, INT dx, INT dy, const RECT *rect, const REC
hwndCaret = fix_caret(hwnd, &rc, dx, dy, flags, &moveCaret, &newCaretPos);
if (hwndCaret)
- HideCaret(hwndCaret);
+ NtUserHideCaret( hwndCaret );
if (is_ex) dcxflags |= DCX_CACHE;
if( style & WS_CLIPSIBLINGS) dcxflags |= DCX_CLIPSIBLINGS;
@@ -388,7 +388,7 @@ static INT scroll_window( HWND hwnd, INT dx, INT dy, const RECT *rect, const REC
if( moveCaret )
SetCaretPos( newCaretPos.x, newCaretPos.y );
if( hwndCaret )
- ShowCaret( hwndCaret );
+ NtUserShowCaret( hwndCaret );
if( bOwnRgn && hrgnUpdate ) DeleteObject( hrgnUpdate );
diff --git a/dlls/user32/scroll.c b/dlls/user32/scroll.c
index 8f085364dab..efe115246f2 100644
--- a/dlls/user32/scroll.c
+++ b/dlls/user32/scroll.c
@@ -756,7 +756,7 @@ static void SCROLL_HandleKbdEvent(HWND hwnd, WPARAM wParam, LPARAM lParam)
/* hide caret on first KEYDOWN to prevent flicker */
if ((lParam & PFD_DOUBLEBUFFER_DONTCARE) == 0)
- HideCaret(hwnd);
+ NtUserHideCaret( hwnd );
switch(wParam)
{
@@ -814,7 +814,7 @@ void SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt )
switch(msg)
{
case WM_LBUTTONDOWN: /* Initialise mouse tracking */
- HideCaret(hwnd); /* hide caret while holding down LBUTTON */
+ NtUserHideCaret( hwnd ); /* hide caret while holding down LBUTTON */
NtUserSetCapture( hwnd );
prevPt = pt;
g_tracking_info.hit_test = hittest = SCROLL_THUMB;
@@ -826,7 +826,7 @@ void SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt )
case WM_LBUTTONUP:
ReleaseCapture();
g_tracking_info.hit_test = hittest = SCROLL_NOWHERE;
- if (hwnd==GetFocus()) ShowCaret(hwnd);
+ if (hwnd == GetFocus()) NtUserShowCaret( hwnd );
break;
case WM_SYSTIMER:
pt = prevPt;
@@ -844,7 +844,7 @@ void SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt )
switch(msg)
{
case WM_LBUTTONDOWN: /* Initialise mouse tracking */
- HideCaret(hwnd); /* hide caret while holding down LBUTTON */
+ NtUserHideCaret( hwnd ); /* hide caret while holding down LBUTTON */
g_tracking_info.vertical = vertical;
g_tracking_info.hit_test = hittest = SCROLL_HitTest( hwnd, nBar, pt, FALSE );
lastClickPos = vertical ? (pt.y - rect.top) : (pt.x - rect.left);
@@ -911,7 +911,7 @@ void SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt )
hittest = SCROLL_NOWHERE;
ReleaseCapture();
/* if scrollbar has focus, show back caret */
- if (hwnd==GetFocus()) ShowCaret(hwnd);
+ if (hwnd == GetFocus()) NtUserShowCaret( hwnd );
break;
case WM_SYSTIMER:
@@ -1468,7 +1468,7 @@ LRESULT WINAPI USER_ScrollBarProc( HWND hwnd, UINT message, WPARAM wParam, LPARA
break;
case WM_KEYUP:
- ShowCaret(hwnd);
+ NtUserShowCaret( hwnd );
break;
case WM_SETFOCUS:
@@ -1480,15 +1480,15 @@ LRESULT WINAPI USER_ScrollBarProc( HWND hwnd, UINT message, WPARAM wParam, LPARA
&arrowSize, &thumbSize, &thumbPos );
if (!vertical)
{
- CreateCaret(hwnd, (HBITMAP)1, thumbSize-2, rect.bottom-rect.top-2);
+ NtUserCreateCaret( hwnd, (HBITMAP)1, thumbSize - 2, rect.bottom - rect.top - 2 );
SetCaretPos(thumbPos+1, rect.top+1);
}
else
{
- CreateCaret(hwnd, (HBITMAP)1, rect.right-rect.left-2,thumbSize-2);
+ NtUserCreateCaret( hwnd, (HBITMAP)1, rect.right - rect.left - 2, thumbSize - 2);
SetCaretPos(rect.top+1, thumbPos+1);
}
- ShowCaret(hwnd);
+ NtUserShowCaret( hwnd );
}
break;
@@ -1506,7 +1506,7 @@ LRESULT WINAPI USER_ScrollBarProc( HWND hwnd, UINT message, WPARAM wParam, LPARA
rect.top=thumbPos+1;
rect.bottom=rect.top+thumbSize;
}
- HideCaret(hwnd);
+ NtUserHideCaret( hwnd );
InvalidateRect(hwnd,&rect,0);
DestroyCaret();
}
diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec
index 6f86fccdfbd..da0b7c5a1ab 100644
--- a/dlls/user32/user32.spec
+++ b/dlls/user32/user32.spec
@@ -86,7 +86,7 @@
@ stdcall CountClipboardFormats() NtUserCountClipboardFormats
@ stdcall CreateAcceleratorTableA(ptr long)
@ stdcall CreateAcceleratorTableW(ptr long) NtUserCreateAcceleratorTable
-@ stdcall CreateCaret(long long long long)
+@ stdcall CreateCaret(long long long long) NtUserCreateCaret
@ stdcall CreateCursor(long long long long long ptr ptr)
@ stdcall CreateDesktopA(str str ptr long long ptr)
@ stdcall CreateDesktopW(wstr wstr ptr long long ptr)
@@ -259,8 +259,8 @@
@ stdcall GetAutoRotationState(ptr)
@ stdcall GetAwarenessFromDpiAwarenessContext(long)
@ stdcall GetCapture()
-@ stdcall GetCaretBlinkTime()
-@ stdcall GetCaretPos(ptr)
+@ stdcall GetCaretBlinkTime() NtUserGetCaretBlinkTime
+@ stdcall GetCaretPos(ptr) NtUserGetCaretPos
@ stdcall GetClassInfoA(long str ptr)
@ stdcall GetClassInfoExA(long str ptr)
@ stdcall GetClassInfoExW(long wstr ptr)
@@ -425,7 +425,7 @@
@ stdcall GrayStringA(long long ptr long long long long long long)
@ stdcall GrayStringW(long long ptr long long long long long long)
# @ stub HasSystemSleepStarted
-@ stdcall HideCaret(long)
+@ stdcall HideCaret(long) NtUserHideCaret
@ stdcall HiliteMenuItem(long long long long)
# @ stub IMPGetIMEA
# @ stub IMPGetIMEW
@@ -736,7 +736,7 @@
@ stdcall SetWindowsHookExA(long long long long)
@ stdcall SetWindowsHookExW(long long long long)
@ stdcall SetWindowsHookW(long ptr)
-@ stdcall ShowCaret(long)
+@ stdcall ShowCaret(long) NtUserShowCaret
@ stdcall -import ShowCursor(long) NtUserShowCursor
@ stdcall ShowOwnedPopups(long long)
@ stdcall ShowScrollBar(long long long)
diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c
index d529e49ba3a..1258181c88a 100644
--- a/dlls/user32/user_main.c
+++ b/dlls/user32/user_main.c
@@ -161,13 +161,10 @@ static const struct user_callbacks user_funcs =
{
AdjustWindowRectEx,
CopyImage,
- DestroyCaret,
EndMenu,
- HideCaret,
ImmProcessKey,
ImmTranslateMessage,
SetSystemMenu,
- ShowCaret,
free_menu_items,
free_win_ptr,
MENU_IsMenuActive,
@@ -177,7 +174,6 @@ static const struct user_callbacks user_funcs =
rawinput_device_get_usages,
register_builtin_classes,
SCROLL_SetStandardScrollPainted,
- toggle_caret,
unpack_dde_message,
register_imm,
unregister_imm,
diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h
index 8fa8af00326..f28fc66bbf2 100644
--- a/dlls/user32/user_private.h
+++ b/dlls/user32/user_private.h
@@ -101,7 +101,6 @@ extern HBRUSH SYSCOLOR_Get55AABrush(void) DECLSPEC_HIDDEN;
extern void SYSPARAMS_Init(void) DECLSPEC_HIDDEN;
extern void USER_CheckNotLock(void) DECLSPEC_HIDDEN;
extern BOOL USER_IsExitingThread( DWORD tid ) DECLSPEC_HIDDEN;
-extern void CDECL toggle_caret( HWND hwnd ) DECLSPEC_HIDDEN;
typedef LRESULT (*winproc_callback_t)( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
LRESULT *result, void *arg );
diff --git a/dlls/win32u/dce.c b/dlls/win32u/dce.c
index aa16c099d97..80f630b5614 100644
--- a/dlls/win32u/dce.c
+++ b/dlls/win32u/dce.c
@@ -1340,7 +1340,7 @@ HDC WINAPI NtUserBeginPaint( HWND hwnd, PAINTSTRUCT *ps )
RECT rect;
UINT flags = UPDATE_NONCLIENT | UPDATE_ERASE | UPDATE_PAINT | UPDATE_INTERNALPAINT | UPDATE_NOCHILDREN;
- if (user_callbacks) user_callbacks->pHideCaret( hwnd );
+ NtUserHideCaret( hwnd );
if (!(hrgn = send_ncpaint( hwnd, NULL, &flags ))) return 0;
@@ -1364,7 +1364,7 @@ HDC WINAPI NtUserBeginPaint( HWND hwnd, PAINTSTRUCT *ps )
*/
BOOL WINAPI NtUserEndPaint( HWND hwnd, const PAINTSTRUCT *ps )
{
- if (user_callbacks) user_callbacks->pShowCaret( hwnd );
+ NtUserShowCaret( hwnd );
flush_window_surfaces( FALSE );
if (!ps) return FALSE;
release_dc( hwnd, ps->hdc, TRUE );
diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c
index 0f82d446269..c5db1bfcc30 100644
--- a/dlls/win32u/gdiobj.c
+++ b/dlls/win32u/gdiobj.c
@@ -1147,6 +1147,7 @@ static struct unix_funcs unix_funcs =
NtUserClipCursor,
NtUserCloseClipboard,
NtUserCountClipboardFormats,
+ NtUserCreateCaret,
NtUserCreateWindowEx,
NtUserDeferWindowPosAndBand,
NtUserDestroyCursor,
@@ -1178,6 +1179,7 @@ static struct unix_funcs unix_funcs =
NtUserGetUpdateRect,
NtUserGetUpdateRgn,
NtUserGetUpdatedClipboardFormats,
+ NtUserHideCaret,
NtUserIsClipboardFormatAvailable,
NtUserMapVirtualKeyEx,
NtUserMessageCall,
@@ -1214,6 +1216,7 @@ static struct unix_funcs unix_funcs =
NtUserSetWindowPos,
NtUserSetWindowRgn,
NtUserSetWindowWord,
+ NtUserShowCaret,
NtUserShowCursor,
NtUserShowWindow,
NtUserShowWindowAsync,
diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c
index c9d14ed746f..28fc5a918c8 100644
--- a/dlls/win32u/input.c
+++ b/dlls/win32u/input.c
@@ -2,10 +2,14 @@
* USER Input processing
*
* Copyright 1993 Bob Amstadt
+ * Copyright 1993 David Metcalfe
* Copyright 1996 Albrecht Kleine
+ * Copyright 1996 Frans van Dorsselaer
* Copyright 1997 David Faure
* Copyright 1998 Morten Welinder
* Copyright 1998 Ulrich Weigand
+ * Copyright 2001 Eric Pouech
+ * Copyright 2002 Alexandre Julliard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -1767,3 +1771,383 @@ BOOL set_foreground_window( HWND hwnd, BOOL mouse )
}
return ret;
}
+
+struct
+{
+ HBITMAP bitmap;
+ unsigned int timeout;
+} caret = {0, 500};
+
+static void display_caret( HWND hwnd, const RECT *r )
+{
+ HDC dc, mem_dc;
+
+ /* do not use DCX_CACHE here, since coördinates are in logical units */
+ if (!(dc = NtUserGetDCEx( hwnd, 0, DCX_USESTYLE )))
+ return;
+ mem_dc = NtGdiCreateCompatibleDC(dc);
+ if (mem_dc)
+ {
+ HBITMAP prev_bitmap;
+
+ prev_bitmap = NtGdiSelectBitmap( mem_dc, caret.bitmap );
+ NtGdiBitBlt( dc, r->left, r->top, r->right-r->left, r->bottom-r->top, mem_dc, 0, 0, SRCINVERT, 0, 0 );
+ NtGdiSelectBitmap( mem_dc, prev_bitmap );
+ NtGdiDeleteObjectApp( mem_dc );
+ }
+ NtUserReleaseDC( hwnd, dc );
+}
+
+static void fill_rect( HDC dc, const RECT *rect, HBRUSH hbrush )
+{
+ HBRUSH prev_brush;
+
+ prev_brush = NtGdiSelectBrush( dc, hbrush );
+ NtGdiPatBlt( dc, rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top, PATCOPY );
+ if (prev_brush) NtGdiSelectBrush( dc, prev_brush );
+}
+
+static unsigned int get_caret_registry_timeout(void)
+{
+ char value_buffer[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[11 * sizeof(WCHAR)])];
+ KEY_VALUE_PARTIAL_INFORMATION *value = (void *)value_buffer;
+ unsigned int ret = 500;
+ HKEY key;
+
+ if (!(key = reg_open_hkcu_key( "Control Panel\\Desktop" )))
+ return ret;
+
+ if (query_reg_ascii_value( key, "CursorBlinkRate", value, sizeof(value_buffer) ))
+ ret = wcstoul( (WCHAR *)value->Data, NULL, 10 );
+ NtClose( key );
+ return ret;
+}
+
+/*****************************************************************
+ * NtUserCreateCaret (win32u.@)
+ */
+BOOL WINAPI NtUserCreateCaret( HWND hwnd, HBITMAP bitmap, int width, int height )
+{
+ HBITMAP caret_bitmap = 0;
+ int old_state = 0;
+ int hidden = 0;
+ HWND prev = 0;
+ BOOL ret;
+ RECT r;
+
+ TRACE( "hwnd %p, bitmap %p, width %d, height %d\n", hwnd, bitmap, width, height );
+
+ if (!hwnd) return FALSE;
+
+ if (bitmap && bitmap != (HBITMAP)1)
+ {
+ BITMAP bitmap_data;
+
+ if (!NtGdiExtGetObjectW( bitmap, sizeof(bitmap_data), &bitmap_data )) return FALSE;
+ caret_bitmap = NtGdiCreateBitmap( bitmap_data.bmWidth, bitmap_data.bmHeight,
+ bitmap_data.bmPlanes, bitmap_data.bmBitsPixel, NULL );
+ if (caret_bitmap)
+ {
+ size_t size = bitmap_data.bmWidthBytes * bitmap_data.bmHeight;
+ BYTE *bits = malloc( size );
+
+ NtGdiGetBitmapBits( bitmap, size, bits );
+ NtGdiSetBitmapBits( caret_bitmap, size, bits );
+ free( bits );
+ }
+ }
+ else
+ {
+ HDC dc;
+
+ if (!width) width = get_system_metrics( SM_CXBORDER );
+ if (!height) height = get_system_metrics( SM_CYBORDER );
+
+ /* create the uniform bitmap on the fly */
+ dc = NtUserGetDCEx( hwnd, 0, DCX_USESTYLE );
+ if (dc)
+ {
+ HDC mem_dc = NtGdiCreateCompatibleDC( dc );
+ if (mem_dc)
+ {
+ if ((caret_bitmap = NtGdiCreateCompatibleBitmap( mem_dc, width, height )))
+ {
+ HBITMAP prev_bitmap = NtGdiSelectBitmap( mem_dc, caret_bitmap );
+ SetRect( &r, 0, 0, width, height );
+ fill_rect( mem_dc, &r, GetStockObject( bitmap ? GRAY_BRUSH : WHITE_BRUSH ));
+ NtGdiSelectBitmap( mem_dc, prev_bitmap );
+ }
+ NtGdiDeleteObjectApp( mem_dc );
+ }
+ NtUserReleaseDC( hwnd, dc );
+ }
+ }
+ if (!caret_bitmap) return FALSE;
+
+ SERVER_START_REQ( set_caret_window )
+ {
+ req->handle = wine_server_user_handle( hwnd );
+ req->width = width;
+ req->height = height;
+ if ((ret = !wine_server_call_err( req )))
+ {
+ prev = wine_server_ptr_handle( reply->previous );
+ r.left = reply->old_rect.left;
+ r.top = reply->old_rect.top;
+ r.right = reply->old_rect.right;
+ r.bottom = reply->old_rect.bottom;
+ old_state = reply->old_state;
+ hidden = reply->old_hide;
+ }
+ }
+ SERVER_END_REQ;
+ if (!ret) return FALSE;
+
+ if (prev && !hidden) /* hide the previous one */
+ {
+ /* FIXME: won't work if prev belongs to a different process */
+ kill_system_timer( prev, SYSTEM_TIMER_CARET );
+ if (old_state) display_caret( prev, &r );
+ }
+
+ if (caret.bitmap) NtGdiDeleteObjectApp( caret.bitmap );
+ caret.bitmap = caret_bitmap;
+ caret.timeout = get_caret_registry_timeout();
+ return TRUE;
+}
+
+/*******************************************************************
+ * destroy_caret
+ */
+BOOL destroy_caret(void)
+{
+ int old_state = 0;
+ int hidden = 0;
+ HWND prev = 0;
+ BOOL ret;
+ RECT r;
+
+ SERVER_START_REQ( set_caret_window )
+ {
+ req->handle = 0;
+ req->width = 0;
+ req->height = 0;
+ if ((ret = !wine_server_call_err( req )))
+ {
+ prev = wine_server_ptr_handle( reply->previous );
+ r.left = reply->old_rect.left;
+ r.top = reply->old_rect.top;
+ r.right = reply->old_rect.right;
+ r.bottom = reply->old_rect.bottom;
+ old_state = reply->old_state;
+ hidden = reply->old_hide;
+ }
+ }
+ SERVER_END_REQ;
+
+ if (ret && prev && !hidden)
+ {
+ /* FIXME: won't work if prev belongs to a different process */
+ kill_system_timer( prev, SYSTEM_TIMER_CARET );
+ if (old_state) display_caret( prev, &r );
+ }
+ if (caret.bitmap) NtGdiDeleteObjectApp( caret.bitmap );
+ caret.bitmap = 0;
+ return ret;
+}
+
+/*****************************************************************
+ * NtUserGetCaretBlinkTime (win32u.@)
+ */
+UINT WINAPI NtUserGetCaretBlinkTime(void)
+{
+ return caret.timeout;
+}
+
+/*******************************************************************
+ * set_caret_blink_time
+ */
+BOOL set_caret_blink_time( unsigned int time )
+{
+ TRACE( "time %u\n", time );
+
+ caret.timeout = time;
+ /* FIXME: update the timer */
+ return TRUE;
+}
+
+/*****************************************************************
+ * NtUserGetCaretPos (win32u.@)
+ */
+BOOL WINAPI NtUserGetCaretPos( POINT *pt )
+{
+ BOOL ret;
+
+ SERVER_START_REQ( set_caret_info )
+ {
+ req->flags = 0; /* don't set anything */
+ req->handle = 0;
+ req->x = 0;
+ req->y = 0;
+ req->hide = 0;
+ req->state = 0;
+ if ((ret = !wine_server_call_err( req )))
+ {
+ pt->x = reply->old_rect.left;
+ pt->y = reply->old_rect.top;
+ }
+ }
+ SERVER_END_REQ;
+ return ret;
+}
+
+/*******************************************************************
+ * set_caret_pos
+ */
+BOOL set_caret_pos( int x, int y )
+{
+ int old_state = 0;
+ int hidden = 0;
+ HWND hwnd = 0;
+ BOOL ret;
+ RECT r;
+
+ TRACE( "(%d, %d)\n", x, y );
+
+ SERVER_START_REQ( set_caret_info )
+ {
+ req->flags = SET_CARET_POS|SET_CARET_STATE;
+ req->handle = 0;
+ req->x = x;
+ req->y = y;
+ req->hide = 0;
+ req->state = CARET_STATE_ON_IF_MOVED;
+ if ((ret = !wine_server_call_err( req )))
+ {
+ hwnd = wine_server_ptr_handle( reply->full_handle );
+ r.left = reply->old_rect.left;
+ r.top = reply->old_rect.top;
+ r.right = reply->old_rect.right;
+ r.bottom = reply->old_rect.bottom;
+ old_state = reply->old_state;
+ hidden = reply->old_hide;
+ }
+ }
+ SERVER_END_REQ;
+ if (ret && !hidden && (x != r.left || y != r.top))
+ {
+ if (old_state) display_caret( hwnd, &r );
+ r.right += x - r.left;
+ r.bottom += y - r.top;
+ r.left = x;
+ r.top = y;
+ display_caret( hwnd, &r );
+ NtUserSetSystemTimer( hwnd, SYSTEM_TIMER_CARET, caret.timeout );
+ }
+ return ret;
+}
+
+/*****************************************************************
+ * NtUserShowCaret (win32u.@)
+ */
+BOOL WINAPI NtUserShowCaret( HWND hwnd )
+{
+ int hidden = 0;
+ BOOL ret;
+ RECT r;
+
+ SERVER_START_REQ( set_caret_info )
+ {
+ req->flags = SET_CARET_HIDE | SET_CARET_STATE;
+ req->handle = wine_server_user_handle( hwnd );
+ req->x = 0;
+ req->y = 0;
+ req->hide = -1;
+ req->state = CARET_STATE_ON;
+ if ((ret = !wine_server_call_err( req )))
+ {
+ hwnd = wine_server_ptr_handle( reply->full_handle );
+ r.left = reply->old_rect.left;
+ r.top = reply->old_rect.top;
+ r.right = reply->old_rect.right;
+ r.bottom = reply->old_rect.bottom;
+ hidden = reply->old_hide;
+ }
+ }
+ SERVER_END_REQ;
+
+ if (ret && hidden == 1) /* hidden was 1 so it's now 0 */
+ {
+ display_caret( hwnd, &r );
+ NtUserSetSystemTimer( hwnd, SYSTEM_TIMER_CARET, caret.timeout );
+ }
+ return ret;
+}
+
+/*****************************************************************
+ * NtUserHideCaret (win32u.@)
+ */
+BOOL WINAPI NtUserHideCaret( HWND hwnd )
+{
+ int old_state = 0;
+ int hidden = 0;
+ BOOL ret;
+ RECT r;
+
+ SERVER_START_REQ( set_caret_info )
+ {
+ req->flags = SET_CARET_HIDE | SET_CARET_STATE;
+ req->handle = wine_server_user_handle( hwnd );
+ req->x = 0;
+ req->y = 0;
+ req->hide = 1;
+ req->state = CARET_STATE_OFF;
+ if ((ret = !wine_server_call_err( req )))
+ {
+ hwnd = wine_server_ptr_handle( reply->full_handle );
+ r.left = reply->old_rect.left;
+ r.top = reply->old_rect.top;
+ r.right = reply->old_rect.right;
+ r.bottom = reply->old_rect.bottom;
+ old_state = reply->old_state;
+ hidden = reply->old_hide;
+ }
+ }
+ SERVER_END_REQ;
+
+ if (ret && !hidden)
+ {
+ if (old_state) display_caret( hwnd, &r );
+ kill_system_timer( hwnd, SYSTEM_TIMER_CARET );
+ }
+ return ret;
+}
+
+void toggle_caret( HWND hwnd )
+{
+ BOOL ret;
+ RECT r;
+ int hidden = 0;
+
+ SERVER_START_REQ( set_caret_info )
+ {
+ req->flags = SET_CARET_STATE;
+ req->handle = wine_server_user_handle( hwnd );
+ req->x = 0;
+ req->y = 0;
+ req->hide = 0;
+ req->state = CARET_STATE_TOGGLE;
+ if ((ret = !wine_server_call( req )))
+ {
+ hwnd = wine_server_ptr_handle( reply->full_handle );
+ r.left = reply->old_rect.left;
+ r.top = reply->old_rect.top;
+ r.right = reply->old_rect.right;
+ r.bottom = reply->old_rect.bottom;
+ hidden = reply->old_hide;
+ }
+ }
+ SERVER_END_REQ;
+
+ if (ret && !hidden) display_caret( hwnd, &r );
+}
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c
index 8ad4a0271b3..d43dca723d2 100644
--- a/dlls/win32u/message.c
+++ b/dlls/win32u/message.c
@@ -2474,8 +2474,7 @@ LRESULT dispatch_message( const MSG *msg, BOOL ansi )
switch (msg->wParam)
{
case SYSTEM_TIMER_CARET:
- if (!user_callbacks) break;
- user_callbacks->toggle_caret( msg->hwnd );
+ toggle_caret( msg->hwnd );
return 0;
case SYSTEM_TIMER_TRACK_MOUSE:
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h
index cad038dbff6..632cb16d23a 100644
--- a/dlls/win32u/ntuser_private.h
+++ b/dlls/win32u/ntuser_private.h
@@ -34,13 +34,10 @@ struct user_callbacks
{
BOOL (WINAPI *pAdjustWindowRectEx)( RECT *, DWORD, BOOL, DWORD );
HANDLE (WINAPI *pCopyImage)( HANDLE, UINT, INT, INT, UINT );
- BOOL (WINAPI *pDestroyCaret)(void);
BOOL (WINAPI *pEndMenu)(void);
- BOOL (WINAPI *pHideCaret)( HWND hwnd );
BOOL (WINAPI *pImmProcessKey)(HWND, HKL, UINT, LPARAM, DWORD);
BOOL (WINAPI *pImmTranslateMessage)(HWND, UINT, WPARAM, LPARAM);
BOOL (WINAPI *pSetSystemMenu)( HWND hwnd, HMENU menu );
- BOOL (WINAPI *pShowCaret)( HWND hwnd );
void (CDECL *free_menu_items)( void *ptr );
void (CDECL *free_win_ptr)( struct tagWND *win );
HWND (CDECL *is_menu_active)(void);
@@ -51,7 +48,6 @@ struct user_callbacks
BOOL (CDECL *rawinput_device_get_usages)(HANDLE handle, USHORT *usage_page, USHORT *usage);
void (CDECL *register_builtin_classes)(void);
void (WINAPI *set_standard_scroll_painted)( HWND hwnd, INT bar, BOOL visible );
- void (CDECL *toggle_caret)( HWND hwnd );
BOOL (CDECL *unpack_dde_message)( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lparam,
void **buffer, size_t size );
BOOL (WINAPI *register_imm)( HWND hwnd );
diff --git a/dlls/win32u/syscall.c b/dlls/win32u/syscall.c
index 0be0863b992..dc58cbe1944 100644
--- a/dlls/win32u/syscall.c
+++ b/dlls/win32u/syscall.c
@@ -119,6 +119,8 @@ static void * const syscalls[] =
NtUserFindWindowEx,
NtUserGetAncestor,
NtUserGetAtomName,
+ NtUserGetCaretBlinkTime,
+ NtUserGetCaretPos,
NtUserGetClassName,
NtUserGetClipboardFormatName,
NtUserGetClipboardOwner,
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c
index 696fc9d922d..3cf03d68399 100644
--- a/dlls/win32u/sysparams.c
+++ b/dlls/win32u/sysparams.c
@@ -4653,6 +4653,9 @@ ULONG_PTR WINAPI NtUserCallNoParam( ULONG code )
{
switch(code)
{
+ case NtUserCallNoParam_DestroyCaret:
+ return destroy_caret();
+
case NtUserCallNoParam_GetDesktopWindow:
return HandleToUlong( get_desktop_window() );
@@ -4744,6 +4747,9 @@ ULONG_PTR WINAPI NtUserCallOneParam( ULONG_PTR arg, ULONG code )
case NtUserCallOneParam_MessageBeep:
return message_beep( arg );
+ case NtUserCallOneParam_SetCaretBlinkTime:
+ return set_caret_blink_time( arg );
+
/* temporary exports */
case NtUserCallHooks:
{
@@ -4800,6 +4806,9 @@ ULONG_PTR WINAPI NtUserCallTwoParam( ULONG_PTR arg1, ULONG_PTR arg2, ULONG code
case NtUserCallTwoParam_ReplyMessage:
return reply_message_result( arg1, (MSG *)arg2 );
+ case NtUserCallTwoParam_SetCaretPos:
+ return set_caret_pos( arg1, arg2 );
+
case NtUserCallTwoParam_SetIconParam:
return set_icon_param( UlongToHandle(arg1), arg2 );
diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec
index e94ec7f4a39..208b167229e 100644
--- a/dlls/win32u/win32u.spec
+++ b/dlls/win32u/win32u.spec
@@ -807,7 +807,7 @@
@ stdcall -syscall NtUserCreateAcceleratorTable(ptr long)
@ stub NtUserCreateActivationGroup
@ stub NtUserCreateActivationObject
-@ stub NtUserCreateCaret
+@ stdcall NtUserCreateCaret(long long long long)
@ stub NtUserCreateDCompositionHwndTarget
@ stdcall -syscall NtUserCreateDesktopEx(ptr ptr ptr long long long)
@ stub NtUserCreateEmptyCursorObject
@@ -896,8 +896,8 @@
@ stub NtUserGetAutoRotationState
@ stub NtUserGetCIMSSM
@ stub NtUserGetCPD
-@ stub NtUserGetCaretBlinkTime
-@ stub NtUserGetCaretPos
+@ stdcall -syscall NtUserGetCaretBlinkTime()
+@ stdcall -syscall NtUserGetCaretPos(ptr)
@ stdcall NtUserGetClassInfoEx(ptr ptr ptr ptr long)
@ stdcall -syscall NtUserGetClassName(long long ptr)
@ stub NtUserGetClipCursor
@@ -1020,7 +1020,7 @@
@ stub NtUserGhostWindowFromHungWindow
@ stub NtUserHandleDelegatedInput
@ stub NtUserHardErrorControl
-@ stub NtUserHideCaret
+@ stdcall NtUserHideCaret(long)
@ stub NtUserHidePointerContactVisualization
@ stub NtUserHiliteMenuItem
@ stub NtUserHungWindowFromGhostWindow
@@ -1257,7 +1257,7 @@
@ stdcall NtUserSetWindowWord(long long long)
@ stub NtUserSetWindowsHookAW
@ stdcall -syscall NtUserSetWindowsHookEx(ptr ptr long long ptr long)
-@ stub NtUserShowCaret
+@ stdcall NtUserShowCaret(long)
@ stdcall NtUserShowCursor(long)
@ stub NtUserShowScrollBar
@ stub NtUserShowSystemCursor
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h
index 122921431fc..caf77590559 100644
--- a/dlls/win32u/win32u_private.h
+++ b/dlls/win32u/win32u_private.h
@@ -197,6 +197,7 @@ struct unix_funcs
BOOL (WINAPI *pNtUserClipCursor)( const RECT *rect );
BOOL (WINAPI *pNtUserCloseClipboard)(void);
INT (WINAPI *pNtUserCountClipboardFormats)(void);
+ BOOL (WINAPI *pNtUserCreateCaret)( HWND hwnd, HBITMAP bitmap, int width, int height );
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,
@@ -240,6 +241,7 @@ struct unix_funcs
BOOL (WINAPI *pNtUserGetUpdateRect)( HWND hwnd, RECT *rect, BOOL erase );
INT (WINAPI *pNtUserGetUpdateRgn)( HWND hwnd, HRGN hrgn, BOOL erase );
BOOL (WINAPI *pNtUserGetUpdatedClipboardFormats)( UINT *formats, UINT size, UINT *out_size );
+ BOOL (WINAPI *pNtUserHideCaret)( HWND hwnd );
BOOL (WINAPI *pNtUserIsClipboardFormatAvailable)( UINT format );
UINT (WINAPI *pNtUserMapVirtualKeyEx)( UINT code, UINT type, HKL layout );
LRESULT (WINAPI *pNtUserMessageCall)( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam,
@@ -284,6 +286,7 @@ struct unix_funcs
BOOL (WINAPI *pNtUserSetWindowPos)( HWND hwnd, HWND after, INT x, INT y, INT cx, INT cy, UINT flags );
int (WINAPI *pNtUserSetWindowRgn)( HWND hwnd, HRGN hrgn, BOOL redraw );
WORD (WINAPI *pNtUserSetWindowWord)( HWND hwnd, INT offset, WORD newval );
+ BOOL (WINAPI *pNtUserShowCaret)( HWND hwnd );
INT (WINAPI *pNtUserShowCursor)( BOOL show );
BOOL (WINAPI *pNtUserShowWindow)( HWND hwnd, INT cmd );
BOOL (WINAPI *pNtUserShowWindowAsync)( HWND hwnd, INT cmd );
@@ -354,6 +357,7 @@ extern LRESULT call_hooks( INT id, INT code, WPARAM wparam, LPARAM lparam, BOOL
extern BOOL unhook_windows_hook( INT id, HOOKPROC proc ) DECLSPEC_HIDDEN;
/* input.c */
+extern BOOL destroy_caret(void) DECLSPEC_HIDDEN;
extern LONG global_key_state_counter DECLSPEC_HIDDEN;
extern HWND get_active_window(void) DECLSPEC_HIDDEN;
extern HWND get_capture(void) DECLSPEC_HIDDEN;
@@ -362,7 +366,10 @@ extern HWND get_focus(void) DECLSPEC_HIDDEN;
extern DWORD get_input_state(void) DECLSPEC_HIDDEN;
extern BOOL WINAPI release_capture(void) DECLSPEC_HIDDEN;
extern BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret ) DECLSPEC_HIDDEN;
+extern BOOL set_caret_blink_time( unsigned int time ) DECLSPEC_HIDDEN;
+extern BOOL set_caret_pos( int x, int y ) DECLSPEC_HIDDEN;
extern BOOL set_foreground_window( HWND hwnd, BOOL mouse ) DECLSPEC_HIDDEN;
+extern void toggle_caret( HWND hwnd ) DECLSPEC_HIDDEN;
extern void update_mouse_tracking_info( HWND hwnd ) DECLSPEC_HIDDEN;
/* menu.c */
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c
index a20c2886bc1..e206881e596 100644
--- a/dlls/win32u/window.c
+++ b/dlls/win32u/window.c
@@ -3307,13 +3307,10 @@ BOOL set_window_pos( WINDOWPOS *winpos, int parent_x, int parent_y )
&new_window_rect, &new_client_rect, valid_rects ))
goto done;
- if (user_callbacks)
- {
- if (winpos->flags & SWP_HIDEWINDOW)
- user_callbacks->pHideCaret( winpos->hwnd );
- else if (winpos->flags & SWP_SHOWWINDOW)
- user_callbacks->pShowCaret( winpos->hwnd );
- }
+ if (winpos->flags & SWP_HIDEWINDOW)
+ NtUserHideCaret( winpos->hwnd );
+ else if (winpos->flags & SWP_SHOWWINDOW)
+ NtUserShowCaret( winpos->hwnd );
if (!(winpos->flags & (SWP_NOACTIVATE|SWP_HIDEWINDOW)))
{
@@ -4407,7 +4404,7 @@ static void send_destroy_message( HWND hwnd )
info.cbSize = sizeof(info);
if (NtUserGetGUIThreadInfo( GetCurrentThreadId(), &info ))
{
- if (hwnd == info.hwndCaret && user_callbacks) user_callbacks->pDestroyCaret();
+ if (hwnd == info.hwndCaret) destroy_caret();
if (hwnd == info.hwndActive) activate_other_window( hwnd );
}
diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c
index d38501f5c4c..05107352dfa 100644
--- a/dlls/win32u/wrappers.c
+++ b/dlls/win32u/wrappers.c
@@ -780,6 +780,12 @@ INT WINAPI NtUserCountClipboardFormats(void)
return unix_funcs->pNtUserCountClipboardFormats();
}
+BOOL WINAPI NtUserCreateCaret( HWND hwnd, HBITMAP bitmap, int width, int height )
+{
+ if (!unix_funcs) return 0;
+ return unix_funcs->pNtUserCreateCaret( hwnd, bitmap, width, height );
+}
+
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,
@@ -957,6 +963,12 @@ INT WINAPI NtUserGetUpdateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
return unix_funcs->pNtUserGetUpdateRgn( hwnd, hrgn, erase );
}
+BOOL WINAPI NtUserHideCaret( HWND hwnd )
+{
+ if (!unix_funcs) return FALSE;
+ return unix_funcs->pNtUserHideCaret( hwnd );
+}
+
BOOL WINAPI NtUserMoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy, BOOL repaint )
{
if (!unix_funcs) return 0;
@@ -1197,6 +1209,12 @@ WORD WINAPI NtUserSetWindowWord( HWND hwnd, INT offset, WORD newval )
return unix_funcs->pNtUserSetWindowWord( hwnd, offset, newval );
}
+BOOL WINAPI NtUserShowCaret( HWND hwnd )
+{
+ if (!unix_funcs) return FALSE;
+ return unix_funcs->pNtUserShowCaret( hwnd );
+}
+
INT WINAPI NtUserShowCursor( BOOL show )
{
if (!unix_funcs) return 0;
diff --git a/dlls/wow64win/syscall.h b/dlls/wow64win/syscall.h
index 124506bdb05..1bfc210eab0 100644
--- a/dlls/wow64win/syscall.h
+++ b/dlls/wow64win/syscall.h
@@ -106,6 +106,8 @@
SYSCALL_ENTRY( NtUserFindWindowEx ) \
SYSCALL_ENTRY( NtUserGetAncestor ) \
SYSCALL_ENTRY( NtUserGetAtomName ) \
+ SYSCALL_ENTRY( NtUserGetCaretBlinkTime ) \
+ SYSCALL_ENTRY( NtUserGetCaretPos ) \
SYSCALL_ENTRY( NtUserGetClassName ) \
SYSCALL_ENTRY( NtUserGetClipboardFormatName ) \
SYSCALL_ENTRY( NtUserGetClipboardOwner ) \
diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c
index 3e8004b005c..554a6634f0e 100644
--- a/dlls/wow64win/user.c
+++ b/dlls/wow64win/user.c
@@ -608,6 +608,18 @@ NTSTATUS WINAPI wow64_NtUserKillTimer( UINT *args )
return NtUserKillTimer( hwnd, id );
}
+NTSTATUS WINAPI wow64_NtUserGetCaretBlinkTime( UINT *args )
+{
+ return NtUserGetCaretBlinkTime();
+}
+
+NTSTATUS WINAPI wow64_NtUserGetCaretPos( UINT *args )
+{
+ POINT *pt = get_ptr( &args );
+
+ return NtUserGetCaretPos( pt );
+}
+
NTSTATUS WINAPI wow64_NtUserCopyAcceleratorTable( UINT *args )
{
HACCEL src = get_handle( &args );
diff --git a/include/ntuser.h b/include/ntuser.h
index 47bc7cbeb41..f49c9bc7723 100644
--- a/include/ntuser.h
+++ b/include/ntuser.h
@@ -463,6 +463,7 @@ BOOL WINAPI NtUserCloseWindowStation( HWINSTA handle );
INT WINAPI NtUserCopyAcceleratorTable( HACCEL src, ACCEL *dst, INT count );
INT WINAPI NtUserCountClipboardFormats(void);
HACCEL WINAPI NtUserCreateAcceleratorTable( ACCEL *table, INT count );
+BOOL WINAPI NtUserCreateCaret( HWND hwnd, HBITMAP bitmap, int width, int height );
HDESK WINAPI NtUserCreateDesktopEx( OBJECT_ATTRIBUTES *attr, UNICODE_STRING *device,
DEVMODEW *devmode, DWORD flags, ACCESS_MASK access,
ULONG heap_size );
@@ -500,6 +501,8 @@ BOOL WINAPI NtUserFlashWindowEx( FLASHWINFO *info );
HWND WINAPI NtUserGetAncestor( HWND hwnd, UINT type );
SHORT WINAPI NtUserGetAsyncKeyState( INT key );
ULONG WINAPI NtUserGetAtomName( ATOM atom, UNICODE_STRING *name );
+UINT WINAPI NtUserGetCaretBlinkTime(void);
+BOOL WINAPI NtUserGetCaretPos( POINT *point );
ATOM WINAPI NtUserGetClassInfoEx( HINSTANCE instance, UNICODE_STRING *name, WNDCLASSEXW *wc,
struct client_menu_name *menu_name, BOOL ansi );
INT WINAPI NtUserGetClassName( HWND hwnd, BOOL real, UNICODE_STRING *name );
@@ -547,6 +550,7 @@ INT WINAPI NtUserGetUpdateRgn( HWND hwnd, HRGN hrgn, BOOL erase );
BOOL WINAPI NtUserGetUpdatedClipboardFormats( UINT *formats, UINT size, UINT *out_size );
BOOL WINAPI NtUserGetUpdateRect( HWND hwnd, RECT *rect, BOOL erase );
int WINAPI NtUserGetWindowRgnEx( HWND hwnd, HRGN hrgn, UINT unk );
+BOOL WINAPI NtUserHideCaret( HWND hwnd );
NTSTATUS WINAPI NtUserInitializeClientPfnArrays( const struct user_client_procs *client_procsA,
const struct user_client_procs *client_procsW,
const void *client_workers, HINSTANCE user_module );
@@ -616,6 +620,7 @@ HHOOK WINAPI NtUserSetWindowsHookEx( HINSTANCE inst, UNICODE_STRING *module, D
HWINEVENTHOOK WINAPI NtUserSetWinEventHook( DWORD event_min, DWORD event_max, HMODULE inst,
UNICODE_STRING *module, WINEVENTPROC proc,
DWORD pid, DWORD tid, DWORD flags );
+BOOL WINAPI NtUserShowCaret( HWND hwnd );
INT WINAPI NtUserShowCursor( BOOL show );
BOOL WINAPI NtUserShowWindow( HWND hwnd, INT cmd );
BOOL WINAPI NtUserShowWindowAsync( HWND hwnd, INT cmd );
@@ -643,6 +648,7 @@ HWND WINAPI NtUserWindowFromPoint( LONG x, LONG y );
/* NtUserCallNoParam codes, not compatible with Windows */
enum
{
+ NtUserCallNoParam_DestroyCaret,
NtUserCallNoParam_GetDesktopWindow,
NtUserCallNoParam_GetInputState,
NtUserCallNoParam_ReleaseCapture,
@@ -651,6 +657,11 @@ enum
NtUserThreadDetach,
};
+static inline BOOL NtUserDestroyCaret(void)
+{
+ return NtUserCallNoParam( NtUserCallNoParam_DestroyCaret );
+}
+
static inline HWND NtUserGetDesktopWindow(void)
{
return UlongToHandle( NtUserCallNoParam( NtUserCallNoParam_GetDesktopWindow ));
@@ -688,6 +699,7 @@ enum
NtUserCallOneParam_IsWindowRectFullScreen,
NtUserCallOneParam_MessageBeep,
NtUserCallOneParam_RealizePalette,
+ NtUserCallOneParam_SetCaretBlinkTime,
/* temporary exports */
NtUserCallHooks,
NtUserGetDeskPattern,
@@ -754,6 +766,11 @@ static inline RECT NtUserGetPrimaryMonitorRect(void)
return primary;
}
+static inline BOOL NtUserSetCaretBlinkTime( unsigned int time )
+{
+ return NtUserCallOneParam( time, NtUserCallOneParam_SetCaretBlinkTime );
+}
+
static inline COLORREF NtUserGetSysColor( INT index )
{
return NtUserCallOneParam( index, NtUserCallOneParam_GetSysColor );
@@ -804,6 +821,7 @@ enum
NtUserCallTwoParam_GetSystemMetricsForDpi,
NtUserCallTwoParam_MonitorFromRect,
NtUserCallTwoParam_ReplyMessage,
+ NtUserCallTwoParam_SetCaretPos,
NtUserCallTwoParam_SetIconParam,
NtUserCallTwoParam_UnhookWindowsHook,
/* temporary exports */
@@ -839,6 +857,11 @@ static inline BOOL NtUserReplyMessage( LRESULT result, MSG *msg )
return NtUserCallTwoParam( result, (UINT_PTR)msg, NtUserCallTwoParam_ReplyMessage );
}
+static inline BOOL NtUserSetCaretPos( int x, int y )
+{
+ return NtUserCallTwoParam( x, y, NtUserCallTwoParam_SetCaretPos );
+}
+
static inline UINT_PTR NtUserSetIconParam( HICON icon, ULONG_PTR param )
{
return NtUserCallTwoParam( HandleToUlong(icon), param, NtUserCallTwoParam_SetIconParam );
--
2.25.1
1
0
26 Apr '22
From: Zebediah Figura <zfigura(a)codeweavers.com>
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/user32/caret.c | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/dlls/user32/caret.c b/dlls/user32/caret.c
index bdc7780bf8f..7b21e03c764 100644
--- a/dlls/user32/caret.c
+++ b/dlls/user32/caret.c
@@ -96,6 +96,24 @@ void CDECL toggle_caret( HWND hwnd )
}
+static unsigned int get_caret_registry_timeout(void)
+{
+ unsigned int ret = 500;
+ WCHAR value[11];
+ DWORD size;
+ HKEY key;
+
+ if (RegOpenKeyExW( HKEY_CURRENT_USER, L"Control Panel\\Desktop", 0, KEY_READ, &key ))
+ return ret;
+
+ size = sizeof(value);
+ if (!RegQueryValueExW( key, L"CursorBlinkRate", NULL, NULL, (BYTE *)value, &size ))
+ ret = wcstoul( value, NULL, 10 );
+ RegCloseKey( key );
+ return ret;
+}
+
+
/*****************************************************************
* CreateCaret (USER32.@)
*/
@@ -185,7 +203,8 @@ BOOL WINAPI CreateCaret( HWND hwnd, HBITMAP bitmap, INT width, INT height )
if (Caret.hBmp) DeleteObject( Caret.hBmp );
Caret.hBmp = hBmp;
- Caret.timeout = GetProfileIntA( "windows", "CursorBlinkRate", 500 );
+
+ Caret.timeout = get_caret_registry_timeout();
return TRUE;
}
--
2.25.1
1
0
[PATCH v2 03/12] win32u: Move NtUserTrackMouseEvent() implementation from user32.
by Huw Davies 26 Apr '22
by Huw Davies 26 Apr '22
26 Apr '22
From: Zebediah Figura <zfigura(a)codeweavers.com>
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/user32/input.c | 254 -----------------------------------
dlls/user32/scroll.c | 8 +-
dlls/user32/user32.spec | 2 +-
dlls/user32/user_main.c | 1 -
dlls/user32/user_private.h | 1 -
dlls/win32u/gdiobj.c | 1 +
dlls/win32u/input.c | 218 ++++++++++++++++++++++++++++++
dlls/win32u/message.c | 3 +-
dlls/win32u/ntuser_private.h | 1 -
dlls/win32u/win32u.spec | 2 +-
dlls/win32u/win32u_private.h | 2 +
dlls/win32u/wrappers.c | 6 +
include/ntuser.h | 1 +
13 files changed, 235 insertions(+), 265 deletions(-)
diff --git a/dlls/user32/input.c b/dlls/user32/input.c
index 4ef33ab2838..dcb46df22b5 100644
--- a/dlls/user32/input.c
+++ b/dlls/user32/input.c
@@ -49,32 +49,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(win);
WINE_DECLARE_DEBUG_CHANNEL(keyboard);
-/***********************************************************************
- * get_key_state
- */
-static WORD get_key_state(void)
-{
- WORD ret = 0;
-
- if (GetSystemMetrics( SM_SWAPBUTTON ))
- {
- if (NtUserGetAsyncKeyState(VK_RBUTTON) & 0x80) ret |= MK_LBUTTON;
- if (NtUserGetAsyncKeyState(VK_LBUTTON) & 0x80) ret |= MK_RBUTTON;
- }
- else
- {
- if (NtUserGetAsyncKeyState(VK_LBUTTON) & 0x80) ret |= MK_LBUTTON;
- if (NtUserGetAsyncKeyState(VK_RBUTTON) & 0x80) ret |= MK_RBUTTON;
- }
- if (NtUserGetAsyncKeyState(VK_MBUTTON) & 0x80) ret |= MK_MBUTTON;
- if (NtUserGetAsyncKeyState(VK_SHIFT) & 0x80) ret |= MK_SHIFT;
- if (NtUserGetAsyncKeyState(VK_CONTROL) & 0x80) ret |= MK_CONTROL;
- if (NtUserGetAsyncKeyState(VK_XBUTTON1) & 0x80) ret |= MK_XBUTTON1;
- if (NtUserGetAsyncKeyState(VK_XBUTTON2) & 0x80) ret |= MK_XBUTTON2;
- return ret;
-}
-
-
/***********************************************************************
* get_locale_kbd_layout
*/
@@ -520,234 +494,6 @@ BOOL WINAPI UnloadKeyboardLayout( HKL layout )
return FALSE;
}
-typedef struct __TRACKINGLIST {
- TRACKMOUSEEVENT tme;
- POINT pos; /* center of hover rectangle */
-} _TRACKINGLIST;
-
-/* FIXME: move tracking stuff into a per thread data */
-static _TRACKINGLIST tracking_info;
-
-static void check_mouse_leave(HWND hwnd, int hittest)
-{
- if (tracking_info.tme.hwndTrack != hwnd)
- {
- if (tracking_info.tme.dwFlags & TME_NONCLIENT)
- PostMessageW(tracking_info.tme.hwndTrack, WM_NCMOUSELEAVE, 0, 0);
- else
- PostMessageW(tracking_info.tme.hwndTrack, WM_MOUSELEAVE, 0, 0);
-
- /* remove the TME_LEAVE flag */
- tracking_info.tme.dwFlags &= ~TME_LEAVE;
- }
- else
- {
- if (hittest == HTCLIENT)
- {
- if (tracking_info.tme.dwFlags & TME_NONCLIENT)
- {
- PostMessageW(tracking_info.tme.hwndTrack, WM_NCMOUSELEAVE, 0, 0);
- /* remove the TME_LEAVE flag */
- tracking_info.tme.dwFlags &= ~TME_LEAVE;
- }
- }
- else
- {
- if (!(tracking_info.tme.dwFlags & TME_NONCLIENT))
- {
- PostMessageW(tracking_info.tme.hwndTrack, WM_MOUSELEAVE, 0, 0);
- /* remove the TME_LEAVE flag */
- tracking_info.tme.dwFlags &= ~TME_LEAVE;
- }
- }
- }
-}
-
-void CDECL update_mouse_tracking_info( HWND hwnd )
-{
- POINT pos;
- INT hoverwidth = 0, hoverheight = 0, hittest;
-
- TRACE( "hwnd %p\n", hwnd );
-
- GetCursorPos(&pos);
- hwnd = WINPOS_WindowFromPoint(hwnd, pos, &hittest);
-
- TRACE("point %s hwnd %p hittest %d\n", wine_dbgstr_point(&pos), hwnd, hittest);
-
- SystemParametersInfoW(SPI_GETMOUSEHOVERWIDTH, 0, &hoverwidth, 0);
- SystemParametersInfoW(SPI_GETMOUSEHOVERHEIGHT, 0, &hoverheight, 0);
-
- TRACE("tracked pos %s, current pos %s, hover width %d, hover height %d\n",
- wine_dbgstr_point(&tracking_info.pos), wine_dbgstr_point(&pos),
- hoverwidth, hoverheight);
-
- /* see if this tracking event is looking for TME_LEAVE and that the */
- /* mouse has left the window */
- if (tracking_info.tme.dwFlags & TME_LEAVE)
- {
- check_mouse_leave(hwnd, hittest);
- }
-
- if (tracking_info.tme.hwndTrack != hwnd)
- {
- /* mouse is gone, stop tracking mouse hover */
- tracking_info.tme.dwFlags &= ~TME_HOVER;
- }
-
- /* see if we are tracking hovering for this hwnd */
- if (tracking_info.tme.dwFlags & TME_HOVER)
- {
- /* has the cursor moved outside the rectangle centered around pos? */
- if ((abs(pos.x - tracking_info.pos.x) > (hoverwidth / 2)) ||
- (abs(pos.y - tracking_info.pos.y) > (hoverheight / 2)))
- {
- /* record this new position as the current position */
- tracking_info.pos = pos;
- }
- else
- {
- if (hittest == HTCLIENT)
- {
- ScreenToClient(hwnd, &pos);
- TRACE("client cursor pos %s\n", wine_dbgstr_point(&pos));
-
- PostMessageW(tracking_info.tme.hwndTrack, WM_MOUSEHOVER,
- get_key_state(), MAKELPARAM( pos.x, pos.y ));
- }
- else
- {
- if (tracking_info.tme.dwFlags & TME_NONCLIENT)
- PostMessageW(tracking_info.tme.hwndTrack, WM_NCMOUSEHOVER,
- hittest, MAKELPARAM( pos.x, pos.y ));
- }
-
- /* stop tracking mouse hover */
- tracking_info.tme.dwFlags &= ~TME_HOVER;
- }
- }
-
- /* stop the timer if the tracking list is empty */
- if (!(tracking_info.tme.dwFlags & (TME_HOVER | TME_LEAVE)))
- {
- KillSystemTimer( tracking_info.tme.hwndTrack, SYSTEM_TIMER_TRACK_MOUSE );
- tracking_info.tme.hwndTrack = 0;
- tracking_info.tme.dwFlags = 0;
- tracking_info.tme.dwHoverTime = 0;
- }
-}
-
-
-/***********************************************************************
- * TrackMouseEvent [USER32]
- *
- * Requests notification of mouse events
- *
- * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
- * to the hwnd specified in the ptme structure. After the event message
- * is posted to the hwnd, the entry in the queue is removed.
- *
- * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
- * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
- * immediately and the TME_LEAVE flag being ignored.
- *
- * PARAMS
- * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
- *
- * RETURNS
- * Success: non-zero
- * Failure: zero
- *
- */
-
-BOOL WINAPI
-TrackMouseEvent (TRACKMOUSEEVENT *ptme)
-{
- HWND hwnd;
- POINT pos;
- DWORD hover_time;
- INT hittest;
-
- TRACE("%x, %x, %p, %u\n", ptme->cbSize, ptme->dwFlags, ptme->hwndTrack, ptme->dwHoverTime);
-
- if (ptme->cbSize != sizeof(TRACKMOUSEEVENT)) {
- WARN("wrong TRACKMOUSEEVENT size from app\n");
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
-
- /* fill the TRACKMOUSEEVENT struct with the current tracking for the given hwnd */
- if (ptme->dwFlags & TME_QUERY )
- {
- *ptme = tracking_info.tme;
- /* set cbSize in the case it's not initialized yet */
- ptme->cbSize = sizeof(TRACKMOUSEEVENT);
-
- return TRUE; /* return here, TME_QUERY is retrieving information */
- }
-
- if (!IsWindow(ptme->hwndTrack))
- {
- SetLastError(ERROR_INVALID_WINDOW_HANDLE);
- return FALSE;
- }
-
- hover_time = (ptme->dwFlags & TME_HOVER) ? ptme->dwHoverTime : HOVER_DEFAULT;
-
- /* if HOVER_DEFAULT was specified replace this with the system's current value.
- * TME_LEAVE doesn't need to specify hover time so use default */
- if (hover_time == HOVER_DEFAULT || hover_time == 0)
- SystemParametersInfoW(SPI_GETMOUSEHOVERTIME, 0, &hover_time, 0);
-
- GetCursorPos(&pos);
- hwnd = WINPOS_WindowFromPoint(ptme->hwndTrack, pos, &hittest);
- TRACE("point %s hwnd %p hittest %d\n", wine_dbgstr_point(&pos), hwnd, hittest);
-
- if (ptme->dwFlags & ~(TME_CANCEL | TME_HOVER | TME_LEAVE | TME_NONCLIENT))
- FIXME("Unknown flag(s) %08x\n", ptme->dwFlags & ~(TME_CANCEL | TME_HOVER | TME_LEAVE | TME_NONCLIENT));
-
- if (ptme->dwFlags & TME_CANCEL)
- {
- if (tracking_info.tme.hwndTrack == ptme->hwndTrack)
- {
- tracking_info.tme.dwFlags &= ~(ptme->dwFlags & ~TME_CANCEL);
-
- /* if we aren't tracking on hover or leave remove this entry */
- if (!(tracking_info.tme.dwFlags & (TME_HOVER | TME_LEAVE)))
- {
- KillSystemTimer( tracking_info.tme.hwndTrack, SYSTEM_TIMER_TRACK_MOUSE );
- tracking_info.tme.hwndTrack = 0;
- tracking_info.tme.dwFlags = 0;
- tracking_info.tme.dwHoverTime = 0;
- }
- }
- } else {
- /* In our implementation it's possible that another window will receive a
- * WM_MOUSEMOVE and call TrackMouseEvent before TrackMouseEventProc is
- * called. In such a situation post the WM_MOUSELEAVE now */
- if (tracking_info.tme.dwFlags & TME_LEAVE && tracking_info.tme.hwndTrack != NULL)
- check_mouse_leave(hwnd, hittest);
-
- KillSystemTimer( tracking_info.tme.hwndTrack, SYSTEM_TIMER_TRACK_MOUSE );
- tracking_info.tme.hwndTrack = 0;
- tracking_info.tme.dwFlags = 0;
- tracking_info.tme.dwHoverTime = 0;
-
- if (ptme->hwndTrack == hwnd)
- {
- /* Adding new mouse event to the tracking list */
- tracking_info.tme = *ptme;
- tracking_info.tme.dwHoverTime = hover_time;
-
- /* Initialize HoverInfo variables even if not hover tracking */
- tracking_info.pos = pos;
-
- NtUserSetSystemTimer( tracking_info.tme.hwndTrack, SYSTEM_TIMER_TRACK_MOUSE, hover_time );
- }
- }
-
- return TRUE;
-}
/***********************************************************************
* EnableMouseInPointer (USER32.@)
diff --git a/dlls/user32/scroll.c b/dlls/user32/scroll.c
index 45980b75b2c..8f085364dab 100644
--- a/dlls/user32/scroll.c
+++ b/dlls/user32/scroll.c
@@ -864,12 +864,12 @@ void SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt )
tme.cbSize = sizeof(tme);
tme.dwFlags = TME_QUERY;
- TrackMouseEvent( &tme );
+ NtUserTrackMouseEvent( &tme );
if (!(tme.dwFlags & TME_LEAVE) || tme.hwndTrack != hwnd)
{
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = hwnd;
- TrackMouseEvent( &tme );
+ NtUserTrackMouseEvent( &tme );
}
break;
@@ -883,12 +883,12 @@ void SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt )
tme.cbSize = sizeof(tme);
tme.dwFlags = TME_QUERY;
- TrackMouseEvent( &tme );
+ NtUserTrackMouseEvent( &tme );
if (((tme.dwFlags & (TME_NONCLIENT | TME_LEAVE)) != (TME_NONCLIENT | TME_LEAVE)) || tme.hwndTrack != hwnd)
{
tme.dwFlags = TME_NONCLIENT | TME_LEAVE;
tme.hwndTrack = hwnd;
- TrackMouseEvent( &tme );
+ NtUserTrackMouseEvent( &tme );
}
break;
diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec
index ec078cc7609..6f86fccdfbd 100644
--- a/dlls/user32/user32.spec
+++ b/dlls/user32/user32.spec
@@ -762,7 +762,7 @@
@ stdcall ToAsciiEx(long long ptr ptr long long)
@ stdcall ToUnicode(long long ptr ptr long long)
@ stdcall ToUnicodeEx(long long ptr ptr long long long) NtUserToUnicodeEx
-@ stdcall TrackMouseEvent(ptr)
+@ stdcall TrackMouseEvent(ptr) NtUserTrackMouseEvent
@ stdcall TrackPopupMenu(long long long long long long ptr)
@ stdcall TrackPopupMenuEx(long long long long long ptr)
@ stdcall TranslateAccelerator(long long ptr) TranslateAcceleratorA
diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c
index 85e22525d80..d529e49ba3a 100644
--- a/dlls/user32/user_main.c
+++ b/dlls/user32/user_main.c
@@ -179,7 +179,6 @@ static const struct user_callbacks user_funcs =
SCROLL_SetStandardScrollPainted,
toggle_caret,
unpack_dde_message,
- update_mouse_tracking_info,
register_imm,
unregister_imm,
};
diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h
index b01c5b8bfda..8fa8af00326 100644
--- a/dlls/user32/user_private.h
+++ b/dlls/user32/user_private.h
@@ -102,7 +102,6 @@ extern void SYSPARAMS_Init(void) DECLSPEC_HIDDEN;
extern void USER_CheckNotLock(void) DECLSPEC_HIDDEN;
extern BOOL USER_IsExitingThread( DWORD tid ) DECLSPEC_HIDDEN;
extern void CDECL toggle_caret( HWND hwnd ) DECLSPEC_HIDDEN;
-extern void CDECL update_mouse_tracking_info( HWND hwnd ) DECLSPEC_HIDDEN;
typedef LRESULT (*winproc_callback_t)( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
LRESULT *result, void *arg );
diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c
index 044ae8232e3..0f82d446269 100644
--- a/dlls/win32u/gdiobj.c
+++ b/dlls/win32u/gdiobj.c
@@ -1220,6 +1220,7 @@ static struct unix_funcs unix_funcs =
NtUserSystemParametersInfo,
NtUserSystemParametersInfoForDpi,
NtUserToUnicodeEx,
+ NtUserTrackMouseEvent,
NtUserTranslateMessage,
NtUserUnregisterClass,
NtUserUnregisterHotKey,
diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c
index dd28170b1f0..c9d14ed746f 100644
--- a/dlls/win32u/input.c
+++ b/dlls/win32u/input.c
@@ -1171,6 +1171,224 @@ int WINAPI NtUserGetMouseMovePointsEx( UINT size, MOUSEMOVEPOINT *ptin, MOUSEMOV
return copied;
}
+static WORD get_key_state(void)
+{
+ WORD ret = 0;
+
+ if (get_system_metrics( SM_SWAPBUTTON ))
+ {
+ if (NtUserGetAsyncKeyState(VK_RBUTTON) & 0x80) ret |= MK_LBUTTON;
+ if (NtUserGetAsyncKeyState(VK_LBUTTON) & 0x80) ret |= MK_RBUTTON;
+ }
+ else
+ {
+ if (NtUserGetAsyncKeyState(VK_LBUTTON) & 0x80) ret |= MK_LBUTTON;
+ if (NtUserGetAsyncKeyState(VK_RBUTTON) & 0x80) ret |= MK_RBUTTON;
+ }
+ if (NtUserGetAsyncKeyState(VK_MBUTTON) & 0x80) ret |= MK_MBUTTON;
+ if (NtUserGetAsyncKeyState(VK_SHIFT) & 0x80) ret |= MK_SHIFT;
+ if (NtUserGetAsyncKeyState(VK_CONTROL) & 0x80) ret |= MK_CONTROL;
+ if (NtUserGetAsyncKeyState(VK_XBUTTON1) & 0x80) ret |= MK_XBUTTON1;
+ if (NtUserGetAsyncKeyState(VK_XBUTTON2) & 0x80) ret |= MK_XBUTTON2;
+ return ret;
+}
+
+struct tracking_list
+{
+ TRACKMOUSEEVENT info;
+ POINT pos; /* center of hover rectangle */
+};
+
+/* FIXME: move tracking stuff into per-thread data */
+static struct tracking_list tracking_info;
+
+static void check_mouse_leave( HWND hwnd, int hittest )
+{
+ if (tracking_info.info.hwndTrack != hwnd)
+ {
+ if (tracking_info.info.dwFlags & TME_NONCLIENT)
+ NtUserPostMessage( tracking_info.info.hwndTrack, WM_NCMOUSELEAVE, 0, 0 );
+ else
+ NtUserPostMessage( tracking_info.info.hwndTrack, WM_MOUSELEAVE, 0, 0 );
+
+ tracking_info.info.dwFlags &= ~TME_LEAVE;
+ }
+ else
+ {
+ if (hittest == HTCLIENT)
+ {
+ if (tracking_info.info.dwFlags & TME_NONCLIENT)
+ {
+ NtUserPostMessage( tracking_info.info.hwndTrack, WM_NCMOUSELEAVE, 0, 0 );
+ tracking_info.info.dwFlags &= ~TME_LEAVE;
+ }
+ }
+ else
+ {
+ if (!(tracking_info.info.dwFlags & TME_NONCLIENT))
+ {
+ NtUserPostMessage( tracking_info.info.hwndTrack, WM_MOUSELEAVE, 0, 0 );
+ tracking_info.info.dwFlags &= ~TME_LEAVE;
+ }
+ }
+ }
+}
+
+void update_mouse_tracking_info( HWND hwnd )
+{
+ int hover_width = 0, hover_height = 0, hittest;
+ POINT pos;
+
+ TRACE( "hwnd %p\n", hwnd );
+
+ get_cursor_pos( &pos );
+ hwnd = window_from_point( hwnd, pos, &hittest );
+
+ TRACE( "point %s hwnd %p hittest %d\n", wine_dbgstr_point(&pos), hwnd, hittest );
+
+ NtUserSystemParametersInfo( SPI_GETMOUSEHOVERWIDTH, 0, &hover_width, 0 );
+ NtUserSystemParametersInfo( SPI_GETMOUSEHOVERHEIGHT, 0, &hover_height, 0 );
+
+ TRACE( "tracked pos %s, current pos %s, hover width %d, hover height %d\n",
+ wine_dbgstr_point(&tracking_info.pos), wine_dbgstr_point(&pos),
+ hover_width, hover_height );
+
+ if (tracking_info.info.dwFlags & TME_LEAVE)
+ check_mouse_leave( hwnd, hittest );
+
+ if (tracking_info.info.hwndTrack != hwnd)
+ tracking_info.info.dwFlags &= ~TME_HOVER;
+
+ if (tracking_info.info.dwFlags & TME_HOVER)
+ {
+ /* has the cursor moved outside the rectangle centered around pos? */
+ if ((abs( pos.x - tracking_info.pos.x ) > (hover_width / 2)) ||
+ (abs( pos.y - tracking_info.pos.y ) > (hover_height / 2)))
+ {
+ tracking_info.pos = pos;
+ }
+ else
+ {
+ if (hittest == HTCLIENT)
+ {
+ screen_to_client(hwnd, &pos);
+ TRACE( "client cursor pos %s\n", wine_dbgstr_point(&pos) );
+
+ NtUserPostMessage( tracking_info.info.hwndTrack, WM_MOUSEHOVER,
+ get_key_state(), MAKELPARAM( pos.x, pos.y ) );
+ }
+ else
+ {
+ if (tracking_info.info.dwFlags & TME_NONCLIENT)
+ NtUserPostMessage( tracking_info.info.hwndTrack, WM_NCMOUSEHOVER,
+ hittest, MAKELPARAM( pos.x, pos.y ) );
+ }
+
+ /* stop tracking mouse hover */
+ tracking_info.info.dwFlags &= ~TME_HOVER;
+ }
+ }
+
+ /* stop the timer if the tracking list is empty */
+ if (!(tracking_info.info.dwFlags & (TME_HOVER | TME_LEAVE)))
+ {
+ kill_system_timer( tracking_info.info.hwndTrack, SYSTEM_TIMER_TRACK_MOUSE );
+ tracking_info.info.hwndTrack = 0;
+ tracking_info.info.dwFlags = 0;
+ tracking_info.info.dwHoverTime = 0;
+ }
+}
+
+/***********************************************************************
+ * NtUserTrackMouseEvent (win32u.@)
+ */
+BOOL WINAPI NtUserTrackMouseEvent( TRACKMOUSEEVENT *info )
+{
+ DWORD hover_time;
+ int hittest;
+ HWND hwnd;
+ POINT pos;
+
+ TRACE( "size %u, flags %#x, hwnd %p, time %u\n",
+ info->cbSize, info->dwFlags, info->hwndTrack, info->dwHoverTime );
+
+ if (info->cbSize != sizeof(TRACKMOUSEEVENT))
+ {
+ WARN( "wrong size %u\n", info->cbSize );
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return FALSE;
+ }
+
+ if (info->dwFlags & TME_QUERY)
+ {
+ *info = tracking_info.info;
+ info->cbSize = sizeof(TRACKMOUSEEVENT);
+ return TRUE;
+ }
+
+ if (!is_window( info->hwndTrack ))
+ {
+ SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+ return FALSE;
+ }
+
+ hover_time = (info->dwFlags & TME_HOVER) ? info->dwHoverTime : HOVER_DEFAULT;
+
+ if (hover_time == HOVER_DEFAULT || hover_time == 0)
+ NtUserSystemParametersInfo( SPI_GETMOUSEHOVERTIME, 0, &hover_time, 0 );
+
+ get_cursor_pos( &pos );
+ hwnd = window_from_point( info->hwndTrack, pos, &hittest );
+ TRACE( "point %s hwnd %p hittest %d\n", wine_dbgstr_point(&pos), hwnd, hittest );
+
+ if (info->dwFlags & ~(TME_CANCEL | TME_HOVER | TME_LEAVE | TME_NONCLIENT))
+ FIXME( "ignoring flags %#x\n", info->dwFlags & ~(TME_CANCEL | TME_HOVER | TME_LEAVE | TME_NONCLIENT) );
+
+ if (info->dwFlags & TME_CANCEL)
+ {
+ if (tracking_info.info.hwndTrack == info->hwndTrack)
+ {
+ tracking_info.info.dwFlags &= ~(info->dwFlags & ~TME_CANCEL);
+
+ /* if we aren't tracking on hover or leave remove this entry */
+ if (!(tracking_info.info.dwFlags & (TME_HOVER | TME_LEAVE)))
+ {
+ kill_system_timer( tracking_info.info.hwndTrack, SYSTEM_TIMER_TRACK_MOUSE );
+ tracking_info.info.hwndTrack = 0;
+ tracking_info.info.dwFlags = 0;
+ tracking_info.info.dwHoverTime = 0;
+ }
+ }
+ }
+ else
+ {
+ /* In our implementation, it's possible that another window will receive
+ * WM_MOUSEMOVE and call TrackMouseEvent before TrackMouseEventProc is
+ * called. In such a situation, post the WM_MOUSELEAVE now. */
+ if ((tracking_info.info.dwFlags & TME_LEAVE) && tracking_info.info.hwndTrack != NULL)
+ check_mouse_leave(hwnd, hittest);
+
+ kill_system_timer( tracking_info.info.hwndTrack, SYSTEM_TIMER_TRACK_MOUSE );
+ tracking_info.info.hwndTrack = 0;
+ tracking_info.info.dwFlags = 0;
+ tracking_info.info.dwHoverTime = 0;
+
+ if (info->hwndTrack == hwnd)
+ {
+ /* Adding new mouse event to the tracking list */
+ tracking_info.info = *info;
+ tracking_info.info.dwHoverTime = hover_time;
+
+ /* Initialize HoverInfo variables even if not hover tracking */
+ tracking_info.pos = pos;
+
+ NtUserSetSystemTimer( tracking_info.info.hwndTrack, SYSTEM_TIMER_TRACK_MOUSE, hover_time );
+ }
+ }
+
+ return TRUE;
+}
+
/**********************************************************************
* set_capture_window
*/
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c
index 02644e71929..8ad4a0271b3 100644
--- a/dlls/win32u/message.c
+++ b/dlls/win32u/message.c
@@ -2479,8 +2479,7 @@ LRESULT dispatch_message( const MSG *msg, BOOL ansi )
return 0;
case SYSTEM_TIMER_TRACK_MOUSE:
- if (!user_callbacks) break;
- user_callbacks->update_mouse_tracking_info( msg->hwnd );
+ update_mouse_tracking_info( msg->hwnd );
return 0;
}
}
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h
index 604817708c7..cad038dbff6 100644
--- a/dlls/win32u/ntuser_private.h
+++ b/dlls/win32u/ntuser_private.h
@@ -54,7 +54,6 @@ struct user_callbacks
void (CDECL *toggle_caret)( HWND hwnd );
BOOL (CDECL *unpack_dde_message)( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lparam,
void **buffer, size_t size );
- void (CDECL *update_mouse_tracking_info)( HWND hwnd );
BOOL (WINAPI *register_imm)( HWND hwnd );
void (WINAPI *unregister_imm)( HWND hwnd );
};
diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec
index 492ff411c1d..e94ec7f4a39 100644
--- a/dlls/win32u/win32u.spec
+++ b/dlls/win32u/win32u.spec
@@ -1277,7 +1277,7 @@
@ stdcall -syscall NtUserThunkedMenuInfo(long ptr)
@ stub NtUserThunkedMenuItemInfo
@ stdcall NtUserToUnicodeEx(long long ptr ptr long long long)
-@ stub NtUserTrackMouseEvent
+@ stdcall NtUserTrackMouseEvent(ptr)
@ stub NtUserTrackPopupMenuEx
@ stub NtUserTransformPoint
@ stub NtUserTransformRect
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h
index 128ff9d7281..122921431fc 100644
--- a/dlls/win32u/win32u_private.h
+++ b/dlls/win32u/win32u_private.h
@@ -292,6 +292,7 @@ struct unix_funcs
UINT winini, UINT dpi );
INT (WINAPI *pNtUserToUnicodeEx)( UINT virt, UINT scan, const BYTE *state,
WCHAR *str, int size, UINT flags, HKL layout );
+ BOOL (WINAPI *pNtUserTrackMouseEvent)( TRACKMOUSEEVENT *info );
BOOL (WINAPI *pNtUserTranslateMessage)( const MSG *msg, UINT flags );
BOOL (WINAPI *pNtUserUnregisterClass)( UNICODE_STRING *name, HINSTANCE instance,
struct client_menu_name *client_menu_name );
@@ -362,6 +363,7 @@ extern DWORD get_input_state(void) DECLSPEC_HIDDEN;
extern BOOL WINAPI release_capture(void) DECLSPEC_HIDDEN;
extern BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret ) DECLSPEC_HIDDEN;
extern BOOL set_foreground_window( HWND hwnd, BOOL mouse ) DECLSPEC_HIDDEN;
+extern void update_mouse_tracking_info( HWND hwnd ) DECLSPEC_HIDDEN;
/* menu.c */
extern HMENU create_menu( BOOL is_popup ) DECLSPEC_HIDDEN;
diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c
index d22e03ac3fb..d38501f5c4c 100644
--- a/dlls/win32u/wrappers.c
+++ b/dlls/win32u/wrappers.c
@@ -1234,6 +1234,12 @@ INT WINAPI NtUserToUnicodeEx( UINT virt, UINT scan, const BYTE *state,
return unix_funcs->pNtUserToUnicodeEx( virt, scan, state, str, size, flags, layout );
}
+BOOL WINAPI NtUserTrackMouseEvent( TRACKMOUSEEVENT *info )
+{
+ if (!unix_funcs) return FALSE;
+ return unix_funcs->pNtUserTrackMouseEvent( info );
+}
+
BOOL WINAPI NtUserTranslateMessage( const MSG *msg, UINT flags )
{
if (!unix_funcs) return 0;
diff --git a/include/ntuser.h b/include/ntuser.h
index 0a833d467b3..47bc7cbeb41 100644
--- a/include/ntuser.h
+++ b/include/ntuser.h
@@ -624,6 +624,7 @@ BOOL WINAPI NtUserSystemParametersInfoForDpi( UINT action, UINT val, PVOID pt
BOOL WINAPI NtUserThunkedMenuInfo( HMENU menu, const MENUINFO *info );
INT WINAPI NtUserToUnicodeEx( UINT virt, UINT scan, const BYTE *state,
WCHAR *str, int size, UINT flags, HKL layout );
+BOOL WINAPI NtUserTrackMouseEvent( TRACKMOUSEEVENT *info );
INT WINAPI NtUserTranslateAccelerator( HWND hwnd, HACCEL accel, MSG *msg );
BOOL WINAPI NtUserTranslateMessage( const MSG *msg, UINT flags );
BOOL WINAPI NtUserUnhookWinEvent( HWINEVENTHOOK hEventHook );
--
2.25.1
1
0