aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/sk_app/ios/Window_ios.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/sk_app/ios/Window_ios.cpp')
-rw-r--r--tools/sk_app/ios/Window_ios.cpp277
1 files changed, 277 insertions, 0 deletions
diff --git a/tools/sk_app/ios/Window_ios.cpp b/tools/sk_app/ios/Window_ios.cpp
new file mode 100644
index 0000000000..c1bdeae5fc
--- /dev/null
+++ b/tools/sk_app/ios/Window_ios.cpp
@@ -0,0 +1,277 @@
+/*
+* Copyright 2017 Google Inc.
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#include "SkUtils.h"
+#include "Timer.h"
+#include "WindowContextFactory_ios.h"
+#include "Window_ios.h"
+
+namespace sk_app {
+
+SkTDynamicHash<Window_ios, Uint32> Window_ios::gWindowMap;
+
+Window* Window::CreateNativeWindow(void*) {
+ Window_ios* window = new Window_ios();
+ if (!window->initWindow()) {
+ delete window;
+ return nullptr;
+ }
+
+ return window;
+}
+
+bool Window_ios::initWindow() {
+ if (fRequestedDisplayParams.fMSAASampleCount != fMSAASampleCount) {
+ this->closeWindow();
+ }
+ // we already have a window
+ if (fWindow) {
+ return true;
+ }
+
+ constexpr int initialWidth = 1280;
+ constexpr int initialHeight = 960;
+
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
+
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
+ SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
+
+ SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
+
+ if (fRequestedDisplayParams.fMSAASampleCount > 0) {
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, fRequestedDisplayParams.fMSAASampleCount);
+ } else {
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
+ }
+ // TODO: handle other display params
+
+ uint32_t windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN | SDL_WINDOW_ALLOW_HIGHDPI;
+ fWindow = SDL_CreateWindow("SDL Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+ initialWidth, initialHeight, windowFlags);
+
+ if (!fWindow) {
+ return false;
+ }
+
+ fMSAASampleCount = fRequestedDisplayParams.fMSAASampleCount;
+
+ // add to hashtable of windows
+ fWindowID = SDL_GetWindowID(fWindow);
+ gWindowMap.add(this);
+
+ return true;
+}
+
+void Window_ios::closeWindow() {
+ if (fWindow) {
+ gWindowMap.remove(fWindowID);
+ SDL_DestroyWindow(fWindow);
+ fWindowID = 0;
+ fWindow = nullptr;
+ }
+}
+
+static Window::Key get_key(const SDL_Keysym& keysym) {
+ static const struct {
+ SDL_Keycode fSDLK;
+ Window::Key fKey;
+ } gPair[] = {
+ { SDLK_BACKSPACE, Window::Key::kBack },
+ { SDLK_CLEAR, Window::Key::kBack },
+ { SDLK_RETURN, Window::Key::kOK },
+ { SDLK_UP, Window::Key::kUp },
+ { SDLK_DOWN, Window::Key::kDown },
+ { SDLK_LEFT, Window::Key::kLeft },
+ { SDLK_RIGHT, Window::Key::kRight },
+ { SDLK_TAB, Window::Key::kTab },
+ { SDLK_PAGEUP, Window::Key::kPageUp },
+ { SDLK_PAGEDOWN, Window::Key::kPageDown },
+ { SDLK_HOME, Window::Key::kHome },
+ { SDLK_END, Window::Key::kEnd },
+ { SDLK_DELETE, Window::Key::kDelete },
+ { SDLK_ESCAPE, Window::Key::kEscape },
+ { SDLK_LSHIFT, Window::Key::kShift },
+ { SDLK_RSHIFT, Window::Key::kShift },
+ { SDLK_LCTRL, Window::Key::kCtrl },
+ { SDLK_RCTRL, Window::Key::kCtrl },
+ { SDLK_LALT, Window::Key::kOption },
+ { SDLK_LALT, Window::Key::kOption },
+ { 'A', Window::Key::kA },
+ { 'C', Window::Key::kC },
+ { 'V', Window::Key::kV },
+ { 'X', Window::Key::kX },
+ { 'Y', Window::Key::kY },
+ { 'Z', Window::Key::kZ },
+ };
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
+ if (gPair[i].fSDLK == keysym.sym) {
+ return gPair[i].fKey;
+ }
+ }
+ return Window::Key::kNONE;
+}
+
+static uint32_t get_modifiers(const SDL_Event& event) {
+ static const struct {
+ unsigned fSDLMask;
+ unsigned fSkMask;
+ } gModifiers[] = {
+ { KMOD_SHIFT, Window::kShift_ModifierKey },
+ { KMOD_CTRL, Window::kControl_ModifierKey },
+ { KMOD_ALT, Window::kOption_ModifierKey },
+ };
+
+ auto modifiers = 0;
+
+ switch (event.type) {
+ case SDL_KEYDOWN:
+ // fall through
+ case SDL_KEYUP: {
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gModifiers); ++i) {
+ if (event.key.keysym.mod & gModifiers[i].fSDLMask) {
+ modifiers |= gModifiers[i].fSkMask;
+ }
+ }
+ if (0 == event.key.repeat) {
+ modifiers |= Window::kFirstPress_ModifierKey;
+ }
+ break;
+ }
+
+ default: {
+ SDL_Keymod mod = SDL_GetModState();
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gModifiers); ++i) {
+ if (mod & gModifiers[i].fSDLMask) {
+ modifiers |= gModifiers[i].fSkMask;
+ }
+ }
+ break;
+ }
+ }
+ return modifiers;
+}
+
+bool Window_ios::HandleWindowEvent(const SDL_Event& event) {
+ Window_ios* win = gWindowMap.find(event.window.windowID);
+ if (win && win->handleEvent(event)) {
+ return true;
+ }
+
+ return false;
+}
+
+bool Window_ios::handleEvent(const SDL_Event& event) {
+ switch (event.type) {
+ case SDL_WINDOWEVENT:
+ if (SDL_WINDOWEVENT_EXPOSED == event.window.event) {
+ this->onPaint();
+ } else if (SDL_WINDOWEVENT_RESIZED == event.window.event) {
+ this->onResize(event.window.data1, event.window.data2);
+ }
+ break;
+
+ case SDL_MOUSEBUTTONDOWN:
+ if (event.button.button == SDL_BUTTON_LEFT) {
+ this->onMouse(event.button.x, event.button.y,
+ Window::kDown_InputState, get_modifiers(event));
+ }
+ break;
+
+ case SDL_MOUSEBUTTONUP:
+ if (event.button.button == SDL_BUTTON_LEFT) {
+ this->onMouse(event.button.x, event.button.y,
+ Window::kUp_InputState, get_modifiers(event));
+ }
+ break;
+
+ case SDL_MOUSEMOTION:
+ this->onMouse(event.motion.x, event.motion.y,
+ Window::kMove_InputState, get_modifiers(event));
+ break;
+
+ case SDL_MOUSEWHEEL:
+ this->onMouseWheel(event.wheel.y, get_modifiers(event));
+ break;
+
+ case SDL_KEYDOWN: {
+ Window::Key key = get_key(event.key.keysym);
+ if (key != Window::Key::kNONE) {
+ if (!this->onKey(key, Window::kDown_InputState, get_modifiers(event))) {
+ if (event.key.keysym.sym == SDLK_ESCAPE) {
+ return true;
+ }
+ }
+ }
+ } break;
+
+ case SDL_KEYUP: {
+ Window::Key key = get_key(event.key.keysym);
+ if (key != Window::Key::kNONE) {
+ (void) this->onKey(key, Window::kUp_InputState,
+ get_modifiers(event));
+ }
+ } break;
+
+ case SDL_TEXTINPUT: {
+ const char* textIter = &event.text.text[0];
+ while (SkUnichar c = SkUTF8_NextUnichar(&textIter)) {
+ (void) this->onChar(c, get_modifiers(event));
+ }
+ } break;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+void Window_ios::setTitle(const char* title) {
+ SDL_SetWindowTitle(fWindow, title);
+}
+
+void Window_ios::show() {
+ SDL_ShowWindow(fWindow);
+}
+
+bool Window_ios::attach(BackendType attachType) {
+ this->initWindow();
+
+ window_context_factory::IOSWindowInfo info;
+ info.fWindow = fWindow;
+ switch (attachType) {
+ case kRaster_BackendType:
+ fWindowContext = NewRasterForIOS(info, fRequestedDisplayParams);
+ break;
+
+ case kNativeGL_BackendType:
+ default:
+ fWindowContext = NewGLForIOS(info, fRequestedDisplayParams);
+ break;
+ }
+ this->onBackendCreated();
+
+ return (SkToBool(fWindowContext));
+}
+
+void Window_ios::onInval() {
+ SDL_Event sdlevent;
+ sdlevent.type = SDL_WINDOWEVENT;
+ sdlevent.window.windowID = fWindowID;
+ sdlevent.window.event = SDL_WINDOWEVENT_EXPOSED;
+ SDL_PushEvent(&sdlevent);
+}
+
+} // namespace sk_app