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 | |
19 // TODO: platform-specific window creation | |
20 Display* display = (Display*)platformData; | |
21 | 18 |
19 Window* Window::CreateNativeWindow(void*) { | |
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 | |
30 return nullptr; | |
31 #endif | |
32 } | 27 } |
33 | |
34 #if 0 | |
35 // TODO: Implement Mac window code | |
36 | 28 |
37 const long kEventMask = ExposureMask | StructureNotifyMask | | 29 bool Window_mac::initWindow(const DisplayParams* params) { |
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)); | 57 } else { |
67 SkASSERT(None == msaaAtt[kAttCount - 1]); | 58 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); |
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 } | 59 } |
76 if (nullptr == fVisualInfo) { | 60 // TODO: handle other display params |
77 fVisualInfo = glXChooseVisual(display, DefaultScreen(display), att); | |
78 fMSAASampleCount = 0; | |
79 } | |
80 | 61 |
81 if (fVisualInfo) { | 62 uint32_t windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; |
robertphillips
2016/08/03 21:22:04
overlength ?
jvanverth1
2016/08/04 15:28:33
Done.
| |
82 Colormap colorMap = XCreateColormap(display, | 63 fWindow = SDL_CreateWindow("SDL Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWP OS_CENTERED, fWidth, fHeight, windowFlags); |
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 { | |
100 // Create a simple window instead. We will not be able to show GL | |
101 fWindow = XCreateSimpleWindow(display, | |
102 DefaultRootWindow(display), | |
103 0, 0, // x, y | |
104 fWidth, fHeight, | |
105 0, // border width | |
106 0, // border value | |
107 0); // background value | |
108 XSelectInput(display, fWindow, kEventMask); | |
109 } | |
110 | 64 |
111 if (!fWindow) { | 65 if (!fWindow) { |
112 return false; | 66 return false; |
113 } | 67 } |
114 | 68 |
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 | 69 // add to hashtable of windows |
70 fWindowID = SDL_GetWindowID(fWindow); | |
120 gWindowMap.add(this); | 71 gWindowMap.add(this); |
121 | 72 |
122 // init event variables | |
123 fPendingPaint = false; | |
124 fPendingResize = false; | |
125 | |
126 return true; | 73 return true; |
127 } | 74 } |
128 | 75 |
129 void Window_mac::closeWindow() { | 76 void Window_mac::closeWindow() { |
130 if (fDisplay) { | 77 if (fWindow) { |
robertphillips
2016/08/03 21:22:04
Shouldn't we be removing the window from gWindowMa
jvanverth1
2016/08/04 15:28:33
Done.
| |
131 this->detach(); | 78 SDL_DestroyWindow(fWindow); |
132 SkASSERT(fGC); | 79 fWindowID = 0; |
133 XFreeGC(fDisplay, fGC); | 80 fWindow = nullptr; |
134 fGC = nullptr; | |
135 gWindowMap.remove(fWindow); | |
136 XDestroyWindow(fDisplay, fWindow); | |
137 fWindow = 0; | |
138 fVisualInfo = nullptr; | |
139 fDisplay = nullptr; | |
140 fMSAASampleCount = 0; | |
141 } | 81 } |
142 } | 82 } |
143 | 83 |
144 static Window::Key get_key(KeySym keysym) { | 84 static Window::Key get_key(const SDL_Keysym& keysym) { |
145 static const struct { | 85 static const struct { |
146 KeySym fXK; | 86 SDL_Keycode fSDLK; |
147 Window::Key fKey; | 87 Window::Key fKey; |
148 } gPair[] = { | 88 } gPair[] = { |
149 { XK_BackSpace, Window::Key::kBack }, | 89 { SDLK_BACKSPACE, Window::Key::kBack }, |
150 { XK_Clear, Window::Key::kBack }, | 90 { SDLK_CLEAR, Window::Key::kBack }, |
151 { XK_Return, Window::Key::kOK }, | 91 { SDLK_RETURN, Window::Key::kOK }, |
152 { XK_Up, Window::Key::kUp }, | 92 { SDLK_UP, Window::Key::kUp }, |
153 { XK_Down, Window::Key::kDown }, | 93 { SDLK_DOWN, Window::Key::kDown }, |
154 { XK_Left, Window::Key::kLeft }, | 94 { SDLK_LEFT, Window::Key::kLeft }, |
155 { XK_Right, Window::Key::kRight } | 95 { SDLK_RIGHT, Window::Key::kRight } |
156 }; | 96 }; |
157 for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) { | 97 for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) { |
158 if (gPair[i].fXK == keysym) { | 98 if (gPair[i].fSDLK == keysym.sym) { |
159 return gPair[i].fKey; | 99 return gPair[i].fKey; |
160 } | 100 } |
161 } | 101 } |
162 return Window::Key::kNONE; | 102 return Window::Key::kNONE; |
163 } | 103 } |
164 | 104 |
165 static uint32_t get_modifiers(const XEvent& event) { | 105 static uint32_t get_modifiers(const SDL_Event& event) { |
166 static const struct { | 106 static const struct { |
167 unsigned fXMask; | 107 unsigned fSDLMask; |
168 unsigned fSkMask; | 108 unsigned fSkMask; |
169 } gModifiers[] = { | 109 } gModifiers[] = { |
170 { ShiftMask, Window::kShift_ModifierKey }, | 110 { KMOD_SHIFT, Window::kShift_ModifierKey }, |
171 { ControlMask, Window::kControl_ModifierKey }, | 111 { KMOD_CTRL, Window::kControl_ModifierKey }, |
172 { Mod1Mask, Window::kOption_ModifierKey }, | 112 { KMOD_ALT, Window::kOption_ModifierKey }, |
173 }; | 113 }; |
174 | 114 |
175 auto modifiers = 0; | 115 auto modifiers = 0; |
176 for (size_t i = 0; i < SK_ARRAY_COUNT(gModifiers); ++i) { | 116 |
177 if (event.xkey.state & gModifiers[i].fXMask) { | 117 switch (event.type) { |
robertphillips
2016/08/03 21:22:04
// fall through
?
jvanverth1
2016/08/04 15:28:33
Done.
| |
178 modifiers |= gModifiers[i].fSkMask; | 118 case SDL_KEYDOWN: |
179 } | 119 case SDL_KEYUP: { |
120 for (size_t i = 0; i < SK_ARRAY_COUNT(gModifiers); ++i) { | |
121 if (event.key.keysym.mod & gModifiers[i].fSDLMask) { | |
122 modifiers |= gModifiers[i].fSkMask; | |
123 } | |
124 } | |
125 if (0 == event.key.repeat) { | |
126 modifiers |= Window::kFirstPress_ModifierKey; | |
127 } | |
robertphillips
2016/08/03 21:22:04
I think the "break" is supposed to be inside the '
jvanverth1
2016/08/04 15:28:33
Done.
| |
128 } break; | |
129 | |
130 default: | |
robertphillips
2016/08/03 21:22:04
bracket this guy due to "mod" ?
jvanverth1
2016/08/04 15:28:33
Done.
| |
131 SDL_Keymod mod = SDL_GetModState(); | |
132 for (size_t i = 0; i < SK_ARRAY_COUNT(gModifiers); ++i) { | |
133 if (mod & gModifiers[i].fSDLMask) { | |
134 modifiers |= gModifiers[i].fSkMask; | |
135 } | |
136 } | |
137 break; | |
180 } | 138 } |
181 return modifiers; | 139 return modifiers; |
182 } | 140 } |
183 | 141 |
184 bool Window_mac::handleEvent(const XEvent& event) { | 142 bool Window_mac::handleEvent(const SDL_Event& event) { |
185 switch (event.type) { | 143 switch (event.type) { |
186 case MapNotify: | 144 case SDL_WINDOWEVENT: |
187 if (!fGC) { | 145 if (SDL_WINDOWEVENT_EXPOSED == event.window.event) { |
188 fGC = XCreateGC(fDisplay, fWindow, 0, nullptr); | 146 this->onPaint(); |
147 } else if (SDL_WINDOWEVENT_RESIZED == event.window.event) { | |
148 this->onResize(event.window.data1, event.window.data2); | |
189 } | 149 } |
190 break; | 150 break; |
191 | 151 |
192 case ClientMessage: | 152 case SDL_MOUSEBUTTONDOWN: |
193 if ((Atom)event.xclient.data.l[0] == fWmDeleteMessage && | 153 if (event.button.button == SDL_BUTTON_LEFT) { |
194 gWindowMap.count() == 1) { | 154 this->onMouse(event.button.x, event.button.y, |
195 return true; | |
196 } | |
197 break; | |
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)); | 155 Window::kDown_InputState, get_modifiers(event)); |
203 } | 156 } |
204 break; | 157 break; |
205 | 158 |
206 case ButtonRelease: | 159 case SDL_MOUSEBUTTONUP: |
207 if (event.xbutton.button == Button1) { | 160 if (event.button.button == SDL_BUTTON_LEFT) { |
208 this->onMouse(event.xbutton.x, event.xbutton.y, | 161 this->onMouse(event.button.x, event.button.y, |
209 Window::kUp_InputState, get_modifiers(event)); | 162 Window::kUp_InputState, get_modifiers(event)); |
210 } | 163 } |
211 break; | 164 break; |
212 | 165 |
213 case MotionNotify: | 166 case SDL_MOUSEMOTION: |
214 // only track if left button is down | 167 // only track if left button is down |
215 if (event.xmotion.state & Button1Mask) { | 168 if (event.motion.state & SDL_BUTTON_LMASK) { |
216 this->onMouse(event.xmotion.x, event.xmotion.y, | 169 this->onMouse(event.motion.x, event.motion.y, |
217 Window::kMove_InputState, get_modifiers(event)); | 170 Window::kMove_InputState, get_modifiers(event)); |
218 } | 171 } |
219 break; | 172 break; |
220 | 173 |
221 case KeyPress: { | 174 case SDL_KEYDOWN: { |
222 int shiftLevel = (event.xkey.state & ShiftMask) ? 1 : 0; | 175 if (event.key.keysym.sym == SDLK_ESCAPE) { |
223 KeySym keysym = XkbKeycodeToKeysym(fDisplay, event.xkey.keycode, | |
224 0, shiftLevel); | |
225 if (keysym == XK_Escape) { | |
226 return true; | 176 return true; |
227 } | 177 } |
228 Window::Key key = get_key(keysym); | 178 Window::Key key = get_key(event.key.keysym); |
229 if (key != Window::Key::kNONE) { | 179 if (key != Window::Key::kNONE) { |
230 (void) this->onKey(key, Window::kDown_InputState, | 180 (void) this->onKey(key, Window::kDown_InputState, |
231 get_modifiers(event)); | 181 get_modifiers(event)); |
232 } else { | 182 } else { |
233 long uni = keysym2ucs(keysym); | 183 (void) this->onChar((SkUnichar) event.key.keysym.sym, |
234 if (uni != -1) { | 184 get_modifiers(event)); |
235 (void) this->onChar((SkUnichar) uni, | |
236 get_modifiers(event)); | |
237 } | |
238 } | 185 } |
239 } break; | 186 } break; |
240 | 187 |
241 case KeyRelease: { | 188 case SDL_KEYUP: { |
242 int shiftLevel = (event.xkey.state & ShiftMask) ? 1 : 0; | 189 Window::Key key = get_key(event.key.keysym); |
243 KeySym keysym = XkbKeycodeToKeysym(fDisplay, event.xkey.keycode, | 190 if (key != Window::Key::kNONE) { |
244 0, shiftLevel); | 191 (void) this->onKey(key, Window::kUp_InputState, |
245 Window::Key key = get_key(keysym); | 192 get_modifiers(event)); |
246 (void) this->onKey(key, Window::kUp_InputState, | 193 } |
247 get_modifiers(event)); | |
248 } break; | 194 } break; |
249 | |
250 | 195 |
251 default: | 196 default: |
252 // these events should be handled in the main event loop | |
253 SkASSERT(event.type != Expose && event.type != ConfigureNotify); | |
254 break; | 197 break; |
255 } | 198 } |
256 | 199 |
257 return false; | 200 return false; |
258 } | 201 } |
259 | 202 |
260 void Window_mac::setTitle(const char* title) { | 203 void Window_mac::setTitle(const char* title) { |
261 XTextProperty textproperty; | 204 SDL_SetWindowTitle(fWindow, title); |
262 XStringListToTextProperty(const_cast<char**>(&title), 1, &textproperty); | |
263 XSetWMName(fDisplay, fWindow, &textproperty); | |
264 } | 205 } |
265 | 206 |
266 void Window_mac::show() { | 207 void Window_mac::show() { |
267 XMapWindow(fDisplay, fWindow); | 208 SDL_ShowWindow(fWindow); |
268 } | 209 } |
269 | 210 |
270 bool Window_mac::attach(BackendType attachType, const DisplayParams& params) { | 211 bool Window_mac::attach(BackendType attachType, const DisplayParams& params) { |
271 this->initWindow(fDisplay, ¶ms); | 212 this->initWindow(¶ms); |
272 | 213 |
273 MacWindowInfo info; | 214 window_context_factory::MacWindowInfo info; |
274 #if 0 | 215 info.fWindow = fWindow; |
275 // Init Mac window info here | |
276 info.foo = foo; | |
277 #endif | |
278 switch (attachType) { | 216 switch (attachType) { |
279 #ifdef SK_VULKAN | |
280 case kVulkan_BackendType: | |
281 fWindowContext = NewVulkanForMac(info, params); | |
282 break; | |
283 #endif | |
284 case kNativeGL_BackendType: | 217 case kNativeGL_BackendType: |
285 default: | 218 default: |
286 fWindowContext = NewGLForMac(info, params); | 219 fWindowContext = NewGLForMac(info, params); |
287 break; | 220 break; |
288 } | 221 } |
289 | 222 |
290 return (SkToBool(fWindowContext)); | 223 return (SkToBool(fWindowContext)); |
291 } | 224 } |
292 | 225 |
293 void Window_mac::onInval() { | 226 void Window_mac::onInval() { |
294 XEvent event; | 227 SDL_Event sdlevent; |
295 event.type = Expose; | 228 sdlevent.type = SDL_WINDOWEVENT; |
296 event.xexpose.send_event = True; | 229 sdlevent.window.windowID = fWindowID; |
297 event.xexpose.display = fDisplay; | 230 sdlevent.window.event = SDL_WINDOWEVENT_EXPOSED; |
298 event.xexpose.window = fWindow; | 231 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 } | 232 } |
307 #endif | 233 |
308 | |
309 } // namespace sk_app | 234 } // namespace sk_app |
OLD | NEW |