Index: trunk/src/org/openstreetmap/josm/actions/ImageryAdjustAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/ImageryAdjustAction.java	(revision 10570)
+++ trunk/src/org/openstreetmap/josm/actions/ImageryAdjustAction.java	(revision 10571)
@@ -28,5 +28,6 @@
 import org.openstreetmap.josm.data.imagery.OffsetBookmark;
 import org.openstreetmap.josm.gui.ExtendedDialog;
-import org.openstreetmap.josm.gui.layer.ImageryLayer;
+import org.openstreetmap.josm.gui.layer.AbstractTileSourceLayer;
+import org.openstreetmap.josm.gui.layer.imagery.TileSourceDisplaySettings;
 import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
 import org.openstreetmap.josm.gui.widgets.JosmTextField;
@@ -42,7 +43,7 @@
     private static Cursor cursor = ImageProvider.getCursor("normal", "move");
 
-    private double oldDx, oldDy;
+    private EastNorth old;
     private EastNorth prevEastNorth;
-    private transient ImageryLayer layer;
+    private transient AbstractTileSourceLayer<?> layer;
     private MapMode oldMapMode;
 
@@ -51,5 +52,5 @@
      * @param layer The imagery layer
      */
-    public ImageryAdjustAction(ImageryLayer layer) {
+    public ImageryAdjustAction(AbstractTileSourceLayer<?> layer) {
         super(tr("New offset"), "adjustimg",
                 tr("Adjust the position of this imagery layer"), Main.map,
@@ -67,6 +68,5 @@
             layer.setVisible(true);
         }
-        oldDx = layer.getDx();
-        oldDy = layer.getDy();
+        old = layer.getDisplaySettings().getDisplacement();
         addListeners();
         offsetDialog = new ImageryOffsetDialog();
@@ -89,5 +89,5 @@
         if (offsetDialog != null) {
             if (layer != null) {
-                layer.setOffset(oldDx, oldDy);
+                layer.getDisplaySettings().setDisplacement(old);
             }
             offsetDialog.setVisible(false);
@@ -155,9 +155,7 @@
     public void mouseDragged(MouseEvent e) {
         if (layer == null || prevEastNorth == null) return;
-        EastNorth eastNorth =
-            Main.map.mapView.getEastNorth(e.getX(), e.getY());
-        double dx = layer.getDx()+eastNorth.east()-prevEastNorth.east();
-        double dy = layer.getDy()+eastNorth.north()-prevEastNorth.north();
-        layer.setOffset(dx, dy);
+        EastNorth eastNorth = Main.map.mapView.getEastNorth(e.getX(), e.getY());
+        EastNorth d = layer.getDisplaySettings().getDisplacement().add(eastNorth).subtract(prevEastNorth);
+        layer.getDisplaySettings().setDisplacement(d);
         if (offsetDialog != null) {
             offsetDialog.updateOffset();
@@ -234,5 +232,5 @@
                     double dx = Double.parseDouble(easting);
                     double dy = Double.parseDouble(northing);
-                    layer.setOffset(dx, dy);
+                    layer.getDisplaySettings().setDisplacement(new EastNorth(dx, dy));
                 } catch (NumberFormatException nfe) {
                     // we repaint offset numbers in any case
@@ -259,7 +257,8 @@
             // US locale to force decimal separator to be '.'
             try (Formatter us = new Formatter(Locale.US)) {
+                TileSourceDisplaySettings ds = layer.getDisplaySettings();
                 tOffset.setText(us.format(new StringBuilder()
                     .append("%1.").append(precision).append("f; %1.").append(precision).append('f').toString(),
-                    layer.getDx(), layer.getDy()).toString());
+                    ds.getDx(), ds.getDy()).toString());
             }
         }
@@ -298,5 +297,5 @@
             if (layer != null) {
                 if (getValue() != 1) {
-                    layer.setOffset(oldDx, oldDy);
+                    layer.getDisplaySettings().setDisplacement(old);
                 } else if (tBookmarkName.getText() != null && !tBookmarkName.getText().isEmpty()) {
                     OffsetBookmark.bookmarkOffset(tBookmarkName.getText(), layer);
Index: trunk/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java	(revision 10570)
+++ trunk/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java	(revision 10571)
@@ -64,4 +64,5 @@
 import org.openstreetmap.gui.jmapviewer.tilesources.AbstractTMSTileSource;
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.ImageryAdjustAction;
 import org.openstreetmap.josm.actions.RenameLayerAction;
 import org.openstreetmap.josm.actions.SaveActionBase;
@@ -165,4 +166,6 @@
     private final TileSourceDisplaySettings displaySettings = createDisplaySettings();
 
+    private final ImageryAdjustAction adjustAction = new ImageryAdjustAction(this);
+
     /**
      * Creates Tile Source based Imagery Layer based on Imagery Info
@@ -286,4 +289,19 @@
     }
 
+    @Override
+    public double getDx() {
+        return getDisplaySettings().getDx();
+    }
+
+    @Override
+    public double getDy() {
+        return getDisplaySettings().getDy();
+    }
+
+    @Override
+    public void displace(double dx, double dy) {
+        getDisplaySettings().addDisplacement(new EastNorth(dx, dy));
+    }
+
     /**
      * Marks layer as needing redraw on offset change
@@ -291,8 +309,21 @@
     @Override
     public void setOffset(double dx, double dy) {
-        super.setOffset(dx, dy);
-        needRedraw = true;
-    }
-
+        getDisplaySettings().setDisplacement(new EastNorth(dx, dy));
+    }
+
+    @Override
+    public Object getInfoComponent() {
+        JPanel panel = (JPanel) super.getInfoComponent();
+        EastNorth offset = getDisplaySettings().getDisplacement();
+        if (offset.distanceSq(0, 0) > 1e-10) {
+            panel.add(new JLabel(tr("Offset: ") + offset.east() + ';' + offset.north()), GBC.eol().insets(0, 5, 10, 0));
+        }
+        return panel;
+    }
+
+    @Override
+    protected Action getAdjustAction() {
+        return adjustAction;
+    }
 
     /**
@@ -1882,3 +1913,9 @@
         return SaveActionBase.createAndOpenSaveFileChooser(tr("Save WMS file"), WMSLayerImporter.FILE_FILTER);
     }
+
+    @Override
+    public void destroy() {
+        super.destroy();
+        adjustAction.destroy();
+    }
 }
Index: trunk/src/org/openstreetmap/josm/gui/layer/ImageryLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/ImageryLayer.java	(revision 10570)
+++ trunk/src/org/openstreetmap/josm/gui/layer/ImageryLayer.java	(revision 10571)
@@ -16,4 +16,5 @@
 
 import javax.swing.AbstractAction;
+import javax.swing.Action;
 import javax.swing.Icon;
 import javax.swing.JCheckBoxMenuItem;
@@ -27,5 +28,4 @@
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.ImageryAdjustAction;
 import org.openstreetmap.josm.data.ProjectionBounds;
 import org.openstreetmap.josm.data.imagery.ImageryInfo;
@@ -35,4 +35,5 @@
 import org.openstreetmap.josm.gui.MenuScroller;
 import org.openstreetmap.josm.gui.layer.imagery.ImageryFilterSettings;
+import org.openstreetmap.josm.gui.layer.imagery.TileSourceDisplaySettings;
 import org.openstreetmap.josm.gui.widgets.UrlLabel;
 import org.openstreetmap.josm.tools.GBC;
@@ -61,9 +62,4 @@
 
     protected Icon icon;
-
-    protected double dx;
-    protected double dy;
-
-    private final ImageryAdjustAction adjustAction = new ImageryAdjustAction(this);
 
     private final ImageryFilterSettings filterSettings = new ImageryFilterSettings();
@@ -96,27 +92,49 @@
     }
 
+    /**
+     * Gets the x displacement of this layer.
+     * To be removed end of 2016
+     * @return The x displacement.
+     * @deprecated Use {@link TileSourceDisplaySettings#getDx()}
+     */
+    @Deprecated
     public double getDx() {
-        return dx;
-    }
-
+        // moved to AbstractTileSourceLayer/TileSourceDisplaySettings. Remains until all actions migrate.
+        return 0;
+    }
+
+    /**
+     * Gets the y displacement of this layer.
+     * To be removed end of 2016
+     * @return The y displacement.
+     * @deprecated Use {@link TileSourceDisplaySettings#getDy()}
+     */
+    @Deprecated
     public double getDy() {
-        return dy;
+        // moved to AbstractTileSourceLayer/TileSourceDisplaySettings. Remains until all actions migrate.
+        return 0;
     }
 
     /**
      * Sets the displacement offset of this layer. The layer is automatically invalidated.
+     * To be removed end of 2016
      * @param dx The x offset
      * @param dy The y offset
-     */
+     * @deprecated Use {@link TileSourceDisplaySettings}
+     */
+    @Deprecated
     public void setOffset(double dx, double dy) {
-        this.dx = dx;
-        this.dy = dy;
-        invalidate();
-    }
-
+        // moved to AbstractTileSourceLayer/TileSourceDisplaySettings. Remains until all actions migrate.
+    }
+
+    /**
+     * To be removed end of 2016
+     * @param dx deprecated
+     * @param dy deprecated
+     * @deprecated Use {@link TileSourceDisplaySettings}
+     */
+    @Deprecated
     public void displace(double dx, double dy) {
-        this.dx += dx;
-        this.dy += dy;
-        setOffset(this.dx, this.dy);
+        // moved to AbstractTileSourceLayer/TileSourceDisplaySettings. Remains until all actions migrate.
     }
 
@@ -152,7 +170,4 @@
                 panel.add(new JLabel(tr("URL: ")), GBC.std().insets(0, 5, 2, 0));
                 panel.add(new UrlLabel(url), GBC.eol().insets(2, 5, 10, 0));
-            }
-            if (dx != 0 || dy != 0) {
-                panel.add(new JLabel(tr("Offset: ") + dx + ';' + dy), GBC.eol().insets(0, 5, 10, 0));
             }
         }
@@ -216,5 +231,5 @@
 
     public JComponent getOffsetMenuItem(JComponent subMenu) {
-        JMenuItem adjustMenuItem = new JMenuItem(adjustAction);
+        JMenuItem adjustMenuItem = new JMenuItem(getAdjustAction());
         if (OffsetBookmark.allBookmarks.isEmpty()) return adjustMenuItem;
 
@@ -228,5 +243,5 @@
             }
             JCheckBoxMenuItem item = new JCheckBoxMenuItem(new ApplyOffsetAction(b));
-            if (Utils.equalsEpsilon(b.dx, dx) && Utils.equalsEpsilon(b.dy, dy)) {
+            if (Utils.equalsEpsilon(b.dx, getDx()) && Utils.equalsEpsilon(b.dy, getDy())) {
                 item.setSelected(true);
             }
@@ -245,4 +260,6 @@
     }
 
+    protected abstract Action getAdjustAction();
+
     /**
      * Gets the settings for the filter that is applied to this layer.
@@ -314,9 +331,3 @@
         return img;
     }
-
-    @Override
-    public void destroy() {
-        super.destroy();
-        adjustAction.destroy();
-    }
 }
Index: trunk/src/org/openstreetmap/josm/gui/layer/imagery/TileSourceDisplaySettings.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/imagery/TileSourceDisplaySettings.java	(revision 10570)
+++ trunk/src/org/openstreetmap/josm/gui/layer/imagery/TileSourceDisplaySettings.java	(revision 10571)
@@ -7,6 +7,9 @@
 import org.openstreetmap.gui.jmapviewer.interfaces.TileSource;
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.preferences.BooleanProperty;
 import org.openstreetmap.josm.gui.layer.AbstractTileSourceLayer;
+import org.openstreetmap.josm.tools.CheckParameterUtil;
+import org.openstreetmap.josm.tools.bugreport.BugReport;
 
 /**
@@ -36,4 +39,6 @@
     private static final String SHOW_ERRORS = "show-errors";
 
+    private static final String DISPLACEMENT = "displacement";
+
     private static final String PREFERENCE_PREFIX = "imagery.generic";
 
@@ -47,4 +52,5 @@
      */
     public static final BooleanProperty PROP_AUTO_ZOOM = new BooleanProperty(PREFERENCE_PREFIX + ".default_autozoom", true);
+
 
     /** if layers changes automatically, when user zooms in */
@@ -54,4 +60,9 @@
     /** if layer should show errors on tiles */
     private boolean showErrors;
+
+    /**
+     * The displacement
+     */
+    private EastNorth displacement = new EastNorth(0, 0);
 
     private final CopyOnWriteArrayList<DisplaySettingsChangeListener> listeners = new CopyOnWriteArrayList<>();
@@ -150,4 +161,52 @@
 
     /**
+     * Gets the displacement in x (east) direction
+     * @return The displacement.
+     * @since 10571
+     */
+    public double getDx() {
+        return displacement.east();
+    }
+
+    /**
+     * Gets the displacement in y (north) direction
+     * @return The displacement.
+     * @since 10571
+     */
+    public double getDy() {
+        return displacement.north();
+    }
+
+    /**
+     * Gets the displacement of the image
+     * @return The displacement.
+     * @since xxx
+     */
+    public EastNorth getDisplacement() {
+        return displacement;
+    }
+
+    /**
+     * Set the displacement
+     * @param displacement The new displacement
+     * @since xxx
+     */
+    public void setDisplacement(EastNorth displacement) {
+        CheckParameterUtil.ensureValidCoordinates(displacement, "displacement");
+        this.displacement = displacement;
+        fireSettingsChange(DISPLACEMENT);
+    }
+
+    /**
+     * Adds the given value to the displacement.
+     * @param displacement The value to add.
+     * @since xxx
+     */
+    public void addDisplacement(EastNorth displacement) {
+        CheckParameterUtil.ensureValidCoordinates(displacement, "displacement");
+        setDisplacement(this.displacement.add(displacement));
+    }
+
+    /**
      * Notifies all listeners that the paint settings have changed
      * @param changedSetting The setting name
@@ -185,4 +244,6 @@
         data.put(AUTO_ZOOM, Boolean.toString(autoZoom));
         data.put(SHOW_ERRORS, Boolean.toString(showErrors));
+        data.put("dx", String.valueOf(getDx()));
+        data.put("dy", String.valueOf(getDy()));
     }
 
@@ -193,17 +254,27 @@
      */
     public void loadFrom(Map<String, String> data) {
-        String doAutoLoad = data.get(AUTO_LOAD);
-        if (doAutoLoad != null) {
-            setAutoLoad(Boolean.parseBoolean(doAutoLoad));
-        }
-
-        String doAutoZoom = data.get(AUTO_ZOOM);
-        if (doAutoZoom != null) {
-            setAutoZoom(Boolean.parseBoolean(doAutoZoom));
-        }
-
-        String doShowErrors = data.get(SHOW_ERRORS);
-        if (doShowErrors != null) {
-            setShowErrors(Boolean.parseBoolean(doShowErrors));
+        try {
+            String doAutoLoad = data.get(AUTO_LOAD);
+            if (doAutoLoad != null) {
+                setAutoLoad(Boolean.parseBoolean(doAutoLoad));
+            }
+
+            String doAutoZoom = data.get(AUTO_ZOOM);
+            if (doAutoZoom != null) {
+                setAutoZoom(Boolean.parseBoolean(doAutoZoom));
+            }
+
+            String doShowErrors = data.get(SHOW_ERRORS);
+            if (doShowErrors != null) {
+                setShowErrors(Boolean.parseBoolean(doShowErrors));
+            }
+
+            String dx = data.get("dx");
+            String dy = data.get("dy");
+            if (dx != null && dy != null) {
+                setDisplacement(new EastNorth(Double.parseDouble(dx), Double.parseDouble(dy)));
+            }
+        } catch (RuntimeException e) {
+            throw BugReport.intercept(e).put("data", data);
         }
     }
Index: trunk/src/org/openstreetmap/josm/io/session/ImagerySessionImporter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/session/ImagerySessionImporter.java	(revision 10570)
+++ trunk/src/org/openstreetmap/josm/io/session/ImagerySessionImporter.java	(revision 10571)
@@ -54,7 +54,4 @@
             tsLayer.getDisplaySettings().loadFrom(attributes);
         }
-        if (attributes.containsKey("dx") && attributes.containsKey("dy")) {
-            layer.setOffset(Double.parseDouble(attributes.get("dx")), Double.parseDouble(attributes.get("dy")));
-        }
         return layer;
     }
