[PATCH v2 2/2] comctl32/listview: Don't send LVN_ENDLABELEDIT twice under some circumstances
Fabian Maurer
dark.shadow4 at web.de
Sat Aug 25 16:43:28 CDT 2018
Signed-off-by: Fabian Maurer <dark.shadow4 at web.de>
---
v2:
-Use message tests
-Check if were already processing LVN_ENDLABELEDIT on a
different position (fixes new tests)
---
dlls/comctl32/listview.c | 9 +++-
dlls/comctl32/tests/listview.c | 76 ++++++++++++++++++++++++++++++++++
2 files changed, 84 insertions(+), 1 deletion(-)
diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
index fa0d18e5d6..bb1aa52e90 100644
--- a/dlls/comctl32/listview.c
+++ b/dlls/comctl32/listview.c
@@ -212,6 +212,7 @@ typedef struct tagDELAYED_ITEM_EDIT
} DELAYED_ITEM_EDIT;
#define FLAG_NOTIFY_CHANGE (0x1) /* Whether we can send change notification messages */
+#define FLAG_NOTIFY_ENDLABELEDIT (0x2) /* Whether we can send LVN_ENDLABELEDIT */
typedef struct tagLISTVIEW_INFO
{
@@ -5916,9 +5917,14 @@ static BOOL LISTVIEW_EndEditLabelT(LISTVIEW_INFO *infoPtr, BOOL storeText, BOOL
dispInfo.item.pszText = same ? NULL : pszText;
dispInfo.item.cchTextMax = textlenT(dispInfo.item.pszText, isW);
+ /* Sending LVN_ENDLABELEDITW might trigger EN_KILLFOCUS which would call this function again */
+ infoPtr->notify_mask &= ~FLAG_NOTIFY_ENDLABELEDIT;
+
/* Do we need to update the Item Text */
res = notify_dispinfoT(infoPtr, LVN_ENDLABELEDITW, &dispInfo, isW);
+ infoPtr->notify_mask |= FLAG_NOTIFY_ENDLABELEDIT;
+
infoPtr->nEditLabelItem = -1;
infoPtr->hwndEdit = 0;
@@ -11908,7 +11914,8 @@ static LRESULT LISTVIEW_Command(LISTVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lP
}
case EN_KILLFOCUS:
{
- LISTVIEW_CancelEditLabel(infoPtr);
+ if (infoPtr->notify_mask & FLAG_NOTIFY_ENDLABELEDIT)
+ LISTVIEW_CancelEditLabel(infoPtr);
break;
}
diff --git a/dlls/comctl32/tests/listview.c b/dlls/comctl32/tests/listview.c
index c118f02026..ff46b472f3 100644
--- a/dlls/comctl32/tests/listview.c
+++ b/dlls/comctl32/tests/listview.c
@@ -75,6 +75,8 @@ static BOOL g_disp_A_to_W;
static NMLVDISPINFOA g_editbox_disp_info;
/* when this is set focus will be tested on LVN_DELETEITEM */
static BOOL g_focus_test_LVN_DELETEITEM;
+/* Whether to send WM_KILLFOCUS to the edit control during LVN_ENDLABELEDIT */
+static BOOL do_LVN_ENDLABELEDIT_killfocus = FALSE;
static HWND subclass_editbox(HWND hwndListview);
@@ -445,6 +447,25 @@ static const struct message parent_list_cd_seq[] = {
{ 0 }
};
+static const struct message listview_LVN_ENDLABELEDITA[] = {
+ { WM_NOTIFY, sent|id, 0, 0, LVN_ENDLABELEDITA },
+ { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING},
+ { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
+ { WM_NOTIFY, sent|id|optional, 0, 0, NM_CUSTOMDRAW }, /* XP */
+ { WM_NOTIFY, sent|id, 0, 0, NM_SETFOCUS },
+ { 0 }
+};
+
+static const struct message listview_kill_focus_during_LVN_ENDLABELEDITA[] = {
+ { WM_NOTIFY, sent|id, 0, 0, LVN_ENDLABELEDITA },
+ { WM_COMMAND, sent|id|optional, 0, 0, EN_KILLFOCUS }, /* todo: not sent by wine yet */
+ { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
+ { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
+ { WM_NOTIFY, sent|id|optional, 0, 0, NM_CUSTOMDRAW }, /* XP */
+ { WM_NOTIFY, sent|id, 0, 0, NM_SETFOCUS },
+ { 0 }
+};
+
static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static LONG defwndproc_counter = 0;
@@ -457,6 +478,7 @@ static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LP
msg.wParam = wParam;
msg.lParam = lParam;
if (message == WM_NOTIFY && lParam) msg.id = ((NMHDR*)lParam)->code;
+ if (message == WM_COMMAND) msg.id = HIWORD(wParam);
/* log system messages, except for painting */
if (message < WM_USER &&
@@ -510,6 +532,9 @@ static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LP
ok(IsWindow(edit), "expected valid edit control handle\n");
ok((GetWindowLongA(edit, GWL_STYLE) & ES_MULTILINE) == 0, "edit is multiline\n");
+ if (do_LVN_ENDLABELEDIT_killfocus)
+ SendMessageA(edit, WM_KILLFOCUS, 0, 0);
+
return TRUE;
}
case LVN_BEGINSCROLL:
@@ -6322,6 +6347,56 @@ static void test_LVSCW_AUTOSIZE(void)
DestroyWindow(hwnd);
}
+static void test_LVN_ENDLABELEDITW(void)
+{
+ HWND hwnd, hwndedit;
+ LVITEMW item = {0};
+ WCHAR text[] = {'l','a','l','a',0};
+ DWORD ret;
+
+ hwnd = create_listview_control(LVS_REPORT | LVS_EDITLABELS);
+
+ insert_column(hwnd, 0);
+
+ item.mask = LVIF_TEXT;
+ item.pszText = text;
+ ListView_InsertItemW(hwnd, &item);
+
+ /* Test normal editing */
+ SetFocus(hwnd);
+ hwndedit = (HWND)SendMessageW(hwnd, LVM_EDITLABELW, 0, 0);
+
+ ret = SendMessageA(hwndedit, WM_SETTEXT, 0, (LPARAM)"test");
+ expect(TRUE, ret);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ ret = SendMessageA(hwndedit, WM_KEYDOWN, VK_RETURN, 0);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, listview_LVN_ENDLABELEDITA,
+ "kill focus during LVN_ENDLABELEDITA", FALSE);
+
+ /* Test editing with kill focus */
+ SetFocus(hwnd);
+ hwndedit = (HWND)SendMessageW(hwnd, LVM_EDITLABELW, 0, 0);
+
+ ret = SendMessageA(hwndedit, WM_SETTEXT, 0, (LPARAM)"test2");
+ expect(TRUE, ret);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ do_LVN_ENDLABELEDIT_killfocus = TRUE;
+ ret = SendMessageA(hwndedit, WM_KEYDOWN, VK_RETURN, 0);
+ do_LVN_ENDLABELEDIT_killfocus = FALSE;
+
+ ok_sequence(sequences, PARENT_SEQ_INDEX, listview_kill_focus_during_LVN_ENDLABELEDITA,
+ "kill focus during LVN_ENDLABELEDITA", FALSE);
+ ok(GetFocus() == hwnd, "Expected combobox to be focused\n");
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ DestroyWindow(hwnd);
+}
+
START_TEST(listview)
{
ULONG_PTR ctx_cookie;
@@ -6425,6 +6500,7 @@ START_TEST(listview)
test_oneclickactivate();
test_state_image();
test_LVSCW_AUTOSIZE();
+ test_LVN_ENDLABELEDITW();
unload_v6_module(ctx_cookie, hCtx);
--
2.18.0
More information about the wine-devel
mailing list