From: Esme Povirk esme@codeweavers.com
--- dlls/comctl32/tab.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/dlls/comctl32/tab.c b/dlls/comctl32/tab.c index 8943d9dce7c..03187046d15 100644 --- a/dlls/comctl32/tab.c +++ b/dlls/comctl32/tab.c @@ -271,6 +271,10 @@ static inline LRESULT TAB_SetCurSel (TAB_INFO *infoPtr, INT iItem)
TAB_EnsureSelectionVisible(infoPtr); TAB_InvalidateTabArea(infoPtr); + if (iItem >= 0) + NotifyWinEvent(EVENT_OBJECT_SELECTION, infoPtr->hwnd, OBJID_CLIENT, iItem + 1); + else + NotifyWinEvent(EVENT_OBJECT_SELECTION, infoPtr->hwnd, OBJID_CLIENT, 0); }
return prevItem; @@ -286,6 +290,8 @@ static LRESULT TAB_SetCurFocus (TAB_INFO *infoPtr, INT iItem) infoPtr->iSelected = -1; TAB_SendSimpleNotify(infoPtr, TCN_SELCHANGE); TAB_InvalidateTabArea(infoPtr); + if (!(infoPtr->dwStyle & TCS_BUTTONS)) + NotifyWinEvent(EVENT_OBJECT_SELECTION, infoPtr->hwnd, OBJID_CLIENT, 0); } } else if (iItem < infoPtr->uNumItem) { @@ -306,6 +312,7 @@ static LRESULT TAB_SetCurFocus (TAB_INFO *infoPtr, INT iItem) InvalidateRect(infoPtr->hwnd, &r, FALSE);
TAB_SendSimpleNotify(infoPtr, TCN_FOCUSCHANGE); + NotifyWinEvent(EVENT_OBJECT_FOCUS, infoPtr->hwnd, OBJID_CLIENT, iItem + 1); } } else { INT oldFocus = infoPtr->uFocus; @@ -320,6 +327,7 @@ static LRESULT TAB_SetCurFocus (TAB_INFO *infoPtr, INT iItem) infoPtr->iSelected = iItem; TAB_EnsureSelectionVisible(infoPtr); TAB_InvalidateTabArea(infoPtr); + NotifyWinEvent(EVENT_OBJECT_SELECTION, infoPtr->hwnd, OBJID_CLIENT, iItem + 1); } } } @@ -2635,6 +2643,9 @@ TAB_InsertItemT (TAB_INFO *infoPtr, INT iItem, const TCITEMW *pti, BOOL bUnicode else InvalidateRect(infoPtr->hwnd, NULL, TRUE);
+ /* The last item is always the "new" MSAA object. */ + NotifyWinEvent(EVENT_OBJECT_CREATE, infoPtr->hwnd, OBJID_CLIENT, infoPtr->uNumItem); + TRACE("[%p]: added item %d %s\n", infoPtr->hwnd, iItem, debugstr_w(item->pszText));
@@ -2861,6 +2872,9 @@ static LRESULT TAB_DeleteItem (TAB_INFO *infoPtr, INT iItem) /* reposition and repaint tabs */ TAB_SetItemBounds(infoPtr);
+ /* The last item is always the destroyed MSAA object */ + NotifyWinEvent(EVENT_OBJECT_DESTROY, infoPtr->hwnd, OBJID_CLIENT, infoPtr->uNumItem + 1); + return TRUE; }
From: Esme Povirk esme@codeweavers.com
--- dlls/comctl32/tests/msg.h | 14 +++--- dlls/comctl32/tests/tab.c | 93 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 100 insertions(+), 7 deletions(-)
diff --git a/dlls/comctl32/tests/msg.h b/dlls/comctl32/tests/msg.h index f6877d6a2b1..22dbfa716dd 100644 --- a/dlls/comctl32/tests/msg.h +++ b/dlls/comctl32/tests/msg.h @@ -61,6 +61,8 @@ struct msg_sequence struct message *sequence; };
+static HWINEVENTHOOK hwineventhook; + static void add_message(struct msg_sequence **seq, int sequence_index, const struct message *msg) { @@ -120,7 +122,7 @@ static void dump_sequence( struct msg_sequence **seq, int sequence_index, if (expected->message == actual->message) { if ((expected->flags & defwinproc) != (actual->flags & defwinproc) && - (expected->flags & optional)) + ((expected->flags & optional) || ((expected->flags & winevent_hook) && !hwineventhook))) { /* don't match messages if their defwinproc status differs */ expected++; @@ -140,7 +142,8 @@ static void dump_sequence( struct msg_sequence **seq, int sequence_index, }
/* optional trailing messages */ - while (expected->message && expected->flags & optional) + while (expected->message && (expected->flags & optional || + ((expected->flags & winevent_hook) && !hwineventhook))) { trace_(file, line)( " %u: expected: msg %04x - actual: nothing\n", count, expected->message ); expected++; @@ -249,7 +252,7 @@ static void ok_sequence_(struct msg_sequence **seq, int sequence_index,
if (expected->flags & id) { - if (expected->id != actual->id && expected->flags & optional) + if (expected->id != actual->id && ((expected->flags & optional) || ((expected->flags & winevent_hook) && !hwineventhook))) { expected++; continue; @@ -321,7 +324,7 @@ static void ok_sequence_(struct msg_sequence **seq, int sequence_index, expected++; actual++; } - else if (expected->flags & optional) + else if ((expected->flags & optional) || ((expected->flags & winevent_hook) && !hwineventhook)) expected++; else if (todo) { @@ -345,7 +348,7 @@ static void ok_sequence_(struct msg_sequence **seq, int sequence_index, }
/* skip all optional trailing messages */ - while (expected->message && ((expected->flags & optional))) + while (expected->message && ((expected->flags & optional) || ((expected->flags & winevent_hook) && !hwineventhook))) expected++;
if (todo) @@ -393,3 +396,4 @@ static void init_msg_sequences(struct msg_sequence **seq, int n) for (i = 0; i < n; i++) seq[i] = heap_alloc_zero(sizeof(*seq[i])); } + diff --git a/dlls/comctl32/tests/tab.c b/dlls/comctl32/tests/tab.c index 67dea94b55c..ba21d02e86c 100644 --- a/dlls/comctl32/tests/tab.c +++ b/dlls/comctl32/tests/tab.c @@ -85,9 +85,65 @@ static HFONT hFont; static DRAWITEMSTRUCT g_drawitem; static HWND parent_wnd; static LRESULT tcn_selchanging_result; +static DWORD winevent_hook_thread_id;
static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
+static void CALLBACK msg_winevent_proc(HWINEVENTHOOK hevent, + DWORD event, + HWND hwnd, + LONG object_id, + LONG child_id, + DWORD thread_id, + DWORD event_time) +{ + struct message msg = {0}; + char class_name[256]; + + ok(thread_id == winevent_hook_thread_id, "we didn't ask for events from other threads\n"); + + /* ignore window and other system events */ + if (object_id != OBJID_CLIENT) return; + + /* ignore events not from a tab control */ + if (!GetClassNameA(hwnd, class_name, ARRAY_SIZE(class_name)) || + strcmp(class_name, WC_TABCONTROLA) != 0) + return; + + msg.message = event; + msg.flags = winevent_hook|wparam|lparam; + msg.wParam = object_id; + msg.lParam = child_id; + add_message(sequences, TAB_SEQ_INDEX, &msg); +} + +static void init_winevent_hook(void) { + HWINEVENTHOOK (WINAPI *pSetWinEventHook)(DWORD, DWORD, HMODULE, WINEVENTPROC, DWORD, DWORD, DWORD); + HMODULE user32 = GetModuleHandleA("user32.dll"); + pSetWinEventHook = (void*)GetProcAddress(user32, "SetWinEventHook"); + if (pSetWinEventHook) { + hwineventhook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, GetModuleHandleA(0), msg_winevent_proc, + 0, GetCurrentThreadId(), WINEVENT_INCONTEXT); + winevent_hook_thread_id = GetCurrentThreadId(); + } + if (!hwineventhook) + win_skip( "no win event hook support\n" ); +} + +static void uninit_winevent_hook(void) { + BOOL (WINAPI *pUnhookWinEvent)(HWINEVENTHOOK); + HMODULE user32 = GetModuleHandleA("user32.dll"); + + if (!hwineventhook) + return; + + pUnhookWinEvent = (void*)GetProcAddress(user32, "UnhookWinEvent"); + if (pUnhookWinEvent) { + pUnhookWinEvent(hwineventhook); + hwineventhook = 0; + } +} + static const struct message empty_sequence[] = { { 0 } }; @@ -99,10 +155,28 @@ static const struct message get_row_count_seq[] = {
static const struct message getset_cur_focus_seq[] = { { TCM_SETCURFOCUS, sent|lparam, 0 }, + { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 5 }, { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, { TCM_SETCURFOCUS, sent|lparam, 0 }, + { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, { TCM_SETCURSEL, sent|lparam, 0 }, + { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 2 }, + { TCM_SETCURFOCUS, sent|lparam, 0 }, + { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, + { 0 } +}; + +static const struct message getset_cur_focus_buttons_seq[] = { + { TCM_SETCURFOCUS, sent|lparam, 0 }, + { TCM_GETITEMCOUNT, sent|defwinproc|optional }, + { TCM_GETITEMCOUNT, sent|defwinproc|optional }, + { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 5 }, + { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, + { TCM_SETCURFOCUS, sent|lparam, 0 }, + { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, + { TCM_SETCURSEL, sent|lparam, 0 }, + { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 2 }, { TCM_SETCURFOCUS, sent|lparam, 0 }, { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, { 0 } @@ -110,11 +184,14 @@ static const struct message getset_cur_focus_seq[] = {
static const struct message getset_cur_sel_seq[] = { { TCM_SETCURSEL, sent|lparam, 0 }, + { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 5 }, { TCM_GETCURSEL, sent|wparam|lparam, 0, 0 }, { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, { TCM_SETCURSEL, sent|lparam, 0 }, + { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { TCM_GETCURSEL, sent|wparam|lparam, 0, 0 }, { TCM_SETCURSEL, sent|lparam, 0 }, + { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 2 }, { TCM_SETCURSEL, sent|lparam, 0 }, { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, { 0 } @@ -166,6 +243,7 @@ static const struct message insert_focus_seq[] = { { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 }, { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, { TCM_INSERTITEMA, sent|wparam, 1 }, + { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CLIENT, 1 }, { WM_NOTIFYFORMAT, sent|defwinproc|optional }, { WM_QUERYUISTATE, sent|defwinproc|optional }, { WM_PARENTNOTIFY, sent|defwinproc|optional }, @@ -175,11 +253,14 @@ static const struct message insert_focus_seq[] = { { WM_NOTIFYFORMAT, sent|defwinproc|optional }, { WM_QUERYUISTATE, sent|defwinproc|optional, }, { WM_PARENTNOTIFY, sent|defwinproc|optional }, + { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CLIENT, 2 }, { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 }, { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, { TCM_SETCURFOCUS, sent|wparam|lparam, -1, 0 }, + { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, { TCM_INSERTITEMA, sent|wparam, 3 }, + { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CLIENT, 3 }, { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, { 0 } }; @@ -188,11 +269,14 @@ static const struct message delete_focus_seq[] = { { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 }, { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, { TCM_DELETEITEM, sent|wparam|lparam, 1, 0 }, + { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, OBJID_CLIENT, 2 }, { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 }, { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, { TCM_SETCURFOCUS, sent|wparam|lparam, -1, 0 }, + { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, { TCM_DELETEITEM, sent|wparam|lparam, 0, 0 }, + { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, OBJID_CLIENT, 1 }, { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 }, { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, { 0 } @@ -347,7 +431,8 @@ static LRESULT WINAPI tab_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, message != WM_NCHITTEST && message != WM_GETTEXT && message != WM_GETICON && - message != WM_DEVICECHANGE) + message != WM_DEVICECHANGE && + message != WM_GETOBJECT) { msg.message = message; msg.flags = sent|wparam|lparam; @@ -667,7 +752,7 @@ static void test_curfocus(void) todo_wine ok(ret == nTabs - 1, "Unexpected focus index %d.\n", ret);
- ok_sequence(sequences, TAB_SEQ_INDEX, getset_cur_focus_seq, "TCS_BUTTONS: set focused tab sequence", FALSE); + ok_sequence(sequences, TAB_SEQ_INDEX, getset_cur_focus_buttons_seq, "TCS_BUTTONS: set focused tab sequence", FALSE); ok_sequence(sequences, PARENT_SEQ_INDEX, setfocus_parent_seq, "TCS_BUTTONS: set focused tab parent sequence", TRUE);
DestroyWindow(hTab); @@ -1501,6 +1586,8 @@ START_TEST(tab)
init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
+ init_winevent_hook(); + parent_wnd = createParentWindow(); ok(parent_wnd != NULL, "Failed to create parent window!\n");
@@ -1523,5 +1610,7 @@ START_TEST(tab) test_TCN_SELCHANGING(); test_TCM_GETROWCOUNT();
+ uninit_winevent_hook(); + DestroyWindow(parent_wnd); }
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=135407
Your paranoid android.
=== w10pro64 (64 bit report) ===
comctl32: propsheet.c:843: Test failed: property sheet with custom window proc: the msg 0x0046 was expected, but got msg 0x0210 instead
Nikolay Sivov (@nsivov) commented about dlls/comctl32/tab.c:
TAB_EnsureSelectionVisible(infoPtr); TAB_InvalidateTabArea(infoPtr);
if (iItem >= 0)
NotifyWinEvent(EVENT_OBJECT_SELECTION, infoPtr->hwnd, OBJID_CLIENT, iItem + 1);
else
NotifyWinEvent(EVENT_OBJECT_SELECTION, infoPtr->hwnd, OBJID_CLIENT, 0);
You could do that unconditionally, with "infoPtr->iSelected + 1" argument.
On Sat Jul 29 20:32:06 2023 +0000, Nikolay Sivov wrote:
You could do that unconditionally, with "infoPtr->iSelected + 1" argument.
I tried that first, but it fails the test because apparently iItem can be less than -1.
On Sat Jul 29 21:08:28 2023 +0000, Esme Povirk wrote:
I tried that first, but it fails the test because apparently iItem can be less than -1.
Oh never mind, I see what you mean now.
On Sat Jul 29 23:07:25 2023 +0000, **** wrote:
Marvin replied on the mailing list:
Hi, It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated. The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details: The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=135407 Your paranoid android. === w10pro64 (64 bit report) === comctl32: propsheet.c:843: Test failed: property sheet with custom window proc: the msg 0x0046 was expected, but got msg 0x0210 instead
I don't think it should be possible for my changes to msg.h to cause this.