about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/local/pager.nim88
-rw-r--r--src/local/select.nim17
2 files changed, 60 insertions, 45 deletions
diff --git a/src/local/pager.nim b/src/local/pager.nim
index b378bbba..349b9006 100644
--- a/src/local/pager.nim
+++ b/src/local/pager.nim
@@ -636,6 +636,7 @@ proc handleMouseInput(pager: Pager; input: MouseInput; container: Container) =
       container.setCursorXY(container.fromx + input.col,
         container.fromy + input.row)
       pager.openMenu(input.col, input.row)
+      pager.menu.unselect()
   of mibThumbInner:
     if input.t == mitPress:
       discard pager.evalAction("cmd.pager.prevBuffer", 0)
@@ -646,54 +647,55 @@ proc handleMouseInput(pager: Pager; input: MouseInput; container: Container) =
 
 proc handleMouseInput(pager: Pager; input: MouseInput; select: Select) =
   let y = select.fromy + input.row - select.y - 1 # one off because of border
-  case input.button
-  of mibRight:
-    if (input.col, input.row) != pager.pressed:
-      # Prevent immediate movement/submission in case the menu appeared under
-      # the cursor.
-      select.setCursorY(y)
-    case input.t
-    of mitPress:
-      # Do not include borders, so that a double right click closes the
-      # menu again.
-      if input.row notin select.y + 1 ..< select.y + select.height - 1 or
-          input.col notin select.x + 1 ..< select.x + select.width - 1:
-        pager.blockTillRelease = true
-        select.cursorLeft()
-    of mitRelease:
-      if input.row in select.y + 1 ..< select.y + select.height - 1 and
-          input.col in select.x + 1 ..< select.x + select.width - 1 and
-          (input.col, input.row) != pager.pressed:
-        select.click()
-      # forget about where we started once btn3 is released
-      pager.pressed = (-1, -1)
-    of mitMove: discard
-  of mibLeft:
-    case input.t
-    of mitPress:
-      if input.row notin select.y ..< select.y + select.height or
-          input.col notin select.x ..< select.x + select.width:
-        # clicked outside the select
-        pager.blockTillRelease = true
-        select.cursorLeft()
-    of mitRelease:
-      let at = (input.col, input.row)
-      if at == pager.pressed and
-          (input.row in select.y + 1 ..< select.y + select.height - 1 and
-            input.col in select.x + 1 ..< select.x + select.width - 1 or
-          select.multiple and at == (select.x, select.y)):
-        # clicked inside the select
+  if input.button in {mibRight, mibLeft}:
+    # Note: "not inside and not outside" is a valid state, and it
+    # represents the mouse being above the border.
+    let inside = input.row in select.y + 1 ..< select.y + select.height - 1 and
+      input.col in select.x + 1 ..< select.x + select.width - 1
+    let outside = input.row notin select.y ..< select.y + select.height or
+      input.col notin select.x ..< select.x + select.width
+    if input.button == mibRight:
+      if not inside:
+        select.unselect()
+      elif (input.col, input.row) != pager.pressed:
+        # Prevent immediate movement/submission in case the menu appeared under
+        # the cursor.
         select.setCursorY(y)
-        select.click()
-    of mitMove: discard
-  else: discard
+      case input.t
+      of mitPress:
+        # Do not include borders, so that a double right click closes the
+        # menu again.
+        if not inside:
+          pager.blockTillRelease = true
+          select.cursorLeft()
+      of mitRelease:
+        if inside and (input.col, input.row) != pager.pressed:
+          select.click()
+        elif outside:
+          select.cursorLeft()
+        # forget about where we started once btn3 is released
+        pager.pressed = (-1, -1)
+      of mitMove: discard
+    else: # mibLeft
+      case input.t
+      of mitPress:
+        if outside: # clicked outside the select
+          pager.blockTillRelease = true
+          select.cursorLeft()
+      of mitRelease:
+        let at = (input.col, input.row)
+        if at == pager.pressed and
+            (inside or select.multiple and at == (select.x, select.y)):
+          # clicked inside the select
+          select.setCursorY(y)
+          select.click()
+      of mitMove: discard
 
 proc handleMouseInput(pager: Pager; input: MouseInput) =
   if pager.blockTillRelease:
-    if input.t == mitRelease:
-      pager.blockTillRelease = false
-    else:
+    if input.t != mitRelease:
       return
+    pager.blockTillRelease = false
   if pager.menu != nil:
     pager.handleMouseInput(input, pager.menu)
   elif (let container = pager.container; container != nil):
diff --git a/src/local/select.nim b/src/local/select.nim
index b8e19d6c..f98fb944 100644
--- a/src/local/select.nim
+++ b/src/local/select.nim
@@ -27,6 +27,7 @@ type
     x*: int
     y*: int
     redraw*: bool
+    unselected*: bool
     bpos: seq[int]
     opaque: RootRef
     finishImpl: SelectFinish
@@ -53,12 +54,17 @@ proc setCursorY*(select: Select; y: int) =
   if not select.multiple:
     y = max(y, 0)
   if select.options[max(y, 0)].nop:
+    if not select.unselected:
+      select.unselected = true
+      select.queueDraw()
     return
   if select.fromy > y:
     select.setFromY(y)
   if select.fromy + select.maxh <= y:
     select.setFromY(y - select.maxh + 1)
   select.cursory = y
+  if select.unselected:
+    select.unselected = false
   select.queueDraw()
 
 proc getCursorX*(select: Select): int =
@@ -139,7 +145,8 @@ proc submit(select: Select) {.jsfunc.} =
   select.finishImpl(select.opaque, select, srSubmit)
 
 proc click*(select: Select) {.jsfunc.} =
-  if select.cursory >= 0 and select.cursory < select.options.len and
+  if select.unselected or
+      select.cursory >= 0 and select.cursory < select.options.len and
       select.options[select.cursory].nop:
     discard
   elif not select.multiple:
@@ -233,6 +240,11 @@ proc popCursorPos*(select: Select; nojump = false) =
   if not nojump:
     select.queueDraw()
 
+proc unselect*(select: Select) =
+  if not select.unselected:
+    select.unselected = true
+    select.queueDraw()
+
 const HorizontalBar = "\u2500"
 const VerticalBar = "\u2502"
 const CornerTopLeft = "\u250C"
@@ -325,7 +337,8 @@ proc drawSelect*(select: Select; display: var FixedGrid) =
     let dls = y * display.width
     if (select.multiple and k < select.selected.len and
           select.selected[k] == i or
-        not select.multiple and select.getCursorY() == y):
+        not select.multiple and select.getCursorY() == y and
+          not select.unselected):
       format.flags.incl(ffReverse)
       inc k
     else: