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