Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
June 2022
- 68 participants
- 3274 messages
Re: [PATCH v2 0/2] MR219: user32: Avoid use of setupapi in raw input device enumeration. - approved
by Alexandre Julliard (@julliard)
This merge request was approved by Alexandre Julliard.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/219
June 10, 2022
Re: [PATCH v2 0/1] MR221: comctl32: Fix integer overflow in DPA_Search. - approved
by Alexandre Julliard (@julliard)
This merge request was approved by Alexandre Julliard.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/221
June 10, 2022
Re: HLSL offsetting
by Zebediah Figura
On 6/10/22 14:13, Francisco Casas wrote:
> So, as Matteo summarized, we are between 2 main options:
>
> a) Multiple register offsets.
> b) Component offsets with structured dereference info.
>
> How I see it, (a) changes hlsl_deref to:
>
> ---
> enum register_set {
> HLSL_REGSET_OBJ,
> HLSL_REGSET_NUM,
> /* ... add more as needed, to cover for all SMs. */
>
> HLSL_REGSET_COUNT,
> };
>
> struct hlsl_deref
> {
> struct hlsl_ir_var *var;
> struct hlsl_src offset[HLSL_REGSET_COUNT];
> };
> ---
>
> Also, the types' reg_size becomes reg_size[HLSL_REGSET_COUNT], and so do
> field offsets. Many functions have to receive an additional register_set
> argument or an array of offsets instead of a single offset.
>
>
> On the other hand, the version of (b) I imagine changes hlsl_deref to:
> ---
> struct hlsl_deref
> {
> struct hlsl_ir_var *var;
> unsigned int route_len;
> struct hlsl_src *route;
> };
> ---
> Where route is intended to be a variable size array of component
> offsets.
I was envisioning something more explicit, but this is simpler, so my
guess is that this is what we want.
> It would make sense to remove reg_size from the types and also
> field offsets.
Yes, absolutely.
> Functions that cannot receive structs or arrays may
> receive a "flattened" component offset that can then be translated into
> a route, other functions would require the route as an array.
Not immediately sure what functions you're thinking of, but I imagine
things like hlsl_compute_component_offset() would now have to translate
the offset into an array.
> At this point I can see the benefits of (b) over (a), but also, several
> complications that may arise (you have pointed most of them):
> - We will have to translate many things that are already in terms of
> register offsets into component offsets.
How many things, though? As far as I can see it's:
- copy-prop
- copy splitting
- hlsl_offset_from_deref() [which is part of the point of the whole
exercise]
That's pretty much it.
> - We will have to move all optimization passes (like vectorization) that
> require register offsets to their specific SMxIR, RA too.
I think we want to do RA per backend anyway. (It kind of already is
per-backend, in a very awkward way.)
Vectorization is the main downside but it's possible that we wanted that
to be per-backend too.
> - We will have to do the proper translation to register offsets, on each
> SMxIR level, and probably some sort of constant folding for them.
Sure, but in a sense this is the point. The translation is
backend-specific (what with alignment and register sets and all) and we
should structure things accordingly.
hlsl_offset_from_deref() will need constant folding in a sense, but
it'll be a pretty restricted form thereof.
> - Once we start supporting non-constant offsets, we may also want to
> introduce a common subexpression elimination pass for the registers
> offsets expressions that will arise (currently, the creation of common
> expressions is mainly avoided by the recursive structure of the split
> passes).
What cases are you thinking of that would want CSE?
> Solely because I have spent a considerable amount of time implementing
> option (a) (and some time giving up on implementing component offsets as
> a single hlsl_src, instead of a path) I am rushing (a) to see how the
> patch turns out in the end, before trying (b).
>
> I so think that (a) can be cleansed one step at the time. Even if the
> register sizes and offsets depend on the SM, we can write an interface
> to abstract the rest of the code of using them directly, and gradually
> migrate the code that does to use this interface instead.
>
>
> But so far, yeah, I am being convinced that (b) is better, however more
> difficult.
> If we do (b), I suggest we try to do it in separate steps, with some
> "scaffolding code":
>
> - Add the component offset route to hlsl_deref without deleting the
> register offset.
> - Create a simple pass that initializes the register offset field using
> the route in all the hlsl_derefs.
> - Translate all the parse code first to work with the routes, and apply
> the pass just after parsing.
> - Translate some more compilation passes and move the translation pass
> forward.
> - Repeat until all the passes that can be written in terms of component
> offsets are.
> - Write the SMxIR·s and the SMxIR translations.
> - Only then, remove the the register offset from hlsl_deref and the
> translation pass from the codebase.
>
>
> Otherwise we may end up writing a very big patch that may take too long
> to complete (!).
Ech, I think that trying to do two things at once is going to be more
confusing than the alternative. I also don't think there's *that* much
code that we'd have to change, i.e. a monolithic patch wouldn't be that bad.
For that matter, I'd be happy to try writing those patches myself :-)
ἔρρωσθε,
Zeb
June 10, 2022
Re: [PATCH 2/2] riched20: Draw OLE objects with IViewObject implementation.
by Marvin
Hi,
While running your changed tests, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at:
https://testbot.winehq.org/JobDetails.pl?Key=116734
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
riched20:
0720:richole: unhandled exception c0000005 at 71E43239
=== w7u_adm (32 bit report) ===
riched20:
00e0:richole: unhandled exception c0000005 at 72103239
=== w7u_el (32 bit report) ===
riched20:
0110:richole: unhandled exception c0000005 at 73993239
=== w8 (32 bit report) ===
riched20:
0ac8:richole: unhandled exception c0000005 at 6878EE6C
=== w8adm (32 bit report) ===
riched20:
0aac:richole: unhandled exception c0000005 at 68F7EE6C
=== w864 (32 bit report) ===
riched20:
0bd8:richole: unhandled exception c0000005 at 7422EE6C
=== w1064v1507 (32 bit report) ===
riched20:
0c28:richole: unhandled exception c0000005 at 740EFDC9
=== w1064v1809 (32 bit report) ===
riched20:
1d44:richole: unhandled exception c0000005 at 74E8D7FE
=== w1064 (32 bit report) ===
riched20:
1c24:richole: unhandled exception c0000005 at 7422B625
=== w1064_tsign (32 bit report) ===
riched20:
0db8:richole: unhandled exception c0000005 at 757AB625
=== w10pro64 (32 bit report) ===
riched20:
1e14:richole: unhandled exception c0000005 at 747DB625
=== w864 (64 bit report) ===
riched20:
0bb0:richole: unhandled exception c0000005 at 00007FFDBD77D9E6
=== w1064v1507 (64 bit report) ===
riched20:
0d10:richole: unhandled exception c0000005 at 00007FFFC86D869E
=== w1064v1809 (64 bit report) ===
riched20:
1d60:richole: unhandled exception c0000005 at 00007FFAA8C61928
=== w1064 (64 bit report) ===
riched20:
1ccc:richole: unhandled exception c0000005 at 00007FFEAE4D19C8
=== w1064_2qxl (64 bit report) ===
riched20:
1e30:richole: unhandled exception c0000005 at 00007FF8C16919C8
=== w1064_adm (64 bit report) ===
riched20:
1c50:richole: unhandled exception c0000005 at 00007FFAB2BC19C8
=== w1064_tsign (64 bit report) ===
riched20:
16dc:richole: unhandled exception c0000005 at 00007FFFDB6419C8
=== w10pro64 (64 bit report) ===
riched20:
1dcc:richole: unhandled exception c0000005 at 00007FFCB95D19C8
=== w10pro64_en_AE_u8 (64 bit report) ===
riched20:
07e4:richole: unhandled exception c0000005 at 00007FF9611019C8
=== w10pro64_ar (64 bit report) ===
riched20:
06f0:richole: unhandled exception c0000005 at 00007FFC15CA19C8
=== w10pro64_ja (64 bit report) ===
riched20:
1cf0:richole: unhandled exception c0000005 at 00007FFA080B19C8
=== w10pro64_zh_CN (64 bit report) ===
riched20:
203c:richole: unhandled exception c0000005 at 00007FFCFA4F19C8
June 10, 2022
Re: [PATCH 1/2] riched20/tests: Add tests for drawing embedded OLE objects.
by Marvin
Hi,
While running your changed tests, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at:
https://testbot.winehq.org/JobDetails.pl?Key=116733
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
riched20:
07a8:richole: unhandled exception c0000005 at 727B3239
=== w7u_adm (32 bit report) ===
riched20:
0608:richole: unhandled exception c0000005 at 72103239
=== w7u_el (32 bit report) ===
riched20:
0584:richole: unhandled exception c0000005 at 72873239
=== w8 (32 bit report) ===
riched20:
0ac4:richole: unhandled exception c0000005 at 6873EE6C
=== w8adm (32 bit report) ===
riched20:
0a84:richole: unhandled exception c0000005 at 6900EE6C
=== w864 (32 bit report) ===
riched20:
04b4:richole: unhandled exception c0000005 at 7422EE6C
=== w1064v1507 (32 bit report) ===
riched20:
0d84:richole: unhandled exception c0000005 at 740EFDC9
=== w1064v1809 (32 bit report) ===
riched20:
1dfc:richole: unhandled exception c0000005 at 74E8D7FE
=== w1064 (32 bit report) ===
riched20:
1ef8:richole: unhandled exception c0000005 at 74D5B625
=== w1064_tsign (32 bit report) ===
riched20:
19a4:richole: unhandled exception c0000005 at 74C0B625
=== w10pro64 (32 bit report) ===
riched20:
1df4:richole: unhandled exception c0000005 at 746CB625
=== w864 (64 bit report) ===
riched20:
0bc0:richole: unhandled exception c0000005 at 00007FFDBE08D9E6
=== w1064v1507 (64 bit report) ===
riched20:
0168:richole: unhandled exception c0000005 at 00007FFFC89E869E
=== w1064v1809 (64 bit report) ===
riched20:
1d3c:richole: unhandled exception c0000005 at 00007FFAA8C61928
=== w1064 (64 bit report) ===
riched20:
1c28:richole: unhandled exception c0000005 at 00007FFEAFF319C8
=== w1064_2qxl (64 bit report) ===
riched20:
1d9c:richole: unhandled exception c0000005 at 00007FF8BFD719C8
=== w1064_adm (64 bit report) ===
riched20:
1c1c:richole: unhandled exception c0000005 at 00007FFAB2F119C8
=== w1064_tsign (64 bit report) ===
riched20:
1050:richole: unhandled exception c0000005 at 00007FFB705C19C8
=== w10pro64 (64 bit report) ===
riched20:
1dd4:richole: unhandled exception c0000005 at 00007FFCB94919C8
=== w10pro64_en_AE_u8 (64 bit report) ===
riched20:
1024:richole: unhandled exception c0000005 at 00007FF9774319C8
=== w10pro64_ar (64 bit report) ===
riched20:
034c:richole: unhandled exception c0000005 at 00007FFC151219C8
=== w10pro64_ja (64 bit report) ===
riched20:
159c:richole: unhandled exception c0000005 at 00007FFA1AA319C8
=== w10pro64_zh_CN (64 bit report) ===
riched20:
2070:richole: unhandled exception c0000005 at 00007FFCFAEF19C8
June 10, 2022
[PATCH 2/2] riched20: Draw OLE objects with IViewObject implementation.
by Jinoh Kang
From: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52752
Signed-off-by: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
---
dlls/riched20/richole.c | 64 +++++++++++++++++++++++++++++++++++
dlls/riched20/tests/richole.c | 2 --
2 files changed, 64 insertions(+), 2 deletions(-)
diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c
index 936f1c928b3..9d414af8ee2 100644
--- a/dlls/riched20/richole.c
+++ b/dlls/riched20/richole.c
@@ -5656,6 +5656,7 @@ static void convert_sizel(const ME_Context *c, const SIZEL* szl, SIZE* sz)
void ME_GetOLEObjectSize(const ME_Context *c, ME_Run *run, SIZE *pSize)
{
IDataObject* ido;
+ IViewObject* ivo;
FORMATETC fmt;
STGMEDIUM stgm;
DIBSECTION dibsect;
@@ -5681,6 +5682,29 @@ void ME_GetOLEObjectSize(const ME_Context *c, ME_Run *run, SIZE *pSize)
return;
}
+ if (SUCCEEDED(IOleObject_QueryInterface(run->reobj->obj.poleobj, &IID_IViewObject, (void**)&ivo)))
+ {
+ HRESULT hr;
+ SIZEL sizel;
+
+ hr = IOleObject_GetExtent(run->reobj->obj.poleobj, DVASPECT_CONTENT, &sizel);
+ if (FAILED(hr))
+ {
+ WARN("failed to get extent: %#08lx\n", hr);
+ sizel.cx = sizel.cy = 0;
+ }
+
+ convert_sizel(c, &sizel, pSize);
+ if (c->editor->nZoomNumerator != 0)
+ {
+ pSize->cx = MulDiv(pSize->cx, c->editor->nZoomNumerator, c->editor->nZoomDenominator);
+ pSize->cy = MulDiv(pSize->cy, c->editor->nZoomNumerator, c->editor->nZoomDenominator);
+ }
+
+ IViewObject_Release(ivo);
+ return;
+ }
+
if (IOleObject_QueryInterface(run->reobj->obj.poleobj, &IID_IDataObject, (void**)&ido) != S_OK)
{
FIXME("Query Interface IID_IDataObject failed!\n");
@@ -5733,6 +5757,7 @@ void ME_GetOLEObjectSize(const ME_Context *c, ME_Run *run, SIZE *pSize)
void draw_ole( ME_Context *c, int x, int y, ME_Run *run, BOOL selected )
{
IDataObject* ido;
+ IViewObject* ivo;
FORMATETC fmt;
STGMEDIUM stgm;
DIBSECTION dibsect;
@@ -5745,6 +5770,45 @@ void draw_ole( ME_Context *c, int x, int y, ME_Run *run, BOOL selected )
assert(run->nFlags & MERF_GRAPHICS);
assert(run->reobj);
+
+ if (SUCCEEDED(IOleObject_QueryInterface(run->reobj->obj.poleobj, &IID_IViewObject, (void**)&ivo)))
+ {
+ HRESULT hr;
+ SIZEL sizel = run->reobj->obj.sizel;
+
+ if (sizel.cx == 0 && sizel.cy == 0)
+ {
+ hr = IOleObject_GetExtent(run->reobj->obj.poleobj, DVASPECT_CONTENT, &sizel);
+ if (FAILED(hr))
+ {
+ WARN("failed to get extent: %#08lx\n", hr);
+ IViewObject_Release(ivo);
+ return;
+ }
+ }
+
+ convert_sizel(c, &sizel, &sz);
+ if (c->editor->nZoomNumerator != 0)
+ {
+ sz.cx = MulDiv(sz.cx, c->editor->nZoomNumerator, c->editor->nZoomDenominator);
+ sz.cy = MulDiv(sz.cy, c->editor->nZoomNumerator, c->editor->nZoomDenominator);
+ }
+
+ rc.left = x;
+ rc.top = y - sz.cy;
+ rc.right = x + sz.cx;
+ rc.bottom = y;
+
+ hr = IViewObject_Draw(ivo, DVASPECT_CONTENT, -1, 0, 0, 0, c->hDC, (RECTL*)&rc, NULL, NULL, 0);
+ if (FAILED(hr))
+ {
+ WARN("failed to draw object: %#08lx\n", hr);
+ }
+
+ IViewObject_Release(ivo);
+ return;
+ }
+
if (IOleObject_QueryInterface(run->reobj->obj.poleobj, &IID_IDataObject, (void**)&ido) != S_OK)
{
FIXME("Couldn't get interface\n");
diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c
index d0ccb8713d6..900c814bce1 100644
--- a/dlls/riched20/tests/richole.c
+++ b/dlls/riched20/tests/richole.c
@@ -4205,7 +4205,6 @@ static void subtest_InsertObject(struct reolecb_obj *callback)
testobj->line = __LINE__;
UpdateWindow(hwnd);
- todo_wine
ok(testobj->draw_count, "expected draw_count to be nonzero, got %d\n", testobj->draw_count);
SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"");
@@ -4222,7 +4221,6 @@ static void subtest_InsertObject(struct reolecb_obj *callback)
testobj->line = __LINE__;
UpdateWindow(hwnd);
- todo_wine
ok(testobj->draw_count, "expected draw_count to be nonzero, got %d\n", testobj->draw_count);
IOleObject_Release(&testobj->IOleObject_iface);
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/227
June 10, 2022
[PATCH 1/2] riched20/tests: Add tests for drawing embedded OLE objects.
by Jinoh Kang
From: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
Signed-off-by: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
---
dlls/riched20/tests/richole.c | 469 +++++++++++++++++++++++++++++++++-
1 file changed, 466 insertions(+), 3 deletions(-)
diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c
index c34c87ef646..d0ccb8713d6 100644
--- a/dlls/riched20/tests/richole.c
+++ b/dlls/riched20/tests/richole.c
@@ -212,6 +212,423 @@ static void olecb_check_QueryInsertObject(struct reolecb_obj *This, int line)
olecb_expect_QueryInsertObject(This, 0, 0, NULL, NULL, 0, S_OK);
}
+DEFINE_GUID(CLSID_testoleobj, 0x4484082e, 0x6d18, 0x4932, 0xa0, 0x86, 0x5b, 0x4d, 0xcf, 0x36, 0xb3, 0xde);
+
+struct testoleobj {
+ IOleObject IOleObject_iface;
+ LONG ref;
+ int line;
+ int draw_count;
+
+ IUnknown *datacache;
+ IOleClientSite *clientsite;
+ IOleAdviseHolder *advise_holder;
+ SIZEL extent;
+
+ IViewObject2 IViewObject2_iface;
+};
+
+static struct testoleobj *impl_from_IOleObject( IOleObject *iface )
+{
+ return CONTAINING_RECORD( iface, struct testoleobj, IOleObject_iface );
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_QueryInterface( IOleObject *iface, REFIID riid, void **obj )
+{
+ struct testoleobj *This = impl_from_IOleObject( iface );
+
+ if (IsEqualGUID( riid, &IID_IUnknown ) || IsEqualGUID( riid, &IID_IOleObject ))
+ {
+ *obj = iface;
+ }
+ else if (IsEqualGUID( riid, &IID_IViewObject ) || IsEqualGUID( riid, &IID_IViewObject2 ))
+ {
+ *obj = &This->IViewObject2_iface;
+ }
+ else if (IsEqualGUID( riid, &IID_IDataObject ))
+ {
+ return IUnknown_QueryInterface( This->datacache, riid, obj );
+ }
+ else
+ {
+ trace( "Unsupported interface: %s\n", debugstr_guid( riid ));
+ *obj = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef( (IUnknown *)*obj );
+ return S_OK;
+}
+
+static ULONG STDMETHODCALLTYPE testoleobj_AddRef( IOleObject *iface )
+{
+ struct testoleobj *This = impl_from_IOleObject( iface );
+ ULONG ref = InterlockedIncrement( &This->ref );
+ return ref;
+}
+
+static ULONG STDMETHODCALLTYPE testoleobj_Release( IOleObject *iface )
+{
+ struct testoleobj *This = impl_from_IOleObject( iface );
+ ULONG ref = InterlockedDecrement( &This->ref );
+ if (!ref)
+ {
+ if (This->advise_holder)
+ {
+ IOleAdviseHolder_Release( This->advise_holder );
+ This->advise_holder = NULL;
+ }
+ if (This->clientsite)
+ {
+ IOleClientSite_Release( This->clientsite );
+ This->clientsite = NULL;
+ }
+ if (This->datacache)
+ {
+ IUnknown_Release( This->datacache );
+ This->datacache = NULL;
+ }
+ free( This );
+ }
+ return ref;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_SetClientSite( IOleObject *iface, IOleClientSite *clientsite )
+{
+ struct testoleobj *This = impl_from_IOleObject( iface );
+
+ if (This->clientsite != clientsite)
+ {
+ if (This->clientsite) IOleClientSite_Release( This->clientsite );
+ This->clientsite = clientsite;
+ if (This->clientsite) IOleClientSite_AddRef( This->clientsite );
+ }
+
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_GetClientSite( IOleObject *iface, IOleClientSite **clientsite )
+{
+ struct testoleobj *This = impl_from_IOleObject( iface );
+
+ if (This->clientsite) IOleClientSite_AddRef( This->clientsite );
+ *clientsite = This->clientsite;
+
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_SetHostNames( IOleObject *iface,
+ LPCOLESTR container_app,
+ LPCOLESTR container_obj )
+{
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_Close( IOleObject *iface, DWORD save_option )
+{
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_SetMoniker( IOleObject *iface,
+ DWORD which_moniker, IMoniker *mk )
+{
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_GetMoniker( IOleObject *iface, DWORD assign,
+ DWORD which_moniker, IMoniker **mk )
+{
+ struct testoleobj *This = impl_from_IOleObject( iface );
+
+ *mk = NULL;
+
+ if (!This->clientsite) return E_UNEXPECTED;
+
+ return IOleClientSite_GetMoniker( This->clientsite, assign, which_moniker, mk );
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_InitFromData( IOleObject *iface, IDataObject *dataobj,
+ BOOL creation, DWORD reserved )
+{
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_GetClipboardData( IOleObject *iface, DWORD reserved,
+ IDataObject **dataobj )
+{
+ *dataobj = NULL;
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_DoVerb( IOleObject *iface, LONG verb, MSG *msg,
+ IOleClientSite *activesite, LONG index,
+ HWND parentwnd, LPCRECT posrect )
+{
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_EnumVerbs( IOleObject *iface, IEnumOLEVERB **enumoleverb )
+{
+ *enumoleverb = NULL;
+ return OLEOBJ_E_NOVERBS;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_Update( IOleObject *iface )
+{
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_IsUpToDate( IOleObject *iface )
+{
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_GetUserClassID( IOleObject *iface, CLSID *clsid )
+{
+ *clsid = CLSID_testoleobj;
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_GetUserType( IOleObject *iface, DWORD form_of_type, LPOLESTR *user_type )
+{
+ static const OLECHAR typename[] = L"richole testoleobj";
+
+ *user_type = CoTaskMemAlloc( sizeof(typename) );
+ if (!*user_type) return E_OUTOFMEMORY;
+
+ memcpy( *user_type, typename, sizeof(typename) );
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_SetExtent( IOleObject *iface, DWORD draw_aspect, SIZEL *sizel )
+{
+ struct testoleobj *This = impl_from_IOleObject( iface );
+
+ if (draw_aspect != DVASPECT_CONTENT) return E_FAIL;
+
+ This->extent = *sizel;
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_GetExtent( IOleObject *iface, DWORD draw_aspect, SIZEL *sizel )
+{
+ struct testoleobj *This = impl_from_IOleObject( iface );
+
+ if (draw_aspect != DVASPECT_CONTENT) return E_FAIL;
+
+ *sizel = This->extent;
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_Advise( IOleObject *iface, IAdviseSink *adv_sink, DWORD *connection )
+{
+ struct testoleobj *This = impl_from_IOleObject( iface );
+ HRESULT hr = S_OK;
+
+ if (!This->advise_holder) hr = CreateOleAdviseHolder( &This->advise_holder );
+ if (SUCCEEDED( hr )) hr = IOleAdviseHolder_Advise( This->advise_holder, adv_sink, connection );
+ return hr;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_Unadvise( IOleObject *iface, DWORD connection )
+{
+ struct testoleobj *This = impl_from_IOleObject( iface );
+
+ if (!This->advise_holder) return OLE_E_NOCONNECTION;
+ return IOleAdviseHolder_Unadvise( This->advise_holder, connection );
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_EnumAdvise( IOleObject *iface, IEnumSTATDATA **enum_advise )
+{
+ struct testoleobj *This = impl_from_IOleObject( iface );
+
+ if (!This->advise_holder)
+ {
+ *enum_advise = NULL;
+ return S_OK;
+ }
+ return IOleAdviseHolder_EnumAdvise( This->advise_holder, enum_advise );
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_GetMiscStatus( IOleObject *iface, DWORD aspect, DWORD *status )
+{
+ *status = 0;
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_SetColorScheme( IOleObject *iface, LOGPALETTE *palette )
+{
+ return E_NOTIMPL;
+}
+
+static const struct IOleObjectVtbl testoleobj_IOleObject_Vtbl = {
+ testoleobj_QueryInterface,
+ testoleobj_AddRef,
+ testoleobj_Release,
+ testoleobj_IOleObject_SetClientSite,
+ testoleobj_IOleObject_GetClientSite,
+ testoleobj_IOleObject_SetHostNames,
+ testoleobj_IOleObject_Close,
+ testoleobj_IOleObject_SetMoniker,
+ testoleobj_IOleObject_GetMoniker,
+ testoleobj_IOleObject_InitFromData,
+ testoleobj_IOleObject_GetClipboardData,
+ testoleobj_IOleObject_DoVerb,
+ testoleobj_IOleObject_EnumVerbs,
+ testoleobj_IOleObject_Update,
+ testoleobj_IOleObject_IsUpToDate,
+ testoleobj_IOleObject_GetUserClassID,
+ testoleobj_IOleObject_GetUserType,
+ testoleobj_IOleObject_SetExtent,
+ testoleobj_IOleObject_GetExtent,
+ testoleobj_IOleObject_Advise,
+ testoleobj_IOleObject_Unadvise,
+ testoleobj_IOleObject_EnumAdvise,
+ testoleobj_IOleObject_GetMiscStatus,
+ testoleobj_IOleObject_SetColorScheme
+};
+
+static struct testoleobj *impl_from_IViewObject2( IViewObject2 *iface )
+{
+ return CONTAINING_RECORD( iface, struct testoleobj, IViewObject2_iface );
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IViewObject2_QueryInterface( IViewObject2 *iface, REFIID riid, void **obj )
+{
+ struct testoleobj *This = impl_from_IViewObject2( iface );
+ return IOleObject_QueryInterface( &This->IOleObject_iface, riid, obj );
+}
+
+static ULONG STDMETHODCALLTYPE testoleobj_IViewObject2_AddRef( IViewObject2 *iface )
+{
+ struct testoleobj *This = impl_from_IViewObject2( iface );
+ return IOleObject_AddRef( &This->IOleObject_iface );
+}
+
+static ULONG STDMETHODCALLTYPE testoleobj_IViewObject2_Release( IViewObject2 *iface )
+{
+ struct testoleobj *This = impl_from_IViewObject2( iface );
+ return IOleObject_Release( &This->IOleObject_iface );
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IViewObject2_Draw( IViewObject2 *iface, DWORD draw_aspect,
+ LONG index, void *aspect, DVTARGETDEVICE *td,
+ HDC hdc_target_dev, HDC hdc_draw,
+ LPCRECTL bounds, LPCRECTL wbounds,
+ BOOL (CALLBACK *fn_continue)(ULONG_PTR),
+ ULONG_PTR arg_continue )
+{
+ struct testoleobj *This = impl_from_IViewObject2( iface );
+ SIZEL dpi;
+
+ if (draw_aspect != DVASPECT_CONTENT || index != -1) return E_NOTIMPL;
+
+ ok_(__FILE__,This->line)( td == NULL, "expected td to be NULL, got %p\n", td );
+ ok_(__FILE__,This->line)( hdc_target_dev == NULL, "expected hdc_target_dev to be NULL, got %p\n", hdc_target_dev );
+ ok_(__FILE__,This->line)( wbounds == NULL, "expected wbounds to be NULL, got %p\n", wbounds );
+
+ dpi.cx = GetDeviceCaps(hdc_draw, LOGPIXELSX);
+ dpi.cy = GetDeviceCaps(hdc_draw, LOGPIXELSY);
+
+ ok_(__FILE__,This->line)( bounds->right - bounds->left == MulDiv( This->extent.cx, dpi.cx, 2540 ),
+ "bounds->right (= %ld) - bounds->left (= %ld) != "
+ "MulDiv( This->extent.cx (= %ld), dpi.cx (= %ld), 2540 )\n",
+ bounds->right, bounds->left, This->extent.cx, dpi.cx );
+ ok_(__FILE__,This->line)( bounds->bottom - bounds->top == MulDiv( This->extent.cy, dpi.cy, 2540 ),
+ "bounds->bottom (= %ld) - bounds->top (= %ld) != "
+ "MulDiv( This->extent.cy (= %ld), dpi.cy (= %ld), 2540 )\n",
+ bounds->bottom, bounds->top, This->extent.cy, dpi.cy );
+
+ FillRect( hdc_draw, (const RECT *)bounds, GetStockObject( DKGRAY_BRUSH ));
+ This->draw_count++;
+
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IViewObject2_GetColorSet( IViewObject2 *iface, DWORD draw_aspect,
+ LONG index, void *aspect, DVTARGETDEVICE *td,
+ HDC hdc_target_dev, LOGPALETTE **color_set )
+{
+ *color_set = NULL;
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IViewObject2_Freeze( IViewObject2 *iface, DWORD draw_aspect,
+ LONG index, void *aspect, DWORD *freeze )
+{
+ *freeze = 0;
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IViewObject2_Unfreeze( IViewObject2 *iface, DWORD freeze )
+{
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IViewObject2_SetAdvise( IViewObject2 *iface, DWORD aspects,
+ DWORD advf, IAdviseSink *adv_sink )
+{
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IViewObject2_GetAdvise( IViewObject2 *iface, DWORD *aspects,
+ DWORD *advf, IAdviseSink **adv_sink )
+{
+ *aspects = 0;
+ *advf = 0;
+ *adv_sink = NULL;
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IViewObject2_GetExtent( IViewObject2 *iface, DWORD draw_aspect,
+ LONG index, DVTARGETDEVICE *td,
+ SIZEL *sizel )
+{
+ struct testoleobj *This = impl_from_IViewObject2( iface );
+
+ if (draw_aspect != DVASPECT_CONTENT || index != -1) return E_FAIL;
+
+ *sizel = This->extent;
+ return S_OK;
+}
+
+static const struct IViewObject2Vtbl testoleobj_IViewObject2_Vtbl = {
+ testoleobj_IViewObject2_QueryInterface,
+ testoleobj_IViewObject2_AddRef,
+ testoleobj_IViewObject2_Release,
+ testoleobj_IViewObject2_Draw,
+ testoleobj_IViewObject2_GetColorSet,
+ testoleobj_IViewObject2_Freeze,
+ testoleobj_IViewObject2_Unfreeze,
+ testoleobj_IViewObject2_SetAdvise,
+ testoleobj_IViewObject2_GetAdvise,
+ testoleobj_IViewObject2_GetExtent,
+};
+
+static HRESULT testoleobj_Create( struct testoleobj **objptr )
+{
+ struct testoleobj *obj;
+ HRESULT hr;
+
+ obj = calloc( sizeof(struct testoleobj), 1 );
+ if (!obj) return E_OUTOFMEMORY;
+
+ obj->IOleObject_iface.lpVtbl = &testoleobj_IOleObject_Vtbl;
+ obj->ref = 1;
+ obj->IViewObject2_iface.lpVtbl = &testoleobj_IViewObject2_Vtbl;
+
+ hr = CreateDataCache( (IUnknown *)&obj->IOleObject_iface, &CLSID_testoleobj,
+ &IID_IUnknown, (void **)&obj->datacache );
+ if (FAILED( hr ))
+ {
+ free( obj );
+ return hr;
+ }
+
+ *objptr = obj;
+ return S_OK;
+}
+
static HMODULE hmoduleRichEdit;
DEFINE_GUID(GUID_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@@ -3441,8 +3858,11 @@ static void subtest_InsertObject(struct reolecb_obj *callback)
HWND hwnd;
const WCHAR *expected_string, *string;
const CHAR *expected_stringA;
+ struct testoleobj *testobj;
ITextSelection *selection;
IDataObject *dataobject;
+ IOleClientSite *clientsite;
+ REOBJECT reobj;
TEXTRANGEA textrange;
FORMATETC formatetc;
CHARRANGE charrange;
@@ -3452,6 +3872,7 @@ static void subtest_InsertObject(struct reolecb_obj *callback)
CHAR bufferA[1024];
LONG count, result;
ITextRange *range;
+
BSTR bstr;
create_interfaces(&hwnd, &reole, &doc, &selection);
@@ -3486,9 +3907,6 @@ static void subtest_InsertObject(struct reolecb_obj *callback)
if (callback)
{
- IOleClientSite *clientsite;
- REOBJECT reobj;
-
/* (fail to) insert object1 in (3, 4)*/
SendMessageA(hwnd, EM_SETSEL, 3, 4);
@@ -3765,6 +4183,51 @@ static void subtest_InsertObject(struct reolecb_obj *callback)
ok(hr == S_OK, "Got hr %#lx.\n", hr);
todo_wine ok(result == 0xfffc, "Got char: %lc\n", (WCHAR)result);
+ hr = IRichEditOle_GetClientSite(reole, &clientsite);
+ ok(hr == S_OK, "IRichEditOle_GetClientSite got hr %#lx.\n", hr);
+
+ hr = testoleobj_Create(&testobj);
+ ok(hr == S_OK, "testoleobj_Create got hr %#lx.\n", hr);
+ testobj->extent.cx = 10;
+ testobj->extent.cy = 10;
+
+ SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"");
+ testobj->draw_count = 0;
+ testobj->line = __LINE__;
+
+ olecb_expect_QueryInsertObject(callback, __LINE__, 1,
+ &CLSID_testoleobj, NULL, REO_CP_SELECTION, S_OK);
+ fill_reobject_struct(&reobj, REO_CP_SELECTION, &testobj->IOleObject_iface, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, 0);
+ reobj.clsid = CLSID_testoleobj;
+ hr = IRichEditOle_InsertObject(reole, &reobj);
+ ok(hr == S_OK, "IRichEditOle_InsertObject got hr %#lx.\n", hr);
+ olecb_check_QueryInsertObject(callback, __LINE__);
+
+ testobj->line = __LINE__;
+ UpdateWindow(hwnd);
+ todo_wine
+ ok(testobj->draw_count, "expected draw_count to be nonzero, got %d\n", testobj->draw_count);
+
+ SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"");
+ testobj->draw_count = 0;
+ testobj->line = __LINE__;
+
+ olecb_expect_QueryInsertObject(callback, __LINE__, 1,
+ &CLSID_testoleobj, NULL, REO_CP_SELECTION, S_OK);
+ fill_reobject_struct(&reobj, REO_CP_SELECTION, &testobj->IOleObject_iface, NULL, clientsite, 0, 0, DVASPECT_CONTENT, 0, 0);
+ reobj.clsid = CLSID_testoleobj;
+ hr = IRichEditOle_InsertObject(reole, &reobj);
+ ok(hr == S_OK, "IRichEditOle_InsertObject got hr %#lx.\n", hr);
+ olecb_check_QueryInsertObject(callback, __LINE__);
+
+ testobj->line = __LINE__;
+ UpdateWindow(hwnd);
+ todo_wine
+ ok(testobj->draw_count, "expected draw_count to be nonzero, got %d\n", testobj->draw_count);
+
+ IOleObject_Release(&testobj->IOleObject_iface);
+ IOleClientSite_Release(clientsite);
+
if (callback)
{
LRESULT sendres = SendMessageA(hwnd, EM_SETOLECALLBACK, 0, 0);
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/227
June 10, 2022
[PATCH 0/2] MR227: riched20: Fix for #52752 (use IViewObject implementation)
by Jinoh Kang (@iamahuman)
Fixes https://bugs.winehq.org/show_bug.cgi?id=52752.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/227
June 10, 2022
Re: HLSL offsetting
by Francisco Casas
So, as Matteo summarized, we are between 2 main options:
a) Multiple register offsets.
b) Component offsets with structured dereference info.
How I see it, (a) changes hlsl_deref to:
---
enum register_set {
HLSL_REGSET_OBJ,
HLSL_REGSET_NUM,
/* ... add more as needed, to cover for all SMs. */
HLSL_REGSET_COUNT,
};
struct hlsl_deref
{
struct hlsl_ir_var *var;
struct hlsl_src offset[HLSL_REGSET_COUNT];
};
---
Also, the types' reg_size becomes reg_size[HLSL_REGSET_COUNT], and so do
field offsets. Many functions have to receive an additional register_set
argument or an array of offsets instead of a single offset.
On the other hand, the version of (b) I imagine changes hlsl_deref to:
---
struct hlsl_deref
{
struct hlsl_ir_var *var;
unsigned int route_len;
struct hlsl_src *route;
};
---
Where route is intended to be a variable size array of component
offsets. It would make sense to remove reg_size from the types and also
field offsets. Functions that cannot receive structs or arrays may
receive a "flattened" component offset that can then be translated into
a route, other functions would require the route as an array.
At this point I can see the benefits of (b) over (a), but also, several
complications that may arise (you have pointed most of them):
- We will have to translate many things that are already in terms of
register offsets into component offsets.
- We will have to move all optimization passes (like vectorization) that
require register offsets to their specific SMxIR, RA too.
- We will have to do the proper translation to register offsets, on each
SMxIR level, and probably some sort of constant folding for them.
- Once we start supporting non-constant offsets, we may also want to
introduce a common subexpression elimination pass for the registers
offsets expressions that will arise (currently, the creation of common
expressions is mainly avoided by the recursive structure of the split
passes).
Solely because I have spent a considerable amount of time implementing
option (a) (and some time giving up on implementing component offsets as
a single hlsl_src, instead of a path) I am rushing (a) to see how the
patch turns out in the end, before trying (b).
I so think that (a) can be cleansed one step at the time. Even if the
register sizes and offsets depend on the SM, we can write an interface
to abstract the rest of the code of using them directly, and gradually
migrate the code that does to use this interface instead.
But so far, yeah, I am being convinced that (b) is better, however more
difficult.
If we do (b), I suggest we try to do it in separate steps, with some
"scaffolding code":
- Add the component offset route to hlsl_deref without deleting the
register offset.
- Create a simple pass that initializes the register offset field using
the route in all the hlsl_derefs.
- Translate all the parse code first to work with the routes, and apply
the pass just after parsing.
- Translate some more compilation passes and move the translation pass
forward.
- Repeat until all the passes that can be written in terms of component
offsets are.
- Write the SMxIR·s and the SMxIR translations.
- Only then, remove the the register offset from hlsl_deref and the
translation pass from the codebase.
Otherwise we may end up writing a very big patch that may take too long
to complete (!).
Best regards,
Francisco.
June 10, 2022
Re: [PATCH v2 resend 1/6] comctl32/tests: Expand ownerdata listview tests.
by Angelo Haller
On 10/06/2022 03.12, Zhiyi Zhang wrote:
>
> On 5/26/22 04:00, Angelo Haller wrote:
>> From: Angelo Haller <angelo(a)szanni.org>
>>
>> Add more test cases to ownderdata listviews.
>> Check LVN_ITEMCHANGED IDs.
>>
>> Signed-off-by: Angelo Haller <angelo(a)szanni.org>
>> ---
>> dlls/comctl32/tests/listview.c | 59 +++++++++++++++++++++++++++++-----
>> 1 file changed, 51 insertions(+), 8 deletions(-)
>>
>> diff --git a/dlls/comctl32/tests/listview.c b/dlls/comctl32/tests/listview.c
>> index 6ac7f53137d..78b3e3ae069 100644
>> --- a/dlls/comctl32/tests/listview.c
>> +++ b/dlls/comctl32/tests/listview.c
>> @@ -255,11 +255,33 @@ static const struct message ownerdata_deselect_all_parent_seq[] = {
>> { 0 }
>> };
>>
>> -static const struct message ownerdata_multiselect_odstatechanged_seq[] = {
>> - { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
>> +static const struct message ownerdata_multiselect_select_0_to_1_seq[] = {
>> + { WM_NOTIFY, sent|id|wparam, -1, 0, LVN_ITEMCHANGED },
>> { WM_NOTIFY, sent|id, 0, 0, LVN_ODSTATECHANGED },
>> - { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
>> - { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
>> + { WM_NOTIFY, sent|id|wparam, 0, 0, LVN_ITEMCHANGED },
>> + { WM_NOTIFY, sent|id|wparam, 1, 0, LVN_ITEMCHANGED },
>> + { 0 }
>> +};
>> +
>> +static const struct message ownerdata_multiselect_select_0_to_2_seq[] = {
>> + { WM_NOTIFY, sent|id|wparam, -1, 0, LVN_ITEMCHANGED },
>> + { WM_NOTIFY, sent|id, 0, 0, LVN_ODSTATECHANGED },
>> + { WM_NOTIFY, sent|id|wparam, 1, 0, LVN_ITEMCHANGED },
>> + { WM_NOTIFY, sent|id|wparam, 2, 0, LVN_ITEMCHANGED },
>> + { 0 }
>> +};
>> +
>> +static const struct message ownerdata_multiselect_deselect_all_select_3_seq[] = {
>> + { WM_NOTIFY, sent|id|wparam, -1, 0, LVN_ITEMCHANGED },
>> + { WM_NOTIFY, sent|id|wparam, 2, 0, LVN_ITEMCHANGED },
>> + { WM_NOTIFY, sent|id|wparam, 3, 0, LVN_ITEMCHANGED },
>> + { 0 }
>> +};
>> +
>> +static const struct message ownerdata_multiselect_deselect_3_select_2_seq[] = {
>> + { WM_NOTIFY, sent|id|wparam, -1, 0, LVN_ITEMCHANGED },
>> + { WM_NOTIFY, sent|id|wparam, 3, 0, LVN_ITEMCHANGED },
>> + { WM_NOTIFY, sent|id|wparam, 2, 0, LVN_ITEMCHANGED },
>> { 0 }
>> };
>>
>> @@ -3575,8 +3597,8 @@ static void test_ownerdata_multiselect(void)
>> expect(0, res);
>>
>> ok_sequence(sequences, PARENT_ODSTATECHANGED_SEQ_INDEX,
>> - ownerdata_multiselect_odstatechanged_seq,
>> - "ownerdata select multiple notification", TRUE);
>> + ownerdata_multiselect_select_0_to_1_seq,
>> + "ownerdata multiselect: select multiple via SHIFT", TRUE);
>>
>> res = SendMessageA(hwnd, WM_KEYUP, VK_DOWN, 0);
>> expect(0, res);
>> @@ -3592,8 +3614,8 @@ static void test_ownerdata_multiselect(void)
>> expect(0, res);
>>
>> ok_sequence(sequences, PARENT_ODSTATECHANGED_SEQ_INDEX,
>> - ownerdata_multiselect_odstatechanged_seq,
>> - "ownerdata select multiple notification", TRUE);
>> + ownerdata_multiselect_select_0_to_2_seq,
>> + "ownerdata multiselect: select multiple via SHIFT+CONTROL", TRUE);
>>
>> res = SendMessageA(hwnd, WM_KEYUP, VK_DOWN, 0);
>> expect(0, res);
>> @@ -3604,6 +3626,27 @@ static void test_ownerdata_multiselect(void)
>> res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
>> expect(3, res);
>>
>> + flush_sequences(sequences, NUM_MSG_SEQUENCES);
>> +
>> + res = SendMessageA(hwnd, WM_KEYDOWN, VK_DOWN, 0);
>> + expect(0, res);
>> +
>> + ok_sequence(sequences, PARENT_ODSTATECHANGED_SEQ_INDEX,
>> + ownerdata_multiselect_deselect_all_select_3_seq,
>> + "ownerdata multiselect: deselect all, select item 3", TRUE);
>> +
>> + res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
>> + expect(1, res);
> Hi Angelo,
>
> Thanks for looking into this. There are a few things can be improved for this series.
>
> Please complete the keyboard sequence by sending WM_KEYUP for VK_DOWN and
> WM_KEYUP for VK_UP.
I'll add the WM_KEYUP events for sure. Not sure how that slipped.
> Also please add tests for pressing VK_UP while holding Shift after setting pressing VK_DOWN while holding Shift.
> Same for holding both Shift and Control And add checks for NMLVODSTATECHANGE member values. For example,
> I don't think uOldState should always be 0.
Happy to add more tests for VK_UP.
With regards to the uOldState: I have not found an instance where it is
not 0. Which kind of makes sense, at least according to the underlying
logic.
Windows seems to only use LVN_ODSTATECHANGED to set a new state
(selection of multiple items). For un-setting (uOldState != 0) Windows
will instead send an all items changed (LVN_ITEMCHANGED = -1) signal
instead. That is at least what I have observed in my testing.
>> +
>> + flush_sequences(sequences, NUM_MSG_SEQUENCES);
>> +
>> + res = SendMessageA(hwnd, WM_KEYDOWN, VK_UP, 0);
>> + expect(0, res);
>> +
>> + ok_sequence(sequences, PARENT_ODSTATECHANGED_SEQ_INDEX,
>> + ownerdata_multiselect_deselect_3_select_2_seq,
>> + "ownerdata multiselect: deselect item 3, select item 2", TRUE);
>> +
>> DestroyWindow(hwnd);
>> }
>>
June 10, 2022