Subject: Re: bug#13560: 24.2.92; tabulated-list header buttons are broken

From: Glenn Morris <[email-masked]>
Date: Tue, 29 Jan 2013 20:27:13 -0500

Ok, I think the issue here is mouse-drag-line pushing the same event
onto unread-command-events twice in some cases.

The recent history is a bit convoluted:

2012-07-08 changes to fix bug#374, and simplify mouse-drag-line loop.

This caused bug#12006, fixed 2012-07-26. These changes reverted some of
the loop simplifications, for reasons I don't understand.

These changes in turn caused bug#12971 (no mouse-1 events in header),
fixed 2012-11-24. It seems the fix actually gave us two sets of mouse-1
events in headers though (this bug).

And then we have 2012-10-26 changes for bug#12731, introduced at some
point along the way.

What seems to work for me is going back to the 2012-07-26 changes, and
reverting some of reversion. Basically, just check for switch-frame and
select-window events and ignore them. Then I found I needed one more
tweak to preserve the bug#12731 fix.

The following change seems to not break any of bug 374, 12006, 12971,
12731, and to fix this bug; but I won't be surprised to hear that it
breaks something else...

*** lisp/mouse.el	2013-01-01 09:11:05 +0000
--- lisp/mouse.el	2013-01-29 22:22:44 +0000
***************
*** 425,431 ****
  				   (frame-parameters frame)))
  			'right)))
  	 (draggable t)
! 	 finished event position growth dragged)
      (cond
       ((eq line 'header)
        ;; Check whether header-line can be dragged at all.
--- 425,431 ----
  				   (frame-parameters frame)))
  			'right)))
  	 (draggable t)
! 	 event position growth dragged)
      (cond
       ((eq line 'header)
        ;; Check whether header-line can be dragged at all.
***************
*** 456,494 ****
  
      ;; Start tracking.
      (track-mouse
!       ;; Loop reading events and sampling the position of the mouse.
!       (while (not finished)
! 	(setq event (read-event))
  	(setq position (mouse-position))
  	;; Do nothing if
  	;;   - there is a switch-frame event.
  	;;   - the mouse isn't in the frame that we started in
  	;;   - the mouse isn't in any Emacs frame
- 	;; Drag if
- 	;;   - there is a mouse-movement event
- 	;;   - there is a scroll-bar-movement event (Why? -- cyd)
- 	;;     (same as mouse movement for our purposes)
- 	;; Quit if
- 	;;   - there is a keyboard event or some other unknown event.
  	(cond
- 	 ((not (consp event))
- 	  (setq finished t))
  	 ((memq (car event) '(switch-frame select-window))
  	  nil)
! 	 ((not (memq (car event) '(mouse-movement scroll-bar-movement)))
! 	  (when (consp event)
! 	    ;; Do not unread a drag-mouse-1 event to avoid selecting
! 	    ;; some other window.  For vertical line dragging do not
! 	    ;; unread mouse-1 events either (but only if we dragged at
! 	    ;; least once to allow mouse-1 clicks get through).
! 	    (unless (and dragged
! 			 (if (eq line 'vertical)
! 			     (memq (car event) '(drag-mouse-1 mouse-1))
! 			   (eq (car event) 'drag-mouse-1)))
! 	      (push event unread-command-events)))
! 	  (setq finished t))
! 	 ((not (and (eq (car position) frame)
! 		    (cadr position)))
  	  nil)
  	 ((eq line 'vertical)
  	  ;; Drag vertical divider.
--- 456,480 ----
  
      ;; Start tracking.
      (track-mouse
!       ;; Loop reading events and sampling the position of the mouse,
!       ;; until there is a non-mouse-movement event.  Also,
!       ;; scroll-bar-movement events are the same as mouse movement for
!       ;; our purposes.  (Why? -- cyd)
!       (while (progn
! 	       (setq event (read-event))
! 	       (memq (car-safe event)
!                      '(mouse-movement scroll-bar-movement
!                                       switch-frame select-window)))
  	(setq position (mouse-position))
  	;; Do nothing if
  	;;   - there is a switch-frame event.
  	;;   - the mouse isn't in the frame that we started in
  	;;   - the mouse isn't in any Emacs frame
  	(cond
  	 ((memq (car event) '(switch-frame select-window))
  	  nil)
!  	 ((not (and (eq (car position) frame)
!  		    (cadr position)))
  	  nil)
  	 ((eq line 'vertical)
  	  ;; Drag vertical divider.
***************
*** 512,523 ****
  						  growth
  						(- growth)))))))
      ;; Process the terminating event.
!     (when (and (mouse-event-p event) on-link (not dragged)
! 	       (mouse--remap-link-click-p start-event event))
!       ;; If mouse-2 has never been done by the user, it doesn't have
!       ;; the necessary property to be interpreted correctly.
!       (put 'mouse-2 'event-kind 'mouse-click)
!       (setcar event 'mouse-2)
        (push event unread-command-events))))
  
  (defun mouse-drag-mode-line (start-event)
--- 498,510 ----
  						  growth
  						(- growth)))))))
      ;; Process the terminating event.
!     (unless dragged
!       (when (and (mouse-event-p event) on-link
!                  (mouse--remap-link-click-p start-event event))
!         ;; If mouse-2 has never been done by the user, it doesn't have
!         ;; the necessary property to be interpreted correctly.
!         (put 'mouse-2 'event-kind 'mouse-click)
!         (setcar event 'mouse-2))
        (push event unread-command-events))))
  
  (defun mouse-drag-mode-line (start-event)