1 | // License: GPL. For details, see LICENSE file.
|
---|
2 | package org.openstreetmap.josm.tools;
|
---|
3 |
|
---|
4 | import static org.openstreetmap.josm.tools.I18n.tr;
|
---|
5 | import static org.openstreetmap.josm.tools.Utils.getSystemProperty;
|
---|
6 |
|
---|
7 | import java.awt.Desktop;
|
---|
8 | import java.awt.GraphicsEnvironment;
|
---|
9 | import java.awt.Image;
|
---|
10 | import java.awt.Window;
|
---|
11 | import java.awt.event.KeyEvent;
|
---|
12 | import java.io.ByteArrayInputStream;
|
---|
13 | import java.io.File;
|
---|
14 | import java.io.IOException;
|
---|
15 | import java.lang.reflect.InvocationHandler;
|
---|
16 | import java.lang.reflect.InvocationTargetException;
|
---|
17 | import java.lang.reflect.Method;
|
---|
18 | import java.lang.reflect.Proxy;
|
---|
19 | import java.nio.charset.StandardCharsets;
|
---|
20 | import java.security.KeyStoreException;
|
---|
21 | import java.security.NoSuchAlgorithmException;
|
---|
22 | import java.security.cert.CertificateException;
|
---|
23 | import java.security.cert.CertificateFactory;
|
---|
24 | import java.security.cert.X509Certificate;
|
---|
25 | import java.util.Arrays;
|
---|
26 | import java.util.List;
|
---|
27 | import java.util.Objects;
|
---|
28 | import java.util.concurrent.ExecutionException;
|
---|
29 |
|
---|
30 | import javax.swing.UIManager;
|
---|
31 |
|
---|
32 | import org.openstreetmap.josm.data.Preferences;
|
---|
33 | import org.openstreetmap.josm.gui.MainApplication;
|
---|
34 | import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetReader;
|
---|
35 | import org.openstreetmap.josm.io.CertificateAmendment.NativeCertAmend;
|
---|
36 |
|
---|
37 | /**
|
---|
38 | * {@code PlatformHook} implementation for Apple macOS (formerly Mac OS X) systems.
|
---|
39 | * @since 1023
|
---|
40 | */
|
---|
41 | public class PlatformHookOsx implements PlatformHook, InvocationHandler {
|
---|
42 |
|
---|
43 | private String oSBuildNumber;
|
---|
44 |
|
---|
45 | private NativeOsCallback osCallback;
|
---|
46 |
|
---|
47 | @Override
|
---|
48 | public Platform getPlatform() {
|
---|
49 | return Platform.OSX;
|
---|
50 | }
|
---|
51 |
|
---|
52 | @Override
|
---|
53 | public void afterPrefStartupHook() {
|
---|
54 | // This will merge our MenuBar into the system menu.
|
---|
55 | // MUST be set before Swing is initialized!
|
---|
56 |
|
---|
57 | // But only use the menu bar if the Name Suggestion Index is not enabled -- see JDK-8297117 (can remove once that is fixed)
|
---|
58 | // The NSI is especially egregious since it adds something like 8k presets, and is the most likely to trigger JDK-8297117.
|
---|
59 | if (TaggingPresetReader.getPresetSources().stream().noneMatch(url -> url.contains("name-suggestion-index"))) {
|
---|
60 | Utils.updateSystemProperty("apple.laf.useScreenMenuBar", "true");
|
---|
61 | }
|
---|
62 | Utils.updateSystemProperty("apple.awt.application.name", "JOSM");
|
---|
63 | }
|
---|
64 |
|
---|
65 | @Override
|
---|
66 | public void startupHook(JavaExpirationCallback javaCallback, WebStartMigrationCallback webStartCallback) {
|
---|
67 | // Here we register callbacks for the menu entries in the system menu and file opening through double-click
|
---|
68 | // https://openjdk.java.net/jeps/272
|
---|
69 | // https://bugs.openjdk.java.net/browse/JDK-8048731
|
---|
70 | // https://cr.openjdk.java.net/~azvegint/jdk/9/8143227/10/jdk/
|
---|
71 | // This method must be cleaned up after we switch to Java 9
|
---|
72 | try {
|
---|
73 | Class<?> eawtApplication = Class.forName("com.apple.eawt.Application");
|
---|
74 | Class<?> quitHandler = findHandlerClass("QuitHandler");
|
---|
75 | Class<?> aboutHandler = findHandlerClass("AboutHandler");
|
---|
76 | Class<?> openFilesHandler = findHandlerClass("OpenFilesHandler");
|
---|
77 | Class<?> preferencesHandler = findHandlerClass("PreferencesHandler");
|
---|
78 | Object proxy = Proxy.newProxyInstance(PlatformHookOsx.class.getClassLoader(), new Class<?>[] {
|
---|
79 | quitHandler, aboutHandler, openFilesHandler, preferencesHandler}, this);
|
---|
80 | Object appli = eawtApplication.getConstructor((Class[]) null).newInstance((Object[]) null);
|
---|
81 | if (Utils.getJavaVersion() < 9) {
|
---|
82 | setHandlers(eawtApplication, quitHandler, aboutHandler, openFilesHandler, preferencesHandler, proxy, appli);
|
---|
83 | // this method has been deprecated, but without replacement. To remove with Java 9 migration
|
---|
84 | eawtApplication.getDeclaredMethod("setEnabledPreferencesMenu", boolean.class).invoke(appli, Boolean.TRUE);
|
---|
85 | } else if (!GraphicsEnvironment.isHeadless()) {
|
---|
86 | setHandlers(Desktop.class, quitHandler, aboutHandler, openFilesHandler, preferencesHandler, proxy, Desktop.getDesktop());
|
---|
87 | }
|
---|
88 | // setup the dock icon. It is automatically set with application bundle and Web start but we need
|
---|
89 | // to do it manually if run with `java -jar``.
|
---|
90 | eawtApplication.getDeclaredMethod("setDockIconImage", Image.class).invoke(
|
---|
91 | appli,
|
---|
92 | ImageProvider.get(/* ICON */ "logo_macOS", ImageProvider.ImageSizes.ABOUT_LOGO).getImage()
|
---|
93 | );
|
---|
94 |
|
---|
95 | // enable full screen
|
---|
96 | enableOSXFullscreen(MainApplication.getMainFrame());
|
---|
97 | } catch (ReflectiveOperationException | SecurityException | IllegalArgumentException ex) {
|
---|
98 | // We'll just ignore this for now. The user will still be able to close JOSM by closing all its windows.
|
---|
99 | Logging.warn("Failed to register with macOS: " + ex);
|
---|
100 | }
|
---|
101 | warnSoonToBeUnsupportedJava(javaCallback);
|
---|
102 | checkExpiredJava(javaCallback);
|
---|
103 | checkWebStartMigration(webStartCallback);
|
---|
104 | }
|
---|
105 |
|
---|
106 | @Override
|
---|
107 | public boolean isHtmlSupportedInMenuTooltips() {
|
---|
108 | // See #17915 - JDK-8164935
|
---|
109 | // "Mac" is the native LAF, "Aqua" is Quaqua. Both use native menus with native tooltips.
|
---|
110 | String laf = UIManager.getLookAndFeel().getID();
|
---|
111 | return !("true".equals(getSystemProperty("apple.laf.useScreenMenuBar"))
|
---|
112 | && ("Aqua".equals(laf) || laf.contains("Mac")));
|
---|
113 | }
|
---|
114 |
|
---|
115 | @Override
|
---|
116 | public int getMenuShortcutKeyMaskEx() {
|
---|
117 | return KeyEvent.META_DOWN_MASK;
|
---|
118 | }
|
---|
119 |
|
---|
120 | /**
|
---|
121 | * Registers Apple handlers.
|
---|
122 | * @param appClass application class
|
---|
123 | * @param quitHandler quit handler class
|
---|
124 | * @param aboutHandler about handler class
|
---|
125 | * @param openFilesHandler open file handler class
|
---|
126 | * @param preferencesHandler preferences handler class
|
---|
127 | * @param proxy proxy
|
---|
128 | * @param appInstance application instance (instance of {@code appClass})
|
---|
129 | * @throws IllegalAccessException in case of reflection error
|
---|
130 | * @throws InvocationTargetException in case of reflection error
|
---|
131 | * @throws NoSuchMethodException if any {@code set*Handler} method cannot be found
|
---|
132 | */
|
---|
133 | protected void setHandlers(Class<?> appClass, Class<?> quitHandler, Class<?> aboutHandler,
|
---|
134 | Class<?> openFilesHandler, Class<?> preferencesHandler, Object proxy, Object appInstance)
|
---|
135 | throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
|
---|
136 | appClass.getDeclaredMethod("setQuitHandler", quitHandler).invoke(appInstance, proxy);
|
---|
137 | appClass.getDeclaredMethod("setAboutHandler", aboutHandler).invoke(appInstance, proxy);
|
---|
138 | appClass.getDeclaredMethod("setOpenFileHandler", openFilesHandler).invoke(appInstance, proxy);
|
---|
139 | appClass.getDeclaredMethod("setPreferencesHandler", preferencesHandler).invoke(appInstance, proxy);
|
---|
140 | }
|
---|
141 |
|
---|
142 | /**
|
---|
143 | * Find Apple handler class in {@code com.apple.eawt} or {@code java.awt.desktop} packages.
|
---|
144 | * @param className simple class name
|
---|
145 | * @return class
|
---|
146 | * @throws ClassNotFoundException if the handler class cannot be found
|
---|
147 | */
|
---|
148 | protected Class<?> findHandlerClass(String className) throws ClassNotFoundException {
|
---|
149 | try {
|
---|
150 | // Java 8 handlers
|
---|
151 | return Class.forName("com.apple.eawt."+className);
|
---|
152 | } catch (ClassNotFoundException e) {
|
---|
153 | Logging.trace(e);
|
---|
154 | // Java 9 handlers
|
---|
155 | return Class.forName("java.awt.desktop."+className);
|
---|
156 | }
|
---|
157 | }
|
---|
158 |
|
---|
159 | /**
|
---|
160 | * Enables fullscreen support for the given window.
|
---|
161 | * @param window The window for which full screen will be available
|
---|
162 | * @since 7482
|
---|
163 | */
|
---|
164 | public static void enableOSXFullscreen(Window window) {
|
---|
165 | CheckParameterUtil.ensureParameterNotNull(window, "window");
|
---|
166 | try {
|
---|
167 | // http://stackoverflow.com/a/8693890/2257172
|
---|
168 | Class<?> eawtFullScreenUtilities = Class.forName("com.apple.eawt.FullScreenUtilities");
|
---|
169 | eawtFullScreenUtilities.getDeclaredMethod("setWindowCanFullScreen",
|
---|
170 | Window.class, boolean.class).invoke(eawtFullScreenUtilities, window, Boolean.TRUE);
|
---|
171 | } catch (ReflectiveOperationException | SecurityException | IllegalArgumentException e) {
|
---|
172 | Logging.warn("Failed to register with macOS: " + e);
|
---|
173 | }
|
---|
174 | }
|
---|
175 |
|
---|
176 | @Override
|
---|
177 | public void setNativeOsCallback(NativeOsCallback callback) {
|
---|
178 | osCallback = Objects.requireNonNull(callback);
|
---|
179 | }
|
---|
180 |
|
---|
181 | @SuppressWarnings("unchecked")
|
---|
182 | @Override
|
---|
183 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
---|
184 | if (Logging.isDebugEnabled()) {
|
---|
185 | Logging.debug("macOS handler: {0} - {1}", method.getName(), Arrays.toString(args));
|
---|
186 | }
|
---|
187 | switch (method.getName()) {
|
---|
188 | case "openFiles":
|
---|
189 | if (args[0] != null) {
|
---|
190 | try {
|
---|
191 | Object oFiles = args[0].getClass().getMethod("getFiles").invoke(args[0]);
|
---|
192 | if (oFiles instanceof List) {
|
---|
193 | osCallback.openFiles((List<File>) oFiles);
|
---|
194 | }
|
---|
195 | } catch (ReflectiveOperationException | SecurityException | IllegalArgumentException ex) {
|
---|
196 | Logging.warn("Failed to access open files event: " + ex);
|
---|
197 | }
|
---|
198 | }
|
---|
199 | break;
|
---|
200 | case "handleQuitRequestWith":
|
---|
201 | boolean closed = osCallback.handleQuitRequest();
|
---|
202 | if (args[1] != null) {
|
---|
203 | try {
|
---|
204 | args[1].getClass().getDeclaredMethod(closed ? "performQuit" : "cancelQuit").invoke(args[1]);
|
---|
205 | } catch (IllegalAccessException e) {
|
---|
206 | Logging.debug(e);
|
---|
207 | // with Java 9, module java.desktop does not export com.apple.eawt, use new Desktop API instead
|
---|
208 | Class.forName("java.awt.desktop.QuitResponse").getMethod(closed ? "performQuit" : "cancelQuit").invoke(args[1]);
|
---|
209 | }
|
---|
210 | }
|
---|
211 | break;
|
---|
212 | case "handleAbout":
|
---|
213 | osCallback.handleAbout();
|
---|
214 | break;
|
---|
215 | case "handlePreferences":
|
---|
216 | osCallback.handlePreferences();
|
---|
217 | break;
|
---|
218 | default:
|
---|
219 | Logging.warn("macOS unsupported method: "+method.getName());
|
---|
220 | }
|
---|
221 | return null;
|
---|
222 | }
|
---|
223 |
|
---|
224 | @Override
|
---|
225 | public void openUrl(String url) throws IOException {
|
---|
226 | Runtime.getRuntime().exec(new String[]{"open", url});
|
---|
227 | }
|
---|
228 |
|
---|
229 | @Override
|
---|
230 | public void initSystemShortcuts() {
|
---|
231 | // CHECKSTYLE.OFF: LineLength
|
---|
232 | auto(Shortcut.registerSystemShortcut("apple-reserved-01", tr("reserved"), KeyEvent.VK_SPACE, KeyEvent.META_DOWN_MASK)); // Show or hide the Spotlight search field (when multiple languages are installed, may rotate through enabled script systems).
|
---|
233 | auto(Shortcut.registerSystemShortcut("apple-reserved-02", tr("reserved"), KeyEvent.VK_SPACE, KeyEvent.META_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK)); // Apple reserved.
|
---|
234 | auto(Shortcut.registerSystemShortcut("apple-reserved-03", tr("reserved"), KeyEvent.VK_SPACE, KeyEvent.META_DOWN_MASK | KeyEvent.ALT_DOWN_MASK)); // Show the Spotlight search results window (when multiple languages are installed, may rotate through keyboard layouts and input methods within a script).
|
---|
235 | auto(Shortcut.registerSystemShortcut("apple-reserved-04", tr("reserved"), KeyEvent.VK_SPACE, KeyEvent.META_DOWN_MASK | KeyEvent.CTRL_DOWN_MASK)); // | Apple reserved.
|
---|
236 | auto(Shortcut.registerSystemShortcut("apple-reserved-05", tr("reserved"), KeyEvent.VK_TAB, KeyEvent.SHIFT_DOWN_MASK)); // Navigate through controls in a reverse direction. See "Keyboard Focus and Navigation."
|
---|
237 | auto(Shortcut.registerSystemShortcut("apple-reserved-06", tr("reserved"), KeyEvent.VK_TAB, KeyEvent.META_DOWN_MASK)); // Move forward to the next most recently used application in a list of open applications.
|
---|
238 | auto(Shortcut.registerSystemShortcut("apple-reserved-07", tr("reserved"), KeyEvent.VK_TAB, KeyEvent.META_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK)); // Move backward through a list of open applications (sorted by recent use).
|
---|
239 | auto(Shortcut.registerSystemShortcut("apple-reserved-08", tr("reserved"), KeyEvent.VK_TAB, KeyEvent.CTRL_DOWN_MASK)); // Move focus to the next grouping of controls in a dialog or the next table (when Tab moves to the next cell). See Accessibility Overview.
|
---|
240 | auto(Shortcut.registerSystemShortcut("apple-reserved-09", tr("reserved"), KeyEvent.VK_TAB, KeyEvent.CTRL_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK)); // Move focus to the previous grouping of controls. See Accessibility Overview.
|
---|
241 | auto(Shortcut.registerSystemShortcut("apple-reserved-10", tr("reserved"), KeyEvent.VK_ESCAPE, KeyEvent.META_DOWN_MASK)); // Open Front Row.
|
---|
242 | auto(Shortcut.registerSystemShortcut("apple-reserved-11", tr("reserved"), KeyEvent.VK_ESCAPE, KeyEvent.META_DOWN_MASK | KeyEvent.ALT_DOWN_MASK)); // Open the Force Quit dialog.
|
---|
243 | auto(Shortcut.registerSystemShortcut("apple-reserved-12", tr("reserved"), KeyEvent.VK_F1, KeyEvent.CTRL_DOWN_MASK)); // Toggle full keyboard access on or off. See Accessibility Overview.
|
---|
244 | auto(Shortcut.registerSystemShortcut("apple-reserved-13", tr("reserved"), KeyEvent.VK_F2, KeyEvent.CTRL_DOWN_MASK)); // Move focus to the menu bar. See Accessibility Overview.
|
---|
245 | auto(Shortcut.registerSystemShortcut("apple-reserved-14", tr("reserved"), KeyEvent.VK_F3, KeyEvent.CTRL_DOWN_MASK)); // Move focus to the Dock. See Accessibility Overview.
|
---|
246 | auto(Shortcut.registerSystemShortcut("apple-reserved-15", tr("reserved"), KeyEvent.VK_F4, KeyEvent.CTRL_DOWN_MASK)); // Move focus to the active (or next) window. See Accessibility Overview.
|
---|
247 | auto(Shortcut.registerSystemShortcut("apple-reserved-16", tr("reserved"), KeyEvent.VK_F4, KeyEvent.CTRL_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK)); // Move focus to the previously active window. See Accessibility Overview.
|
---|
248 | auto(Shortcut.registerSystemShortcut("apple-reserved-17", tr("reserved"), KeyEvent.VK_F5, KeyEvent.CTRL_DOWN_MASK)); // Move focus to the toolbar. See Accessibility Overview.
|
---|
249 | auto(Shortcut.registerSystemShortcut("apple-reserved-18", tr("reserved"), KeyEvent.VK_F5, KeyEvent.META_DOWN_MASK)); // Turn VoiceOver on or off. See Accessibility Overview.
|
---|
250 | auto(Shortcut.registerSystemShortcut("apple-reserved-19", tr("reserved"), KeyEvent.VK_F6, KeyEvent.CTRL_DOWN_MASK)); // Move focus to the first (or next) panel. See Accessibility Overview.
|
---|
251 | auto(Shortcut.registerSystemShortcut("apple-reserved-20", tr("reserved"), KeyEvent.VK_F6, KeyEvent.CTRL_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK)); // Move focus to the previous panel. See Accessibility Overview.
|
---|
252 | auto(Shortcut.registerSystemShortcut("apple-reserved-21", tr("reserved"), KeyEvent.VK_F7, KeyEvent.CTRL_DOWN_MASK)); // Temporarily override the current keyboard access mode in windows and dialogs. See Accessibility Overview.
|
---|
253 | //auto(Shortcut.registerSystemShortcut("apple-reserved-22", tr("reserved"), KeyEvent.VK_F9, 0)); // Tile or untile all open windows.
|
---|
254 | //auto(Shortcut.registerSystemShortcut("apple-reserved-23", tr("reserved"), KeyEvent.VK_F10, 0)); // Tile or untile all open windows in the currently active application.
|
---|
255 | //auto(Shortcut.registerSystemShortcut("apple-reserved-24", tr("reserved"), KeyEvent.VK_F11, 0)); // Hide or show all open windows.
|
---|
256 | //auto(Shortcut.registerSystemShortcut("apple-reserved-25", tr("reserved"), KeyEvent.VK_F12, 0)); // Hide or display Dashboard.
|
---|
257 | auto(Shortcut.registerSystemShortcut("apple-reserved-26", tr("reserved"), KeyEvent.VK_DEAD_GRAVE, KeyEvent.META_DOWN_MASK)); // Activate the next open window in the frontmost application. See "Window Layering."
|
---|
258 | auto(Shortcut.registerSystemShortcut("apple-reserved-27", tr("reserved"), KeyEvent.VK_DEAD_GRAVE, KeyEvent.META_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK)); // Activate the previous open window in the frontmost application. See "Window Layering."
|
---|
259 | auto(Shortcut.registerSystemShortcut("apple-reserved-28", tr("reserved"), KeyEvent.VK_DEAD_GRAVE, KeyEvent.META_DOWN_MASK | KeyEvent.ALT_DOWN_MASK)); // Move focus to the window drawer.
|
---|
260 | //auto(Shortcut.registerSystemShortcut("apple-reserved-29", tr("reserved"), KeyEvent.VK_MINUS, KeyEvent.META_DOWN_MASK)); // Decrease the size of the selected item (equivalent to the Smaller command). See "The Format Menu."
|
---|
261 | auto(Shortcut.registerSystemShortcut("apple-reserved-30", tr("reserved"), KeyEvent.VK_MINUS, KeyEvent.META_DOWN_MASK | KeyEvent.ALT_DOWN_MASK)); // Zoom out when screen zooming is on. See Accessibility Overview.
|
---|
262 |
|
---|
263 | //Shortcut.registerSystemShortcut("system:align-left", tr("reserved"), KeyEvent.VK_OPEN_BRACKET, KeyEvent.META_DOWN_MASK); // Left-align a selection (equivalent to the Align Left command). See "The Format Menu."
|
---|
264 | //Shortcut.registerSystemShortcut("system:align-right",tr("reserved"), KeyEvent.VK_CLOSE_BRACKET, KeyEvent.META_DOWN_MASK); // Right-align a selection (equivalent to the Align Right command). See "The Format Menu."
|
---|
265 | // I found no KeyEvent for |
|
---|
266 | //Shortcut.registerSystemCut("system:align-center", tr("reserved"), '|', KeyEvent.META_DOWN_MASK); // Center-align a selection (equivalent to the Align Center command). See "The Format Menu."
|
---|
267 | //Shortcut.registerSystemShortcut("system:spelling", tr("reserved"), KeyEvent.VK_COLON, KeyEvent.META_DOWN_MASK); // Display the Spelling window (equivalent to the Spelling command). See "The Edit Menu."
|
---|
268 | //Shortcut.registerSystemShortcut("system:spellcheck", tr("reserved"), KeyEvent.VK_SEMICOLON, KeyEvent.META_DOWN_MASK); // Find misspelled words in the document (equivalent to the Check Spelling command). See "The Edit Menu."
|
---|
269 | auto(Shortcut.registerSystemShortcut("system:preferences", tr("reserved"), KeyEvent.VK_COMMA, KeyEvent.META_DOWN_MASK)); // Open the application's preferences window (equivalent to the Preferences command). See "The Application Menu."
|
---|
270 |
|
---|
271 | auto(Shortcut.registerSystemShortcut("apple-reserved-31", tr("reserved"), KeyEvent.VK_COMMA, KeyEvent.META_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK | KeyEvent.ALT_DOWN_MASK)); // Decrease screen contrast. See Accessibility Overview.
|
---|
272 | auto(Shortcut.registerSystemShortcut("apple-reserved-32", tr("reserved"), KeyEvent.VK_PERIOD, KeyEvent.META_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK | KeyEvent.ALT_DOWN_MASK)); // Increase screen contrast. See Accessibility Overview.
|
---|
273 |
|
---|
274 | // I found no KeyEvent for ?
|
---|
275 | //auto(Shortcut.registerSystemCut("system:help", tr("reserved"), '?', KeyEvent.META_DOWN_MASK)); // Open the application's help in Help Viewer. See "The Help Menu."
|
---|
276 |
|
---|
277 | auto(Shortcut.registerSystemShortcut("apple-reserved-33", tr("reserved"), KeyEvent.VK_SLASH, KeyEvent.META_DOWN_MASK | KeyEvent.ALT_DOWN_MASK)); // Turn font smoothing on or off.
|
---|
278 | auto(Shortcut.registerSystemShortcut("apple-reserved-34", tr("reserved"), KeyEvent.VK_EQUALS, KeyEvent.META_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK)); // Increase the size of the selected item (equivalent to the Bigger command). See "The Format Menu."
|
---|
279 | auto(Shortcut.registerSystemShortcut("apple-reserved-35", tr("reserved"), KeyEvent.VK_EQUALS, KeyEvent.META_DOWN_MASK | KeyEvent.ALT_DOWN_MASK)); // Zoom in when screen zooming is on. See Accessibility Overview.
|
---|
280 | auto(Shortcut.registerSystemShortcut("apple-reserved-36", tr("reserved"), KeyEvent.VK_3, KeyEvent.META_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK)); // Capture the screen to a file.
|
---|
281 | auto(Shortcut.registerSystemShortcut("apple-reserved-37", tr("reserved"), KeyEvent.VK_3, KeyEvent.META_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK | KeyEvent.CTRL_DOWN_MASK)); // Capture the screen to the Clipboard.
|
---|
282 | auto(Shortcut.registerSystemShortcut("apple-reserved-38", tr("reserved"), KeyEvent.VK_4, KeyEvent.META_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK)); // Capture a selection to a file.
|
---|
283 | auto(Shortcut.registerSystemShortcut("apple-reserved-39", tr("reserved"), KeyEvent.VK_4, KeyEvent.META_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK | KeyEvent.CTRL_DOWN_MASK)); // Capture a selection to the Clipboard.
|
---|
284 | auto(Shortcut.registerSystemShortcut("apple-reserved-40", tr("reserved"), KeyEvent.VK_8, KeyEvent.META_DOWN_MASK | KeyEvent.ALT_DOWN_MASK)); // Turn screen zooming on or off. See Accessibility Overview.
|
---|
285 | auto(Shortcut.registerSystemShortcut("apple-reserved-41", tr("reserved"), KeyEvent.VK_8, KeyEvent.META_DOWN_MASK | KeyEvent.ALT_DOWN_MASK | KeyEvent.CTRL_DOWN_MASK)); // Invert the screen colors. See Accessibility Overview.
|
---|
286 |
|
---|
287 | Shortcut.registerSystemShortcut("system:selectall", tr("reserved"), KeyEvent.VK_A, KeyEvent.META_DOWN_MASK); // Highlight every item in a document or window, or all characters in a text field (equivalent to the Select All command). See "The Edit Menu."
|
---|
288 | //Shortcut.registerSystemShortcut("system:bold", tr("reserved"), KeyEvent.VK_B, KeyEvent.META_DOWN_MASK); // Boldface the selected text or toggle boldfaced text on and off (equivalent to the Bold command). See "The Edit Menu."
|
---|
289 | Shortcut.registerSystemShortcut("system:copy", tr("reserved"), KeyEvent.VK_C, KeyEvent.META_DOWN_MASK); // Duplicate the selected data and store on the Clipboard (equivalent to the Copy command). See "The Edit Menu."
|
---|
290 | //Shortcut.registerSystemShortcut("system:colors", tr("reserved"), KeyEvent.VK_C, KeyEvent.META_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK); // Display the Colors window (equivalent to the Show Colors command). See "The Format Menu."
|
---|
291 | //Shortcut.registerSystemShortcut("system:copystyle", tr("reserved"), KeyEvent.VK_C, KeyEvent.META_DOWN_MASK | KeyEvent.ALT_DOWN_MASK); // Copy the style of the selected text (equivalent to the Copy Style command). See "The Format Menu."
|
---|
292 | //Shortcut.registerSystemShortcut("system:copyformat", tr("reserved"), KeyEvent.VK_C, KeyEvent.META_DOWN_MASK | KeyEvent.CTRL_DOWN_MASK)); // Copy the formatting settings of the selected item and store on the Clipboard (equivalent to the Copy Ruler command). See "The Format Menu."
|
---|
293 |
|
---|
294 | auto(Shortcut.registerSystemShortcut("apple-reserved-42", tr("reserved"), KeyEvent.VK_D, KeyEvent.META_DOWN_MASK | KeyEvent.ALT_DOWN_MASK)); // Show or hide the Dock. See "The Dock."
|
---|
295 |
|
---|
296 | Shortcut.registerSystemShortcut("system:dictionarylookup", tr("reserved"), KeyEvent.VK_D, KeyEvent.META_DOWN_MASK | KeyEvent.CTRL_DOWN_MASK); // Display the definition of the selected word in the Dictionary application.
|
---|
297 | //Shortcut.registerSystemShortcut("system:findselected", tr("reserved"), KeyEvent.VK_E, KeyEvent.META_DOWN_MASK); // Use the selection for a find operation. See "Find Windows."
|
---|
298 | Shortcut.registerSystemShortcut("system:find", tr("reserved"), KeyEvent.VK_F, KeyEvent.META_DOWN_MASK); // Open a Find window (equivalent to the Find command). See "The Edit Menu."
|
---|
299 | Shortcut.registerSystemShortcut("system:search", tr("reserved"), KeyEvent.VK_F, KeyEvent.META_DOWN_MASK | KeyEvent.ALT_DOWN_MASK); // Jump to the search field control. See "Search Fields."
|
---|
300 | //Shortcut.registerSystemShortcut("system:findnext", tr("reserved"), KeyEvent.VK_G, KeyEvent.META_DOWN_MASK); // Find the next occurrence of the selection (equivalent to the Find Next command). See "The Edit Menu."
|
---|
301 | //Shortcut.registerSystemShortcut("system:findprev", tr("reserved"), KeyEvent.VK_G, KeyEvent.META_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK); // Find the previous occurrence of the selection (equivalent to the Find Previous command). See "The Edit Menu."
|
---|
302 | auto(Shortcut.registerSystemShortcut("system:hide", tr("reserved"), KeyEvent.VK_H, KeyEvent.META_DOWN_MASK)); // Hide the windows of the currently running application (equivalent to the Hide ApplicationName command). See "The Application Menu."
|
---|
303 | auto(Shortcut.registerSystemShortcut("system:hideothers", tr("reserved"), KeyEvent.VK_H, KeyEvent.META_DOWN_MASK | KeyEvent.ALT_DOWN_MASK)); // Hide the windows of all other running applications (equivalent to the Hide Others command). See "The Application Menu."
|
---|
304 | // What about applications that have italic text AND info windows?
|
---|
305 | //Shortcut.registerSystemCut("system:italic", tr("reserved"), KeyEvent.VK_I, KeyEvent.META_DOWN_MASK); // Italicize the selected text or toggle italic text on or off (equivalent to the Italic command). See "The Format Menu."
|
---|
306 | //Shortcut.registerSystemShortcut("system:info", tr("reserved"), KeyEvent.VK_I, KeyEvent.META_DOWN_MASK); // Display an Info window. See "Inspector Windows."
|
---|
307 | //Shortcut.registerSystemShortcut("system:inspector", tr("reserved"), KeyEvent.VK_I, KeyEvent.META_DOWN_MASK | KeyEvent.ALT_DOWN_MASK); // Display an inspector window. See "Inspector Windows."
|
---|
308 | //Shortcut.registerSystemShortcut("system:toselection", tr("reserved"), KeyEvent.VK_J, KeyEvent.META_DOWN_MASK); // Scroll to a selection.
|
---|
309 | //Shortcut.registerSystemShortcut("system:minimize", tr("reserved"), KeyEvent.VK_M, KeyEvent.META_DOWN_MASK); // Minimize the active window to the Dock (equivalent to the Minimize command). See "The Window Menu."
|
---|
310 | //Shortcut.registerSystemShortcut("system:minimizeall", tr("reserved"), KeyEvent.VK_M, KeyEvent.META_DOWN_MASK | KeyEvent.ALT_DOWN_MASK); // Minimize all windows of the active application to the Dock (equivalent to the Minimize All command). See "The Window Menu."
|
---|
311 | Shortcut.registerSystemShortcut("system:new", tr("reserved"), KeyEvent.VK_N, KeyEvent.META_DOWN_MASK); // Open a new document (equivalent to the New command). See "The File Menu."
|
---|
312 | Shortcut.registerSystemShortcut("system:open", tr("reserved"), KeyEvent.VK_O, KeyEvent.META_DOWN_MASK); // Display a dialog for choosing a document to open (equivalent to the Open command). See "The File Menu."
|
---|
313 | Shortcut.registerSystemShortcut("system:print", tr("reserved"), KeyEvent.VK_P, KeyEvent.META_DOWN_MASK); // Display the Print dialog (equivalent to the Print command). See "The File Menu."
|
---|
314 | //Shortcut.registerSystemShortcut("system:printsetup", tr("reserved"), KeyEvent.VK_P, KeyEvent.META_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK); // Display a dialog for specifying printing parameters (equivalent to the Page Setup command). See "The File Menu."
|
---|
315 | auto(Shortcut.registerSystemShortcut("system:menuexit", tr("reserved"), KeyEvent.VK_Q, KeyEvent.META_DOWN_MASK)); // Quit the application (equivalent to the Quit command). See "The Application Menu."
|
---|
316 |
|
---|
317 | auto(Shortcut.registerSystemShortcut("apple-reserved-43", tr("reserved"), KeyEvent.VK_Q, KeyEvent.META_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK)); // Log out the current user (equivalent to the Log Out command).
|
---|
318 | auto(Shortcut.registerSystemShortcut("apple-reserved-44", tr("reserved"), KeyEvent.VK_Q, KeyEvent.META_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK | KeyEvent.ALT_DOWN_MASK)); // Log out the current user without confirmation.
|
---|
319 |
|
---|
320 | Shortcut.registerSystemShortcut("system:save", tr("reserved"), KeyEvent.VK_S, KeyEvent.META_DOWN_MASK); // Save the active document (equivalent to the Save command). See "The File Menu."
|
---|
321 | Shortcut.registerSystemShortcut("system:saveas", tr("reserved"), KeyEvent.VK_S, KeyEvent.META_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK); // Display the Save dialog (equivalent to the Save As command). See "The File Menu."
|
---|
322 | //Shortcut.registerSystemShortcut("system:fonts", tr("reserved"), KeyEvent.VK_T, KeyEvent.META_DOWN_MASK); // Display the Fonts window (equivalent to the Show Fonts command). See "The Format Menu."
|
---|
323 | Shortcut.registerSystemShortcut("system:toggletoolbar", tr("reserved"), KeyEvent.VK_T, KeyEvent.META_DOWN_MASK | KeyEvent.ALT_DOWN_MASK); // Show or hide a toolbar (equivalent to the Show/Hide Toolbar command). See "The View Menu" and "Toolbars."
|
---|
324 | //Shortcut.registerSystemShortcut("system:underline", tr("reserved"), KeyEvent.VK_U, KeyEvent.META_DOWN_MASK); // Underline the selected text or turn underlining on or off (equivalent to the Underline command). See "The Format Menu."
|
---|
325 | Shortcut.registerSystemShortcut("system:paste", tr("reserved"), KeyEvent.VK_V, KeyEvent.META_DOWN_MASK); // Insert the Clipboard contents at the insertion point (equivalent to the Paste command). See "The File Menu."
|
---|
326 | //Shortcut.registerSystemShortcut("system:pastestyle", tr("reserved"), KeyEvent.VK_V, KeyEvent.META_DOWN_MASK | KeyEvent.ALT_DOWN_MASK); // Apply the style of one object to the selected object (equivalent to the Paste Style command). See "The Format Menu."
|
---|
327 | //Shortcut.registerSystemShortcut("system:pastemwithoutstyle", tr("reserved"), KeyEvent.VK_V, KeyEvent.META_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK | KeyEvent.ALT_DOWN_MASK); // Apply the style of the surrounding text to the inserted object (equivalent to the Paste and Match Style command). See "The Edit Menu."
|
---|
328 | //Shortcut.registerSystemShortcut("system:pasteformatting", tr("reserved"), KeyEvent.VK_V, KeyEvent.META_DOWN_MASK | KeyEvent.CTRL_DOWN_MASK); // Apply formatting settings to the selected object (equivalent to the Paste Ruler command). See "The Format Menu."
|
---|
329 | //Shortcut.registerSystemShortcut("system:closewindow", tr("reserved"), KeyEvent.VK_W, KeyEvent.META_DOWN_MASK); // Close the active window (equivalent to the Close command). See "The File Menu."
|
---|
330 | Shortcut.registerSystemShortcut("system:closefile", tr("reserved"), KeyEvent.VK_W, KeyEvent.META_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK); // Close a file and its associated windows (equivalent to the Close File command). See "The File Menu."
|
---|
331 | Shortcut.registerSystemShortcut("system:closeallwindows", tr("reserved"), KeyEvent.VK_W, KeyEvent.META_DOWN_MASK | KeyEvent.ALT_DOWN_MASK); // Close all windows in the application (equivalent to the Close All command). See "The File Menu."
|
---|
332 | Shortcut.registerSystemShortcut("system:cut", tr("reserved"), KeyEvent.VK_X, KeyEvent.META_DOWN_MASK); // Remove the selection and store on the Clipboard (equivalent to the Cut command). See "The Edit Menu."
|
---|
333 | Shortcut.registerSystemShortcut("system:undo", tr("reserved"), KeyEvent.VK_Z, KeyEvent.META_DOWN_MASK); // Reverse the effect of the user's previous operation (equivalent to the Undo command). See "The Edit Menu."
|
---|
334 | Shortcut.registerSystemShortcut("system:redo", tr("reserved"), KeyEvent.VK_Z, KeyEvent.META_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK); // Reverse the effect of the last Undo command (equivalent to the Redo command). See "The Edit Menu."
|
---|
335 |
|
---|
336 | auto(Shortcut.registerSystemShortcut("apple-reserved-45", tr("reserved"), KeyEvent.VK_RIGHT, KeyEvent.META_DOWN_MASK)); // Change the keyboard layout to current layout of Roman script.
|
---|
337 | //auto(Shortcut.registerSystemCut("apple-reserved-46", tr("reserved"), KeyEvent.VK_RIGHT, KeyEvent.META_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK)); // Extend selection to the next semantic unit, typically the end of the current line.
|
---|
338 | //auto(Shortcut.registerSystemCut("apple-reserved-47", tr("reserved"), KeyEvent.VK_RIGHT, KeyEvent.SHIFT_DOWN_MASK)); // Extend selection one character to the right.
|
---|
339 | //auto(Shortcut.registerSystemCut("apple-reserved-48", tr("reserved"), KeyEvent.VK_RIGHT, KeyEvent.ALT_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK)); // Extend selection to the end of the current word, then to the end of the next word.
|
---|
340 |
|
---|
341 | Shortcut.registerSystemShortcut("system:movefocusright", tr("reserved"), KeyEvent.VK_RIGHT, KeyEvent.CTRL_DOWN_MASK); // Move focus to another value or cell within a view, such as a table. See Accessibility Overview.
|
---|
342 |
|
---|
343 | auto(Shortcut.registerSystemShortcut("apple-reserved-49", tr("reserved"), KeyEvent.VK_LEFT, KeyEvent.META_DOWN_MASK)); // Change the keyboard layout to current layout of system script.
|
---|
344 | //auto(Shortcut.registerSystemCut("apple-reserved-50", tr("reserved"), KeyEvent.VK_LEFT, KeyEvent.META_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK)); // Extend selection to the previous semantic unit, typically the beginning of the current line.
|
---|
345 | //auto(Shortcut.registerSystemCut("apple-reserved-51", tr("reserved"), KeyEvent.VK_LEFT, KeyEvent.SHIFT_DOWN_MASK)); // Extend selection one character to the left.
|
---|
346 | //auto(Shortcut.registerSystemCut("apple-reserved-52", tr("reserved"), KeyEvent.VK_LEFT, KeyEvent.ALT_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK)); // Extend selection to the beginning of the current word, then to the beginning of the previous word.
|
---|
347 |
|
---|
348 | Shortcut.registerSystemShortcut("system:movefocusleft", tr("reserved"), KeyEvent.VK_LEFT, KeyEvent.CTRL_DOWN_MASK); // Move focus to another value or cell within a view, such as a table. See Accessibility Overview.
|
---|
349 |
|
---|
350 | //auto(Shortcut.registerSystemCut("apple-reserved-53", tr("reserved"), KeyEvent.VK_UP, KeyEvent.META_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK)); // Extend selection upward in the next semantic unit, typically the beginning of the document.
|
---|
351 | //auto(Shortcut.registerSystemCut("apple-reserved-54", tr("reserved"), KeyEvent.VK_UP, KeyEvent.SHIFT_DOWN_MASK)); // Extend selection to the line above, to the nearest character boundary at the same horizontal location.
|
---|
352 | //auto(Shortcut.registerSystemCut("apple-reserved-55", tr("reserved"), KeyEvent.VK_UP, KeyEvent.ALT_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK)); // Extend selection to the beginning of the current paragraph, then to the beginning of the next paragraph.
|
---|
353 |
|
---|
354 | Shortcut.registerSystemShortcut("system:movefocusup", tr("reserved"), KeyEvent.VK_UP, KeyEvent.CTRL_DOWN_MASK); // Move focus to another value or cell within a view, such as a table. See Accessibility Overview.
|
---|
355 |
|
---|
356 | //auto(Shortcut.registerSystemCut("apple-reserved-56", tr("reserved"), KeyEvent.VK_DOWN, KeyEvent.META_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK)); // Extend selection downward in the next semantic unit, typically the end of the document.
|
---|
357 | //auto(Shortcut.registerSystemCut("apple-reserved-57", tr("reserved"), KeyEvent.VK_DOWN, KeyEvent.SHIFT_DOWN_MASK)); // Extend selection to the line below, to the nearest character boundary at the same horizontal location.
|
---|
358 | //auto(Shortcut.registerSystemCut("apple-reserved-58", tr("reserved"), KeyEvent.VK_DOWN, KeyEvent.ALT_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK)); // Extend selection to the end of the current paragraph, then to the end of the next paragraph (include the blank line between paragraphs in cut, copy, and paste operations).
|
---|
359 |
|
---|
360 | Shortcut.registerSystemShortcut("system:movefocusdown", tr("reserved"), KeyEvent.VK_DOWN, KeyEvent.CTRL_DOWN_MASK); // Move focus to another value or cell within a view, such as a table. See Accessibility Overview.
|
---|
361 |
|
---|
362 | auto(Shortcut.registerSystemShortcut("system:about", tr("reserved"), 0, -1)); // About
|
---|
363 |
|
---|
364 | //Shortcut.registerSystemShortcut("view:zoomin", tr("reserved"), KeyEvent.VK_ADD, KeyEvent.META_DOWN_MASK); // Zoom in
|
---|
365 | //Shortcut.registerSystemShortcut("view:zoomout", tr("reserved"), KeyEvent.VK_SUBTRACT, KeyEvent.META_DOWN_MASK); // Zoom out
|
---|
366 | // CHECKSTYLE.ON: LineLength
|
---|
367 | }
|
---|
368 |
|
---|
369 | private static void auto(Shortcut sc) {
|
---|
370 | if (sc != null) {
|
---|
371 | sc.setAutomatic();
|
---|
372 | }
|
---|
373 | }
|
---|
374 |
|
---|
375 | @Override
|
---|
376 | public String getDefaultStyle() {
|
---|
377 | return "com.apple.laf.AquaLookAndFeel";
|
---|
378 | }
|
---|
379 |
|
---|
380 | @Override
|
---|
381 | public boolean canFullscreen() {
|
---|
382 | // OS X provides native full screen support registered at initialization, no need for custom action
|
---|
383 | return false;
|
---|
384 | }
|
---|
385 |
|
---|
386 | @Override
|
---|
387 | public String getOSDescription() {
|
---|
388 | return getSystemProperty("os.name") + ' ' + getSystemProperty("os.version");
|
---|
389 | }
|
---|
390 |
|
---|
391 | private String buildOSBuildNumber() {
|
---|
392 | StringBuilder sb = new StringBuilder();
|
---|
393 | try {
|
---|
394 | sb.append(exec("sw_vers", "-productName"))
|
---|
395 | .append(' ')
|
---|
396 | .append(exec("sw_vers", "-productVersion"))
|
---|
397 | .append(" (")
|
---|
398 | .append(exec("sw_vers", "-buildVersion"))
|
---|
399 | .append(')');
|
---|
400 | } catch (IOException e) {
|
---|
401 | Logging.error(e);
|
---|
402 | }
|
---|
403 | return sb.toString();
|
---|
404 | }
|
---|
405 |
|
---|
406 | @Override
|
---|
407 | public String getOSBuildNumber() {
|
---|
408 | if (oSBuildNumber == null) {
|
---|
409 | oSBuildNumber = buildOSBuildNumber();
|
---|
410 | }
|
---|
411 | return oSBuildNumber;
|
---|
412 | }
|
---|
413 |
|
---|
414 | @Override
|
---|
415 | public File getDefaultCacheDirectory() {
|
---|
416 | return new File(getSystemProperty("user.home")+"/Library/Caches",
|
---|
417 | Preferences.getJOSMDirectoryBaseName());
|
---|
418 | }
|
---|
419 |
|
---|
420 | @Override
|
---|
421 | public File getDefaultPrefDirectory() {
|
---|
422 | return new File(getSystemProperty("user.home")+"/Library/Preferences",
|
---|
423 | Preferences.getJOSMDirectoryBaseName());
|
---|
424 | }
|
---|
425 |
|
---|
426 | @Override
|
---|
427 | public File getDefaultUserDataDirectory() {
|
---|
428 | return new File(getSystemProperty("user.home")+"/Library",
|
---|
429 | Preferences.getJOSMDirectoryBaseName());
|
---|
430 | }
|
---|
431 |
|
---|
432 | @Override
|
---|
433 | public X509Certificate getX509Certificate(NativeCertAmend certAmend)
|
---|
434 | throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
|
---|
435 | for (String macAlias : certAmend.getNativeAliases()) {
|
---|
436 | try {
|
---|
437 | // Get platform certificate in PEM format
|
---|
438 | String pem = Utils.execOutput(Arrays.asList("security", "find-certificate",
|
---|
439 | "-c", macAlias, "-p", "/System/Library/Keychains/SystemRootCertificates.keychain"));
|
---|
440 | Logging.debug(pem);
|
---|
441 | return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(
|
---|
442 | new ByteArrayInputStream(pem.getBytes(StandardCharsets.UTF_8)));
|
---|
443 | } catch (ExecutionException | InterruptedException | IllegalArgumentException | CertificateException e) {
|
---|
444 | Logging.debug(e);
|
---|
445 | }
|
---|
446 | }
|
---|
447 | return null;
|
---|
448 | }
|
---|
449 | }
|
---|