shell32: Add a travellog to the ExplorerBrowser control.
This commit is contained in:
parent
00889f1723
commit
fdccbd91af
|
@ -43,6 +43,11 @@ typedef struct _event_client {
|
||||||
DWORD cookie;
|
DWORD cookie;
|
||||||
} event_client;
|
} event_client;
|
||||||
|
|
||||||
|
typedef struct _travellog_entry {
|
||||||
|
struct list entry;
|
||||||
|
LPITEMIDLIST pidl;
|
||||||
|
} travellog_entry;
|
||||||
|
|
||||||
typedef struct _ExplorerBrowserImpl {
|
typedef struct _ExplorerBrowserImpl {
|
||||||
const IExplorerBrowserVtbl *lpVtbl;
|
const IExplorerBrowserVtbl *lpVtbl;
|
||||||
const IShellBrowserVtbl *lpsbVtbl;
|
const IShellBrowserVtbl *lpsbVtbl;
|
||||||
|
@ -57,6 +62,9 @@ typedef struct _ExplorerBrowserImpl {
|
||||||
|
|
||||||
struct list event_clients;
|
struct list event_clients;
|
||||||
DWORD events_next_cookie;
|
DWORD events_next_cookie;
|
||||||
|
struct list travellog;
|
||||||
|
travellog_entry *travellog_cursor;
|
||||||
|
int travellog_count;
|
||||||
|
|
||||||
IShellView *psv;
|
IShellView *psv;
|
||||||
RECT sv_rc;
|
RECT sv_rc;
|
||||||
|
@ -139,6 +147,99 @@ static void events_ViewCreated(ExplorerBrowserImpl *This, IShellView *psv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* Travellog functions.
|
||||||
|
*/
|
||||||
|
static void travellog_remove_entry(ExplorerBrowserImpl *This, travellog_entry *entry)
|
||||||
|
{
|
||||||
|
TRACE("Removing %p\n", entry);
|
||||||
|
|
||||||
|
list_remove(&entry->entry);
|
||||||
|
HeapFree(GetProcessHeap(), 0, entry);
|
||||||
|
This->travellog_count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void travellog_remove_all_entries(ExplorerBrowserImpl *This)
|
||||||
|
{
|
||||||
|
travellog_entry *cursor, *cursor2;
|
||||||
|
TRACE("%p\n", This);
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->travellog, travellog_entry, entry)
|
||||||
|
travellog_remove_entry(This, cursor);
|
||||||
|
|
||||||
|
This->travellog_cursor = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void travellog_add_entry(ExplorerBrowserImpl *This, LPITEMIDLIST pidl)
|
||||||
|
{
|
||||||
|
travellog_entry *new, *cursor, *cursor2;
|
||||||
|
TRACE("%p (old count %d)\n", pidl, This->travellog_count);
|
||||||
|
|
||||||
|
/* Replace the old tail, if any, with the new entry */
|
||||||
|
if(This->travellog_cursor)
|
||||||
|
{
|
||||||
|
LIST_FOR_EACH_ENTRY_SAFE_REV(cursor, cursor2, &This->travellog, travellog_entry, entry)
|
||||||
|
{
|
||||||
|
if(cursor == This->travellog_cursor)
|
||||||
|
break;
|
||||||
|
travellog_remove_entry(This, cursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create and add the new entry */
|
||||||
|
new = HeapAlloc(GetProcessHeap(), 0, sizeof(travellog_entry));
|
||||||
|
new->pidl = ILClone(pidl);
|
||||||
|
list_add_tail(&This->travellog, &new->entry);
|
||||||
|
This->travellog_cursor = new;
|
||||||
|
This->travellog_count++;
|
||||||
|
|
||||||
|
/* Remove the first few entries if the size limit is reached. */
|
||||||
|
if(This->travellog_count > 200)
|
||||||
|
{
|
||||||
|
UINT i = 0;
|
||||||
|
LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->travellog, travellog_entry, entry)
|
||||||
|
{
|
||||||
|
if(i++ > 10)
|
||||||
|
break;
|
||||||
|
travellog_remove_entry(This, cursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static LPCITEMIDLIST travellog_go_back(ExplorerBrowserImpl *This)
|
||||||
|
{
|
||||||
|
travellog_entry *prev;
|
||||||
|
TRACE("%p, %p\n", This, This->travellog_cursor);
|
||||||
|
|
||||||
|
if(!This->travellog_cursor)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
prev = LIST_ENTRY(list_prev(&This->travellog, &This->travellog_cursor->entry),
|
||||||
|
travellog_entry, entry);
|
||||||
|
if(!prev)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
This->travellog_cursor = prev;
|
||||||
|
return prev->pidl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LPCITEMIDLIST travellog_go_forward(ExplorerBrowserImpl *This)
|
||||||
|
{
|
||||||
|
travellog_entry *next;
|
||||||
|
TRACE("%p, %p\n", This, This->travellog_cursor);
|
||||||
|
|
||||||
|
if(!This->travellog_cursor)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
next = LIST_ENTRY(list_next(&This->travellog, &This->travellog_cursor->entry),
|
||||||
|
travellog_entry, entry);
|
||||||
|
if(!next)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
This->travellog_cursor = next;
|
||||||
|
return next->pidl;
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Helper functions
|
* Helper functions
|
||||||
*/
|
*/
|
||||||
|
@ -386,6 +487,7 @@ static HRESULT WINAPI IExplorerBrowser_fnDestroy(IExplorerBrowser *iface)
|
||||||
}
|
}
|
||||||
|
|
||||||
events_unadvise_all(This);
|
events_unadvise_all(This);
|
||||||
|
travellog_remove_all_entries(This);
|
||||||
|
|
||||||
ILFree(This->current_pidl);
|
ILFree(This->current_pidl);
|
||||||
This->current_pidl = NULL;
|
This->current_pidl = NULL;
|
||||||
|
@ -520,9 +622,6 @@ static HRESULT WINAPI IExplorerBrowser_fnGetOptions(IExplorerBrowser *iface,
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const UINT unsupported_browse_flags =
|
|
||||||
SBSP_NAVIGATEBACK | SBSP_NAVIGATEFORWARD | SBSP_NEWBROWSER |
|
|
||||||
EBF_SELECTFROMDATAOBJECT | EBF_NODROPTARGET;
|
|
||||||
static HRESULT WINAPI IExplorerBrowser_fnBrowseToIDList(IExplorerBrowser *iface,
|
static HRESULT WINAPI IExplorerBrowser_fnBrowseToIDList(IExplorerBrowser *iface,
|
||||||
PCUIDLIST_RELATIVE pidl,
|
PCUIDLIST_RELATIVE pidl,
|
||||||
UINT uFlags)
|
UINT uFlags)
|
||||||
|
@ -530,6 +629,8 @@ static HRESULT WINAPI IExplorerBrowser_fnBrowseToIDList(IExplorerBrowser *iface,
|
||||||
ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
|
ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
|
||||||
LPITEMIDLIST absolute_pidl = NULL;
|
LPITEMIDLIST absolute_pidl = NULL;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
static const UINT unsupported_browse_flags =
|
||||||
|
SBSP_NEWBROWSER | EBF_SELECTFROMDATAOBJECT | EBF_NODROPTARGET;
|
||||||
TRACE("%p (%p, 0x%x)\n", This, pidl, uFlags);
|
TRACE("%p (%p, 0x%x)\n", This, pidl, uFlags);
|
||||||
|
|
||||||
if(!This->hwnd_main)
|
if(!This->hwnd_main)
|
||||||
|
@ -547,7 +648,27 @@ static HRESULT WINAPI IExplorerBrowser_fnBrowseToIDList(IExplorerBrowser *iface,
|
||||||
if(uFlags & unsupported_browse_flags)
|
if(uFlags & unsupported_browse_flags)
|
||||||
FIXME("Argument 0x%x contains unsupported flags.\n", uFlags);
|
FIXME("Argument 0x%x contains unsupported flags.\n", uFlags);
|
||||||
|
|
||||||
if(uFlags & SBSP_PARENT)
|
if(uFlags & SBSP_NAVIGATEBACK)
|
||||||
|
{
|
||||||
|
TRACE("SBSP_NAVIGATEBACK\n");
|
||||||
|
absolute_pidl = ILClone(travellog_go_back(This));
|
||||||
|
if(!absolute_pidl && !This->current_pidl)
|
||||||
|
return E_FAIL;
|
||||||
|
else if(!absolute_pidl)
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(uFlags & SBSP_NAVIGATEFORWARD)
|
||||||
|
{
|
||||||
|
TRACE("SBSP_NAVIGATEFORWARD\n");
|
||||||
|
absolute_pidl = ILClone(travellog_go_forward(This));
|
||||||
|
if(!absolute_pidl && !This->current_pidl)
|
||||||
|
return E_FAIL;
|
||||||
|
else if(!absolute_pidl)
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(uFlags & SBSP_PARENT)
|
||||||
{
|
{
|
||||||
if(This->current_pidl)
|
if(This->current_pidl)
|
||||||
{
|
{
|
||||||
|
@ -618,6 +739,14 @@ static HRESULT WINAPI IExplorerBrowser_fnBrowseToIDList(IExplorerBrowser *iface,
|
||||||
IShellItem_Release(psi);
|
IShellItem_Release(psi);
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add to travellog */
|
||||||
|
if( !(This->eb_options & EBO_NOTRAVELLOG) &&
|
||||||
|
!(uFlags & (SBSP_NAVIGATEFORWARD|SBSP_NAVIGATEBACK)) )
|
||||||
|
{
|
||||||
|
travellog_add_entry(This, absolute_pidl);
|
||||||
|
}
|
||||||
|
|
||||||
IShellItem_Release(psi);
|
IShellItem_Release(psi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -928,6 +1057,7 @@ HRESULT WINAPI ExplorerBrowser_Constructor(IUnknown *pUnkOuter, REFIID riid, voi
|
||||||
eb->lpsbVtbl = &vt_IShellBrowser;
|
eb->lpsbVtbl = &vt_IShellBrowser;
|
||||||
|
|
||||||
list_init(&eb->event_clients);
|
list_init(&eb->event_clients);
|
||||||
|
list_init(&eb->travellog);
|
||||||
|
|
||||||
ret = IExplorerBrowser_QueryInterface((IExplorerBrowser*)eb, riid, ppv);
|
ret = IExplorerBrowser_QueryInterface((IExplorerBrowser*)eb, riid, ppv);
|
||||||
IExplorerBrowser_Release((IExplorerBrowser*)eb);
|
IExplorerBrowser_Release((IExplorerBrowser*)eb);
|
||||||
|
|
|
@ -811,14 +811,34 @@ static void test_navigation(void)
|
||||||
test_browse_pidl_sb(peb2, &ebev, 0, SBSP_RELATIVE, E_FAIL, 0, 0, 0, 0);
|
test_browse_pidl_sb(peb2, &ebev, 0, SBSP_RELATIVE, E_FAIL, 0, 0, 0, 0);
|
||||||
test_browse_pidl(peb, &ebev, 0, SBSP_PARENT, E_FAIL, 0, 0, 0, 0);
|
test_browse_pidl(peb, &ebev, 0, SBSP_PARENT, E_FAIL, 0, 0, 0, 0);
|
||||||
test_browse_pidl_sb(peb2, &ebev, 0, SBSP_PARENT, E_FAIL, 0, 0, 0, 0);
|
test_browse_pidl_sb(peb2, &ebev, 0, SBSP_PARENT, E_FAIL, 0, 0, 0, 0);
|
||||||
|
test_browse_pidl(peb, &ebev, 0, SBSP_NAVIGATEFORWARD, E_FAIL, 0, 0, 0, 0);
|
||||||
|
test_browse_pidl_sb(peb2, &ebev, 0, SBSP_NAVIGATEFORWARD, E_FAIL, 0, 0, 0, 0);
|
||||||
|
test_browse_pidl(peb, &ebev, 0, SBSP_NAVIGATEBACK, E_FAIL, 0, 0, 0, 0);
|
||||||
|
test_browse_pidl_sb(peb2, &ebev, 0, SBSP_NAVIGATEBACK, E_FAIL, 0, 0, 0, 0);
|
||||||
|
|
||||||
/* "The first browse is synchronous" */
|
/* "The first browse is synchronous" */
|
||||||
test_browse_pidl(peb, &ebev, pidl_child, SBSP_ABSOLUTE, S_OK, 1, 1, 0, 1);
|
test_browse_pidl(peb, &ebev, pidl_child, SBSP_ABSOLUTE, S_OK, 1, 1, 0, 1);
|
||||||
test_browse_pidl_sb(peb2, &ebev, pidl_child, SBSP_ABSOLUTE, S_OK, 1, 1, 0, 1);
|
test_browse_pidl_sb(peb2, &ebev, pidl_child, SBSP_ABSOLUTE, S_OK, 1, 1, 0, 1);
|
||||||
|
|
||||||
|
/* Navigate empty history */
|
||||||
|
test_browse_pidl(peb, &ebev, 0, SBSP_NAVIGATEFORWARD, S_OK, 0, 0, 0, 0);
|
||||||
|
test_browse_pidl_sb(peb2, &ebev, 0, SBSP_NAVIGATEFORWARD, S_OK, 0, 0, 0, 0);
|
||||||
|
test_browse_pidl(peb, &ebev, 0, SBSP_NAVIGATEBACK, S_OK, 0, 0, 0, 0);
|
||||||
|
test_browse_pidl_sb(peb2, &ebev, 0, SBSP_NAVIGATEBACK, S_OK, 0, 0, 0, 0);
|
||||||
|
|
||||||
|
/* Navigate history */
|
||||||
|
test_browse_pidl(peb, &ebev, 0, SBSP_PARENT, S_OK, 1, 1, 0, 1);
|
||||||
|
test_browse_pidl_sb(peb2, &ebev, 0, SBSP_PARENT, S_OK, 1, 1, 0, 1);
|
||||||
|
test_browse_pidl(peb, &ebev, 0, SBSP_NAVIGATEBACK, S_OK, 1, 1, 0, 1);
|
||||||
|
test_browse_pidl_sb(peb2, &ebev, 0, SBSP_NAVIGATEBACK, S_OK, 1, 1, 0, 1);
|
||||||
|
test_browse_pidl(peb, &ebev, 0, SBSP_NAVIGATEFORWARD, S_OK, 1, 1, 0, 1);
|
||||||
|
test_browse_pidl_sb(peb2, &ebev, 0, SBSP_NAVIGATEFORWARD, S_OK, 1, 1, 0, 1);
|
||||||
|
test_browse_pidl(peb, &ebev, 0, SBSP_ABSOLUTE, S_OK, 0, 0, 0, 0);
|
||||||
|
test_browse_pidl_sb(peb2, &ebev, 0, SBSP_ABSOLUTE, S_OK, 0, 0, 0, 0);
|
||||||
|
|
||||||
/* Relative navigation */
|
/* Relative navigation */
|
||||||
test_browse_pidl(peb, &ebev, pidl_current, SBSP_ABSOLUTE, S_OK, 1, 1, 0, 1);
|
test_browse_pidl(peb, &ebev, pidl_current, SBSP_ABSOLUTE, S_OK, 1, 0, 0, 1);
|
||||||
test_browse_pidl_sb(peb2, &ebev, pidl_current, SBSP_ABSOLUTE, S_OK, 1, 1, 0, 1);
|
test_browse_pidl_sb(peb2, &ebev, pidl_current, SBSP_ABSOLUTE, S_OK, 1, 0, 0, 1);
|
||||||
|
|
||||||
hr = IExplorerBrowser_GetCurrentView(peb, &IID_IFolderView, (void**)&pfv);
|
hr = IExplorerBrowser_GetCurrentView(peb, &IID_IFolderView, (void**)&pfv);
|
||||||
ok(hr == S_OK, "Got 0x%08x\n", hr);
|
ok(hr == S_OK, "Got 0x%08x\n", hr);
|
||||||
|
|
Loading…
Reference in New Issue