| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 //#include <tchar.h> | 8 //#include <tchar.h> |
| 9 | 9 |
| 10 #include "SkUtils.h" | 10 #include "SkUtils.h" |
| 11 #include "Timer.h" | 11 #include "Timer.h" |
| 12 #include "WindowContextFactory_mac.h" | 12 #include "WindowContextFactory_mac.h" |
| 13 #include "Window_mac.h" | 13 #include "Window_mac.h" |
| 14 | 14 |
| 15 namespace sk_app { | 15 namespace sk_app { |
| 16 | 16 |
| 17 Window* Window::CreateNativeWindow(void* platformData) { | 17 SkTDynamicHash<Window_mac, Uint32> Window_mac::gWindowMap; |
| 18 #if 0 | 18 |
| 19 // TODO: platform-specific window creation | 19 Window* Window::CreateNativeWindow(void*) { |
| 20 Display* display = (Display*)platformData; | |
| 21 | |
| 22 Window_mac* window = new Window_mac(); | 20 Window_mac* window = new Window_mac(); |
| 23 if (!window->initWindow(display, nullptr)) { | 21 if (!window->initWindow(nullptr)) { |
| 24 delete window; | 22 delete window; |
| 25 return nullptr; | 23 return nullptr; |
| 26 } | 24 } |
| 27 | 25 |
| 28 return window; | 26 return window; |
| 29 #else | 27 } |
| 30 return nullptr; | 28 |
| 31 #endif | 29 bool Window_mac::initWindow(const DisplayParams* params) { |
| 32 } | |
| 33 | |
| 34 #if 0 | |
| 35 // TODO: Implement Mac window code | |
| 36 | |
| 37 const long kEventMask = ExposureMask | StructureNotifyMask | | |
| 38 KeyPressMask | KeyReleaseMask | | |
| 39 PointerMotionMask | ButtonPressMask | ButtonReleaseMask; | |
| 40 | |
| 41 bool Window_mac::initWindow(Display* display, const DisplayParams* params) { | |
| 42 if (params && params->fMSAASampleCount != fMSAASampleCount) { | 30 if (params && params->fMSAASampleCount != fMSAASampleCount) { |
| 43 this->closeWindow(); | 31 this->closeWindow(); |
| 44 } | 32 } |
| 45 // we already have a window | 33 // we already have a window |
| 46 if (fDisplay) { | 34 if (fWindow) { |
| 47 return true; | 35 return true; |
| 48 } | 36 } |
| 49 fDisplay = display; | |
| 50 | 37 |
| 51 fWidth = 1280; | 38 fWidth = 1280; |
| 52 fHeight = 960; | 39 fHeight = 960; |
| 53 | 40 |
| 54 // Attempt to create a window that supports GL | 41 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); |
| 55 GLint att[] = { | 42 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); |
| 56 GLX_RGBA, | 43 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE
); |
| 57 GLX_DEPTH_SIZE, 24, | 44 |
| 58 GLX_DOUBLEBUFFER, | 45 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); |
| 59 GLX_STENCIL_SIZE, 8, | 46 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); |
| 60 None | 47 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); |
| 61 }; | 48 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); |
| 62 SkASSERT(nullptr == fVisualInfo); | 49 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0); |
| 50 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); |
| 51 |
| 52 SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); |
| 53 |
| 63 if (params && params->fMSAASampleCount > 0) { | 54 if (params && params->fMSAASampleCount > 0) { |
| 64 static const GLint kAttCount = SK_ARRAY_COUNT(att); | 55 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); |
| 65 GLint msaaAtt[kAttCount + 4]; | 56 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, params->fMSAASampleCount)
; |
| 66 memcpy(msaaAtt, att, sizeof(att)); | |
| 67 SkASSERT(None == msaaAtt[kAttCount - 1]); | |
| 68 msaaAtt[kAttCount - 1] = GLX_SAMPLE_BUFFERS_ARB; | |
| 69 msaaAtt[kAttCount + 0] = 1; | |
| 70 msaaAtt[kAttCount + 1] = GLX_SAMPLES_ARB; | |
| 71 msaaAtt[kAttCount + 2] = params->fMSAASampleCount; | |
| 72 msaaAtt[kAttCount + 3] = None; | |
| 73 fVisualInfo = glXChooseVisual(display, DefaultScreen(display), msaaAtt); | |
| 74 fMSAASampleCount = params->fMSAASampleCount; | |
| 75 } | |
| 76 if (nullptr == fVisualInfo) { | |
| 77 fVisualInfo = glXChooseVisual(display, DefaultScreen(display), att); | |
| 78 fMSAASampleCount = 0; | |
| 79 } | |
| 80 | |
| 81 if (fVisualInfo) { | |
| 82 Colormap colorMap = XCreateColormap(display, | |
| 83 RootWindow(display, fVisualInfo->scr
een), | |
| 84 fVisualInfo->visual, | |
| 85 AllocNone); | |
| 86 XSetWindowAttributes swa; | |
| 87 swa.colormap = colorMap; | |
| 88 swa.event_mask = kEventMask; | |
| 89 fWindow = XCreateWindow(display, | |
| 90 RootWindow(display, fVisualInfo->screen), | |
| 91 0, 0, // x, y | |
| 92 fWidth, fHeight, | |
| 93 0, // border width | |
| 94 fVisualInfo->depth, | |
| 95 InputOutput, | |
| 96 fVisualInfo->visual, | |
| 97 CWEventMask | CWColormap, | |
| 98 &swa); | |
| 99 } else { | 57 } else { |
| 100 // Create a simple window instead. We will not be able to show GL | 58 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); |
| 101 fWindow = XCreateSimpleWindow(display, | 59 } |
| 102 DefaultRootWindow(display), | 60 // TODO: handle other display params |
| 103 0, 0, // x, y | 61 |
| 104 fWidth, fHeight, | 62 uint32_t windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; |
| 105 0, // border width | 63 fWindow = SDL_CreateWindow("SDL Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWP
OS_CENTERED, |
| 106 0, // border value | 64 fWidth, fHeight, windowFlags); |
| 107 0); // background value | |
| 108 XSelectInput(display, fWindow, kEventMask); | |
| 109 } | |
| 110 | 65 |
| 111 if (!fWindow) { | 66 if (!fWindow) { |
| 112 return false; | 67 return false; |
| 113 } | 68 } |
| 114 | 69 |
| 115 // set up to catch window delete message | |
| 116 fWmDeleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", False); | |
| 117 XSetWMProtocols(display, fWindow, &fWmDeleteMessage, 1); | |
| 118 | |
| 119 // add to hashtable of windows | 70 // add to hashtable of windows |
| 71 fWindowID = SDL_GetWindowID(fWindow); |
| 120 gWindowMap.add(this); | 72 gWindowMap.add(this); |
| 121 | 73 |
| 122 // init event variables | |
| 123 fPendingPaint = false; | |
| 124 fPendingResize = false; | |
| 125 | |
| 126 return true; | 74 return true; |
| 127 } | 75 } |
| 128 | 76 |
| 129 void Window_mac::closeWindow() { | 77 void Window_mac::closeWindow() { |
| 130 if (fDisplay) { | 78 if (fWindow) { |
| 131 this->detach(); | 79 gWindowMap.remove(fWindowID); |
| 132 SkASSERT(fGC); | 80 SDL_DestroyWindow(fWindow); |
| 133 XFreeGC(fDisplay, fGC); | 81 fWindowID = 0; |
| 134 fGC = nullptr; | 82 fWindow = nullptr; |
| 135 gWindowMap.remove(fWindow); | 83 } |
| 136 XDestroyWindow(fDisplay, fWindow); | 84 } |
| 137 fWindow = 0; | 85 |
| 138 fVisualInfo = nullptr; | 86 static Window::Key get_key(const SDL_Keysym& keysym) { |
| 139 fDisplay = nullptr; | |
| 140 fMSAASampleCount = 0; | |
| 141 } | |
| 142 } | |
| 143 | |
| 144 static Window::Key get_key(KeySym keysym) { | |
| 145 static const struct { | 87 static const struct { |
| 146 KeySym fXK; | 88 SDL_Keycode fSDLK; |
| 147 Window::Key fKey; | 89 Window::Key fKey; |
| 148 } gPair[] = { | 90 } gPair[] = { |
| 149 { XK_BackSpace, Window::Key::kBack }, | 91 { SDLK_BACKSPACE, Window::Key::kBack }, |
| 150 { XK_Clear, Window::Key::kBack }, | 92 { SDLK_CLEAR, Window::Key::kBack }, |
| 151 { XK_Return, Window::Key::kOK }, | 93 { SDLK_RETURN, Window::Key::kOK }, |
| 152 { XK_Up, Window::Key::kUp }, | 94 { SDLK_UP, Window::Key::kUp }, |
| 153 { XK_Down, Window::Key::kDown }, | 95 { SDLK_DOWN, Window::Key::kDown }, |
| 154 { XK_Left, Window::Key::kLeft }, | 96 { SDLK_LEFT, Window::Key::kLeft }, |
| 155 { XK_Right, Window::Key::kRight } | 97 { SDLK_RIGHT, Window::Key::kRight } |
| 156 }; | 98 }; |
| 157 for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) { | 99 for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) { |
| 158 if (gPair[i].fXK == keysym) { | 100 if (gPair[i].fSDLK == keysym.sym) { |
| 159 return gPair[i].fKey; | 101 return gPair[i].fKey; |
| 160 } | 102 } |
| 161 } | 103 } |
| 162 return Window::Key::kNONE; | 104 return Window::Key::kNONE; |
| 163 } | 105 } |
| 164 | 106 |
| 165 static uint32_t get_modifiers(const XEvent& event) { | 107 static uint32_t get_modifiers(const SDL_Event& event) { |
| 166 static const struct { | 108 static const struct { |
| 167 unsigned fXMask; | 109 unsigned fSDLMask; |
| 168 unsigned fSkMask; | 110 unsigned fSkMask; |
| 169 } gModifiers[] = { | 111 } gModifiers[] = { |
| 170 { ShiftMask, Window::kShift_ModifierKey }, | 112 { KMOD_SHIFT, Window::kShift_ModifierKey }, |
| 171 { ControlMask, Window::kControl_ModifierKey }, | 113 { KMOD_CTRL, Window::kControl_ModifierKey }, |
| 172 { Mod1Mask, Window::kOption_ModifierKey }, | 114 { KMOD_ALT, Window::kOption_ModifierKey }, |
| 173 }; | 115 }; |
| 174 | 116 |
| 175 auto modifiers = 0; | 117 auto modifiers = 0; |
| 176 for (size_t i = 0; i < SK_ARRAY_COUNT(gModifiers); ++i) { | 118 |
| 177 if (event.xkey.state & gModifiers[i].fXMask) { | 119 switch (event.type) { |
| 178 modifiers |= gModifiers[i].fSkMask; | 120 case SDL_KEYDOWN: |
| 121 // fall through |
| 122 case SDL_KEYUP: { |
| 123 for (size_t i = 0; i < SK_ARRAY_COUNT(gModifiers); ++i) { |
| 124 if (event.key.keysym.mod & gModifiers[i].fSDLMask) { |
| 125 modifiers |= gModifiers[i].fSkMask; |
| 126 } |
| 127 } |
| 128 if (0 == event.key.repeat) { |
| 129 modifiers |= Window::kFirstPress_ModifierKey; |
| 130 } |
| 131 break; |
| 179 } | 132 } |
| 133 |
| 134 default: { |
| 135 SDL_Keymod mod = SDL_GetModState(); |
| 136 for (size_t i = 0; i < SK_ARRAY_COUNT(gModifiers); ++i) { |
| 137 if (mod & gModifiers[i].fSDLMask) { |
| 138 modifiers |= gModifiers[i].fSkMask; |
| 139 } |
| 140 } |
| 141 break; |
| 142 } |
| 180 } | 143 } |
| 181 return modifiers; | 144 return modifiers; |
| 182 } | 145 } |
| 183 | 146 |
| 184 bool Window_mac::handleEvent(const XEvent& event) { | 147 bool Window_mac::HandleWindowEvent(const SDL_Event& event) { |
| 148 Window_mac* win = gWindowMap.find(event.window.windowID); |
| 149 if (win && win->handleEvent(event)) { |
| 150 return true; |
| 151 } |
| 152 |
| 153 return false; |
| 154 } |
| 155 |
| 156 bool Window_mac::handleEvent(const SDL_Event& event) { |
| 185 switch (event.type) { | 157 switch (event.type) { |
| 186 case MapNotify: | 158 case SDL_WINDOWEVENT: |
| 187 if (!fGC) { | 159 if (SDL_WINDOWEVENT_EXPOSED == event.window.event) { |
| 188 fGC = XCreateGC(fDisplay, fWindow, 0, nullptr); | 160 this->onPaint(); |
| 189 } | 161 } else if (SDL_WINDOWEVENT_RESIZED == event.window.event) { |
| 190 break; | 162 this->onResize(event.window.data1, event.window.data2); |
| 191 | 163 } |
| 192 case ClientMessage: | 164 break; |
| 193 if ((Atom)event.xclient.data.l[0] == fWmDeleteMessage && | 165 |
| 194 gWindowMap.count() == 1) { | 166 case SDL_MOUSEBUTTONDOWN: |
| 167 if (event.button.button == SDL_BUTTON_LEFT) { |
| 168 this->onMouse(event.button.x, event.button.y, |
| 169 Window::kDown_InputState, get_modifiers(event)); |
| 170 } |
| 171 break; |
| 172 |
| 173 case SDL_MOUSEBUTTONUP: |
| 174 if (event.button.button == SDL_BUTTON_LEFT) { |
| 175 this->onMouse(event.button.x, event.button.y, |
| 176 Window::kUp_InputState, get_modifiers(event)); |
| 177 } |
| 178 break; |
| 179 |
| 180 case SDL_MOUSEMOTION: |
| 181 // only track if left button is down |
| 182 if (event.motion.state & SDL_BUTTON_LMASK) { |
| 183 this->onMouse(event.motion.x, event.motion.y, |
| 184 Window::kMove_InputState, get_modifiers(event)); |
| 185 } |
| 186 break; |
| 187 |
| 188 case SDL_KEYDOWN: { |
| 189 if (event.key.keysym.sym == SDLK_ESCAPE) { |
| 195 return true; | 190 return true; |
| 196 } | 191 } |
| 197 break; | 192 Window::Key key = get_key(event.key.keysym); |
| 198 | |
| 199 case ButtonPress: | |
| 200 if (event.xbutton.button == Button1) { | |
| 201 this->onMouse(event.xbutton.x, event.xbutton.y, | |
| 202 Window::kDown_InputState, get_modifiers(event)); | |
| 203 } | |
| 204 break; | |
| 205 | |
| 206 case ButtonRelease: | |
| 207 if (event.xbutton.button == Button1) { | |
| 208 this->onMouse(event.xbutton.x, event.xbutton.y, | |
| 209 Window::kUp_InputState, get_modifiers(event)); | |
| 210 } | |
| 211 break; | |
| 212 | |
| 213 case MotionNotify: | |
| 214 // only track if left button is down | |
| 215 if (event.xmotion.state & Button1Mask) { | |
| 216 this->onMouse(event.xmotion.x, event.xmotion.y, | |
| 217 Window::kMove_InputState, get_modifiers(event)); | |
| 218 } | |
| 219 break; | |
| 220 | |
| 221 case KeyPress: { | |
| 222 int shiftLevel = (event.xkey.state & ShiftMask) ? 1 : 0; | |
| 223 KeySym keysym = XkbKeycodeToKeysym(fDisplay, event.xkey.keycode, | |
| 224 0, shiftLevel); | |
| 225 if (keysym == XK_Escape) { | |
| 226 return true; | |
| 227 } | |
| 228 Window::Key key = get_key(keysym); | |
| 229 if (key != Window::Key::kNONE) { | 193 if (key != Window::Key::kNONE) { |
| 230 (void) this->onKey(key, Window::kDown_InputState, | 194 (void) this->onKey(key, Window::kDown_InputState, |
| 231 get_modifiers(event)); | 195 get_modifiers(event)); |
| 232 } else { | 196 } else { |
| 233 long uni = keysym2ucs(keysym); | 197 (void) this->onChar((SkUnichar) event.key.keysym.sym, |
| 234 if (uni != -1) { | 198 get_modifiers(event)); |
| 235 (void) this->onChar((SkUnichar) uni, | |
| 236 get_modifiers(event)); | |
| 237 } | |
| 238 } | 199 } |
| 239 } break; | 200 } break; |
| 240 | 201 |
| 241 case KeyRelease: { | 202 case SDL_KEYUP: { |
| 242 int shiftLevel = (event.xkey.state & ShiftMask) ? 1 : 0; | 203 Window::Key key = get_key(event.key.keysym); |
| 243 KeySym keysym = XkbKeycodeToKeysym(fDisplay, event.xkey.keycode, | 204 if (key != Window::Key::kNONE) { |
| 244 0, shiftLevel); | 205 (void) this->onKey(key, Window::kUp_InputState, |
| 245 Window::Key key = get_key(keysym); | 206 get_modifiers(event)); |
| 246 (void) this->onKey(key, Window::kUp_InputState, | 207 } |
| 247 get_modifiers(event)); | |
| 248 } break; | 208 } break; |
| 249 | |
| 250 | 209 |
| 251 default: | 210 default: |
| 252 // these events should be handled in the main event loop | 211 break; |
| 253 SkASSERT(event.type != Expose && event.type != ConfigureNotify); | 212 } |
| 254 break; | 213 |
| 255 } | |
| 256 | |
| 257 return false; | 214 return false; |
| 258 } | 215 } |
| 259 | 216 |
| 260 void Window_mac::setTitle(const char* title) { | 217 void Window_mac::setTitle(const char* title) { |
| 261 XTextProperty textproperty; | 218 SDL_SetWindowTitle(fWindow, title); |
| 262 XStringListToTextProperty(const_cast<char**>(&title), 1, &textproperty); | |
| 263 XSetWMName(fDisplay, fWindow, &textproperty); | |
| 264 } | 219 } |
| 265 | 220 |
| 266 void Window_mac::show() { | 221 void Window_mac::show() { |
| 267 XMapWindow(fDisplay, fWindow); | 222 SDL_ShowWindow(fWindow); |
| 268 } | 223 } |
| 269 | 224 |
| 270 bool Window_mac::attach(BackendType attachType, const DisplayParams& params) { | 225 bool Window_mac::attach(BackendType attachType, const DisplayParams& params) { |
| 271 this->initWindow(fDisplay, ¶ms); | 226 this->initWindow(¶ms); |
| 272 | 227 |
| 273 MacWindowInfo info; | 228 window_context_factory::MacWindowInfo info; |
| 274 #if 0 | 229 info.fWindow = fWindow; |
| 275 // Init Mac window info here | |
| 276 info.foo = foo; | |
| 277 #endif | |
| 278 switch (attachType) { | 230 switch (attachType) { |
| 279 #ifdef SK_VULKAN | |
| 280 case kVulkan_BackendType: | |
| 281 fWindowContext = NewVulkanForMac(info, params); | |
| 282 break; | |
| 283 #endif | |
| 284 case kNativeGL_BackendType: | 231 case kNativeGL_BackendType: |
| 285 default: | 232 default: |
| 286 fWindowContext = NewGLForMac(info, params); | 233 fWindowContext = NewGLForMac(info, params); |
| 287 break; | 234 break; |
| 288 } | 235 } |
| 289 | 236 |
| 290 return (SkToBool(fWindowContext)); | 237 return (SkToBool(fWindowContext)); |
| 291 } | 238 } |
| 292 | 239 |
| 293 void Window_mac::onInval() { | 240 void Window_mac::onInval() { |
| 294 XEvent event; | 241 SDL_Event sdlevent; |
| 295 event.type = Expose; | 242 sdlevent.type = SDL_WINDOWEVENT; |
| 296 event.xexpose.send_event = True; | 243 sdlevent.window.windowID = fWindowID; |
| 297 event.xexpose.display = fDisplay; | 244 sdlevent.window.event = SDL_WINDOWEVENT_EXPOSED; |
| 298 event.xexpose.window = fWindow; | 245 SDL_PushEvent(&sdlevent); |
| 299 event.xexpose.x = 0; | |
| 300 event.xexpose.y = 0; | |
| 301 event.xexpose.width = fWidth; | |
| 302 event.xexpose.height = fHeight; | |
| 303 event.xexpose.count = 0; | |
| 304 | |
| 305 XSendEvent(fDisplay, fWindow, False, 0, &event); | |
| 306 } | 246 } |
| 307 #endif | 247 |
| 308 | |
| 309 } // namespace sk_app | 248 } // namespace sk_app |
| OLD | NEW |