Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(269)

Side by Side Diff: chrome_frame/test/simulate_input.cc

Issue 604014: First batch of context menu tests... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome_frame/test/simulate_input.h"
6
7 #include <atlbase.h>
8 #include <atlwin.h>
9
10 #include "chrome_frame/utils.h"
11
12 namespace simulate_input {
13
14 class ForegroundHelperWindow : public CWindowImpl<ForegroundHelperWindow> {
15 public:
16 BEGIN_MSG_MAP(ForegroundHelperWindow)
17 MESSAGE_HANDLER(WM_HOTKEY, OnHotKey)
18 END_MSG_MAP()
19
20 ForegroundHelperWindow() : window_(NULL) {}
21
22 HRESULT SetForeground(HWND window) {
23 DCHECK(::IsWindow(window));
24 window_ = window;
25 if (NULL == Create(NULL, NULL, NULL, WS_POPUP))
26 return AtlHresultFromLastError();
27
28 static const int kHotKeyId = 0x0000baba;
29 static const int kHotKeyWaitTimeout = 2000;
30
31 RegisterHotKey(m_hWnd, kHotKeyId, 0, VK_F22);
32
33 MSG msg = {0};
34 PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
35
36 SendMnemonic(VK_F22, false, false, false, false, false);
37 // There are scenarios where the WM_HOTKEY is not dispatched by the
38 // the corresponding foreground thread. To prevent us from indefinitely
39 // waiting for the hotkey, we set a timer and exit the loop.
40 SetTimer(kHotKeyId, kHotKeyWaitTimeout, NULL);
41
42 while (GetMessage(&msg, NULL, 0, 0)) {
43 TranslateMessage(&msg);
44 DispatchMessage(&msg);
45 if (msg.message == WM_HOTKEY) {
46 break;
47 }
48 if (msg.message == WM_TIMER) {
49 SetForegroundWindow(window);
50 break;
51 }
52 }
53
54 UnregisterHotKey(m_hWnd, kHotKeyId);
55 KillTimer(kHotKeyId);
56 DestroyWindow();
57 return S_OK;
58 }
59
60 LRESULT OnHotKey(UINT msg, WPARAM wp, LPARAM lp, BOOL& handled) { // NOLINT
61 SetForegroundWindow(window_);
62 return 1;
63 }
64 private:
65 HWND window_;
66 };
67
68 bool ForceSetForegroundWindow(HWND window) {
69 if (GetForegroundWindow() == window)
70 return true;
71 ForegroundHelperWindow foreground_helper_window;
72 HRESULT hr = foreground_helper_window.SetForeground(window);
73 return SUCCEEDED(hr);
74 }
75
76 struct PidAndWindow {
77 base::ProcessId pid;
78 HWND hwnd;
79 };
80
81 BOOL CALLBACK FindWindowInProcessCallback(HWND hwnd, LPARAM param) {
82 PidAndWindow* paw = reinterpret_cast<PidAndWindow*>(param);
83 base::ProcessId pid;
84 GetWindowThreadProcessId(hwnd, &pid);
85 if (pid == paw->pid && IsWindowVisible(hwnd)) {
86 paw->hwnd = hwnd;
87 return FALSE;
88 }
89
90 return TRUE;
91 }
92
93 bool EnsureProcessInForeground(base::ProcessId process_id) {
94 HWND hwnd = GetForegroundWindow();
95 base::ProcessId current_foreground_pid = 0;
96 DWORD active_thread_id = GetWindowThreadProcessId(hwnd,
97 &current_foreground_pid);
98 if (current_foreground_pid == process_id)
99 return true;
100
101 PidAndWindow paw = { process_id };
102 EnumWindows(FindWindowInProcessCallback, reinterpret_cast<LPARAM>(&paw));
103 if (!IsWindow(paw.hwnd)) {
104 DLOG(ERROR) << "failed to find process window";
105 return false;
106 }
107
108 bool ret = ForceSetForegroundWindow(paw.hwnd);
109 LOG_IF(ERROR, !ret) << "ForceSetForegroundWindow: " << ret;
110
111 return ret;
112 }
113
114 void SendChar(char c, bool control, bool alt) {
115 SendMnemonic(toupper(c), !!isupper(c), control, alt, false, false);
116 }
117
118 void SendChar(wchar_t c, bool control, bool alt) {
119 SendMnemonic(towupper(c), !!iswupper(c), control, alt, false, true);
120 }
121
122 // Sends a keystroke to the currently active application with optional
123 // modifiers set.
124 bool SendMnemonic(WORD mnemonic_char, bool shift_pressed, bool control_pressed,
125 bool alt_pressed, bool extended, bool unicode) {
126 INPUT keys[4] = {0}; // Keyboard events
127 int key_count = 0; // Number of generated events
128
129 if (shift_pressed) {
130 keys[key_count].type = INPUT_KEYBOARD;
131 keys[key_count].ki.wVk = VK_SHIFT;
132 key_count++;
133 }
134
135 if (control_pressed) {
136 keys[key_count].type = INPUT_KEYBOARD;
137 keys[key_count].ki.wVk = VK_CONTROL;
138 key_count++;
139 }
140
141 if (alt_pressed) {
142 keys[key_count].type = INPUT_KEYBOARD;
143 keys[key_count].ki.wVk = VK_MENU;
144 key_count++;
145 }
146
147 keys[key_count].type = INPUT_KEYBOARD;
148 keys[key_count].ki.wVk = mnemonic_char;
149 if (extended)
150 keys[key_count].ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;
151 if (unicode)
152 keys[key_count].ki.dwFlags |= KEYEVENTF_UNICODE;
153 key_count++;
154
155 // Send key downs
156 for (int i = 0; i < key_count; i++) {
157 SendInput(1, &keys[ i ], sizeof(keys[0]));
158 keys[i].ki.dwFlags |= KEYEVENTF_KEYUP;
159 }
160
161 // Now send key ups in reverse order
162 for (int i = key_count; i; i--) {
163 SendInput(1, &keys[ i - 1 ], sizeof(keys[0]));
164 }
165
166 return true;
167 }
168
169 void SetKeyboardFocusToWindow(HWND window) {
170 SendMouseClick(window, 1, 1, LEFT);
171 }
172
173 void SendMouseClick(HWND window, int x, int y, MouseButton button) {
174 if (!IsWindow(window)) {
175 NOTREACHED() << "Invalid window handle.";
176 return;
177 }
178
179 HWND top_level_window = window;
180 if (!IsTopLevelWindow(top_level_window)) {
181 top_level_window = GetAncestor(window, GA_ROOT);
182 }
183
184 ForceSetForegroundWindow(top_level_window);
185
186 POINT cursor_position = {x, y};
187 ClientToScreen(window, &cursor_position);
188
189 // TODO(joshia): Fix this. GetSystemMetrics(SM_CXSCREEN) will
190 // retrieve screen size of the primarary monitor only. And monitors
191 // arrangement could be pretty arbitrary.
192 double screen_width = ::GetSystemMetrics(SM_CXSCREEN) - 1;
193 double screen_height = ::GetSystemMetrics(SM_CYSCREEN) - 1;
194 double location_x = cursor_position.x * (65535.0f / screen_width);
195 double location_y = cursor_position.y * (65535.0f / screen_height);
196
197 // Take advantage of button flag bitmask layout
198 unsigned int button_flag = MOUSEEVENTF_LEFTDOWN << (button + button);
199
200 INPUT input_info = {0};
201 input_info.type = INPUT_MOUSE;
202 input_info.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;
203 input_info.mi.dx = static_cast<long>(location_x);
204 input_info.mi.dy = static_cast<long>(location_y);
205 ::SendInput(1, &input_info, sizeof(INPUT));
206
207 Sleep(10);
208
209 input_info.mi.dwFlags = button_flag | MOUSEEVENTF_ABSOLUTE;
210 ::SendInput(1, &input_info, sizeof(INPUT));
211
212 Sleep(10);
213
214 input_info.mi.dwFlags = (button_flag << 1) | MOUSEEVENTF_ABSOLUTE;
215 ::SendInput(1, &input_info, sizeof(INPUT));
216 }
217
218 bool SendExtendedKey(WORD key, bool shift, bool control, bool alt) {
219 return SendMnemonic(key, shift, control, alt, true, false);
220 }
221
222 } // namespace simulate_input
223
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698