diff --git a/src/display/selection.js b/src/display/selection.js
index ba6feb8f14b98d213bd096e504cc1cda14f182f0..dca96a442b4977204fd0c89406eb08caeb36878c 100644
--- a/src/display/selection.js
+++ b/src/display/selection.js
@@ -54,6 +54,7 @@ function drawSelectionRange(cm, range, output) {
   let fragment = document.createDocumentFragment()
   let padding = paddingH(cm.display), leftSide = padding.left
   let rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right
+  let docLTR = doc.direction == "ltr"
 
   function add(left, top, width, bottom) {
     if (top < 0) top = 0
@@ -72,42 +73,43 @@ function drawSelectionRange(cm, range, output) {
       return charCoords(cm, Pos(line, ch), "div", lineObj, bias)
     }
 
+    function wrapX(pos, dir, side) {
+      let extent = wrappedLineExtentChar(cm, lineObj, null, pos)
+      let prop = (dir == "ltr") == (side == "after") ? "left" : "right"
+      let ch = side == "after" ? extent.begin : extent.end - (/\s/.test(lineObj.text.charAt(extent.end - 1)) ? 2 : 1)
+      return coords(ch, prop)[prop]
+    }
+
     let order = getOrder(lineObj, doc.direction)
     iterateBidiSections(order, fromArg || 0, toArg == null ? lineLen : toArg, (from, to, dir, i) => {
-      let fromPos = coords(from, dir == "ltr" ? "left" : "right")
-      let toPos = coords(to - 1, dir == "ltr" ? "right" : "left")
-      if (dir == "ltr") {
-        let fromLeft = fromArg == null && from == 0 ? leftSide : fromPos.left
-        let toRight = toArg == null && to == lineLen ? rightSide : toPos.right
-        if (toPos.top - fromPos.top <= 3) { // Single line
-          add(fromLeft, toPos.top, toRight - fromLeft, toPos.bottom)
-        } else { // Multiple lines
-          add(fromLeft, fromPos.top, null, fromPos.bottom)
-          if (fromPos.bottom < toPos.top) add(leftSide, fromPos.bottom, null, toPos.top)
-          add(leftSide, toPos.top, toPos.right, toPos.bottom)
-        }
-      } else if (from < to) { // RTL
-        let fromRight = fromArg == null && from == 0 ? rightSide : fromPos.right
-        let toLeft = toArg == null && to == lineLen ? leftSide : toPos.left
-        if (toPos.top - fromPos.top <= 3) { // Single line
-          add(toLeft, toPos.top, fromRight - toLeft, toPos.bottom)
-        } else { // Multiple lines
-          let topLeft = leftSide
-          if (i) {
-            let topEnd = wrappedLineExtentChar(cm, lineObj, null, from).end
-            // The coordinates returned for an RTL wrapped space tend to
-            // be complete bogus, so try to skip that here.
-            topLeft = coords(topEnd - (/\s/.test(lineObj.text.charAt(topEnd - 1)) ? 2 : 1), "left").left
-          }
-          add(topLeft, fromPos.top, fromRight - topLeft, fromPos.bottom)
-          if (fromPos.bottom < toPos.top) add(leftSide, fromPos.bottom, null, toPos.top)
-          let botWidth = null
-          if (i < order.length  - 1 || true) {
-            let botStart = wrappedLineExtentChar(cm, lineObj, null, to).begin
-            botWidth = coords(botStart, "right").right - toLeft
-          }
-          add(toLeft, toPos.top, botWidth, toPos.bottom)
+      let ltr = dir == "ltr"
+      let fromPos = coords(from, ltr ? "left" : "right")
+      let toPos = coords(to - 1, ltr ? "right" : "left")
+
+      let openStart = fromArg == null && from == 0, openEnd = toArg == null && to == lineLen
+      let first = i == 0, last = !order || i == order.length - 1
+      if (toPos.top - fromPos.top <= 3) { // Single line
+        let openLeft = (docLTR ? openStart : openEnd) && first
+        let openRight = (docLTR ? openEnd : openStart) && last
+        let left = openLeft ? leftSide : (ltr ? fromPos : toPos).left
+        let right = openRight ? rightSide : (ltr ? toPos : fromPos).right
+        add(left, fromPos.top, right - left, fromPos.bottom)
+      } else { // Multiple lines
+        let topLeft, topRight, botLeft, botRight
+        if (ltr) {
+          topLeft = docLTR && openStart && first ? leftSide : fromPos.left
+          topRight = docLTR ? rightSide : wrapX(from, dir, "before")
+          botLeft = docLTR ? leftSide : wrapX(to, dir, "after")
+          botRight = docLTR && openEnd && last ? rightSide : toPos.right
+        } else {
+          topLeft = !docLTR ? leftSide : wrapX(from, dir, "before")
+          topRight = !docLTR && openStart && first ? rightSide : fromPos.right
+          botLeft = !docLTR && openEnd && last ? leftSide : toPos.left
+          botRight = !docLTR ? rightSide : wrapX(to, dir, "after")
         }
+        add(topLeft, fromPos.top, topRight - topLeft, fromPos.bottom)
+        if (fromPos.bottom < toPos.top) add(leftSide, fromPos.bottom, null, toPos.top)
+        add(botLeft, toPos.top, botRight - botLeft, toPos.bottom)
       }
 
       if (!start || cmpCoords(fromPos, start) < 0) start = fromPos