;;; -*- Mode: Common-Lisp; Package: User; Base: 10.; Patch-File: T -*-

;;; Reason: Fixes various problems with passive grabs.

;;;                           RESTRICTED RIGHTS LEGEND
;;;
;;; Use, duplication, or disclosure by the Government is subject to
;;; restrictions as set forth in subdivision (c)(1)(ii) of the Rights in
;;; Technical Data and Computer Software clause at 52.227-7013.
;;;
;;;   TEXAS INSTRUMENTS INCORPORATED      
;;;   P.O. BOX 2909, M/S 2151             
;;;   AUSTIN, TEXAS 78769                 
;;;
;;; Copyright (C) 1989 Texas Instruments Incorporated.
;;; All rights reserved.

;;; Written 06/01/90 15:55:04 by HAGY,
;;; while running on Zwingli from band LOD2
;;; With SYSTEM 6.25, VIRTUAL-MEMORY 6.2, EH 6.5, MAKE-SYSTEM 6.2, MICRONET 6.0, LOCAL-FILE 6.1,
;;;  BASIC-PATHNAME 6.2, NETWORK-SUPPORT-COLD 6.2, BASIC-NAMESPACE 6.7, NETWORK-NAMESPACE 6.0,
;;;  DISK-IO 6.1, DISK-LABEL 6.0, BASIC-FILE 6.6, MAC-PATHNAME 6.0, NETWORK-PATHNAME 6.0,
;;;  COMPILER 6.14, TV 6.19, DATALINK 6.0, CHAOSNET 6.5, GC 6.3, MEMORY-AUX 6.0, NVRAM 6.2,
;;;  SYSLOG 6.2, STREAMER-TAPE 6.5, UCL 6.0, INPUT-EDITOR 6.0, METER 6.1, ZWEI 6.8,
;;;  DEBUG-TOOLS 6.3, NETWORK-SUPPORT 6.0, NETWORK-SERVICE 6.2, DATALINK-DISPLAYS 6.0,
;;;  FONT-EDITOR 6.1, SERIAL 6.0, PRINTER 6.3, MAC-PRINTER-TYPES 6.1, PRINTER-TYPES 6.2,
;;;  IMAGEN 6.1, SUGGESTIONS 6.1, MAIL-DAEMON 6.3, MAIL-READER 6.6, TELNET 6.0, VT100 6.0,
;;;  NAMESPACE-EDITOR 6.4, PROFILE 6.2, VISIDOC 6.5, TI-CLOS 6.26, CLEH 6.5, IP 3.56,
;;;  Experimental CLX 6.11, CLUE 6.104, X11M 6.24, Experimental BUG 11.17, Experimental CLIO 1.0,
;;;   microcode 430, Band Name: REl 6.0 +SLE +CLIO

#!C
; From file GRABS.LISP#> X11M.SERVER; Hotel:
#10R X11#:
(COMPILER-LET ((*PACKAGE* (FIND-PACKAGE "X11"))
                          (SI:*LISP-MODE* :COMMON-LISP)
                          (*READTABLE* SYS:COMMON-LISP-READTABLE)
                          (SI:*READER-SYMBOL-SUBSTITUTIONS* SYS::*COMMON-LISP-SYMBOL-SUBSTITUTIONS*))
  (COMPILER#:PATCH-SOURCE-FILE "SYS: X11M.SERVER; GRABS.#"


(DEFUN GRAB-MATCHES-SECOND (FIRST-GRAB SECOND-GRAB)
  (DECLARE (TYPE GRAB-RECORD FIRST-GRAB SECOND-GRAB)
           (VALUES BOOLEAN))
  (COND ((NEQ (GRAB-RECORD.DEVICE FIRST-GRAB) (GRAB-RECORD.DEVICE SECOND-GRAB))
         NIL)
        ((GRAB-SUPERSEDES-SECOND FIRST-GRAB SECOND-GRAB)
         T)
        ((GRAB-SUPERSEDES-SECOND SECOND-GRAB FIRST-GRAB)
         T)
        ((AND (DETAIL-SUPERSEDES-SECOND
                (GRAB-RECORD.DETAIL SECOND-GRAB)
                (GRAB-RECORD.DETAIL FIRST-GRAB)
                ANY-KEY)
              (DETAIL-SUPERSEDES-SECOND (GRAB-RECORD.MODIFIERS-DETAIL FIRST-GRAB)
                                        (GRAB-RECORD.MODIFIERS-DETAIL SECOND-GRAB)
                                        ANY-MODIFIER-MASK))
         T)
        ((AND (DETAIL-SUPERSEDES-SECOND (GRAB-RECORD.DETAIL FIRST-GRAB)
                                        (GRAB-RECORD.DETAIL SECOND-GRAB)
                                        ANY-KEY)
              (DETAIL-SUPERSEDES-SECOND (GRAB-RECORD.MODIFIERS-DETAIL SECOND-GRAB)
                                        (GRAB-RECORD.MODIFIERS-DETAIL FIRST-GRAB)
                                        ANY-MODIFIER-MASK))
         T)
        (T
         NIL)))
))

#!C
; From file EVENTS.LISP#> X11M.SERVER; Hotel:
#10R X11#:
(COMPILER-LET ((*PACKAGE* (FIND-PACKAGE "X11"))
                          (SI:*LISP-MODE* :COMMON-LISP)
                          (*READTABLE* SYS:COMMON-LISP-READTABLE)
                          (SI:*READER-SYMBOL-SUBSTITUTIONS* SYS::*COMMON-LISP-SYMBOL-SUBSTITUTIONS*))
  (COMPILER#:PATCH-SOURCE-FILE "SYS: X11M.SERVER; EVENTS.#"


(DEFUN CHECK-PASSIVE-GRABS-ON-WINDOW (WINDOW DEVICE EVENT IS-KEYBOARD)
  (DECLARE (TYPE WINDOW WINDOW)
           (TYPE DEVICE DEVICE)
           (TYPE EVENT-RECORD EVENT)
           (TYPE BOOLEAN IS-KEYBOARD)
           (VALUES BOOLEAN))
  (EVENT-TRACE-ENTERING "CHECK-PASSIVE-GRABS-ON-WINDOW")
  (LET ((TEMPORARY-GRAB (MAKE-GRAB-RECORD
                          :WINDOW WINDOW
                          :DEVICE DEVICE
                          :MODIFIERS-DETAIL (MAKE-DETAIL-REC
                                              :EXACT (LOGAND
                                                       (X-EVENT-KEY-BUTTON-POINTER.STATE EVENT)
                                                       ALL-MODIFIERS-MASK))
                          :DETAIL (make-detail-rec
				    :EXACT (X-EVENT-KEY-BUTTON-POINTER.DETAIL EVENT)
				    :mask 0)
			  )))
    (PROG1
      (LOOP FOR GRAB FIRST (WINDOW.PASSIVE-GRABS WINDOW) THEN (GRAB-RECORD.NEXT GRAB)
            WHILE GRAB
            DO (WHEN (GRAB-MATCHES-SECOND TEMPORARY-GRAB GRAB)
                 (IF IS-KEYBOARD
                     (ACTIVATE-KEYBOARD-GRAB DEVICE GRAB CURRENT-TIME T)
                     ;;ELSE
                     (ACTIVATE-POINTER-GRAB DEVICE GRAB CURRENT-TIME T))
                 (FIX-UP-EVENT-FROM-WINDOW EVENT (GRAB-RECORD.WINDOW GRAB) NIL T)
                 (TRY-CLIENT-EVENTS (GRAB-RECORD.CLIENT GRAB) EVENT 1 (GRAB-RECORD.EVENT-MASK GRAB)
                                    (AREF FILTERS (EVENT-U.TYPE EVENT)) GRAB)
                 (WHEN (= (SYNC.STATE (DEVICE.SYNC DEVICE)) FROZEN-NO-EVENT)
                   (SETF (SYNC.EVENT (DEVICE.SYNC DEVICE)) EVENT)
                   (SETF (SYNC.STATE (DEVICE.SYNC DEVICE)) FROZEN-WITH-EVENT))
                 (RETURN T))
            FINALLY (RETURN NIL))
      (EVENT-TRACE-LEAVING "CHECK-PASSIVE-GRABS-ON-WINDOW"))))
))

#!C
; From file EVENTS.LISP#> X11M.SERVER; Hotel:
#10R X11#:
(COMPILER-LET ((*PACKAGE* (FIND-PACKAGE "X11"))
                          (SI:*LISP-MODE* :COMMON-LISP)
                          (*READTABLE* SYS:COMMON-LISP-READTABLE)
                          (SI:*READER-SYMBOL-SUBSTITUTIONS* SYS::*COMMON-LISP-SYMBOL-SUBSTITUTIONS*))
  (COMPILER#:PATCH-SOURCE-FILE "SYS: X11M.SERVER; EVENTS.#"


(DEFUN ALLOW-SOME (CLIENT TIME THIS-DEV OTHER-DEV NEW-STATE)
  (DECLARE (TYPE STATE CLIENT)
           (TYPE TIME-STAMP TIME)
           (TYPE DEVICE THIS-DEV OTHER-DEV)
           (TYPE INTEGER NEW-STATE))
  (EVENT-TRACE-ENTERING "ALLOW-SOME")
  (LET ((THIS-GRABBED (AND (DEVICE.GRAB THIS-DEV)
                           (EQ (GRAB-RECORD.CLIENT (DEVICE.GRAB THIS-DEV)) CLIENT)))
        (OTHER-GRABBED (AND (DEVICE.GRAB OTHER-DEV)
                            (EQ (GRAB-RECORD.CLIENT (DEVICE.GRAB OTHER-DEV)) CLIENT)))
        GRAB-TIME)
    (DECLARE (TYPE BOOLEAN THIS-GRABBED )
             (TYPE (OR NULL TIME-STAMP) GRAB-TIME))
    (WHEN (OR (AND THIS-GRABBED
                   (>= (SYNC.STATE (DEVICE.SYNC THIS-DEV)) FROZEN))
              (AND OTHER-GRABBED (SYNC.OTHER (DEVICE.SYNC THIS-DEV))))
      (IF (AND THIS-GRABBED
               (OR (NULL OTHER-GRABBED)
                   (MINUSP (COMPARE-TIME-STAMPS (DEVICE.GRAB-TIME OTHER-DEV)
                                                (DEVICE.GRAB-TIME THIS-DEV)))))
          (SETQ GRAB-TIME (DEVICE.GRAB-TIME THIS-DEV))
          ;;ELSE
          (SETQ GRAB-TIME (DEVICE.GRAB-TIME OTHER-DEV)))
      (IF (OR (PLUSP (COMPARE-TIME-STAMPS TIME CURRENT-TIME))
              (MINUSP (COMPARE-TIME-STAMPS TIME GRAB-TIME)))
          NIL
          ;;ELSE
          (SELECTOR NEW-STATE eql
            (THAWED                    ; Async
             (WHEN THIS-GRABBED
               (SETF (SYNC.STATE (DEVICE.SYNC THIS-DEV)) THAWED))
             (WHEN OTHER-GRABBED
               (SETF (SYNC.OTHER (DEVICE.SYNC THIS-DEV)) NIL))
             (COMPUTE-FREEZES THIS-DEV OTHER-DEV))

            (FREEZE-NEXT-EVENT         ; Sync
             (WHEN THIS-GRABBED
               (SETF (SYNC.STATE (DEVICE.SYNC THIS-DEV)) FREEZE-NEXT-EVENT)
               (WHEN OTHER-GRABBED
                 (SETF (SYNC.OTHER (DEVICE.SYNC THIS-DEV)) NIL))
               (COMPUTE-FREEZES THIS-DEV OTHER-DEV)))

            (THAWED-BOTH               ; AsyncBoth
             (WHEN (OR (AND OTHER-GRABBED
                            (>= (SYNC.STATE (DEVICE.SYNC OTHER-DEV)) FROZEN))
                       (AND THIS-GRABBED
                            (SYNC.OTHER (DEVICE.SYNC OTHER-DEV))))
               (WHEN THIS-GRABBED
                 (SETF (SYNC.STATE (DEVICE.SYNC THIS-DEV)) THAWED)
                 (SETF (SYNC.OTHER (DEVICE.SYNC OTHER-DEV)) NIL))
               (WHEN OTHER-GRABBED
                 (SETF (SYNC.STATE (DEVICE.SYNC OTHER-DEV)) THAWED)
                 (SETF (SYNC.OTHER (DEVICE.SYNC THIS-DEV)) NIL))
               (COMPUTE-FREEZES THIS-DEV OTHER-DEV)))

            (FREEZE-BOTH-NEXT-EVENT   ; SyncBoth
             (WHEN (OR (AND OTHER-GRABBED
                            (>= (SYNC.STATE (DEVICE.SYNC OTHER-DEV)) FROZEN))
                       (AND THIS-GRABBED
                            (SYNC.OTHER (DEVICE.SYNC OTHER-DEV))))
               (WHEN THIS-GRABBED
                 (SETF (SYNC.STATE (DEVICE.SYNC THIS-DEV)) FREEZE-BOTH-NEXT-EVENT)
                 (SETF (SYNC.OTHER (DEVICE.SYNC OTHER-DEV)) NIL))
               (WHEN OTHER-GRABBED
                 (SETF (SYNC.STATE (DEVICE.SYNC OTHER-DEV)) FREEZE-BOTH-NEXT-EVENT)
                 (SETF (SYNC.OTHER (DEVICE.SYNC THIS-DEV)) NIL)
                 (COMPUTE-FREEZES THIS-DEV OTHER-DEV))))

            (NOT-GRABBED               ; Replay
             (WHEN (AND THIS-GRABBED
                        (= (SYNC.STATE (DEVICE.SYNC THIS-DEV)) FROZEN-WITH-EVENT))
               (SETF (SYNC-EVENTS.REPLAY-DEVICE SYNC-EVENTS) THIS-DEV)
               (SETF (SYNC-EVENTS.REPLAY-WINDOW SYNC-EVENTS) (GRAB-RECORD.WINDOW (DEVICE.GRAB
                                                                                   THIS-DEV)))
               (IF (EQ THIS-DEV (INPUT-INFO.POINTER INPUT-INFO))
                   (DEACTIVATE-POINTER-GRAB THIS-DEV)
                   ;;ELSE
                   (DEACTIVATE-KEYBOARD-GRAB THIS-DEV))
               (SETF (SYNC-EVENTS.REPLAY-DEVICE SYNC-EVENTS) NIL)))))))
  (EVENT-TRACE-LEAVING "ALLOW-SOME"))
))

#!C
; From file EVENTS.LISP#> X11M.SERVER; Hotel:
#10R X11#:
(COMPILER-LET ((*PACKAGE* (FIND-PACKAGE "X11"))
                          (SI:*LISP-MODE* :COMMON-LISP)
                          (*READTABLE* SYS:COMMON-LISP-READTABLE)
                          (SI:*READER-SYMBOL-SUBSTITUTIONS* SYS::*COMMON-LISP-SYMBOL-SUBSTITUTIONS*))
  (COMPILER#:PATCH-SOURCE-FILE "SYS: X11M.SERVER; EVENTS.#"


(DEFUN COMPUTE-FREEZES (DEV1 DEV2)
  (DECLARE (TYPE DEVICE DEV1 DEV2))
  (EVENT-TRACE-ENTERING "COMPUTE-FREEZES")
  (LET ((REPLAY-DEV (SYNC-EVENTS.REPLAY-DEVICE SYNC-EVENTS))
        WINDOW
        IS-KEYBOARD
        EVENT)
    (SETF (SYNC.FROZEN (DEVICE.SYNC DEV1)) (IF (OR (SYNC.OTHER (DEVICE.SYNC DEV1))
                                                   (>= (SYNC.STATE (DEVICE.SYNC DEV1)) FROZEN))
                                               T NIL))
    (SETF (SYNC.FROZEN (DEVICE.SYNC DEV2)) (IF (OR (SYNC.OTHER (DEVICE.SYNC DEV2))
                                                   (>= (SYNC.STATE (DEVICE.SYNC DEV2)) FROZEN))
                                               T NIL))
    (WHEN (NULL (SYNC-EVENTS.PLAYING-EVENTS SYNC-EVENTS))
      (SETF (SYNC-EVENTS.PLAYING-EVENTS SYNC-EVENTS) T)
      (WHEN REPLAY-DEV
        (block PLAYMORE
          (SETQ IS-KEYBOARD (EQ REPLAY-DEV (INPUT-INFO.KEYBOARD INPUT-INFO)))
          (SETQ EVENT (SYNC.EVENT (DEVICE.SYNC REPLAY-DEV)))
          (SETF (SYNC-EVENTS.REPLAY-DEVICE SYNC-EVENTS) NIL)
          (SETQ WINDOW (XY-TO-WINDOW (X-EVENT-KEY-BUTTON-POINTER.ROOT-X EVENT)
                                     (X-EVENT-KEY-BUTTON-POINTER.ROOT-Y EVENT)))
          (LOOP FOR INDEX FROM 0 BELOW SPRITE-TRACE-GOOD
                WHEN (EQ (SYNC-EVENTS.REPLAY-WINDOW SYNC-EVENTS)  (AREF SPRITE-TRACE INDEX))
                DO (PROGN
                     (WHEN (NULL (CHECK-DEVICE-GRABS REPLAY-DEV EVENT (1+ INDEX) IS-KEYBOARD))
                       (IF IS-KEYBOARD
                           (NORMAL-KEYBOARD-EVENT REPLAY-DEV EVENT WINDOW)
                           ;;ELSE
                           (DELIVER-DEVICE-EVENTS WINDOW EVENT NIL NIL)))
                     (return-from PLAYMORE NIL)))
          ;; Must not still be in the same stack.
          (IF IS-KEYBOARD
              (NORMAL-KEYBOARD-EVENT REPLAY-DEV EVENT WINDOW)
              ;;ELSE
              (DELIVER-DEVICE-EVENTS WINDOW EVENT NIL NIL))))
      (WHEN (OR (NOT (SYNC.FROZEN (DEVICE.SYNC DEV1)))
                (NOT (SYNC.FROZEN (DEVICE.SYNC DEV2))))
        (PLAY-RELEASED-EVENTS))
      (SETF (SYNC-EVENTS.PLAYING-EVENTS SYNC-EVENTS) NIL)))
  (EVENT-TRACE-LEAVING "COMPUTE-FREEZES"))
))
