Bug 1734067 [wpt PR 31108] - Update wpt metadata, a=testonly
[gecko.git] / widget / PuppetWidget.cpp
blobc2bdf1352281a3ed0ee7a19cfeff0c643832a9d5
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: sw=2 ts=8 et :
3 */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #include "base/basictypes.h"
10 #include "gfxPlatform.h"
11 #include "nsRefreshDriver.h"
12 #include "mozilla/dom/BrowserChild.h"
13 #include "mozilla/gfx/gfxVars.h"
14 #include "mozilla/Hal.h"
15 #include "mozilla/IMEStateManager.h"
16 #include "mozilla/layers/APZChild.h"
17 #include "mozilla/layers/WebRenderLayerManager.h"
18 #include "mozilla/Preferences.h"
19 #include "mozilla/PresShell.h"
20 #include "mozilla/SchedulerGroup.h"
21 #include "mozilla/StaticPrefs_browser.h"
22 #include "mozilla/StaticPrefs_gfx.h"
23 #include "mozilla/TextComposition.h"
24 #include "mozilla/TextEventDispatcher.h"
25 #include "mozilla/TextEvents.h"
26 #include "mozilla/Unused.h"
27 #include "PuppetWidget.h"
28 #include "nsContentUtils.h"
29 #include "nsIWidgetListener.h"
30 #include "imgIContainer.h"
31 #include "nsView.h"
32 #include "nsXPLookAndFeel.h"
33 #include "nsPrintfCString.h"
35 using namespace mozilla;
36 using namespace mozilla::dom;
37 using namespace mozilla::hal;
38 using namespace mozilla::gfx;
39 using namespace mozilla::layers;
40 using namespace mozilla::widget;
42 static void InvalidateRegion(nsIWidget* aWidget,
43 const LayoutDeviceIntRegion& aRegion) {
44 for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) {
45 aWidget->Invalidate(iter.Get());
49 /*static*/
50 already_AddRefed<nsIWidget> nsIWidget::CreatePuppetWidget(
51 BrowserChild* aBrowserChild) {
52 MOZ_ASSERT(!aBrowserChild || nsIWidget::UsePuppetWidgets(),
53 "PuppetWidgets not allowed in this configuration");
55 nsCOMPtr<nsIWidget> widget = new PuppetWidget(aBrowserChild);
56 return widget.forget();
59 namespace mozilla {
60 namespace widget {
62 static bool IsPopup(const nsWidgetInitData* aInitData) {
63 return aInitData && aInitData->mWindowType == eWindowType_popup;
66 static bool MightNeedIMEFocus(const nsWidgetInitData* aInitData) {
67 // In the puppet-widget world, popup widgets are just dummies and
68 // shouldn't try to mess with IME state.
69 #ifdef MOZ_CROSS_PROCESS_IME
70 return !IsPopup(aInitData);
71 #else
72 return false;
73 #endif
76 // Arbitrary, fungible.
77 const size_t PuppetWidget::kMaxDimension = 4000;
79 NS_IMPL_ISUPPORTS_INHERITED(PuppetWidget, nsBaseWidget,
80 TextEventDispatcherListener)
82 PuppetWidget::PuppetWidget(BrowserChild* aBrowserChild)
83 : mBrowserChild(aBrowserChild),
84 mMemoryPressureObserver(nullptr),
85 mDPI(-1),
86 mRounding(1),
87 mDefaultScale(-1),
88 mEnabled(false),
89 mVisible(false),
90 mNeedIMEStateInit(false),
91 mIgnoreCompositionEvents(false) {
92 // Setting 'Unknown' means "not yet cached".
93 mInputContext.mIMEState.mEnabled = IMEEnabled::Unknown;
96 PuppetWidget::~PuppetWidget() { Destroy(); }
98 void PuppetWidget::InfallibleCreate(nsIWidget* aParent,
99 nsNativeWidget aNativeParent,
100 const LayoutDeviceIntRect& aRect,
101 nsWidgetInitData* aInitData) {
102 MOZ_ASSERT(!aNativeParent, "got a non-Puppet native parent");
104 BaseCreate(nullptr, aInitData);
106 mBounds = aRect;
107 mEnabled = true;
108 mVisible = true;
110 mDrawTarget = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
111 IntSize(1, 1), SurfaceFormat::B8G8R8A8);
113 mNeedIMEStateInit = MightNeedIMEFocus(aInitData);
115 PuppetWidget* parent = static_cast<PuppetWidget*>(aParent);
116 if (parent) {
117 parent->SetChild(this);
118 mWindowRenderer = parent->GetWindowRenderer();
119 } else {
120 Resize(mBounds.X(), mBounds.Y(), mBounds.Width(), mBounds.Height(), false);
122 mMemoryPressureObserver = MemoryPressureObserver::Create(this);
125 nsresult PuppetWidget::Create(nsIWidget* aParent, nsNativeWidget aNativeParent,
126 const LayoutDeviceIntRect& aRect,
127 nsWidgetInitData* aInitData) {
128 InfallibleCreate(aParent, aNativeParent, aRect, aInitData);
129 return NS_OK;
132 void PuppetWidget::InitIMEState() {
133 MOZ_ASSERT(mBrowserChild);
134 if (mNeedIMEStateInit) {
135 mContentCache.Clear();
136 mBrowserChild->SendUpdateContentCache(mContentCache);
137 mIMENotificationRequestsOfParent = IMENotificationRequests();
138 mNeedIMEStateInit = false;
142 already_AddRefed<nsIWidget> PuppetWidget::CreateChild(
143 const LayoutDeviceIntRect& aRect, nsWidgetInitData* aInitData,
144 bool aForceUseIWidgetParent) {
145 bool isPopup = IsPopup(aInitData);
146 nsCOMPtr<nsIWidget> widget = nsIWidget::CreatePuppetWidget(mBrowserChild);
147 return ((widget && NS_SUCCEEDED(widget->Create(isPopup ? nullptr : this,
148 nullptr, aRect, aInitData)))
149 ? widget.forget()
150 : nullptr);
153 void PuppetWidget::Destroy() {
154 if (mOnDestroyCalled) {
155 return;
157 mOnDestroyCalled = true;
159 Base::OnDestroy();
160 Base::Destroy();
161 if (mMemoryPressureObserver) {
162 mMemoryPressureObserver->Unregister();
163 mMemoryPressureObserver = nullptr;
165 mChild = nullptr;
166 if (mWindowRenderer) {
167 mWindowRenderer->Destroy();
169 mWindowRenderer = nullptr;
170 mBrowserChild = nullptr;
173 void PuppetWidget::Show(bool aState) {
174 NS_ASSERTION(mEnabled,
175 "does it make sense to Show()/Hide() a disabled widget?");
177 bool wasVisible = mVisible;
178 mVisible = aState;
180 if (mChild) {
181 mChild->mVisible = aState;
184 if (!wasVisible && mVisible) {
185 // The previously attached widget listener is handy if
186 // we're transitioning from page to page without dropping
187 // layers (since we'll continue to show the old layers
188 // associated with that old widget listener). If the
189 // PuppetWidget was hidden, those layers are dropped,
190 // so the previously attached widget listener is really
191 // of no use anymore (and is actually actively harmful - see
192 // bug 1323586).
193 mPreviouslyAttachedWidgetListener = nullptr;
194 Resize(mBounds.Width(), mBounds.Height(), false);
195 Invalidate(mBounds);
199 void PuppetWidget::Resize(double aWidth, double aHeight, bool aRepaint) {
200 LayoutDeviceIntRect oldBounds = mBounds;
201 mBounds.SizeTo(
202 LayoutDeviceIntSize(NSToIntRound(aWidth), NSToIntRound(aHeight)));
204 if (mChild) {
205 mChild->Resize(aWidth, aHeight, aRepaint);
206 return;
209 // XXX: roc says that |aRepaint| dictates whether or not to
210 // invalidate the expanded area
211 if (oldBounds.Size() < mBounds.Size() && aRepaint) {
212 LayoutDeviceIntRegion dirty(mBounds);
213 dirty.Sub(dirty, oldBounds);
214 InvalidateRegion(this, dirty);
217 // call WindowResized() on both the current listener, and possibly
218 // also the previous one if we're in a state where we're drawing that one
219 // because the current one is paint suppressed
220 if (!oldBounds.IsEqualEdges(mBounds) && mAttachedWidgetListener) {
221 if (GetCurrentWidgetListener() &&
222 GetCurrentWidgetListener() != mAttachedWidgetListener) {
223 GetCurrentWidgetListener()->WindowResized(this, mBounds.Width(),
224 mBounds.Height());
226 mAttachedWidgetListener->WindowResized(this, mBounds.Width(),
227 mBounds.Height());
231 nsresult PuppetWidget::ConfigureChildren(
232 const nsTArray<Configuration>& aConfigurations) {
233 for (uint32_t i = 0; i < aConfigurations.Length(); ++i) {
234 const Configuration& configuration = aConfigurations[i];
235 PuppetWidget* w = static_cast<PuppetWidget*>(configuration.mChild.get());
236 NS_ASSERTION(w->GetParent() == this, "Configured widget is not a child");
237 w->SetWindowClipRegion(configuration.mClipRegion, true);
238 LayoutDeviceIntRect bounds = w->GetBounds();
239 if (bounds.Size() != configuration.mBounds.Size()) {
240 w->Resize(configuration.mBounds.X(), configuration.mBounds.Y(),
241 configuration.mBounds.Width(), configuration.mBounds.Height(),
242 true);
243 } else if (bounds.TopLeft() != configuration.mBounds.TopLeft()) {
244 w->Move(configuration.mBounds.X(), configuration.mBounds.Y());
246 w->SetWindowClipRegion(configuration.mClipRegion, false);
248 return NS_OK;
251 void PuppetWidget::SetFocus(Raise aRaise, CallerType aCallerType) {
252 if (aRaise == Raise::Yes && mBrowserChild) {
253 mBrowserChild->SendRequestFocus(true, aCallerType);
257 void PuppetWidget::Invalidate(const LayoutDeviceIntRect& aRect) {
258 #ifdef DEBUG
259 debug_DumpInvalidate(stderr, this, &aRect, "PuppetWidget", 0);
260 #endif
262 if (mChild) {
263 mChild->Invalidate(aRect);
264 return;
267 if (mBrowserChild && !aRect.IsEmpty() && !mWidgetPaintTask.IsPending()) {
268 mWidgetPaintTask = new WidgetPaintTask(this);
269 nsCOMPtr<nsIRunnable> event(mWidgetPaintTask.get());
270 SchedulerGroup::Dispatch(TaskCategory::Other, event.forget());
274 mozilla::LayoutDeviceToLayoutDeviceMatrix4x4
275 PuppetWidget::WidgetToTopLevelWidgetTransform() {
276 if (!GetOwningBrowserChild()) {
277 NS_WARNING("PuppetWidget without Tab does not have transform information.");
278 return mozilla::LayoutDeviceToLayoutDeviceMatrix4x4();
280 return GetOwningBrowserChild()->GetChildToParentConversionMatrix();
283 void PuppetWidget::InitEvent(WidgetGUIEvent& aEvent,
284 LayoutDeviceIntPoint* aPoint) {
285 if (nullptr == aPoint) {
286 aEvent.mRefPoint = LayoutDeviceIntPoint(0, 0);
287 } else {
288 // use the point override if provided
289 aEvent.mRefPoint = *aPoint;
291 aEvent.mTime = PR_Now() / 1000;
294 nsresult PuppetWidget::DispatchEvent(WidgetGUIEvent* aEvent,
295 nsEventStatus& aStatus) {
296 #ifdef DEBUG
297 debug_DumpEvent(stdout, aEvent->mWidget, aEvent, "PuppetWidget", 0);
298 #endif
300 MOZ_ASSERT(!mChild || mChild->mWindowType == eWindowType_popup,
301 "Unexpected event dispatch!");
303 MOZ_ASSERT(!aEvent->AsKeyboardEvent() ||
304 aEvent->mFlags.mIsSynthesizedForTests ||
305 aEvent->AsKeyboardEvent()->AreAllEditCommandsInitialized(),
306 "Non-sysnthesized keyboard events should have edit commands for "
307 "all types "
308 "before dispatched");
310 if (aEvent->mClass == eCompositionEventClass) {
311 // If we've already requested to commit/cancel the latest composition,
312 // TextComposition for the old composition has been destroyed. Then,
313 // the DOM tree needs to listen to next eCompositionStart and its
314 // following events. So, until we meet new eCompositionStart, let's
315 // discard all unnecessary composition events here.
316 if (mIgnoreCompositionEvents) {
317 if (aEvent->mMessage != eCompositionStart) {
318 aStatus = nsEventStatus_eIgnore;
319 return NS_OK;
321 // Now, we receive new eCompositionStart. Let's restart to handle
322 // composition in this process.
323 mIgnoreCompositionEvents = false;
325 // Store the latest native IME context of parent process's widget or
326 // TextEventDispatcher if it's in this process.
327 WidgetCompositionEvent* compositionEvent = aEvent->AsCompositionEvent();
328 #ifdef DEBUG
329 if (mNativeIMEContext.IsValid() &&
330 mNativeIMEContext != compositionEvent->mNativeIMEContext) {
331 RefPtr<TextComposition> composition =
332 IMEStateManager::GetTextCompositionFor(this);
333 MOZ_ASSERT(
334 !composition,
335 "When there is composition caused by old native IME context, "
336 "composition events caused by different native IME context are not "
337 "allowed");
339 #endif // #ifdef DEBUG
340 mNativeIMEContext = compositionEvent->mNativeIMEContext;
341 mContentCache.OnCompositionEvent(*compositionEvent);
344 // If the event is a composition event or a keyboard event, it should be
345 // dispatched with TextEventDispatcher if we could do that with current
346 // design. However, we cannot do that without big changes and the behavior
347 // is not so complicated for now. Therefore, we should just notify it
348 // of dispatching events and TextEventDispatcher should emulate the state
349 // with events here.
350 if (aEvent->mClass == eCompositionEventClass ||
351 aEvent->mClass == eKeyboardEventClass) {
352 TextEventDispatcher* dispatcher = GetTextEventDispatcher();
353 // However, if the event is being dispatched by the text event dispatcher
354 // or, there is native text event dispatcher listener, that means that
355 // native text input event handler is in this process like on Android,
356 // and the event is not synthesized for tests, the event is coming from
357 // the TextEventDispatcher. In these cases, we shouldn't notify
358 // TextEventDispatcher of dispatching the event.
359 if (!dispatcher->IsDispatchingEvent() &&
360 !(mNativeTextEventDispatcherListener &&
361 !aEvent->mFlags.mIsSynthesizedForTests)) {
362 DebugOnly<nsresult> rv =
363 dispatcher->BeginInputTransactionFor(aEvent, this);
364 NS_WARNING_ASSERTION(
365 NS_SUCCEEDED(rv),
366 "The text event dispatcher should always succeed to start input "
367 "transaction for the event");
371 aStatus = nsEventStatus_eIgnore;
373 if (GetCurrentWidgetListener()) {
374 aStatus =
375 GetCurrentWidgetListener()->HandleEvent(aEvent, mUseAttachedEvents);
378 return NS_OK;
381 nsIWidget::ContentAndAPZEventStatus PuppetWidget::DispatchInputEvent(
382 WidgetInputEvent* aEvent) {
383 ContentAndAPZEventStatus status;
384 if (!AsyncPanZoomEnabled()) {
385 DispatchEvent(aEvent, status.mContentStatus);
386 return status;
389 if (!mBrowserChild) {
390 return status;
393 switch (aEvent->mClass) {
394 case eWheelEventClass:
395 Unused << mBrowserChild->SendDispatchWheelEvent(*aEvent->AsWheelEvent());
396 break;
397 case eMouseEventClass:
398 Unused << mBrowserChild->SendDispatchMouseEvent(*aEvent->AsMouseEvent());
399 break;
400 case eKeyboardEventClass:
401 Unused << mBrowserChild->SendDispatchKeyboardEvent(
402 *aEvent->AsKeyboardEvent());
403 break;
404 case eTouchEventClass:
405 Unused << mBrowserChild->SendDispatchTouchEvent(*aEvent->AsTouchEvent());
406 break;
407 default:
408 MOZ_ASSERT_UNREACHABLE("unsupported event type");
411 return status;
414 nsresult PuppetWidget::SynthesizeNativeKeyEvent(
415 int32_t aNativeKeyboardLayout, int32_t aNativeKeyCode,
416 uint32_t aModifierFlags, const nsAString& aCharacters,
417 const nsAString& aUnmodifiedCharacters, nsIObserver* aObserver) {
418 AutoObserverNotifier notifier(aObserver, "keyevent");
419 if (!mBrowserChild) {
420 return NS_ERROR_FAILURE;
422 mBrowserChild->SendSynthesizeNativeKeyEvent(
423 aNativeKeyboardLayout, aNativeKeyCode, aModifierFlags,
424 nsString(aCharacters), nsString(aUnmodifiedCharacters),
425 notifier.SaveObserver());
426 return NS_OK;
429 nsresult PuppetWidget::SynthesizeNativeMouseEvent(
430 mozilla::LayoutDeviceIntPoint aPoint, NativeMouseMessage aNativeMessage,
431 MouseButton aButton, nsIWidget::Modifiers aModifierFlags,
432 nsIObserver* aObserver) {
433 AutoObserverNotifier notifier(aObserver, "mouseevent");
434 if (!mBrowserChild) {
435 return NS_ERROR_FAILURE;
437 mBrowserChild->SendSynthesizeNativeMouseEvent(
438 aPoint, static_cast<uint32_t>(aNativeMessage),
439 static_cast<int16_t>(aButton), static_cast<uint32_t>(aModifierFlags),
440 notifier.SaveObserver());
441 return NS_OK;
444 nsresult PuppetWidget::SynthesizeNativeMouseMove(
445 mozilla::LayoutDeviceIntPoint aPoint, nsIObserver* aObserver) {
446 AutoObserverNotifier notifier(aObserver, "mousemove");
447 if (!mBrowserChild) {
448 return NS_ERROR_FAILURE;
450 mBrowserChild->SendSynthesizeNativeMouseMove(aPoint, notifier.SaveObserver());
451 return NS_OK;
454 nsresult PuppetWidget::SynthesizeNativeMouseScrollEvent(
455 mozilla::LayoutDeviceIntPoint aPoint, uint32_t aNativeMessage,
456 double aDeltaX, double aDeltaY, double aDeltaZ, uint32_t aModifierFlags,
457 uint32_t aAdditionalFlags, nsIObserver* aObserver) {
458 AutoObserverNotifier notifier(aObserver, "mousescrollevent");
459 if (!mBrowserChild) {
460 return NS_ERROR_FAILURE;
462 mBrowserChild->SendSynthesizeNativeMouseScrollEvent(
463 aPoint, aNativeMessage, aDeltaX, aDeltaY, aDeltaZ, aModifierFlags,
464 aAdditionalFlags, notifier.SaveObserver());
465 return NS_OK;
468 nsresult PuppetWidget::SynthesizeNativeTouchPoint(
469 uint32_t aPointerId, TouchPointerState aPointerState,
470 LayoutDeviceIntPoint aPoint, double aPointerPressure,
471 uint32_t aPointerOrientation, nsIObserver* aObserver) {
472 AutoObserverNotifier notifier(aObserver, "touchpoint");
473 if (!mBrowserChild) {
474 return NS_ERROR_FAILURE;
476 mBrowserChild->SendSynthesizeNativeTouchPoint(
477 aPointerId, aPointerState, aPoint, aPointerPressure, aPointerOrientation,
478 notifier.SaveObserver());
479 return NS_OK;
482 nsresult PuppetWidget::SynthesizeNativeTouchPadPinch(
483 TouchpadGesturePhase aEventPhase, float aScale, LayoutDeviceIntPoint aPoint,
484 int32_t aModifierFlags) {
485 if (!mBrowserChild) {
486 return NS_ERROR_FAILURE;
488 mBrowserChild->SendSynthesizeNativeTouchPadPinch(aEventPhase, aScale, aPoint,
489 aModifierFlags);
490 return NS_OK;
493 nsresult PuppetWidget::SynthesizeNativeTouchTap(LayoutDeviceIntPoint aPoint,
494 bool aLongTap,
495 nsIObserver* aObserver) {
496 AutoObserverNotifier notifier(aObserver, "touchtap");
497 if (!mBrowserChild) {
498 return NS_ERROR_FAILURE;
500 mBrowserChild->SendSynthesizeNativeTouchTap(aPoint, aLongTap,
501 notifier.SaveObserver());
502 return NS_OK;
505 nsresult PuppetWidget::ClearNativeTouchSequence(nsIObserver* aObserver) {
506 AutoObserverNotifier notifier(aObserver, "cleartouch");
507 if (!mBrowserChild) {
508 return NS_ERROR_FAILURE;
510 mBrowserChild->SendClearNativeTouchSequence(notifier.SaveObserver());
511 return NS_OK;
514 nsresult PuppetWidget::SynthesizeNativePenInput(
515 uint32_t aPointerId, TouchPointerState aPointerState,
516 LayoutDeviceIntPoint aPoint, double aPressure, uint32_t aRotation,
517 int32_t aTiltX, int32_t aTiltY, int32_t aButton, nsIObserver* aObserver) {
518 AutoObserverNotifier notifier(aObserver, "peninput");
519 if (!mBrowserChild) {
520 return NS_ERROR_FAILURE;
522 mBrowserChild->SendSynthesizeNativePenInput(
523 aPointerId, aPointerState, aPoint, aPressure, aRotation, aTiltX, aTiltY,
524 aButton, notifier.SaveObserver());
525 return NS_OK;
528 nsresult PuppetWidget::SynthesizeNativeTouchpadDoubleTap(
529 LayoutDeviceIntPoint aPoint, uint32_t aModifierFlags) {
530 if (!mBrowserChild) {
531 return NS_ERROR_FAILURE;
533 mBrowserChild->SendSynthesizeNativeTouchpadDoubleTap(aPoint, aModifierFlags);
534 return NS_OK;
537 nsresult PuppetWidget::SynthesizeNativeTouchpadPan(
538 TouchpadGesturePhase aEventPhase, LayoutDeviceIntPoint aPoint,
539 double aDeltaX, double aDeltaY, int32_t aModifierFlags) {
540 if (!mBrowserChild) {
541 return NS_ERROR_FAILURE;
543 mBrowserChild->SendSynthesizeNativeTouchpadPan(aEventPhase, aPoint, aDeltaX,
544 aDeltaY, aModifierFlags);
545 return NS_OK;
548 void PuppetWidget::LockNativePointer() {
549 if (!mBrowserChild) {
550 return;
552 mBrowserChild->SendLockNativePointer();
555 void PuppetWidget::UnlockNativePointer() {
556 if (!mBrowserChild) {
557 return;
559 mBrowserChild->SendUnlockNativePointer();
562 void PuppetWidget::SetConfirmedTargetAPZC(
563 uint64_t aInputBlockId,
564 const nsTArray<ScrollableLayerGuid>& aTargets) const {
565 if (mBrowserChild) {
566 mBrowserChild->SetTargetAPZC(aInputBlockId, aTargets);
570 void PuppetWidget::UpdateZoomConstraints(
571 const uint32_t& aPresShellId, const ScrollableLayerGuid::ViewID& aViewId,
572 const Maybe<ZoomConstraints>& aConstraints) {
573 if (mBrowserChild) {
574 mBrowserChild->DoUpdateZoomConstraints(aPresShellId, aViewId, aConstraints);
578 bool PuppetWidget::AsyncPanZoomEnabled() const {
579 return mBrowserChild && mBrowserChild->AsyncPanZoomEnabled();
582 bool PuppetWidget::GetEditCommands(NativeKeyBindingsType aType,
583 const WidgetKeyboardEvent& aEvent,
584 nsTArray<CommandInt>& aCommands) {
585 MOZ_ASSERT(!aEvent.mFlags.mIsSynthesizedForTests);
586 // Validate the arguments.
587 if (NS_WARN_IF(!nsIWidget::GetEditCommands(aType, aEvent, aCommands))) {
588 return false;
590 if (NS_WARN_IF(!mBrowserChild)) {
591 return false;
593 mBrowserChild->RequestEditCommands(aType, aEvent, aCommands);
594 return true;
597 WindowRenderer* PuppetWidget::GetWindowRenderer() {
598 if (!mWindowRenderer) {
599 if (XRE_IsParentProcess()) {
600 // On the parent process there is no CompositorBridgeChild which confuses
601 // some layers code, so we use basic layers instead. Note that we create
602 mWindowRenderer = new FallbackRenderer;
603 return mWindowRenderer;
606 // If we know for sure that the parent side of this BrowserChild is not
607 // connected to the compositor, we don't want to use a "remote" layer
608 // manager like WebRender or Client. Instead we use a Basic one which
609 // can do drawing in this process.
610 MOZ_ASSERT(!mBrowserChild ||
611 mBrowserChild->IsLayersConnected() != Some(true));
612 mWindowRenderer = CreateBasicLayerManager();
615 return mWindowRenderer;
618 bool PuppetWidget::CreateRemoteLayerManager(
619 const std::function<bool(WebRenderLayerManager*)>& aInitializeFunc) {
620 RefPtr<WebRenderLayerManager> lm = new WebRenderLayerManager(this);
621 MOZ_ASSERT(mBrowserChild);
623 if (!aInitializeFunc(lm)) {
624 return false;
627 // Force the old LM to self destruct, otherwise if the reference dangles we
628 // could fail to revoke the most recent transaction. We only want to replace
629 // it if we successfully create its successor because a partially initialized
630 // layer manager is worse than a fully initialized but shutdown layer manager.
631 DestroyLayerManager();
632 mWindowRenderer = std::move(lm);
633 return true;
636 nsresult PuppetWidget::RequestIMEToCommitComposition(bool aCancel) {
637 if (!mBrowserChild) {
638 return NS_ERROR_FAILURE;
641 MOZ_ASSERT(!Destroyed());
643 // There must not be composition which is caused by the PuppetWidget instance.
644 if (NS_WARN_IF(!mNativeIMEContext.IsValid())) {
645 return NS_OK;
648 // We've already requested to commit/cancel composition.
649 if (NS_WARN_IF(mIgnoreCompositionEvents)) {
650 #ifdef DEBUG
651 RefPtr<TextComposition> composition =
652 IMEStateManager::GetTextCompositionFor(this);
653 MOZ_ASSERT(!composition);
654 #endif // #ifdef DEBUG
655 return NS_OK;
658 RefPtr<TextComposition> composition =
659 IMEStateManager::GetTextCompositionFor(this);
660 // This method shouldn't be called when there is no text composition instance.
661 if (NS_WARN_IF(!composition)) {
662 return NS_OK;
665 MOZ_DIAGNOSTIC_ASSERT(
666 composition->IsRequestingCommitOrCancelComposition(),
667 "Requesting commit or cancel composition should be requested via "
668 "TextComposition instance");
670 bool isCommitted = false;
671 nsAutoString committedString;
672 if (NS_WARN_IF(!mBrowserChild->SendRequestIMEToCommitComposition(
673 aCancel, &isCommitted, &committedString))) {
674 return NS_ERROR_FAILURE;
677 // If the composition wasn't committed synchronously, we need to wait async
678 // composition events for destroying the TextComposition instance.
679 if (!isCommitted) {
680 return NS_OK;
683 // Dispatch eCompositionCommit event.
684 WidgetCompositionEvent compositionCommitEvent(true, eCompositionCommit, this);
685 InitEvent(compositionCommitEvent, nullptr);
686 compositionCommitEvent.mData = committedString;
687 nsEventStatus status = nsEventStatus_eIgnore;
688 DispatchEvent(&compositionCommitEvent, status);
690 #ifdef DEBUG
691 RefPtr<TextComposition> currentComposition =
692 IMEStateManager::GetTextCompositionFor(this);
693 MOZ_ASSERT(!currentComposition);
694 #endif // #ifdef DEBUG
696 // Ignore the following composition events until we receive new
697 // eCompositionStart event.
698 mIgnoreCompositionEvents = true;
700 Unused << mBrowserChild->SendOnEventNeedingAckHandled(
701 eCompositionCommitRequestHandled);
703 // NOTE: PuppetWidget might be destroyed already.
704 return NS_OK;
707 // When this widget caches input context and currently managed by
708 // IMEStateManager, the cache is valid.
709 bool PuppetWidget::HaveValidInputContextCache() const {
710 return (mInputContext.mIMEState.mEnabled != IMEEnabled::Unknown &&
711 IMEStateManager::GetWidgetForActiveInputContext() == this);
714 nsRefreshDriver* PuppetWidget::GetTopLevelRefreshDriver() const {
715 if (!mBrowserChild) {
716 return nullptr;
719 if (PresShell* presShell = mBrowserChild->GetTopLevelPresShell()) {
720 return presShell->GetRefreshDriver();
723 return nullptr;
726 void PuppetWidget::SetInputContext(const InputContext& aContext,
727 const InputContextAction& aAction) {
728 mInputContext = aContext;
729 // Any widget instances cannot cache IME open state because IME open state
730 // can be changed by user but native IME may not notify us of changing the
731 // open state on some platforms.
732 mInputContext.mIMEState.mOpen = IMEState::OPEN_STATE_NOT_SUPPORTED;
733 if (!mBrowserChild) {
734 return;
736 mBrowserChild->SendSetInputContext(aContext, aAction);
739 InputContext PuppetWidget::GetInputContext() {
740 // XXX Currently, we don't support retrieving IME open state from child
741 // process.
743 // If the cache of input context is valid, we can avoid to use synchronous
744 // IPC.
745 if (HaveValidInputContextCache()) {
746 return mInputContext;
749 NS_WARNING("PuppetWidget::GetInputContext() needs to retrieve it with IPC");
751 // Don't cache InputContext here because this process isn't managing IME
752 // state of the chrome widget. So, we cannot modify mInputContext when
753 // chrome widget is set to new context.
754 InputContext context;
755 if (mBrowserChild) {
756 mBrowserChild->SendGetInputContext(&context.mIMEState);
758 return context;
761 NativeIMEContext PuppetWidget::GetNativeIMEContext() {
762 return mNativeIMEContext;
765 nsresult PuppetWidget::NotifyIMEOfFocusChange(
766 const IMENotification& aIMENotification) {
767 MOZ_ASSERT(IMEStateManager::CanSendNotificationToWidget());
769 if (!mBrowserChild) {
770 return NS_ERROR_FAILURE;
773 bool gotFocus = aIMENotification.mMessage == NOTIFY_IME_OF_FOCUS;
774 if (gotFocus) {
775 // When IME gets focus, we should initialize all information of the
776 // content.
777 if (NS_WARN_IF(!mContentCache.CacheAll(this, &aIMENotification))) {
778 return NS_ERROR_FAILURE;
780 } else {
781 // When IME loses focus, we don't need to store anything.
782 mContentCache.Clear();
785 mIMENotificationRequestsOfParent =
786 IMENotificationRequests(IMENotificationRequests::NOTIFY_ALL);
787 RefPtr<PuppetWidget> self = this;
788 mBrowserChild->SendNotifyIMEFocus(mContentCache, aIMENotification)
789 ->Then(
790 GetMainThreadSerialEventTarget(), __func__,
791 [self](IMENotificationRequests&& aRequests) {
792 self->mIMENotificationRequestsOfParent = aRequests;
793 if (TextEventDispatcher* dispatcher =
794 self->GetTextEventDispatcher()) {
795 dispatcher->OnWidgetChangeIMENotificationRequests(self);
798 [self](mozilla::ipc::ResponseRejectReason&& aReason) {
799 NS_WARNING("SendNotifyIMEFocus got rejected.");
802 return NS_OK;
805 nsresult PuppetWidget::NotifyIMEOfCompositionUpdate(
806 const IMENotification& aIMENotification) {
807 MOZ_ASSERT(IMEStateManager::CanSendNotificationToWidget());
809 if (NS_WARN_IF(!mBrowserChild)) {
810 return NS_ERROR_FAILURE;
813 if (NS_WARN_IF(!mContentCache.CacheSelection(this, &aIMENotification))) {
814 return NS_ERROR_FAILURE;
816 mBrowserChild->SendNotifyIMECompositionUpdate(mContentCache,
817 aIMENotification);
818 return NS_OK;
821 nsresult PuppetWidget::NotifyIMEOfTextChange(
822 const IMENotification& aIMENotification) {
823 MOZ_ASSERT(IMEStateManager::CanSendNotificationToWidget());
824 MOZ_ASSERT(aIMENotification.mMessage == NOTIFY_IME_OF_TEXT_CHANGE,
825 "Passed wrong notification");
827 if (!mBrowserChild) {
828 return NS_ERROR_FAILURE;
831 // FYI: text change notification is the first notification after
832 // a user operation changes the content. So, we need to modify
833 // the cache as far as possible here.
835 if (NS_WARN_IF(!mContentCache.CacheText(this, &aIMENotification))) {
836 return NS_ERROR_FAILURE;
839 // BrowserParent doesn't this this to cache. we don't send the notification
840 // if parent process doesn't request NOTIFY_TEXT_CHANGE.
841 if (mIMENotificationRequestsOfParent.WantTextChange()) {
842 mBrowserChild->SendNotifyIMETextChange(mContentCache, aIMENotification);
843 } else {
844 mBrowserChild->SendUpdateContentCache(mContentCache);
846 return NS_OK;
849 nsresult PuppetWidget::NotifyIMEOfSelectionChange(
850 const IMENotification& aIMENotification) {
851 MOZ_ASSERT(IMEStateManager::CanSendNotificationToWidget());
852 MOZ_ASSERT(aIMENotification.mMessage == NOTIFY_IME_OF_SELECTION_CHANGE,
853 "Passed wrong notification");
854 if (!mBrowserChild) {
855 return NS_ERROR_FAILURE;
858 // Note that selection change must be notified after text change if it occurs.
859 // Therefore, we don't need to query text content again here.
860 mContentCache.SetSelection(
861 this, aIMENotification.mSelectionChangeData.mOffset,
862 aIMENotification.mSelectionChangeData.Length(),
863 aIMENotification.mSelectionChangeData.mReversed,
864 aIMENotification.mSelectionChangeData.GetWritingMode());
866 mBrowserChild->SendNotifyIMESelection(mContentCache, aIMENotification);
868 return NS_OK;
871 nsresult PuppetWidget::NotifyIMEOfMouseButtonEvent(
872 const IMENotification& aIMENotification) {
873 MOZ_ASSERT(IMEStateManager::CanSendNotificationToWidget());
874 if (!mBrowserChild) {
875 return NS_ERROR_FAILURE;
878 bool consumedByIME = false;
879 if (!mBrowserChild->SendNotifyIMEMouseButtonEvent(aIMENotification,
880 &consumedByIME)) {
881 return NS_ERROR_FAILURE;
884 return consumedByIME ? NS_SUCCESS_EVENT_CONSUMED : NS_OK;
887 nsresult PuppetWidget::NotifyIMEOfPositionChange(
888 const IMENotification& aIMENotification) {
889 MOZ_ASSERT(IMEStateManager::CanSendNotificationToWidget());
890 if (NS_WARN_IF(!mBrowserChild)) {
891 return NS_ERROR_FAILURE;
894 if (NS_WARN_IF(!mContentCache.CacheEditorRect(this, &aIMENotification))) {
895 return NS_ERROR_FAILURE;
897 if (NS_WARN_IF(!mContentCache.CacheSelection(this, &aIMENotification))) {
898 return NS_ERROR_FAILURE;
900 if (mIMENotificationRequestsOfParent.WantPositionChanged()) {
901 mBrowserChild->SendNotifyIMEPositionChange(mContentCache, aIMENotification);
902 } else {
903 mBrowserChild->SendUpdateContentCache(mContentCache);
905 return NS_OK;
908 struct CursorSurface {
909 UniquePtr<char[]> mData;
910 IntSize mSize;
913 void PuppetWidget::SetCursor(const Cursor& aCursor) {
914 if (!mBrowserChild) {
915 return;
918 const bool force = mUpdateCursor;
919 if (!force && mCursor == aCursor) {
920 return;
923 bool hasCustomCursor = false;
924 UniquePtr<char[]> customCursorData;
925 size_t length = 0;
926 IntSize customCursorSize;
927 int32_t stride = 0;
928 auto format = SurfaceFormat::B8G8R8A8;
929 ImageResolution resolution = aCursor.mResolution;
930 if (aCursor.IsCustom()) {
931 int32_t width = 0, height = 0;
932 aCursor.mContainer->GetWidth(&width);
933 aCursor.mContainer->GetHeight(&height);
934 const int32_t flags =
935 imgIContainer::FLAG_SYNC_DECODE | imgIContainer::FLAG_ASYNC_NOTIFY;
936 RefPtr<SourceSurface> surface;
937 if (width && height &&
938 aCursor.mContainer->GetType() == imgIContainer::TYPE_VECTOR) {
939 // For vector images, scale to device pixels.
940 resolution.ScaleBy(GetDefaultScale().scale);
941 resolution.ApplyInverseTo(width, height);
942 surface = aCursor.mContainer->GetFrameAtSize(
943 {width, height}, imgIContainer::FRAME_CURRENT, flags);
944 } else {
945 // NOTE(emilio): We get the frame at the full size, ignoring resolution,
946 // because we're going to rasterize it, and we'd effectively lose the
947 // extra pixels if we rasterized to CustomCursorSize.
948 surface =
949 aCursor.mContainer->GetFrame(imgIContainer::FRAME_CURRENT, flags);
951 if (surface) {
952 if (RefPtr<DataSourceSurface> dataSurface = surface->GetDataSurface()) {
953 hasCustomCursor = true;
954 customCursorData = nsContentUtils::GetSurfaceData(
955 WrapNotNull(dataSurface), &length, &stride);
956 customCursorSize = dataSurface->GetSize();
957 format = dataSurface->GetFormat();
962 nsDependentCString cursorData(customCursorData ? customCursorData.get() : "",
963 length);
964 if (!mBrowserChild->SendSetCursor(
965 aCursor.mDefaultCursor, hasCustomCursor, cursorData,
966 customCursorSize.width, customCursorSize.height, resolution.mX,
967 resolution.mY, stride, format, aCursor.mHotspotX, aCursor.mHotspotY,
968 force)) {
969 return;
971 mCursor = aCursor;
974 void PuppetWidget::SetChild(PuppetWidget* aChild) {
975 MOZ_ASSERT(this != aChild, "can't parent a widget to itself");
976 MOZ_ASSERT(!aChild->mChild,
977 "fake widget 'hierarchy' only expected to have one level");
979 mChild = aChild;
982 NS_IMETHODIMP
983 PuppetWidget::WidgetPaintTask::Run() {
984 if (mWidget) {
985 mWidget->Paint();
987 return NS_OK;
990 void PuppetWidget::Paint() {
991 if (!GetCurrentWidgetListener()) return;
993 mWidgetPaintTask.Revoke();
995 RefPtr<PuppetWidget> strongThis(this);
997 GetCurrentWidgetListener()->WillPaintWindow(this);
999 if (GetCurrentWidgetListener()) {
1000 GetCurrentWidgetListener()->DidPaintWindow();
1004 void PuppetWidget::PaintNowIfNeeded() {
1005 if (IsVisible() && mWidgetPaintTask.IsPending()) {
1006 Paint();
1010 void PuppetWidget::OnMemoryPressure(layers::MemoryPressureReason aWhy) {
1011 if (aWhy != MemoryPressureReason::LOW_MEMORY_ONGOING && !mVisible &&
1012 mWindowRenderer && mWindowRenderer->AsWebRender() &&
1013 XRE_IsContentProcess()) {
1014 mWindowRenderer->AsWebRender()->ClearCachedResources();
1018 bool PuppetWidget::NeedsPaint() {
1019 // e10s popups are handled by the parent process, so never should be painted
1020 // here
1021 if (XRE_IsContentProcess() &&
1022 StaticPrefs::browser_tabs_remote_desktopbehavior() &&
1023 mWindowType == eWindowType_popup) {
1024 NS_WARNING("Trying to paint an e10s popup in the child process!");
1025 return false;
1028 return mVisible;
1031 float PuppetWidget::GetDPI() { return mDPI; }
1033 double PuppetWidget::GetDefaultScaleInternal() { return mDefaultScale; }
1035 int32_t PuppetWidget::RoundsWidgetCoordinatesTo() { return mRounding; }
1037 LayoutDeviceIntPoint PuppetWidget::GetChromeOffset() {
1038 if (!GetOwningBrowserChild()) {
1039 NS_WARNING("PuppetWidget without Tab does not have chrome information.");
1040 return LayoutDeviceIntPoint();
1042 return GetOwningBrowserChild()->GetChromeOffset();
1045 LayoutDeviceIntPoint PuppetWidget::WidgetToScreenOffset() {
1046 auto positionRalativeToWindow =
1047 WidgetToTopLevelWidgetTransform().TransformPoint(LayoutDevicePoint());
1049 return GetWindowPosition() +
1050 LayoutDeviceIntPoint::Round(positionRalativeToWindow);
1053 LayoutDeviceIntPoint PuppetWidget::GetWindowPosition() {
1054 if (!GetOwningBrowserChild()) {
1055 return LayoutDeviceIntPoint();
1058 int32_t winX, winY, winW, winH;
1059 NS_ENSURE_SUCCESS(
1060 GetOwningBrowserChild()->GetDimensions(0, &winX, &winY, &winW, &winH),
1061 LayoutDeviceIntPoint());
1062 return LayoutDeviceIntPoint(winX, winY) +
1063 GetOwningBrowserChild()->GetClientOffset();
1066 LayoutDeviceIntRect PuppetWidget::GetScreenBounds() {
1067 return LayoutDeviceIntRect(WidgetToScreenOffset(), mBounds.Size());
1070 uint32_t PuppetWidget::GetMaxTouchPoints() const {
1071 return mBrowserChild ? mBrowserChild->MaxTouchPoints() : 0;
1074 void PuppetWidget::StartAsyncScrollbarDrag(
1075 const AsyncDragMetrics& aDragMetrics) {
1076 mBrowserChild->StartScrollbarDrag(aDragMetrics);
1079 PuppetScreen::PuppetScreen(void* nativeScreen) {}
1081 PuppetScreen::~PuppetScreen() = default;
1083 static ScreenConfiguration ScreenConfig() {
1084 ScreenConfiguration config;
1085 hal::GetCurrentScreenConfiguration(&config);
1086 return config;
1089 nsIntSize PuppetWidget::GetScreenDimensions() {
1090 nsIntRect r = ScreenConfig().rect();
1091 return nsIntSize(r.Width(), r.Height());
1094 NS_IMETHODIMP
1095 PuppetScreen::GetRect(int32_t* outLeft, int32_t* outTop, int32_t* outWidth,
1096 int32_t* outHeight) {
1097 nsIntRect r = ScreenConfig().rect();
1098 r.GetRect(outLeft, outTop, outWidth, outHeight);
1099 return NS_OK;
1102 NS_IMETHODIMP
1103 PuppetScreen::GetAvailRect(int32_t* outLeft, int32_t* outTop, int32_t* outWidth,
1104 int32_t* outHeight) {
1105 return GetRect(outLeft, outTop, outWidth, outHeight);
1108 NS_IMETHODIMP
1109 PuppetScreen::GetPixelDepth(int32_t* aPixelDepth) {
1110 *aPixelDepth = ScreenConfig().pixelDepth();
1111 return NS_OK;
1114 NS_IMETHODIMP
1115 PuppetScreen::GetColorDepth(int32_t* aColorDepth) {
1116 *aColorDepth = ScreenConfig().colorDepth();
1117 return NS_OK;
1120 NS_IMPL_ISUPPORTS(PuppetScreenManager, nsIScreenManager)
1122 PuppetScreenManager::PuppetScreenManager() {
1123 mOneScreen = new PuppetScreen(nullptr);
1126 PuppetScreenManager::~PuppetScreenManager() = default;
1128 NS_IMETHODIMP
1129 PuppetScreenManager::GetPrimaryScreen(nsIScreen** outScreen) {
1130 NS_IF_ADDREF(*outScreen = mOneScreen.get());
1131 return NS_OK;
1134 NS_IMETHODIMP
1135 PuppetScreenManager::GetTotalScreenPixels(int64_t* aTotalScreenPixels) {
1136 MOZ_ASSERT(aTotalScreenPixels);
1137 if (mOneScreen) {
1138 int32_t x, y, width, height;
1139 x = y = width = height = 0;
1140 mOneScreen->GetRect(&x, &y, &width, &height);
1141 *aTotalScreenPixels = width * height;
1142 } else {
1143 *aTotalScreenPixels = 0;
1145 return NS_OK;
1148 NS_IMETHODIMP
1149 PuppetScreenManager::ScreenForRect(int32_t inLeft, int32_t inTop,
1150 int32_t inWidth, int32_t inHeight,
1151 nsIScreen** outScreen) {
1152 return GetPrimaryScreen(outScreen);
1155 ScreenIntMargin PuppetWidget::GetSafeAreaInsets() const {
1156 return mSafeAreaInsets;
1159 void PuppetWidget::UpdateSafeAreaInsets(
1160 const ScreenIntMargin& aSafeAreaInsets) {
1161 mSafeAreaInsets = aSafeAreaInsets;
1164 nsIWidgetListener* PuppetWidget::GetCurrentWidgetListener() {
1165 if (!mPreviouslyAttachedWidgetListener || !mAttachedWidgetListener) {
1166 return mAttachedWidgetListener;
1169 if (mAttachedWidgetListener->GetView()->IsPrimaryFramePaintSuppressed()) {
1170 return mPreviouslyAttachedWidgetListener;
1173 return mAttachedWidgetListener;
1176 void PuppetWidget::ZoomToRect(const uint32_t& aPresShellId,
1177 const ScrollableLayerGuid::ViewID& aViewId,
1178 const CSSRect& aRect, const uint32_t& aFlags) {
1179 if (!mBrowserChild) {
1180 return;
1183 mBrowserChild->ZoomToRect(aPresShellId, aViewId, aRect, aFlags);
1186 void PuppetWidget::LookUpDictionary(
1187 const nsAString& aText, const nsTArray<mozilla::FontRange>& aFontRangeArray,
1188 const bool aIsVertical, const LayoutDeviceIntPoint& aPoint) {
1189 if (!mBrowserChild) {
1190 return;
1193 mBrowserChild->SendLookUpDictionary(nsString(aText), aFontRangeArray,
1194 aIsVertical, aPoint);
1197 bool PuppetWidget::HasPendingInputEvent() {
1198 if (!mBrowserChild) {
1199 return false;
1202 bool ret = false;
1204 mBrowserChild->GetIPCChannel()->PeekMessages(
1205 [&ret](const IPC::Message& aMsg) -> bool {
1206 if (nsContentUtils::IsMessageInputEvent(aMsg)) {
1207 ret = true;
1208 return false; // Stop peeking.
1210 return true;
1213 return ret;
1216 // TextEventDispatcherListener
1218 NS_IMETHODIMP
1219 PuppetWidget::NotifyIME(TextEventDispatcher* aTextEventDispatcher,
1220 const IMENotification& aIMENotification) {
1221 MOZ_ASSERT(aTextEventDispatcher == mTextEventDispatcher);
1223 // If there is different text event dispatcher listener for handling
1224 // text event dispatcher, that means that native keyboard events and
1225 // IME events are handled in this process. Therefore, we don't need
1226 // to send any requests and notifications to the parent process.
1227 if (mNativeTextEventDispatcherListener) {
1228 return NS_ERROR_NOT_IMPLEMENTED;
1231 switch (aIMENotification.mMessage) {
1232 case REQUEST_TO_COMMIT_COMPOSITION:
1233 return RequestIMEToCommitComposition(false);
1234 case REQUEST_TO_CANCEL_COMPOSITION:
1235 return RequestIMEToCommitComposition(true);
1236 case NOTIFY_IME_OF_FOCUS:
1237 case NOTIFY_IME_OF_BLUR:
1238 return NotifyIMEOfFocusChange(aIMENotification);
1239 case NOTIFY_IME_OF_SELECTION_CHANGE:
1240 return NotifyIMEOfSelectionChange(aIMENotification);
1241 case NOTIFY_IME_OF_TEXT_CHANGE:
1242 return NotifyIMEOfTextChange(aIMENotification);
1243 case NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED:
1244 return NotifyIMEOfCompositionUpdate(aIMENotification);
1245 case NOTIFY_IME_OF_MOUSE_BUTTON_EVENT:
1246 return NotifyIMEOfMouseButtonEvent(aIMENotification);
1247 case NOTIFY_IME_OF_POSITION_CHANGE:
1248 return NotifyIMEOfPositionChange(aIMENotification);
1249 default:
1250 return NS_ERROR_NOT_IMPLEMENTED;
1253 return NS_ERROR_NOT_IMPLEMENTED;
1256 NS_IMETHODIMP_(IMENotificationRequests)
1257 PuppetWidget::GetIMENotificationRequests() {
1258 return IMENotificationRequests(
1259 mIMENotificationRequestsOfParent.mWantUpdates |
1260 IMENotificationRequests::NOTIFY_TEXT_CHANGE |
1261 IMENotificationRequests::NOTIFY_POSITION_CHANGE);
1264 NS_IMETHODIMP_(void)
1265 PuppetWidget::OnRemovedFrom(TextEventDispatcher* aTextEventDispatcher) {
1266 MOZ_ASSERT(aTextEventDispatcher == mTextEventDispatcher);
1269 NS_IMETHODIMP_(void)
1270 PuppetWidget::WillDispatchKeyboardEvent(
1271 TextEventDispatcher* aTextEventDispatcher,
1272 WidgetKeyboardEvent& aKeyboardEvent, uint32_t aIndexOfKeypress,
1273 void* aData) {
1274 MOZ_ASSERT(aTextEventDispatcher == mTextEventDispatcher);
1277 nsresult PuppetWidget::SetSystemFont(const nsCString& aFontName) {
1278 if (!mBrowserChild) {
1279 return NS_ERROR_FAILURE;
1282 mBrowserChild->SendSetSystemFont(aFontName);
1283 return NS_OK;
1286 nsresult PuppetWidget::GetSystemFont(nsCString& aFontName) {
1287 if (!mBrowserChild) {
1288 return NS_ERROR_FAILURE;
1290 mBrowserChild->SendGetSystemFont(&aFontName);
1291 return NS_OK;
1294 } // namespace widget
1295 } // namespace mozilla