1 /*
   2  * Copyright (c) 2011, 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 com.apple.eawt;
  27 
  28 import java.awt.*;
  29 import java.awt.peer.*;
  30 import java.beans.Beans;
  31 import java.security.PrivilegedAction;
  32 
  33 import javax.swing.JMenuBar;
  34 
  35 import sun.lwawt.*;
  36 import sun.lwawt.macosx.*;
  37 
  38 /**
  39  * The <code>Application</code> class allows you to integrate your Java application with the native Mac OS X environment.
  40  * You can provide your Mac OS X users a greatly enhanced experience by implementing a few basic handlers for standard system events.
  41  *
  42  * For example:
  43  * <ul>
  44  * <li>Open an about dialog when a user chooses About from the application menu.</li>
  45  * <li>Open a preferences window when the users chooses Preferences from the application menu.</li>
  46  * <li>Create a new document when the user clicks on your Dock icon, and no windows are open.</li>
  47  * <li>Open a document that the user double-clicked on in the Finder.</li>
  48  * <li>Open a custom URL scheme when a user clicks on link in a web browser.</li>
  49  * <li>Reconnect to network services after the system has awoke from sleep.</li>
  50  * <li>Cleanly shutdown your application when the user chooses Quit from the application menu, Dock icon, or types Command-Q.</li>
  51  * <li>Cancel shutdown/logout if the user has unsaved changes in your application.</li>
  52  * </ul>
  53  *
  54  * @since 1.4
  55  */
  56 public class Application {
  57     private static native void nativeInitializeApplicationDelegate();
  58 
  59     static Application sApplication = null;
  60 
  61     static {
  62         java.security.AccessController.doPrivileged((PrivilegedAction<?>)new sun.security.action.LoadLibraryAction("awt"));
  63 
  64         checkSecurity();
  65         if (!Beans.isDesignTime()) {
  66             nativeInitializeApplicationDelegate();
  67         }
  68 
  69         sApplication = new Application();
  70     }
  71 
  72     private static void checkSecurity() {
  73         final SecurityManager security = System.getSecurityManager();
  74         if (security == null) return;
  75         security.checkPermission(new RuntimePermission("canProcessApplicationEvents"));
  76     }
  77 
  78     /**
  79      * @return the singleton representing this Mac OS X Application
  80      *
  81      * @since 1.4
  82      */
  83     public static Application getApplication() {
  84         checkSecurity();
  85         return sApplication;
  86     }
  87 
  88     // some singletons, since they get called back into from native
  89     final _AppEventHandler eventHandler = _AppEventHandler.getInstance();
  90     final _AppMenuBarHandler menuBarHandler = _AppMenuBarHandler.getInstance();
  91     final _AppDockIconHandler iconHandler = new _AppDockIconHandler();
  92 
  93     /**
  94      * Creates an Application instance. Should only be used in JavaBean environments.
  95      * @deprecated use {@link #getApplication()}
  96      *
  97      * @since 1.4
  98      */
  99     @Deprecated
 100     public Application() {
 101         checkSecurity();
 102     }
 103 
 104     /**
 105      * Adds sub-types of {@link AppEventListener} to listen for notifications from the native Mac OS X system.
 106      *
 107      * @see AppForegroundListener
 108      * @see AppHiddenListener
 109      * @see AppReOpenedListener
 110      * @see ScreenSleepListener
 111      * @see SystemSleepListener
 112      * @see UserSessionListener
 113      *
 114      * @param listener
 115      * @since Java for Mac OS X 10.6 Update 3
 116      * @since Java for Mac OS X 10.5 Update 8
 117      */
 118     public void addAppEventListener(final AppEventListener listener) {
 119         eventHandler.addListener(listener);
 120     }
 121 
 122     /**
 123      * Removes sub-types of {@link AppEventListener} from listening for notifications from the native Mac OS X system.
 124      *
 125      * @see AppForegroundListener
 126      * @see AppHiddenListener
 127      * @see AppReOpenedListener
 128      * @see ScreenSleepListener
 129      * @see SystemSleepListener
 130      * @see UserSessionListener
 131      *
 132      * @param listener
 133      * @since Java for Mac OS X 10.6 Update 3
 134      * @since Java for Mac OS X 10.5 Update 8
 135      */
 136     public void removeAppEventListener(final AppEventListener listener) {
 137         eventHandler.removeListener(listener);
 138     }
 139 
 140     /**
 141      * Installs a handler to show a custom About window for your application.
 142      *
 143      * Setting the {@link AboutHandler} to <code>null</code> reverts it to the default Cocoa About window.
 144      *
 145      * @param aboutHandler the handler to respond to the {@link AboutHandler#handleAbout()} message
 146      * @since Java for Mac OS X 10.6 Update 3
 147      * @since Java for Mac OS X 10.5 Update 8
 148      */
 149     public void setAboutHandler(final AboutHandler aboutHandler) {
 150         eventHandler.aboutDispatcher.setHandler(aboutHandler);
 151     }
 152 
 153     /**
 154      * Installs a handler to create the Preferences menu item in your application's app menu.
 155      *
 156      * Setting the {@link PreferencesHandler} to <code>null</code> will remove the Preferences item from the app menu.
 157      *
 158      * @param preferencesHandler
 159      * @since Java for Mac OS X 10.6 Update 3
 160      * @since Java for Mac OS X 10.5 Update 8
 161      */
 162     public void setPreferencesHandler(final PreferencesHandler preferencesHandler) {
 163         eventHandler.preferencesDispatcher.setHandler(preferencesHandler);
 164     }
 165 
 166     /**
 167      * Installs the handler which is notified when the application is asked to open a list of files.
 168      * The {@link OpenFilesHandler#openFiles(AppEvent.OpenFilesEvent)} notifications are only sent if the Java app is a bundled application, with a <code>CFBundleDocumentTypes</code> array present in it's Info.plist.
 169      * See the <a href="http://developer.apple.com/mac/library/documentation/General/Reference/InfoPlistKeyReference">Info.plist Key Reference</a> for more information about adding a <code>CFBundleDocumentTypes</code> key to your app's Info.plist.
 170      *
 171      * @param openFileHandler
 172      * @since Java for Mac OS X 10.6 Update 3
 173      * @since Java for Mac OS X 10.5 Update 8
 174      */
 175     public void setOpenFileHandler(final OpenFilesHandler openFileHandler) {
 176         eventHandler.openFilesDispatcher.setHandler(openFileHandler);
 177     }
 178 
 179     /**
 180      * Installs the handler which is notified when the application is asked to print a list of files.
 181      * The {@link PrintFilesHandler#printFiles(AppEvent.PrintFilesEvent)} notifications are only sent if the Java app is a bundled application, with a <code>CFBundleDocumentTypes</code> array present in it's Info.plist.
 182      * See the <a href="http://developer.apple.com/mac/library/documentation/General/Reference/InfoPlistKeyReference">Info.plist Key Reference</a> for more information about adding a <code>CFBundleDocumentTypes</code> key to your app's Info.plist.
 183      *
 184      * @param printFileHandler
 185      * @since Java for Mac OS X 10.6 Update 3
 186      * @since Java for Mac OS X 10.5 Update 8
 187      */
 188     public void setPrintFileHandler(final PrintFilesHandler printFileHandler) {
 189         eventHandler.printFilesDispatcher.setHandler(printFileHandler);
 190     }
 191 
 192     /**
 193      * Installs the handler which is notified when the application is asked to open a URL.
 194      * The {@link OpenURIHandler#openURI(AppEvent.OpenURIEvent)} notifications are only sent if the Java app is a bundled application, with a <code>CFBundleURLTypes</code> array present in it's Info.plist.
 195      * See the <a href="http://developer.apple.com/mac/library/documentation/General/Reference/InfoPlistKeyReference">Info.plist Key Reference</a> for more information about adding a <code>CFBundleURLTypes</code> key to your app's Info.plist.
 196      *
 197      * Setting the handler to <code>null</code> causes all {@link OpenURIHandler#openURI(AppEvent.OpenURIEvent)} requests to be enqueued until another handler is set.
 198      *
 199      * @param openURIHandler
 200      * @since Java for Mac OS X 10.6 Update 3
 201      * @since Java for Mac OS X 10.5 Update 8
 202      */
 203     public void setOpenURIHandler(final OpenURIHandler openURIHandler) {
 204         eventHandler.openURIDispatcher.setHandler(openURIHandler);
 205     }
 206 
 207     /**
 208      * Installs the handler which determines if the application should quit.
 209      * The handler is passed a one-shot {@link QuitResponse} which can cancel or proceed with the quit.
 210      * Setting the handler to <code>null</code> causes all quit requests to directly perform the default {@link QuitStrategy}.
 211      *
 212      * @param quitHandler the handler that is called when the application is asked to quit
 213      * @since Java for Mac OS X 10.6 Update 3
 214      * @since Java for Mac OS X 10.5 Update 8
 215      */
 216     public void setQuitHandler(final QuitHandler quitHandler) {
 217         eventHandler.quitDispatcher.setHandler(quitHandler);
 218     }
 219 
 220     /**
 221      * Sets the default strategy used to quit this application. The default is calling SYSTEM_EXIT_0.
 222      *
 223      * The quit strategy can also be set with the "apple.eawt.quitStrategy" system property.
 224      *
 225      * @param strategy the way this application should be shutdown
 226      * @since Java for Mac OS X 10.6 Update 3
 227      * @since Java for Mac OS X 10.5 Update 8
 228      */
 229     public void setQuitStrategy(final QuitStrategy strategy) {
 230         eventHandler.setDefaultQuitStrategy(strategy);
 231     }
 232 
 233     /**
 234      * Enables this application to be suddenly terminated.
 235      *
 236      * Call this method to indicate your application's state is saved, and requires no notification to be terminated.
 237      * Letting your application remain terminatable improves the user experience by avoiding re-paging in your application when it's asked to quit.
 238      *
 239      * <b>Note: enabling sudden termination will allow your application to be quit without notifying your QuitHandler, or running any shutdown hooks.</b>
 240      * User initiated Cmd-Q, logout, restart, or shutdown requests will effectively "kill -KILL" your application.
 241      *
 242      * This call has no effect on Mac OS X versions prior to 10.6.
 243      *
 244      * @see <a href="http://developer.apple.com/mac/library/documentation/cocoa/reference/foundation/Classes/NSProcessInfo_Class">NSProcessInfo class references</a> for more information about Sudden Termination.
 245      * @see Application#disableSuddenTermination()
 246      *
 247      * @since Java for Mac OS X 10.6 Update 3
 248      * @since Java for Mac OS X 10.5 Update 8
 249      */
 250     public void enableSuddenTermination() {
 251         _AppMiscHandlers.enableSuddenTermination();
 252     }
 253 
 254     /**
 255      * Prevents this application from being suddenly terminated.
 256      *
 257      * Call this method to indicate that your application has unsaved state, and may not be terminated without notification.
 258      *
 259      * This call has no effect on Mac OS X versions prior to 10.6.
 260      *
 261      * @see <a href="http://developer.apple.com/mac/library/documentation/cocoa/reference/foundation/Classes/NSProcessInfo_Class">NSProcessInfo class references</a> for more information about Sudden Termination.
 262      * @see Application#enableSuddenTermination()
 263      *
 264      * @since Java for Mac OS X 10.6 Update 3
 265      * @since Java for Mac OS X 10.5 Update 8
 266      */
 267     public void disableSuddenTermination() {
 268         _AppMiscHandlers.disableSuddenTermination();
 269     }
 270 
 271     /**
 272      * Requests this application to move to the foreground.
 273      *
 274      * @param allWindows if all windows of this application should be moved to the foreground, or only the foremost one
 275      *
 276      * @since Java for Mac OS X 10.6 Update 1
 277      * @since Java for Mac OS X 10.5 Update 6 - 1.6, 1.5
 278      */
 279     public void requestForeground(final boolean allWindows) {
 280         _AppMiscHandlers.requestActivation(allWindows);
 281     }
 282 
 283     /**
 284      * Requests user attention to this application (usually through bouncing the Dock icon). Critical
 285      * requests will continue to bounce the Dock icon until the app is activated. An already active
 286      * application requesting attention does nothing.
 287      *
 288      * @param critical if this is an important request
 289      *
 290      * @since Java for Mac OS X 10.6 Update 1
 291      * @since Java for Mac OS X 10.5 Update 6 - 1.6, 1.5
 292      */
 293     public void requestUserAttention(final boolean critical) {
 294         _AppMiscHandlers.requestUserAttention(critical);
 295     }
 296 
 297     /**
 298      * Opens the native help viewer application if a Help Book has been added to the
 299      * application bundler and registered in the Info.plist with CFBundleHelpBookFolder.
 300      *
 301      * See http://developer.apple.com/qa/qa2001/qa1022.html for more information.
 302      *
 303      * @since Java for Mac OS X 10.5 - 1.5
 304      * @since Java for Mac OS X 10.5 Update 1 - 1.6
 305      */
 306     public void openHelpViewer() {
 307         _AppMiscHandlers.openHelpViewer();
 308     }
 309 
 310     /**
 311      * Attaches the contents of the provided PopupMenu to the application's Dock icon.
 312      *
 313      * @param menu the PopupMenu to attach to this application's Dock icon
 314      *
 315      * @since Java for Mac OS X 10.5 - 1.5
 316      * @since Java for Mac OS X 10.5 Update 1 - 1.6
 317      */
 318     public void setDockMenu(final PopupMenu menu) {
 319         iconHandler.setDockMenu(menu);
 320     }
 321 
 322     /**
 323      * @return the PopupMenu used to add items to this application's Dock icon
 324      *
 325      * @since Java for Mac OS X 10.5 - 1.5
 326      * @since Java for Mac OS X 10.5 Update 1 - 1.6
 327      */
 328     public PopupMenu getDockMenu() {
 329         return iconHandler.getDockMenu();
 330     }
 331 
 332     /**
 333      * Changes this application's Dock icon to the provided image.
 334      *
 335      * @param image
 336      *
 337      * @since Java for Mac OS X 10.5 - 1.5
 338      * @since Java for Mac OS X 10.5 Update 1 - 1.6
 339      */
 340     public void setDockIconImage(final Image image) {
 341         iconHandler.setDockIconImage(image);
 342     }
 343 
 344     /**
 345      * Obtains an image of this application's Dock icon.
 346      *
 347      * @return an image of this application's Dock icon
 348      *
 349      * @since Java for Mac OS X 10.5 - 1.5
 350      * @since Java for Mac OS X 10.5 Update 1 - 1.6
 351      */
 352     public Image getDockIconImage() {
 353         return iconHandler.getDockIconImage();
 354     }
 355 
 356     /**
 357      * Affixes a small system provided badge to this application's Dock icon. Usually a number.
 358      *
 359      * @param badge textual label to affix to the Dock icon
 360      *
 361      * @since Java for Mac OS X 10.5 - 1.5
 362      * @since Java for Mac OS X 10.5 Update 1 - 1.6
 363      */
 364     public void setDockIconBadge(final String badge) {
 365         iconHandler.setDockIconBadge(badge);
 366     }
 367 
 368     /**
 369      * Sets the default menu bar to use when there are no active frames.
 370      * Only used when the system property "apple.laf.useScreenMenuBar" is "true", and
 371      * the Aqua Look and Feel is active.
 372      *
 373      * @param menuBar to use when no other frames are active
 374      *
 375      * @since Java for Mac OS X 10.6 Update 1
 376      * @since Java for Mac OS X 10.5 Update 6 - 1.6, 1.5
 377      */
 378     public void setDefaultMenuBar(final JMenuBar menuBar) {
 379         menuBarHandler.setDefaultMenuBar(menuBar);
 380     }
 381 
 382     /**
 383      * Requests that a {@link Window} should animate into or out of full screen mode.
 384      * Only {@link Window}s marked as full screenable by {@link FullScreenUtilities#setWindowCanFullScreen(Window, boolean)} can be toggled.
 385      *
 386      * @param window to animate into or out of full screen mode
 387      *
 388      * @since Java for Mac OS X 10.7 Update 1
 389      */
 390     @SuppressWarnings("deprecation")
 391     public void requestToggleFullScreen(final Window window) {
 392         final ComponentPeer peer = window.getPeer();
 393 
 394         if (!(peer instanceof LWWindowPeer)) return;
 395         Object platformWindow = ((LWWindowPeer) peer).getPlatformWindow();
 396         if (!(platformWindow instanceof CPlatformWindow)) return;
 397         ((CPlatformWindow)platformWindow).toggleFullScreen();
 398     }
 399 
 400 
 401     // -- DEPRECATED API --
 402 
 403     /**
 404      * Adds the specified ApplicationListener as a receiver of callbacks from this class.
 405      * This method throws a RuntimeException if the newer About, Preferences, Quit, etc handlers are installed.
 406      *
 407      * @param listener an implementation of ApplicationListener that handles ApplicationEvents
 408      *
 409      * @deprecated register individual handlers for each task (About, Preferences, Open, Print, Quit, etc)
 410      * @since 1.4
 411      */
 412     @SuppressWarnings("deprecation")
 413     @Deprecated
 414     public void addApplicationListener(final ApplicationListener listener) {
 415         eventHandler.legacyHandler.addLegacyAppListener(listener);
 416     }
 417 
 418     /**
 419      * Removes the specified ApplicationListener from being a receiver of callbacks from this class.
 420      * This method throws a RuntimeException if the newer About, Preferences, Quit, etc handlers are installed.
 421      *
 422      * @param listener an implementation of ApplicationListener that had previously been registered to handle ApplicationEvents
 423      *
 424      * @deprecated unregister individual handlers for each task (About, Preferences, Open, Print, Quit, etc)
 425      * @since 1.4
 426      */
 427     @SuppressWarnings("deprecation")
 428     @Deprecated
 429     public void removeApplicationListener(final ApplicationListener listener) {
 430         eventHandler.legacyHandler.removeLegacyAppListener(listener);
 431     }
 432 
 433     /**
 434      * Enables the Preferences item in the application menu. The ApplicationListener receives a callback for
 435      * selection of the Preferences item in the application menu only if this is set to <code>true</code>.
 436      *
 437      * If a Preferences item isn't present, this method adds and enables it.
 438      *
 439      * @param enable specifies whether the Preferences item in the application menu should be enabled (<code>true</code>) or not (<code>false</code>)
 440      *
 441      * @deprecated no replacement
 442      * @since 1.4
 443      */
 444     @Deprecated
 445     public void setEnabledPreferencesMenu(final boolean enable) {
 446         menuBarHandler.setPreferencesMenuItemVisible(true);
 447         menuBarHandler.setPreferencesMenuItemEnabled(enable);
 448     }
 449 
 450     /**
 451      * Enables the About item in the application menu. The ApplicationListener receives a callback for
 452      * selection of the About item in the application menu only if this is set to <code>true</code>. Because AWT supplies
 453      * a standard About window when an application may not, by default this is set to <code>true</code>.
 454      *
 455      * If the About item isn't present, this method adds and enables it.
 456      *
 457      * @param enable specifies whether the About item in the application menu should be enabled (<code>true</code>) or not (<code>false</code>)
 458      *
 459      * @deprecated no replacement
 460      * @since 1.4
 461      */
 462     @Deprecated
 463     public void setEnabledAboutMenu(final boolean enable) {
 464         menuBarHandler.setAboutMenuItemEnabled(enable);
 465     }
 466 
 467     /**
 468      * Determines if the Preferences item of the application menu is enabled.
 469      *
 470      * @deprecated no replacement
 471      * @since 1.4
 472      */
 473     @Deprecated
 474     public boolean getEnabledPreferencesMenu() {
 475         return menuBarHandler.isPreferencesMenuItemEnabled();
 476     }
 477 
 478     /**
 479      * Determines if the About item of the application menu is enabled.
 480      *
 481      * @deprecated no replacement
 482      * @since 1.4
 483      */
 484     @Deprecated
 485     public boolean getEnabledAboutMenu() {
 486         return menuBarHandler.isAboutMenuItemEnabled();
 487     }
 488 
 489     /**
 490      * Determines if the About item of the application menu is present.
 491      *
 492      * @deprecated no replacement
 493      * @since 1.4
 494      */
 495     @Deprecated
 496     public boolean isAboutMenuItemPresent() {
 497         return menuBarHandler.isAboutMenuItemVisible();
 498     }
 499 
 500     /**
 501      * Adds the About item to the application menu if the item is not already present.
 502      *
 503      * @deprecated use {@link #setAboutHandler(AboutHandler)} with a non-null {@link AboutHandler} parameter
 504      * @since 1.4
 505      */
 506     @Deprecated
 507     public void addAboutMenuItem() {
 508         menuBarHandler.setAboutMenuItemVisible(true);
 509     }
 510 
 511     /**
 512      * Removes the About item from the application menu if  the item is present.
 513      *
 514      * @deprecated use {@link #setAboutHandler(AboutHandler)} with a null parameter
 515      * @since 1.4
 516      */
 517     @Deprecated
 518     public void removeAboutMenuItem() {
 519         menuBarHandler.setAboutMenuItemVisible(false);
 520     }
 521 
 522     /**
 523      * Determines if the About Preferences of the application menu is present. By default there is no Preferences menu item.
 524      *
 525      * @deprecated no replacement
 526      * @since 1.4
 527      */
 528     @Deprecated
 529     public boolean isPreferencesMenuItemPresent() {
 530         return menuBarHandler.isPreferencesMenuItemVisible();
 531     }
 532 
 533     /**
 534      * Adds the Preferences item to the application menu if the item is not already present.
 535      *
 536      * @deprecated use {@link #setPreferencesHandler(PreferencesHandler)} with a non-null {@link PreferencesHandler} parameter
 537      * @since 1.4
 538      */
 539     @Deprecated
 540     public void addPreferencesMenuItem() {
 541         menuBarHandler.setPreferencesMenuItemVisible(true);
 542     }
 543 
 544     /**
 545      * Removes the Preferences item from the application menu if that item is present.
 546      *
 547      * @deprecated use {@link #setPreferencesHandler(PreferencesHandler)} with a null parameter
 548      * @since 1.4
 549      */
 550     @Deprecated
 551     public void removePreferencesMenuItem() {
 552         menuBarHandler.setPreferencesMenuItemVisible(false);
 553     }
 554 
 555     /**
 556      * @deprecated Use <code>java.awt.MouseInfo.getPointerInfo().getLocation()</code>.
 557      *
 558      * @since 1.4
 559      */
 560     @Deprecated
 561     public static Point getMouseLocationOnScreen() {
 562         return java.awt.MouseInfo.getPointerInfo().getLocation();
 563     }
 564 }