Skip to content

Instantly share code, notes, and snippets.

@silphire
Created March 9, 2014 13:15
Show Gist options
  • Save silphire/9447590 to your computer and use it in GitHub Desktop.
Save silphire/9447590 to your computer and use it in GitHub Desktop.
Windows 7 jumplist patch for mintty
Index: Makefile
===================================================================
--- Makefile (revision 1322)
+++ Makefile (working copy)
@@ -69,7 +69,7 @@
endif
LDFLAGS := -L$(shell $(CC) -print-file-name=w32api) -static-libgcc
-LDLIBS := -mwindows -lcomctl32 -limm32 -lwinspool -lole32 -luuid
+LDLIBS := -mwindows -lcomctl32 -limm32 -lwinspool -lole32 -luuid -lshlwapi
ifdef DEBUG
CFLAGS += -g
Index: config.c
===================================================================
--- config.c (revision 1322)
+++ config.c (working copy)
@@ -97,6 +97,15 @@
[BOLD_MAGENTA_I] = 0xFF40FF,
[BOLD_CYAN_I] = 0xFFFF40,
[BOLD_WHITE_I] = 0xFFFFFF,
+ },
+ // Jump List
+ .jump_list_cmd = {
+ "", "", "", "", "",
+ "", "", "", "", "",
+ },
+ .jump_list_title = {
+ "", "", "", "", "",
+ "", "", "", "", "",
}
};
@@ -209,6 +218,29 @@
{"BoldCyan", OPT_COLOUR, offcfg(ansi_colours[BOLD_CYAN_I])},
{"BoldWhite", OPT_COLOUR, offcfg(ansi_colours[BOLD_WHITE_I])},
+ // Jump List
+ {"JumpListCmd0", OPT_STRING, offcfg(jump_list_cmd[0])},
+ {"JumpListCmd1", OPT_STRING, offcfg(jump_list_cmd[1])},
+ {"JumpListCmd2", OPT_STRING, offcfg(jump_list_cmd[2])},
+ {"JumpListCmd3", OPT_STRING, offcfg(jump_list_cmd[3])},
+ {"JumpListCmd4", OPT_STRING, offcfg(jump_list_cmd[4])},
+ {"JumpListCmd5", OPT_STRING, offcfg(jump_list_cmd[5])},
+ {"JumpListCmd6", OPT_STRING, offcfg(jump_list_cmd[6])},
+ {"JumpListCmd7", OPT_STRING, offcfg(jump_list_cmd[7])},
+ {"JumpListCmd8", OPT_STRING, offcfg(jump_list_cmd[8])},
+ {"JumpListCmd9", OPT_STRING, offcfg(jump_list_cmd[9])},
+
+ {"JumpListTitle0", OPT_STRING, offcfg(jump_list_title[0])},
+ {"JumpListTitle1", OPT_STRING, offcfg(jump_list_title[1])},
+ {"JumpListTitle2", OPT_STRING, offcfg(jump_list_title[2])},
+ {"JumpListTitle3", OPT_STRING, offcfg(jump_list_title[3])},
+ {"JumpListTitle4", OPT_STRING, offcfg(jump_list_title[4])},
+ {"JumpListTitle5", OPT_STRING, offcfg(jump_list_title[5])},
+ {"JumpListTitle6", OPT_STRING, offcfg(jump_list_title[6])},
+ {"JumpListTitle7", OPT_STRING, offcfg(jump_list_title[7])},
+ {"JumpListTitle8", OPT_STRING, offcfg(jump_list_title[8])},
+ {"JumpListTitle9", OPT_STRING, offcfg(jump_list_title[9])},
+
// Legacy
{"UseSystemColours", OPT_BOOL | OPT_LEGACY, offcfg(use_system_colours)},
{"BoldAsBright", OPT_BOOL | OPT_LEGACY, offcfg(bold_as_colour)},
Index: config.h
===================================================================
--- config.h (revision 1322)
+++ config.h (working copy)
@@ -99,6 +99,9 @@
string word_chars;
colour ime_cursor_colour;
colour ansi_colours[16];
+ // Jump List
+ string jump_list_cmd[10];
+ string jump_list_title[10];
// Legacy
bool use_system_colours;
} config;
Index: jumplist.c
===================================================================
--- jumplist.c (revision 0)
+++ jumplist.c (working copy)
@@ -0,0 +1,208 @@
+#include <objbase.h>
+#include <shlobj.h>
+#include <shobjidl.h>
+#include <propvarutil.h>
+#include <propkey.h>
+#include <unistd.h>
+
+#include "jumplist.h"
+#include "charset.h"
+#include "config.h"
+
+#if WINVER >= 0x0601
+
+static HRESULT clear_jumplist(void)
+{
+ HRESULT hr = S_OK;
+ ICustomDestinationList *pCustomDestinationList;
+
+ hr = CoCreateInstance(&CLSID_DestinationList, NULL, CLSCTX_INPROC_SERVER, &IID_ICustomDestinationList, (void **)&pCustomDestinationList);
+ if(FAILED(hr)) {
+ return hr;
+ }
+
+ hr = pCustomDestinationList->lpVtbl->DeleteList((void *)pCustomDestinationList, NULL);
+
+ pCustomDestinationList->lpVtbl->Release((void *)pCustomDestinationList);
+ return hr;
+}
+
+#ifndef __cplusplus
+
+static HRESULT InitPropVariantFromString(PCSTR pString, PROPVARIANT *pPropVariant)
+{
+ HRESULT hr = SHStrDupA(pString, &pPropVariant->pwszVal);
+ if(SUCCEEDED(hr)) {
+ pPropVariant->vt = VT_LPWSTR;
+ } else {
+ PropVariantInit(pPropVariant);
+ }
+
+ return hr;
+}
+
+#endif
+
+static HRESULT register_task(IObjectCollection *pObjectCollection, const string title, const string args)
+{
+ HRESULT hr = S_OK;
+ IShellLink *pShellLink;
+
+ if(args == NULL || strlen(args) == 0)
+ return S_OK;
+
+ const string showTitle = (title == NULL || strlen(title) == 0) ? args : title;
+
+ char exePath[MAX_PATH + 1];
+ if(GetModuleFileName(NULL, exePath, MAX_PATH) == 0)
+ return S_FALSE;
+
+ hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, (void **)&pShellLink);
+ if(SUCCEEDED(hr)) {
+
+ do {
+
+ // set title
+ IPropertyStore *pPropertyStore;
+ hr = pShellLink->lpVtbl->QueryInterface((void *)pShellLink, &IID_IPropertyStore, (void **)&pPropertyStore);
+ if(SUCCEEDED(hr)) {
+
+ PROPVARIANT propVariant;
+
+ hr = InitPropVariantFromString(showTitle, &propVariant);
+ if(SUCCEEDED(hr)) {
+
+ hr = pPropertyStore->lpVtbl->SetValue((void *)pPropertyStore, &PKEY_Title, &propVariant);
+ if(SUCCEEDED(hr)) {
+
+ pPropertyStore->lpVtbl->Commit((void *)pPropertyStore);
+ }
+ }
+ }
+ if(FAILED(hr))
+ break;
+
+ // set full path of mintty.exe
+ hr = pShellLink->lpVtbl->SetPath((void *)pShellLink, exePath);
+ if(FAILED(hr))
+ break;
+
+ // set arguments
+ hr = pShellLink->lpVtbl->SetArguments((void *)pShellLink, args);
+ if(FAILED(hr))
+ break;
+
+ // finally, register this column into the jump list
+ hr = pObjectCollection->lpVtbl->AddObject((void *)pObjectCollection, (IUnknown *)pShellLink);
+ } while(0);
+
+ pShellLink->lpVtbl->Release((void *)pShellLink);
+ }
+
+ return hr;
+}
+
+static HRESULT create_jumplist(const string titles[], const string args[])
+{
+ HRESULT hr = S_OK;
+ ICustomDestinationList *pCustomDestinationList;
+
+ hr = CoCreateInstance(&CLSID_DestinationList, NULL, CLSCTX_INPROC_SERVER, &IID_ICustomDestinationList, (void **)&pCustomDestinationList);
+ if(SUCCEEDED(hr)) {
+
+ // register all custom tasks
+ size_t len = cs_mbstowcs(0, cfg.app_id, 0) + 1;
+ if(len) {
+
+ wchar_t wAppID[len];
+
+ cs_mbstowcs(wAppID, cfg.app_id, len);
+ hr = pCustomDestinationList->lpVtbl->SetAppID((void *)pCustomDestinationList, wAppID);
+ if(SUCCEEDED(hr)) {
+
+ UINT nSlots;
+ IObjectArray *pRemovedList;
+
+ hr = pCustomDestinationList->lpVtbl->BeginList((void *)pCustomDestinationList, &nSlots, &IID_IObjectArray, (void **)&pRemovedList);
+ if(SUCCEEDED(hr)) {
+
+ IObjectCollection *pObjectCollection;
+
+ hr = CoCreateInstance(&CLSID_EnumerableObjectCollection, NULL, CLSCTX_INPROC_SERVER, &IID_IObjectCollection, (void **)&pObjectCollection);
+ if(SUCCEEDED(hr)) {
+
+ // add all tasks
+ for(int i = 0; i < 10; ++i) {
+ hr = register_task(pObjectCollection, titles[i], args[i]);
+ if(FAILED(hr)) {
+ break;
+ }
+ }
+
+ if(SUCCEEDED(hr)) {
+
+ IObjectArray *pObjectArray;
+
+ hr = pObjectCollection->lpVtbl->QueryInterface((void *)pObjectCollection, &IID_IObjectArray, (void **)&pObjectArray);
+ if(SUCCEEDED(hr)) {
+
+ hr = pCustomDestinationList->lpVtbl->AddUserTasks((void *)pCustomDestinationList, pObjectArray);
+
+ pObjectArray->lpVtbl->Release((void *)pObjectArray);
+ }
+
+ pCustomDestinationList->lpVtbl->CommitList((void *)pCustomDestinationList);
+ }
+
+ pObjectCollection->lpVtbl->Release((void *)pObjectCollection);
+ }
+
+ pRemovedList->lpVtbl->Release((void *)pRemovedList);
+ }
+ }
+ }
+
+ pCustomDestinationList->lpVtbl->Release((void *)pCustomDestinationList);
+ }
+
+ return hr;
+}
+
+HRESULT setup_jumplist(const string titles[], const string args[])
+{
+ OSVERSIONINFO ver;
+ ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ GetVersionEx(&ver);
+
+ // if running under the machine older than Windows 7, silently return.
+ if(!((ver.dwMajorVersion == 6 && ver.dwMinorVersion >= 1) || ver.dwMajorVersion >= 7)) {
+ return S_OK;
+ }
+
+ HRESULT hr = S_OK;
+
+ hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+ if(FAILED(hr))
+ return hr;
+
+ hr = clear_jumplist();
+ if(SUCCEEDED(hr)) {
+ hr = create_jumplist(titles, args);
+ }
+
+ CoUninitialize();
+ return hr;
+}
+
+#else
+
+HRESULT setup_jumplist(const string titles[], const string args[])
+{
+ (void)titles;
+ (void)args;
+
+ return S_OK;
+}
+
+#endif
+
Index: jumplist.h
===================================================================
--- jumplist.h (revision 0)
+++ jumplist.h (working copy)
@@ -0,0 +1,8 @@
+#ifndef JUMPLIST_H_
+#define JUMPLIST_H_
+
+#include <objbase.h>
+
+HRESULT setup_jumplist(const string titles[], const string args[]);
+
+#endif // JUMPLIST_H_
Index: std.h
===================================================================
--- std.h (revision 1322)
+++ std.h (working copy)
@@ -41,7 +41,8 @@
char *asform(const char *fmt, ...);
-#define WINVER 0x500 // Windows 2000
+// #define WINVER 0x500 // Windows 2000
+#define WINVER 0x601 // Windows 7
#define _WIN32_WINNT WINVER
#define _WIN32_IE WINVER
Index: winmain.c
===================================================================
--- winmain.c (revision 1322)
+++ winmain.c (working copy)
@@ -9,6 +9,7 @@
#include "appinfo.h"
#include "child.h"
#include "charset.h"
+#include "jumplist.h"
#include <locale.h>
#include <getopt.h>
@@ -41,6 +42,8 @@
int cyBottomHeight;
} MARGINS;
+#else
+#include <dwmapi.h>
#endif
static HRESULT (WINAPI *pDwmIsCompositionEnabled)(BOOL *);
@@ -765,7 +768,7 @@
string rc_file = asform("%s/.minttyrc", home);
load_config(rc_file);
delete(rc_file);
-
+
for (;;) {
int opt = getopt_long(argc, argv, short_opts, opts, 0);
if (opt == -1 || opt == 'e')
@@ -892,6 +895,8 @@
inst = GetModuleHandle(NULL);
+ setup_jumplist(cfg.jump_list_title, cfg.jump_list_cmd);
+
// Window class name.
wstring wclass = _W(APPNAME);
if (*cfg.class) {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment