Index: trunk/src/org/openstreetmap/josm/Main.java
===================================================================
--- trunk/src/org/openstreetmap/josm/Main.java	(revision 4717)
+++ trunk/src/org/openstreetmap/josm/Main.java	(revision 4718)
@@ -22,10 +22,8 @@
 import java.util.Collection;
 import java.util.Iterator;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.StringTokenizer;
 import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 import java.util.regex.Matcher;
@@ -41,6 +39,8 @@
 import javax.swing.JTextArea;
 import javax.swing.KeyStroke;
+import javax.swing.RepaintManager;
 import javax.swing.UIManager;
 
+import org.jdesktop.swinghelper.debug.CheckThreadViolationRepaintManager;
 import org.openstreetmap.gui.jmapviewer.FeatureAdapter;
 import org.openstreetmap.josm.actions.JosmAction;
@@ -76,4 +76,6 @@
 import org.openstreetmap.josm.gui.preferences.TaggingPresetPreference;
 import org.openstreetmap.josm.gui.preferences.ToolbarPreferences;
+import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
+import org.openstreetmap.josm.gui.progress.ProgressMonitorExecutor;
 import org.openstreetmap.josm.io.OsmApi;
 import org.openstreetmap.josm.plugins.PluginHandler;
@@ -116,5 +118,5 @@
      * and sequential.
      */
-    public final static ExecutorService worker = Executors.newSingleThreadExecutor();
+    public final static ExecutorService worker = new ProgressMonitorExecutor();
     /**
      * Global application preferences
@@ -143,4 +145,6 @@
 
     public UndoRedoHandler undoRedo = new UndoRedoHandler();
+
+    public static PleaseWaitProgressMonitor currentProgressMonitor;
 
     /**
@@ -208,4 +212,7 @@
 
         PluginHandler.notifyMapFrameChanged(old, map);
+        if (map == null && currentProgressMonitor != null) {
+            currentProgressMonitor.showForegroundDialog();
+        }
     }
 
@@ -238,6 +245,7 @@
         isOpenjdk = System.getProperty("java.vm.name").toUpperCase().indexOf("OPENJDK") != -1;
 
-        if (initListener != null)
+        if (initListener != null) {
             initListener.updateStatus(tr("Executing platform startup hook"));
+        }
         platform.startupHook();
 
@@ -245,6 +253,7 @@
         // capabilities are already known to the editor instance. However
         // if it goes wrong that's not critical at this stage.
-        if (initListener != null)
+        if (initListener != null) {
             initListener.updateStatus(tr("Initializing OSM API"));
+        }
         try {
             OsmApi.getOsmApi().initialize(null, true);
@@ -253,6 +262,7 @@
         }
 
-        if (initListener != null)
+        if (initListener != null) {
             initListener.updateStatus(tr("Building main menu"));
+        }
         contentPanePrivate.add(panel, BorderLayout.CENTER);
         panel.add(gettingStarted, BorderLayout.CENTER);
@@ -267,18 +277,22 @@
                 KeyEvent.VK_F1, Shortcut.GROUP_DIRECT));
 
-        if (initListener != null)
+        if (initListener != null) {
             initListener.updateStatus(tr("Initializing presets"));
+        }
         TaggingPresetPreference.initialize();
 
-        if (initListener != null)
+        if (initListener != null) {
             initListener.updateStatus(tr("Initializing map styles"));
+        }
         MapPaintPreference.initialize();
 
-        if (initListener != null)
+        if (initListener != null) {
             initListener.updateStatus(tr("Loading imagery preferences"));
+        }
         ImageryPreference.initialize();
 
-        if (initListener != null)
+        if (initListener != null) {
             initListener.updateStatus(tr("Initializing validator"));
+        }
         validator = new OsmValidator();
         MapView.addLayerChangeListener(validator);
@@ -293,6 +307,7 @@
         FeatureAdapter.registerTranslationAdapter(I18n.getTranslationAdapter());
 
-        if (initListener != null)
+        if (initListener != null) {
             initListener.updateStatus(tr("Updating user interface"));
+        }
 
         toolbar.refreshToolbarControl();
@@ -527,5 +542,5 @@
                                 tr("Warning"),
                                 JOptionPane.WARNING_MESSAGE
-                        );
+                                );
                     }
                     if (f!=null) {
@@ -560,5 +575,5 @@
                             tr("Warning"),
                             JOptionPane.WARNING_MESSAGE
-                    );
+                            );
                 }
             }
@@ -647,5 +662,5 @@
                     tr("Warning"),
                     JOptionPane.WARNING_MESSAGE
-            );
+                    );
         } else {
             downloadFromParamBounds(rawGps, b);
@@ -664,5 +679,5 @@
                     new LatLon(Double.parseDouble(st.nextToken()),Double.parseDouble(st.nextToken())),
                     new LatLon(Double.parseDouble(st.nextToken()),Double.parseDouble(st.nextToken()))
-            );
+                    );
             downloadFromParamBounds(rawGps, b);
         }
Index: trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadGpsTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadGpsTask.java	(revision 4717)
+++ trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadGpsTask.java	(revision 4718)
@@ -15,4 +15,6 @@
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+import org.openstreetmap.josm.gui.progress.ProgressTaskId;
+import org.openstreetmap.josm.gui.progress.ProgressTaskIds;
 import org.openstreetmap.josm.io.BoundingBoxDownloader;
 import org.openstreetmap.josm.io.OsmServerLocationReader;
@@ -24,7 +26,7 @@
 
     private DownloadTask downloadTask;
-    
+
     private static final String PATTERN_TRACE_ID = "http://.*openstreetmap.org/trace/\\p{Digit}+/data";
-    
+
     private static final String PATTERN_TRACKPOINTS_BBOX = "http://.*/api/0.6/trackpoints\\?bbox=.*,.*,.*,.*";
 
@@ -44,11 +46,10 @@
             // message if necessary. If no one calls getErrorMessage() it just behaves like execute.
             return Main.worker.submit(downloadTask);
-            
+
         } else if (url != null && url.matches(PATTERN_TRACKPOINTS_BBOX)) {
             String[] table = url.split("\\?|=|&");
             for (int i = 0; i<table.length; i++) {
-                if (table[i].equals("bbox") && i<table.length-1 ) {
+                if (table[i].equals("bbox") && i<table.length-1 )
                     return download(newLayer, new Bounds(table[i+1], ",", ParseMethod.LEFT_BOTTOM_RIGHT_TOP), progressMonitor);
-                }
             }
         }
@@ -124,5 +125,5 @@
                 if (l instanceof GpxLayer &&  (merge || ((GpxLayer)l).data.fromServer))
                     return l;
-            return null;
+                    return null;
         }
 
@@ -133,4 +134,9 @@
             }
         }
+
+        @Override
+        public ProgressTaskId canRunInBackground() {
+            return ProgressTaskIds.DOWNLOAD_GPS;
+        }
     }
 }
Index: trunk/src/org/openstreetmap/josm/gui/MapStatus.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MapStatus.java	(revision 4717)
+++ trunk/src/org/openstreetmap/josm/gui/MapStatus.java	(revision 4718)
@@ -32,8 +32,10 @@
 import javax.swing.JLabel;
 import javax.swing.JPanel;
+import javax.swing.JProgressBar;
 import javax.swing.JScrollPane;
 import javax.swing.JTextField;
 import javax.swing.Popup;
 import javax.swing.PopupFactory;
+import javax.swing.UIManager;
 
 import org.openstreetmap.josm.Main;
@@ -44,4 +46,6 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
 import org.openstreetmap.josm.gui.help.Helpful;
+import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
+import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor.ProgressMonitorDialog;
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -95,4 +99,50 @@
     }
 
+    public class BackgroundProgressMonitor implements ProgressMonitorDialog {
+
+        private String title;
+        private String customText;
+
+        private void updateText() {
+            if (customText != null && !customText.isEmpty()) {
+                progressBar.setToolTipText(tr("{0} ({1})", title, customText));
+            } else {
+                progressBar.setToolTipText(title);
+            }
+        }
+
+        public void setVisible(boolean visible) {
+            progressBar.setVisible(visible);
+        }
+
+        public void updateProgress(int progress) {
+            progressBar.setValue(progress);
+            MapStatus.this.doLayout();
+        }
+
+        public void setCustomText(String text) {
+            this.customText = text;
+            updateText();
+        }
+
+        public void setTitle(String text) {
+            this.title = text;
+            updateText();
+        }
+
+        public void setIndeterminate(boolean newValue) {
+            UIManager.put("ProgressBar.cycleTime", UIManager.getInt("ProgressBar.repaintInterval") * 100);
+            progressBar.setIndeterminate(newValue);
+        }
+
+        @Override
+        public void appendLogMessage(String message) {
+            if (message != null && !message.isEmpty()) {
+                System.out.println("appendLogMessage not implemented for background tasks. Message was: " + message);
+            }
+        }
+
+    }
+
     final ImageLabel lonText = new ImageLabel("lon", tr("The geographic longitude at the mouse pointer."), 11);
     final ImageLabel nameText = new ImageLabel("name", tr("The name of the object at the mouse pointer."), 20);
@@ -102,4 +152,6 @@
     final ImageLabel headingText = new ImageLabel("heading", tr("The (compass) heading of the line segment being drawn."), 6);
     final ImageLabel distText = new ImageLabel("dist", tr("The length of the new way segment being drawn."), 10);
+    final JProgressBar progressBar = new JProgressBar();
+    public final BackgroundProgressMonitor progressMonitor = new BackgroundProgressMonitor();
 
     /**
@@ -658,5 +710,21 @@
         helpText.setEditable(false);
         add(nameText, GBC.std().insets(3,0,0,0));
-        add(helpText, GBC.eol().insets(3,0,0,0).fill(GBC.HORIZONTAL));
+        add(helpText, GBC.std().insets(3,0,0,0).fill(GBC.HORIZONTAL));
+
+        progressBar.setMaximum(PleaseWaitProgressMonitor.PROGRESS_BAR_MAX);
+        {
+            GBC gbc = GBC.eol();
+            gbc.ipadx = 100;
+            add(progressBar,gbc);
+        }
+        progressBar.addMouseListener(new MouseAdapter() {
+            @Override
+            public void mouseClicked(MouseEvent e) {
+                PleaseWaitProgressMonitor monitor = Main.currentProgressMonitor;
+                if (monitor != null) {
+                    monitor.showForegroundDialog();
+                }
+            }
+        });
 
         // The background thread
Index: trunk/src/org/openstreetmap/josm/gui/PleaseWaitDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/PleaseWaitDialog.java	(revision 4717)
+++ trunk/src/org/openstreetmap/josm/gui/PleaseWaitDialog.java	(revision 4718)
@@ -24,8 +24,9 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor.ProgressMonitorDialog;
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.ImageProvider;
 
-public class PleaseWaitDialog extends JDialog {
+public class PleaseWaitDialog extends JDialog implements ProgressMonitorDialog {
 
     private final JProgressBar progressBar = new JProgressBar();
@@ -34,5 +35,6 @@
     private final JLabel customText = new JLabel("");
     public final BoundedRangeModel progress = progressBar.getModel();
-    private  JButton btnCancel;
+    private JButton btnCancel;
+    private JButton btnInBackground;
     /** the text area and the scroll pane for the log */
     private JTextArea taLog = new JTextArea(5,50);
@@ -46,8 +48,14 @@
         pane.add(customText, GBC.eol().fill(GBC.HORIZONTAL));
         pane.add(progressBar, GBC.eop().fill(GBC.HORIZONTAL));
+        JPanel buttons = new JPanel();
+        buttons.setLayout(new GridBagLayout());
         btnCancel = new JButton(tr("Cancel"));
         btnCancel.setIcon(ImageProvider.get("cancel"));
         btnCancel.setToolTipText(tr("Click to cancel the current operation"));
-        pane.add(btnCancel, GBC.eol().anchor(GBC.CENTER));
+        buttons.add(btnCancel);
+        btnInBackground = new JButton(tr("In background"));
+        btnInBackground.setToolTipText(tr("Click to run job in background"));
+        buttons.add(btnInBackground, GBC.std().fill(GBC.VERTICAL).insets(5, 0, 0, 0));
+        pane.add(buttons, GBC.eol().anchor(GBC.CENTER));
         GridBagConstraints gc = GBC.eol().fill(GBC.BOTH);
         gc.weighty = 1.0;
@@ -132,4 +140,8 @@
     }
 
+    public void setInBackgroundPossible(boolean value) {
+        btnInBackground.setVisible(value);
+    }
+
     /**
      * Installs a callback for the cancel button. If callback is null, all action listeners
@@ -148,3 +160,26 @@
         }
     }
+
+    /**
+     * Installs a callback for the "In background" button. If callback is null, all action listeners
+     * are removed from the cancel button.
+     *
+     * @param callback the cancel callback
+     */    
+    public void setInBackgroundCallback(ActionListener callback) {
+        if (callback == null) {
+            ActionListener[] listeners = btnInBackground.getActionListeners();
+            for (ActionListener l: listeners) {
+                btnInBackground.removeActionListener(l);
+            }
+        } else {
+            btnInBackground.addActionListener(callback);
+        }
+    }
+
+    @Override
+    public void updateProgress(int progress) {
+        this.progress.setValue(progress);
+    }
+
 }
Index: trunk/src/org/openstreetmap/josm/gui/PleaseWaitRunnable.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/PleaseWaitRunnable.java	(revision 4717)
+++ trunk/src/org/openstreetmap/josm/gui/PleaseWaitRunnable.java	(revision 4718)
@@ -11,4 +11,5 @@
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor.CancelListener;
+import org.openstreetmap.josm.gui.progress.ProgressTaskId;
 import org.openstreetmap.josm.io.OsmTransferException;
 import org.openstreetmap.josm.tools.BugReportExceptionHandler;
@@ -35,5 +36,4 @@
         this(title, false);
     }
-
     /**
      * Create the runnable object with a given message for the user.
@@ -73,7 +73,10 @@
     private void doRealRun() {
         try {
+            ProgressTaskId oldTaskId = null;
             try {
                 progressMonitor.addCancelListener(this);
                 progressMonitor.beginTask(title);
+                oldTaskId = progressMonitor.getProgressTaskId();
+                progressMonitor.setProgressTaskId(canRunInBackground());
                 try {
                     realRun();
@@ -92,7 +95,9 @@
                 progressMonitor.finishTask();
                 progressMonitor.removeCancelListener(this);
+                progressMonitor.setProgressTaskId(oldTaskId);
                 if (progressMonitor instanceof PleaseWaitProgressMonitor) {
                     ((PleaseWaitProgressMonitor)progressMonitor).close();
                 }
+                afterFinish();
             }
         } catch (final Exception e) {
@@ -110,4 +115,11 @@
             }
         }
+    }
+
+    /**
+     * Can be overriden if something needs to run after progress monitor is closed.
+     */
+    protected void afterFinish() {
+
     }
 
@@ -152,3 +164,12 @@
         return progressMonitor;
     }
+
+    /**
+     * Task can run in background if returned value <> null. Note that it's tasks responsibility
+     * to ensure proper synchronization, PleaseWaitRunnable doesn't with it.
+     * @return If returned value is <> null then task can run in background. TaskId could be used in future for "Always run in background" checkbox
+     */
+    public ProgressTaskId canRunInBackground() {
+        return null;
+    }
 }
Index: trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 4717)
+++ trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 4718)
@@ -1021,5 +1021,5 @@
                     getClass().getName() + ".geometry",
                     WindowGeometry.centerInWindow(Main.parent, new Dimension(1000, 500))
-            );
+                    );
             ed.showDialog();
             int v = ed.getValue();
@@ -1177,4 +1177,8 @@
                 @Override
                 protected void finish() {
+                }
+
+                @Override
+                protected void afterFinish() {
                     if(cancel)
                         return;
@@ -1274,10 +1278,4 @@
 
             if (toDownload.size() > 1) {
-                // hide progress dialog before displaying another pop up. Really closing the
-                // dialog will be handled by PleaseWaitRunnable.
-                if (progressMonitor instanceof PleaseWaitProgressMonitor) {
-                    ((PleaseWaitProgressMonitor) progressMonitor).getDialog().setVisible(false);
-                }
-
                 int ret = JOptionPane.showConfirmDialog(
                         Main.parent,
Index: trunk/src/org/openstreetmap/josm/gui/progress/AbstractProgressMonitor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/progress/AbstractProgressMonitor.java	(revision 4717)
+++ trunk/src/org/openstreetmap/josm/gui/progress/AbstractProgressMonitor.java	(revision 4718)
@@ -6,4 +6,6 @@
 import java.util.LinkedList;
 import java.util.Queue;
+
+import javax.swing.SwingUtilities;
 
 public abstract class AbstractProgressMonitor implements ProgressMonitor {
@@ -61,4 +63,12 @@
     }
 
+    protected void doInEDT(Runnable runnable) {
+        if (SwingUtilities.isEventDispatchThread()) {
+            runnable.run();
+        } else {
+            SwingUtilities.invokeLater(runnable);
+        }
+    }
+
     /*=======
      * Tasks
@@ -69,5 +79,5 @@
     }
 
-    public synchronized void beginTask(final String title, int ticks) {
+    public synchronized void beginTask(String title, int ticks) {
         this.taskTitle = title;
         checkState(State.INIT);
Index: trunk/src/org/openstreetmap/josm/gui/progress/ChildProgress.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/progress/ChildProgress.java	(revision 4717)
+++ trunk/src/org/openstreetmap/josm/gui/progress/ChildProgress.java	(revision 4718)
@@ -55,3 +55,13 @@
         parent.childFinished(this);
     }
+
+    @Override
+    public void setProgressTaskId(ProgressTaskId taskId) {
+        parent.setProgressTaskId(taskId);
+    }
+
+    @Override
+    public ProgressTaskId getProgressTaskId() {
+        return parent.getProgressTaskId();
+    }
 }
Index: trunk/src/org/openstreetmap/josm/gui/progress/NullProgressMonitor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/progress/NullProgressMonitor.java	(revision 4717)
+++ trunk/src/org/openstreetmap/josm/gui/progress/NullProgressMonitor.java	(revision 4718)
@@ -80,3 +80,12 @@
         return 0;
     }
+
+    @Override
+    public void setProgressTaskId(ProgressTaskId taskId) {
+    }
+
+    @Override
+    public ProgressTaskId getProgressTaskId() {
+        return null;
+    }
 }
Index: trunk/src/org/openstreetmap/josm/gui/progress/PleaseWaitProgressMonitor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/progress/PleaseWaitProgressMonitor.java	(revision 4717)
+++ trunk/src/org/openstreetmap/josm/gui/progress/PleaseWaitProgressMonitor.java	(revision 4718)
@@ -4,5 +4,4 @@
 import java.awt.Component;
 import java.awt.Dialog;
-import java.awt.EventQueue;
 import java.awt.Frame;
 import java.awt.Window;
@@ -16,16 +15,66 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.gui.MapStatus.BackgroundProgressMonitor;
 import org.openstreetmap.josm.gui.PleaseWaitDialog;
 
 public class PleaseWaitProgressMonitor extends AbstractProgressMonitor {
 
-    private static final int PROGRESS_BAR_MAX = 100;
+	/**
+	 * Implemented by both foreground dialog and background progress dialog (in status bar)
+	 */
+    public interface ProgressMonitorDialog {
+        void setVisible(boolean visible);
+        void updateProgress(int progress);
+        void setCustomText(String text);
+        void setTitle(String text);
+        void setIndeterminate(boolean newValue);
+        void appendLogMessage(String message);
+    }
+
+    public static final int PROGRESS_BAR_MAX = 100;
     private final Window dialogParent;
     private int currentProgressValue = 0;
 
+    private boolean isInBackground;
     private PleaseWaitDialog dialog;
     private String windowTitle;
-    
+    protected ProgressTaskId taskId;
+
     private boolean cancelable;
+
+    private ProgressMonitorDialog getDialog() {
+
+        BackgroundProgressMonitor backgroundMonitor = null;
+        MapFrame map = Main.map;
+        if (map != null) {
+            backgroundMonitor = map.statusLine.progressMonitor;
+        }
+
+        if (backgroundMonitor != null) {
+            backgroundMonitor.setVisible(isInBackground);
+        }
+        if (dialog != null) {
+            dialog.setVisible(!isInBackground || backgroundMonitor == null);
+        }
+
+        if (isInBackground && backgroundMonitor != null) {
+            backgroundMonitor.setVisible(true);
+            if (dialog != null) {
+                dialog.setVisible(false);
+            }
+            return backgroundMonitor;
+        } else if (backgroundMonitor != null) {
+            backgroundMonitor.setVisible(false);
+            if (dialog != null) {
+                dialog.setVisible(true);
+            }
+            return dialog;
+        } else if (dialog != null) {
+            dialog.setVisible(true);
+            return dialog;
+        } else
+            return null;
+    }
 
     public PleaseWaitProgressMonitor() {
@@ -55,4 +104,15 @@
     };
 
+    private ActionListener inBackgroundListener = new ActionListener() {
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            isInBackground = true;
+            ProgressMonitorDialog dialog = getDialog();
+            if (dialog != null) {
+                dialog.setVisible(true);
+            }
+        }
+    };
+
     private WindowListener windowListener = new WindowAdapter(){
         @Override public void windowClosing(WindowEvent e) {
@@ -69,12 +129,9 @@
     }
 
-    private void doInEDT(Runnable runnable) {
-        EventQueue.invokeLater(runnable);
-    }
-
     @Override
     public void doBeginTask() {
         doInEDT(new Runnable() {
             public void run() {
+                Main.currentProgressMonitor = PleaseWaitProgressMonitor.this;
                 if (dialogParent instanceof Frame && dialog == null) {
                     dialog = new PleaseWaitDialog(dialogParent);
@@ -89,4 +146,5 @@
                 dialog.setCancelEnabled(cancelable);
                 dialog.setCancelCallback(cancelListener);
+                dialog.setInBackgroundCallback(inBackgroundListener);
                 dialog.setCustomText("");
                 dialog.addWindowListener(windowListener);
@@ -109,5 +167,8 @@
             doInEDT(new Runnable() {
                 public void run() {
-                    dialog.progress.setValue(currentProgressValue);
+                    ProgressMonitorDialog dialog = getDialog();
+                    if (dialog != null) {
+                        dialog.updateProgress(currentProgressValue);
+                    }
                 }
             });
@@ -120,5 +181,8 @@
         doInEDT(new Runnable() {
             public void run() {
-                dialog.setCustomText(title);
+                ProgressMonitorDialog dialog = getDialog();
+                if (dialog != null) {
+                    dialog.setCustomText(title);
+                }
             }
         });
@@ -130,5 +194,8 @@
         doInEDT(new Runnable() {
             public void run() {
-                dialog.currentAction.setText(title);
+                ProgressMonitorDialog dialog = getDialog();
+                if (dialog != null) {
+                    dialog.setTitle(title);
+                }
             }
         });
@@ -139,10 +206,9 @@
         doInEDT(new Runnable() {
             public void run() {
-                if (value && dialog.progress.getValue() == 0) {
-                    // Enable only if progress is at the beginning. Doing intermediate progress in the middle
-                    // will hide already reached progress
-                    dialog.setIndeterminate(true);
-                } else {
-                    dialog.setIndeterminate(false);
+                // Enable only if progress is at the beginning. Doing intermediate progress in the middle
+                // will hide already reached progress
+                ProgressMonitorDialog dialog = getDialog();
+                if (dialog != null) {
+                    dialog.setIndeterminate(value && PleaseWaitProgressMonitor.this.dialog.progress.getValue() == 0);
                 }
             }
@@ -154,5 +220,8 @@
         doInEDT(new Runnable() {
             public void run() {
-                dialog.appendLogMessage(message);
+                ProgressMonitorDialog dialog = getDialog();
+                if (dialog != null) {
+                    dialog.appendLogMessage(message);
+                }
             }
         });
@@ -160,13 +229,49 @@
 
     public void close() {
-        dialog.setVisible(false);
-        dialog.setCancelCallback(null);
-        dialog.removeWindowListener(windowListener);
-        dialog.dispose();
-        dialog = null;
-    }
-    
-    public Component getDialog() {
-        return dialog;
-    }
+        doInEDT(new Runnable() {
+            @Override
+            public void run() {
+                dialog.setVisible(false);
+                dialog.setCancelCallback(null);
+                dialog.setInBackgroundCallback(null);
+                dialog.removeWindowListener(windowListener);
+                dialog.dispose();
+                dialog = null;
+                MapFrame map = Main.map;
+                if (map != null) {
+                    map.statusLine.progressMonitor.setVisible(false);
+                }
+                Main.currentProgressMonitor = null;
+            }
+        });
+    }
+
+    public void showForegroundDialog() {
+        isInBackground = false;
+        doInEDT(new Runnable() {
+            @Override
+            public void run() {
+                dialog.setInBackgroundPossible(PleaseWaitProgressMonitor.this.taskId != null && Main.isDisplayingMapView());
+                getDialog();
+            }
+        });
+
+    }
+
+    @Override
+    public void setProgressTaskId(ProgressTaskId taskId) {
+        this.taskId = taskId;
+        doInEDT(new Runnable() {
+            @Override
+            public void run() {
+                dialog.setInBackgroundPossible(PleaseWaitProgressMonitor.this.taskId != null && Main.isDisplayingMapView());
+            }
+        });
+    }
+
+    @Override
+    public ProgressTaskId getProgressTaskId() {
+        return taskId;
+    }
+
 }
Index: trunk/src/org/openstreetmap/josm/gui/progress/ProgressMonitor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/progress/ProgressMonitor.java	(revision 4717)
+++ trunk/src/org/openstreetmap/josm/gui/progress/ProgressMonitor.java	(revision 4718)
@@ -50,4 +50,5 @@
      */
     void beginTask(String title, int ticks);
+
     /**
      * Finish this progress monitor, close the dialog or inform the parent progress monitor
@@ -55,4 +56,5 @@
      * then further calls are ignored)
      */
+
     void finishTask();
     /**
@@ -126,3 +128,15 @@
      */
     void appendLogMessage(String message);
+
+    /**
+     * Should be used only by PleaseWaitRunnable. If taskId <> null then "In background" button will be shown
+     * @param taskId
+     */
+    void setProgressTaskId(ProgressTaskId taskId);
+
+    /**
+     * Should be used only by PleaseWaitRunnable
+     * @param taskId
+     */
+    ProgressTaskId getProgressTaskId();
 }
Index: trunk/src/org/openstreetmap/josm/gui/progress/ProgressMonitorExecutor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/progress/ProgressMonitorExecutor.java	(revision 4718)
+++ trunk/src/org/openstreetmap/josm/gui/progress/ProgressMonitorExecutor.java	(revision 4718)
@@ -0,0 +1,26 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.progress;
+
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import org.openstreetmap.josm.Main;
+
+public class ProgressMonitorExecutor extends ThreadPoolExecutor {
+
+    public ProgressMonitorExecutor() {
+        super(1, 1, 0L, TimeUnit.MILLISECONDS,
+                new LinkedBlockingQueue<Runnable>());
+    }
+
+    @Override
+    public void execute(Runnable command) {
+        if (Main.currentProgressMonitor != null) {
+            //TODO show only if this can't be in background or better if always in background is not checked
+            Main.currentProgressMonitor.showForegroundDialog();
+        }
+        super.execute(command);
+    }
+
+}
Index: trunk/src/org/openstreetmap/josm/gui/progress/ProgressTaskId.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/progress/ProgressTaskId.java	(revision 4718)
+++ trunk/src/org/openstreetmap/josm/gui/progress/ProgressTaskId.java	(revision 4718)
@@ -0,0 +1,34 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.progress;
+
+public class ProgressTaskId {
+
+    private final String id;
+
+    public ProgressTaskId(String component, String task) {
+        this.id = component + "." + task;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    @Override
+    public int hashCode() {
+        return id.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        ProgressTaskId other = (ProgressTaskId) obj;
+        return other.id.equals(id);
+
+    }
+
+}
Index: trunk/src/org/openstreetmap/josm/gui/progress/ProgressTaskIds.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/progress/ProgressTaskIds.java	(revision 4718)
+++ trunk/src/org/openstreetmap/josm/gui/progress/ProgressTaskIds.java	(revision 4718)
@@ -0,0 +1,8 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.progress;
+
+public interface ProgressTaskIds {
+
+    ProgressTaskId DOWNLOAD_GPS = new ProgressTaskId("core", "downloadGps");
+
+}
Index: trunk/src/org/openstreetmap/josm/gui/progress/SwingRenderingProgressMonitor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/progress/SwingRenderingProgressMonitor.java	(revision 4717)
+++ trunk/src/org/openstreetmap/josm/gui/progress/SwingRenderingProgressMonitor.java	(revision 4718)
@@ -1,6 +1,4 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.gui.progress;
-
-import javax.swing.SwingUtilities;
 
 import org.openstreetmap.josm.tools.CheckParameterUtil;
@@ -27,12 +25,4 @@
         CheckParameterUtil.ensureParameterNotNull(delegate, "delegate");
         this.delegate = delegate;
-    }
-
-    private void doInEDT(Runnable runnable) {
-        if (SwingUtilities.isEventDispatchThread()) {
-            runnable.run();
-        } else {
-            SwingUtilities.invokeLater(runnable);
-        }
     }
 
@@ -93,3 +83,12 @@
         });
     }
+
+    @Override
+    public void setProgressTaskId(ProgressTaskId taskId) {
+    }
+
+    @Override
+    public ProgressTaskId getProgressTaskId() {
+        return null;
+    }
 }
Index: trunk/src/org/openstreetmap/josm/io/session/SessionReader.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/session/SessionReader.java	(revision 4717)
+++ trunk/src/org/openstreetmap/josm/io/session/SessionReader.java	(revision 4718)
@@ -5,12 +5,13 @@
 import static org.openstreetmap.josm.tools.Utils.equal;
 
-import java.awt.Component;
 import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
 import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -25,6 +26,4 @@
 import java.util.zip.ZipException;
 import java.util.zip.ZipFile;
-import java.net.URI;
-import java.net.URISyntaxException;
 
 import javax.swing.JOptionPane;
@@ -34,4 +33,12 @@
 import javax.xml.parsers.ParserConfigurationException;
 
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.ExtendedDialog;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+import org.openstreetmap.josm.io.IllegalDataException;
+import org.openstreetmap.josm.tools.MultiMap;
+import org.openstreetmap.josm.tools.Utils;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -39,14 +46,4 @@
 import org.w3c.dom.NodeList;
 import org.xml.sax.SAXException;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.gui.ExtendedDialog;
-import org.openstreetmap.josm.gui.layer.Layer;
-import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
-import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
-import org.openstreetmap.josm.gui.progress.ProgressMonitor;
-import org.openstreetmap.josm.io.IllegalDataException;
-import org.openstreetmap.josm.tools.MultiMap;
-import org.openstreetmap.josm.tools.Utils;
 
 /**
@@ -153,7 +150,7 @@
             File file = getFile(uriStr);
             try {
-                if (file != null) {
+                if (file != null)
                     return new BufferedInputStream(new FileInputStream(file));
-                } else if (inZipPath != null) {
+                else if (inZipPath != null) {
                     ZipEntry entry = zipFile.getEntry(inZipPath);
                     if (entry != null) {
@@ -178,15 +175,15 @@
             try {
                 URI uri = new URI(uriStr);
-                if ("file".equals(uri.getScheme())) {
+                if ("file".equals(uri.getScheme()))
                     // absolute path
                     return new File(uri);
-                } else if (uri.getScheme() == null) {
+                else if (uri.getScheme() == null) {
                     // Check if this is an absolute path without 'file:' scheme part.
                     // At this point, (as an exception) platform dependent path separator will be recognized.
                     // (This form is discouraged, only for users that like to copy and paste a path manually.)
                     File file = new File(uriStr);
-                    if (file.isAbsolute()) {
+                    if (file.isAbsolute())
                         return file;
-                    } else {
+                    else {
                         // for relative paths, only forward slashes are permitted
                         if (isZip()) {
@@ -200,11 +197,9 @@
                                 return null;
                             }
-                        } else {
+                        } else
                             return new File(sessionFile.toURI().resolve(uri));
-                        }
-                    }
-                } else {
+                    }
+                } else
                     throw new IOException(tr("Unsupported scheme ''{0}'' in URI ''{1}''.", uri.getScheme(), uriStr));
-                }
             } catch (URISyntaxException e) {
                 throw new IOException(e);
@@ -328,9 +323,9 @@
                 CancelOrContinueDialog dialog = new CancelOrContinueDialog();
                 dialog.show(
-                    tr("Unable to load layer"),
-                    tr("Cannot load layer of type ''{0}'' because no suitable importer was found.", type),
-                    JOptionPane.WARNING_MESSAGE,
-                    progressMonitor
-                );
+                        tr("Unable to load layer"),
+                        tr("Cannot load layer of type ''{0}'' because no suitable importer was found.", type),
+                        JOptionPane.WARNING_MESSAGE,
+                        progressMonitor
+                        );
                 if (dialog.isCancel()) {
                     progressMonitor.cancel();
@@ -347,9 +342,9 @@
                         CancelOrContinueDialog dialog = new CancelOrContinueDialog();
                         dialog.show(
-                            tr("Unable to load layer"),
-                            tr("Cannot load layer {0} because it depends on layer {1} which has been skipped.", idx, d),
-                            JOptionPane.WARNING_MESSAGE,
-                            progressMonitor
-                        );
+                                tr("Unable to load layer"),
+                                tr("Cannot load layer {0} because it depends on layer {1} which has been skipped.", idx, d),
+                                JOptionPane.WARNING_MESSAGE,
+                                progressMonitor
+                                );
                         if (dialog.isCancel()) {
                             progressMonitor.cancel();
@@ -375,9 +370,9 @@
                     CancelOrContinueDialog dialog = new CancelOrContinueDialog();
                     dialog.show(
-                        tr("Error loading layer"),
-                        tr("<html>Could not load layer {0} ''{1}''.<br>Error is:<br>{2}</html>", idx, name, exception.getMessage()),
-                        JOptionPane.ERROR_MESSAGE,
-                        progressMonitor
-                    );
+                            tr("Error loading layer"),
+                            tr("<html>Could not load layer {0} ''{1}''.<br>Error is:<br>{2}</html>", idx, name, exception.getMessage()),
+                            JOptionPane.ERROR_MESSAGE,
+                            progressMonitor
+                            );
                     if (dialog.isCancel()) {
                         progressMonitor.cancel();
@@ -397,5 +392,7 @@
         for (Entry<Integer, Layer> e : layersMap.entrySet()) {
             Layer l = e.getValue();
-            if (l == null) continue;
+            if (l == null) {
+                continue;
+            }
             l.setName(names.get(e.getKey()));
             layers.add(l);
@@ -418,15 +415,9 @@
                 SwingUtilities.invokeAndWait(new Runnable() {
                     @Override public void run() {
-                        Component parent;
-                        if (progressMonitor instanceof PleaseWaitProgressMonitor) {
-                            parent = ((PleaseWaitProgressMonitor) progressMonitor).getDialog();
-                        } else {
-                            parent = Main.parent;
-                        }
                         ExtendedDialog dlg = new ExtendedDialog(
-                                parent,
+                                Main.parent,
                                 title,
                                 new String[] { tr("Cancel"), tr("Skip layer and continue") }
-                        );
+                                );
                         dlg.setButtonIcons(new String[] {"cancel", "dialogs/next"});
                         dlg.setIcon(icon);
