Window_ios.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /*
  2. * Copyright 2017 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "src/core/SkUtils.h"
  8. #include "tools/ModifierKey.h"
  9. #include "tools/sk_app/ios/WindowContextFactory_ios.h"
  10. #include "tools/sk_app/ios/Window_ios.h"
  11. #include "tools/timer/Timer.h"
  12. namespace sk_app {
  13. SkTDynamicHash<Window_ios, Uint32> Window_ios::gWindowMap;
  14. Window* Window::CreateNativeWindow(void*) {
  15. Window_ios* window = new Window_ios();
  16. if (!window->initWindow()) {
  17. delete window;
  18. return nullptr;
  19. }
  20. return window;
  21. }
  22. bool Window_ios::initWindow() {
  23. if (fRequestedDisplayParams.fMSAASampleCount != fMSAASampleCount) {
  24. this->closeWindow();
  25. }
  26. // we already have a window
  27. if (fWindow) {
  28. return true;
  29. }
  30. constexpr int initialWidth = 1280;
  31. constexpr int initialHeight = 960;
  32. SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
  33. SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
  34. SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
  35. SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
  36. SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
  37. SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
  38. SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
  39. SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
  40. SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
  41. SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
  42. if (fRequestedDisplayParams.fMSAASampleCount > 1) {
  43. SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
  44. SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, fRequestedDisplayParams.fMSAASampleCount);
  45. } else {
  46. SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
  47. }
  48. // TODO: handle other display params
  49. uint32_t windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN | SDL_WINDOW_ALLOW_HIGHDPI;
  50. fWindow = SDL_CreateWindow("SDL Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
  51. initialWidth, initialHeight, windowFlags);
  52. if (!fWindow) {
  53. return false;
  54. }
  55. fMSAASampleCount = fRequestedDisplayParams.fMSAASampleCount;
  56. // add to hashtable of windows
  57. fWindowID = SDL_GetWindowID(fWindow);
  58. gWindowMap.add(this);
  59. fGLContext = SDL_GL_CreateContext(fWindow);
  60. if (!fGLContext) {
  61. SkDebugf("%s\n", SDL_GetError());
  62. this->closeWindow();
  63. return false;
  64. }
  65. return true;
  66. }
  67. void Window_ios::closeWindow() {
  68. if (fGLContext) {
  69. SDL_GL_DeleteContext(fGLContext);
  70. fGLContext = nullptr;
  71. }
  72. if (fWindow) {
  73. gWindowMap.remove(fWindowID);
  74. SDL_DestroyWindow(fWindow);
  75. fWindowID = 0;
  76. fWindow = nullptr;
  77. }
  78. }
  79. static Window::Key get_key(const SDL_Keysym& keysym) {
  80. static const struct {
  81. SDL_Keycode fSDLK;
  82. Window::Key fKey;
  83. } gPair[] = {
  84. { SDLK_BACKSPACE, Window::Key::kBack },
  85. { SDLK_CLEAR, Window::Key::kBack },
  86. { SDLK_RETURN, Window::Key::kOK },
  87. { SDLK_UP, Window::Key::kUp },
  88. { SDLK_DOWN, Window::Key::kDown },
  89. { SDLK_LEFT, Window::Key::kLeft },
  90. { SDLK_RIGHT, Window::Key::kRight },
  91. { SDLK_TAB, Window::Key::kTab },
  92. { SDLK_PAGEUP, Window::Key::kPageUp },
  93. { SDLK_PAGEDOWN, Window::Key::kPageDown },
  94. { SDLK_HOME, Window::Key::kHome },
  95. { SDLK_END, Window::Key::kEnd },
  96. { SDLK_DELETE, Window::Key::kDelete },
  97. { SDLK_ESCAPE, Window::Key::kEscape },
  98. { SDLK_LSHIFT, Window::Key::kShift },
  99. { SDLK_RSHIFT, Window::Key::kShift },
  100. { SDLK_LCTRL, Window::Key::kCtrl },
  101. { SDLK_RCTRL, Window::Key::kCtrl },
  102. { SDLK_LALT, Window::Key::kOption },
  103. { SDLK_LALT, Window::Key::kOption },
  104. { 'A', Window::Key::kA },
  105. { 'C', Window::Key::kC },
  106. { 'V', Window::Key::kV },
  107. { 'X', Window::Key::kX },
  108. { 'Y', Window::Key::kY },
  109. { 'Z', Window::Key::kZ },
  110. };
  111. for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
  112. if (gPair[i].fSDLK == keysym.sym) {
  113. return gPair[i].fKey;
  114. }
  115. }
  116. return Window::Key::kNONE;
  117. }
  118. static ModifierKey get_modifiers(const SDL_Event& event) {
  119. static const struct {
  120. unsigned fSDLMask;
  121. ModifierKey fSkMask;
  122. } gModifiers[] = {
  123. { KMOD_SHIFT, ModifierKey::kShift },
  124. { KMOD_CTRL, ModifierKey::kControl },
  125. { KMOD_ALT, ModifierKey::kOption },
  126. };
  127. ModifierKey modifiers = ModifierKey::kNone;
  128. switch (event.type) {
  129. case SDL_KEYDOWN:
  130. // fall through
  131. case SDL_KEYUP: {
  132. for (size_t i = 0; i < SK_ARRAY_COUNT(gModifiers); ++i) {
  133. if (event.key.keysym.mod & gModifiers[i].fSDLMask) {
  134. modifiers |= gModifiers[i].fSkMask;
  135. }
  136. }
  137. if (0 == event.key.repeat) {
  138. modifiers |= ModifierKey::kFirstPress;
  139. }
  140. break;
  141. }
  142. default: {
  143. SDL_Keymod mod = SDL_GetModState();
  144. for (size_t i = 0; i < SK_ARRAY_COUNT(gModifiers); ++i) {
  145. if (mod & gModifiers[i].fSDLMask) {
  146. modifiers |= gModifiers[i].fSkMask;
  147. }
  148. }
  149. break;
  150. }
  151. }
  152. return modifiers;
  153. }
  154. bool Window_ios::HandleWindowEvent(const SDL_Event& event) {
  155. Window_ios* win = gWindowMap.find(event.window.windowID);
  156. if (win && win->handleEvent(event)) {
  157. return true;
  158. }
  159. return false;
  160. }
  161. bool Window_ios::handleEvent(const SDL_Event& event) {
  162. switch (event.type) {
  163. case SDL_WINDOWEVENT:
  164. if (SDL_WINDOWEVENT_EXPOSED == event.window.event) {
  165. this->onPaint();
  166. } else if (SDL_WINDOWEVENT_RESIZED == event.window.event) {
  167. this->onResize(event.window.data1, event.window.data2);
  168. }
  169. break;
  170. case SDL_FINGERDOWN:
  171. this->onTouch(event.tfinger.fingerId, InputState::kDown,
  172. (int)(this->width()*event.tfinger.x),
  173. (int)(this->height()*event.tfinger.y));
  174. break;
  175. case SDL_FINGERUP:
  176. this->onTouch(event.tfinger.fingerId, InputState::kUp,
  177. (int)(this->width()*event.tfinger.x),
  178. (int)(this->height()*event.tfinger.y));
  179. break;
  180. case SDL_FINGERMOTION:
  181. this->onTouch(event.tfinger.fingerId, InputState::kMove,
  182. (int)(this->width()*event.tfinger.x),
  183. (int)(this->height()*event.tfinger.y));
  184. break;
  185. case SDL_KEYDOWN: {
  186. Window::Key key = get_key(event.key.keysym);
  187. if (key != Window::Key::kNONE) {
  188. if (!this->onKey(key, InputState::kDown, get_modifiers(event))) {
  189. if (event.key.keysym.sym == SDLK_ESCAPE) {
  190. return true;
  191. }
  192. }
  193. }
  194. } break;
  195. case SDL_KEYUP: {
  196. Window::Key key = get_key(event.key.keysym);
  197. if (key != Window::Key::kNONE) {
  198. (void) this->onKey(key, InputState::kUp,
  199. get_modifiers(event));
  200. }
  201. } break;
  202. case SDL_TEXTINPUT: {
  203. const char* textIter = &event.text.text[0];
  204. while (SkUnichar c = SkUTF8_NextUnichar(&textIter)) {
  205. (void) this->onChar(c, get_modifiers(event));
  206. }
  207. } break;
  208. default:
  209. break;
  210. }
  211. return false;
  212. }
  213. void Window_ios::setTitle(const char* title) {
  214. SDL_SetWindowTitle(fWindow, title);
  215. }
  216. void Window_ios::show() {
  217. SDL_ShowWindow(fWindow);
  218. }
  219. bool Window_ios::attach(BackendType attachType) {
  220. this->initWindow();
  221. window_context_factory::IOSWindowInfo info;
  222. info.fWindow = fWindow;
  223. info.fGLContext = fGLContext;
  224. switch (attachType) {
  225. case kRaster_BackendType:
  226. fWindowContext = NewRasterForIOS(info, fRequestedDisplayParams);
  227. break;
  228. case kNativeGL_BackendType:
  229. default:
  230. fWindowContext = NewGLForIOS(info, fRequestedDisplayParams);
  231. break;
  232. }
  233. this->onBackendCreated();
  234. return (SkToBool(fWindowContext));
  235. }
  236. void Window_ios::onInval() {
  237. SDL_Event sdlevent;
  238. sdlevent.type = SDL_WINDOWEVENT;
  239. sdlevent.window.windowID = fWindowID;
  240. sdlevent.window.event = SDL_WINDOWEVENT_EXPOSED;
  241. SDL_PushEvent(&sdlevent);
  242. }
  243. } // namespace sk_app