|
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include "FrameworkView.h" |
|
7 #include "MetroAppShell.h" |
|
8 #include "MetroWidget.h" |
|
9 #include "mozilla/AutoRestore.h" |
|
10 #include "MetroUtils.h" |
|
11 #include "MetroApp.h" |
|
12 #include "UIABridgePublic.h" |
|
13 #include "KeyboardLayout.h" |
|
14 |
|
15 // generated |
|
16 #include "UIABridge.h" |
|
17 |
|
18 using namespace mozilla; |
|
19 using namespace mozilla::widget::winrt; |
|
20 #ifdef ACCESSIBILITY |
|
21 using namespace mozilla::a11y; |
|
22 #endif |
|
23 using namespace ABI::Windows::ApplicationModel; |
|
24 using namespace ABI::Windows::ApplicationModel::Core; |
|
25 using namespace ABI::Windows::ApplicationModel::Activation; |
|
26 using namespace ABI::Windows::UI::Core; |
|
27 using namespace ABI::Windows::UI::ViewManagement; |
|
28 using namespace ABI::Windows::UI::Input; |
|
29 using namespace ABI::Windows::Devices::Input; |
|
30 using namespace ABI::Windows::System; |
|
31 using namespace ABI::Windows::Foundation; |
|
32 using namespace Microsoft::WRL; |
|
33 using namespace Microsoft::WRL::Wrappers; |
|
34 |
|
35 namespace mozilla { |
|
36 namespace widget { |
|
37 namespace winrt { |
|
38 |
|
39 // statics |
|
40 bool FrameworkView::sKeyboardIsVisible = false; |
|
41 Rect FrameworkView::sKeyboardRect; |
|
42 HSTRING FrameworkView::sActivationURI = NULL; |
|
43 ApplicationExecutionState FrameworkView::sPreviousExecutionState; |
|
44 nsTArray<nsString>* sSettingsArray; |
|
45 |
|
46 FrameworkView::FrameworkView(MetroApp* aMetroApp) : |
|
47 mDPI(-1.0f), |
|
48 mWidget(nullptr), |
|
49 mShuttingDown(false), |
|
50 mMetroApp(aMetroApp), |
|
51 mWindow(nullptr), |
|
52 mMetroInput(nullptr), |
|
53 mWinVisible(false), |
|
54 mWinActiveState(false) |
|
55 { |
|
56 mActivated.value = 0; |
|
57 mWindowActivated.value = 0; |
|
58 mWindowVisibilityChanged.value = 0; |
|
59 mWindowSizeChanged.value = 0; |
|
60 mSoftKeyboardHidden.value = 0; |
|
61 mSoftKeyboardShown.value = 0; |
|
62 mDisplayPropertiesChanged.value = 0; |
|
63 mAutomationProviderRequested.value = 0; |
|
64 mDataTransferRequested.value = 0; |
|
65 mSearchQuerySubmitted.value = 0; |
|
66 mPlayToRequested.value = 0; |
|
67 mSettingsPane.value = 0; |
|
68 mPrintManager.value = 0; |
|
69 memset(&sKeyboardRect, 0, sizeof(Rect)); |
|
70 sSettingsArray = new nsTArray<nsString>(); |
|
71 LogFunction(); |
|
72 } |
|
73 |
|
74 //////////////////////////////////////////////////// |
|
75 // IFrameworkView impl. |
|
76 |
|
77 HRESULT |
|
78 FrameworkView::Initialize(ICoreApplicationView* aAppView) |
|
79 { |
|
80 LogFunction(); |
|
81 if (mShuttingDown) |
|
82 return E_FAIL; |
|
83 |
|
84 aAppView->add_Activated(Callback<__FITypedEventHandler_2_Windows__CApplicationModel__CCore__CCoreApplicationView_Windows__CApplicationModel__CActivation__CIActivatedEventArgs_t>( |
|
85 this, &FrameworkView::OnActivated).Get(), &mActivated); |
|
86 |
|
87 //CoCreateInstance(CLSID_WICImagingFactory, nullptr, |
|
88 // CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&mWicFactory)); |
|
89 return S_OK; |
|
90 } |
|
91 |
|
92 HRESULT |
|
93 FrameworkView::Uninitialize() |
|
94 { |
|
95 return S_OK; |
|
96 } |
|
97 |
|
98 HRESULT |
|
99 FrameworkView::Load(HSTRING aEntryPoint) |
|
100 { |
|
101 return S_OK; |
|
102 } |
|
103 |
|
104 // called by winrt on startup |
|
105 HRESULT |
|
106 FrameworkView::Run() |
|
107 { |
|
108 LogFunction(); |
|
109 |
|
110 // Initialize XPCOM, create mWidget and go! We get a |
|
111 // callback in MetroAppShell::Run, in which we kick |
|
112 // off normal browser execution / event dispatching. |
|
113 mMetroApp->Run(); |
|
114 |
|
115 // Gecko is completely shut down at this point. |
|
116 WinUtils::Log("Exiting FrameworkView::Run()"); |
|
117 |
|
118 WindowsDeleteString(sActivationURI); |
|
119 return S_OK; |
|
120 } |
|
121 |
|
122 HRESULT |
|
123 FrameworkView::ActivateView() |
|
124 { |
|
125 LogFunction(); |
|
126 |
|
127 UpdateWidgetSizeAndPosition(); |
|
128 |
|
129 nsIntRegion region(nsIntRect(0, 0, mWindowBounds.width, mWindowBounds.height)); |
|
130 mWidget->Paint(region); |
|
131 |
|
132 // Activate the window, this kills the splash screen |
|
133 mWindow->Activate(); |
|
134 |
|
135 ProcessLaunchArguments(); |
|
136 AddEventHandlers(); |
|
137 SetupContracts(); |
|
138 |
|
139 return S_OK; |
|
140 } |
|
141 |
|
142 HRESULT |
|
143 FrameworkView::SetWindow(ICoreWindow* aWindow) |
|
144 { |
|
145 LogFunction(); |
|
146 |
|
147 NS_ASSERTION(!mWindow, "Attempting to set a window on a view that already has a window!"); |
|
148 NS_ASSERTION(aWindow, "Attempting to set a null window on a view!"); |
|
149 |
|
150 mWindow = aWindow; |
|
151 UpdateLogicalDPI(); |
|
152 return S_OK; |
|
153 } |
|
154 |
|
155 //////////////////////////////////////////////////// |
|
156 // FrameworkView impl. |
|
157 |
|
158 void |
|
159 FrameworkView::AddEventHandlers() { |
|
160 NS_ASSERTION(mWindow, "SetWindow must be called before AddEventHandlers!"); |
|
161 NS_ASSERTION(mWidget, "SetWidget must be called before AddEventHAndlers!"); |
|
162 |
|
163 mMetroInput = Make<MetroInput>(mWidget.Get(), |
|
164 mWindow.Get()); |
|
165 |
|
166 mWindow->add_VisibilityChanged(Callback<__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CVisibilityChangedEventArgs>( |
|
167 this, &FrameworkView::OnWindowVisibilityChanged).Get(), &mWindowVisibilityChanged); |
|
168 mWindow->add_Activated(Callback<__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowActivatedEventArgs_t>( |
|
169 this, &FrameworkView::OnWindowActivated).Get(), &mWindowActivated); |
|
170 mWindow->add_SizeChanged(Callback<__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowSizeChangedEventArgs_t>( |
|
171 this, &FrameworkView::OnWindowSizeChanged).Get(), &mWindowSizeChanged); |
|
172 |
|
173 mWindow->add_AutomationProviderRequested(Callback<__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CAutomationProviderRequestedEventArgs_t>( |
|
174 this, &FrameworkView::OnAutomationProviderRequested).Get(), &mAutomationProviderRequested); |
|
175 |
|
176 HRESULT hr; |
|
177 ComPtr<ABI::Windows::Graphics::Display::IDisplayPropertiesStatics> dispProps; |
|
178 if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), dispProps.GetAddressOf()))) { |
|
179 hr = dispProps->add_LogicalDpiChanged(Callback<ABI::Windows::Graphics::Display::IDisplayPropertiesEventHandler, FrameworkView>( |
|
180 this, &FrameworkView::OnLogicalDpiChanged).Get(), &mDisplayPropertiesChanged); |
|
181 LogHRESULT(hr); |
|
182 } |
|
183 |
|
184 ComPtr<ABI::Windows::UI::ViewManagement::IInputPaneStatics> inputStatic; |
|
185 if (SUCCEEDED(hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_ViewManagement_InputPane).Get(), inputStatic.GetAddressOf()))) { |
|
186 ComPtr<ABI::Windows::UI::ViewManagement::IInputPane> inputPane; |
|
187 if (SUCCEEDED(inputStatic->GetForCurrentView(inputPane.GetAddressOf()))) { |
|
188 inputPane->add_Hiding(Callback<__FITypedEventHandler_2_Windows__CUI__CViewManagement__CInputPane_Windows__CUI__CViewManagement__CInputPaneVisibilityEventArgs_t>( |
|
189 this, &FrameworkView::OnSoftkeyboardHidden).Get(), &mSoftKeyboardHidden); |
|
190 inputPane->add_Showing(Callback<__FITypedEventHandler_2_Windows__CUI__CViewManagement__CInputPane_Windows__CUI__CViewManagement__CInputPaneVisibilityEventArgs_t>( |
|
191 this, &FrameworkView::OnSoftkeyboardShown).Get(), &mSoftKeyboardShown); |
|
192 } |
|
193 } |
|
194 } |
|
195 |
|
196 // Called by MetroApp |
|
197 void |
|
198 FrameworkView::Shutdown() |
|
199 { |
|
200 LogFunction(); |
|
201 mShuttingDown = true; |
|
202 |
|
203 if (mWindow && mWindowVisibilityChanged.value) { |
|
204 mWindow->remove_VisibilityChanged(mWindowVisibilityChanged); |
|
205 mWindow->remove_Activated(mWindowActivated); |
|
206 mWindow->remove_Closed(mWindowClosed); |
|
207 mWindow->remove_SizeChanged(mWindowSizeChanged); |
|
208 mWindow->remove_AutomationProviderRequested(mAutomationProviderRequested); |
|
209 } |
|
210 |
|
211 ComPtr<ABI::Windows::Graphics::Display::IDisplayPropertiesStatics> dispProps; |
|
212 if (mDisplayPropertiesChanged.value && |
|
213 SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), dispProps.GetAddressOf()))) { |
|
214 dispProps->remove_LogicalDpiChanged(mDisplayPropertiesChanged); |
|
215 } |
|
216 |
|
217 ComPtr<ABI::Windows::UI::ViewManagement::IInputPaneStatics> inputStatic; |
|
218 if (mSoftKeyboardHidden.value && |
|
219 SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_ViewManagement_InputPane).Get(), inputStatic.GetAddressOf()))) { |
|
220 ComPtr<ABI::Windows::UI::ViewManagement::IInputPane> inputPane; |
|
221 if (SUCCEEDED(inputStatic->GetForCurrentView(inputPane.GetAddressOf()))) { |
|
222 inputPane->remove_Hiding(mSoftKeyboardHidden); |
|
223 inputPane->remove_Showing(mSoftKeyboardShown); |
|
224 } |
|
225 } |
|
226 |
|
227 if (mAutomationProvider) { |
|
228 ComPtr<IUIABridge> provider; |
|
229 mAutomationProvider.As(&provider); |
|
230 if (provider) { |
|
231 provider->Disconnect(); |
|
232 } |
|
233 } |
|
234 mAutomationProvider = nullptr; |
|
235 |
|
236 mMetroInput = nullptr; |
|
237 delete sSettingsArray; |
|
238 sSettingsArray = nullptr; |
|
239 mWidget = nullptr; |
|
240 mMetroApp = nullptr; |
|
241 mWindow = nullptr; |
|
242 } |
|
243 |
|
244 void |
|
245 FrameworkView::SetCursor(CoreCursorType aCursorType, DWORD aCustomId) |
|
246 { |
|
247 if (mShuttingDown) { |
|
248 return; |
|
249 } |
|
250 NS_ASSERTION(mWindow, "SetWindow must be called before SetCursor!"); |
|
251 ComPtr<ABI::Windows::UI::Core::ICoreCursorFactory> factory; |
|
252 AssertHRESULT(GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Core_CoreCursor).Get(), factory.GetAddressOf())); |
|
253 ComPtr<ABI::Windows::UI::Core::ICoreCursor> cursor; |
|
254 AssertHRESULT(factory->CreateCursor(aCursorType, aCustomId, cursor.GetAddressOf())); |
|
255 mWindow->put_PointerCursor(cursor.Get()); |
|
256 } |
|
257 |
|
258 void |
|
259 FrameworkView::ClearCursor() |
|
260 { |
|
261 if (mShuttingDown) { |
|
262 return; |
|
263 } |
|
264 NS_ASSERTION(mWindow, "SetWindow must be called before ClearCursor!"); |
|
265 mWindow->put_PointerCursor(nullptr); |
|
266 } |
|
267 |
|
268 void |
|
269 FrameworkView::UpdateLogicalDPI() |
|
270 { |
|
271 ComPtr<ABI::Windows::Graphics::Display::IDisplayPropertiesStatics> dispProps; |
|
272 HRESULT hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), |
|
273 dispProps.GetAddressOf()); |
|
274 AssertHRESULT(hr); |
|
275 FLOAT value; |
|
276 AssertHRESULT(dispProps->get_LogicalDpi(&value)); |
|
277 SetDpi(value); |
|
278 } |
|
279 |
|
280 void |
|
281 FrameworkView::GetBounds(nsIntRect &aRect) |
|
282 { |
|
283 // May be called by compositor thread |
|
284 if (mShuttingDown) { |
|
285 return; |
|
286 } |
|
287 aRect = mWindowBounds; |
|
288 } |
|
289 |
|
290 void |
|
291 FrameworkView::UpdateWidgetSizeAndPosition() |
|
292 { |
|
293 if (mShuttingDown) |
|
294 return; |
|
295 |
|
296 NS_ASSERTION(mWindow, "SetWindow must be called before UpdateWidgetSizeAndPosition!"); |
|
297 NS_ASSERTION(mWidget, "SetWidget must be called before UpdateWidgetSizeAndPosition!"); |
|
298 |
|
299 UpdateBounds(); |
|
300 mWidget->Move(0, 0); |
|
301 mWidget->Resize(0, 0, mWindowBounds.width, mWindowBounds.height, true); |
|
302 mWidget->SizeModeChanged(); |
|
303 } |
|
304 |
|
305 bool |
|
306 FrameworkView::IsEnabled() const |
|
307 { |
|
308 return mWinActiveState; |
|
309 } |
|
310 |
|
311 bool |
|
312 FrameworkView::IsVisible() const |
|
313 { |
|
314 // we could check the wnd in MetroWidget for this, but |
|
315 // generally we don't let nsIWidget control visibility |
|
316 // or activation. |
|
317 return mWinVisible; |
|
318 } |
|
319 |
|
320 void FrameworkView::SetDpi(float aDpi) |
|
321 { |
|
322 if (aDpi != mDPI) { |
|
323 LogFunction(); |
|
324 |
|
325 mDPI = aDpi; |
|
326 |
|
327 // notify the widget that dpi has changed |
|
328 if (mWidget) { |
|
329 mWidget->ChangedDPI(); |
|
330 UpdateBounds(); |
|
331 } |
|
332 } |
|
333 } |
|
334 |
|
335 void |
|
336 FrameworkView::UpdateBounds() |
|
337 { |
|
338 if (!mWidget) |
|
339 return; |
|
340 |
|
341 RECT winRect; |
|
342 GetClientRect(mWidget->GetICoreWindowHWND(), &winRect); |
|
343 |
|
344 mWindowBounds = nsIntRect(winRect.left, |
|
345 winRect.top, |
|
346 winRect.right - winRect.left, |
|
347 winRect.bottom - winRect.top); |
|
348 } |
|
349 |
|
350 void |
|
351 FrameworkView::SetWidget(MetroWidget* aWidget) |
|
352 { |
|
353 NS_ASSERTION(!mWidget, "Attempting to set a widget for a view that already has a widget!"); |
|
354 NS_ASSERTION(aWidget, "Attempting to set a null widget for a view!"); |
|
355 LogFunction(); |
|
356 mWidget = aWidget; |
|
357 mWidget->FindMetroWindow(); |
|
358 UpdateBounds(); |
|
359 } |
|
360 |
|
361 //////////////////////////////////////////////////// |
|
362 // Event handlers |
|
363 |
|
364 void |
|
365 FrameworkView::SendActivationEvent() |
|
366 { |
|
367 if (mShuttingDown) { |
|
368 return; |
|
369 } |
|
370 NS_ASSERTION(mWindow, "SetWindow must be called before SendActivationEvent!"); |
|
371 mWidget->Activated(mWinActiveState); |
|
372 if (mWinActiveState) { |
|
373 UpdateWidgetSizeAndPosition(); |
|
374 } |
|
375 EnsureAutomationProviderCreated(); |
|
376 } |
|
377 |
|
378 HRESULT |
|
379 FrameworkView::OnWindowVisibilityChanged(ICoreWindow* aWindow, |
|
380 IVisibilityChangedEventArgs* aArgs) |
|
381 { |
|
382 // If we're visible, or we can't determine if we're visible, just store |
|
383 // that we are visible. |
|
384 boolean visible; |
|
385 mWinVisible = FAILED(aArgs->get_Visible(&visible)) || visible; |
|
386 return S_OK; |
|
387 } |
|
388 |
|
389 HRESULT |
|
390 FrameworkView::OnActivated(ICoreApplicationView* aApplicationView, |
|
391 IActivatedEventArgs* aArgs) |
|
392 { |
|
393 LogFunction(); |
|
394 |
|
395 if (mShuttingDown) { |
|
396 return S_OK; |
|
397 } |
|
398 |
|
399 aArgs->get_PreviousExecutionState(&sPreviousExecutionState); |
|
400 bool startup = sPreviousExecutionState == ApplicationExecutionState::ApplicationExecutionState_Terminated || |
|
401 sPreviousExecutionState == ApplicationExecutionState::ApplicationExecutionState_ClosedByUser || |
|
402 sPreviousExecutionState == ApplicationExecutionState::ApplicationExecutionState_NotRunning; |
|
403 ProcessActivationArgs(aArgs, startup); |
|
404 return S_OK; |
|
405 } |
|
406 |
|
407 HRESULT |
|
408 FrameworkView::OnSoftkeyboardHidden(IInputPane* aSender, |
|
409 IInputPaneVisibilityEventArgs* aArgs) |
|
410 { |
|
411 LogFunction(); |
|
412 sKeyboardIsVisible = false; |
|
413 memset(&sKeyboardRect, 0, sizeof(Rect)); |
|
414 MetroUtils::FireObserver("metro_softkeyboard_hidden"); |
|
415 aArgs->put_EnsuredFocusedElementInView(true); |
|
416 return S_OK; |
|
417 } |
|
418 |
|
419 HRESULT |
|
420 FrameworkView::OnSoftkeyboardShown(IInputPane* aSender, |
|
421 IInputPaneVisibilityEventArgs* aArgs) |
|
422 { |
|
423 LogFunction(); |
|
424 sKeyboardIsVisible = true; |
|
425 aSender->get_OccludedRect(&sKeyboardRect); |
|
426 MetroUtils::FireObserver("metro_softkeyboard_shown"); |
|
427 aArgs->put_EnsuredFocusedElementInView(true); |
|
428 return S_OK; |
|
429 } |
|
430 |
|
431 HRESULT |
|
432 FrameworkView::OnWindowSizeChanged(ICoreWindow* aSender, IWindowSizeChangedEventArgs* aArgs) |
|
433 { |
|
434 LogFunction(); |
|
435 UpdateWidgetSizeAndPosition(); |
|
436 return S_OK; |
|
437 } |
|
438 |
|
439 HRESULT |
|
440 FrameworkView::OnWindowActivated(ICoreWindow* aSender, IWindowActivatedEventArgs* aArgs) |
|
441 { |
|
442 LogFunction(); |
|
443 if (!mWidget) { |
|
444 return S_OK; |
|
445 } |
|
446 CoreWindowActivationState state; |
|
447 aArgs->get_WindowActivationState(&state); |
|
448 mWinActiveState = !(state == CoreWindowActivationState::CoreWindowActivationState_Deactivated); |
|
449 SendActivationEvent(); |
|
450 return S_OK; |
|
451 } |
|
452 |
|
453 HRESULT |
|
454 FrameworkView::OnLogicalDpiChanged(IInspectable* aSender) |
|
455 { |
|
456 LogFunction(); |
|
457 UpdateLogicalDPI(); |
|
458 if (mWidget) { |
|
459 mWidget->Invalidate(); |
|
460 } |
|
461 return S_OK; |
|
462 } |
|
463 |
|
464 bool |
|
465 FrameworkView::EnsureAutomationProviderCreated() |
|
466 { |
|
467 #ifdef ACCESSIBILITY |
|
468 if (!mWidget || mShuttingDown) |
|
469 return false; |
|
470 |
|
471 if (mAutomationProvider) { |
|
472 return true; |
|
473 } |
|
474 |
|
475 Accessible *rootAccessible = mWidget->GetRootAccessible(); |
|
476 if (rootAccessible) { |
|
477 IInspectable* inspectable; |
|
478 HRESULT hr; |
|
479 AssertRetHRESULT(hr = UIABridge_CreateInstance(&inspectable), hr); // Addref |
|
480 IUIABridge* bridge = nullptr; |
|
481 inspectable->QueryInterface(IID_IUIABridge, (void**)&bridge); // Addref |
|
482 if (bridge) { |
|
483 bridge->Init(this, mWindow.Get(), (ULONG)rootAccessible); |
|
484 mAutomationProvider = inspectable; |
|
485 inspectable->Release(); |
|
486 return true; |
|
487 } |
|
488 } |
|
489 #endif |
|
490 return false; |
|
491 } |
|
492 |
|
493 HRESULT |
|
494 FrameworkView::OnAutomationProviderRequested(ICoreWindow* aSender, |
|
495 IAutomationProviderRequestedEventArgs* aArgs) |
|
496 { |
|
497 LogFunction(); |
|
498 if (!EnsureAutomationProviderCreated()) |
|
499 return E_FAIL; |
|
500 HRESULT hr = aArgs->put_AutomationProvider(mAutomationProvider.Get()); |
|
501 if (FAILED(hr)) { |
|
502 WinUtils::Log("put failed? %X", hr); |
|
503 } |
|
504 return S_OK; |
|
505 } |
|
506 |
|
507 } } } |