;; dir-focus.gwm -- moves the focus to the closest window in a given direction
;;
;; Author: Teemu Hirsimaki <thirsima@cc.hut.fi>
;; Last change: 8 Nov 1998
;;
;; The function is "(focus-dir DIR)" where DIR is 'north, 'east,
;; 'south or 'west.  It searches the closest window in the given
;; direction and sets focus in it.  The variable dir-skip-list
;; specifies regular expressions for windows to ignore.

(defaults-to
  dir-skip-list '(
    "^panlist$" "^virtual$" "^door-mgr$" "load$" "lock$" "^Gwm$")
)

(defun abs (x)
  (if (< x 0) (- x) x)
)

;; Score function
(defun dir-score-function (distance offset)
  (if (< distance 1)
    0
    (+ (/ (* 1000 (abs offset)) distance) distance)
)))

;; Calculates a score for a window.  The smaller the better.
(defun dir-calculate-score (cur dir)
  (with (win-x (+ window-x (/ window-width 2)) win-y window-y)
    (with (window cur)
      (with (cur-x (+ window-x (/ window-width 2)) cur-y window-y)
        (cond
          ((= dir 'north)
            (dir-score-function (- cur-y win-y) (- cur-x win-x))
          )
          ((= dir 'south)
            (dir-score-function (- win-y cur-y) (- cur-x win-x))
          )
          ((= dir 'east)
            (dir-score-function (- win-x cur-x) (- cur-y win-y))
          )
          ((= dir 'west)

            (dir-score-function (- cur-x win-x) (- cur-y win-y))
))))))

;; Checks if the window is in dir-skip-list
(defun dir-legal-window ()
  (tag return
    (for exp dir-skip-list
      (if (match exp window-name)
        (exit return ())
    ))
    t
))

;; Moves focus to the closest window in the given direction
(defun dir-focus (dir)
  (with (cur window best-score 0 best-win ())
    (for window (list-of-windows 'mapped 'window)
      (if (dir-legal-window)
        (with (score (dir-calculate-score cur dir))
          (if
            (and (> score 0)
              (or (< score best-score)
                (= best-win ())))
            (progn
              (setq best-score score)
              (setq best-win window)))))
    )
    (if (not (= best-win ()))
      (with (window best-win)
        (if (boundp 'virtual-make-window-visible)
            (virtual-make-window-visible))
        (warp-pointer (/ window-width 2) 2 best-win)
        (process-events)
        (set-focus best-win)
))))

;; end of file
