diff --git a/src/backend/curses/n.rs b/src/backend/curses/n.rs index 473d774..2f8332e 100644 --- a/src/backend/curses/n.rs +++ b/src/backend/curses/n.rs @@ -89,18 +89,19 @@ impl InputParser { if ncurses::getmouse(&mut mevent as *mut ncurses::MEVENT) == ncurses::OK { - // eprintln!("{:032b}", mevent.bstate); // Currently unused + let _ctrl = (mevent.bstate & ncurses::BUTTON_CTRL as mmask_t) != 0; let _shift = (mevent.bstate & ncurses::BUTTON_SHIFT as mmask_t) != 0; let _alt = (mevent.bstate & ncurses::BUTTON_ALT as mmask_t) != 0; - let _ctrl = (mevent.bstate & ncurses::BUTTON_CTRL as mmask_t) != 0; + // Keep the base state, without the modifiers mevent.bstate &= !(ncurses::BUTTON_SHIFT | ncurses::BUTTON_ALT | ncurses::BUTTON_CTRL) as mmask_t; + // This makes a full `Event` from a `MouseEvent`. let make_event = |event| Event::Mouse { offset: Vec2::zero(), position: Vec2::new(mevent.x as usize, mevent.y as usize), diff --git a/src/views/scroll_view.rs b/src/views/scroll_view.rs index 106c9c5..ef56564 100644 --- a/src/views/scroll_view.rs +++ b/src/views/scroll_view.rs @@ -189,7 +189,11 @@ where /// Returns the size available for the child view. fn available_size(&self) -> Vec2 { - self.last_size.saturating_sub(self.scrollbar_size()) + if self.show_scrollbars { + self.last_size.saturating_sub(self.scrollbar_size()) + } else { + self.last_size + } } /// Compute the size we would need. @@ -231,20 +235,21 @@ where /// /// Returns `true` if the event was consumed. fn start_drag(&mut self, position: Vec2) -> bool { + // For each scrollbar, how far it is. let scrollbar_pos = self.last_size.saturating_sub((1, 1)); - let grabbed = scrollbar_pos.zip_map(position, |s, p| s == p); + // This is true for Y if we grabbed the vertical scrollbar + let grabbed = scrollbar_pos.zip_map(position, |s, p| s == p).swap(); let lengths = self.scrollbar_thumb_lengths(); let offsets = self.scrollbar_thumb_offsets(lengths); - // See if we grabbed one of the scrollbars + // Iterate on axises, and keep the one we grabbed. for (orientation, pos, length, offset) in XY::zip4(Orientation::pair(), position, lengths, offsets) - .zip(grabbed.swap()) + .keep(grabbed.and(self.enabled)) .into_iter() - .filter(|&(_, grab)| grab) - .map(|(x, _)| x) + .filter_map(|x| x) { if pos >= offset && pos < offset + length { // We grabbed the thumb! Now scroll from that position. @@ -262,7 +267,9 @@ where false } + /// Called when a mouse drag is detected. fn drag(&mut self, position: Vec2) { + // Only do something if we grabbed something before. if let Some((orientation, grab)) = self.thumb_grab { self.scroll_to_thumb( orientation, @@ -466,10 +473,11 @@ where event: MouseEvent::Press(MouseButton::Left), position, offset, - } if position - .checked_sub(offset) - .map(|position| self.start_drag(position)) - .unwrap_or(false) => + } if self.show_scrollbars + && position + .checked_sub(offset) + .map(|position| self.start_drag(position)) + .unwrap_or(false) => { // Just consume the event. } @@ -477,7 +485,8 @@ where event: MouseEvent::Hold(MouseButton::Left), position, offset, - } => { + } if self.show_scrollbars => + { let position = position.saturating_sub(offset); self.drag(position); } diff --git a/src/xy.rs b/src/xy.rs index aa7570d..f0e0989 100644 --- a/src/xy.rs +++ b/src/xy.rs @@ -140,6 +140,11 @@ impl XY { { XY::new(f(self.x, other.x), f(self.y, other.y)) } + + /// For each axis, keep the element from `self` if `keep` is `true`. + pub fn keep(self, keep: XY) -> XY> { + keep.select(self) + } } impl XY { @@ -192,6 +197,16 @@ impl XY { pub fn select_or(&self, if_true: XY, if_false: XY) -> XY { self.select(if_true).unwrap_or(if_false) } + + /// Returns a term-by-term AND operation. + pub fn and(&self, other: Self) -> Self { + self.zip_map(other, |s, o| s && o) + } + + /// Returns a term-by-term OR operation. + pub fn or(&self, other: Self) -> Self { + self.zip_map(other, |s, o| s || o) + } } impl XY {