/*************************************************************************
    Project:    Babble
    Module:     winevents.c

    Author:     Charles Oppermann
    Date:       4 October 1996
    
    Notes:      Contains routines to initailize Active Accessibility and
                gather events.

    Copyright (C) 1996 by Microsoft Corporation.  All rights reserved.
    See bottom of file for disclaimer
    
    History:
    10/21/96 CWO Added OnFocusChangedEvent()
    12/12/96 CWO Changed HEVENT to HWINEVENTHOOK

*************************************************************************/
#define STRICT
#include <windows.h>
#include <windowsx.h>
#include <ole2.h>

#include <winable.h>
#include <oleacc.h>

#include "resource.h"
#include "babble.h"
#include "actions.h"
#include "winevent.h"
#include "tts.h"
#include "getprop.h"

// Local functions
BOOL OnFocusChangedEvent(DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwmsTimeStamp);

// Local variables
HWINEVENTHOOK   hEventHook;

/*************************************************************************
    Function:   WinEventProc
    Purpose:    Callback function handles events
    Inputs:     HWINEVENTHOOK hEvent - Handle of the instance of the event proc
                DWORD event - Event type constant
                HWND hwndMsg - HWND of window generating event
                LONG idObject - ID of object generating event
                LONG idChild - ID of child generating event (0 if object)
                DWORD idThread - ID of thread generating event
                DWORD dwmsEventTime - Timestamp of event
    Returns:    
    History:    
*************************************************************************/
void CALLBACK WinEventProc(HWINEVENTHOOK hEvent,
                          DWORD event,
                          HWND hwndMsg,
                          LONG idObject,
                          LONG idChild,
                          DWORD idThread,
                          DWORD dwmsEventTime)
{
    // What type of event is coming throug?
    switch (event)
	    {
        case EVENT_OBJECT_FOCUS:
            // Focus is changing
            OnFocusChangedEvent(event, hwndMsg, 
                                idObject, idChild,
                                dwmsEventTime);
            break;
    	}

    return;
}

/*************************************************************************
    Function:   OnFocusChangedEvent
    Purpose:    Receives focus events
    Inputs:     DWORD event - What event are we processing
                HWND hwnd - HWND of window generating event
                LONG idObject - ID of object generating event
                LONG idChild - ID of child generating event (0 if object)
                DWORD idThread - ID of thread generating event
                DWORD dwmsEventTime - Timestamp of event
    Returns:    BOOL - TRUE if succeeded
    History:    10/21/96 CWO Created
*************************************************************************/
BOOL OnFocusChangedEvent(DWORD event,
                         HWND hwnd,
                         LONG idObject,
                         LONG idChild,
                         DWORD dwmsTimeStamp)
{
    VARIANT varChild;
    IAccessible* pIAcc;
    HRESULT hr;
    int cchName = 128;
    TCHAR tszName[128];
    TCHAR tszSpeak[1024];

    // Check to see if we are getting rapid focus changes
    // Consider using the Time stamp and saving away the last object
    
    // Important to init variants
    VariantInit(&varChild);

    //BUGBUG: AOFE uses DWORDs instead of LONGS for object/child
    hr = AccessibleObjectFromEvent(hwnd, idObject, idChild, &pIAcc, &varChild);
    
    // Check to see if we got a valid pointer
    if (SUCCEEDED(hr))
        {
        OBJINFO objCurrent;

        objCurrent.hwnd = hwnd;
        objCurrent.plObj = (long*)pIAcc;
        objCurrent.varChild = varChild;

        GetObjectName(&objCurrent, tszName, cchName);

        wsprintf(tszSpeak, "Focus now %s.", tszName);
        
        SpeakString(tszSpeak);

        if (pIAcc)
            pIAcc->Release();

        return(TRUE);
        }
    
    return(FALSE);
}

/*************************************************************************
    Function:   InitMSAA
    Purpose:    Initalize the Active Accessibility subsystem
    Inputs:     none
    Returns:    BOOL - TRUE if successful
    History:    
*************************************************************************/
BOOL InitMSAA(void)
{
    // Set up event call back
    hEventHook = SetWinEventHook(EVENT_MIN,              // We want all events
                                 EVENT_MAX,              //
                                 GetModuleHandle(NULL),  // Use our own module
                                 WinEventProc,           // Our callback function
                                 0,                      // All processes
                                 0,                      // All threads
                                 WINEVENT_OUTOFCONTEXT); // Receive async events
    // Did we install correctly? 
    if (hEventHook)
        return(TRUE);

    // Did not install properly - fail
    return(FALSE);
}

/*************************************************************************
    Function:   UnInitMSAA
    Purpose:    Shuts down the Active Accessibility subsystem
    Inputs:     none
    Returns:    BOOL - TRUE if successful
    History:    
*************************************************************************/
BOOL UnInitMSAA(void)
{
    // Remove the WinEvent hook
    UnhookWinEvent(hEventHook);
    
    return(TRUE);
}

/*************************************************************************
    THE INFORMATION AND CODE PROVIDED HEREUNDER (COLLECTIVELY REFERRED TO
    AS "SOFTWARE") IS PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND, EITHER
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN
    NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR
    ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL,
    CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF
    MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE
    POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR
    LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE
    FOREGOING LIMITATION MAY NOT APPLY.
*************************************************************************/