;;; xwem-events.el --- Events handlers.

;; 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-events.el,v 1.2 2004/05/05 22:43:08 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 file used to work with X events, also includes some events
;; handlers.
;;
;;; Code


(defun xwem-ev-defhnd (xdpy win xev)
  "Default X-Events handler."

  (X-Event-CASE xev
;   (:X-ClientMessage (xwem-ev-clnmsg xdpy win xev))
;   (:X-PropertyNotify (xwem-ev-property xdpy win xev))
   (:X-ConfigureRequest (xwem-ev-reconfig xdpy win xev))
   (:X-MapRequest (xwem-ev-remap xdpy win xev))
   (:X-DestroyNotify (xwem-ev-destroy xdpy win xev))
   (:X-ResizeRequest (xwem-ev-reresize xdpy win xev)))
  )

(defun xwem-ev-reconfig (xdpy win xev)
  "Common ConfigureRequest handler."
  (let* ((win (X-Event-xconfigurerequest-window xev))
	 (cl (X-Win-get-prop win 'xwem-cl))
;	 (clgeom (if (xwem-cl-p cl) (xwem-cl-xgeom cl) nil))
	 (vmask (X-Event-xconfigurerequest-value-mask xev)))

    (X-Dpy-log (xwem-dpy) "XWEM-EVENTS: ConfigureRequest event for win=%s vmask=%s, x=%S, y=%S, width=%S, height=%S\n"
	       '(X-Win-id win) 'vmask '(X-Event-xconfigurerequest-x xev) '(X-Event-xconfigurerequest-y xev)
	       '(X-Event-xconfigurerequest-width xev) '(X-Event-xconfigurerequest-height xev))

    (if (not (xwem-cl-p cl))
	(XConfigureWindow (xwem-dpy) win
			  (make-X-Conf :dpy (X-Win-dpy win)
				       :x (X-Event-xconfigurerequest-x xev)
				       :y (X-Event-xconfigurerequest-y xev)
				       :width (X-Event-xconfigurerequest-width xev)
				       :height (X-Event-xconfigurerequest-height xev)
				       :border-width (X-Event-xconfigurerequest-border-width xev)))

      ;; [else] Client window already in air
      (if (not (= 0 (Xmask-and vmask (Xmask-or X-CWWidth X-CWHeight X-CWBorderWidth))))
          (xwem-manda-refit cl)

        (xwem-cl-send-config cl)))
    nil))

(defun xwem-ev-remap (xdpy win xev)
  "MapRequest handler."
  (X-Dpy-log (xwem-dpy) "XWEM-EVENTS: MapRequest event handled for win=%s\n"
	     '(X-Win-id win))

  (let ((cl (xwem-find-client win)))
    (if (xwem-cl-p cl)
	(xwem-manda-manage cl)
      (xwem-make-client win)))
  nil)

(defun xwem-ev-destroy (xdpy win xev)
  "DestroyNotify handler."
  ;; TODO: - May this stuff should be moved to `xwem-xdestrnot-hooks'?
  (X-Dpy-log (xwem-dpy) "XWEM-EVENTS: DestroyNotify event handled for win=%s, evwin=%S\n"
	     '(X-Win-id win) '(X-Win-id (X-Event-xdestroywindow-event xev)))
  )

(defun xwem-ev-reresize (xdpy win xev)
  "On display XDPY handler ResizeRequest for WIN."
  (X-Dpy-log xdpy "XWEM-EVENTS: ResizeRequest: win=%S, width=%S, height=%S\n"
	     '(X-Win-id (X-Event-xresizerequest-window xev)) '(X-Event-xresizerequest-width xev)
	     '(X-Event-xresizerequest-height xev))
  )

;;; Unusesd events
(defun xwem-ev-focusin (xdpy win xev)
  "Handle FocusIn event."
  (X-Dpy-log (xwem-dpy) "FocusIn event: win=%s mode=%s\n" '(X-Win-id win) '(X-Event-xfocus-mode xev))
  )

(defun xwem-ev-focusout (xdpy win xev)
  "Handle FocusOut event."
  (X-Dpy-log (xwem-dpy) "FocusOut event: win=%s mode=%s\n" '(X-Win-id win) '(X-Event-xfocus-mode xev))
  )

(defun xwem-ev-config (xdpy win xev)
  "ConfigureNotify handler."
  (X-Dpy-log (xwem-dpy) "ConfigureNotify event handled for win=%s\n" '(X-Win-id win))
  nil)

(defun xwem-ev-map (xdpy win xev)
  "MapNotify handler."
  (X-Dpy-log (xwem-dpy) "MapNotify event handled for win=%s\n" '(X-Win-id win))
  nil)

(defun xwem-ev-unmap (xdpy win xev)
  "UnmapNotify handler."
  (X-Dpy-log (xwem-dpy) "UnmapNotify event handled for win=%s\n" '(X-Win-id win))
  nil)

(defun xwem-ev-create (xdpy win xev)
  "CreateNotify handler."
  (X-Dpy-log (xwem-dpy) "CreateNotify event handled for win=%s\n" '(X-Win-id win))
  nil)

(defun xwem-ev-enter (xdpy win xev)
  "EnterNotify handler."
  (X-Dpy-log (xwem-dpy) "EnterNotify event handled for win=%s\n" '(X-Win-id win))
  (let ((cl (xwem-find-client win)))

    (X-Dpy-log (xwem-dpy) "ev-enter: win-id=%f\n" '(X-Win-id win))
    (when cl
      (X-Dpy-log (xwem-dpy) "CL founded\n"))
    ))

(defun xwem-ev-expose (xdpy win xev)
  "ExposureNotify handler."
  (X-Dpy-log (xwem-dpy) "ExposureNotify event handled for win=%s\n" '(X-Win-id win))
  nil)


;;;###autoload
(defun xwem-init-events ()
  "Init part rot events. Installs events dispatcher on `xwem-dpy'."
;  (X-Dpy-EventHandler-add (xwem-dpy) 'xwem-ev-defhnd 100)
  )

;;;###autoload
(defun xwem-fini-events ()
  )

;;;###autoload
(defvar xwem-events-queue nil)

;; Current events execution depth
(defvar xwem-events-depth 0)

;;; Function to call when there data in XDPY, but noone reading it.
;;;###autoload
(defun xwem-parse-message-guess (xdpy)
  "There is data waiting on XDPY, but no-one is reading it.
Try to guess what it is."
  (X-Dpy-p xdpy 'xwem-parse-message-guess)

  (condition-case nil
      ;; If no-one reading now, mean than error or event arrived.
      (when (zerop (X-Dpy-readings xdpy))

        (while (> (length (X-Dpy-message-buffer xdpy)) 0)
          (X-Dpy-eval-error-or-event xdpy))

        (flet ((evmatch (ev)
                        (let ((evtype (X-Event-type ev)))
                          (or (= evtype X-KeyPress)
;                    (= evtype X-KeyRelease)
                              (= evtype X-ButtonPress)
                              (= evtype X-ButtonRelease)
                              (= evtype X-MotionNotify)))))

          (mapc (lambda (ev)
                  (when (evmatch ev)
                    (setq xwem-events-queue (append xwem-events-queue (list ev)))))
                (X-Dpy-evq xdpy))

          ;; Execute normal events
          (when (zerop (X-Dpy-evq-protects xdpy))
            (while (X-Dpy-evq xdpy)
              (let ((ev (X-Dpy-event-dequeue xdpy)))
                (unless (evmatch ev)
                  (X-Dpy-event-dispatch ev))
                ))))

        ;; Execute covertable events
        (when (>= (recursion-depth) xwem-events-depth)
          (incf xwem-events-depth)
          (unwind-protect
              (while xwem-events-queue
                (X-Dpy-event-dispatch (pop xwem-events-queue)))
            (decf xwem-events-depth)))
        )
    (X-Error nil)))

;;;###autoload
(defun xwem-next-event (&optional timeout)
  "Fetch next xwem keyboard or mouse event.
If optional argument PEEK is non-nil than do not remove."
  (incf xwem-events-depth)
  (let (xev done)
    (unwind-protect
        (while (not done)
          (if xwem-events-queue
              (setq xev (pop xwem-events-queue)
                    done t)

            (when (and (not (accept-process-output (X-Dpy-proc (xwem-dpy)) (or timeout 1)))
                       timeout)
              (setq xev nil done t))))
    (decf xwem-events-depth))
    xev))

(provide 'xwem-events)

;;; xwem-events.el ends here
