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