Adding PSN_QUERYINITIALFOCUS helped fix some focus issues with the property sheet in bug 54862. Previously the listview in the tab control did not get focus from the start when it should have.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=54862
-- v9: comctl32: Add handling for PSN_QUERYINITIALFOCUS in prop.c.
From: Jacob Czekalla jczekalla@codeweavers.com
--- dlls/comctl32/tests/propsheet.c | 109 ++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+)
diff --git a/dlls/comctl32/tests/propsheet.c b/dlls/comctl32/tests/propsheet.c index 9bd1c08bd6a..7552fe05741 100644 --- a/dlls/comctl32/tests/propsheet.c +++ b/dlls/comctl32/tests/propsheet.c @@ -1388,6 +1388,114 @@ static void test_invalid_hpropsheetpage(void) DestroyWindow(hdlg); }
+int query_initial_focus = 0; +int edit_test_ID = IDC_PS_EDIT2; +LRESULT CALLBACK TestDlgProc(HWND hdlg, UINT uMessage, WPARAM wParam, LPARAM lParam) +{ + LPNMHDR lpnmhdr; + + switch (uMessage) + { + case WM_NOTIFY: + lpnmhdr = (NMHDR *)lParam; + switch (lpnmhdr->code) + { + case PSN_QUERYINITIALFOCUS: + { + query_initial_focus++; + if(edit_test_ID == IDC_PS_EDIT1) + return 0; + SetWindowLongPtrA(hdlg, DWLP_MSGRESULT, (LONG_PTR)GetDlgItem(hdlg, IDC_PS_EDIT2)); + return 1; + } + } + } + + return FALSE; +} + +static void test_QueryInitialFocus(void) +{ + PROPSHEETPAGEA psp[2]; + PROPSHEETHEADERA psh; + HWND tab_ctrl = NULL; + HWND hp; + RECT rc; + LPARAM lp; + + memset(&psh, 0, sizeof(psh)); + memset(psp, 0, sizeof(psp)); + psp[0].dwSize = sizeof(PROPSHEETPAGEA); + psp[0].dwFlags = PSP_USETITLE; + psp[0].hInstance = GetModuleHandleA(NULL);; + psp[0].pszTemplate = (const char *)MAKEINTRESOURCE(IDD_PROP_PAGE_EDIT); + psp[0].pszIcon = NULL; + psp[0].pfnDlgProc = (DLGPROC) TestDlgProc; + psp[0].pszTitle = "Page1"; + psp[0].lParam = 0; + + psp[1].dwSize = sizeof(PROPSHEETPAGEA); + psp[1].dwFlags = PSP_USETITLE; + psp[1].hInstance = GetModuleHandleA(NULL); + psp[1].pszTemplate = (const char*)MAKEINTRESOURCE(IDD_PROP_PAGE_EDIT); + psp[1].pszIcon = NULL; + psp[1].pfnDlgProc = (DLGPROC) TestDlgProc; + psp[1].pszTitle = "Page2"; + psp[1].lParam = 0; + + psh.dwSize = sizeof(PROPSHEETHEADERA); + psh.dwFlags = PSH_PROPSHEETPAGE | PSH_MODELESS; + psh.hwndParent = GetDesktopWindow(); + psh.pszCaption = "Modeless Property Sheet"; + psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGEA); + psh.ppsp = (LPCPROPSHEETPAGEA)&psp; + + hp = (HWND)pPropertySheetA(&psh); + tab_ctrl = (HWND)SendMessageA(hp, PSM_GETTABCONTROL, 0, 0); + + /* Test PSN_QUERYINITIALFOCUS gets sent on start */ + todo_wine ok(query_initial_focus == 1, "Did not recieve PSN_QUERYINITIALFOCUS on start.\n"); + todo_wine ok(GetDlgCtrlID(GetFocus()) == IDC_PS_EDIT2, "Focus not set to IDC_PS_EDIT2.\n"); + + /* Test changing of tabs */ + edit_test_ID = IDC_PS_EDIT1; + query_initial_focus = 0; + todo_wine ok(tab_ctrl != 0, "Could not test changing tabs. No tab control found.\n"); + SendMessageA(tab_ctrl, TCM_GETITEMRECT, 1, (LPARAM) &rc); + lp = MAKELPARAM(rc.left + ((rc.right - rc.left) / 2), rc.top + ((rc.bottom - rc.top) / 2)); + SendMessageA(tab_ctrl, WM_LBUTTONDOWN, MK_LBUTTON, lp); + todo_wine ok(query_initial_focus == 1, "Did not recieve PSN_QUERYINITIALFOCUS from changing tabs.\n"); + todo_wine ok(GetDlgCtrlID(GetFocus()) == IDC_PS_EDIT1, "Focus not set to IDC_PS_EDIT1.\n"); + + /* Test Apply Button */ + edit_test_ID = IDC_PS_EDIT2; + query_initial_focus = 0; + SendMessageA(hp, PSM_PRESSBUTTON, PSBTN_APPLYNOW, 0); + todo_wine ok(query_initial_focus == 1, "Did not recieve PSN_QUERYINITIALFOCUS from apply button.\n"); + todo_wine ok(GetDlgCtrlID(GetFocus()) == IDC_PS_EDIT2, "Focus not set to IDC_PS_EDIT2.\n"); + + DestroyWindow(hp); + + edit_test_ID = IDC_PS_EDIT1; + query_initial_focus = 0; + + psh.dwFlags = PSH_PROPSHEETPAGE | PSH_USECALLBACK | PSH_WIZARD | PSH_MODELESS; + hp = (HWND)pPropertySheetA(&psh); + + /* Test PSN_QUERYINITIALFOCUS gets sent on start */ + todo_wine ok(query_initial_focus == 1, "Did not recieve PSN_QUERYINITIALFOCUS on start.\n"); + todo_wine ok(GetDlgCtrlID(GetFocus()) == IDC_PS_EDIT1, "Focus not set to IDC_PS_EDIT1.\n"); + + /* Test Next Button */ + edit_test_ID = IDC_PS_EDIT2; + query_initial_focus = 0; + SendMessageA(hp, PSM_PRESSBUTTON, PSBTN_NEXT, 0); + todo_wine ok(query_initial_focus == 1, "Did not recieve PSN_QUERYINITIALFOCUS from next button.\n"); + todo_wine ok(GetDlgCtrlID(GetFocus()) == IDC_PS_EDIT2, "Focus not set to IDC_PS_EDIT2.\n"); + + DestroyWindow(hp); +} + static void init_comctl32_functions(void) { HMODULE hComCtl32 = LoadLibraryA("comctl32.dll"); @@ -1442,6 +1550,7 @@ START_TEST(propsheet) test_CreatePropertySheetPage(); test_page_dialog_texture(); test_invalid_hpropsheetpage(); + test_QueryInitialFocus();
if (!load_v6_module(&ctx_cookie, &ctx)) return;
From: Jacob Czekalla jczekalla@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=54862 --- dlls/comctl32/propsheet.c | 35 ++++++++++++++++++++++++++------- dlls/comctl32/tests/propsheet.c | 22 ++++++++++----------- 2 files changed, 39 insertions(+), 18 deletions(-)
diff --git a/dlls/comctl32/propsheet.c b/dlls/comctl32/propsheet.c index b530a1a8094..73c4faef350 100644 --- a/dlls/comctl32/propsheet.c +++ b/dlls/comctl32/propsheet.c @@ -37,7 +37,6 @@ * o WM_CONTEXTMENU * - Notifications: * o PSN_GETOBJECT - * o PSN_QUERYINITIALFOCUS * o PSN_TRANSLATEACCELERATOR * - Styles: * o PSH_RTLREADING @@ -582,6 +581,30 @@ static void HPSP_draw_text(HPROPSHEETPAGE hpsp, HDC hdc, BOOL title, RECT *r, UI }
#define add_flag(a) if (dwFlags & a) {strcat(string, #a );strcat(string," ");} + +static void PROPSHEET_QueryInitialFocus(HWND hwndDlg, int index, PropSheetInfo* psInfo) +{ + PSHNOTIFY psn; + HWND focusable_item = NULL; + HWND initial_focus = NULL; + + focusable_item = GetNextDlgTabItem(psInfo->proppage[index].hwndPage, NULL, FALSE); + + if (!focusable_item) + return; + + psn.hdr.code = PSN_QUERYINITIALFOCUS; + psn.hdr.hwndFrom = hwndDlg; + psn.hdr.idFrom = 0; + psn.lParam = 0; + initial_focus = (HWND)SendMessageW(psInfo->proppage[index].hwndPage, WM_NOTIFY, 0, (LPARAM)&psn); + + if (initial_focus) + SetFocus(initial_focus); + else if (focusable_item) + SetFocus(focusable_item); +} + /****************************************************************************** * PROPSHEET_UnImplementedFlags * @@ -1655,7 +1678,6 @@ static BOOL PROPSHEET_ShowPage(HWND hwndDlg, int index, PropSheetInfo * psInfo) { HWND hwndTabCtrl; HWND hwndLineHeader; - HWND control;
TRACE("active_page %d, index %d\n", psInfo->active_page, index); if (index == psInfo->active_page) @@ -1674,10 +1696,6 @@ static BOOL PROPSHEET_ShowPage(HWND hwndDlg, int index, PropSheetInfo * psInfo) { PROPSHEET_SetTitleW(hwndDlg, psInfo->ppshheader.dwFlags, psInfo->proppage[index].pszText); - - control = GetNextDlgTabItem(psInfo->proppage[index].hwndPage, NULL, FALSE); - if(control != NULL) - SetFocus(control); }
if (psInfo->active_page != -1) @@ -1693,6 +1711,8 @@ static BOOL PROPSHEET_ShowPage(HWND hwndDlg, int index, PropSheetInfo * psInfo) psInfo->active_page = index; psInfo->activeValid = TRUE;
+ PROPSHEET_QueryInitialFocus(hwndDlg, index, psInfo); + if (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW) ) { hwndLineHeader = GetDlgItem(hwndDlg, IDC_SUNKEN_LINEHEADER); @@ -1891,6 +1911,7 @@ static BOOL PROPSHEET_Apply(HWND hwndDlg, LPARAM lParam) psn.lParam = 0; hwndPage = psInfo->proppage[psInfo->active_page].hwndPage; SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn); + PROPSHEET_QueryInitialFocus(hwndPage, psInfo->active_page, psInfo); }
return TRUE; @@ -3645,7 +3666,7 @@ PROPSHEET_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD) return FALSE;
- return TRUE; + return FALSE; }
case WM_PRINTCLIENT: diff --git a/dlls/comctl32/tests/propsheet.c b/dlls/comctl32/tests/propsheet.c index 7552fe05741..a8791ddddcb 100644 --- a/dlls/comctl32/tests/propsheet.c +++ b/dlls/comctl32/tests/propsheet.c @@ -1454,25 +1454,25 @@ static void test_QueryInitialFocus(void) tab_ctrl = (HWND)SendMessageA(hp, PSM_GETTABCONTROL, 0, 0);
/* Test PSN_QUERYINITIALFOCUS gets sent on start */ - todo_wine ok(query_initial_focus == 1, "Did not recieve PSN_QUERYINITIALFOCUS on start.\n"); - todo_wine ok(GetDlgCtrlID(GetFocus()) == IDC_PS_EDIT2, "Focus not set to IDC_PS_EDIT2.\n"); + ok(query_initial_focus == 1, "Did not recieve PSN_QUERYINITIALFOCUS on start.\n"); + ok(GetDlgCtrlID(GetFocus()) == IDC_PS_EDIT2, "Focus not set to IDC_PS_EDIT2.\n");
/* Test changing of tabs */ edit_test_ID = IDC_PS_EDIT1; query_initial_focus = 0; - todo_wine ok(tab_ctrl != 0, "Could not test changing tabs. No tab control found.\n"); + ok(tab_ctrl != 0, "Could not test changing tabs. No tab control found.\n"); SendMessageA(tab_ctrl, TCM_GETITEMRECT, 1, (LPARAM) &rc); lp = MAKELPARAM(rc.left + ((rc.right - rc.left) / 2), rc.top + ((rc.bottom - rc.top) / 2)); SendMessageA(tab_ctrl, WM_LBUTTONDOWN, MK_LBUTTON, lp); - todo_wine ok(query_initial_focus == 1, "Did not recieve PSN_QUERYINITIALFOCUS from changing tabs.\n"); - todo_wine ok(GetDlgCtrlID(GetFocus()) == IDC_PS_EDIT1, "Focus not set to IDC_PS_EDIT1.\n"); + ok(query_initial_focus == 1, "Did not recieve PSN_QUERYINITIALFOCUS from changing tabs.\n"); + ok(GetDlgCtrlID(GetFocus()) == IDC_PS_EDIT1, "Focus not set to IDC_PS_EDIT1.\n");
/* Test Apply Button */ edit_test_ID = IDC_PS_EDIT2; query_initial_focus = 0; SendMessageA(hp, PSM_PRESSBUTTON, PSBTN_APPLYNOW, 0); - todo_wine ok(query_initial_focus == 1, "Did not recieve PSN_QUERYINITIALFOCUS from apply button.\n"); - todo_wine ok(GetDlgCtrlID(GetFocus()) == IDC_PS_EDIT2, "Focus not set to IDC_PS_EDIT2.\n"); + ok(query_initial_focus == 1, "Did not recieve PSN_QUERYINITIALFOCUS from apply button.\n"); + ok(GetDlgCtrlID(GetFocus()) == IDC_PS_EDIT2, "Focus not set to IDC_PS_EDIT2.\n");
DestroyWindow(hp);
@@ -1483,15 +1483,15 @@ static void test_QueryInitialFocus(void) hp = (HWND)pPropertySheetA(&psh);
/* Test PSN_QUERYINITIALFOCUS gets sent on start */ - todo_wine ok(query_initial_focus == 1, "Did not recieve PSN_QUERYINITIALFOCUS on start.\n"); - todo_wine ok(GetDlgCtrlID(GetFocus()) == IDC_PS_EDIT1, "Focus not set to IDC_PS_EDIT1.\n"); + ok(query_initial_focus == 1, "Did not recieve PSN_QUERYINITIALFOCUS on start.\n"); + ok(GetDlgCtrlID(GetFocus()) == IDC_PS_EDIT1, "Focus not set to IDC_PS_EDIT1.\n");
/* Test Next Button */ edit_test_ID = IDC_PS_EDIT2; query_initial_focus = 0; SendMessageA(hp, PSM_PRESSBUTTON, PSBTN_NEXT, 0); - todo_wine ok(query_initial_focus == 1, "Did not recieve PSN_QUERYINITIALFOCUS from next button.\n"); - todo_wine ok(GetDlgCtrlID(GetFocus()) == IDC_PS_EDIT2, "Focus not set to IDC_PS_EDIT2.\n"); + ok(query_initial_focus == 1, "Did not recieve PSN_QUERYINITIALFOCUS from next button.\n"); + ok(GetDlgCtrlID(GetFocus()) == IDC_PS_EDIT2, "Focus not set to IDC_PS_EDIT2.\n");
DestroyWindow(hp); }
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=147486
Your paranoid android.
=== debian11b (64 bit WoW report) ===
user32: input.c:4305: Test succeeded inside todo block: button_down_hwnd_todo 1: got MSG_TEST_WIN hwnd 00000000012300EE, msg WM_LBUTTONDOWN, wparam 0x1, lparam 0x320032
Zhiyi Zhang (@zhiyi) commented about dlls/comctl32/tests/propsheet.c:
+int query_initial_focus = 0; +int edit_test_ID = IDC_PS_EDIT2; +LRESULT CALLBACK TestDlgProc(HWND hdlg, UINT uMessage, WPARAM wParam, LPARAM lParam) +{
- LPNMHDR lpnmhdr;
- switch (uMessage)
- {
- case WM_NOTIFY:
lpnmhdr = (NMHDR *)lParam;
switch (lpnmhdr->code)
{
case PSN_QUERYINITIALFOCUS:
{
query_initial_focus++;
if(edit_test_ID == IDC_PS_EDIT1)
Let's add a space after if.
Zhiyi Zhang (@zhiyi) commented about dlls/comctl32/propsheet.c:
}
#define add_flag(a) if (dwFlags & a) {strcat(string, #a );strcat(string," ");}
+static void PROPSHEET_QueryInitialFocus(HWND hwndDlg, int index, PropSheetInfo* psInfo)
The indent width should be 4 in this function.
Zhiyi Zhang (@zhiyi) commented about dlls/comctl32/propsheet.c:
}
#define add_flag(a) if (dwFlags & a) {strcat(string, #a );strcat(string," ");}
+static void PROPSHEET_QueryInitialFocus(HWND hwndDlg, int index, PropSheetInfo* psInfo) +{
- PSHNOTIFY psn;
- HWND focusable_item = NULL;
- HWND initial_focus = NULL;
- focusable_item = GetNextDlgTabItem(psInfo->proppage[index].hwndPage, NULL, FALSE);
Let's remove this empty line.
Zhiyi Zhang (@zhiyi) commented about dlls/comctl32/propsheet.c:
+{
- PSHNOTIFY psn;
- HWND focusable_item = NULL;
- HWND initial_focus = NULL;
- focusable_item = GetNextDlgTabItem(psInfo->proppage[index].hwndPage, NULL, FALSE);
- if (!focusable_item)
- return;
- psn.hdr.code = PSN_QUERYINITIALFOCUS;
- psn.hdr.hwndFrom = hwndDlg;
- psn.hdr.idFrom = 0;
- psn.lParam = 0;
- initial_focus = (HWND)SendMessageW(psInfo->proppage[index].hwndPage, WM_NOTIFY, 0, (LPARAM)&psn);
Same here.