Article View: gnu.epoch.misc
Article #1715intermittent problem with minibuffer
From: Ken Wood
Date: Wed, 02 Oct 1991 16:41
Date: Wed, 02 Oct 1991 16:41
310 lines
11795 bytes
11795 bytes
Jerry Graves writes:
> I put the statment
>
> epoch -f vm &
>
> in my .xinitrc file to run epoch with vm (ViewMail) when I first start
> OpenWindows and it works fine about 2/3 of the time. However, 1/3 of
> the time the minibuffer does not drop but remains behind the edit
> screen.
I had this problem a couple of months ago, and eventually figured out
what was going on. It's basically a synchronisation problem between
the epoch process and the window manager: epoch asks the window
manager to move the minibuffer to the top of the screen and then
enquires as to it's actual location. Sometimes the enquiry may
complete before the minibuffer has actually moved, which confuses
epoch. This commonly happens if the window manager is running on a
slower or more heavily loaded machine to epoch
Here's a new version of minibuf.el that fixes the problem. About a
dozen users at this site have been using this code with twm for
several weeks with no problems. It hasn't been tested with other
window managers, but should work at least as well as the original.
Note: this code requires that a variable called running-epoch be set
to t if you are using epoch, or nil for emacs. The epoch-running.el
file included at the end will take care of this.
Ken
Ken Wood, Austek Microsystems, Technology Park, Adelaide, SA 5095, Australia
INTERNET: kwood@austek.oz.au UUCP: uunet.uu.net!munnari!austek.oz.au!kwood
;;----------------8<------------------------------------------------------
;*****************************************************************************
;
; Filename: minibuf.el
;
; Description: Minibuffer handling code.
;
; This version posted by Ken Wood <kwood@austek.oz.au>.
;
;*****************************************************************************
; Comment out the next line if you have your own means of setting the
; variable running-epoch.
(require 'epoch-running)
(provide 'epoch-minibuffer)
; Put the whole thing inside a test, so it will compile under emacs.
(if running-epoch
(progn
; First, some easy iconification code
;
(defun auto-iconify-event-handler (type value screen)
"\
Map event handler. Will iconify the minibuffer if it is the only
screen still mapped. Calls on-event::handler first."
(on-event::handler type value screen)
(if (and (not (or value (screen-list)))
; No normal screens mapped, check if minibuffer is mapped.
(screen-mapped-p (minibuf-screen)))
; If so, iconify minibuffer.
(iconify-screen (minibuf-screen))))
; Install the above event handler.
(push-event 'map 'auto-iconify-event-handler)
;;;
;;; minbuf.el
;;;
;;; make the minibuffer screen stay attached to the bottom
;;; of a particular window. the minibuffer takes on the same
;;; width and font as the screen it's attached to; it's height
;;; is unaltered.
;;;
;;; the function "anchor-minibuffer-to-selected-screen" can be used
;;; interactively to attach the minibuffer to the current screen
;;;
;;; if the variable *minibuffer-sticks-to-selected-screen-p* is
;;; non-null, the minibuffer follows the focus (i.e. it attaches
;;; itself to whichever screen has the input focus).
;;;
;;; this file should be loaded after epoch.el, as it hacks the
;;; event-alist and handle-focus-change
;;;
;;; Original author unknown.
;;; Contributed by Dan L. Pierson, pierson@encore.com
;;; Reworked by Alan Carroll and Chris Love
;;;
(require 'cl)
(defvar *minibuffer-anchor-screen* (current-screen)
"The screen that the minibuffer sticks to.")
(defvar *minibuffer-sticks-to-selected-screen-p* t
"If non-null, causes the minibuffer to follow the input focus.")
(defvar *minibuffer-anchor-inhibit* nil)
(defun handle-move-event (type event screen)
(setq *minibuffer-anchor-screen* (current-screen))
(if *minibuffer-sticks-to-selected-screen-p*
(cond
((eq screen *minibuffer-anchor-screen*)
(move-minibuffer-screen-with-anchor-screen)
(setq *minibuffer-anchor-inhibit* nil)
)
((and (not *minibuffer-anchor-inhibit*)
(eq screen (minibuf-screen)))
(move-minibuffer-screen-with-anchor-screen)
(setq *minibuffer-anchor-inhibit* t)
)
(t (setq *minibuffer-anchor-inhibit* nil)
)))
(on-event::handler type event screen))
(push-event 'move 'handle-move-event)
(defun handle-resize-event (type event screen)
(setq *minibuffer-anchor-screen* (current-screen))
(and *minibuffer-sticks-to-selected-screen-p*
(when
(or
(eq screen *minibuffer-anchor-screen*)
(eq screen (minibuf-screen))
)
(resize-minibuffer-screen-with-anchor-screen)))
(on-event::handler type event screen))
(push-event 'resize 'handle-resize-event)
;;; -----------------------------------------------------------------
(defvar minibuf-delta-x 0)
(defvar minibuf-delta-y 0)
(defun backing-screen-info (&optional win)
"\
Return the screen information for the backing X-window of the given screen"
(setq win (or win (current-screen)))
(let ((parent nil)
(root nil)
(wlist nil))
(while (and (setq wlist (query-tree win))
(setq parent (cadr wlist))
(setq root (car wlist))
(not (equal root parent)))
(setq win parent))
(and parent (screen-information win))))
(defun wm-location-delta (&optional win)
"Given optional SCREEN-OR-XWIN, this function returns a list of (DX DY)
for how much the window manager changes move-screen requests."
(setq win (or win (current-screen)))
(let* ((start-info (screen-information win)) ; initial attributes
; of the screen
(start-x (car start-info)) ; initial x coord of screen
(start-y (cadr start-info)) ; initial y coord of screen
(start-map-state (nth 5 start-info)) ; t if screen is
; not iconified
dx dy ; delta values
info ; attributes of screen after move
final-x final-y ; coords of the screen after moving it
(loop-count 0))
; Un-iconify the screen if necessary.
(if (not start-map-state)
(map-screen win))
; Move the given screen to a fixed location
(move-screen 0 0 win)
; Now, the window manager may not be able to move the
; screen immediately, so we'll loop for a while until
; we detect a change in position. It's just possible that
; the screen was originally at 0 0, so we wait a maximum
; of 20 seconds in this case.
(while
(progn
; Check new screen location
(setq info (screen-information win))
(setq final-x (car info))
(setq final-y (cadr info))
; If screen hasn't moved, and we've waited for
; less than 20 seconds so far, then wait for 1 second
; and try again
(if (and (= final-x start-x) (= final-y start-y) (< loop-count 20))
(progn
(sleep-for 1)
(setq loop-count (+ loop-count 1))
t)
nil)))
; Now, figure out the delta values
(setq dx (- final-x))
(setq dy (- final-y))
; Put the screen back where we found it, using newly
; calculated delta values to correct for WM positioning
; fudge-factor.
(move-screen (+ start-x dx) (+ start-y dy) win)
; Re-iconify the screen if it was iconified initially
(if (not start-map-state)
(unmap-screen win))
(list dx dy)
))
;;; Allright, calculate the actual deltas
;;; Things to account for -
;;; 1. Size of WM borders
;;; 2. Size of X window borders
;;; 3. WM fudging of move requests
;;;
(let
(
(minfo (screen-information (minibuf-screen)))
(mbinfo (backing-screen-info (minibuf-screen)))
(einfo (screen-information))
(ebinfo (backing-screen-info))
(wm-fudge (wm-location-delta (minibuf-screen)))
)
(setq minibuf-delta-x
(+
; for now, just line up the edge of the edit screen
; with the edge of the minibuffer screen, so only account
; for the WM fudge factor.
(car wm-fudge)
))
(setq minibuf-delta-y
(+
(cadr wm-fudge)
;; size of the minibuffer title
(- (nth 1 minfo) (nth 1 mbinfo))
;; the size of the bottom bar on the edit screen
(- (+ (nth 1 ebinfo) (nth 3 ebinfo))
(+ (nth 1 einfo) (nth 3 einfo)))
(nth 4 mbinfo) ; borders
(nth 4 ebinfo)
)))
;;; -----------------------------------------------------------------
(defun move-minibuffer-screen-with-anchor-screen ()
(let* ((mbscreen (minibuf-screen))
(info (screen-information *minibuffer-anchor-screen*))
)
(move-screen
(+ (car info) minibuf-delta-x)
(+ (nth 1 info) (nth 3 info) minibuf-delta-y)
mbscreen)
))
(defun resize-minibuffer-screen-with-anchor-screen ()
(let* ((char-width (epoch::screen-width *minibuffer-anchor-screen*))
(mbscreen (minibuf-screen))
(font (car (font nil *minibuffer-anchor-screen*)))
(mbfont (car (font nil mbscreen)))
)
(move-minibuffer-screen-with-anchor-screen)
; make the minibuffer have the same font as the screen
; it's attached to.
(when (and font mbfont (not (string= font mbfont)))
(font font mbscreen))
(change-screen-size char-width 0 mbscreen)
))
(defun anchor-minibuffer-to-selected-screen ()
"Make the minibuffer stick to the current screen."
(interactive)
(setq *minibuffer-anchor-screen* (current-screen))
(and *minibuffer-sticks-to-selected-screen-p*
(resize-minibuffer-screen-with-anchor-screen)))
(prepend-unique-hook
'*select-screen-hook* 'anchor-minibuffer-to-selected-screen)
(and *minibuffer-sticks-to-selected-screen-p*
(resize-minibuffer-screen-with-anchor-screen))
)) ; end: running-epoch test
;; end of minibuf.el
;*****************************************************************************
;
; Filename: epoch-running.el
;
; Description: Sets a flag to indicate if user is running Epoch or Emacs.
;
; This version posted by Ken Wood <kwood@austek.oz.au>.
;
;*****************************************************************************
(provide 'epoch-running)
;; epoch-version is an epoch-defined variable whose value is not nil.
;; By looking at it you can tell if you are running epoch. But! on
;; the other hand, it doesnt exist in a regular gnuemacs, so defvar-ing
;; it to nil here guarantees it will be nil in gnuemacs and non-nil
;; in epoch
(defvar epoch::version nil) ;; in epoch this will not set!
;; running-epoch is a better name for the variable that tells us is we are
;; in epoch or not
(setq running-epoch epoch::version)
;; end of epoch-running.el
Technical Details
Message-ID:
<9110020111.AA02266@angels.adl.austek>Path:
arc1-ca.pugleaf.net!gmdzi!unido!mcsun!uunet!cis.ohio-state.edu!adl.AUstek.oz.AU!kwoodReferences:
<9110011825.AA06457@banach.math.ep.utexas.edu>Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: fc7ee,ec50ad882599778c,start X-Google-Attributes: gidfc7ee,public X-Google-ArrivalTime: 1991-10-01 23:40:43 PST Path: arc1-ca.pugleaf.net!gmdzi!unido!mcsun!uunet!cis.ohio-state.edu!adl.AUstek.oz.AU!kwood From: kwood@adl.AUstek.oz.AU (Ken Wood) Newsgroups: gnu.epoch.misc Subject: intermittent problem with minibuffer Message-ID: <9110020111.AA02266@angels.adl.austek> Date: 2 Oct 91 16:41:38 GMT References: <9110011825.AA06457@banach.math.ep.utexas.edu> Sender: daemon@cis.ohio-state.edu Distribution: gnu Organization: GNUs Not Usenet Lines: 310