summaryrefslogtreecommitdiffhomepage
path: root/Tobii-EyeX/samples/ActivatableBoardGame/EyeXHost.h
blob: 98aa84d32897c11e182ac13e48ea049f0435c300 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/*
 * EyeXHost class: Responsible for the gaze interaction within a window.
 * Holds the current set of activatable regions and acts as a simple interactor repository.
 * Sends notifications as Windows messages so that they are received on the main thread and can be handled there.
 *
 * Copyright 2013 Tobii Technology AB. All rights reserved.
 */

#pragma once

#include <windows.h>
#include <vector>
#include <mutex>
#include "eyex/EyeX.h"

class EyeXHost
{
public:
	// Represents an activatable region, that is, one particular kind of interactor.
	struct ActivatableRegion
	{
		int id;
		RECT bounds;

		ActivatableRegion(int paramId, RECT paramBounds) : id(paramId), bounds(paramBounds) { }
	};

	EyeXHost();
	virtual ~EyeXHost();

	// attaches to the window with the given handle.
	// the message parameters are custom windows messages sent to the window when an event has occurred.
	void Init(HWND hWnd, UINT statusChangedMessage, UINT focusedRegionChangedMessage, UINT regionActivatedMessage);

	// updates the collection (repository) of activatable regions.
	void SetActivatableRegions(const std::vector<ActivatableRegion>& regions);

	// gets the ID of the region that currently has the activation focus.
	int GetFocusedRegionId() const;

    // triggers an activation ("direct click").
	void TriggerActivation();

    // trigger a request to the EyeX Engine to switch activation mode on.
    // this will trigger Activation Focus Changed events to be raised for the
    // interactor the user is looking at/no longer looking at.
    // in this sample, the focus is used to draw a highlight on in the square
    // that is about to be "clicked" - where the "X" will be placed.
    void TriggerActivationModeOn();

	// indicates whether the connection to the EyeX Engine is working.
	bool IsFunctional() const;

private:
	enum State
	{
		Initializing,
		Connected,
		Disconnected,
		Failed
	};

	// registers handlers for notifications from the engine.
	bool RegisterConnectionStateChangedHandler();
	bool RegisterQueryHandler();
	bool RegisterEventHandler();

	// event handlers.
	void OnEngineConnectionStateChanged(TX_CONNECTIONSTATE connectionState);
	void HandleQuery(TX_CONSTHANDLE hAsyncData);
	void HandleEvent(TX_CONSTHANDLE hAsyncData);
	void HandleActivatableEvent(TX_HANDLE hEvent, int interactorId);
	void OnActivationFocusChanged(TX_HANDLE hBehavior, int interactorId);
	void OnActivated(TX_HANDLE hBehavior, int interactorId);

	// callback function invoked when a snapshot has been committed.
	static void TX_CALLCONVENTION OnSnapshotCommitted(TX_CONSTHANDLE hAsyncData, TX_USERPARAM param);

	// sets the internal state.
	void SetState(State state);

	// sets the ID of the region that currently has the activation focus.
	void SetFocusedRegionId(int regionId);

	// clears the focused region ID if there is no matching region in the repository.
	void ResetFocusedRegionIdIfNonExistent();

	static bool QueryIsForWindowId(TX_HANDLE hQuery, const TX_CHAR* windowId);

	// mutex protecting the state of the object from race conditions caused by multiple threads.
	// (for example, a call to SetActivatableRegions from the main thread while the HandleQuery 
	// method is iterating through the regions on a worker thread.)
	std::mutex _mutex;
	State _state;
	std::vector<ActivatableRegion> _regions;
	int _focusedRegionId;
	TX_CONTEXTHANDLE _context;
	TX_TICKET _connectionStateChangedTicket;
	TX_TICKET _queryHandlerTicket;
	TX_TICKET _eventHandlerTicket;

	// attached window and custom messages.
	HWND _hWnd;
	UINT _statusChangedMessage;
	UINT _focusedRegionChangedMessage;
	UINT _regionActivatedMessage;

	// private copy constructor and operator making the class non-copyable (declared but not implemented).
	EyeXHost(const EyeXHost&);
	EyeXHost& operator = (const EyeXHost&);
};