Patch 9.0.0906
Problem:    Mouse scroll code is not optimal.
Solution:   Properly organise Normal mode, Insert mode and common code.
            (Christopher Plewright, closes #11572)
Files:      src/mouse.c


*** ../vim-9.0.0905/src/mouse.c 2022-11-18 17:53:29.761863978 +0000
--- src/mouse.c 2022-11-19 10:43:28.646691926 +0000
***************
*** 1102,1109 ****
  }
  
  /*
!  * Implementation for scrolling in Insert mode in direction "dir", which is 
one
!  * of the MSCR_ values.
   */
      void
  ins_mousescroll(int dir)
--- 1102,1182 ----
  }
  
  /*
!  * Common mouse wheel scrolling, shared between Insert mode and NV modes.
!  * Default action is to scroll mouse_vert_step lines (or mouse_hor_step 
columns
!  * depending on the scroll direction) or one page when Shift or Ctrl is used.
!  * Direction is indicated by "cap->arg":
!  *    K_MOUSEUP    - MSCR_UP
!  *    K_MOUSEDOWN  - MSCR_DOWN
!  *    K_MOUSELEFT  - MSCR_LEFT
!  *    K_MOUSERIGHT - MSCR_RIGHT
!  * "curwin" may have been changed to the window that should be scrolled and
!  * differ from the window that actually has focus.
!  */
!     static void
! do_mousescroll(cmdarg_T *cap)
! {
!     int shift_or_ctrl = mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL);
! 
! #ifdef FEAT_TERMINAL
!     if (term_use_loop())
!       // This window is a terminal window, send the mouse event there.
!       // Set "typed" to FALSE to avoid an endless loop.
!       send_keys_to_term(curbuf->b_term, cap->cmdchar, mod_mask, FALSE);
!     else
! #endif
!     if (cap->arg == MSCR_UP || cap->arg == MSCR_DOWN)
!     {
!       // Vertical scrolling
!       if (!(State & MODE_INSERT) && (mouse_vert_step < 0 || shift_or_ctrl))
!       {
!           // whole page up or down
!           onepage(cap->arg == MSCR_UP ? FORWARD : BACKWARD, 1L);
!       }
!       else
!       {
!           if (mouse_vert_step < 0 || shift_or_ctrl)
!           {
!               // whole page up or down
!               cap->count1 = (long)(curwin->w_botline - curwin->w_topline);
!           }
!           // Don't scroll more than half the window height.
!           else if (curwin->w_height < mouse_vert_step * 2)
!           {
!               cap->count1 = curwin->w_height / 2;
!               if (cap->count1 == 0)
!                   cap->count1 = 1;
!           }
!           else
!           {
!               cap->count1 = mouse_vert_step;
!           }
!           cap->count0 = cap->count1;
!           nv_scroll_line(cap);
!       }
! 
! #ifdef FEAT_PROP_POPUP
!       if (WIN_IS_POPUP(curwin))
!           popup_set_firstline(curwin);
! #endif
!     }
!     else
!     {
!       // Horizontal scrolling
!       long step = (mouse_hor_step < 0 || shift_or_ctrl)
!                                           ? curwin->w_width : mouse_hor_step;
!       long leftcol = curwin->w_leftcol
!                                    + (cap->arg == MSCR_RIGHT ? -step : step);
!       if (leftcol < 0)
!           leftcol = 0;
!       do_mousescroll_horiz((long_u)leftcol);
!     }
!     may_trigger_winscrolled();
! }
! 
! /*
!  * Insert mode implementation for scrolling in direction "dir", which is
!  * one of the MSCR_ values.
   */
      void
  ins_mousescroll(int dir)
***************
*** 1133,1150 ****
            siemsg("Invalid ins_mousescroll() argument: %d", dir);
      }
  
!     win_T *wp = curwin;
      if (mouse_row >= 0 && mouse_col >= 0)
      {
        // Find the window at the mouse pointer coordinates.
        int row = mouse_row;
        int col = mouse_col;
!       wp = mouse_find_win(&row, &col, FIND_POPUP);
!       if (wp == NULL)
            return;
      }
  
!     if (wp == curwin)
      {
        // Don't scroll the current window if the popup menu is visible.
        if (pum_visible())
--- 1206,1228 ----
            siemsg("Invalid ins_mousescroll() argument: %d", dir);
      }
  
!     win_T *old_curwin = curwin;
      if (mouse_row >= 0 && mouse_col >= 0)
      {
        // Find the window at the mouse pointer coordinates.
+       // NOTE: Must restore "curwin" to "old_curwin" before returning!
        int row = mouse_row;
        int col = mouse_col;
!       curwin = mouse_find_win(&row, &col, FIND_POPUP);
!       if (curwin == NULL)
!       {
!           curwin = old_curwin;
            return;
+       }
+       curbuf = curwin->w_buffer;
      }
  
!     if (curwin == old_curwin)
      {
        // Don't scroll the current window if the popup menu is visible.
        if (pum_visible())
***************
*** 1153,1169 ****
        undisplay_dollar();
      }
  
!     linenr_T  orig_topline = wp->w_topline;
!     colnr_T   orig_leftcol = wp->w_leftcol;
      pos_T     orig_cursor = curwin->w_cursor;
  
!     // The scrolling works almost the same way as in Normal mode.
!     nv_mousescroll(&cap);
  
      // If the window actually scrolled and the popup menu may overlay the
      // window, need to redraw it.
!     if ((orig_topline != wp->w_topline || orig_leftcol != wp->w_leftcol)
!           && pum_visible())
      {
        // TODO: Would be more efficient to only redraw the windows that are
        // overlapped by the popup menu.
--- 1231,1253 ----
        undisplay_dollar();
      }
  
!     linenr_T  orig_topline = curwin->w_topline;
!     colnr_T   orig_leftcol = curwin->w_leftcol;
      pos_T     orig_cursor = curwin->w_cursor;
  
!     // Call the common mouse scroll function shared with other modes.
!     do_mousescroll(&cap);
! 
!     int did_scroll = (orig_topline != curwin->w_topline
!                  || orig_leftcol != curwin->w_leftcol);
! 
!     curwin->w_redr_status = TRUE;
!     curwin = old_curwin;
!     curbuf = curwin->w_buffer;
  
      // If the window actually scrolled and the popup menu may overlay the
      // window, need to redraw it.
!     if (did_scroll && pum_visible())
      {
        // TODO: Would be more efficient to only redraw the windows that are
        // overlapped by the popup menu.
***************
*** 2094,2107 ****
  }
  
  /*
!  * Mouse scroll wheel: Default action is to scroll mouse_vert_step lines (or
!  * mouse_hor_step, depending on the scroll direction), or one page when Shift
!  * or Ctrl is used.
!  * Direction is indicated by "cap->arg":
!  *    K_MOUSEUP    - MSCR_UP
!  *    K_MOUSEDOWN  - MSCR_DOWN
!  *    K_MOUSELEFT  - MSCR_LEFT
!  *    K_MOUSERIGHT - MSCR_RIGHT
   */
      void
  nv_mousescroll(cmdarg_T *cap)
--- 2178,2185 ----
  }
  
  /*
!  * Normal and Visual modes implementation for scrolling in direction
!  * "cap->arg", which is one of the MSCR_ values.
   */
      void
  nv_mousescroll(cmdarg_T *cap)
***************
*** 2111,2195 ****
      if (mouse_row >= 0 && mouse_col >= 0)
      {
        // Find the window at the mouse pointer coordinates.
        int row = mouse_row;
        int col = mouse_col;
!       win_T *wp = mouse_find_win(&row, &col, FIND_POPUP);
!       if (wp == NULL)
            return;
  #ifdef FEAT_PROP_POPUP
!       if (WIN_IS_POPUP(wp) && !wp->w_has_scrollbar)
            // cannot scroll this popup window
            return;
  #endif
-       // NOTE: Must restore "curwin" to "old_curwin" before returning!
-       curwin = wp;
        curbuf = curwin->w_buffer;
      }
  
!     int shift_or_ctrl = mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL);
! 
! #ifdef FEAT_TERMINAL
!     if (term_use_loop())
!       // This window is a terminal window, send the mouse event there.
!       // Set "typed" to FALSE to avoid an endless loop.
!       send_keys_to_term(curbuf->b_term, cap->cmdchar, mod_mask, FALSE);
!     else
! #endif
!     if (cap->arg == MSCR_UP || cap->arg == MSCR_DOWN)
!     {
!       // Vertical scrolling
!       if (!(State & MODE_INSERT) && (mouse_vert_step < 0 || shift_or_ctrl))
!       {
!           // whole page up or down
!           onepage(cap->arg == MSCR_UP ? FORWARD : BACKWARD, 1L);
!       }
!       else
!       {
!           if (mouse_vert_step < 0 || shift_or_ctrl)
!           {
!               // whole page up or down
!               cap->count1 = (long)(curwin->w_botline - curwin->w_topline);
!           }
!           // Don't scroll more than half the window height.
!           else if (curwin->w_height < mouse_vert_step * 2)
!           {
!               cap->count1 = curwin->w_height / 2;
!               if (cap->count1 == 0)
!                   cap->count1 = 1;
!           }
!           else
!           {
!               cap->count1 = mouse_vert_step;
!           }
!           cap->count0 = cap->count1;
!           nv_scroll_line(cap);
!       }
! 
! #ifdef FEAT_PROP_POPUP
!       if (WIN_IS_POPUP(curwin))
!           popup_set_firstline(curwin);
! #endif
!     }
!     else
!     {
!       // Horizontal scrolling
!       long step = (mouse_hor_step < 0 || shift_or_ctrl)
!                                           ? curwin->w_width : mouse_hor_step;
!       long leftcol = curwin->w_leftcol
!                                    + (cap->arg == MSCR_RIGHT ? -step : step);
!       if (leftcol < 0)
!           leftcol = 0;
!       do_mousescroll_horiz((long_u)leftcol);
!     }
  
  #ifdef FEAT_SYN_HL
      if (curwin != old_curwin && curwin->w_p_cul)
        redraw_for_cursorline(curwin);
  #endif
-     may_trigger_winscrolled();
- 
      curwin->w_redr_status = TRUE;
- 
      curwin = old_curwin;
      curbuf = curwin->w_buffer;
  }
--- 2189,2223 ----
      if (mouse_row >= 0 && mouse_col >= 0)
      {
        // Find the window at the mouse pointer coordinates.
+       // NOTE: Must restore "curwin" to "old_curwin" before returning!
        int row = mouse_row;
        int col = mouse_col;
!       curwin = mouse_find_win(&row, &col, FIND_POPUP);
!       if (curwin == NULL)
!       {
!           curwin = old_curwin;
            return;
+       }
+ 
  #ifdef FEAT_PROP_POPUP
!       if (WIN_IS_POPUP(curwin) && !curwin->w_has_scrollbar)
!       {
            // cannot scroll this popup window
+           curwin = old_curwin;
            return;
+       }
  #endif
        curbuf = curwin->w_buffer;
      }
  
!     // Call the common mouse scroll function shared with other modes.
!     do_mousescroll(cap);
  
  #ifdef FEAT_SYN_HL
      if (curwin != old_curwin && curwin->w_p_cul)
        redraw_for_cursorline(curwin);
  #endif
      curwin->w_redr_status = TRUE;
      curwin = old_curwin;
      curbuf = curwin->w_buffer;
  }
*** ../vim-9.0.0905/src/version.c       2022-11-18 23:13:27.050157746 +0000
--- src/version.c       2022-11-19 10:37:05.951417912 +0000
***************
*** 697,698 ****
--- 697,700 ----
  {   /* Add new patch number below this line */
+ /**/
+     906,
  /**/

-- 
Momento mori, ergo carpe diem

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20221119104842.165591C12B2%40moolenaar.net.

Raspunde prin e-mail lui