dom/plugins/test/testplugin/nptest_windows.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial