Extend the custom Jump List API

Add `app.getJumpListSettings()` and `app.setJumpList(callback)` that
make it possible to fully customize the Jump List of an Electron app.
It is now possible to:
- Add tasks to the standard `Tasks` category.
- Add separators to the standard `Tasks` category.
- Add custom categories containing tasks and file links.
- Add system managed Recent/Frequent categories.
- Remove the custom Jump List.
This commit is contained in:
Vadim Macagon 2016-08-12 16:31:17 +07:00
parent b5dec9990e
commit c64294cf60
7 changed files with 897 additions and 41 deletions

View file

@ -7,10 +7,10 @@
#include <windows.h> // windows.h must be included first
#include <atlbase.h>
#include <propkey.h>
#include <shlobj.h>
#include <shobjidl.h>
#include "atom/browser/ui/win/jump_list.h"
#include "atom/common/atom_version.h"
#include "atom/common/native_mate_converters/string16_converter.h"
#include "base/base_paths.h"
@ -104,49 +104,27 @@ void Browser::SetAppUserModelID(const base::string16& name) {
}
bool Browser::SetUserTasks(const std::vector<UserTask>& tasks) {
CComPtr<ICustomDestinationList> destinations;
if (FAILED(destinations.CoCreateInstance(CLSID_DestinationList)))
return false;
if (FAILED(destinations->SetAppID(GetAppUserModelID())))
JumpList jump_list(GetAppUserModelID());
if (!jump_list.Begin())
return false;
// Start a transaction that updates the JumpList of this application.
UINT max_slots;
CComPtr<IObjectArray> removed;
if (FAILED(destinations->BeginList(&max_slots, IID_PPV_ARGS(&removed))))
return false;
CComPtr<IObjectCollection> collection;
if (FAILED(collection.CoCreateInstance(CLSID_EnumerableObjectCollection)))
return false;
for (auto& task : tasks) {
CComPtr<IShellLink> link;
if (FAILED(link.CoCreateInstance(CLSID_ShellLink)) ||
FAILED(link->SetPath(task.program.value().c_str())) ||
FAILED(link->SetArguments(task.arguments.c_str())) ||
FAILED(link->SetDescription(task.description.c_str())))
return false;
if (!task.icon_path.empty() &&
FAILED(link->SetIconLocation(task.icon_path.value().c_str(),
task.icon_index)))
return false;
CComQIPtr<IPropertyStore> property_store = link;
if (!base::win::SetStringValueForPropertyStore(property_store, PKEY_Title,
task.title.c_str()))
return false;
if (FAILED(collection->AddObject(link)))
return false;
JumpListCategory category;
category.type = JumpListCategory::Type::TASKS;
category.items.reserve(tasks.size());
JumpListItem item;
item.type = JumpListItem::Type::TASK;
for (const auto& task : tasks) {
item.title = task.title;
item.path = task.program;
item.arguments = task.arguments;
item.icon_path = task.icon_path;
item.icon_index = task.icon_index;
item.description = task.description;
category.items.push_back(item);
}
// When the list is empty "AddUserTasks" could fail, so we don't check return
// value for it.
CComQIPtr<IObjectArray> task_array = collection;
destinations->AddUserTasks(task_array);
return SUCCEEDED(destinations->CommitList());
jump_list.AppendCategory(category);
return jump_list.Commit();
}
bool Browser::RemoveAsDefaultProtocolClient(const std::string& protocol,