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
[PATCH v2 1/2] user32/tests: Test for parent window exposure by SetWindowPos().
by Jinoh Kang
From: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
Signed-off-by: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
---
dlls/user32/tests/msg.c | 278 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 278 insertions(+)
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c
index 2705914d5e5..67f58032cb3 100644
--- a/dlls/user32/tests/msg.c
+++ b/dlls/user32/tests/msg.c
@@ -9035,6 +9035,278 @@ static void test_paint_messages(void)
DeleteObject( hrgn2 );
}
+static void visualize_region_differences( HWND hwnd, HWND hother, HRGN hrgn_expect, HRGN hrgn_actual )
+{
+ HBRUSH b_expectonly, b_actualonly, b_intersect;
+ HRGN hrgn_intersect;
+ HWND hchild, hshow, hhide;
+ HDC hdc, hdctmp;
+ HBITMAP hbitmap;
+ MSG msg;
+ RECT rect;
+ DWORD start_time, elapsed, timeout = 60 * 1000;
+ BOOL wait = TRUE, toggle = TRUE;
+
+ b_expectonly = CreateSolidBrush( RGB( 64, 64, 255 ));
+ b_actualonly = CreateSolidBrush( RGB( 255, 64, 64 ));
+ b_intersect = CreateSolidBrush( RGB( 159, 64, 159 ));
+
+ hrgn_intersect = CreateRectRgn( 0, 0, 0, 0 );
+ CombineRgn( hrgn_intersect, hrgn_expect, hrgn_actual, RGN_AND );
+
+ GetClientRect( hwnd, &rect );
+ hdc = GetDC( hwnd );
+ hbitmap = CreateCompatibleBitmap( hdc, rect.right, rect.bottom );
+ hdctmp = CreateCompatibleDC( hdc );
+ ReleaseDC( hwnd, hdc );
+
+ SelectObject( hdctmp, hbitmap );
+ FillRgn( hdctmp, hrgn_expect, b_expectonly );
+ FillRgn( hdctmp, hrgn_actual, b_actualonly );
+ FillRgn( hdctmp, hrgn_intersect, b_intersect );
+
+ DeleteObject( hdctmp );
+ DeleteObject( hrgn_intersect );
+ DeleteObject( b_intersect );
+ DeleteObject( b_actualonly );
+ DeleteObject( b_expectonly );
+
+ hchild = CreateWindowExA( 0, WC_STATICA, "", WS_CHILD | SS_BITMAP,
+ 0, 0, rect.right, rect.bottom, hwnd, 0, 0, NULL );
+ SendMessageA( hchild, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbitmap );
+
+ hshow = hchild;
+ hhide = hother;
+
+ start_time = GetTickCount();
+ for (;;)
+ {
+ if (toggle)
+ {
+ HWND htmp;
+ if (hhide)
+ {
+ ShowWindow( hhide, SW_HIDE );
+ }
+ if (hshow)
+ {
+ SetWindowPos( hshow, HWND_TOP, 0, 0, 0, 0,
+ SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW );
+ }
+ htmp = hshow;
+ hshow = hhide;
+ hhide = htmp;
+ toggle = FALSE;
+ }
+ if ((elapsed = GetTickCount() - start_time) >= timeout)
+ {
+ break;
+ }
+ if (wait)
+ {
+ MsgWaitForMultipleObjects( 0, NULL, FALSE, timeout - elapsed, QS_ALLINPUT );
+ wait = FALSE;
+ continue;
+ }
+ if (!PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ))
+ {
+ wait = TRUE;
+ continue;
+ }
+ TranslateMessage( &msg );
+ DispatchMessageA( &msg );
+ if (msg.message == WM_MOUSEMOVE)
+ {
+ start_time = GetTickCount();
+ }
+ else if (msg.message == WM_LBUTTONUP)
+ {
+ toggle = TRUE;
+ }
+ else if (msg.message == WM_RBUTTONUP)
+ {
+ break;
+ }
+ }
+
+ DestroyWindow( hchild );
+ DeleteObject( hbitmap );
+}
+
+#define subtest_swp_paint_regions(w,p,c) subtest_swp_paint_regions_(__LINE__,w,p,c)
+
+static void subtest_swp_paint_regions_( int line, int wrap_toplevel, LPCSTR parent_class, LPCSTR child_class )
+{
+ static const struct exposure_test {
+ int ex_style, style;
+ } exposure_tests[] = {
+ { 0, WS_CLIPCHILDREN },
+ { 0, 0 },
+ { WS_EX_COMPOSITED, WS_CLIPCHILDREN },
+ { WS_EX_COMPOSITED, 0 },
+ };
+ size_t i;
+ HWND htoplevel = NULL, hparent, hchild;
+ RECT rect_old = { 10, 10, 100, 100 }, rect_cli;
+ HRGN hrgn_clip;
+ HRGN hrgn_old = CreateRectRgnIndirect( &rect_old );
+ HRGN hrgn_new = CreateRectRgn( 0, 0, 0, 0 );
+ HRGN hrgn_expect = CreateRectRgn( 0, 0, 0, 0 );
+ HRGN hrgn_actual = CreateRectRgn( 0, 0, 0, 0 );
+ int base_style;
+ BOOL is_composition_possible, has_parentdc_anomaly;
+ WNDCLASSA parent_wc;
+
+ if (wrap_toplevel)
+ {
+ htoplevel = CreateWindowExA( 0, "SimpleWindowClass", "Test toplevel", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+ 100, 100, 400, 400, 0, 0, 0, NULL );
+ ok( htoplevel != 0, "Failed to create top-level window: %lu\n", GetLastError() );
+ base_style = WS_CHILD | WS_VISIBLE;
+ }
+ else
+ {
+ base_style = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
+ }
+
+ ok( GetClassInfoA( GetModuleHandleA( NULL ), parent_class, &parent_wc ),
+ "GetClassInfoA failed\n" );
+
+ is_composition_possible = (base_style & (WS_POPUP|WS_CHILD)) != WS_CHILD ||
+ (parent_wc.style & CS_PARENTDC) == 0;
+
+ has_parentdc_anomaly = (base_style & (WS_POPUP|WS_CHILD)) != WS_CHILD &&
+ (parent_wc.style & CS_PARENTDC) != 0;
+
+ hparent = CreateWindowExA( 0, parent_class, "Test parent", base_style,
+ 80, 80, 200, 200, htoplevel, 0, 0, NULL );
+ ok( hparent != 0, "Creating parent window (%s) returned error %lu\n",
+ debugstr_a( parent_class ), GetLastError() );
+
+ hchild = CreateWindowExA( 0, child_class, "Test child", WS_CHILD | WS_VISIBLE | WS_BORDER,
+ rect_old.left, rect_old.top,
+ rect_old.right - rect_old.left, rect_old.bottom - rect_old.top,
+ hparent, 0, 0, NULL );
+ ok( hchild != 0, "Creating child window (%s) returned error %lu\n",
+ debugstr_a( child_class ), GetLastError() );
+
+ GetClientRect( hparent, &rect_cli );
+ hrgn_clip = CreateRectRgnIndirect( &rect_cli );
+
+ for (i = 0; i < ARRAY_SIZE(exposure_tests); i++)
+ {
+ const struct exposure_test *extest = &exposure_tests[i];
+ BOOL is_composited = (extest->ex_style & WS_EX_COMPOSITED) != 0;
+ int delta;
+
+ winetest_push_context( "%d: SetWindowPos redraw #%Id (ex_style = %#x, style = %#x)",
+ line, i, extest->ex_style, extest->style );
+
+ SetWindowLongA( hparent, GWL_EXSTYLE, extest->ex_style );
+ SetWindowLongA( hparent, GWL_STYLE, base_style | extest->style );
+ RedrawWindow( hparent, NULL, NULL, RDW_INVALIDATE|RDW_ERASE|RDW_FRAME );
+
+ for (delta = -20; delta <= 20; delta += 20)
+ {
+ RECT rect_new = rect_old;
+ int rgn_equal;
+ int region_op = (is_composition_possible && is_composited) ? RGN_OR : RGN_DIFF;
+
+ winetest_push_context( "delta = %+d", delta );
+
+ OffsetRect( &rect_new, delta, delta );
+ SetRectRgn( hrgn_new, rect_new.left, rect_new.top, rect_new.right, rect_new.bottom );
+ if (EqualRect( &rect_old, &rect_new ))
+ {
+ SetRectRgn( hrgn_expect, 0, 0, 0, 0 );
+ }
+ else
+ {
+ CombineRgn( hrgn_expect, hrgn_old, hrgn_new, region_op );
+ CombineRgn( hrgn_expect, hrgn_expect, hrgn_clip, RGN_AND );
+ }
+ SetRectRgn( hrgn_actual, 0, 0, 0, 0 );
+
+ SetWindowPos( hchild, 0,
+ rect_old.left,
+ rect_old.top,
+ rect_old.right - rect_old.left,
+ rect_old.bottom - rect_old.top,
+ SWP_NOACTIVATE | SWP_NOZORDER );
+
+ UpdateWindow( hparent );
+ flush_events();
+
+ SetWindowPos( hchild, 0,
+ rect_new.left,
+ rect_new.top,
+ rect_new.right - rect_new.left,
+ rect_new.bottom - rect_new.top,
+ SWP_NOACTIVATE | SWP_NOZORDER );
+
+ ok( GetUpdateRgn( hparent, hrgn_actual, FALSE ) != ERROR,
+ "GetUpdateRgn shall succeed\n" );
+
+ rgn_equal = EqualRgn( hrgn_expect, hrgn_actual );
+ if (!rgn_equal && broken( has_parentdc_anomaly && is_composited &&
+ LOBYTE(LOWORD(GetVersion())) < 8 ) /* Win7 */)
+ {
+ trace( "Forcing composited update region (broken)\n" );
+ CombineRgn( hrgn_expect, hrgn_old, hrgn_new, RGN_DIFF );
+ CombineRgn( hrgn_expect, hrgn_expect, hrgn_clip, RGN_AND );
+ rgn_equal = EqualRgn( hrgn_expect, hrgn_actual );
+ }
+ todo_wine_if( !EqualRect( &rect_old, &rect_new ) &&
+ ((extest->style & WS_CLIPCHILDREN) == 0 || region_op == RGN_OR) )
+ ok( !!rgn_equal, "Update region shall match expected region\n" );
+
+ flush_events();
+
+ if (!rgn_equal && winetest_debug > 0)
+ {
+ printf( "Expected update region: " );
+ dump_region( hrgn_expect );
+ printf( "Actual update region: " );
+ dump_region( hrgn_actual );
+ printf( "Old window position: " );
+ dump_region( hrgn_old );
+ printf( "New window position: " );
+ dump_region( hrgn_new );
+
+ if (winetest_interactive)
+ {
+ visualize_region_differences( hparent, hchild, hrgn_expect, hrgn_actual );
+ }
+ }
+
+ winetest_pop_context();
+ }
+
+ winetest_pop_context();
+ }
+
+ DestroyWindow( hchild );
+ DestroyWindow( hparent );
+ if (htoplevel) DestroyWindow( htoplevel );
+
+ DeleteObject( hrgn_actual );
+ DeleteObject( hrgn_expect );
+ DeleteObject( hrgn_new );
+ DeleteObject( hrgn_old );
+}
+
+static void test_swp_paint_regions(void)
+{
+ subtest_swp_paint_regions( 1, "SimpleWindowClass", "SimpleWindowClass" );
+ subtest_swp_paint_regions( 1, "SimpleWindowClass", "SimpleWindowClassWithParentDC" );
+ subtest_swp_paint_regions( 1, "SimpleWindowClassWithParentDC", "SimpleWindowClass" );
+ subtest_swp_paint_regions( 1, "SimpleWindowClassWithParentDC", "SimpleWindowClassWithParentDC" );
+ subtest_swp_paint_regions( 0, "SimpleWindowClass", "SimpleWindowClass" );
+ subtest_swp_paint_regions( 0, "SimpleWindowClass", "SimpleWindowClassWithParentDC" );
+ subtest_swp_paint_regions( 0, "SimpleWindowClassWithParentDC", "SimpleWindowClass" );
+ subtest_swp_paint_regions( 0, "SimpleWindowClassWithParentDC", "SimpleWindowClassWithParentDC" );
+}
+
struct wnd_event
{
HWND hwnd;
@@ -10387,6 +10659,11 @@ static BOOL RegisterWindowClasses(void)
cls.lpszClassName = "TestDialogClass";
if(!RegisterClassA(&cls)) return FALSE;
+ cls.lpfnWndProc = DefWindowProcA;
+ cls.style = CS_PARENTDC;
+ cls.lpszClassName = "SimpleWindowClassWithParentDC";
+ if(!RegisterClassA(&cls)) return FALSE;
+
clsW.style = 0;
clsW.lpfnWndProc = MsgCheckProcW;
clsW.cbClsExtra = 0;
@@ -18870,6 +19147,7 @@ START_TEST(msg)
test_combobox_messages();
test_wmime_keydown_message();
test_paint_messages();
+ test_swp_paint_regions();
test_interthread_messages();
test_message_conversion();
test_accelerators();
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/231
June 13, 2022
[PATCH v2 0/2] MR231: SetWindowPos() parent window exposure fixes (#53153)
by Jinoh Kang (@iamahuman)
Signed-off-by: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
--
v2: server: Correctly expose composited parent window on SetWindowPos().
user32/tests: Test for parent window exposure by SetWindowPos().
https://gitlab.winehq.org/wine/wine/-/merge_requests/231
June 13, 2022
Re: [PATCH 5/5] mfplat/buffer: Redirect all Lock2D() implementations to Lock2DSize().
by Nikolay Sivov
I didn't do that to avoid two traces per Lock2D() call. Why is it better
to forward?
June 13, 2022
Re: [PATCH 1/5] mfplat/buffer: Fix size for IMC2/IMC4 buffers with odd height.
by Nikolay Sivov
On 6/13/22 16:14, Giovanni Mascellani wrote:
> diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
> index 28b89de4b1f..8fddef8fd40 100644
> --- a/dlls/mfplat/tests/mfplat.c
> +++ b/dlls/mfplat/tests/mfplat.c
> @@ -5736,9 +5736,11 @@ static void test_MFCreate2DMediaBuffer(void)
> { 2, 2, MAKEFOURCC('I','M','C','2'), 6, 128, 0, 384 },
> { 4, 2, MAKEFOURCC('I','M','C','2'), 12, 128 },
> { 2, 4, MAKEFOURCC('I','M','C','2'), 12, 128 },
> + { 3, 5, MAKEFOURCC('I','M','C','2'), 20, 128 },
> { 2, 2, MAKEFOURCC('I','M','C','4'), 6, 128 },
> { 4, 2, MAKEFOURCC('I','M','C','4'), 12, 128 },
> { 2, 4, MAKEFOURCC('I','M','C','4'), 12, 128 },
> + { 3, 5, MAKEFOURCC('I','M','C','4'), 20, 128 },
>
> { 4, 2, MAKEFOURCC('I','M','C','1'), 32, 128, 2 },
> { 4, 4, MAKEFOURCC('I','M','C','1'), 64, 128, 2 },
> @@ -5998,13 +6000,6 @@ static void test_MFCreate2DMediaBuffer(void)
> hr = IMFMediaBuffer_Unlock(buffer);
> ok(hr == S_OK, "Failed to unlock buffer, hr %#lx.\n", hr);
>
> - hr = pMFGetPlaneSize(ptr->fourcc, ptr->width, ptr->height, &length2);
> - ok(hr == S_OK, "Failed to get plane size, hr %#lx.\n", hr);
> - if (ptr->plane_multiplier)
> - length2 *= ptr->plane_multiplier;
> - ok(length2 == length, "%d: contiguous length %lu does not match plane size %lu, %u x %u, format %s.\n", i, length,
> - length2, ptr->width, ptr->height, wine_dbgstr_an((char *)&ptr->fourcc, 4));
> -
Do we have all interesting tests cases for MFGetPlaneSize duplicated in
other tests, to remove this one? Also if it needs to be removed
multiplier field becomes unused.
June 13, 2022
[PATCH v5 3/3] 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 | 29 +++++++++++++++++++++++++++++
dlls/riched20/tests/richole.c | 2 --
2 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c
index 936f1c928b3..3d88b8a65b0 100644
--- a/dlls/riched20/richole.c
+++ b/dlls/riched20/richole.c
@@ -5733,6 +5733,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 +5746,34 @@ 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;
+ RECTL bounds;
+
+ convert_sizel(c, &run->reobj->obj.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);
+ }
+
+ bounds.left = x;
+ bounds.top = y - sz.cy;
+ bounds.right = x + sz.cx;
+ bounds.bottom = y;
+
+ hr = IViewObject_Draw(ivo, DVASPECT_CONTENT, -1, 0, 0, 0, c->hDC, &bounds, 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 db9d123815e..6a361bc3fa4 100644
--- a/dlls/riched20/tests/richole.c
+++ b/dlls/riched20/tests/richole.c
@@ -4193,7 +4193,6 @@ static void subtest_InsertObject(struct reolecb_obj *callback)
UpdateWindow(hwnd);
testobj->line = __LINE__;
flush_dispatch_messages();
- todo_wine
ok(testobj->draw_count != 0, "expected draw_count to be nonzero, got %d\n", testobj->draw_count);
SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"");
@@ -4225,7 +4224,6 @@ static void subtest_InsertObject(struct reolecb_obj *callback)
UpdateWindow(hwnd);
testobj->line = __LINE__;
flush_dispatch_messages();
- todo_wine
ok(testobj->draw_count != 0, "expected draw_count to be nonzero, got %d\n", testobj->draw_count);
SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"");
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/227
June 13, 2022
[PATCH v5 2/3] riched20: Fetch extent from object if REOBJECT::sizel is unset.
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/caret.c | 13 +++++++++++++
dlls/riched20/tests/richole.c | 2 --
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c
index 09ec0ffc735..c9fd327e87e 100644
--- a/dlls/riched20/caret.c
+++ b/dlls/riched20/caret.c
@@ -464,6 +464,7 @@ HRESULT editor_insert_oleobj(ME_TextEditor *editor, const REOBJECT *reo)
ME_Cursor *cursor, cursor_from_ofs;
ME_Style *style;
HRESULT hr;
+ SIZEL extent;
if (editor->lpOleCallback)
{
@@ -472,6 +473,17 @@ HRESULT editor_insert_oleobj(ME_TextEditor *editor, const REOBJECT *reo)
return hr;
}
+ extent = reo->sizel;
+ if (!extent.cx && !extent.cy && reo->poleobj)
+ {
+ hr = IOleObject_GetExtent( reo->poleobj, DVASPECT_CONTENT, &extent );
+ if (FAILED(hr))
+ {
+ extent.cx = 0;
+ extent.cy = 0;
+ }
+ }
+
if (reo->cp == REO_CP_SELECTION)
cursor = editor->pCursors;
else
@@ -487,6 +499,7 @@ HRESULT editor_insert_oleobj(ME_TextEditor *editor, const REOBJECT *reo)
run = run_insert( editor, cursor, style, &space, 1, MERF_GRAPHICS );
run->reobj = create_re_object( reo, run );
+ run->reobj->obj.sizel = extent;
prev = run;
while ((prev = run_prev_all_paras( prev )))
diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c
index bb7ee869e0d..db9d123815e 100644
--- a/dlls/riched20/tests/richole.c
+++ b/dlls/riched20/tests/richole.c
@@ -4217,9 +4217,7 @@ static void subtest_InsertObject(struct reolecb_obj *callback)
reobj.cbStruct = sizeof(reobj);
hr = IRichEditOle_GetObject(reole, 0, &reobj, REO_GETOBJ_NO_INTERFACES);
ok(hr == S_OK, "IRichEditOle_GetObject got hr %#lx.\n", hr);
- todo_wine
ok(reobj.sizel.cx == 800, "expected reobj.sizel.cx to be %ld, got %ld\n", 800L, reobj.sizel.cx);
- todo_wine
ok(reobj.sizel.cy == 400, "expected reobj.sizel.cy to be %ld, got %ld\n", 400L, reobj.sizel.cy);
IOleClientSite_Release(clientsite);
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/227
June 13, 2022
[PATCH v5 1/3] 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 | 474 +++++++++++++++++++++++++++++++++-
1 file changed, 471 insertions(+), 3 deletions(-)
diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c
index c34c87ef646..bb7ee869e0d 100644
--- a/dlls/riched20/tests/richole.c
+++ b/dlls/riched20/tests/richole.c
@@ -212,6 +212,396 @@ 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;
+
+ IOleClientSite *clientsite;
+ IOleAdviseHolder *advise_holder;
+ SIZEL extent;
+
+ IViewObject IViewObject_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 ))
+ {
+ *obj = &This->IViewObject_iface;
+ }
+ else
+ {
+ if (!IsEqualGUID( riid, &IID_IOleLink ) &&
+ !IsEqualGUID( riid, &IID_IRunnableObject ) &&
+ !IsEqualGUID( riid, &IID_IMarshal ))
+ {
+ 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;
+ }
+ 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_IViewObject( IViewObject *iface )
+{
+ return CONTAINING_RECORD( iface, struct testoleobj, IViewObject_iface );
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IViewObject_QueryInterface( IViewObject *iface, REFIID riid, void **obj )
+{
+ struct testoleobj *This = impl_from_IViewObject( iface );
+ return IOleObject_QueryInterface( &This->IOleObject_iface, riid, obj );
+}
+
+static ULONG STDMETHODCALLTYPE testoleobj_IViewObject_AddRef( IViewObject *iface )
+{
+ struct testoleobj *This = impl_from_IViewObject( iface );
+ return IOleObject_AddRef( &This->IOleObject_iface );
+}
+
+static ULONG STDMETHODCALLTYPE testoleobj_IViewObject_Release( IViewObject *iface )
+{
+ struct testoleobj *This = impl_from_IViewObject( iface );
+ return IOleObject_Release( &This->IOleObject_iface );
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IViewObject_Draw( IViewObject *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_IViewObject( 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_IViewObject_GetColorSet( IViewObject *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_IViewObject_Freeze( IViewObject *iface, DWORD draw_aspect,
+ LONG index, void *aspect, DWORD *freeze )
+{
+ *freeze = 0;
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IViewObject_Unfreeze( IViewObject *iface, DWORD freeze )
+{
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IViewObject_SetAdvise( IViewObject *iface, DWORD aspects,
+ DWORD advf, IAdviseSink *adv_sink )
+{
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IViewObject_GetAdvise( IViewObject *iface, DWORD *aspects,
+ DWORD *advf, IAdviseSink **adv_sink )
+{
+ *aspects = 0;
+ *advf = 0;
+ *adv_sink = NULL;
+ return E_NOTIMPL;
+}
+
+static const struct IViewObjectVtbl testoleobj_IViewObject_Vtbl = {
+ testoleobj_IViewObject_QueryInterface,
+ testoleobj_IViewObject_AddRef,
+ testoleobj_IViewObject_Release,
+ testoleobj_IViewObject_Draw,
+ testoleobj_IViewObject_GetColorSet,
+ testoleobj_IViewObject_Freeze,
+ testoleobj_IViewObject_Unfreeze,
+ testoleobj_IViewObject_SetAdvise,
+ testoleobj_IViewObject_GetAdvise,
+};
+
+static HRESULT testoleobj_Create( struct testoleobj **objptr )
+{
+ struct testoleobj *obj;
+
+ obj = calloc( sizeof(struct testoleobj), 1 );
+ *objptr = obj;
+ if (!obj) return E_OUTOFMEMORY;
+
+ obj->IOleObject_iface.lpVtbl = &testoleobj_IOleObject_Vtbl;
+ obj->ref = 1;
+ obj->IViewObject_iface.lpVtbl = &testoleobj_IViewObject_Vtbl;
+
+ return S_OK;
+}
+
static HMODULE hmoduleRichEdit;
DEFINE_GUID(GUID_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@@ -3431,6 +3821,16 @@ static void _insert_reobject(struct reolecb_obj *callback, IRichEditOle *reole,
olecb_check_QueryInsertObject(callback, line);
}
+static void flush_dispatch_messages(void)
+{
+ MSG msg;
+ while (PeekMessageW( &msg, NULL, 0, 0, PM_REMOVE ))
+ {
+ TranslateMessage( &msg );
+ DispatchMessageW( &msg );
+ }
+}
+
static void subtest_InsertObject(struct reolecb_obj *callback)
{
static CHAR test_text1[] = "abcdefg";
@@ -3453,6 +3853,9 @@ static void subtest_InsertObject(struct reolecb_obj *callback)
LONG count, result;
ITextRange *range;
BSTR bstr;
+ struct testoleobj *testobj;
+ IOleClientSite *clientsite;
+ REOBJECT reobj;
create_interfaces(&hwnd, &reole, &doc, &selection);
if (callback)
@@ -3486,9 +3889,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 +4165,74 @@ 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 = testoleobj_Create(&testobj);
+ ok(hr == S_OK, "testoleobj_Create got hr %#lx.\n", hr);
+ testobj->extent.cx = 800;
+ testobj->extent.cy = 400;
+
+ SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"");
+ testobj->draw_count = 0;
+ testobj->line = __LINE__;
+
+ hr = IRichEditOle_GetClientSite(reole, &clientsite);
+ ok(hr == S_OK, "IRichEditOle_GetClientSite got hr %#lx.\n", hr);
+ hr = IOleObject_SetClientSite(&testobj->IOleObject_iface, clientsite);
+ ok(hr == S_OK, "IOleObject_SetClientSite got hr %#lx.\n", hr);
+
+ 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, 800, 400, 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__);
+
+ IOleClientSite_Release(clientsite);
+
+ testobj->line = __LINE__;
+ UpdateWindow(hwnd);
+ testobj->line = __LINE__;
+ flush_dispatch_messages();
+ todo_wine
+ ok(testobj->draw_count != 0, "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__;
+
+ hr = IRichEditOle_GetClientSite(reole, &clientsite);
+ ok(hr == S_OK, "IRichEditOle_GetClientSite got hr %#lx.\n", hr);
+ hr = IOleObject_SetClientSite(&testobj->IOleObject_iface, clientsite);
+ ok(hr == S_OK, "IOleObject_SetClientSite got hr %#lx.\n", hr);
+
+ 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__);
+
+ memset(&reobj, 0xcc, sizeof(reobj));
+ reobj.cbStruct = sizeof(reobj);
+ hr = IRichEditOle_GetObject(reole, 0, &reobj, REO_GETOBJ_NO_INTERFACES);
+ ok(hr == S_OK, "IRichEditOle_GetObject got hr %#lx.\n", hr);
+ todo_wine
+ ok(reobj.sizel.cx == 800, "expected reobj.sizel.cx to be %ld, got %ld\n", 800L, reobj.sizel.cx);
+ todo_wine
+ ok(reobj.sizel.cy == 400, "expected reobj.sizel.cy to be %ld, got %ld\n", 400L, reobj.sizel.cy);
+ IOleClientSite_Release(clientsite);
+
+ testobj->line = __LINE__;
+ UpdateWindow(hwnd);
+ testobj->line = __LINE__;
+ flush_dispatch_messages();
+ todo_wine
+ ok(testobj->draw_count != 0, "expected draw_count to be nonzero, got %d\n", testobj->draw_count);
+
+ SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"");
+ IOleObject_Release(&testobj->IOleObject_iface);
+
if (callback)
{
LRESULT sendres = SendMessageA(hwnd, EM_SETOLECALLBACK, 0, 0);
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/227
June 13, 2022
[PATCH v5 0/3] MR227: riched20: Fix for #52752 (use IViewObject implementation)
by Jinoh Kang (@iamahuman)
Fixes https://bugs.winehq.org/show_bug.cgi?id=52752.
--
v5: riched20: Draw OLE objects with IViewObject implementation.
riched20: Fetch extent from object if REOBJECT::sizel is unset.
riched20/tests: Add tests for drawing embedded OLE objects.
https://gitlab.winehq.org/wine/wine/-/merge_requests/227
June 13, 2022
[PATCH 1/1] winebus.sys: Implement SOCD neutral cleaning for hatswitches.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52841
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/winebus.sys/bus_sdl.c | 27 +++++++++++++++------------
dlls/winebus.sys/hid.c | 11 +++++++++++
dlls/winebus.sys/unix_private.h | 1 +
3 files changed, 27 insertions(+), 12 deletions(-)
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c
index 7dc47cdd518..5d810d25205 100644
--- a/dlls/winebus.sys/bus_sdl.c
+++ b/dlls/winebus.sys/bus_sdl.c
@@ -382,6 +382,8 @@ static NTSTATUS build_controller_report_descriptor(struct unix_device *iface)
static const USAGE trigger_axis_usages[] = {HID_USAGE_GENERIC_Z, HID_USAGE_GENERIC_RZ};
struct sdl_device *impl = impl_from_unix_device(iface);
ULONG i, button_count = SDL_CONTROLLER_BUTTON_MAX - 1;
+ BOOL state;
+
C_ASSERT(SDL_CONTROLLER_AXIS_MAX == 6);
if (!hid_device_begin_report_descriptor(iface, &device_usage))
@@ -420,14 +422,15 @@ static NTSTATUS build_controller_report_descriptor(struct unix_device *iface)
/* Initialize axis in the report */
for (i = SDL_CONTROLLER_AXIS_LEFTX; i < SDL_CONTROLLER_AXIS_MAX; i++)
hid_device_set_abs_axis(iface, i, pSDL_GameControllerGetAxis(impl->sdl_controller, i));
- if (pSDL_GameControllerGetButton(impl->sdl_controller, SDL_CONTROLLER_BUTTON_DPAD_UP))
- hid_device_set_hatswitch_y(iface, 0, -1);
- if (pSDL_GameControllerGetButton(impl->sdl_controller, SDL_CONTROLLER_BUTTON_DPAD_DOWN))
- hid_device_set_hatswitch_y(iface, 0, +1);
- if (pSDL_GameControllerGetButton(impl->sdl_controller, SDL_CONTROLLER_BUTTON_DPAD_LEFT))
- hid_device_set_hatswitch_x(iface, 0, -1);
- if (pSDL_GameControllerGetButton(impl->sdl_controller, SDL_CONTROLLER_BUTTON_DPAD_RIGHT))
- hid_device_set_hatswitch_x(iface, 0, +1);
+
+ state = pSDL_GameControllerGetButton(impl->sdl_controller, SDL_CONTROLLER_BUTTON_DPAD_UP);
+ hid_device_move_hatswitch(iface, 0, 0, state ? -1 : +1);
+ state = pSDL_GameControllerGetButton(impl->sdl_controller, SDL_CONTROLLER_BUTTON_DPAD_DOWN);
+ hid_device_move_hatswitch(iface, 0, 0, state ? +1 : -1);
+ state = pSDL_GameControllerGetButton(impl->sdl_controller, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
+ hid_device_move_hatswitch(iface, 0, state ? -1 : +1, 0);
+ state = pSDL_GameControllerGetButton(impl->sdl_controller, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
+ hid_device_move_hatswitch(iface, 0, state ? +1 : -1, 0);
return STATUS_SUCCESS;
}
@@ -873,16 +876,16 @@ static BOOL set_report_from_controller_event(struct sdl_device *impl, SDL_Event
switch ((button = ie->button))
{
case SDL_CONTROLLER_BUTTON_DPAD_UP:
- hid_device_set_hatswitch_y(iface, 0, ie->state ? -1 : 0);
+ hid_device_move_hatswitch(iface, 0, 0, ie->state ? -1 : +1);
break;
case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
- hid_device_set_hatswitch_y(iface, 0, ie->state ? +1 : 0);
+ hid_device_move_hatswitch(iface, 0, 0, ie->state ? +1 : -1);
break;
case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
- hid_device_set_hatswitch_x(iface, 0, ie->state ? -1 : 0);
+ hid_device_move_hatswitch(iface, 0, ie->state ? -1 : +1, 0);
break;
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
- hid_device_set_hatswitch_x(iface, 0, ie->state ? +1 : 0);
+ hid_device_move_hatswitch(iface, 0, ie->state ? +1 : -1, 0);
break;
case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: button = 4; break;
case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: button = 5; break;
diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c
index 8ed8c752893..c5543e081ae 100644
--- a/dlls/winebus.sys/hid.c
+++ b/dlls/winebus.sys/hid.c
@@ -1453,6 +1453,17 @@ BOOL hid_device_set_hatswitch_y(struct unix_device *iface, ULONG index, LONG new
return TRUE;
}
+BOOL hid_device_move_hatswitch(struct unix_device *iface, ULONG index, LONG x, LONG y)
+{
+ struct hid_device_state *state = &iface->hid_device_state;
+ ULONG offset = state->hatswitch_start + index;
+ LONG old_x, old_y;
+ if (index > state->hatswitch_count) return FALSE;
+ hatswitch_decompose(state->report_buf[offset], &old_x, &old_y);
+ hatswitch_compose(old_x + x, old_y + y, &state->report_buf[offset]);
+ return TRUE;
+}
+
BOOL hid_device_sync_report(struct unix_device *iface)
{
BOOL dropped;
diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h
index f94a243d887..85eab6ccf5d 100644
--- a/dlls/winebus.sys/unix_private.h
+++ b/dlls/winebus.sys/unix_private.h
@@ -257,6 +257,7 @@ extern BOOL hid_device_set_rel_axis(struct unix_device *iface, ULONG index, LONG
extern BOOL hid_device_set_button(struct unix_device *iface, ULONG index, BOOL is_set) DECLSPEC_HIDDEN;
extern BOOL hid_device_set_hatswitch_x(struct unix_device *iface, ULONG index, LONG new_x) DECLSPEC_HIDDEN;
extern BOOL hid_device_set_hatswitch_y(struct unix_device *iface, ULONG index, LONG new_y) DECLSPEC_HIDDEN;
+extern BOOL hid_device_move_hatswitch(struct unix_device *iface, ULONG index, LONG x, LONG y) DECLSPEC_HIDDEN;
extern BOOL hid_device_sync_report(struct unix_device *iface) DECLSPEC_HIDDEN;
extern void hid_device_drop_report(struct unix_device *iface) DECLSPEC_HIDDEN;
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/236
June 13, 2022