1 //
2 // Copyright 2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 #include "OSWindow.h"
8
9 #include <fstream>
10 #include <iostream>
11 #include <sstream>
12
13 #include "common/debug.h"
14 #include "common/system_utils.h"
15
16 #if defined(ANGLE_PLATFORM_ANDROID)
17 # include "util/android/AndroidWindow.h"
18 #endif // defined(ANGLE_PLATFORM_ANDROID)
19
20 #ifndef DEBUG_EVENTS
21 # define DEBUG_EVENTS 0
22 #endif
23
24 #if DEBUG_EVENTS
MouseButtonName(MouseButton button)25 static const char *MouseButtonName(MouseButton button)
26 {
27 switch (button)
28 {
29 case MOUSEBUTTON_UNKNOWN:
30 return "Unknown";
31 case MOUSEBUTTON_LEFT:
32 return "Left";
33 case MOUSEBUTTON_RIGHT:
34 return "Right";
35 case MOUSEBUTTON_MIDDLE:
36 return "Middle";
37 case MOUSEBUTTON_BUTTON4:
38 return "Button4";
39 case MOUSEBUTTON_BUTTON5:
40 return "Button5";
41 default:
42 UNREACHABLE();
43 return nullptr;
44 }
45 }
46
KeyName(Key key)47 static const char *KeyName(Key key)
48 {
49 switch (key)
50 {
51 case KEY_UNKNOWN:
52 return "Unknown";
53 case KEY_A:
54 return "A";
55 case KEY_B:
56 return "B";
57 case KEY_C:
58 return "C";
59 case KEY_D:
60 return "D";
61 case KEY_E:
62 return "E";
63 case KEY_F:
64 return "F";
65 case KEY_G:
66 return "G";
67 case KEY_H:
68 return "H";
69 case KEY_I:
70 return "I";
71 case KEY_J:
72 return "J";
73 case KEY_K:
74 return "K";
75 case KEY_L:
76 return "L";
77 case KEY_M:
78 return "M";
79 case KEY_N:
80 return "N";
81 case KEY_O:
82 return "O";
83 case KEY_P:
84 return "P";
85 case KEY_Q:
86 return "Q";
87 case KEY_R:
88 return "R";
89 case KEY_S:
90 return "S";
91 case KEY_T:
92 return "T";
93 case KEY_U:
94 return "U";
95 case KEY_V:
96 return "V";
97 case KEY_W:
98 return "W";
99 case KEY_X:
100 return "X";
101 case KEY_Y:
102 return "Y";
103 case KEY_Z:
104 return "Z";
105 case KEY_NUM0:
106 return "Num0";
107 case KEY_NUM1:
108 return "Num1";
109 case KEY_NUM2:
110 return "Num2";
111 case KEY_NUM3:
112 return "Num3";
113 case KEY_NUM4:
114 return "Num4";
115 case KEY_NUM5:
116 return "Num5";
117 case KEY_NUM6:
118 return "Num6";
119 case KEY_NUM7:
120 return "Num7";
121 case KEY_NUM8:
122 return "Num8";
123 case KEY_NUM9:
124 return "Num9";
125 case KEY_ESCAPE:
126 return "Escape";
127 case KEY_LCONTROL:
128 return "Left Control";
129 case KEY_LSHIFT:
130 return "Left Shift";
131 case KEY_LALT:
132 return "Left Alt";
133 case KEY_LSYSTEM:
134 return "Left System";
135 case KEY_RCONTROL:
136 return "Right Control";
137 case KEY_RSHIFT:
138 return "Right Shift";
139 case KEY_RALT:
140 return "Right Alt";
141 case KEY_RSYSTEM:
142 return "Right System";
143 case KEY_MENU:
144 return "Menu";
145 case KEY_LBRACKET:
146 return "Left Bracket";
147 case KEY_RBRACKET:
148 return "Right Bracket";
149 case KEY_SEMICOLON:
150 return "Semicolon";
151 case KEY_COMMA:
152 return "Comma";
153 case KEY_PERIOD:
154 return "Period";
155 case KEY_QUOTE:
156 return "Quote";
157 case KEY_SLASH:
158 return "Slash";
159 case KEY_BACKSLASH:
160 return "Backslash";
161 case KEY_TILDE:
162 return "Tilde";
163 case KEY_EQUAL:
164 return "Equal";
165 case KEY_DASH:
166 return "Dash";
167 case KEY_SPACE:
168 return "Space";
169 case KEY_RETURN:
170 return "Return";
171 case KEY_BACK:
172 return "Back";
173 case KEY_TAB:
174 return "Tab";
175 case KEY_PAGEUP:
176 return "Page Up";
177 case KEY_PAGEDOWN:
178 return "Page Down";
179 case KEY_END:
180 return "End";
181 case KEY_HOME:
182 return "Home";
183 case KEY_INSERT:
184 return "Insert";
185 case KEY_DELETE:
186 return "Delete";
187 case KEY_ADD:
188 return "Add";
189 case KEY_SUBTRACT:
190 return "Substract";
191 case KEY_MULTIPLY:
192 return "Multiply";
193 case KEY_DIVIDE:
194 return "Divide";
195 case KEY_LEFT:
196 return "Left";
197 case KEY_RIGHT:
198 return "Right";
199 case KEY_UP:
200 return "Up";
201 case KEY_DOWN:
202 return "Down";
203 case KEY_NUMPAD0:
204 return "Numpad 0";
205 case KEY_NUMPAD1:
206 return "Numpad 1";
207 case KEY_NUMPAD2:
208 return "Numpad 2";
209 case KEY_NUMPAD3:
210 return "Numpad 3";
211 case KEY_NUMPAD4:
212 return "Numpad 4";
213 case KEY_NUMPAD5:
214 return "Numpad 5";
215 case KEY_NUMPAD6:
216 return "Numpad 6";
217 case KEY_NUMPAD7:
218 return "Numpad 7";
219 case KEY_NUMPAD8:
220 return "Numpad 8";
221 case KEY_NUMPAD9:
222 return "Numpad 9";
223 case KEY_F1:
224 return "F1";
225 case KEY_F2:
226 return "F2";
227 case KEY_F3:
228 return "F3";
229 case KEY_F4:
230 return "F4";
231 case KEY_F5:
232 return "F5";
233 case KEY_F6:
234 return "F6";
235 case KEY_F7:
236 return "F7";
237 case KEY_F8:
238 return "F8";
239 case KEY_F9:
240 return "F9";
241 case KEY_F10:
242 return "F10";
243 case KEY_F11:
244 return "F11";
245 case KEY_F12:
246 return "F12";
247 case KEY_F13:
248 return "F13";
249 case KEY_F14:
250 return "F14";
251 case KEY_F15:
252 return "F15";
253 case KEY_PAUSE:
254 return "Pause";
255 default:
256 return "Unknown Key";
257 }
258 }
259
KeyState(const Event::KeyEvent & event)260 static std::string KeyState(const Event::KeyEvent &event)
261 {
262 if (event.Shift || event.Control || event.Alt || event.System)
263 {
264 std::ostringstream buffer;
265 buffer << " [";
266
267 if (event.Shift)
268 {
269 buffer << "Shift";
270 }
271 if (event.Control)
272 {
273 buffer << "Control";
274 }
275 if (event.Alt)
276 {
277 buffer << "Alt";
278 }
279 if (event.System)
280 {
281 buffer << "System";
282 }
283
284 buffer << "]";
285 return buffer.str();
286 }
287 return "";
288 }
289
PrintEvent(const Event & event)290 static void PrintEvent(const Event &event)
291 {
292 switch (event.Type)
293 {
294 case Event::EVENT_CLOSED:
295 std::cout << "Event: Window Closed" << std::endl;
296 break;
297 case Event::EVENT_MOVED:
298 std::cout << "Event: Window Moved (" << event.Move.X << ", " << event.Move.Y << ")"
299 << std::endl;
300 break;
301 case Event::EVENT_RESIZED:
302 std::cout << "Event: Window Resized (" << event.Size.Width << ", " << event.Size.Height
303 << ")" << std::endl;
304 break;
305 case Event::EVENT_LOST_FOCUS:
306 std::cout << "Event: Window Lost Focus" << std::endl;
307 break;
308 case Event::EVENT_GAINED_FOCUS:
309 std::cout << "Event: Window Gained Focus" << std::endl;
310 break;
311 case Event::EVENT_TEXT_ENTERED:
312 // TODO(cwallez) show the character
313 std::cout << "Event: Text Entered" << std::endl;
314 break;
315 case Event::EVENT_KEY_PRESSED:
316 std::cout << "Event: Key Pressed (" << KeyName(event.Key.Code) << KeyState(event.Key)
317 << ")" << std::endl;
318 break;
319 case Event::EVENT_KEY_RELEASED:
320 std::cout << "Event: Key Released (" << KeyName(event.Key.Code) << KeyState(event.Key)
321 << ")" << std::endl;
322 break;
323 case Event::EVENT_MOUSE_WHEEL_MOVED:
324 std::cout << "Event: Mouse Wheel (" << event.MouseWheel.Delta << ")" << std::endl;
325 break;
326 case Event::EVENT_MOUSE_BUTTON_PRESSED:
327 std::cout << "Event: Mouse Button Pressed " << MouseButtonName(event.MouseButton.Button)
328 << " at (" << event.MouseButton.X << ", " << event.MouseButton.Y << ")"
329 << std::endl;
330 break;
331 case Event::EVENT_MOUSE_BUTTON_RELEASED:
332 std::cout << "Event: Mouse Button Released "
333 << MouseButtonName(event.MouseButton.Button) << " at (" << event.MouseButton.X
334 << ", " << event.MouseButton.Y << ")" << std::endl;
335 break;
336 case Event::EVENT_MOUSE_MOVED:
337 std::cout << "Event: Mouse Moved (" << event.MouseMove.X << ", " << event.MouseMove.Y
338 << ")" << std::endl;
339 break;
340 case Event::EVENT_MOUSE_ENTERED:
341 std::cout << "Event: Mouse Entered Window" << std::endl;
342 break;
343 case Event::EVENT_MOUSE_LEFT:
344 std::cout << "Event: Mouse Left Window" << std::endl;
345 break;
346 case Event::EVENT_TEST:
347 std::cout << "Event: Test" << std::endl;
348 break;
349 default:
350 UNREACHABLE();
351 break;
352 }
353 }
354 #endif
355
OSWindow()356 OSWindow::OSWindow() : mX(0), mY(0), mWidth(0), mHeight(0), mValid(false), mIgnoreSizeEvents(false)
357 {}
358
~OSWindow()359 OSWindow::~OSWindow() {}
360
initialize(const std::string & name,int width,int height)361 bool OSWindow::initialize(const std::string &name, int width, int height)
362 {
363 mValid = initializeImpl(name, width, height);
364 return mValid;
365 }
366
getX() const367 int OSWindow::getX() const
368 {
369 return mX;
370 }
371
getY() const372 int OSWindow::getY() const
373 {
374 return mY;
375 }
376
getWidth() const377 int OSWindow::getWidth() const
378 {
379 return mWidth;
380 }
381
getHeight() const382 int OSWindow::getHeight() const
383 {
384 return mHeight;
385 }
386
takeScreenshot(uint8_t * pixelData)387 bool OSWindow::takeScreenshot(uint8_t *pixelData)
388 {
389 return false;
390 }
391
popEvent(Event * event)392 bool OSWindow::popEvent(Event *event)
393 {
394 if (mEvents.size() > 0 && event)
395 {
396 *event = mEvents.front();
397 mEvents.pop_front();
398 return true;
399 }
400 else
401 {
402 return false;
403 }
404 }
405
pushEvent(Event event)406 void OSWindow::pushEvent(Event event)
407 {
408 switch (event.Type)
409 {
410 case Event::EVENT_MOVED:
411 mX = event.Move.X;
412 mY = event.Move.Y;
413 break;
414 case Event::EVENT_RESIZED:
415 mWidth = event.Size.Width;
416 mHeight = event.Size.Height;
417 break;
418 default:
419 break;
420 }
421
422 mEvents.push_back(event);
423
424 #if DEBUG_EVENTS
425 PrintEvent(event);
426 #endif
427 }
428
didTestEventFire()429 bool OSWindow::didTestEventFire()
430 {
431 Event topEvent;
432 while (popEvent(&topEvent))
433 {
434 if (topEvent.Type == Event::EVENT_TEST)
435 {
436 return true;
437 }
438 }
439
440 return false;
441 }
442
443 // static
Delete(OSWindow ** window)444 void OSWindow::Delete(OSWindow **window)
445 {
446 delete *window;
447 *window = nullptr;
448 }
449
450 namespace angle
451 {
FindTestDataPath(const char * searchPath,char * dataPathOut,size_t maxDataPathOutLen)452 bool FindTestDataPath(const char *searchPath, char *dataPathOut, size_t maxDataPathOutLen)
453 {
454 #if defined(ANGLE_PLATFORM_ANDROID)
455 const std::string searchPaths[] = {
456 AndroidWindow::GetExternalStorageDirectory(),
457 AndroidWindow::GetExternalStorageDirectory() + "/third_party/angle"};
458 #else
459 const std::string searchPaths[] = {
460 GetExecutableDirectory(), GetExecutableDirectory() + "/../..", ".",
461 GetExecutableDirectory() + "/../../third_party/angle", "third_party/angle"};
462 #endif // defined(ANGLE_PLATFORM_ANDROID)
463
464 for (const std::string &path : searchPaths)
465 {
466 std::stringstream pathStream;
467 pathStream << path << "/" << searchPath;
468 std::string candidatePath = pathStream.str();
469
470 if (candidatePath.size() + 1 >= maxDataPathOutLen)
471 {
472 ERR() << "FindTestDataPath: Path too long.";
473 return false;
474 }
475
476 if (angle::IsDirectory(candidatePath.c_str()))
477 {
478 memcpy(dataPathOut, candidatePath.c_str(), candidatePath.size() + 1);
479 return true;
480 }
481
482 std::ifstream inFile(candidatePath.c_str());
483 if (!inFile.fail())
484 {
485 memcpy(dataPathOut, candidatePath.c_str(), candidatePath.size() + 1);
486 return true;
487 }
488 }
489
490 return false;
491 }
492 } // namespace angle
493