|
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/. */ |
|
6 |
|
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" |
|
42 |
|
43 using namespace Microsoft::WRL; |
|
44 using namespace Microsoft::WRL::Wrappers; |
|
45 |
|
46 using namespace mozilla; |
|
47 using namespace mozilla::widget; |
|
48 using namespace mozilla::layers; |
|
49 using namespace mozilla::widget::winrt; |
|
50 |
|
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; |
|
61 |
|
62 #ifdef PR_LOGGING |
|
63 extern PRLogModuleInfo* gWindowsLog; |
|
64 #endif |
|
65 |
|
66 #if !defined(SM_CONVERTIBLESLATEMODE) |
|
67 #define SM_CONVERTIBLESLATEMODE 0x2003 |
|
68 #endif |
|
69 |
|
70 static uint32_t gInstanceCount = 0; |
|
71 const char16_t* kMetroSubclassThisProp = L"MetroSubclassThisProp"; |
|
72 HWND MetroWidget::sICoreHwnd = nullptr; |
|
73 |
|
74 namespace mozilla { |
|
75 namespace widget { |
|
76 UINT sDefaultBrowserMsgId = RegisterWindowMessageW(L"DefaultBrowserClosing"); |
|
77 } } |
|
78 |
|
79 // WM_GETOBJECT id pulled from uia headers |
|
80 #define UiaRootObjectId -25 |
|
81 |
|
82 namespace mozilla { |
|
83 namespace widget { |
|
84 namespace winrt { |
|
85 extern ComPtr<MetroApp> sMetroApp; |
|
86 extern ComPtr<IUIABridge> gProviderRoot; |
|
87 } } } |
|
88 |
|
89 namespace { |
|
90 |
|
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 } |
|
102 |
|
103 uint32_t const len = keySequence.Length() * 2 + aExtraInputsLen; |
|
104 |
|
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; |
|
151 |
|
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 } |
|
169 |
|
170 NS_IMPL_ISUPPORTS_INHERITED0(MetroWidget, nsBaseWidget) |
|
171 |
|
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 } |
|
189 |
|
190 MetroWidget::~MetroWidget() |
|
191 { |
|
192 LogThis(); |
|
193 |
|
194 gInstanceCount--; |
|
195 |
|
196 // Global shutdown |
|
197 if (!gInstanceCount) { |
|
198 APZController::sAPZC = nullptr; |
|
199 nsTextStore::Terminate(); |
|
200 } // !gInstanceCount |
|
201 } |
|
202 |
|
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(); |
|
212 |
|
213 nsWidgetInitData defaultInitData; |
|
214 if (!aInitData) |
|
215 aInitData = &defaultInitData; |
|
216 |
|
217 mWindowType = aInitData->mWindowType; |
|
218 |
|
219 // Ensure that the toolkit is created. |
|
220 nsToolkit::GetToolkit(); |
|
221 |
|
222 BaseCreate(aParent, aRect, aContext, aInitData); |
|
223 |
|
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 } |
|
246 |
|
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 } |
|
254 |
|
255 // the main widget gets created first |
|
256 gTopLevelAssigned = true; |
|
257 sMetroApp->SetWidget(this); |
|
258 WinUtils::SetNSWindowBasePtr(mWnd, this); |
|
259 |
|
260 if (mWidgetListener) { |
|
261 mWidgetListener->WindowActivated(); |
|
262 } |
|
263 |
|
264 return NS_OK; |
|
265 } |
|
266 |
|
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 } |
|
275 |
|
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; |
|
283 |
|
284 nsCOMPtr<nsIWidget> kungFuDeathGrip(this); |
|
285 |
|
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 } |
|
295 |
|
296 RemoveSubclass(); |
|
297 NotifyWindowDestroyed(); |
|
298 |
|
299 // Prevent the widget from sending additional events. |
|
300 mWidgetListener = nullptr; |
|
301 mAttachedWidgetListener = nullptr; |
|
302 |
|
303 // Release references to children, device context, toolkit, and app shell. |
|
304 nsBaseWidget::Destroy(); |
|
305 nsBaseWidget::OnDestroy(); |
|
306 WinUtils::SetNSWindowBasePtr(mWnd, nullptr); |
|
307 |
|
308 if (mLayerManager) { |
|
309 mLayerManager->Destroy(); |
|
310 } |
|
311 |
|
312 mLayerManager = nullptr; |
|
313 mView = nullptr; |
|
314 mIdleService = nullptr; |
|
315 mWnd = nullptr; |
|
316 |
|
317 return NS_OK; |
|
318 } |
|
319 |
|
320 NS_IMETHODIMP |
|
321 MetroWidget::SetParent(nsIWidget *aNewParent) |
|
322 { |
|
323 return NS_OK; |
|
324 } |
|
325 |
|
326 NS_IMETHODIMP |
|
327 MetroWidget::Show(bool bState) |
|
328 { |
|
329 return NS_OK; |
|
330 } |
|
331 |
|
332 uint32_t |
|
333 MetroWidget::GetMaxTouchPoints() const |
|
334 { |
|
335 ComPtr<IPointerDeviceStatics> deviceStatics; |
|
336 |
|
337 HRESULT hr = GetActivationFactory( |
|
338 HStringReference(RuntimeClass_Windows_Devices_Input_PointerDevice).Get(), |
|
339 deviceStatics.GetAddressOf()); |
|
340 |
|
341 if (FAILED(hr)) { |
|
342 return 0; |
|
343 } |
|
344 |
|
345 ComPtr< IVectorView<PointerDevice*> > deviceList; |
|
346 hr = deviceStatics->GetPointerDevices(&deviceList); |
|
347 |
|
348 if (FAILED(hr)) { |
|
349 return 0; |
|
350 } |
|
351 |
|
352 uint32_t deviceNum = 0; |
|
353 deviceList->get_Size(&deviceNum); |
|
354 |
|
355 uint32_t maxTouchPoints = 0; |
|
356 for (uint32_t index = 0; index < deviceNum; ++index) { |
|
357 ComPtr<IPointerDevice> device; |
|
358 PointerDeviceType deviceType; |
|
359 |
|
360 if (FAILED(deviceList->GetAt(index, device.GetAddressOf()))) { |
|
361 continue; |
|
362 } |
|
363 |
|
364 if (FAILED(device->get_PointerDeviceType(&deviceType))) { |
|
365 continue; |
|
366 } |
|
367 |
|
368 if (deviceType == PointerDeviceType_Touch) { |
|
369 uint32_t deviceMaxTouchPoints = 0; |
|
370 device->get_MaxContacts(&deviceMaxTouchPoints); |
|
371 maxTouchPoints = std::max(maxTouchPoints, deviceMaxTouchPoints); |
|
372 } |
|
373 } |
|
374 |
|
375 return maxTouchPoints; |
|
376 } |
|
377 |
|
378 NS_IMETHODIMP |
|
379 MetroWidget::IsVisible(bool & aState) |
|
380 { |
|
381 aState = mView->IsVisible(); |
|
382 return NS_OK; |
|
383 } |
|
384 |
|
385 bool |
|
386 MetroWidget::IsVisible() const |
|
387 { |
|
388 if (!mView) |
|
389 return false; |
|
390 return mView->IsVisible(); |
|
391 } |
|
392 |
|
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 } |
|
402 |
|
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 } |
|
409 |
|
410 HRESULT hr = ::RevokeDragDrop(mWnd); |
|
411 return SUCCEEDED(hr) ? NS_OK : NS_ERROR_FAILURE; |
|
412 } |
|
413 } |
|
414 |
|
415 NS_IMETHODIMP |
|
416 MetroWidget::IsEnabled(bool *aState) |
|
417 { |
|
418 *aState = mView->IsEnabled(); |
|
419 return NS_OK; |
|
420 } |
|
421 |
|
422 bool |
|
423 MetroWidget::IsEnabled() const |
|
424 { |
|
425 if (!mView) |
|
426 return false; |
|
427 return mView->IsEnabled(); |
|
428 } |
|
429 |
|
430 NS_IMETHODIMP |
|
431 MetroWidget::Enable(bool bState) |
|
432 { |
|
433 return NS_OK; |
|
434 } |
|
435 |
|
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 } |
|
447 |
|
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 } |
|
459 |
|
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 } |
|
471 |
|
472 NS_IMETHODIMP |
|
473 MetroWidget::SetCursor(nsCursor aCursor) |
|
474 { |
|
475 if (!mView) |
|
476 return NS_ERROR_FAILURE; |
|
477 |
|
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 } |
|
581 |
|
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 } |
|
594 |
|
595 nsresult |
|
596 MetroWidget::SynthesizeNativeMouseEvent(nsIntPoint aPoint, |
|
597 uint32_t aNativeMessage, |
|
598 uint32_t aModifierFlags) |
|
599 { |
|
600 WinUtils::Log("ENTERED SynthesizeNativeMouseEvent"); |
|
601 |
|
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); |
|
614 |
|
615 WinUtils::Log("Exiting SynthesizeNativeMouseEvent"); |
|
616 return NS_OK; |
|
617 } |
|
618 |
|
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 } |
|
634 |
|
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 } |
|
645 |
|
646 // Async event sending for mouse and keyboard input. |
|
647 |
|
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 } |
|
682 |
|
683 void |
|
684 MetroWidget::DeliverNextScrollEvent() |
|
685 { |
|
686 WidgetGUIEvent* event = |
|
687 static_cast<WidgetInputEvent*>(mEventQueue.PopFront()); |
|
688 DispatchWindowEvent(event); |
|
689 delete event; |
|
690 } |
|
691 |
|
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 } |
|
709 |
|
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 }; |
|
728 |
|
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 } |
|
739 |
|
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 } |
|
748 |
|
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 } |
|
761 |
|
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 } |
|
781 |
|
782 // Indicates if we should hand messages to the default windows |
|
783 // procedure for processing. |
|
784 bool processDefault = true; |
|
785 |
|
786 // The result returned if we do not do default processing. |
|
787 LRESULT processResult = 0; |
|
788 |
|
789 MSGResult msgResult(&processResult); |
|
790 MouseScrollHandler::ProcessMessage(this, aMsg, aWParam, aLParam, msgResult); |
|
791 if (msgResult.mConsumed) { |
|
792 return processResult; |
|
793 } |
|
794 |
|
795 nsTextStore::ProcessMessage(this, aMsg, aWParam, aLParam, msgResult); |
|
796 if (msgResult.mConsumed) { |
|
797 return processResult; |
|
798 } |
|
799 |
|
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 } |
|
816 |
|
817 // Keyboard handling is passed to KeyboardLayout, which delivers gecko events |
|
818 // via DispatchKeyboardEvent. |
|
819 |
|
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); |
|
831 |
|
832 if (nsTextStore::IsComposingOn(this)) { |
|
833 break; |
|
834 } |
|
835 |
|
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 } |
|
844 |
|
845 case WM_KEYUP: |
|
846 case WM_SYSKEYUP: |
|
847 { |
|
848 if (nsTextStore::IsComposingOn(this)) { |
|
849 break; |
|
850 } |
|
851 |
|
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 } |
|
858 |
|
859 case WM_CHAR: |
|
860 case WM_SYSCHAR: |
|
861 { |
|
862 if (nsTextStore::IsComposingOn(this)) { |
|
863 nsTextStore::CommitComposition(false); |
|
864 } |
|
865 |
|
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 } |
|
872 |
|
873 case WM_INPUTLANGCHANGE: |
|
874 { |
|
875 KeyboardLayout::GetInstance()-> |
|
876 OnLayoutChange(reinterpret_cast<HKL>(aLParam)); |
|
877 processResult = 1; |
|
878 break; |
|
879 } |
|
880 |
|
881 case WM_APPCOMMAND: |
|
882 processDefault = HandleAppCommandMsg(aWParam, aLParam, &processResult); |
|
883 break; |
|
884 |
|
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 } |
|
909 |
|
910 default: |
|
911 { |
|
912 break; |
|
913 } |
|
914 } |
|
915 |
|
916 if (processDefault) { |
|
917 return CallWindowProc(mMetroWndProc, aWnd, aMsg, aWParam, |
|
918 aLParam); |
|
919 } |
|
920 return processResult; |
|
921 } |
|
922 |
|
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 } |
|
937 |
|
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."); |
|
946 |
|
947 // subclass it |
|
948 SetSubclass(); |
|
949 sICoreHwnd = mWnd; |
|
950 return; |
|
951 } |
|
952 |
|
953 void |
|
954 MetroWidget::SetSubclass() |
|
955 { |
|
956 if (!mWnd) { |
|
957 NS_NOTREACHED("SetSubclass called without a valid hwnd."); |
|
958 return; |
|
959 } |
|
960 |
|
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 } |
|
975 |
|
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 } |
|
991 |
|
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); |
|
1001 } |
|
1002 |
|
1003 bool |
|
1004 MetroWidget::ShouldUseMainThreadD3D10Manager() |
|
1005 { |
|
1006 // Either we're not initialized yet, or this is the toolkit widget |
|
1007 if (!mView) { |
|
1008 return false; |
|
1009 } |
|
1010 return (!CompositorParent::CompositorLoop() && mWindowType == eWindowType_toplevel); |
|
1011 } |
|
1012 |
|
1013 bool |
|
1014 MetroWidget::ShouldUseBasicManager() |
|
1015 { |
|
1016 // toolkit or test widgets fall back on empty shadow layers |
|
1017 return (mWindowType != eWindowType_toplevel); |
|
1018 } |
|
1019 |
|
1020 bool |
|
1021 MetroWidget::ShouldUseAPZC() |
|
1022 { |
|
1023 const char* kPrefName = "layers.async-pan-zoom.enabled"; |
|
1024 return ShouldUseOffMainThreadCompositing() && |
|
1025 Preferences::GetBool(kPrefName, false); |
|
1026 } |
|
1027 |
|
1028 void |
|
1029 MetroWidget::SetWidgetListener(nsIWidgetListener* aWidgetListener) |
|
1030 { |
|
1031 mWidgetListener = aWidgetListener; |
|
1032 if (mController) { |
|
1033 mController->SetWidgetListener(aWidgetListener); |
|
1034 } |
|
1035 } |
|
1036 |
|
1037 CompositorParent* MetroWidget::NewCompositorParent(int aSurfaceWidth, int aSurfaceHeight) |
|
1038 { |
|
1039 CompositorParent *compositor = nsBaseWidget::NewCompositorParent(aSurfaceWidth, aSurfaceHeight); |
|
1040 |
|
1041 if (ShouldUseAPZC()) { |
|
1042 mRootLayerTreeId = compositor->RootLayerTreeId(); |
|
1043 |
|
1044 mController = new APZController(); |
|
1045 mController->SetWidgetListener(mWidgetListener); |
|
1046 |
|
1047 CompositorParent::SetControllerForLayerTree(mRootLayerTreeId, mController); |
|
1048 |
|
1049 APZController::sAPZC = CompositorParent::GetAPZCTreeManager(compositor->RootLayerTreeId()); |
|
1050 APZController::sAPZC->SetDPI(GetDPI()); |
|
1051 |
|
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); |
|
1058 } |
|
1059 } |
|
1060 |
|
1061 return compositor; |
|
1062 } |
|
1063 |
|
1064 MetroWidget::TouchBehaviorFlags |
|
1065 MetroWidget::ContentGetAllowedTouchBehavior(const nsIntPoint& aPoint) |
|
1066 { |
|
1067 return ContentHelper::GetAllowedTouchBehavior(this, aPoint); |
|
1068 } |
|
1069 |
|
1070 void |
|
1071 MetroWidget::ApzcGetAllowedTouchBehavior(WidgetInputEvent* aTransformedEvent, |
|
1072 nsTArray<TouchBehaviorFlags>& aOutBehaviors) |
|
1073 { |
|
1074 LogFunction(); |
|
1075 return APZController::sAPZC->GetAllowedTouchBehavior(aTransformedEvent, aOutBehaviors); |
|
1076 } |
|
1077 |
|
1078 void |
|
1079 MetroWidget::ApzcSetAllowedTouchBehavior(const ScrollableLayerGuid& aGuid, |
|
1080 nsTArray<TouchBehaviorFlags>& aBehaviors) |
|
1081 { |
|
1082 LogFunction(); |
|
1083 if (!APZController::sAPZC) { |
|
1084 return; |
|
1085 } |
|
1086 APZController::sAPZC->SetAllowedTouchBehavior(aGuid, aBehaviors); |
|
1087 } |
|
1088 |
|
1089 void |
|
1090 MetroWidget::ApzContentConsumingTouch(const ScrollableLayerGuid& aGuid) |
|
1091 { |
|
1092 LogFunction(); |
|
1093 if (!mController) { |
|
1094 return; |
|
1095 } |
|
1096 mController->ContentReceivedTouch(aGuid, true); |
|
1097 } |
|
1098 |
|
1099 void |
|
1100 MetroWidget::ApzContentIgnoringTouch(const ScrollableLayerGuid& aGuid) |
|
1101 { |
|
1102 LogFunction(); |
|
1103 if (!mController) { |
|
1104 return; |
|
1105 } |
|
1106 mController->ContentReceivedTouch(aGuid, false); |
|
1107 } |
|
1108 |
|
1109 bool |
|
1110 MetroWidget::ApzHitTest(ScreenIntPoint& pt) |
|
1111 { |
|
1112 if (!mController) { |
|
1113 return false; |
|
1114 } |
|
1115 return mController->HitTestAPZC(pt); |
|
1116 } |
|
1117 |
|
1118 void |
|
1119 MetroWidget::ApzTransformGeckoCoordinate(const ScreenIntPoint& aPoint, |
|
1120 LayoutDeviceIntPoint* aRefPointOut) |
|
1121 { |
|
1122 if (!mController) { |
|
1123 return; |
|
1124 } |
|
1125 mController->TransformCoordinateToGecko(aPoint, aRefPointOut); |
|
1126 } |
|
1127 |
|
1128 nsEventStatus |
|
1129 MetroWidget::ApzReceiveInputEvent(WidgetInputEvent* aEvent, |
|
1130 ScrollableLayerGuid* aOutTargetGuid) |
|
1131 { |
|
1132 MOZ_ASSERT(aEvent); |
|
1133 |
|
1134 if (!mController) { |
|
1135 return nsEventStatus_eIgnore; |
|
1136 } |
|
1137 return mController->ReceiveInputEvent(aEvent, aOutTargetGuid); |
|
1138 } |
|
1139 |
|
1140 LayerManager* |
|
1141 MetroWidget::GetLayerManager(PLayerTransactionChild* aShadowManager, |
|
1142 LayersBackend aBackendHint, |
|
1143 LayerManagerPersistence aPersistence, |
|
1144 bool* aAllowRetaining) |
|
1145 { |
|
1146 bool retaining = true; |
|
1147 |
|
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; |
|
1155 } |
|
1156 |
|
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()); |
|
1165 |
|
1166 mLayerManager->Destroy(); |
|
1167 mLayerManager = nullptr; |
|
1168 retaining = false; |
|
1169 } |
|
1170 } |
|
1171 } |
|
1172 |
|
1173 HRESULT hr = S_OK; |
|
1174 |
|
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; |
|
1186 } |
|
1187 } else if (ShouldUseBasicManager()) { |
|
1188 mLayerManager = CreateBasicLayerManager(); |
|
1189 } |
|
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)); |
|
1206 } |
|
1207 #endif |
|
1208 NS_RUNTIMEABORT("Couldn't create layer manager"); |
|
1209 } |
|
1210 } |
|
1211 } |
|
1212 |
|
1213 if (aAllowRetaining) { |
|
1214 *aAllowRetaining = retaining; |
|
1215 } |
|
1216 |
|
1217 return mLayerManager; |
|
1218 } |
|
1219 |
|
1220 NS_IMETHODIMP |
|
1221 MetroWidget::Invalidate(bool aEraseBackground, |
|
1222 bool aUpdateNCArea, |
|
1223 bool aIncludeChildren) |
|
1224 { |
|
1225 nsIntRect rect; |
|
1226 if (mView) { |
|
1227 mView->GetBounds(rect); |
|
1228 } |
|
1229 Invalidate(rect); |
|
1230 return NS_OK; |
|
1231 } |
|
1232 |
|
1233 NS_IMETHODIMP |
|
1234 MetroWidget::Invalidate(const nsIntRect & aRect) |
|
1235 { |
|
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); |
|
1243 } |
|
1244 |
|
1245 return NS_OK; |
|
1246 } |
|
1247 |
|
1248 nsTransparencyMode |
|
1249 MetroWidget::GetTransparencyMode() |
|
1250 { |
|
1251 return mTransparencyMode; |
|
1252 } |
|
1253 |
|
1254 void |
|
1255 MetroWidget::SetTransparencyMode(nsTransparencyMode aMode) |
|
1256 { |
|
1257 mTransparencyMode = aMode; |
|
1258 } |
|
1259 |
|
1260 nsIWidgetListener* |
|
1261 MetroWidget::GetPaintListener() |
|
1262 { |
|
1263 if (mOnDestroyCalled) |
|
1264 return nullptr; |
|
1265 return mAttachedWidgetListener ? mAttachedWidgetListener : |
|
1266 mWidgetListener; |
|
1267 } |
|
1268 |
|
1269 void MetroWidget::Paint(const nsIntRegion& aInvalidRegion) |
|
1270 { |
|
1271 gfxWindowsPlatform::GetPlatform()->UpdateRenderMode(); |
|
1272 |
|
1273 nsIWidgetListener* listener = GetPaintListener(); |
|
1274 if (!listener) |
|
1275 return; |
|
1276 |
|
1277 listener->WillPaintWindow(this); |
|
1278 |
|
1279 // Refresh since calls like WillPaintWindow can destroy the widget |
|
1280 listener = GetPaintListener(); |
|
1281 if (!listener) |
|
1282 return; |
|
1283 |
|
1284 listener->PaintWindow(this, aInvalidRegion); |
|
1285 |
|
1286 listener = GetPaintListener(); |
|
1287 if (!listener) |
|
1288 return; |
|
1289 |
|
1290 listener->DidPaintWindow(); |
|
1291 } |
|
1292 |
|
1293 void MetroWidget::UserActivity() |
|
1294 { |
|
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"); |
|
1298 } |
|
1299 |
|
1300 // Check that we now have the idle service. |
|
1301 if (mIdleService) { |
|
1302 mIdleService->ResetIdleTimeOut(0); |
|
1303 } |
|
1304 } |
|
1305 |
|
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) |
|
1310 { |
|
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; |
|
1316 } |
|
1317 event.time = ::GetMessageTime(); |
|
1318 } |
|
1319 |
|
1320 bool |
|
1321 MetroWidget::DispatchWindowEvent(WidgetGUIEvent* aEvent) |
|
1322 { |
|
1323 MOZ_ASSERT(aEvent); |
|
1324 nsEventStatus status = nsEventStatus_eIgnore; |
|
1325 DispatchEvent(aEvent, status); |
|
1326 return (status == nsEventStatus_eConsumeNoDefault); |
|
1327 } |
|
1328 |
|
1329 NS_IMETHODIMP |
|
1330 MetroWidget::DispatchEvent(WidgetGUIEvent* event, nsEventStatus & aStatus) |
|
1331 { |
|
1332 if (event->AsInputEvent()) { |
|
1333 UserActivity(); |
|
1334 } |
|
1335 |
|
1336 aStatus = nsEventStatus_eIgnore; |
|
1337 |
|
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); |
|
1344 } |
|
1345 else if (mWidgetListener) { |
|
1346 aStatus = mWidgetListener->HandleEvent(event, mUseAttachedEvents); |
|
1347 } |
|
1348 |
|
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; |
|
1355 } |
|
1356 |
|
1357 #ifdef ACCESSIBILITY |
|
1358 mozilla::a11y::Accessible* |
|
1359 MetroWidget::GetAccessible() |
|
1360 { |
|
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; |
|
1369 |
|
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; |
|
1376 } |
|
1377 } |
|
1378 |
|
1379 // If the pref was true, return null here, disabling a11y. |
|
1380 if (accForceDisable) |
|
1381 return nullptr; |
|
1382 |
|
1383 return GetRootAccessible(); |
|
1384 } |
|
1385 #endif |
|
1386 |
|
1387 double |
|
1388 MetroWidget::GetDefaultScaleInternal() |
|
1389 { |
|
1390 return MetroUtils::ScaleFactor(); |
|
1391 } |
|
1392 |
|
1393 LayoutDeviceIntPoint |
|
1394 MetroWidget::CSSIntPointToLayoutDeviceIntPoint(const CSSIntPoint &aCSSPoint) |
|
1395 { |
|
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; |
|
1400 } |
|
1401 |
|
1402 float |
|
1403 MetroWidget::GetDPI() |
|
1404 { |
|
1405 if (!mView) { |
|
1406 return 96.0; |
|
1407 } |
|
1408 return mView->GetDPI(); |
|
1409 } |
|
1410 |
|
1411 void |
|
1412 MetroWidget::ChangedDPI() |
|
1413 { |
|
1414 if (mWidgetListener) { |
|
1415 nsIPresShell* presShell = mWidgetListener->GetPresShell(); |
|
1416 if (presShell) { |
|
1417 presShell->BackingScaleFactorChanged(); |
|
1418 } |
|
1419 } |
|
1420 } |
|
1421 |
|
1422 already_AddRefed<nsIPresShell> |
|
1423 MetroWidget::GetPresShell() |
|
1424 { |
|
1425 if (mWidgetListener) { |
|
1426 nsCOMPtr<nsIPresShell> ps = mWidgetListener->GetPresShell(); |
|
1427 return ps.forget(); |
|
1428 } |
|
1429 return nullptr; |
|
1430 } |
|
1431 |
|
1432 NS_IMETHODIMP |
|
1433 MetroWidget::ConstrainPosition(bool aAllowSlop, int32_t *aX, int32_t *aY) |
|
1434 { |
|
1435 return NS_OK; |
|
1436 } |
|
1437 |
|
1438 void |
|
1439 MetroWidget::SizeModeChanged() |
|
1440 { |
|
1441 if (mWidgetListener) { |
|
1442 mWidgetListener->SizeModeChanged(nsSizeMode_Normal); |
|
1443 } |
|
1444 } |
|
1445 |
|
1446 void |
|
1447 MetroWidget::Activated(bool aActiveated) |
|
1448 { |
|
1449 if (mWidgetListener) { |
|
1450 aActiveated ? |
|
1451 mWidgetListener->WindowActivated() : |
|
1452 mWidgetListener->WindowDeactivated(); |
|
1453 } |
|
1454 } |
|
1455 |
|
1456 NS_IMETHODIMP |
|
1457 MetroWidget::Move(double aX, double aY) |
|
1458 { |
|
1459 NotifyWindowMoved(aX, aY); |
|
1460 return NS_OK; |
|
1461 } |
|
1462 |
|
1463 NS_IMETHODIMP |
|
1464 MetroWidget::Resize(double aWidth, double aHeight, bool aRepaint) |
|
1465 { |
|
1466 return Resize(0, 0, aWidth, aHeight, aRepaint); |
|
1467 } |
|
1468 |
|
1469 NS_IMETHODIMP |
|
1470 MetroWidget::Resize(double aX, double aY, double aWidth, double aHeight, bool aRepaint) |
|
1471 { |
|
1472 WinUtils::Log("Resize: %f %f %f %f", aX, aY, aWidth, aHeight); |
|
1473 if (mAttachedWidgetListener) { |
|
1474 mAttachedWidgetListener->WindowResized(this, aWidth, aHeight); |
|
1475 } |
|
1476 if (mWidgetListener) { |
|
1477 mWidgetListener->WindowResized(this, aWidth, aHeight); |
|
1478 } |
|
1479 Invalidate(); |
|
1480 return NS_OK; |
|
1481 } |
|
1482 |
|
1483 NS_IMETHODIMP |
|
1484 MetroWidget::SetFocus(bool aRaise) |
|
1485 { |
|
1486 return NS_OK; |
|
1487 } |
|
1488 |
|
1489 nsresult |
|
1490 MetroWidget::ConfigureChildren(const nsTArray<Configuration>& aConfigurations) |
|
1491 { |
|
1492 return NS_OK; |
|
1493 } |
|
1494 |
|
1495 void* |
|
1496 MetroWidget::GetNativeData(uint32_t aDataType) |
|
1497 { |
|
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()); |
|
1504 } |
|
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); |
|
1510 } |
|
1511 return nullptr; |
|
1512 } |
|
1513 |
|
1514 void |
|
1515 MetroWidget::FreeNativeData(void * data, uint32_t aDataType) |
|
1516 { |
|
1517 } |
|
1518 |
|
1519 NS_IMETHODIMP |
|
1520 MetroWidget::SetTitle(const nsAString& aTitle) |
|
1521 { |
|
1522 return NS_OK; |
|
1523 } |
|
1524 |
|
1525 nsIntPoint |
|
1526 MetroWidget::WidgetToScreenOffset() |
|
1527 { |
|
1528 return nsIntPoint(0,0); |
|
1529 } |
|
1530 |
|
1531 NS_IMETHODIMP |
|
1532 MetroWidget::CaptureRollupEvents(nsIRollupListener * aListener, |
|
1533 bool aDoCapture) |
|
1534 { |
|
1535 return NS_OK; |
|
1536 } |
|
1537 |
|
1538 NS_IMETHODIMP_(void) |
|
1539 MetroWidget::SetInputContext(const InputContext& aContext, |
|
1540 const InputContextAction& aAction) |
|
1541 { |
|
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); |
|
1550 } |
|
1551 } |
|
1552 |
|
1553 NS_IMETHODIMP_(nsIWidget::InputContext) |
|
1554 MetroWidget::GetInputContext() |
|
1555 { |
|
1556 return mInputContext; |
|
1557 } |
|
1558 |
|
1559 NS_IMETHODIMP |
|
1560 MetroWidget::NotifyIME(const IMENotification& aIMENotification) |
|
1561 { |
|
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; |
|
1583 } |
|
1584 } |
|
1585 |
|
1586 NS_IMETHODIMP |
|
1587 MetroWidget::GetToggledKeyState(uint32_t aKeyCode, bool* aLEDState) |
|
1588 { |
|
1589 NS_ENSURE_ARG_POINTER(aLEDState); |
|
1590 *aLEDState = (::GetKeyState(aKeyCode) & 1) != 0; |
|
1591 return NS_OK; |
|
1592 } |
|
1593 |
|
1594 nsIMEUpdatePreference |
|
1595 MetroWidget::GetIMEUpdatePreference() |
|
1596 { |
|
1597 return nsTextStore::GetIMEUpdatePreference(); |
|
1598 } |
|
1599 |
|
1600 NS_IMETHODIMP |
|
1601 MetroWidget::ReparentNativeWidget(nsIWidget* aNewParent) |
|
1602 { |
|
1603 return NS_OK; |
|
1604 } |
|
1605 |
|
1606 void |
|
1607 MetroWidget::SuppressBlurEvents(bool aSuppress) |
|
1608 { |
|
1609 } |
|
1610 |
|
1611 bool |
|
1612 MetroWidget::BlurEventsSuppressed() |
|
1613 { |
|
1614 return false; |
|
1615 } |
|
1616 |
|
1617 void |
|
1618 MetroWidget::PickerOpen() |
|
1619 { |
|
1620 } |
|
1621 |
|
1622 void |
|
1623 MetroWidget::PickerClosed() |
|
1624 { |
|
1625 } |
|
1626 |
|
1627 bool |
|
1628 MetroWidget::HasPendingInputEvent() |
|
1629 { |
|
1630 if (HIWORD(GetQueueStatus(QS_INPUT))) |
|
1631 return true; |
|
1632 return false; |
|
1633 } |
|
1634 |
|
1635 NS_IMETHODIMP |
|
1636 MetroWidget::Observe(nsISupports *subject, const char *topic, const char16_t *data) |
|
1637 { |
|
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; |
|
1643 |
|
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"); |
|
1649 } |
|
1650 |
|
1651 ScrollableLayerGuid guid = ScrollableLayerGuid(mRootLayerTreeId, presShellId, viewId); |
|
1652 APZController::sAPZC->ZoomToRect(guid, rect); |
|
1653 } |
|
1654 else if (!strcmp(topic, "apzc-disable-zoom")) { |
|
1655 uint64_t viewId = 0; |
|
1656 int32_t presShellId = 0; |
|
1657 |
|
1658 int reScan = swscanf(data, L"%d,%llu", |
|
1659 &presShellId, &viewId); |
|
1660 if (reScan != 2) { |
|
1661 NS_WARNING("Malformed apzc-disable-zoom message"); |
|
1662 } |
|
1663 |
|
1664 ScrollableLayerGuid guid = ScrollableLayerGuid(mRootLayerTreeId, presShellId, viewId); |
|
1665 APZController::sAPZC->UpdateZoomConstraints(guid, |
|
1666 ZoomConstraints(false, false, CSSToScreenScale(1.0f), CSSToScreenScale(1.0f))); |
|
1667 } |
|
1668 return NS_OK; |
|
1669 } |