Zebediah Figura : explorer: Look for an existing window browsing the given path first.

Alexandre Julliard julliard at winehq.org
Mon May 18 15:00:14 CDT 2020


Module: wine
Branch: master
Commit: 1a7b4fb9c15ddd3d107af73a68fd312ea9c52e40
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=1a7b4fb9c15ddd3d107af73a68fd312ea9c52e40

Author: Zebediah Figura <z.figura12 at gmail.com>
Date:   Sun May 17 23:29:44 2020 -0500

explorer: Look for an existing window browsing the given path first.

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 programs/explorer/explorer.c | 164 +++++++++++++++++++++++++++++--------------
 1 file changed, 110 insertions(+), 54 deletions(-)

diff --git a/programs/explorer/explorer.c b/programs/explorer/explorer.c
index 763fca381b..43bd4ef13a 100644
--- a/programs/explorer/explorer.c
+++ b/programs/explorer/explorer.c
@@ -70,6 +70,9 @@ typedef struct
     LPITEMIDLIST pidl;
     IImageList *icon_list;
     DWORD advise_cookie;
+
+    IShellWindows *sw;
+    LONG sw_cookie;
 } explorer_info;
 
 enum
@@ -77,6 +80,13 @@ enum
     BACK_BUTTON,FORWARD_BUTTON,UP_BUTTON
 };
 
+static void variant_from_pidl(VARIANT *var, const ITEMIDLIST *pidl)
+{
+    V_VT(var) = VT_ARRAY | VT_UI1;
+    V_ARRAY(var) = SafeArrayCreateVector(VT_UI1, 0, ILGetSize(pidl));
+    memcpy(V_ARRAY(var)->pvData, pidl, ILGetSize(pidl));
+}
+
 typedef struct
 {
     IExplorerBrowserEvents IExplorerBrowserEvents_iface;
@@ -265,6 +275,15 @@ static HRESULT WINAPI IExplorerBrowserEventsImpl_fnOnNavigationComplete(IExplore
     STRRET strret;
     WCHAR *name;
 
+    if (This->info->sw)
+    {
+        VARIANT var;
+
+        variant_from_pidl(&var, pidl);
+        IShellWindows_OnNavigate(This->info->sw, This->info->sw_cookie, &var);
+        VariantClear(&var);
+    }
+
     ILFree(This->info->pidl);
     This->info->pidl = ILClone(pidl);
     update_path_box(This->info);
@@ -325,7 +344,35 @@ static IExplorerBrowserEvents *make_explorer_events(explorer_info *info)
     return &ret->IExplorerBrowserEvents_iface;
 }
 
-static void make_explorer_window(IShellFolder* startFolder)
+static IShellFolder *get_starting_shell_folder(WCHAR *path)
+{
+    IShellFolder* desktop,*folder;
+    LPITEMIDLIST root_pidl;
+    HRESULT hres;
+
+    SHGetDesktopFolder(&desktop);
+
+    if (!path)
+        return desktop;
+
+    hres = IShellFolder_ParseDisplayName(desktop, NULL, NULL, path, NULL, &root_pidl, NULL);
+    if(FAILED(hres))
+    {
+        return desktop;
+    }
+    hres = IShellFolder_BindToObject(desktop,root_pidl,NULL,
+                                     &IID_IShellFolder,
+                                     (void**)&folder);
+    ILFree(root_pidl);
+    if(FAILED(hres))
+    {
+        return desktop;
+    }
+    IShellFolder_Release(desktop);
+    return folder;
+}
+
+static void make_explorer_window(parameters_struct *params)
 {
     RECT rect;
     HWND rebar,nav_toolbar;
@@ -339,8 +386,49 @@ static void make_explorer_window(IShellFolder* startFolder)
     TBBUTTON nav_buttons[3];
     int hist_offset,view_offset;
     REBARBANDINFOW band_info;
+    VARIANT var, empty_var;
+    IShellFolder *folder;
+    IDispatch *dispatch;
+    WCHAR *path = NULL;
+    IShellWindows *sw;
+    ITEMIDLIST *pidl;
     UINT dpix, dpiy;
+    DWORD size;
+    LONG hwnd;
     HDC hdc;
+    MSG msg;
+
+    CoCreateInstance(&CLSID_ShellWindows, NULL, CLSCTX_LOCAL_SERVER,
+            &IID_IShellWindows, (void **)&sw);
+
+    if (params->root[0])
+    {
+        size = GetFullPathNameW(params->root, 0, NULL, NULL);
+        path = malloc(size);
+        GetFullPathNameW(params->root, size, path, NULL);
+    }
+
+    if (sw && path)
+    {
+        if (!(pidl = ILCreateFromPathW(path)))
+        {
+            ERR("Failed to create PIDL for %s.\n", debugstr_w(path));
+            IShellWindows_Release(sw);
+            return;
+        }
+
+        variant_from_pidl(&var, pidl);
+        V_VT(&empty_var) = VT_EMPTY;
+        if (IShellWindows_FindWindowSW(sw, &var, &empty_var, SWC_EXPLORER, &hwnd, 0, &dispatch) == S_OK)
+        {
+            TRACE("Found window %#x already browsing path %s.\n", hwnd, debugstr_w(path));
+            SetForegroundWindow((HWND)(LONG_PTR)hwnd);
+            IShellWindows_Release(sw);
+            return;
+        }
+        ILFree(pidl);
+        VariantClear(&var);
+    }
 
     memset(nav_buttons,0,sizeof(nav_buttons));
 
@@ -376,6 +464,12 @@ static void make_explorer_window(IShellFolder* startFolder)
                         CW_USEDEFAULT,CW_USEDEFAULT,default_width,
                         default_height,NULL,NULL,explorer_hInstance,NULL);
 
+    if (sw)
+    {
+        IShellWindows_Register(sw, NULL, (LONG_PTR)info->main_window, SWC_EXPLORER, &info->sw_cookie);
+        info->sw = sw;
+    }
+
     fs.ViewMode = FVM_DETAILS;
     fs.fFlags = FWF_AUTOARRANGE;
 
@@ -439,11 +533,20 @@ static void make_explorer_window(IShellFolder* startFolder)
     SendMessageW(rebar,RB_INSERTBANDW,-1,(LPARAM)&band_info);
     events = make_explorer_events(info);
     IExplorerBrowser_Advise(info->browser,events,&info->advise_cookie);
-    IExplorerBrowser_BrowseToObject(info->browser,(IUnknown*)startFolder,
-                                    SBSP_ABSOLUTE);
+
+    folder = get_starting_shell_folder(path);
+    IExplorerBrowser_BrowseToObject(info->browser, (IUnknown *)folder, SBSP_ABSOLUTE);
+    IShellFolder_Release(folder);
+
     ShowWindow(info->main_window,SW_SHOWDEFAULT);
     UpdateWindow(info->main_window);
     IExplorerBrowserEvents_Release(events);
+
+    while (GetMessageW(&msg, NULL, 0, 0))
+    {
+        TranslateMessage(&msg);
+        DispatchMessageW(&msg);
+    }
 }
 
 static void update_window_size(explorer_info *info, int height, int width)
@@ -568,6 +671,9 @@ static LRESULT CALLBACK explorer_wnd_proc(HWND hwnd, UINT uMsg, WPARAM wParam, L
     switch(uMsg)
     {
     case WM_DESTROY:
+        IShellWindows_Revoke(info->sw, info->sw_cookie);
+        IShellWindows_Release(info->sw);
+
         IExplorerBrowser_Unadvise(browser,info->advise_cookie);
         IExplorerBrowser_Destroy(browser);
         IExplorerBrowser_Release(browser);
@@ -625,47 +731,6 @@ static void register_explorer_window_class(void)
     RegisterClassExW(&window_class);
 }
 
-static IShellFolder* get_starting_shell_folder(parameters_struct* params)
-{
-    IShellFolder* desktop,*folder;
-    LPITEMIDLIST root_pidl;
-    WCHAR *fullpath = NULL;
-    HRESULT hres;
-    DWORD size;
-
-    SHGetDesktopFolder(&desktop);
-    if (!params->root[0])
-    {
-        return desktop;
-    }
-
-    size = GetFullPathNameW(params->root, 0, fullpath, NULL);
-    if (!size)
-        return desktop;
-    fullpath = heap_alloc(size * sizeof(WCHAR));
-    GetFullPathNameW(params->root, size, fullpath, NULL);
-
-    hres = IShellFolder_ParseDisplayName(desktop,NULL,NULL,
-                                         fullpath,NULL,
-                                         &root_pidl,NULL);
-    heap_free(fullpath);
-
-    if(FAILED(hres))
-    {
-        return desktop;
-    }
-    hres = IShellFolder_BindToObject(desktop,root_pidl,NULL,
-                                     &IID_IShellFolder,
-                                     (void**)&folder);
-    ILFree(root_pidl);
-    if(FAILED(hres))
-    {
-        return desktop;
-    }
-    IShellFolder_Release(desktop);
-    return folder;
-}
-
 static WCHAR *copy_path_string(WCHAR *target, WCHAR *source)
 {
     INT i = 0;
@@ -793,8 +858,6 @@ int WINAPI wWinMain(HINSTANCE hinstance,
 
     parameters_struct   parameters;
     HRESULT hres;
-    MSG msg;
-    IShellFolder *folder;
     INITCOMMONCONTROLSEX init_info;
 
     memset(&parameters,0,sizeof(parameters));
@@ -817,13 +880,6 @@ int WINAPI wWinMain(HINSTANCE hinstance,
         ExitProcess(EXIT_FAILURE);
     }
     register_explorer_window_class();
-    folder = get_starting_shell_folder(&parameters);
-    make_explorer_window(folder);
-    IShellFolder_Release(folder);
-    while(GetMessageW( &msg, NULL, 0, 0 ) != 0)
-    {
-	    TranslateMessage(&msg);
-	    DispatchMessageW(&msg);
-    }
+    make_explorer_window(&parameters);
     return 0;
 }




More information about the wine-cvs mailing list