| // | |
| // Copyright 2014 The ANGLE Project Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| // | |
| #include "OSWindow.h" | |
| #include <cstring> | |
| #include <fstream> | |
| #include <iostream> | |
| #include <sstream> | |
| #include "common/debug.h" | |
| #include "common/system_utils.h" | |
| #if defined(ANGLE_PLATFORM_ANDROID) | |
| # include "util/android/AndroidWindow.h" | |
| #endif // defined(ANGLE_PLATFORM_ANDROID) | |
| #ifndef DEBUG_EVENTS | |
| # define DEBUG_EVENTS 0 | |
| #endif | |
| #if DEBUG_EVENTS | |
| static const char *MouseButtonName(MouseButton button) | |
| { | |
| switch (button) | |
| { | |
| case MOUSEBUTTON_UNKNOWN: | |
| return "Unknown"; | |
| case MOUSEBUTTON_LEFT: | |
| return "Left"; | |
| case MOUSEBUTTON_RIGHT: | |
| return "Right"; | |
| case MOUSEBUTTON_MIDDLE: | |
| return "Middle"; | |
| case MOUSEBUTTON_BUTTON4: | |
| return "Button4"; | |
| case MOUSEBUTTON_BUTTON5: | |
| return "Button5"; | |
| default: | |
| UNREACHABLE(); | |
| return nullptr; | |
| } | |
| } | |
| static const char *KeyName(Key key) | |
| { | |
| switch (key) | |
| { | |
| case KEY_UNKNOWN: | |
| return "Unknown"; | |
| case KEY_A: | |
| return "A"; | |
| case KEY_B: | |
| return "B"; | |
| case KEY_C: | |
| return "C"; | |
| case KEY_D: | |
| return "D"; | |
| case KEY_E: | |
| return "E"; | |
| case KEY_F: | |
| return "F"; | |
| case KEY_G: | |
| return "G"; | |
| case KEY_H: | |
| return "H"; | |
| case KEY_I: | |
| return "I"; | |
| case KEY_J: | |
| return "J"; | |
| case KEY_K: | |
| return "K"; | |
| case KEY_L: | |
| return "L"; | |
| case KEY_M: | |
| return "M"; | |
| case KEY_N: | |
| return "N"; | |
| case KEY_O: | |
| return "O"; | |
| case KEY_P: | |
| return "P"; | |
| case KEY_Q: | |
| return "Q"; | |
| case KEY_R: | |
| return "R"; | |
| case KEY_S: | |
| return "S"; | |
| case KEY_T: | |
| return "T"; | |
| case KEY_U: | |
| return "U"; | |
| case KEY_V: | |
| return "V"; | |
| case KEY_W: | |
| return "W"; | |
| case KEY_X: | |
| return "X"; | |
| case KEY_Y: | |
| return "Y"; | |
| case KEY_Z: | |
| return "Z"; | |
| case KEY_NUM0: | |
| return "Num0"; | |
| case KEY_NUM1: | |
| return "Num1"; | |
| case KEY_NUM2: | |
| return "Num2"; | |
| case KEY_NUM3: | |
| return "Num3"; | |
| case KEY_NUM4: | |
| return "Num4"; | |
| case KEY_NUM5: | |
| return "Num5"; | |
| case KEY_NUM6: | |
| return "Num6"; | |
| case KEY_NUM7: | |
| return "Num7"; | |
| case KEY_NUM8: | |
| return "Num8"; | |
| case KEY_NUM9: | |
| return "Num9"; | |
| case KEY_ESCAPE: | |
| return "Escape"; | |
| case KEY_LCONTROL: | |
| return "Left Control"; | |
| case KEY_LSHIFT: | |
| return "Left Shift"; | |
| case KEY_LALT: | |
| return "Left Alt"; | |
| case KEY_LSYSTEM: | |
| return "Left System"; | |
| case KEY_RCONTROL: | |
| return "Right Control"; | |
| case KEY_RSHIFT: | |
| return "Right Shift"; | |
| case KEY_RALT: | |
| return "Right Alt"; | |
| case KEY_RSYSTEM: | |
| return "Right System"; | |
| case KEY_MENU: | |
| return "Menu"; | |
| case KEY_LBRACKET: | |
| return "Left Bracket"; | |
| case KEY_RBRACKET: | |
| return "Right Bracket"; | |
| case KEY_SEMICOLON: | |
| return "Semicolon"; | |
| case KEY_COMMA: | |
| return "Comma"; | |
| case KEY_PERIOD: | |
| return "Period"; | |
| case KEY_QUOTE: | |
| return "Quote"; | |
| case KEY_SLASH: | |
| return "Slash"; | |
| case KEY_BACKSLASH: | |
| return "Backslash"; | |
| case KEY_TILDE: | |
| return "Tilde"; | |
| case KEY_EQUAL: | |
| return "Equal"; | |
| case KEY_DASH: | |
| return "Dash"; | |
| case KEY_SPACE: | |
| return "Space"; | |
| case KEY_RETURN: | |
| return "Return"; | |
| case KEY_BACK: | |
| return "Back"; | |
| case KEY_TAB: | |
| return "Tab"; | |
| case KEY_PAGEUP: | |
| return "Page Up"; | |
| case KEY_PAGEDOWN: | |
| return "Page Down"; | |
| case KEY_END: | |
| return "End"; | |
| case KEY_HOME: | |
| return "Home"; | |
| case KEY_INSERT: | |
| return "Insert"; | |
| case KEY_DELETE: | |
| return "Delete"; | |
| case KEY_ADD: | |
| return "Add"; | |
| case KEY_SUBTRACT: | |
| return "Substract"; | |
| case KEY_MULTIPLY: | |
| return "Multiply"; | |
| case KEY_DIVIDE: | |
| return "Divide"; | |
| case KEY_LEFT: | |
| return "Left"; | |
| case KEY_RIGHT: | |
| return "Right"; | |
| case KEY_UP: | |
| return "Up"; | |
| case KEY_DOWN: | |
| return "Down"; | |
| case KEY_NUMPAD0: | |
| return "Numpad 0"; | |
| case KEY_NUMPAD1: | |
| return "Numpad 1"; | |
| case KEY_NUMPAD2: | |
| return "Numpad 2"; | |
| case KEY_NUMPAD3: | |
| return "Numpad 3"; | |
| case KEY_NUMPAD4: | |
| return "Numpad 4"; | |
| case KEY_NUMPAD5: | |
| return "Numpad 5"; | |
| case KEY_NUMPAD6: | |
| return "Numpad 6"; | |
| case KEY_NUMPAD7: | |
| return "Numpad 7"; | |
| case KEY_NUMPAD8: | |
| return "Numpad 8"; | |
| case KEY_NUMPAD9: | |
| return "Numpad 9"; | |
| case KEY_F1: | |
| return "F1"; | |
| case KEY_F2: | |
| return "F2"; | |
| case KEY_F3: | |
| return "F3"; | |
| case KEY_F4: | |
| return "F4"; | |
| case KEY_F5: | |
| return "F5"; | |
| case KEY_F6: | |
| return "F6"; | |
| case KEY_F7: | |
| return "F7"; | |
| case KEY_F8: | |
| return "F8"; | |
| case KEY_F9: | |
| return "F9"; | |
| case KEY_F10: | |
| return "F10"; | |
| case KEY_F11: | |
| return "F11"; | |
| case KEY_F12: | |
| return "F12"; | |
| case KEY_F13: | |
| return "F13"; | |
| case KEY_F14: | |
| return "F14"; | |
| case KEY_F15: | |
| return "F15"; | |
| case KEY_PAUSE: | |
| return "Pause"; | |
| default: | |
| return "Unknown Key"; | |
| } | |
| } | |
| static std::string KeyState(const Event::KeyEvent &event) | |
| { | |
| if (event.Shift || event.Control || event.Alt || event.System) | |
| { | |
| std::ostringstream buffer; | |
| buffer << " ["; | |
| if (event.Shift) | |
| { | |
| buffer << "Shift"; | |
| } | |
| if (event.Control) | |
| { | |
| buffer << "Control"; | |
| } | |
| if (event.Alt) | |
| { | |
| buffer << "Alt"; | |
| } | |
| if (event.System) | |
| { | |
| buffer << "System"; | |
| } | |
| buffer << "]"; | |
| return buffer.str(); | |
| } | |
| return ""; | |
| } | |
| static void PrintEvent(const Event &event) | |
| { | |
| switch (event.Type) | |
| { | |
| case Event::EVENT_CLOSED: | |
| std::cout << "Event: Window Closed" << std::endl; | |
| break; | |
| case Event::EVENT_MOVED: | |
| std::cout << "Event: Window Moved (" << event.Move.X << ", " << event.Move.Y << ")" | |
| << std::endl; | |
| break; | |
| case Event::EVENT_RESIZED: | |
| std::cout << "Event: Window Resized (" << event.Size.Width << ", " << event.Size.Height | |
| << ")" << std::endl; | |
| break; | |
| case Event::EVENT_LOST_FOCUS: | |
| std::cout << "Event: Window Lost Focus" << std::endl; | |
| break; | |
| case Event::EVENT_GAINED_FOCUS: | |
| std::cout << "Event: Window Gained Focus" << std::endl; | |
| break; | |
| case Event::EVENT_TEXT_ENTERED: | |
| // TODO(cwallez) show the character | |
| std::cout << "Event: Text Entered" << std::endl; | |
| break; | |
| case Event::EVENT_KEY_PRESSED: | |
| std::cout << "Event: Key Pressed (" << KeyName(event.Key.Code) << KeyState(event.Key) | |
| << ")" << std::endl; | |
| break; | |
| case Event::EVENT_KEY_RELEASED: | |
| std::cout << "Event: Key Released (" << KeyName(event.Key.Code) << KeyState(event.Key) | |
| << ")" << std::endl; | |
| break; | |
| case Event::EVENT_MOUSE_WHEEL_MOVED: | |
| std::cout << "Event: Mouse Wheel (" << event.MouseWheel.Delta << ")" << std::endl; | |
| break; | |
| case Event::EVENT_MOUSE_BUTTON_PRESSED: | |
| std::cout << "Event: Mouse Button Pressed " << MouseButtonName(event.MouseButton.Button) | |
| << " at (" << event.MouseButton.X << ", " << event.MouseButton.Y << ")" | |
| << std::endl; | |
| break; | |
| case Event::EVENT_MOUSE_BUTTON_RELEASED: | |
| std::cout << "Event: Mouse Button Released " | |
| << MouseButtonName(event.MouseButton.Button) << " at (" << event.MouseButton.X | |
| << ", " << event.MouseButton.Y << ")" << std::endl; | |
| break; | |
| case Event::EVENT_MOUSE_MOVED: | |
| std::cout << "Event: Mouse Moved (" << event.MouseMove.X << ", " << event.MouseMove.Y | |
| << ")" << std::endl; | |
| break; | |
| case Event::EVENT_MOUSE_ENTERED: | |
| std::cout << "Event: Mouse Entered Window" << std::endl; | |
| break; | |
| case Event::EVENT_MOUSE_LEFT: | |
| std::cout << "Event: Mouse Left Window" << std::endl; | |
| break; | |
| case Event::EVENT_TEST: | |
| std::cout << "Event: Test" << std::endl; | |
| break; | |
| default: | |
| UNREACHABLE(); | |
| break; | |
| } | |
| } | |
| #endif | |
| OSWindow::OSWindow() : mX(0), mY(0), mWidth(0), mHeight(0), mValid(false), mIgnoreSizeEvents(false) | |
| {} | |
| OSWindow::~OSWindow() {} | |
| bool OSWindow::initialize(const std::string &name, int width, int height) | |
| { | |
| mValid = initializeImpl(name, width, height); | |
| return mValid; | |
| } | |
| int OSWindow::getX() const | |
| { | |
| return mX; | |
| } | |
| int OSWindow::getY() const | |
| { | |
| return mY; | |
| } | |
| int OSWindow::getWidth() const | |
| { | |
| return mWidth; | |
| } | |
| int OSWindow::getHeight() const | |
| { | |
| return mHeight; | |
| } | |
| bool OSWindow::takeScreenshot(uint8_t *pixelData) | |
| { | |
| return false; | |
| } | |
| void *OSWindow::getPlatformExtension() | |
| { | |
| return reinterpret_cast<void *>(getNativeWindow()); | |
| } | |
| bool OSWindow::popEvent(Event *event) | |
| { | |
| if (mEvents.size() > 0 && event) | |
| { | |
| *event = mEvents.front(); | |
| mEvents.pop_front(); | |
| return true; | |
| } | |
| else | |
| { | |
| return false; | |
| } | |
| } | |
| void OSWindow::pushEvent(Event event) | |
| { | |
| switch (event.Type) | |
| { | |
| case Event::EVENT_MOVED: | |
| mX = event.Move.X; | |
| mY = event.Move.Y; | |
| break; | |
| case Event::EVENT_RESIZED: | |
| mWidth = event.Size.Width; | |
| mHeight = event.Size.Height; | |
| break; | |
| default: | |
| break; | |
| } | |
| mEvents.push_back(event); | |
| #if DEBUG_EVENTS | |
| PrintEvent(event); | |
| #endif | |
| } | |
| bool OSWindow::didTestEventFire() | |
| { | |
| Event topEvent; | |
| while (popEvent(&topEvent)) | |
| { | |
| if (topEvent.Type == Event::EVENT_TEST) | |
| { | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| // static | |
| void OSWindow::Delete(OSWindow **window) | |
| { | |
| delete *window; | |
| *window = nullptr; | |
| } | |
| namespace angle | |
| { | |
| bool FindTestDataPath(const char *searchPath, char *dataPathOut, size_t maxDataPathOutLen) | |
| { | |
| #if defined(ANGLE_PLATFORM_ANDROID) | |
| const std::string searchPaths[] = { | |
| AndroidWindow::GetExternalStorageDirectory(), | |
| AndroidWindow::GetExternalStorageDirectory() + "/third_party/angle"}; | |
| #elif ANGLE_PLATFORM_IOS_FAMILY | |
| const std::string searchPaths[] = {GetExecutableDirectory(), | |
| GetExecutableDirectory() + "/third_party/angle"}; | |
| #else | |
| const std::string searchPaths[] = { | |
| GetExecutableDirectory(), GetExecutableDirectory() + "/../..", ".", | |
| GetExecutableDirectory() + "/../../third_party/angle", "third_party/angle"}; | |
| #endif // defined(ANGLE_PLATFORM_ANDROID) | |
| for (const std::string &path : searchPaths) | |
| { | |
| std::stringstream pathStream; | |
| pathStream << path << "/" << searchPath; | |
| std::string candidatePath = pathStream.str(); | |
| if (candidatePath.size() + 1 >= maxDataPathOutLen) | |
| { | |
| ERR() << "FindTestDataPath: Path too long."; | |
| return false; | |
| } | |
| if (angle::IsDirectory(candidatePath.c_str())) | |
| { | |
| memcpy(dataPathOut, candidatePath.c_str(), candidatePath.size() + 1); | |
| return true; | |
| } | |
| std::ifstream inFile(candidatePath.c_str()); | |
| if (!inFile.fail()) | |
| { | |
| memcpy(dataPathOut, candidatePath.c_str(), candidatePath.size() + 1); | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| } // namespace angle |