]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/TaskBar.java
Remove invalid SHA-256-Digests
[simantics/platform.git] / bundles / org.eclipse.swt.win32.win32.x86_64 / src / org / eclipse / swt / widgets / TaskBar.java
1 /*******************************************************************************
2  * Copyright (c) 2010, 2017 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *     Tasktop Technologies - initial API and implementation
14  *******************************************************************************/
15 package org.eclipse.swt.widgets;
16
17
18 import java.io.*;
19
20 import org.eclipse.swt.*;
21 import org.eclipse.swt.graphics.*;
22 import org.eclipse.swt.internal.*;
23 import org.eclipse.swt.internal.ole.win32.*;
24 import org.eclipse.swt.internal.win32.*;
25
26 /**
27  * Instances of this class represent the system task bar.
28  *
29  * <dl>
30  * <dt><b>Styles:</b></dt>
31  * <dd>(none)</dd>
32  * <dt><b>Events:</b></dt>
33  * <dd>(none)</dd>
34  * </dl>
35  *
36  * @see Display#getSystemTaskBar
37  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
38  *
39  * @since 3.6
40  *
41  * @noextend This class is not intended to be subclassed by clients.
42  */
43 public class TaskBar extends Widget {
44         int itemCount;
45         TaskItem [] items = new TaskItem [4];
46         ITaskbarList3 mTaskbarList3;
47         String iconsDir;
48
49         static final char [] EXE_PATH;
50         static final PROPERTYKEY PKEY_Title = new PROPERTYKEY ();
51         static final PROPERTYKEY PKEY_AppUserModel_IsDestListSeparator = new PROPERTYKEY ();
52         static final String EXE_PATH_KEY = "org.eclipse.swt.win32.taskbar.executable";  //$NON-NLS-1$
53         static final String EXE_ARGS_KEY = "org.eclipse.swt.win32.taskbar.arguments";  //$NON-NLS-1$
54         static final String ICON_KEY = "org.eclipse.swt.win32.taskbar.icon";  //$NON-NLS-1$
55         static final String ICON_INDEX_KEY = "org.eclipse.swt.win32.taskbar.icon.index";  //$NON-NLS-1$
56         static {
57                 OS.PSPropertyKeyFromString ("{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 2\0".toCharArray (), PKEY_Title); //$NON-NLS-1$
58                 OS.PSPropertyKeyFromString ("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}, 6\0".toCharArray (), PKEY_AppUserModel_IsDestListSeparator); //$NON-NLS-1$
59                 char [] buffer = new char [OS.MAX_PATH];
60                 while (OS.GetModuleFileName (0, buffer, buffer.length) == buffer.length) {
61                         buffer = new char [buffer.length + OS.MAX_PATH];
62                 }
63                 EXE_PATH = buffer;
64         }
65
66 TaskBar (Display display, int style) {
67         this.display = display;
68         createHandle ();
69         reskinWidget ();
70 }
71
72 void createHandle () {
73         long[] ppv = new long [1];
74         int hr = COM.CoCreateInstance (COM.CLSID_TaskbarList, 0, COM.CLSCTX_INPROC_SERVER, COM.IID_ITaskbarList3, ppv);
75         if (hr != OS.S_OK) error (SWT.ERROR_NO_HANDLES);
76         mTaskbarList3 = new ITaskbarList3 (ppv [0]);
77 }
78
79 void createItem (TaskItem item, int index) {
80         if (index == -1) index = itemCount;
81         if (!(0 <= index && index <= itemCount)) error (SWT.ERROR_INVALID_RANGE);
82         if (itemCount == items.length) {
83                 TaskItem [] newItems = new TaskItem [items.length + 4];
84                 System.arraycopy (items, 0, newItems, 0, items.length);
85                 items = newItems;
86         }
87         System.arraycopy (items, index, items, index + 1, itemCount++ - index);
88         items [index] = item;
89 }
90
91 void createItems () {
92         Shell [] shells = display.getShells ();
93         for (int i = 0; i < shells.length; i++) {
94                 getItem (shells[i]);
95         }
96         getItem (null);
97 }
98
99 IShellLink createShellLink (MenuItem item) {
100         int style = item.getStyle ();
101         if ((style & SWT.CASCADE) != 0) return null;
102         long [] ppv = new long [1];
103         int hr = COM.CoCreateInstance (COM.CLSID_ShellLink, 0, COM.CLSCTX_INPROC_SERVER, COM.IID_IShellLinkW, ppv);
104         if (hr != OS.S_OK) error (SWT.ERROR_NO_HANDLES);
105         IShellLink pLink = new IShellLink (ppv [0]);
106
107         long hHeap = OS.GetProcessHeap ();
108         long pv = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, OS.PROPVARIANT_sizeof());
109         long titlePtr = 0;
110         PROPERTYKEY key;
111         if ((style & SWT.SEPARATOR) != 0) {
112                 OS.MoveMemory (pv, new short [] {OS.VT_BOOL}, 2);
113                 OS.MoveMemory (pv + 8, new short [] {OS.VARIANT_TRUE}, 2);
114                 key = PKEY_AppUserModel_IsDestListSeparator;
115         } else {
116                 String text = item.getText ();
117                 int length = text.length ();
118                 char [] buffer = new char [length + 1];
119                 text.getChars (0, length, buffer, 0);
120                 titlePtr = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, buffer.length * 2);
121                 OS.MoveMemory (titlePtr, buffer, buffer.length * 2);
122                 OS.MoveMemory (pv, new short [] {OS.VT_LPWSTR}, 2);
123                 OS.MoveMemory (pv + 8, new long [] {titlePtr}, C.PTR_SIZEOF);
124                 key = PKEY_Title;
125
126                 String exePath = (String)item.getData (EXE_PATH_KEY);
127                 if (exePath != null) {
128                         length = exePath.length ();
129                         buffer = new char [length + 1];
130                         exePath.getChars (0, length, buffer, 0);
131                 } else {
132                         buffer = EXE_PATH;
133                 }
134                 hr = pLink.SetPath(buffer);
135                 if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
136
137                 text = (String)item.getData (EXE_ARGS_KEY);
138                 if (text == null) text = Display.LAUNCHER_PREFIX + Display.TASKBAR_EVENT + item.id;
139                 length = text.length ();
140                 buffer = new char [length + 1];
141                 text.getChars (0, length, buffer, 0);
142                 hr = pLink.SetArguments(buffer);
143                 if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
144
145                 /* This code is intentionally commented */
146 //              String tooltip = item.tooltip;
147 //              if (tooltip != null) {
148 //                      length = tooltip.length ();
149 //                      buffer = new char [length + 1];
150 //                      tooltip.getChars (0, length, buffer, 0);
151 //                      hr = pLink.SetDescription (buffer);
152 //                      if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
153 //              }
154
155                 String icon = (String)item.getData (ICON_KEY);
156                 int index = 0;
157                 if (icon != null) {
158                         text = (String)item.getData (ICON_INDEX_KEY);
159                         if (text != null) index = Integer.parseInt (text);
160                 } else {
161                         String directory = null;
162                         Image image = item.getImage ();
163                         if (image != null) directory = getIconsDir ();
164                         if (directory != null) {
165                                 icon = directory + "\\" + "menu" + item.id + ".ico";
166                                 ImageData data;
167                                 if (item.hBitmap != 0) {
168                                         Image image2 = Image.win32_new (display, SWT.BITMAP, item.hBitmap);
169                                         data = image2.getImageData (DPIUtil.getDeviceZoom ());
170                                 } else {
171                                         data = image.getImageData (DPIUtil.getDeviceZoom ());
172                                 }
173                                 ImageLoader loader = new ImageLoader ();
174                                 loader.data = new ImageData [] {data};
175                                 loader.save (icon, SWT.IMAGE_ICO);
176                         }
177                 }
178                 if (icon != null) {
179                         length = icon.length ();
180                         buffer = new char [length + 1];
181                         icon.getChars (0, length, buffer, 0);
182                         hr = pLink.SetIconLocation(buffer, index);
183                         if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
184                 }
185         }
186
187         hr = pLink.QueryInterface(COM.IID_IPropertyStore, ppv);
188         if (hr != OS.S_OK) error (SWT.ERROR_NO_HANDLES);
189         IPropertyStore pPropStore = new IPropertyStore (ppv [0]);
190         hr = pPropStore.SetValue(key, pv);
191         if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
192         pPropStore.Commit();
193         pPropStore.Release();
194
195         OS.HeapFree (hHeap, 0, pv);
196         if (titlePtr != 0) OS.HeapFree (hHeap, 0, titlePtr);
197         return pLink;
198 }
199
200 IObjectArray createShellLinkArray (MenuItem [] items) {
201         if (items == null) return null;
202         if (items.length == 0) return null;
203         long [] ppv = new long [1];
204         int hr = COM.CoCreateInstance (COM.CLSID_EnumerableObjectCollection, 0, COM.CLSCTX_INPROC_SERVER, COM.IID_IObjectCollection, ppv);
205         if (hr != OS.S_OK) error (SWT.ERROR_NO_HANDLES);
206         IObjectCollection pObjColl = new IObjectCollection (ppv [0]);
207         for (int i = 0; i < items.length; i++) {
208                 IShellLink pLink = createShellLink (items[i]);
209                 if (pLink != null) {
210                         /*IObjectCollection::AddObject*/
211                         pObjColl.AddObject (pLink);
212                         if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
213                         pLink.Release ();
214                 }
215         }
216         /*IUnknown::QueryInterface*/
217         hr = pObjColl.QueryInterface(COM.IID_IObjectArray, ppv);
218         if (hr != OS.S_OK) error (SWT.ERROR_NO_HANDLES);
219         IObjectArray poa = new IObjectArray (ppv [0]);
220         pObjColl.Release ();
221         return poa;
222 }
223
224 void destroyItem (TaskItem item) {
225         int index = 0;
226         while (index < itemCount) {
227                 if (items [index] == item) break;
228                 index++;
229         }
230         if (index == itemCount) return;
231         System.arraycopy (items, index + 1, items, index, --itemCount - index);
232         items [itemCount] = null;
233 }
234
235 String getIconsDir() {
236         if (iconsDir != null) return iconsDir;
237         String appData = System.getenv("LOCALAPPDATA");
238         String appName = Display.APP_NAME;
239         if (appData == null || appName == null) return null;
240         appName = appName.replaceAll("[\\\\/:*?\"<>|]", "_");
241         File dir = new File(appData + "\\" + appName + "\\ico_dir");
242         if (dir.exists()) {
243                 // remove old icons
244                 for (File file : dir.listFiles()) file.delete();
245         } else if (!dir.mkdirs()) {
246                 return null;
247         }
248         return iconsDir = dir.getPath();
249 }
250
251 /**
252  * Returns the item at the given, zero-relative index in the
253  * receiver. Throws an exception if the index is out of range.
254  *
255  * @param index the index of the item to return
256  * @return the item at the given index
257  *
258  * @exception IllegalArgumentException <ul>
259  *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
260  * </ul>
261  * @exception SWTException <ul>
262  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
263  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
264  * </ul>
265  */
266 public TaskItem getItem (int index) {
267         checkWidget ();
268         createItems ();
269         if (!(0 <= index && index < itemCount)) error (SWT.ERROR_INVALID_RANGE);
270         return items [index];
271 }
272
273 /**
274  * Returns the <code>TaskItem</code> for the given <code>Shell</code> or the <code>TaskItem</code>
275  * for the application if the <code>Shell</code> parameter is <code>null</code>.
276  * If the requested item is not supported by the platform it returns <code>null</code>.
277  *
278  * @param shell the shell for which the task item is requested, or null to request the application item
279  * @return the task item for the given shell or the application
280  *
281  * @exception SWTException <ul>
282  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
283  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
284  * </ul>
285  */
286 public TaskItem getItem (Shell shell) {
287         checkWidget ();
288         for (int i = 0; i < items.length; i++) {
289                 if (items [i] != null && items [i].shell == shell) {
290                         return items [i];
291                 }
292         }
293         TaskItem item = new TaskItem (this, SWT.NONE);
294         if (shell != null) item.setShell (shell);
295         return item;
296 }
297
298 /**
299  * Returns the number of items contained in the receiver.
300  *
301  * @return the number of items
302  *
303  * @exception SWTException <ul>
304  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
305  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
306  * </ul>
307  */
308 public int getItemCount () {
309         checkWidget ();
310         createItems ();
311         return itemCount;
312 }
313
314 /**
315  * Returns an array of <code>TaskItem</code>s which are the items
316  * in the receiver.
317  * <p>
318  * Note: This is not the actual structure used by the receiver
319  * to maintain its list of items, so modifying the array will
320  * not affect the receiver.
321  * </p>
322  *
323  * @return the items in the receiver
324  *
325  * @exception SWTException <ul>
326  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
327  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
328  * </ul>
329  */
330 public TaskItem [] getItems () {
331         checkWidget ();
332         createItems ();
333         TaskItem [] result = new TaskItem [itemCount];
334         System.arraycopy (items, 0, result, 0, result.length);
335         return result;
336 }
337
338 @Override
339 void releaseChildren (boolean destroy) {
340         if (items != null) {
341                 for (int i=0; i<items.length; i++) {
342                         TaskItem item = items [i];
343                         if (item != null && !item.isDisposed ()) {
344                                 item.release (false);
345                         }
346                 }
347                 items = null;
348         }
349         super.releaseChildren (destroy);
350 }
351
352 @Override
353 void releaseParent () {
354         super.releaseParent ();
355         if (display.taskBar == this) display.taskBar = null;
356 }
357
358 @Override
359 void releaseWidget () {
360         super.releaseWidget ();
361         mTaskbarList3.Release();
362         mTaskbarList3 = null;
363 }
364
365 @Override
366 void reskinChildren (int flags) {
367         if (items != null) {
368                 for (int i=0; i<items.length; i++) {
369                         TaskItem item = items [i];
370                         if (item != null) item.reskin (flags);
371                 }
372         }
373         super.reskinChildren (flags);
374 }
375
376 void setMenu (Menu menu) {
377         long [] ppv = new long [1];
378         int hr = COM.CoCreateInstance (COM.CLSID_DestinationList, 0, COM.CLSCTX_INPROC_SERVER, COM.IID_ICustomDestinationList, ppv);
379         if (hr != OS.S_OK) error (SWT.ERROR_NO_HANDLES);
380         ICustomDestinationList pDestList = new ICustomDestinationList (ppv [0]);
381         String appName = Display.APP_NAME;
382         char [] buffer = {'S', 'W', 'T', '\0'};
383         if (appName != null && appName.length () > 0) {
384                 int length = appName.length ();
385                 buffer = new char [length + 1];
386                 appName.getChars (0, length, buffer, 0);
387         }
388         MenuItem [] items = null;
389         if (menu != null && (items = menu.getItems ()).length != 0) {
390                 IObjectArray poa = createShellLinkArray (items);
391                 if (poa != null) {
392                         hr = pDestList.SetAppID (buffer);
393                         if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
394
395                         int [] cMaxSlots = new int [1];
396                         pDestList.BeginList(cMaxSlots, COM.IID_IObjectArray, ppv);
397                         if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
398                         IObjectArray pRemovedItems = new IObjectArray (ppv [0]);
399
400                         int [] count = new int [1];
401                         poa.GetCount (count);
402                         if (count [0] != 0) {
403                                 hr = pDestList.AddUserTasks (poa);
404                                 if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
405                         }
406
407                         for (int i = 0; i < items.length; i++) {
408                                 MenuItem item = items [i];
409                                 if ((item.getStyle () & SWT.CASCADE) != 0) {
410                                         Menu subMenu = item.getMenu ();
411                                         if (subMenu != null) {
412                                                 MenuItem [] subItems = subMenu.getItems ();
413                                                 IObjectArray poa2 = createShellLinkArray (subItems);
414                                                 if (poa2 != null) {
415                                                         poa2.GetCount (count);
416                                                         if (count [0] != 0) {
417                                                                 String text = item.getText ();
418                                                                 int length = text.length ();
419                                                                 char [] buffer2 = new char [length + 1];
420                                                                 text.getChars (0, length, buffer2, 0);
421                                                                 hr = pDestList.AppendCategory (buffer2, poa2);
422                                                                 if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
423                                                         }
424                                                         /*IUnknown::Release*/
425                                                         poa2.Release ();
426                                                 }
427                                         }
428                                 }
429                         }
430                         poa.Release();
431                         hr = pDestList.CommitList ();
432                         if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
433                         pRemovedItems.Release ();
434                 }
435         } else {
436                 hr = pDestList.DeleteList (buffer);
437                 if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
438         }
439         pDestList.Release ();
440 }
441
442 }