Yak-shaving for https://gitlab.winehq.org/wine/wine/-/merge_requests/7618.
I added a test to show that DefWindowProc, specifically, sends this event.
The timing is slightly off compared to WM_CTLCOLOR* sometimes, but I think that's fine. There's no reason to expect accessibility tools, specifically, to be sensitive to that.
The spurious events with MDI children changing state may be less fine. The MDI code (in user32) uses DefWindowProc internally to change the window text. Somehow, Windows must accomplish this without sending the event, so presumably there's some backdoor or internal interface in win32u that allows for it. There's a possibility that a screen reader responds to the NAMECHANGE by speaking the window title (I have no idea if any screen reader actually does this), which could be annoying to a user. Still, given that I don't know whether it's a problem, and it's extra complexity that we may not even need, I thought it'd be better to send the MR first with that known issue and see what people think.
From: Esme Povirk esme@codeweavers.com
--- dlls/user32/tests/msg.c | 20 ++++++++++++++++++-- dlls/win32u/defwnd.c | 2 ++ 2 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index 2b0baae7cf3..1c456b0a8b7 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -3548,6 +3548,7 @@ static const struct message WmCreateMDIchildInvisibleMaxSeq4[] = { { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_STATECHANGED }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, + { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam|wine_only, 0, 0 }, /* in MDI frame */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, @@ -3849,6 +3850,7 @@ static const struct message WmMaximizeMDIchildInvisibleSeq[] = { { WM_MDIACTIVATE, sent|optional|defwinproc }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, + { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam|wine_only, 0, 0 }, /* in MDI frame */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, @@ -3966,6 +3968,7 @@ static const struct message WmMaximizeMDIchildVisibleSeq[] = { { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, + { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam|wine_only, 0, 0 }, /* in MDI frame */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, @@ -3982,6 +3985,7 @@ static const struct message WmRestoreMDIchildVisibleSeq[] = { { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, + { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam|wine_only, 0, 0 }, /* in MDI frame */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, @@ -4031,6 +4035,7 @@ static const struct message WmRestoreMDIchildInvisibleSeq[] = { { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, + { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam|wine_only, 0, 0 }, /* in MDI frame */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, @@ -6629,6 +6634,7 @@ static const struct message WmSetTextButtonSeq[] = { WM_SETTEXT, sent }, { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, { WM_CTLCOLORBTN, sent|parent }, + { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam|wine_only, 0, 0 }, { WM_CTLCOLORBTN, sent|parent }, { WM_COMMAND, sent|parent|optional }, { WM_DRAWITEM, sent|parent|optional }, @@ -6639,6 +6645,7 @@ static const struct message WmSetTextStaticSeq[] = { WM_SETTEXT, sent }, { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, { WM_CTLCOLORSTATIC, sent|parent }, + { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam|wine_only, 0, 0 }, { WM_CTLCOLORSTATIC, sent|parent }, { 0 } }; @@ -6646,7 +6653,7 @@ static const struct message WmSetTextGroupSeq[] = { { WM_SETTEXT, sent }, { WM_CTLCOLORSTATIC, sent|parent }, - { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, + { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam, 0, 0 }, { WM_CTLCOLORSTATIC, sent|parent|msg_todo }, /* FIXME: Missing in Wine */ { WM_CTLCOLORSTATIC, sent|parent|msg_todo }, /* FIXME: Missing in Wine */ { 0 } @@ -6654,7 +6661,7 @@ static const struct message WmSetTextGroupSeq[] = static const struct message WmSetTextInvisibleSeq[] = { { WM_SETTEXT, sent }, - { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, + { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 } }; static const struct message WmSetStyleButtonSeq[] = @@ -12019,6 +12026,11 @@ static const struct message WmMouseLLHookSeq[] = { { 0 } };
+static const struct message WmSetText[] = { + { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam, OBJID_WINDOW, CHILDID_SELF }, + { 0 } +}; + static void CALLBACK win_event_global_hook_proc(HWINEVENTHOOK hevent, DWORD event, HWND hwnd, @@ -12221,6 +12233,10 @@ static void test_winevents(void) NULL, NULL, 0); ok(!!hwnd, "Failed to create window, error %lu.\n", GetLastError());
+ flush_sequence(); + DefWindowProcA(hwnd, WM_SETTEXT, 0, (LPARAM)"test"); + ok_sequence(WmSetText, "SetText on a simple window", FALSE); + /****** start of global hook test *************/ hCBT_global_hook = SetWindowsHookExA(WH_CBT, cbt_global_hook_proc, GetModuleHandleA(0), 0); if (!hCBT_global_hook) diff --git a/dlls/win32u/defwnd.c b/dlls/win32u/defwnd.c index 34fb2cab1f5..106b7ab4cf7 100644 --- a/dlls/win32u/defwnd.c +++ b/dlls/win32u/defwnd.c @@ -2608,6 +2608,8 @@ LRESULT default_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam,
case WM_SETTEXT: result = set_window_text( hwnd, (void *)lparam, ansi ); + if (result) + NtUserNotifyWinEvent( EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_WINDOW, CHILDID_SELF ); if (result && (get_window_long( hwnd, GWL_STYLE ) & WS_CAPTION) == WS_CAPTION) handle_nc_paint( hwnd , (HRGN)1 ); /* repaint caption */ break;