Prevent artist-mode from creating runaway timers (Bug#6130).

* subr.el (posnp): Correct docstring of `posnp'.
(posn-col-row): Make it work with all mouse position objects.
* textmodes/artist.el (artist-mouse-draw-continously): Cancel
timers if an error occurs during continuous drawing.  (Bug#6130)

* commands.texi (Drag Events, Motion Events, Event Examples)
(Accessing Mouse): Describe actual range of values that mouse
position objects can have.
This commit is contained in:
Daniel Koning 2015-01-21 09:01:30 +01:00 committed by Martin Rudalics
parent 4c09e3aef9
commit 3ea1b31f46
5 changed files with 94 additions and 54 deletions

View file

@ -1,3 +1,9 @@
2015-01-21 Daniel Koning <dk@danielkoning.com> (tiny change)
* commands.texi (Drag Events, Motion Events, Event Examples)
(Accessing Mouse): Describe actual range of values that mouse
position objects can have.
2015-01-20 Eli Zaretskii <eliz@gnu.org> 2015-01-20 Eli Zaretskii <eliz@gnu.org>
* display.texi (Manipulating Buttons): Explain more about the * display.texi (Manipulating Buttons): Explain more about the

View file

@ -1485,8 +1485,10 @@ prefix @samp{drag-}. For example, dragging the mouse with button 2
held down generates a @code{drag-mouse-2} event. The second and third held down generates a @code{drag-mouse-2} event. The second and third
elements of the event give the starting and ending position of the elements of the event give the starting and ending position of the
drag, as mouse position lists (@pxref{Click Events}). You can access drag, as mouse position lists (@pxref{Click Events}). You can access
the second element of any mouse event in the same way, with no need to the second element of any mouse event in the same way. However, the
distinguish drag events from others. drag event may end outside the boundaries of the frame that was
initially selected. In that case, the third element's position list
contains that frame in place of a window.
The @samp{drag-} prefix follows the modifier key prefixes such as The @samp{drag-} prefix follows the modifier key prefixes such as
@samp{C-} and @samp{M-}. @samp{C-} and @samp{M-}.
@ -1631,7 +1633,10 @@ represented by lists that look like this:
@noindent @noindent
@var{position} is a mouse position list (@pxref{Click Events}), @var{position} is a mouse position list (@pxref{Click Events}),
specifying the current position of the mouse cursor. specifying the current position of the mouse cursor. As with the
end-position of a drag event, this position list may represent a
location outside the boundaries of the initially selected frame, in
which case the list contains that frame in place of a window.
The special form @code{track-mouse} enables generation of motion The special form @code{track-mouse} enables generation of motion
events within its body. Outside of @code{track-mouse} forms, Emacs events within its body. Outside of @code{track-mouse} forms, Emacs
@ -1846,6 +1851,14 @@ into another window. That produces a pair of events like these:
-453816)) -453816))
@end smallexample @end smallexample
The frame with input focus might not take up the entire screen, and
the user might move the mouse outside the scope of the frame. Inside
the @code{track-mouse} special form, that produces an event like this:
@smallexample
(mouse-movement (#<frame *ielm* 0x102849a30> nil (563 . 205) 532301936))
@end smallexample
To handle a SIGUSR1 signal, define an interactive function, and To handle a SIGUSR1 signal, define an interactive function, and
bind it to the @code{signal usr1} event sequence: bind it to the @code{signal usr1} event sequence:
@ -2010,7 +2023,9 @@ Events}); and @code{nil} otherwise.
various parts of it: various parts of it:
@defun posn-window position @defun posn-window position
Return the window that @var{position} is in. Return the window that @var{position} is in. If @var{position}
represents a location outside the frame where the event was initiated,
return that frame instead.
@end defun @end defun
@defun posn-area position @defun posn-area position

View file

@ -1,3 +1,10 @@
2015-01-21 Daniel Koning <dk@danielkoning.com> (tiny change)
* subr.el (posnp): Correct docstring of `posnp'.
(posn-col-row): Make it work with all mouse position objects.
* textmodes/artist.el (artist-mouse-draw-continously): Cancel
timers if an error occurs during continuous drawing. (Bug#6130)
2015-01-20 Eli Zaretskii <eliz@gnu.org> 2015-01-20 Eli Zaretskii <eliz@gnu.org>
* button.el (button-activate, push-button): Doc fix. (Bug#19628) * button.el (button-activate, push-button): Doc fix. (Bug#19628)

View file

@ -1062,7 +1062,12 @@ The return value is a positive integer."
;;;; Extracting fields of the positions in an event. ;;;; Extracting fields of the positions in an event.
(defun posnp (obj) (defun posnp (obj)
"Return non-nil if OBJ appears to be a valid `posn' object." "Return non-nil if OBJ appears to be a valid `posn' object specifying a window.
If OBJ is a valid `posn' object, but specifies a frame rather
than a window, return nil."
;; FIXME: Correct the behavior of this function so that all valid
;; `posn' objects are recognized, after updating other code that
;; depends on its present behavior.
(and (windowp (car-safe obj)) (and (windowp (car-safe obj))
(atom (car-safe (setq obj (cdr obj)))) ;AREA-OR-POS. (atom (car-safe (setq obj (cdr obj)))) ;AREA-OR-POS.
(integerp (car-safe (car-safe (setq obj (cdr obj))))) ;XOFFSET. (integerp (car-safe (car-safe (setq obj (cdr obj))))) ;XOFFSET.
@ -1122,24 +1127,28 @@ For a scroll-bar event, the result column is 0, and the row
corresponds to the vertical position of the click in the scroll bar. corresponds to the vertical position of the click in the scroll bar.
POSITION should be a list of the form returned by the `event-start' POSITION should be a list of the form returned by the `event-start'
and `event-end' functions." and `event-end' functions."
(let* ((pair (posn-x-y position)) (let* ((pair (posn-x-y position))
(window (posn-window position)) (frame-or-window (posn-window position))
(area (posn-area position))) (frame (if (framep frame-or-window)
frame-or-window
(window-frame frame-or-window)))
(window (when (windowp frame-or-window) frame-or-window))
(area (posn-area position)))
(cond (cond
((null window) ((null frame-or-window)
'(0 . 0)) '(0 . 0))
((eq area 'vertical-scroll-bar) ((eq area 'vertical-scroll-bar)
(cons 0 (scroll-bar-scale pair (1- (window-height window))))) (cons 0 (scroll-bar-scale pair (1- (window-height window)))))
((eq area 'horizontal-scroll-bar) ((eq area 'horizontal-scroll-bar)
(cons (scroll-bar-scale pair (window-width window)) 0)) (cons (scroll-bar-scale pair (window-width window)) 0))
(t (t
(let* ((frame (if (framep window) window (window-frame window))) ;; FIXME: This should take line-spacing properties on
;; FIXME: This should take line-spacing properties on ;; newlines into account.
;; newlines into account. (let* ((spacing (when (display-graphic-p frame)
(spacing (when (display-graphic-p frame) (or (with-current-buffer
(or (with-current-buffer (window-buffer window) (window-buffer (frame-selected-window frame))
line-spacing) line-spacing)
(frame-parameter frame 'line-spacing))))) (frame-parameter frame 'line-spacing)))))
(cond ((floatp spacing) (cond ((floatp spacing)
(setq spacing (truncate (* spacing (setq spacing (truncate (* spacing
(frame-char-height frame))))) (frame-char-height frame)))))

View file

@ -4963,52 +4963,55 @@ The event, EV, is the mouse event."
(artist-funcall init-fn x1 y1) (artist-funcall init-fn x1 y1)
(if (not artist-rubber-banding) (if (not artist-rubber-banding)
(artist-no-rb-set-point1 x1 y1)) (artist-no-rb-set-point1 x1 y1))
(track-mouse (unwind-protect
(while (or (mouse-movement-p ev) (track-mouse
(member 'down (event-modifiers ev))) (while (or (mouse-movement-p ev)
(setq ev-start-pos (artist-coord-win-to-buf (member 'down (event-modifiers ev)))
(posn-col-row (event-start ev)))) (setq ev-start-pos (artist-coord-win-to-buf
(setq x1 (car ev-start-pos)) (posn-col-row (event-start ev))))
(setq y1 (cdr ev-start-pos)) (setq x1 (car ev-start-pos))
(setq y1 (cdr ev-start-pos))
;; Cancel previous timer ;; Cancel previous timer
(if timer (if timer
(cancel-timer timer)) (cancel-timer timer))
(if (not (eq initial-win (posn-window (event-start ev)))) (if (not (eq initial-win (posn-window (event-start ev))))
;; If we moved outside the window, do nothing ;; If we moved outside the window, do nothing
nil nil
;; Still in same window: ;; Still in same window:
;; ;;
;; Check if user presses or releases shift key ;; Check if user presses or releases shift key
(if (artist-shift-has-changed shift-state ev) (if (artist-shift-has-changed shift-state ev)
;; First check that the draw-how is the same as we ;; First check that the draw-how is the same as we
;; already have. Otherwise, ignore the changed shift-state. ;; already have. Otherwise, ignore the changed shift-state.
(if (not (eq draw-how (if (not (eq draw-how
(artist-go-get-draw-how-from-symbol (artist-go-get-draw-how-from-symbol
(if (not shift-state) shifted unshifted)))) (if (not shift-state) shifted unshifted))))
(message "Cannot switch to shifted operation") (message "Cannot switch to shifted operation")
;; progn is "implicit" since this is the else-part ;; progn is "implicit" since this is the else-part
(setq shift-state (not shift-state)) (setq shift-state (not shift-state))
(setq op (if shift-state shifted unshifted)) (setq op (if shift-state shifted unshifted))
(setq draw-how (artist-go-get-draw-how-from-symbol op)) (setq draw-how (artist-go-get-draw-how-from-symbol op))
(setq draw-fn (artist-go-get-draw-fn-from-symbol op)))) (setq draw-fn (artist-go-get-draw-fn-from-symbol op))))
;; Draw the new shape ;; Draw the new shape
(setq shape (artist-funcall draw-fn x1 y1)) (setq shape (artist-funcall draw-fn x1 y1))
(artist-move-to-xy x1 y1) (artist-move-to-xy x1 y1)
;; Start the timer to call `draw-fn' repeatedly every ;; Start the timer to call `draw-fn' repeatedly every
;; `interval' second ;; `interval' second
(if (and interval draw-fn) (if (and interval draw-fn)
(setq timer (run-at-time interval interval draw-fn x1 y1)))) (setq timer (run-at-time interval interval draw-fn x1 y1))))
;; Read next event
(setq ev (read-event))))
;; Read next event
(setq ev (read-event))))
;; Cleanup: get rid of any active timer.
(if timer
(cancel-timer timer)))
;; Cancel any timers ;; Cancel any timers
(if timer (if timer
(cancel-timer timer)) (cancel-timer timer))