1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/plugins/test/testplugin/nptest_windows.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,749 @@ 1.4 +/* ***** BEGIN LICENSE BLOCK ***** 1.5 + * 1.6 + * Copyright (c) 2008, Mozilla Corporation 1.7 + * All rights reserved. 1.8 + * 1.9 + * Redistribution and use in source and binary forms, with or without 1.10 + * modification, are permitted provided that the following conditions are met: 1.11 + * 1.12 + * * Redistributions of source code must retain the above copyright notice, this 1.13 + * list of conditions and the following disclaimer. 1.14 + * * Redistributions in binary form must reproduce the above copyright notice, 1.15 + * this list of conditions and the following disclaimer in the documentation 1.16 + * and/or other materials provided with the distribution. 1.17 + * * Neither the name of the Mozilla Corporation nor the names of its 1.18 + * contributors may be used to endorse or promote products derived from this 1.19 + * software without specific prior written permission. 1.20 + * 1.21 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 1.22 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 1.23 + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 1.24 + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 1.25 + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 1.26 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 1.27 + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 1.28 + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.29 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 1.30 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.31 + * 1.32 + * Contributor(s): 1.33 + * Josh Aas <josh@mozilla.com> 1.34 + * Jim Mathies <jmathies@mozilla.com> 1.35 + * 1.36 + * ***** END LICENSE BLOCK ***** */ 1.37 + 1.38 +#include "nptest_platform.h" 1.39 + 1.40 +#include <windows.h> 1.41 +#include <windowsx.h> 1.42 +#include <stdio.h> 1.43 + 1.44 +#include <d3d10_1.h> 1.45 + 1.46 +using namespace std; 1.47 + 1.48 +void SetSubclass(HWND hWnd, InstanceData* instanceData); 1.49 +void ClearSubclass(HWND hWnd); 1.50 +LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); 1.51 + 1.52 +struct _PlatformData { 1.53 + HWND childWindow; 1.54 + ID3D10Device1 *device; 1.55 + ID3D10Texture2D *frontBuffer; 1.56 + ID3D10Texture2D *backBuffer; 1.57 +}; 1.58 + 1.59 +bool 1.60 +pluginSupportsWindowMode() 1.61 +{ 1.62 + return true; 1.63 +} 1.64 + 1.65 +bool 1.66 +pluginSupportsWindowlessMode() 1.67 +{ 1.68 + return true; 1.69 +} 1.70 + 1.71 +bool 1.72 +pluginSupportsAsyncBitmapDrawing() 1.73 +{ 1.74 + return true; 1.75 +} 1.76 + 1.77 +NPError 1.78 +pluginInstanceInit(InstanceData* instanceData) 1.79 +{ 1.80 + NPP npp = instanceData->npp; 1.81 + 1.82 + instanceData->platformData = static_cast<PlatformData*> 1.83 + (NPN_MemAlloc(sizeof(PlatformData))); 1.84 + if (!instanceData->platformData) 1.85 + return NPERR_OUT_OF_MEMORY_ERROR; 1.86 + 1.87 + instanceData->platformData->childWindow = nullptr; 1.88 + instanceData->platformData->device = nullptr; 1.89 + instanceData->platformData->frontBuffer = nullptr; 1.90 + instanceData->platformData->backBuffer = nullptr; 1.91 + return NPERR_NO_ERROR; 1.92 +} 1.93 + 1.94 +void 1.95 +pluginInstanceShutdown(InstanceData* instanceData) 1.96 +{ 1.97 + PlatformData *pd = instanceData->platformData; 1.98 + if (pd->frontBuffer) { 1.99 + pd->frontBuffer->Release(); 1.100 + } 1.101 + if (pd->backBuffer) { 1.102 + pd->backBuffer->Release(); 1.103 + } 1.104 + if (pd->device) { 1.105 + pd->device->Release(); 1.106 + } 1.107 + NPN_MemFree(instanceData->platformData); 1.108 + instanceData->platformData = 0; 1.109 +} 1.110 + 1.111 +static ID3D10Device1* 1.112 +getD3D10Device() 1.113 +{ 1.114 + ID3D10Device1 *device; 1.115 + 1.116 + HMODULE d3d10module = LoadLibraryA("d3d10_1.dll"); 1.117 + decltype(D3D10CreateDevice1)* createD3DDevice = 1.118 + (decltype(D3D10CreateDevice1)*) GetProcAddress(d3d10module, 1.119 + "D3D10CreateDevice1"); 1.120 + 1.121 + if (createD3DDevice) { 1.122 + HMODULE dxgiModule = LoadLibraryA("dxgi.dll"); 1.123 + decltype(CreateDXGIFactory1)* createDXGIFactory1 = 1.124 + (decltype(CreateDXGIFactory1)*) GetProcAddress(dxgiModule, 1.125 + "CreateDXGIFactory1"); 1.126 + 1.127 + HRESULT hr; 1.128 + 1.129 + // Try to use a DXGI 1.1 adapter in order to share resources 1.130 + // across processes. 1.131 + IDXGIAdapter1 *adapter1; 1.132 + if (createDXGIFactory1) { 1.133 + IDXGIFactory1 *factory1; 1.134 + hr = createDXGIFactory1(__uuidof(IDXGIFactory1), 1.135 + (void**)&factory1); 1.136 + 1.137 + if (FAILED(hr) || !factory1) { 1.138 + // Uh-oh 1.139 + return nullptr; 1.140 + } 1.141 + 1.142 + hr = factory1->EnumAdapters1(0, &adapter1); 1.143 + 1.144 + if (SUCCEEDED(hr) && adapter1) { 1.145 + hr = adapter1->CheckInterfaceSupport(__uuidof(ID3D10Device), 1.146 + nullptr); 1.147 + if (FAILED(hr)) { 1.148 + adapter1 = nullptr; 1.149 + } 1.150 + } 1.151 + factory1->Release(); 1.152 + } 1.153 + 1.154 + hr = createD3DDevice( 1.155 + adapter1, 1.156 + D3D10_DRIVER_TYPE_HARDWARE, 1.157 + nullptr, 1.158 + D3D10_CREATE_DEVICE_BGRA_SUPPORT | 1.159 + D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS, 1.160 + D3D10_FEATURE_LEVEL_10_0, 1.161 + D3D10_1_SDK_VERSION, 1.162 + &device); 1.163 + 1.164 + adapter1->Release(); 1.165 + } 1.166 + 1.167 + return device; 1.168 +} 1.169 + 1.170 +void 1.171 +pluginDoSetWindow(InstanceData* instanceData, NPWindow* newWindow) 1.172 +{ 1.173 + instanceData->window = *newWindow; 1.174 + NPP npp = instanceData->npp; 1.175 + 1.176 + if (instanceData->asyncDrawing == AD_DXGI) { 1.177 + if (instanceData->frontBuffer && 1.178 + instanceData->frontBuffer->size.width == newWindow->width && 1.179 + instanceData->frontBuffer->size.height == newWindow->height) { 1.180 + return; 1.181 + } 1.182 + if (instanceData->frontBuffer) { 1.183 + instanceData->platformData->frontBuffer->Release(); 1.184 + instanceData->platformData->frontBuffer = nullptr; 1.185 + NPN_FinalizeAsyncSurface(npp, instanceData->frontBuffer); 1.186 + NPN_MemFree(instanceData->frontBuffer); 1.187 + } 1.188 + if (instanceData->backBuffer) { 1.189 + instanceData->platformData->backBuffer->Release(); 1.190 + instanceData->platformData->backBuffer = nullptr; 1.191 + NPN_FinalizeAsyncSurface(npp, instanceData->backBuffer); 1.192 + NPN_MemFree(instanceData->backBuffer); 1.193 + } 1.194 + 1.195 + if (!instanceData->platformData->device) { 1.196 + instanceData->platformData->device = getD3D10Device(); 1.197 + } 1.198 + 1.199 + ID3D10Device1 *dev = instanceData->platformData->device; 1.200 + 1.201 + if (!dev) { 1.202 + return; 1.203 + } 1.204 + 1.205 + instanceData->frontBuffer = (NPAsyncSurface*)NPN_MemAlloc(sizeof(NPAsyncSurface)); 1.206 + instanceData->backBuffer = (NPAsyncSurface*)NPN_MemAlloc(sizeof(NPAsyncSurface)); 1.207 + 1.208 + NPSize size; 1.209 + size.width = newWindow->width; 1.210 + size.height = newWindow->height; 1.211 + 1.212 + memset(instanceData->frontBuffer, 0, sizeof(NPAsyncSurface)); 1.213 + memset(instanceData->backBuffer, 0, sizeof(NPAsyncSurface)); 1.214 + 1.215 + NPN_InitAsyncSurface(npp, &size, NPImageFormatBGRA32, nullptr, instanceData->frontBuffer); 1.216 + NPN_InitAsyncSurface(npp, &size, NPImageFormatBGRA32, nullptr, instanceData->backBuffer); 1.217 + 1.218 + dev->OpenSharedResource(instanceData->frontBuffer->sharedHandle, __uuidof(ID3D10Texture2D), (void**)&instanceData->platformData->frontBuffer); 1.219 + dev->OpenSharedResource(instanceData->backBuffer->sharedHandle, __uuidof(ID3D10Texture2D), (void**)&instanceData->platformData->backBuffer); 1.220 + 1.221 + pluginDrawAsyncDxgiColor(instanceData); 1.222 + } 1.223 +} 1.224 + 1.225 +#define CHILD_WIDGET_SIZE 10 1.226 + 1.227 +void 1.228 +pluginWidgetInit(InstanceData* instanceData, void* oldWindow) 1.229 +{ 1.230 + HWND hWnd = (HWND)instanceData->window.window; 1.231 + if (oldWindow) { 1.232 + // chrashtests/539897-1.html excercises this code 1.233 + HWND hWndOld = (HWND)oldWindow; 1.234 + ClearSubclass(hWndOld); 1.235 + if (instanceData->platformData->childWindow) { 1.236 + ::DestroyWindow(instanceData->platformData->childWindow); 1.237 + } 1.238 + } 1.239 + 1.240 + SetSubclass(hWnd, instanceData); 1.241 + 1.242 + instanceData->platformData->childWindow = 1.243 + ::CreateWindowW(L"SCROLLBAR", L"Dummy child window", 1.244 + WS_CHILD, 0, 0, CHILD_WIDGET_SIZE, CHILD_WIDGET_SIZE, hWnd, nullptr, 1.245 + nullptr, nullptr); 1.246 +} 1.247 + 1.248 +static void 1.249 +drawToDC(InstanceData* instanceData, HDC dc, 1.250 + int x, int y, int width, int height) 1.251 +{ 1.252 + switch (instanceData->scriptableObject->drawMode) { 1.253 + case DM_DEFAULT: 1.254 + { 1.255 + const RECT fill = { x, y, x + width, y + height }; 1.256 + 1.257 + int oldBkMode = ::SetBkMode(dc, TRANSPARENT); 1.258 + HBRUSH brush = ::CreateSolidBrush(RGB(0, 0, 0)); 1.259 + if (brush) { 1.260 + ::FillRect(dc, &fill, brush); 1.261 + ::DeleteObject(brush); 1.262 + } 1.263 + if (width > 6 && height > 6) { 1.264 + brush = ::CreateSolidBrush(RGB(192, 192, 192)); 1.265 + if (brush) { 1.266 + RECT inset = { x + 3, y + 3, x + width - 3, y + height - 3 }; 1.267 + ::FillRect(dc, &inset, brush); 1.268 + ::DeleteObject(brush); 1.269 + } 1.270 + } 1.271 + 1.272 + const char* uaString = NPN_UserAgent(instanceData->npp); 1.273 + if (uaString && width > 10 && height > 10) { 1.274 + HFONT font = 1.275 + ::CreateFontA(20, 0, 0, 0, 400, FALSE, FALSE, FALSE, 1.276 + DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, 1.277 + CLIP_DEFAULT_PRECIS, 5, // CLEARTYPE_QUALITY 1.278 + DEFAULT_PITCH, "Arial"); 1.279 + if (font) { 1.280 + HFONT oldFont = (HFONT)::SelectObject(dc, font); 1.281 + RECT inset = { x + 5, y + 5, x + width - 5, y + height - 5 }; 1.282 + ::DrawTextA(dc, uaString, -1, &inset, 1.283 + DT_LEFT | DT_TOP | DT_NOPREFIX | DT_WORDBREAK); 1.284 + ::SelectObject(dc, oldFont); 1.285 + ::DeleteObject(font); 1.286 + } 1.287 + } 1.288 + ::SetBkMode(dc, oldBkMode); 1.289 + } 1.290 + break; 1.291 + 1.292 + case DM_SOLID_COLOR: 1.293 + { 1.294 + HDC offscreenDC = ::CreateCompatibleDC(dc); 1.295 + if (!offscreenDC) 1.296 + return; 1.297 + 1.298 + const BITMAPV4HEADER bitmapheader = { 1.299 + sizeof(BITMAPV4HEADER), 1.300 + width, 1.301 + height, 1.302 + 1, // planes 1.303 + 32, // bits 1.304 + BI_BITFIELDS, 1.305 + 0, // unused size 1.306 + 0, 0, // unused metrics 1.307 + 0, 0, // unused colors used/important 1.308 + 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000, // ARGB masks 1.309 + }; 1.310 + uint32_t *pixelData; 1.311 + HBITMAP offscreenBitmap = 1.312 + ::CreateDIBSection(dc, reinterpret_cast<const BITMAPINFO*>(&bitmapheader), 1.313 + 0, reinterpret_cast<void**>(&pixelData), 0, 0); 1.314 + if (!offscreenBitmap) 1.315 + return; 1.316 + 1.317 + uint32_t rgba = instanceData->scriptableObject->drawColor; 1.318 + unsigned int alpha = ((rgba & 0xFF000000) >> 24); 1.319 + BYTE r = ((rgba & 0xFF0000) >> 16); 1.320 + BYTE g = ((rgba & 0xFF00) >> 8); 1.321 + BYTE b = (rgba & 0xFF); 1.322 + 1.323 + // Windows expects premultiplied 1.324 + r = BYTE(float(alpha * r) / 0xFF); 1.325 + g = BYTE(float(alpha * g) / 0xFF); 1.326 + b = BYTE(float(alpha * b) / 0xFF); 1.327 + uint32_t premultiplied = 1.328 + (alpha << 24) + (r << 16) + (g << 8) + b; 1.329 + 1.330 + for (uint32_t* lastPixel = pixelData + width * height; 1.331 + pixelData < lastPixel; 1.332 + ++pixelData) 1.333 + *pixelData = premultiplied; 1.334 + 1.335 + ::SelectObject(offscreenDC, offscreenBitmap); 1.336 + BLENDFUNCTION blendFunc; 1.337 + blendFunc.BlendOp = AC_SRC_OVER; 1.338 + blendFunc.BlendFlags = 0; 1.339 + blendFunc.SourceConstantAlpha = 255; 1.340 + blendFunc.AlphaFormat = AC_SRC_ALPHA; 1.341 + ::AlphaBlend(dc, x, y, width, height, offscreenDC, 0, 0, width, height, 1.342 + blendFunc); 1.343 + 1.344 + ::DeleteObject(offscreenDC); 1.345 + ::DeleteObject(offscreenBitmap); 1.346 + } 1.347 + break; 1.348 + } 1.349 +} 1.350 + 1.351 +void 1.352 +pluginDraw(InstanceData* instanceData) 1.353 +{ 1.354 + NPP npp = instanceData->npp; 1.355 + if (!npp) 1.356 + return; 1.357 + 1.358 + HDC hdc = nullptr; 1.359 + PAINTSTRUCT ps; 1.360 + 1.361 + notifyDidPaint(instanceData); 1.362 + 1.363 + if (instanceData->hasWidget) 1.364 + hdc = ::BeginPaint((HWND)instanceData->window.window, &ps); 1.365 + else 1.366 + hdc = (HDC)instanceData->window.window; 1.367 + 1.368 + if (hdc == nullptr) 1.369 + return; 1.370 + 1.371 + // Push the browser's hdc on the resource stack. If this test plugin is windowless, 1.372 + // we share the drawing surface with the rest of the browser. 1.373 + int savedDCID = SaveDC(hdc); 1.374 + 1.375 + // When we have a widget, window.x/y are meaningless since our widget 1.376 + // is always positioned correctly and we just draw into it at 0,0. 1.377 + int x = instanceData->hasWidget ? 0 : instanceData->window.x; 1.378 + int y = instanceData->hasWidget ? 0 : instanceData->window.y; 1.379 + int width = instanceData->window.width; 1.380 + int height = instanceData->window.height; 1.381 + drawToDC(instanceData, hdc, x, y, width, height); 1.382 + 1.383 + // Pop our hdc changes off the resource stack 1.384 + RestoreDC(hdc, savedDCID); 1.385 + 1.386 + if (instanceData->hasWidget) 1.387 + ::EndPaint((HWND)instanceData->window.window, &ps); 1.388 +} 1.389 + 1.390 +/* script interface */ 1.391 + 1.392 +int32_t 1.393 +pluginGetEdge(InstanceData* instanceData, RectEdge edge) 1.394 +{ 1.395 + if (!instanceData || !instanceData->hasWidget) 1.396 + return NPTEST_INT32_ERROR; 1.397 + 1.398 + // Get the plugin client rect in screen coordinates 1.399 + RECT rect = {0}; 1.400 + if (!::GetClientRect((HWND)instanceData->window.window, &rect)) 1.401 + return NPTEST_INT32_ERROR; 1.402 + ::MapWindowPoints((HWND)instanceData->window.window, nullptr, 1.403 + (LPPOINT)&rect, 2); 1.404 + 1.405 + // Get the toplevel window frame rect in screen coordinates 1.406 + HWND rootWnd = ::GetAncestor((HWND)instanceData->window.window, GA_ROOT); 1.407 + if (!rootWnd) 1.408 + return NPTEST_INT32_ERROR; 1.409 + RECT rootRect; 1.410 + if (!::GetWindowRect(rootWnd, &rootRect)) 1.411 + return NPTEST_INT32_ERROR; 1.412 + 1.413 + switch (edge) { 1.414 + case EDGE_LEFT: 1.415 + return rect.left - rootRect.left; 1.416 + case EDGE_TOP: 1.417 + return rect.top - rootRect.top; 1.418 + case EDGE_RIGHT: 1.419 + return rect.right - rootRect.left; 1.420 + case EDGE_BOTTOM: 1.421 + return rect.bottom - rootRect.top; 1.422 + } 1.423 + 1.424 + return NPTEST_INT32_ERROR; 1.425 +} 1.426 + 1.427 +static BOOL 1.428 +getWindowRegion(HWND wnd, HRGN rgn) 1.429 +{ 1.430 + if (::GetWindowRgn(wnd, rgn) != ERROR) 1.431 + return TRUE; 1.432 + 1.433 + RECT clientRect; 1.434 + if (!::GetClientRect(wnd, &clientRect)) 1.435 + return FALSE; 1.436 + return ::SetRectRgn(rgn, 0, 0, clientRect.right, clientRect.bottom); 1.437 +} 1.438 + 1.439 +static RGNDATA* 1.440 +computeClipRegion(InstanceData* instanceData) 1.441 +{ 1.442 + HWND wnd = (HWND)instanceData->window.window; 1.443 + HRGN rgn = ::CreateRectRgn(0, 0, 0, 0); 1.444 + if (!rgn) 1.445 + return nullptr; 1.446 + HRGN ancestorRgn = ::CreateRectRgn(0, 0, 0, 0); 1.447 + if (!ancestorRgn) { 1.448 + ::DeleteObject(rgn); 1.449 + return nullptr; 1.450 + } 1.451 + if (!getWindowRegion(wnd, rgn)) { 1.452 + ::DeleteObject(ancestorRgn); 1.453 + ::DeleteObject(rgn); 1.454 + return nullptr; 1.455 + } 1.456 + 1.457 + HWND ancestor = wnd; 1.458 + for (;;) { 1.459 + ancestor = ::GetAncestor(ancestor, GA_PARENT); 1.460 + if (!ancestor || ancestor == ::GetDesktopWindow()) { 1.461 + ::DeleteObject(ancestorRgn); 1.462 + 1.463 + DWORD size = ::GetRegionData(rgn, 0, nullptr); 1.464 + if (!size) { 1.465 + ::DeleteObject(rgn); 1.466 + return nullptr; 1.467 + } 1.468 + 1.469 + HANDLE heap = ::GetProcessHeap(); 1.470 + RGNDATA* data = static_cast<RGNDATA*>(::HeapAlloc(heap, 0, size)); 1.471 + if (!data) { 1.472 + ::DeleteObject(rgn); 1.473 + return nullptr; 1.474 + } 1.475 + DWORD result = ::GetRegionData(rgn, size, data); 1.476 + ::DeleteObject(rgn); 1.477 + if (!result) { 1.478 + ::HeapFree(heap, 0, data); 1.479 + return nullptr; 1.480 + } 1.481 + 1.482 + return data; 1.483 + } 1.484 + 1.485 + if (!getWindowRegion(ancestor, ancestorRgn)) { 1.486 + ::DeleteObject(ancestorRgn); 1.487 + ::DeleteObject(rgn); 1.488 + return 0; 1.489 + } 1.490 + 1.491 + POINT pt = { 0, 0 }; 1.492 + ::MapWindowPoints(ancestor, wnd, &pt, 1); 1.493 + if (::OffsetRgn(ancestorRgn, pt.x, pt.y) == ERROR || 1.494 + ::CombineRgn(rgn, rgn, ancestorRgn, RGN_AND) == ERROR) { 1.495 + ::DeleteObject(ancestorRgn); 1.496 + ::DeleteObject(rgn); 1.497 + return 0; 1.498 + } 1.499 + } 1.500 +} 1.501 + 1.502 +int32_t 1.503 +pluginGetClipRegionRectCount(InstanceData* instanceData) 1.504 +{ 1.505 + RGNDATA* data = computeClipRegion(instanceData); 1.506 + if (!data) 1.507 + return NPTEST_INT32_ERROR; 1.508 + 1.509 + int32_t result = data->rdh.nCount; 1.510 + ::HeapFree(::GetProcessHeap(), 0, data); 1.511 + return result; 1.512 +} 1.513 + 1.514 +static int32_t 1.515 +addOffset(LONG coord, int32_t offset) 1.516 +{ 1.517 + if (offset == NPTEST_INT32_ERROR) 1.518 + return NPTEST_INT32_ERROR; 1.519 + return coord + offset; 1.520 +} 1.521 + 1.522 +int32_t 1.523 +pluginGetClipRegionRectEdge(InstanceData* instanceData, 1.524 + int32_t rectIndex, RectEdge edge) 1.525 +{ 1.526 + RGNDATA* data = computeClipRegion(instanceData); 1.527 + if (!data) 1.528 + return NPTEST_INT32_ERROR; 1.529 + 1.530 + HANDLE heap = ::GetProcessHeap(); 1.531 + if (rectIndex >= int32_t(data->rdh.nCount)) { 1.532 + ::HeapFree(heap, 0, data); 1.533 + return NPTEST_INT32_ERROR; 1.534 + } 1.535 + 1.536 + RECT rect = reinterpret_cast<RECT*>(data->Buffer)[rectIndex]; 1.537 + ::HeapFree(heap, 0, data); 1.538 + 1.539 + switch (edge) { 1.540 + case EDGE_LEFT: 1.541 + return addOffset(rect.left, pluginGetEdge(instanceData, EDGE_LEFT)); 1.542 + case EDGE_TOP: 1.543 + return addOffset(rect.top, pluginGetEdge(instanceData, EDGE_TOP)); 1.544 + case EDGE_RIGHT: 1.545 + return addOffset(rect.right, pluginGetEdge(instanceData, EDGE_LEFT)); 1.546 + case EDGE_BOTTOM: 1.547 + return addOffset(rect.bottom, pluginGetEdge(instanceData, EDGE_TOP)); 1.548 + } 1.549 + 1.550 + return NPTEST_INT32_ERROR; 1.551 +} 1.552 + 1.553 +/* windowless plugin events */ 1.554 + 1.555 +static bool 1.556 +handleEventInternal(InstanceData* instanceData, NPEvent* pe, LRESULT* result) 1.557 +{ 1.558 + switch ((UINT)pe->event) { 1.559 + case WM_PAINT: 1.560 + pluginDraw(instanceData); 1.561 + return true; 1.562 + 1.563 + case WM_MOUSEACTIVATE: 1.564 + if (instanceData->hasWidget) { 1.565 + ::SetFocus((HWND)instanceData->window.window); 1.566 + *result = MA_ACTIVATEANDEAT; 1.567 + return true; 1.568 + } 1.569 + return false; 1.570 + 1.571 + case WM_MOUSEWHEEL: 1.572 + return true; 1.573 + 1.574 + case WM_WINDOWPOSCHANGED: { 1.575 + WINDOWPOS* pPos = (WINDOWPOS*)pe->lParam; 1.576 + instanceData->winX = instanceData->winY = 0; 1.577 + if (pPos) { 1.578 + instanceData->winX = pPos->x; 1.579 + instanceData->winY = pPos->y; 1.580 + return true; 1.581 + } 1.582 + return false; 1.583 + } 1.584 + 1.585 + case WM_MOUSEMOVE: 1.586 + case WM_LBUTTONDOWN: 1.587 + case WM_LBUTTONUP: 1.588 + case WM_MBUTTONDOWN: 1.589 + case WM_MBUTTONUP: 1.590 + case WM_RBUTTONDOWN: 1.591 + case WM_RBUTTONUP: { 1.592 + int x = instanceData->hasWidget ? 0 : instanceData->winX; 1.593 + int y = instanceData->hasWidget ? 0 : instanceData->winY; 1.594 + instanceData->lastMouseX = GET_X_LPARAM(pe->lParam) - x; 1.595 + instanceData->lastMouseY = GET_Y_LPARAM(pe->lParam) - y; 1.596 + if ((UINT)pe->event == WM_LBUTTONUP) { 1.597 + instanceData->mouseUpEventCount++; 1.598 + } 1.599 + return true; 1.600 + } 1.601 + 1.602 + case WM_KEYDOWN: 1.603 + instanceData->lastKeyText.erase(); 1.604 + *result = 0; 1.605 + return true; 1.606 + 1.607 + case WM_CHAR: { 1.608 + *result = 0; 1.609 + wchar_t uniChar = static_cast<wchar_t>(pe->wParam); 1.610 + if (!uniChar) { 1.611 + return true; 1.612 + } 1.613 + char utf8Char[6]; 1.614 + int len = 1.615 + ::WideCharToMultiByte(CP_UTF8, 0, &uniChar, 1, utf8Char, 6, 1.616 + nullptr, nullptr); 1.617 + if (len == 0 || len > 6) { 1.618 + return true; 1.619 + } 1.620 + instanceData->lastKeyText.append(utf8Char, len); 1.621 + return true; 1.622 + } 1.623 + 1.624 + default: 1.625 + return false; 1.626 + } 1.627 +} 1.628 + 1.629 +int16_t 1.630 +pluginHandleEvent(InstanceData* instanceData, void* event) 1.631 +{ 1.632 + NPEvent* pe = (NPEvent*)event; 1.633 + 1.634 + if (pe == nullptr || instanceData == nullptr || 1.635 + instanceData->window.type != NPWindowTypeDrawable) 1.636 + return 0; 1.637 + 1.638 + LRESULT result = 0; 1.639 + return handleEventInternal(instanceData, pe, &result); 1.640 +} 1.641 + 1.642 +/* windowed plugin events */ 1.643 + 1.644 +LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 1.645 +{ 1.646 + WNDPROC wndProc = (WNDPROC)GetProp(hWnd, "MozillaWndProc"); 1.647 + if (!wndProc) 1.648 + return 0; 1.649 + InstanceData* pInstance = (InstanceData*)GetProp(hWnd, "InstanceData"); 1.650 + if (!pInstance) 1.651 + return 0; 1.652 + 1.653 + NPEvent event = { static_cast<uint16_t>(uMsg), wParam, lParam }; 1.654 + 1.655 + LRESULT result = 0; 1.656 + if (handleEventInternal(pInstance, &event, &result)) 1.657 + return result; 1.658 + 1.659 + if (uMsg == WM_CLOSE) { 1.660 + ClearSubclass((HWND)pInstance->window.window); 1.661 + } 1.662 + 1.663 + return CallWindowProc(wndProc, hWnd, uMsg, wParam, lParam); 1.664 +} 1.665 + 1.666 +void 1.667 +ClearSubclass(HWND hWnd) 1.668 +{ 1.669 + if (GetProp(hWnd, "MozillaWndProc")) { 1.670 + ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)GetProp(hWnd, "MozillaWndProc")); 1.671 + RemoveProp(hWnd, "MozillaWndProc"); 1.672 + RemoveProp(hWnd, "InstanceData"); 1.673 + } 1.674 +} 1.675 + 1.676 +void 1.677 +SetSubclass(HWND hWnd, InstanceData* instanceData) 1.678 +{ 1.679 + // Subclass the plugin window so we can handle our own windows events. 1.680 + SetProp(hWnd, "InstanceData", (HANDLE)instanceData); 1.681 + WNDPROC origProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)PluginWndProc); 1.682 + SetProp(hWnd, "MozillaWndProc", (HANDLE)origProc); 1.683 +} 1.684 + 1.685 +static void checkEquals(int a, int b, const char* msg, string& error) 1.686 +{ 1.687 + if (a == b) { 1.688 + return; 1.689 + } 1.690 + 1.691 + error.append(msg); 1.692 + char buf[100]; 1.693 + sprintf(buf, " (got %d, expected %d)\n", a, b); 1.694 + error.append(buf); 1.695 +} 1.696 + 1.697 +void pluginDoInternalConsistencyCheck(InstanceData* instanceData, string& error) 1.698 +{ 1.699 + if (instanceData->platformData->childWindow) { 1.700 + RECT childRect; 1.701 + ::GetWindowRect(instanceData->platformData->childWindow, &childRect); 1.702 + RECT ourRect; 1.703 + HWND hWnd = (HWND)instanceData->window.window; 1.704 + ::GetWindowRect(hWnd, &ourRect); 1.705 + checkEquals(childRect.left, ourRect.left, "Child widget left", error); 1.706 + checkEquals(childRect.top, ourRect.top, "Child widget top", error); 1.707 + checkEquals(childRect.right, childRect.left + CHILD_WIDGET_SIZE, "Child widget width", error); 1.708 + checkEquals(childRect.bottom, childRect.top + CHILD_WIDGET_SIZE, "Child widget height", error); 1.709 + } 1.710 +} 1.711 + 1.712 +void 1.713 +pluginDrawAsyncDxgiColor(InstanceData* id) 1.714 +{ 1.715 + PlatformData *pd = id->platformData; 1.716 + 1.717 + ID3D10Device1 *dev = pd->device; 1.718 + 1.719 + IDXGIKeyedMutex *mutex; 1.720 + pd->backBuffer->QueryInterface(&mutex); 1.721 + 1.722 + mutex->AcquireSync(0, INFINITE); 1.723 + ID3D10RenderTargetView *rtView; 1.724 + dev->CreateRenderTargetView(pd->backBuffer, nullptr, &rtView); 1.725 + 1.726 + uint32_t rgba = id->scriptableObject->drawColor; 1.727 + 1.728 + unsigned char subpixels[4]; 1.729 + subpixels[0] = rgba & 0xFF; 1.730 + subpixels[1] = (rgba & 0xFF00) >> 8; 1.731 + subpixels[2] = (rgba & 0xFF0000) >> 16; 1.732 + subpixels[3] = (rgba & 0xFF000000) >> 24; 1.733 + 1.734 + float color[4]; 1.735 + color[2] = float(subpixels[3] * subpixels[0]) / 0xFE01; 1.736 + color[1] = float(subpixels[3] * subpixels[1]) / 0xFE01; 1.737 + color[0] = float(subpixels[3] * subpixels[2]) / 0xFE01; 1.738 + color[3] = float(subpixels[3]) / 0xFF; 1.739 + dev->ClearRenderTargetView(rtView, color); 1.740 + rtView->Release(); 1.741 + 1.742 + mutex->ReleaseSync(0); 1.743 + mutex->Release(); 1.744 + 1.745 + NPN_SetCurrentAsyncSurface(id->npp, id->backBuffer, nullptr); 1.746 + NPAsyncSurface *oldFront = id->frontBuffer; 1.747 + id->frontBuffer = id->backBuffer; 1.748 + id->backBuffer = oldFront; 1.749 + ID3D10Texture2D *oldFrontT = pd->frontBuffer; 1.750 + pd->frontBuffer = pd->backBuffer; 1.751 + pd->backBuffer = oldFrontT; 1.752 +}