Function: window-in-direction

window-in-direction is a byte-compiled function defined in window.el.gz.

Signature

(window-in-direction DIRECTION &optional WINDOW IGNORE SIGN WRAP MINIBUF)

Documentation

Return window in DIRECTION as seen from WINDOW.

More precisely, return the nearest window in direction DIRECTION as seen from the position of window-point in window WINDOW. DIRECTION should be one of above, below, left or right. WINDOW must be a live window and defaults to the selected one.

Do not return a window for which window-no-other-p returns non-nil. If window-no-other-p returns non-nil for the nearest window, try to find another window in the indicated direction. If, however, the optional argument IGNORE is non-nil, return the nearest window even if window-no-other-p returns for it a non-nil value.

Optional argument SIGN a negative number means to use the right or bottom edge of WINDOW as reference position instead of window-point. SIGN a positive number means to use the left or top edge of WINDOW as reference position.

Optional argument WRAP non-nil means to wrap DIRECTION around frame borders. This means to return for WINDOW at the top of the frame and DIRECTION above the minibuffer window if the frame has one, and a window at the bottom of the frame otherwise.

Optional argument MINIBUF t means to return the minibuffer window even if it isn't active. MINIBUF nil or omitted means to return the minibuffer window if and only if it is currently active. MINIBUF neither nil nor t means never return the minibuffer window. However, if WRAP is non-nil, always act as if MINIBUF were nil.

Return nil if no suitable window can be found.

View in manual

Probably introduced at or before Emacs version 24.4.

Source Code

;; Defined in /usr/src/emacs/lisp/window.el.gz
;; Predecessors to the below have been devised by Julian Assange in
;; change-windows-intuitively.el and Hovav Shacham in windmove.el.
;; Neither of these allow one to selectively ignore specific windows
;; (windows whose `no-other-window' parameter is non-nil) as targets of
;; the movement.
(defun window-in-direction (direction &optional window ignore sign wrap minibuf)
  "Return window in DIRECTION as seen from WINDOW.
More precisely, return the nearest window in direction DIRECTION
as seen from the position of `window-point' in window WINDOW.
DIRECTION should be one of `above', `below', `left' or `right'.
WINDOW must be a live window and defaults to the selected one.

Do not return a window for which `window-no-other-p' returns non-nil.
If `window-no-other-p' returns non-nil for the nearest window, try to
find another window in the indicated direction.  If, however, the
optional argument IGNORE is non-nil, return the nearest window even if
`window-no-other-p' returns for it a non-nil value.

Optional argument SIGN a negative number means to use the right
or bottom edge of WINDOW as reference position instead of
`window-point'.  SIGN a positive number means to use the left or
top edge of WINDOW as reference position.

Optional argument WRAP non-nil means to wrap DIRECTION around
frame borders.  This means to return for WINDOW at the top of the
frame and DIRECTION `above' the minibuffer window if the frame
has one, and a window at the bottom of the frame otherwise.

Optional argument MINIBUF t means to return the minibuffer
window even if it isn't active.  MINIBUF nil or omitted means
to return the minibuffer window if and only if it is currently active.
MINIBUF neither nil nor t means never return the minibuffer window.
However, if WRAP is non-nil, always act as if MINIBUF were nil.

Return nil if no suitable window can be found."
  (setq window (window-normalize-window window t))
  (cond
   ((eq direction 'up)
    (setq direction 'above))
   ((eq direction 'down)
    (setq direction 'below))
   ((not (memq direction '(above below left right)))
    (error "Wrong direction %s" direction)))
  (let* ((frame (window-frame window))
	 (hor (memq direction '(left right)))
	 (first (if hor
		    (window-pixel-left window)
		  (window-pixel-top window)))
	 (last (+ first (window-size window hor t)))
	 ;; The column / row value of `posn-at-point' can be nil for the
	 ;; mini-window, guard against that.
	 (posn
	  (cond
	   ((and (numberp sign) (< sign 0))
	    (if hor
		(1- (+ (window-pixel-top window) (window-pixel-height window)))
	      (1- (+ (window-pixel-left window) (window-pixel-width window)))))
	   ((and (numberp sign) (> sign 0))
	    (if hor
		(window-pixel-top window)
	      (window-pixel-left window)))
	   ((let ((posn-cons (nth 2 (posn-at-point (window-point window) window))))
	      (if hor
		  (+ (or (cdr posn-cons) 1) (window-pixel-top window))
		(+ (or (car posn-cons) 1) (window-pixel-left window)))))))
	 (best-edge
	  (cond
	   ((eq direction 'below) (frame-pixel-height frame))
	   ((eq direction 'right) (frame-pixel-width frame))
	   (t -1)))
	 (best-edge-2 best-edge)
	 (best-diff-2 (if hor (frame-pixel-height frame) (frame-pixel-width frame)))
	 best best-2 best-diff-2-new)
    (walk-window-tree
     (lambda (w)
       (let* ((w-top (window-pixel-top w))
	      (w-left (window-pixel-left w)))
	 (cond
	  ((or (eq window w)
	       ;; Ignore ourselves.
	       (and (window-no-other-p w)
		    ;; Ignore W unless IGNORE is non-nil.
		    (not ignore))))
	  (hor
	   (cond
	    ((and (<= w-top posn)
		  (< posn (+ w-top (window-pixel-height w))))
	     ;; W is to the left or right of WINDOW and covers POSN.
	     (when (or (and (eq direction 'left)
			    (or (and (<= w-left first) (> w-left best-edge))
				(and wrap
				     (window-at-side-p window 'left)
				     (window-at-side-p w 'right))))
		       (and (eq direction 'right)
			    (or (and (>= w-left last) (< w-left best-edge))
				(and wrap
				     (window-at-side-p window 'right)
				     (window-at-side-p w 'left)))))
	       (setq best-edge w-left)
	       (setq best w)))
	    ((and (or (and (eq direction 'left)
			   (<= (+ w-left (window-pixel-width w)) first))
		      (and (eq direction 'right) (<= last w-left)))
		  ;; W is to the left or right of WINDOW but does not
		  ;; cover POSN.
		  (setq best-diff-2-new
			(window--in-direction-2 w posn hor))
		  (or (< best-diff-2-new best-diff-2)
		      (and (= best-diff-2-new best-diff-2)
			   (if (eq direction 'left)
			       (> w-left best-edge-2)
			     (< w-left best-edge-2)))))
	     (setq best-edge-2 w-left)
	     (setq best-diff-2 best-diff-2-new)
	     (setq best-2 w))))
	  ((and (<= w-left posn)
		(< posn (+ w-left (window-pixel-width w))))
	   ;; W is above or below WINDOW and covers POSN.
	   (when (or (and (eq direction 'above)
			  (or (and (<= w-top first) (> w-top best-edge))
			      (and wrap
				   (window-at-side-p window 'top)
				   (if (active-minibuffer-window)
				       (minibuffer-window-active-p w)
				     (window-at-side-p w 'bottom)))))
		     (and (eq direction 'below)
			  (or (and (>= w-top first) (< w-top best-edge))
			      (and wrap
				   (if (active-minibuffer-window)
				       (minibuffer-window-active-p window)
				     (window-at-side-p window 'bottom))
				   (window-at-side-p w 'top)))))
	     (setq best-edge w-top)
	     (setq best w)))
	  ((and (or (and (eq direction 'above)
			 (<= (+ w-top (window-pixel-height w)) first))
		    (and (eq direction 'below) (<= last w-top)))
		;; W is above or below WINDOW but does not cover POSN.
		(setq best-diff-2-new
		      (window--in-direction-2 w posn hor))
		(or (< best-diff-2-new best-diff-2)
		    (and (= best-diff-2-new best-diff-2)
			 (if (eq direction 'above)
			     (> w-top best-edge-2)
			   (< w-top best-edge-2)))))
	   (setq best-edge-2 w-top)
	   (setq best-diff-2 best-diff-2-new)
	   (setq best-2 w)))))
     frame nil minibuf)
    (or best best-2)))