home *** CD-ROM | disk | FTP | other *** search
/ ftp.freefriends.org / ftp.freefriends.org.tar / ftp.freefriends.org / arnold / Source / gwm-dist.tar.gz / gwm-dist.tar / home-gwm / focus.gwm < prev    next >
Text File  |  1993-07-07  |  7KB  |  204 lines

  1. ; focus.gwm - maintain a list of focus windows and make sure that if
  2. ; there are any mapped windows that can have the focus, one always
  3. ; does.
  4. ; BUG FIX: don't give focus to root-window -- it bad!  use (set-focus nil)
  5. ; instead
  6.  
  7. (if (not (boundp 'tty-window-classes))
  8.     (: tty-window-classes '("XTerm")))
  9.  
  10. (for var '(focus-list must-assign-focus current-focus-window)
  11.     (if (not (= screen. (namespace-of var)))
  12.     (defname var screen.))
  13.     (if (not (boundp var))
  14.     (set var nil)))
  15.  
  16. (: root-behavior
  17.     (state-make
  18.     root-behavior
  19.     (on focus-out (revert-focus))))
  20.  
  21. (: window-behavior
  22.     (state-make
  23.     window-behavior
  24.     (on map-notify (handle-map-notify))))
  25.  
  26. (reparse-standard-behaviors)
  27.  
  28. (de pick-focus-window (startup)
  29.     (with (fw nil)
  30.     (for w (list-of-windows 'mapped 'window)
  31.         (if (and (not fw)
  32.              (with (window w)
  33.              (member window-client-class tty-window-classes)))
  34.         (: fw w)))
  35.     (if (not fw)
  36.         (progn
  37.         (if startup
  38.             (progn
  39.             (? "WARNING: can't pick a focus window sensibly\n")
  40.             (? "WARNING: assigning focus to root window\n")
  41.             ))
  42.         (: fw nil)
  43.         (: must-assign-focus t))
  44.         (if (not startup)
  45.         (progn
  46.             (? "WARNING: had to pick a focus window\n")
  47.             (bell 100))))
  48.     fw))
  49.  
  50. (if (not (boundp 'primitive-set-focus))
  51.     (: primitive-set-focus set-focus))
  52.  
  53. (df set-focus w
  54.     (with (ww window)
  55.     (tag my-set-focus-tag
  56.         (if w
  57.         (if (> (length w) 1)
  58.             (progn
  59.             (? "ERROR: set-focus takes 0 or 1 argument:\n")
  60.             (? (+ '(set-focus) w) "\n")
  61.             (exit my-set-focus-tag nil))
  62.             (if (error-occurred (: ww (eval (# 0 w))))
  63.             (progn
  64.                 (? "ERROR: error in evaluation of argument:\n")
  65.                 (? (+ '(set-focus) w) "\n")
  66.                 (exit my-set-focus-tag nil)))))
  67.  
  68.         ; At this point, we have set ww to the target window, which may
  69.         ; have defaulted if the argument was missing, or may be nil if
  70.         ; someone is trying explicitly to set the focus to PointerRoot
  71.         ; mode.  We don't allow that.
  72.  
  73. ;        (if (null ww) 
  74. ;        (progn
  75. ;            (? "ERROR: not allowed to set-focus to nil:\n")
  76. ;            (? (+ '(set-focus) w) "\n")
  77. ;            (exit my-set-focus-tag nil)))
  78.  
  79.         ; Make sure the window really does take the focus before
  80.         ; updating focus-list.  Don't add ww to focus-list if it
  81.         ; is nil.  Then, return the right value.
  82.  
  83.         (if (primitive-set-focus ww)
  84.         (progn
  85.             (: current-focus-window ww)
  86.             (if ww
  87.             (progn
  88.                 (if t ; (= check-input-focus-flag 0)
  89.                 (add-to-focus-list ww))
  90.                 (: must-assign-focus nil)))
  91.             t)
  92.         nil))))
  93.  
  94. (de add-to-focus-list (w)
  95.     (with (pos (member w focus-list))
  96.     (: focus-list
  97.         (if (null pos)        ; This one has never had the focus.
  98.         (+ (list w) focus-list)
  99.         (+ (list w)
  100.            (sublist 0 pos focus-list)
  101.            (sublist (+ pos 1) (length focus-list) focus-list))))))
  102.  
  103. ; let's see if the autofocus can do this for us
  104. ;(: to-be-done-after-setup
  105. ;     (+ to-be-done-after-setup
  106. ;     '((set-focus (pick-focus-window t))))) ; Initial focus must be somewhere
  107.  
  108. ; This function is one of the main points of our focus handling.  Called
  109. ; by a focus-in event in the root window, it assigns the focus to the
  110. ; window that most recently had it, on the assumption that the one that
  111. ; just gave it up was destroyed or unmapped somehow, perhaps by being
  112. ; iconified or its client exiting.  Warn the user if things look funny.
  113.  
  114. (de revert-focus ()
  115.     (with (w (# 0 focus-list) pos nil)
  116.  
  117.     (if (member w (list-of-windows))
  118.  
  119.         ; So the window still exists.  But is it mapped?
  120.  
  121.         (with (window w)
  122.         (if window-is-mapped
  123.             (progn
  124.             (? "WARNING: a mapped window relinquished the focus\n")
  125.             ; can't really do this because of sam? (bell 100)
  126.             ))))
  127.  
  128.     ; One way or another the first element is coming out of the
  129.     ; focus list now.  We start at the second and assign the focus
  130.     ; to the first one we find that is still a window and still
  131.     ; mapped.  Elements to the left of that are all deleted.
  132.  
  133.     (for pfw (sublist 1 (length focus-list) focus-list)
  134.         (if (and (null pos)
  135.              (member pfw (list-of-windows))
  136.              (with (window pfw) window-is-mapped))
  137.         (: pos (member pfw focus-list))))
  138.     (if (null pos)
  139.  
  140.         ; Wow.  Not one of the windows that formerly had the focus
  141.         ; is in a position to take it back.  What a situation!  We'll
  142.         ; try to pick a focus window; if we can't, the focus goes to
  143.         ; the root, and the next window created or deiconified will
  144.         ; get it (by virtue of the "opening" code and the global
  145.         ; (per-screen) flag must-assign-focus).
  146.  
  147.         (progn
  148.         (: focus-list nil)
  149.         (set-focus (pick-focus-window nil)))
  150.  
  151.         ; Here, things are not so bad.  We've located the window that
  152.         ; most recently had the focus and can take it back.
  153.  
  154.         (progn
  155.         (: focus-list (sublist pos (length focus-list) focus-list))
  156.         (: current-focus-window (# 0 focus-list))
  157.         (primitive-set-focus (# 0 focus-list))
  158.         (with (window (# 0 focus-list))
  159.             (if (not window-is-mapped)
  160.             (revert-focus)))))))    ; It's gone! Try again...
  161.  
  162. ; We have to maintain the property list correctly if we lose the focus
  163. ; due to being iconified.  This also allows us to set the focus if needed
  164. ; on de-iconification.  Creation will have to be handled elsewhere...
  165.  
  166. (if (not (boundp 'primitive-iconify-window))
  167.     (: primitive-iconify-window iconify-window))
  168.  
  169. (de iconify-window nil
  170.     (if (eq window-status 'window)
  171.     (progn
  172.         (window-property (# 'has-focus window-property nil))
  173.  
  174.         ; Now THIS, THIS is what I call a HIDEOUS KLUDGE.
  175.         (send-user-event 'focus-out)
  176.  
  177.         (primitive-iconify-window))
  178.     (eq window-status 'icon)
  179.     (progn
  180.         (primitive-iconify-window)    ; Current window is now the window.
  181. ;
  182. ; The following three lines aren't really bad code, but we don't want
  183. ; them right now.  If you put them in, and take out the "if t" following,
  184. ; then only some windows will get the focus on deiconify, instead of
  185. ; all of them.
  186. ;        (if (and must-assign-focus
  187. ;             (or (member window-client-class tty-window-classes)
  188. ;             (member window focus-list)))
  189.         (if t
  190.         (if (set-focus)
  191.             (send-user-event 'focus-in))))
  192.     (primitive-iconify-window)))    ; Don't know this kind, just do it.
  193.  
  194. ; Automatically assign focus to a window on mapping, provided it is
  195. ; either a tty-window or else a pop-up from the window which has the focus.
  196.  
  197. (de handle-map-notify nil
  198.     (if (and (eq window-status 'window)
  199.          (eq wob-status 'window)
  200.          (or (member window-client-class tty-window-classes)
  201.              (and window-is-transient-for
  202.               (= window-is-transient-for current-focus-window))))
  203.                 (currtop nil)))
  204.