This fixes an application that expects to go through full UI activation after IOleObject::DoVerb(OLEIVERB_HIDE) + IOleObject::DoVerb(OLEIVERB_UIACTIVATE).
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/ieframe/ieframe.h | 2 + dlls/ieframe/oleobject.c | 44 +++++++--- dlls/ieframe/tests/webbrowser.c | 148 +++++++++++++++++++++++++++++++- 3 files changed, 177 insertions(+), 17 deletions(-)
diff --git a/dlls/ieframe/ieframe.h b/dlls/ieframe/ieframe.h index 329cea2f7c..24d490c272 100644 --- a/dlls/ieframe/ieframe.h +++ b/dlls/ieframe/ieframe.h @@ -210,6 +210,8 @@ struct WebBrowser { OLEINPLACEFRAMEINFO frameinfo; SIZEL extent;
+ BOOL ui_activated; + HWND shell_embedding_hwnd;
VARIANT_BOOL register_browser; diff --git a/dlls/ieframe/oleobject.c b/dlls/ieframe/oleobject.c index 031994caa5..a2f87dda2f 100644 --- a/dlls/ieframe/oleobject.c +++ b/dlls/ieframe/oleobject.c @@ -214,6 +214,9 @@ static HRESULT activate_ui(WebBrowser *This, IOleClientSite *active_site) if(FAILED(hres)) return hres;
+ if(This->ui_activated) + return S_OK; + IOleInPlaceSiteEx_OnUIActivate(This->inplace);
if(This->doc_host.frame) @@ -227,6 +230,8 @@ static HRESULT activate_ui(WebBrowser *This, IOleClientSite *active_site) SetFocus(This->shell_embedding_hwnd); notify_on_focus(This, TRUE);
+ This->ui_activated = TRUE; + return S_OK; }
@@ -579,6 +584,26 @@ static HRESULT WINAPI OleObject_SetHostNames(IOleObject *iface, LPCOLESTR szCont return S_OK; }
+static void deactivate_ui(WebBrowser *This) +{ + if(This->ui_activated) { + if(This->doc_host.frame) + IOleInPlaceFrame_SetActiveObject(This->doc_host.frame, NULL, NULL); + + if(This->uiwindow) + IOleInPlaceUIWindow_SetActiveObject(This->uiwindow, NULL, NULL); + + if(This->inplace) + IOleInPlaceSiteEx_OnUIDeactivate(This->inplace, FALSE); + notify_on_focus(This, FALSE); + + This->ui_activated = FALSE; + } + + if(This->inplace) + IOleInPlaceSiteEx_OnInPlaceDeactivate(This->inplace); +} + static HRESULT WINAPI OleObject_Close(IOleObject *iface, DWORD dwSaveOption) { WebBrowser *This = impl_from_IOleObject(iface); @@ -592,17 +617,7 @@ static HRESULT WINAPI OleObject_Close(IOleObject *iface, DWORD dwSaveOption) return E_NOTIMPL; }
- if(This->doc_host.frame) - IOleInPlaceFrame_SetActiveObject(This->doc_host.frame, NULL, NULL); - - if(This->uiwindow) - IOleInPlaceUIWindow_SetActiveObject(This->uiwindow, NULL, NULL); - - if(This->inplace) - IOleInPlaceSiteEx_OnUIDeactivate(This->inplace, FALSE); - notify_on_focus(This, FALSE); - if(This->inplace) - IOleInPlaceSiteEx_OnInPlaceDeactivate(This->inplace); + deactivate_ui(This);
/* store old client site - we need to restore it in DoVerb */ client = This->client; @@ -677,8 +692,11 @@ static HRESULT WINAPI OleObject_DoVerb(IOleObject *iface, LONG iVerb, struct tag return activate_inplace(This, pActiveSite); case OLEIVERB_HIDE: TRACE("OLEIVERB_HIDE\n"); - if(This->inplace) - IOleInPlaceSiteEx_OnInPlaceDeactivate(This->inplace); + if(This->inplace) { + deactivate_ui(This); + IOleInPlaceSiteEx_Release(This->inplace); + This->inplace = NULL; + } if(This->shell_embedding_hwnd) ShowWindow(This->shell_embedding_hwnd, SW_HIDE); return S_OK; diff --git a/dlls/ieframe/tests/webbrowser.c b/dlls/ieframe/tests/webbrowser.c index e0af0d4642..fc6dbb6756 100644 --- a/dlls/ieframe/tests/webbrowser.c +++ b/dlls/ieframe/tests/webbrowser.c @@ -167,7 +167,8 @@ static VARIANT_BOOL exvb; static IWebBrowser2 *wb;
static HWND container_hwnd, shell_embedding_hwnd; -static BOOL is_downloading, do_download, is_first_load, use_container_olecmd, test_close, is_http, use_container_dochostui; +static BOOL is_downloading, do_download, is_first_load, use_container_olecmd; +static BOOL test_close, test_hide, is_http, use_container_dochostui; static HRESULT hr_dochost_TranslateAccelerator = E_NOTIMPL; static HRESULT hr_site_TranslateAccelerator = E_NOTIMPL; static const WCHAR *current_url; @@ -1265,7 +1266,7 @@ static HRESULT WINAPI InPlaceUIWindow_SetActiveObject(IOleInPlaceFrame *iface, IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName) { CHECK_EXPECT(UIWindow_SetActiveObject); - if(!test_close) { + if(!test_close && !test_hide) { ok(pActiveObject != NULL, "pActiveObject = NULL\n"); ok(!lstrcmpW(pszObjName, wszItem), "unexpected pszObjName\n"); } else { @@ -1279,7 +1280,7 @@ static HRESULT WINAPI InPlaceFrame_SetActiveObject(IOleInPlaceFrame *iface, IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName) { CHECK_EXPECT(Frame_SetActiveObject); - if(!test_close) { + if(!test_close && !test_hide) { ok(pActiveObject != NULL, "pActiveObject = NULL\n"); ok(!lstrcmpW(pszObjName, wszItem), "unexpected pszObjName\n"); } else { @@ -1838,6 +1839,7 @@ static void test_DoVerb(IWebBrowser2 *unk) RECT rect = {0,0,1000,1000}; HRESULT hres; DWORD connection; + VARIANT_BOOL b;
hres = IWebBrowser2_QueryInterface(unk, &IID_IOleObject, (void**)&oleobj); ok(hres == S_OK, "QueryInterface(IID_OleObject) failed: %08x\n", hres); @@ -1847,6 +1849,77 @@ static void test_DoVerb(IWebBrowser2 *unk) hres = IOleObject_Advise(oleobj, &test_sink, &connection); ok(hres == S_OK, "Advise failed: %08x\n", hres);
+ b = 0x100; + hres = IWebBrowser2_get_Visible(unk, &b); + ok(hres == S_OK, "get_Visible failed: %08x\n", hres); + ok(b == VARIANT_TRUE, "Visible = %x\n", b); + + SET_EXPECT(CanInPlaceActivate); + SET_EXPECT(Site_GetWindow); + SET_EXPECT(OnInPlaceActivate); + SET_EXPECT(GetWindowContext); + SET_EXPECT(ShowObject); + SET_EXPECT(GetContainer); + SET_EXPECT(Frame_GetWindow); + SET_EXPECT(OnUIActivate); + SET_EXPECT(Frame_SetActiveObject); + SET_EXPECT(UIWindow_SetActiveObject); + SET_EXPECT(SetMenu); + SET_EXPECT(OnFocus_TRUE); + + hres = IOleObject_DoVerb(oleobj, OLEIVERB_SHOW, NULL, &ClientSite, + 0, (HWND)0xdeadbeef, &rect); + ok(hres == S_OK, "DoVerb failed: %08x\n", hres); + + CHECK_CALLED(CanInPlaceActivate); + CHECK_CALLED(Site_GetWindow); + CHECK_CALLED(OnInPlaceActivate); + CHECK_CALLED(GetWindowContext); + CHECK_CALLED(ShowObject); + CHECK_CALLED(GetContainer); + CHECK_CALLED(Frame_GetWindow); + CHECK_CALLED(OnUIActivate); + CHECK_CALLED(Frame_SetActiveObject); + CHECK_CALLED(UIWindow_SetActiveObject); + CHECK_CALLED(SetMenu); + CHECK_CALLED(OnFocus_TRUE); + + b = 0x100; + hres = IWebBrowser2_get_Visible(unk, &b); + ok(hres == S_OK, "get_Visible failed: %08x\n", hres); + ok(b == VARIANT_TRUE, "Visible = %x\n", b); + + hres = IOleObject_DoVerb(oleobj, OLEIVERB_SHOW, NULL, &ClientSite, + 0, (HWND)0xdeadbeef, &rect); + ok(hres == S_OK, "DoVerb failed: %08x\n", hres); + + hres = IOleObject_DoVerb(oleobj, OLEIVERB_UIACTIVATE, NULL, &ClientSite, + 0, (HWND)0xdeadbeef, &rect); + ok(hres == S_OK, "DoVerb failed: %08x\n", hres); + + SET_EXPECT(Frame_SetActiveObject); + SET_EXPECT(UIWindow_SetActiveObject); + SET_EXPECT(OnUIDeactivate); + SET_EXPECT(OnFocus_FALSE); + SET_EXPECT(OnInPlaceDeactivate); + + test_hide = TRUE; + hres = IOleObject_DoVerb(oleobj, OLEIVERB_HIDE, NULL, &ClientSite, + 0, (HWND)0xdeadbeef, &rect); + ok(hres == S_OK, "DoVerb failed: %08x\n", hres); + test_hide = FALSE; + + CHECK_CALLED(Frame_SetActiveObject); + CHECK_CALLED(UIWindow_SetActiveObject); + CHECK_CALLED(OnUIDeactivate); + CHECK_CALLED(OnFocus_FALSE); + CHECK_CALLED(OnInPlaceDeactivate); + + b = 0x100; + hres = IWebBrowser2_get_Visible(unk, &b); + ok(hres == S_OK, "get_Visible failed: %08x\n", hres); + ok(b == VARIANT_TRUE, "Visible = %x\n", b); + SET_EXPECT(CanInPlaceActivate); SET_EXPECT(Site_GetWindow); SET_EXPECT(OnInPlaceActivate); @@ -1877,6 +1950,73 @@ static void test_DoVerb(IWebBrowser2 *unk) CHECK_CALLED(SetMenu); CHECK_CALLED(OnFocus_TRUE);
+ b = 0x100; + hres = IWebBrowser2_get_Visible(unk, &b); + ok(hres == S_OK, "get_Visible failed: %08x\n", hres); + ok(b == VARIANT_TRUE, "Visible = %x\n", b); + + SET_EXPECT(Frame_SetActiveObject); + SET_EXPECT(UIWindow_SetActiveObject); + SET_EXPECT(OnUIDeactivate); + SET_EXPECT(OnFocus_FALSE); + SET_EXPECT(OnInPlaceDeactivate); + + test_hide = TRUE; + hres = IOleObject_DoVerb(oleobj, OLEIVERB_HIDE, NULL, &ClientSite, + 0, (HWND)0xdeadbeef, &rect); + ok(hres == S_OK, "DoVerb failed: %08x\n", hres); + + CHECK_CALLED(Frame_SetActiveObject); + CHECK_CALLED(UIWindow_SetActiveObject); + CHECK_CALLED(OnUIDeactivate); + CHECK_CALLED(OnFocus_FALSE); + CHECK_CALLED(OnInPlaceDeactivate); + + hres = IOleObject_DoVerb(oleobj, OLEIVERB_HIDE, NULL, &ClientSite, + 0, (HWND)0xdeadbeef, &rect); + ok(hres == S_OK, "DoVerb failed: %08x\n", hres); + test_hide = FALSE; + + b = 0x100; + hres = IWebBrowser2_get_Visible(unk, &b); + ok(hres == S_OK, "get_Visible failed: %08x\n", hres); + ok(b == VARIANT_TRUE, "Visible = %x\n", b); + + SET_EXPECT(CanInPlaceActivate); + SET_EXPECT(Site_GetWindow); + SET_EXPECT(OnInPlaceActivate); + SET_EXPECT(GetWindowContext); + SET_EXPECT(ShowObject); + SET_EXPECT(GetContainer); + SET_EXPECT(Frame_GetWindow); + SET_EXPECT(OnUIActivate); + SET_EXPECT(Frame_SetActiveObject); + SET_EXPECT(UIWindow_SetActiveObject); + SET_EXPECT(SetMenu); + SET_EXPECT(OnFocus_TRUE); + + hres = IOleObject_DoVerb(oleobj, OLEIVERB_UIACTIVATE, NULL, &ClientSite, + 0, (HWND)0xdeadbeef, &rect); + ok(hres == S_OK, "DoVerb failed: %08x\n", hres); + + CHECK_CALLED(CanInPlaceActivate); + CHECK_CALLED(Site_GetWindow); + CHECK_CALLED(OnInPlaceActivate); + CHECK_CALLED(GetWindowContext); + CHECK_CALLED(ShowObject); + CHECK_CALLED(GetContainer); + CHECK_CALLED(Frame_GetWindow); + CHECK_CALLED(OnUIActivate); + CHECK_CALLED(Frame_SetActiveObject); + CHECK_CALLED(UIWindow_SetActiveObject); + CHECK_CALLED(SetMenu); + CHECK_CALLED(OnFocus_TRUE); + + b = 0x100; + hres = IWebBrowser2_get_Visible(unk, &b); + ok(hres == S_OK, "get_Visible failed: %08x\n", hres); + ok(b == VARIANT_TRUE, "Visible = %x\n", b); + hres = IOleObject_DoVerb(oleobj, OLEIVERB_SHOW, NULL, &ClientSite, 0, (HWND)0xdeadbeef, &rect); ok(hres == S_OK, "DoVerb failed: %08x\n", hres); @@ -3743,7 +3883,7 @@ static void test_Close(IWebBrowser2 *wb, BOOL do_download) SET_EXPECT(Advise_OnClose); hres = IOleObject_Close(oo, OLECLOSE_NOSAVE); ok(hres == S_OK, "OleObject_Close failed: %x\n", hres); - todo_wine CHECK_NOT_CALLED(OnFocus_FALSE); + CHECK_NOT_CALLED(OnFocus_FALSE); todo_wine CHECK_NOT_CALLED(Invoke_COMMANDSTATECHANGE_NAVIGATEBACK_FALSE); todo_wine CHECK_NOT_CALLED(Invoke_COMMANDSTATECHANGE_NAVIGATEFORWARD_FALSE); CHECK_CALLED(Advise_OnClose);
Hi Dmitry,
On 04.08.2020 11:01, Dmitry Timoshkov wrote:
@@ -1847,6 +1849,77 @@ static void test_DoVerb(IWebBrowser2 *unk) hres = IOleObject_Advise(oleobj, &test_sink, &connection); ok(hres == S_OK, "Advise failed: %08x\n", hres);
- b = 0x100;
- hres = IWebBrowser2_get_Visible(unk, &b);
- ok(hres == S_OK, "get_Visible failed: %08x\n", hres);
- ok(b == VARIANT_TRUE, "Visible = %x\n", b);
- SET_EXPECT(CanInPlaceActivate);
- SET_EXPECT(Site_GetWindow);
- SET_EXPECT(OnInPlaceActivate);
- SET_EXPECT(GetWindowContext);
- SET_EXPECT(ShowObject);
- SET_EXPECT(GetContainer);
- SET_EXPECT(Frame_GetWindow);
- SET_EXPECT(OnUIActivate);
- SET_EXPECT(Frame_SetActiveObject);
- SET_EXPECT(UIWindow_SetActiveObject);
- SET_EXPECT(SetMenu);
- SET_EXPECT(OnFocus_TRUE);
- hres = IOleObject_DoVerb(oleobj, OLEIVERB_SHOW, NULL, &ClientSite,
0, (HWND)0xdeadbeef, &rect);
- ok(hres == S_OK, "DoVerb failed: %08x\n", hres);
- CHECK_CALLED(CanInPlaceActivate);
- CHECK_CALLED(Site_GetWindow);
- CHECK_CALLED(OnInPlaceActivate);
- CHECK_CALLED(GetWindowContext);
- CHECK_CALLED(ShowObject);
- CHECK_CALLED(GetContainer);
- CHECK_CALLED(Frame_GetWindow);
- CHECK_CALLED(OnUIActivate);
- CHECK_CALLED(Frame_SetActiveObject);
- CHECK_CALLED(UIWindow_SetActiveObject);
- CHECK_CALLED(SetMenu);
- CHECK_CALLED(OnFocus_TRUE);
The patch looks mostly good to me, but could you please move tests to test_WebBrowser_DoVerb? test_DoVerb is a bit unfortunate name, it's effectively used in a few places as a helper for DoVerb(OLEIVERB_SHOW) call.
Thanks,
Jacek