unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* scroll-down with pixel transition
@ 2017-04-09 23:49 Tak Kunihiro
  2017-04-10  5:58 ` Eli Zaretskii
  0 siblings, 1 reply; 63+ messages in thread
From: Tak Kunihiro @ 2017-04-09 23:49 UTC (permalink / raw)
  To: emacs-devel; +Cc: Kunihiro Tak

I see scroll-up a line with pixel transition can be implemented
by `set-window-vscroll' as shown below.

(progn
  (vertical-motion 1)
  (dolist (vs (number-sequence 1 (1- (frame-char-height))))
    (set-window-vscroll nil vs t) (sit-for 0.001))
  (scroll-up 1))

Do you have ideas to scroll-down with pixel transition?




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-09 23:49 scroll-down with pixel transition Tak Kunihiro
@ 2017-04-10  5:58 ` Eli Zaretskii
  2017-04-10  7:06   ` Tak Kunihiro
  0 siblings, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2017-04-10  5:58 UTC (permalink / raw)
  To: Tak Kunihiro; +Cc: emacs-devel

> From: Tak Kunihiro <tkk@misasa.okayama-u.ac.jp>
> Date: Mon, 10 Apr 2017 08:49:59 +0900
> Cc: Kunihiro Tak <tkk@misasa.okayama-u.ac.jp>
> 
> I see scroll-up a line with pixel transition can be implemented
> by `set-window-vscroll' as shown below.
> 
> (progn
>   (vertical-motion 1)
>   (dolist (vs (number-sequence 1 (1- (frame-char-height))))
>     (set-window-vscroll nil vs t) (sit-for 0.001))
>   (scroll-up 1))
> 
> Do you have ideas to scroll-down with pixel transition?

Scroll down one line, then use set-window-vscroll to scroll up by
pixels?



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-10  5:58 ` Eli Zaretskii
@ 2017-04-10  7:06   ` Tak Kunihiro
  2017-04-10  7:42     ` Eli Zaretskii
  0 siblings, 1 reply; 63+ messages in thread
From: Tak Kunihiro @ 2017-04-10  7:06 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Kunihiro Tak, emacs-devel

>> I see scroll-up a line with pixel transition can be implemented
>> by `set-window-vscroll' as shown below.
>> 
>> (progn
>>  (vertical-motion 1)
>>  (dolist (vs (number-sequence 1 (1- (frame-char-height))))
>>    (set-window-vscroll nil vs t) (sit-for 0.001))
>>  (scroll-up 1))
>> 
>> Do you have ideas to scroll-down with pixel transition?
> 
> Scroll down one line, then use set-window-vscroll to scroll up by
> pixels?

It works.
Is there a way to visually hide the overshoot on (scroll-down 1)?

(progn
  (scroll-down 1)
  (set-window-vscroll nil (1- (frame-char-height)) t) (sit-for 0.001)
  (dolist (vs (reverse (number-sequence 0 (- (frame-char-height) 2))))
    (set-window-vscroll nil vs t) (sit-for 0.001)))




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-10  7:06   ` Tak Kunihiro
@ 2017-04-10  7:42     ` Eli Zaretskii
  2017-04-10 22:24       ` Tak Kunihiro
  0 siblings, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2017-04-10  7:42 UTC (permalink / raw)
  To: Tak Kunihiro; +Cc: emacs-devel

> From: Tak Kunihiro <tkk@misasa.okayama-u.ac.jp>
> Date: Mon, 10 Apr 2017 16:06:37 +0900
> Cc: Kunihiro Tak <tkk@misasa.okayama-u.ac.jp>,
>  emacs-devel@gnu.org
> 
> > Scroll down one line, then use set-window-vscroll to scroll up by
> > pixels?
> 
> It works.
> Is there a way to visually hide the overshoot on (scroll-down 1)?

I don't understand the question.  The display is only refreshed when
you call sit-for, so you have complete control of that already, and
AFAICS the code does what you told it to do.  Am I missing something?

(Btw, I think (sit-for 0) should also work, you don't need the 1 msec
delay.)



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-10  7:42     ` Eli Zaretskii
@ 2017-04-10 22:24       ` Tak Kunihiro
  2017-04-11  7:44         ` Eli Zaretskii
  0 siblings, 1 reply; 63+ messages in thread
From: Tak Kunihiro @ 2017-04-10 22:24 UTC (permalink / raw)
  To: eliz; +Cc: tkk, emacs-devel

>> It works.
>> Is there a way to visually hide the overshoot on (scroll-down 1)?
> 
> I don't understand the question.  The display is only refreshed when
> you call sit-for, so you have complete control of that already, and
> AFAICS the code does what you told it to do.  Am I missing something?

In Emacs around me (25.1 on Mac, 25.1 on Windows), the following lines
give me overshoot for each scroll-down.  Is not the case for you?

(dotimes (ii 10)
  (scroll-down 1)
  (set-window-vscroll nil (1- (frame-char-height)) t) (sit-for 0.05)
  (dolist (vs (reverse (number-sequence 0 (- (frame-char-height) 2))))
    (set-window-vscroll nil vs t) (sit-for 0.05)))



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-10 22:24       ` Tak Kunihiro
@ 2017-04-11  7:44         ` Eli Zaretskii
  2017-04-12 12:13           ` Tak Kunihiro
  0 siblings, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2017-04-11  7:44 UTC (permalink / raw)
  To: Tak Kunihiro; +Cc: emacs-devel

> Date: Tue, 11 Apr 2017 07:24:17 +0900 (JST)
> Cc: emacs-devel@gnu.org, tkk@misasa.okayama-u.ac.jp
> From: Tak Kunihiro <tkk@misasa.okayama-u.ac.jp>
> 
> >> It works.
> >> Is there a way to visually hide the overshoot on (scroll-down 1)?
> > 
> > I don't understand the question.  The display is only refreshed when
> > you call sit-for, so you have complete control of that already, and
> > AFAICS the code does what you told it to do.  Am I missing something?
> 
> In Emacs around me (25.1 on Mac, 25.1 on Windows), the following lines
> give me overshoot for each scroll-down.  Is not the case for you?
> 
> (dotimes (ii 10)
>   (scroll-down 1)
>   (set-window-vscroll nil (1- (frame-char-height)) t) (sit-for 0.05)
>   (dolist (vs (reverse (number-sequence 0 (- (frame-char-height) 2))))
>     (set-window-vscroll nil vs t) (sit-for 0.05)))

I'm still not sure what you mean by "overshoot", but if that's the
extra full-line scroll for each of the 10 iterations, then you see the
same in the snippet you shown that scrolls in the other direction, if
you look carefully.

The current display code doesn't like starting a window with a
partially visible line, so it zeroes out the vscroll if that produces
a fully-visible line at the window start.  E.g., try this:

  (progn
    (vertical-motion 1)
    (dolist (vs (number-sequence 1 (- (frame-char-height) 6)))
      (set-window-vscroll nil vs t) (sit-for 0.001)))

This ends up with the first window line partially visible, but as soon
as you move the cursor (triggering a redisplay cycle, just like
sit-for does), Emacs zeroes the window's vscroll to make that line
fully visible.  Changing that (probably as some special optional mode)
will require changes in the display engine on the C level and in
probably also in the line-moving commands in simple.el.  Patches
welcome.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-11  7:44         ` Eli Zaretskii
@ 2017-04-12 12:13           ` Tak Kunihiro
  2017-04-12 12:43             ` Eli Zaretskii
  0 siblings, 1 reply; 63+ messages in thread
From: Tak Kunihiro @ 2017-04-12 12:13 UTC (permalink / raw)
  To: eliz; +Cc: tkk, emacs-devel

GOAL: Pixel-level vertical scrolling up and down

> I'm still not sure what you mean by "overshoot", but if that's the
> extra full-line scroll for each of the 10 iterations

Yes, that's what I meant!

> then you see the same in the snippet you shown that scrolls in the
> other direction, if you look carefully.

This I do not see (even with careful look).  At least, following lines
give me pixel-level and smooth scrolling.  Not for you?

(dotimes (ii 10)
  (vertical-motion 1)
  (dolist (vs (number-sequence 1 (1- (frame-char-height))))
    (set-window-vscroll nil vs t) (sit-for 0.02))
  (scroll-up 1) (sit-for 0.02))

> Changing that (probably as some special optional mode) will require
> changes in the display engine on the C level and in probably also in
> the line-moving commands in simple.el.  Patches welcome.

Let's say the lines above give smooth scrolling.  If so, to make Emacs
scroll both up and down with pixel-to-pixel resolution, requirement is
that `set-window-vscroll' accepts negative number.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-12 12:13           ` Tak Kunihiro
@ 2017-04-12 12:43             ` Eli Zaretskii
  2017-04-13  7:02               ` Tak Kunihiro
  0 siblings, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2017-04-12 12:43 UTC (permalink / raw)
  To: Tak Kunihiro; +Cc: emacs-devel

> Date: Wed, 12 Apr 2017 21:13:35 +0900 (JST)
> Cc: emacs-devel@gnu.org, tkk@misasa.okayama-u.ac.jp
> From: Tak Kunihiro <tkk@misasa.okayama-u.ac.jp>
> 
> GOAL: Pixel-level vertical scrolling up and down
> 
> > I'm still not sure what you mean by "overshoot", but if that's the
> > extra full-line scroll for each of the 10 iterations
> 
> Yes, that's what I meant!
> 
> > then you see the same in the snippet you shown that scrolls in the
> > other direction, if you look carefully.
> 
> This I do not see (even with careful look).  At least, following lines
> give me pixel-level and smooth scrolling.  Not for you?

That's because the last iteration of the inner loop comes within 1
pixel of the next screen line, so you don't see the jump, which is
visible when you scroll in the other direction.  I've provided a
snippet to demonstrate the basic issue which causes that; if something
is unclear in my explanation, I can try clarifying.

> Let's say the lines above give smooth scrolling.  If so, to make Emacs
> scroll both up and down with pixel-to-pixel resolution, requirement is
> that `set-window-vscroll' accepts negative number.

Like I explained, it won't help, because the moment you do something
that potentially requires a redisplay, the vscroll will be zeroed, and
the text will scroll back to the state where the first screen line
visible in the window is fully visible.  So this cannot be the
solution to your problem, I think.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-12 12:43             ` Eli Zaretskii
@ 2017-04-13  7:02               ` Tak Kunihiro
  2017-04-13  7:21                 ` Eli Zaretskii
  0 siblings, 1 reply; 63+ messages in thread
From: Tak Kunihiro @ 2017-04-13  7:02 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Kunihiro Tak, emacs-devel

>> Let's say the lines above give smooth scrolling.  If so, to make Emacs
>> scroll both up and down with pixel-to-pixel resolution, requirement is
>> that `set-window-vscroll' accepts negative number.
> 
> Like I explained, it won't help, because the moment you do something
> that potentially requires a redisplay, the vscroll will be zeroed, and
> the text will scroll back to the state where the first screen line
> visible in the window is fully visible.  So this cannot be the
> solution to your problem, I think.

I think before pixel-level vertical scrolling up or down,
scrolling single line up or down `with pixel transition' should be
implemented.  It ends up (window-vscroll nil t) to be zero.
This may be good enough to give modern feel.

I assign the snippet to mwheel-scroll-up-function and it works
OK so far.




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-13  7:02               ` Tak Kunihiro
@ 2017-04-13  7:21                 ` Eli Zaretskii
  2017-04-13  8:12                   ` Tak Kunihiro
  2017-04-13  8:35                   ` Yuri Khan
  0 siblings, 2 replies; 63+ messages in thread
From: Eli Zaretskii @ 2017-04-13  7:21 UTC (permalink / raw)
  To: Tak Kunihiro; +Cc: emacs-devel

> From: Tak Kunihiro <tkk@misasa.okayama-u.ac.jp>
> Date: Thu, 13 Apr 2017 16:02:13 +0900
> Cc: Kunihiro Tak <tkk@misasa.okayama-u.ac.jp>,
>  emacs-devel@gnu.org
> 
> I think before pixel-level vertical scrolling up or down,
> scrolling single line up or down `with pixel transition' should be
> implemented.  It ends up (window-vscroll nil t) to be zero.
> This may be good enough to give modern feel.
> 
> I assign the snippet to mwheel-scroll-up-function and it works
> OK so far.

Sorry, I don't understand your proposal.  Can you show some code?



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-13  7:21                 ` Eli Zaretskii
@ 2017-04-13  8:12                   ` Tak Kunihiro
  2017-04-13  8:20                     ` Eli Zaretskii
  2017-04-13  8:35                   ` Yuri Khan
  1 sibling, 1 reply; 63+ messages in thread
From: Tak Kunihiro @ 2017-04-13  8:12 UTC (permalink / raw)
  To: eliz; +Cc: tkk, emacs-devel

[-- Attachment #1: Type: Text/Plain, Size: 508 bytes --]

>> I think before pixel-level vertical scrolling up or down,
>> scrolling single line up or down `with pixel transition' should be
>> implemented.  It ends up (window-vscroll nil t) to be zero.
>> This may be good enough to give modern feel.
>> 
>> I assign the snippet to mwheel-scroll-up-function and it works
>> OK so far.
> 
> Sorry, I don't understand your proposal.  Can you show some code?

Yes.  I attach a package in a middle.  With this Emacs scrolls a line
with pixel transition but ONLY upward.


[-- Attachment #2: pixel-scroll.el --]
[-- Type: Text/Plain, Size: 7690 bytes --]

;;; pixel-scroll.el --- Scroll with pixel-to-pixel transition

;; Copyright (C) 2017 Tak Kunihiro
;; Author: Tak Kunihiro <tak.kunihiro@gmail.com>
;; Maintainer: Tak Kunihiro <tak.kunihiro@gmail.com>
;; URL: http://dream.misasa.okayama-u.ac.jp
;; Package-Requires: ((emacs "24.5"))
;; Version: 1.0.0
;; Package-Version: 20170413.1707
;; Keywords: convenience, usability

;;; This file is NOT part of GNU Emacs

;;; License

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program; see the file COPYING.  If not, write to
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
;; Floor, Boston, MA 02110-1301, USA.

;;; Commentary:

;; To interactively toggle the mode on / off:
;;
;;   M-x pixel-scroll-mode
;;
;; To make the mode permanent, put this in your init file:
;;
;;   (require 'pixel-scroll)
;;   (pixel-scroll-mode 1)
;;
;; If you want to scroll by pixel-level also include:
;;   (setq pixel-resolusion-fine-p t)
;;
;; This package offers a global minor mode which makes Emacs scroll
;; vertically with feel of modern applications.  This minor mode
;; offers pixel-by-pixel scroll upward by mouse wheel using
;; `set-window-vscroll', `window-vscroll', and `scroll-up'.  The minor
;; mode overwrites parameters defined in `mwheel.el' to refer
;; `pixel-scroll-up' and `pixel-scroll-down' instead of `scroll-up'
;; and `scroll-down'.

;;; Principle of vertical scroll:

;; Scrolling text upward a line by pixels using `set-window-vscroll'
;; and by a line using `scroll-up' gives similar visual feedback when
;; vscroll location is @0.  Note vscroll location is vertical shift
;; obtained by `window-vscroll'.  Line height by pixel is obtained by
;; `frame-char-height' (to be exact, this is true for buffer with
;; mono-sized font).  Following two lines scroll text in similar
;; fashion, visually.
;;
;;   (scroll-up 1)
;;   (set-window-vscroll nil (frame-char-height) t)
;;
;; Scrolling text upward by a pixel and a line yields similar result
;; when vscroll location is at the last pixel.  Following two lines
;; scroll text in similar fashion, visually.
;;
;;   (scroll-up 1)
;;   (set-window-vscroll nil (1- (frame-char-height) t)) (scroll-up 1)
;;
;; When vscroll gets larger and as soon as point is beyond beginning
;; of a window, vscroll is set to zero.  To user, scope is changed
;; suddenly without point moved.  This package tries to scroll text
;; upward by a line with pixel-by-pixel transition by following
;; sequences.
;;
;;   (progn
;;     (vertical-motion 1)
;;     (dolist (vs (number-sequence 1 (1- (frame-char-height))))
;;       (set-window-vscroll nil vs t) (sit-for 0.001))
;;     (scroll-up 1))

;;; Change Log:

;; 20170319.1153
;;  - Replace `frame-char-height' by `pixel-line-height'.

;;; TODO:
;; - Scroll pixel-by-pixel to upward direction.

;;; Code:

(require 'mwheel)

(defgroup pixel-scroll nil
  "Scroll pixel-by-pixel in Emacs."
  :group 'mouse
  :prefix "pixel-")

(defcustom pixel-wait 0
  "Idle time on pixel scroll specified in second."
  :group 'pixel-scroll
  :type 'float)

(defcustom pixel-amount '(1 ((shift) . 5) ((control)))
  "Amount to scroll by when spinning the mouse wheel."
  :group 'pixel-scroll)

(defcustom pixel-resolusion-fine-p nil
  "Enhance scrolling resolution to pixel-to-pixel instead of
line-to-line."
  :group 'pixel-scroll
  :type 'boolean)

(define-minor-mode pixel-scroll-mode
  "A minor mode to scroll text pixel-by-pixel.  With a prefix argument ARG,
enable Pixel Scroll mode if ARG is positive, and disable it
otherwise.  If called from Lisp, enable Pixel Scroll mode if ARG
is omitted or nil."
  :init-value nil
  :group 'pixel-scroll
  :global t

  (if pixel-scroll-mode
      (progn (setq mwheel-scroll-up-function 'pixel-scroll-up)
             ;; (setq mwheel-scroll-down-function 'pixel-scroll-down)
             (setq mouse-wheel-scroll-amount pixel-amount)
             (setq mouse-wheel-progressive-speed pixel-resolusion-fine-p))
    (setq mwheel-scroll-up-function 'scroll-up)
    ;; (setq mwheel-scroll-down-function 'scroll-down)
    (dolist (var '(mouse-wheel-scroll-amount
                   mouse-wheel-progressive-speed))
      (custom-reevaluate-setting var))))

(defun pixel-scroll-up (&optional arg)
  "Scroll text of selected window up ARG lines.  This is
alternative of `scroll-up'.  Scope moves downward."
  (interactive)
  (or arg (setq arg 1))
  (dotimes (ii arg) ; move scope downward
    ;; (equal (window-end) (point-max)) ; when end-of-buffer is seen, use `scroll-up' to be conservative
    (if (<= (count-lines (window-start) (window-end)) 2)
        (scroll-up 1) ; when end of scroll is close, relay on more robust guy
      (when (or (equal (point-at-bol) (window-start)) ; prevent too late
                (and scroll-preserve-screen-position
                     (not (equal (point-at-bol) (window-end))))) ; prevent too fast
        (vertical-motion 1)) ; move point downward
      (pixel-scroll-pixel-up (if pixel-resolusion-fine-p
                                 1
                               (pixel-line-height)))))) ; move scope downward

(defun pixel-scroll-pixel-up (amt)
  "Scroll text of selected windows up AMT pixels.  Scope moves
downward."
  (while (>= (+ (window-vscroll nil t) amt)
            (pixel-line-height))
    (setq amt (- amt (pixel--flush-line-up)))) ; major scroll
  (pixel--sweep-pixel-up amt)) ; minor scroll

(defun pixel--flush-line-up ()
  "Flush text upward a line with pixel transition.  When `vscroll' is non-zero,
complete scrolling a line.  When `vscroll' is larger than height
of multiple lines, this flushes the lines.  At the end, `vscroll'
will be set to zero.  This assumes that lines to be caught up are
with the same height.  Scope moves downward.  This function
returns number of pixels that were scroled."
  (let* ((src (window-vscroll nil t))  ; EXAMPLE (initial)      @0   @8  @88
         (height (pixel-line-height))  ;                        25   25   23
         (line (1+ (/ src height)))    ; catch up + one line    Δ1   Δ1   Δ4
         (dst (* line height))         ; goal                  @25  @25  @92
         (delta (- dst src)))          ; pixels to be scrolled  25   17    4
    (pixel--sweep-pixel-up (1- delta)) ; sweep until one less  @24  @24  @91
    (scroll-up line) (sit-for pixel-wait) ; scroll 1 pixel      @0   @0   @0
    delta))

(defun pixel--sweep-pixel-up (n)
  "Sweep text upward to N pixels.  Scope moves downward."
  (when (> n 0)
    (let ((vs0 (window-vscroll nil t)))
      (dolist (vs (number-sequence (1+ vs0) (+ vs0 n)))
        (set-window-vscroll nil vs t) (sit-for pixel-wait)))))

(defun pixel-line-height (&optional pos)
  "Measure line height of POS in pixel.  When height of all lines
are equal, you don't need this function but `frame-char-height'.
See Info node `(elisp) Line Height'."
  (or pos (setq pos (window-start)))
  (save-excursion
    (goto-char pos)
    (line-pixel-height)))

(provide 'pixel-scroll)
;;; pixel-scroll.el ends here

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-13  8:12                   ` Tak Kunihiro
@ 2017-04-13  8:20                     ` Eli Zaretskii
  2017-04-13  8:40                       ` Tak Kunihiro
  0 siblings, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2017-04-13  8:20 UTC (permalink / raw)
  To: Tak Kunihiro; +Cc: emacs-devel

> Date: Thu, 13 Apr 2017 17:12:34 +0900 (JST)
> Cc: emacs-devel@gnu.org, tkk@misasa.okayama-u.ac.jp
> From: Tak Kunihiro <tkk@misasa.okayama-u.ac.jp>
> 
> > Sorry, I don't understand your proposal.  Can you show some code?
> 
> Yes.  I attach a package in a middle.  With this Emacs scrolls a line
> with pixel transition but ONLY upward.

Thanks.  AFAICT, this exhibits the same problem I was talking about:
after pixel-level scrolling, if the first screen line of the window is
not completely visible, typing C-n or C-p will scroll the window to
make it fully visible, thus undoing the effect of the pixel-level
scroll.  Isn't that what you see?



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-13  7:21                 ` Eli Zaretskii
  2017-04-13  8:12                   ` Tak Kunihiro
@ 2017-04-13  8:35                   ` Yuri Khan
  2017-04-13  8:57                     ` Eli Zaretskii
  1 sibling, 1 reply; 63+ messages in thread
From: Yuri Khan @ 2017-04-13  8:35 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Tak Kunihiro, Emacs developers

On Thu, Apr 13, 2017 at 2:21 PM, Eli Zaretskii <eliz@gnu.org> wrote:
>> From: Tak Kunihiro <tkk@misasa.okayama-u.ac.jp>
>> I think before pixel-level vertical scrolling up or down,
>> scrolling single line up or down `with pixel transition' should be
>> implemented.  It ends up (window-vscroll nil t) to be zero.
>> This may be good enough to give modern feel.
>>
>> I assign the snippet to mwheel-scroll-up-function and it works
>> OK so far.
>
> Sorry, I don't understand your proposal.  Can you show some code?

I think I do, and can translate.

To reproduce: Scroll a window up or down by one line, e.g. by
(scroll-up 1) or (scroll-down 1).

Current behavior: The display is updated once, with the window
scrolled a whole line.

Desired behavior: The display is updated n times, with the window
scrolled 1 pixel, then 2 pixels, …, then n-1 pixels, then n pixels,
where n is the height of a line in pixels.

Attempted implementation:

(defun my-scroll-down-line ()
  (interactive)
  (scroll-down 1) ;; Undesired redraw happens here
  (set-window-vscroll nil (1- (frame-char-height)) t)
  (sit-for 0.001)
  (dolist (vs (reverse (number-sequence 0 (- (frame-char-height) 2))))
    (set-window-vscroll nil vs t)
    (sit-for 0.001)))

Observed behavior: The display is updated n+1 times, first with the
window scrolled a whole line, then 1 pixel, 2 pixels, …, n-1 pixels,
finally a whole line again.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-13  8:20                     ` Eli Zaretskii
@ 2017-04-13  8:40                       ` Tak Kunihiro
  2017-04-13  9:04                         ` Eli Zaretskii
  0 siblings, 1 reply; 63+ messages in thread
From: Tak Kunihiro @ 2017-04-13  8:40 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Kunihiro Tak, emacs-devel

>> Yes.  I attach a package in a middle.  With this Emacs scrolls a line
>> with pixel transition but ONLY upward.
> 
> Thanks.  AFAICT, this exhibits the same problem I was talking about:
> after pixel-level scrolling, if the first screen line of the window is
> not completely visible, typing C-n or C-p will scroll the window to
> make it fully visible, thus undoing the effect of the pixel-level
> scroll.  Isn't that what you see?

Not really, because it checks (line-pixel-height) before scrolling and 
scrolls up until fully visible.  There is no chance to move point into
partially visible line.




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-13  8:35                   ` Yuri Khan
@ 2017-04-13  8:57                     ` Eli Zaretskii
  0 siblings, 0 replies; 63+ messages in thread
From: Eli Zaretskii @ 2017-04-13  8:57 UTC (permalink / raw)
  To: Yuri Khan; +Cc: tkk, emacs-devel

> From: Yuri Khan <yuri.v.khan@gmail.com>
> Date: Thu, 13 Apr 2017 15:35:51 +0700
> Cc: Tak Kunihiro <tkk@misasa.okayama-u.ac.jp>, Emacs developers <emacs-devel@gnu.org>
> 
> Desired behavior: The display is updated n times, with the window
> scrolled 1 pixel, then 2 pixels, …, then n-1 pixels, then n pixels,
> where n is the height of a line in pixels.
> 
> Attempted implementation:
> 
> (defun my-scroll-down-line ()
>   (interactive)
>   (scroll-down 1) ;; Undesired redraw happens here
>   (set-window-vscroll nil (1- (frame-char-height)) t)
>   (sit-for 0.001)
>   (dolist (vs (reverse (number-sequence 0 (- (frame-char-height) 2))))
>     (set-window-vscroll nil vs t)
>     (sit-for 0.001)))
> 
> Observed behavior: The display is updated n+1 times, first with the
> window scrolled a whole line, then 1 pixel, 2 pixels, …, n-1 pixels,
> finally a whole line again.

See my response to the code posted by Tak-san.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-13  8:40                       ` Tak Kunihiro
@ 2017-04-13  9:04                         ` Eli Zaretskii
  2017-04-13  9:22                           ` Tak Kunihiro
  0 siblings, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2017-04-13  9:04 UTC (permalink / raw)
  To: Tak Kunihiro; +Cc: emacs-devel

> From: Tak Kunihiro <tkk@misasa.okayama-u.ac.jp>
> Date: Thu, 13 Apr 2017 17:40:48 +0900
> Cc: Kunihiro Tak <tkk@misasa.okayama-u.ac.jp>,
>  emacs-devel@gnu.org
> 
> >> Yes.  I attach a package in a middle.  With this Emacs scrolls a line
> >> with pixel transition but ONLY upward.
> > 
> > Thanks.  AFAICT, this exhibits the same problem I was talking about:
> > after pixel-level scrolling, if the first screen line of the window is
> > not completely visible, typing C-n or C-p will scroll the window to
> > make it fully visible, thus undoing the effect of the pixel-level
> > scroll.  Isn't that what you see?
> 
> Not really, because it checks (line-pixel-height) before scrolling and 
> scrolls up until fully visible.  There is no chance to move point into
> partially visible line.

I think there's a misunderstanding.  Here's a recipe:

  emacs -Q
  M-x load-file RET pixel-scroll.el RET
  M-x pixel-scroll-mode RET
  M-x set-variable RET pixel-resolution-fine-p RET
  C-x C-f some-file RET
  C-u C-u C-n
  Scroll slowly with the mouse-wheel, one click at a time, until the
    first screen line is partially visible
  C-n

The last C-n causes a scroll which undoes the pixel-level scroll.  The
first screen line is now fully visible, and window's vscroll is now
zero.

Am I missing something?



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-13  9:04                         ` Eli Zaretskii
@ 2017-04-13  9:22                           ` Tak Kunihiro
  2017-04-13 10:24                             ` Eli Zaretskii
  0 siblings, 1 reply; 63+ messages in thread
From: Tak Kunihiro @ 2017-04-13  9:22 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: yuri.v.khan, Kunihiro Tak, emacs-devel

>>> Thanks.  AFAICT, this exhibits the same problem I was talking about:
>>> after pixel-level scrolling, if the first screen line of the window is
>>> not completely visible, typing C-n or C-p will scroll the window to
>>> make it fully visible, thus undoing the effect of the pixel-level
>>> scroll.  Isn't that what you see?
>> 
>> Not really, because it checks (line-pixel-height) before scrolling and 
>> scrolls up until fully visible.  There is no chance to move point into
>> partially visible line.
> 
> I think there's a misunderstanding.  Here's a recipe:
> 
>  emacs -Q
>  M-x load-file RET pixel-scroll.el RET
>  M-x pixel-scroll-mode RET
>  M-x set-variable RET pixel-resolution-fine-p RET
>  C-x C-f some-file RET
>  C-u C-u C-n
>  Scroll slowly with the mouse-wheel, one click at a time, until the
>    first screen line is partially visible
>  C-n
> 
> The last C-n causes a scroll which undoes the pixel-level scroll.  The
> first screen line is now fully visible, and window's vscroll is now
> zero.
> 
> Am I missing something?

You are correct.  Sorry for confusion.
I should have eliminated codes in regard to `pixel-resolution-fine-p’.

My intension was, to show an example of scrolling single line up with
(setq pixel-resolution-fine-p nil).

Thank you Yuri, for translation.




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-13  9:22                           ` Tak Kunihiro
@ 2017-04-13 10:24                             ` Eli Zaretskii
  2017-04-14  2:40                               ` Tak Kunihiro
  0 siblings, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2017-04-13 10:24 UTC (permalink / raw)
  To: Tak Kunihiro; +Cc: emacs-devel, yuri.v.khan

> From: Tak Kunihiro <tkk@misasa.okayama-u.ac.jp>
> Date: Thu, 13 Apr 2017 18:22:37 +0900
> Cc: yuri.v.khan@gmail.com, Kunihiro Tak <tkk@misasa.okayama-u.ac.jp>,
> 	emacs-devel@gnu.org
> 
> I should have eliminated codes in regard to `pixel-resolution-fine-p’.
> 
> My intension was, to show an example of scrolling single line up with
> (setq pixel-resolution-fine-p nil).

For scrolling in the other direction, the following snippet should I
hope show how to avoid the unwanted extra scroll:

  (defun pscroll-down (arg)
    (interactive "p")
    (let ((pos
	   (save-excursion
	     (goto-char (window-start))
	     (beginning-of-visual-line 0))))
      (set-window-start nil pos t)
      (set-window-vscroll nil arg t)))
  (define-key global-map [f9] 'pscroll-up)

With this, you can say "C-u 6 F9" and have the window text scrolled
down so that the first 6 pixels of the first screen line are not
shown.  Since this is just a demo, there are no protection against
hitting the beginning of buffer, against point being in the last
screen line, etc.; but adding that should be trivial.

The important part here is that you must call set-window-start as
shown, to force the display engine use that particular position as the
window-start point.  Otherwise, redisplay will reset the window's
vscroll.

HTH



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-13 10:24                             ` Eli Zaretskii
@ 2017-04-14  2:40                               ` Tak Kunihiro
  2017-04-14  7:37                                 ` Eli Zaretskii
  0 siblings, 1 reply; 63+ messages in thread
From: Tak Kunihiro @ 2017-04-14  2:40 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Kunihiro Tak, emacs-devel, yuri.v.khan

> For scrolling in the other direction, the following snippet should I
> hope show how to avoid the unwanted extra scroll:
> 
>  (defun pscroll-down (arg)
>    (interactive "p")
>    (let ((pos
> 	   (save-excursion
> 	     (goto-char (window-start))
> 	     (beginning-of-visual-line 0))))
>      (set-window-start nil pos t)
>      (set-window-vscroll nil arg t)))
>  (define-key global-map [f9] 'pscroll-up)

This helps a lot.  Thank you!

Now (1) I can scroll single line up or down with `pixel transition'.
Also (2) I can scroll a pixel up or down.

For (2), concern remains.  After a pixel scroll by (2), typing C-n or
C-p scrolls the window to make it fully visible, and undos the effect
of the pixel-level scroll.  

CONCLUSION: Emacs almost gets modern scroll




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-14  2:40                               ` Tak Kunihiro
@ 2017-04-14  7:37                                 ` Eli Zaretskii
  2017-04-14 22:32                                   ` Tak Kunihiro
  0 siblings, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2017-04-14  7:37 UTC (permalink / raw)
  To: Tak Kunihiro; +Cc: emacs-devel, yuri.v.khan

> From: Tak Kunihiro <tkk@misasa.okayama-u.ac.jp>
> Date: Fri, 14 Apr 2017 11:40:28 +0900
> Cc: Kunihiro Tak <tkk@misasa.okayama-u.ac.jp>,
>  yuri.v.khan@gmail.com,
>  emacs-devel@gnu.org
> 
> This helps a lot.  Thank you!

You are welcome.

I think we should have a minor mode that scrolls "smoothly" as in your
code.  Would you like to code that for inclusion in Emacs?

> Now (1) I can scroll single line up or down with `pixel transition'.
> Also (2) I can scroll a pixel up or down.
> 
> For (2), concern remains.  After a pixel scroll by (2), typing C-n or
> C-p scrolls the window to make it fully visible, and undos the effect
> of the pixel-level scroll.  

This particular issue probably comes from line-move and its
subroutines, and could be fixed there, given some user option.  But my
point is more general: allowing pixel-level scrolling in Emacs
requires a thorough review of the related functionalities, to make
sure none of them zeroes out vscroll where users won't want that.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-14  7:37                                 ` Eli Zaretskii
@ 2017-04-14 22:32                                   ` Tak Kunihiro
  2017-04-15 10:13                                     ` Eli Zaretskii
  2017-04-15 14:31                                     ` Clément Pit-Claudel
  0 siblings, 2 replies; 63+ messages in thread
From: Tak Kunihiro @ 2017-04-14 22:32 UTC (permalink / raw)
  To: eliz; +Cc: tkk, emacs-devel, yuri.v.khan

[-- Attachment #1: Type: Text/Plain, Size: 353 bytes --]

> I think we should have a minor mode that scrolls "smoothly" as in
> your code.  Would you like to code that for inclusion in Emacs?

Yes, please make Emacs smoothly.

I have revised code to include your algorithm for scroll-down.  I
attach it.

The top-level functions need to be more robust.  For example, I see
glitches during scroll-down on Info.


[-- Attachment #2: pixel-scroll.el --]
[-- Type: Text/Plain, Size: 10360 bytes --]

;;; pixel-scroll.el --- Scroll a line smoothly

;; Package-Requires: ((emacs "24.5"))
;; Version: 1.0.0
;; Package-Version: 20170415.0722
;; Keywords: convenience, usability

;;; This file is NOT part of GNU Emacs

;;; License

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program; see the file COPYING.  If not, write to
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
;; Floor, Boston, MA 02110-1301, USA.

;;; Commentary:

;; To interactively toggle the mode on / off:
;;
;;   M-x pixel-scroll-mode
;;
;; To make the mode permanent, put this in your init file:
;;
;;   (require 'pixel-scroll)
;;   (pixel-scroll-mode 1)
;;
;; This package offers a global minor mode which makes Emacs scroll
;; vertically with feel of modern applications.  This minor mode
;; offers pixel-by-pixel scroll upward by mouse wheel using
;; `set-window-vscroll', `window-vscroll', and `scroll-up'.  The minor
;; mode overwrites parameters defined in `mwheel.el' to refer
;; `pixel-scroll-up' and `pixel-scroll-down' instead of `scroll-up'
;; and `scroll-down'.

;;; Principle of vertical scroll:

;; Scrolling text upward a line by pixels using `set-window-vscroll'
;; and by a line using `scroll-up' gives similar visual feedback when
;; vscroll location is @0.  Note vscroll location is vertical shift
;; obtained by `window-vscroll'.  Line height by pixel is obtained by
;; `frame-char-height' (to be exact, this is true for buffer with
;; mono-sized font).  Following two lines scroll text in similar
;; fashion, visually.
;;
;;   (scroll-up 1)
;;   (set-window-vscroll nil (frame-char-height) t)
;;
;; Scrolling text upward by a pixel and a line yields similar result
;; when vscroll location is at the last pixel.  Following two lines
;; scroll text in similar fashion, visually.
;;
;;   (scroll-up 1)
;;   (set-window-vscroll nil (1- (frame-char-height) t)) (scroll-up 1)
;;
;; When vscroll gets larger and as soon as point is beyond beginning
;; of a window, vscroll is set to zero.  To user, scope is changed
;; suddenly without point moved.  This package tries to scroll text
;; upward by a line with pixel-by-pixel transition by following
;; sequences.
;;
;;   (progn
;;     (vertical-motion 1)
;;     (dolist (vs (number-sequence 1 (1- (frame-char-height))))
;;       (set-window-vscroll nil vs t) (sit-for 0.001))
;;     (scroll-up 1))

;;; Remarks:

;; If you want to try pixel-level scrolling, that is in the middle of
;; implementation, also include following in your init file:
;;
;;   (setq pixel-resolution-fine-p t)

;;; Change Log:

;; 20170319.1153
;;  - Replace `frame-char-height' by `line-pixel-height'.
;; 20170414.0958
;;  - Algorithm to scroll-down is offered by Eli Zaretskii.
;;  - Implement scroll pixel-by-pixel upward.

;;; Todo:
;; - Estimate height of unseen line at the top, on scrolling down.
;; - Handle error to scroll stable For now, Scroll does not well in Info.

;;; Long term concern:
;; - After a pixel scroll, typing C-n or C-p scrolls the window to make
;;   it fully visible, and undos the effect of the pixel-level scroll.

;;; Code:

(require 'mwheel)

(defgroup pixel-scroll nil
  "Scroll pixel-by-pixel in Emacs."
  :group 'mouse
  :prefix "pixel-")

(defcustom pixel-wait 0.001
  "Idle time on pixel scroll specified in second."
  :group 'pixel-scroll
  :type 'float)

(defcustom pixel-amount '(1 ((shift) . 5) ((control)))
  "Amount to scroll by when spinning the mouse wheel."
  :group 'pixel-scroll)

(defcustom pixel-resolution-fine-p nil
  "Enhance scrolling resolution to pixel-to-pixel instead of
line-to-line."
  :group 'pixel-scroll
  :type 'boolean)

(define-minor-mode pixel-scroll-mode
  "A minor mode to scroll text pixel-by-pixel.  With a prefix argument ARG,
enable Pixel Scroll mode if ARG is positive, and disable it
otherwise.  If called from Lisp, enable Pixel Scroll mode if ARG
is omitted or nil."
  :init-value nil
  :group 'pixel-scroll
  :global t

  (if pixel-scroll-mode
      (progn (setq mwheel-scroll-up-function 'pixel-scroll-up)
             (setq mwheel-scroll-down-function 'pixel-scroll-down)
             (setq mouse-wheel-scroll-amount pixel-amount)
             (setq mouse-wheel-progressive-speed pixel-resolution-fine-p))
    (setq mwheel-scroll-up-function 'scroll-up)
    (setq mwheel-scroll-down-function 'scroll-down)
    (dolist (var '(mouse-wheel-scroll-amount
                   mouse-wheel-progressive-speed))
      (custom-reevaluate-setting var))))

(defun pixel-scroll-up (&optional arg)
  "Scroll text of selected window up ARG lines.  This is
alternative of `scroll-up'.  Scope moves downward."
  (interactive)
  (or arg (setq arg 1))
  (dotimes (ii arg) ; move scope downward
    (if (<= (count-lines (window-start) (window-end)) 2)
        (scroll-up 1) ; when end of scroll is close, relay on robust guy
      (when (or (pixel-point-at-top-p) ; prevent too late
                (and scroll-preserve-screen-position
                     (not (pixel-point-at-bottom-p)))) ; prevent too fast
        (vertical-motion 1)) ; move point downward
      (pixel-scroll-pixel-up (if pixel-resolution-fine-p
                                 1
                               (pixel-line-height)))))) ; move scope downward

(defun pixel-scroll-down (&optional arg)
  "Scroll text of selected window down ARG lines.  This is
alternative of `scroll-down'.  Scope moves upward."
  (interactive)
  (or arg (setq arg 1))
  (dotimes (ii arg)
    (if (equal (window-start) (point-min))
        (scroll-down 1) ; when beginning-of-buffer is seen, relay on robust guy
      (when (or (pixel-point-at-bottom-p) ; prevent too late
                (and scroll-preserve-screen-position
                     (not (pixel-point-at-top-p)))) ; prevent too fast
        (vertical-motion -2))) ; FIXME: -1 gives glitch
    (pixel-scroll-pixel-down (if pixel-resolution-fine-p
                                 1
                               (pixel-line-height)))))

(defun pixel-point-at-top-p ()
  "Return if point is at top of a window."
  (equal (save-excursion (beginning-of-visual-line)
                         (point-at-bol))
         (window-start)))

(defun pixel-point-at-bottom-p ()
  "Return if point is at bottom of a window."
  (<= (count-lines (save-excursion
                     (beginning-of-visual-line)
                     (point-at-bol))
                   (pixel-window-end)) 1))

(defun pixel-scroll-pixel-up (amt)
  "Scroll text of selected windows up AMT pixels.  Scope moves
downward."
  (while (>= (+ (window-vscroll nil t) amt)
             (pixel-line-height))
    (setq amt (- amt (pixel--catch-line-up)))) ; major scroll
  (pixel--sweep-pixel-up amt)) ; minor scroll

(defun pixel-scroll-pixel-down (amt)
  "Scroll text of selected windows down AMT pixels.  Scope moves
upward."
  ;; FIXME: Cannot scroll down on Info sometimes
  (while (> amt 0)
    (let ((vs (window-vscroll nil t)))
      (if (equal vs 0)
          (pixel-scroll-down-and-set-window-vscroll (1- (pixel-line-height)))
        (set-window-vscroll nil (1- vs) t))
      (setq amt (1- amt))
      (sit-for pixel-wait))))

(defun pixel--catch-line-up ()
  "Flush text upward a line with pixel transition.  When `vscroll' is non-zero,
complete scrolling a line.  When `vscroll' is larger than height
of multiple lines, for example 88, this flushes multiple lines.
At the end, `vscroll' will be zero.  This assumes that the lines
are with the same height.  Scope moves downward.  This function
returns number of pixels that were scrolled."
  (let* ((src (window-vscroll nil t))  ; EXAMPLE (initial)      @0   @8  @88
         (height (pixel-line-height))  ;                        25   25   23
         (line (1+ (/ src height)))    ; catch up + one line    Δ1   Δ1   Δ4
         (dst (* line height))         ; goal                  @25  @25  @92
         (delta (- dst src)))          ; pixels to be scrolled  25   17    4
    (pixel--sweep-pixel-up (1- delta)) ; sweep until one less  @24  @24  @91
    (scroll-up line) (sit-for pixel-wait) ; scroll 1 pixel      @0   @0   @0
    delta))

(defun pixel--sweep-pixel-up (n)
  "Sweep text upward to N pixels.  Scope moves downward."
  (when (> n 0)
    (let ((vs0 (window-vscroll nil t)))
      (dolist (vs (number-sequence (1+ vs0) (+ vs0 n)))
        (set-window-vscroll nil vs t) (sit-for pixel-wait)))))

(defun pixel-window-end ()
  "Return position of the last character of fully-visible line in
WINDOW.  This is similar to `window-end' but see a full visible
line."
  (let ((pos (window-end)))
    (if (pos-visible-in-window-p pos nil t)
        pos
      (save-excursion
        (goto-char pos)
        (vertical-motion -2)
        (point-at-bol)))))

(defun pixel-line-height (&optional pos)
  "Measure line height of POS in pixel.  When height of all lines
are equal, you don't need this function but `frame-char-height'.
See Info node `(elisp) Line Height'."
  (or pos (setq pos (window-start)))
  (save-excursion
    (goto-char pos)
    (line-pixel-height)))

(defun pixel-scroll-down-and-set-window-vscroll (vscroll)
  "Scroll down a line and set VSCROLL in pixel.  This is written
by Eli Zaretskii.  It is important to call `set-window-start' to
force the display engine use that particular position as the
window-start point.  Otherwise, redisplay will reset the window's
vscroll."
  (let ((pos
         (save-excursion
           (goto-char (window-start))
           (beginning-of-visual-line 0))))
    (set-window-start nil pos t)
    (set-window-vscroll nil vscroll t)))

(provide 'pixel-scroll)
;;; pixel-scroll.el ends here

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-14 22:32                                   ` Tak Kunihiro
@ 2017-04-15 10:13                                     ` Eli Zaretskii
  2017-04-16  8:35                                       ` Tak Kunihiro
  2017-04-15 14:31                                     ` Clément Pit-Claudel
  1 sibling, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2017-04-15 10:13 UTC (permalink / raw)
  To: Tak Kunihiro; +Cc: emacs-devel, yuri.v.khan

> Date: Sat, 15 Apr 2017 07:32:52 +0900 (JST)
> Cc: yuri.v.khan@gmail.com, emacs-devel@gnu.org, tkk@misasa.okayama-u.ac.jp
> From: Tak Kunihiro <tkk@misasa.okayama-u.ac.jp>
> 
> > I think we should have a minor mode that scrolls "smoothly" as in
> > your code.  Would you like to code that for inclusion in Emacs?
> 
> Yes, please make Emacs smoothly.
> 
> I have revised code to include your algorithm for scroll-down.  I
> attach it.

Thanks.  I'll let people try this and comment.  In the meantime, a few
comments from myself:

> The top-level functions need to be more robust.  For example, I see
> glitches during scroll-down on Info.

Probably due to Info using fonts of different sizes.

> ;;; This file is NOT part of GNU Emacs

Should be changed once this is in core.

> (defgroup pixel-scroll nil
>   "Scroll pixel-by-pixel in Emacs."
>   :group 'mouse
>   :prefix "pixel-")

I see no need for a new group, please use the existing group
'scrolling'.

> (defcustom pixel-wait 0.001
>   "Idle time on pixel scroll specified in second."
>   :group 'pixel-scroll
>   :type 'float)

The doc string should say a bit more to explain the user-visible
effect of the value.

Also, please add a ':version' tag to each defcustom.

> (defcustom pixel-amount '(1 ((shift) . 5) ((control)))
>   "Amount to scroll by when spinning the mouse wheel."
>   :group 'pixel-scroll)

Do we really need a separate defcustom for this?  Why not use
mouse-wheel-scroll-amount?

> (defcustom pixel-resolution-fine-p nil
>   "Enhance scrolling resolution to pixel-to-pixel instead of
> line-to-line."
>   :group 'pixel-scroll
>   :type 'boolean)

Not sure this should be advertised, as the functionality has issues.
At the very least those issues should be described in the doc string.

>         (vertical-motion -2))) ; FIXME: -1 gives glitch

What glitch is that?

> (defun pixel-point-at-top-p ()
>   "Return if point is at top of a window."
>   (equal (save-excursion (beginning-of-visual-line)
>                          (point-at-bol))
>          (window-start)))

I think this will fail with bidirectional text, if the first character
in the logical order is not displayed at the leftmost screen position
of the first line of the window.

I suggest to use posn-at-point instead.

> (defun pixel-point-at-bottom-p ()
>   "Return if point is at bottom of a window."
>   (<= (count-lines (save-excursion
>                      (beginning-of-visual-line)
>                      (point-at-bol))
>                    (pixel-window-end)) 1))

Likewise here, I suggest to use window-end and posn-at-point.

> (defun pixel--catch-line-up ()
>   "Flush text upward a line with pixel transition.  When `vscroll' is non-zero,
> complete scrolling a line.  When `vscroll' is larger than height
> of multiple lines, for example 88, this flushes multiple lines.
> At the end, `vscroll' will be zero.  This assumes that the lines
> are with the same height.  Scope moves downward.  This function
> returns number of pixels that were scrolled."

I'm not sure what you mean by "flush" here.  And why the function's
name uses 'catch' if you mean 'flush'?

> (defun pixel--sweep-pixel-up (n)
>   "Sweep text upward to N pixels.  Scope moves downward."

Maybe I'm misunderstanding what this does, but "sweep" doesn't seem to
describe it.

> (defun pixel-window-end ()
>   "Return position of the last character of fully-visible line in
> WINDOW.  This is similar to `window-end' but see a full visible
> line."
>   (let ((pos (window-end)))
>     (if (pos-visible-in-window-p pos nil t)
>         pos
>       (save-excursion
>         (goto-char pos)
>         (vertical-motion -2)
>         (point-at-bol)))))

I don't understand the 'else' part here.  What situation does it
handle?  AFAIU, if pos-visible-in-window-p returns nil in this case,
the window-end position is completely invisible, which is something
that cannot happen, I think.

> (defun pixel-line-height (&optional pos)
>   "Measure line height of POS in pixel.  When height of all lines
> are equal, you don't need this function but `frame-char-height'.
> See Info node `(elisp) Line Height'."
>   (or pos (setq pos (window-start)))
            ^^^^^^^^^^^^^^^^^^^^^^^^
This part is not mentioned in the doc string, so the situation where
POS is unspecified is left undefined.

> (defun pixel-scroll-down-and-set-window-vscroll (vscroll)
>   "Scroll down a line and set VSCROLL in pixel.  This is written
> by Eli Zaretskii.  It is important to call `set-window-start' to
> force the display engine use that particular position as the
> window-start point.  Otherwise, redisplay will reset the window's
> vscroll."

We don't put such information in the doc strings, certainly not
authorship.  Comments are more appropriate, and you could simply cite
the emacs-devel message by its URL.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-14 22:32                                   ` Tak Kunihiro
  2017-04-15 10:13                                     ` Eli Zaretskii
@ 2017-04-15 14:31                                     ` Clément Pit-Claudel
  2017-04-15 14:57                                       ` Eli Zaretskii
  1 sibling, 1 reply; 63+ messages in thread
From: Clément Pit-Claudel @ 2017-04-15 14:31 UTC (permalink / raw)
  To: Tak Kunihiro, eliz; +Cc: yuri.v.khan, emacs-devel

On 2017-04-14 18:32, Tak Kunihiro wrote:
> 
> I have revised code to include your algorithm for scroll-down.  I
> attach it.

Thanks, this is nice. Scroll seems much slower with this on than without it, though — is that intended?

Will this have a significant impact on performance / CPU / battery usage?

Thanks!
Clément.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-15 14:31                                     ` Clément Pit-Claudel
@ 2017-04-15 14:57                                       ` Eli Zaretskii
  2017-04-15 15:33                                         ` Clément Pit-Claudel
  0 siblings, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2017-04-15 14:57 UTC (permalink / raw)
  To: Clément Pit-Claudel; +Cc: tkk, emacs-devel, yuri.v.khan

> From: Clément Pit-Claudel <cpitclaudel@gmail.com>
> Date: Sat, 15 Apr 2017 10:31:33 -0400
> Cc: yuri.v.khan@gmail.com, emacs-devel@gnu.org
> 
> On 2017-04-14 18:32, Tak Kunihiro wrote:
> > 
> > I have revised code to include your algorithm for scroll-down.  I
> > attach it.
> 
> Thanks, this is nice. Scroll seems much slower with this on than without it, though — is that intended?
> 
> Will this have a significant impact on performance / CPU / battery usage?

It's expected: each line is now scrolled in 10 pixel-level scrolls
rather than a single character-level scroll.

Does it help to set pixel-wait to zero?



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-15 14:57                                       ` Eli Zaretskii
@ 2017-04-15 15:33                                         ` Clément Pit-Claudel
  0 siblings, 0 replies; 63+ messages in thread
From: Clément Pit-Claudel @ 2017-04-15 15:33 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: tkk, emacs-devel, yuri.v.khan

On 2017-04-15 10:57, Eli Zaretskii wrote:
>> Will this have a significant impact on performance / CPU / battery usage?
> 
> It's expected: each line is now scrolled in 10 pixel-level scrolls
> rather than a single character-level scroll.

Thanks for clarifying.

> Does it help to set pixel-wait to zero?

No, not perceptibly.

Clément.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-15 10:13                                     ` Eli Zaretskii
@ 2017-04-16  8:35                                       ` Tak Kunihiro
  2017-04-16 10:26                                         ` Eli Zaretskii
  0 siblings, 1 reply; 63+ messages in thread
From: Tak Kunihiro @ 2017-04-16  8:35 UTC (permalink / raw)
  To: eliz; +Cc: tkk, Clément Pit-Claudel, emacs-devel, yuri.v.khan

[-- Attachment #1: Type: Text/Plain, Size: 7567 bytes --]

I revised the code to respond to your comments.  I attach the revised
file and diff.

* REMAINED ISSUES

1. On Info, pixel-scroll-down-and-set-window-vscroll cannot
   scroll-down sometimes.  Please see detail below, and help
   me.

2. Name of a function was changed from pixel--sweep-pixel-up to
   pixel--scroll-pixel-up.  Still verb does not sound right.  Please
   see detail below, and suggest me.

* EACH RESPONSE:

>> The top-level functions need to be more robust.  For example, I see
>> glitches during scroll-down on Info.
> 
> Probably due to Info using fonts of different sizes.

This I cannot find out how to solve.  With emacs -Q, on top info page,
goto point-max, then I cannot scroll-down using
`pixel-scroll-down-and-set-window-vscroll' when larger font sits on
the top of window.  Can you solve this?

>> ;;; This file is NOT part of GNU Emacs
> 
> Should be changed once this is in core.

I changed to is to `part of GNU Emacs'.  This can be too early.

>> (defgroup pixel-scroll nil
>>   "Scroll pixel-by-pixel in Emacs."
>>   :group 'mouse
>>   :prefix "pixel-")
> 
> I see no need for a new group, please use the existing group
> 'scrolling'.

I changed all to :group 'scrolling.

>> (defcustom pixel-wait 0.001
>>   "Idle time on pixel scroll specified in second."
>>   :group 'pixel-scroll
>>   :type 'float)
> 
> The doc string should say a bit more to explain the user-visible
> effect of the value.

I revised the doc string to "Idle time on a pixel scroll specified in
second.  More wait will retult in slow and gentle scroll."

> Also, please add a ':version' tag to each defcustom.

I put each defcustom :version "26.1".

>> (defcustom pixel-amount '(1 ((shift) . 5) ((control)))
>>   "Amount to scroll by when spinning the mouse wheel."
>>   :group 'pixel-scroll)
> 
> Do we really need a separate defcustom for this?  Why not use
> mouse-wheel-scroll-amount?

It is not necessary.  I removed it.

>> (defcustom pixel-resolution-fine-p nil
>>   "Enhance scrolling resolution to pixel-to-pixel instead of
>> line-to-line."
>>   :group 'pixel-scroll
>>   :type 'boolean)
> 
> Not sure this should be advertised, as the functionality has issues.
> At the very least those issues should be described in the doc string.

I changed it to defvar and revised the doc string to "Increase
scrolling resolution to a pixel instead of a line.  After a pixel
scroll, typing C-n or C-p scrolls the window to make it fully visible,
and undos the effect of the pixel-level scroll."

>>         (vertical-motion -2))) ; FIXME: -1 gives glitch
> 
> What glitch is that?

This was related to implementation of pixel-point-at-bottom-p.  Now
the glitch disappeared (at least I think).

>> (defun pixel-point-at-top-p ()
>>   "Return if point is at top of a window."
>>   (equal (save-excursion (beginning-of-visual-line)
>>                          (point-at-bol))
>>          (window-start)))
> 
> I think this will fail with bidirectional text, if the first character
> in the logical order is not displayed at the leftmost screen position
> of the first line of the window.
> 
> I suggest to use posn-at-point instead.

Thank you for such good suggestion!  I revised as shown below.

(defun pixel-point-at-top-p ()
  "Return if point is at top of a window."
  (<= (cdr (posn-x-y (posn-at-point)))
      (line-pixel-height)))

>> (defun pixel-point-at-bottom-p ()
>>   "Return if point is at bottom of a window."
>>   (<= (count-lines (save-excursion
>>                      (beginning-of-visual-line)
>>                      (point-at-bol))
>>                    (pixel-window-end)) 1))
> 
> Likewise here, I suggest to use window-end and posn-at-point.

I revised as suggested, as shown below.  I used
window-inside-pixel-edges instead of window-end.  Correct me if
something is not correct.

(defun pixel-point-at-bottom-p ()
  "Return if point is at bottom of a window."
  (let* ((edges (window-inside-pixel-edges))
         (height (- (nth 3 edges) (nth 1 edges))) ; bottom - top
         (mergin (- height (cdr (posn-x-y (posn-at-point))))))
    (<= mergin
        (* 2 (line-pixel-height)))))

>> (defun pixel--catch-line-up ()
>>   "Flush text upward a line with pixel transition.  When `vscroll' is non-zero,
>> complete scrolling a line.  When `vscroll' is larger than height
>> of multiple lines, for example 88, this flushes multiple lines.
>> At the end, `vscroll' will be zero.  This assumes that the lines
>> are with the same height.  Scope moves downward.  This function
>> returns number of pixels that were scrolled."
> 
> I'm not sure what you mean by "flush" here.  And why the function's
> name uses 'catch' if you mean 'flush'?

Inconsistent expression was removed.  Now the name is just
pixel--scroll-line-up.  I put two hyphens because this should be
regarded as lower level one.

>> (defun pixel--sweep-pixel-up (n)
>>   "Sweep text upward to N pixels.  Scope moves downward."
> 
> Maybe I'm misunderstanding what this does, but "sweep" doesn't seem to
> describe it.

This is because I cannot find a good verb to describe its
functionality.  I change pixel--sweep-pixel-up to
pixel--scroll-pixel-up for now.  Note that there is
pixel-scroll-pixel-up already and the new name is source of confusion.
Can you read the code suggest a name (or verb)?

>> (defun pixel-window-end ()
>>   "Return position of the last character of fully-visible line in
>> WINDOW.  This is similar to `window-end' but see a full visible
>> line."
>>   (let ((pos (window-end)))
>>     (if (pos-visible-in-window-p pos nil t)
>>         pos
>>       (save-excursion
>>         (goto-char pos)
>>         (vertical-motion -2)
>>         (point-at-bol)))))
> 
> I don't understand the 'else' part here.  What situation does it
> handle?  AFAIU, if pos-visible-in-window-p returns nil in this case,
> the window-end position is completely invisible, which is something
> that cannot happen, I think.

Since pixel-point-at-bottom-p was improved, this disappeared.

>> (defun pixel-line-height (&optional pos)
>>   "Measure line height of POS in pixel.  When height of all lines
>> are equal, you don't need this function but `frame-char-height'.
>> See Info node `(elisp) Line Height'."
>>   (or pos (setq pos (window-start)))
>             ^^^^^^^^^^^^^^^^^^^^^^^^
> This part is not mentioned in the doc string, so the situation where
> POS is unspecified is left undefined.

I revised the doc string to "Return height in pixels of text line
of POS in the selected window.  When POS is nil, height of the first
line of the window is provided.  When height of all lines are equal,
you don't need this function but `frame-char-height'.  See Info node
`(elisp) Line Height'."

>> (defun pixel-scroll-down-and-set-window-vscroll (vscroll)
>>   "Scroll down a line and set VSCROLL in pixel.  This is written
>> by Eli Zaretskii.  It is important to call `set-window-start' to
>> force the display engine use that particular position as the
>> window-start point.  Otherwise, redisplay will reset the window's
>> vscroll."
> 
> We don't put such information in the doc strings, certainly not
> authorship.  Comments are more appropriate, and you could simply cite
> the emacs-devel message by its URL.

I revise the doc string to "Scroll down a line and set VSCROLL in
pixels.  This is code is presented at
https://lists.gnu.org/archive/html/emacs-devel/2017-04/msg00366.html.
It is important to call `set-window-start' to force the display engine
use that particular position as the window-start point.  Otherwise,
redisplay will reset the window's vscroll."

[-- Attachment #2: pixel-scroll.el --]
[-- Type: Text/Plain, Size: 9658 bytes --]

;;; pixel-scroll.el --- Scroll a line smoothly

;; Package-Requires: ((emacs "24.5"))
;; Version: 1.0.0
;; Package-Version: 20170416.1713
;; Keywords: convenience, usability

;;; This file is part of GNU Emacs

;;; License

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program; see the file COPYING.  If not, write to
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
;; Floor, Boston, MA 02110-1301, USA.

;;; Commentary:

;; To interactively toggle the mode on / off:
;;
;;   M-x pixel-scroll-mode
;;
;; To make the mode permanent, put this in your init file:
;;
;;   (require 'pixel-scroll)
;;   (pixel-scroll-mode 1)
;;
;; This package offers a global minor mode which makes Emacs scroll
;; vertically with feel of modern applications.  This minor mode
;; offers pixel-by-pixel scroll upward by mouse wheel using
;; `set-window-vscroll', `window-vscroll', and `scroll-up'.  The minor
;; mode overwrites parameters defined in `mwheel.el' to refer
;; `pixel-scroll-up' and `pixel-scroll-down' instead of `scroll-up'
;; and `scroll-down'.

;;; Principle of vertical scroll:

;; Scrolling text upward a line by pixels using `set-window-vscroll'
;; and by a line using `scroll-up' gives similar visual feedback when
;; vscroll location is @0.  Note vscroll location is vertical shift
;; obtained by `window-vscroll'.  Line height by pixel is obtained by
;; `frame-char-height' (to be exact, this is true for buffer with
;; mono-sized font).  Following two lines scroll text in similar
;; fashion, visually.
;;
;;   (scroll-up 1)
;;   (set-window-vscroll nil (frame-char-height) t)
;;
;; Scrolling text upward by a pixel and a line yields similar result
;; when vscroll location is at the last pixel.  Following two lines
;; scroll text in similar fashion, visually.
;;
;;   (scroll-up 1)
;;   (set-window-vscroll nil (1- (frame-char-height) t)) (scroll-up 1)
;;
;; When vscroll gets larger and as soon as point is beyond beginning
;; of a window, vscroll is set to zero.  To user, scope is changed
;; suddenly without point moved.  This package tries to scroll text
;; upward by a line with pixel-by-pixel transition by following
;; sequences.
;;
;;   (progn
;;     (vertical-motion 1)
;;     (dolist (vs (number-sequence 1 (1- (frame-char-height))))
;;       (set-window-vscroll nil vs t) (sit-for 0.001))
;;     (scroll-up 1))


;;; Change Log:

;; 20170319.1153
;;  - Replace `frame-char-height' by `line-pixel-height'.
;; 20170414.0958
;;  - Algorithm to scroll-down is offered by Eli Zaretskii.
;;  - Implement scroll pixel-by-pixel upward.

;;; Todo:
;; - Estimate height of unseen line at the top, on scrolling down.
;; - Handle error to scroll stable For now, Scroll does not well in Info.

;;; Long term concern:
;; - Allowing pixel-level scrolling in Emacs requires a thorough
;;   review of the related functionalities, to make sure none of them
;;   zeroes out vscroll where users won't want that.

;;; Code:

(require 'mwheel)

(defcustom pixel-wait 0.001
  "Idle time on a pixel scroll specified in second.  More wait
will retult in slow and gentle scroll."
  :group 'scrolling
  :version "26.1"
  :type 'float)

(defvar pixel-resolution-fine-p nil
  "Increase scrolling resolution to a pixel instead of a line.
After a pixel scroll, typing C-n or C-p scrolls the window to
make it fully visible, and undos the effect of the pixel-level
scroll.")

(define-minor-mode pixel-scroll-mode
  "A minor mode to scroll text pixel-by-pixel.  With a prefix argument ARG,
enable Pixel Scroll mode if ARG is positive, and disable it
otherwise.  If called from Lisp, enable Pixel Scroll mode if ARG
is omitted or nil."
  :init-value nil
  :group 'scrolling
  :global t

  (if pixel-scroll-mode
      (progn (setq mwheel-scroll-up-function 'pixel-scroll-up)
             (setq mwheel-scroll-down-function 'pixel-scroll-down))
    (setq mwheel-scroll-up-function 'scroll-up)
    (setq mwheel-scroll-down-function 'scroll-down)))

(defun pixel-scroll-up (&optional arg)
  "Scroll text of selected window up ARG lines.  This is
alternative of `scroll-up'.  Scope moves downward."
  (interactive)
  (or arg (setq arg 1))
  (dotimes (ii arg) ; move scope downward
    (if (<= (count-lines (window-start) (window-end)) 2)
        (scroll-up 1) ; when end of scroll is close, relay on robust guy
      (when (or (pixel-point-at-top-p) ; prevent too late
                (and scroll-preserve-screen-position
                     (not (pixel-point-at-bottom-p)))) ; prevent too fast
        (vertical-motion 1)) ; move point downward
      (pixel-scroll-pixel-up (if pixel-resolution-fine-p
                                 1
                               (pixel-line-height)))))) ; move scope downward

(defun pixel-scroll-down (&optional arg)
  "Scroll text of selected window down ARG lines.  This is
alternative of `scroll-down'.  Scope moves upward."
  (interactive)
  (or arg (setq arg 1))
  (dotimes (ii arg)
    (if (equal (window-start) (point-min))
        (scroll-down 1) ; when beginning-of-buffer is seen, relay on robust guy
      (when (or (pixel-point-at-bottom-p) ; prevent too late
                (and scroll-preserve-screen-position
                     (not (pixel-point-at-top-p)))) ; prevent too fast
        (vertical-motion -1)))
    (pixel-scroll-pixel-down (if pixel-resolution-fine-p
                                 1
                               (pixel-line-height)))))

(defun pixel-point-at-top-p ()
  "Return if point is at top of a window."
  (<= (cdr (posn-x-y (posn-at-point)))
      (line-pixel-height)))

(defun pixel-point-at-bottom-p ()
  "Return if point is at bottom of a window."
  (let* ((edges (window-inside-pixel-edges))
         (height (- (nth 3 edges) (nth 1 edges))) ; bottom - top
         (mergin (- height (cdr (posn-x-y (posn-at-point))))))
    (<= mergin
        (* 2 (line-pixel-height)))))

(defun pixel-scroll-pixel-up (amt)
  "Scroll text of selected windows up AMT pixels.  Scope moves
downward."
  (while (>= (+ (window-vscroll nil t) amt)
             (pixel-line-height))
    (setq amt (- amt (pixel--scroll-line-up)))) ; major scroll
  (pixel--scroll-pixel-up amt)) ; minor scroll

(defun pixel-scroll-pixel-down (amt)
  "Scroll text of selected windows down AMT pixels.  Scope moves
upward."
  ;; FIXME: Cannot scroll down on Info sometimes
  (while (> amt 0)
    (let ((vs (window-vscroll nil t)))
      (if (equal vs 0)
          (pixel-scroll-down-and-set-window-vscroll (1- (pixel-line-height)))
        (set-window-vscroll nil (1- vs) t))
      (setq amt (1- amt))
      (sit-for pixel-wait))))

(defun pixel--scroll-line-up ()
  "Scroll text upward a line with pixel transition.  When `vscroll' is non-zero,
complete scrolling a line.  When `vscroll' is larger than height
of multiple lines, for example 88, this flushes multiple lines.
At the end, `vscroll' will be zero.  This assumes that the lines
are with the same height.  Scope moves downward.  This function
returns number of pixels that were scrolled."
  (let* ((src (window-vscroll nil t))  ; EXAMPLE (initial)      @0   @8  @88
         (height (pixel-line-height))  ;                        25   25   23
         (line (1+ (/ src height)))    ; catch up + one line    Δ1   Δ1   Δ4
         (dst (* line height))         ; goal                  @25  @25  @92
         (delta (- dst src)))          ; pixels to be scrolled  25   17    4
    (pixel--scroll-pixel-up (1- delta)) ; sweep until one less  @24  @24  @91
    (scroll-up line) (sit-for pixel-wait) ; scroll 1 pixel      @0   @0   @0
    delta))

(defun pixel--scroll-pixel-up (n)
  "Scroll text upward to N pixels with pixel transition.  Scope
moves downward."
  (when (> n 0)
    (let ((vs0 (window-vscroll nil t)))
      (dolist (vs (number-sequence (1+ vs0) (+ vs0 n)))
        (set-window-vscroll nil vs t) (sit-for pixel-wait)))))

(defun pixel-line-height (&optional pos)
  "Return height in pixels of text line of POS in the selected
window.  When POS is nil, height of the first line of the window
is provided.  When height of all lines are equal, you don't need
this function but `frame-char-height'.  See Info node `(elisp)
Line Height'."
  (or pos (setq pos (window-start)))
  (save-excursion
    (goto-char pos)
    (line-pixel-height)))

(defun pixel-scroll-down-and-set-window-vscroll (vscroll)
  "Scroll down a line and set VSCROLL in pixels.  This is code is
presented at
https://lists.gnu.org/archive/html/emacs-devel/2017-04/msg00366.html.
It is important to call `set-window-start' to force the display
engine use that particular position as the window-start point.
Otherwise, redisplay will reset the window's vscroll."
  (let ((pos
         (save-excursion
           (goto-char (window-start))
           (beginning-of-visual-line 0))))
    (set-window-start nil pos t)
    (set-window-vscroll nil vscroll t)))

(provide 'pixel-scroll)
;;; pixel-scroll.el ends here

[-- Attachment #3: pixel-scroll.20170415.el.patch --]
[-- Type: Text/X-Patch, Size: 8225 bytes --]

--- pixel-scroll.20170415.el	2017-04-15 07:22:47.387221900 +0900
+++ pixel-scroll.el	2017-04-16 17:13:55.185671600 +0900
@@ -2,10 +2,10 @@
 
 ;; Package-Requires: ((emacs "24.5"))
 ;; Version: 1.0.0
-;; Package-Version: 20170415.0722
+;; Package-Version: 20170416.1713
 ;; Keywords: convenience, usability
 
-;;; This file is NOT part of GNU Emacs
+;;; This file is part of GNU Emacs
 
 ;;; License
 
@@ -75,12 +75,6 @@
 ;;       (set-window-vscroll nil vs t) (sit-for 0.001))
 ;;     (scroll-up 1))
 
-;;; Remarks:
-
-;; If you want to try pixel-level scrolling, that is in the middle of
-;; implementation, also include following in your init file:
-;;
-;;   (setq pixel-resolution-fine-p t)
 
 ;;; Change Log:
 
@@ -95,32 +89,26 @@
 ;; - Handle error to scroll stable For now, Scroll does not well in Info.
 
 ;;; Long term concern:
-;; - After a pixel scroll, typing C-n or C-p scrolls the window to make
-;;   it fully visible, and undos the effect of the pixel-level scroll.
+;; - Allowing pixel-level scrolling in Emacs requires a thorough
+;;   review of the related functionalities, to make sure none of them
+;;   zeroes out vscroll where users won't want that.
 
 ;;; Code:
 
 (require 'mwheel)
 
-(defgroup pixel-scroll nil
-  "Scroll pixel-by-pixel in Emacs."
-  :group 'mouse
-  :prefix "pixel-")
-
 (defcustom pixel-wait 0.001
-  "Idle time on pixel scroll specified in second."
-  :group 'pixel-scroll
+  "Idle time on a pixel scroll specified in second.  More wait
+will retult in slow and gentle scroll."
+  :group 'scrolling
+  :version "26.1"
   :type 'float)
 
-(defcustom pixel-amount '(1 ((shift) . 5) ((control)))
-  "Amount to scroll by when spinning the mouse wheel."
-  :group 'pixel-scroll)
-
-(defcustom pixel-resolution-fine-p nil
-  "Enhance scrolling resolution to pixel-to-pixel instead of
-line-to-line."
-  :group 'pixel-scroll
-  :type 'boolean)
+(defvar pixel-resolution-fine-p nil
+  "Increase scrolling resolution to a pixel instead of a line.
+After a pixel scroll, typing C-n or C-p scrolls the window to
+make it fully visible, and undos the effect of the pixel-level
+scroll.")
 
 (define-minor-mode pixel-scroll-mode
   "A minor mode to scroll text pixel-by-pixel.  With a prefix argument ARG,
@@ -128,19 +116,14 @@
 otherwise.  If called from Lisp, enable Pixel Scroll mode if ARG
 is omitted or nil."
   :init-value nil
-  :group 'pixel-scroll
+  :group 'scrolling
   :global t
 
   (if pixel-scroll-mode
       (progn (setq mwheel-scroll-up-function 'pixel-scroll-up)
-             (setq mwheel-scroll-down-function 'pixel-scroll-down)
-             (setq mouse-wheel-scroll-amount pixel-amount)
-             (setq mouse-wheel-progressive-speed pixel-resolution-fine-p))
+             (setq mwheel-scroll-down-function 'pixel-scroll-down))
     (setq mwheel-scroll-up-function 'scroll-up)
-    (setq mwheel-scroll-down-function 'scroll-down)
-    (dolist (var '(mouse-wheel-scroll-amount
-                   mouse-wheel-progressive-speed))
-      (custom-reevaluate-setting var))))
+    (setq mwheel-scroll-down-function 'scroll-down)))
 
 (defun pixel-scroll-up (&optional arg)
   "Scroll text of selected window up ARG lines.  This is
@@ -169,31 +152,31 @@
       (when (or (pixel-point-at-bottom-p) ; prevent too late
                 (and scroll-preserve-screen-position
                      (not (pixel-point-at-top-p)))) ; prevent too fast
-        (vertical-motion -2))) ; FIXME: -1 gives glitch
+        (vertical-motion -1)))
     (pixel-scroll-pixel-down (if pixel-resolution-fine-p
                                  1
                                (pixel-line-height)))))
 
 (defun pixel-point-at-top-p ()
   "Return if point is at top of a window."
-  (equal (save-excursion (beginning-of-visual-line)
-                         (point-at-bol))
-         (window-start)))
+  (<= (cdr (posn-x-y (posn-at-point)))
+      (line-pixel-height)))
 
 (defun pixel-point-at-bottom-p ()
   "Return if point is at bottom of a window."
-  (<= (count-lines (save-excursion
-                     (beginning-of-visual-line)
-                     (point-at-bol))
-                   (pixel-window-end)) 1))
+  (let* ((edges (window-inside-pixel-edges))
+         (height (- (nth 3 edges) (nth 1 edges))) ; bottom - top
+         (mergin (- height (cdr (posn-x-y (posn-at-point))))))
+    (<= mergin
+        (* 2 (line-pixel-height)))))
 
 (defun pixel-scroll-pixel-up (amt)
   "Scroll text of selected windows up AMT pixels.  Scope moves
 downward."
   (while (>= (+ (window-vscroll nil t) amt)
              (pixel-line-height))
-    (setq amt (- amt (pixel--catch-line-up)))) ; major scroll
-  (pixel--sweep-pixel-up amt)) ; minor scroll
+    (setq amt (- amt (pixel--scroll-line-up)))) ; major scroll
+  (pixel--scroll-pixel-up amt)) ; minor scroll
 
 (defun pixel-scroll-pixel-down (amt)
   "Scroll text of selected windows down AMT pixels.  Scope moves
@@ -207,8 +190,8 @@
       (setq amt (1- amt))
       (sit-for pixel-wait))))
 
-(defun pixel--catch-line-up ()
-  "Flush text upward a line with pixel transition.  When `vscroll' is non-zero,
+(defun pixel--scroll-line-up ()
+  "Scroll text upward a line with pixel transition.  When `vscroll' is non-zero,
 complete scrolling a line.  When `vscroll' is larger than height
 of multiple lines, for example 88, this flushes multiple lines.
 At the end, `vscroll' will be zero.  This assumes that the lines
@@ -219,44 +202,36 @@
          (line (1+ (/ src height)))    ; catch up + one line    Δ1   Δ1   Δ4
          (dst (* line height))         ; goal                  @25  @25  @92
          (delta (- dst src)))          ; pixels to be scrolled  25   17    4
-    (pixel--sweep-pixel-up (1- delta)) ; sweep until one less  @24  @24  @91
+    (pixel--scroll-pixel-up (1- delta)) ; sweep until one less  @24  @24  @91
     (scroll-up line) (sit-for pixel-wait) ; scroll 1 pixel      @0   @0   @0
     delta))
 
-(defun pixel--sweep-pixel-up (n)
-  "Sweep text upward to N pixels.  Scope moves downward."
+(defun pixel--scroll-pixel-up (n)
+  "Scroll text upward to N pixels with pixel transition.  Scope
+moves downward."
   (when (> n 0)
     (let ((vs0 (window-vscroll nil t)))
       (dolist (vs (number-sequence (1+ vs0) (+ vs0 n)))
         (set-window-vscroll nil vs t) (sit-for pixel-wait)))))
 
-(defun pixel-window-end ()
-  "Return position of the last character of fully-visible line in
-WINDOW.  This is similar to `window-end' but see a full visible
-line."
-  (let ((pos (window-end)))
-    (if (pos-visible-in-window-p pos nil t)
-        pos
-      (save-excursion
-        (goto-char pos)
-        (vertical-motion -2)
-        (point-at-bol)))))
-
 (defun pixel-line-height (&optional pos)
-  "Measure line height of POS in pixel.  When height of all lines
-are equal, you don't need this function but `frame-char-height'.
-See Info node `(elisp) Line Height'."
+  "Return height in pixels of text line of POS in the selected
+window.  When POS is nil, height of the first line of the window
+is provided.  When height of all lines are equal, you don't need
+this function but `frame-char-height'.  See Info node `(elisp)
+Line Height'."
   (or pos (setq pos (window-start)))
   (save-excursion
     (goto-char pos)
     (line-pixel-height)))
 
 (defun pixel-scroll-down-and-set-window-vscroll (vscroll)
-  "Scroll down a line and set VSCROLL in pixel.  This is written
-by Eli Zaretskii.  It is important to call `set-window-start' to
-force the display engine use that particular position as the
-window-start point.  Otherwise, redisplay will reset the window's
-vscroll."
+  "Scroll down a line and set VSCROLL in pixels.  This is code is
+presented at
+https://lists.gnu.org/archive/html/emacs-devel/2017-04/msg00366.html.
+It is important to call `set-window-start' to force the display
+engine use that particular position as the window-start point.
+Otherwise, redisplay will reset the window's vscroll."
   (let ((pos
          (save-excursion
            (goto-char (window-start))

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-16  8:35                                       ` Tak Kunihiro
@ 2017-04-16 10:26                                         ` Eli Zaretskii
  2017-04-16 12:17                                           ` Tak Kunihiro
  0 siblings, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2017-04-16 10:26 UTC (permalink / raw)
  To: Tak Kunihiro; +Cc: cpitclaudel, emacs-devel, yuri.v.khan

> Date: Sun, 16 Apr 2017 17:35:41 +0900 (JST)
> Cc: yuri.v.khan@gmail.com, emacs-devel@gnu.org, Clément
>  Pit-Claudel <cpitclaudel@gmail.com>, tkk@misasa.okayama-u.ac.jp
> From: Tak Kunihiro <tkk@misasa.okayama-u.ac.jp>
> 
> >> The top-level functions need to be more robust.  For example, I see
> >> glitches during scroll-down on Info.
> > 
> > Probably due to Info using fonts of different sizes.
> 
> This I cannot find out how to solve.  With emacs -Q, on top info page,
> goto point-max, then I cannot scroll-down using
> `pixel-scroll-down-and-set-window-vscroll' when larger font sits on
> the top of window.  Can you solve this?

Please show a complete recipe starting from "emacs -Q".  When the
first line of the window uses a larger font, you generally cannot
scroll down because you already are at beginning of buffer, so it's
expected.  But maybe you found some Info file/node where there's some
other problem.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-16 10:26                                         ` Eli Zaretskii
@ 2017-04-16 12:17                                           ` Tak Kunihiro
  2017-04-16 16:51                                             ` Eli Zaretskii
  0 siblings, 1 reply; 63+ messages in thread
From: Tak Kunihiro @ 2017-04-16 12:17 UTC (permalink / raw)
  To: Eli Zaretskii
  Cc: cpitclaudel, 国広卓也, emacs-devel,
	yuri.v.khan

>>>> The top-level functions need to be more robust.  For example, I see
>>>> glitches during scroll-down on Info.
>>> 
>>> Probably due to Info using fonts of different sizes.
>> 
>> This I cannot find out how to solve.  With emacs -Q, on top info page,
>> goto point-max, then I cannot scroll-down using
>> `pixel-scroll-down-and-set-window-vscroll' when larger font sits on
>> the top of window.  Can you solve this?
> 
> Please show a complete recipe starting from "emacs -Q".  When the
> first line of the window uses a larger font, you generally cannot
> scroll down because you already are at beginning of buffer, so it's
> expected.  But maybe you found some Info file/node where there's some
> other problem.

Can you check with following recipe?

emacs -Q
M-x load-file RET pixel-scroll.el RET
M-x info
C-s gnus RET
M-: (pixel-scroll-down 100)

As soon as I see `The Info Directory' with large fonts, Emacs refuses scrolling down.




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-16 12:17                                           ` Tak Kunihiro
@ 2017-04-16 16:51                                             ` Eli Zaretskii
  2017-04-16 18:00                                               ` Eli Zaretskii
  0 siblings, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2017-04-16 16:51 UTC (permalink / raw)
  To: Tak Kunihiro; +Cc: cpitclaudel, yuri.v.khan, emacs-devel

> From: Tak Kunihiro <tkk@misasa.okayama-u.ac.jp>
> Date: Sun, 16 Apr 2017 21:17:11 +0900
> Cc: cpitclaudel@gmail.com,
> 	国広卓也 <tkk@misasa.okayama-u.ac.jp>,
> 	emacs-devel@gnu.org, yuri.v.khan@gmail.com
> 
> emacs -Q
> M-x load-file RET pixel-scroll.el RET
> M-x info
> C-s gnus RET
> M-: (pixel-scroll-down 100)
> 
> As soon as I see `The Info Directory' with large fonts, Emacs refuses scrolling down.

What do you mean by "refuses"?  Do you mean that the header-line is
not shown?  Or do you mean something else?



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-16 16:51                                             ` Eli Zaretskii
@ 2017-04-16 18:00                                               ` Eli Zaretskii
  2017-04-16 23:06                                                 ` Tak Kunihiro
  0 siblings, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2017-04-16 18:00 UTC (permalink / raw)
  To: tkk; +Cc: cpitclaudel, emacs-devel, yuri.v.khan

> Date: Sun, 16 Apr 2017 19:51:55 +0300
> From: Eli Zaretskii <eliz@gnu.org>
> Cc: cpitclaudel@gmail.com, yuri.v.khan@gmail.com, emacs-devel@gnu.org
> 
> What do you mean by "refuses"?  Do you mean that the header-line is
> not shown?

Sorry, I didn't mean header-line, I meant the overlay at the beginning
of the buffer which shows the "breadcrumbs".



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-16 18:00                                               ` Eli Zaretskii
@ 2017-04-16 23:06                                                 ` Tak Kunihiro
  2017-04-17  8:54                                                   ` Eli Zaretskii
  0 siblings, 1 reply; 63+ messages in thread
From: Tak Kunihiro @ 2017-04-16 23:06 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: cpitclaudel, Kunihiro Tak, emacs-devel, yuri.v.khan

>> emacs -Q
>> M-x load-file RET pixel-scroll.el RET
>> M-x info
>> C-s gnus RET
>> M-: (pixel-scroll-down 100)
>> 
>> As soon as I see `The Info Directory' with large fonts, Emacs refuses scrolling down.
> 
> What do you mean by "refuses"?  Do you mean that the overlay at the beginning
> of the buffer which shows the "breadcrumbs”. Or do you mean something else?

Sorry for the vague expression.

I meant a line with “(dir)Top” will not be shown by pixel-scroll-down-and-set-window-vscroll.  I suppose you refer the line as “breadcrumbs”.

emacs -Q
M-x load-file RET pixel-scroll.el RET
M-x info
C-s gnus RET
M-x pixel-scroll-down
M-x pixel-scroll-down
M-x pixel-scroll-down




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-16 23:06                                                 ` Tak Kunihiro
@ 2017-04-17  8:54                                                   ` Eli Zaretskii
  2017-04-17 23:15                                                     ` Tak Kunihiro
  0 siblings, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2017-04-17  8:54 UTC (permalink / raw)
  To: Tak Kunihiro; +Cc: cpitclaudel, emacs-devel, yuri.v.khan

> From: Tak Kunihiro <tkk@misasa.okayama-u.ac.jp>
> Date: Mon, 17 Apr 2017 08:06:32 +0900
> Cc: Kunihiro Tak <tkk@misasa.okayama-u.ac.jp>,
>  cpitclaudel@gmail.com,
>  yuri.v.khan@gmail.com,
>  emacs-devel@gnu.org
> 
> I meant a line with “(dir)Top” will not be shown by pixel-scroll-down-and-set-window-vscroll.  I suppose you refer the line as “breadcrumbs”.
> 
> emacs -Q
> M-x load-file RET pixel-scroll.el RET
> M-x info
> C-s gnus RET
> M-x pixel-scroll-down
> M-x pixel-scroll-down
> M-x pixel-scroll-down

You need to carefully examine the behavior of the functions you use
near that special place, as some of them might behave unexpectedly
when an overlay string is present that hides some of the buffer text,
which makes the effect of these functions not well-defined.

The diffs below should give you a start, but there still are some
minor glitches near the beginning of an Info node; these are left as
exercises ;-)

--- pixel-scroll.el~0	2017-04-16 13:19:06.708750000 +0300
+++ pixel-scroll.el	2017-04-17 11:48:10.661875000 +0300
@@ -235,7 +235,15 @@
   (let ((pos
          (save-excursion
            (goto-char (window-start))
-           (beginning-of-visual-line 0))))
+	   (if (bobp)
+	       (point-min)
+	     ;; When there's an overlay string at window-start,
+	     ;; (beginning-of-visual-line 0) stays put.
+	     (let* ((ppos (point))
+		    (tem (beginning-of-visual-line 0)))
+	       (if (eq tem ppos)
+		   (vertical-motion -1))
+	       (point))))))
     (set-window-start nil pos t)
     (set-window-vscroll nil vscroll t)))
 



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-17  8:54                                                   ` Eli Zaretskii
@ 2017-04-17 23:15                                                     ` Tak Kunihiro
  2017-04-19 12:21                                                       ` Tak Kunihiro
  0 siblings, 1 reply; 63+ messages in thread
From: Tak Kunihiro @ 2017-04-17 23:15 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: cpitclaudel, Kunihiro Tak, emacs-devel, yuri.v.khan

>> I meant a line with “(dir)Top” will not be shown by pixel-scroll-down-and-set-window-vscroll.  I suppose you refer the line as “breadcrumbs”.
>> 
>> emacs -Q
>> M-x load-file RET pixel-scroll.el RET
>> M-x info
>> C-s gnus RET
>> M-x pixel-scroll-down
>> M-x pixel-scroll-down
>> M-x pixel-scroll-down
> 
> You need to carefully examine the behavior of the functions you use
> near that special place, as some of them might behave unexpectedly
> when an overlay string is present that hides some of the buffer text,
> which makes the effect of these functions not well-defined.
> 
> The diffs below should give you a start, but there still are some
> minor glitches near the beginning of an Info node; these are left as
> exercises ;-)
> 
> --- pixel-scroll.el~0	2017-04-16 13:19:06.708750000 +0300
> +++ pixel-scroll.el	2017-04-17 11:48:10.661875000 +0300
> @@ -235,7 +235,15 @@
>   (let ((pos
>          (save-excursion
>            (goto-char (window-start))
> -           (beginning-of-visual-line 0))))
> +	   (if (bobp)
> +	       (point-min)
> +	     ;; When there's an overlay string at window-start,
> +	     ;; (beginning-of-visual-line 0) stays put.
> +	     (let* ((ppos (point))
> +		    (tem (beginning-of-visual-line 0)))
> +	       (if (eq tem ppos)
> +		   (vertical-motion -1))
> +	       (point))))))
>     (set-window-start nil pos t)
>     (set-window-vscroll nil vscroll t)))

Thank you very much!  

I start to test pixel-resolution-fine-p t.  Even typing C-n or
C-p after a pixel scroll shifts text a little, it seems that
the itch does not bother me much. 

I plan to revise the code and come back on this weekend.




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-17 23:15                                                     ` Tak Kunihiro
@ 2017-04-19 12:21                                                       ` Tak Kunihiro
  2017-04-19 12:38                                                         ` Kaushal Modi
  0 siblings, 1 reply; 63+ messages in thread
From: Tak Kunihiro @ 2017-04-19 12:21 UTC (permalink / raw)
  To: eliz; +Cc: cpitclaudel, tkk, emacs-devel, yuri.v.khan

[-- Attachment #1: Type: Text/Plain, Size: 781 bytes --]

>> there still are some minor glitches near the beginning of an Info
>> node; these are left as exercises

1. I think I fixed glitches at the beginning of Info node.  The key
   was to get height of the `unseen' and coming line above the first
   line of the current window.

2. Name of a function was not appropriate.  I found a good verb,
   `whistlestop' and renamed them.

   - `pixel--sweep-pixel-up' is renamed to `pixel--whistlestop-line-up'

I send the revised copy and the diff.  Two possible ways to test the
code are shown below.

 (require 'pixel-scroll)
 (pixel-scroll-mode 1)
 (setq pixel-resolution-fine-p t)

 (require 'pixel-scroll)
 (pixel-scroll-mode 1)
 (setq mouse-wheel-scroll-amount '(1 ((shift) . 5) ((control))))
 (setq mouse-wheel-progressive-speed nil)


[-- Attachment #2: pixel-scroll.el --]
[-- Type: Text/Plain, Size: 10004 bytes --]

;;; pixel-scroll.el --- Scroll a line smoothly

;; Package-Requires: ((emacs "24.5"))
;; Version: 1.0.0
;; Package-Version: 20170419.2104
;; Keywords: convenience, usability

;;; This file is part of GNU Emacs

;;; License

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program; see the file COPYING.  If not, write to
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
;; Floor, Boston, MA 02110-1301, USA.

;; Usage:
;;
;; To interactively toggle the mode:
;;
;;   M-x pixel-scroll-mode RET
;;
;; To make the mode permanent, put these in your init file:
;;
;;   (require 'pixel-scroll)
;;   (pixel-scroll-mode 1)

;;; Commentary:

;; This package offers a global minor mode which makes Emacs scroll a
;; line smoothly.

;; The smooth scroll-up is carried out using `set-window-vscroll',
;; `window-vscroll', and `scroll-up'.  Scrolling text upward a line by
;; pixels using `set-window-vscroll' and by a line using `scroll-up'
;; gives similar visual feedback when vscroll location is @0.  Note
;; that vscroll location is vertical shift obtained by
;; `window-vscroll'.  Line height by pixel is obtained by
;; `frame-char-height'.  Following two lines scroll text in similar
;; fashion, visually.
;;
;;   (scroll-up 1)
;;   (set-window-vscroll nil (frame-char-height) t)
;;
;; Scrolling text upward by a pixel and a line yields similar result
;; when vscroll location is at the last pixel.  Following two lines
;; scroll text in similar fashion, visually.
;;
;;   (scroll-up 1)
;;   (set-window-vscroll nil (1- (frame-char-height) t)) (scroll-up 1)
;;
;; When vscroll gets larger and as soon as point is beyond beginning
;; of a window, vscroll is set to zero.  To user, scope is changed
;; suddenly without point moved.  This package tries to scroll text
;; upward by a line with pixel-by-pixel transition by a following
;; sequence.
;;
;;   (progn
;;     (vertical-motion 1)
;;     (dolist (vs (number-sequence 1 (1- (frame-char-height))))
;;       (set-window-vscroll nil vs t) (sit-for 0.1))
;;     (scroll-up 1))

;;; Todo:
;;
;; Allowing pixel-level scrolling in Emacs requires a thorough review
;; of the related functionalities, to make sure none of them zeroes
;; out vscroll where users won't want that.

;;; Code:

(require 'mwheel)

(defvar pixel-wait 0
  "Idle time on each step of pixel scroll specified in second.
More wait will result in slow and gentle scroll.")

(defvar pixel-resolution-fine-p nil
  "Set scrolling resolution to a pixel instead of a line.
After a pixel scroll, typing C-n or C-p scrolls the window to
make it fully visible, and undos the effect of the pixel-level
scroll.")

(define-minor-mode pixel-scroll-mode
  "A minor mode to scroll text pixel-by-pixel.  With a prefix argument ARG,
enable Pixel Scroll mode if ARG is positive, and disable it
otherwise.  If called from Lisp, enable Pixel Scroll mode if ARG
is omitted or nil."
  :init-value nil
  :group 'scrolling
  :global t

  (if pixel-scroll-mode
      (setq mwheel-scroll-up-function 'pixel-scroll-up
            mwheel-scroll-down-function 'pixel-scroll-down)
    (setq mwheel-scroll-up-function 'scroll-up
          mwheel-scroll-down-function 'scroll-down)))

(defun pixel-scroll-up (&optional arg)
  "Scroll text of selected window up ARG lines.  This is
alternative of `scroll-up'.  Scope moves downward."
  (interactive)
  (or arg (setq arg 1))
  (dotimes (ii arg) ; move scope downward
    (if (<= (count-lines (window-start) (window-end)) 2)
        (scroll-up 1) ; when end of scroll is close, relay on robust guy
      (when (or (pixel-point-at-top-p) ; prevent too late
                (and scroll-preserve-screen-position
                     (not (pixel-point-at-bottom-p)))) ; prevent too fast
        (vertical-motion 1)) ; move point downward
      (pixel-scroll-pixel-up (if pixel-resolution-fine-p
                                 1
                               (pixel-line-height)))))) ; move scope downward

(defun pixel-scroll-down (&optional arg)
  "Scroll text of selected window down ARG lines.  This is
alternative of `scroll-down'.  Scope moves upward."
  (interactive)
  (or arg (setq arg 1))
  (dotimes (ii arg)
    (if (equal (window-start) (point-min))
        (scroll-down 1) ; when beginning-of-buffer is seen, relay on robust guy
      (while (or (pixel-point-at-bottom-p) ; prevent too late (try several lines)
                 (and scroll-preserve-screen-position
                      (not (pixel-point-at-top-p)))) ; prevent too fast
        (vertical-motion -1)))
    (pixel-scroll-pixel-down (if pixel-resolution-fine-p
                                 1
                               (pixel-line-height -1)))))

(defun pixel-point-at-top-p ()
  "Return if point is at top of a window."
  (let ((y (cdr (posn-x-y (posn-at-point)))))
    (if y
        (< y ; top margin
           (pixel-line-height))
      ;; when point is out of scope by hscroll
      (< (count-lines (window-start) (point)) 1))))

(defun pixel-point-at-bottom-p ()
  "Return if point is at bottom of a window."
  (let* ((y (cdr (posn-x-y (posn-at-point))))
         (edges (window-inside-pixel-edges))
         (height (- (nth 3 edges) (nth 1 edges)))) ; (- bottom top)
    (if y
        (< (- height (+ y (line-pixel-height))) ; bottom margin
           (pixel-line-height -1)) ; coming line
      ;; when point is out of scope by hscroll
      (< (count-lines (point) (window-end)) 4))))

(defun pixel-scroll-pixel-up (amt)
  "Scroll text of selected windows up AMT pixels.  Scope moves
downward."
  (while (>= (+ (window-vscroll nil t) amt)
             (pixel-line-height))
    (setq amt (- amt (pixel--whistlestop-line-up)))) ; major scroll
  (pixel--whistlestop-pixel-up amt)) ; minor scroll

(defun pixel-scroll-pixel-down (amt)
  "Scroll text of selected windows down AMT pixels.  Scope moves
upward."
  (while (> amt 0)
    (let ((vs (window-vscroll nil t)))
      (if (equal vs 0)
          (pixel-scroll-down-and-set-window-vscroll
           (1- (pixel-line-height -1)))
        (set-window-vscroll nil (1- vs) t))
      (setq amt (1- amt))
      (sit-for pixel-wait))))

(defun pixel--whistlestop-line-up ()
  "Scroll text upward a line with each pixel whistlestopped.
When `vscroll' is non-zero, complete scrolling a line.  When
`vscroll' is larger than height of multiple lines, for example
88, this flushes multiple lines.  At the end, `vscroll' will be
zero.  This assumes that the lines are with the same height.
Scope moves downward.  This function returns number of pixels
that was scrolled."
  (let* ((src (window-vscroll nil t))  ; EXAMPLE (initial)      @0   @8  @88
         (height (pixel-line-height))  ;                        25   25   23
         (line (1+ (/ src height)))    ; catch up + one line    Δ1   Δ1   Δ4
         (dst (* line height))         ; goal                  @25  @25  @92
         (delta (- dst src)))          ; pixels to be scrolled  25   17    4
    (pixel--whistlestop-pixel-up (1- delta)) ; until one less  @24  @24  @91
    (scroll-up line) (sit-for pixel-wait) ; scroll 1 pixel      @0   @0   @0
    delta))

(defun pixel--whistlestop-pixel-up (n)
  "Scroll text upward by N pixels with each pixel whistlestopped.
Scope moves downward."
  (when (> n 0)
    (let ((vs0 (window-vscroll nil t)))
      (dolist (vs (number-sequence (1+ vs0) (+ vs0 n)))
        (set-window-vscroll nil vs t) (sit-for pixel-wait)))))

(defun pixel-line-height (&optional pos)
  "Return height in pixels of text line of POS in the selected
window.  When POS is nil or negative, height of the first line or
the coming line above the first line is provided."
  (or pos (setq pos (window-start)))
  (if (< pos 0)
      (setq pos (pixel-point-at-coming-line)))
  (save-excursion
    (goto-char pos)
    (line-pixel-height))) ; frame-char-height

(defun pixel-point-at-coming-line ()
  "Return the character position of the first character on the
coming line just above the scope of current window.  This code is
presented at
https://lists.gnu.org/archive/html/emacs-devel/2017-04/msg00475.html."
  (let* ((win0 (window-start))
         (vscroll0 (window-vscroll nil t))
         (pos
          (save-excursion
            (goto-char win0)
            (if (bobp)
                (point-min)
              ;; When there's an overlay string at window-start,
              ;; (beginning-of-visual-line 0) stays put.
              (let ((ppos (point))
                    (tem (beginning-of-visual-line 0)))
                (if (eq tem ppos)
                    (vertical-motion -1))
                (point))))))
    (set-window-start nil win0 t) ; restore the window
    (set-window-vscroll nil vscroll0 t) ; restore the window
    pos))

(defun pixel-scroll-down-and-set-window-vscroll (vscroll)
  "Scroll down a line and set VSCROLL in pixels.  This code is
presented at
https://lists.gnu.org/archive/html/emacs-devel/2017-04/msg00366.html.
It is important to call `set-window-start' to force the display
engine use that particular position as the window-start point.
Otherwise, redisplay will reset the window's vscroll."
  (set-window-start nil (pixel-point-at-coming-line) t)
  (set-window-vscroll nil vscroll t))

(provide 'pixel-scroll)
;;; pixel-scroll.el ends here

[-- Attachment #3: pixel-scroll.20170416.el.patch --]
[-- Type: Text/X-Patch, Size: 12446 bytes --]

--- pixel-scroll.20170416.el	2017-04-16 17:59:33.285776700 +0900
+++ pixel-scroll.el	2017-04-19 21:04:20.374769600 +0900
@@ -2,7 +2,7 @@
 
 ;; Package-Requires: ((emacs "24.5"))
 ;; Version: 1.0.0
-;; Package-Version: 20170416.1713
+;; Package-Version: 20170419.2104
 ;; Keywords: convenience, usability
 
 ;;; This file is part of GNU Emacs
@@ -24,33 +24,29 @@
 ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
 ;; Floor, Boston, MA 02110-1301, USA.
 
-;;; Commentary:
-
-;; To interactively toggle the mode on / off:
+;; Usage:
+;;
+;; To interactively toggle the mode:
 ;;
-;;   M-x pixel-scroll-mode
+;;   M-x pixel-scroll-mode RET
 ;;
-;; To make the mode permanent, put this in your init file:
+;; To make the mode permanent, put these in your init file:
 ;;
 ;;   (require 'pixel-scroll)
 ;;   (pixel-scroll-mode 1)
-;;
-;; This package offers a global minor mode which makes Emacs scroll
-;; vertically with feel of modern applications.  This minor mode
-;; offers pixel-by-pixel scroll upward by mouse wheel using
-;; `set-window-vscroll', `window-vscroll', and `scroll-up'.  The minor
-;; mode overwrites parameters defined in `mwheel.el' to refer
-;; `pixel-scroll-up' and `pixel-scroll-down' instead of `scroll-up'
-;; and `scroll-down'.
-
-;;; Principle of vertical scroll:
-
-;; Scrolling text upward a line by pixels using `set-window-vscroll'
-;; and by a line using `scroll-up' gives similar visual feedback when
-;; vscroll location is @0.  Note vscroll location is vertical shift
-;; obtained by `window-vscroll'.  Line height by pixel is obtained by
-;; `frame-char-height' (to be exact, this is true for buffer with
-;; mono-sized font).  Following two lines scroll text in similar
+
+;;; Commentary:
+
+;; This package offers a global minor mode which makes Emacs scroll a
+;; line smoothly.
+
+;; The smooth scroll-up is carried out using `set-window-vscroll',
+;; `window-vscroll', and `scroll-up'.  Scrolling text upward a line by
+;; pixels using `set-window-vscroll' and by a line using `scroll-up'
+;; gives similar visual feedback when vscroll location is @0.  Note
+;; that vscroll location is vertical shift obtained by
+;; `window-vscroll'.  Line height by pixel is obtained by
+;; `frame-char-height'.  Following two lines scroll text in similar
 ;; fashion, visually.
 ;;
 ;;   (scroll-up 1)
@@ -66,46 +62,31 @@
 ;; When vscroll gets larger and as soon as point is beyond beginning
 ;; of a window, vscroll is set to zero.  To user, scope is changed
 ;; suddenly without point moved.  This package tries to scroll text
-;; upward by a line with pixel-by-pixel transition by following
-;; sequences.
+;; upward by a line with pixel-by-pixel transition by a following
+;; sequence.
 ;;
 ;;   (progn
 ;;     (vertical-motion 1)
 ;;     (dolist (vs (number-sequence 1 (1- (frame-char-height))))
-;;       (set-window-vscroll nil vs t) (sit-for 0.001))
+;;       (set-window-vscroll nil vs t) (sit-for 0.1))
 ;;     (scroll-up 1))
 
-
-;;; Change Log:
-
-;; 20170319.1153
-;;  - Replace `frame-char-height' by `line-pixel-height'.
-;; 20170414.0958
-;;  - Algorithm to scroll-down is offered by Eli Zaretskii.
-;;  - Implement scroll pixel-by-pixel upward.
-
 ;;; Todo:
-;; - Estimate height of unseen line at the top, on scrolling down.
-;; - Handle error to scroll stable For now, Scroll does not well in Info.
-
-;;; Long term concern:
-;; - Allowing pixel-level scrolling in Emacs requires a thorough
-;;   review of the related functionalities, to make sure none of them
-;;   zeroes out vscroll where users won't want that.
+;;
+;; Allowing pixel-level scrolling in Emacs requires a thorough review
+;; of the related functionalities, to make sure none of them zeroes
+;; out vscroll where users won't want that.
 
 ;;; Code:
 
 (require 'mwheel)
 
-(defcustom pixel-wait 0.001
-  "Idle time on a pixel scroll specified in second.  More wait
-will retult in slow and gentle scroll."
-  :group 'scrolling
-  :version "26.1"
-  :type 'float)
+(defvar pixel-wait 0
+  "Idle time on each step of pixel scroll specified in second.
+More wait will result in slow and gentle scroll.")
 
 (defvar pixel-resolution-fine-p nil
-  "Increase scrolling resolution to a pixel instead of a line.
+  "Set scrolling resolution to a pixel instead of a line.
 After a pixel scroll, typing C-n or C-p scrolls the window to
 make it fully visible, and undos the effect of the pixel-level
 scroll.")
@@ -120,10 +101,10 @@
   :global t
 
   (if pixel-scroll-mode
-      (progn (setq mwheel-scroll-up-function 'pixel-scroll-up)
-             (setq mwheel-scroll-down-function 'pixel-scroll-down))
-    (setq mwheel-scroll-up-function 'scroll-up)
-    (setq mwheel-scroll-down-function 'scroll-down)))
+      (setq mwheel-scroll-up-function 'pixel-scroll-up
+            mwheel-scroll-down-function 'pixel-scroll-down)
+    (setq mwheel-scroll-up-function 'scroll-up
+          mwheel-scroll-down-function 'scroll-down)))
 
 (defun pixel-scroll-up (&optional arg)
   "Scroll text of selected window up ARG lines.  This is
@@ -149,66 +130,74 @@
   (dotimes (ii arg)
     (if (equal (window-start) (point-min))
         (scroll-down 1) ; when beginning-of-buffer is seen, relay on robust guy
-      (when (or (pixel-point-at-bottom-p) ; prevent too late
-                (and scroll-preserve-screen-position
-                     (not (pixel-point-at-top-p)))) ; prevent too fast
+      (while (or (pixel-point-at-bottom-p) ; prevent too late (try several lines)
+                 (and scroll-preserve-screen-position
+                      (not (pixel-point-at-top-p)))) ; prevent too fast
         (vertical-motion -1)))
     (pixel-scroll-pixel-down (if pixel-resolution-fine-p
                                  1
-                               (pixel-line-height)))))
+                               (pixel-line-height -1)))))
 
 (defun pixel-point-at-top-p ()
   "Return if point is at top of a window."
-  (<= (cdr (posn-x-y (posn-at-point)))
-      (line-pixel-height)))
+  (let ((y (cdr (posn-x-y (posn-at-point)))))
+    (if y
+        (< y ; top margin
+           (pixel-line-height))
+      ;; when point is out of scope by hscroll
+      (< (count-lines (window-start) (point)) 1))))
 
 (defun pixel-point-at-bottom-p ()
   "Return if point is at bottom of a window."
-  (let* ((edges (window-inside-pixel-edges))
-         (height (- (nth 3 edges) (nth 1 edges))) ; bottom - top
-         (mergin (- height (cdr (posn-x-y (posn-at-point))))))
-    (<= mergin
-        (* 2 (line-pixel-height)))))
+  (let* ((y (cdr (posn-x-y (posn-at-point))))
+         (edges (window-inside-pixel-edges))
+         (height (- (nth 3 edges) (nth 1 edges)))) ; (- bottom top)
+    (if y
+        (< (- height (+ y (line-pixel-height))) ; bottom margin
+           (pixel-line-height -1)) ; coming line
+      ;; when point is out of scope by hscroll
+      (< (count-lines (point) (window-end)) 4))))
 
 (defun pixel-scroll-pixel-up (amt)
   "Scroll text of selected windows up AMT pixels.  Scope moves
 downward."
   (while (>= (+ (window-vscroll nil t) amt)
              (pixel-line-height))
-    (setq amt (- amt (pixel--scroll-line-up)))) ; major scroll
-  (pixel--scroll-pixel-up amt)) ; minor scroll
+    (setq amt (- amt (pixel--whistlestop-line-up)))) ; major scroll
+  (pixel--whistlestop-pixel-up amt)) ; minor scroll
 
 (defun pixel-scroll-pixel-down (amt)
   "Scroll text of selected windows down AMT pixels.  Scope moves
 upward."
-  ;; FIXME: Cannot scroll down on Info sometimes
   (while (> amt 0)
     (let ((vs (window-vscroll nil t)))
       (if (equal vs 0)
-          (pixel-scroll-down-and-set-window-vscroll (1- (pixel-line-height)))
+          (pixel-scroll-down-and-set-window-vscroll
+           (1- (pixel-line-height -1)))
         (set-window-vscroll nil (1- vs) t))
       (setq amt (1- amt))
       (sit-for pixel-wait))))
 
-(defun pixel--scroll-line-up ()
-  "Scroll text upward a line with pixel transition.  When `vscroll' is non-zero,
-complete scrolling a line.  When `vscroll' is larger than height
-of multiple lines, for example 88, this flushes multiple lines.
-At the end, `vscroll' will be zero.  This assumes that the lines
-are with the same height.  Scope moves downward.  This function
-returns number of pixels that were scrolled."
+(defun pixel--whistlestop-line-up ()
+  "Scroll text upward a line with each pixel whistlestopped.
+When `vscroll' is non-zero, complete scrolling a line.  When
+`vscroll' is larger than height of multiple lines, for example
+88, this flushes multiple lines.  At the end, `vscroll' will be
+zero.  This assumes that the lines are with the same height.
+Scope moves downward.  This function returns number of pixels
+that was scrolled."
   (let* ((src (window-vscroll nil t))  ; EXAMPLE (initial)      @0   @8  @88
          (height (pixel-line-height))  ;                        25   25   23
          (line (1+ (/ src height)))    ; catch up + one line    Δ1   Δ1   Δ4
          (dst (* line height))         ; goal                  @25  @25  @92
          (delta (- dst src)))          ; pixels to be scrolled  25   17    4
-    (pixel--scroll-pixel-up (1- delta)) ; sweep until one less  @24  @24  @91
+    (pixel--whistlestop-pixel-up (1- delta)) ; until one less  @24  @24  @91
     (scroll-up line) (sit-for pixel-wait) ; scroll 1 pixel      @0   @0   @0
     delta))
 
-(defun pixel--scroll-pixel-up (n)
-  "Scroll text upward to N pixels with pixel transition.  Scope
-moves downward."
+(defun pixel--whistlestop-pixel-up (n)
+  "Scroll text upward by N pixels with each pixel whistlestopped.
+Scope moves downward."
   (when (> n 0)
     (let ((vs0 (window-vscroll nil t)))
       (dolist (vs (number-sequence (1+ vs0) (+ vs0 n)))
@@ -216,28 +205,47 @@
 
 (defun pixel-line-height (&optional pos)
   "Return height in pixels of text line of POS in the selected
-window.  When POS is nil, height of the first line of the window
-is provided.  When height of all lines are equal, you don't need
-this function but `frame-char-height'.  See Info node `(elisp)
-Line Height'."
+window.  When POS is nil or negative, height of the first line or
+the coming line above the first line is provided."
   (or pos (setq pos (window-start)))
+  (if (< pos 0)
+      (setq pos (pixel-point-at-coming-line)))
   (save-excursion
     (goto-char pos)
-    (line-pixel-height)))
+    (line-pixel-height))) ; frame-char-height
+
+(defun pixel-point-at-coming-line ()
+  "Return the character position of the first character on the
+coming line just above the scope of current window.  This code is
+presented at
+https://lists.gnu.org/archive/html/emacs-devel/2017-04/msg00475.html."
+  (let* ((win0 (window-start))
+         (vscroll0 (window-vscroll nil t))
+         (pos
+          (save-excursion
+            (goto-char win0)
+            (if (bobp)
+                (point-min)
+              ;; When there's an overlay string at window-start,
+              ;; (beginning-of-visual-line 0) stays put.
+              (let ((ppos (point))
+                    (tem (beginning-of-visual-line 0)))
+                (if (eq tem ppos)
+                    (vertical-motion -1))
+                (point))))))
+    (set-window-start nil win0 t) ; restore the window
+    (set-window-vscroll nil vscroll0 t) ; restore the window
+    pos))
 
 (defun pixel-scroll-down-and-set-window-vscroll (vscroll)
-  "Scroll down a line and set VSCROLL in pixels.  This is code is
+  "Scroll down a line and set VSCROLL in pixels.  This code is
 presented at
 https://lists.gnu.org/archive/html/emacs-devel/2017-04/msg00366.html.
 It is important to call `set-window-start' to force the display
 engine use that particular position as the window-start point.
 Otherwise, redisplay will reset the window's vscroll."
-  (let ((pos
-         (save-excursion
-           (goto-char (window-start))
-           (beginning-of-visual-line 0))))
-    (set-window-start nil pos t)
-    (set-window-vscroll nil vscroll t)))
+  (set-window-start nil (pixel-point-at-coming-line) t)
+  (set-window-vscroll nil vscroll t))
 
 (provide 'pixel-scroll)
 ;;; pixel-scroll.el ends here

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-19 12:21                                                       ` Tak Kunihiro
@ 2017-04-19 12:38                                                         ` Kaushal Modi
  2017-04-19 12:42                                                           ` Kaushal Modi
  2017-04-19 14:44                                                           ` Eli Zaretskii
  0 siblings, 2 replies; 63+ messages in thread
From: Kaushal Modi @ 2017-04-19 12:38 UTC (permalink / raw)
  To: Tak Kunihiro, Eli Zaretskii
  Cc: Clément Pit-Claudel, yuri.v.khan, Emacs developers

[-- Attachment #1: Type: text/plain, Size: 466 bytes --]

On Wed, Apr 19, 2017, 8:22 AM Tak Kunihiro <tkk@misasa.okayama-u.ac.jp>
wrote:

>
>  (setq pixel-resolution-fine-p t)


I have yet to try this minor mode.

But I have a comment on that variable name. I learnt recently that foo-p
naming convention is only for predicate functions that return nil or
non-nil.

So may be remove the "-p" from that variable as the variable being t
implies that whatever the variable is describing is going to happen.

> --

Kaushal Modi

[-- Attachment #2: Type: text/html, Size: 1040 bytes --]

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-19 12:38                                                         ` Kaushal Modi
@ 2017-04-19 12:42                                                           ` Kaushal Modi
  2017-04-19 14:44                                                           ` Eli Zaretskii
  1 sibling, 0 replies; 63+ messages in thread
From: Kaushal Modi @ 2017-04-19 12:42 UTC (permalink / raw)
  To: Tak Kunihiro, Eli Zaretskii
  Cc: Clément Pit-Claudel, yuri.v.khan, Emacs developers

[-- Attachment #1: Type: text/plain, Size: 684 bytes --]

On Wed, Apr 19, 2017, 8:38 AM Kaushal Modi <kaushal.modi@gmail.com> wrote:

> On Wed, Apr 19, 2017, 8:22 AM Tak Kunihiro <tkk@misasa.okayama-u.ac.jp>
> wrote:
>
>>
>>  (setq pixel-resolution-fine-p t)
>
>
> I have yet to try this minor mode.
>
> But I have a comment on that variable name. I learnt recently that foo-p
> naming convention is only for predicate functions that return nil or
> non-nil.
>
> So may be remove the "-p" from that variable as the variable being t
> implies that whatever the variable is describing is going to happen.
>

Reference:
https://lists.gnu.org/archive/html/emacs-devel/2016-07/msg00734.html

Search for 'predicate' on that page.
-- 

Kaushal Modi

[-- Attachment #2: Type: text/html, Size: 1464 bytes --]

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-19 12:38                                                         ` Kaushal Modi
  2017-04-19 12:42                                                           ` Kaushal Modi
@ 2017-04-19 14:44                                                           ` Eli Zaretskii
  2017-04-19 15:02                                                             ` Stefan Monnier
  2017-04-19 15:07                                                             ` Kaushal Modi
  1 sibling, 2 replies; 63+ messages in thread
From: Eli Zaretskii @ 2017-04-19 14:44 UTC (permalink / raw)
  To: Kaushal Modi; +Cc: cpitclaudel, tkk, yuri.v.khan, emacs-devel

> From: Kaushal Modi <kaushal.modi@gmail.com>
> Date: Wed, 19 Apr 2017 12:38:52 +0000
> Cc: Clément Pit-Claudel <cpitclaudel@gmail.com>, 
> 	Emacs developers <emacs-devel@gnu.org>, yuri.v.khan@gmail.com
> 
> I learnt recently that foo-p naming convention is only for predicate
> functions that return nil or non-nil.

We have several dozen of variables in Emacs whose names end in "-p".



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-19 14:44                                                           ` Eli Zaretskii
@ 2017-04-19 15:02                                                             ` Stefan Monnier
  2017-04-19 15:07                                                             ` Kaushal Modi
  1 sibling, 0 replies; 63+ messages in thread
From: Stefan Monnier @ 2017-04-19 15:02 UTC (permalink / raw)
  To: emacs-devel

> We have several dozen of variables in Emacs whose names end in "-p".

Yes, it's a common error.


        Stefan




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-19 14:44                                                           ` Eli Zaretskii
  2017-04-19 15:02                                                             ` Stefan Monnier
@ 2017-04-19 15:07                                                             ` Kaushal Modi
  2017-04-19 15:37                                                               ` Eli Zaretskii
  1 sibling, 1 reply; 63+ messages in thread
From: Kaushal Modi @ 2017-04-19 15:07 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: cpitclaudel, tkk, yuri.v.khan, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1043 bytes --]

On Wed, Apr 19, 2017 at 10:44 AM Eli Zaretskii <eliz@gnu.org> wrote:

> > From: Kaushal Modi <kaushal.modi@gmail.com>
> > Date: Wed, 19 Apr 2017 12:38:52 +0000
> > Cc: Clément Pit-Claudel <cpitclaudel@gmail.com>,
> >       Emacs developers <emacs-devel@gnu.org>, yuri.v.khan@gmail.com
> >
> > I learnt recently that foo-p naming convention is only for predicate
> > functions that return nil or non-nil.
>
> We have several dozen of variables in Emacs whose names end in "-p".
>

It's just a convention, and it makes sense so I suggested that.

I ran ag in emacs/lisp:

1. 1511 matches -- defuns and defsubsts ending in -p -- ag
'def(un|subst)\s+[^ ]+-p\s+' --stats
2. 149 matches -- defvars, defconsts and defcustoms ending in -p -- ag
'def(var|const|custom)\s+[^ ]+-p\s+' --stats
3. 65 matches -- Just the user-facing defcustoms -- ag 'defcustom\s+[^
]+-p\s+' --stats

So it is correct that there are dozens of variables that end in -p, but
it's a stronger convention to have -p in functions.
-- 

Kaushal Modi

[-- Attachment #2: Type: text/html, Size: 1794 bytes --]

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-19 15:07                                                             ` Kaushal Modi
@ 2017-04-19 15:37                                                               ` Eli Zaretskii
  2017-04-19 15:49                                                                 ` Kaushal Modi
  0 siblings, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2017-04-19 15:37 UTC (permalink / raw)
  To: Kaushal Modi; +Cc: cpitclaudel, tkk, yuri.v.khan, emacs-devel

> From: Kaushal Modi <kaushal.modi@gmail.com>
> Date: Wed, 19 Apr 2017 15:07:11 +0000
> Cc: tkk@misasa.okayama-u.ac.jp, cpitclaudel@gmail.com, emacs-devel@gnu.org, 
> 	yuri.v.khan@gmail.com
> 
>  > I learnt recently that foo-p naming convention is only for predicate
>  > functions that return nil or non-nil.
> 
>  We have several dozen of variables in Emacs whose names end in "-p".
> 
> It's just a convention, and it makes sense so I suggested that.

IMO it's not a convention as long as we don't have it in the
appropriate section of the ELisp manual.  If we want to make it a
convention, we should begin by documenting it.  Otherwise we have no
reason to expect contributors to discover such conventions and follow
them.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-19 15:37                                                               ` Eli Zaretskii
@ 2017-04-19 15:49                                                                 ` Kaushal Modi
  2017-04-19 16:10                                                                   ` Eli Zaretskii
                                                                                     ` (2 more replies)
  0 siblings, 3 replies; 63+ messages in thread
From: Kaushal Modi @ 2017-04-19 15:49 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: cpitclaudel, tkk, emacs-devel, yuri.v.khan

[-- Attachment #1: Type: text/plain, Size: 682 bytes --]

On Wed, Apr 19, 2017 at 11:37 AM Eli Zaretskii <eliz@gnu.org> wrote:

> IMO it's not a convention as long as we don't have it in the
> appropriate section of the ELisp manual.  If we want to make it a
> convention, we should begin by documenting it.  Otherwise we have no
> reason to expect contributors to discover such conventions and follow
> them.
>

I can try my hand providing a patch for that. Which section should I
update?

I have opened a bug report where we can continue this discussion:
https://debbugs.gnu.org/cgi/bugreport.cgi?bug=26564

But for the patch Tak provided, do we want to continue with the unspoken
convention of not ending vars in "-p"?
-- 

Kaushal Modi

[-- Attachment #2: Type: text/html, Size: 1171 bytes --]

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-19 15:49                                                                 ` Kaushal Modi
@ 2017-04-19 16:10                                                                   ` Eli Zaretskii
       [not found]                                                                   ` <<83zifcbcoc.fsf@gnu.org>
  2017-04-21  2:05                                                                   ` Richard Stallman
  2 siblings, 0 replies; 63+ messages in thread
From: Eli Zaretskii @ 2017-04-19 16:10 UTC (permalink / raw)
  To: Kaushal Modi; +Cc: cpitclaudel, tkk, yuri.v.khan, emacs-devel

> From: Kaushal Modi <kaushal.modi@gmail.com>
> Date: Wed, 19 Apr 2017 15:49:43 +0000
> Cc: cpitclaudel@gmail.com, tkk@misasa.okayama-u.ac.jp, emacs-devel@gnu.org,
> 	yuri.v.khan@gmail.com
> 
> I can try my hand providing a patch for that. Which section should I update? 

"Coding Conventions".  TIA.

> But for the patch Tak provided, do we want to continue with the unspoken convention of not ending vars in "-p"?

I'd like first to hear what people think about this new convention.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* RE: scroll-down with pixel transition
       [not found]                                                                   ` <<83zifcbcoc.fsf@gnu.org>
@ 2017-04-19 17:33                                                                     ` Drew Adams
  2017-04-19 18:21                                                                       ` Lars Brinkhoff
  0 siblings, 1 reply; 63+ messages in thread
From: Drew Adams @ 2017-04-19 17:33 UTC (permalink / raw)
  To: Eli Zaretskii, Kaushal Modi; +Cc: cpitclaudel, tkk, emacs-devel, yuri.v.khan

> I'd like first to hear what people think about this new convention.

I oppose it - just one opinion.  On the contrary, I think that
we should encourage `-p' for Boolean non-option variables, and
we should have a different naming convention (e.g. `-flag')
for Boolean options.

I put my reasons in the bug thread:
https://debbugs.gnu.org/cgi/bugreport.cgi?bug=26564#14



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-19 17:33                                                                     ` Drew Adams
@ 2017-04-19 18:21                                                                       ` Lars Brinkhoff
  0 siblings, 0 replies; 63+ messages in thread
From: Lars Brinkhoff @ 2017-04-19 18:21 UTC (permalink / raw)
  To: emacs-devel

Drew Adams wrote:
>> I'd like first to hear what people think about this new convention.
>
> I oppose it - just one opinion.  On the contrary, I think that we
> should encourage `-p' for Boolean non-option variables, and we should
> have a different naming convention (e.g. `-flag') for Boolean options.

I'm not sure this is a reason for or against or anything at all really,
but I note that Common Lisp doesn't seem have any variables using the -p
convention.

The same goes for Maclisp.  Which presumably was an inspiration for
Emacs Lisp.




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-19 15:49                                                                 ` Kaushal Modi
  2017-04-19 16:10                                                                   ` Eli Zaretskii
       [not found]                                                                   ` <<83zifcbcoc.fsf@gnu.org>
@ 2017-04-21  2:05                                                                   ` Richard Stallman
  2017-04-21  6:26                                                                     ` Eli Zaretskii
  2 siblings, 1 reply; 63+ messages in thread
From: Richard Stallman @ 2017-04-21  2:05 UTC (permalink / raw)
  To: Kaushal Modi; +Cc: eliz, tkk, yuri.v.khan, cpitclaudel, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > But for the patch Tak provided, do we want to continue with the unspoken
  > convention of not ending vars in "-p"?

Our convention is to end user option names in '-flag', when they are
for users to set.  Let's document that, if it isn't already.

I don't know whether we have any particular convention for t-or-nil
variables that aren't user options.

-- 
Dr Richard Stallman
President, Free Software Foundation (gnu.org, fsf.org)
Internet Hall-of-Famer (internethalloffame.org)
Skype: No way! See stallman.org/skype.html.




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-21  2:05                                                                   ` Richard Stallman
@ 2017-04-21  6:26                                                                     ` Eli Zaretskii
  2017-04-21  8:52                                                                       ` Tak Kunihiro
                                                                                         ` (3 more replies)
  0 siblings, 4 replies; 63+ messages in thread
From: Eli Zaretskii @ 2017-04-21  6:26 UTC (permalink / raw)
  To: rms; +Cc: yuri.v.khan, tkk, emacs-devel, cpitclaudel, kaushal.modi

> From: Richard Stallman <rms@gnu.org>
> Date: Thu, 20 Apr 2017 22:05:25 -0400
> Cc: eliz@gnu.org, tkk@misasa.okayama-u.ac.jp, yuri.v.khan@gmail.com,
> 	cpitclaudel@gmail.com, emacs-devel@gnu.org
> 
> Our convention is to end user option names in '-flag', when they are
> for users to set.  Let's document that, if it isn't already.

It is not currently documented in code conventions.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-21  6:26                                                                     ` Eli Zaretskii
@ 2017-04-21  8:52                                                                       ` Tak Kunihiro
  2017-04-30 12:13                                                                         ` Tak Kunihiro
  2017-04-21 13:21                                                                       ` Perry E. Metzger
                                                                                         ` (2 subsequent siblings)
  3 siblings, 1 reply; 63+ messages in thread
From: Tak Kunihiro @ 2017-04-21  8:52 UTC (permalink / raw)
  To: eliz; +Cc: cpitclaudel, rms, yuri.v.khan, tkk, kaushal.modi, emacs-devel

[-- Attachment #1: Type: Text/Plain, Size: 855 bytes --]

> So may be remove the "-p" from that variable as the variable being t
> implies that whatever the variable is describing is going to happen.

> We have several dozen of variables in Emacs whose names end in "-p".

> Yes, it's a common error.

> Our convention is to end user option names in '-flag', when they are
> for users to set.  Let's document that, if it isn't already.

Since no one is positive for `-p', I changed name of the variable
`pixel-resolution-fine-p' to `pixel-resolution-fine-flag'.  I also
tried to polish comments.

I send the revised copy and the diff.  Two possible ways to test the
minor-mode are shown below.

 (require 'pixel-scroll)
 (pixel-scroll-mode 1)
 (setq pixel-resolution-fine-flag t)

 (require 'pixel-scroll)
 (pixel-scroll-mode 1)
 (setq mouse-wheel-scroll-amount '(1 ((shift) . 5) ((control))))

Happy Scrolling!


[-- Attachment #2: pixel-scroll.el --]
[-- Type: Text/Plain, Size: 9552 bytes --]

;;; pixel-scroll.el --- Scroll a line smoothly

;; Package-Requires: ((emacs "24.5"))
;; Version: 1.0.0
;; Package-Version: 20170421.1738
;; Keywords: convenience, usability

;;; This file is part of GNU Emacs

;;; License

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program; see the file COPYING.  If not, write to
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
;; Floor, Boston, MA 02110-1301, USA.

;; Usage:
;;
;; To interactively toggle the mode:
;;
;;   M-x pixel-scroll-mode RET
;;
;; To make the mode permanent, put these in your init file:
;;
;;   (require 'pixel-scroll)
;;   (pixel-scroll-mode 1)

;;; Commentary:

;; This package offers a global minor mode which makes mouse-wheel
;; scroll a line smoothly.
;;
;; Scrolling a line up by `set-window-vscroll' and that by `scroll-up'
;; give similar display as shown below.
;;
;;  A: (scroll-up 1)
;;  B: (set-window-vscroll nil (frame-char-height) t)
;;
;; Also scrolling a pixel up by `set-window-vscroll' and that by
;; `scroll-up' give similar display, when vscroll is the last pixel of
;; the line, as shown below.
;;
;;  A: (scroll-up 1)
;;  B: (set-window-vscroll nil (1- (frame-char-height) t)) (scroll-up 1)
;;
;; When point reaches to the top of a window on scroll by
;; `set-window-vscroll', vscroll is set to zero.  To scroll a line
;; smoothly and continuously, this package scrolls a line by following
;; sequences.
;;
;;  (vertical-motion 1)
;;  (dolist (vs (number-sequence 1 (1- (frame-char-height))))
;;    (set-window-vscroll nil vs t) (sit-for 0))
;;  (scroll-up 1)

;;; Todo:
;;
;; Allowing pixel-level scrolling in Emacs requires a thorough review
;; of the related functionalities, to make sure none of them zeroes
;; out vscroll where users won't want that.

;;; Code:

(require 'mwheel)

(defvar pixel-wait 0
  "Idle time on each step of pixel scroll specified in second.
More wait will result in slow and gentle scroll.")

(defvar pixel-resolution-fine-flag nil
  "Set scrolling resolution to a pixel instead of a line.
After a pixel scroll, typing C-n or C-p scrolls the window to
make it fully visible, and undos the effect of the pixel-level
scroll.")

(define-minor-mode pixel-scroll-mode
  "A minor mode to scroll text pixel-by-pixel.  With a prefix argument ARG,
enable Pixel Scroll mode if ARG is positive, and disable it
otherwise.  If called from Lisp, enable Pixel Scroll mode if ARG
is omitted or nil."
  :init-value nil
  :group 'scrolling
  :global t

  (if pixel-scroll-mode
      (setq mwheel-scroll-up-function 'pixel-scroll-up
            mwheel-scroll-down-function 'pixel-scroll-down)
    (setq mwheel-scroll-up-function 'scroll-up
          mwheel-scroll-down-function 'scroll-down)))

(defun pixel-scroll-up (&optional arg)
  "Scroll text of selected window up ARG lines.  This is
alternative of `scroll-up'.  Scope moves downward."
  (interactive)
  (or arg (setq arg 1))
  (dotimes (ii arg) ; move scope downward
    (if (<= (count-lines (window-start) (window-end)) 2)
        (scroll-up 1) ; when end-of-buffer is close, relay on robust guy
      (when (or (pixel-point-at-top-p) ; prevent too late
                (and scroll-preserve-screen-position
                     (not (pixel-point-at-bottom-p)))) ; prevent too fast
        (vertical-motion 1)) ; move point downward
      (pixel-scroll-pixel-up (if pixel-resolution-fine-flag
                                 1
                               (pixel-line-height)))))) ; move scope downward

(defun pixel-scroll-down (&optional arg)
  "Scroll text of selected window down ARG lines.  This is
alternative of `scroll-down'.  Scope moves upward."
  (interactive)
  (or arg (setq arg 1))
  (dotimes (ii arg)
    (if (equal (window-start) (point-min))
        (scroll-down 1) ; when beginning-of-buffer is seen, relay on robust guy
      (while (or (pixel-point-at-bottom-p) ; prevent too late (try several lines)
                 (and scroll-preserve-screen-position
                      (not (pixel-point-at-top-p)))) ; prevent too fast
        (vertical-motion -1)))
    (pixel-scroll-pixel-down (if pixel-resolution-fine-flag
                                 1
                               (pixel-line-height -1)))))

(defun pixel-point-at-top-p ()
  "Return if point is at top of a window."
  (let ((y (cdr (posn-x-y (posn-at-point)))))
    (if y
        (< y ; top margin
           (pixel-line-height))
      ;; when point is out of scope by hscroll
      (< (count-lines (window-start) (point)) 1))))

(defun pixel-point-at-bottom-p ()
  "Return if point is at bottom of a window."
  (let* ((y (cdr (posn-x-y (posn-at-point))))
         (edges (window-inside-pixel-edges))
         (height (- (nth 3 edges) (nth 1 edges)))) ; (- bottom top)
    (if y
        (< (- height (+ y (line-pixel-height))) ; bottom margin
           (pixel-line-height -1)) ; coming line
      ;; when point is out of scope by hscroll
      (< (count-lines (point) (window-end)) 4))))

(defun pixel-scroll-pixel-up (amt)
  "Scroll text of selected windows up AMT pixels.  Scope moves
downward."
  (while (>= (+ (window-vscroll nil t) amt)
             (pixel-line-height))
    (setq amt (- amt (pixel--whistlestop-line-up)))) ; major scroll
  (pixel--whistlestop-pixel-up amt)) ; minor scroll

(defun pixel-scroll-pixel-down (amt)
  "Scroll text of selected windows down AMT pixels.  Scope moves
upward."
  (while (> amt 0)
    (let ((vs (window-vscroll nil t)))
      (if (equal vs 0)
          (pixel-scroll-down-and-set-window-vscroll
           (1- (pixel-line-height -1)))
        (set-window-vscroll nil (1- vs) t))
      (setq amt (1- amt))
      (sit-for pixel-wait))))

(defun pixel--whistlestop-line-up ()
  "Scroll text upward a line with each pixel whistlestopped.
When `vscroll' is non-zero, complete scrolling a line.  When
`vscroll' is larger than height of multiple lines, for example
88, this flushes multiple lines.  At the end, `vscroll' will be
zero.  This assumes that the lines are with the same height.
Scope moves downward.  This function returns number of pixels
that was scrolled."
  (let* ((src (window-vscroll nil t))  ; EXAMPLE (initial)      @0   @8  @88
         (height (pixel-line-height))  ;                        25   25   23
         (line (1+ (/ src height)))    ; catch up + one line    Δ1   Δ1   Δ4
         (dst (* line height))         ; goal                  @25  @25  @92
         (delta (- dst src)))          ; pixels to be scrolled  25   17    4
    (pixel--whistlestop-pixel-up (1- delta)) ; until one less  @24  @24  @91
    (scroll-up line) (sit-for pixel-wait) ; scroll 1 pixel      @0   @0   @0
    delta))

(defun pixel--whistlestop-pixel-up (n)
  "Scroll text upward by N pixels with each pixel whistlestopped.
Scope moves downward."
  (when (> n 0)
    (let ((vs0 (window-vscroll nil t)))
      (dolist (vs (number-sequence (1+ vs0) (+ vs0 n)))
        (set-window-vscroll nil vs t) (sit-for pixel-wait)))))

(defun pixel-line-height (&optional pos)
  "Return height in pixels of text line of POS in the selected
window.  When POS is nil or negative, height of the first line or
the coming line above the first line, respectively, is provided."
  (or pos (setq pos (window-start)))
  (when (< pos 0)
    (setq pos (pixel-point-at-coming-line)))
  (save-excursion
    (goto-char pos)
    (line-pixel-height))) ; frame-char-height

(defun pixel-point-at-coming-line ()
  "Return the character position of the first character on the
coming line just above the scope of current window.  This code is
presented at
https://lists.gnu.org/archive/html/emacs-devel/2017-04/msg00475.html."
  (let* ((win0 (window-start))
         (vscroll0 (window-vscroll nil t))
         (pos
          (save-excursion
            (goto-char win0)
            (if (bobp)
                (point-min)
              ;; When there's an overlay string at window-start,
              ;; (beginning-of-visual-line 0) stays put.
              (let ((ppos (point))
                    (tem (beginning-of-visual-line 0)))
                (if (eq tem ppos)
                    (vertical-motion -1))
                (point))))))
    (set-window-start nil win0 t) ; restore the window
    (set-window-vscroll nil vscroll0 t) ; restore the window
    pos))

(defun pixel-scroll-down-and-set-window-vscroll (vscroll)
  "Scroll down a line and set VSCROLL in pixels.  This code is
presented at
https://lists.gnu.org/archive/html/emacs-devel/2017-04/msg00366.html.
It is important to call `set-window-start' to force the display
engine use that particular position as the window-start point.
Otherwise, redisplay will reset the window's vscroll."
  (set-window-start nil (pixel-point-at-coming-line) t)
  (set-window-vscroll nil vscroll t))

(provide 'pixel-scroll)
;;; pixel-scroll.el ends here

[-- Attachment #3: pixel-scroll.20170419.el.patch --]
[-- Type: Text/X-Patch, Size: 4902 bytes --]

--- pixel-scroll.20170419.el	2017-04-20 06:42:39.022814500 +0900
+++ pixel-scroll.el	2017-04-21 17:38:07.903718800 +0900
@@ -2,7 +2,7 @@
 
 ;; Package-Requires: ((emacs "24.5"))
 ;; Version: 1.0.0
-;; Package-Version: 20170419.2104
+;; Package-Version: 20170421.1738
 ;; Keywords: convenience, usability
 
 ;;; This file is part of GNU Emacs
@@ -37,39 +37,31 @@
 
 ;;; Commentary:
 
-;; This package offers a global minor mode which makes Emacs scroll a
-;; line smoothly.
-
-;; The smooth scroll-up is carried out using `set-window-vscroll',
-;; `window-vscroll', and `scroll-up'.  Scrolling text upward a line by
-;; pixels using `set-window-vscroll' and by a line using `scroll-up'
-;; gives similar visual feedback when vscroll location is @0.  Note
-;; that vscroll location is vertical shift obtained by
-;; `window-vscroll'.  Line height by pixel is obtained by
-;; `frame-char-height'.  Following two lines scroll text in similar
-;; fashion, visually.
-;;
-;;   (scroll-up 1)
-;;   (set-window-vscroll nil (frame-char-height) t)
-;;
-;; Scrolling text upward by a pixel and a line yields similar result
-;; when vscroll location is at the last pixel.  Following two lines
-;; scroll text in similar fashion, visually.
-;;
-;;   (scroll-up 1)
-;;   (set-window-vscroll nil (1- (frame-char-height) t)) (scroll-up 1)
-;;
-;; When vscroll gets larger and as soon as point is beyond beginning
-;; of a window, vscroll is set to zero.  To user, scope is changed
-;; suddenly without point moved.  This package tries to scroll text
-;; upward by a line with pixel-by-pixel transition by a following
-;; sequence.
-;;
-;;   (progn
-;;     (vertical-motion 1)
-;;     (dolist (vs (number-sequence 1 (1- (frame-char-height))))
-;;       (set-window-vscroll nil vs t) (sit-for 0.1))
-;;     (scroll-up 1))
+;; This package offers a global minor mode which makes mouse-wheel
+;; scroll a line smoothly.
+;;
+;; Scrolling a line up by `set-window-vscroll' and that by `scroll-up'
+;; give similar display as shown below.
+;;
+;;  A: (scroll-up 1)
+;;  B: (set-window-vscroll nil (frame-char-height) t)
+;;
+;; Also scrolling a pixel up by `set-window-vscroll' and that by
+;; `scroll-up' give similar display, when vscroll is the last pixel of
+;; the line, as shown below.
+;;
+;;  A: (scroll-up 1)
+;;  B: (set-window-vscroll nil (1- (frame-char-height) t)) (scroll-up 1)
+;;
+;; When point reaches to the top of a window on scroll by
+;; `set-window-vscroll', vscroll is set to zero.  To scroll a line
+;; smoothly and continuously, this package scrolls a line by following
+;; sequences.
+;;
+;;  (vertical-motion 1)
+;;  (dolist (vs (number-sequence 1 (1- (frame-char-height))))
+;;    (set-window-vscroll nil vs t) (sit-for 0))
+;;  (scroll-up 1)
 
 ;;; Todo:
 ;;
@@ -85,7 +77,7 @@
   "Idle time on each step of pixel scroll specified in second.
 More wait will result in slow and gentle scroll.")
 
-(defvar pixel-resolution-fine-p nil
+(defvar pixel-resolution-fine-flag nil
   "Set scrolling resolution to a pixel instead of a line.
 After a pixel scroll, typing C-n or C-p scrolls the window to
 make it fully visible, and undos the effect of the pixel-level
@@ -113,12 +105,12 @@
   (or arg (setq arg 1))
   (dotimes (ii arg) ; move scope downward
     (if (<= (count-lines (window-start) (window-end)) 2)
-        (scroll-up 1) ; when end of scroll is close, relay on robust guy
+        (scroll-up 1) ; when end-of-buffer is close, relay on robust guy
       (when (or (pixel-point-at-top-p) ; prevent too late
                 (and scroll-preserve-screen-position
                      (not (pixel-point-at-bottom-p)))) ; prevent too fast
         (vertical-motion 1)) ; move point downward
-      (pixel-scroll-pixel-up (if pixel-resolution-fine-p
+      (pixel-scroll-pixel-up (if pixel-resolution-fine-flag
                                  1
                                (pixel-line-height)))))) ; move scope downward
 
@@ -134,7 +126,7 @@
                  (and scroll-preserve-screen-position
                       (not (pixel-point-at-top-p)))) ; prevent too fast
         (vertical-motion -1)))
-    (pixel-scroll-pixel-down (if pixel-resolution-fine-p
+    (pixel-scroll-pixel-down (if pixel-resolution-fine-flag
                                  1
                                (pixel-line-height -1)))))
 
@@ -206,10 +198,10 @@
 (defun pixel-line-height (&optional pos)
   "Return height in pixels of text line of POS in the selected
 window.  When POS is nil or negative, height of the first line or
-the coming line above the first line is provided."
+the coming line above the first line, respectively, is provided."
   (or pos (setq pos (window-start)))
-  (if (< pos 0)
-      (setq pos (pixel-point-at-coming-line)))
+  (when (< pos 0)
+    (setq pos (pixel-point-at-coming-line)))
   (save-excursion
     (goto-char pos)
     (line-pixel-height))) ; frame-char-height

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-21  6:26                                                                     ` Eli Zaretskii
  2017-04-21  8:52                                                                       ` Tak Kunihiro
@ 2017-04-21 13:21                                                                       ` Perry E. Metzger
  2017-04-21 13:36                                                                         ` Eli Zaretskii
  2017-04-21 13:29                                                                       ` scroll-down with pixel transition Stefan Monnier
  2017-04-22  2:31                                                                       ` Richard Stallman
  3 siblings, 1 reply; 63+ messages in thread
From: Perry E. Metzger @ 2017-04-21 13:21 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: rms, emacs-devel

On Fri, 21 Apr 2017 09:26:09 +0300 Eli Zaretskii <eliz@gnu.org> wrote:
> > From: Richard Stallman <rms@gnu.org>
> > Date: Thu, 20 Apr 2017 22:05:25 -0400
> > Cc: eliz@gnu.org, tkk@misasa.okayama-u.ac.jp,
> > yuri.v.khan@gmail.com, cpitclaudel@gmail.com, emacs-devel@gnu.org
> > 
> > Our convention is to end user option names in '-flag', when they
> > are for users to set.  Let's document that, if it isn't already.  
> 
> It is not currently documented in code conventions.
> 

If this really is the convention, I should change the option name I'm
about to add (related to column number display.) Or perhaps I
misunderstand the convention?

Perry
-- 
Perry E. Metzger		perry@piermont.com



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-21  6:26                                                                     ` Eli Zaretskii
  2017-04-21  8:52                                                                       ` Tak Kunihiro
  2017-04-21 13:21                                                                       ` Perry E. Metzger
@ 2017-04-21 13:29                                                                       ` Stefan Monnier
  2017-04-21 15:47                                                                         ` Drew Adams
  2017-04-22  2:31                                                                       ` Richard Stallman
  3 siblings, 1 reply; 63+ messages in thread
From: Stefan Monnier @ 2017-04-21 13:29 UTC (permalink / raw)
  To: emacs-devel

>>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:

>> From: Richard Stallman <rms@gnu.org>
>> Date: Thu, 20 Apr 2017 22:05:25 -0400
>> Cc: eliz@gnu.org, tkk@misasa.okayama-u.ac.jp, yuri.v.khan@gmail.com,
>> cpitclaudel@gmail.com, emacs-devel@gnu.org
>> 
>> Our convention is to end user option names in '-flag', when they are
>> for users to set.  Let's document that, if it isn't already.

> It is not currently documented in code conventions.

I think it used to be there, but I demoted it to:

    @item @dots{}-flag
    The value is significant only as to whether it is @code{nil} or not.
    Since such variables often end up acquiring more values over time,
    this convention is not strongly recommended.

in variables.texi.
In my experience, using FOO instead of FOO-flag is a better choice.

Also, many boolean config variables can be introduced as minor modes
(in which case their name should end in "-mode").


        Stefan




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-21 13:21                                                                       ` Perry E. Metzger
@ 2017-04-21 13:36                                                                         ` Eli Zaretskii
  2017-04-21 14:24                                                                           ` Option name conventions (was Re: scroll-down with pixel transition) Perry E. Metzger
  0 siblings, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2017-04-21 13:36 UTC (permalink / raw)
  To: Perry E. Metzger; +Cc: rms, emacs-devel

> Date: Fri, 21 Apr 2017 09:21:52 -0400
> From: "Perry E. Metzger" <perry@piermont.com>
> Cc: rms@gnu.org, emacs-devel@gnu.org
> 
> > > Our convention is to end user option names in '-flag', when they
> > > are for users to set.  Let's document that, if it isn't already.  
> > 
> > It is not currently documented in code conventions.
> > 
> 
> If this really is the convention, I should change the option name I'm
> about to add (related to column number display.)

I see no reason to do that at this time, not until we agree that this
is the convention and document it as such.

Thanks.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Option name conventions (was Re: scroll-down with pixel transition)
  2017-04-21 13:36                                                                         ` Eli Zaretskii
@ 2017-04-21 14:24                                                                           ` Perry E. Metzger
  0 siblings, 0 replies; 63+ messages in thread
From: Perry E. Metzger @ 2017-04-21 14:24 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: rms, emacs-devel

On Fri, 21 Apr 2017 16:36:56 +0300 Eli Zaretskii <eliz@gnu.org> wrote:
> > > > Our convention is to end user option names in '-flag', when
> > > > they are for users to set.  Let's document that, if it isn't
> > > > already.    
> > > 
> > > It is not currently documented in code conventions.
> > >   
> > 
> > If this really is the convention, I should change the option name
> > I'm about to add (related to column number display.)  
> 
> I see no reason to do that at this time, not until we agree that
> this is the convention and document it as such.

Cool. Please do let people know if that changes.

Perry
-- 
Perry E. Metzger		perry@piermont.com



^ permalink raw reply	[flat|nested] 63+ messages in thread

* RE: scroll-down with pixel transition
  2017-04-21 13:29                                                                       ` scroll-down with pixel transition Stefan Monnier
@ 2017-04-21 15:47                                                                         ` Drew Adams
  0 siblings, 0 replies; 63+ messages in thread
From: Drew Adams @ 2017-04-21 15:47 UTC (permalink / raw)
  To: emacs-devel

> >> Our convention is to end user option names in '-flag', when they
> >> are for users to set.  Let's document that, if it isn't already.

+1

Except that the criterion should not be "when they are for
users to set".  All user options are for users to set.

Perhaps you didn't mean that, but you meant only names of
Boolean options?  (Your later mention of "t-or-nil" suggests
that.)

> > It is not currently documented in code conventions.
> 
> I think it used to be there, but I demoted it to:
> 
>     @item @dots{}-flag
>     The value is significant only as to whether it is @code{nil} or not.
>     Since such variables often end up acquiring more values over time,
>     this convention is not strongly recommended.

That's not a strong reason, IMO.  Lots of things change over
time, and if we want helpful names then we update the names
as needed, accordingly.

Yes, any name is a stake in the sand, and change can erode its
relevance.  But that's not a reason not to use helpful names.
Otherwise, we'd always use names that have no special meaning
(`x', `y', 'z'), to ensure maximum space for possible changes
in meaning.

I understand completely the problem of having a Boolean
option `foo-flag' evolve to an option where certain non-nil
values have special meaning (it is no longer strictly Boolean,
or even perhaps vaguely Boolean).  That's life.  A name change
at that point lets users know about the behavior change.

And in some cases a name change is not needed - when, for
example, all of the non-nil behaviors have a major behavior in
common, and that behavior is the main raison d'etre for the
option.  IOW, if it is still essentially a Boolean, but there
are some additional behavior differences, we might want to
keep the suffix `-flag'.

It's a judgment call.  Here's an example - you might argue
whether `-flag' is appropriate here, but the point is that
non-nil means use WYSIWYG display and nil does not.

(Evolution was not involved here, in fact - it was like
this at the outset.  But it could have evolved to this
from a simple t/nil choice.)

(defcustom icicle-WYSIWYG-Completions-flag "MMMM"
  "*Non-nil means show candidates in `*Completions*' using WYSIWYG.
...the particular non-nil value determines the appearance:
* If t, the candidate displays its meaning: WYSIWYG.
* If a string, the string is propertized and then appended to the
  candidate,  to serve as a color swatch."
  :group 'Icicles-Completions-Display
  :type '(choice
          (string
           :tag "Show candidate plus a WYSIWYG swatch with text..."
           :value "MMMM")
          (const
           :tag "Show candidate itself using WYSIWYG"
           t)
          (const
           :tag "Show candidate as is, with no text properties"
           nil)))

An alternative to such a naming convention, though it too
is imperfect, is to use a test - something like this:

(defun custom-type (variable)
  (and (custom-variable-p variable)
       (get variable 'custom-type)))

In my code (Icicles), there is a command that lets you
toggle Boolean options.  By default, the only options you
can do this to are those whose `custom-type' is `boolean'.
But with a prefix argument you can also toggle options
that are effectively Boolean, such as the one above.

(`nil' is always toggled to `t' by this command, but there
are other commands that cycle specific options among the
possible values or that remember the last non-nil value
and toggle `nil' back to it.)

The point is that in Emacs "Boolean", and so `-flag', can
mean something less strict than `t' vs `nil', and it can
help users if we provide easy ways to use more or less
strict interpretation - au choix - of whether a variable
is Boolean.

> In my experience, using FOO instead of FOO-flag is a better choice.

Does this boil down to the reason given in the doc (above)
that you wrote when you made the policy change?  Or is
there some additional reason?

> Also, many boolean config variables can be introduced as minor
> modes (in which case their name should end in "-mode").

Clearly that's not a relevant argument against the
convention, since `*-mode' minor-mode variables are also
necessarily Boolean.  On the contrary: `*-flag' vs `*-mode'
makes clear that the former is not associated with a minor mode.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-21  6:26                                                                     ` Eli Zaretskii
                                                                                         ` (2 preceding siblings ...)
  2017-04-21 13:29                                                                       ` scroll-down with pixel transition Stefan Monnier
@ 2017-04-22  2:31                                                                       ` Richard Stallman
  2017-04-22  7:54                                                                         ` Eli Zaretskii
  3 siblings, 1 reply; 63+ messages in thread
From: Richard Stallman @ 2017-04-22  2:31 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: yuri.v.khan, tkk, emacs-devel, cpitclaudel, kaushal.modi

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > > Our convention is to end user option names in '-flag', when they are
  > > for users to set.  Let's document that, if it isn't already.

  > It is not currently documented in code conventions.

Would you like to add it?

-- 
Dr Richard Stallman
President, Free Software Foundation (gnu.org, fsf.org)
Internet Hall-of-Famer (internethalloffame.org)
Skype: No way! See stallman.org/skype.html.




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-22  2:31                                                                       ` Richard Stallman
@ 2017-04-22  7:54                                                                         ` Eli Zaretskii
  2017-04-23  0:03                                                                           ` Richard Stallman
  0 siblings, 1 reply; 63+ messages in thread
From: Eli Zaretskii @ 2017-04-22  7:54 UTC (permalink / raw)
  To: rms, Stefan Monnier
  Cc: yuri.v.khan, tkk, emacs-devel, cpitclaudel, kaushal.modi

> From: Richard Stallman <rms@gnu.org>
> CC: kaushal.modi@gmail.com, tkk@misasa.okayama-u.ac.jp,
> 	yuri.v.khan@gmail.com, cpitclaudel@gmail.com,
> 	emacs-devel@gnu.org
> Date: Fri, 21 Apr 2017 22:31:16 -0400
> 
>   > > Our convention is to end user option names in '-flag', when they are
>   > > for users to set.  Let's document that, if it isn't already.
> 
>   > It is not currently documented in code conventions.
> 
> Would you like to add it?

I don't necessarily mind, but others evidently do, which is why this
was actually removed from the code conventions in Emacs 23 by Stefan.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-22  7:54                                                                         ` Eli Zaretskii
@ 2017-04-23  0:03                                                                           ` Richard Stallman
  2017-04-23 12:32                                                                             ` Stefan Monnier
  0 siblings, 1 reply; 63+ messages in thread
From: Richard Stallman @ 2017-04-23  0:03 UTC (permalink / raw)
  To: Eli Zaretskii
  Cc: cpitclaudel, emacs-devel, tkk, monnier, kaushal.modi, yuri.v.khan

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > >   > > Our convention is to end user option names in '-flag', when they are
  > >   > > for users to set.  Let's document that, if it isn't already.

Stefan, why did you remove that convention from the Emacs Lisp Manual?

-- 
Dr Richard Stallman
President, Free Software Foundation (gnu.org, fsf.org)
Internet Hall-of-Famer (internethalloffame.org)
Skype: No way! See stallman.org/skype.html.




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-23  0:03                                                                           ` Richard Stallman
@ 2017-04-23 12:32                                                                             ` Stefan Monnier
  2017-04-25 19:40                                                                               ` Richard Stallman
  0 siblings, 1 reply; 63+ messages in thread
From: Stefan Monnier @ 2017-04-23 12:32 UTC (permalink / raw)
  To: emacs-devel

> Stefan, why did you remove that convention from the Emacs Lisp Manual?

As already explained, because such hungarian-style notation doesn't let
you change the variable's type without renaming it.  For -face
and -function variables it's usually not a problem, but in my
experience, it's common for boolean config vars to want to evolve
seamlessly to a new type by adding new meanings to non-nil non-t values.

Furthermore, in my experience using the FOO instead of FOO-flag name
works just as well (`toto-use-zipa' is just as clear as
`toto-use-zipa-flag`, and reads even better in the code).


        Stefan




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-23 12:32                                                                             ` Stefan Monnier
@ 2017-04-25 19:40                                                                               ` Richard Stallman
  2017-04-25 20:06                                                                                 ` Dmitry Gutov
  0 siblings, 1 reply; 63+ messages in thread
From: Richard Stallman @ 2017-04-25 19:40 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > Furthermore, in my experience using the FOO instead of FOO-flag name
  > works just as well (`toto-use-zipa' is just as clear as
  > `toto-use-zipa-flag`, and reads even better in the code).

One purpose that '-flag' serves is to show that it's a variable
that enables or disables a feature.

  > As already explained, because such hungarian-style notation doesn't let
  > you change the variable's type without renaming it.

Perhaps we shouldn't do that.  That sort of thing was a good idea
back when it was important to economize on symbols.  Nowadays,
why not make a second variable to specify the further information?

-- 
Dr Richard Stallman
President, Free Software Foundation (gnu.org, fsf.org)
Internet Hall-of-Famer (internethalloffame.org)
Skype: No way! See stallman.org/skype.html.




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-25 19:40                                                                               ` Richard Stallman
@ 2017-04-25 20:06                                                                                 ` Dmitry Gutov
  2017-04-25 20:38                                                                                   ` Stefan Monnier
  2017-04-26 17:15                                                                                   ` Richard Stallman
  0 siblings, 2 replies; 63+ messages in thread
From: Dmitry Gutov @ 2017-04-25 20:06 UTC (permalink / raw)
  To: rms, Stefan Monnier; +Cc: emacs-devel

On 25.04.2017 22:40, Richard Stallman wrote:

>    > As already explained, because such hungarian-style notation doesn't let
>    > you change the variable's type without renaming it.
> 
> Perhaps we shouldn't do that.  That sort of thing was a good idea
> back when it was important to economize on symbols.  Nowadays,
> why not make a second variable to specify the further information?

It often simplifies code. You cl-case (or pcase) on one variable, 
instead of several.



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-25 20:06                                                                                 ` Dmitry Gutov
@ 2017-04-25 20:38                                                                                   ` Stefan Monnier
  2017-04-26 17:16                                                                                     ` Richard Stallman
  2017-04-26 17:15                                                                                   ` Richard Stallman
  1 sibling, 1 reply; 63+ messages in thread
From: Stefan Monnier @ 2017-04-25 20:38 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: rms, emacs-devel

>> Perhaps we shouldn't do that.  That sort of thing was a good idea
>> back when it was important to economize on symbols.  Nowadays,
>> why not make a second variable to specify the further information?
> It often simplifies code.  You cl-case (or pcase) on one variable, instead
> of several.

And it also avoids the problem of deciding what to do when the two vars
have conflicting values.


        Stefan



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-25 20:06                                                                                 ` Dmitry Gutov
  2017-04-25 20:38                                                                                   ` Stefan Monnier
@ 2017-04-26 17:15                                                                                   ` Richard Stallman
  1 sibling, 0 replies; 63+ messages in thread
From: Richard Stallman @ 2017-04-26 17:15 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: monnier, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > > Perhaps we shouldn't do that.  That sort of thing was a good idea
  > > back when it was important to economize on symbols.  Nowadays,
  > > why not make a second variable to specify the further information?

  > It often simplifies code. You cl-case (or pcase) on one variable, 
  > instead of several.

For a user interface, the cleanness of the interface is more important
than that little detail.

-- 
Dr Richard Stallman
President, Free Software Foundation (gnu.org, fsf.org)
Internet Hall-of-Famer (internethalloffame.org)
Skype: No way! See stallman.org/skype.html.




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-25 20:38                                                                                   ` Stefan Monnier
@ 2017-04-26 17:16                                                                                     ` Richard Stallman
  0 siblings, 0 replies; 63+ messages in thread
From: Richard Stallman @ 2017-04-26 17:16 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel, dgutov

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > And it also avoids the problem of deciding what to do when the two vars
  > have conflicting values.

If we are not sloppy about the definitions, there are no such conflcts.

Assuming there is already a -flag variable that controls whether
the feature is active at all, then other variables can be defined
to specify details of its behavior.  Then there is no conflict
between their values and the -flag variable.

-- 
Dr Richard Stallman
President, Free Software Foundation (gnu.org, fsf.org)
Internet Hall-of-Famer (internethalloffame.org)
Skype: No way! See stallman.org/skype.html.




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-21  8:52                                                                       ` Tak Kunihiro
@ 2017-04-30 12:13                                                                         ` Tak Kunihiro
  2017-05-13 17:27                                                                           ` Eli Zaretskii
  0 siblings, 1 reply; 63+ messages in thread
From: Tak Kunihiro @ 2017-04-30 12:13 UTC (permalink / raw)
  To: eliz; +Cc: cpitclaudel, rms, yuri.v.khan, tkk, kaushal.modi, emacs-devel

[-- Attachment #1: Type: Text/Plain, Size: 516 bytes --]

I optimized the code including got rid of unnecessary lines.  I send
the revised copy and diff.

Variable name is remained to be `pixel-resolution-fine-flag'.  How
suffix `-flag' will go?  At the same time, is prefix `pixel-'
appropriate?

Two possible ways to test the minor-mode are shown below.

 (require 'pixel-scroll)
 (pixel-scroll-mode 1)
 (setq pixel-resolution-fine-flag t)

 (require 'pixel-scroll)
 (pixel-scroll-mode 1)
 (setq mouse-wheel-scroll-amount '(1 ((shift) . 5) ((control))))

Happy Scrolling!

[-- Attachment #2: pixel-scroll.el --]
[-- Type: Text/Plain, Size: 9888 bytes --]

;;; pixel-scroll.el --- Scroll a line smoothly

;; Package-Requires: ((emacs "24.5"))
;; Version: 1.0.0
;; Package-Version: 20170430.1149
;; Keywords: convenience, usability

;;; This file is part of GNU Emacs

;;; License

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program; see the file COPYING.  If not, write to
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
;; Floor, Boston, MA 02110-1301, USA.

;; Usage:
;;
;; To interactively toggle the mode:
;;
;;   M-x pixel-scroll-mode RET
;;
;; To make the mode permanent, put these in your init file:
;;
;;   (require 'pixel-scroll)
;;   (pixel-scroll-mode 1)

;;; Commentary:

;; This package offers a global minor mode which makes mouse-wheel
;; scroll a line smoothly.
;;
;; Scrolling a line up by `set-window-vscroll' and that by `scroll-up'
;; give similar display as shown below.
;;
;;  A: (scroll-up 1)
;;  B: (set-window-vscroll nil (frame-char-height) t)
;;
;; Also scrolling a pixel up by `set-window-vscroll' and that by
;; `scroll-up' give similar display, when vscroll is the last pixel of
;; the line, as shown below.
;;
;;  A: (scroll-up 1)
;;  B: (set-window-vscroll nil (1- (frame-char-height) t)) (scroll-up 1)
;;
;; When point reaches to the top of a window on scroll by
;; `set-window-vscroll', vscroll is set to zero.  To scroll a line
;; smoothly and continuously, this package scrolls a line by following
;; sequences.
;;
;;  (vertical-motion 1)
;;  (dolist (vs (number-sequence 1 (1- (frame-char-height))))
;;    (set-window-vscroll nil vs t) (sit-for 0))
;;  (scroll-up 1)

;;; Todo:
;;
;; Allowing pixel-level scrolling in Emacs requires a thorough review
;; of the related functionalities, to make sure none of them zeroes
;; out vscroll where users won't want that.

;;; Code:

(require 'mwheel)

(defvar pixel-wait 0
  "Idle time on each step of pixel scroll specified in second.
More wait will result in slow and gentle scroll.")

(defvar pixel-resolution-fine-flag nil
  "Set scrolling resolution to a pixel instead of a line.
After a pixel scroll, typing C-n or C-p scrolls the window to
make it fully visible, and undoes the effect of the pixel-level
scroll.")

(define-minor-mode pixel-scroll-mode
  "A minor mode to scroll text pixel-by-pixel.  With a prefix argument ARG,
enable Pixel Scroll mode if ARG is positive, and disable it
otherwise.  If called from Lisp, enable Pixel Scroll mode if ARG
is omitted or nil."
  :init-value nil
  :group 'scrolling
  :global t

  (if pixel-scroll-mode
      (setq mwheel-scroll-up-function 'pixel-scroll-up
            mwheel-scroll-down-function 'pixel-scroll-down)
    (setq mwheel-scroll-up-function 'scroll-up
          mwheel-scroll-down-function 'scroll-down)))

(defun pixel-scroll-up (&optional arg)
  "Scroll text of selected window up ARG lines.  This is
alternative of `scroll-up'.  Scope moves downward."
  (interactive)
  (or arg (setq arg 1))
  (dotimes (ii arg) ; move scope downward
    (if (pixel-eob-at-top-p) ; when end-of-the-buffer is close
        (scroll-up 1) ; relay on robust method
      (when (pixel-point-at-top-p) ; prevent too late
        (vertical-motion 1)) ; move point downward
      (pixel-scroll-pixel-up (if pixel-resolution-fine-flag
                                 1
                               (pixel-line-height)))))) ; move scope downward

(defun pixel-scroll-down (&optional arg)
  "Scroll text of selected window down ARG lines.  This is
alternative of `scroll-down'.  Scope moves upward."
  (interactive)
  (or arg (setq arg 1))
  (dotimes (ii arg)
    (if (or (pixel-bob-at-top-p) ; when beginning-of-the-buffer is seen
            (pixel-eob-at-top-p)) ; for file with a long line
        (scroll-down 1) ; relay on robust method
      (while (pixel-point-at-bottom-p) ; prevent too late (multi tries)
        (vertical-motion -1))
      (pixel-scroll-pixel-down (if pixel-resolution-fine-flag
                                   1
                                 (pixel-line-height -1))))))

(defun pixel-bob-at-top-p ()
  "Return if beginning of the buffer is located at the top of a
window."
  (equal (window-start) (point-min)))

(defun pixel-eob-at-top-p ()
  "Return if end of the buffer is located at the top of a
window."
  (<= (count-lines (window-start) (window-end)) 2)) ; count-screen-lines

(defun pixel-posn-y-at-point ()
  "Return y coordinates of point in pixels of current window."
  (let ((hscroll0 (window-hscroll))
        (y (cdr (posn-x-y (posn-at-point)))))
    ;; when point is out of scope by hscroll
    (unless y
      (save-excursion
        (set-window-hscroll nil (current-column))
        (setq y (cdr (posn-x-y (posn-at-point))))
        (set-window-hscroll nil hscroll0)))
    y))

(defun pixel-point-at-top-p ()
  "Return if point is located at top of a window."
  (let* ((y (pixel-posn-y-at-point))
         (top-margin y))
    (< top-margin (pixel-line-height))))

(defun pixel-point-at-bottom-p ()
  "Return if point is located at bottom of a window."
  (let* ((y (pixel-posn-y-at-point))
         (edges (window-inside-pixel-edges))
         (height (- (nth 3 edges) (nth 1 edges))) ; (- bottom top)
         (bottom-margin (- height (+ y (line-pixel-height))))) ; bottom margin
    (< bottom-margin (pixel-line-height -1)))) ; coming unseen line

(defun pixel-scroll-pixel-up (amt)
  "Scroll text of selected windows up AMT pixels.  Scope moves
downward."
  (while (>= (+ (window-vscroll nil t) amt)
             (pixel-line-height))
    (setq amt (- amt (pixel--whistlestop-line-up)))) ; major scroll
  (pixel--whistlestop-pixel-up amt)) ; minor scroll

(defun pixel-scroll-pixel-down (amt)
  "Scroll text of selected windows down AMT pixels.  Scope moves
upward."
  (while (> amt 0)
    (let ((vs (window-vscroll nil t)))
      (if (equal vs 0)
          (pixel-scroll-down-and-set-window-vscroll
           (1- (pixel-line-height -1)))
        (set-window-vscroll nil (1- vs) t))
      (setq amt (1- amt))
      (sit-for pixel-wait))))

(defun pixel--whistlestop-line-up ()
  "Scroll text upward a line with each pixel whistlestopped.
When `vscroll' is non-zero, complete scrolling a line.  When
`vscroll' is larger than height of multiple lines, for example
88, this flushes multiple lines.  At the end, `vscroll' will be
zero.  This assumes that the lines are with the same height.
Scope moves downward.  This function returns number of pixels
that was scrolled."
  (let* ((src (window-vscroll nil t))  ; EXAMPLE (initial)      @0   @8  @88
         (height (pixel-line-height))  ;                        25   25   23
         (line (1+ (/ src height)))    ; catch up + one line    Δ1   Δ1   Δ4
         (dst (* line height))         ; goal                  @25  @25  @92
         (delta (- dst src)))          ; pixels to be scrolled  25   17    4
    (pixel--whistlestop-pixel-up (1- delta)) ; until one less  @24  @24  @91
    (scroll-up line) (sit-for pixel-wait) ; scroll 1 pixel      @0   @0   @0
    delta))

(defun pixel--whistlestop-pixel-up (n)
  "Scroll text upward by N pixels with each pixel whistlestopped.
Scope moves downward."
  (when (> n 0)
    (let ((vs0 (window-vscroll nil t)))
      (dolist (vs (number-sequence (1+ vs0) (+ vs0 n)))
        (set-window-vscroll nil vs t) (sit-for pixel-wait)))))

(defun pixel-line-height (&optional pos)
  "Return height in pixels of text line of POS in the selected
window.  When POS is nil or negative, height of the first line or
the coming unseen line above the first line, respectively, is provided."
  (or pos (setq pos (window-start)))
  (when (< pos 0)
    (setq pos (pixel-point-at-unseen-line)))
  (save-excursion
    (goto-char pos)
    (line-pixel-height))) ; frame-char-height

(defun pixel-point-at-unseen-line ()
  "Return the character position of the first character on the
unseen line just above the scope of current window.  This code is
presented at
https://lists.gnu.org/archive/html/emacs-devel/2017-04/msg00475.html."
  (let* ((pos0 (window-start))
         (vscroll0 (window-vscroll nil t))
         (pos
          (save-excursion
            (goto-char pos0)
            (if (bobp)
                (point-min)
              ;; When there's an overlay string at window-start,
              ;; (beginning-of-visual-line 0) stays put.
              (let ((ppos (point))
                    (tem (beginning-of-visual-line 0)))
                (if (eq tem ppos)
                    (vertical-motion -1))
                (point))))))
    ;; restore initial position
    (set-window-start nil pos0 t)
    (set-window-vscroll nil vscroll0 t)
    pos))

(defun pixel-scroll-down-and-set-window-vscroll (vscroll)
  "Scroll down a line and set VSCROLL in pixels.  This code is
presented at
https://lists.gnu.org/archive/html/emacs-devel/2017-04/msg00366.html.
It is important to call `set-window-start' to force the display
engine use that particular position as the window-start point.
Otherwise, redisplay will reset the window's vscroll."
  (set-window-start nil (pixel-point-at-unseen-line) t)
  (set-window-vscroll nil vscroll t))

(provide 'pixel-scroll)
;;; pixel-scroll.el ends here

[-- Attachment #3: pixel-scroll.20170421.el.patch --]
[-- Type: Text/X-Patch, Size: 6663 bytes --]

--- pixel-scroll.20170421.el	2017-04-30 18:59:29.781367800 +0900
+++ pixel-scroll.el	2017-04-30 11:49:48.368866100 +0900
@@ -2,7 +2,7 @@
 
 ;; Package-Requires: ((emacs "24.5"))
 ;; Version: 1.0.0
-;; Package-Version: 20170430.1859
+;; Package-Version: 20170430.1149
 ;; Keywords: convenience, usability
 
 ;;; This file is part of GNU Emacs
@@ -80,7 +80,7 @@
 (defvar pixel-resolution-fine-flag nil
   "Set scrolling resolution to a pixel instead of a line.
 After a pixel scroll, typing C-n or C-p scrolls the window to
-make it fully visible, and undos the effect of the pixel-level
+make it fully visible, and undoes the effect of the pixel-level
 scroll.")
 
 (define-minor-mode pixel-scroll-mode
@@ -104,11 +104,9 @@
   (interactive)
   (or arg (setq arg 1))
   (dotimes (ii arg) ; move scope downward
-    (if (<= (count-lines (window-start) (window-end)) 2)
-        (scroll-up 1) ; when end-of-buffer is close, relay on robust guy
-      (when (or (pixel-point-at-top-p) ; prevent too late
-                (and scroll-preserve-screen-position
-                     (not (pixel-point-at-bottom-p)))) ; prevent too fast
+    (if (pixel-eob-at-top-p) ; when end-of-the-buffer is close
+        (scroll-up 1) ; relay on robust method
+      (when (pixel-point-at-top-p) ; prevent too late
         (vertical-motion 1)) ; move point downward
       (pixel-scroll-pixel-up (if pixel-resolution-fine-flag
                                  1
@@ -120,35 +118,50 @@
   (interactive)
   (or arg (setq arg 1))
   (dotimes (ii arg)
-    (if (equal (window-start) (point-min))
-        (scroll-down 1) ; when beginning-of-buffer is seen, relay on robust guy
-      (while (or (pixel-point-at-bottom-p) ; prevent too late (try several lines)
-                 (and scroll-preserve-screen-position
-                      (not (pixel-point-at-top-p)))) ; prevent too fast
-        (vertical-motion -1)))
-    (pixel-scroll-pixel-down (if pixel-resolution-fine-flag
-                                 1
-                               (pixel-line-height -1)))))
+    (if (or (pixel-bob-at-top-p) ; when beginning-of-the-buffer is seen
+            (pixel-eob-at-top-p)) ; for file with a long line
+        (scroll-down 1) ; relay on robust method
+      (while (pixel-point-at-bottom-p) ; prevent too late (multi tries)
+        (vertical-motion -1))
+      (pixel-scroll-pixel-down (if pixel-resolution-fine-flag
+                                   1
+                                 (pixel-line-height -1))))))
+
+(defun pixel-bob-at-top-p ()
+  "Return if beginning of the buffer is located at the top of a
+window."
+  (equal (window-start) (point-min)))
+
+(defun pixel-eob-at-top-p ()
+  "Return if end of the buffer is located at the top of a
+window."
+  (<= (count-lines (window-start) (window-end)) 2)) ; count-screen-lines
+
+(defun pixel-posn-y-at-point ()
+  "Return y coordinates of point in pixels of current window."
+  (let ((hscroll0 (window-hscroll))
+        (y (cdr (posn-x-y (posn-at-point)))))
+    ;; when point is out of scope by hscroll
+    (unless y
+      (save-excursion
+        (set-window-hscroll nil (current-column))
+        (setq y (cdr (posn-x-y (posn-at-point))))
+        (set-window-hscroll nil hscroll0)))
+    y))
 
 (defun pixel-point-at-top-p ()
-  "Return if point is at top of a window."
-  (let ((y (cdr (posn-x-y (posn-at-point)))))
-    (if y
-        (< y ; top margin
-           (pixel-line-height))
-      ;; when point is out of scope by hscroll
-      (< (count-lines (window-start) (point)) 1))))
+  "Return if point is located at top of a window."
+  (let* ((y (pixel-posn-y-at-point))
+         (top-margin y))
+    (< top-margin (pixel-line-height))))
 
 (defun pixel-point-at-bottom-p ()
-  "Return if point is at bottom of a window."
-  (let* ((y (cdr (posn-x-y (posn-at-point))))
+  "Return if point is located at bottom of a window."
+  (let* ((y (pixel-posn-y-at-point))
          (edges (window-inside-pixel-edges))
-         (height (- (nth 3 edges) (nth 1 edges)))) ; (- bottom top)
-    (if y
-        (< (- height (+ y (line-pixel-height))) ; bottom margin
-           (pixel-line-height -1)) ; coming line
-      ;; when point is out of scope by hscroll
-      (< (count-lines (point) (window-end)) 4))))
+         (height (- (nth 3 edges) (nth 1 edges))) ; (- bottom top)
+         (bottom-margin (- height (+ y (line-pixel-height))))) ; bottom margin
+    (< bottom-margin (pixel-line-height -1)))) ; coming unseen line
 
 (defun pixel-scroll-pixel-up (amt)
   "Scroll text of selected windows up AMT pixels.  Scope moves
@@ -198,24 +211,24 @@
 (defun pixel-line-height (&optional pos)
   "Return height in pixels of text line of POS in the selected
 window.  When POS is nil or negative, height of the first line or
-the coming line above the first line, respectively, is provided."
+the coming unseen line above the first line, respectively, is provided."
   (or pos (setq pos (window-start)))
   (when (< pos 0)
-    (setq pos (pixel-point-at-coming-line)))
+    (setq pos (pixel-point-at-unseen-line)))
   (save-excursion
     (goto-char pos)
     (line-pixel-height))) ; frame-char-height
 
-(defun pixel-point-at-coming-line ()
+(defun pixel-point-at-unseen-line ()
   "Return the character position of the first character on the
-coming line just above the scope of current window.  This code is
+unseen line just above the scope of current window.  This code is
 presented at
 https://lists.gnu.org/archive/html/emacs-devel/2017-04/msg00475.html."
-  (let* ((win0 (window-start))
+  (let* ((pos0 (window-start))
          (vscroll0 (window-vscroll nil t))
          (pos
           (save-excursion
-            (goto-char win0)
+            (goto-char pos0)
             (if (bobp)
                 (point-min)
               ;; When there's an overlay string at window-start,
@@ -225,8 +238,9 @@
                 (if (eq tem ppos)
                     (vertical-motion -1))
                 (point))))))
-    (set-window-start nil win0 t) ; restore the window
-    (set-window-vscroll nil vscroll0 t) ; restore the window
+    ;; restore initial position
+    (set-window-start nil pos0 t)
+    (set-window-vscroll nil vscroll0 t)
     pos))
 
 (defun pixel-scroll-down-and-set-window-vscroll (vscroll)
@@ -236,7 +250,7 @@
 It is important to call `set-window-start' to force the display
 engine use that particular position as the window-start point.
 Otherwise, redisplay will reset the window's vscroll."
-  (set-window-start nil (pixel-point-at-coming-line) t)
+  (set-window-start nil (pixel-point-at-unseen-line) t)
   (set-window-vscroll nil vscroll t))
 
 (provide 'pixel-scroll)

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: scroll-down with pixel transition
  2017-04-30 12:13                                                                         ` Tak Kunihiro
@ 2017-05-13 17:27                                                                           ` Eli Zaretskii
  0 siblings, 0 replies; 63+ messages in thread
From: Eli Zaretskii @ 2017-05-13 17:27 UTC (permalink / raw)
  To: Tak Kunihiro; +Cc: cpitclaudel, yuri.v.khan, emacs-devel, rms, kaushal.modi

> Date: Sun, 30 Apr 2017 21:13:46 +0900 (JST)
> Cc: rms@gnu.org, kaushal.modi@gmail.com, yuri.v.khan@gmail.com,
>  cpitclaudel@gmail.com, emacs-devel@gnu.org, tkk@misasa.okayama-u.ac.jp
> From: Tak Kunihiro <tkk@misasa.okayama-u.ac.jp>
> 
> I optimized the code including got rid of unnecessary lines.  I send
> the revised copy and diff.

Thanks, installed.

In the future, please make sure the first line of each doc string is a
complete sentence.



^ permalink raw reply	[flat|nested] 63+ messages in thread

end of thread, other threads:[~2017-05-13 17:27 UTC | newest]

Thread overview: 63+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-04-09 23:49 scroll-down with pixel transition Tak Kunihiro
2017-04-10  5:58 ` Eli Zaretskii
2017-04-10  7:06   ` Tak Kunihiro
2017-04-10  7:42     ` Eli Zaretskii
2017-04-10 22:24       ` Tak Kunihiro
2017-04-11  7:44         ` Eli Zaretskii
2017-04-12 12:13           ` Tak Kunihiro
2017-04-12 12:43             ` Eli Zaretskii
2017-04-13  7:02               ` Tak Kunihiro
2017-04-13  7:21                 ` Eli Zaretskii
2017-04-13  8:12                   ` Tak Kunihiro
2017-04-13  8:20                     ` Eli Zaretskii
2017-04-13  8:40                       ` Tak Kunihiro
2017-04-13  9:04                         ` Eli Zaretskii
2017-04-13  9:22                           ` Tak Kunihiro
2017-04-13 10:24                             ` Eli Zaretskii
2017-04-14  2:40                               ` Tak Kunihiro
2017-04-14  7:37                                 ` Eli Zaretskii
2017-04-14 22:32                                   ` Tak Kunihiro
2017-04-15 10:13                                     ` Eli Zaretskii
2017-04-16  8:35                                       ` Tak Kunihiro
2017-04-16 10:26                                         ` Eli Zaretskii
2017-04-16 12:17                                           ` Tak Kunihiro
2017-04-16 16:51                                             ` Eli Zaretskii
2017-04-16 18:00                                               ` Eli Zaretskii
2017-04-16 23:06                                                 ` Tak Kunihiro
2017-04-17  8:54                                                   ` Eli Zaretskii
2017-04-17 23:15                                                     ` Tak Kunihiro
2017-04-19 12:21                                                       ` Tak Kunihiro
2017-04-19 12:38                                                         ` Kaushal Modi
2017-04-19 12:42                                                           ` Kaushal Modi
2017-04-19 14:44                                                           ` Eli Zaretskii
2017-04-19 15:02                                                             ` Stefan Monnier
2017-04-19 15:07                                                             ` Kaushal Modi
2017-04-19 15:37                                                               ` Eli Zaretskii
2017-04-19 15:49                                                                 ` Kaushal Modi
2017-04-19 16:10                                                                   ` Eli Zaretskii
     [not found]                                                                   ` <<83zifcbcoc.fsf@gnu.org>
2017-04-19 17:33                                                                     ` Drew Adams
2017-04-19 18:21                                                                       ` Lars Brinkhoff
2017-04-21  2:05                                                                   ` Richard Stallman
2017-04-21  6:26                                                                     ` Eli Zaretskii
2017-04-21  8:52                                                                       ` Tak Kunihiro
2017-04-30 12:13                                                                         ` Tak Kunihiro
2017-05-13 17:27                                                                           ` Eli Zaretskii
2017-04-21 13:21                                                                       ` Perry E. Metzger
2017-04-21 13:36                                                                         ` Eli Zaretskii
2017-04-21 14:24                                                                           ` Option name conventions (was Re: scroll-down with pixel transition) Perry E. Metzger
2017-04-21 13:29                                                                       ` scroll-down with pixel transition Stefan Monnier
2017-04-21 15:47                                                                         ` Drew Adams
2017-04-22  2:31                                                                       ` Richard Stallman
2017-04-22  7:54                                                                         ` Eli Zaretskii
2017-04-23  0:03                                                                           ` Richard Stallman
2017-04-23 12:32                                                                             ` Stefan Monnier
2017-04-25 19:40                                                                               ` Richard Stallman
2017-04-25 20:06                                                                                 ` Dmitry Gutov
2017-04-25 20:38                                                                                   ` Stefan Monnier
2017-04-26 17:16                                                                                     ` Richard Stallman
2017-04-26 17:15                                                                                   ` Richard Stallman
2017-04-15 14:31                                     ` Clément Pit-Claudel
2017-04-15 14:57                                       ` Eli Zaretskii
2017-04-15 15:33                                         ` Clément Pit-Claudel
2017-04-13  8:35                   ` Yuri Khan
2017-04-13  8:57                     ` Eli Zaretskii

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).