Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/cpp/webdriver-interactions/event_firing_thread.cpp
2867 views
1
/*
2
Licensed to the Software Freedom Conservancy (SFC) under one
3
or more contributor license agreements. See the NOTICE file
4
distributed with this work for additional information
5
regarding copyright ownership. The SFC licenses this file
6
to you under the Apache License, Version 2.0 (the "License");
7
you may not use this file except in compliance with the License.
8
You may obtain a copy of the License at
9
10
http://www.apache.org/licenses/LICENSE-2.0
11
12
Unless required by applicable law or agreed to in writing, software
13
distributed under the License is distributed on an "AS IS" BASIS,
14
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
See the License for the specific language governing permissions and
16
limitations under the License.
17
*/
18
19
#include "stdafx.h"
20
#include "event_firing_thread.h"
21
22
// Defaults to false, unless the driver explicitly turns this on.
23
static bool gEnablePersistentEventFiring = false;
24
// Thread for firing event
25
HANDLE hConstantEventsThread = NULL;
26
class EventFiringData
27
{
28
public:
29
EventFiringData(HWND directInputTo, long onX, long onY, WPARAM buttonValue) :
30
m_shouldFire(true), m_keepRunning(true),
31
m_to(directInputTo), m_x(onX), m_y(onY), m_buttonState(buttonValue) { }
32
// Used to control temporary firing of events.
33
void pauseFiring() { m_shouldFire = false; }
34
void resumeFiring() { m_shouldFire = true; }
35
bool shouldFire() { return m_shouldFire; }
36
// Used to control the existance of the background thread:
37
// when shouldRun returns false the thread will exit.
38
void stopRunning() { m_keepRunning = false; }
39
bool shouldRun() { return m_keepRunning; }
40
41
// Information on where to send the event to.
42
HWND getTarget() { return m_to; }
43
long getXLocation() { return m_x; }
44
long getYLocation() { return m_y; }
45
WPARAM getInputDevicesState() { return m_buttonState; }
46
47
// Update the keyboard state.
48
void setInputDevicesState(WPARAM buttonValue) { m_buttonState = buttonValue; }
49
50
// Fire events to a new window / coordinates.
51
void setNewTarget(HWND directInputTo, long onX, long onY, WPARAM buttonValue)
52
{
53
m_to = directInputTo;
54
m_x = onX;
55
m_y = onY;
56
m_buttonState = buttonValue;
57
}
58
59
private:
60
bool m_shouldFire;
61
bool m_keepRunning;
62
HWND m_to;
63
long m_x, m_y;
64
WPARAM m_buttonState;
65
};
66
67
// Function passed to the thread.
68
DWORD WINAPI MouseEventFiringFunction(LPVOID lpParam)
69
{
70
EventFiringData* firingData;
71
72
firingData = (EventFiringData*) lpParam;
73
// busy-wait loop, waiting for 10 milliseconds between
74
// dispatching events. Since the thread is usually
75
// paused for short periods of time (tens of milliseconds),
76
// a more modern signalling method was not used.
77
while (firingData->shouldRun()) {
78
if (firingData->shouldFire()) {
79
HWND target = firingData->getTarget();
80
if (IsWindow(target)) {
81
SendMessage(firingData->getTarget(),
82
WM_MOUSEMOVE, firingData->getInputDevicesState(),
83
MAKELPARAM(firingData->getXLocation(),
84
firingData->getYLocation()));
85
}
86
}
87
Sleep(10 /* ms */);
88
}
89
90
return 0;
91
}
92
93
EventFiringData* EVENT_FIRING_DATA;
94
95
void pausePersistentEventsFiring()
96
{
97
if (!gEnablePersistentEventFiring) {
98
// Persistent event firing is disabled.
99
return;
100
}
101
if ((hConstantEventsThread != NULL) && (EVENT_FIRING_DATA != NULL)) {
102
EVENT_FIRING_DATA->pauseFiring();
103
Sleep(10 /* ms */);
104
}
105
}
106
107
// Helper method to update the state of a given flag according to a toggle.
108
static void setStateByFlag(bool shouldSetFlag, UINT flagValue)
109
{
110
if (!gEnablePersistentEventFiring) {
111
// Persistent event firing is disabled.
112
return;
113
}
114
if ((hConstantEventsThread == NULL) || (EVENT_FIRING_DATA == NULL)) {
115
return;
116
}
117
118
WPARAM currentInputState = EVENT_FIRING_DATA->getInputDevicesState();
119
if (shouldSetFlag) {
120
currentInputState |= flagValue;
121
} else {
122
currentInputState = currentInputState & (~flagValue);
123
}
124
EVENT_FIRING_DATA->setInputDevicesState(currentInputState);
125
}
126
127
void updateShiftKeyState(bool isShiftPressed)
128
{
129
setStateByFlag(isShiftPressed, MK_SHIFT);
130
}
131
132
void updateLeftMouseButtonState(bool isButtonPressed)
133
{
134
setStateByFlag(isButtonPressed, MK_LBUTTON);
135
}
136
137
// Creates a new thread if there isn't one up and running.
138
void resumePersistentEventsFiring(
139
HWND inputTo, long toX, long toY, WPARAM buttonValue)
140
{
141
if (!gEnablePersistentEventFiring) {
142
// Persistent event firing is disabled.
143
return;
144
}
145
146
if (hConstantEventsThread == NULL) {
147
EVENT_FIRING_DATA = new EventFiringData(inputTo, toX, toY, buttonValue);
148
hConstantEventsThread = CreateThread(
149
NULL, // Security permissions.
150
0, // default stack size.
151
MouseEventFiringFunction,
152
EVENT_FIRING_DATA,
153
0, // default creation flags
154
NULL);
155
} else {
156
EVENT_FIRING_DATA->setNewTarget(inputTo, toX, toY, buttonValue);
157
EVENT_FIRING_DATA->resumeFiring();
158
}
159
}
160
161
void resumePersistentEventsFiring()
162
{
163
if (!gEnablePersistentEventFiring) {
164
// Persistent event firing is disabled.
165
return;
166
}
167
if ((hConstantEventsThread == NULL) || (EVENT_FIRING_DATA == NULL)) {
168
return;
169
}
170
EVENT_FIRING_DATA->resumeFiring();
171
}
172
173
extern "C" {
174
// Terminates the background thread.
175
void stopPersistentEventFiring()
176
{
177
if ((hConstantEventsThread != NULL) && (EVENT_FIRING_DATA != NULL)) {
178
EVENT_FIRING_DATA->stopRunning();
179
WaitForSingleObject(hConstantEventsThread, 2500 /* ms */);
180
CloseHandle(hConstantEventsThread);
181
hConstantEventsThread = NULL;
182
delete EVENT_FIRING_DATA;
183
EVENT_FIRING_DATA = NULL;
184
}
185
}
186
187
void setEnablePersistentHover(bool enablePersistentHover)
188
{
189
gEnablePersistentEventFiring = enablePersistentHover;
190
}
191
}
192
193