From 71e6691e5c9347f53fc984ccba83065c5e9fabaf Mon Sep 17 00:00:00 2001 From: Martin Rudalics Date: Fri, 13 Dec 2013 18:06:30 +0100 Subject: [PATCH] Fix windmove-find-other-window broken after pixelwise resizing (Bug#16017). * windmove.el (windmove-other-window-loc): Revert change from 2013-12-04. (windmove-find-other-window): Call window-in-direction. * window.el (window-in-direction): New arguments SIGN, WRAP and MINI to emulate original windmove-find-other-window behavior. --- lisp/ChangeLog | 10 ++++++ lisp/windmove.el | 37 +++++++------------ lisp/window.el | 106 ++++++++++++++++++++++++++++++++++++++----------------- 3 files changed, 96 insertions(+), 57 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 7b0e00d0251..b48563761c4 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,13 @@ +2013-12-13 Martin Rudalics + + Fix windmove-find-other-window broken after pixelwise resizing + (Bug#16017). + * windmove.el (windmove-other-window-loc): Revert change from + 2013-12-04. + (windmove-find-other-window): Call window-in-direction. + * window.el (window-in-direction): New arguments SIGN, WRAP and + MINI to emulate original windmove-find-other-window behavior. + 2013-12-13 Dmitry Gutov * simple.el (blink-matching--overlay): New variable. diff --git a/lisp/windmove.el b/lisp/windmove.el index 638240347c1..ad191b3a24f 100644 --- a/lisp/windmove.el +++ b/lisp/windmove.el @@ -438,49 +438,38 @@ Return value is a frame-based (HPOS . VPOS) value that should be moved to. DIR is one of `left', `up', `right', or `down'; an optional ARG is handled as by `windmove-reference-loc'; WINDOW is the window that movement is relative to." - (let ((edges (window-pixel-edges window)) ; edges: (x0, y0, x1, y1) + (let ((edges (window-edges window)) ; edges: (x0, y0, x1, y1) (refpoint (windmove-reference-loc arg window))) ; (x . y) (cond ((eq dir 'left) - (cons (- (ceiling (nth 0 edges) - (frame-char-width (window-frame window))) + (cons (- (nth 0 edges) windmove-window-distance-delta) (cdr refpoint))) ; (x0-d, y) ((eq dir 'up) (cons (car refpoint) - (- (ceiling (nth 1 edges) - (frame-char-height (window-frame window))) + (- (nth 1 edges) windmove-window-distance-delta))) ; (x, y0-d) ((eq dir 'right) - (cons (+ (1- (ceiling (nth 2 edges) - (frame-char-width (window-frame window)))) ; -1 to get actual max x + (cons (+ (1- (nth 2 edges)) ; -1 to get actual max x windmove-window-distance-delta) (cdr refpoint))) ; (x1+d-1, y) ((eq dir 'down) ; -1 to get actual max y (cons (car refpoint) - (+ (1- (ceiling (nth 3 edges) - (frame-char-height (window-frame window)))) + (+ (1- (nth 3 edges)) windmove-window-distance-delta))) ; (x, y1+d-1) (t (error "Invalid direction of movement: %s" dir))))) +;; Rewritten on 2013-12-13 using `window-in-direction'. After the +;; pixelwise change the old approach didn't work any more. martin (defun windmove-find-other-window (dir &optional arg window) "Return the window object in direction DIR. DIR, ARG, and WINDOW are handled as by `windmove-other-window-loc'." - (let* ((actual-current-window (or window (selected-window))) - (raw-other-window-loc - (windmove-other-window-loc dir arg actual-current-window)) - (constrained-other-window-loc - (windmove-constrain-loc-for-movement raw-other-window-loc - actual-current-window - dir)) - (other-window-loc - (if windmove-wrap-around - (windmove-wrap-loc-for-movement constrained-other-window-loc - actual-current-window) - constrained-other-window-loc))) - (window-at (car other-window-loc) - (cdr other-window-loc)))) - + (window-in-direction + (cond + ((eq dir 'up) 'above) + ((eq dir 'down) 'below) + (t dir)) + window nil arg windmove-wrap-around t)) ;; Selects the window that's hopefully at the location returned by ;; `windmove-other-window-loc', or screams if there's no window there. diff --git a/lisp/window.el b/lisp/window.el index 714979d8df1..ba21dbc7bcc 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -1719,7 +1719,7 @@ SIDE can be any of the symbols `left', `top', `right' or ;; Neither of these allow 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) +(defun window-in-direction (direction &optional window ignore sign wrap mini) "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. @@ -1732,6 +1732,22 @@ non-nil, try to find another window in the indicated direction. If, however, the optional argument IGNORE is non-nil, return that window even if its `no-other-window' parameter is non-nil. +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 a WINDOW a the top of +the frame and DIRECTION `above' to return the minibuffer window +if the frame has one, and a window at the bottom of the frame +otherwise. + +Optional argument MINI nil means to return the minibuffer window +if and only if it is currently active. MINI non-nil means to +return the minibuffer window even when it's not active. However, +if WRAP non-nil, always act as if MINI were nil. + Return nil if no suitable window can be found." (setq window (window-normalize-window window t)) (unless (memq direction '(above below left right)) @@ -1742,12 +1758,22 @@ Return nil if no suitable window can be found." (window-pixel-left window) (window-pixel-top window))) (last (+ first (window-size window hor t))) - (posn-cons (nth 2 (posn-at-point (window-point window) window))) ;; The column / row value of `posn-at-point' can be nil for the ;; mini-window, guard against that. - (posn (if hor - (+ (or (cdr posn-cons) 1) (window-pixel-top window)) - (+ (or (car posn-cons) 1) (window-pixel-left window)))) + (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)) @@ -1772,9 +1798,15 @@ Return nil if no suitable window can be found." (< 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) - (<= w-left first) (> w-left best-edge)) + (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) - (>= w-left last) (< w-left best-edge))) + (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) @@ -1792,32 +1824,40 @@ Return nil if no suitable window can be found." (setq best-edge-2 w-left) (setq best-diff-2 best-diff-2-new) (setq best-2 w)))) - (t - (cond - ((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) - (<= w-top first) (> w-top best-edge)) - (and (eq direction 'below) - (>= w-top first) (< w-top best-edge))) - (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) + ((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 (and mini t)) (or best best-2))) (defun get-window-with-predicate (predicate &optional minibuf all-frames default) -- 2.11.4.GIT