Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add profiles to the Jumplist #7515

Merged
9 commits merged into from
Sep 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/actions/spell-check/dictionary/microsoft.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pgo
pgosweep
powerrename
powershell
propkey
pscustomobject
robocopy
SACLs
Expand Down
4 changes: 4 additions & 0 deletions src/cascadia/TerminalApp/AppLogic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,8 @@ namespace winrt::TerminalApp::implementation

// Register for directory change notification.
_RegisterSettingsChange();

Jumplist::UpdateJumplist(*_settings);
}

// Method Description:
Expand Down Expand Up @@ -851,6 +853,8 @@ namespace winrt::TerminalApp::implementation

_RefreshThemeRoutine();
_ApplyStartupTaskStateChange();

Jumplist::UpdateJumplist(*_settings);
}

// Method Description:
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalApp/AppLogic.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "Tab.h"
#include "CascadiaSettings.h"
#include "TerminalPage.h"
#include "Jumplist.h"
#include "../../cascadia/inc/cppwinrt_utils.h"

namespace winrt::TerminalApp::implementation
Expand Down
131 changes: 131 additions & 0 deletions src/cascadia/TerminalApp/Jumplist.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

#include "pch.h"
#include "Jumplist.h"

#include <ShObjIdl.h>
#include <Propkey.h>

using namespace winrt::TerminalApp;

// This property key isn't already defined in propkey.h, but is used by UWP Jumplist to determine the icon of the jumplist item.
// IShellLink's SetIconLocation isn't going to read "ms-appx://" icon paths, so we'll need to use this to set the icon.
DEFINE_PROPERTYKEY(PKEY_AppUserModel_DestListLogoUri, 0x9F4C2855, 0x9F79, 0x4B39, 0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3, 29);
#define INIT_PKEY_AppUserModel_DestListLogoUri \
{ \
{ 0x9F4C2855, 0x9F79, 0x4B39, 0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3 }, 29 \
}

// Method Description:
// - Updates the items of the Jumplist based on the given settings.
// Arguments:
// - settings - The settings object to update the jumplist with.
// Return Value:
// - <none>
HRESULT Jumplist::UpdateJumplist(const TerminalApp::CascadiaSettings& settings) noexcept
{
leonMSFT marked this conversation as resolved.
Show resolved Hide resolved
try
{
auto jumplistInstance = winrt::create_instance<ICustomDestinationList>(CLSID_DestinationList, CLSCTX_ALL);

// Start the Jumplist edit transaction
uint32_t slots;
winrt::com_ptr<IObjectCollection> jumplistItems;
jumplistItems.capture(jumplistInstance, &ICustomDestinationList::BeginList, &slots);

// It's easier to clear the list and re-add everything. The settings aren't
// updated often, and there likely isn't a huge amount of items to add.
RETURN_IF_FAILED(jumplistItems->Clear());

// Update the list of profiles.
RETURN_IF_FAILED(_updateProfiles(jumplistItems.get(), settings.GetProfiles()));

// TODO GH#1571: Add items from the future customizable new tab dropdown as well.
// This could either replace the default profiles, or be added alongside them.

// Add the items to the jumplist Task section.
// The Tasks section is immutable by the user, unlike the destinations
// section that can have its items pinned and removed.
RETURN_IF_FAILED(jumplistInstance->AddUserTasks(jumplistItems.get()));

RETURN_IF_FAILED(jumplistInstance->CommitList());

return S_OK;
}
CATCH_RETURN();
}

// Method Description:
// - Creates and adds a ShellLink object to the Jumplist for each profile.
// Arguments:
// - jumplistItems - The jumplist item list
// - profiles - The profiles to add to the jumplist
// Return Value:
// - S_OK or HRESULT failure code.
[[nodiscard]] HRESULT Jumplist::_updateProfiles(IObjectCollection* jumplistItems, const gsl::span<const Profile>& profiles) noexcept
{
try
{
for (const auto& profile : profiles)
{
// Craft the arguments following "wt.exe"
auto args = fmt::format(L"-p {}", to_hstring(profile.Guid()));

// Create the shell link object for the profile
winrt::com_ptr<IShellLinkW> shLink;
RETURN_IF_FAILED(_createShellLink(profile.Name(), profile.GetExpandedIconPath(), args, shLink.put()));

RETURN_IF_FAILED(jumplistItems->AddObject(shLink.get()));
}

return S_OK;
}
CATCH_RETURN();
}

// Method Description:
// - Creates a ShellLink object. Each item in a jumplist is a ShellLink, which is sort of
// like a shortcut. It requires the path to the application (wt.exe), the arguments to pass,
// and the path to the icon for the jumplist item. The path to the application isn't passed
// into this function, as we'll determine it with GetModuleFileName.
// Arguments:
// - name: The name of the item displayed in the jumplist.
// - path: The path to the icon for the jumplist item.
// - args: The arguments to pass along with wt.exe
// - shLink: The shell link object to return.
// Return Value:
// - S_OK or HRESULT failure code.
[[nodiscard]] HRESULT Jumplist::_createShellLink(const std::wstring_view name,
const std::wstring_view path,
const std::wstring_view args,
IShellLinkW** shLink) noexcept
{
try
{
auto sh = winrt::create_instance<IShellLinkW>(CLSID_ShellLink, CLSCTX_ALL);

std::filesystem::path module{ wil::GetModuleFileNameW<std::wstring>(nullptr) };
RETURN_IF_FAILED(sh->SetPath(module.c_str()));
RETURN_IF_FAILED(sh->SetArguments(args.data()));

PROPVARIANT titleProp;
titleProp.vt = VT_LPWSTR;
titleProp.pwszVal = const_cast<wchar_t*>(name.data());

PROPVARIANT iconProp;
iconProp.vt = VT_LPWSTR;
iconProp.pwszVal = const_cast<wchar_t*>(path.data());

auto propStore{ sh.as<IPropertyStore>() };
RETURN_IF_FAILED(propStore->SetValue(PKEY_Title, titleProp));
RETURN_IF_FAILED(propStore->SetValue(PKEY_AppUserModel_DestListLogoUri, iconProp));

RETURN_IF_FAILED(propStore->Commit());

*shLink = sh.detach();

return S_OK;
}
CATCH_RETURN();
}
29 changes: 29 additions & 0 deletions src/cascadia/TerminalApp/Jumplist.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
// Module Name:
// - Jumplist.h
//
// Abstract:
// - The Jumplist is the menu that pops up when right clicking a pinned
// item in the taskbar. This class handles updating the Terminal's jumplist
// using the Terminal's settings.
//

#pragma once

#include "CascadiaSettings.h"
#include "Profile.h"

struct IObjectCollection;
struct IShellLinkW;

class Jumplist
{
public:
static HRESULT UpdateJumplist(const TerminalApp::CascadiaSettings& settings) noexcept;

private:
[[nodiscard]] static HRESULT _updateProfiles(IObjectCollection* jumplistItems, const gsl::span<const winrt::TerminalApp::Profile>& profiles) noexcept;
[[nodiscard]] static HRESULT _createShellLink(const std::wstring_view name, const std::wstring_view path, const std::wstring_view args, IShellLinkW** shLink) noexcept;
};
2 changes: 2 additions & 0 deletions src/cascadia/TerminalApp/TerminalAppLib.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
<ClInclude Include="App.base.h" />
<ClInclude Include="AppCommandlineArgs.h" />
<ClInclude Include="Commandline.h" />
<ClInclude Include="Jumplist.h" />
<ClInclude Include="MinMaxCloseControl.h">
<DependentUpon>MinMaxCloseControl.xaml</DependentUpon>
</ClInclude>
Expand Down Expand Up @@ -155,6 +156,7 @@
<ClCompile Include="init.cpp" />
<ClCompile Include="AppCommandlineArgs.cpp" />
<ClCompile Include="Commandline.cpp" />
<ClCompile Include="Jumplist.cpp" />
<ClCompile Include="MinMaxCloseControl.cpp">
<DependentUpon>MinMaxCloseControl.xaml</DependentUpon>
</ClCompile>
Expand Down