Sync brsfolder.c with keyboard shortcut code from wine (#2290)

* [SHELL32] Add shortcut to rename folders with the F2 key.

Sync Wine Commit 2e25a43f3fb6230460447bae6fb5db2edbd4a42f by Fabian Maurer

* [SHELL32] Add shortcut to delete folders with the delete key.

Sync Wine Commit 43f44ffb3779ff23c863d9b3297f92720e7e3733 by Fabian Maurer

* Disable the code for file deletion. The Wine way doesn't work on ROS. Add an explaining comment why we can't use the Wine code, as requested by Amine
This commit is contained in:
Robert Naumann 2020-03-18 21:57:10 +01:00 committed by GitHub
parent 1816e4f6cb
commit fc4c4d4911
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -41,6 +41,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(shell);
#define SHV_CHANGE_NOTIFY (WM_USER + 0x1111)
/* original margins and control size */
typedef struct tagLAYOUT_DATA
{
@ -56,6 +58,7 @@ typedef struct tagbrowse_info
LPITEMIDLIST pidlRet;
LAYOUT_DATA *layout; /* filled by LayoutInit, used by LayoutUpdate */
SIZE szMin;
ULONG hNotify; /* change notification handle */
} browse_info;
typedef struct tagTV_ITEMDATA
@ -615,6 +618,67 @@ static LRESULT BrsFolder_Treeview_Rename(browse_info *info, NMTVDISPINFOW *pnmtv
return 0;
}
static HRESULT BrsFolder_Rename(browse_info *info, HTREEITEM rename)
{
SendMessageW(info->hwndTreeView, TVM_SELECTITEM, TVGN_CARET, (LPARAM)rename);
SendMessageW(info->hwndTreeView, TVM_EDITLABELW, 0, (LPARAM)rename);
return S_OK;
}
static LRESULT BrsFolder_Treeview_Keydown(browse_info *info, LPNMTVKEYDOWN keydown)
{
HTREEITEM selected_item;
/* Old dialog doesn't support those advanced features */
if (!(info->lpBrowseInfo->ulFlags & BIF_NEWDIALOGSTYLE))
return 0;
selected_item = (HTREEITEM)SendMessageW(info->hwndTreeView, TVM_GETNEXTITEM, TVGN_CARET, 0);
switch (keydown->wVKey)
{
case VK_F2:
BrsFolder_Rename(info, selected_item);
break;
case VK_DELETE:
{
#ifdef __REACTOS__
/*********************************************************
FIXME: Add a proper alternative implementation for ReactOS
NOTES: Wine makes use of the ISFHelper interface, which we
don't have in ReactOS.
It's defined in dlls/shell32/shellfolder.h and implemented
in dlls/shell32/shfldr_fs.c on Wine's side.
*********************************************************/
#else
const ITEMIDLIST *item_id;
ISFHelper *psfhlp;
HRESULT hr;
TVITEMW item;
TV_ITEMDATA *item_data;
item.mask = TVIF_PARAM;
item.mask = TVIF_HANDLE|TVIF_PARAM;
item.hItem = selected_item;
SendMessageW(info->hwndTreeView, TVM_GETITEMW, 0, (LPARAM)&item);
item_data = (TV_ITEMDATA *)item.lParam;
item_id = item_data->lpi;
hr = IShellFolder_QueryInterface(item_data->lpsfParent, &IID_ISFHelper, (void**)&psfhlp);
if(FAILED(hr))
return 0;
/* perform the item deletion - tree view gets updated over shell notification */
ISFHelper_DeleteItems(psfhlp, 1, &item_id);
ISFHelper_Release(psfhlp);
#endif
}
break;
}
return 0;
}
static LRESULT BrsFolder_OnNotify( browse_info *info, UINT CtlID, LPNMHDR lpnmh )
{
NMTREEVIEWW *pnmtv = (NMTREEVIEWW *)lpnmh;
@ -641,6 +705,9 @@ static LRESULT BrsFolder_OnNotify( browse_info *info, UINT CtlID, LPNMHDR lpnmh
case TVN_ENDLABELEDITA:
case TVN_ENDLABELEDITW:
return BrsFolder_Treeview_Rename( info, (LPNMTVDISPINFOW)pnmtv );
case TVN_KEYDOWN:
return BrsFolder_Treeview_Keydown( info, (LPNMTVKEYDOWN)pnmtv );
default:
WARN("unhandled (%d)\n", pnmtv->hdr.code);
@ -653,6 +720,8 @@ static LRESULT BrsFolder_OnNotify( browse_info *info, UINT CtlID, LPNMHDR lpnmh
static BOOL BrsFolder_OnCreate( HWND hWnd, browse_info *info )
{
LPITEMIDLIST computer_pidl;
SHChangeNotifyEntry ntreg;
LPBROWSEINFOW lpBrowseInfo = info->lpBrowseInfo;
info->hWnd = hWnd;
@ -718,18 +787,19 @@ static BOOL BrsFolder_OnCreate( HWND hWnd, browse_info *info )
else
ERR("treeview control missing!\n");
/* Register for change notifications */
SHGetFolderLocation(NULL, CSIDL_DESKTOP, NULL, 0, &computer_pidl);
ntreg.pidl = computer_pidl;
ntreg.fRecursive = TRUE;
info->hNotify = SHChangeNotifyRegister(hWnd, SHCNRF_InterruptLevel, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg);
browsefolder_callback( info->lpBrowseInfo, hWnd, BFFM_INITIALIZED, 0 );
return TRUE;
}
static HRESULT BrsFolder_Rename(browse_info *info, HTREEITEM rename)
{
SendMessageW(info->hwndTreeView, TVM_SELECTITEM, TVGN_CARET, (LPARAM)rename);
SendMessageW(info->hwndTreeView, TVM_EDITLABELW, 0, (LPARAM)rename);
return S_OK;
}
static HRESULT BrsFolder_NewFolder(browse_info *info)
{
DWORD flags = BrowseFlagsToSHCONTF(info->lpBrowseInfo->ulFlags);
@ -1024,9 +1094,62 @@ static INT BrsFolder_OnDestroy(browse_info *info)
info->layout = NULL;
}
SHChangeNotifyDeregister(info->hNotify);
return 0;
}
/* Find a treeview node by recursively walking the treeview */
static HTREEITEM BrsFolder_FindItemByPidl(browse_info *info, LPCITEMIDLIST pidl, HTREEITEM hItem)
{
TV_ITEMW item;
TV_ITEMDATA *item_data;
HRESULT hr;
item.mask = TVIF_HANDLE | TVIF_PARAM;
item.hItem = hItem;
SendMessageW(info->hwndTreeView, TVM_GETITEMW, 0, (LPARAM)&item);
item_data = (TV_ITEMDATA *)item.lParam;
hr = IShellFolder_CompareIDs(item_data->lpsfParent, 0, item_data->lpifq, pidl);
if(SUCCEEDED(hr) && !HRESULT_CODE(hr))
return hItem;
hItem = (HTREEITEM)SendMessageW(info->hwndTreeView, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
while (hItem)
{
HTREEITEM newItem = BrsFolder_FindItemByPidl(info, pidl, hItem);
if (newItem)
return newItem;
hItem = (HTREEITEM)SendMessageW(info->hwndTreeView, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem);
}
return NULL;
}
static LRESULT BrsFolder_OnChange(browse_info *info, const LPCITEMIDLIST *pidls, LONG event)
{
BOOL ret = TRUE;
TRACE("(%p)->(%p, %p, 0x%08x)\n", info, pidls[0], pidls[1], event);
switch (event)
{
case SHCNE_RMDIR:
case SHCNE_DELETE:
{
HTREEITEM handle_root = (HTREEITEM)SendMessageW(info->hwndTreeView, TVM_GETNEXTITEM, TVGN_ROOT, 0);
HTREEITEM handle_item = BrsFolder_FindItemByPidl(info, pidls[0], handle_root);
if (handle_item)
SendMessageW(info->hwndTreeView, TVM_DELETEITEM, 0, (LPARAM)handle_item);
break;
}
}
return ret;
}
/*************************************************************************
* BrsFolderDlgProc32 (not an exported API function)
*/
@ -1087,6 +1210,9 @@ static INT_PTR CALLBACK BrsFolderDlgProc( HWND hWnd, UINT msg, WPARAM wParam,
case BFFM_SETEXPANDED: /* unicode only */
return BrsFolder_OnSetExpanded(info, (LPVOID)lParam, (BOOL)wParam, NULL);
case SHV_CHANGE_NOTIFY:
return BrsFolder_OnChange(info, (const LPCITEMIDLIST*)wParam, (LONG)lParam);
case WM_DESTROY:
return BrsFolder_OnDestroy(info);
}