aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/mouse.el
diff options
context:
space:
mode:
authorBastien2017-07-03 09:06:29 +0200
committerBastien2017-07-03 09:06:29 +0200
commit5ca1888fe670aee7febd4d42665d7372ab2ffebc (patch)
tree1f7f8d8a7580e556fc83cf3a6aaeec567b33a090 /lisp/mouse.el
parent20e006ffee41062f1b551a92c24d9edc53cd0f56 (diff)
parent1b4f0a92ff3505ef9a465b9b391756e3a73a6443 (diff)
downloademacs-5ca1888fe670aee7febd4d42665d7372ab2ffebc.tar.gz
emacs-5ca1888fe670aee7febd4d42665d7372ab2ffebc.zip
Merge branch 'master' into scratch/org-mode-merge
Diffstat (limited to 'lisp/mouse.el')
-rw-r--r--lisp/mouse.el433
1 files changed, 410 insertions, 23 deletions
diff --git a/lisp/mouse.el b/lisp/mouse.el
index 9b6b169e568..e0794435d7a 100644
--- a/lisp/mouse.el
+++ b/lisp/mouse.el
@@ -380,7 +380,7 @@ This command must be bound to a mouse click."
380 380
381(defun mouse-drag-line (start-event line) 381(defun mouse-drag-line (start-event line)
382 "Drag a mode line, header line, or vertical line with the mouse. 382 "Drag a mode line, header line, or vertical line with the mouse.
383START-EVENT is the starting mouse-event of the drag action. LINE 383START-EVENT is the starting mouse event of the drag action. LINE
384must be one of the symbols `header', `mode', or `vertical'." 384must be one of the symbols `header', `mode', or `vertical'."
385 ;; Give temporary modes such as isearch a chance to turn off. 385 ;; Give temporary modes such as isearch a chance to turn off.
386 (run-hooks 'mouse-leave-buffer-hook) 386 (run-hooks 'mouse-leave-buffer-hook)
@@ -405,29 +405,15 @@ must be one of the symbols `header', `mode', or `vertical'."
405 ;; window's edge we drag. 405 ;; window's edge we drag.
406 (cond 406 (cond
407 ((eq line 'header) 407 ((eq line 'header)
408 (if (window-at-side-p window 'top) 408 ;; Drag bottom edge of window above the header line.
409 ;; We can't drag the header line of a topmost window. 409 (setq window (window-in-direction 'above window t)))
410 (setq draggable nil) 410 ((eq line 'mode))
411 ;; Drag bottom edge of window above the header line.
412 (setq window (window-in-direction 'above window t))))
413 ((eq line 'mode)
414 (if (and (window-at-side-p window 'bottom)
415 ;; Allow resizing the minibuffer window if it's on the
416 ;; same frame as and immediately below `window', and it's
417 ;; either active or `resize-mini-windows' is nil.
418 (let ((minibuffer-window (minibuffer-window frame)))
419 (not (and (eq (window-frame minibuffer-window) frame)
420 (or (not resize-mini-windows)
421 (eq minibuffer-window
422 (active-minibuffer-window)))))))
423 (setq draggable nil)))
424 ((eq line 'vertical) 411 ((eq line 'vertical)
425 (let ((divider-width (frame-right-divider-width frame))) 412 (let ((divider-width (frame-right-divider-width frame)))
426 (when (and (or (not (numberp divider-width)) 413 (when (and (or (not (numberp divider-width))
427 (zerop divider-width)) 414 (zerop divider-width))
428 (eq (frame-parameter frame 'vertical-scroll-bars) 'left)) 415 (eq (frame-parameter frame 'vertical-scroll-bars) 'left))
429 (setq window (window-in-direction 'left window t)))))) 416 (setq window (window-in-direction 'left window t))))))
430
431 (let* ((exitfun nil) 417 (let* ((exitfun nil)
432 (move 418 (move
433 (lambda (event) (interactive "e") 419 (lambda (event) (interactive "e")
@@ -530,20 +516,405 @@ must be one of the symbols `header', `mode', or `vertical'."
530 t (lambda () (setq track-mouse old-track-mouse))))))) 516 t (lambda () (setq track-mouse old-track-mouse)))))))
531 517
532(defun mouse-drag-mode-line (start-event) 518(defun mouse-drag-mode-line (start-event)
533 "Change the height of a window by dragging on the mode line." 519 "Change the height of a window by dragging on its mode line.
520START-EVENT is the starting mouse event of the drag action.
521
522If the drag happens in a mode line on the bottom of a frame and
523that frame's `drag-with-mode-line' parameter is non-nil, drag the
524frame instead."
534 (interactive "e") 525 (interactive "e")
535 (mouse-drag-line start-event 'mode)) 526 (let* ((start (event-start start-event))
527 (window (posn-window start))
528 (frame (window-frame window)))
529 (cond
530 ((not (window-live-p window)))
531 ((or (not (window-at-side-p window 'bottom))
532 ;; Allow resizing the minibuffer window if it's on the
533 ;; same frame as and immediately below `window', and it's
534 ;; either active or `resize-mini-windows' is nil.
535 (let ((minibuffer-window (minibuffer-window frame)))
536 (and (eq (window-frame minibuffer-window) frame)
537 (or (not resize-mini-windows)
538 (eq minibuffer-window
539 (active-minibuffer-window))))))
540 (mouse-drag-line start-event 'mode))
541 ((and (frame-parameter frame 'drag-with-mode-line)
542 (window-at-side-p window 'bottom)
543 (let ((minibuffer-window (minibuffer-window frame)))
544 (not (eq (window-frame minibuffer-window) frame))))
545 ;; Drag frame when the window is on the bottom of its frame and
546 ;; there is no minibuffer window below.
547 (mouse-drag-frame start-event 'move)))))
536 548
537(defun mouse-drag-header-line (start-event) 549(defun mouse-drag-header-line (start-event)
538 "Change the height of a window by dragging on the header line." 550 "Change the height of a window by dragging on its header line.
551START-EVENT is the starting mouse event of the drag action.
552
553If the drag happens in a header line on the top of a frame and
554that frame's `drag-with-header-line' parameter is non-nil, drag
555the frame instead."
539 (interactive "e") 556 (interactive "e")
540 (mouse-drag-line start-event 'header)) 557 (let* ((start (event-start start-event))
558 (window (posn-window start)))
559 (if (and (window-live-p window)
560 (not (window-at-side-p window 'top)))
561 (mouse-drag-line start-event 'header)
562 (let ((frame (window-frame window)))
563 (when (frame-parameter frame 'drag-with-header-line)
564 (mouse-drag-frame start-event 'move))))))
541 565
542(defun mouse-drag-vertical-line (start-event) 566(defun mouse-drag-vertical-line (start-event)
543 "Change the width of a window by dragging on the vertical line." 567 "Change the width of a window by dragging on a vertical line.
568START-EVENT is the starting mouse event of the drag action."
544 (interactive "e") 569 (interactive "e")
545 (mouse-drag-line start-event 'vertical)) 570 (mouse-drag-line start-event 'vertical))
546 571
572(defun mouse-resize-frame (frame x-diff y-diff &optional x-move y-move)
573 "Helper function for `mouse-drag-frame'."
574 (let* ((frame-x-y (frame-position frame))
575 (frame-x (car frame-x-y))
576 (frame-y (cdr frame-x-y))
577 alist)
578 (if (> x-diff 0)
579 (when x-move
580 (setq x-diff (min x-diff frame-x))
581 (setq x-move (- frame-x x-diff)))
582 (let* ((min-width (frame-windows-min-size frame t nil t))
583 (min-diff (max 0 (- (frame-inner-width frame) min-width))))
584 (setq x-diff (max x-diff (- min-diff)))
585 (when x-move
586 (setq x-move (+ frame-x (- x-diff))))))
587
588 (if (> y-diff 0)
589 (when y-move
590 (setq y-diff (min y-diff frame-y))
591 (setq y-move (- frame-y y-diff)))
592 (let* ((min-height (frame-windows-min-size frame nil nil t))
593 (min-diff (max 0 (- (frame-inner-height frame) min-height))))
594 (setq y-diff (max y-diff (- min-diff)))
595 (when y-move
596 (setq y-move (+ frame-y (- y-diff))))))
597
598 (unless (zerop x-diff)
599 (when x-move
600 (push `(left . ,x-move) alist))
601 (push `(width . (text-pixels . ,(+ (frame-text-width frame) x-diff)))
602 alist))
603 (unless (zerop y-diff)
604 (when y-move
605 (push `(top . ,y-move) alist))
606 (push `(height . (text-pixels . ,(+ (frame-text-height frame) y-diff)))
607 alist))
608 (when alist
609 (modify-frame-parameters frame alist))))
610
611(defun mouse-drag-frame (start-event part)
612 "Drag a frame or one of its edges with the mouse.
613START-EVENT is the starting mouse event of the drag action. Its
614position window denotes the frame that will be dragged.
615
616PART specifies the part that has been dragged and must be one of
617the symbols 'left', 'top', 'right', 'bottom', 'top-left',
618'top-right', 'bottom-left', 'bottom-right' to drag an internal
619border or edge. If PART equals 'move', this means to move the
620frame with the mouse."
621 ;; Give temporary modes such as isearch a chance to turn off.
622 (run-hooks 'mouse-leave-buffer-hook)
623 (let* ((echo-keystrokes 0)
624 (start (event-start start-event))
625 (window (posn-window start))
626 ;; FRAME is the frame to drag.
627 (frame (if (window-live-p window)
628 (window-frame window)
629 window))
630 (width (frame-native-width frame))
631 (height (frame-native-height frame))
632 ;; PARENT is the parent frame of FRAME or, if FRAME is a
633 ;; top-level frame, FRAME's workarea.
634 (parent (frame-parent frame))
635 (parent-edges
636 (if parent
637 `(0 0 ,(frame-native-width parent) ,(frame-native-height parent))
638 (let* ((attributes
639 (car (display-monitor-attributes-list)))
640 (workarea (assq 'workarea attributes)))
641 (and workarea
642 `(,(nth 1 workarea) ,(nth 2 workarea)
643 ,(+ (nth 1 workarea) (nth 3 workarea))
644 ,(+ (nth 2 workarea) (nth 4 workarea)))))))
645 (parent-left (and parent-edges (nth 0 parent-edges)))
646 (parent-top (and parent-edges (nth 1 parent-edges)))
647 (parent-right (and parent-edges (nth 2 parent-edges)))
648 (parent-bottom (and parent-edges (nth 3 parent-edges)))
649 ;; `pos-x' and `pos-y' record the x- and y-coordinates of the
650 ;; last sampled mouse position. Note that we sample absolute
651 ;; mouse positions to avoid that moving the mouse from one
652 ;; frame into another gets into our way. `last-x' and `last-y'
653 ;; records the x- and y-coordinates of the previously sampled
654 ;; position. The differences between `last-x' and `pos-x' as
655 ;; well as `last-y' and `pos-y' determine the amount the mouse
656 ;; has been dragged between the last two samples.
657 pos-x-y pos-x pos-y
658 (last-x-y (mouse-absolute-pixel-position))
659 (last-x (car last-x-y))
660 (last-y (cdr last-x-y))
661 ;; `snap-x' and `snap-y' record the x- and y-coordinates of the
662 ;; mouse position when FRAME snapped. As soon as the
663 ;; difference between `pos-x' and `snap-x' (or `pos-y' and
664 ;; `snap-y') exceeds the value of FRAME's `snap-width'
665 ;; parameter, unsnap FRAME (at the respective side). `snap-x'
666 ;; and `snap-y' nil mean FRAME is curerntly not snapped.
667 snap-x snap-y
668 (exitfun nil)
669 (move
670 (lambda (event)
671 (interactive "e")
672 (when (consp event)
673 (setq pos-x-y (mouse-absolute-pixel-position))
674 (setq pos-x (car pos-x-y))
675 (setq pos-y (cdr pos-x-y))
676 (cond
677 ((eq part 'left)
678 (mouse-resize-frame frame (- last-x pos-x) 0 t))
679 ((eq part 'top)
680 (mouse-resize-frame frame 0 (- last-y pos-y) nil t))
681 ((eq part 'right)
682 (mouse-resize-frame frame (- pos-x last-x) 0))
683 ((eq part 'bottom)
684 (mouse-resize-frame frame 0 (- pos-y last-y)))
685 ((eq part 'top-left)
686 (mouse-resize-frame
687 frame (- last-x pos-x) (- last-y pos-y) t t))
688 ((eq part 'top-right)
689 (mouse-resize-frame
690 frame (- pos-x last-x) (- last-y pos-y) nil t))
691 ((eq part 'bottom-left)
692 (mouse-resize-frame
693 frame (- last-x pos-x) (- pos-y last-y) t))
694 ((eq part 'bottom-right)
695 (mouse-resize-frame
696 frame (- pos-x last-x) (- pos-y last-y)))
697 ((eq part 'move)
698 (let* ((old-position (frame-position frame))
699 (old-left (car old-position))
700 (old-top (cdr old-position))
701 (left (+ old-left (- pos-x last-x)))
702 (top (+ old-top (- pos-y last-y)))
703 right bottom
704 ;; `snap-width' (maybe also a yet to be provided
705 ;; `snap-height') could become floats to handle
706 ;; proportionality wrt PARENT. We don't do any
707 ;; checks on this parameter so far.
708 (snap-width (frame-parameter frame 'snap-width)))
709 ;; Docking and constraining.
710 (when (and (numberp snap-width) parent-edges)
711 (cond
712 ;; Docking at the left parent edge.
713 ((< pos-x last-x)
714 (cond
715 ((and (> left parent-left)
716 (<= (- left parent-left) snap-width))
717 ;; Snap when the mouse moved leftward and
718 ;; FRAME's left edge would end up within
719 ;; `snap-width' pixels from PARENT's left edge.
720 (setq snap-x pos-x)
721 (setq left parent-left))
722 ((and (<= left parent-left)
723 (<= (- parent-left left) snap-width)
724 snap-x (<= (- snap-x pos-x) snap-width))
725 ;; Stay snapped when the mouse moved leftward
726 ;; but not more than `snap-width' pixels from
727 ;; the time FRAME snapped.
728 (setq left parent-left))
729 (t
730 ;; Unsnap when the mouse moved more than
731 ;; `snap-width' pixels leftward from the time
732 ;; FRAME snapped.
733 (setq snap-x nil))))
734 ((> pos-x last-x)
735 (setq right (+ left width))
736 (cond
737 ((and (< right parent-right)
738 (<= (- parent-right right) snap-width))
739 ;; Snap when the mouse moved rightward and
740 ;; FRAME's right edge would end up within
741 ;; `snap-width' pixels from PARENT's right edge.
742 (setq snap-x pos-x)
743 (setq left (- parent-right width)))
744 ((and (>= right parent-right)
745 (<= (- right parent-right) snap-width)
746 snap-x (<= (- pos-x snap-x) snap-width))
747 ;; Stay snapped when the mouse moved rightward
748 ;; but not more more than `snap-width' pixels
749 ;; from the time FRAME snapped.
750 (setq left (- parent-right width)))
751 (t
752 ;; Unsnap when the mouse moved rightward more
753 ;; than `snap-width' pixels from the time FRAME
754 ;; snapped.
755 (setq snap-x nil)))))
756
757 (cond
758 ((< pos-y last-y)
759 (cond
760 ((and (> top parent-top)
761 (<= (- top parent-top) snap-width))
762 ;; Snap when the mouse moved upward and FRAME's
763 ;; top edge would end up within `snap-width'
764 ;; pixels from PARENT's top edge.
765 (setq snap-y pos-y)
766 (setq top parent-top))
767 ((and (<= top parent-top)
768 (<= (- parent-top top) snap-width)
769 snap-y (<= (- snap-y pos-y) snap-width))
770 ;; Stay snapped when the mouse moved upward but
771 ;; not more more than `snap-width' pixels from
772 ;; the time FRAME snapped.
773 (setq top parent-top))
774 (t
775 ;; Unsnap when the mouse moved upward more than
776 ;; `snap-width' pixels from the time FRAME
777 ;; snapped.
778 (setq snap-y nil))))
779 ((> pos-y last-y)
780 (setq bottom (+ top height))
781 (cond
782 ((and (< bottom parent-bottom)
783 (<= (- parent-bottom bottom) snap-width))
784 ;; Snap when the mouse moved downward and
785 ;; FRAME's bottom edge would end up within
786 ;; `snap-width' pixels from PARENT's bottom
787 ;; edge.
788 (setq snap-y pos-y)
789 (setq top (- parent-bottom height)))
790 ((and (>= bottom parent-bottom)
791 (<= (- bottom parent-bottom) snap-width)
792 snap-y (<= (- pos-y snap-y) snap-width))
793 ;; Stay snapped when the mouse moved downward
794 ;; but not more more than `snap-width' pixels
795 ;; from the time FRAME snapped.
796 (setq top (- parent-bottom height)))
797 (t
798 ;; Unsnap when the mouse moved downward more
799 ;; than `snap-width' pixels from the time FRAME
800 ;; snapped.
801 (setq snap-y nil))))))
802
803 ;; If requested, constrain FRAME's draggable areas to
804 ;; PARENT's edges. The `top-visible' parameter should
805 ;; be set when FRAME has a draggable header-line. If
806 ;; set to a number, it ascertains that the top of
807 ;; FRAME is always constrained to the top of PARENT
808 ;; and that at least as many pixels of FRAME as
809 ;; specified by that number are visible on each of the
810 ;; three remaining sides of PARENT.
811 ;;
812 ;; The `bottom-visible' parameter should be set when
813 ;; FRAME has a draggable mode-line. If set to a
814 ;; number, it ascertains that the bottom of FRAME is
815 ;; always constrained to the bottom of PARENT and that
816 ;; at least as many pixels of FRAME as specified by
817 ;; that number are visible on each of the three
818 ;; remaining sides of PARENT.
819 (let ((par (frame-parameter frame 'top-visible))
820 bottom-visible)
821 (unless par
822 (setq par (frame-parameter frame 'bottom-visible))
823 (setq bottom-visible t))
824 (when (and (numberp par) parent-edges)
825 (setq left
826 (max (min (- parent-right par) left)
827 (+ (- parent-left width) par)))
828 (setq top
829 (if bottom-visible
830 (min (max top (- parent-top (- height par)))
831 (- parent-bottom height))
832 (min (max top parent-top)
833 (- parent-bottom par))))))
834
835 ;; Use `modify-frame-parameters' since `left' and
836 ;; `top' may want to move FRAME out of its PARENT.
837 (modify-frame-parameters
838 frame
839 `((left . (+ ,left)) (top . (+ ,top)))))))
840 (setq last-x pos-x)
841 (setq last-y pos-y))))
842 (old-track-mouse track-mouse))
843 ;; Start tracking. The special value 'dragging' signals the
844 ;; display engine to freeze the mouse pointer shape for as long
845 ;; as we drag.
846 (setq track-mouse 'dragging)
847 ;; Loop reading events and sampling the position of the mouse.
848 (setq exitfun
849 (set-transient-map
850 (let ((map (make-sparse-keymap)))
851 (define-key map [switch-frame] #'ignore)
852 (define-key map [select-window] #'ignore)
853 (define-key map [scroll-bar-movement] #'ignore)
854 (define-key map [mouse-movement] move)
855 ;; Swallow drag-mouse-1 events to avoid selecting some other window.
856 (define-key map [drag-mouse-1]
857 (lambda () (interactive) (funcall exitfun)))
858 ;; Some of the events will of course end up looked up
859 ;; with a mode-line, header-line or vertical-line prefix ...
860 (define-key map [mode-line] map)
861 (define-key map [header-line] map)
862 (define-key map [vertical-line] map)
863 ;; ... and some maybe even with a right- or bottom-divider
864 ;; prefix.
865 (define-key map [right-divider] map)
866 (define-key map [bottom-divider] map)
867 map)
868 t (lambda () (setq track-mouse old-track-mouse))))))
869
870(defun mouse-drag-left-edge (start-event)
871 "Drag left edge of a frame with the mouse.
872START-EVENT is the starting mouse event of the drag action."
873 (interactive "e")
874 (mouse-drag-frame start-event 'left))
875
876(defun mouse-drag-top-left-corner (start-event)
877 "Drag top left corner of a frame with the mouse.
878START-EVENT is the starting mouse event of the drag action."
879 (interactive "e")
880 (mouse-drag-frame start-event 'top-left))
881
882(defun mouse-drag-top-edge (start-event)
883 "Drag top edge of a frame with the mouse.
884START-EVENT is the starting mouse event of the drag action."
885 (interactive "e")
886 (mouse-drag-frame start-event 'top))
887
888(defun mouse-drag-top-right-corner (start-event)
889 "Drag top right corner of a frame with the mouse.
890START-EVENT is the starting mouse event of the drag action."
891 (interactive "e")
892 (mouse-drag-frame start-event 'top-right))
893
894(defun mouse-drag-right-edge (start-event)
895 "Drag right edge of a frame with the mouse.
896START-EVENT is the starting mouse event of the drag action."
897 (interactive "e")
898 (mouse-drag-frame start-event 'right))
899
900(defun mouse-drag-bottom-right-corner (start-event)
901 "Drag bottom right corner of a frame with the mouse.
902START-EVENT is the starting mouse event of the drag action."
903 (interactive "e")
904 (mouse-drag-frame start-event 'bottom-right))
905
906(defun mouse-drag-bottom-edge (start-event)
907 "Drag bottom edge of a frame with the mouse.
908START-EVENT is the starting mouse event of the drag action."
909 (interactive "e")
910 (mouse-drag-frame start-event 'bottom))
911
912(defun mouse-drag-bottom-left-corner (start-event)
913 "Drag bottom left corner of a frame with the mouse.
914START-EVENT is the starting mouse event of the drag action."
915 (interactive "e")
916 (mouse-drag-frame start-event 'bottom-left))
917
547(defcustom mouse-select-region-move-to-beginning nil 918(defcustom mouse-select-region-move-to-beginning nil
548 "Effect of selecting a region extending backward from double click. 919 "Effect of selecting a region extending backward from double click.
549Nil means keep point at the position clicked (region end); 920Nil means keep point at the position clicked (region end);
@@ -2078,6 +2449,22 @@ is copied instead of being cut."
2078(global-set-key [bottom-divider down-mouse-1] 'mouse-drag-mode-line) 2449(global-set-key [bottom-divider down-mouse-1] 'mouse-drag-mode-line)
2079(global-set-key [bottom-divider mouse-1] 'ignore) 2450(global-set-key [bottom-divider mouse-1] 'ignore)
2080(global-set-key [bottom-divider C-mouse-2] 'mouse-split-window-horizontally) 2451(global-set-key [bottom-divider C-mouse-2] 'mouse-split-window-horizontally)
2452(global-set-key [left-edge down-mouse-1] 'mouse-drag-left-edge)
2453(global-set-key [left-edge mouse-1] 'ignore)
2454(global-set-key [top-left-corner down-mouse-1] 'mouse-drag-top-left-corner)
2455(global-set-key [top-left-corner mouse-1] 'ignore)
2456(global-set-key [top-edge down-mouse-1] 'mouse-drag-top-edge)
2457(global-set-key [top-edge mouse-1] 'ignore)
2458(global-set-key [top-right-corner down-mouse-1] 'mouse-drag-top-right-corner)
2459(global-set-key [top-right-corner mouse-1] 'ignore)
2460(global-set-key [right-edge down-mouse-1] 'mouse-drag-right-edge)
2461(global-set-key [right-edge mouse-1] 'ignore)
2462(global-set-key [bottom-right-corner down-mouse-1] 'mouse-drag-bottom-right-corner)
2463(global-set-key [bottom-right-corner mouse-1] 'ignore)
2464(global-set-key [bottom-edge down-mouse-1] 'mouse-drag-bottom-edge)
2465(global-set-key [bottom-edge mouse-1] 'ignore)
2466(global-set-key [bottom-left-corner down-mouse-1] 'mouse-drag-bottom-left-corner)
2467(global-set-key [bottom-left-corner mouse-1] 'ignore)
2081 2468
2082(provide 'mouse) 2469(provide 'mouse)
2083 2470