comctl32/listview: Update focus index when new item data is already there.
This commit is contained in:
parent
bd72767eed
commit
dbd997c3c9
|
@ -4164,7 +4164,7 @@ static inline BOOL is_assignable_item(const LVITEMW *lpLVItem, LONG lStyle)
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* DESCRIPTION:
|
* DESCRIPTION:
|
||||||
* Helper for LISTVIEW_SetItemT *only*: sets item attributes.
|
* Helper for LISTVIEW_SetItemT and LISTVIEW_InsertItemT: sets item attributes.
|
||||||
*
|
*
|
||||||
* PARAMETER(S):
|
* PARAMETER(S):
|
||||||
* [I] infoPtr : valid pointer to the listview structure
|
* [I] infoPtr : valid pointer to the listview structure
|
||||||
|
@ -4256,6 +4256,15 @@ static BOOL set_main_item(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem, BOOL
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* When item is inserted we need to shift existing focus index if new item has lower index. */
|
||||||
|
if (isNew && (stateMask & ~infoPtr->uCallbackMask & LVIS_FOCUSED) &&
|
||||||
|
/* this means we won't hit a focus change path later */
|
||||||
|
((uChanged & LVIF_STATE) == 0 || (!(lpLVItem->state & LVIS_FOCUSED) && (infoPtr->nFocusedItem != lpLVItem->iItem))))
|
||||||
|
{
|
||||||
|
if (infoPtr->nFocusedItem != -1 && (lpLVItem->iItem <= infoPtr->nFocusedItem))
|
||||||
|
infoPtr->nFocusedItem++;
|
||||||
|
}
|
||||||
|
|
||||||
if (!uChanged) return TRUE;
|
if (!uChanged) return TRUE;
|
||||||
*bChanged = TRUE;
|
*bChanged = TRUE;
|
||||||
|
|
||||||
|
@ -4288,7 +4297,14 @@ static BOOL set_main_item(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem, BOOL
|
||||||
{
|
{
|
||||||
ranges_delitem(infoPtr->selectionRanges, lpLVItem->iItem);
|
ranges_delitem(infoPtr->selectionRanges, lpLVItem->iItem);
|
||||||
}
|
}
|
||||||
/* if we are asked to change focus, and we manage it, do it */
|
/* If we are asked to change focus, and we manage it, do it.
|
||||||
|
It's important to have all new item data stored at this point,
|
||||||
|
cause changing existing focus could result in redrawing operation,
|
||||||
|
which in turn could ask for disp data, application should see all data
|
||||||
|
for inserted item when processing LVN_GETDISPINFO.
|
||||||
|
|
||||||
|
The way this works application will see nested item change notifications -
|
||||||
|
changed item notifications interrupted by ones from item loosing focus. */
|
||||||
if (stateMask & ~infoPtr->uCallbackMask & LVIS_FOCUSED)
|
if (stateMask & ~infoPtr->uCallbackMask & LVIS_FOCUSED)
|
||||||
{
|
{
|
||||||
if (lpLVItem->state & LVIS_FOCUSED)
|
if (lpLVItem->state & LVIS_FOCUSED)
|
||||||
|
@ -7680,7 +7696,7 @@ static INT LISTVIEW_InsertItemT(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem,
|
||||||
LVITEMW item;
|
LVITEMW item;
|
||||||
HWND hwndSelf = infoPtr->hwndSelf;
|
HWND hwndSelf = infoPtr->hwndSelf;
|
||||||
|
|
||||||
TRACE("(lpLVItem=%s, isW=%d)\n", debuglvitem_t(lpLVItem, isW), isW);
|
TRACE("(item=%s, isW=%d)\n", debuglvitem_t(lpLVItem, isW), isW);
|
||||||
|
|
||||||
if (infoPtr->dwStyle & LVS_OWNERDATA) return infoPtr->nItemCount++;
|
if (infoPtr->dwStyle & LVS_OWNERDATA) return infoPtr->nItemCount++;
|
||||||
|
|
||||||
|
@ -7730,14 +7746,13 @@ static INT LISTVIEW_InsertItemT(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem,
|
||||||
else
|
else
|
||||||
nItem = min(lpLVItem->iItem, infoPtr->nItemCount);
|
nItem = min(lpLVItem->iItem, infoPtr->nItemCount);
|
||||||
|
|
||||||
TRACE(" inserting at %d, sorted=%d, count=%d, iItem=%d\n", nItem, is_sorted, infoPtr->nItemCount, lpLVItem->iItem);
|
TRACE("inserting at %d, sorted=%d, count=%d, iItem=%d\n", nItem, is_sorted, infoPtr->nItemCount, lpLVItem->iItem);
|
||||||
nItem = DPA_InsertPtr( infoPtr->hdpaItems, nItem, hdpaSubItems );
|
nItem = DPA_InsertPtr( infoPtr->hdpaItems, nItem, hdpaSubItems );
|
||||||
if (nItem == -1) goto fail;
|
if (nItem == -1) goto fail;
|
||||||
infoPtr->nItemCount++;
|
infoPtr->nItemCount++;
|
||||||
|
|
||||||
/* shift indices first so they don't get tangled */
|
/* shift indices first so they don't get tangled */
|
||||||
LISTVIEW_ShiftIndices(infoPtr, nItem, 1);
|
LISTVIEW_ShiftIndices(infoPtr, nItem, 1);
|
||||||
LISTVIEW_ShiftFocus(infoPtr, infoPtr->nFocusedItem, nItem, 1);
|
|
||||||
|
|
||||||
/* set the item attributes */
|
/* set the item attributes */
|
||||||
if (lpLVItem->mask & (LVIF_GROUPID|LVIF_COLUMNS))
|
if (lpLVItem->mask & (LVIF_GROUPID|LVIF_COLUMNS))
|
||||||
|
@ -7763,6 +7778,7 @@ static INT LISTVIEW_InsertItemT(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem,
|
||||||
item.state &= ~LVIS_STATEIMAGEMASK;
|
item.state &= ~LVIS_STATEIMAGEMASK;
|
||||||
item.state |= INDEXTOSTATEIMAGEMASK(1);
|
item.state |= INDEXTOSTATEIMAGEMASK(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!set_main_item(infoPtr, &item, TRUE, isW, &has_changed)) goto undo;
|
if (!set_main_item(infoPtr, &item, TRUE, isW, &has_changed)) goto undo;
|
||||||
|
|
||||||
/* make room for the position, if we are in the right mode */
|
/* make room for the position, if we are in the right mode */
|
||||||
|
@ -7778,7 +7794,7 @@ static INT LISTVIEW_InsertItemT(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send LVN_INSERTITEM notification */
|
/* send LVN_INSERTITEM notification */
|
||||||
ZeroMemory(&nmlv, sizeof(NMLISTVIEW));
|
memset(&nmlv, 0, sizeof(NMLISTVIEW));
|
||||||
nmlv.iItem = nItem;
|
nmlv.iItem = nItem;
|
||||||
nmlv.lParam = lpItem->lParam;
|
nmlv.lParam = lpItem->lParam;
|
||||||
notify_listview(infoPtr, LVN_INSERTITEM, &nmlv);
|
notify_listview(infoPtr, LVN_INSERTITEM, &nmlv);
|
||||||
|
|
|
@ -363,6 +363,15 @@ static const struct message listview_header_set_imagelist[] = {
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct message parent_insert_focused_seq[] = {
|
||||||
|
{ WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
|
||||||
|
{ WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
|
||||||
|
{ WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
|
||||||
|
{ WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
|
||||||
|
{ WM_NOTIFY, sent|id, 0, 0, LVN_INSERTITEM },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
static LONG defwndproc_counter = 0;
|
static LONG defwndproc_counter = 0;
|
||||||
|
@ -5434,6 +5443,58 @@ static void test_deleteitem(void)
|
||||||
DestroyWindow(hwnd);
|
DestroyWindow(hwnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_insertitem(void)
|
||||||
|
{
|
||||||
|
LVITEMA item;
|
||||||
|
UINT state;
|
||||||
|
HWND hwnd;
|
||||||
|
INT ret;
|
||||||
|
|
||||||
|
hwnd = create_listview_control(LVS_REPORT);
|
||||||
|
|
||||||
|
/* insert item 0 focused */
|
||||||
|
item.mask = LVIF_STATE;
|
||||||
|
item.state = LVIS_FOCUSED;
|
||||||
|
item.stateMask = LVIS_FOCUSED;
|
||||||
|
item.iItem = 0;
|
||||||
|
item.iSubItem = 0;
|
||||||
|
ret = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
|
||||||
|
ok(ret == 0, "got %d\n", ret);
|
||||||
|
|
||||||
|
state = SendMessageA(hwnd, LVM_GETITEMSTATE, 0, LVIS_FOCUSED);
|
||||||
|
ok(state == LVIS_FOCUSED, "got %x\n", state);
|
||||||
|
|
||||||
|
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
||||||
|
|
||||||
|
/* insert item 1, focus shift */
|
||||||
|
item.mask = LVIF_STATE;
|
||||||
|
item.state = LVIS_FOCUSED;
|
||||||
|
item.stateMask = LVIS_FOCUSED;
|
||||||
|
item.iItem = 1;
|
||||||
|
item.iSubItem = 0;
|
||||||
|
ret = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
|
||||||
|
ok(ret == 1, "got %d\n", ret);
|
||||||
|
|
||||||
|
ok_sequence(sequences, PARENT_SEQ_INDEX, parent_insert_focused_seq, "insert focused", TRUE);
|
||||||
|
|
||||||
|
state = SendMessageA(hwnd, LVM_GETITEMSTATE, 1, LVIS_FOCUSED);
|
||||||
|
ok(state == LVIS_FOCUSED, "got %x\n", state);
|
||||||
|
|
||||||
|
/* insert item 2, no focus shift */
|
||||||
|
item.mask = LVIF_STATE;
|
||||||
|
item.state = 0;
|
||||||
|
item.stateMask = LVIS_FOCUSED;
|
||||||
|
item.iItem = 2;
|
||||||
|
item.iSubItem = 0;
|
||||||
|
ret = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
|
||||||
|
ok(ret == 2, "got %d\n", ret);
|
||||||
|
|
||||||
|
state = SendMessageA(hwnd, LVM_GETITEMSTATE, 1, LVIS_FOCUSED);
|
||||||
|
ok(state == LVIS_FOCUSED, "got %x\n", state);
|
||||||
|
|
||||||
|
DestroyWindow(hwnd);
|
||||||
|
}
|
||||||
|
|
||||||
START_TEST(listview)
|
START_TEST(listview)
|
||||||
{
|
{
|
||||||
HMODULE hComctl32;
|
HMODULE hComctl32;
|
||||||
|
@ -5502,6 +5563,7 @@ START_TEST(listview)
|
||||||
test_LVM_SETITEMTEXT();
|
test_LVM_SETITEMTEXT();
|
||||||
test_imagelists();
|
test_imagelists();
|
||||||
test_deleteitem();
|
test_deleteitem();
|
||||||
|
test_insertitem();
|
||||||
|
|
||||||
if (!load_v6_module(&ctx_cookie, &hCtx))
|
if (!load_v6_module(&ctx_cookie, &hCtx))
|
||||||
{
|
{
|
||||||
|
@ -5533,6 +5595,7 @@ START_TEST(listview)
|
||||||
test_LVS_EX_HEADERINALLVIEWS();
|
test_LVS_EX_HEADERINALLVIEWS();
|
||||||
test_deleteitem();
|
test_deleteitem();
|
||||||
test_multiselect();
|
test_multiselect();
|
||||||
|
test_insertitem();
|
||||||
|
|
||||||
unload_v6_module(ctx_cookie, hCtx);
|
unload_v6_module(ctx_cookie, hCtx);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue