| /* |
| * 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. |
| */ |
| package com.intellij.ui; |
| |
| import com.intellij.openapi.application.ApplicationManager; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.wm.IdeFrame; |
| import com.sun.jna.Function; |
| import com.sun.jna.Memory; |
| import com.sun.jna.Native; |
| import com.sun.jna.Pointer; |
| import com.sun.jna.platform.win32.*; |
| import com.sun.jna.ptr.PointerByReference; |
| import com.sun.jna.win32.StdCallLibrary; |
| import com.sun.jna.win32.W32APIOptions; |
| |
| import java.awt.*; |
| import java.awt.peer.ComponentPeer; |
| import java.lang.reflect.Method; |
| |
| /** |
| * @author Alexander Lobas |
| */ |
| class Win7TaskBar { |
| private static final Logger LOG = Logger.getInstance("Win7TaskBar"); |
| |
| private static final int TaskBarList_Methods = 21; |
| private static final int TaskBarList_SetProgressValue = 9; |
| private static final int TaskBarList_SetProgressState = 10; |
| private static final int TaskBarList_SetOverlayIcon = 18; |
| |
| private static final WinDef.DWORD ICO_VERSION = new WinDef.DWORD(0x00030000); |
| private static final WinDef.DWORD DWORD_ZERO = new WinDef.DWORD(0); |
| private static final WinDef.DWORD TBPF_NOPROGRESS = DWORD_ZERO; |
| private static final WinDef.DWORD TBPF_NORMAL = new WinDef.DWORD(0x2); |
| private static final WinDef.DWORD TBPF_ERROR = new WinDef.DWORD(0x4); |
| private static final WinDef.ULONGLONG TOTAL_PROGRESS = new WinDef.ULONGLONG(100); |
| |
| private static Pointer myInterfacePointer; |
| private static Function mySetProgressValue; |
| private static Function mySetProgressState; |
| private static Function mySetOverlayIcon; |
| |
| public interface User32Ex extends StdCallLibrary { |
| User32Ex INSTANCE = (User32Ex)Native.loadLibrary("user32", User32Ex.class, W32APIOptions.DEFAULT_OPTIONS); |
| |
| int LookupIconIdFromDirectoryEx(Memory presbits, boolean fIcon, int cxDesired, int cyDesired, int Flags); |
| |
| WinDef.HICON CreateIconFromResourceEx(Pointer presbits, |
| WinDef.DWORD dwResSize, |
| boolean fIcon, |
| WinDef.DWORD dwVer, |
| int cxDesired, |
| int cyDesired, |
| int Flags); |
| |
| boolean FlashWindow(WinDef.HWND hwnd, boolean bInvert); |
| } |
| |
| private static class MyMemory extends Memory { |
| private MyMemory(long size) { |
| super(size); |
| } |
| |
| @Override |
| public synchronized void dispose() { |
| super.dispose(); |
| } |
| } |
| |
| private static boolean ourInitialized = true; |
| |
| static { |
| try { |
| initialize(); |
| } |
| catch (Throwable e) { |
| LOG.error(e); |
| ourInitialized = false; |
| } |
| } |
| |
| private static void initialize() { |
| if (ApplicationManager.getApplication().isUnitTestMode()) { |
| return; |
| } |
| |
| Ole32 ole32 = Ole32.INSTANCE; |
| ole32.CoInitializeEx(Pointer.NULL, 0); |
| |
| Guid.GUID CLSID_TaskbarList = Ole32Util.getGUIDFromString("{56FDF344-FD6D-11d0-958A-006097C9A090}"); |
| Guid.GUID IID_ITaskbarList3 = Ole32Util.getGUIDFromString("{EA1AFB91-9E28-4B86-90E9-9E9F8A5EEFAF}"); |
| PointerByReference p = new PointerByReference(); |
| WinNT.HRESULT hr = ole32.CoCreateInstance(CLSID_TaskbarList, Pointer.NULL, ObjBase.CLSCTX_ALL, IID_ITaskbarList3, p); |
| if (!W32Errors.S_OK.equals(hr)) { |
| LOG.error("Win7TaskBar CoCreateInstance(IID_ITaskbarList3) hResult: " + hr); |
| ourInitialized = false; |
| return; |
| } |
| |
| myInterfacePointer = p.getValue(); |
| Pointer vTablePointer = myInterfacePointer.getPointer(0); |
| Pointer[] vTable = new Pointer[TaskBarList_Methods]; |
| vTablePointer.read(0, vTable, 0, vTable.length); |
| |
| mySetProgressValue = Function.getFunction(vTable[TaskBarList_SetProgressValue], Function.ALT_CONVENTION); |
| mySetProgressState = Function.getFunction(vTable[TaskBarList_SetProgressState], Function.ALT_CONVENTION); |
| mySetOverlayIcon = Function.getFunction(vTable[TaskBarList_SetOverlayIcon], Function.ALT_CONVENTION); |
| } |
| |
| static void setProgress(IdeFrame frame, double value, boolean isOk) { |
| if (!isEnabled()) { |
| return; |
| } |
| |
| WinDef.HWND handle = getHandle(frame); |
| mySetProgressState.invokeInt(new Object[]{myInterfacePointer, handle, isOk ? TBPF_NORMAL : TBPF_ERROR}); |
| mySetProgressValue.invokeInt(new Object[]{myInterfacePointer, handle, new WinDef.ULONGLONG((long)(value * 100)), TOTAL_PROGRESS}); |
| } |
| |
| private static boolean isEnabled() { |
| return !ApplicationManager.getApplication().isUnitTestMode() && ourInitialized; |
| } |
| |
| static void hideProgress(IdeFrame frame) { |
| if (!isEnabled()) { |
| return; |
| } |
| |
| mySetProgressState.invokeInt(new Object[]{myInterfacePointer, getHandle(frame), TBPF_NOPROGRESS}); |
| } |
| |
| static void setOverlayIcon(IdeFrame frame, Object icon, boolean dispose) { |
| if (!isEnabled()) { |
| return; |
| } |
| |
| if (icon == null) { |
| icon = Pointer.NULL; |
| } |
| mySetOverlayIcon.invokeInt(new Object[]{myInterfacePointer, getHandle(frame), icon, Pointer.NULL}); |
| if (dispose) { |
| User32.INSTANCE.DestroyIcon((WinDef.HICON)icon); |
| } |
| } |
| |
| static Object createIcon(byte[] ico) { |
| if (!isEnabled()) { |
| return new Object(); |
| } |
| |
| MyMemory memory = new MyMemory(ico.length); |
| |
| try { |
| memory.write(0, ico, 0, ico.length); |
| |
| int nSize = 100; |
| int offset = User32Ex.INSTANCE.LookupIconIdFromDirectoryEx(memory, true, nSize, nSize, 0); |
| if (offset != 0) { |
| return User32Ex.INSTANCE.CreateIconFromResourceEx(memory.share(offset), DWORD_ZERO, true, ICO_VERSION, nSize, nSize, 0); |
| } |
| return null; |
| } |
| finally { |
| memory.dispose(); |
| } |
| } |
| |
| static void attention(IdeFrame frame, boolean critical) { |
| if (!isEnabled()) { |
| return; |
| } |
| |
| User32Ex.INSTANCE.FlashWindow(getHandle(frame), true); |
| } |
| |
| private static WinDef.HWND getHandle(IdeFrame frame) { |
| try { |
| ComponentPeer peer = ((Component)frame).getPeer(); |
| Method getHWnd = peer.getClass().getMethod("getHWnd"); |
| return new WinDef.HWND(new Pointer((Long)getHWnd.invoke(peer))); |
| } |
| catch (Throwable e) { |
| LOG.error(e); |
| return null; |
| } |
| } |
| } |