Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
2 /*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8 #include "SkTypes.h"
10 #if defined(SK_BUILD_FOR_WIN)
12 #include <GL/gl.h>
13 #include <WindowsX.h>
14 #include "SkWGL.h"
15 #include "SkWindow.h"
16 #include "SkCanvas.h"
17 #include "SkOSMenu.h"
18 #include "SkTime.h"
19 #include "SkUtils.h"
21 #include "SkGraphics.h"
23 #if SK_ANGLE
24 #include "gl/GrGLInterface.h"
26 #include "GLES2/gl2.h"
28 #define ANGLE_GL_CALL(IFACE, X) \
29 do { \
30 (IFACE)->fFunctions.f##X; \
31 } while (false)
33 #endif
35 #define INVALIDATE_DELAY_MS 200
37 static SkOSWindow* gCurrOSWin;
38 static HWND gEventTarget;
40 #define WM_EVENT_CALLBACK (WM_USER+0)
42 void post_skwinevent()
43 {
44 PostMessage(gEventTarget, WM_EVENT_CALLBACK, 0, 0);
45 }
47 SkOSWindow::SkOSWindow(void* hWnd) {
48 fHWND = hWnd;
49 #if SK_SUPPORT_GPU
50 #if SK_ANGLE
51 fDisplay = EGL_NO_DISPLAY;
52 fContext = EGL_NO_CONTEXT;
53 fSurface = EGL_NO_SURFACE;
54 #endif
55 fHGLRC = NULL;
56 #endif
57 fAttached = kNone_BackEndType;
58 gEventTarget = (HWND)hWnd;
59 }
61 SkOSWindow::~SkOSWindow() {
62 #if SK_SUPPORT_GPU
63 if (NULL != fHGLRC) {
64 wglDeleteContext((HGLRC)fHGLRC);
65 }
66 #if SK_ANGLE
67 if (EGL_NO_CONTEXT != fContext) {
68 eglDestroyContext(fDisplay, fContext);
69 fContext = EGL_NO_CONTEXT;
70 }
72 if (EGL_NO_SURFACE != fSurface) {
73 eglDestroySurface(fDisplay, fSurface);
74 fSurface = EGL_NO_SURFACE;
75 }
77 if (EGL_NO_DISPLAY != fDisplay) {
78 eglTerminate(fDisplay);
79 fDisplay = EGL_NO_DISPLAY;
80 }
81 #endif // SK_ANGLE
82 #endif // SK_SUPPORT_GPU
83 }
85 static SkKey winToskKey(WPARAM vk) {
86 static const struct {
87 WPARAM fVK;
88 SkKey fKey;
89 } gPair[] = {
90 { VK_BACK, kBack_SkKey },
91 { VK_CLEAR, kBack_SkKey },
92 { VK_RETURN, kOK_SkKey },
93 { VK_UP, kUp_SkKey },
94 { VK_DOWN, kDown_SkKey },
95 { VK_LEFT, kLeft_SkKey },
96 { VK_RIGHT, kRight_SkKey }
97 };
98 for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
99 if (gPair[i].fVK == vk) {
100 return gPair[i].fKey;
101 }
102 }
103 return kNONE_SkKey;
104 }
106 static unsigned getModifiers(UINT message) {
107 return 0; // TODO
108 }
110 bool SkOSWindow::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
111 switch (message) {
112 case WM_KEYDOWN: {
113 SkKey key = winToskKey(wParam);
114 if (kNONE_SkKey != key) {
115 this->handleKey(key);
116 return true;
117 }
118 } break;
119 case WM_KEYUP: {
120 SkKey key = winToskKey(wParam);
121 if (kNONE_SkKey != key) {
122 this->handleKeyUp(key);
123 return true;
124 }
125 } break;
126 case WM_UNICHAR:
127 this->handleChar((SkUnichar) wParam);
128 return true;
129 case WM_CHAR: {
130 this->handleChar(SkUTF8_ToUnichar((char*)&wParam));
131 return true;
132 } break;
133 case WM_SIZE: {
134 INT width = LOWORD(lParam);
135 INT height = HIWORD(lParam);
136 this->resize(width, height);
137 break;
138 }
139 case WM_PAINT: {
140 PAINTSTRUCT ps;
141 HDC hdc = BeginPaint(hWnd, &ps);
142 this->doPaint(hdc);
143 EndPaint(hWnd, &ps);
144 return true;
145 } break;
147 case WM_TIMER: {
148 RECT* rect = (RECT*)wParam;
149 InvalidateRect(hWnd, rect, FALSE);
150 KillTimer(hWnd, (UINT_PTR)rect);
151 delete rect;
152 return true;
153 } break;
155 case WM_LBUTTONDOWN:
156 this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
157 Click::kDown_State, NULL, getModifiers(message));
158 return true;
160 case WM_MOUSEMOVE:
161 this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
162 Click::kMoved_State, NULL, getModifiers(message));
163 return true;
165 case WM_LBUTTONUP:
166 this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
167 Click::kUp_State, NULL, getModifiers(message));
168 return true;
170 case WM_EVENT_CALLBACK:
171 if (SkEvent::ProcessEvent()) {
172 post_skwinevent();
173 }
174 return true;
175 }
176 return false;
177 }
179 void SkOSWindow::doPaint(void* ctx) {
180 this->update(NULL);
182 if (kNone_BackEndType == fAttached)
183 {
184 HDC hdc = (HDC)ctx;
185 const SkBitmap& bitmap = this->getBitmap();
187 BITMAPINFO bmi;
188 memset(&bmi, 0, sizeof(bmi));
189 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
190 bmi.bmiHeader.biWidth = bitmap.width();
191 bmi.bmiHeader.biHeight = -bitmap.height(); // top-down image
192 bmi.bmiHeader.biPlanes = 1;
193 bmi.bmiHeader.biBitCount = 32;
194 bmi.bmiHeader.biCompression = BI_RGB;
195 bmi.bmiHeader.biSizeImage = 0;
197 //
198 // Do the SetDIBitsToDevice.
199 //
200 // TODO(wjmaclean):
201 // Fix this call to handle SkBitmaps that have rowBytes != width,
202 // i.e. may have padding at the end of lines. The SkASSERT below
203 // may be ignored by builds, and the only obviously safe option
204 // seems to be to copy the bitmap to a temporary (contiguous)
205 // buffer before passing to SetDIBitsToDevice().
206 SkASSERT(bitmap.width() * bitmap.bytesPerPixel() == bitmap.rowBytes());
207 bitmap.lockPixels();
208 int ret = SetDIBitsToDevice(hdc,
209 0, 0,
210 bitmap.width(), bitmap.height(),
211 0, 0,
212 0, bitmap.height(),
213 bitmap.getPixels(),
214 &bmi,
215 DIB_RGB_COLORS);
216 (void)ret; // we're ignoring potential failures for now.
217 bitmap.unlockPixels();
218 }
219 }
221 #if 0
222 void SkOSWindow::updateSize()
223 {
224 RECT r;
225 GetWindowRect((HWND)this->getHWND(), &r);
226 this->resize(r.right - r.left, r.bottom - r.top);
227 }
228 #endif
230 void SkOSWindow::onHandleInval(const SkIRect& r) {
231 RECT* rect = new RECT;
232 rect->left = r.fLeft;
233 rect->top = r.fTop;
234 rect->right = r.fRight;
235 rect->bottom = r.fBottom;
236 SetTimer((HWND)fHWND, (UINT_PTR)rect, INVALIDATE_DELAY_MS, NULL);
237 }
239 void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu)
240 {
241 }
243 void SkOSWindow::onSetTitle(const char title[]){
244 SetWindowTextA((HWND)fHWND, title);
245 }
247 enum {
248 SK_MacReturnKey = 36,
249 SK_MacDeleteKey = 51,
250 SK_MacEndKey = 119,
251 SK_MacLeftKey = 123,
252 SK_MacRightKey = 124,
253 SK_MacDownKey = 125,
254 SK_MacUpKey = 126,
256 SK_Mac0Key = 0x52,
257 SK_Mac1Key = 0x53,
258 SK_Mac2Key = 0x54,
259 SK_Mac3Key = 0x55,
260 SK_Mac4Key = 0x56,
261 SK_Mac5Key = 0x57,
262 SK_Mac6Key = 0x58,
263 SK_Mac7Key = 0x59,
264 SK_Mac8Key = 0x5b,
265 SK_Mac9Key = 0x5c
266 };
268 static SkKey raw2key(uint32_t raw)
269 {
270 static const struct {
271 uint32_t fRaw;
272 SkKey fKey;
273 } gKeys[] = {
274 { SK_MacUpKey, kUp_SkKey },
275 { SK_MacDownKey, kDown_SkKey },
276 { SK_MacLeftKey, kLeft_SkKey },
277 { SK_MacRightKey, kRight_SkKey },
278 { SK_MacReturnKey, kOK_SkKey },
279 { SK_MacDeleteKey, kBack_SkKey },
280 { SK_MacEndKey, kEnd_SkKey },
281 { SK_Mac0Key, k0_SkKey },
282 { SK_Mac1Key, k1_SkKey },
283 { SK_Mac2Key, k2_SkKey },
284 { SK_Mac3Key, k3_SkKey },
285 { SK_Mac4Key, k4_SkKey },
286 { SK_Mac5Key, k5_SkKey },
287 { SK_Mac6Key, k6_SkKey },
288 { SK_Mac7Key, k7_SkKey },
289 { SK_Mac8Key, k8_SkKey },
290 { SK_Mac9Key, k9_SkKey }
291 };
293 for (unsigned i = 0; i < SK_ARRAY_COUNT(gKeys); i++)
294 if (gKeys[i].fRaw == raw)
295 return gKeys[i].fKey;
296 return kNONE_SkKey;
297 }
299 ///////////////////////////////////////////////////////////////////////////////////////
301 void SkEvent::SignalNonEmptyQueue()
302 {
303 post_skwinevent();
304 //SkDebugf("signal nonempty\n");
305 }
307 static UINT_PTR gTimer;
309 VOID CALLBACK sk_timer_proc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
310 {
311 SkEvent::ServiceQueueTimer();
312 //SkDebugf("timer task fired\n");
313 }
315 void SkEvent::SignalQueueTimer(SkMSec delay)
316 {
317 if (gTimer)
318 {
319 KillTimer(NULL, gTimer);
320 gTimer = NULL;
321 }
322 if (delay)
323 {
324 gTimer = SetTimer(NULL, 0, delay, sk_timer_proc);
325 //SkDebugf("SetTimer of %d returned %d\n", delay, gTimer);
326 }
327 }
329 #if SK_SUPPORT_GPU
331 bool SkOSWindow::attachGL(int msaaSampleCount, AttachmentInfo* info) {
332 HDC dc = GetDC((HWND)fHWND);
333 if (NULL == fHGLRC) {
334 fHGLRC = SkCreateWGLContext(dc, msaaSampleCount, false);
335 if (NULL == fHGLRC) {
336 return false;
337 }
338 glClearStencil(0);
339 glClearColor(0, 0, 0, 0);
340 glStencilMask(0xffffffff);
341 glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
342 }
343 if (wglMakeCurrent(dc, (HGLRC)fHGLRC)) {
344 // use DescribePixelFormat to get the stencil bit depth.
345 int pixelFormat = GetPixelFormat(dc);
346 PIXELFORMATDESCRIPTOR pfd;
347 DescribePixelFormat(dc, pixelFormat, sizeof(pfd), &pfd);
348 info->fStencilBits = pfd.cStencilBits;
350 // Get sample count if the MSAA WGL extension is present
351 SkWGLExtensions extensions;
352 if (extensions.hasExtension(dc, "WGL_ARB_multisample")) {
353 static const int kSampleCountAttr = SK_WGL_SAMPLES;
354 extensions.getPixelFormatAttribiv(dc,
355 pixelFormat,
356 0,
357 1,
358 &kSampleCountAttr,
359 &info->fSampleCount);
360 } else {
361 info->fSampleCount = 0;
362 }
364 glViewport(0, 0,
365 SkScalarRoundToInt(this->width()),
366 SkScalarRoundToInt(this->height()));
367 return true;
368 }
369 return false;
370 }
372 void SkOSWindow::detachGL() {
373 wglMakeCurrent(GetDC((HWND)fHWND), 0);
374 wglDeleteContext((HGLRC)fHGLRC);
375 fHGLRC = NULL;
376 }
378 void SkOSWindow::presentGL() {
379 glFlush();
380 HDC dc = GetDC((HWND)fHWND);
381 SwapBuffers(dc);
382 ReleaseDC((HWND)fHWND, dc);
383 }
385 #if SK_ANGLE
386 bool create_ANGLE(EGLNativeWindowType hWnd,
387 int msaaSampleCount,
388 EGLDisplay* eglDisplay,
389 EGLContext* eglContext,
390 EGLSurface* eglSurface,
391 EGLConfig* eglConfig) {
392 static const EGLint contextAttribs[] = {
393 EGL_CONTEXT_CLIENT_VERSION, 2,
394 EGL_NONE, EGL_NONE
395 };
396 static const EGLint configAttribList[] = {
397 EGL_RED_SIZE, 8,
398 EGL_GREEN_SIZE, 8,
399 EGL_BLUE_SIZE, 8,
400 EGL_ALPHA_SIZE, 8,
401 EGL_DEPTH_SIZE, 8,
402 EGL_STENCIL_SIZE, 8,
403 EGL_NONE
404 };
405 static const EGLint surfaceAttribList[] = {
406 EGL_NONE, EGL_NONE
407 };
409 EGLDisplay display = eglGetDisplay(GetDC(hWnd));
410 if (display == EGL_NO_DISPLAY ) {
411 return false;
412 }
414 // Initialize EGL
415 EGLint majorVersion, minorVersion;
416 if (!eglInitialize(display, &majorVersion, &minorVersion)) {
417 return false;
418 }
420 EGLint numConfigs;
421 if (!eglGetConfigs(display, NULL, 0, &numConfigs)) {
422 return false;
423 }
425 // Choose config
426 bool foundConfig = false;
427 if (msaaSampleCount) {
428 static const int kConfigAttribListCnt =
429 SK_ARRAY_COUNT(configAttribList);
430 EGLint msaaConfigAttribList[kConfigAttribListCnt + 4];
431 memcpy(msaaConfigAttribList,
432 configAttribList,
433 sizeof(configAttribList));
434 SkASSERT(EGL_NONE == msaaConfigAttribList[kConfigAttribListCnt - 1]);
435 msaaConfigAttribList[kConfigAttribListCnt - 1] = EGL_SAMPLE_BUFFERS;
436 msaaConfigAttribList[kConfigAttribListCnt + 0] = 1;
437 msaaConfigAttribList[kConfigAttribListCnt + 1] = EGL_SAMPLES;
438 msaaConfigAttribList[kConfigAttribListCnt + 2] = msaaSampleCount;
439 msaaConfigAttribList[kConfigAttribListCnt + 3] = EGL_NONE;
440 if (eglChooseConfig(display, configAttribList, eglConfig, 1, &numConfigs)) {
441 SkASSERT(numConfigs > 0);
442 foundConfig = true;
443 }
444 }
445 if (!foundConfig) {
446 if (!eglChooseConfig(display, configAttribList, eglConfig, 1, &numConfigs)) {
447 return false;
448 }
449 }
451 // Create a surface
452 EGLSurface surface = eglCreateWindowSurface(display, *eglConfig,
453 (EGLNativeWindowType)hWnd,
454 surfaceAttribList);
455 if (surface == EGL_NO_SURFACE) {
456 return false;
457 }
459 // Create a GL context
460 EGLContext context = eglCreateContext(display, *eglConfig,
461 EGL_NO_CONTEXT,
462 contextAttribs );
463 if (context == EGL_NO_CONTEXT ) {
464 return false;
465 }
467 // Make the context current
468 if (!eglMakeCurrent(display, surface, surface, context)) {
469 return false;
470 }
472 *eglDisplay = display;
473 *eglContext = context;
474 *eglSurface = surface;
475 return true;
476 }
478 bool SkOSWindow::attachANGLE(int msaaSampleCount, AttachmentInfo* info) {
479 if (EGL_NO_DISPLAY == fDisplay) {
480 bool bResult = create_ANGLE((HWND)fHWND,
481 msaaSampleCount,
482 &fDisplay,
483 &fContext,
484 &fSurface,
485 &fConfig);
486 if (false == bResult) {
487 return false;
488 }
489 SkAutoTUnref<const GrGLInterface> intf(GrGLCreateANGLEInterface());
491 if (intf) {
492 ANGLE_GL_CALL(intf, ClearStencil(0));
493 ANGLE_GL_CALL(intf, ClearColor(0, 0, 0, 0));
494 ANGLE_GL_CALL(intf, StencilMask(0xffffffff));
495 ANGLE_GL_CALL(intf, Clear(GL_STENCIL_BUFFER_BIT |GL_COLOR_BUFFER_BIT));
496 }
497 }
498 if (eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
499 eglGetConfigAttrib(fDisplay, fConfig, EGL_STENCIL_SIZE, &info->fStencilBits);
500 eglGetConfigAttrib(fDisplay, fConfig, EGL_SAMPLES, &info->fSampleCount);
502 SkAutoTUnref<const GrGLInterface> intf(GrGLCreateANGLEInterface());
504 if (intf ) {
505 ANGLE_GL_CALL(intf, Viewport(0, 0,
506 SkScalarRoundToInt(this->width()),
507 SkScalarRoundToInt(this->height())));
508 }
509 return true;
510 }
511 return false;
512 }
514 void SkOSWindow::detachANGLE() {
515 eglMakeCurrent(fDisplay, EGL_NO_SURFACE , EGL_NO_SURFACE , EGL_NO_CONTEXT);
517 eglDestroyContext(fDisplay, fContext);
518 fContext = EGL_NO_CONTEXT;
520 eglDestroySurface(fDisplay, fSurface);
521 fSurface = EGL_NO_SURFACE;
523 eglTerminate(fDisplay);
524 fDisplay = EGL_NO_DISPLAY;
525 }
527 void SkOSWindow::presentANGLE() {
528 SkAutoTUnref<const GrGLInterface> intf(GrGLCreateANGLEInterface());
530 if (intf) {
531 ANGLE_GL_CALL(intf, Flush());
532 }
534 eglSwapBuffers(fDisplay, fSurface);
535 }
536 #endif // SK_ANGLE
537 #endif // SK_SUPPORT_GPU
539 // return true on success
540 bool SkOSWindow::attach(SkBackEndTypes attachType, int msaaSampleCount, AttachmentInfo* info) {
542 // attach doubles as "windowResize" so we need to allo
543 // already bound states to pass through again
544 // TODO: split out the resize functionality
545 // SkASSERT(kNone_BackEndType == fAttached);
546 bool result = true;
548 switch (attachType) {
549 case kNone_BackEndType:
550 // nothing to do
551 break;
552 #if SK_SUPPORT_GPU
553 case kNativeGL_BackEndType:
554 result = attachGL(msaaSampleCount, info);
555 break;
556 #if SK_ANGLE
557 case kANGLE_BackEndType:
558 result = attachANGLE(msaaSampleCount, info);
559 break;
560 #endif // SK_ANGLE
561 #endif // SK_SUPPORT_GPU
562 default:
563 SkASSERT(false);
564 result = false;
565 break;
566 }
568 if (result) {
569 fAttached = attachType;
570 }
572 return result;
573 }
575 void SkOSWindow::detach() {
576 switch (fAttached) {
577 case kNone_BackEndType:
578 // nothing to do
579 break;
580 #if SK_SUPPORT_GPU
581 case kNativeGL_BackEndType:
582 detachGL();
583 break;
584 #if SK_ANGLE
585 case kANGLE_BackEndType:
586 detachANGLE();
587 break;
588 #endif // SK_ANGLE
589 #endif // SK_SUPPORT_GPU
590 default:
591 SkASSERT(false);
592 break;
593 }
594 fAttached = kNone_BackEndType;
595 }
597 void SkOSWindow::present() {
598 switch (fAttached) {
599 case kNone_BackEndType:
600 // nothing to do
601 return;
602 #if SK_SUPPORT_GPU
603 case kNativeGL_BackEndType:
604 presentGL();
605 break;
606 #if SK_ANGLE
607 case kANGLE_BackEndType:
608 presentANGLE();
609 break;
610 #endif // SK_ANGLE
611 #endif // SK_SUPPORT_GPU
612 default:
613 SkASSERT(false);
614 break;
615 }
616 }
618 #endif