Index: trunk/src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java	(revision 7216)
+++ trunk/src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java	(revision 7217)
@@ -4,8 +4,5 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import java.awt.AWTEvent;
 import java.awt.Cursor;
-import java.awt.Toolkit;
-import java.awt.event.AWTEventListener;
 import java.awt.event.ActionEvent;
 import java.awt.event.InputEvent;
@@ -29,4 +26,5 @@
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.util.HighlightHelper;
+import org.openstreetmap.josm.gui.util.ModifierListener;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -48,5 +46,5 @@
  * @author imi
  */
-public class DeleteAction extends MapMode implements AWTEventListener {
+public class DeleteAction extends MapMode implements ModifierListener {
     // Cache previous mouse event (needed when only the modifier keys are
     // pressed but the mouse isn't moved)
@@ -113,9 +111,5 @@
         Main.map.mapView.addMouseMotionListener(this);
         // This is required to update the cursors when ctrl/shift/alt is pressed
-        try {
-            Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK);
-        } catch (SecurityException ex) {
-            Main.warn(ex);
-        }
+        Main.map.keyDetector.addModifierListener(this);
     }
 
@@ -125,9 +119,5 @@
         Main.map.mapView.removeMouseListener(this);
         Main.map.mapView.removeMouseMotionListener(this);
-        try {
-            Toolkit.getDefaultToolkit().removeAWTEventListener(this);
-        } catch (SecurityException ex) {
-            Main.warn(ex);
-        }
+        Main.map.keyDetector.removeModifierListener(this);
         removeHighlighting();
     }
@@ -400,10 +390,10 @@
      */
     @Override
-    public void eventDispatched(AWTEvent e) {
+    public void modifiersChanged(int modifiers) {
         if(oldEvent == null)
             return;
         // We don't have a mouse event, so we pass the old mouse event but the
         // new modifiers.
-        giveUserFeedback(oldEvent, ((InputEvent) e).getModifiers());
+        giveUserFeedback(oldEvent, modifiers);
     }
 }
Index: trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java	(revision 7216)
+++ trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java	(revision 7217)
@@ -7,18 +7,11 @@
 import static org.openstreetmap.josm.tools.I18n.trn;
 
-import java.awt.AWTEvent;
 import java.awt.BasicStroke;
 import java.awt.Color;
-import java.awt.Component;
 import java.awt.Cursor;
 import java.awt.Graphics2D;
-import java.awt.KeyboardFocusManager;
 import java.awt.Point;
 import java.awt.Stroke;
-import java.awt.Toolkit;
-import java.awt.event.AWTEventListener;
 import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
 import java.awt.event.MouseEvent;
@@ -36,14 +29,10 @@
 import java.util.Map;
 import java.util.Set;
-import java.util.TreeSet;
 
 import javax.swing.AbstractAction;
 import javax.swing.JCheckBoxMenuItem;
-import javax.swing.JFrame;
 import javax.swing.JMenuItem;
 import javax.swing.JOptionPane;
 import javax.swing.JPopupMenu;
-import javax.swing.SwingUtilities;
-import javax.swing.Timer;
 
 import org.openstreetmap.josm.Main;
@@ -71,4 +60,6 @@
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.util.GuiHelper;
+import org.openstreetmap.josm.gui.util.KeyPressReleaseListener;
+import org.openstreetmap.josm.gui.util.ModifierListener;
 import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
 import org.openstreetmap.josm.tools.Geometry;
@@ -81,5 +72,5 @@
  * Mapmode to add nodes, create and extend ways.
  */
-public class DrawAction extends MapMode implements MapViewPaintable, SelectionChangedListener, AWTEventListener {
+public class DrawAction extends MapMode implements MapViewPaintable, SelectionChangedListener, KeyPressReleaseListener, ModifierListener {
     private final Cursor cursorJoinNode;
     private final Cursor cursorJoinWay;
@@ -112,7 +103,8 @@
     private final SnapHelper snapHelper = new SnapHelper();
 
-    private Shortcut backspaceShortcut;
-    private BackSpaceAction backspaceAction;
+    private final Shortcut backspaceShortcut;
+    private final BackSpaceAction backspaceAction;
     private final Shortcut snappingShortcut;
+    private boolean ignoreNextKeyRelease;
 
     private final SnapChangeAction snapChangeAction;
@@ -227,14 +219,4 @@
         snapCheckboxMenuItem.getAction().setEnabled(true);
 
-        timer = new Timer(0, new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent ae) {
-                timer.stop();
-                if (set.remove(releaseEvent.getKeyCode())) {
-                    doKeyReleaseEvent(releaseEvent);
-                }
-            }
-
-        });
         Main.map.statusLine.getAnglePanel().addMouseListener(snapHelper.anglePopupListener);
         Main.registerActionShortcut(backspaceAction, backspaceShortcut);
@@ -245,9 +227,7 @@
         DataSet.addSelectionListener(this);
 
-        try {
-            Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK);
-        } catch (SecurityException ex) {
-            Main.warn(ex);
-        }
+        Main.map.keyDetector.addKeyListener(this);
+        Main.map.keyDetector.addModifierListener(this);
+        ignoreNextKeyRelease = true;
         // would like to but haven't got mouse position yet:
         // computeHelperLine(false, false, false);
@@ -269,9 +249,6 @@
 
         removeHighlighting();
-        try {
-            Toolkit.getDefaultToolkit().removeAWTEventListener(this);
-        } catch (SecurityException ex) {
-            Main.warn(ex);
-        }
+        Main.map.keyDetector.removeKeyListener(this);
+        Main.map.keyDetector.removeModifierListener(this);
 
         // when exiting we let everybody know about the currently selected
@@ -288,54 +265,29 @@
      */
     @Override
-    public void eventDispatched(AWTEvent event) {
+    public void modifiersChanged(int modifiers) {
         if (!Main.isDisplayingMapView() || !Main.map.mapView.isActiveLayerDrawable())
             return;
-        if (event instanceof KeyEvent) {
-            KeyEvent e = (KeyEvent) event;
-            if (snappingShortcut.isEvent(e) || (useRepeatedShortcut && getShortcut().isEvent(e))) {
-                Component focused = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
-                if (SwingUtilities.getWindowAncestor(focused) instanceof JFrame) {
-                    processKeyEvent(e);
-                }
-            }
-        } //  toggle angle snapping
-        updateKeyModifiers((InputEvent) event);
+        updateKeyModifiers(modifiers);
         computeHelperLine();
         addHighlighting();
     }
 
-    // events for crossplatform key holding processing
-    private final Set<Integer> set = new TreeSet<>();
-    private KeyEvent releaseEvent;
-    private Timer timer;
-    void processKeyEvent(KeyEvent e) {
+    @Override
+    public void doKeyPressed(KeyEvent e) {
         if (!snappingShortcut.isEvent(e) && !(useRepeatedShortcut && getShortcut().isEvent(e)))
             return;
-
-        if (e.getID() == KeyEvent.KEY_PRESSED) {
-            if (timer.isRunning()) {
-                timer.stop();
-            } else if (set.add((e.getKeyCode()))) {
-                doKeyPressEvent(e);
-            }
-        } else if (e.getID() == KeyEvent.KEY_RELEASED) {
-            if (timer.isRunning()) {
-                timer.stop();
-                if (set.remove(e.getKeyCode())) {
-                    doKeyReleaseEvent(e);
-                }
-            } else {
-                releaseEvent = e;
-                timer.restart();
-            }
-        }
-    }
-
-    private void doKeyPressEvent(KeyEvent e) {
         snapHelper.setFixedMode();
         computeHelperLine();
         redrawIfRequired();
     }
-    private void doKeyReleaseEvent(KeyEvent e) {
+
+    @Override
+    public void doKeyReleased(KeyEvent e) {
+        if (!snappingShortcut.isEvent(e) && !(useRepeatedShortcut && getShortcut().isEvent(e)))
+            return;
+        if (ignoreNextKeyRelease) {
+            ignoreNextKeyRelease = false;
+            return;
+        }
         snapHelper.unFixOrTurnOff();
         computeHelperLine();
@@ -393,5 +345,6 @@
      * If in nodeway mode, insert the node into the way.
      */
-    @Override public void mouseReleased(MouseEvent e) {
+    @Override
+    public void mouseReleased(MouseEvent e) {
         if (e.getButton() == MouseEvent.BUTTON3) {
             Point curMousePos = e.getPoint();
@@ -419,5 +372,5 @@
 
         // we copy ctrl/alt/shift from the event just in case our global
-        // AWTEvent didn't make it through the security manager. Unclear
+        // keyDetector didn't make it through the security manager. Unclear
         // if that can ever happen but better be safe.
         updateKeyModifiers(e);
@@ -775,5 +728,5 @@
 
         // we copy ctrl/alt/shift from the event just in case our global
-        // AWTEvent didn't make it through the security manager. Unclear
+        // keyDetector didn't make it through the security manager. Unclear
         // if that can ever happen but better be safe.
         updateKeyModifiers(e);
@@ -941,5 +894,6 @@
      * Repaint on mouse exit so that the helper line goes away.
      */
-    @Override public void mouseExited(MouseEvent e) {
+    @Override
+    public void mouseExited(MouseEvent e) {
         if(!Main.map.mapView.isActiveLayerDrawable())
             return;
Index: trunk/src/org/openstreetmap/josm/actions/mapmode/ExtrudeAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/ExtrudeAction.java	(revision 7216)
+++ trunk/src/org/openstreetmap/josm/actions/mapmode/ExtrudeAction.java	(revision 7217)
@@ -6,19 +6,12 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import java.awt.AWTEvent;
 import java.awt.BasicStroke;
 import java.awt.Color;
-import java.awt.Component;
 import java.awt.Cursor;
 import java.awt.Graphics2D;
-import java.awt.KeyboardFocusManager;
 import java.awt.Point;
 import java.awt.Rectangle;
 import java.awt.Stroke;
-import java.awt.Toolkit;
-import java.awt.event.AWTEventListener;
 import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
 import java.awt.event.MouseEvent;
@@ -32,11 +25,6 @@
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Set;
-import java.util.TreeSet;
 import javax.swing.JCheckBoxMenuItem;
-import javax.swing.JFrame;
 import javax.swing.JMenuItem;
-import javax.swing.SwingUtilities;
-import javax.swing.Timer;
 
 import org.openstreetmap.josm.Main;
@@ -60,5 +48,7 @@
 import org.openstreetmap.josm.gui.layer.MapViewPaintable;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.gui.util.KeyPressReleaseListener;
 import org.openstreetmap.josm.gui.util.GuiHelper;
+import org.openstreetmap.josm.gui.util.ModifierListener;
 import org.openstreetmap.josm.tools.Geometry;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -68,5 +58,5 @@
  * Makes a rectangle from a line, or modifies a rectangle.
  */
-public class ExtrudeAction extends MapMode implements MapViewPaintable {
+public class ExtrudeAction extends MapMode implements MapViewPaintable, KeyPressReleaseListener, ModifierListener {
 
     enum Mode { extrude, translate, select, create_new, translate_node }
@@ -157,4 +147,6 @@
     /** The cursor for the 'alwaysCreateNodes' submode. */
     private final Cursor cursorCreateNodes;
+
+    private boolean ignoreNextKeyRelease;
 
     private static class ReferenceSegment {
@@ -225,13 +217,4 @@
                 tr("Mode: {0}", tr("Extrude Dual alignment")), KeyEvent.CHAR_UNDEFINED, Shortcut.NONE);
         useRepeatedShortcut = Main.pref.getBoolean("extrude.dualalign.toggleOnRepeatedX", true);
-        timer = new Timer(0, new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent ae) {
-                timer.stop();
-                if (set.remove(releaseEvent.getKeyCode())) {
-                    doKeyReleaseEvent(releaseEvent);
-                }
-            }
-        });
     }
 
@@ -294,9 +277,4 @@
         Main.map.mapView.addMouseListener(this);
         Main.map.mapView.addMouseMotionListener(this);
-        try {
-            Toolkit.getDefaultToolkit().addAWTEventListener(altKeyListener, AWTEvent.KEY_EVENT_MASK);
-        } catch (SecurityException ex) {
-            Main.warn(ex);
-        }
         initialMoveDelay = Main.pref.getInteger("edit.initial-move-delay",200);
         initialMoveThreshold = Main.pref.getInteger("extrude.initial-move-threshold", 1);
@@ -313,4 +291,7 @@
         ignoreSharedNodes = Main.pref.getBoolean("extrude.ignore-shared-nodes", true);
         dualAlignCheckboxMenuItem.getAction().setEnabled(true);
+        ignoreNextKeyRelease = true;
+        Main.map.keyDetector.addKeyListener(this);
+        Main.map.keyDetector.addModifierListener(this);
     }
 
@@ -321,9 +302,6 @@
         Main.map.mapView.removeTemporaryLayer(this);
         dualAlignCheckboxMenuItem.getAction().setEnabled(false);
-        try {
-            Toolkit.getDefaultToolkit().removeAWTEventListener(altKeyListener);
-        } catch (SecurityException ex) {
-            Main.warn(ex);
-        }
+        Main.map.keyDetector.removeKeyListener(this);
+        Main.map.keyDetector.removeModifierListener(this);
         super.exitMode();
     }
@@ -334,66 +312,30 @@
 
     /**
-     * This listener is used to indicate different modes via cursor when the Alt/Ctrl/Shift modifier is pressed,
-     * and for listening to dual alignment shortcuts.
-     */
-    private final AWTEventListener altKeyListener = new AWTEventListener() {
-        @Override
-        public void eventDispatched(AWTEvent e) {
-            if (!Main.isDisplayingMapView() || !Main.map.mapView.isActiveLayerDrawable())
-                return;
-            InputEvent ie = (InputEvent) e;
-            boolean alt = (ie.getModifiers() & (ActionEvent.ALT_MASK|InputEvent.ALT_GRAPH_MASK)) != 0;
-            boolean ctrl = (ie.getModifiers() & (ActionEvent.CTRL_MASK)) != 0;
-            boolean shift = (ie.getModifiers() & (ActionEvent.SHIFT_MASK)) != 0;
-            if (mode == Mode.select) {
-                Main.map.mapView.setNewCursor(ctrl ? cursorTranslate : alt ? cursorCreateNew : shift ? cursorCreateNodes : cursor, this);
-            }
-            if (e instanceof KeyEvent) {
-                KeyEvent ke = (KeyEvent) e;
-                if (dualAlignShortcut.isEvent(ke) || (useRepeatedShortcut && getShortcut().isEvent(ke))) {
-                    Component focused = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
-                    if (SwingUtilities.getWindowAncestor(focused) instanceof JFrame) {
-                        processKeyEvent(ke);
-                    }
-                }
-            }
+     * This method is called to indicate different modes via cursor when the Alt/Ctrl/Shift modifier is pressed,
+     */
+    @Override
+    public void modifiersChanged(int modifiers) {
+        if (!Main.isDisplayingMapView() || !Main.map.mapView.isActiveLayerDrawable())
+            return;
+        updateKeyModifiers(modifiers);
+        if (mode == Mode.select) {
+            Main.map.mapView.setNewCursor(ctrl ? cursorTranslate : alt ? cursorCreateNew : shift ? cursorCreateNodes : cursor, this);
         }
     };
 
-    // events for crossplatform key holding processing
-    // thanks to http://www.arco.in-berlin.de/keyevent.html
-    private final Set<Integer> set = new TreeSet<Integer>();
-    private KeyEvent releaseEvent;
-    private Timer timer;
-    private void processKeyEvent(KeyEvent e) {
+    @Override
+    public void doKeyPressed(KeyEvent e) {
+    }
+
+    @Override
+    public void doKeyReleased(KeyEvent e) {
         if (!dualAlignShortcut.isEvent(e) && !(useRepeatedShortcut && getShortcut().isEvent(e)))
-            return;
-
-        if (e.getID() == KeyEvent.KEY_PRESSED) {
-            if (timer.isRunning()) {
-                timer.stop();
-            } else if (set.add((e.getKeyCode()))) {
-                doKeyPressEvent(e);
-            }
-        } else if (e.getID() == KeyEvent.KEY_RELEASED) {
-            if (timer.isRunning()) {
-                timer.stop();
-                if (set.remove(e.getKeyCode())) {
-                    doKeyReleaseEvent(e);
-                }
-            } else {
-                releaseEvent = e;
-                timer.restart();
-            }
-        }
-    }
-
-    private void doKeyPressEvent(KeyEvent e) {
-    }
-
-    private void doKeyReleaseEvent(KeyEvent e) {
-        toggleDualAlign();
-    }
-
+             return;
+        if (ignoreNextKeyRelease) {
+            ignoreNextKeyRelease = false;
+        } else {
+            toggleDualAlign();
+        }
+    }
     /**
      * Toggles dual alignment mode.
Index: trunk/src/org/openstreetmap/josm/actions/mapmode/ImproveWayAccuracyAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/ImproveWayAccuracyAction.java	(revision 7216)
+++ trunk/src/org/openstreetmap/josm/actions/mapmode/ImproveWayAccuracyAction.java	(revision 7217)
@@ -6,5 +6,4 @@
 import static org.openstreetmap.josm.tools.I18n.trn;
 
-import java.awt.AWTEvent;
 import java.awt.Color;
 import java.awt.Cursor;
@@ -12,7 +11,4 @@
 import java.awt.Point;
 import java.awt.Stroke;
-import java.awt.Toolkit;
-import java.awt.event.AWTEventListener;
-import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
 import java.awt.event.MouseEvent;
@@ -47,4 +43,5 @@
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.util.GuiHelper;
+import org.openstreetmap.josm.gui.util.ModifierListener;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Pair;
@@ -55,5 +52,5 @@
  */
 public class ImproveWayAccuracyAction extends MapMode implements MapViewPaintable,
-        SelectionChangedListener, AWTEventListener {
+        SelectionChangedListener, ModifierListener {
 
     enum State {
@@ -145,10 +142,5 @@
         DataSet.addSelectionListener(this);
 
-        try {
-            Toolkit.getDefaultToolkit().addAWTEventListener(this,
-                    AWTEvent.KEY_EVENT_MASK);
-        } catch (SecurityException ex) {
-            Main.warn(ex);
-        }
+        Main.map.keyDetector.addModifierListener(this);
     }
 
@@ -162,10 +154,5 @@
         DataSet.removeSelectionListener(this);
 
-        try {
-            Toolkit.getDefaultToolkit().removeAWTEventListener(this);
-        } catch (SecurityException ex) {
-            Main.warn(ex);
-        }
-
+        Main.map.keyDetector.addModifierListener(this);
         Main.map.mapView.repaint();
     }
@@ -321,9 +308,9 @@
     // -------------------------------------------------------------------------
     @Override
-    public void eventDispatched(AWTEvent event) {
+    public void modifiersChanged(int modifiers) {
         if (!Main.isDisplayingMapView() || !Main.map.mapView.isActiveLayerDrawable()) {
             return;
         }
-        updateKeyModifiers((InputEvent) event);
+        updateKeyModifiers(modifiers);
         updateCursorDependentObjectsIfNeeded();
         updateCursor();
Index: trunk/src/org/openstreetmap/josm/actions/mapmode/ParallelWayAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/ParallelWayAction.java	(revision 7216)
+++ trunk/src/org/openstreetmap/josm/actions/mapmode/ParallelWayAction.java	(revision 7217)
@@ -6,5 +6,4 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import java.awt.AWTEvent;
 import java.awt.Color;
 import java.awt.Cursor;
@@ -12,7 +11,4 @@
 import java.awt.Point;
 import java.awt.Stroke;
-import java.awt.Toolkit;
-import java.awt.event.AWTEventListener;
-import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
 import java.awt.event.MouseEvent;
@@ -41,4 +37,5 @@
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.util.GuiHelper;
+import org.openstreetmap.josm.gui.util.ModifierListener;
 import org.openstreetmap.josm.tools.Geometry;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -84,5 +81,5 @@
  * @author Ole Jørgen Brønner (olejorgenb)
  */
-public class ParallelWayAction extends MapMode implements AWTEventListener, MapViewPaintable, PreferenceChangedListener {
+public class ParallelWayAction extends MapMode implements ModifierListener, MapViewPaintable, PreferenceChangedListener {
 
     private enum Mode {
@@ -161,9 +158,5 @@
 
         //// Needed to update the mouse cursor if modifiers are changed when the mouse is motionless
-        try {
-            Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK);
-        } catch (SecurityException ex) {
-            Main.warn(ex);
-        }
+        Main.map.keyDetector.addModifierListener(this);
         sourceWays = new LinkedHashSet<>(getCurrentDataSet().getSelectedWays());
         for (Way w : sourceWays) {
@@ -181,9 +174,5 @@
         Main.map.statusLine.setDist(-1);
         Main.map.statusLine.repaint();
-        try {
-            Toolkit.getDefaultToolkit().removeAWTEventListener(this);
-        } catch (SecurityException ex) {
-            Main.warn(ex);
-        }
+        Main.map.keyDetector.removeModifierListener(this);
         removeWayHighlighting(sourceWays);
         pWays = null;
@@ -238,10 +227,10 @@
 
     @Override
-    public void eventDispatched(AWTEvent e) {
+    public void modifiersChanged(int modifiers) {
         if (Main.map == null || mv == null || !mv.isActiveLayerDrawable())
             return;
 
         // Should only get InputEvents due to the mask in enterMode
-        if (updateModifiersState((InputEvent) e)) {
+        if (updateModifiersState(modifiers)) {
             updateStatusLine();
             updateCursor();
@@ -249,7 +238,7 @@
     }
 
-    private boolean updateModifiersState(InputEvent e) {
+    private boolean updateModifiersState(int modifiers) {
         boolean oldAlt = alt, oldShift = shift, oldCtrl = ctrl;
-        updateKeyModifiers(e);
+        updateKeyModifiers(modifiers);
         return (oldAlt != alt || oldShift != shift || oldCtrl != ctrl);
     }
@@ -302,5 +291,5 @@
     public void mousePressed(MouseEvent e) {
         requestFocusInMapView();
-        updateModifiersState(e);
+        updateModifiersState(e.getModifiers());
         // Other buttons are off limit, but we still get events.
         if (e.getButton() != MouseEvent.BUTTON1)
@@ -327,5 +316,5 @@
     @Override
     public void mouseReleased(MouseEvent e) {
-        updateModifiersState(e);
+        updateModifiersState(e.getModifiers());
         // Other buttons are off limit, but we still get events.
         if (e.getButton() != MouseEvent.BUTTON1)
@@ -382,5 +371,5 @@
             return;
 
-        boolean modifiersChanged = updateModifiersState(e);
+        boolean modifiersChanged = updateModifiersState(e.getModifiers());
         updateFlagsChangeableAlways();
 
Index: trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 7216)
+++ trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 7217)
@@ -6,13 +6,9 @@
 import static org.openstreetmap.josm.tools.I18n.trn;
 
-import java.awt.AWTEvent;
 import java.awt.Cursor;
 import java.awt.Point;
 import java.awt.Rectangle;
-import java.awt.Toolkit;
-import java.awt.event.AWTEventListener;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
 import java.awt.event.MouseEvent;
@@ -53,4 +49,5 @@
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.util.GuiHelper;
+import org.openstreetmap.josm.gui.util.ModifierListener;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Pair;
@@ -68,5 +65,5 @@
  * feature "selection remove" is disabled on this platform.
  */
-public class SelectAction extends MapMode implements AWTEventListener, SelectionEnded {
+public class SelectAction extends MapMode implements ModifierListener, SelectionEnded {
     // "select" means the selection rectangle and "move" means either dragging
     // or select if no mouse movement occurs (i.e. just clicking)
@@ -188,9 +185,5 @@
         virtualManager.init();
         // This is required to update the cursors when ctrl/shift/alt is pressed
-        try {
-            Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK);
-        } catch (SecurityException ex) {
-            Main.warn(ex);
-        }
+        Main.map.keyDetector.addModifierListener(this);
     }
 
@@ -202,9 +195,5 @@
         mv.removeMouseMotionListener(this);
         mv.setVirtualNodesEnabled(false);
-        try {
-            Toolkit.getDefaultToolkit().removeAWTEventListener(this);
-        } catch (SecurityException ex) {
-            Main.warn(ex);
-        }
+        Main.map.keyDetector.removeModifierListener(this);
         removeHighlighting();
     }
@@ -212,18 +201,8 @@
     int previousModifiers;
 
-     /**
-     * This is called whenever the keyboard modifier status changes
-     */
     @Override
-    public void eventDispatched(AWTEvent e) {
-        if(oldEvent == null)
-            return;
-        // We don't have a mouse event, so we pass the old mouse event but the
-        // new modifiers.
-        int modif = ((InputEvent) e).getModifiers();
-        if (previousModifiers == modif)
-            return;
-        previousModifiers = modif;
-        if(giveUserFeedback(oldEvent, ((InputEvent) e).getModifiers())) {
+    public void modifiersChanged(int modifiers) {
+        if (!Main.isDisplayingMapView() || oldEvent==null) return;
+        if(giveUserFeedback(oldEvent, modifiers)) {
             mv.repaint();
         }
Index: trunk/src/org/openstreetmap/josm/gui/MapFrame.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MapFrame.java	(revision 7216)
+++ trunk/src/org/openstreetmap/josm/gui/MapFrame.java	(revision 7217)
@@ -73,4 +73,5 @@
 import org.openstreetmap.josm.gui.dialogs.properties.PropertiesDialog;
 import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.util.AdvancedKeyPressDetector;
 import org.openstreetmap.josm.tools.Destroyable;
 import org.openstreetmap.josm.tools.GBC;
@@ -95,4 +96,9 @@
      */
     public final MapView mapView;
+
+    /**
+     * This object allows to detect key press and release events
+     */
+    public final AdvancedKeyPressDetector keyDetector = new AdvancedKeyPressDetector();
 
     /**
@@ -245,4 +251,6 @@
             for (JComponent c: allMapModeButtons) c.setFocusTraversalKeysEnabled(false);
         }
+
+        keyDetector.register();
     }
 
@@ -290,4 +298,5 @@
         statusLine.destroy();
         mapView.destroy();
+        keyDetector.unregister();
     }
 
