diff --git a/src/org/openstreetmap/josm/Main.java b/src/org/openstreetmap/josm/Main.java
index ac883f4..19fce6a 100644
--- a/src/org/openstreetmap/josm/Main.java
+++ b/src/org/openstreetmap/josm/Main.java
@@ -8,8 +8,6 @@ import java.awt.Component;
 import java.awt.GridBagConstraints;
 import java.awt.GridBagLayout;
 import java.awt.Window;
-import java.awt.event.ComponentEvent;
-import java.awt.event.ComponentListener;
 import java.awt.event.KeyEvent;
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
@@ -46,7 +44,6 @@ import java.util.logging.Logger;
 import javax.swing.Action;
 import javax.swing.InputMap;
 import javax.swing.JComponent;
-import javax.swing.JFrame;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JTextArea;
@@ -120,7 +117,6 @@ import org.openstreetmap.josm.tools.PlatformHookUnixoid;
 import org.openstreetmap.josm.tools.PlatformHookWindows;
 import org.openstreetmap.josm.tools.Shortcut;
 import org.openstreetmap.josm.tools.Utils;
-import org.openstreetmap.josm.tools.WindowGeometry;
 
 /**
  * Abstract class holding various static global variables and methods used in large parts of JOSM application.
@@ -562,10 +558,18 @@ public abstract class Main {
     }
 
     /**
-     * Constructs new {@code Main} object. A lot of global variables are initialized here.
+     * Constructs new {@code Main} object.
+     * @see #initalize()
      */
     public Main() {
         main = this;
+    }
+
+    /**
+     * Initialize the main object. A lot of global variables are initialized here.
+     * @since xxx
+     */
+    public void initalize() {
         isOpenjdk = System.getProperty("java.vm.name").toUpperCase(Locale.ENGLISH).indexOf("OPENJDK") != -1;
         fileWatcher.start();
 
@@ -580,9 +584,7 @@ public abstract class Main {
 
             @Override
             public void initialize() {
-                contentPanePrivate.add(panel, BorderLayout.CENTER);
-                panel.add(gettingStarted, BorderLayout.CENTER);
-                menu = new MainMenu();
+                initializeMainWindow();
             }
         }.call();
 
@@ -714,6 +716,14 @@ public abstract class Main {
         }.call();
     }
 
+    /**
+     * Called once at startup to initialize the main window content.
+     * Should set {@link #menu}
+     */
+    protected void initializeMainWindow() {
+        // can be implementd by subclasses
+    }
+
     private abstract static class InitializationTask implements Callable<Void> {
 
         private final String name;
@@ -936,9 +946,6 @@ public abstract class Main {
      */
     public static final JPanel panel = new JPanel(new BorderLayout());
 
-    protected static volatile WindowGeometry geometry;
-    protected static int windowState = JFrame.NORMAL;
-
     private final CommandQueueListener redoUndoListener = new CommandQueueListener() {
         @Override
         public void commandChanged(final int queueSize, final int redoSize) {
@@ -1015,9 +1022,6 @@ public abstract class Main {
             CoordinateFormat.setCoordinateFormat(CoordinateFormat.DECIMAL_DEGREES);
         }
 
-        geometry = WindowGeometry.mainWindow("gui.geometry",
-            args.containsKey(Option.GEOMETRY) ? args.get(Option.GEOMETRY).iterator().next() : null,
-            !args.containsKey(Option.NO_MAXIMIZE) && Main.pref.getBoolean("gui.maximized", false));
     }
 
     protected static void postConstructorProcessCmdLine(Map<Option, Collection<String>> args) {
@@ -1106,30 +1110,7 @@ public abstract class Main {
      */
     public static boolean exitJosm(boolean exit, int exitCode) {
         if (Main.saveUnsavedModifications()) {
-            worker.shutdown();
-            ImageProvider.shutdown(false);
-            JCSCacheManager.shutdown();
-            if (geometry != null) {
-                geometry.remember("gui.geometry");
-            }
-            if (map != null) {
-                map.rememberToggleDialogWidth();
-            }
-            pref.put("gui.maximized", (windowState & JFrame.MAXIMIZED_BOTH) != 0);
-            // Remove all layers because somebody may rely on layerRemoved events (like AutosaveTask)
-            if (Main.isDisplayingMapView()) {
-                Collection<Layer> layers = new ArrayList<>(getLayerManager().getLayers());
-                for (Layer l: layers) {
-                    Main.main.removeLayer(l);
-                }
-            }
-            try {
-                pref.saveDefaults();
-            } catch (IOException ex) {
-                Main.warn(tr("Failed to save default preferences."));
-            }
-            worker.shutdownNow();
-            ImageProvider.shutdown(true);
+            Main.main.shutdown();
 
             if (exit) {
                 System.exit(exitCode);
@@ -1139,6 +1120,29 @@ public abstract class Main {
         return false;
     }
 
+    protected void shutdown() {
+        worker.shutdown();
+        ImageProvider.shutdown(false);
+        JCSCacheManager.shutdown();
+        if (map != null) {
+            map.rememberToggleDialogWidth();
+        }
+        // Remove all layers because somebody may rely on layerRemoved events (like AutosaveTask)
+        if (Main.isDisplayingMapView()) {
+            Collection<Layer> layers = new ArrayList<>(getLayerManager().getLayers());
+            for (Layer l: layers) {
+                Main.main.removeLayer(l);
+            }
+        }
+        try {
+            pref.saveDefaults();
+        } catch (IOException ex) {
+            Main.warn(tr("Failed to save default preferences."));
+        }
+        worker.shutdownNow();
+        ImageProvider.shutdown(true);
+    }
+
     /**
      * The type of a command line parameter, to be used in switch statements.
      * @see #paramType
@@ -1288,49 +1292,6 @@ public abstract class Main {
         }
     }
 
-    private static class WindowPositionSizeListener extends WindowAdapter implements ComponentListener {
-        @Override
-        public void windowStateChanged(WindowEvent e) {
-            Main.windowState = e.getNewState();
-        }
-
-        @Override
-        public void componentHidden(ComponentEvent e) {
-            // Do nothing
-        }
-
-        @Override
-        public void componentMoved(ComponentEvent e) {
-            handleComponentEvent(e);
-        }
-
-        @Override
-        public void componentResized(ComponentEvent e) {
-            handleComponentEvent(e);
-        }
-
-        @Override
-        public void componentShown(ComponentEvent e) {
-            // Do nothing
-        }
-
-        private static void handleComponentEvent(ComponentEvent e) {
-            Component c = e.getComponent();
-            if (c instanceof JFrame && c.isVisible()) {
-                if (Main.windowState == JFrame.NORMAL) {
-                    Main.geometry = new WindowGeometry((JFrame) c);
-                } else {
-                    Main.geometry.fixScreen((JFrame) c);
-                }
-            }
-        }
-    }
-
-    protected static void addListener() {
-        parent.addComponentListener(new WindowPositionSizeListener());
-        ((JFrame) parent).addWindowStateListener(new WindowPositionSizeListener());
-    }
-
     /**
      * Determines if JOSM currently runs with Java 8 or later.
      * @return {@code true} if the current JVM is at least Java 8, {@code false} otherwise
diff --git a/src/org/openstreetmap/josm/gui/MainApplication.java b/src/org/openstreetmap/josm/gui/MainApplication.java
index 400c83f..1861960 100644
--- a/src/org/openstreetmap/josm/gui/MainApplication.java
+++ b/src/org/openstreetmap/josm/gui/MainApplication.java
@@ -5,10 +5,6 @@ import static org.openstreetmap.josm.tools.I18n.tr;
 import static org.openstreetmap.josm.tools.I18n.trn;
 
 import java.awt.Dimension;
-import java.awt.Image;
-import java.awt.Toolkit;
-import java.awt.event.WindowAdapter;
-import java.awt.event.WindowEvent;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
@@ -32,7 +28,6 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.EnumMap;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -40,7 +35,6 @@ import java.util.Set;
 import java.util.TreeSet;
 import java.util.concurrent.Callable;
 
-import javax.swing.JFrame;
 import javax.swing.JOptionPane;
 import javax.swing.RepaintManager;
 import javax.swing.SwingUtilities;
@@ -69,10 +63,10 @@ import org.openstreetmap.josm.plugins.PluginInformation;
 import org.openstreetmap.josm.tools.FontsManager;
 import org.openstreetmap.josm.tools.HttpClient;
 import org.openstreetmap.josm.tools.I18n;
-import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.OsmUrlToBounds;
 import org.openstreetmap.josm.tools.PlatformHookWindows;
 import org.openstreetmap.josm.tools.Utils;
+import org.openstreetmap.josm.tools.WindowGeometry;
 import org.openstreetmap.josm.tools.bugreport.BugReportExceptionHandler;
 
 import gnu.getopt.Getopt;
@@ -85,38 +79,40 @@ import gnu.getopt.LongOpt;
  */
 public class MainApplication extends Main {
 
+    private MainFrame mainFrame;
+
     /**
-     * Constructs a new {@code MainApplication}.
+     * Constructs a new {@code MainApplication} without a window.
      */
     public MainApplication() {
-       // Allow subclassing (see JOSM.java)
+        // Allow subclassing (see JOSM.java)
+        this(null);
     }
 
     /**
      * Constructs a main frame, ready sized and operating. Does not display the frame.
      * @param mainFrame The main JFrame of the application
      */
-    public MainApplication(JFrame mainFrame) {
-        addListener();
-        mainFrame.setContentPane(contentPanePrivate);
-        mainFrame.setJMenuBar(menu);
-        geometry.applySafe(mainFrame);
-        List<Image> l = new LinkedList<>();
-        l.add(ImageProvider.get("logo_16x16x32").getImage());
-        l.add(ImageProvider.get("logo_16x16x8").getImage());
-        l.add(ImageProvider.get("logo_32x32x32").getImage());
-        l.add(ImageProvider.get("logo_32x32x8").getImage());
-        l.add(ImageProvider.get("logo_48x48x32").getImage());
-        l.add(ImageProvider.get("logo_48x48x8").getImage());
-        l.add(ImageProvider.get("logo").getImage());
-        mainFrame.setIconImages(l);
-        mainFrame.addWindowListener(new WindowAdapter() {
-            @Override
-            public void windowClosing(final WindowEvent arg0) {
-                Main.exitJosm(true, 0);
-            }
-        });
-        mainFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+    public MainApplication(MainFrame mainFrame) {
+        this.mainFrame = mainFrame;
+    }
+
+    @Override
+    protected void initializeMainWindow() {
+        if (mainFrame != null) {
+            mainFrame.initialize();
+
+            menu = mainFrame.getMenu();
+        } else {
+            // required for running some tests.
+            menu = new MainMenu();
+        }
+    }
+
+    @Override
+    protected void shutdown() {
+        mainFrame.storeState();
+        super.shutdown();
     }
 
     /**
@@ -396,7 +392,10 @@ public class MainApplication extends Main {
 
         I18n.setupLanguageFonts();
 
-        final JFrame mainFrame = new JFrame(tr("Java OpenStreetMap Editor"));
+        WindowGeometry geometry = WindowGeometry.mainWindow("gui.geometry",
+                args.containsKey(Option.GEOMETRY) ? args.get(Option.GEOMETRY).iterator().next() : null,
+                !args.containsKey(Option.NO_MAXIMIZE) && Main.pref.getBoolean("gui.maximized", false));
+        final MainFrame mainFrame = new MainFrame(contentPanePrivate, geometry);
         Main.parent = mainFrame;
 
         if (args.containsKey(Option.LOAD_PREFERENCES)) {
@@ -463,6 +462,7 @@ public class MainApplication extends Main {
 
         monitor.indeterminateSubTask(tr("Creating main GUI"));
         final Main main = new MainApplication(mainFrame);
+        main.initalize();
 
         if (!skipLoadingPlugins) {
             loadLatePlugins(splash, monitor, pluginsToLoad);
@@ -482,12 +482,7 @@ public class MainApplication extends Main {
 
         boolean maximized = Main.pref.getBoolean("gui.maximized", false);
         if ((!args.containsKey(Option.NO_MAXIMIZE) && maximized) || args.containsKey(Option.MAXIMIZE)) {
-            if (Toolkit.getDefaultToolkit().isFrameStateSupported(JFrame.MAXIMIZED_BOTH)) {
-                Main.windowState = JFrame.MAXIMIZED_BOTH;
-                mainFrame.setExtendedState(Main.windowState);
-            } else {
-                Main.debug("Main window: maximizing not supported");
-            }
+            mainFrame.setMaximized(true);
         }
         if (main.menu.fullscreenToggleAction != null) {
             main.menu.fullscreenToggleAction.initial();
diff --git a/src/org/openstreetmap/josm/gui/MainFrame.java b/src/org/openstreetmap/josm/gui/MainFrame.java
new file mode 100644
index 0000000..9593097
--- /dev/null
+++ b/src/org/openstreetmap/josm/gui/MainFrame.java
@@ -0,0 +1,247 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Image;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.layer.LayerManager.LayerAddEvent;
+import org.openstreetmap.josm.gui.layer.LayerManager.LayerChangeListener;
+import org.openstreetmap.josm.gui.layer.LayerManager.LayerOrderChangeEvent;
+import org.openstreetmap.josm.gui.layer.LayerManager.LayerRemoveEvent;
+import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeEvent;
+import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer.LayerStateChangeListener;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.WindowGeometry;
+
+/**
+ * This is the JOSM main window. It updates it's title.
+ * @author Michael Zangl
+ * @since xxx
+ */
+public class MainFrame extends JFrame {
+    protected transient WindowGeometry geometry;
+    protected int windowState = JFrame.NORMAL;
+    private MainMenu menu;
+
+    private final transient LayerStateChangeListener updateTitleOnLayerStateChange = new LayerStateChangeListener() {
+        @Override
+        public void uploadDiscouragedChanged(OsmDataLayer layer, boolean newValue) {
+            onLayerChange(layer);
+        }
+    };
+
+    private final transient PropertyChangeListener updateTitleOnSaveChange = new PropertyChangeListener() {
+
+        @Override
+        public void propertyChange(PropertyChangeEvent evt) {
+            if (evt.getPropertyName().equals(OsmDataLayer.REQUIRES_SAVE_TO_DISK_PROP)
+                    || evt.getPropertyName().equals(OsmDataLayer.REQUIRES_UPLOAD_TO_SERVER_PROP)) {
+                OsmDataLayer layer = (OsmDataLayer) evt.getSource();
+                onLayerChange(layer);
+            }
+        }
+    };
+
+    /**
+     * Create a new main window.
+     */
+    public MainFrame() {
+        this(new JPanel(), new WindowGeometry(new Rectangle(10, 10, 500, 500)));
+    }
+
+    /**
+     * Create a new main window.
+     * @param contentPanePrivate The content
+     * @param geometry The inital geometry to use.
+     */
+    public MainFrame(Container contentPanePrivate, WindowGeometry geometry) {
+        super();
+        this.geometry = geometry;
+        setContentPane(contentPanePrivate);
+    }
+
+    /**
+     * Initializes the content of the window and get the current status panel.
+     */
+    public void initialize() {
+        menu = new MainMenu();
+        addComponentListener(new WindowPositionSizeListener());
+        addWindowStateListener(new WindowPositionSizeListener());
+
+        setJMenuBar(menu);
+        geometry.applySafe(this);
+        List<Image> l = new LinkedList<>();
+        l.add(ImageProvider.get("logo_16x16x32").getImage());
+        l.add(ImageProvider.get("logo_16x16x8").getImage());
+        l.add(ImageProvider.get("logo_32x32x32").getImage());
+        l.add(ImageProvider.get("logo_32x32x8").getImage());
+        l.add(ImageProvider.get("logo_48x48x32").getImage());
+        l.add(ImageProvider.get("logo_48x48x8").getImage());
+        l.add(ImageProvider.get("logo").getImage());
+        setIconImages(l);
+        addWindowListener(new WindowAdapter() {
+            @Override
+            public void windowClosing(final WindowEvent arg0) {
+                Main.exitJosm(true, 0);
+            }
+        });
+        setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+
+        // This listener is never removed, since the main frame exists forever.
+        Main.getLayerManager().addActiveLayerChangeListener(new ActiveLayerChangeListener() {
+            @Override
+            public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) {
+                refreshTitle();
+            }
+        }, false);
+        Main.getLayerManager().addLayerChangeListener(new ManageLayerListeners(), true);
+
+        refreshTitle();
+
+        getContentPane().add(Main.panel, BorderLayout.CENTER);
+        Main.panel.add(Main.main.gettingStarted, BorderLayout.CENTER);
+        menu.initialize();
+    }
+
+    /**
+     * Stores the current state of the main frame.
+     */
+    public void storeState() {
+        if (geometry != null) {
+            geometry.remember("gui.geometry");
+        }
+        Main.pref.put("gui.maximized", (windowState & JFrame.MAXIMIZED_BOTH) != 0);
+    }
+
+    /**
+     * Gets the main menu used for this window.
+     * @return The main menu.
+     */
+    public MainMenu getMenu() {
+        if (menu == null) {
+            throw new IllegalStateException("Not initialized.");
+        }
+        return menu;
+    }
+
+    /**
+     * Sets this frame to be maximized.
+     * @param maximized <code>true</code> if the window should be maximized.
+     */
+    public void setMaximized(boolean maximized) {
+        if (maximized) {
+            if (Toolkit.getDefaultToolkit().isFrameStateSupported(JFrame.MAXIMIZED_BOTH)) {
+                windowState = JFrame.MAXIMIZED_BOTH;
+                setExtendedState(windowState);
+            } else {
+                Main.debug("Main window: maximizing not supported");
+            }
+        } else {
+            throw new UnsupportedOperationException("Unimplemented.");
+        }
+    }
+
+    /**
+     * Update the title of the window to reflect the current content.
+     */
+    public void refreshTitle() {
+        OsmDataLayer editLayer = Main.getLayerManager().getEditLayer();
+        boolean dirty = editLayer != null && (editLayer.requiresSaveToFile()
+                || (editLayer.requiresUploadToServer() && !editLayer.isUploadDiscouraged()));
+        setTitle((dirty ? "* " : "") + tr("Java OpenStreetMap Editor"));
+        getRootPane().putClientProperty("Window.documentModified", dirty);
+    }
+
+    private void onLayerChange(OsmDataLayer layer) {
+        if (layer == Main.getLayerManager().getEditLayer()) {
+            refreshTitle();
+        }
+    }
+
+    /**
+     * Manages the layer listeners, adds them to every layer.
+     */
+    private final class ManageLayerListeners implements LayerChangeListener {
+        @Override
+        public void layerAdded(LayerAddEvent e) {
+            if (e.getAddedLayer() instanceof OsmDataLayer) {
+                OsmDataLayer osmDataLayer = (OsmDataLayer) e.getAddedLayer();
+                osmDataLayer.addLayerStateChangeListener(updateTitleOnLayerStateChange);
+            }
+            e.getAddedLayer().addPropertyChangeListener(updateTitleOnSaveChange);
+        }
+
+        @Override
+        public void layerRemoving(LayerRemoveEvent e) {
+            if (e.getRemovedLayer() instanceof OsmDataLayer) {
+                OsmDataLayer osmDataLayer = (OsmDataLayer) e.getRemovedLayer();
+                osmDataLayer.removeLayerStateChangeListener(updateTitleOnLayerStateChange);
+            }
+            e.getRemovedLayer().removePropertyChangeListener(updateTitleOnSaveChange);
+        }
+
+        @Override
+        public void layerOrderChanged(LayerOrderChangeEvent e) {
+            // not used
+        }
+    }
+
+    private class WindowPositionSizeListener extends WindowAdapter implements ComponentListener {
+        @Override
+        public void windowStateChanged(WindowEvent e) {
+            windowState = e.getNewState();
+        }
+
+        @Override
+        public void componentHidden(ComponentEvent e) {
+            // Do nothing
+        }
+
+        @Override
+        public void componentMoved(ComponentEvent e) {
+            handleComponentEvent(e);
+        }
+
+        @Override
+        public void componentResized(ComponentEvent e) {
+            handleComponentEvent(e);
+        }
+
+        @Override
+        public void componentShown(ComponentEvent e) {
+            // Do nothing
+        }
+
+        private void handleComponentEvent(ComponentEvent e) {
+            Component c = e.getComponent();
+            if (c instanceof JFrame && c.isVisible()) {
+                if (windowState == JFrame.NORMAL) {
+                    geometry = new WindowGeometry((JFrame) c);
+                } else {
+                    geometry.fixScreen((JFrame) c);
+                }
+            }
+        }
+    }
+
+}
diff --git a/src/org/openstreetmap/josm/gui/MainMenu.java b/src/org/openstreetmap/josm/gui/MainMenu.java
index 15115e1..5b02ec9 100644
--- a/src/org/openstreetmap/josm/gui/MainMenu.java
+++ b/src/org/openstreetmap/josm/gui/MainMenu.java
@@ -632,9 +632,9 @@ public class MainMenu extends JMenuBar {
     }
 
     /**
-     * Constructs a new {@code MainMenu}.
+     * Initialize the main menu.
      */
-    public MainMenu() {
+    public void initialize() {
         moreToolsMenu.setVisible(false);
         dataMenu.setVisible(false);
         gpsMenu.setVisible(false);
diff --git a/src/org/openstreetmap/josm/gui/MapView.java b/src/org/openstreetmap/josm/gui/MapView.java
index d32dc94..d2859f7 100644
--- a/src/org/openstreetmap/josm/gui/MapView.java
+++ b/src/org/openstreetmap/josm/gui/MapView.java
@@ -34,7 +34,6 @@ import javax.swing.AbstractButton;
 import javax.swing.ActionMap;
 import javax.swing.InputMap;
 import javax.swing.JComponent;
-import javax.swing.JFrame;
 import javax.swing.JPanel;
 
 import org.openstreetmap.josm.Main;
@@ -90,7 +89,7 @@ import org.openstreetmap.josm.tools.bugreport.BugReportExceptionHandler;
  * @author imi
  */
 public class MapView extends NavigatableComponent
-implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.LayerStateChangeListener,
+implements PropertyChangeListener, PreferenceChangedListener,
 LayerManager.LayerChangeListener, MainLayerManager.ActiveLayerChangeListener {
     /**
      * Interface to notify listeners of a layer change.
@@ -578,11 +577,6 @@ LayerManager.LayerChangeListener, MainLayerManager.ActiveLayerChangeListener {
             playHeadMarker = PlayHeadMarker.create();
         }
 
-        boolean isOsmDataLayer = layer instanceof OsmDataLayer;
-        if (isOsmDataLayer) {
-            ((OsmDataLayer) layer).addLayerStateChangeListener(this);
-        }
-
         layer.addPropertyChangeListener(this);
         Main.addProjectionChangeListener(layer);
         invalidatedListener.addTo(layer);
@@ -665,9 +659,6 @@ LayerManager.LayerChangeListener, MainLayerManager.ActiveLayerChangeListener {
     @Override
     public void layerRemoving(LayerRemoveEvent e) {
         Layer layer = e.getRemovedLayer();
-        if (layer instanceof OsmDataLayer) {
-            ((OsmDataLayer) layer).removeLayerPropertyChangeListener(this);
-        }
 
         Main.removeProjectionChangeListener(layer);
         layer.removePropertyChangeListener(this);
@@ -1072,7 +1063,6 @@ LayerManager.LayerChangeListener, MainLayerManager.ActiveLayerChangeListener {
             });
         }
         AudioPlayer.reset();
-        refreshTitle();
         repaint();
     }
 
@@ -1155,26 +1145,18 @@ LayerManager.LayerChangeListener, MainLayerManager.ActiveLayerChangeListener {
                 changedLayer = l;
                 repaint();
             }
-        } else if (evt.getPropertyName().equals(OsmDataLayer.REQUIRES_SAVE_TO_DISK_PROP)
-                || evt.getPropertyName().equals(OsmDataLayer.REQUIRES_UPLOAD_TO_SERVER_PROP)) {
-            OsmDataLayer layer = (OsmDataLayer) evt.getSource();
-            if (layer == getEditLayer()) {
-                refreshTitle();
-            }
         }
     }
 
     /**
      * Sets the title of the JOSM main window, adding a star if there are dirty layers.
      * @see Main#parent
+     * @deprecated Replaced by {@link MainFrame#refreshTitle()}. The {@link MainFrame} should handle this by itself.
      */
+    @Deprecated
     protected void refreshTitle() {
         if (Main.parent != null) {
-            OsmDataLayer editLayer = layerManager.getEditLayer();
-            boolean dirty = editLayer != null &&
-                    (editLayer.requiresSaveToFile() || (editLayer.requiresUploadToServer() && !editLayer.isUploadDiscouraged()));
-            ((JFrame) Main.parent).setTitle((dirty ? "* " : "") + tr("Java OpenStreetMap Editor"));
-            ((JFrame) Main.parent).getRootPane().putClientProperty("Window.documentModified", dirty);
+            ((MainFrame) Main.parent).refreshTitle();
         }
     }
 
@@ -1207,13 +1189,6 @@ LayerManager.LayerChangeListener, MainLayerManager.ActiveLayerChangeListener {
         }
     }
 
-    @Override
-    public void uploadDiscouragedChanged(OsmDataLayer layer, boolean newValue) {
-        if (layer == layerManager.getEditLayer()) {
-            refreshTitle();
-        }
-    }
-
     /**
      * Get a string representation of all layers suitable for the {@code source} changeset tag.
      * @return A String of sources separated by ';'
diff --git a/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java b/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
index 6cd3c50..624c16c 100644
--- a/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
+++ b/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
@@ -268,12 +268,24 @@ public class OsmDataLayer extends AbstractModifiableLayer implements Listener, S
     }
 
     /**
-     * Removes a layer property change listener
+     * Removes a layer state change listener
      *
      * @param listener the listener. Ignored if null or already registered.
      * @since 5519
+     * @deprecated Method name contains a typo, use {@link #removeLayerStateChangeListener(LayerStateChangeListener)}.
      */
+    @Deprecated
     public void removeLayerPropertyChangeListener(LayerStateChangeListener listener) {
+        removeLayerStateChangeListener(listener);
+    }
+
+    /**
+     * Removes a layer state change listener
+     *
+     * @param listener the listener. Ignored if null or already registered.
+     * @since xxx
+     */
+    public void removeLayerStateChangeListener(LayerStateChangeListener listener) {
         layerStateChangeListeners.remove(listener);
     }
 
diff --git a/test/unit/org/openstreetmap/josm/JOSMFixture.java b/test/unit/org/openstreetmap/josm/JOSMFixture.java
index 21ec5c7..66db5e5 100644
--- a/test/unit/org/openstreetmap/josm/JOSMFixture.java
+++ b/test/unit/org/openstreetmap/josm/JOSMFixture.java
@@ -119,7 +119,7 @@ public class JOSMFixture {
                 Main.toolbar = new ToolbarPreferences();
             }
             if (Main.main == null) {
-                new MainApplication();
+                new MainApplication().initalize();
             }
             if (Main.map == null) {
                 Main.main.createMapFrame(null, null);
diff --git a/test/unit/org/openstreetmap/josm/MainTest.java b/test/unit/org/openstreetmap/josm/MainTest.java
index 3e6f015..ca80f24 100644
--- a/test/unit/org/openstreetmap/josm/MainTest.java
+++ b/test/unit/org/openstreetmap/josm/MainTest.java
@@ -6,15 +6,12 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
-import java.awt.Dimension;
-import java.awt.Point;
 import java.util.Collection;
 
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.openstreetmap.josm.Main.DownloadParamType;
 import org.openstreetmap.josm.gui.MainApplication;
-import org.openstreetmap.josm.tools.WindowGeometry;
 
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 
@@ -51,7 +48,7 @@ public class MainTest {
     public void testPreConstructorInit() {
         Main.preConstructorInit(MainApplication.buildCommandLineArgumentMap(new String[0]));
         Main.preConstructorInit(MainApplication.buildCommandLineArgumentMap(new String[]{"--geometry=400x300+10+5", "--no-maximize"}));
-        assertEquals(new WindowGeometry(new Point(10, 5), new Dimension(400, 300)), Main.geometry);
+        //assertEquals(new WindowGeometry(new Point(10, 5), new Dimension(400, 300)), Main.geometry);
     }
 
     /**
