;;; -*- Mode:Common-Lisp; Package:X11; Base:10; Fonts:(MEDFNB HL12B HL12BI) -*-

;;;			      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
;;;			      AUSTIN, TEXAS 78769
;;;				    MS 2151
;;;
;;; Copyright (C) 1988 Texas Instruments Incorporated. All rights reserved.

#|

This file contains all of the code for handling grabs.
It is closely modeled after the grabs.c file in the server/dix/ directory.
|#

;;; Change history:
;;;
;;;  Date      Author	Description
;;; -------------------------------------------------------------------------------------
;;;  2/13/89    DAN     Patch 1.12; Added FREE-GRABS to get rid of any grabs associated 
;;;			with a dying client.
;;; 10/19/88    LGO     Nuked COPY-DETAIL-MASK1,* DETAIL-BIT-NUMBER-TO-BIT1,* CREATE-DETAIL-MASK
;;;			and DETAIL-BIT-NUMBER-TO-WORD. Simplified DELETE-DETAIL-FROM-MASK.
;;;                     Fixed bug in IS-IN-GRAB-MASK.
;;;  9/12/88    LGO	Fix CREATE-GRAB to create detail-rec's with correct mask
;;;  5/24/88    DAN	Fixed ADD-PASSIVE-GRAB-TO-WINDOW-LIST not to call
;;;			(STATE.ID-BASE (GRAB-RECORD.CLIENT GRAB)) since FAKE-ID-CLIENT wants
;;;			a client.
;;;  2/25/88    TWE	Initial creation.


(DEFUN DELETE-DETAIL-FROM-MASK (DETAIL-MASK DETAIL)
  (DECLARE (TYPE (OR NULL number) DETAIL-MASK)
           (TYPE INTEGER DETAIL)
           (VALUES integer))
  (LOGANDC2 (OR detail-mask 0) (ASH 1 detail)))

(DEFUN ADD-PASSIVE-GRAB-TO-WINDOW-LIST (GRAB)
  (DECLARE (TYPE GRAB-RECORD GRAB))

;  (SETF (GRAB-RECORD.RESOURCE GRAB) (FAKE-CLIENT-ID (STATE.ID-BASE (GRAB-RECORD.CLIENT GRAB))))
  ;1;*FAKE-CLIENT-ID1 calls *STATE.ID-BASE1 on CLIENT.*
  (SETF (GRAB-RECORD.RESOURCE GRAB) (FAKE-CLIENT-ID (GRAB-RECORD.CLIENT GRAB)))
  (SETF (GRAB-RECORD.NEXT GRAB) (WINDOW.PASSIVE-GRABS (GRAB-RECORD.WINDOW GRAB)))
  (SETF (WINDOW.PASSIVE-GRABS (GRAB-RECORD.WINDOW GRAB)) GRAB)
  (ADD-RESOURCE (GRAB-RECORD.RESOURCE GRAB) (GRAB-RECORD.WINDOW GRAB)))



(DEFUN CREATE-GRAB (CLIENT DEVICE WINDOW EVENT-MASK OWNER-EVENTS KEYBOARD-MODE
	POINTER-MODE MODIFIERS KEY)
  (DECLARE (TYPE STATE CLIENT)
           (TYPE DEVICE DEVICE)
           (TYPE WINDOW WINDOW)
           (TYPE INTEGER EVENT-MASK)
           (TYPE BOOLEAN OWNER-EVENTS KEYBOARD-MODE POINTER-MODE)
           (TYPE INTEGER MODIFIERS KEY)
           (VALUES GRAB-RECORD))
  (MAKE-GRAB-RECORD :CLIENT CLIENT
                             :DEVICE DEVICE
                             :WINDOW WINDOW
                             :EVENT-MASK EVENT-MASK
                             :OWNER-EVENTS OWNER-EVENTS
                             :KEYBOARD-MODE KEYBOARD-MODE
                             :POINTER-MODE POINTER-MODE
                             :MODIFIERS-DETAIL (MAKE-DETAIL-REC :EXACT MODIFIERS
                                                                :MASK UNIVERSAL-NONE)
                             :DETAIL (MAKE-DETAIL-REC :EXACT KEY
						      :MASK UNIVERSAL-NONE)))
(DEFUN DELETE-GRAB (GRAB)
  (DECLARE (TYPE GRAB-RECORD GRAB))
  (DECLARE (IGNORE GRAB))
  ;; Not much to do here.  All the C code is doing is freeing up storage.
  )

(DEFUN free-grabs (client root)
  "2Need to free any grabs associated with this client as it is probably being shutdown.*"
  (LET* ((pointer (input-info.pointer  input-info))
         (kbd     (input-info.keyboard input-info))
         (ptr-grab (device.grab pointer))
         (kbd-grab (device.grab kbd)))
    (WHEN ptr-grab
      (IF (EQ (grab-record.client ptr-grab) client)
          (deactivate-pointer-grab pointer)))
    (WHEN kbd-grab
      (IF (EQ (grab-record.client kbd-grab) client)
          (deactivate-keyboard-grab kbd)))
    (LOOP for grab first (window.PASSIVE-GRABS root) then (grab-record.next grab)
          while grab do (DELETE-PASSIVE-GRAB-FROM-LIST grab))))

(DEFUN IS-IN-GRAB-MASK (FIRST-DETAIL SECOND-DETAIL EXCEPTION)
  (DECLARE (TYPE DETAIL-REC FIRST-DETAIL SECOND-DETAIL)
           (TYPE INTEGER EXCEPTION)
           (VALUES BOOLEAN))
  (IF (= (DETAIL-REC.EXACT FIRST-DETAIL) EXCEPTION)
      (PROGN
	(COND ((NULL (DETAIL-REC.MASK FIRST-DETAIL))
               T)
              ;; (at present) never called with two non-null pMasks.
              ((= (DETAIL-REC.EXACT SECOND-DETAIL) EXCEPTION)
               NIL)
              (
                ;; Get the bit specified by SECOND-DETAIL's EXACT
               (NOT (ZEROP (LOGAND (DETAIL-REC.MASK FIRST-DETAIL)
                                   (DETAIL-REC.EXACT SECOND-DETAIL))))
                T)
              (T
               NIL)))
      ;;ELSE
      NIL))


(DEFUN IDENTICAL-EXACT-DETAILS (FIRST-EXACT SECOND-EXACT EXCEPTION)
  (DECLARE (INTEGER FIRST-EXACT SECOND-EXACT EXCEPTION)
           (VALUES BOOLEAN))
  (COND ((OR (= FIRST-EXACT  EXCEPTION)
             (= SECOND-EXACT EXCEPTION))
         NIL)
        ((= FIRST-EXACT SECOND-EXACT)
         T)
        (T
         NIL)))

(DEFUN DETAIL-SUPERSEDES-SECOND (FIRST-DETAIL SECOND-DETAIL EXCEPTION)
  (DECLARE (TYPE DETAIL-REC FIRST-DETAIL SECOND-DETAIL)
           (TYPE INTEGER EXCEPTION)
           (VALUES BOOLEAN))
  (COND ((IS-IN-GRAB-MASK FIRST-DETAIL SECOND-DETAIL EXCEPTION)
         T)
        ((IDENTICAL-EXACT-DETAILS (DETAIL-REC.EXACT FIRST-DETAIL)
                                  (DETAIL-REC.EXACT SECOND-DETAIL)
                                  EXCEPTION)
         T)
        (T
         NIL)))

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


(DEFUN GRAB-MATCHES-SECOND (FIRST-GRAB SECOND-GRAB)
  (DECLARE (TYPE GRAB-RECORD FIRST-GRAB SECOND-GRAB)
           (VALUES BOOLEAN))
  (COND ((EQ (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)))

(DEFUN DELETE-PASSIVE-GRAB-FROM-LIST (MINUEND-GRAB)
  (DECLARE (TYPE GRAB-RECORD MINUEND-GRAB))
  (LOOP WITH GRAB = NIL
        WITH NEXT = (WINDOW.PASSIVE-GRABS (GRAB-RECORD.WINDOW MINUEND-GRAB))
        WHILE NEXT
        DO (PROGN
             (SETQ GRAB NEXT)
             (WHEN (AND (GRAB-SUPERSEDES-SECOND MINUEND-GRAB GRAB)
                        (EQ (GRAB-RECORD.CLIENT GRAB) (GRAB-RECORD.CLIENT MINUEND-GRAB)))
               (COND ((GRAB-SUPERSEDES-SECOND MINUEND-GRAB GRAB)
                      ;; This is really sleazy and counts on FreeResource to update NEXT.
                      (FREE-RESOURCE (GRAB-RECORD.RESOURCE GRAB) 'PASSIVE-CLIENT-GONE))
                     ((AND (= (DETAIL-REC.EXACT (GRAB-RECORD.DETAIL GRAB))
                              ANY-KEY)
                            (NOT (= (DETAIL-REC.EXACT (GRAB-RECORD.MODIFIERS-DETAIL GRAB))
                                    ANY-MODIFIER-MASK)))
                      (SETF (DETAIL-REC.MASK (GRAB-RECORD.DETAIL GRAB))
                            (DELETE-DETAIL-FROM-MASK (DETAIL-REC.MASK
                                                       (GRAB-RECORD.DETAIL GRAB))
                                                     (DETAIL-REC.EXACT
                                                       (GRAB-RECORD.DETAIL
                                                         MINUEND-GRAB)))))
                     ((AND (= (DETAIL-REC.EXACT (GRAB-RECORD.MODIFIERS-DETAIL GRAB))
                              ANY-MODIFIER-MASK)
                           (= (DETAIL-REC.EXACT (GRAB-RECORD.DETAIL GRAB)) ANY-KEY))
                      (SETF (DETAIL-REC.MASK (GRAB-RECORD.MODIFIERS-DETAIL GRAB))
                            (DELETE-DETAIL-FROM-MASK (DETAIL-REC.MASK
                                                       (GRAB-RECORD.MODIFIERS-DETAIL GRAB))
                                                     (DETAIL-REC.EXACT
                                                       (GRAB-RECORD.MODIFIERS-DETAIL
                                                         MINUEND-GRAB)))))
                     ((AND (= (DETAIL-REC.EXACT (GRAB-RECORD.DETAIL MINUEND-GRAB))
                              ANY-KEY)
                           (NOT (= (DETAIL-REC.EXACT (GRAB-RECORD.MODIFIERS-DETAIL MINUEND-GRAB))
                                   ANY-MODIFIER-MASK)))
                      (SETF (DETAIL-REC.MASK (GRAB-RECORD.DETAIL GRAB))
                            (DELETE-DETAIL-FROM-MASK (DETAIL-REC.MASK
                                                       (GRAB-RECORD.DETAIL GRAB))
                                                     (DETAIL-REC.EXACT
                                                       (GRAB-RECORD.DETAIL
                                                         MINUEND-GRAB))))
                      (LET ((NEW-GRAB (CREATE-GRAB (GRAB-RECORD.CLIENT GRAB)
                                                   (GRAB-RECORD.DEVICE GRAB)
                                                   (GRAB-RECORD.WINDOW GRAB)
                                                   (GRAB-RECORD.EVENT-MASK GRAB)
                                                   (GRAB-RECORD.OWNER-EVENTS GRAB)
                                                   (GRAB-RECORD.KEYBOARD-MODE GRAB)
                                                   (GRAB-RECORD.POINTER-MODE GRAB)
                                                   ANY-MODIFIER-MASK
                                                   (DETAIL-REC.EXACT
                                                       (GRAB-RECORD.DETAIL
                                                         MINUEND-GRAB)))))
                        (SETF (DETAIL-REC.MASK (GRAB-RECORD.MODIFIERS-DETAIL NEW-GRAB))
                              (DETAIL-REC.MASK (GRAB-RECORD.MODIFIERS-DETAIL
                                                                   GRAB)))
                        (SETF (DETAIL-REC.MASK (GRAB-RECORD.MODIFIERS-DETAIL NEW-GRAB))
                              (DELETE-DETAIL-FROM-MASK (DETAIL-REC.MASK
                                                         (GRAB-RECORD.MODIFIERS-DETAIL NEW-GRAB))
                                                       (DETAIL-REC.EXACT
                                                         (GRAB-RECORD.MODIFIERS-DETAIL
                                                           MINUEND-GRAB))))
                        (ADD-PASSIVE-GRAB-TO-WINDOW-LIST NEW-GRAB)))
                     ((= (DETAIL-REC.EXACT (GRAB-RECORD.DETAIL MINUEND-GRAB))
                              ANY-KEY)
                      (SETF (DETAIL-REC.MASK (GRAB-RECORD.MODIFIERS-DETAIL GRAB))
                              (DELETE-DETAIL-FROM-MASK (DETAIL-REC.MASK
                                                         (GRAB-RECORD.MODIFIERS-DETAIL GRAB))
                                                       (DETAIL-REC.EXACT
                                                         (GRAB-RECORD.MODIFIERS-DETAIL
                                                           MINUEND-GRAB)))))
                     (T
                      (SETF (DETAIL-REC.MASK (GRAB-RECORD.DETAIL GRAB))
                              (DELETE-DETAIL-FROM-MASK (DETAIL-REC.MASK
                                                         (GRAB-RECORD.DETAIL GRAB))
                                                       (DETAIL-REC.EXACT
                                                         (GRAB-RECORD.DETAIL
                                                           MINUEND-GRAB)))))))
             (SETQ NEXT (GRAB-RECORD.NEXT NEXT)))))