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&);
};
|