1 /*
2  * Copyright (c) 2011, 2017, 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.Image;
29 import java.awt.PopupMenu;
30 import java.awt.Toolkit;
31 import java.awt.Window;
32 import java.awt.desktop.AboutHandler;
33 import java.awt.desktop.AppForegroundListener;
34 import java.awt.desktop.AppHiddenListener;
35 import java.awt.desktop.AppReopenedListener;
36 import java.awt.desktop.OpenFilesEvent;
37 import java.awt.desktop.OpenFilesHandler;
38 import java.awt.desktop.OpenURIEvent;
39 import java.awt.desktop.OpenURIHandler;
40 import java.awt.desktop.PreferencesHandler;
41 import java.awt.desktop.PrintFilesEvent;
42 import java.awt.desktop.PrintFilesHandler;
43 import java.awt.desktop.QuitHandler;
44 import java.awt.desktop.QuitResponse;
45 import java.awt.desktop.QuitStrategy;
46 import java.awt.desktop.ScreenSleepListener;
47 import java.awt.desktop.SystemEventListener;
48 import java.awt.desktop.SystemSleepListener;
49 import java.awt.desktop.UserSessionListener;
50 import java.beans.Beans;
51 
52 import javax.swing.JMenuBar;
53 
54 import sun.awt.AWTAccessor;
55 import sun.lwawt.LWWindowPeer;
56 import sun.lwawt.macosx.CPlatformWindow;
57 
58 /**
59  * The {@code Application} class allows you to integrate your Java application with the native Mac OS X environment.
60  * You can provide your Mac OS X users a greatly enhanced experience by implementing a few basic handlers for standard system events.
61  *
62  * For example:
63  * <ul>
64  * <li>Open an about dialog when a user chooses About from the application menu.</li>
65  * <li>Open a preferences window when the users chooses Preferences from the application menu.</li>
66  * <li>Create a new document when the user clicks on your Dock icon, and no windows are open.</li>
67  * <li>Open a document that the user double-clicked on in the Finder.</li>
68  * <li>Open a custom URL scheme when a user clicks on link in a web browser.</li>
69  * <li>Reconnect to network services after the system has awoke from sleep.</li>
70  * <li>Cleanly shutdown your application when the user chooses Quit from the application menu, Dock icon, or types Command-Q.</li>
71  * <li>Cancel shutdown/logout if the user has unsaved changes in your application.</li>
72  * </ul>
73  *
74  * @since 1.4
75  */
76 public class Application {
nativeInitializeApplicationDelegate()77     private static native void nativeInitializeApplicationDelegate();
78 
79     static Application sApplication = null;
80 
81     static {
checkSecurity()82         checkSecurity();
Toolkit.getDefaultToolkit()83         Toolkit.getDefaultToolkit(); // Start AppKit
84         if (!Beans.isDesignTime()) {
nativeInitializeApplicationDelegate()85             nativeInitializeApplicationDelegate();
86         }
87 
88         sApplication = new Application();
89     }
90 
checkSecurity()91     private static void checkSecurity() {
92         final SecurityManager security = System.getSecurityManager();
93         if (security == null) return;
94         security.checkPermission(new RuntimePermission("canProcessApplicationEvents"));
95     }
96 
97     /**
98      * @return the singleton representing this Mac OS X Application
99      *
100      * @since 1.4
101      */
getApplication()102     public static Application getApplication() {
103         checkSecurity();
104         return sApplication;
105     }
106 
107     // some singletons, since they get called back into from native
108     final _AppEventHandler eventHandler = _AppEventHandler.getInstance();
109     final _AppMenuBarHandler menuBarHandler = _AppMenuBarHandler.getInstance();
110     final _AppDockIconHandler iconHandler = new _AppDockIconHandler();
111 
112     /**
113      * Creates an Application instance. Should only be used in JavaBean environments.
114      * @deprecated use {@link #getApplication()}
115      *
116      * @since 1.4
117      */
118     @Deprecated
Application()119     public Application() {
120         checkSecurity();
121     }
122 
123     /**
124      * Adds sub-types of {@link SystemEventListener} to listen for notifications from the native Mac OS X system.
125      *
126      * @see AppForegroundListener
127      * @see AppHiddenListener
128      * @see AppReopenedListener
129      * @see ScreenSleepListener
130      * @see SystemSleepListener
131      * @see UserSessionListener
132      *
133      * @param listener
134      * @since Java for Mac OS X 10.6 Update 3
135      * @since Java for Mac OS X 10.5 Update 8
136      */
addAppEventListener(final SystemEventListener listener)137     public void addAppEventListener(final SystemEventListener listener) {
138         eventHandler.addListener(listener);
139     }
140 
141     /**
142      * Removes sub-types of {@link SystemEventListener} from listening for notifications from the native Mac OS X system.
143      *
144      * @see AppForegroundListener
145      * @see AppHiddenListener
146      * @see AppReopenedListener
147      * @see ScreenSleepListener
148      * @see SystemSleepListener
149      * @see UserSessionListener
150      *
151      * @param listener
152      * @since Java for Mac OS X 10.6 Update 3
153      * @since Java for Mac OS X 10.5 Update 8
154      */
removeAppEventListener(final SystemEventListener listener)155     public void removeAppEventListener(final SystemEventListener listener) {
156         eventHandler.removeListener(listener);
157     }
158 
159     /**
160      * Installs a handler to show a custom About window for your application.
161      *
162      * Setting the {@link AboutHandler} to {@code null} reverts it to the default Cocoa About window.
163      *
164      * @param aboutHandler the handler to respond to the {@link AboutHandler#handleAbout} message
165      * @since Java for Mac OS X 10.6 Update 3
166      * @since Java for Mac OS X 10.5 Update 8
167      */
setAboutHandler(final AboutHandler aboutHandler)168     public void setAboutHandler(final AboutHandler aboutHandler) {
169         eventHandler.aboutDispatcher.setHandler(aboutHandler);
170     }
171 
172     /**
173      * Installs a handler to create the Preferences menu item in your application's app menu.
174      *
175      * Setting the {@link PreferencesHandler} to {@code null} will remove the Preferences item from the app menu.
176      *
177      * @param preferencesHandler
178      * @since Java for Mac OS X 10.6 Update 3
179      * @since Java for Mac OS X 10.5 Update 8
180      */
setPreferencesHandler(final PreferencesHandler preferencesHandler)181     public void setPreferencesHandler(final PreferencesHandler preferencesHandler) {
182         eventHandler.preferencesDispatcher.setHandler(preferencesHandler);
183     }
184 
185     /**
186      * Installs the handler which is notified when the application is asked to open a list of files.
187      * The {@link OpenFilesHandler#openFiles(OpenFilesEvent)} notifications are only sent if the Java app is a bundled application, with a {@code CFBundleDocumentTypes} array present in it's Info.plist.
188      * 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} key to your app's Info.plist.
189      *
190      * @param openFileHandler
191      * @since Java for Mac OS X 10.6 Update 3
192      * @since Java for Mac OS X 10.5 Update 8
193      */
setOpenFileHandler(final OpenFilesHandler openFileHandler)194     public void setOpenFileHandler(final OpenFilesHandler openFileHandler) {
195         eventHandler.openFilesDispatcher.setHandler(openFileHandler);
196     }
197 
198     /**
199      * Installs the handler which is notified when the application is asked to print a list of files.
200      * The {@link PrintFilesHandler#printFiles(PrintFilesEvent)} notifications are only sent if the Java app is a bundled application, with a {@code CFBundleDocumentTypes} array present in it's Info.plist.
201      * 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} key to your app's Info.plist.
202      *
203      * @param printFileHandler
204      * @since Java for Mac OS X 10.6 Update 3
205      * @since Java for Mac OS X 10.5 Update 8
206      */
setPrintFileHandler(final PrintFilesHandler printFileHandler)207     public void setPrintFileHandler(final PrintFilesHandler printFileHandler) {
208         eventHandler.printFilesDispatcher.setHandler(printFileHandler);
209     }
210 
211     /**
212      * Installs the handler which is notified when the application is asked to open a URL.
213      * The {@link OpenURIHandler#openURI(OpenURIEvent)} notifications are only sent if the Java app is a bundled application, with a {@code CFBundleURLTypes} array present in it's Info.plist.
214      * 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} key to your app's Info.plist.
215      *
216      * Setting the handler to {@code null} causes all {@link OpenURIHandler#openURI(OpenURIEvent)} requests to be enqueued until another handler is set.
217      *
218      * @param openURIHandler
219      * @since Java for Mac OS X 10.6 Update 3
220      * @since Java for Mac OS X 10.5 Update 8
221      */
setOpenURIHandler(final OpenURIHandler openURIHandler)222     public void setOpenURIHandler(final OpenURIHandler openURIHandler) {
223         eventHandler.openURIDispatcher.setHandler(openURIHandler);
224     }
225 
226     /**
227      * Installs the handler which determines if the application should quit.
228      * The handler is passed a one-shot {@link QuitResponse} which can cancel or proceed with the quit.
229      * Setting the handler to {@code null} causes all quit requests to directly perform the default {@link QuitStrategy}.
230      *
231      * @param quitHandler the handler that is called when the application is asked to quit
232      * @since Java for Mac OS X 10.6 Update 3
233      * @since Java for Mac OS X 10.5 Update 8
234      */
setQuitHandler(final QuitHandler quitHandler)235     public void setQuitHandler(final QuitHandler quitHandler) {
236         eventHandler.quitDispatcher.setHandler(quitHandler);
237     }
238 
239     /**
240      * Sets the default strategy used to quit this application. The default is calling SYSTEM_EXIT_0.
241      *
242      * The quit strategy can also be set with the "apple.eawt.quitStrategy" system property.
243      *
244      * @param strategy the way this application should be shutdown
245      * @since Java for Mac OS X 10.6 Update 3
246      * @since Java for Mac OS X 10.5 Update 8
247      */
setQuitStrategy(final QuitStrategy strategy)248     public void setQuitStrategy(final QuitStrategy strategy) {
249         eventHandler.setDefaultQuitStrategy(strategy);
250     }
251 
252     /**
253      * Enables this application to be suddenly terminated.
254      *
255      * Call this method to indicate your application's state is saved, and requires no notification to be terminated.
256      * Letting your application remain terminatable improves the user experience by avoiding re-paging in your application when it's asked to quit.
257      *
258      * <b>Note: enabling sudden termination will allow your application to be quit without notifying your QuitHandler, or running any shutdown hooks.</b>
259      * User initiated Cmd-Q, logout, restart, or shutdown requests will effectively "kill -KILL" your application.
260      *
261      * This call has no effect on Mac OS X versions prior to 10.6.
262      *
263      * @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.
264      * @see Application#disableSuddenTermination()
265      *
266      * @since Java for Mac OS X 10.6 Update 3
267      * @since Java for Mac OS X 10.5 Update 8
268      */
enableSuddenTermination()269     public void enableSuddenTermination() {
270         _AppMiscHandlers.enableSuddenTermination();
271     }
272 
273     /**
274      * Prevents this application from being suddenly terminated.
275      *
276      * Call this method to indicate that your application has unsaved state, and may not be terminated without notification.
277      *
278      * This call has no effect on Mac OS X versions prior to 10.6.
279      *
280      * @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.
281      * @see Application#enableSuddenTermination()
282      *
283      * @since Java for Mac OS X 10.6 Update 3
284      * @since Java for Mac OS X 10.5 Update 8
285      */
disableSuddenTermination()286     public void disableSuddenTermination() {
287         _AppMiscHandlers.disableSuddenTermination();
288     }
289 
290     /**
291      * Requests this application to move to the foreground.
292      *
293      * @param allWindows if all windows of this application should be moved to the foreground, or only the foremost one
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      */
requestForeground(final boolean allWindows)298     public void requestForeground(final boolean allWindows) {
299         _AppMiscHandlers.requestActivation(allWindows);
300     }
301 
302     /**
303      * Requests user attention to this application (usually through bouncing the Dock icon). Critical
304      * requests will continue to bounce the Dock icon until the app is activated. An already active
305      * application requesting attention does nothing.
306      *
307      * @param critical if this is an important request
308      *
309      * @since Java for Mac OS X 10.6 Update 1
310      * @since Java for Mac OS X 10.5 Update 6 - 1.6, 1.5
311      */
requestUserAttention(final boolean critical)312     public void requestUserAttention(final boolean critical) {
313         _AppMiscHandlers.requestUserAttention(critical);
314     }
315 
316     /**
317      * Opens the native help viewer application if a Help Book has been added to the
318      * application bundler and registered in the Info.plist with CFBundleHelpBookFolder.
319      *
320      * See http://developer.apple.com/qa/qa2001/qa1022.html for more information.
321      *
322      * @since Java for Mac OS X 10.5 - 1.5
323      * @since Java for Mac OS X 10.5 Update 1 - 1.6
324      */
openHelpViewer()325     public void openHelpViewer() {
326         _AppMiscHandlers.openHelpViewer();
327     }
328 
329     /**
330      * Attaches the contents of the provided PopupMenu to the application's Dock icon.
331      *
332      * @param menu the PopupMenu to attach to this application's Dock icon
333      *
334      * @since Java for Mac OS X 10.5 - 1.5
335      * @since Java for Mac OS X 10.5 Update 1 - 1.6
336      */
setDockMenu(final PopupMenu menu)337     public void setDockMenu(final PopupMenu menu) {
338         iconHandler.setDockMenu(menu);
339     }
340 
341     /**
342      * @return the PopupMenu used to add items to this application's Dock icon
343      *
344      * @since Java for Mac OS X 10.5 - 1.5
345      * @since Java for Mac OS X 10.5 Update 1 - 1.6
346      */
getDockMenu()347     public PopupMenu getDockMenu() {
348         return iconHandler.getDockMenu();
349     }
350 
351     /**
352      * Changes this application's Dock icon to the provided image.
353      *
354      * @param image
355      *
356      * @since Java for Mac OS X 10.5 - 1.5
357      * @since Java for Mac OS X 10.5 Update 1 - 1.6
358      */
setDockIconImage(final Image image)359     public void setDockIconImage(final Image image) {
360         iconHandler.setDockIconImage(image);
361     }
362 
363     /**
364      * Obtains an image of this application's Dock icon.
365      *
366      * @return an image of this application's Dock icon
367      *
368      * @since Java for Mac OS X 10.5 - 1.5
369      * @since Java for Mac OS X 10.5 Update 1 - 1.6
370      */
getDockIconImage()371     public Image getDockIconImage() {
372         return iconHandler.getDockIconImage();
373     }
374 
375     /**
376      * Affixes a small system provided badge to this application's Dock icon. Usually a number.
377      *
378      * @param badge textual label to affix to the Dock icon
379      *
380      * @since Java for Mac OS X 10.5 - 1.5
381      * @since Java for Mac OS X 10.5 Update 1 - 1.6
382      */
setDockIconBadge(final String badge)383     public void setDockIconBadge(final String badge) {
384         iconHandler.setDockIconBadge(badge);
385     }
386 
387     /**
388      * Displays a progress bar to this application's Dock icon.
389      * Acceptable values are from 0 to 100, any other disables progress indication.
390      *
391      * @param value progress value
392      */
setDockIconProgress(final int value)393     public void setDockIconProgress(final int value) {
394         iconHandler.setDockIconProgress(value);
395     }
396 
397     /**
398      * Sets the default menu bar to use when there are no active frames.
399      * Only used when the system property "apple.laf.useScreenMenuBar" is "true", and
400      * the Aqua Look and Feel is active.
401      *
402      * @param menuBar to use when no other frames are active
403      *
404      * @since Java for Mac OS X 10.6 Update 1
405      * @since Java for Mac OS X 10.5 Update 6 - 1.6, 1.5
406      */
setDefaultMenuBar(final JMenuBar menuBar)407     public void setDefaultMenuBar(final JMenuBar menuBar) {
408         menuBarHandler.setDefaultMenuBar(menuBar);
409     }
410 
411     /**
412      * Requests that a {@link Window} should animate into or out of full screen mode.
413      * Only {@link Window}s marked as full screenable by {@link FullScreenUtilities#setWindowCanFullScreen(Window, boolean)} can be toggled.
414      *
415      * @param window to animate into or out of full screen mode
416      *
417      * @since Java for Mac OS X 10.7 Update 1
418      */
requestToggleFullScreen(final Window window)419     public void requestToggleFullScreen(final Window window) {
420         final Object peer = AWTAccessor.getComponentAccessor().getPeer(window);
421         if (!(peer instanceof LWWindowPeer)) return;
422         Object platformWindow = ((LWWindowPeer) peer).getPlatformWindow();
423         if (!(platformWindow instanceof CPlatformWindow)) return;
424         ((CPlatformWindow)platformWindow).toggleFullScreen();
425     }
426 
427 }
428