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

Dmitry Timoshkov dmitry at baikal.ru
Tue Aug 4 04:01:22 CDT 2020


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 at 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);
-- 
2.26.2




More information about the wine-devel mailing list