]> git.eshelyaron.com Git - emacs.git/commitdiff
Allow stopping animations automatically when the image disappears
authorLars Ingebrigtsen <larsi@gnus.org>
Fri, 12 Nov 2021 02:27:23 +0000 (03:27 +0100)
committerLars Ingebrigtsen <larsi@gnus.org>
Fri, 12 Nov 2021 02:31:53 +0000 (03:31 +0100)
* lisp/image.el (image-animate): Allow the animation to be stopped
automatically when the image is removed from the buffer.
(image-animate-timeout): Stop the animation if the image is
removed (and that has been requested).

* lisp/net/shr.el (shr-put-image): Stop animations if the image is
removed.

lisp/image.el
lisp/net/shr.el

index a149caa1a973ce8bfba414b783970bee28e6e213..edbf6c54df6d94e7af2b3fa86361cf561158f1b7 100644 (file)
@@ -836,15 +836,18 @@ in which case you might want to use `image-default-frame-delay'."
 
 (make-obsolete 'image-animated-p 'image-multi-frame-p "24.4")
 
-;; "Destructively"?
-(defun image-animate (image &optional index limit)
+(defun image-animate (image &optional index limit position)
   "Start animating IMAGE.
 Animation occurs by destructively altering the IMAGE spec list.
 
 With optional INDEX, begin animating from that animation frame.
 LIMIT specifies how long to animate the image.  If omitted or
 nil, play the animation until the end.  If t, loop forever.  If a
-number, play until that number of seconds has elapsed."
+number, play until that number of seconds has elapsed.
+
+If POSITION (which should be buffer position where the image is
+displayed), stop the animation if the image is no longer
+displayed."
   (let ((animation (image-multi-frame-p image))
        timer)
     (when animation
@@ -852,6 +855,9 @@ number, play until that number of seconds has elapsed."
          (cancel-timer timer))
       (plist-put (cdr image) :animate-buffer (current-buffer))
       (plist-put (cdr image) :animate-tardiness 0)
+      (when position
+        (plist-put (cdr image) :animate-position
+                   (set-marker (make-marker) position (current-buffer))))
       ;; Stash the data about the animation here so that we don't
       ;; trigger image recomputation unnecessarily later.
       (plist-put (cdr image) :animate-multi-frame-data animation)
@@ -925,40 +931,54 @@ for the animation speed.  A negative value means to animate in reverse."
   (plist-put (cdr image) :animate-tardiness
              (+ (* (plist-get (cdr image) :animate-tardiness) 0.9)
                 (float-time (time-since target-time))))
-  (when (and (buffer-live-p (plist-get (cdr image) :animate-buffer))
-             ;; Cumulatively delayed two seconds more than expected.
-             (or (< (plist-get (cdr image) :animate-tardiness) 2)
-                (progn
-                  (message "Stopping animation; animation possibly too big")
-                  nil)))
-    (image-show-frame image n t)
-    (let* ((speed (image-animate-get-speed image))
-          (time (current-time))
-          (time-to-load-image (time-since time))
-          (stated-delay-time
-            (/ (or (cdr (plist-get (cdr image) :animate-multi-frame-data))
-                  image-default-frame-delay)
-              (float (abs speed))))
-          ;; Subtract off the time we took to load the image from the
-          ;; stated delay time.
-          (delay (max (float-time (time-subtract stated-delay-time
-                                                 time-to-load-image))
-                      image-minimum-frame-delay))
-          done)
-      (setq n (if (< speed 0)
-                 (1- n)
-               (1+ n)))
-      (if limit
-         (cond ((>= n count) (setq n 0))
-               ((< n 0) (setq n (1- count))))
-       (and (or (>= n count) (< n 0)) (setq done t)))
-      (setq time-elapsed (+ delay time-elapsed))
-      (if (numberp limit)
-         (setq done (>= time-elapsed limit)))
-      (unless done
-       (run-with-timer delay nil #'image-animate-timeout
-                       image n count time-elapsed limit
-                        (+ (float-time) delay))))))
+  (let ((buffer (plist-get (cdr image) :animate-buffer))
+        (position (plist-get (cdr image) :animate-position)))
+    (when (and (buffer-live-p buffer)
+               ;; If we have a :animate-position setting, the caller
+               ;; has requested that the animation be stopped if the
+               ;; image is no longer displayed in the buffer.
+               (or (null position)
+                   (with-current-buffer buffer
+                     (let ((disp (get-text-property position 'display)))
+                       (and (consp disp)
+                            (eq (car disp) 'image)
+                            ;; We can't check `eq'-ness of the image
+                            ;; itself, since that may change.
+                            (eq position
+                                (plist-get (cdr disp) :animate-position))))))
+               ;; Cumulatively delayed two seconds more than expected.
+               (or (< (plist-get (cdr image) :animate-tardiness) 2)
+                  (progn
+                    (message "Stopping animation; animation possibly too big")
+                    nil)))
+      (image-show-frame image n t)
+      (let* ((speed (image-animate-get-speed image))
+            (time (current-time))
+            (time-to-load-image (time-since time))
+            (stated-delay-time
+              (/ (or (cdr (plist-get (cdr image) :animate-multi-frame-data))
+                    image-default-frame-delay)
+                (float (abs speed))))
+            ;; Subtract off the time we took to load the image from the
+            ;; stated delay time.
+            (delay (max (float-time (time-subtract stated-delay-time
+                                                   time-to-load-image))
+                        image-minimum-frame-delay))
+            done)
+        (setq n (if (< speed 0)
+                   (1- n)
+                 (1+ n)))
+        (if limit
+           (cond ((>= n count) (setq n 0))
+                 ((< n 0) (setq n (1- count))))
+         (and (or (>= n count) (< n 0)) (setq done t)))
+        (setq time-elapsed (+ delay time-elapsed))
+        (if (numberp limit)
+           (setq done (>= time-elapsed limit)))
+        (unless done
+         (run-with-timer delay nil #'image-animate-timeout
+                         image n count time-elapsed limit
+                          (+ (float-time) delay)))))))
 
 \f
 (defvar imagemagick-types-inhibit)
index 71c18ff99479390aa918efb22d64f6d2228c262b..19d324b16f25760f90ee2603e5e2baee1aa00d4f 100644 (file)
@@ -1174,13 +1174,14 @@ element is the data blob and the second element is the content-type."
          (when (and (> (current-column) 0)
                     (> (car (image-size image t)) 400))
            (insert "\n"))
-         (if (eq size 'original)
-             (insert-sliced-image image (or alt "*") nil 20 1)
-           (insert-image image (or alt "*")))
-         (put-text-property start (point) 'image-size size)
-         (when (and shr-image-animate
-                     (cdr (image-multi-frame-p image)))
-            (image-animate image nil 60)))
+          (let ((image-pos (point)))
+           (if (eq size 'original)
+               (insert-sliced-image image (or alt "*") nil 20 1)
+             (insert-image image (or alt "*")))
+           (put-text-property start (point) 'image-size size)
+           (when (and shr-image-animate
+                       (cdr (image-multi-frame-p image)))
+              (image-animate image nil 60 image-pos))))
        image)
     (insert (or alt ""))))