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 "../GLWindowContext.h" | |
13 #include "../VulkanWindowContext.h" | 12 #include "../VulkanWindowContext.h" |
14 #include "Window_unix.h" | 13 #include "Window_unix.h" |
15 | 14 |
16 extern "C" { | 15 extern "C" { |
17 #include "keysym2ucs.h" | 16 #include "keysym2ucs.h" |
18 } | 17 } |
19 #include <X11/Xutil.h> | 18 #include <X11/Xutil.h> |
20 #include <X11/XKBlib.h> | 19 #include <X11/XKBlib.h> |
21 | 20 |
22 namespace sk_app { | 21 namespace sk_app { |
23 | 22 |
24 SkTDynamicHash<Window_unix, XWindow> Window_unix::gWindowMap; | 23 SkTDynamicHash<Window_unix, XWindow> Window_unix::gWindowMap; |
25 | 24 |
26 Window* Window::CreateNativeWindow(void* platformData) { | 25 Window* Window::CreateNativeWindow(void* platformData) { |
27 Display* display = (Display*)platformData; | 26 Display* display = (Display*)platformData; |
28 | 27 |
29 Window_unix* window = new Window_unix(); | 28 Window_unix* window = new Window_unix(); |
30 if (!window->initWindow(display, nullptr)) { | 29 if (!window->init(display)) { |
31 delete window; | 30 delete window; |
32 return nullptr; | 31 return nullptr; |
33 } | 32 } |
34 | 33 |
35 return window; | 34 return window; |
36 } | 35 } |
37 | 36 |
38 const long kEventMask = ExposureMask | StructureNotifyMask | | 37 bool Window_unix::init(Display* display) { |
39 KeyPressMask | KeyReleaseMask | | |
40 PointerMotionMask | ButtonPressMask | ButtonReleaseMask; | |
41 | |
42 bool Window_unix::initWindow(Display* display, const DisplayParams* params) { | |
43 if (params && params->fMSAASampleCount != fMSAASampleCount) { | |
44 this->closeWindow(); | |
45 } | |
46 // we already have a window | |
47 if (fDisplay) { | |
48 return true; | |
49 } | |
50 fDisplay = display; | 38 fDisplay = display; |
51 | 39 |
52 fWidth = 1280; | 40 fWidth = 1280; |
53 fHeight = 960; | 41 fHeight = 960; |
| 42 fHWnd = XCreateSimpleWindow(display, DefaultRootWindow(display), 0, 0, fWidt
h, fHeight, |
| 43 0, BlackPixel(display, DefaultScreen(display)), |
| 44 BlackPixel(display, DefaultScreen(display))); |
54 | 45 |
55 // Attempt to create a window that supports GL | 46 if (!fHWnd) { |
56 GLint att[] = { | |
57 GLX_RGBA, | |
58 GLX_DEPTH_SIZE, 24, | |
59 GLX_DOUBLEBUFFER, | |
60 GLX_STENCIL_SIZE, 8, | |
61 None | |
62 }; | |
63 SkASSERT(nullptr == fVisualInfo); | |
64 if (params && params->fMSAASampleCount > 0) { | |
65 static const GLint kAttCount = SK_ARRAY_COUNT(att); | |
66 GLint msaaAtt[kAttCount + 4]; | |
67 memcpy(msaaAtt, att, sizeof(att)); | |
68 SkASSERT(None == msaaAtt[kAttCount - 1]); | |
69 msaaAtt[kAttCount - 1] = GLX_SAMPLE_BUFFERS_ARB; | |
70 msaaAtt[kAttCount + 0] = 1; | |
71 msaaAtt[kAttCount + 1] = GLX_SAMPLES_ARB; | |
72 msaaAtt[kAttCount + 2] = params->fMSAASampleCount; | |
73 msaaAtt[kAttCount + 3] = None; | |
74 fVisualInfo = glXChooseVisual(display, DefaultScreen(display), msaaAtt); | |
75 fMSAASampleCount = params->fMSAASampleCount; | |
76 } | |
77 if (nullptr == fVisualInfo) { | |
78 fVisualInfo = glXChooseVisual(display, DefaultScreen(display), att); | |
79 fMSAASampleCount = 0; | |
80 } | |
81 | |
82 if (fVisualInfo) { | |
83 Colormap colorMap = XCreateColormap(display, | |
84 RootWindow(display, fVisualInfo->scr
een), | |
85 fVisualInfo->visual, | |
86 AllocNone); | |
87 XSetWindowAttributes swa; | |
88 swa.colormap = colorMap; | |
89 swa.event_mask = kEventMask; | |
90 fWindow = XCreateWindow(display, | |
91 RootWindow(display, fVisualInfo->screen), | |
92 0, 0, // x, y | |
93 fWidth, fHeight, | |
94 0, // border width | |
95 fVisualInfo->depth, | |
96 InputOutput, | |
97 fVisualInfo->visual, | |
98 CWEventMask | CWColormap, | |
99 &swa); | |
100 } else { | |
101 // Create a simple window instead. We will not be able to show GL | |
102 fWindow = XCreateSimpleWindow(display, | |
103 DefaultRootWindow(display), | |
104 0, 0, // x, y | |
105 fWidth, fHeight, | |
106 0, // border width | |
107 0, // border value | |
108 0); // background value | |
109 XSelectInput(display, fWindow, kEventMask); | |
110 } | |
111 | |
112 if (!fWindow) { | |
113 return false; | 47 return false; |
114 } | 48 } |
115 | 49 |
| 50 // choose the events we care about |
| 51 XSelectInput(display, fHWnd, |
| 52 ExposureMask | StructureNotifyMask | KeyPressMask | KeyReleaseM
ask | |
| 53 PointerMotionMask | ButtonPressMask | ButtonReleaseMask); |
| 54 |
116 // set up to catch window delete message | 55 // set up to catch window delete message |
117 fWmDeleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", False); | 56 fWmDeleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", False); |
118 XSetWMProtocols(display, fWindow, &fWmDeleteMessage, 1); | 57 XSetWMProtocols(display, fHWnd, &fWmDeleteMessage, 1); |
119 | 58 |
120 // add to hashtable of windows | 59 // add to hashtable of windows |
121 gWindowMap.add(this); | 60 gWindowMap.add(this); |
122 | 61 |
123 // init event variables | 62 // init event variables |
124 fPendingPaint = false; | 63 fPendingPaint = false; |
125 fPendingResize = false; | 64 fPendingResize = false; |
126 | 65 |
127 return true; | 66 return true; |
128 } | 67 } |
129 | 68 |
130 void Window_unix::closeWindow() { | |
131 if (fDisplay) { | |
132 this->detach(); | |
133 SkASSERT(fGC); | |
134 XFreeGC(fDisplay, fGC); | |
135 fGC = nullptr; | |
136 gWindowMap.remove(fWindow); | |
137 XDestroyWindow(fDisplay, fWindow); | |
138 fWindow = 0; | |
139 fVisualInfo = nullptr; | |
140 fDisplay = nullptr; | |
141 fMSAASampleCount = 0; | |
142 } | |
143 } | |
144 | |
145 static Window::Key get_key(KeySym keysym) { | 69 static Window::Key get_key(KeySym keysym) { |
146 static const struct { | 70 static const struct { |
147 KeySym fXK; | 71 KeySym fXK; |
148 Window::Key fKey; | 72 Window::Key fKey; |
149 } gPair[] = { | 73 } gPair[] = { |
150 { XK_BackSpace, Window::Key::kBack }, | 74 { XK_BackSpace, Window::Key::kBack }, |
151 { XK_Clear, Window::Key::kBack }, | 75 { XK_Clear, Window::Key::kBack }, |
152 { XK_Return, Window::Key::kOK }, | 76 { XK_Return, Window::Key::kOK }, |
153 { XK_Up, Window::Key::kUp }, | 77 { XK_Up, Window::Key::kUp }, |
154 { XK_Down, Window::Key::kDown }, | 78 { XK_Down, Window::Key::kDown }, |
(...skipping 22 matching lines...) Expand all Loading... |
177 for (size_t i = 0; i < SK_ARRAY_COUNT(gModifiers); ++i) { | 101 for (size_t i = 0; i < SK_ARRAY_COUNT(gModifiers); ++i) { |
178 if (event.xkey.state & gModifiers[i].fXMask) { | 102 if (event.xkey.state & gModifiers[i].fXMask) { |
179 modifiers |= gModifiers[i].fSkMask; | 103 modifiers |= gModifiers[i].fSkMask; |
180 } | 104 } |
181 } | 105 } |
182 return modifiers; | 106 return modifiers; |
183 } | 107 } |
184 | 108 |
185 bool Window_unix::handleEvent(const XEvent& event) { | 109 bool Window_unix::handleEvent(const XEvent& event) { |
186 switch (event.type) { | 110 switch (event.type) { |
187 case MapNotify: | |
188 if (!fGC) { | |
189 fGC = XCreateGC(fDisplay, fWindow, 0, nullptr); | |
190 } | |
191 break; | |
192 | |
193 case ClientMessage: | 111 case ClientMessage: |
194 if ((Atom)event.xclient.data.l[0] == fWmDeleteMessage && | 112 if ((Atom)event.xclient.data.l[0] == fWmDeleteMessage && |
195 gWindowMap.count() == 1) { | 113 gWindowMap.count() == 1) { |
196 return true; | 114 return true; |
197 } | 115 } |
198 break; | 116 break; |
199 | 117 |
200 case ButtonPress: | 118 case ButtonPress: |
201 if (event.xbutton.button == Button1) { | 119 if (event.xbutton.button == Button1) { |
202 this->onMouse(event.xbutton.x, event.xbutton.y, | 120 this->onMouse(event.xbutton.x, event.xbutton.y, |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 SkASSERT(event.type != Expose && event.type != ConfigureNotify); | 172 SkASSERT(event.type != Expose && event.type != ConfigureNotify); |
255 break; | 173 break; |
256 } | 174 } |
257 | 175 |
258 return false; | 176 return false; |
259 } | 177 } |
260 | 178 |
261 void Window_unix::setTitle(const char* title) { | 179 void Window_unix::setTitle(const char* title) { |
262 XTextProperty textproperty; | 180 XTextProperty textproperty; |
263 XStringListToTextProperty(const_cast<char**>(&title), 1, &textproperty); | 181 XStringListToTextProperty(const_cast<char**>(&title), 1, &textproperty); |
264 XSetWMName(fDisplay, fWindow, &textproperty); | 182 XSetWMName(fDisplay, fHWnd, &textproperty); |
265 } | 183 } |
266 | 184 |
267 void Window_unix::show() { | 185 void Window_unix::show() { |
268 XMapWindow(fDisplay, fWindow); | 186 XMapWindow(fDisplay, fHWnd); |
269 } | 187 } |
270 | 188 |
271 bool Window_unix::attach(BackendType attachType, const DisplayParams& params) { | 189 bool Window_unix::attach(BackendType attachType, const DisplayParams& params) { |
272 this->initWindow(fDisplay, ¶ms); | |
273 | |
274 ContextPlatformData_unix platformData; | 190 ContextPlatformData_unix platformData; |
275 platformData.fDisplay = fDisplay; | 191 platformData.fDisplay = fDisplay; |
276 platformData.fWindow = fWindow; | 192 platformData.fHWnd = fHWnd; |
277 platformData.fVisualInfo = fVisualInfo; | 193 XWindowAttributes attribs; |
| 194 XGetWindowAttributes(fDisplay, fHWnd, &attribs); |
| 195 platformData.fVisualID = XVisualIDFromVisual(attribs.visual); |
278 switch (attachType) { | 196 switch (attachType) { |
279 case kVulkan_BackendType: | 197 case kVulkan_BackendType: |
| 198 default: |
280 fWindowContext = VulkanWindowContext::Create((void*)&platformData, p
arams); | 199 fWindowContext = VulkanWindowContext::Create((void*)&platformData, p
arams); |
281 break; | 200 break; |
282 | |
283 case kNativeGL_BackendType: | |
284 default: | |
285 fWindowContext = GLWindowContext::Create((void*)&platformData, param
s); | |
286 break; | |
287 } | 201 } |
288 | 202 |
289 return (SkToBool(fWindowContext)); | 203 return (SkToBool(fWindowContext)); |
290 } | 204 } |
291 | 205 |
292 void Window_unix::onInval() { | 206 void Window_unix::onInval() { |
293 XEvent event; | 207 XEvent event; |
294 event.type = Expose; | 208 event.type = Expose; |
295 event.xexpose.send_event = True; | 209 event.xexpose.send_event = True; |
296 event.xexpose.display = fDisplay; | 210 event.xexpose.display = fDisplay; |
297 event.xexpose.window = fWindow; | 211 event.xexpose.window = fHWnd; |
298 event.xexpose.x = 0; | 212 event.xexpose.x = 0; |
299 event.xexpose.y = 0; | 213 event.xexpose.y = 0; |
300 event.xexpose.width = fWidth; | 214 event.xexpose.width = fWidth; |
301 event.xexpose.height = fHeight; | 215 event.xexpose.height = fHeight; |
302 event.xexpose.count = 0; | 216 event.xexpose.count = 0; |
303 | 217 |
304 XSendEvent(fDisplay, fWindow, False, 0, &event); | 218 XSendEvent(fDisplay, fHWnd, False, 0, &event); |
305 } | 219 } |
306 | 220 |
307 } // namespace sk_app | 221 } // namespace sk_app |
OLD | NEW |