diff --git a/lib/codemirror.js b/lib/codemirror.js
index <HASH>..<HASH> 100644
--- a/lib/codemirror.js
+++ b/lib/codemirror.js
@@ -926,9 +926,9 @@ var CodeMirror = (function() {
     function updateCursor() {
       var head = sel.inverted ? sel.from : sel.to, lh = textHeight();
       var pos = localCoords(head, true);
-      var globalY = pos.y + displayOffset * textHeight();
-      inputDiv.style.top = Math.max(Math.min(globalY, scroller.offsetHeight), 0) + "px";
-      inputDiv.style.left = pos.x + "px";
+      var wrapOff = eltOffset(wrapper), lineOff = eltOffset(lineDiv);
+      inputDiv.style.top = (pos.y + lineOff.top - wrapOff.top) + "px";
+      inputDiv.style.left = (pos.x + lineOff.left - wrapOff.left) + "px";
       if (posEq(sel.from, sel.to)) {
         cursor.style.top = pos.y + "px";
         cursor.style.left = (options.lineWrapping ? Math.min(pos.x, lineSpace.offsetWidth) : pos.x) + "px";
Be more precise about hidden input placement

This reduces scrolling artifacts caused by the input being scrolled into
view.