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.

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

mercurial