Index: trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetCacheManager.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetCacheManager.java	(revision 9915)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetCacheManager.java	(revision 9916)
@@ -9,4 +9,6 @@
 import java.awt.Dimension;
 import java.awt.FlowLayout;
+import java.awt.GraphicsEnvironment;
+import java.awt.Window;
 import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
@@ -48,4 +50,5 @@
 import org.openstreetmap.josm.gui.help.HelpUtil;
 import org.openstreetmap.josm.gui.io.CloseChangesetTask;
+import org.openstreetmap.josm.gui.util.GuiHelper;
 import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
 import org.openstreetmap.josm.io.ChangesetQuery;
@@ -60,5 +63,5 @@
  * downloading, querying, closing changesets, in addition to removing changesets from
  * the local cache.
- *
+ * @since 2689
  */
 public class ChangesetCacheManager extends JFrame {
@@ -86,6 +89,5 @@
 
     /**
-     * Hides and destroys the unique instance of the changeset cache
-     * manager.
+     * Hides and destroys the unique instance of the changeset cache manager.
      *
      */
@@ -109,15 +111,11 @@
 
     /**
-     * Creates the various models required
-     */
-    protected void buildModel() {
+     * Creates the various models required.
+     * @return the changeset cache model
+     */
+    static ChangesetCacheManagerModel buildModel() {
         DefaultListSelectionModel selectionModel = new DefaultListSelectionModel();
         selectionModel.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
-        model = new ChangesetCacheManagerModel(selectionModel);
-
-        actRemoveFromCacheAction = new RemoveFromCacheAction();
-        actCloseSelectedChangesetsAction = new CloseSelectedChangesetsAction();
-        actDownloadSelectedChangesets = new DownloadSelectedChangesetsAction();
-        actDownloadSelectedContent = new DownloadSelectedChangesetContentAction();
+        return new ChangesetCacheManagerModel(selectionModel);
     }
 
@@ -127,5 +125,5 @@
      * @return the toolbar panel
      */
-    protected JPanel buildToolbarPanel() {
+    static JPanel buildToolbarPanel() {
         JPanel pnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
 
@@ -143,5 +141,5 @@
      * @return the button row pane
      */
-    protected JPanel buildButtonPanel() {
+    static JPanel buildButtonPanel() {
         JPanel pnl = new JPanel(new FlowLayout(FlowLayout.CENTER));
 
@@ -150,9 +148,5 @@
 
         //-- help action
-        pnl.add(new SideButton(
-                new ContextSensitiveHelpAction(
-                        HelpUtil.ht("/Dialog/ChangesetManager"))
-        )
-        );
+        pnl.add(new SideButton(new ContextSensitiveHelpAction(HelpUtil.ht("/Dialog/ChangesetManager"))));
 
         return pnl;
@@ -266,6 +260,6 @@
         tblChangesets.addMouseListener(new MouseEventHandler());
         tblChangesets.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "showDetails");
-        tblChangesets.getActionMap().put("showDetails", new ShowDetailAction());
-        model.getSelectionModel().addListSelectionListener(new ChangesetDetailViewSynchronizer());
+        tblChangesets.getActionMap().put("showDetails", new ShowDetailAction(model));
+        model.getSelectionModel().addListSelectionListener(new ChangesetDetailViewSynchronizer(model));
 
         // activate DEL on the table
@@ -285,5 +279,10 @@
         cp.setLayout(new BorderLayout());
 
-        buildModel();
+        model = buildModel();
+        actRemoveFromCacheAction = new RemoveFromCacheAction(model);
+        actCloseSelectedChangesetsAction = new CloseSelectedChangesetsAction(model);
+        actDownloadSelectedChangesets = new DownloadSelectedChangesetsAction(model);
+        actDownloadSelectedContent = new DownloadSelectedChangesetContentAction(model);
+
         cp.add(buildToolbarPanel(), BorderLayout.NORTH);
         cp.add(buildContentPanel(), BorderLayout.CENTER);
@@ -340,5 +339,5 @@
 
         @Override
-        public void windowActivated(WindowEvent arg0) {
+        public void windowActivated(WindowEvent e) {
             if (needsSplitPaneAdjustment) {
                 spContent.setDividerLocation(0.5);
@@ -363,5 +362,5 @@
 
         @Override
-        public void actionPerformed(ActionEvent arg0) {
+        public void actionPerformed(ActionEvent e) {
             cancelAndClose();
         }
@@ -371,5 +370,6 @@
      * The action to query and download changesets
      */
-    class QueryAction extends AbstractAction {
+    static class QueryAction extends AbstractAction {
+
         QueryAction() {
             putValue(NAME, tr("Query"));
@@ -381,17 +381,20 @@
         @Override
         public void actionPerformed(ActionEvent evt) {
-            ChangesetQueryDialog dialog = new ChangesetQueryDialog(ChangesetCacheManager.this);
-            dialog.initForUserInput();
-            dialog.setVisible(true);
-            if (dialog.isCanceled())
-                return;
-
-            try {
-                ChangesetQuery query = dialog.getChangesetQuery();
-                if (query == null) return;
-                ChangesetQueryTask task = new ChangesetQueryTask(ChangesetCacheManager.this, query);
-                ChangesetCacheManager.getInstance().runDownloadTask(task);
-            } catch (IllegalStateException e) {
-                JOptionPane.showMessageDialog(ChangesetCacheManager.this, e.getMessage(), tr("Error"), JOptionPane.ERROR_MESSAGE);
+            Window parent = GuiHelper.getWindowAncestorFor(evt);
+            if (!GraphicsEnvironment.isHeadless()) {
+                ChangesetQueryDialog dialog = new ChangesetQueryDialog(parent);
+                dialog.initForUserInput();
+                dialog.setVisible(true);
+                if (dialog.isCanceled())
+                    return;
+
+                try {
+                    ChangesetQuery query = dialog.getChangesetQuery();
+                    if (query != null) {
+                        ChangesetCacheManager.getInstance().runDownloadTask(new ChangesetQueryTask(parent, query));
+                    }
+                } catch (IllegalStateException e) {
+                    JOptionPane.showMessageDialog(parent, e.getMessage(), tr("Error"), JOptionPane.ERROR_MESSAGE);
+                }
             }
         }
@@ -402,16 +405,18 @@
      *
      */
-    class RemoveFromCacheAction extends AbstractAction implements ListSelectionListener {
-        RemoveFromCacheAction() {
+    static class RemoveFromCacheAction extends AbstractAction implements ListSelectionListener {
+        private final ChangesetCacheManagerModel model;
+
+        RemoveFromCacheAction(ChangesetCacheManagerModel model) {
             putValue(NAME, tr("Remove from cache"));
             putValue(SMALL_ICON, ImageProvider.get("dialogs", "delete"));
             putValue(SHORT_DESCRIPTION, tr("Remove the selected changesets from the local cache"));
+            this.model = model;
             updateEnabledState();
         }
 
         @Override
-        public void actionPerformed(ActionEvent arg0) {
-            List<Changeset> selected = model.getSelectedChangesets();
-            ChangesetCache.getInstance().remove(selected);
+        public void actionPerformed(ActionEvent e) {
+            ChangesetCache.getInstance().remove(model.getSelectedChangesets());
         }
 
@@ -430,16 +435,18 @@
      *
      */
-    class CloseSelectedChangesetsAction extends AbstractAction implements ListSelectionListener {
-        CloseSelectedChangesetsAction() {
+    static class CloseSelectedChangesetsAction extends AbstractAction implements ListSelectionListener {
+        private final ChangesetCacheManagerModel model;
+
+        CloseSelectedChangesetsAction(ChangesetCacheManagerModel model) {
             putValue(NAME, tr("Close"));
             putValue(SMALL_ICON, ImageProvider.get("closechangeset"));
             putValue(SHORT_DESCRIPTION, tr("Close the selected changesets"));
+            this.model = model;
             updateEnabledState();
         }
 
         @Override
-        public void actionPerformed(ActionEvent arg0) {
-            List<Changeset> selected = model.getSelectedChangesets();
-            Main.worker.submit(new CloseChangesetTask(selected));
+        public void actionPerformed(ActionEvent e) {
+            Main.worker.submit(new CloseChangesetTask(model.getSelectedChangesets()));
         }
 
@@ -472,17 +479,21 @@
      *
      */
-    class DownloadSelectedChangesetsAction extends AbstractAction implements ListSelectionListener {
-        DownloadSelectedChangesetsAction() {
+    static class DownloadSelectedChangesetsAction extends AbstractAction implements ListSelectionListener {
+        private final ChangesetCacheManagerModel model;
+
+        DownloadSelectedChangesetsAction(ChangesetCacheManagerModel model) {
             putValue(NAME, tr("Update changeset"));
             putValue(SMALL_ICON, ImageProvider.get("dialogs/changeset", "updatechangeset"));
             putValue(SHORT_DESCRIPTION, tr("Updates the selected changesets with current data from the OSM server"));
+            this.model = model;
             updateEnabledState();
         }
 
         @Override
-        public void actionPerformed(ActionEvent arg0) {
-            List<Changeset> selected = model.getSelectedChangesets();
-            ChangesetHeaderDownloadTask task = ChangesetHeaderDownloadTask.buildTaskForChangesets(ChangesetCacheManager.this, selected);
-            ChangesetCacheManager.getInstance().runDownloadTask(task);
+        public void actionPerformed(ActionEvent e) {
+            if (!GraphicsEnvironment.isHeadless()) {
+                ChangesetCacheManager.getInstance().runDownloadTask(
+                        ChangesetHeaderDownloadTask.buildTaskForChangesets(GuiHelper.getWindowAncestorFor(e), model.getSelectedChangesets()));
+            }
         }
 
@@ -501,16 +512,21 @@
      *
      */
-    class DownloadSelectedChangesetContentAction extends AbstractAction implements ListSelectionListener {
-        DownloadSelectedChangesetContentAction() {
+    static class DownloadSelectedChangesetContentAction extends AbstractAction implements ListSelectionListener {
+        private final ChangesetCacheManagerModel model;
+
+        DownloadSelectedChangesetContentAction(ChangesetCacheManagerModel model) {
             putValue(NAME, tr("Download changeset content"));
             putValue(SMALL_ICON, DOWNLOAD_CONTENT_ICON);
             putValue(SHORT_DESCRIPTION, tr("Download the content of the selected changesets from the server"));
+            this.model = model;
             updateEnabledState();
         }
 
         @Override
-        public void actionPerformed(ActionEvent arg0) {
-            ChangesetContentDownloadTask task = new ChangesetContentDownloadTask(ChangesetCacheManager.this, model.getSelectedChangesetIds());
-            ChangesetCacheManager.getInstance().runDownloadTask(task);
+        public void actionPerformed(ActionEvent e) {
+            if (!GraphicsEnvironment.isHeadless()) {
+                ChangesetCacheManager.getInstance().runDownloadTask(
+                        new ChangesetContentDownloadTask(GuiHelper.getWindowAncestorFor(e), model.getSelectedChangesetIds()));
+            }
         }
 
@@ -525,19 +541,25 @@
     }
 
-    class ShowDetailAction extends AbstractAction {
-
-        public void showDetails() {
+    static class ShowDetailAction extends AbstractAction {
+        private final ChangesetCacheManagerModel model;
+
+        ShowDetailAction(ChangesetCacheManagerModel model) {
+            this.model = model;
+        }
+
+        protected void showDetails() {
             List<Changeset> selected = model.getSelectedChangesets();
-            if (selected.size() != 1) return;
-            model.setChangesetInDetailView(selected.get(0));
-        }
-
-        @Override
-        public void actionPerformed(ActionEvent arg0) {
+            if (selected.size() == 1) {
+                model.setChangesetInDetailView(selected.get(0));
+            }
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent e) {
             showDetails();
         }
     }
 
-    class DownloadMyChangesets extends AbstractAction {
+    static class DownloadMyChangesets extends AbstractAction {
         DownloadMyChangesets() {
             putValue(NAME, tr("My changesets"));
@@ -547,7 +569,7 @@
         }
 
-        protected void alertAnonymousUser() {
+        protected void alertAnonymousUser(Component parent) {
             HelpAwareOptionPane.showOptionDialog(
-                    ChangesetCacheManager.this,
+                    parent,
                     tr("<html>JOSM is currently running with an anonymous user. It cannot download<br>"
                             + "your changesets from the OSM server unless you enter your OSM user name<br>"
@@ -561,8 +583,9 @@
 
         @Override
-        public void actionPerformed(ActionEvent arg0) {
+        public void actionPerformed(ActionEvent e) {
+            Window parent = GuiHelper.getWindowAncestorFor(e);
             JosmUserIdentityManager im = JosmUserIdentityManager.getInstance();
             if (im.isAnonymous()) {
-                alertAnonymousUser();
+                alertAnonymousUser(parent);
                 return;
             }
@@ -573,6 +596,7 @@
                 query = query.forUser(im.getUserName());
             }
-            ChangesetQueryTask task = new ChangesetQueryTask(ChangesetCacheManager.this, query);
-            ChangesetCacheManager.getInstance().runDownloadTask(task);
+            if (!GraphicsEnvironment.isHeadless()) {
+                ChangesetCacheManager.getInstance().runDownloadTask(new ChangesetQueryTask(parent, query));
+            }
         }
     }
@@ -587,5 +611,5 @@
         public void mouseClicked(MouseEvent evt) {
             if (isDoubleClick(evt)) {
-                new ShowDetailAction().showDetails();
+                new ShowDetailAction(model).showDetails();
             }
         }
@@ -601,5 +625,11 @@
     }
 
-    class ChangesetDetailViewSynchronizer implements ListSelectionListener {
+    static class ChangesetDetailViewSynchronizer implements ListSelectionListener {
+        private final ChangesetCacheManagerModel model;
+
+        ChangesetDetailViewSynchronizer(ChangesetCacheManagerModel model) {
+            this.model = model;
+        }
+
         @Override
         public void valueChanged(ListSelectionEvent e) {
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/query/ChangesetQueryDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/query/ChangesetQueryDialog.java	(revision 9915)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/query/ChangesetQueryDialog.java	(revision 9916)
@@ -6,8 +6,7 @@
 import java.awt.BorderLayout;
 import java.awt.Container;
-import java.awt.Dialog;
 import java.awt.Dimension;
 import java.awt.FlowLayout;
-import java.awt.Frame;
+import java.awt.Window;
 import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
@@ -95,10 +94,5 @@
     }
 
-    public ChangesetQueryDialog(Dialog parent) {
-        super(parent, ModalityType.DOCUMENT_MODAL);
-        build();
-    }
-
-    public ChangesetQueryDialog(Frame parent) {
+    public ChangesetQueryDialog(Window parent) {
         super(parent, ModalityType.DOCUMENT_MODAL);
         build();
Index: trunk/src/org/openstreetmap/josm/gui/util/GuiHelper.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/util/GuiHelper.java	(revision 9915)
+++ trunk/src/org/openstreetmap/josm/gui/util/GuiHelper.java	(revision 9916)
@@ -27,4 +27,5 @@
 import java.lang.reflect.InvocationTargetException;
 import java.util.Enumeration;
+import java.util.EventObject;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
@@ -463,3 +464,14 @@
         return GraphicsEnvironment.isHeadless() ? null : Toolkit.getDefaultToolkit().getSystemSelection();
     }
+
+    /**
+     * Returns the first <code>Window</code> ancestor of event source, or
+     * {@code null} if event source is not a component contained inside a <code>Window</code>.
+     * @param e event object
+     * @return a Window, or {@code null}
+     * @since 9916
+     */
+    public static Window getWindowAncestorFor(EventObject e) {
+        return e != null && e.getSource() instanceof Component ? SwingUtilities.getWindowAncestor((Component) e.getSource()) : null;
+    }
 }
Index: trunk/src/org/openstreetmap/josm/tools/Utils.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/Utils.java	(revision 9915)
+++ trunk/src/org/openstreetmap/josm/tools/Utils.java	(revision 9916)
@@ -8,4 +8,5 @@
 import java.awt.Color;
 import java.awt.Font;
+import java.awt.HeadlessException;
 import java.awt.Toolkit;
 import java.awt.datatransfer.Clipboard;
@@ -635,10 +636,10 @@
      */
     public static String getClipboardContent() {
-        Transferable t = getTransferableContent(Toolkit.getDefaultToolkit().getSystemClipboard());
         try {
+            Transferable t = getTransferableContent(Toolkit.getDefaultToolkit().getSystemClipboard());
             if (t != null && t.isDataFlavorSupported(DataFlavor.stringFlavor)) {
                 return (String) t.getTransferData(DataFlavor.stringFlavor);
             }
-        } catch (UnsupportedFlavorException | IOException ex) {
+        } catch (UnsupportedFlavorException | IOException | HeadlessException ex) {
             Main.error(ex);
             return null;
