;;; xwem-main.el --- Main part of xwem.

;; Copyright (C) 2003 by Free Software Foundation, Inc.

;; Author: Zajcev Evgeny <zevlg@yandex.ru>
;; Created: 21 Mar 2003
;; Keywords: xlib, xwem
;; X-CVS: $Id: xwem-main.el,v 1.7 2004/05/14 12:36:54 lg Exp $

;; This file is part of XWEM.

;; XWEM is free software; you can redistribute it and/or modify it
;; under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.

;; XWEM is distributed in the hope that it will be useful, but WITHOUT
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
;; License for more details.

;; You should have received a copy of the GNU General Public License
;; along with XEmacs; see the file COPYING.  If not, write to the Free
;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
;; 02111-1307, USA.

;;; Synched up with: Not in FSF

;;; Commentary:
;;
;; This main part of XWEM.
;;
;; I strongly recommend you to raise max-lisp-eval-depth value to say
;; 5000.
;; 	(setq max-lisp-eval-depth 5000)
;;
;; Try to avoid to use such evil thing as `mouse-avoidance-mode', but
;; if you really want it, than set it to either 'banish or 'jump.
;;
;; If you want develop some xwem addons or take in touch with xwem, it
;; will be usefull to change `find-function-regexp', because xwem uses
;; its own syntax to define interactive commands.

;;     (setq find-function-regexp
;;    	     (concat "^\\s-*(\\(def[^cgvW]\\w+\\*?"
;;    		  "\\|define-function"
;;    		  "\\|define-obsolete-function-alias"
;;    		  "\\|define-compatible-function-alias"
;;    		  "\\|define-derived-mode"
;;    		  "\\|define-xwem-command"
;;    		  "\\)\\s-+%s\\(\\s-\\|$\\)"))

;;; Code:



(eval-when-compile
  (require 'cl))			;last, intersection etc

(eval-when 'load
  (load "xwem-keydefs")
  (run-hooks 'xwem-load-hook))

;;;###autoload
(defconst xwem-version "xwem(xemacs-package):  $Revision: 1.7 $")

(defgroup xwem nil
  "XWEM window manager."
  :prefix "xwem-"
  :group 'applications)

(defgroup xwem-hooks nil
  "Group to customize xwem hooks."
  :prefix "xwem-"
  :group 'xwem)

;;;###autoload
(defcustom xwem-dir (file-name-as-directory
		     (expand-file-name ".xwem" (getenv "HOME")))
  "Directory to store XWEM's files."
  :type 'directory
  :group 'xwem)

;;;###autoload
(defcustom xwem-debug nil
  "*Non-nil mean run xlib and xwem in debugging mode."
  :type 'boolean
  :group 'xwem)

;;;###autoload
(defcustom xwem-commands-inhibit-gc t
  "*Non-nil mean that xwem interactive commands runs without GCing."
  :type 'boolean
  :group 'xwem)

(defcustom xwem-custom-display nil ;"127.0.0.1:2"
  "*Custom display, mostly for debugging purposes."
  :type '(restricted-sexp :match-alternatives (stringp null))
  :group 'xwem)

;;;###autoload
(defcustom xwem-load-hook nil
  "*Hooks to call after xwem was load."
  :type 'hook
  :group 'xwem-hooks)

(defcustom xwem-before-init-wins-hook nil
  "Hooks called before `xwem-init-wins'."
  :type 'hook
  :group 'xwem-hooks)

(defcustom xwem-after-init-wins-hook nil
  "Hooks called after `xwem-init-wins'."
  :type 'hook
  :group 'xwem-hooks)

(defcustom xwem-after-init-hook nil
  "Hooks to be runned after xwem initialisation."
  :type 'hook
  :group 'xwem-hooks)

(defcustom xwem-exit-hook nil
  "Hooks called after xwem exit."
  :type 'hook
  :group 'xwem-hooks)


;;; Variables
;;;###autoload
(defvar xwem-started nil
  "Non-nil when xwem started.
Do not modify!")


;;; Functions
(defun xwem-init-wins ()
  "Manage all mapped X windows."
  (xwem-message 'msg "Initializing X windows ... wait")

  (run-hooks 'xwem-before-init-wins-hook)

  (let ((wins (XQueryTree (xwem-dpy) (xwem-rootwin)))
        cln-wins attrs)
    (setq wins (cdr (cdr (cdr (cdr wins)))))

    (X-Dpy-log (xwem-dpy) "IN xwem-init-wins: wins length = %d\n" '(length wins))
    (while wins
      (X-Dpy-log (xwem-dpy) "XGetWindowAttr BEGIN in xwem-init-wins\n")
      (setq attrs (XGetWindowAttributes (xwem-dpy) (car wins)))
      (X-Dpy-log (xwem-dpy) "XGetWindowAttr END in xwem-init-wins, as=%s\n" 'attrs)

      (when (and (not (X-Attr-override-redirect attrs))
		 (= (X-Attr-mapstate attrs) X-Viewable)
		 (not (X-Win-get-prop (car wins) 'xwem-frame)))
	;; X window visible and not an XWEM frame
        (setq cln-wins (cons (car wins) cln-wins)))

      (setq wins (cdr wins)))
    
    ;; Manage all visible clients
    (X-Dpy-log (xwem-dpy) "IN xwem-init-wins: managing wins length = %d\n" '(length shcfgl))
    (mapc 'xwem-make-client cln-wins)
    )

  (run-hooks 'xwem-after-init-wins-hook)
  )

(defun xwem-after-window-setup ()
  "Function which will be added to `window-setup-hook'.
Called after ~/.emacs file loaded and Emacs X window subsystems
initialized."

  ;; Create XWEM minibuffer
  (xwem-minib-create)

  ;; revert back `menubar-visible-p' specifier
  (set-specifier menubar-visible-p xwem-saved-menubar-visible-p)

  (let ((dfen (or xwem-custom-display (getenv "DISPLAY"))))
    (xwem-init-root
     (if (eq (aref dfen 0) ?\:)
	 (concat "127.0.0.1" dfen)
       dfen)))

  ;; Select input on root window
  (XSelectInput (xwem-dpy) (xwem-rootwin) xwem-root-ev-mask)
  (X-Win-EventHandler-add-new (xwem-rootwin) 'xwem-root-events-handler 100)

  (xwem-init-cursors)
  (xwem-init-faces)
  (xwem-init-events)
  (xwem-kbd-init)
  (xwem-init-frames)
  (xwem-init-win)
  (xwem-init-misc)

  ;; Handle all X clients
  (xwem-init-wins)

  (when xwem-strokes-enabled
    (xwem-strokes-init))

  ;; Initialize xwem system tray
  (when xwem-tray-enabled
    (xwem-tray-startit (xwem-dpy)))

  (setq xwem-started t)

  ;; Now xwem is fully intialized and it is time to run hooks
  (run-hooks 'xwem-after-init-hook)

  (XSync (xwem-dpy))
  (xwem-message 'asis (concat (xwem-logo-string)
			      " succesfully started. Start with `M-x xwem-help RET'."))
  )

(defcustom xwem-use-presetup t
  "*When non-nil, us things that normally should be in xwemrc."
  :type 'boolean
  :group 'xwem)

;;;###autoload
(defun xwem-init ()
  "Initialization of xwem subsystems."
  (require 'xwem-keydefs)               ; load keyboard difinitions

  (setq inhibit-startup-message t)      ; DO NOT REMOVE

  (when xwem-use-presetup
    ;; default presetup
    (setf allow-deletion-of-last-visible-frame t)
    (defadvice kill-buffer (before delete-dedicated-frame activate)
      "Work around dedicated frame problem."
      (let ((frame (buffer-dedicated-frame
                    (get-buffer (or (ad-get-arg 0) (current-buffer))))))
        (when (framep frame)
          (delete-frame frame))))
    (xwem-init-tabber))

  ;; read configuration
  (let ((cfg (expand-file-name "xwemrc.el" xwem-dir)))
    (if (file-exists-p cfg)
	(load cfg)
      (xwem-message 'warn "Configuration file `%s' does not exists" cfg)))

  ;; Initialize various stuff that does not need display
  (xwem-manda-init)

  (add-hook 'window-setup-hook 'xwem-after-window-setup)
  (add-hook 'kill-emacs-hook 'xwem-fini t)
  )

;;;###autoload
(defun xwem-fini ()
  "Fini all subsystems."
  (xwem-kbd-quit)
  (xwem-fini-events)
  (xwem-fini-frames)
  (xwem-fini-clients)
  (when xwem-tray-enabled
    (xwem-tray-fini))
  (xwem-fini-root)

  ;; Finally run exit hooks
  (run-hooks 'xwem-exit-hook))


(provide 'xwem-main)

;;; xwem-main.el ends here
