[PATCH v2] ieframe: Deactivate UI when processing IOleObject::DoVerb(OLEIVERB_HIDE).

Dmitry Timoshkov dmitry at baikal.ru
Tue Aug 4 10:56:26 CDT 2020


This fixes an application that expects to go through full UI activation after
IOleObject::DoVerb(OLEIVERB_HIDE) + IOleObject::DoVerb(OLEIVERB_UIACTIVATE).

v2: Move the tests to test_WebBrowser_DoVerb().

Signed-off-by: Dmitry Timoshkov <dmitry at baikal.ru>
---
 dlls/ieframe/ieframe.h          |   2 +
 dlls/ieframe/oleobject.c        |  44 ++++++---
 dlls/ieframe/tests/webbrowser.c | 154 +++++++++++++++++++++++++++++++-
 3 files changed, 183 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..9c2c393aaf 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 {
@@ -3743,7 +3744,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);
@@ -4018,6 +4019,8 @@ static void test_WebBrowser_DoVerb(void)
     HWND hwnd;
     ULONG ref;
     BOOL res;
+    HRESULT hres;
+    VARIANT_BOOL b;
 
     webbrowser = create_webbrowser();
     init_test(webbrowser, 0);
@@ -4050,6 +4053,149 @@ static void test_WebBrowser_DoVerb(void)
     call_DoVerb(webbrowser, OLEIVERB_HIDE);
     CHECK_CALLED(OnInPlaceDeactivate);
 
+    b = 0x100;
+    hres = IWebBrowser2_get_Visible(webbrowser, &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);
+    call_DoVerb(webbrowser, OLEIVERB_SHOW);
+    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(webbrowser, &b);
+    ok(hres == S_OK, "get_Visible failed: %08x\n", hres);
+    ok(b == VARIANT_TRUE, "Visible = %x\n", b);
+
+    call_DoVerb(webbrowser, OLEIVERB_SHOW);
+    call_DoVerb(webbrowser, OLEIVERB_UIACTIVATE);
+
+    SET_EXPECT(Frame_SetActiveObject);
+    SET_EXPECT(UIWindow_SetActiveObject);
+    SET_EXPECT(OnUIDeactivate);
+    SET_EXPECT(OnFocus_FALSE);
+    SET_EXPECT(OnInPlaceDeactivate);
+    test_hide = TRUE;
+    call_DoVerb(webbrowser, OLEIVERB_HIDE);
+    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(webbrowser, &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);
+    call_DoVerb(webbrowser, OLEIVERB_SHOW);
+    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(webbrowser, &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;
+    call_DoVerb(webbrowser, OLEIVERB_HIDE);
+    CHECK_CALLED(Frame_SetActiveObject);
+    CHECK_CALLED(UIWindow_SetActiveObject);
+    CHECK_CALLED(OnUIDeactivate);
+    CHECK_CALLED(OnFocus_FALSE);
+    CHECK_CALLED(OnInPlaceDeactivate);
+
+    call_DoVerb(webbrowser, OLEIVERB_HIDE);
+    test_hide = FALSE;
+
+    b = 0x100;
+    hres = IWebBrowser2_get_Visible(webbrowser, &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);
+    call_DoVerb(webbrowser, OLEIVERB_UIACTIVATE);
+    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(webbrowser, &b);
+    ok(hres == S_OK, "get_Visible failed: %08x\n", hres);
+    ok(b == VARIANT_TRUE, "Visible = %x\n", b);
+
+    call_DoVerb(webbrowser, OLEIVERB_SHOW);
+
     test_ClientSite(webbrowser, NULL, FALSE);
 
     ref = IWebBrowser2_Release(webbrowser);
-- 
2.26.2




More information about the wine-devel mailing list