aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorJuri Linkov2019-11-30 23:16:03 +0200
committerJuri Linkov2019-11-30 23:16:03 +0200
commitd64ea182fb6e2bf3af8ac8a289e8029ded36407e (patch)
tree0e7835bc8f2f2b62a64a1fed3f72871abf3ad611 /lisp
parent9ac78ef56c184b757f9866edc3092eb62e259c90 (diff)
downloademacs-d64ea182fb6e2bf3af8ac8a289e8029ded36407e.tar.gz
emacs-d64ea182fb6e2bf3af8ac8a289e8029ded36407e.zip
Use run-with-idle-timer instead of debounce for responsive image scaling.
* lisp/emacs-lisp/timer.el (debounce, debounce-reduce): Revert macro addition. https://lists.gnu.org/archive/html/emacs-devel/2019-11/msg01133.html * lisp/image.el (image-increase-size, image-decrease-size): Use run-with-idle-timer. (image--change-size): Rename back from image--change-size-function. * lisp/image-mode.el (image-mode--setup-mode): Remove hooks window-size-change-functions and window-selection-change-functions (bug#32672) (image-fit-to-window): Rename from image--window-change-function. (image--window-state-change): Rename from image--window-change. Use run-with-idle-timer.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/emacs-lisp/timer.el44
-rw-r--r--lisp/image-mode.el49
-rw-r--r--lisp/image.el46
3 files changed, 54 insertions, 85 deletions
diff --git a/lisp/emacs-lisp/timer.el b/lisp/emacs-lisp/timer.el
index 5fdf9a426a7..561cc70078f 100644
--- a/lisp/emacs-lisp/timer.el
+++ b/lisp/emacs-lisp/timer.el
@@ -488,50 +488,6 @@ The argument should be a value previously returned by `with-timeout-suspend'."
488If the user does not answer after SECONDS seconds, return DEFAULT-VALUE." 488If the user does not answer after SECONDS seconds, return DEFAULT-VALUE."
489 (with-timeout (seconds default-value) 489 (with-timeout (seconds default-value)
490 (y-or-n-p prompt))) 490 (y-or-n-p prompt)))
491
492(defmacro debounce (secs function)
493 "Call FUNCTION after SECS seconds have elapsed.
494Postpone FUNCTION call until after SECS seconds have elapsed since the
495last time it was invoked. On consecutive calls within the interval of
496SECS seconds, cancel all previous calls that occur rapidly in quick succession,
497and execute only the last call. This improves performance of event processing."
498 (declare (indent 1) (debug t))
499 (let ((timer-sym (make-symbol "timer")))
500 `(let (,timer-sym)
501 (lambda (&rest args)
502 (when (timerp ,timer-sym)
503 (cancel-timer ,timer-sym))
504 (setq ,timer-sym
505 (run-with-timer
506 ,secs nil (lambda ()
507 (apply ,function args))))))))
508
509(defmacro debounce-reduce (secs initial-state state-function function)
510 "Call FUNCTION after SECS seconds have elapsed.
511Postpone FUNCTION call until after SECS seconds have elapsed since the
512last time it was invoked. On consecutive calls within the interval of
513SECS seconds, cancel all previous calls that occur rapidly in quick succession,
514and execute only the last call. This improves performance of event processing.
515
516STATE-FUNCTION can be used to accumulate the state on consecutive calls
517starting with the value of INITIAL-STATE, and then execute the last call
518with the collected state value."
519 (declare (indent 1) (debug t))
520 (let ((timer-sym (make-symbol "timer"))
521 (state-sym (make-symbol "state")))
522 `(let (,timer-sym (,state-sym ,initial-state))
523 (lambda (&rest args)
524 (setq ,state-sym (apply ,state-function ,state-sym args))
525 (when (timerp ,timer-sym)
526 (cancel-timer ,timer-sym))
527 (setq ,timer-sym
528 (run-with-timer
529 ,secs nil (lambda ()
530 (apply ,function (if (listp ,state-sym)
531 ,state-sym
532 (list ,state-sym)))
533 (setq ,state-sym ,initial-state))))))))
534
535 491
536(defconst timer-duration-words 492(defconst timer-duration-words
537 (list (cons "microsec" 0.000001) 493 (list (cons "microsec" 0.000001)
diff --git a/lisp/image-mode.el b/lisp/image-mode.el
index 09d7828047e..b9ba376cafc 100644
--- a/lisp/image-mode.el
+++ b/lisp/image-mode.el
@@ -599,9 +599,7 @@ Key bindings:
599 599
600 (add-hook 'change-major-mode-hook #'image-toggle-display-text nil t) 600 (add-hook 'change-major-mode-hook #'image-toggle-display-text nil t)
601 (add-hook 'after-revert-hook #'image-after-revert-hook nil t) 601 (add-hook 'after-revert-hook #'image-after-revert-hook nil t)
602 (add-hook 'window-size-change-functions #'image--window-change nil t) 602 (add-hook 'window-state-change-functions #'image--window-state-change nil t)
603 (add-hook 'window-state-change-functions #'image--window-change nil t)
604 (add-hook 'window-selection-change-functions #'image--window-change nil t)
605 603
606 (run-mode-hooks 'image-mode-hook) 604 (run-mode-hooks 'image-mode-hook)
607 (let ((image (image-get-display-property)) 605 (let ((image (image-get-display-property))
@@ -860,26 +858,31 @@ Otherwise, display the image by calling `image-mode'."
860 (get-buffer-window-list (current-buffer) 'nomini 'visible)) 858 (get-buffer-window-list (current-buffer) 'nomini 'visible))
861 (image-toggle-display-image))) 859 (image-toggle-display-image)))
862 860
863(defvar image--window-change-function 861(defun image--window-state-change (window)
864 (debounce 1.0 862 ;; Wait for a bit of idle-time before actually performing the change,
865 (lambda (window) 863 ;; so as to batch together sequences of closely consecutive size changes.
866 (when (window-live-p window) 864 ;; `image-fit-to-window' just changes one value in a plist. The actual
867 (with-current-buffer (window-buffer) 865 ;; image resizing happens later during redisplay. So if those
868 (when (derived-mode-p 'image-mode) 866 ;; consecutive calls happen without any redisplay between them,
869 (let ((spec (image-get-display-property))) 867 ;; the costly operation of image resizing should happen only once.
870 (when (eq (car-safe spec) 'image) 868 (run-with-idle-timer 1 nil #'image-fit-to-window window))
871 (let* ((image-width (plist-get (cdr spec) :max-width)) 869
872 (image-height (plist-get (cdr spec) :max-height)) 870(defun image-fit-to-window (window)
873 (edges (window-inside-pixel-edges window)) 871 "Adjust size of image to display it exactly in WINDOW boundaries."
874 (window-width (- (nth 2 edges) (nth 0 edges))) 872 (when (window-live-p window)
875 (window-height (- (nth 3 edges) (nth 1 edges)))) 873 (with-current-buffer (window-buffer)
876 (when (and image-width image-height 874 (when (derived-mode-p 'image-mode)
877 (or (not (= image-width window-width)) 875 (let ((spec (image-get-display-property)))
878 (not (= image-height window-height)))) 876 (when (eq (car-safe spec) 'image)
879 (image-toggle-display-image))))))))))) 877 (let* ((image-width (plist-get (cdr spec) :max-width))
880 878 (image-height (plist-get (cdr spec) :max-height))
881(defun image--window-change (window) 879 (edges (window-inside-pixel-edges window))
882 (funcall image--window-change-function window)) 880 (window-width (- (nth 2 edges) (nth 0 edges)))
881 (window-height (- (nth 3 edges) (nth 1 edges))))
882 (when (and image-width image-height
883 (or (not (= image-width window-width))
884 (not (= image-height window-height))))
885 (image-toggle-display-image)))))))))
883 886
884 887
885;;; Animated images 888;;; Animated images
diff --git a/lisp/image.el b/lisp/image.el
index c4304782327..f4ed4e79fc0 100644
--- a/lisp/image.el
+++ b/lisp/image.el
@@ -1017,20 +1017,34 @@ has no effect."
1017If N is 3, then the image size will be increased by 30%. The 1017If N is 3, then the image size will be increased by 30%. The
1018default is 20%." 1018default is 20%."
1019 (interactive "P") 1019 (interactive "P")
1020 (funcall image--change-size-function 1020 ;; Wait for a bit of idle-time before actually performing the change,
1021 (if n 1021 ;; so as to batch together sequences of closely consecutive size changes.
1022 (1+ (/ (prefix-numeric-value n) 10.0)) 1022 ;; `image--change-size' just changes one value in a plist. The actual
1023 1.2))) 1023 ;; image resizing happens later during redisplay. So if those
1024 ;; consecutive calls happen without any redisplay between them,
1025 ;; the costly operation of image resizing should happen only once.
1026 (run-with-idle-timer 0.3 nil
1027 #'image--change-size
1028 (if n
1029 (1+ (/ (prefix-numeric-value n) 10.0))
1030 1.2)))
1024 1031
1025(defun image-decrease-size (&optional n) 1032(defun image-decrease-size (&optional n)
1026 "Decrease the image size by a factor of N. 1033 "Decrease the image size by a factor of N.
1027If N is 3, then the image size will be decreased by 30%. The 1034If N is 3, then the image size will be decreased by 30%. The
1028default is 20%." 1035default is 20%."
1029 (interactive "P") 1036 (interactive "P")
1030 (funcall image--change-size-function 1037 ;; Wait for a bit of idle-time before actually performing the change,
1031 (if n 1038 ;; so as to batch together sequences of closely consecutive size changes.
1032 (- 1 (/ (prefix-numeric-value n) 10.0)) 1039 ;; `image--change-size' just changes one value in a plist. The actual
1033 0.8))) 1040 ;; image resizing happens later during redisplay. So if those
1041 ;; consecutive calls happen without any redisplay between them,
1042 ;; the costly operation of image resizing should happen only once.
1043 (run-with-idle-timer 0.3 nil
1044 #'image--change-size
1045 (if n
1046 (- 1 (/ (prefix-numeric-value n) 10.0))
1047 0.8)))
1034 1048
1035(defun image-mouse-increase-size (&optional event) 1049(defun image-mouse-increase-size (&optional event)
1036 "Increase the image size using the mouse." 1050 "Increase the image size using the mouse."
@@ -1065,16 +1079,12 @@ default is 20%."
1065 (plist-put (cdr image) :type 'imagemagick)) 1079 (plist-put (cdr image) :type 'imagemagick))
1066 image)) 1080 image))
1067 1081
1068(defvar image--change-size-function 1082(defun image--change-size (factor)
1069 (debounce-reduce 0.3 1 1083 (let* ((image (image--get-imagemagick-and-warn))
1070 (lambda (state factor) 1084 (new-image (image--image-without-parameters image))
1071 (* state factor)) 1085 (scale (image--current-scaling image new-image)))
1072 (lambda (factor) 1086 (setcdr image (cdr new-image))
1073 (let* ((image (image--get-imagemagick-and-warn)) 1087 (plist-put (cdr image) :scale (* scale factor))))
1074 (new-image (image--image-without-parameters image))
1075 (scale (image--current-scaling image new-image)))
1076 (setcdr image (cdr new-image))
1077 (plist-put (cdr image) :scale (* scale factor))))))
1078 1088
1079(defun image--image-without-parameters (image) 1089(defun image--image-without-parameters (image)
1080 (cons (pop image) 1090 (cons (pop image)