1 /* 2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.awt; 27 28 import java.awt.peer.TaskbarPeer; 29 import sun.awt.SunToolkit; 30 31 /** 32 * The {@code Taskbar} class allows a Java application to interact with 33 * the system task area (taskbar, Dock, etc.). 34 * 35 * <p> 36 * There are a variety of interactions depending on the current platform such as 37 * displaying progress of some task, appending user-specified menu to the application 38 * icon context menu, etc. 39 * 40 * @implNote Linux support is currently limited to Unity. However to make these 41 * features work on Unity, the app should be run from a .desktop file with 42 * specified {@code java.desktop.appName} system property set to this .desktop 43 * file name: 44 * {@code Exec=java -Djava.desktop.appName=MyApp.desktop -jar /path/to/myapp.jar} 45 * see <a href="https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles"> 46 * https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles</a> 47 */ 48 49 public class Taskbar { 50 51 /** 52 * List of provided features. 53 */ 54 public static enum Feature { 55 56 /** 57 * @see #setIconBadge(java.lang.String) 58 */ 59 ICON_BADGE_TEXT, 60 61 /** 62 * @see #setIconBadge(java.lang.String) 63 */ 64 ICON_BADGE_NUMBER, 65 66 /** 67 * @see #setWindowIconBadge(java.awt.Window, java.awt.Image) 68 */ 69 ICON_BADGE_IMAGE_WINDOW, 70 71 /** 72 * @see #setIconImage(java.awt.Image) 73 */ 74 ICON_IMAGE, 75 76 /** 77 * @see #setMenu(java.awt.PopupMenu) 78 * @see #getMenu() 79 */ 80 MENU, 81 82 /** 83 * @see #setWindowProgressState(java.awt.Window, int) 84 */ 85 PROGRESS_STATE_WINDOW, 86 87 /** 88 * @see #setProgressValue(int) 89 */ 90 PROGRESS_VALUE, 91 92 /** 93 * @see #setWindowProgressValue(java.awt.Window, int) 94 */ 95 PROGRESS_VALUE_WINDOW, 96 97 /** 98 * @see #requestUserAttention(boolean, boolean) 99 */ 100 USER_ATTENTION, 101 102 /** 103 * @see #requestWindowUserAttention(java.awt.Window) 104 */ 105 USER_ATTENTION_WINDOW 106 } 107 108 /** 109 * Stops displaying the progress. 110 */ 111 public static final int STATE_OFF = 0x0; 112 113 /** 114 * The progress indicator displays with normal color and determinate mode. 115 */ 116 public static final int STATE_NORMAL = 0x1; 117 118 /** 119 * Shows progress as paused, progress can be resumed by the user. 120 * Switches to the determinate display. 121 */ 122 public static final int STATE_PAUSED = 0x2; 123 124 /** 125 * The progress indicator displays activity without specifying what 126 * proportion of the progress is complete. 127 */ 128 public static final int STATE_INDETERMINATE = 0x3; 129 130 /** 131 * Shows that an error has occurred. 132 * Switches to the determinate display. 133 */ 134 public static final int STATE_ERROR = 0x4; 135 136 private TaskbarPeer peer; 137 138 /** 139 * Tests whether a {@code Feature} is supported on the current platform. 140 * @param feature the specified {@link Feature} 141 * @return true if the specified feature is supported on the current platform 142 */ 143 public boolean isSupported(Feature feature) { 144 return peer.isSupported(feature); 145 } 146 147 /** 148 * Checks if the feature type is supported. 149 * 150 * @param featureType the action type in question 151 * @throws UnsupportedOperationException if the specified action type is not 152 * supported on the current platform 153 */ 154 private void checkFeatureSupport(Feature featureType){ 155 if (!isSupported(featureType)) { 156 throw new UnsupportedOperationException("The " + featureType.name() 157 + " feature is not supported on the current platform!"); 158 } 159 } 160 161 /** 162 * Calls to the security manager's <code>checkPermission</code> method with 163 * an <code>AWTPermission("showWindowWithoutWarningBanner")</code> 164 * permission. 165 */ 166 private void checkAWTPermission(){ 167 SecurityManager sm = System.getSecurityManager(); 168 if (sm != null) { 169 sm.checkPermission(new AWTPermission( 170 "showWindowWithoutWarningBanner")); 171 } 172 } 173 174 private Taskbar() { 175 Toolkit defaultToolkit = Toolkit.getDefaultToolkit(); 176 if (defaultToolkit instanceof SunToolkit) { 177 peer = ((SunToolkit) defaultToolkit).createTaskbarPeer(this); 178 } 179 } 180 181 /** 182 * Returns the <code>Taskbar</code> instance of the current 183 * taskbar context. On some platforms the Taskbar API may not be 184 * supported; use the {@link #isTaskbarSupported} method to 185 * determine if the current taskbar is supported. 186 * @return the Taskbar instance 187 * @throws HeadlessException if {@link 188 * GraphicsEnvironment#isHeadless()} returns {@code true} 189 * @throws UnsupportedOperationException if this class is not 190 * supported on the current platform 191 * @see #isTaskbarSupported() 192 * @see java.awt.GraphicsEnvironment#isHeadless 193 */ 194 public static synchronized Taskbar getTaskbar(){ 195 if (GraphicsEnvironment.isHeadless()) throw new HeadlessException(); 196 197 if (!Taskbar.isTaskbarSupported()) { 198 throw new UnsupportedOperationException("Taskbar API is not " + 199 "supported on the current platform"); 200 } 201 202 sun.awt.AppContext context = sun.awt.AppContext.getAppContext(); 203 Taskbar taskbar = (Taskbar)context.get(Taskbar.class); 204 205 if (taskbar == null) { 206 taskbar = new Taskbar(); 207 context.put(Taskbar.class, taskbar); 208 } 209 210 return taskbar; 211 } 212 213 /** 214 * Tests whether this class is supported on the current platform. 215 * If it's supported, use {@link #getTaskbar()} to retrieve an 216 * instance. 217 * 218 * @return <code>true</code> if this class is supported on the 219 * current platform; <code>false</code> otherwise 220 * @see #getTaskbar() 221 */ 222 public static boolean isTaskbarSupported(){ 223 Toolkit defaultToolkit = Toolkit.getDefaultToolkit(); 224 if (defaultToolkit instanceof SunToolkit) { 225 return ((SunToolkit)defaultToolkit).isTaskbarSupported(); 226 } 227 return false; 228 } 229 230 /** 231 * Requests user attention to this application. 232 * 233 * Depending on the platform, this may be visually indicated by a bouncing 234 * or flashing icon in the task area. It may have no effect on an already active 235 * application. 236 * 237 * On some platforms (e.g. Mac OS) this effect may disappear upon app activation 238 * and cannot be dismissed by setting {@code enabled} to false. 239 * Other platforms may require an additional call 240 * {@link #requestUserAttention} to dismiss this request 241 * with {@code enabled} parameter set to false. 242 * 243 * @param enabled disables this request if false 244 * @param critical if this is an important request 245 */ 246 public void requestUserAttention(final boolean enabled, final boolean critical) { 247 checkAWTPermission(); 248 checkFeatureSupport(Feature.USER_ATTENTION); 249 peer.requestUserAttention(enabled, critical); 250 } 251 252 /** 253 * Requests user attention to the specified window until it is activated. 254 * 255 * On an already active window requesting attention does nothing. 256 * 257 * @param w window 258 */ 259 public void requestWindowUserAttention(Window w) { 260 checkAWTPermission(); 261 checkFeatureSupport(Feature.USER_ATTENTION_WINDOW); 262 peer.requestWindowUserAttention(w); 263 } 264 265 /** 266 * Attaches the contents of the provided PopupMenu to the application icon 267 * in the task area. 268 * 269 * @param menu the PopupMenu to attach to this application 270 */ 271 public void setMenu(final PopupMenu menu) { 272 checkAWTPermission(); 273 checkFeatureSupport(Feature.MENU); 274 peer.setMenu(menu); 275 } 276 277 /** 278 * Gets PopupMenu used to add items to this application's icon in system task area. 279 * 280 * @return the PopupMenu 281 */ 282 public PopupMenu getMenu() { 283 checkAWTPermission(); 284 checkFeatureSupport(Feature.MENU); 285 return peer.getMenu(); 286 } 287 288 /** 289 * Changes this application's icon to the provided image. 290 * 291 * @param image to change 292 */ 293 public void setIconImage(final Image image) { 294 checkAWTPermission(); 295 checkFeatureSupport(Feature.ICON_IMAGE); 296 peer.setIconImage(image); 297 } 298 299 /** 300 * Obtains an image of this application's icon. 301 * 302 * @return an image of this application's icon 303 */ 304 public Image getIconImage() { 305 checkAWTPermission(); 306 checkFeatureSupport(Feature.ICON_IMAGE); 307 return peer.getIconImage(); 308 } 309 310 /** 311 * Affixes a small system-provided badge to this application's icon. 312 * Usually a number. 313 * 314 * Some platforms do not support string values and accept only integer 315 * values. In this case, pass an integer represented as a string as parameter. 316 * This can be tested by {@code Feature.ICON_BADGE_STRING} and 317 * {@code Feature.ICON_BADGE_NUMBER}. 318 * 319 * Passing {@code null} as parameter hides the badge. 320 * @param badge label to affix to the icon 321 */ 322 public void setIconBadge(final String badge) { 323 checkAWTPermission(); 324 checkFeatureSupport(Feature.ICON_BADGE_NUMBER); 325 peer.setIconBadge(badge); 326 } 327 328 /** 329 * Affixes a small badge to this application's icon in the task area 330 * for the specified window. 331 * It may be disabled by system settings. 332 * 333 * @param w window to update 334 * @param badge image to affix to the icon 335 */ 336 public void setWindowIconBadge(Window w, final Image badge) { 337 checkAWTPermission(); 338 checkFeatureSupport(Feature.ICON_BADGE_IMAGE_WINDOW); 339 if (w != null) { 340 peer.setWindowIconBadge(w, badge); 341 } 342 } 343 344 345 /** 346 * Affixes a small system-provided progress bar to this application's icon. 347 * 348 * @param value from 0 to 100, other to disable progress indication 349 */ 350 public void setProgressValue(int value) { 351 checkAWTPermission(); 352 checkFeatureSupport(Feature.PROGRESS_VALUE); 353 peer.setProgressValue(value); 354 } 355 356 /** 357 * Displays progress for specified window. 358 * 359 * @param w window to update 360 * @param value from 0 to 100, other to disable progress indication 361 */ 362 public void setWindowProgressValue(Window w, int value) { 363 checkAWTPermission(); 364 checkFeatureSupport(Feature.PROGRESS_VALUE_WINDOW); 365 if (w != null) { 366 peer.setWindowProgressValue(w, value); 367 } 368 } 369 370 /** 371 * Sets a progress state for a specified window. 372 * 373 * @param w window 374 * @param state to change to 375 * @see #STATE_OFF 376 * @see #STATE_NORMAL 377 * @see #STATE_PAUSED 378 * @see #STATE_INDETERMINATE 379 * @see #STATE_ERROR 380 */ 381 public void setWindowProgressState(Window w, int state) { 382 checkAWTPermission(); 383 checkFeatureSupport(Feature.PROGRESS_STATE_WINDOW); 384 if (state < STATE_OFF && state > STATE_ERROR) { 385 throw new IllegalArgumentException("Invalid state value"); 386 } 387 if (w != null) { 388 peer.setWindowProgressState(w, state); 389 } 390 } 391 392 private native void initIDs(); 393 }