diff --git a/bin/win/jumplistbridge.dll b/bin/win/jumplistbridge.dll index be1209cba6d8..cc614d8d3893 100644 Binary files a/bin/win/jumplistbridge.dll and b/bin/win/jumplistbridge.dll differ diff --git a/bin/win/jumplistbridge64.dll b/bin/win/jumplistbridge64.dll index c5f2fdd7a648..212c6d4cde9b 100644 Binary files a/bin/win/jumplistbridge64.dll and b/bin/win/jumplistbridge64.dll differ diff --git a/native/jumplistbridge/jumplistbridge.cpp b/native/jumplistbridge/jumplistbridge.cpp new file mode 100644 index 000000000000..4703ab5d7ee2 --- /dev/null +++ b/native/jumplistbridge/jumplistbridge.cpp @@ -0,0 +1,275 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + /** + * @author Denis Fokin + */ + +#include "stdafx.h" +#include +#include +#include "jumplistbridge64.h" +#include +#include +#include +#include +#pragma comment(lib, "Shlwapi.lib") +#include +#include +#include +#include +#include +#include + +wchar_t * jstowsz(JNIEnv* env, jstring string) +{ + if (string == NULL) { + return NULL; + } + + int chCount = env->GetStringLength(string); + const jchar* javaChars = env->GetStringChars(string, NULL); + + if (javaChars == NULL) { + return NULL; + } + + wchar_t* wideString = new wchar_t[chCount+1]; + memcpy(wideString, javaChars, chCount*2); + wideString[chCount] = 0; + env->ReleaseStringChars(string, javaChars); + return wideString; +} + +PCWSTR jetBrainsAppId; + +/* +* Class: com_intellij_ui_win_RecentTasks +* Method: initialize +* Signature: (Ljava/lang/String;)V +*/ +JNIEXPORT void JNICALL Java_com_intellij_ui_win_RecentTasks_initialize + (JNIEnv * jEnv, jclass clz, jstring jAppId) { + jetBrainsAppId = jstowsz(jEnv, jAppId); + SetCurrentProcessExplicitAppUserModelID(jetBrainsAppId); + ::CoInitialize(NULL); +} + +/* +* Class: com_intellij_ui_win_RecentTasks +* Method: clearNative +* Signature: ()V +*/ +JNIEXPORT void JNICALL Java_com_intellij_ui_win_RecentTasks_clearNative + (JNIEnv *, jclass) { + + ICustomDestinationList * pcdl; + HRESULT hr = CoCreateInstance(CLSID_DestinationList, NULL, CLSCTX_INPROC_SERVER, IID_ICustomDestinationList, (void**)&pcdl); + + if (SUCCEEDED(hr)) { + pcdl->SetAppID(jetBrainsAppId); + + UINT uMaxSlots; + IObjectArray *poaRemoved; + hr = pcdl->BeginList( + &uMaxSlots, + IID_PPV_ARGS(&poaRemoved)); + pcdl->DeleteList(jetBrainsAppId); + hr = pcdl->CommitList(); + } +} + +HRESULT _CreateShellLink(PCWSTR pszPath, + PCWSTR pszArguments, PCWSTR pszTitle, + IShellLink **ppsl) +{ + IShellLink *psl; + HRESULT hr = CoCreateInstance( + CLSID_ShellLink, + NULL, + CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&psl)); + if (SUCCEEDED(hr)) + { + hr = psl->SetPath(pszPath); + if (SUCCEEDED(hr)) + { + hr = psl->SetArguments(pszArguments); + if (SUCCEEDED(hr)) + { + IPropertyStore *pps; + hr = psl->QueryInterface(IID_PPV_ARGS(&pps)); + if (SUCCEEDED(hr)) + { + PROPVARIANT propvar; + hr = InitPropVariantFromString(pszTitle, &propvar); + if (SUCCEEDED(hr)) + { hr = pps->SetValue(PKEY_Title, propvar); + if (SUCCEEDED(hr)) + { + hr = pps->Commit(); + if (SUCCEEDED(hr)) + { + hr = psl->QueryInterface + (IID_PPV_ARGS(ppsl)); + } + } + PropVariantClear(&propvar); + } + pps->Release(); + } + } + } + else + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + psl->Release(); + } + return hr; +} + +void checkJNISuccess (JNIEnv * jEnv) { + if (jEnv->ExceptionOccurred()) { + jEnv->ExceptionDescribe(); + } +} + + +LPCWSTR getShortPath (LPCWSTR lpszPath) { + long length = 0; + TCHAR* buffer = NULL; + length = GetShortPathName(lpszPath, NULL, 0); + buffer = new TCHAR[length]; + length = GetShortPathName(lpszPath, buffer, length); + return buffer; + +} + +/* +* Class: com_intellij_ui_win_RecentTasks +* Method: getShortenPath +* Signature: ([Ljava/lang/String;)[Ljava/lang/String; +*/ +JNIEXPORT jstring JNICALL Java_com_intellij_ui_win_RecentTasks_getShortenPath + (JNIEnv * jEnv, jclass c, jstring path) +{ + + if (path == NULL) { + wprintf(L"The object is NULL \n"); + } + + long length = 0; + TCHAR* shortenPath = NULL; + length = GetShortPathName(jstowsz(jEnv, path), NULL, 0); + shortenPath = new TCHAR[length]; + GetShortPathName(jstowsz(jEnv, path), shortenPath, length); + + char *mbDcr = 0; + + int mblen = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, shortenPath, length, mbDcr, NULL, NULL, NULL); + mbDcr = new char[mblen + 1]; + WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, shortenPath, length, mbDcr, length + 1, NULL, NULL); + + jstring jstrBuf = jEnv->NewStringUTF(mbDcr); + + return jstrBuf; +} + +/* +* Class: com_intellij_ui_win_RecentTasks +* Method: addTasksNativeForCategory +* Signature: (Ljava/lang/String;[Lcom/intellij/ui/win/RecentTasks/Task;)V +*/ +JNIEXPORT void JNICALL Java_com_intellij_ui_win_RecentTasks_addTasksNativeForCategory + (JNIEnv * jEnv, jclass c, jstring cn, jobjectArray linksArray) +{ + LPCWSTR categoryName = (wchar_t*) jEnv->GetStringChars(cn, 0); + + ICustomDestinationList * pcdl; + HRESULT hr = CoCreateInstance(CLSID_DestinationList, NULL, CLSCTX_INPROC_SERVER, IID_ICustomDestinationList, (void**)&pcdl); + + if (SUCCEEDED(hr)) { + pcdl->SetAppID(jetBrainsAppId); + + UINT uMaxSlots; + IObjectArray *poaRemoved; + hr = pcdl->BeginList( + &uMaxSlots, + IID_PPV_ARGS(&poaRemoved)); + if (SUCCEEDED(hr)) + { + IObjectCollection *poc; + HRESULT hr = CoCreateInstance(CLSID_EnumerableObjectCollection, NULL, CLSCTX_INPROC, IID_PPV_ARGS(&poc)); + if (SUCCEEDED(hr)) + { + jint i; + jint count = jEnv->GetArrayLength(linksArray); + for (i=0; i < count; i++) { + jobject linkData = jEnv->GetObjectArrayElement(linksArray, i); + checkJNISuccess(jEnv); + + jclass cls = jEnv->GetObjectClass(linkData); + checkJNISuccess(jEnv); + + jfieldID pathFieldId = jEnv->GetFieldID(cls, "path", "Ljava/lang/String;"); + checkJNISuccess(jEnv); + + jfieldID argsFieldId = jEnv->GetFieldID(cls, "args", "Ljava/lang/String;"); + checkJNISuccess(jEnv); + + jfieldID descriptionFieldId = jEnv->GetFieldID(cls, "description", "Ljava/lang/String;"); + checkJNISuccess(jEnv); + + jstring path = (jstring)jEnv->GetObjectField(linkData, pathFieldId); + checkJNISuccess(jEnv); + + jstring args = (jstring)jEnv->GetObjectField(linkData, argsFieldId); + checkJNISuccess(jEnv); + + jstring description = (jstring)jEnv->GetObjectField(linkData, descriptionFieldId); + checkJNISuccess(jEnv); + + IShellLink * psl; + hr = _CreateShellLink(jstowsz(jEnv, path), + jstowsz(jEnv, args), + jstowsz(jEnv, description), &psl); + + if (SUCCEEDED(hr)) + { + hr = poc->AddObject(psl); + psl->Release(); + + } else { + jEnv->ThrowNew(jEnv->FindClass("java/lang/Exception"), "Cannot create a shell link"); + } + + jEnv->DeleteLocalRef(linkData); + } + + pcdl->AppendCategory(categoryName, poc); + } else { + jEnv->ThrowNew(jEnv->FindClass("java/lang/Exception"), "Cannot recieve CLSID_EnumerableObjectCollection interface"); + } + pcdl->CommitList(); + pcdl->Release(); + } else { + jEnv->ThrowNew(jEnv->FindClass("java/lang/Exception"), "Cannot begin DestinationList"); + } + } else { + jEnv->ThrowNew(jEnv->FindClass("java/lang/Exception"), "Cannot recieve CLSID_DestinationList interface"); + } +} \ No newline at end of file diff --git a/native/jumplistbridge/jumplistbridge.h b/native/jumplistbridge/jumplistbridge.h new file mode 100644 index 000000000000..ff4c0e2c52f8 --- /dev/null +++ b/native/jumplistbridge/jumplistbridge.h @@ -0,0 +1,72 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + /** + * @author Denis Fokin + */ + +#ifdef JUMPLISTBRIDGEJNI_EXPORTS +#define JUMPLISTBRIDGEJNI_API __declspec(dllexport) +#else +#define JUMPLISTBRIDGEJNI_API __declspec(dllimport) +#endif + +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class com_intellij_ui_win_RecentTasks */ + +#ifndef _Included_com_intellij_ui_win_RecentTasks +#define _Included_com_intellij_ui_win_RecentTasks +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_intellij_ui_win_RecentTasks + * Method: initialize + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_intellij_ui_win_RecentTasks_initialize + (JNIEnv *, jclass, jstring); + +/* + * Class: com_intellij_ui_win_RecentTasks + * Method: addTasksNativeForCategory + * Signature: (Ljava/lang/String;[Lcom/intellij/ui/win/RecentTasks/Task;)V + */ +JNIEXPORT void JNICALL Java_com_intellij_ui_win_RecentTasks_addTasksNativeForCategory + (JNIEnv *, jclass, jstring, jobjectArray); + +/* +* Class: com_intellij_ui_win_RecentTasks +* Method: getShortenPath +* Signature: ([Ljava/lang/String;)[Ljava/lang/String; +*/ +JNIEXPORT jstring JNICALL Java_com_intellij_ui_win_RecentTasks_getShortenPath + (JNIEnv * jEnv, jclass c, jstring path); + +/* + * Class: com_intellij_ui_win_RecentTasks + * Method: clearNative + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_intellij_ui_win_RecentTasks_clearNative + (JNIEnv *, jclass); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/platform/platform-impl/src/com/intellij/ui/win/RecentTasks.java b/platform/platform-impl/src/com/intellij/ui/win/RecentTasks.java index ceb834e196c0..6729505df55c 100644 --- a/platform/platform-impl/src/com/intellij/ui/win/RecentTasks.java +++ b/platform/platform-impl/src/com/intellij/ui/win/RecentTasks.java @@ -47,6 +47,7 @@ public class RecentTasks { */ native private static void initialize (String applicationId); native private static void addTasksNativeForCategory (String category, Task [] tasks); + native static String getShortenPath(String paths); native private static void clearNative(); public synchronized static void clear() { diff --git a/platform/platform-impl/src/com/intellij/ui/win/WinDockDelegate.java b/platform/platform-impl/src/com/intellij/ui/win/WinDockDelegate.java index 7f1e02a92c6e..0e6a076c32b7 100644 --- a/platform/platform-impl/src/com/intellij/ui/win/WinDockDelegate.java +++ b/platform/platform-impl/src/com/intellij/ui/win/WinDockDelegate.java @@ -46,7 +46,7 @@ public class WinDockDelegate implements SystemDock.Delegate { Task[] tasks = new Task[recentProjectActions.length]; for (int i = 0; i < recentProjectActions.length; i ++) { ReopenProjectAction rpa = (ReopenProjectAction)recentProjectActions[i]; - tasks[i] = new Task(javaExe, argsToExecute + rpa.getProjectPath(), rpa.getProjectName()); + tasks[i] = new Task(javaExe, argsToExecute + RecentTasks.getShortenPath(rpa.getProjectPath()), rpa.getProjectName()); } RecentTasks.addTasks(tasks); }