dom/plugins/test/testplugin/nptest_windows.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

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.

michael@0 1 /* ***** BEGIN LICENSE BLOCK *****
michael@0 2 *
michael@0 3 * Copyright (c) 2008, Mozilla Corporation
michael@0 4 * All rights reserved.
michael@0 5 *
michael@0 6 * Redistribution and use in source and binary forms, with or without
michael@0 7 * modification, are permitted provided that the following conditions are met:
michael@0 8 *
michael@0 9 * * Redistributions of source code must retain the above copyright notice, this
michael@0 10 * list of conditions and the following disclaimer.
michael@0 11 * * Redistributions in binary form must reproduce the above copyright notice,
michael@0 12 * this list of conditions and the following disclaimer in the documentation
michael@0 13 * and/or other materials provided with the distribution.
michael@0 14 * * Neither the name of the Mozilla Corporation nor the names of its
michael@0 15 * contributors may be used to endorse or promote products derived from this
michael@0 16 * software without specific prior written permission.
michael@0 17 *
michael@0 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
michael@0 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
michael@0 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
michael@0 21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
michael@0 22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
michael@0 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
michael@0 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
michael@0 25 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
michael@0 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
michael@0 27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
michael@0 28 *
michael@0 29 * Contributor(s):
michael@0 30 * Josh Aas <josh@mozilla.com>
michael@0 31 * Jim Mathies <jmathies@mozilla.com>
michael@0 32 *
michael@0 33 * ***** END LICENSE BLOCK ***** */
michael@0 34
michael@0 35 #include "nptest_platform.h"
michael@0 36
michael@0 37 #include <windows.h>
michael@0 38 #include <windowsx.h>
michael@0 39 #include <stdio.h>
michael@0 40
michael@0 41 #include <d3d10_1.h>
michael@0 42
michael@0 43 using namespace std;
michael@0 44
michael@0 45 void SetSubclass(HWND hWnd, InstanceData* instanceData);
michael@0 46 void ClearSubclass(HWND hWnd);
michael@0 47 LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
michael@0 48
michael@0 49 struct _PlatformData {
michael@0 50 HWND childWindow;
michael@0 51 ID3D10Device1 *device;
michael@0 52 ID3D10Texture2D *frontBuffer;
michael@0 53 ID3D10Texture2D *backBuffer;
michael@0 54 };
michael@0 55
michael@0 56 bool
michael@0 57 pluginSupportsWindowMode()
michael@0 58 {
michael@0 59 return true;
michael@0 60 }
michael@0 61
michael@0 62 bool
michael@0 63 pluginSupportsWindowlessMode()
michael@0 64 {
michael@0 65 return true;
michael@0 66 }
michael@0 67
michael@0 68 bool
michael@0 69 pluginSupportsAsyncBitmapDrawing()
michael@0 70 {
michael@0 71 return true;
michael@0 72 }
michael@0 73
michael@0 74 NPError
michael@0 75 pluginInstanceInit(InstanceData* instanceData)
michael@0 76 {
michael@0 77 NPP npp = instanceData->npp;
michael@0 78
michael@0 79 instanceData->platformData = static_cast<PlatformData*>
michael@0 80 (NPN_MemAlloc(sizeof(PlatformData)));
michael@0 81 if (!instanceData->platformData)
michael@0 82 return NPERR_OUT_OF_MEMORY_ERROR;
michael@0 83
michael@0 84 instanceData->platformData->childWindow = nullptr;
michael@0 85 instanceData->platformData->device = nullptr;
michael@0 86 instanceData->platformData->frontBuffer = nullptr;
michael@0 87 instanceData->platformData->backBuffer = nullptr;
michael@0 88 return NPERR_NO_ERROR;
michael@0 89 }
michael@0 90
michael@0 91 void
michael@0 92 pluginInstanceShutdown(InstanceData* instanceData)
michael@0 93 {
michael@0 94 PlatformData *pd = instanceData->platformData;
michael@0 95 if (pd->frontBuffer) {
michael@0 96 pd->frontBuffer->Release();
michael@0 97 }
michael@0 98 if (pd->backBuffer) {
michael@0 99 pd->backBuffer->Release();
michael@0 100 }
michael@0 101 if (pd->device) {
michael@0 102 pd->device->Release();
michael@0 103 }
michael@0 104 NPN_MemFree(instanceData->platformData);
michael@0 105 instanceData->platformData = 0;
michael@0 106 }
michael@0 107
michael@0 108 static ID3D10Device1*
michael@0 109 getD3D10Device()
michael@0 110 {
michael@0 111 ID3D10Device1 *device;
michael@0 112
michael@0 113 HMODULE d3d10module = LoadLibraryA("d3d10_1.dll");
michael@0 114 decltype(D3D10CreateDevice1)* createD3DDevice =
michael@0 115 (decltype(D3D10CreateDevice1)*) GetProcAddress(d3d10module,
michael@0 116 "D3D10CreateDevice1");
michael@0 117
michael@0 118 if (createD3DDevice) {
michael@0 119 HMODULE dxgiModule = LoadLibraryA("dxgi.dll");
michael@0 120 decltype(CreateDXGIFactory1)* createDXGIFactory1 =
michael@0 121 (decltype(CreateDXGIFactory1)*) GetProcAddress(dxgiModule,
michael@0 122 "CreateDXGIFactory1");
michael@0 123
michael@0 124 HRESULT hr;
michael@0 125
michael@0 126 // Try to use a DXGI 1.1 adapter in order to share resources
michael@0 127 // across processes.
michael@0 128 IDXGIAdapter1 *adapter1;
michael@0 129 if (createDXGIFactory1) {
michael@0 130 IDXGIFactory1 *factory1;
michael@0 131 hr = createDXGIFactory1(__uuidof(IDXGIFactory1),
michael@0 132 (void**)&factory1);
michael@0 133
michael@0 134 if (FAILED(hr) || !factory1) {
michael@0 135 // Uh-oh
michael@0 136 return nullptr;
michael@0 137 }
michael@0 138
michael@0 139 hr = factory1->EnumAdapters1(0, &adapter1);
michael@0 140
michael@0 141 if (SUCCEEDED(hr) && adapter1) {
michael@0 142 hr = adapter1->CheckInterfaceSupport(__uuidof(ID3D10Device),
michael@0 143 nullptr);
michael@0 144 if (FAILED(hr)) {
michael@0 145 adapter1 = nullptr;
michael@0 146 }
michael@0 147 }
michael@0 148 factory1->Release();
michael@0 149 }
michael@0 150
michael@0 151 hr = createD3DDevice(
michael@0 152 adapter1,
michael@0 153 D3D10_DRIVER_TYPE_HARDWARE,
michael@0 154 nullptr,
michael@0 155 D3D10_CREATE_DEVICE_BGRA_SUPPORT |
michael@0 156 D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
michael@0 157 D3D10_FEATURE_LEVEL_10_0,
michael@0 158 D3D10_1_SDK_VERSION,
michael@0 159 &device);
michael@0 160
michael@0 161 adapter1->Release();
michael@0 162 }
michael@0 163
michael@0 164 return device;
michael@0 165 }
michael@0 166
michael@0 167 void
michael@0 168 pluginDoSetWindow(InstanceData* instanceData, NPWindow* newWindow)
michael@0 169 {
michael@0 170 instanceData->window = *newWindow;
michael@0 171 NPP npp = instanceData->npp;
michael@0 172
michael@0 173 if (instanceData->asyncDrawing == AD_DXGI) {
michael@0 174 if (instanceData->frontBuffer &&
michael@0 175 instanceData->frontBuffer->size.width == newWindow->width &&
michael@0 176 instanceData->frontBuffer->size.height == newWindow->height) {
michael@0 177 return;
michael@0 178 }
michael@0 179 if (instanceData->frontBuffer) {
michael@0 180 instanceData->platformData->frontBuffer->Release();
michael@0 181 instanceData->platformData->frontBuffer = nullptr;
michael@0 182 NPN_FinalizeAsyncSurface(npp, instanceData->frontBuffer);
michael@0 183 NPN_MemFree(instanceData->frontBuffer);
michael@0 184 }
michael@0 185 if (instanceData->backBuffer) {
michael@0 186 instanceData->platformData->backBuffer->Release();
michael@0 187 instanceData->platformData->backBuffer = nullptr;
michael@0 188 NPN_FinalizeAsyncSurface(npp, instanceData->backBuffer);
michael@0 189 NPN_MemFree(instanceData->backBuffer);
michael@0 190 }
michael@0 191
michael@0 192 if (!instanceData->platformData->device) {
michael@0 193 instanceData->platformData->device = getD3D10Device();
michael@0 194 }
michael@0 195
michael@0 196 ID3D10Device1 *dev = instanceData->platformData->device;
michael@0 197
michael@0 198 if (!dev) {
michael@0 199 return;
michael@0 200 }
michael@0 201
michael@0 202 instanceData->frontBuffer = (NPAsyncSurface*)NPN_MemAlloc(sizeof(NPAsyncSurface));
michael@0 203 instanceData->backBuffer = (NPAsyncSurface*)NPN_MemAlloc(sizeof(NPAsyncSurface));
michael@0 204
michael@0 205 NPSize size;
michael@0 206 size.width = newWindow->width;
michael@0 207 size.height = newWindow->height;
michael@0 208
michael@0 209 memset(instanceData->frontBuffer, 0, sizeof(NPAsyncSurface));
michael@0 210 memset(instanceData->backBuffer, 0, sizeof(NPAsyncSurface));
michael@0 211
michael@0 212 NPN_InitAsyncSurface(npp, &size, NPImageFormatBGRA32, nullptr, instanceData->frontBuffer);
michael@0 213 NPN_InitAsyncSurface(npp, &size, NPImageFormatBGRA32, nullptr, instanceData->backBuffer);
michael@0 214
michael@0 215 dev->OpenSharedResource(instanceData->frontBuffer->sharedHandle, __uuidof(ID3D10Texture2D), (void**)&instanceData->platformData->frontBuffer);
michael@0 216 dev->OpenSharedResource(instanceData->backBuffer->sharedHandle, __uuidof(ID3D10Texture2D), (void**)&instanceData->platformData->backBuffer);
michael@0 217
michael@0 218 pluginDrawAsyncDxgiColor(instanceData);
michael@0 219 }
michael@0 220 }
michael@0 221
michael@0 222 #define CHILD_WIDGET_SIZE 10
michael@0 223
michael@0 224 void
michael@0 225 pluginWidgetInit(InstanceData* instanceData, void* oldWindow)
michael@0 226 {
michael@0 227 HWND hWnd = (HWND)instanceData->window.window;
michael@0 228 if (oldWindow) {
michael@0 229 // chrashtests/539897-1.html excercises this code
michael@0 230 HWND hWndOld = (HWND)oldWindow;
michael@0 231 ClearSubclass(hWndOld);
michael@0 232 if (instanceData->platformData->childWindow) {
michael@0 233 ::DestroyWindow(instanceData->platformData->childWindow);
michael@0 234 }
michael@0 235 }
michael@0 236
michael@0 237 SetSubclass(hWnd, instanceData);
michael@0 238
michael@0 239 instanceData->platformData->childWindow =
michael@0 240 ::CreateWindowW(L"SCROLLBAR", L"Dummy child window",
michael@0 241 WS_CHILD, 0, 0, CHILD_WIDGET_SIZE, CHILD_WIDGET_SIZE, hWnd, nullptr,
michael@0 242 nullptr, nullptr);
michael@0 243 }
michael@0 244
michael@0 245 static void
michael@0 246 drawToDC(InstanceData* instanceData, HDC dc,
michael@0 247 int x, int y, int width, int height)
michael@0 248 {
michael@0 249 switch (instanceData->scriptableObject->drawMode) {
michael@0 250 case DM_DEFAULT:
michael@0 251 {
michael@0 252 const RECT fill = { x, y, x + width, y + height };
michael@0 253
michael@0 254 int oldBkMode = ::SetBkMode(dc, TRANSPARENT);
michael@0 255 HBRUSH brush = ::CreateSolidBrush(RGB(0, 0, 0));
michael@0 256 if (brush) {
michael@0 257 ::FillRect(dc, &fill, brush);
michael@0 258 ::DeleteObject(brush);
michael@0 259 }
michael@0 260 if (width > 6 && height > 6) {
michael@0 261 brush = ::CreateSolidBrush(RGB(192, 192, 192));
michael@0 262 if (brush) {
michael@0 263 RECT inset = { x + 3, y + 3, x + width - 3, y + height - 3 };
michael@0 264 ::FillRect(dc, &inset, brush);
michael@0 265 ::DeleteObject(brush);
michael@0 266 }
michael@0 267 }
michael@0 268
michael@0 269 const char* uaString = NPN_UserAgent(instanceData->npp);
michael@0 270 if (uaString && width > 10 && height > 10) {
michael@0 271 HFONT font =
michael@0 272 ::CreateFontA(20, 0, 0, 0, 400, FALSE, FALSE, FALSE,
michael@0 273 DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
michael@0 274 CLIP_DEFAULT_PRECIS, 5, // CLEARTYPE_QUALITY
michael@0 275 DEFAULT_PITCH, "Arial");
michael@0 276 if (font) {
michael@0 277 HFONT oldFont = (HFONT)::SelectObject(dc, font);
michael@0 278 RECT inset = { x + 5, y + 5, x + width - 5, y + height - 5 };
michael@0 279 ::DrawTextA(dc, uaString, -1, &inset,
michael@0 280 DT_LEFT | DT_TOP | DT_NOPREFIX | DT_WORDBREAK);
michael@0 281 ::SelectObject(dc, oldFont);
michael@0 282 ::DeleteObject(font);
michael@0 283 }
michael@0 284 }
michael@0 285 ::SetBkMode(dc, oldBkMode);
michael@0 286 }
michael@0 287 break;
michael@0 288
michael@0 289 case DM_SOLID_COLOR:
michael@0 290 {
michael@0 291 HDC offscreenDC = ::CreateCompatibleDC(dc);
michael@0 292 if (!offscreenDC)
michael@0 293 return;
michael@0 294
michael@0 295 const BITMAPV4HEADER bitmapheader = {
michael@0 296 sizeof(BITMAPV4HEADER),
michael@0 297 width,
michael@0 298 height,
michael@0 299 1, // planes
michael@0 300 32, // bits
michael@0 301 BI_BITFIELDS,
michael@0 302 0, // unused size
michael@0 303 0, 0, // unused metrics
michael@0 304 0, 0, // unused colors used/important
michael@0 305 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000, // ARGB masks
michael@0 306 };
michael@0 307 uint32_t *pixelData;
michael@0 308 HBITMAP offscreenBitmap =
michael@0 309 ::CreateDIBSection(dc, reinterpret_cast<const BITMAPINFO*>(&bitmapheader),
michael@0 310 0, reinterpret_cast<void**>(&pixelData), 0, 0);
michael@0 311 if (!offscreenBitmap)
michael@0 312 return;
michael@0 313
michael@0 314 uint32_t rgba = instanceData->scriptableObject->drawColor;
michael@0 315 unsigned int alpha = ((rgba & 0xFF000000) >> 24);
michael@0 316 BYTE r = ((rgba & 0xFF0000) >> 16);
michael@0 317 BYTE g = ((rgba & 0xFF00) >> 8);
michael@0 318 BYTE b = (rgba & 0xFF);
michael@0 319
michael@0 320 // Windows expects premultiplied
michael@0 321 r = BYTE(float(alpha * r) / 0xFF);
michael@0 322 g = BYTE(float(alpha * g) / 0xFF);
michael@0 323 b = BYTE(float(alpha * b) / 0xFF);
michael@0 324 uint32_t premultiplied =
michael@0 325 (alpha << 24) + (r << 16) + (g << 8) + b;
michael@0 326
michael@0 327 for (uint32_t* lastPixel = pixelData + width * height;
michael@0 328 pixelData < lastPixel;
michael@0 329 ++pixelData)
michael@0 330 *pixelData = premultiplied;
michael@0 331
michael@0 332 ::SelectObject(offscreenDC, offscreenBitmap);
michael@0 333 BLENDFUNCTION blendFunc;
michael@0 334 blendFunc.BlendOp = AC_SRC_OVER;
michael@0 335 blendFunc.BlendFlags = 0;
michael@0 336 blendFunc.SourceConstantAlpha = 255;
michael@0 337 blendFunc.AlphaFormat = AC_SRC_ALPHA;
michael@0 338 ::AlphaBlend(dc, x, y, width, height, offscreenDC, 0, 0, width, height,
michael@0 339 blendFunc);
michael@0 340
michael@0 341 ::DeleteObject(offscreenDC);
michael@0 342 ::DeleteObject(offscreenBitmap);
michael@0 343 }
michael@0 344 break;
michael@0 345 }
michael@0 346 }
michael@0 347
michael@0 348 void
michael@0 349 pluginDraw(InstanceData* instanceData)
michael@0 350 {
michael@0 351 NPP npp = instanceData->npp;
michael@0 352 if (!npp)
michael@0 353 return;
michael@0 354
michael@0 355 HDC hdc = nullptr;
michael@0 356 PAINTSTRUCT ps;
michael@0 357
michael@0 358 notifyDidPaint(instanceData);
michael@0 359
michael@0 360 if (instanceData->hasWidget)
michael@0 361 hdc = ::BeginPaint((HWND)instanceData->window.window, &ps);
michael@0 362 else
michael@0 363 hdc = (HDC)instanceData->window.window;
michael@0 364
michael@0 365 if (hdc == nullptr)
michael@0 366 return;
michael@0 367
michael@0 368 // Push the browser's hdc on the resource stack. If this test plugin is windowless,
michael@0 369 // we share the drawing surface with the rest of the browser.
michael@0 370 int savedDCID = SaveDC(hdc);
michael@0 371
michael@0 372 // When we have a widget, window.x/y are meaningless since our widget
michael@0 373 // is always positioned correctly and we just draw into it at 0,0.
michael@0 374 int x = instanceData->hasWidget ? 0 : instanceData->window.x;
michael@0 375 int y = instanceData->hasWidget ? 0 : instanceData->window.y;
michael@0 376 int width = instanceData->window.width;
michael@0 377 int height = instanceData->window.height;
michael@0 378 drawToDC(instanceData, hdc, x, y, width, height);
michael@0 379
michael@0 380 // Pop our hdc changes off the resource stack
michael@0 381 RestoreDC(hdc, savedDCID);
michael@0 382
michael@0 383 if (instanceData->hasWidget)
michael@0 384 ::EndPaint((HWND)instanceData->window.window, &ps);
michael@0 385 }
michael@0 386
michael@0 387 /* script interface */
michael@0 388
michael@0 389 int32_t
michael@0 390 pluginGetEdge(InstanceData* instanceData, RectEdge edge)
michael@0 391 {
michael@0 392 if (!instanceData || !instanceData->hasWidget)
michael@0 393 return NPTEST_INT32_ERROR;
michael@0 394
michael@0 395 // Get the plugin client rect in screen coordinates
michael@0 396 RECT rect = {0};
michael@0 397 if (!::GetClientRect((HWND)instanceData->window.window, &rect))
michael@0 398 return NPTEST_INT32_ERROR;
michael@0 399 ::MapWindowPoints((HWND)instanceData->window.window, nullptr,
michael@0 400 (LPPOINT)&rect, 2);
michael@0 401
michael@0 402 // Get the toplevel window frame rect in screen coordinates
michael@0 403 HWND rootWnd = ::GetAncestor((HWND)instanceData->window.window, GA_ROOT);
michael@0 404 if (!rootWnd)
michael@0 405 return NPTEST_INT32_ERROR;
michael@0 406 RECT rootRect;
michael@0 407 if (!::GetWindowRect(rootWnd, &rootRect))
michael@0 408 return NPTEST_INT32_ERROR;
michael@0 409
michael@0 410 switch (edge) {
michael@0 411 case EDGE_LEFT:
michael@0 412 return rect.left - rootRect.left;
michael@0 413 case EDGE_TOP:
michael@0 414 return rect.top - rootRect.top;
michael@0 415 case EDGE_RIGHT:
michael@0 416 return rect.right - rootRect.left;
michael@0 417 case EDGE_BOTTOM:
michael@0 418 return rect.bottom - rootRect.top;
michael@0 419 }
michael@0 420
michael@0 421 return NPTEST_INT32_ERROR;
michael@0 422 }
michael@0 423
michael@0 424 static BOOL
michael@0 425 getWindowRegion(HWND wnd, HRGN rgn)
michael@0 426 {
michael@0 427 if (::GetWindowRgn(wnd, rgn) != ERROR)
michael@0 428 return TRUE;
michael@0 429
michael@0 430 RECT clientRect;
michael@0 431 if (!::GetClientRect(wnd, &clientRect))
michael@0 432 return FALSE;
michael@0 433 return ::SetRectRgn(rgn, 0, 0, clientRect.right, clientRect.bottom);
michael@0 434 }
michael@0 435
michael@0 436 static RGNDATA*
michael@0 437 computeClipRegion(InstanceData* instanceData)
michael@0 438 {
michael@0 439 HWND wnd = (HWND)instanceData->window.window;
michael@0 440 HRGN rgn = ::CreateRectRgn(0, 0, 0, 0);
michael@0 441 if (!rgn)
michael@0 442 return nullptr;
michael@0 443 HRGN ancestorRgn = ::CreateRectRgn(0, 0, 0, 0);
michael@0 444 if (!ancestorRgn) {
michael@0 445 ::DeleteObject(rgn);
michael@0 446 return nullptr;
michael@0 447 }
michael@0 448 if (!getWindowRegion(wnd, rgn)) {
michael@0 449 ::DeleteObject(ancestorRgn);
michael@0 450 ::DeleteObject(rgn);
michael@0 451 return nullptr;
michael@0 452 }
michael@0 453
michael@0 454 HWND ancestor = wnd;
michael@0 455 for (;;) {
michael@0 456 ancestor = ::GetAncestor(ancestor, GA_PARENT);
michael@0 457 if (!ancestor || ancestor == ::GetDesktopWindow()) {
michael@0 458 ::DeleteObject(ancestorRgn);
michael@0 459
michael@0 460 DWORD size = ::GetRegionData(rgn, 0, nullptr);
michael@0 461 if (!size) {
michael@0 462 ::DeleteObject(rgn);
michael@0 463 return nullptr;
michael@0 464 }
michael@0 465
michael@0 466 HANDLE heap = ::GetProcessHeap();
michael@0 467 RGNDATA* data = static_cast<RGNDATA*>(::HeapAlloc(heap, 0, size));
michael@0 468 if (!data) {
michael@0 469 ::DeleteObject(rgn);
michael@0 470 return nullptr;
michael@0 471 }
michael@0 472 DWORD result = ::GetRegionData(rgn, size, data);
michael@0 473 ::DeleteObject(rgn);
michael@0 474 if (!result) {
michael@0 475 ::HeapFree(heap, 0, data);
michael@0 476 return nullptr;
michael@0 477 }
michael@0 478
michael@0 479 return data;
michael@0 480 }
michael@0 481
michael@0 482 if (!getWindowRegion(ancestor, ancestorRgn)) {
michael@0 483 ::DeleteObject(ancestorRgn);
michael@0 484 ::DeleteObject(rgn);
michael@0 485 return 0;
michael@0 486 }
michael@0 487
michael@0 488 POINT pt = { 0, 0 };
michael@0 489 ::MapWindowPoints(ancestor, wnd, &pt, 1);
michael@0 490 if (::OffsetRgn(ancestorRgn, pt.x, pt.y) == ERROR ||
michael@0 491 ::CombineRgn(rgn, rgn, ancestorRgn, RGN_AND) == ERROR) {
michael@0 492 ::DeleteObject(ancestorRgn);
michael@0 493 ::DeleteObject(rgn);
michael@0 494 return 0;
michael@0 495 }
michael@0 496 }
michael@0 497 }
michael@0 498
michael@0 499 int32_t
michael@0 500 pluginGetClipRegionRectCount(InstanceData* instanceData)
michael@0 501 {
michael@0 502 RGNDATA* data = computeClipRegion(instanceData);
michael@0 503 if (!data)
michael@0 504 return NPTEST_INT32_ERROR;
michael@0 505
michael@0 506 int32_t result = data->rdh.nCount;
michael@0 507 ::HeapFree(::GetProcessHeap(), 0, data);
michael@0 508 return result;
michael@0 509 }
michael@0 510
michael@0 511 static int32_t
michael@0 512 addOffset(LONG coord, int32_t offset)
michael@0 513 {
michael@0 514 if (offset == NPTEST_INT32_ERROR)
michael@0 515 return NPTEST_INT32_ERROR;
michael@0 516 return coord + offset;
michael@0 517 }
michael@0 518
michael@0 519 int32_t
michael@0 520 pluginGetClipRegionRectEdge(InstanceData* instanceData,
michael@0 521 int32_t rectIndex, RectEdge edge)
michael@0 522 {
michael@0 523 RGNDATA* data = computeClipRegion(instanceData);
michael@0 524 if (!data)
michael@0 525 return NPTEST_INT32_ERROR;
michael@0 526
michael@0 527 HANDLE heap = ::GetProcessHeap();
michael@0 528 if (rectIndex >= int32_t(data->rdh.nCount)) {
michael@0 529 ::HeapFree(heap, 0, data);
michael@0 530 return NPTEST_INT32_ERROR;
michael@0 531 }
michael@0 532
michael@0 533 RECT rect = reinterpret_cast<RECT*>(data->Buffer)[rectIndex];
michael@0 534 ::HeapFree(heap, 0, data);
michael@0 535
michael@0 536 switch (edge) {
michael@0 537 case EDGE_LEFT:
michael@0 538 return addOffset(rect.left, pluginGetEdge(instanceData, EDGE_LEFT));
michael@0 539 case EDGE_TOP:
michael@0 540 return addOffset(rect.top, pluginGetEdge(instanceData, EDGE_TOP));
michael@0 541 case EDGE_RIGHT:
michael@0 542 return addOffset(rect.right, pluginGetEdge(instanceData, EDGE_LEFT));
michael@0 543 case EDGE_BOTTOM:
michael@0 544 return addOffset(rect.bottom, pluginGetEdge(instanceData, EDGE_TOP));
michael@0 545 }
michael@0 546
michael@0 547 return NPTEST_INT32_ERROR;
michael@0 548 }
michael@0 549
michael@0 550 /* windowless plugin events */
michael@0 551
michael@0 552 static bool
michael@0 553 handleEventInternal(InstanceData* instanceData, NPEvent* pe, LRESULT* result)
michael@0 554 {
michael@0 555 switch ((UINT)pe->event) {
michael@0 556 case WM_PAINT:
michael@0 557 pluginDraw(instanceData);
michael@0 558 return true;
michael@0 559
michael@0 560 case WM_MOUSEACTIVATE:
michael@0 561 if (instanceData->hasWidget) {
michael@0 562 ::SetFocus((HWND)instanceData->window.window);
michael@0 563 *result = MA_ACTIVATEANDEAT;
michael@0 564 return true;
michael@0 565 }
michael@0 566 return false;
michael@0 567
michael@0 568 case WM_MOUSEWHEEL:
michael@0 569 return true;
michael@0 570
michael@0 571 case WM_WINDOWPOSCHANGED: {
michael@0 572 WINDOWPOS* pPos = (WINDOWPOS*)pe->lParam;
michael@0 573 instanceData->winX = instanceData->winY = 0;
michael@0 574 if (pPos) {
michael@0 575 instanceData->winX = pPos->x;
michael@0 576 instanceData->winY = pPos->y;
michael@0 577 return true;
michael@0 578 }
michael@0 579 return false;
michael@0 580 }
michael@0 581
michael@0 582 case WM_MOUSEMOVE:
michael@0 583 case WM_LBUTTONDOWN:
michael@0 584 case WM_LBUTTONUP:
michael@0 585 case WM_MBUTTONDOWN:
michael@0 586 case WM_MBUTTONUP:
michael@0 587 case WM_RBUTTONDOWN:
michael@0 588 case WM_RBUTTONUP: {
michael@0 589 int x = instanceData->hasWidget ? 0 : instanceData->winX;
michael@0 590 int y = instanceData->hasWidget ? 0 : instanceData->winY;
michael@0 591 instanceData->lastMouseX = GET_X_LPARAM(pe->lParam) - x;
michael@0 592 instanceData->lastMouseY = GET_Y_LPARAM(pe->lParam) - y;
michael@0 593 if ((UINT)pe->event == WM_LBUTTONUP) {
michael@0 594 instanceData->mouseUpEventCount++;
michael@0 595 }
michael@0 596 return true;
michael@0 597 }
michael@0 598
michael@0 599 case WM_KEYDOWN:
michael@0 600 instanceData->lastKeyText.erase();
michael@0 601 *result = 0;
michael@0 602 return true;
michael@0 603
michael@0 604 case WM_CHAR: {
michael@0 605 *result = 0;
michael@0 606 wchar_t uniChar = static_cast<wchar_t>(pe->wParam);
michael@0 607 if (!uniChar) {
michael@0 608 return true;
michael@0 609 }
michael@0 610 char utf8Char[6];
michael@0 611 int len =
michael@0 612 ::WideCharToMultiByte(CP_UTF8, 0, &uniChar, 1, utf8Char, 6,
michael@0 613 nullptr, nullptr);
michael@0 614 if (len == 0 || len > 6) {
michael@0 615 return true;
michael@0 616 }
michael@0 617 instanceData->lastKeyText.append(utf8Char, len);
michael@0 618 return true;
michael@0 619 }
michael@0 620
michael@0 621 default:
michael@0 622 return false;
michael@0 623 }
michael@0 624 }
michael@0 625
michael@0 626 int16_t
michael@0 627 pluginHandleEvent(InstanceData* instanceData, void* event)
michael@0 628 {
michael@0 629 NPEvent* pe = (NPEvent*)event;
michael@0 630
michael@0 631 if (pe == nullptr || instanceData == nullptr ||
michael@0 632 instanceData->window.type != NPWindowTypeDrawable)
michael@0 633 return 0;
michael@0 634
michael@0 635 LRESULT result = 0;
michael@0 636 return handleEventInternal(instanceData, pe, &result);
michael@0 637 }
michael@0 638
michael@0 639 /* windowed plugin events */
michael@0 640
michael@0 641 LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
michael@0 642 {
michael@0 643 WNDPROC wndProc = (WNDPROC)GetProp(hWnd, "MozillaWndProc");
michael@0 644 if (!wndProc)
michael@0 645 return 0;
michael@0 646 InstanceData* pInstance = (InstanceData*)GetProp(hWnd, "InstanceData");
michael@0 647 if (!pInstance)
michael@0 648 return 0;
michael@0 649
michael@0 650 NPEvent event = { static_cast<uint16_t>(uMsg), wParam, lParam };
michael@0 651
michael@0 652 LRESULT result = 0;
michael@0 653 if (handleEventInternal(pInstance, &event, &result))
michael@0 654 return result;
michael@0 655
michael@0 656 if (uMsg == WM_CLOSE) {
michael@0 657 ClearSubclass((HWND)pInstance->window.window);
michael@0 658 }
michael@0 659
michael@0 660 return CallWindowProc(wndProc, hWnd, uMsg, wParam, lParam);
michael@0 661 }
michael@0 662
michael@0 663 void
michael@0 664 ClearSubclass(HWND hWnd)
michael@0 665 {
michael@0 666 if (GetProp(hWnd, "MozillaWndProc")) {
michael@0 667 ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)GetProp(hWnd, "MozillaWndProc"));
michael@0 668 RemoveProp(hWnd, "MozillaWndProc");
michael@0 669 RemoveProp(hWnd, "InstanceData");
michael@0 670 }
michael@0 671 }
michael@0 672
michael@0 673 void
michael@0 674 SetSubclass(HWND hWnd, InstanceData* instanceData)
michael@0 675 {
michael@0 676 // Subclass the plugin window so we can handle our own windows events.
michael@0 677 SetProp(hWnd, "InstanceData", (HANDLE)instanceData);
michael@0 678 WNDPROC origProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)PluginWndProc);
michael@0 679 SetProp(hWnd, "MozillaWndProc", (HANDLE)origProc);
michael@0 680 }
michael@0 681
michael@0 682 static void checkEquals(int a, int b, const char* msg, string& error)
michael@0 683 {
michael@0 684 if (a == b) {
michael@0 685 return;
michael@0 686 }
michael@0 687
michael@0 688 error.append(msg);
michael@0 689 char buf[100];
michael@0 690 sprintf(buf, " (got %d, expected %d)\n", a, b);
michael@0 691 error.append(buf);
michael@0 692 }
michael@0 693
michael@0 694 void pluginDoInternalConsistencyCheck(InstanceData* instanceData, string& error)
michael@0 695 {
michael@0 696 if (instanceData->platformData->childWindow) {
michael@0 697 RECT childRect;
michael@0 698 ::GetWindowRect(instanceData->platformData->childWindow, &childRect);
michael@0 699 RECT ourRect;
michael@0 700 HWND hWnd = (HWND)instanceData->window.window;
michael@0 701 ::GetWindowRect(hWnd, &ourRect);
michael@0 702 checkEquals(childRect.left, ourRect.left, "Child widget left", error);
michael@0 703 checkEquals(childRect.top, ourRect.top, "Child widget top", error);
michael@0 704 checkEquals(childRect.right, childRect.left + CHILD_WIDGET_SIZE, "Child widget width", error);
michael@0 705 checkEquals(childRect.bottom, childRect.top + CHILD_WIDGET_SIZE, "Child widget height", error);
michael@0 706 }
michael@0 707 }
michael@0 708
michael@0 709 void
michael@0 710 pluginDrawAsyncDxgiColor(InstanceData* id)
michael@0 711 {
michael@0 712 PlatformData *pd = id->platformData;
michael@0 713
michael@0 714 ID3D10Device1 *dev = pd->device;
michael@0 715
michael@0 716 IDXGIKeyedMutex *mutex;
michael@0 717 pd->backBuffer->QueryInterface(&mutex);
michael@0 718
michael@0 719 mutex->AcquireSync(0, INFINITE);
michael@0 720 ID3D10RenderTargetView *rtView;
michael@0 721 dev->CreateRenderTargetView(pd->backBuffer, nullptr, &rtView);
michael@0 722
michael@0 723 uint32_t rgba = id->scriptableObject->drawColor;
michael@0 724
michael@0 725 unsigned char subpixels[4];
michael@0 726 subpixels[0] = rgba & 0xFF;
michael@0 727 subpixels[1] = (rgba & 0xFF00) >> 8;
michael@0 728 subpixels[2] = (rgba & 0xFF0000) >> 16;
michael@0 729 subpixels[3] = (rgba & 0xFF000000) >> 24;
michael@0 730
michael@0 731 float color[4];
michael@0 732 color[2] = float(subpixels[3] * subpixels[0]) / 0xFE01;
michael@0 733 color[1] = float(subpixels[3] * subpixels[1]) / 0xFE01;
michael@0 734 color[0] = float(subpixels[3] * subpixels[2]) / 0xFE01;
michael@0 735 color[3] = float(subpixels[3]) / 0xFF;
michael@0 736 dev->ClearRenderTargetView(rtView, color);
michael@0 737 rtView->Release();
michael@0 738
michael@0 739 mutex->ReleaseSync(0);
michael@0 740 mutex->Release();
michael@0 741
michael@0 742 NPN_SetCurrentAsyncSurface(id->npp, id->backBuffer, nullptr);
michael@0 743 NPAsyncSurface *oldFront = id->frontBuffer;
michael@0 744 id->frontBuffer = id->backBuffer;
michael@0 745 id->backBuffer = oldFront;
michael@0 746 ID3D10Texture2D *oldFrontT = pd->frontBuffer;
michael@0 747 pd->frontBuffer = pd->backBuffer;
michael@0 748 pd->backBuffer = oldFrontT;
michael@0 749 }

mercurial