Index: /trunk/src/org/openstreetmap/josm/gui/MainApplication.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/MainApplication.java	(revision 10199)
+++ /trunk/src/org/openstreetmap/josm/gui/MainApplication.java	(revision 10200)
@@ -237,5 +237,10 @@
     }
 
-    private static Map<Option, Collection<String>> buildCommandLineArgumentMap(String[] args) {
+    /**
+     * Builds the command-line argument map.
+     * @param args command-line arguments array
+     * @return command-line argument map
+     */
+    public static Map<Option, Collection<String>> buildCommandLineArgumentMap(String[] args) {
 
         List<LongOpt> los = new ArrayList<>();
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/Cascade.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/Cascade.java	(revision 10199)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/Cascade.java	(revision 10200)
@@ -211,5 +211,5 @@
         TreeSet<String> props = new TreeSet<>();
         for (Entry<String, Object> entry : prop.entrySet()) {
-            StringBuilder sb = new StringBuilder(entry.getKey()+':');
+            StringBuilder sb = new StringBuilder(entry.getKey()).append(':');
             Object val = entry.getValue();
             if (val instanceof float[]) {
Index: /trunk/src/org/openstreetmap/josm/tools/WindowGeometry.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/WindowGeometry.java	(revision 10199)
+++ /trunk/src/org/openstreetmap/josm/tools/WindowGeometry.java	(revision 10200)
@@ -24,7 +24,73 @@
  * This is a helper class for persisting the geometry of a JOSM window to the preference store
  * and for restoring it from the preference store.
- *
+ * @since 2008
  */
 public class WindowGeometry {
+
+    /** the top left point */
+    private Point topLeft;
+    /** the size */
+    private Dimension extent;
+
+    /**
+     * Creates a window geometry from a position and dimension
+     *
+     * @param topLeft the top left point
+     * @param extent the extent
+     */
+    public WindowGeometry(Point topLeft, Dimension extent) {
+        this.topLeft = topLeft;
+        this.extent = extent;
+    }
+
+    /**
+     * Creates a window geometry from a rectangle
+     *
+     * @param rect the position
+     */
+    public WindowGeometry(Rectangle rect) {
+        this(rect.getLocation(), rect.getSize());
+    }
+
+    /**
+     * Creates a window geometry from the position and the size of a window.
+     *
+     * @param window the window
+     */
+    public WindowGeometry(Window window)  {
+        this(window.getLocationOnScreen(), window.getSize());
+    }
+
+    /**
+     * Creates a window geometry from the values kept in the preference store under the
+     * key <code>preferenceKey</code>
+     *
+     * @param preferenceKey the preference key
+     * @throws WindowGeometryException if no such key exist or if the preference value has
+     * an illegal format
+     */
+    public WindowGeometry(String preferenceKey) throws WindowGeometryException {
+        initFromPreferences(preferenceKey);
+    }
+
+    /**
+     * Creates a window geometry from the values kept in the preference store under the
+     * key <code>preferenceKey</code>. Falls back to the <code>defaultGeometry</code> if
+     * something goes wrong.
+     *
+     * @param preferenceKey the preference key
+     * @param defaultGeometry the default geometry
+     *
+     */
+    public WindowGeometry(String preferenceKey, WindowGeometry defaultGeometry) {
+        try {
+            initFromPreferences(preferenceKey);
+        } catch (WindowGeometryException e) {
+            if (Main.isDebugEnabled()) {
+                Main.debug(e.getMessage());
+            }
+            initFromWindowGeometry(defaultGeometry);
+        }
+    }
 
     /**
@@ -85,45 +151,11 @@
      */
     public static class WindowGeometryException extends Exception {
-        public WindowGeometryException(String message, Throwable cause) {
+        WindowGeometryException(String message, Throwable cause) {
             super(message, cause);
         }
 
-        public WindowGeometryException(String message) {
+        WindowGeometryException(String message) {
             super(message);
         }
-    }
-
-    /** the top left point */
-    private Point topLeft;
-    /** the size */
-    private Dimension extent;
-
-    /**
-     * Creates a window geometry from a position and dimension
-     *
-     * @param topLeft the top left point
-     * @param extent the extent
-     */
-    public WindowGeometry(Point topLeft, Dimension extent) {
-        this.topLeft = topLeft;
-        this.extent = extent;
-    }
-
-    /**
-     * Creates a window geometry from a rectangle
-     *
-     * @param rect the position
-     */
-    public WindowGeometry(Rectangle rect) {
-        this(rect.getLocation(), rect.getSize());
-    }
-
-    /**
-     * Creates a window geometry from the position and the size of a window.
-     *
-     * @param window the window
-     */
-    public WindowGeometry(Window window)  {
-        this(window.getLocationOnScreen(), window.getSize());
     }
 
@@ -162,5 +194,5 @@
                        "Cannot restore window geometry from preferences.",
                             preferenceKey, field, v), e);
-        } catch (Exception e) {
+        } catch (RuntimeException e) {
             throw new WindowGeometryException(
                     tr("Failed to parse field ''{1}'' in preference with key ''{0}''. Exception was: {2}. " +
@@ -195,5 +227,6 @@
                 int w = Integer.parseInt(m.group(1));
                 int h = Integer.parseInt(m.group(2));
-                int x = screenDimension.x, y = screenDimension.y;
+                int x = screenDimension.x;
+                int y = screenDimension.y;
                 if (m.group(3) != null) {
                     x = Integer.parseInt(m.group(5));
@@ -224,33 +257,4 @@
 
     /**
-     * Creates a window geometry from the values kept in the preference store under the
-     * key <code>preferenceKey</code>
-     *
-     * @param preferenceKey the preference key
-     * @throws WindowGeometryException if no such key exist or if the preference value has
-     * an illegal format
-     */
-    public WindowGeometry(String preferenceKey) throws WindowGeometryException {
-        initFromPreferences(preferenceKey);
-    }
-
-    /**
-     * Creates a window geometry from the values kept in the preference store under the
-     * key <code>preferenceKey</code>. Falls back to the <code>defaultGeometry</code> if
-     * something goes wrong.
-     *
-     * @param preferenceKey the preference key
-     * @param defaultGeometry the default geometry
-     *
-     */
-    public WindowGeometry(String preferenceKey, WindowGeometry defaultGeometry) {
-        try {
-            initFromPreferences(preferenceKey);
-        } catch (WindowGeometryException e) {
-            initFromWindowGeometry(defaultGeometry);
-        }
-    }
-
-    /**
      * Remembers a window geometry under a specific preference key
      *
@@ -369,7 +373,9 @@
         Rectangle virtualBounds = new Rectangle();
         GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
-        for (GraphicsDevice gd : ge.getScreenDevices()) {
-            if (gd.getType() == GraphicsDevice.TYPE_RASTER_SCREEN) {
-                virtualBounds = virtualBounds.union(gd.getDefaultConfiguration().getBounds());
+        if (!GraphicsEnvironment.isHeadless()) {
+            for (GraphicsDevice gd : ge.getScreenDevices()) {
+                if (gd.getType() == GraphicsDevice.TYPE_RASTER_SCREEN) {
+                    virtualBounds = virtualBounds.union(gd.getDefaultConfiguration().getBounds());
+                }
             }
         }
@@ -424,32 +430,33 @@
      */
     private static Rectangle getScreenInfo(Rectangle g) {
-        GraphicsDevice[] gs = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
-        int intersect = 0;
         Rectangle bounds = null;
-        for (GraphicsDevice gd : gs) {
-            if (gd.getType() == GraphicsDevice.TYPE_RASTER_SCREEN) {
-                Rectangle b = gd.getDefaultConfiguration().getBounds();
-                if (b.height > 0 && b.width / b.height >= 3) /* multiscreen with wrong definition */ {
-                    b.width /= 2;
-                    Rectangle is = b.intersection(g);
-                    int s = is.width * is.height;
-                    if (bounds == null || intersect < s) {
-                        intersect = s;
-                        bounds = b;
-                    }
-                    b = new Rectangle(b);
-                    b.x += b.width;
-                    is = b.intersection(g);
-                    s = is.width * is.height;
-                    if (intersect < s) {
-                        intersect = s;
-                        bounds = b;
-                    }
-                } else {
-                    Rectangle is = b.intersection(g);
-                    int s = is.width * is.height;
-                    if (bounds == null || intersect < s) {
-                        intersect = s;
-                        bounds = b;
+        if (!GraphicsEnvironment.isHeadless()) {
+            int intersect = 0;
+            for (GraphicsDevice gd : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()) {
+                if (gd.getType() == GraphicsDevice.TYPE_RASTER_SCREEN) {
+                    Rectangle b = gd.getDefaultConfiguration().getBounds();
+                    if (b.height > 0 && b.width / b.height >= 3) /* multiscreen with wrong definition */ {
+                        b.width /= 2;
+                        Rectangle is = b.intersection(g);
+                        int s = is.width * is.height;
+                        if (bounds == null || intersect < s) {
+                            intersect = s;
+                            bounds = b;
+                        }
+                        b = new Rectangle(b);
+                        b.x += b.width;
+                        is = b.intersection(g);
+                        s = is.width * is.height;
+                        if (intersect < s) {
+                            intersect = s;
+                            bounds = b;
+                        }
+                    } else {
+                        Rectangle is = b.intersection(g);
+                        int s = is.width * is.height;
+                        if (bounds == null || intersect < s) {
+                            intersect = s;
+                            bounds = b;
+                        }
                     }
                 }
@@ -468,4 +475,33 @@
 
     @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((extent == null) ? 0 : extent.hashCode());
+        result = prime * result + ((topLeft == null) ? 0 : topLeft.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null || getClass() != obj.getClass())
+            return false;
+        WindowGeometry other = (WindowGeometry) obj;
+        if (extent == null) {
+            if (other.extent != null)
+                return false;
+        } else if (!extent.equals(other.extent))
+            return false;
+        if (topLeft == null) {
+            if (other.topLeft != null)
+                return false;
+        } else if (!topLeft.equals(other.topLeft))
+            return false;
+        return true;
+    }
+
+    @Override
     public String toString() {
         return "WindowGeometry{topLeft="+topLeft+",extent="+extent+'}';
Index: /trunk/test/unit/org/openstreetmap/josm/MainTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/MainTest.java	(revision 10199)
+++ /trunk/test/unit/org/openstreetmap/josm/MainTest.java	(revision 10200)
@@ -7,8 +7,13 @@
 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;
 
 /**
@@ -16,4 +21,12 @@
  */
 public class MainTest {
+
+    /**
+     * Setup test.
+     */
+    @BeforeClass
+    public static void setUp() {
+        JOSMFixture.createUnitTestFixture().init();
+    }
 
     /**
@@ -28,4 +41,14 @@
         assertEquals(DownloadParamType.httpUrl, DownloadParamType.paramType("http://somewhere.com/data.osm"));
         assertEquals(DownloadParamType.httpUrl, DownloadParamType.paramType("https://somewhere.com/data.osm"));
+    }
+
+    /**
+     * Unit test of {@code Main#preConstructorInit}.
+     */
+    @Test
+    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);
     }
 
Index: /trunk/test/unit/org/openstreetmap/josm/tools/WindowGeometryTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/tools/WindowGeometryTest.java	(revision 10200)
+++ /trunk/test/unit/org/openstreetmap/josm/tools/WindowGeometryTest.java	(revision 10200)
@@ -0,0 +1,151 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.tools;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.awt.Dimension;
+import java.awt.Point;
+import java.awt.Rectangle;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openstreetmap.josm.JOSMFixture;
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.tools.WindowGeometry.WindowGeometryException;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+import nl.jqno.equalsverifier.Warning;
+
+/**
+ * Unit tests of {@link WindowGeometry} class.
+ */
+public class WindowGeometryTest {
+
+    /**
+     * Setup test.
+     */
+    @BeforeClass
+    public static void setUp() {
+        JOSMFixture.createUnitTestFixture().init();
+    }
+
+    /**
+     * Test of {@link WindowGeometry#centerInWindow} method.
+     */
+    @Test
+    public void testCenterInWindow() {
+        assertNotNull(WindowGeometry.centerInWindow(null, null));
+        assertNotNull(WindowGeometry.centerInWindow(new JPanel(), null));
+    }
+
+    /**
+     * Test of {@link WindowGeometry#centerOnScreen} method.
+     */
+    @Test
+    public void testCenterOnScreen() {
+        Dimension dim = new Dimension(200, 100);
+        assertEquals(new WindowGeometry(new Point(0, 0), dim), WindowGeometry.centerOnScreen(dim));
+        assertEquals(new WindowGeometry(new Point(300, 250), dim), WindowGeometry.centerOnScreen(dim, null));
+    }
+
+    /**
+     * Test of {@link WindowGeometry.WindowGeometryException} class.
+     * @throws WindowGeometryException always
+     */
+    @Test(expected = WindowGeometryException.class)
+    public void testWindowGeometryException1() throws WindowGeometryException {
+        Main.pref.put("test", null);
+        new WindowGeometry("test");
+    }
+
+    /**
+     * Test of {@link WindowGeometry.WindowGeometryException} class.
+     * @throws WindowGeometryException always
+     */
+    @Test(expected = WindowGeometryException.class)
+    public void testWindowGeometryException2() throws WindowGeometryException {
+        Main.pref.put("test", "");
+        new WindowGeometry("test");
+    }
+
+    /**
+     * Test of {@link WindowGeometry.WindowGeometryException} class.
+     * @throws WindowGeometryException always
+     */
+    @Test(expected = WindowGeometryException.class)
+    public void testWindowGeometryException3() throws WindowGeometryException {
+        Main.pref.put("test", "x=not_a_number");
+        new WindowGeometry("test");
+    }
+
+    /**
+     * Test of {@link WindowGeometry.WindowGeometryException} class.
+     * @throws WindowGeometryException always
+     */
+    @Test(expected = WindowGeometryException.class)
+    public void testWindowGeometryException4() throws WindowGeometryException {
+        Main.pref.put("test", "wrong_pattern");
+        new WindowGeometry("test");
+    }
+
+    /**
+     * Test of {@link WindowGeometry.WindowGeometryException} class.
+     * @throws WindowGeometryException never
+     */
+    @Test
+    public void testWindowGeometryException5() throws WindowGeometryException {
+        Main.pref.put("test", "x=15,y=55,width=200,height=100");
+        assertNotNull(new WindowGeometry("test"));
+    }
+
+    /**
+     * Test of {@link WindowGeometry#isBugInMaximumWindowBounds} method.
+     */
+    @Test
+    public void testIsBugInMaximumWindowBounds() {
+        assertFalse(WindowGeometry.isBugInMaximumWindowBounds(new Rectangle(10, 10)));
+        assertTrue(WindowGeometry.isBugInMaximumWindowBounds(new Rectangle(10, 0)));
+        assertTrue(WindowGeometry.isBugInMaximumWindowBounds(new Rectangle(0, 10)));
+    }
+
+    /**
+     * Test of {@link WindowGeometry#getVirtualScreenBounds} method.
+     */
+    @Test
+    public void testGetVirtualScreenBounds() {
+        assertNotNull(WindowGeometry.getVirtualScreenBounds());
+    }
+
+    /**
+     * Test of {@link WindowGeometry#getMaxDimensionOnScreen} method.
+     */
+    @Test
+    public void testGetMaxDimensionOnScreen() {
+        assertNotNull(WindowGeometry.getMaxDimensionOnScreen(new JLabel()));
+    }
+
+    /**
+     * Test of {@link WindowGeometry#toString} method.
+     */
+    @Test
+    public void testToString() {
+        assertEquals("WindowGeometry{topLeft=java.awt.Point[x=0,y=0],extent=java.awt.Dimension[width=0,height=0]}",
+                new WindowGeometry(new Rectangle()).toString());
+    }
+
+    /**
+     * Unit test of methods {@link WindowGeometry#equals} and {@link WindowGeometry#hashCode}.
+     */
+    @Test
+    public void equalsContract() {
+        EqualsVerifier.forClass(WindowGeometry.class).usingGetClass()
+            .suppress(Warning.NONFINAL_FIELDS)
+            .verify();
+    }
+}
