Updated version of stop-focus
- From: "Andrea Vettorello" <andrea vettorello gmail com>
- To: Sawfish <sawfish-list gnome org>
- Subject: Updated version of stop-focus
- Date: Wed, 17 Dec 2008 19:07:36 +0100
Hi,
I'll post here my updated version of stop-focus instead of the wiki
because it needs a small patch (
http://sawfish.wikia.com/wiki/Slide-window-hook ) that I recently
proposed (yesterday ^__^). It could interest the persons that use a
"sloppy" focus mode (enter-only, stop-focus) as it tries to solve all
the invariants that change the windows position not introduced by a
mouse movement, like windows unmapping, change of desktop, moving
resizing a window with the keyboard.
I've found at least a couple of corner cases: Firefox child windows
seems to confuse it when the pointer is not inside the Firefox window
and, with my current configuration, unmapping/closing a windows, the
expected window is not focused (the next MRU window). I've found
yesterday that this doesn't happen with Sawfish running alone (i.e.
not in a Gnome session) and with a clean configuration, so probably I
can try to isolate why it fails.
I don't consider it perfect yet but, IMHO, it's an improvement to the
default enter-only focus mode (and without using warp-pointer hacks)..
;;;; stop-focus.jl -- focuses a window when the cursor enters the
;;;; window and remains stationary for a period of time.
;; Copyright (C) 2000 John Kodis <kodis jagunet com>. The sawfish
;; stop-focus.jl module is based on hover-focus.jl by Nils Barth,
;; which was influenced by scwm's hover-focus.scm by John Kodis and
;; Greg Badros, which was in turn based on scwm's auto-raise.scm by
;; Maciej Stachowiak and Greg Badros. That's one hell of a pedigree
;; for a hundred lines of code.
;; Andrea Vettorello <andrea vettorello gmail com>, september 2008.
;; Now, a window is focused only as result of a mouse motion. To
;; achive that, the pointer position is updated and checked not only
;; on window enter events, as in the original version, but also on
;; workspace change, window unshading, window unmaximizing and window
;; slide. It tries to never focus the desktop when a window is
;; unmapped, but here (using Gnome) this doesn't happen when a window
;; is unmapped and the pointer is on the desktop. If Sawfish is
;; running alone it works as expected. I should try to isolate the
;; issue. Finally I hacked a way to enable click to focus, even if I
;; copied more code than I would liked from focus.jl...
;; This file is free software distributed under the terms of the GNU
;; General Public License; either version 2, or (at your option) any
;; later version. You should have received a copy of the GNU General
;; Public License along with sawfish; see the file COPYING. If not,
;; write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA
;; 02139, USA.
(require 'timers)
(require 'sawfish.wm.util.window-order)
(require 'sawfish.wm.focus)
(provide 'stop-focus)
;; Variables
(defcustom stop-focus-delay 250
"Delay in milliseconds until a window gains focus (in stop-focus mode)."
:group (focus)
:type number
:range (0 . 5000))
(defcustom stop-focus-slop 10
"Distance the cursor can move when stopped (in stop-focus mode)."
:group (focus)
:type number
:range (0 . 5000))
(defvar stop-focus-timer nil)
(defvar stop-focus-positions nil)
(defvar stop-focus-count nil)
(defvar stop-focus-interval nil)
;; Functions
;; motion -- approximates the distance from the eldest saved pointer
;; position to the current pointer location.
(defun motion ()
(let* ((point (query-pointer))
(dx (abs (- (caar stop-focus-positions) (car point))))
(dy (abs (- (cdar stop-focus-positions) (cdr point)))))
(+ (max dx dy) (/ (min dx dy) 2))))
;; stopped-p -- determines if the pointer has stopped, based on motion
;; and allowable position slop.
(defun stopped-p ()
(and (>= (length stop-focus-positions) stop-focus-count)
(< (motion) stop-focus-slop)))
;; stop-focus-timer-handler -- focuses a window if stopped, otherwise
;; re-arms timer and pushes a new position onto the position list.
(defun stop-focus-timer-handler (w)
(if (stopped-p)
(when (window-really-wants-input-p w)
(grab-server)
(set-input-focus w)
(ungrab-server))
(set-timer stop-focus-timer 0 stop-focus-interval)
(when (>= (length stop-focus-positions) stop-focus-count)
(setq stop-focus-positions (cdr stop-focus-positions)))
(setq stop-focus-positions
(append stop-focus-positions (list (query-pointer))))))
;; stop-focus-set-timer-values -- tries to split stop-focus-delay into
;; max-count intervals (arbitrarily chosen as 5), unless this would
;; reduce the interval below min-interval (20 ms, intended to reflect what
;; can be scheduled reliably), in which case fewer intervals are used.
(defun stop-focus-set-timer-values ()
(let* ((max-count 5)
(min-interval 20)
(stop-time stop-focus-delay)
(count (max 1 (min max-count (quotient stop-time min-interval))))
(interval (max min-interval (quotient stop-time count))))
(setq stop-focus-count count)
(setq stop-focus-interval interval)))
;; stop-focus-enter -- triggered on entering any window in stop-focus
;; mode. Pushes the current pointer on the positions list, computes
;; timer parameters, and starts the focus timer running.
(defun stop-focus-enter (w)
(if (zerop stop-focus-delay)
(when (window-really-wants-input-p w)
(grab-server)
(set-input-focus w)
(ungrab-server))
(unless (eq w (input-focus))
(setq stop-focus-positions (list (query-pointer)))
(stop-focus-set-timer-values)
(setq stop-focus-timer
(make-timer (lambda () (stop-focus-timer-handler w))
0 stop-focus-interval)))))
;; stop-focus-leave -- cleans up on exiting a window by deleting the
;; focus timer.
(defun stop-focus-leave (w)
(when stop-focus-timer
(delete-timer stop-focus-timer)
(setq stop-focus-timer nil)))
;; stop-focus-update-positions -- update the mouse pointer position.
(defun stop-focus-update-positions ()
(setq stop-focus-positions (list (query-pointer))))
(add-hook 'before-slide-hook stop-focus-update-positions)
(add-hook 'leave-workspace-hook stop-focus-update-positions)
(add-hook 'window-unmaximized-hook stop-focus-update-positions)
(add-hook 'shade-window-hook stop-focus-update-positions)
(define-focus-mode 'stop-focus
(lambda (w action . args)
(case action
((pointer-in)
(when (window-really-wants-input-p w)
(unless (or (desktop-window-p w)
(equal (car stop-focus-positions) (query-pointer)))
(stop-focus-enter w))))
((pointer-out)
(stop-focus-leave w))
((enter-root)
(unless (input-focus)
(window-order-focus-most-recent)))
((focus-in)
(focus-pop-map w))
((focus-out add-window)
(unless (or (not (window-really-wants-input-p w))
(eq w (input-focus)))
(focus-push-map w click-to-focus-map))))))
--
Andrea
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]