Index: trunk/src/org/openstreetmap/josm/Main.java
===================================================================
--- trunk/src/org/openstreetmap/josm/Main.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/Main.java	(revision 14138)
@@ -41,8 +41,6 @@
 import org.openstreetmap.josm.tools.JosmRuntimeException;
 import org.openstreetmap.josm.tools.Logging;
-import org.openstreetmap.josm.tools.Platform;
 import org.openstreetmap.josm.tools.PlatformHook;
-import org.openstreetmap.josm.tools.PlatformHookOsx;
-import org.openstreetmap.josm.tools.PlatformHookWindows;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.Utils;
 import org.openstreetmap.josm.tools.bugreport.BugReport;
@@ -88,6 +86,8 @@
      * So if you need to hook into those early ones, split your class and send the one with the early hooks
      * to the JOSM team for inclusion.
-     */
-    public static volatile PlatformHook platform;
+     * @deprecated Use {@link PlatformManager#getPlatform}
+     */
+    @Deprecated
+    public static final PlatformHook platform = PlatformManager.getPlatform();
 
     /**
@@ -291,7 +291,9 @@
      * Identifies the current operating system family and initializes the platform hook accordingly.
      * @since 1849
-     */
+     * @deprecated Not needed anymore
+     */
+    @Deprecated
     public static void determinePlatformHook() {
-        platform = Platform.determinePlatform().accept(PlatformHook.CONSTRUCT_FROM_PLATFORM);
+        // Do nothing
     }
 
@@ -461,7 +463,9 @@
      * @return {@code true} if we are currently running on OSX
      * @since 6957
-     */
+     * @deprecated Use {@link PlatformManager#isPlatformOsx}
+     */
+    @Deprecated
     public static boolean isPlatformOsx() {
-        return Main.platform instanceof PlatformHookOsx;
+        return PlatformManager.isPlatformOsx();
     }
 
@@ -470,7 +474,9 @@
      * @return {@code true} if we are currently running on Windows
      * @since 7335
-     */
+     * @deprecated Use {@link PlatformManager#isPlatformWindows}
+     */
+    @Deprecated
     public static boolean isPlatformWindows() {
-        return Main.platform instanceof PlatformHookWindows;
+        return PlatformManager.isPlatformWindows();
     }
 
Index: trunk/src/org/openstreetmap/josm/actions/FullscreenToggleAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/FullscreenToggleAction.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/actions/FullscreenToggleAction.java	(revision 14138)
@@ -23,4 +23,5 @@
 import org.openstreetmap.josm.gui.util.GuiHelper;
 import org.openstreetmap.josm.spi.preferences.Config;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -98,5 +99,5 @@
         // screen by default (it's a simulated mode, but should be ok)
         String exclusive = Config.getPref().get("draw.fullscreen.exclusive-mode", "auto");
-        if (("true".equals(exclusive) || ("auto".equals(exclusive) && !Main.isPlatformWindows())) && gd != null) {
+        if (("true".equals(exclusive) || ("auto".equals(exclusive) && !PlatformManager.isPlatformWindows())) && gd != null) {
             gd.setFullScreenWindow(selected ? frame : null);
         }
Index: trunk/src/org/openstreetmap/josm/actions/JosmAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/JosmAction.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/actions/JosmAction.java	(revision 14138)
@@ -38,4 +38,5 @@
 import org.openstreetmap.josm.tools.ImageResource;
 import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -287,5 +288,5 @@
     public final void setTooltip(String tooltip) {
         if (tooltip != null) {
-            putValue(SHORT_DESCRIPTION, Main.platform.makeTooltip(tooltip, sc));
+            putValue(SHORT_DESCRIPTION, PlatformManager.getPlatform().makeTooltip(tooltip, sc));
         }
     }
Index: trunk/src/org/openstreetmap/josm/actions/OpenFileAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/OpenFileAction.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/actions/OpenFileAction.java	(revision 14138)
@@ -45,4 +45,5 @@
 import org.openstreetmap.josm.tools.Logging;
 import org.openstreetmap.josm.tools.MultiMap;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.Shortcut;
 import org.openstreetmap.josm.tools.Utils;
@@ -135,5 +136,5 @@
             for (final File file : files) {
                 if (file.exists()) {
-                    this.files.add(Main.platform.resolveFileLink(file));
+                    this.files.add(PlatformManager.getPlatform().resolveFileLink(file));
                 } else if (file.getParentFile() != null) {
                     // try to guess an extension using the specified fileFilter
Index: trunk/src/org/openstreetmap/josm/actions/RenameLayerAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/RenameLayerAction.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/actions/RenameLayerAction.java	(revision 14138)
@@ -20,4 +20,5 @@
 import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.PlatformManager;
 
 /**
@@ -96,5 +97,5 @@
                 if (!SaveActionBase.confirmOverwrite(newFile))
                     return;
-                if (Main.platform.rename(file, newFile)) {
+                if (PlatformManager.getPlatform().rename(file, newFile)) {
                     layer.setAssociatedFile(newFile);
                     if (!layer.isRenamed()) {
Index: trunk/src/org/openstreetmap/josm/actions/RestartAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/RestartAction.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/actions/RestartAction.java	(revision 14138)
@@ -16,5 +16,4 @@
 import java.util.List;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec;
 import org.openstreetmap.josm.gui.MainApplication;
@@ -24,4 +23,5 @@
 import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
 import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -92,5 +92,5 @@
         final List<String> cmd;
         // special handling for OSX .app package
-        if (Main.isPlatformOsx() && getSystemProperty("java.library.path").contains("/JOSM.app/Contents/MacOS")) {
+        if (PlatformManager.isPlatformOsx() && getSystemProperty("java.library.path").contains("/JOSM.app/Contents/MacOS")) {
             cmd = getAppleCommands();
         } else {
@@ -177,5 +177,5 @@
     private static String getJavaRuntime() throws IOException {
         final String java = getSystemProperty("java.home") + File.separator + "bin" + File.separator +
-                (Main.isPlatformWindows() ? "java.exe" : "java");
+                (PlatformManager.isPlatformWindows() ? "java.exe" : "java");
         if (!new File(java).isFile()) {
             throw new IOException("Unable to find suitable java runtime at "+java);
Index: trunk/src/org/openstreetmap/josm/actions/ShowStatusReportAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/ShowStatusReportAction.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/actions/ShowStatusReportAction.java	(revision 14138)
@@ -43,4 +43,5 @@
 import org.openstreetmap.josm.tools.Logging;
 import org.openstreetmap.josm.tools.PlatformHookUnixoid;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.Shortcut;
 import org.openstreetmap.josm.tools.Utils;
@@ -89,5 +90,5 @@
         text.append(Version.getInstance().getReleaseAttributes())
             .append("\nIdentification: ").append(Version.getInstance().getAgentString());
-        String buildNumber = Main.platform.getOSBuildNumber();
+        String buildNumber = PlatformManager.getPlatform().getOSBuildNumber();
         if (!buildNumber.isEmpty()) {
             text.append("\nOS Build number: ").append(buildNumber);
@@ -119,7 +120,8 @@
             .append((int) maxScreenSize.getHeight()).append('\n');
 
-        if (Main.platform instanceof PlatformHookUnixoid) {
+        if (PlatformManager.isPlatformUnixoid()) {
+            PlatformHookUnixoid platform = (PlatformHookUnixoid) PlatformManager.getPlatform();
             // Add Java package details
-            String packageDetails = ((PlatformHookUnixoid) Main.platform).getJavaPackageDetails();
+            String packageDetails = platform.getJavaPackageDetails();
             if (packageDetails != null) {
                 text.append("Java package: ")
@@ -129,5 +131,5 @@
             // Add WebStart package details if run from JNLP
             if (isRunningJavaWebStart()) {
-                String webStartDetails = ((PlatformHookUnixoid) Main.platform).getWebStartPackageDetails();
+                String webStartDetails = platform.getWebStartPackageDetails();
                 if (webStartDetails != null) {
                     text.append("WebStart package: ")
@@ -137,5 +139,5 @@
             }
             // Add Gnome Atk wrapper details if found
-            String atkWrapperDetails = ((PlatformHookUnixoid) Main.platform).getAtkWrapperPackageDetails();
+            String atkWrapperDetails = platform.getAtkWrapperPackageDetails();
             if (atkWrapperDetails != null) {
                 text.append("Java ATK Wrapper package: ")
@@ -230,5 +232,5 @@
     private static String paramCleanup(String param) {
         final String envJavaHome = getSystemEnv("JAVA_HOME");
-        final String envJavaHomeAlt = Main.isPlatformWindows() ? "%JAVA_HOME%" : "${JAVA_HOME}";
+        final String envJavaHomeAlt = PlatformManager.isPlatformWindows() ? "%JAVA_HOME%" : "${JAVA_HOME}";
         final String propJavaHome = getSystemProperty("java.home");
         final String propJavaHomeAlt = "<java.home>";
@@ -240,5 +242,5 @@
         final String userCacheDirAlt = "<josm.cache>";
         final String userHomeDir = getSystemProperty("user.home");
-        final String userHomeDirAlt = Main.isPlatformWindows() ? "%UserProfile%" : "${HOME}";
+        final String userHomeDirAlt = PlatformManager.isPlatformWindows() ? "%UserProfile%" : "${HOME}";
         final String userName = getSystemProperty("user.name");
         final String userNameAlt = "<user.name>";
Index: trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 14138)
@@ -58,4 +58,5 @@
 import org.openstreetmap.josm.tools.Logging;
 import org.openstreetmap.josm.tools.Pair;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.Shortcut;
 import org.openstreetmap.josm.tools.Utils;
@@ -343,5 +344,5 @@
                 c = "lasso";
             } else {
-                c = "rect" + (shift ? "_add" : (ctrl && !Main.isPlatformOsx() ? "_rm" : ""));
+                c = "rect" + (shift ? "_add" : (ctrl && !PlatformManager.isPlatformOsx() ? "_rm" : ""));
             }
             break;
@@ -446,5 +447,5 @@
         case SELECT:
         default:
-            if (!(ctrl && Main.isPlatformOsx())) {
+            if (!(ctrl && PlatformManager.isPlatformOsx())) {
                 // start working with rectangle or lasso
                 selectionManager.register(mv, lassoMode);
@@ -462,5 +463,5 @@
     public void mouseMoved(MouseEvent e) {
         // Mac OSX simulates with ctrl + mouse 1 the second mouse button hence no dragging events get fired.
-        if (Main.isPlatformOsx() && (mode == Mode.ROTATE || mode == Mode.SCALE)) {
+        if (PlatformManager.isPlatformOsx() && (mode == Mode.ROTATE || mode == Mode.SCALE)) {
             mouseDragged(e);
             return;
@@ -490,5 +491,5 @@
         if (mode == Mode.SELECT) {
             // Unregisters selectionManager if ctrl has been pressed after mouse click on Mac OS X in order to move the map
-            if (ctrl && Main.isPlatformOsx()) {
+            if (ctrl && PlatformManager.isPlatformOsx()) {
                 selectionManager.unregister(mv);
                 // Make sure correct cursor is displayed
Index: trunk/src/org/openstreetmap/josm/data/Preferences.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/Preferences.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/data/Preferences.java	(revision 14138)
@@ -52,4 +52,5 @@
 import org.openstreetmap.josm.tools.ListenerList;
 import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.Utils;
 import org.xml.sax.SAXException;
@@ -280,5 +281,5 @@
         addPossibleResourceDir(locations, getSystemEnv("JOSM_RESOURCES"));
         addPossibleResourceDir(locations, getSystemProperty("josm.resources"));
-        if (Main.isPlatformWindows()) {
+        if (PlatformManager.isPlatformWindows()) {
             String appdata = getSystemEnv("APPDATA");
             if (appdata != null && getSystemEnv("ALLUSERSPROFILE") != null
@@ -521,5 +522,5 @@
             } else if (reset) {
                 File backupFile = new File(prefDir, "preferences.xml.bak");
-                Main.platform.rename(preferenceFile, backupFile);
+                PlatformManager.getPlatform().rename(preferenceFile, backupFile);
                 Logging.warn(tr("Replacing existing preference file ''{0}'' with default preference file.", preferenceFile.getAbsoluteFile()));
                 resetToDefault();
@@ -555,5 +556,5 @@
                 );
             }
-            Main.platform.rename(preferenceFile, backupFile);
+            PlatformManager.getPlatform().rename(preferenceFile, backupFile);
             try {
                 resetToDefault();
Index: trunk/src/org/openstreetmap/josm/data/Version.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/Version.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/data/Version.java	(revision 14138)
@@ -10,7 +10,7 @@
 import java.util.Properties;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.tools.LanguageInfo;
 import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.Utils;
 
@@ -187,6 +187,6 @@
         }
         String result = "JOSM/1.5 ("+ s+' '+LanguageInfo.getJOSMLocaleCode()+')';
-        if (includeOsDetails && Main.platform != null) {
-            result += ' ' + Main.platform.getOSDescription();
+        if (includeOsDetails) {
+            result += ' ' + PlatformManager.getPlatform().getOSDescription();
         }
         return result;
Index: trunk/src/org/openstreetmap/josm/data/preferences/JosmBaseDirectories.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/preferences/JosmBaseDirectories.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/data/preferences/JosmBaseDirectories.java	(revision 14138)
@@ -14,4 +14,5 @@
 import org.openstreetmap.josm.spi.preferences.IBaseDirectories;
 import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.PlatformManager;
 
 /**
@@ -63,5 +64,5 @@
                     preferencesDir = new File(path).getAbsoluteFile();
                 } else {
-                    preferencesDir = Main.platform.getDefaultPrefDirectory();
+                    preferencesDir = PlatformManager.getPlatform().getDefaultPrefDirectory();
                 }
             }
@@ -96,5 +97,5 @@
                     userdataDir = new File(path).getAbsoluteFile();
                 } else {
-                    userdataDir = Main.platform.getDefaultUserDataDirectory();
+                    userdataDir = PlatformManager.getPlatform().getDefaultUserDataDirectory();
                 }
             }
@@ -133,5 +134,5 @@
                         cacheDir = new File(path).getAbsoluteFile();
                     } else {
-                        cacheDir = Main.platform.getDefaultCacheDirectory();
+                        cacheDir = PlatformManager.getPlatform().getDefaultCacheDirectory();
                     }
                 }
Index: trunk/src/org/openstreetmap/josm/gui/MainApplication.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MainApplication.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/gui/MainApplication.java	(revision 14138)
@@ -178,4 +178,5 @@
 import org.openstreetmap.josm.tools.PlatformHook.NativeOsCallback;
 import org.openstreetmap.josm.tools.PlatformHookWindows;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.RightAndLefthandTraffic;
 import org.openstreetmap.josm.tools.Shortcut;
@@ -386,5 +387,5 @@
             StringBuilder content = new StringBuilder(tr("You are running version {0} of Java.",
                     "<b>"+getSystemProperty("java.version")+"</b>")).append("<br><br>");
-            if ("Sun Microsystems Inc.".equals(getSystemProperty("java.vendor")) && !platform.isOpenJDK()) {
+            if ("Sun Microsystems Inc.".equals(getSystemProperty("java.vendor")) && !PlatformManager.getPlatform().isOpenJDK()) {
                 content.append("<b>").append(tr("This version is no longer supported by {0} since {1} and is not recommended for use.",
                         "Oracle", eolDate)).append("</b><br><br>");
@@ -400,5 +401,5 @@
             if (ed.showDialog().getValue() == 2) {
                 try {
-                    platform.openUrl(url);
+                    PlatformManager.getPlatform().openUrl(url);
                 } catch (IOException e) {
                     Logging.warn(e);
@@ -412,5 +413,6 @@
         return Arrays.asList(
             new InitializationTask(tr("Starting file watcher"), FileWatcher.getDefaultInstance()::start),
-            new InitializationTask(tr("Executing platform startup hook"), () -> platform.startupHook(MainApplication::askUpdateJava)),
+            new InitializationTask(tr("Executing platform startup hook"),
+                    () -> PlatformManager.getPlatform().startupHook(MainApplication::askUpdateJava)),
             new InitializationTask(tr("Building main menu"), this::initializeMainWindow),
             new InitializationTask(tr("Updating user interface"), () -> {
@@ -831,9 +833,9 @@
                 align("\t-Djosm.dir.name=JOSM") + tr("Change the JOSM directory name") + "\n\n" +
                 align("\t-Djosm.pref=" + tr("/PATH/TO/JOSM/PREF    ")) + tr("Set the preferences directory") + "\n" +
-                align("\t") + tr("Default: {0}", platform.getDefaultPrefDirectory()) + "\n\n" +
+                align("\t") + tr("Default: {0}", PlatformManager.getPlatform().getDefaultPrefDirectory()) + "\n\n" +
                 align("\t-Djosm.userdata=" + tr("/PATH/TO/JOSM/USERDATA")) + tr("Set the user data directory") + "\n" +
-                align("\t") + tr("Default: {0}", platform.getDefaultUserDataDirectory()) + "\n\n" +
+                align("\t") + tr("Default: {0}", PlatformManager.getPlatform().getDefaultUserDataDirectory()) + "\n\n" +
                 align("\t-Djosm.cache=" + tr("/PATH/TO/JOSM/CACHE   ")) + tr("Set the cache directory") + "\n" +
-                align("\t") + tr("Default: {0}", platform.getDefaultCacheDirectory()) + "\n\n" +
+                align("\t") + tr("Default: {0}", PlatformManager.getPlatform().getDefaultCacheDirectory()) + "\n\n" +
                 align("\t-Djosm.home=" + tr("/PATH/TO/JOSM/HOMEDIR ")) +
                 tr("Set the preferences+data+cache directory (cache directory will be josm.home/cache)")+"\n\n"+
@@ -927,8 +929,7 @@
 
         // initialize the platform hook, and
-        Main.determinePlatformHook();
-        Main.platform.setNativeOsCallback(new DefaultNativeOsCallback());
+        PlatformManager.getPlatform().setNativeOsCallback(new DefaultNativeOsCallback());
         // call the really early hook before we do anything else
-        Main.platform.preStartupHook();
+        PlatformManager.getPlatform().preStartupHook();
 
         Config.setPreferencesInstance(Main.pref);
@@ -978,5 +979,5 @@
         processOffline(args);
 
-        Main.platform.afterPrefStartupHook();
+        PlatformManager.getPlatform().afterPrefStartupHook();
 
         applyWorkarounds();
@@ -1111,5 +1112,5 @@
         SwingUtilities.invokeLater(new GuiFinalizationWorker(args, proxySelector));
 
-        if (Main.isPlatformWindows()) {
+        if (PlatformManager.isPlatformWindows()) {
             try {
                 // Check for insecure certificates to remove.
@@ -1187,5 +1188,5 @@
         // To remove during Java 9 migration
         if (getSystemProperty("os.name").toLowerCase(Locale.ENGLISH).contains("windows 10") &&
-                platform.getDefaultStyle().equals(LafPreference.LAF.get())) {
+                PlatformManager.getPlatform().getDefaultStyle().equals(LafPreference.LAF.get())) {
             try {
                 String build = PlatformHookWindows.getCurrentBuild();
@@ -1229,5 +1230,5 @@
 
     static void setupUIManager() {
-        String defaultlaf = platform.getDefaultStyle();
+        String defaultlaf = PlatformManager.getPlatform().getDefaultStyle();
         String laf = LafPreference.LAF.get();
         try {
Index: trunk/src/org/openstreetmap/josm/gui/MainMenu.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MainMenu.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/gui/MainMenu.java	(revision 14138)
@@ -25,5 +25,4 @@
 import javax.swing.event.MenuListener;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.AboutAction;
 import org.openstreetmap.josm.actions.AddNodeAction;
@@ -125,4 +124,5 @@
 import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetSearchPrimitiveDialog;
 import org.openstreetmap.josm.spi.preferences.Config;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -734,5 +734,5 @@
         viewportFollowToggleAction.addButtonModel(vft.getModel());
 
-        if (Main.platform.canFullscreen()) {
+        if (PlatformManager.getPlatform().canFullscreen()) {
             // -- fullscreen toggle action
             fullscreenToggleAction = new FullscreenToggleAction();
Index: trunk/src/org/openstreetmap/josm/gui/MapMover.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MapMover.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/gui/MapMover.java	(revision 14138)
@@ -17,5 +17,4 @@
 
 import org.openstreetmap.gui.jmapviewer.JMapViewer;
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.mapmode.SelectAction;
 import org.openstreetmap.josm.data.coor.EastNorth;
@@ -28,4 +27,5 @@
 import org.openstreetmap.josm.tools.Destroyable;
 import org.openstreetmap.josm.tools.Pair;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -145,5 +145,5 @@
 
         // see #10592 - Disable these alternate shortcuts on OS X because of conflict with system shortcut
-        if (!Main.isPlatformOsx()) {
+        if (!PlatformManager.isPlatformOsx()) {
             registerActionShortcut(new ZoomerAction(",", "MapMover.Zoomer.in"),
                     Shortcut.registerShortcut("view:zoominalternate", tr("Map: {0}", tr("Zoom In")), KeyEvent.VK_COMMA, Shortcut.CTRL));
@@ -175,5 +175,5 @@
         int offMask = MouseEvent.BUTTON1_DOWN_MASK | MouseEvent.BUTTON2_DOWN_MASK;
         boolean allowMovement = (e.getModifiersEx() & (MouseEvent.BUTTON3_DOWN_MASK | offMask)) == MouseEvent.BUTTON3_DOWN_MASK;
-        if (Main.isPlatformOsx()) {
+        if (PlatformManager.isPlatformOsx()) {
             MapFrame map = MainApplication.getMap();
             int macMouseMask = MouseEvent.CTRL_DOWN_MASK | MouseEvent.BUTTON1_DOWN_MASK;
@@ -207,5 +207,5 @@
         int macMouseMask = MouseEvent.CTRL_DOWN_MASK | MouseEvent.BUTTON1_DOWN_MASK;
         if ((e.getButton() == MouseEvent.BUTTON3 && (e.getModifiersEx() & offMask) == 0) ||
-                (Main.isPlatformOsx() && e.getModifiersEx() == macMouseMask)) {
+                (PlatformManager.isPlatformOsx() && e.getModifiersEx() == macMouseMask)) {
             startMovement(e);
         }
@@ -217,5 +217,5 @@
     @Override
     public void mouseReleased(MouseEvent e) {
-        if (e.getButton() == MouseEvent.BUTTON3 || (Main.isPlatformOsx() && e.getButton() == MouseEvent.BUTTON1)) {
+        if (e.getButton() == MouseEvent.BUTTON3 || (PlatformManager.isPlatformOsx() && e.getButton() == MouseEvent.BUTTON1)) {
             endMovement();
         }
@@ -267,5 +267,5 @@
         // Mac OSX simulates with  ctrl + mouse 1  the second mouse button hence no dragging events get fired.
         // Is only the selected mouse button pressed?
-        if (Main.isPlatformOsx()) {
+        if (PlatformManager.isPlatformOsx()) {
             if (e.getModifiersEx() == MouseEvent.CTRL_DOWN_MASK) {
                 doMoveForDrag(e);
Index: trunk/src/org/openstreetmap/josm/gui/bbox/SlippyMapControler.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/bbox/SlippyMapControler.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/gui/bbox/SlippyMapControler.java	(revision 14138)
@@ -18,5 +18,5 @@
 import javax.swing.KeyStroke;
 
-import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.tools.PlatformManager;
 
 /**
@@ -122,5 +122,5 @@
     @Override
     public void mousePressed(MouseEvent e) {
-        if (e.getButton() == MouseEvent.BUTTON1 && !(Main.isPlatformOsx() && e.getModifiersEx() == MAC_MOUSE_BUTTON3_MASK)) {
+        if (e.getButton() == MouseEvent.BUTTON1 && !(PlatformManager.isPlatformOsx() && e.getModifiersEx() == MAC_MOUSE_BUTTON3_MASK)) {
             iStartSelectionPoint = e.getPoint();
             iEndSelectionPoint = e.getPoint();
@@ -131,5 +131,5 @@
     public void mouseDragged(MouseEvent e) {
         if (iStartSelectionPoint != null && (e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) == MouseEvent.BUTTON1_DOWN_MASK
-                && !(Main.isPlatformOsx() && e.getModifiersEx() == MAC_MOUSE_BUTTON3_MASK)) {
+                && !(PlatformManager.isPlatformOsx() && e.getModifiersEx() == MAC_MOUSE_BUTTON3_MASK)) {
             iEndSelectionPoint = e.getPoint();
             iSlippyMapChooser.setSelection(iStartSelectionPoint, iEndSelectionPoint);
Index: trunk/src/org/openstreetmap/josm/gui/bugreport/JosmUpdatePanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/bugreport/JosmUpdatePanel.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/gui/bugreport/JosmUpdatePanel.java	(revision 14138)
@@ -12,5 +12,4 @@
 import javax.swing.SwingUtilities;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.Version;
 import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
@@ -21,4 +20,5 @@
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.PlatformManager;
 
 /**
@@ -100,5 +100,5 @@
     private static void openJosmUpdateSite() {
         try {
-            Main.platform.openUrl(Config.getUrls().getJOSMWebsite());
+            PlatformManager.getPlatform().openUrl(Config.getUrls().getJOSMWebsite());
         } catch (IOException ex) {
             Logging.log(Logging.LEVEL_WARN, "Unable to access JOSM website:", ex);
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/FilterDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/FilterDialog.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/FilterDialog.java	(revision 14138)
@@ -25,5 +25,4 @@
 import javax.swing.table.TableModel;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.mapmode.MapMode;
 import org.openstreetmap.josm.actions.search.SearchAction;
@@ -50,4 +49,5 @@
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.InputMapUtils;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -103,6 +103,6 @@
 
     private static final String[] COLUMN_TOOLTIPS = {
-            Main.platform.makeTooltip(tr("Enable filter"), ENABLE_FILTER_SHORTCUT),
-            Main.platform.makeTooltip(tr("Hiding filter"), HIDING_FILTER_SHORTCUT),
+            PlatformManager.getPlatform().makeTooltip(tr("Enable filter"), ENABLE_FILTER_SHORTCUT),
+            PlatformManager.getPlatform().makeTooltip(tr("Hiding filter"), HIDING_FILTER_SHORTCUT),
             null,
             tr("Inverse filter"),
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java	(revision 14138)
@@ -42,5 +42,4 @@
 import javax.swing.table.TableModel;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.MergeLayerAction;
 import org.openstreetmap.josm.data.coor.EastNorth;
@@ -83,4 +82,5 @@
 import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
 import org.openstreetmap.josm.tools.InputMapUtils;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -229,6 +229,6 @@
         // Disable some default JTable shortcuts to use JOSM ones (see #5678, #10458)
         for (KeyStroke ks : new KeyStroke[] {
-                KeyStroke.getKeyStroke(KeyEvent.VK_C, Main.platform.getMenuShortcutKeyMaskEx()),
-                KeyStroke.getKeyStroke(KeyEvent.VK_V, Main.platform.getMenuShortcutKeyMaskEx()),
+                KeyStroke.getKeyStroke(KeyEvent.VK_C, PlatformManager.getPlatform().getMenuShortcutKeyMaskEx()),
+                KeyStroke.getKeyStroke(KeyEvent.VK_V, PlatformManager.getPlatform().getMenuShortcutKeyMaskEx()),
                 KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.SHIFT_DOWN_MASK),
                 KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.SHIFT_DOWN_MASK),
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java	(revision 14138)
@@ -33,5 +33,4 @@
 import javax.swing.event.PopupMenuListener;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.ExpertToggleAction;
 import org.openstreetmap.josm.actions.IPrimitiveAction;
@@ -88,4 +87,5 @@
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.InputMapUtils;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.Shortcut;
 import org.openstreetmap.josm.tools.SubclassFilteredCollection;
@@ -202,5 +202,5 @@
         // Do not hide copy action because of default JList override (fix #9815)
         displaylist.getActionMap().put("copy", MainApplication.getMenu().copy);
-        displaylist.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_C, Main.platform.getMenuShortcutKeyMaskEx()), "copy");
+        displaylist.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_C, PlatformManager.getPlatform().getMenuShortcutKeyMaskEx()), "copy");
 
         updateActionsRelationLists();
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/properties/TagEditHelper.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/properties/TagEditHelper.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/properties/TagEditHelper.java	(revision 14138)
@@ -94,4 +94,5 @@
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.Shortcut;
 import org.openstreetmap.josm.tools.Utils;
@@ -817,5 +818,5 @@
         @Override
         public void setContentPane(Container contentPane) {
-            final int commandDownMask = Main.platform.getMenuShortcutKeyMaskEx();
+            final int commandDownMask = PlatformManager.getPlatform().getMenuShortcutKeyMaskEx();
             List<String> lines = new ArrayList<>();
             Shortcut.findShortcut(KeyEvent.VK_1, commandDownMask).ifPresent(sc ->
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DownloadIncompleteMembersAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DownloadIncompleteMembersAction.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/DownloadIncompleteMembersAction.java	(revision 14138)
@@ -8,8 +8,8 @@
 import java.awt.event.KeyEvent;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask;
 import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -31,5 +31,5 @@
             KeyEvent.VK_HOME, Shortcut.ALT);
         sc.setAccelerator(this);
-        putValue(SHORT_DESCRIPTION, Main.platform.makeTooltip(tr("Download all incomplete members"), sc));
+        putValue(SHORT_DESCRIPTION, PlatformManager.getPlatform().makeTooltip(tr("Download all incomplete members"), sc));
         new ImageProvider("dialogs/relation", "downloadincomplete").getResource().attachImageIcon(this, true);
         putValue(NAME, tr("Download members"));
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/MoveDownAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/MoveDownAction.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/MoveDownAction.java	(revision 14138)
@@ -7,6 +7,6 @@
 import java.awt.event.KeyEvent;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -28,5 +28,5 @@
         Shortcut sc = Shortcut.registerShortcut("relationeditor:movedown", tr("Relation Editor: Move Down"), KeyEvent.VK_DOWN, Shortcut.ALT);
         sc.setAccelerator(this);
-        putValue(SHORT_DESCRIPTION, Main.platform.makeTooltip(tr("Move the currently selected members down"), sc));
+        putValue(SHORT_DESCRIPTION, PlatformManager.getPlatform().makeTooltip(tr("Move the currently selected members down"), sc));
         setEnabled(false);
     }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/MoveUpAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/MoveUpAction.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/MoveUpAction.java	(revision 14138)
@@ -7,6 +7,6 @@
 import java.awt.event.KeyEvent;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -28,5 +28,5 @@
         Shortcut sc = Shortcut.registerShortcut("relationeditor:moveup", tr("Relation Editor: Move Up"), KeyEvent.VK_UP, Shortcut.ALT);
         sc.setAccelerator(this);
-        putValue(SHORT_DESCRIPTION, Main.platform.makeTooltip(tr("Move the currently selected members up"), sc));
+        putValue(SHORT_DESCRIPTION, PlatformManager.getPlatform().makeTooltip(tr("Move the currently selected members up"), sc));
         setEnabled(false);
     }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RefreshAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RefreshAction.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RefreshAction.java	(revision 14138)
@@ -19,4 +19,5 @@
 import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
 import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -37,5 +38,5 @@
         Shortcut sc = Shortcut.registerShortcut("relationeditor:refresh", tr("Relation Editor: Refresh"), KeyEvent.CHAR_UNDEFINED, Shortcut.NONE);
         // CHECKSTYLE.ON: LineLength
-        putValue(SHORT_DESCRIPTION, Main.platform.makeTooltip(tr("Refresh relation from data layer"), sc));
+        putValue(SHORT_DESCRIPTION, PlatformManager.getPlatform().makeTooltip(tr("Refresh relation from data layer"), sc));
         new ImageProvider("dialogs/refresh").getResource().attachImageIcon(this, true);
         putValue(NAME, tr("Refresh"));
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RemoveAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RemoveAction.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/RemoveAction.java	(revision 14138)
@@ -7,6 +7,6 @@
 import java.awt.event.KeyEvent;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -29,5 +29,6 @@
         Shortcut sc = Shortcut.registerShortcut("relationeditor:remove", tr("Relation Editor: Remove"), KeyEvent.VK_DELETE, Shortcut.ALT);
         sc.setAccelerator(this);
-        putValue(SHORT_DESCRIPTION, Main.platform.makeTooltip(tr("Remove the currently selected members from this relation"), sc));
+        putValue(SHORT_DESCRIPTION, PlatformManager.getPlatform().makeTooltip(
+                tr("Remove the currently selected members from this relation"), sc));
         setEnabled(false);
     }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SortAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SortAction.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SortAction.java	(revision 14138)
@@ -7,6 +7,6 @@
 import java.awt.event.KeyEvent;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -28,5 +28,5 @@
         Shortcut sc = Shortcut.registerShortcut("relationeditor:sort", tr("Relation Editor: Sort"), KeyEvent.VK_END, Shortcut.ALT);
         sc.setAccelerator(this);
-        putValue(SHORT_DESCRIPTION, Main.platform.makeTooltip(tr("Sort the relation members"), sc));
+        putValue(SHORT_DESCRIPTION, PlatformManager.getPlatform().makeTooltip(tr("Sort the relation members"), sc));
         updateEnabledState();
     }
Index: trunk/src/org/openstreetmap/josm/gui/preferences/ToolbarPreferences.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/ToolbarPreferences.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/ToolbarPreferences.java	(revision 14138)
@@ -77,4 +77,5 @@
 import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
 import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -1260,5 +1261,5 @@
                     tt = tt.substring(6, tt.length()-6);
                 }
-                tt = Main.platform.makeTooltip(tt, sc);
+                tt = PlatformManager.getPlatform().makeTooltip(tt, sc);
             }
         }
Index: trunk/src/org/openstreetmap/josm/gui/preferences/display/LafPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/display/LafPreference.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/display/LafPreference.java	(revision 14138)
@@ -24,5 +24,4 @@
 import javax.swing.UIManager.LookAndFeelInfo;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.ExpertToggleAction;
 import org.openstreetmap.josm.data.preferences.StringProperty;
@@ -42,4 +41,5 @@
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.date.DateUtils;
 
@@ -53,5 +53,5 @@
      * @since 11713
      */
-    public static final StringProperty LAF = new StringProperty("laf", Main.platform.getDefaultStyle());
+    public static final StringProperty LAF = new StringProperty("laf", PlatformManager.getPlatform().getDefaultStyle());
 
     static final class LafListCellRenderer implements ListCellRenderer<LookAndFeelInfo> {
@@ -97,5 +97,5 @@
 
         // let's try to load additional LookAndFeels and put them into the list
-        if (Main.isPlatformOsx()) {
+        if (PlatformManager.isPlatformOsx()) {
             try {
                 Class<?> cquaqua = Class.forName("ch.randelshofer.quaqua.QuaquaLookAndFeel");
Index: trunk/src/org/openstreetmap/josm/gui/preferences/remotecontrol/RemoteControlPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/remotecontrol/RemoteControlPreference.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/remotecontrol/RemoteControlPreference.java	(revision 14138)
@@ -27,5 +27,4 @@
 import javax.swing.JSeparator;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.gui.help.HelpUtil;
 import org.openstreetmap.josm.gui.preferences.DefaultTabPreferenceSetting;
@@ -43,4 +42,5 @@
 import org.openstreetmap.josm.tools.Logging;
 import org.openstreetmap.josm.tools.PlatformHookWindows;
+import org.openstreetmap.josm.tools.PlatformManager;
 
 /**
@@ -114,5 +114,5 @@
 
         // Certificate installation only available on Windows for now, see #10033
-        if (Main.isPlatformWindows()) {
+        if (PlatformManager.isPlatformWindows()) {
             installCertificate = new JButton(tr("Install..."));
             uninstallCertificate = new JButton(tr("Uninstall..."));
Index: trunk/src/org/openstreetmap/josm/gui/widgets/FileChooserManager.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/widgets/FileChooserManager.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/gui/widgets/FileChooserManager.java	(revision 14138)
@@ -16,4 +16,5 @@
 import org.openstreetmap.josm.data.preferences.BooleanProperty;
 import org.openstreetmap.josm.spi.preferences.Config;
+import org.openstreetmap.josm.tools.PlatformManager;
 
 /**
@@ -33,5 +34,5 @@
     public static final BooleanProperty PROP_USE_NATIVE_FILE_DIALOG = new BooleanProperty("use.native.file.dialog",
             // Native dialogs do not support file filters, so do not set them as default, except for OS X where they never worked
-            Main.isPlatformOsx());
+            PlatformManager.isPlatformOsx());
 
     private final boolean open;
Index: trunk/src/org/openstreetmap/josm/gui/widgets/NativeFileChooser.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/widgets/NativeFileChooser.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/gui/widgets/NativeFileChooser.java	(revision 14138)
@@ -14,4 +14,5 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.Utils;
 
@@ -138,5 +139,5 @@
     @Override
     public int showOpenDialog(Component parent) {
-        boolean appleProperty = Main.isPlatformOsx() && selectionMode == JFileChooser.DIRECTORIES_ONLY;
+        boolean appleProperty = PlatformManager.isPlatformOsx() && selectionMode == JFileChooser.DIRECTORIES_ONLY;
         if (appleProperty) {
             Utils.updateSystemProperty("apple.awt.fileDialogForDirectories", "true");
@@ -176,5 +177,5 @@
             // http://stackoverflow.com/questions/1224714/how-can-i-make-a-java-filedialog-accept-directories-as-its-filetype-in-os-x/1224744#1224744
             // CHECKSTYLE.ON: LineLength
-            return Main.isPlatformOsx();
+            return PlatformManager.isPlatformOsx();
         case JFileChooser.FILES_ONLY:
         default:
Index: trunk/src/org/openstreetmap/josm/gui/widgets/TextContextualPopupMenu.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/widgets/TextContextualPopupMenu.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/gui/widgets/TextContextualPopupMenu.java	(revision 14138)
@@ -24,8 +24,8 @@
 import javax.swing.undo.UndoManager;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.PlatformManager;
 
 /**
@@ -95,7 +95,7 @@
                 if (!GraphicsEnvironment.isHeadless()) {
                     component.getInputMap().put(
-                            KeyStroke.getKeyStroke(KeyEvent.VK_Z, Main.platform.getMenuShortcutKeyMaskEx()), undoAction);
+                            KeyStroke.getKeyStroke(KeyEvent.VK_Z, PlatformManager.getPlatform().getMenuShortcutKeyMaskEx()), undoAction);
                     component.getInputMap().put(
-                            KeyStroke.getKeyStroke(KeyEvent.VK_Y, Main.platform.getMenuShortcutKeyMaskEx()), redoAction);
+                            KeyStroke.getKeyStroke(KeyEvent.VK_Y, PlatformManager.getPlatform().getMenuShortcutKeyMaskEx()), redoAction);
                 }
             }
Index: trunk/src/org/openstreetmap/josm/io/CachedFile.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/CachedFile.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/io/CachedFile.java	(revision 14138)
@@ -34,4 +34,5 @@
 import org.openstreetmap.josm.tools.Logging;
 import org.openstreetmap.josm.tools.Pair;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.Utils;
 
@@ -521,5 +522,5 @@
             activeConnection = null;
             localFile = new File(destDir, localPath);
-            if (Main.platform.rename(destDirFile, localFile)) {
+            if (PlatformManager.getPlatform().rename(destDirFile, localFile)) {
                 Config.getPref().putList(prefKey,
                         Arrays.asList(Long.toString(System.currentTimeMillis()), localFile.toString()));
@@ -549,5 +550,5 @@
             // Windows doesn't support paths longer than 260, leave 5 chars as safe buffer, 4 will be used by ".tmp"
             // TODO: what about filename size on other systems? 255?
-            if (directory.length() > 191 && Main.isPlatformWindows()) {
+            if (directory.length() > 191 && PlatformManager.isPlatformWindows()) {
                 // digest length + name prefix == 64
                 // 255 - 64 = 191
Index: trunk/src/org/openstreetmap/josm/io/CertificateAmendment.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/CertificateAmendment.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/io/CertificateAmendment.java	(revision 14138)
@@ -27,7 +27,7 @@
 import javax.net.ssl.TrustManagerFactory;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.Utils;
 
@@ -227,5 +227,5 @@
             // Try to add platform certificates. Do not exit in case of error (embedded certificates may be OK)
             for (NativeCertAmend certAmend : PLATFORM_CERT_AMEND) {
-                X509Certificate cert = Main.platform.getX509Certificate(certAmend);
+                X509Certificate cert = PlatformManager.getPlatform().getX509Certificate(certAmend);
                 if (checkAndAddCertificate(md, cert, certAmend, keyStore)) {
                     certificateAdded = true;
Index: trunk/src/org/openstreetmap/josm/io/remotecontrol/RemoteControlHttpsServer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/remotecontrol/RemoteControlHttpsServer.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/io/remotecontrol/RemoteControlHttpsServer.java	(revision 14138)
@@ -39,8 +39,8 @@
 import javax.net.ssl.TrustManagerFactory;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.preferences.StringProperty;
 import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.PlatformManager;
 
 import sun.security.util.ObjectIdentifier;
@@ -301,5 +301,5 @@
         Enumeration<String> aliases = josmKs.aliases();
         if (aliases.hasMoreElements()) {
-            return Main.platform.setupHttpsCertificate(ENTRY_ALIAS,
+            return PlatformManager.getPlatform().setupHttpsCertificate(ENTRY_ALIAS,
                     new KeyStore.TrustedCertificateEntry(josmKs.getCertificate(aliases.nextElement())));
         }
Index: trunk/src/org/openstreetmap/josm/tools/KeyboardUtils.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/KeyboardUtils.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/tools/KeyboardUtils.java	(revision 14138)
@@ -9,6 +9,4 @@
 import java.util.Locale;
 import java.util.Map;
-
-import org.openstreetmap.josm.Main;
 
 /**
@@ -293,5 +291,5 @@
             // UK Apple, https://en.wikipedia.org/wiki/QWERTY#UK_Apple_keyboard
             // International English Apple, https://en.wikipedia.org/wiki/QWERTY#Apple_International_English_Keyboard
-            if (Main.isPlatformOsx()) {
+            if (PlatformManager.isPlatformOsx()) {
                 result.add('§'); // https://en.wikipedia.org/wiki/Section_sign
             }
Index: trunk/src/org/openstreetmap/josm/tools/OpenBrowser.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/OpenBrowser.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/tools/OpenBrowser.java	(revision 14138)
@@ -25,7 +25,7 @@
 
     private static void displayUrlFallback(URI uri) throws IOException {
-        if (Main.platform == null)
+        if (PlatformManager.getPlatform() == null)
             throw new IllegalStateException(tr("Failed to open URL. There is currently no platform set. Please set a platform first."));
-        Main.platform.openUrl(uri.toString());
+        PlatformManager.getPlatform().openUrl(uri.toString());
     }
 
@@ -45,10 +45,10 @@
         if (Desktop.isDesktopSupported()) {
             try {
-                if (Main.isPlatformWindows()) {
+                if (PlatformManager.isPlatformWindows()) {
                     // Desktop API works fine under Windows, so we don't try any fallback in case of I/O exceptions because it's not API's fault
                     Desktop.getDesktop().browse(uri);
-                } else if (Main.platform instanceof PlatformHookUnixoid || Main.platform instanceof PlatformHookOsx) {
+                } else if (PlatformManager.isPlatformUnixoid() || PlatformManager.isPlatformOsx()) {
                     // see #5629 #5108 #9568
-                    Main.platform.openUrl(uri.toString());
+                    PlatformManager.getPlatform().openUrl(uri.toString());
                 } else {
                     // This is not the case with some Linux environments (see below),
Index: trunk/src/org/openstreetmap/josm/tools/PlatformManager.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/PlatformManager.java	(revision 14138)
+++ trunk/src/org/openstreetmap/josm/tools/PlatformManager.java	(revision 14138)
@@ -0,0 +1,50 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.tools;
+
+/**
+ * Holder for current platform hook.
+ * @since 14138
+ */
+public final class PlatformManager {
+
+    /**
+     * Platform specific code goes in here.
+     */
+    private static final PlatformHook PLATFORM = Platform.determinePlatform().accept(PlatformHook.CONSTRUCT_FROM_PLATFORM);
+
+    private PlatformManager() {
+        // Hide constructor
+    }
+
+    /**
+     * Returns the current platform hook.
+     * @return the current platform hook
+     */
+    public static PlatformHook getPlatform() {
+        return PLATFORM;
+    }
+
+    /**
+     * Determines if we are currently running on macOS.
+     * @return {@code true} if we are currently running on macOS
+     */
+    public static boolean isPlatformOsx() {
+        return PLATFORM instanceof PlatformHookOsx;
+    }
+
+    /**
+     * Determines if we are currently running on an Unix system.
+     * @return {@code true} if we are currently running on an Unix system
+     */
+    public static boolean isPlatformUnixoid() {
+        return PLATFORM instanceof PlatformHookUnixoid;
+    }
+
+    /**
+     * Determines if we are currently running on Windows.
+     * @return {@code true} if we are currently running on Windows
+     */
+    public static boolean isPlatformWindows() {
+        return PLATFORM instanceof PlatformHookWindows;
+    }
+}
Index: trunk/src/org/openstreetmap/josm/tools/Shortcut.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/Shortcut.java	(revision 14137)
+++ trunk/src/org/openstreetmap/josm/tools/Shortcut.java	(revision 14138)
@@ -371,5 +371,5 @@
         if (initdone) return;
         initdone = true;
-        int commandDownMask = Main.platform.getMenuShortcutKeyMaskEx();
+        int commandDownMask = PlatformManager.getPlatform().getMenuShortcutKeyMaskEx();
         groups.put(NONE, -1);
         groups.put(MNEMONIC, KeyEvent.ALT_DOWN_MASK);
@@ -384,5 +384,5 @@
 
         // (1) System reserved shortcuts
-        Main.platform.initSystemShortcuts();
+        PlatformManager.getPlatform().initSystemShortcuts();
         // (2) User defined shortcuts
         Main.pref.getAllPrefixCollectionKeys("shortcut.entry.").stream()
@@ -507,5 +507,5 @@
         } else if (existing.isPresent()) {
             final Shortcut conflict = existing.get();
-            if (Main.isPlatformOsx()) {
+            if (PlatformManager.isPlatformOsx()) {
                 // Try to reassign Meta to Ctrl
                 int newmodifier = findNewOsxModifier(requestedGroup);
