1 ;;; xwem-special.el --- Special Emacs frames handling.
3 ;; Copyright (C) 2003-2005 by XWEM Org.
5 ;; Author: Zajcev Evgeny <zevlg@yandex.ru>
6 ;; Created: Thu Dec 4 15:01:21 MSK 2003
7 ;; Keywords: xwem, xlib
8 ;; X-CVS: $Id: xwem-special.el,v 1.11 2005-04-04 19:54:16 lg Exp $
10 ;; This file is part of XWEM.
12 ;; XWEM is free software; you can redistribute it and/or modify it
13 ;; under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 2, or (at your option)
17 ;; XWEM is distributed in the hope that it will be useful, but WITHOUT
18 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
20 ;; License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with XEmacs; see the file COPYING. If not, write to the Free
24 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 ;;; Synched up with: Not in FSF
31 ;; Special emacs uses by XWEM to accomplish various tasks. Such as
32 ;; help system, and others. Special frames are handled in different
33 ;; way, but remain normal XWEM client. Usually special frame used by
34 ;; XWEM has dedicated window, i.e. removing window will remove frame,
35 ;; but optionally you can create normal frames. Take a look at
36 ;; documentation for `xwem-special-popup-frame' function.
38 ;; XEmacs has a bug, when window is dedicated to buffer, after buffer
39 ;; deletion window will be deleted as well and if it is only window in
40 ;; frame frame will be also deleted. But if there is no visible
41 ;; frames at the moment `replace-buffer-in-windows' will skip value of
42 ;; `allow-deletion-of-last-visible-frame' and does not deletes frame.
43 ;; So we can't use dedicated windows, because almost everywhere we
44 ;; will get such sitiation, for example runnig H-h H-h when there is
45 ;; no active emacs frame. `xwem-special-popup-frame' will use
46 ;; dedicated frame to display buffer and here is advice for
49 ;; (defadvice kill-buffer (before delete-dedicated-frame activate)
50 ;; "Work around dedicated frame problem."
51 ;; (let ((frame (buffer-dedicated-frame (ad-get-arg 0))))
52 ;; (when (framep frame)
53 ;; (delete-frame frame))))
62 (require 'xwem-manage)
65 (defvar x-emacs-application-class nil))
68 (defgroup xwem-special nil
69 "Group to customize special emacs frames handling."
70 :prefix "xwem-special-"
73 (defcustom xwem-special-frame-name "xwem-special-frame"
74 "*Name for special emacs frames"
78 (defcustom xwem-special-model-function 'xwem-special-at-center
79 "*Special frame handiling model function."
80 :type '(choice (const :tag "At Center" xwem-special-at-center)
81 (const :tag "At Pointer" xwem-special-at-pointer)
82 (function :tag "User function"))
85 (defcustom xwem-special-border-width 2
86 "Border width of special Emacs frames."
90 (defcustom xwem-special-border-color "red4"
91 "Border color of special Emacs frames."
95 (defcustom xwem-special-auto-hide nil
96 "*Non-nill mean that special frames will autohide when loses focus or visibility."
100 (defcustom xwem-special-hide-method 'XDestroyWindow
101 "*Method used to hide special frames.
102 One of 'XDestroyWindow or 'XUnmapWindow.
103 If 'XUnmapWindow than special frames will not be removed from clients
104 list, so it will be possible to access them after hidding."
106 :group 'xwem-special)
108 (defcustom xwem-special-menubar-visible-p nil
109 "Non-nil for menubar in special Emacs frames."
111 :group 'xwem-special)
113 (defcustom xwem-special-toolbar-visible-p nil
114 "Non-nil for toolbar in special Emacs frames."
116 :group 'xwem-special)
118 (defcustom xwem-special-display-buffer-names nil
119 "*List of buffer names to display using special frame."
120 :type '(repeat string)
121 :group 'xwem-special)
123 (defcustom xwem-special-display-buffer-strategy 'half
124 "*Strategy to use when display one of `xwem-special-display-buffer-names' buffer in special frame."
125 :type '(choice (const :tag "Half screen" half)
126 (const :tag "Center" centre))
127 :group 'xwem-special)
129 (defcustom xwem-special-default-strategy 'half
130 "*Default strategy to use when displaying special Emacs frame."
131 :type '(choice (const :tag "Half screen" half)
132 (const :tag "Fill current client" fill)
133 (const :tag "Center" centre))
134 :group 'xwem-special)
136 (defcustom xwem-special-fill-border-width 10
137 "*Pixels border when using `fill' strategy."
139 :group 'xwem-special)
141 ;;; Internal variables
143 (defvar xwem-special-frames-list nil "List of special frames.")
146 (defun xwem-special-frame-init ()
147 "Initialize stuff to work with special emacs frames."
148 (setq special-display-frame-plist
149 (plist-put special-display-frame-plist 'minibuffer nil))
150 (setq special-display-frame-plist
151 (plist-put special-display-frame-plist 'name xwem-special-frame-name))
152 (setq special-display-frame-plist
153 (plist-put special-display-frame-plist 'border-width xwem-special-border-width))
154 (setq special-display-frame-plist
155 (plist-put special-display-frame-plist 'border-color xwem-special-border-color))
156 (setq special-display-frame-plist
157 (plist-put special-display-frame-plist 'menubar-visible-p xwem-special-menubar-visible-p))
158 (setq special-display-frame-plist
159 (plist-put special-display-frame-plist 'default-toolbar-visible-p xwem-special-toolbar-visible-p))
160 (setq special-display-frame-plist
161 (plist-put special-display-frame-plist 'wait-for-wm nil))
166 ;; - setting initially-unmapped to t causes double MapRequest
168 (defun xwem-special-make-frame ()
170 NOTE: frame is initially unmapped, use `make-frame-visible' to map it."
171 (let ((props special-display-frame-plist))
172 (setq props (plist-put props 'name xwem-special-frame-name))
173 ; (setq props (plist-put props 'initially-unmapped t))
175 (make-frame props (default-x-device))))
177 (defun xwem-special-display-popup-frame (buffer &optional args)
178 "Popup special frame with BUFFER."
179 (frame-selected-window (xwem-special-popup-frame buffer)))
182 (defun xwem-special-popup-frame (buf &optional nondedicated-p args)
183 "As `special-display-popup-frame', but popup frame for sure.
184 When NONDEDICATED-P is non-nil then frame will not be dedicated."
185 (let ((sfr (xwem-special-make-frame)))
186 (set-window-buffer (frame-selected-window sfr) buf)
187 (unless nondedicated-p
188 (set-window-dedicated-p (frame-selected-window sfr) t))
190 (set-buffer-dedicated-frame buf sfr) ; XXX
192 ;; Put special frame property, to know that this frame forced to
194 (set-frame-property sfr 'xwem-forced-special t)
196 (make-frame-visible sfr)
202 (defun xwem-special-p (cl)
203 "Return non-nil if CL is special client."
204 (eq (xwem-cl-manage-type cl) 'emacs-special))
206 (defun xwem-special-select (cl)
207 "Select special client CL."
208 (xwem-client-set-property cl 'skip-deselect t)
209 (xwem-client-set-property cl 'override-skip-deselect t)
211 (xwem-select-client cl))
214 (defun xwem-special-revert-focus (&optional spec-cl)
215 "Try to predict who has focus, before SPEC-CL and revert to it."
216 (xwem-client-set-property spec-cl 'skip-deselect nil)
217 (xwem-client-set-property spec-cl 'override-skip-deselect nil)
219 (xwem-select-last-or-other-client spec-cl))
222 (defun xwem-special-evhandler (xdpy win xev)
223 "Event handler for speical emacs frames."
224 (xwem-debug 'xwem-misc "XWEM-SPECIAL-EVHANDLER: ev = %S, winid = %S"
225 '(X-Event-name xev) '(aref win 2))
228 ((:X-FocusOut :X-VisibilityNotify)
229 (when xwem-special-auto-hide
230 (xwem-deactivate (xwem-xwin-cl win))))
232 ((:X-DestroyNotify :X-UnmapNotify)
234 (X-Win-EventHandler-rem win 'xwem-special-evhandler)
235 (xwem-special-revert-focus (xwem-xwin-cl win))))
238 ;;;; ---- Manage methods for special frame ----
240 (defun xwem-manage-emacs-special (cl)
241 "Manage method for special emacs frame client CL."
242 (let* ((frame (xwem-misc-find-emacs-frame cl))
243 (bname (buffer-name (window-buffer (frame-selected-window frame))))
244 (win (xwem-cl-xwin cl))
245 (par-win (xwem-rootwin))
248 (cond ((member bname xwem-special-display-buffer-names)
249 (setq strategy xwem-special-display-buffer-strategy))
250 (t (setq strategy xwem-special-default-strategy)))
252 (cond ((eq strategy 'half)
256 :y (/ (X-Geom-y (xwem-minib-xgeom xwem-minibuffer)) 2)
257 :width (X-Geom-width-with-borders
258 (xwem-minib-cl-xgeom xwem-minibuffer))
259 :height (/ (X-Geom-y (xwem-minib-xgeom xwem-minibuffer)) 2)
262 ((and (eq strategy 'fill)
263 (xwem-cl-alive-p (xwem-cl-selected))
264 (not (eq cl (xwem-cl-selected))))
265 (setq fgeom (copy-X-Geom (xwem-cl-xgeom (xwem-cl-selected))))
266 (setf (X-Geom-x fgeom) 0)
267 (setf (X-Geom-y fgeom) 0)
268 (setf (X-Geom-border-width fgeom) xwem-special-fill-border-width)
269 (setq par-win (xwem-cl-xwin (xwem-cl-selected)))))
271 ;; Operate on unmapped window
272 (XSelectInput (xwem-dpy) win 0)
275 (xwem-cl-correct-size-for-size cl fgeom))
276 (xwem-cl-apply-xgeom-1 cl)
278 (XReparentWindow (xwem-dpy) win par-win
279 (X-Geom-x (xwem-cl-xgeom cl))
280 (X-Geom-y (xwem-cl-xgeom cl)))
282 ;; Setup events handler for special frames
283 (XSelectInput (xwem-dpy) win
284 (Xmask-or XM-FocusChange
285 XM-VisibilityChange XM-StructureNotify))
286 (X-Win-EventHandler-add-new win 'xwem-special-evhandler)
289 (xwem-special-select cl)))
291 (define-xwem-deffered xwem-special-apply-state (cl)
292 "Apply CL's state to life."
293 (cond ((eq (xwem-cl-state cl) 'active)
294 (xwem-misc-raise-xwin (xwem-cl-xwin cl))
295 (XMapWindow (xwem-dpy) (xwem-cl-xwin cl)))
297 ((eq (xwem-cl-state cl) '(inactive iconify))
298 (XUnmapWindow (xwem-dpy) (xwem-cl-xwin cl))
299 (xwem-special-revert-focus cl))))
301 (defun xwem-activate-emacs-special (cl &optional type)
302 "Activate method for special emacs frame client CL."
303 (xwem-special-apply-state cl))
305 (defun xwem-deactivate-emacs-special (cl &optional type)
306 "Demanage specal xwem client CL."
307 (cond ((eq type 'deactivate)
308 (xwem-special-apply-state cl))))
310 (defun xwem-iconify-emacs-special (cl)
311 "Iconify handler for special frame."
312 (xwem-special-apply-state cl))
315 (provide 'xwem-special)
317 ;;;; On-load actions:
318 ;; Define application
319 (add-to-list 'xwem-applications-alist
320 `("xemacs-xwem-special"
321 (and (class-name ,(concat "^" x-emacs-application-class "$"))
322 (class-inst ,(concat "^" xwem-special-frame-name "$")))))
325 (define-xwem-manage-model emacs-special
326 "Managing model for special Emacs frames."
327 :match-spec '(application "xemacs-xwem-special")
329 :manage-method 'xwem-manage-emacs-special
330 :activate-method 'xwem-activate-emacs-special
331 :deactivate-method 'xwem-deactivate-emacs-special
332 :iconify-method 'xwem-iconify-emacs-special)
334 ;; - Before init hook
336 (xwem-special-frame-init)
337 (add-hook 'xwem-before-init-hook 'xwem-special-frame-init))
339 ;;; xwem-special.el ends here