// File: x11inputthread.h
// Created by: <Jörn Reimerdes>
// Created on: 22.03.2005

/**
 * x11inputthread.h - is part of the iwear-framework
 * @file
 * $Id$
 * $Revision$
 * $Author$
 * $Date$
 *
 * This file is part of The iWear Framework.
 * In particular this file is part of the Framework Input Library
 *
 * The iWear Framework 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 as in version 2 of the License.

 * 
 * The iWear Framework 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
 * The iWear Framework; if not, write to the Free Software Foundation, Inc., 59
 * Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef __X11INPUTTHREAD_H
#define __X11INPUTTHREAD_H


extern "C"{
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
}

#ifndef __INPUTHARDWAREINFO_H
#include <iwear_input/inputhardwareinfo.h>
#endif

#ifndef __INPUTENUMS_H
#include <iwear_input/inputenums.h>
#endif

#ifndef __KEYINPUTDATA_H
#include <iwear_input/keyinputdata.h>
#endif

#ifndef __MOUSEINPUTDATA_H
#include <iwear_input/mouseinputdata.h>
#endif

#ifndef __THREAD_H
#include <iwear/thread.h>
#endif

namespace iwear {
namespace input {

    /* Forward declaration of InputModule */
    class InputModule;

namespace x11{

    /** X11InpuTthread stores all data which is common to all X11InputThread
     * subclasses.
     */
class X11InputThread : public Thread
{
public:

    X11InputThread(InputModule* input_module, EventDispatcher& ed);

    X11InputThread(InputModule* input_module, EventDispatcher& ed,
		   bool grab_keys,
		   bool grab_mouse_buttons);

    virtual ~X11InputThread( void );

    /** Stops the event catching loop. */
    void stop_event_catching( void ){
	this->catch_events = false;
    }

protected:
    
    /** The InputModule which created the X11InputThread object. */
    InputModule* input_module;

    /** The InputData which is used for KeyInputEvents. */
    KeyInputData* key_input_data;

    /** The InputData which is used for MouseInputEvents. */
    MouseInputData* mouse_input_data;

    virtual void Run( void );

    virtual void Final( void );

private: 

    bool catch_events;
    bool grab_keyboard;
    bool grab_mouse_buttons;
    const string hardware_name_keyboard;
    const string hardware_name_mouse;
    InputHardwareInfo* keyboard_hardware_info;
    InputHardwareInfo* mouse_hardware_info;

    bool is_catching_key_events;
    bool is_catching_pointer_events;

    void start_event_catching(void);

    /** Catches key events and dispatches iWear KeyInputEvents.
     * @param event A KeyRelease or KeyPress XEvent.
     */
    void catch_key_events(XEvent* event, Display* display, Window* window);

    /** Catches mouse button events and dispatches an iWear
     * MouseInputEvent.
     * @param event the ButtonPress or ButtonRelease XEvent.
     */
    void catch_mouse_events(XEvent* event);

    /** Catches pointer motion events and dispatches an iWear
     * MouseInputEvent.
     * @param event The MotionNotify XEvent.
     */
    void catch_pointer_motion_events(XEvent* event);

    /** Constructor with no InputModule is not allowed. */
    X11InputThread( void );

    /** Sets the button status of the mouse. 
     * @param mouse_key The mouse key/button which should be set.
     * @param event_type The type of the mouse input event.
     */
    inline void set_mouse_button_status(MouseKey mouse_key, 
					MouseInputEventType event_type){
	/* If the key was released set the value to false. */
	if ( event_type == INPUT_MOUSE_BUTTON_UP){
	    this->mouse_input_data->
		mouse_button_status_set[mouse_key] = false;		
	}
	/* If the key was pressed set to true. */
	else if ( event_type == INPUT_MOUSE_BUTTON_DOWN ) {
	    mouse_input_data->
		mouse_button_status_set[mouse_key] = true;
	}
    }

    
    /** Starts the retreaval of key events. */
    void grab_keyboard_events ( Display* display, Window* window );
    
    /** Stops the key event grabbing. */
    void ungrab_keyboard_events ( Display* display );
    
    /** Starts the retreaval of pointer events. */
    void grab_pointer_events ( Display* display, Window* window ); 

    /** Stops the pointer event grabbing. */
    void ungrab_pointer_events ( Display* display );

};

} // x11
} // input
} // iwear
#endif	//__X11INPUTTHREAD_H

