Skip to content

Commit

Permalink
make "open terminal here" context menu work for directory background (#…
Browse files Browse the repository at this point in the history
…8638)

This commit makes "Open in Windows Terminal" Context menu work again for
directory background even on system that OS fix is not applied.

This is a fallback solution to OS fixes mentioned in #6414.
While OS fix is on its way, we need a fallback that works on existing OS
versions.

The approach to this is: when no item is selected (nullptr for
IShellItemArray*), we use shell api to query the path of current active
Explorer window. A special case is handled for Windows Desktop. Once
we are able to obtain the path, we launch Windows Terminal with it.

1. Right click on desktop to bring up the Context menu, pick "Open in
   Windows Terminal", verify that a terminal is opened with correct
   initial path.

2. Open a few File Explorer windows, pick any window, navigate to a
   folder, click on "Background" to bring up the context menu, click
   "Open in Windows Terminal" verify that a terminal is opened with
   correct initial path.

Closes #6414

(cherry picked from commit fcca88a)
  • Loading branch information
hereafter authored and DHowett committed Jan 25, 2021
1 parent 9e9c0be commit 334e518
Show file tree
Hide file tree
Showing 9 changed files with 138 additions and 51 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
checkboxes
CSIDL
csv
horiz
IDispatch
inlines
IWeb
Progman
reserialize
SHANDLE
SHGFP
udk
unfocus
WClass
22 changes: 3 additions & 19 deletions .github/actions/spell-check/expect/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ BOLDFONT
BOOLIFY
bools
Bopomofo
boostorg
Borland
BOTTOMLEFT
BOTTOMRIGHT
Expand Down Expand Up @@ -247,7 +248,6 @@ charset
CHARSETINFO
chcp
checkbox
Checkboxes
chh
Childitem
chk
Expand Down Expand Up @@ -382,7 +382,6 @@ CORESYSTEM
cotaskmem
countof
cout
CParams
CPG
cpinfo
CPINFOEX
Expand Down Expand Up @@ -411,7 +410,6 @@ csbi
csbiex
csharp
CSHORT
cso
csproj
Csr
csrmsg
Expand All @@ -424,7 +422,6 @@ cstdlib
cstr
cstring
cstyle
CSV
CSwitch
CText
ctime
Expand Down Expand Up @@ -836,7 +833,6 @@ gcy
gdi
gdip
gdirenderer
GENERATEPROJECTPRIFILE
geopol
GETALIAS
GETALIASES
Expand Down Expand Up @@ -951,7 +947,6 @@ hfont
hglobal
hh
hhh
hhhh
hhook
hhx
HIBYTE
Expand All @@ -978,7 +973,6 @@ hmod
hmodule
hmon
HMONITOR
Horiz
HORZ
hostable
hostlib
Expand Down Expand Up @@ -1088,10 +1082,8 @@ INITMENU
inkscape
inl
INLINEPREFIX
Inlines
INotify
inout
INPATHROOT
inproc
Inputkeyinfo
INPUTPROCESSORPROFILE
Expand Down Expand Up @@ -1333,7 +1325,6 @@ mailto
majorly
makeappx
MAKEINTRESOURCE
MAKEINTRESOURCEA
MAKEINTRESOURCEW
MAKELANGID
MAKELONG
Expand Down Expand Up @@ -1406,7 +1397,6 @@ monostate
MOUSEACTIVATE
MOUSEFIRST
MOUSEHWHEEL
mousemode
MOUSEMOVE
mousewheel
MOVESTART
Expand All @@ -1428,7 +1418,6 @@ MSGSELECTMODE
msiexec
MSIL
msix
msixbundle
msrc
msvcrt
MSVS
Expand Down Expand Up @@ -1943,7 +1932,6 @@ Replymessage
repositorypath
rescap
Resequence
Reserialize
RESETCONTENT
resheader
resizable
Expand All @@ -1970,7 +1958,6 @@ rgpwsz
rgrc
rgs
rgui
rgus
rgw
rgwch
rhs
Expand Down Expand Up @@ -2104,7 +2091,6 @@ sfi
SFINAE
SFUI
sgr
SGRXY
SHCo
shcore
shellapi
Expand Down Expand Up @@ -2277,6 +2263,7 @@ tcome
tcommandline
tcommands
tcon
TDelegated
TDP
TEAMPROJECT
tearoff
Expand Down Expand Up @@ -2443,7 +2430,6 @@ UNCPRIORITY
undef
Unescape
unexpand
Unfocus
unhighlighting
unhosted
unicode
Expand Down Expand Up @@ -2768,14 +2754,12 @@ XColors
xcopy
XCount
xdy
xe
XEncoding
xes
Xes
XES
xff
XFile
xlang
XManifest
XMath
XMFLOAT
Expand All @@ -2800,6 +2784,7 @@ xvalue
XVIRTUALSCREEN
XWalk
xy
Xzn
yact
YAML
YCast
Expand All @@ -2826,7 +2811,6 @@ zu
zxcvbnm
zy
AAAAABBBBBBCCC
AAAAA
BBBBBCCC
abcd
LPMINMAXINFO
Expand Down
9 changes: 2 additions & 7 deletions src/cascadia/CascadiaPackage/Package-Dev.appxmanifest
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,9 @@
<desktop5:ItemType Type="Directory">
<desktop5:Verb Id="Command1" Clsid="9f156763-7844-4dc4-b2b1-901f640f5155" />
</desktop5:ItemType>
<!-- Due to a bug in the OS, this doesn't actually work right -
we'll get a nullptr in our implementation. So this is disabled
temporarily. See MSFT:24623699 for more details.
<desktop5:ItemType Type="Directory\Background">
<desktop5:Verb Id="Command2" Clsid="9f156763-7844-4dc4-b2b1-901f640f5155" />
</desktop5:ItemType>
-->
<desktop5:Verb Id="Command2" Clsid="9f156763-7844-4dc4-b2b1-901f640f5155" />
</desktop5:ItemType>
</desktop4:FileExplorerContextMenus>
</desktop4:Extension>

Expand Down
8 changes: 1 addition & 7 deletions src/cascadia/CascadiaPackage/Package-Pre.appxmanifest
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,9 @@
<desktop5:ItemType Type="Directory">
<desktop5:Verb Id="Command1" Clsid="9f156763-7844-4dc4-b2b1-901f640f5155" />
</desktop5:ItemType>
<!-- Due to a bug in the OS, this doesn't actually work right -
we'll get a nullptr in our implementation. So this is disabled
temporarily. See MSFT:24623699 for more details.
<desktop5:ItemType Type="Directory\Background">
<desktop5:Verb Id="Command2" Clsid="9f156763-7844-4dc4-b2b1-901f640f5155" />
<desktop5:Verb Id="Command2" Clsid="9f156763-7844-4dc4-b2b1-901f640f5155" />
</desktop5:ItemType>
-->

</desktop4:FileExplorerContextMenus>
</desktop4:Extension>

Expand Down
7 changes: 1 addition & 6 deletions src/cascadia/CascadiaPackage/Package.appxmanifest
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,9 @@
<desktop5:ItemType Type="Directory">
<desktop5:Verb Id="Command1" Clsid="9f156763-7844-4dc4-b2b1-901f640f5155" />
</desktop5:ItemType>
<!-- Due to a bug in the OS, this doesn't actually work right -
we'll get a nullptr in our implementation. So this is disabled
temporarily. See MSFT:24623699 for more details.
<desktop5:ItemType Type="Directory\Background">
<desktop5:Verb Id="Command2" Clsid="9f156763-7844-4dc4-b2b1-901f640f5155" />
<desktop5:Verb Id="Command2" Clsid="9f156763-7844-4dc4-b2b1-901f640f5155" />
</desktop5:ItemType>
-->
</desktop4:FileExplorerContextMenus>
</desktop4:Extension>

Expand Down
115 changes: 109 additions & 6 deletions src/cascadia/ShellExtension/OpenTerminalHere.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "pch.h"
#include "OpenTerminalHere.h"
#include <ShlObj.h>

// TODO GH#6112: Localize these strings
static constexpr std::wstring_view VerbDisplayName{ L"Open in Windows Terminal" };
Expand Down Expand Up @@ -117,14 +118,29 @@ static std::wstring _getExePath()
HRESULT OpenTerminalHere::Invoke(IShellItemArray* psiItemArray,
IBindCtx* /*pBindContext*/)
{
DWORD count;
psiItemArray->GetCount(&count);
wil::unique_cotaskmem_string pszName;

winrt::com_ptr<IShellItem> psi;
RETURN_IF_FAILED(psiItemArray->GetItemAt(0, psi.put()));
if (psiItemArray == nullptr)
{
// get the current path from explorer.exe
const auto path = this->_GetPathFromExplorer();

wil::unique_cotaskmem_string pszName;
RETURN_IF_FAILED(psi->GetDisplayName(SIGDN_FILESYSPATH, &pszName));
// no go, unable to get a reasonable path
if (path.empty())
{
return S_FALSE;
}
pszName = wil::make_cotaskmem_string(path.c_str(), path.length());
}
else
{
DWORD count;
psiItemArray->GetCount(&count);

winrt::com_ptr<IShellItem> psi;
RETURN_IF_FAILED(psiItemArray->GetItemAt(0, psi.put()));
RETURN_IF_FAILED(psi->GetDisplayName(SIGDN_FILESYSPATH, &pszName));
}

{
wil::unique_process_information _piClient;
Expand Down Expand Up @@ -214,3 +230,90 @@ HRESULT OpenTerminalHere::EnumSubCommands(IEnumExplorerCommand** ppEnum)
*ppEnum = nullptr;
return E_NOTIMPL;
}

std::wstring OpenTerminalHere::_GetPathFromExplorer() const
{
using namespace std;
using namespace winrt;

wstring path;
HRESULT hr = NOERROR;

auto hwnd = ::GetForegroundWindow();
if (hwnd == nullptr)
{
return path;
}

TCHAR szName[MAX_PATH] = { 0 };
::GetClassName(hwnd, szName, MAX_PATH);
if (0 == StrCmp(szName, L"WorkerW") ||
0 == StrCmp(szName, L"Progman"))
{
//special folder: desktop
hr = ::SHGetFolderPath(NULL, CSIDL_DESKTOP, NULL, SHGFP_TYPE_CURRENT, szName);
if (FAILED(hr))
{
return path;
}

path = szName;
return path;
}

if (0 != StrCmp(szName, L"CabinetWClass"))
{
return path;
}

auto shell = create_instance<IShellWindows>(CLSID_ShellWindows);
if (shell == nullptr)
{
return path;
}

com_ptr<IDispatch> disp;
wil::unique_variant variant;
variant.vt = VT_I4;

com_ptr<IWebBrowserApp> browser;
// look for correct explorer window
for (variant.intVal = 0;
shell->Item(variant, disp.put()) == S_OK;
variant.intVal++)
{
com_ptr<IWebBrowserApp> tmp;
if (FAILED(disp->QueryInterface(tmp.put())))
{
continue;
}

HWND tmpHWND = NULL;
hr = tmp->get_HWND(reinterpret_cast<SHANDLE_PTR*>(&tmpHWND));
if (hwnd == tmpHWND)
{
browser = tmp;
break; //found
}
}

if (browser != nullptr)
{
wil::unique_bstr url;
hr = browser->get_LocationURL(&url);
if (FAILED(hr))
{
return path;
}

wstring sUrl(url.get(), SysStringLen(url.get()));
DWORD size = MAX_PATH;
hr = ::PathCreateFromUrl(sUrl.c_str(), szName, &size, NULL);
if (SUCCEEDED(hr))
{
path = szName;
}
}

return path;
}
3 changes: 3 additions & 0 deletions src/cascadia/ShellExtension/OpenTerminalHere.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ struct __declspec(uuid("9f156763-7844-4dc4-b2b1-901f640f5155"))
STDMETHODIMP GetCanonicalName(GUID* pguidCommandName);
STDMETHODIMP EnumSubCommands(IEnumExplorerCommand** ppEnum);
#pragma endregion

private:
std::wstring _GetPathFromExplorer() const;
};

CoCreatableClass(OpenTerminalHere);
Loading

0 comments on commit 334e518

Please sign in to comment.