widget/windows/winrt/MetroWidget.cpp

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "ContentHelper.h"
     8 #include "LayerManagerD3D10.h"
     9 #include "MetroWidget.h"
    10 #include "MetroApp.h"
    11 #include "mozilla/Preferences.h"
    12 #include "nsToolkit.h"
    13 #include "KeyboardLayout.h"
    14 #include "MetroUtils.h"
    15 #include "WinUtils.h"
    16 #include "nsToolkitCompsCID.h"
    17 #include "nsIAppStartup.h"
    18 #include "../resource.h"
    19 #include "nsIWidgetListener.h"
    20 #include "nsIPresShell.h"
    21 #include "nsPrintfCString.h"
    22 #include "nsWindowDefs.h"
    23 #include "FrameworkView.h"
    24 #include "nsTextStore.h"
    25 #include "Layers.h"
    26 #include "ClientLayerManager.h"
    27 #include "BasicLayers.h"
    28 #include "FrameMetrics.h"
    29 #include <windows.devices.input.h>
    30 #include "Windows.Graphics.Display.h"
    31 #include "DisplayInfo_sdk81.h"
    32 #include "nsNativeDragTarget.h"
    33 #ifdef MOZ_CRASHREPORTER
    34 #include "nsExceptionHandler.h"
    35 #endif
    36 #include "UIABridgePrivate.h"
    37 #include "WinMouseScrollHandler.h"
    38 #include "InputData.h"
    39 #include "mozilla/TextEvents.h"
    40 #include "mozilla/TouchEvents.h"
    41 #include "mozilla/MiscEvents.h"
    43 using namespace Microsoft::WRL;
    44 using namespace Microsoft::WRL::Wrappers;
    46 using namespace mozilla;
    47 using namespace mozilla::widget;
    48 using namespace mozilla::layers;
    49 using namespace mozilla::widget::winrt;
    51 using namespace ABI::Windows::ApplicationModel;
    52 using namespace ABI::Windows::ApplicationModel::Core;
    53 using namespace ABI::Windows::ApplicationModel::Activation;
    54 using namespace ABI::Windows::UI::Input;
    55 using namespace ABI::Windows::Devices::Input;
    56 using namespace ABI::Windows::UI::Core;
    57 using namespace ABI::Windows::System;
    58 using namespace ABI::Windows::Foundation;
    59 using namespace ABI::Windows::Foundation::Collections;
    60 using namespace ABI::Windows::Graphics::Display;
    62 #ifdef PR_LOGGING
    63 extern PRLogModuleInfo* gWindowsLog;
    64 #endif
    66 #if !defined(SM_CONVERTIBLESLATEMODE)
    67 #define SM_CONVERTIBLESLATEMODE 0x2003
    68 #endif
    70 static uint32_t gInstanceCount = 0;
    71 const char16_t* kMetroSubclassThisProp = L"MetroSubclassThisProp";
    72 HWND MetroWidget::sICoreHwnd = nullptr;
    74 namespace mozilla {
    75 namespace widget {
    76 UINT sDefaultBrowserMsgId = RegisterWindowMessageW(L"DefaultBrowserClosing");
    77 } }
    79 // WM_GETOBJECT id pulled from uia headers
    80 #define UiaRootObjectId -25
    82 namespace mozilla {
    83 namespace widget {
    84 namespace winrt {
    85 extern ComPtr<MetroApp> sMetroApp;
    86 extern ComPtr<IUIABridge> gProviderRoot;
    87 } } }
    89 namespace {
    91   void SendInputs(uint32_t aModifiers, INPUT* aExtraInputs, uint32_t aExtraInputsLen)
    92   {
    93     // keySequence holds the virtual key values of each of the keys we intend
    94     // to press
    95     nsAutoTArray<KeyPair,32> keySequence;
    96     for (uint32_t i = 0; i < ArrayLength(sModifierKeyMap); ++i) {
    97       const uint32_t* map = sModifierKeyMap[i];
    98       if (aModifiers & map[0]) {
    99         keySequence.AppendElement(KeyPair(map[1], map[2]));
   100       }
   101     }
   103     uint32_t const len = keySequence.Length() * 2 + aExtraInputsLen;
   105     // The `inputs` array is a sequence of input events that will happen
   106     // serially.  We set the array up so that each modifier key is pressed
   107     // down, then the additional input events happen,
   108     // then each modifier key is released in reverse order of when
   109     // it was pressed down.  We pass this array to `SendInput`.
   110     //
   111     // inputs[0]: modifier key (e.g. shift, ctrl, etc) down
   112     // ...        ...
   113     // inputs[keySequence.Length()-1]: modifier key (e.g. shift, ctrl, etc) down
   114     // inputs[keySequence.Length()]: aExtraInputs[0]
   115     // inputs[keySequence.Length()+1]: aExtraInputs[1]
   116     // ...        ...
   117     // inputs[keySequence.Length() + aExtraInputsLen - 1]: aExtraInputs[aExtraInputsLen - 1]
   118     // inputs[keySequence.Length() + aExtraInputsLen]: modifier key (e.g. shift, ctrl, etc) up
   119     // ...        ...
   120     // inputs[len-1]: modifier key (e.g. shift, ctrl, etc) up
   121     INPUT* inputs = new INPUT[len];
   122     memset(inputs, 0, len * sizeof(INPUT));
   123     for (uint32_t i = 0; i < keySequence.Length(); ++i) {
   124       inputs[i].type = inputs[len-i-1].type = INPUT_KEYBOARD;
   125       inputs[i].ki.wVk = inputs[len-i-1].ki.wVk = keySequence[i].mSpecific
   126                                                 ? keySequence[i].mSpecific
   127                                                 : keySequence[i].mGeneral;
   128       inputs[len-i-1].ki.dwFlags |= KEYEVENTF_KEYUP;
   129     }
   130     for (uint32_t i = 0; i < aExtraInputsLen; i++) {
   131       inputs[keySequence.Length()+i] = aExtraInputs[i];
   132     }
   133     WinUtils::Log("  Sending inputs");
   134     for (uint32_t i = 0; i < len; i++) {
   135       if (inputs[i].type == INPUT_KEYBOARD) {
   136         WinUtils::Log("    Key press: 0x%x %s",
   137             inputs[i].ki.wVk,
   138             inputs[i].ki.dwFlags & KEYEVENTF_KEYUP
   139             ? "UP"
   140             : "DOWN");
   141       } else if(inputs[i].type == INPUT_MOUSE) {
   142         WinUtils::Log("    Mouse input: 0x%x 0x%x",
   143             inputs[i].mi.dwFlags,
   144             inputs[i].mi.mouseData);
   145       } else {
   146         WinUtils::Log("    Unknown input type!");
   147       }
   148     }
   149     ::SendInput(len, inputs, sizeof(INPUT));
   150     delete[] inputs;
   152     // The inputs have been sent, and the WM_* messages they generate are
   153     // waiting to be processed by our event loop.  Now we manually pump
   154     // those messages so that, upon our return, all the inputs have been
   155     // processed.
   156     WinUtils::Log("  Inputs sent. Waiting for input messages to clear");
   157     MSG msg;
   158     while (WinUtils::PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
   159       if (nsTextStore::ProcessRawKeyMessage(msg)) {
   160         continue;  // the message is consumed by TSF
   161       }
   162       ::TranslateMessage(&msg);
   163       ::DispatchMessage(&msg);
   164       WinUtils::Log("    Dispatched 0x%x 0x%x 0x%x", msg.message, msg.wParam, msg.lParam);
   165     }
   166     WinUtils::Log("  No more input messages");
   167   }
   168 }
   170 NS_IMPL_ISUPPORTS_INHERITED0(MetroWidget, nsBaseWidget)
   172 MetroWidget::MetroWidget() :
   173   mTransparencyMode(eTransparencyOpaque),
   174   mWnd(nullptr),
   175   mMetroWndProc(nullptr),
   176   mTempBasicLayerInUse(false),
   177   mRootLayerTreeId(),
   178   nsWindowBase()
   179 {
   180   // Global initialization
   181   if (!gInstanceCount) {
   182     UserActivity();
   183     nsTextStore::Initialize();
   184     MouseScrollHandler::Initialize();
   185     KeyboardLayout::GetInstance()->OnLayoutChange(::GetKeyboardLayout(0));
   186   } // !gInstanceCount
   187   gInstanceCount++;
   188 }
   190 MetroWidget::~MetroWidget()
   191 {
   192   LogThis();
   194   gInstanceCount--;
   196   // Global shutdown
   197   if (!gInstanceCount) {
   198     APZController::sAPZC = nullptr;
   199     nsTextStore::Terminate();
   200   } // !gInstanceCount
   201 }
   203 static bool gTopLevelAssigned = false;
   204 NS_IMETHODIMP
   205 MetroWidget::Create(nsIWidget *aParent,
   206                     nsNativeWidget aNativeParent,
   207                     const nsIntRect &aRect,
   208                     nsDeviceContext *aContext,
   209                     nsWidgetInitData *aInitData)
   210 {
   211   LogFunction();
   213   nsWidgetInitData defaultInitData;
   214   if (!aInitData)
   215     aInitData = &defaultInitData;
   217   mWindowType = aInitData->mWindowType;
   219   // Ensure that the toolkit is created.
   220   nsToolkit::GetToolkit();
   222   BaseCreate(aParent, aRect, aContext, aInitData);
   224   if (mWindowType != eWindowType_toplevel) {
   225     switch(mWindowType) {
   226       case eWindowType_dialog:
   227       WinUtils::Log("eWindowType_dialog window requested, returning failure.");
   228       break;
   229       case eWindowType_child:
   230       WinUtils::Log("eWindowType_child window requested, returning failure.");
   231       break;
   232       case eWindowType_popup:
   233       WinUtils::Log("eWindowType_popup window requested, returning failure.");
   234       break;
   235       case eWindowType_plugin:
   236       WinUtils::Log("eWindowType_plugin window requested, returning failure.");
   237       break;
   238       // we should support toolkit's eWindowType_invisible at some point.
   239       case eWindowType_invisible:
   240       WinUtils::Log("eWindowType_invisible window requested, this doesn't actually exist!");
   241       return NS_OK;
   242     }
   243     NS_WARNING("Invalid window type requested.");
   244     return NS_ERROR_FAILURE;
   245   }
   247   if (gTopLevelAssigned) {
   248     // Need to accept so that the mochitest-chrome test harness window
   249     // can be created.
   250     NS_WARNING("New eWindowType_toplevel window requested after FrameworkView widget created.");
   251     NS_WARNING("Widget created but the physical window does not exist! Fix me!");
   252     return NS_OK;
   253   }
   255   // the main widget gets created first
   256   gTopLevelAssigned = true;
   257   sMetroApp->SetWidget(this);
   258   WinUtils::SetNSWindowBasePtr(mWnd, this);
   260   if (mWidgetListener) {
   261     mWidgetListener->WindowActivated();
   262   }
   264   return NS_OK;
   265 }
   267 void
   268 MetroWidget::SetView(FrameworkView* aView)
   269 {
   270   mView = aView;
   271   // If we've already set this up, it points to a useless
   272   // layer manager, so reset it.
   273   mLayerManager = nullptr;
   274 }
   276 NS_IMETHODIMP
   277 MetroWidget::Destroy()
   278 {
   279   if (mOnDestroyCalled)
   280     return NS_OK;
   281   WinUtils::Log("[%X] %s mWnd=%X type=%d", this, __FUNCTION__, mWnd, mWindowType);
   282   mOnDestroyCalled = true;
   284   nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
   286   if (ShouldUseAPZC()) {
   287     nsresult rv;
   288     nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1", &rv);
   289     if (NS_SUCCEEDED(rv)) {
   290       observerService->RemoveObserver(this, "apzc-scroll-offset-changed");
   291       observerService->RemoveObserver(this, "apzc-zoom-to-rect");
   292       observerService->RemoveObserver(this, "apzc-disable-zoom");
   293     }
   294   }
   296   RemoveSubclass();
   297   NotifyWindowDestroyed();
   299   // Prevent the widget from sending additional events.
   300   mWidgetListener = nullptr;
   301   mAttachedWidgetListener = nullptr;
   303   // Release references to children, device context, toolkit, and app shell.
   304   nsBaseWidget::Destroy();
   305   nsBaseWidget::OnDestroy();
   306   WinUtils::SetNSWindowBasePtr(mWnd, nullptr);
   308   if (mLayerManager) {
   309     mLayerManager->Destroy();
   310   }
   312   mLayerManager = nullptr;
   313   mView = nullptr;
   314   mIdleService = nullptr;
   315   mWnd = nullptr;
   317   return NS_OK;
   318 }
   320 NS_IMETHODIMP
   321 MetroWidget::SetParent(nsIWidget *aNewParent)
   322 {
   323   return NS_OK;
   324 }
   326 NS_IMETHODIMP
   327 MetroWidget::Show(bool bState)
   328 {
   329   return NS_OK;
   330 }
   332 uint32_t
   333 MetroWidget::GetMaxTouchPoints() const
   334 {
   335   ComPtr<IPointerDeviceStatics> deviceStatics;
   337   HRESULT hr = GetActivationFactory(
   338     HStringReference(RuntimeClass_Windows_Devices_Input_PointerDevice).Get(),
   339     deviceStatics.GetAddressOf());
   341   if (FAILED(hr)) {
   342     return 0;
   343   }
   345   ComPtr< IVectorView<PointerDevice*> > deviceList;
   346   hr = deviceStatics->GetPointerDevices(&deviceList);
   348   if (FAILED(hr)) {
   349     return 0;
   350   }
   352   uint32_t deviceNum = 0;
   353   deviceList->get_Size(&deviceNum);
   355   uint32_t maxTouchPoints = 0;
   356   for (uint32_t index = 0; index < deviceNum; ++index) {
   357     ComPtr<IPointerDevice> device;
   358     PointerDeviceType deviceType;
   360     if (FAILED(deviceList->GetAt(index, device.GetAddressOf()))) {
   361       continue;
   362     }
   364     if (FAILED(device->get_PointerDeviceType(&deviceType)))  {
   365       continue;
   366     }
   368     if (deviceType == PointerDeviceType_Touch) {
   369       uint32_t deviceMaxTouchPoints = 0;
   370       device->get_MaxContacts(&deviceMaxTouchPoints);
   371       maxTouchPoints = std::max(maxTouchPoints, deviceMaxTouchPoints);
   372     }
   373   }
   375   return maxTouchPoints;
   376 }
   378 NS_IMETHODIMP
   379 MetroWidget::IsVisible(bool & aState)
   380 {
   381   aState = mView->IsVisible();
   382   return NS_OK;
   383 }
   385 bool
   386 MetroWidget::IsVisible() const
   387 {
   388   if (!mView)
   389     return false;
   390   return mView->IsVisible();
   391 }
   393 NS_IMETHODIMP
   394 MetroWidget::EnableDragDrop(bool aEnable) {
   395   if (aEnable) {
   396     if (nullptr == mNativeDragTarget) {
   397       mNativeDragTarget = new nsNativeDragTarget(this);
   398       if (!mNativeDragTarget) {
   399         return NS_ERROR_FAILURE;
   400       }
   401     }
   403     HRESULT hr = ::RegisterDragDrop(mWnd, static_cast<LPDROPTARGET>(mNativeDragTarget));
   404     return SUCCEEDED(hr) ? NS_OK : NS_ERROR_FAILURE;
   405   } else {
   406     if (nullptr == mNativeDragTarget) {
   407       return NS_OK;
   408     }
   410     HRESULT hr = ::RevokeDragDrop(mWnd);
   411     return SUCCEEDED(hr) ? NS_OK : NS_ERROR_FAILURE;
   412   }
   413 }
   415 NS_IMETHODIMP
   416 MetroWidget::IsEnabled(bool *aState)
   417 {
   418   *aState = mView->IsEnabled();
   419   return NS_OK;
   420 }
   422 bool
   423 MetroWidget::IsEnabled() const
   424 {
   425   if (!mView)
   426     return false;
   427   return mView->IsEnabled();
   428 }
   430 NS_IMETHODIMP
   431 MetroWidget::Enable(bool bState)
   432 {
   433   return NS_OK;
   434 }
   436 NS_IMETHODIMP
   437 MetroWidget::GetBounds(nsIntRect &aRect)
   438 {
   439   if (mView) {
   440     mView->GetBounds(aRect);
   441   } else {
   442     nsIntRect rect(0,0,0,0);
   443     aRect = rect;
   444   }
   445   return NS_OK;
   446 }
   448 NS_IMETHODIMP
   449 MetroWidget::GetScreenBounds(nsIntRect &aRect)
   450 {
   451   if (mView) {
   452     mView->GetBounds(aRect);
   453   } else {
   454     nsIntRect rect(0,0,0,0);
   455     aRect = rect;
   456   }
   457   return NS_OK;
   458 }
   460 NS_IMETHODIMP
   461 MetroWidget::GetClientBounds(nsIntRect &aRect)
   462 {
   463   if (mView) {
   464     mView->GetBounds(aRect);
   465   } else {
   466     nsIntRect rect(0,0,0,0);
   467     aRect = rect;
   468   }
   469   return NS_OK;
   470 }
   472 NS_IMETHODIMP
   473 MetroWidget::SetCursor(nsCursor aCursor)
   474 {
   475   if (!mView)
   476     return NS_ERROR_FAILURE;
   478   switch (aCursor) {
   479     case eCursor_select:
   480       mView->SetCursor(CoreCursorType::CoreCursorType_IBeam);
   481       break;
   482     case eCursor_wait:
   483       mView->SetCursor(CoreCursorType::CoreCursorType_Wait);
   484       break;
   485     case eCursor_hyperlink:
   486       mView->SetCursor(CoreCursorType::CoreCursorType_Hand);
   487       break;
   488     case eCursor_standard:
   489       mView->SetCursor(CoreCursorType::CoreCursorType_Arrow);
   490       break;
   491     case eCursor_n_resize:
   492     case eCursor_s_resize:
   493       mView->SetCursor(CoreCursorType::CoreCursorType_SizeNorthSouth);
   494       break;
   495     case eCursor_w_resize:
   496     case eCursor_e_resize:
   497       mView->SetCursor(CoreCursorType::CoreCursorType_SizeWestEast);
   498       break;
   499     case eCursor_nw_resize:
   500     case eCursor_se_resize:
   501       mView->SetCursor(CoreCursorType::CoreCursorType_SizeNorthwestSoutheast);
   502       break;
   503     case eCursor_ne_resize:
   504     case eCursor_sw_resize:
   505       mView->SetCursor(CoreCursorType::CoreCursorType_SizeNortheastSouthwest);
   506       break;
   507     case eCursor_crosshair:
   508       mView->SetCursor(CoreCursorType::CoreCursorType_Cross);
   509       break;
   510     case eCursor_move:
   511       mView->SetCursor(CoreCursorType::CoreCursorType_SizeAll);
   512       break;
   513     case eCursor_help:
   514       mView->SetCursor(CoreCursorType::CoreCursorType_Help);
   515       break;
   516     // CSS3 custom cursors
   517     case eCursor_copy:
   518       mView->SetCursor(CoreCursorType::CoreCursorType_Custom, IDC_COPY);
   519       break;
   520     case eCursor_alias:
   521       mView->SetCursor(CoreCursorType::CoreCursorType_Custom, IDC_ALIAS);
   522       break;
   523     case eCursor_cell:
   524       mView->SetCursor(CoreCursorType::CoreCursorType_Custom, IDC_CELL);
   525       break;
   526     case eCursor_grab:
   527       mView->SetCursor(CoreCursorType::CoreCursorType_Custom, IDC_GRAB);
   528       break;
   529     case eCursor_grabbing:
   530       mView->SetCursor(CoreCursorType::CoreCursorType_Custom, IDC_GRABBING);
   531       break;
   532     case eCursor_spinning:
   533       mView->SetCursor(CoreCursorType::CoreCursorType_Wait);
   534       break;
   535     case eCursor_context_menu:
   536       mView->SetCursor(CoreCursorType::CoreCursorType_Arrow);
   537       break;
   538     case eCursor_zoom_in:
   539       mView->SetCursor(CoreCursorType::CoreCursorType_Custom, IDC_ZOOMIN);
   540       break;
   541     case eCursor_zoom_out:
   542       mView->SetCursor(CoreCursorType::CoreCursorType_Custom, IDC_ZOOMOUT);
   543       break;
   544     case eCursor_not_allowed:
   545     case eCursor_no_drop:
   546       mView->SetCursor(CoreCursorType::CoreCursorType_UniversalNo);
   547       break;
   548     case eCursor_col_resize:
   549       mView->SetCursor(CoreCursorType::CoreCursorType_Custom, IDC_COLRESIZE);
   550       break;
   551     case eCursor_row_resize:
   552       mView->SetCursor(CoreCursorType::CoreCursorType_Custom, IDC_ROWRESIZE);
   553       break;
   554     case eCursor_vertical_text:
   555       mView->SetCursor(CoreCursorType::CoreCursorType_Custom, IDC_VERTICALTEXT);
   556       break;
   557     case eCursor_all_scroll:
   558       mView->SetCursor(CoreCursorType::CoreCursorType_SizeAll);
   559       break;
   560     case eCursor_nesw_resize:
   561       mView->SetCursor(CoreCursorType::CoreCursorType_SizeNortheastSouthwest);
   562       break;
   563     case eCursor_nwse_resize:
   564       mView->SetCursor(CoreCursorType::CoreCursorType_SizeNorthwestSoutheast);
   565       break;
   566     case eCursor_ns_resize:
   567       mView->SetCursor(CoreCursorType::CoreCursorType_SizeNorthSouth);
   568       break;
   569     case eCursor_ew_resize:
   570       mView->SetCursor(CoreCursorType::CoreCursorType_SizeWestEast);
   571       break;
   572     case eCursor_none:
   573       mView->ClearCursor();
   574       break;
   575     default:
   576       NS_WARNING("Invalid cursor type");
   577       break;
   578   }
   579   return NS_OK;
   580 }
   582 nsresult
   583 MetroWidget::SynthesizeNativeKeyEvent(int32_t aNativeKeyboardLayout,
   584                                       int32_t aNativeKeyCode,
   585                                       uint32_t aModifierFlags,
   586                                       const nsAString& aCharacters,
   587                                       const nsAString& aUnmodifiedCharacters)
   588 {
   589   KeyboardLayout* keyboardLayout = KeyboardLayout::GetInstance();
   590   return keyboardLayout->SynthesizeNativeKeyEvent(
   591            this, aNativeKeyboardLayout, aNativeKeyCode, aModifierFlags,
   592            aCharacters, aUnmodifiedCharacters);
   593 }
   595 nsresult
   596 MetroWidget::SynthesizeNativeMouseEvent(nsIntPoint aPoint,
   597                                         uint32_t aNativeMessage,
   598                                         uint32_t aModifierFlags)
   599 {
   600   WinUtils::Log("ENTERED SynthesizeNativeMouseEvent");
   602   INPUT inputs[2];
   603   memset(inputs, 0, 2*sizeof(INPUT));
   604   inputs[0].type = inputs[1].type = INPUT_MOUSE;
   605   inputs[0].mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;
   606   // Inexplicably, the x and y coordinates that we want to move the mouse to
   607   // are specified as values in the range (0, 65535). (0,0) represents the
   608   // top left of the primary monitor and (65535, 65535) represents the
   609   // bottom right of the primary monitor.
   610   inputs[0].mi.dx = (aPoint.x * 65535) / ::GetSystemMetrics(SM_CXSCREEN);
   611   inputs[0].mi.dy = (aPoint.y * 65535) / ::GetSystemMetrics(SM_CYSCREEN);
   612   inputs[1].mi.dwFlags = aNativeMessage;
   613   SendInputs(aModifierFlags, inputs, 2);
   615   WinUtils::Log("Exiting SynthesizeNativeMouseEvent");
   616   return NS_OK;
   617 }
   619 nsresult
   620 MetroWidget::SynthesizeNativeMouseScrollEvent(nsIntPoint aPoint,
   621                                               uint32_t aNativeMessage,
   622                                               double aDeltaX,
   623                                               double aDeltaY,
   624                                               double aDeltaZ,
   625                                               uint32_t aModifierFlags,
   626                                               uint32_t aAdditionalFlags)
   627 {
   628   return MouseScrollHandler::SynthesizeNativeMouseScrollEvent(
   629            this, aPoint, aNativeMessage,
   630            (aNativeMessage == WM_MOUSEWHEEL || aNativeMessage == WM_VSCROLL) ?
   631              static_cast<int32_t>(aDeltaY) : static_cast<int32_t>(aDeltaX),
   632            aModifierFlags, aAdditionalFlags);
   633 }
   635 static void
   636 CloseGesture()
   637 {
   638   LogFunction();
   639   nsCOMPtr<nsIAppStartup> appStartup =
   640     do_GetService(NS_APPSTARTUP_CONTRACTID);
   641   if (appStartup) {
   642     appStartup->Quit(nsIAppStartup::eForceQuit);
   643   }
   644 }
   646 // Async event sending for mouse and keyboard input.
   648 // defined in nsWindowBase, called from shared module WinMouseScrollHandler.
   649 bool
   650 MetroWidget::DispatchScrollEvent(mozilla::WidgetGUIEvent* aEvent)
   651 {
   652   WidgetGUIEvent* newEvent = nullptr;
   653   switch(aEvent->eventStructType) {
   654     case NS_WHEEL_EVENT:
   655     {
   656       WidgetWheelEvent* oldEvent = aEvent->AsWheelEvent();
   657       WidgetWheelEvent* wheelEvent =
   658         new WidgetWheelEvent(oldEvent->mFlags.mIsTrusted, oldEvent->message, oldEvent->widget);
   659       wheelEvent->AssignWheelEventData(*oldEvent, true);
   660       newEvent = static_cast<WidgetGUIEvent*>(wheelEvent);
   661     }
   662     break;
   663     case NS_CONTENT_COMMAND_EVENT:
   664     {
   665       WidgetContentCommandEvent* oldEvent = aEvent->AsContentCommandEvent();
   666       WidgetContentCommandEvent* cmdEvent =
   667         new WidgetContentCommandEvent(oldEvent->mFlags.mIsTrusted, oldEvent->message, oldEvent->widget);
   668       cmdEvent->AssignContentCommandEventData(*oldEvent, true);
   669       newEvent = static_cast<WidgetGUIEvent*>(cmdEvent);
   670     }
   671     break;
   672     default:
   673       MOZ_CRASH("unknown event in DispatchScrollEvent");
   674     break;
   675   }
   676   mEventQueue.Push(newEvent);
   677   nsCOMPtr<nsIRunnable> runnable =
   678     NS_NewRunnableMethod(this, &MetroWidget::DeliverNextScrollEvent);
   679   NS_DispatchToCurrentThread(runnable);
   680   return false;
   681 }
   683 void
   684 MetroWidget::DeliverNextScrollEvent()
   685 {
   686   WidgetGUIEvent* event =
   687     static_cast<WidgetInputEvent*>(mEventQueue.PopFront());
   688   DispatchWindowEvent(event);
   689   delete event;
   690 }
   692 // defined in nsWindowBase, called from shared module KeyboardLayout.
   693 bool
   694 MetroWidget::DispatchKeyboardEvent(WidgetGUIEvent* aEvent)
   695 {
   696   MOZ_ASSERT(aEvent);
   697   WidgetKeyboardEvent* oldKeyEvent = aEvent->AsKeyboardEvent();
   698   WidgetKeyboardEvent* keyEvent =
   699     new WidgetKeyboardEvent(oldKeyEvent->mFlags.mIsTrusted,
   700                             oldKeyEvent->message, oldKeyEvent->widget);
   701   // XXX note this leaves pluginEvent null, which is fine for now.
   702   keyEvent->AssignKeyEventData(*oldKeyEvent, true);
   703   mKeyEventQueue.Push(keyEvent);
   704   nsCOMPtr<nsIRunnable> runnable =
   705     NS_NewRunnableMethod(this, &MetroWidget::DeliverNextKeyboardEvent);
   706   NS_DispatchToCurrentThread(runnable);
   707   return false;
   708 }
   710 // Used in conjunction with mKeyEventQueue to find a keypress event
   711 // that should not be delivered due to the return result of the
   712 // preceeding keydown.
   713 class KeyQueryIdAndCancel : public nsDequeFunctor {
   714 public:
   715   KeyQueryIdAndCancel(uint32_t aIdToCancel) :
   716     mId(aIdToCancel) {
   717   }
   718   virtual void* operator() (void* aObject) {
   719     WidgetKeyboardEvent* event = static_cast<WidgetKeyboardEvent*>(aObject);
   720     if (event->mUniqueId == mId) {
   721       event->mFlags.mPropagationStopped = true;
   722     }
   723     return nullptr;
   724   }
   725 protected:
   726   uint32_t mId;
   727 };
   729 void
   730 MetroWidget::DeliverNextKeyboardEvent()
   731 {
   732   WidgetKeyboardEvent* event =
   733     static_cast<WidgetKeyboardEvent*>(mKeyEventQueue.PopFront());
   734   if (event->mFlags.mPropagationStopped) {
   735     // This can happen if a keypress was previously cancelled.
   736     delete event;
   737     return;
   738   }
   740   if (DispatchWindowEvent(event) && event->message == NS_KEY_DOWN) {
   741     // keydown events may be followed by multiple keypress events which
   742     // shouldn't be sent if preventDefault is called on keydown.
   743     KeyQueryIdAndCancel query(event->mUniqueId);
   744     mKeyEventQueue.ForEach(query);
   745   }
   746   delete event;
   747 }
   749 // static
   750 LRESULT CALLBACK
   751 MetroWidget::StaticWindowProcedure(HWND aWnd, UINT aMsg, WPARAM aWParam, LPARAM aLParam)
   752 {
   753   MetroWidget* self = reinterpret_cast<MetroWidget*>(
   754     GetProp(aWnd, kMetroSubclassThisProp));
   755   if (!self) {
   756     NS_NOTREACHED("Missing 'this' prop on subclassed metro window, this is bad.");
   757     return 0;
   758   }
   759   return self->WindowProcedure(aWnd, aMsg, aWParam, aLParam);
   760 }
   762 LRESULT
   763 MetroWidget::WindowProcedure(HWND aWnd, UINT aMsg, WPARAM aWParam, LPARAM aLParam)
   764 {
   765   if(sDefaultBrowserMsgId == aMsg) {
   766     CloseGesture();
   767   } else if (WM_SETTINGCHANGE == aMsg) {
   768     if (aLParam && !wcsicmp(L"ConvertibleSlateMode", (wchar_t*)aLParam)) {
   769       // If we're switching away from slate mode, switch to Desktop for
   770       // hardware that supports this feature if the pref is set.
   771       if (GetSystemMetrics(SM_CONVERTIBLESLATEMODE) != 0 &&
   772           Preferences::GetBool("browser.shell.metro-auto-switch-enabled",
   773                                false)) {
   774         nsCOMPtr<nsIAppStartup> appStartup(do_GetService(NS_APPSTARTUP_CONTRACTID));
   775         if (appStartup) {
   776           appStartup->Quit(nsIAppStartup::eForceQuit | nsIAppStartup::eRestart);
   777         }
   778       }
   779     }
   780   }
   782   // Indicates if we should hand messages to the default windows
   783   // procedure for processing.
   784   bool processDefault = true;
   786   // The result returned if we do not do default processing.
   787   LRESULT processResult = 0;
   789   MSGResult msgResult(&processResult);
   790   MouseScrollHandler::ProcessMessage(this, aMsg, aWParam, aLParam, msgResult);
   791   if (msgResult.mConsumed) {
   792     return processResult;
   793   }
   795   nsTextStore::ProcessMessage(this, aMsg, aWParam, aLParam, msgResult);
   796   if (msgResult.mConsumed) {
   797     return processResult;
   798   }
   800   switch (aMsg) {
   801     case WM_POWERBROADCAST:
   802     {
   803       switch (aWParam)
   804       {
   805         case PBT_APMSUSPEND:
   806           MetroApp::PostSleepWakeNotification(true);
   807           break;
   808         case PBT_APMRESUMEAUTOMATIC:
   809         case PBT_APMRESUMECRITICAL:
   810         case PBT_APMRESUMESUSPEND:
   811           MetroApp::PostSleepWakeNotification(false);
   812           break;
   813       }
   814       break;
   815     }
   817     // Keyboard handling is passed to KeyboardLayout, which delivers gecko events
   818     // via DispatchKeyboardEvent.
   820     case WM_KEYDOWN:
   821     case WM_SYSKEYDOWN:
   822     {
   823       MSG msg = WinUtils::InitMSG(aMsg, aWParam, aLParam, aWnd);
   824       // If this method doesn't call NativeKey::HandleKeyDownMessage(), this
   825       // method must clean up the redirected message information itself.  For
   826       // more information, see above comment of
   827       // RedirectedKeyDownMessageManager::AutoFlusher class definition in
   828       // KeyboardLayout.h.
   829       RedirectedKeyDownMessageManager::AutoFlusher
   830         redirectedMsgFlusher(this, msg);
   832       if (nsTextStore::IsComposingOn(this)) {
   833         break;
   834       }
   836       ModifierKeyState modKeyState;
   837       NativeKey nativeKey(this, msg, modKeyState);
   838       processDefault = !nativeKey.HandleKeyDownMessage();
   839       // HandleKeyDownMessage cleaned up the redirected message information
   840       // itself, so, we should do nothing.
   841       redirectedMsgFlusher.Cancel();
   842       break;
   843     }
   845     case WM_KEYUP:
   846     case WM_SYSKEYUP:
   847     {
   848       if (nsTextStore::IsComposingOn(this)) {
   849         break;
   850       }
   852       MSG msg = WinUtils::InitMSG(aMsg, aWParam, aLParam, aWnd);
   853       ModifierKeyState modKeyState;
   854       NativeKey nativeKey(this, msg, modKeyState);
   855       processDefault = !nativeKey.HandleKeyUpMessage();
   856       break;
   857     }
   859     case WM_CHAR:
   860     case WM_SYSCHAR:
   861     {
   862       if (nsTextStore::IsComposingOn(this)) {
   863         nsTextStore::CommitComposition(false);
   864       }
   866       MSG msg = WinUtils::InitMSG(aMsg, aWParam, aLParam, aWnd);
   867       ModifierKeyState modKeyState;
   868       NativeKey nativeKey(this, msg, modKeyState);
   869       processDefault = !nativeKey.HandleCharMessage(msg);
   870       break;
   871     }
   873     case WM_INPUTLANGCHANGE:
   874     {
   875       KeyboardLayout::GetInstance()->
   876         OnLayoutChange(reinterpret_cast<HKL>(aLParam));
   877       processResult = 1;
   878       break;
   879     }
   881     case WM_APPCOMMAND:
   882       processDefault = HandleAppCommandMsg(aWParam, aLParam, &processResult);
   883       break;
   885     case WM_GETOBJECT:
   886     {
   887       DWORD dwObjId = (LPARAM)(DWORD) aLParam;
   888       // Passing this to CallWindowProc can result in a failure due to a timing issue
   889       // in winrt core window server code, so we call it directly here. Also, it's not
   890       // clear Windows::UI::Core::WindowServer::OnAutomationProviderRequestedEvent is
   891       // compatible with metro enabled desktop browsers, it makes an initial call to
   892       // UiaReturnRawElementProvider passing the return result from FrameworkView
   893       // OnAutomationProviderRequested as the hwnd (me scratches head) which results in
   894       // GetLastError always being set to invalid handle (6) after CallWindowProc returns.
   895       if (dwObjId == UiaRootObjectId && gProviderRoot) {
   896         ComPtr<IRawElementProviderSimple> simple;
   897         gProviderRoot.As(&simple);
   898         if (simple) {
   899           LRESULT res = UiaReturnRawElementProvider(aWnd, aWParam, aLParam, simple.Get());
   900           if (res) {
   901             return res;
   902           }
   903           NS_ASSERTION(res, "UiaReturnRawElementProvider failed!");
   904           WinUtils::Log("UiaReturnRawElementProvider failed! GetLastError=%X", GetLastError());
   905         }
   906       }
   907       break;
   908     }
   910     default:
   911     {
   912       break;
   913     }
   914   }
   916   if (processDefault) {
   917     return CallWindowProc(mMetroWndProc, aWnd, aMsg, aWParam,
   918                           aLParam);
   919   }
   920   return processResult;
   921 }
   923 static BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
   924 {
   925   WCHAR className[56];
   926   if (GetClassNameW(hwnd, className, sizeof(className)/sizeof(WCHAR)) &&
   927       !wcscmp(L"Windows.UI.Core.CoreWindow", className)) {
   928     DWORD processID = 0;
   929     GetWindowThreadProcessId(hwnd, &processID);
   930     if (processID && processID == GetCurrentProcessId()) {
   931       *((HWND*)lParam) = hwnd;
   932       return FALSE;
   933     }
   934   }
   935   return TRUE;
   936 }
   938 void
   939 MetroWidget::FindMetroWindow()
   940 {
   941   LogFunction();
   942   if (mWnd)
   943     return;
   944   EnumWindows(EnumWindowsProc, (LPARAM)&mWnd);
   945   NS_ASSERTION(mWnd, "Couldn't find our metro CoreWindow, this is bad.");
   947   // subclass it
   948   SetSubclass();
   949   sICoreHwnd = mWnd;
   950   return;
   951 }
   953 void
   954 MetroWidget::SetSubclass()
   955 {
   956   if (!mWnd) {
   957     NS_NOTREACHED("SetSubclass called without a valid hwnd.");
   958     return;
   959   }
   961   WNDPROC wndProc = reinterpret_cast<WNDPROC>(
   962     GetWindowLongPtr(mWnd, GWLP_WNDPROC));
   963   if (wndProc != StaticWindowProcedure) {
   964       if (!SetPropW(mWnd, kMetroSubclassThisProp, this)) {
   965         NS_NOTREACHED("SetProp failed, can't continue.");
   966         return;
   967       }
   968       mMetroWndProc =
   969         reinterpret_cast<WNDPROC>(
   970           SetWindowLongPtr(mWnd, GWLP_WNDPROC,
   971             reinterpret_cast<LONG_PTR>(StaticWindowProcedure)));
   972       NS_ASSERTION(mMetroWndProc != StaticWindowProcedure, "WTF?");
   973   }
   974 }
   976 void
   977 MetroWidget::RemoveSubclass()
   978 {
   979   if (!mWnd)
   980     return;
   981   WNDPROC wndProc = reinterpret_cast<WNDPROC>(
   982     GetWindowLongPtr(mWnd, GWLP_WNDPROC));
   983   if (wndProc == StaticWindowProcedure) {
   984       NS_ASSERTION(mMetroWndProc, "Should have old proc here.");
   985       SetWindowLongPtr(mWnd, GWLP_WNDPROC,
   986         reinterpret_cast<LONG_PTR>(mMetroWndProc));
   987       mMetroWndProc = nullptr;
   988   }
   989   RemovePropW(mWnd, kMetroSubclassThisProp);
   990 }
   992 bool
   993 MetroWidget::ShouldUseOffMainThreadCompositing()
   994 {
   995   // Either we're not initialized yet, or this is the toolkit widget
   996   if (!mView) {
   997     return false;
   998   }
   999   // toolkit or test widgets can't use omtc, they don't have ICoreWindow.
  1000   return (CompositorParent::CompositorLoop() && mWindowType == eWindowType_toplevel);
  1003 bool
  1004 MetroWidget::ShouldUseMainThreadD3D10Manager()
  1006   // Either we're not initialized yet, or this is the toolkit widget
  1007   if (!mView) {
  1008     return false;
  1010   return (!CompositorParent::CompositorLoop() && mWindowType == eWindowType_toplevel);
  1013 bool
  1014 MetroWidget::ShouldUseBasicManager()
  1016   // toolkit or test widgets fall back on empty shadow layers
  1017   return (mWindowType != eWindowType_toplevel);
  1020 bool
  1021 MetroWidget::ShouldUseAPZC()
  1023   const char* kPrefName = "layers.async-pan-zoom.enabled";
  1024   return ShouldUseOffMainThreadCompositing() &&
  1025          Preferences::GetBool(kPrefName, false);
  1028 void
  1029 MetroWidget::SetWidgetListener(nsIWidgetListener* aWidgetListener)
  1031   mWidgetListener = aWidgetListener;
  1032   if (mController) {
  1033     mController->SetWidgetListener(aWidgetListener);
  1037 CompositorParent* MetroWidget::NewCompositorParent(int aSurfaceWidth, int aSurfaceHeight)
  1039   CompositorParent *compositor = nsBaseWidget::NewCompositorParent(aSurfaceWidth, aSurfaceHeight);
  1041   if (ShouldUseAPZC()) {
  1042     mRootLayerTreeId = compositor->RootLayerTreeId();
  1044     mController = new APZController();
  1045     mController->SetWidgetListener(mWidgetListener);
  1047     CompositorParent::SetControllerForLayerTree(mRootLayerTreeId, mController);
  1049     APZController::sAPZC = CompositorParent::GetAPZCTreeManager(compositor->RootLayerTreeId());
  1050     APZController::sAPZC->SetDPI(GetDPI());
  1052     nsresult rv;
  1053     nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1", &rv);
  1054     if (NS_SUCCEEDED(rv)) {
  1055       observerService->AddObserver(this, "apzc-scroll-offset-changed", false);
  1056       observerService->AddObserver(this, "apzc-zoom-to-rect", false);
  1057       observerService->AddObserver(this, "apzc-disable-zoom", false);
  1061   return compositor;
  1064 MetroWidget::TouchBehaviorFlags
  1065 MetroWidget::ContentGetAllowedTouchBehavior(const nsIntPoint& aPoint)
  1067   return ContentHelper::GetAllowedTouchBehavior(this, aPoint);
  1070 void
  1071 MetroWidget::ApzcGetAllowedTouchBehavior(WidgetInputEvent* aTransformedEvent,
  1072                                          nsTArray<TouchBehaviorFlags>& aOutBehaviors)
  1074   LogFunction();
  1075   return APZController::sAPZC->GetAllowedTouchBehavior(aTransformedEvent, aOutBehaviors);
  1078 void
  1079 MetroWidget::ApzcSetAllowedTouchBehavior(const ScrollableLayerGuid& aGuid,
  1080                                          nsTArray<TouchBehaviorFlags>& aBehaviors)
  1082   LogFunction();
  1083   if (!APZController::sAPZC) {
  1084     return;
  1086   APZController::sAPZC->SetAllowedTouchBehavior(aGuid, aBehaviors);
  1089 void
  1090 MetroWidget::ApzContentConsumingTouch(const ScrollableLayerGuid& aGuid)
  1092   LogFunction();
  1093   if (!mController) {
  1094     return;
  1096   mController->ContentReceivedTouch(aGuid, true);
  1099 void
  1100 MetroWidget::ApzContentIgnoringTouch(const ScrollableLayerGuid& aGuid)
  1102   LogFunction();
  1103   if (!mController) {
  1104     return;
  1106   mController->ContentReceivedTouch(aGuid, false);
  1109 bool
  1110 MetroWidget::ApzHitTest(ScreenIntPoint& pt)
  1112   if (!mController) {
  1113     return false;
  1115   return mController->HitTestAPZC(pt);
  1118 void
  1119 MetroWidget::ApzTransformGeckoCoordinate(const ScreenIntPoint& aPoint,
  1120                                          LayoutDeviceIntPoint* aRefPointOut)
  1122   if (!mController) {
  1123     return;
  1125   mController->TransformCoordinateToGecko(aPoint, aRefPointOut);
  1128 nsEventStatus
  1129 MetroWidget::ApzReceiveInputEvent(WidgetInputEvent* aEvent,
  1130                                   ScrollableLayerGuid* aOutTargetGuid)
  1132   MOZ_ASSERT(aEvent);
  1134   if (!mController) {
  1135     return nsEventStatus_eIgnore;
  1137   return mController->ReceiveInputEvent(aEvent, aOutTargetGuid);
  1140 LayerManager*
  1141 MetroWidget::GetLayerManager(PLayerTransactionChild* aShadowManager,
  1142                              LayersBackend aBackendHint,
  1143                              LayerManagerPersistence aPersistence,
  1144                              bool* aAllowRetaining)
  1146   bool retaining = true;
  1148   // If we initialized earlier than the view, recreate the layer manager now
  1149   if (mLayerManager &&
  1150       mTempBasicLayerInUse &&
  1151       ShouldUseOffMainThreadCompositing()) {
  1152     mLayerManager = nullptr;
  1153     mTempBasicLayerInUse = false;
  1154     retaining = false;
  1157   // If the backend device has changed, create a new manager (pulled from nswindow)
  1158   if (mLayerManager) {
  1159     if (mLayerManager->GetBackendType() == LayersBackend::LAYERS_D3D10) {
  1160       LayerManagerD3D10 *layerManagerD3D10 =
  1161         static_cast<LayerManagerD3D10*>(mLayerManager.get());
  1162       if (layerManagerD3D10->device() !=
  1163           gfxWindowsPlatform::GetPlatform()->GetD3D10Device()) {
  1164         MOZ_ASSERT(!mLayerManager->IsInTransaction());
  1166         mLayerManager->Destroy();
  1167         mLayerManager = nullptr;
  1168         retaining = false;
  1173   HRESULT hr = S_OK;
  1175   // Create a layer manager: try to use an async compositor first, if enabled.
  1176   // Otherwise fall back on the main thread d3d manager.
  1177   if (!mLayerManager) {
  1178     if (ShouldUseOffMainThreadCompositing()) {
  1179       NS_ASSERTION(aShadowManager == nullptr, "Async Compositor not supported with e10s");
  1180       CreateCompositor();
  1181     } else if (ShouldUseMainThreadD3D10Manager()) {
  1182       nsRefPtr<mozilla::layers::LayerManagerD3D10> layerManager =
  1183         new mozilla::layers::LayerManagerD3D10(this);
  1184       if (layerManager->Initialize(true, &hr)) {
  1185         mLayerManager = layerManager;
  1187     } else if (ShouldUseBasicManager()) {
  1188       mLayerManager = CreateBasicLayerManager();
  1190     // Either we're not ready to initialize yet due to a missing view pointer,
  1191     // or something has gone wrong.
  1192     if (!mLayerManager) {
  1193       if (!mView) {
  1194         NS_WARNING("Using temporary basic layer manager.");
  1195         mLayerManager = new BasicLayerManager(this);
  1196         mTempBasicLayerInUse = true;
  1197       } else {
  1198 #ifdef MOZ_CRASHREPORTER
  1199         if (FAILED(hr)) {
  1200           char errorBuf[10];
  1201           errorBuf[0] = '\0';
  1202           _snprintf_s(errorBuf, sizeof(errorBuf), _TRUNCATE, "%X", hr);
  1203           CrashReporter::
  1204             AnnotateCrashReport(NS_LITERAL_CSTRING("HRESULT"),
  1205                                 nsDependentCString(errorBuf));
  1207 #endif
  1208         NS_RUNTIMEABORT("Couldn't create layer manager");
  1213   if (aAllowRetaining) {
  1214     *aAllowRetaining = retaining;
  1217   return mLayerManager;
  1220 NS_IMETHODIMP
  1221 MetroWidget::Invalidate(bool aEraseBackground,
  1222                         bool aUpdateNCArea,
  1223                         bool aIncludeChildren)
  1225   nsIntRect rect;
  1226   if (mView) {
  1227     mView->GetBounds(rect);
  1229   Invalidate(rect);
  1230   return NS_OK;
  1233 NS_IMETHODIMP
  1234 MetroWidget::Invalidate(const nsIntRect & aRect)
  1236   if (mWnd) {
  1237     RECT rect;
  1238     rect.left   = aRect.x;
  1239     rect.top    = aRect.y;
  1240     rect.right  = aRect.x + aRect.width;
  1241     rect.bottom = aRect.y + aRect.height;
  1242     InvalidateRect(mWnd, &rect, FALSE);
  1245   return NS_OK;
  1248 nsTransparencyMode
  1249 MetroWidget::GetTransparencyMode()
  1251   return mTransparencyMode;
  1254 void
  1255 MetroWidget::SetTransparencyMode(nsTransparencyMode aMode)
  1257   mTransparencyMode = aMode;
  1260 nsIWidgetListener*
  1261 MetroWidget::GetPaintListener()
  1263   if (mOnDestroyCalled)
  1264     return nullptr;
  1265   return mAttachedWidgetListener ? mAttachedWidgetListener :
  1266     mWidgetListener;
  1269 void MetroWidget::Paint(const nsIntRegion& aInvalidRegion)
  1271   gfxWindowsPlatform::GetPlatform()->UpdateRenderMode();
  1273   nsIWidgetListener* listener = GetPaintListener();
  1274   if (!listener)
  1275     return;
  1277   listener->WillPaintWindow(this);
  1279   // Refresh since calls like WillPaintWindow can destroy the widget
  1280   listener = GetPaintListener();
  1281   if (!listener)
  1282     return;
  1284   listener->PaintWindow(this, aInvalidRegion);
  1286   listener = GetPaintListener();
  1287   if (!listener)
  1288     return;
  1290   listener->DidPaintWindow();
  1293 void MetroWidget::UserActivity()
  1295   // Check if we have the idle service, if not we try to get it.
  1296   if (!mIdleService) {
  1297     mIdleService = do_GetService("@mozilla.org/widget/idleservice;1");
  1300   // Check that we now have the idle service.
  1301   if (mIdleService) {
  1302     mIdleService->ResetIdleTimeOut(0);
  1306 // InitEvent assumes physical coordinates and is used by shared win32 code. Do
  1307 // not hand winrt event coordinates to this routine.
  1308 void
  1309 MetroWidget::InitEvent(WidgetGUIEvent& event, nsIntPoint* aPoint)
  1311   if (!aPoint) {
  1312     event.refPoint.x = event.refPoint.y = 0;
  1313   } else {
  1314     event.refPoint.x = aPoint->x;
  1315     event.refPoint.y = aPoint->y;
  1317   event.time = ::GetMessageTime();
  1320 bool
  1321 MetroWidget::DispatchWindowEvent(WidgetGUIEvent* aEvent)
  1323   MOZ_ASSERT(aEvent);
  1324   nsEventStatus status = nsEventStatus_eIgnore;
  1325   DispatchEvent(aEvent, status);
  1326   return (status == nsEventStatus_eConsumeNoDefault);
  1329 NS_IMETHODIMP
  1330 MetroWidget::DispatchEvent(WidgetGUIEvent* event, nsEventStatus & aStatus)
  1332   if (event->AsInputEvent()) {
  1333     UserActivity();
  1336   aStatus = nsEventStatus_eIgnore;
  1338   // Top level windows can have a view attached which requires events be sent
  1339   // to the underlying base window and the view. Added when we combined the
  1340   // base chrome window with the main content child for nc client area (title
  1341   // bar) rendering.
  1342   if (mAttachedWidgetListener) {
  1343     aStatus = mAttachedWidgetListener->HandleEvent(event, mUseAttachedEvents);
  1345   else if (mWidgetListener) {
  1346     aStatus = mWidgetListener->HandleEvent(event, mUseAttachedEvents);
  1349   // the window can be destroyed during processing of seemingly innocuous events like, say,
  1350   // mousedowns due to the magic of scripting. mousedowns will return nsEventStatus_eIgnore,
  1351   // which causes problems with the deleted window. therefore:
  1352   if (mOnDestroyCalled)
  1353     aStatus = nsEventStatus_eConsumeNoDefault;
  1354   return NS_OK;
  1357 #ifdef ACCESSIBILITY
  1358 mozilla::a11y::Accessible*
  1359 MetroWidget::GetAccessible()
  1361   // We want the ability to forcibly disable a11y on windows, because
  1362   // some non-a11y-related components attempt to bring it up.  See bug
  1363   // 538530 for details; we have a pref here that allows it to be disabled
  1364   // for performance and testing resons.
  1365   //
  1366   // This pref is checked only once, and the browser needs a restart to
  1367   // pick up any changes.
  1368   static int accForceDisable = -1;
  1370   if (accForceDisable == -1) {
  1371     const char* kPrefName = "accessibility.win32.force_disabled";
  1372     if (Preferences::GetBool(kPrefName, false)) {
  1373       accForceDisable = 1;
  1374     } else {
  1375       accForceDisable = 0;
  1379   // If the pref was true, return null here, disabling a11y.
  1380   if (accForceDisable)
  1381       return nullptr;
  1383   return GetRootAccessible();
  1385 #endif
  1387 double
  1388 MetroWidget::GetDefaultScaleInternal()
  1390   return MetroUtils::ScaleFactor();
  1393 LayoutDeviceIntPoint
  1394 MetroWidget::CSSIntPointToLayoutDeviceIntPoint(const CSSIntPoint &aCSSPoint)
  1396   CSSToLayoutDeviceScale scale = GetDefaultScale();
  1397   LayoutDeviceIntPoint devPx(int32_t(NS_round(scale.scale * aCSSPoint.x)),
  1398                              int32_t(NS_round(scale.scale * aCSSPoint.y)));
  1399   return devPx;
  1402 float
  1403 MetroWidget::GetDPI()
  1405   if (!mView) {
  1406     return 96.0;
  1408   return mView->GetDPI();
  1411 void
  1412 MetroWidget::ChangedDPI()
  1414   if (mWidgetListener) {
  1415     nsIPresShell* presShell = mWidgetListener->GetPresShell();
  1416     if (presShell) {
  1417       presShell->BackingScaleFactorChanged();
  1422 already_AddRefed<nsIPresShell>
  1423 MetroWidget::GetPresShell()
  1425   if (mWidgetListener) {
  1426     nsCOMPtr<nsIPresShell> ps = mWidgetListener->GetPresShell();
  1427     return ps.forget();
  1429   return nullptr;
  1432 NS_IMETHODIMP
  1433 MetroWidget::ConstrainPosition(bool aAllowSlop, int32_t *aX, int32_t *aY)
  1435   return NS_OK;
  1438 void
  1439 MetroWidget::SizeModeChanged()
  1441   if (mWidgetListener) {
  1442     mWidgetListener->SizeModeChanged(nsSizeMode_Normal);
  1446 void
  1447 MetroWidget::Activated(bool aActiveated)
  1449   if (mWidgetListener) {
  1450     aActiveated ?
  1451       mWidgetListener->WindowActivated() :
  1452       mWidgetListener->WindowDeactivated();
  1456 NS_IMETHODIMP
  1457 MetroWidget::Move(double aX, double aY)
  1459   NotifyWindowMoved(aX, aY);
  1460   return NS_OK;
  1463 NS_IMETHODIMP
  1464 MetroWidget::Resize(double aWidth, double aHeight, bool aRepaint)
  1466   return Resize(0, 0, aWidth, aHeight, aRepaint);
  1469 NS_IMETHODIMP
  1470 MetroWidget::Resize(double aX, double aY, double aWidth, double aHeight, bool aRepaint)
  1472   WinUtils::Log("Resize: %f %f %f %f", aX, aY, aWidth, aHeight);
  1473   if (mAttachedWidgetListener) {
  1474     mAttachedWidgetListener->WindowResized(this, aWidth, aHeight);
  1476   if (mWidgetListener) {
  1477     mWidgetListener->WindowResized(this, aWidth, aHeight);
  1479   Invalidate();
  1480   return NS_OK;
  1483 NS_IMETHODIMP
  1484 MetroWidget::SetFocus(bool aRaise)
  1486   return NS_OK;
  1489 nsresult
  1490 MetroWidget::ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
  1492   return NS_OK;
  1495 void*
  1496 MetroWidget::GetNativeData(uint32_t aDataType)
  1498   switch(aDataType) {
  1499     case NS_NATIVE_WINDOW:
  1500       return mWnd;
  1501     case NS_NATIVE_ICOREWINDOW:
  1502       if (mView) {
  1503         return reinterpret_cast<IUnknown*>(mView->GetCoreWindow());
  1505       break;
  1506    case NS_NATIVE_TSF_THREAD_MGR:
  1507    case NS_NATIVE_TSF_CATEGORY_MGR:
  1508    case NS_NATIVE_TSF_DISPLAY_ATTR_MGR:
  1509      return nsTextStore::GetNativeData(aDataType);
  1511   return nullptr;
  1514 void
  1515 MetroWidget::FreeNativeData(void * data, uint32_t aDataType)
  1519 NS_IMETHODIMP
  1520 MetroWidget::SetTitle(const nsAString& aTitle)
  1522   return NS_OK;
  1525 nsIntPoint
  1526 MetroWidget::WidgetToScreenOffset()
  1528   return nsIntPoint(0,0);
  1531 NS_IMETHODIMP
  1532 MetroWidget::CaptureRollupEvents(nsIRollupListener * aListener,
  1533                                  bool aDoCapture)
  1535   return NS_OK;
  1538 NS_IMETHODIMP_(void)
  1539 MetroWidget::SetInputContext(const InputContext& aContext,
  1540                              const InputContextAction& aAction)
  1542   mInputContext = aContext;
  1543   nsTextStore::SetInputContext(this, mInputContext, aAction);
  1544   bool enable = (mInputContext.mIMEState.mEnabled == IMEState::ENABLED ||
  1545                  mInputContext.mIMEState.mEnabled == IMEState::PLUGIN);
  1546   if (enable &&
  1547       mInputContext.mIMEState.mOpen != IMEState::DONT_CHANGE_OPEN_STATE) {
  1548     bool open = (mInputContext.mIMEState.mOpen == IMEState::OPEN);
  1549     nsTextStore::SetIMEOpenState(open);
  1553 NS_IMETHODIMP_(nsIWidget::InputContext)
  1554 MetroWidget::GetInputContext()
  1556   return mInputContext;
  1559 NS_IMETHODIMP
  1560 MetroWidget::NotifyIME(const IMENotification& aIMENotification)
  1562   switch (aIMENotification.mMessage) {
  1563     case REQUEST_TO_COMMIT_COMPOSITION:
  1564       nsTextStore::CommitComposition(false);
  1565       return NS_OK;
  1566     case REQUEST_TO_CANCEL_COMPOSITION:
  1567       nsTextStore::CommitComposition(true);
  1568       return NS_OK;
  1569     case NOTIFY_IME_OF_FOCUS:
  1570       return nsTextStore::OnFocusChange(true, this,
  1571                                         mInputContext.mIMEState.mEnabled);
  1572     case NOTIFY_IME_OF_BLUR:
  1573       return nsTextStore::OnFocusChange(false, this,
  1574                                         mInputContext.mIMEState.mEnabled);
  1575     case NOTIFY_IME_OF_SELECTION_CHANGE:
  1576       return nsTextStore::OnSelectionChange();
  1577     case NOTIFY_IME_OF_TEXT_CHANGE:
  1578       return nsTextStore::OnTextChange(aIMENotification);
  1579     case NOTIFY_IME_OF_POSITION_CHANGE:
  1580       return nsTextStore::OnLayoutChange();
  1581     default:
  1582       return NS_ERROR_NOT_IMPLEMENTED;
  1586 NS_IMETHODIMP
  1587 MetroWidget::GetToggledKeyState(uint32_t aKeyCode, bool* aLEDState)
  1589   NS_ENSURE_ARG_POINTER(aLEDState);
  1590   *aLEDState = (::GetKeyState(aKeyCode) & 1) != 0;
  1591   return NS_OK;
  1594 nsIMEUpdatePreference
  1595 MetroWidget::GetIMEUpdatePreference()
  1597   return nsTextStore::GetIMEUpdatePreference();
  1600 NS_IMETHODIMP
  1601 MetroWidget::ReparentNativeWidget(nsIWidget* aNewParent)
  1603   return NS_OK;
  1606 void
  1607 MetroWidget::SuppressBlurEvents(bool aSuppress)
  1611 bool
  1612 MetroWidget::BlurEventsSuppressed()
  1614   return false;
  1617 void
  1618 MetroWidget::PickerOpen()
  1622 void
  1623 MetroWidget::PickerClosed()
  1627 bool
  1628 MetroWidget::HasPendingInputEvent()
  1630   if (HIWORD(GetQueueStatus(QS_INPUT)))
  1631     return true;
  1632   return false;
  1635 NS_IMETHODIMP
  1636 MetroWidget::Observe(nsISupports *subject, const char *topic, const char16_t *data)
  1638   NS_ENSURE_ARG_POINTER(topic);
  1639   if (!strcmp(topic, "apzc-zoom-to-rect")) {
  1640     CSSRect rect = CSSRect();
  1641     uint64_t viewId = 0;
  1642     int32_t presShellId = 0;
  1644     int reScan = swscanf(data, L"%f,%f,%f,%f,%d,%llu",
  1645                  &rect.x, &rect.y, &rect.width, &rect.height,
  1646                  &presShellId, &viewId);
  1647     if(reScan != 6) {
  1648       NS_WARNING("Malformed apzc-zoom-to-rect message");
  1651     ScrollableLayerGuid guid = ScrollableLayerGuid(mRootLayerTreeId, presShellId, viewId);
  1652     APZController::sAPZC->ZoomToRect(guid, rect);
  1654   else if (!strcmp(topic, "apzc-disable-zoom")) {
  1655     uint64_t viewId = 0;
  1656     int32_t presShellId = 0;
  1658     int reScan = swscanf(data, L"%d,%llu",
  1659       &presShellId, &viewId);
  1660     if (reScan != 2) {
  1661       NS_WARNING("Malformed apzc-disable-zoom message");
  1664     ScrollableLayerGuid guid = ScrollableLayerGuid(mRootLayerTreeId, presShellId, viewId);
  1665     APZController::sAPZC->UpdateZoomConstraints(guid,
  1666       ZoomConstraints(false, false, CSSToScreenScale(1.0f), CSSToScreenScale(1.0f)));
  1668   return NS_OK;

mercurial