1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
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 "ClientLayerManager.h"
11 #include "gfxPlatform.h"
12 #include "mozilla/dom/TabChild.h"
13 #include "mozilla/dom/TabGroup.h"
14 #include "mozilla/gfx/gfxVars.h"
15 #include "mozilla/Hal.h"
16 #include "mozilla/IMEStateManager.h"
17 #include "mozilla/layers/APZChild.h"
18 #include "mozilla/layers/PLayerTransactionChild.h"
19 #include "mozilla/layers/WebRenderLayerManager.h"
20 #include "mozilla/Preferences.h"
21 #include "mozilla/TextComposition.h"
22 #include "mozilla/TextEventDispatcher.h"
23 #include "mozilla/TextEvents.h"
24 #include "mozilla/Unused.h"
25 #include "BasicLayers.h"
26 #include "PuppetWidget.h"
27 #include "nsContentUtils.h"
28 #include "nsIWidgetListener.h"
29 #include "imgIContainer.h"
31 #include "nsPrintfCString.h"
33 using namespace mozilla
;
34 using namespace mozilla::dom
;
35 using namespace mozilla::hal
;
36 using namespace mozilla::gfx
;
37 using namespace mozilla::layers
;
38 using namespace mozilla::widget
;
41 InvalidateRegion(nsIWidget
* aWidget
, const LayoutDeviceIntRegion
& aRegion
)
43 for (auto iter
= aRegion
.RectIter(); !iter
.Done(); iter
.Next()) {
44 aWidget
->Invalidate(iter
.Get());
48 /*static*/ already_AddRefed
<nsIWidget
>
49 nsIWidget::CreatePuppetWidget(TabChild
* aTabChild
)
51 MOZ_ASSERT(!aTabChild
|| nsIWidget::UsePuppetWidgets(),
52 "PuppetWidgets not allowed in this configuration");
54 nsCOMPtr
<nsIWidget
> widget
= new PuppetWidget(aTabChild
);
55 return widget
.forget();
62 IsPopup(const nsWidgetInitData
* aInitData
)
64 return aInitData
&& aInitData
->mWindowType
== eWindowType_popup
;
68 MightNeedIMEFocus(const nsWidgetInitData
* aInitData
)
70 // In the puppet-widget world, popup widgets are just dummies and
71 // shouldn't try to mess with IME state.
72 #ifdef MOZ_CROSS_PROCESS_IME
73 return !IsPopup(aInitData
);
79 // Arbitrary, fungible.
80 const size_t PuppetWidget::kMaxDimension
= 4000;
82 static bool gRemoteDesktopBehaviorEnabled
= false;
83 static bool gRemoteDesktopBehaviorInitialized
= false;
85 NS_IMPL_ISUPPORTS_INHERITED(PuppetWidget
, nsBaseWidget
86 , TextEventDispatcherListener
)
88 PuppetWidget::PuppetWidget(TabChild
* aTabChild
)
89 : mTabChild(aTabChild
)
90 , mMemoryPressureObserver(nullptr)
98 , mNeedIMEStateInit(false)
99 , mIgnoreCompositionEvents(false)
101 // Setting 'Unknown' means "not yet cached".
102 mInputContext
.mIMEState
.mEnabled
= IMEState::UNKNOWN
;
104 if (!gRemoteDesktopBehaviorInitialized
) {
105 Preferences::AddBoolVarCache(&gRemoteDesktopBehaviorEnabled
, "browser.tabs.remote.desktopbehavior", false);
106 gRemoteDesktopBehaviorInitialized
= true;
110 PuppetWidget::~PuppetWidget()
116 PuppetWidget::InfallibleCreate(nsIWidget
* aParent
,
117 nsNativeWidget aNativeParent
,
118 const LayoutDeviceIntRect
& aRect
,
119 nsWidgetInitData
* aInitData
)
121 MOZ_ASSERT(!aNativeParent
, "got a non-Puppet native parent");
123 BaseCreate(nullptr, aInitData
);
129 mDrawTarget
= gfxPlatform::GetPlatform()->
130 CreateOffscreenContentDrawTarget(IntSize(1, 1), SurfaceFormat::B8G8R8A8
);
132 mNeedIMEStateInit
= MightNeedIMEFocus(aInitData
);
134 PuppetWidget
* parent
= static_cast<PuppetWidget
*>(aParent
);
136 parent
->SetChild(this);
137 mLayerManager
= parent
->GetLayerManager();
140 Resize(mBounds
.X(), mBounds
.Y(), mBounds
.Width(), mBounds
.Height(), false);
142 nsCOMPtr
<nsIObserverService
> obs
= mozilla::services::GetObserverService();
144 mMemoryPressureObserver
= new MemoryPressureObserver(this);
145 obs
->AddObserver(mMemoryPressureObserver
, "memory-pressure", false);
150 PuppetWidget::Create(nsIWidget
* aParent
,
151 nsNativeWidget aNativeParent
,
152 const LayoutDeviceIntRect
& aRect
,
153 nsWidgetInitData
* aInitData
)
155 InfallibleCreate(aParent
, aNativeParent
, aRect
, aInitData
);
160 PuppetWidget::InitIMEState()
162 MOZ_ASSERT(mTabChild
);
163 if (mNeedIMEStateInit
) {
164 mContentCache
.Clear();
165 mTabChild
->SendUpdateContentCache(mContentCache
);
166 mIMENotificationRequestsOfParent
= IMENotificationRequests();
167 mNeedIMEStateInit
= false;
171 already_AddRefed
<nsIWidget
>
172 PuppetWidget::CreateChild(const LayoutDeviceIntRect
& aRect
,
173 nsWidgetInitData
* aInitData
,
174 bool aForceUseIWidgetParent
)
176 bool isPopup
= IsPopup(aInitData
);
177 nsCOMPtr
<nsIWidget
> widget
= nsIWidget::CreatePuppetWidget(mTabChild
);
179 NS_SUCCEEDED(widget
->Create(isPopup
? nullptr: this, nullptr, aRect
,
181 widget
.forget() : nullptr);
185 PuppetWidget::Destroy()
187 if (mOnDestroyCalled
) {
190 mOnDestroyCalled
= true;
195 if (mMemoryPressureObserver
) {
196 mMemoryPressureObserver
->Remove();
198 mMemoryPressureObserver
= nullptr;
201 mLayerManager
->Destroy();
203 mLayerManager
= nullptr;
208 PuppetWidget::Show(bool aState
)
210 NS_ASSERTION(mEnabled
,
211 "does it make sense to Show()/Hide() a disabled widget?");
213 bool wasVisible
= mVisible
;
217 mChild
->mVisible
= aState
;
220 if (!wasVisible
&& mVisible
) {
221 // The previously attached widget listener is handy if
222 // we're transitioning from page to page without dropping
223 // layers (since we'll continue to show the old layers
224 // associated with that old widget listener). If the
225 // PuppetWidget was hidden, those layers are dropped,
226 // so the previously attached widget listener is really
227 // of no use anymore (and is actually actively harmful - see
229 mPreviouslyAttachedWidgetListener
= nullptr;
230 Resize(mBounds
.Width(), mBounds
.Height(), false);
236 PuppetWidget::Resize(double aWidth
,
240 LayoutDeviceIntRect oldBounds
= mBounds
;
241 mBounds
.SizeTo(LayoutDeviceIntSize(NSToIntRound(aWidth
),
242 NSToIntRound(aHeight
)));
245 mChild
->Resize(aWidth
, aHeight
, aRepaint
);
249 // XXX: roc says that |aRepaint| dictates whether or not to
250 // invalidate the expanded area
251 if (oldBounds
.Size() < mBounds
.Size() && aRepaint
) {
252 LayoutDeviceIntRegion
dirty(mBounds
);
253 dirty
.Sub(dirty
, oldBounds
);
254 InvalidateRegion(this, dirty
);
257 // call WindowResized() on both the current listener, and possibly
258 // also the previous one if we're in a state where we're drawing that one
259 // because the current one is paint suppressed
260 if (!oldBounds
.IsEqualEdges(mBounds
) && mAttachedWidgetListener
) {
261 if (GetCurrentWidgetListener() &&
262 GetCurrentWidgetListener() != mAttachedWidgetListener
) {
263 GetCurrentWidgetListener()->WindowResized(this, mBounds
.Width(), mBounds
.Height());
265 mAttachedWidgetListener
->WindowResized(this, mBounds
.Width(), mBounds
.Height());
270 PuppetWidget::ConfigureChildren(const nsTArray
<Configuration
>& aConfigurations
)
272 for (uint32_t i
= 0; i
< aConfigurations
.Length(); ++i
) {
273 const Configuration
& configuration
= aConfigurations
[i
];
274 PuppetWidget
* w
= static_cast<PuppetWidget
*>(configuration
.mChild
.get());
275 NS_ASSERTION(w
->GetParent() == this,
276 "Configured widget is not a child");
277 w
->SetWindowClipRegion(configuration
.mClipRegion
, true);
278 LayoutDeviceIntRect bounds
= w
->GetBounds();
279 if (bounds
.Size() != configuration
.mBounds
.Size()) {
280 w
->Resize(configuration
.mBounds
.X(), configuration
.mBounds
.Y(),
281 configuration
.mBounds
.Width(), configuration
.mBounds
.Height(),
283 } else if (bounds
.TopLeft() != configuration
.mBounds
.TopLeft()) {
284 w
->Move(configuration
.mBounds
.X(), configuration
.mBounds
.Y());
286 w
->SetWindowClipRegion(configuration
.mClipRegion
, false);
292 PuppetWidget::SetFocus(bool aRaise
)
294 if (aRaise
&& mTabChild
) {
295 mTabChild
->SendRequestFocus(true);
302 PuppetWidget::Invalidate(const LayoutDeviceIntRect
& aRect
)
305 debug_DumpInvalidate(stderr
, this, &aRect
, "PuppetWidget", 0);
309 mChild
->Invalidate(aRect
);
313 mDirtyRegion
.Or(mDirtyRegion
, aRect
);
315 if (mTabChild
&& !mDirtyRegion
.IsEmpty() && !mPaintTask
.IsPending()) {
316 mPaintTask
= new PaintTask(this);
317 nsCOMPtr
<nsIRunnable
> event(mPaintTask
.get());
318 mTabChild
->TabGroup()->Dispatch(TaskCategory::Other
, event
.forget());
324 PuppetWidget::InitEvent(WidgetGUIEvent
& aEvent
, LayoutDeviceIntPoint
* aPoint
)
326 if (nullptr == aPoint
) {
327 aEvent
.mRefPoint
= LayoutDeviceIntPoint(0, 0);
329 // use the point override if provided
330 aEvent
.mRefPoint
= *aPoint
;
332 aEvent
.mTime
= PR_Now() / 1000;
336 PuppetWidget::DispatchEvent(WidgetGUIEvent
* aEvent
, nsEventStatus
& aStatus
)
339 debug_DumpEvent(stdout
, aEvent
->mWidget
, aEvent
, "PuppetWidget", 0);
342 MOZ_ASSERT(!mChild
|| mChild
->mWindowType
== eWindowType_popup
,
343 "Unexpected event dispatch!");
345 MOZ_ASSERT(!aEvent
->AsKeyboardEvent() ||
346 aEvent
->mFlags
.mIsSynthesizedForTests
||
347 aEvent
->AsKeyboardEvent()->AreAllEditCommandsInitialized(),
348 "Non-sysnthesized keyboard events should have edit commands for all types "
349 "before dispatched");
351 if (aEvent
->mClass
== eCompositionEventClass
) {
352 // If we've already requested to commit/cancel the latest composition,
353 // TextComposition for the old composition has been destroyed. Then,
354 // the DOM tree needs to listen to next eCompositionStart and its
355 // following events. So, until we meet new eCompositionStart, let's
356 // discard all unnecessary composition events here.
357 if (mIgnoreCompositionEvents
) {
358 if (aEvent
->mMessage
!= eCompositionStart
) {
359 aStatus
= nsEventStatus_eIgnore
;
362 // Now, we receive new eCompositionStart. Let's restart to handle
363 // composition in this process.
364 mIgnoreCompositionEvents
= false;
366 // Store the latest native IME context of parent process's widget or
367 // TextEventDispatcher if it's in this process.
368 WidgetCompositionEvent
* compositionEvent
= aEvent
->AsCompositionEvent();
370 if (mNativeIMEContext
.IsValid() &&
371 mNativeIMEContext
!= compositionEvent
->mNativeIMEContext
) {
372 RefPtr
<TextComposition
> composition
=
373 IMEStateManager::GetTextCompositionFor(this);
374 MOZ_ASSERT(!composition
,
375 "When there is composition caused by old native IME context, "
376 "composition events caused by different native IME context are not "
379 #endif // #ifdef DEBUG
380 mNativeIMEContext
= compositionEvent
->mNativeIMEContext
;
383 // If the event is a composition event or a keyboard event, it should be
384 // dispatched with TextEventDispatcher if we could do that with current
385 // design. However, we cannot do that without big changes and the behavior
386 // is not so complicated for now. Therefore, we should just notify it
387 // of dispatching events and TextEventDispatcher should emulate the state
389 if (aEvent
->mClass
== eCompositionEventClass
||
390 aEvent
->mClass
== eKeyboardEventClass
) {
391 TextEventDispatcher
* dispatcher
= GetTextEventDispatcher();
392 // However, if the event is being dispatched by the text event dispatcher
393 // or, there is native text event dispatcher listener, that means that
394 // native text input event handler is in this process like on Android,
395 // and the event is not synthesized for tests, the event is coming from
396 // the TextEventDispatcher. In these cases, we shouldn't notify
397 // TextEventDispatcher of dispatching the event.
398 if (!dispatcher
->IsDispatchingEvent() &&
399 !(mNativeTextEventDispatcherListener
&&
400 !aEvent
->mFlags
.mIsSynthesizedForTests
)) {
401 DebugOnly
<nsresult
> rv
=
402 dispatcher
->BeginInputTransactionFor(aEvent
, this);
403 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
404 "The text event dispatcher should always succeed to start input "
405 "transaction for the event");
409 aStatus
= nsEventStatus_eIgnore
;
411 if (GetCurrentWidgetListener()) {
413 GetCurrentWidgetListener()->HandleEvent(aEvent
, mUseAttachedEvents
);
420 PuppetWidget::DispatchInputEvent(WidgetInputEvent
* aEvent
)
422 if (!AsyncPanZoomEnabled()) {
423 nsEventStatus status
= nsEventStatus_eIgnore
;
424 DispatchEvent(aEvent
, status
);
429 return nsEventStatus_eIgnore
;
432 switch (aEvent
->mClass
) {
433 case eWheelEventClass
:
435 mTabChild
->SendDispatchWheelEvent(*aEvent
->AsWheelEvent());
437 case eMouseEventClass
:
439 mTabChild
->SendDispatchMouseEvent(*aEvent
->AsMouseEvent());
441 case eKeyboardEventClass
:
443 mTabChild
->SendDispatchKeyboardEvent(*aEvent
->AsKeyboardEvent());
446 MOZ_ASSERT_UNREACHABLE("unsupported event type");
449 return nsEventStatus_eIgnore
;
453 PuppetWidget::SynthesizeNativeKeyEvent(int32_t aNativeKeyboardLayout
,
454 int32_t aNativeKeyCode
,
455 uint32_t aModifierFlags
,
456 const nsAString
& aCharacters
,
457 const nsAString
& aUnmodifiedCharacters
,
458 nsIObserver
* aObserver
)
460 AutoObserverNotifier
notifier(aObserver
, "keyevent");
462 return NS_ERROR_FAILURE
;
464 mTabChild
->SendSynthesizeNativeKeyEvent(aNativeKeyboardLayout
, aNativeKeyCode
,
465 aModifierFlags
, nsString(aCharacters
),
466 nsString(aUnmodifiedCharacters
),
467 notifier
.SaveObserver());
472 PuppetWidget::SynthesizeNativeMouseEvent(mozilla::LayoutDeviceIntPoint aPoint
,
473 uint32_t aNativeMessage
,
474 uint32_t aModifierFlags
,
475 nsIObserver
* aObserver
)
477 AutoObserverNotifier
notifier(aObserver
, "mouseevent");
479 return NS_ERROR_FAILURE
;
481 mTabChild
->SendSynthesizeNativeMouseEvent(aPoint
, aNativeMessage
,
483 notifier
.SaveObserver());
488 PuppetWidget::SynthesizeNativeMouseMove(mozilla::LayoutDeviceIntPoint aPoint
,
489 nsIObserver
* aObserver
)
491 AutoObserverNotifier
notifier(aObserver
, "mousemove");
493 return NS_ERROR_FAILURE
;
495 mTabChild
->SendSynthesizeNativeMouseMove(aPoint
, notifier
.SaveObserver());
500 PuppetWidget::SynthesizeNativeMouseScrollEvent(
501 mozilla::LayoutDeviceIntPoint aPoint
,
502 uint32_t aNativeMessage
,
506 uint32_t aModifierFlags
,
507 uint32_t aAdditionalFlags
,
508 nsIObserver
* aObserver
)
510 AutoObserverNotifier
notifier(aObserver
, "mousescrollevent");
512 return NS_ERROR_FAILURE
;
514 mTabChild
->SendSynthesizeNativeMouseScrollEvent(aPoint
, aNativeMessage
,
515 aDeltaX
, aDeltaY
, aDeltaZ
,
518 notifier
.SaveObserver());
523 PuppetWidget::SynthesizeNativeTouchPoint(uint32_t aPointerId
,
524 TouchPointerState aPointerState
,
525 LayoutDeviceIntPoint aPoint
,
526 double aPointerPressure
,
527 uint32_t aPointerOrientation
,
528 nsIObserver
* aObserver
)
530 AutoObserverNotifier
notifier(aObserver
, "touchpoint");
532 return NS_ERROR_FAILURE
;
534 mTabChild
->SendSynthesizeNativeTouchPoint(aPointerId
, aPointerState
,
535 aPoint
, aPointerPressure
,
537 notifier
.SaveObserver());
542 PuppetWidget::SynthesizeNativeTouchTap(LayoutDeviceIntPoint aPoint
,
544 nsIObserver
* aObserver
)
546 AutoObserverNotifier
notifier(aObserver
, "touchtap");
548 return NS_ERROR_FAILURE
;
550 mTabChild
->SendSynthesizeNativeTouchTap(aPoint
, aLongTap
,
551 notifier
.SaveObserver());
556 PuppetWidget::ClearNativeTouchSequence(nsIObserver
* aObserver
)
558 AutoObserverNotifier
notifier(aObserver
, "cleartouch");
560 return NS_ERROR_FAILURE
;
562 mTabChild
->SendClearNativeTouchSequence(notifier
.SaveObserver());
567 PuppetWidget::SetConfirmedTargetAPZC(
568 uint64_t aInputBlockId
,
569 const nsTArray
<ScrollableLayerGuid
>& aTargets
) const
572 mTabChild
->SetTargetAPZC(aInputBlockId
, aTargets
);
577 PuppetWidget::UpdateZoomConstraints(const uint32_t& aPresShellId
,
578 const FrameMetrics::ViewID
& aViewId
,
579 const Maybe
<ZoomConstraints
>& aConstraints
)
582 mTabChild
->DoUpdateZoomConstraints(aPresShellId
, aViewId
, aConstraints
);
587 PuppetWidget::AsyncPanZoomEnabled() const
589 return mTabChild
&& mTabChild
->AsyncPanZoomEnabled();
593 PuppetWidget::GetEditCommands(NativeKeyBindingsType aType
,
594 const WidgetKeyboardEvent
& aEvent
,
595 nsTArray
<CommandInt
>& aCommands
)
597 // Validate the arguments.
598 nsIWidget::GetEditCommands(aType
, aEvent
, aCommands
);
600 mTabChild
->RequestEditCommands(aType
, aEvent
, aCommands
);
604 PuppetWidget::GetLayerManager(PLayerTransactionChild
* aShadowManager
,
605 LayersBackend aBackendHint
,
606 LayerManagerPersistence aPersistence
)
608 if (!mLayerManager
) {
609 if (XRE_IsParentProcess()) {
610 // On the parent process there is no CompositorBridgeChild which confuses
611 // some layers code, so we use basic layers instead. Note that we create
612 // a non-retaining layer manager since we don't care about performance.
613 mLayerManager
= new BasicLayerManager(BasicLayerManager::BLM_OFFSCREEN
);
614 return mLayerManager
;
617 // If we know for sure that the parent side of this TabChild is not
618 // connected to the compositor, we don't want to use a "remote" layer
619 // manager like WebRender or Client. Instead we use a Basic one which
620 // can do drawing in this process.
621 MOZ_ASSERT(!mTabChild
|| mTabChild
->IsLayersConnected() != Some(true));
622 mLayerManager
= new BasicLayerManager(this);
625 return mLayerManager
;
629 PuppetWidget::CreateRemoteLayerManager(const std::function
<bool(LayerManager
*)>& aInitializeFunc
)
631 RefPtr
<LayerManager
> lm
;
632 MOZ_ASSERT(mTabChild
);
633 if (mTabChild
->GetCompositorOptions().UseWebRender()) {
634 lm
= new WebRenderLayerManager(this);
636 lm
= new ClientLayerManager(this);
639 if (!aInitializeFunc(lm
)) {
643 // Force the old LM to self destruct, otherwise if the reference dangles we
644 // could fail to revoke the most recent transaction. We only want to replace
645 // it if we successfully create its successor because a partially initialized
646 // layer manager is worse than a fully initialized but shutdown layer manager.
647 DestroyLayerManager();
648 mLayerManager
= lm
.forget();
653 PuppetWidget::RequestIMEToCommitComposition(bool aCancel
)
656 return NS_ERROR_FAILURE
;
659 MOZ_ASSERT(!Destroyed());
661 // There must not be composition which is caused by the PuppetWidget instance.
662 if (NS_WARN_IF(!mNativeIMEContext
.IsValid())) {
666 // We've already requested to commit/cancel composition.
667 if (NS_WARN_IF(mIgnoreCompositionEvents
)) {
669 RefPtr
<TextComposition
> composition
=
670 IMEStateManager::GetTextCompositionFor(this);
671 MOZ_ASSERT(!composition
);
672 #endif // #ifdef DEBUG
676 RefPtr
<TextComposition
> composition
=
677 IMEStateManager::GetTextCompositionFor(this);
678 // This method shouldn't be called when there is no text composition instance.
679 if (NS_WARN_IF(!composition
)) {
683 MOZ_DIAGNOSTIC_ASSERT(composition
->IsRequestingCommitOrCancelComposition(),
684 "Requesting commit or cancel composition should be requested via "
685 "TextComposition instance");
687 bool isCommitted
= false;
688 nsAutoString committedString
;
689 if (NS_WARN_IF(!mTabChild
->SendRequestIMEToCommitComposition(
690 aCancel
, &isCommitted
, &committedString
))) {
691 return NS_ERROR_FAILURE
;
694 // If the composition wasn't committed synchronously, we need to wait async
695 // composition events for destroying the TextComposition instance.
700 // Dispatch eCompositionCommit event.
701 WidgetCompositionEvent
compositionCommitEvent(true, eCompositionCommit
, this);
702 InitEvent(compositionCommitEvent
, nullptr);
703 compositionCommitEvent
.mData
= committedString
;
704 nsEventStatus status
= nsEventStatus_eIgnore
;
705 DispatchEvent(&compositionCommitEvent
, status
);
708 RefPtr
<TextComposition
> currentComposition
=
709 IMEStateManager::GetTextCompositionFor(this);
710 MOZ_ASSERT(!currentComposition
);
711 #endif // #ifdef DEBUG
713 // Ignore the following composition events until we receive new
714 // eCompositionStart event.
715 mIgnoreCompositionEvents
= true;
718 mTabChild
->SendOnEventNeedingAckHandled(eCompositionCommitRequestHandled
);
720 // NOTE: PuppetWidget might be destroyed already.
725 PuppetWidget::StartPluginIME(const mozilla::WidgetKeyboardEvent
& aKeyboardEvent
,
726 int32_t aPanelX
, int32_t aPanelY
,
727 nsString
& aCommitted
)
730 !mTabChild
->SendStartPluginIME(aKeyboardEvent
, aPanelX
,
731 aPanelY
, &aCommitted
)) {
732 return NS_ERROR_FAILURE
;
738 PuppetWidget::SetPluginFocused(bool& aFocused
)
741 mTabChild
->SendSetPluginFocused(aFocused
);
746 PuppetWidget::DefaultProcOfPluginEvent(const WidgetPluginEvent
& aEvent
)
751 mTabChild
->SendDefaultProcOfPluginEvent(aEvent
);
754 // When this widget caches input context and currently managed by
755 // IMEStateManager, the cache is valid.
757 PuppetWidget::HaveValidInputContextCache() const
759 return (mInputContext
.mIMEState
.mEnabled
!= IMEState::UNKNOWN
&&
760 IMEStateManager::GetWidgetForActiveInputContext() == this);
764 PuppetWidget::SetInputContext(const InputContext
& aContext
,
765 const InputContextAction
& aAction
)
767 mInputContext
= aContext
;
768 // Any widget instances cannot cache IME open state because IME open state
769 // can be changed by user but native IME may not notify us of changing the
770 // open state on some platforms.
771 mInputContext
.mIMEState
.mOpen
= IMEState::OPEN_STATE_NOT_SUPPORTED
;
775 mTabChild
->SendSetInputContext(aContext
, aAction
);
779 PuppetWidget::GetInputContext()
781 // XXX Currently, we don't support retrieving IME open state from child
784 // If the cache of input context is valid, we can avoid to use synchronous
786 if (HaveValidInputContextCache()) {
787 return mInputContext
;
790 NS_WARNING("PuppetWidget::GetInputContext() needs to retrieve it with IPC");
792 // Don't cache InputContext here because this process isn't managing IME
793 // state of the chrome widget. So, we cannot modify mInputContext when
794 // chrome widget is set to new context.
795 InputContext context
;
797 mTabChild
->SendGetInputContext(&context
.mIMEState
);
803 PuppetWidget::GetNativeIMEContext()
805 return mNativeIMEContext
;
809 PuppetWidget::NotifyIMEOfFocusChange(const IMENotification
& aIMENotification
)
812 return NS_ERROR_FAILURE
;
815 bool gotFocus
= aIMENotification
.mMessage
== NOTIFY_IME_OF_FOCUS
;
817 if (mInputContext
.mIMEState
.mEnabled
!= IMEState::PLUGIN
) {
818 // When IME gets focus, we should initalize all information of the
820 if (NS_WARN_IF(!mContentCache
.CacheAll(this, &aIMENotification
))) {
821 return NS_ERROR_FAILURE
;
824 // However, if a plugin has focus, only the editor rect information is
826 if (NS_WARN_IF(!mContentCache
.CacheEditorRect(this, &aIMENotification
))) {
827 return NS_ERROR_FAILURE
;
831 // When IME loses focus, we don't need to store anything.
832 mContentCache
.Clear();
835 mIMENotificationRequestsOfParent
=
836 IMENotificationRequests(IMENotificationRequests::NOTIFY_ALL
);
837 RefPtr
<PuppetWidget
> self
= this;
838 mTabChild
->SendNotifyIMEFocus(mContentCache
, aIMENotification
)->Then(
839 mTabChild
->TabGroup()->EventTargetFor(TaskCategory::UI
),
841 [self
] (IMENotificationRequests aRequests
) {
842 self
->mIMENotificationRequestsOfParent
= aRequests
;
844 [self
] (mozilla::ipc::ResponseRejectReason aReason
) {
845 NS_WARNING("SendNotifyIMEFocus got rejected.");
852 PuppetWidget::NotifyIMEOfCompositionUpdate(
853 const IMENotification
& aIMENotification
)
855 if (NS_WARN_IF(!mTabChild
)) {
856 return NS_ERROR_FAILURE
;
859 if (mInputContext
.mIMEState
.mEnabled
!= IMEState::PLUGIN
&&
860 NS_WARN_IF(!mContentCache
.CacheSelection(this, &aIMENotification
))) {
861 return NS_ERROR_FAILURE
;
863 mTabChild
->SendNotifyIMECompositionUpdate(mContentCache
, aIMENotification
);
868 PuppetWidget::NotifyIMEOfTextChange(const IMENotification
& aIMENotification
)
870 MOZ_ASSERT(aIMENotification
.mMessage
== NOTIFY_IME_OF_TEXT_CHANGE
,
871 "Passed wrong notification");
873 return NS_ERROR_FAILURE
;
876 // While a plugin has focus, text change notification shouldn't be available.
877 if (NS_WARN_IF(mInputContext
.mIMEState
.mEnabled
== IMEState::PLUGIN
)) {
878 return NS_ERROR_FAILURE
;
881 // FYI: text change notification is the first notification after
882 // a user operation changes the content. So, we need to modify
883 // the cache as far as possible here.
885 if (NS_WARN_IF(!mContentCache
.CacheText(this, &aIMENotification
))) {
886 return NS_ERROR_FAILURE
;
889 // TabParent doesn't this this to cache. we don't send the notification
890 // if parent process doesn't request NOTIFY_TEXT_CHANGE.
891 if (mIMENotificationRequestsOfParent
.WantTextChange()) {
892 mTabChild
->SendNotifyIMETextChange(mContentCache
, aIMENotification
);
894 mTabChild
->SendUpdateContentCache(mContentCache
);
900 PuppetWidget::NotifyIMEOfSelectionChange(
901 const IMENotification
& aIMENotification
)
903 MOZ_ASSERT(aIMENotification
.mMessage
== NOTIFY_IME_OF_SELECTION_CHANGE
,
904 "Passed wrong notification");
906 return NS_ERROR_FAILURE
;
909 // While a plugin has focus, selection change notification shouldn't be
911 if (NS_WARN_IF(mInputContext
.mIMEState
.mEnabled
== IMEState::PLUGIN
)) {
912 return NS_ERROR_FAILURE
;
915 // Note that selection change must be notified after text change if it occurs.
916 // Therefore, we don't need to query text content again here.
917 mContentCache
.SetSelection(
919 aIMENotification
.mSelectionChangeData
.mOffset
,
920 aIMENotification
.mSelectionChangeData
.Length(),
921 aIMENotification
.mSelectionChangeData
.mReversed
,
922 aIMENotification
.mSelectionChangeData
.GetWritingMode());
924 mTabChild
->SendNotifyIMESelection(mContentCache
, aIMENotification
);
930 PuppetWidget::NotifyIMEOfMouseButtonEvent(
931 const IMENotification
& aIMENotification
)
934 return NS_ERROR_FAILURE
;
937 // While a plugin has focus, mouse button event notification shouldn't be
939 if (NS_WARN_IF(mInputContext
.mIMEState
.mEnabled
== IMEState::PLUGIN
)) {
940 return NS_ERROR_FAILURE
;
944 bool consumedByIME
= false;
945 if (!mTabChild
->SendNotifyIMEMouseButtonEvent(aIMENotification
,
947 return NS_ERROR_FAILURE
;
950 return consumedByIME
? NS_SUCCESS_EVENT_CONSUMED
: NS_OK
;
954 PuppetWidget::NotifyIMEOfPositionChange(const IMENotification
& aIMENotification
)
956 if (NS_WARN_IF(!mTabChild
)) {
957 return NS_ERROR_FAILURE
;
960 if (NS_WARN_IF(!mContentCache
.CacheEditorRect(this, &aIMENotification
))) {
961 return NS_ERROR_FAILURE
;
963 // While a plugin has focus, selection range isn't available. So, we don't
964 // need to cache it at that time.
965 if (mInputContext
.mIMEState
.mEnabled
!= IMEState::PLUGIN
&&
966 NS_WARN_IF(!mContentCache
.CacheSelection(this, &aIMENotification
))) {
967 return NS_ERROR_FAILURE
;
969 if (mIMENotificationRequestsOfParent
.WantPositionChanged()) {
970 mTabChild
->SendNotifyIMEPositionChange(mContentCache
, aIMENotification
);
972 mTabChild
->SendUpdateContentCache(mContentCache
);
978 PuppetWidget::SetCursor(nsCursor aCursor
)
980 // Don't cache on windows, Windowless flash breaks this via async cursor updates.
982 if (mCursor
== aCursor
&& !mCustomCursor
&& !mUpdateCursor
) {
987 mCustomCursor
= nullptr;
990 !mTabChild
->SendSetCursor(aCursor
, mUpdateCursor
)) {
995 mUpdateCursor
= false;
999 PuppetWidget::SetCursor(imgIContainer
* aCursor
,
1000 uint32_t aHotspotX
, uint32_t aHotspotY
)
1002 if (!aCursor
|| !mTabChild
) {
1006 #if !defined(XP_WIN)
1007 if (mCustomCursor
== aCursor
&&
1008 mCursorHotspotX
== aHotspotX
&&
1009 mCursorHotspotY
== aHotspotY
&&
1015 RefPtr
<mozilla::gfx::SourceSurface
> surface
=
1016 aCursor
->GetFrame(imgIContainer::FRAME_CURRENT
,
1017 imgIContainer::FLAG_SYNC_DECODE
);
1019 return NS_ERROR_FAILURE
;
1022 RefPtr
<mozilla::gfx::DataSourceSurface
> dataSurface
=
1023 surface
->GetDataSurface();
1025 return NS_ERROR_FAILURE
;
1030 mozilla::UniquePtr
<char[]> surfaceData
=
1031 nsContentUtils::GetSurfaceData(WrapNotNull(dataSurface
), &length
, &stride
);
1033 nsDependentCString
cursorData(surfaceData
.get(), length
);
1034 mozilla::gfx::IntSize size
= dataSurface
->GetSize();
1035 if (!mTabChild
->SendSetCustomCursor(cursorData
, size
.width
, size
.height
, stride
,
1036 dataSurface
->GetFormat(),
1037 aHotspotX
, aHotspotY
, mUpdateCursor
)) {
1038 return NS_ERROR_FAILURE
;
1041 mCursor
= eCursorInvalid
;
1042 mCustomCursor
= aCursor
;
1043 mCursorHotspotX
= aHotspotX
;
1044 mCursorHotspotY
= aHotspotY
;
1045 mUpdateCursor
= false;
1051 PuppetWidget::ClearCachedCursor()
1053 nsBaseWidget::ClearCachedCursor();
1054 mCustomCursor
= nullptr;
1058 PuppetWidget::Paint()
1060 MOZ_ASSERT(!mDirtyRegion
.IsEmpty(), "paint event logic messed up");
1062 if (!GetCurrentWidgetListener())
1065 LayoutDeviceIntRegion region
= mDirtyRegion
;
1067 // reset repaint tracking
1068 mDirtyRegion
.SetEmpty();
1069 mPaintTask
.Revoke();
1071 RefPtr
<PuppetWidget
> strongThis(this);
1073 GetCurrentWidgetListener()->WillPaintWindow(this);
1075 if (GetCurrentWidgetListener()) {
1077 debug_DumpPaintEvent(stderr
, this, region
.ToUnknownRegion(),
1081 if (mLayerManager
->GetBackendType() == mozilla::layers::LayersBackend::LAYERS_CLIENT
||
1082 mLayerManager
->GetBackendType() == mozilla::layers::LayersBackend::LAYERS_WR
||
1083 (mozilla::layers::LayersBackend::LAYERS_BASIC
== mLayerManager
->GetBackendType() &&
1084 mTabChild
&& mTabChild
->IsLayersConnected().isSome())) {
1085 // Do nothing, the compositor will handle drawing
1087 mTabChild
->NotifyPainted();
1089 } else if (mozilla::layers::LayersBackend::LAYERS_BASIC
== mLayerManager
->GetBackendType()) {
1090 RefPtr
<gfxContext
> ctx
= gfxContext::CreateOrNull(mDrawTarget
);
1092 gfxDevCrash(LogReason::InvalidContext
) << "PuppetWidget context problem " << gfx::hexa(mDrawTarget
);
1093 return NS_ERROR_FAILURE
;
1095 ctx
->Rectangle(gfxRect(0,0,0,0));
1097 AutoLayerManagerSetup
setupLayerManager(this, ctx
,
1098 BufferMode::BUFFER_NONE
);
1099 GetCurrentWidgetListener()->PaintWindow(this, region
);
1101 mTabChild
->NotifyPainted();
1106 if (GetCurrentWidgetListener()) {
1107 GetCurrentWidgetListener()->DidPaintWindow();
1114 PuppetWidget::SetChild(PuppetWidget
* aChild
)
1116 MOZ_ASSERT(this != aChild
, "can't parent a widget to itself");
1117 MOZ_ASSERT(!aChild
->mChild
,
1118 "fake widget 'hierarchy' only expected to have one level");
1124 PuppetWidget::PaintTask::Run()
1133 PuppetWidget::PaintNowIfNeeded()
1135 if (IsVisible() && mPaintTask
.IsPending()) {
1140 NS_IMPL_ISUPPORTS(PuppetWidget::MemoryPressureObserver
, nsIObserver
)
1143 PuppetWidget::MemoryPressureObserver::Observe(nsISupports
* aSubject
,
1145 const char16_t
* aData
)
1151 if (strcmp("memory-pressure", aTopic
) == 0 &&
1152 !StringBeginsWith(nsDependentString(aData
),
1153 NS_LITERAL_STRING("low-memory-ongoing"))) {
1154 if (!mWidget
->mVisible
&& mWidget
->mLayerManager
&&
1155 XRE_IsContentProcess()) {
1156 mWidget
->mLayerManager
->ClearCachedResources();
1163 PuppetWidget::MemoryPressureObserver::Remove()
1165 nsCOMPtr
<nsIObserverService
> obs
= mozilla::services::GetObserverService();
1167 obs
->RemoveObserver(this, "memory-pressure");
1173 PuppetWidget::NeedsPaint()
1175 // e10s popups are handled by the parent process, so never should be painted here
1176 if (XRE_IsContentProcess() &&
1177 gRemoteDesktopBehaviorEnabled
&&
1178 mWindowType
== eWindowType_popup
) {
1179 NS_WARNING("Trying to paint an e10s popup in the child process!");
1187 PuppetWidget::GetDPI()
1193 PuppetWidget::GetDefaultScaleInternal()
1195 return mDefaultScale
;
1199 PuppetWidget::RoundsWidgetCoordinatesTo()
1205 PuppetWidget::GetNativeData(uint32_t aDataType
)
1207 switch (aDataType
) {
1208 case NS_NATIVE_SHAREABLE_WINDOW
: {
1209 // NOTE: We can not have a tab child in some situations, such as when we're
1210 // rendering to a fake widget for thumbnails.
1212 NS_WARNING("Need TabChild to get the nativeWindow from!");
1214 mozilla::WindowsHandle nativeData
= 0;
1216 nativeData
= mTabChild
->WidgetNativeData();
1218 return (void*)nativeData
;
1220 case NS_NATIVE_WINDOW
:
1221 case NS_NATIVE_WIDGET
:
1222 case NS_NATIVE_DISPLAY
:
1223 // These types are ignored (see bug 1183828, bug 1240891).
1225 case NS_RAW_NATIVE_IME_CONTEXT
:
1226 MOZ_CRASH("You need to call GetNativeIMEContext() instead");
1227 case NS_NATIVE_PLUGIN_PORT
:
1228 case NS_NATIVE_GRAPHIC
:
1229 case NS_NATIVE_SHELLWIDGET
:
1231 NS_WARNING("nsWindow::GetNativeData called with bad value");
1239 PuppetWidget::SetNativeData(uint32_t aDataType
, uintptr_t aVal
)
1241 switch (aDataType
) {
1242 case NS_NATIVE_CHILD_OF_SHAREABLE_WINDOW
:
1243 MOZ_ASSERT(mTabChild
, "Need TabChild to send the message.");
1245 mTabChild
->SendSetNativeChildOfShareableWindow(aVal
);
1249 NS_WARNING("SetNativeData called with unsupported data type.");
1254 LayoutDeviceIntPoint
1255 PuppetWidget::GetChromeOffset()
1257 if (!GetOwningTabChild()) {
1258 NS_WARNING("PuppetWidget without Tab does not have chrome information.");
1259 return LayoutDeviceIntPoint();
1261 return GetOwningTabChild()->GetChromeOffset();
1264 LayoutDeviceIntPoint
1265 PuppetWidget::GetWindowPosition()
1267 if (!GetOwningTabChild()) {
1268 return LayoutDeviceIntPoint();
1271 int32_t winX
, winY
, winW
, winH
;
1272 NS_ENSURE_SUCCESS(GetOwningTabChild()->GetDimensions(0, &winX
, &winY
, &winW
, &winH
), LayoutDeviceIntPoint());
1273 return LayoutDeviceIntPoint(winX
, winY
) + GetOwningTabChild()->GetClientOffset();
1277 PuppetWidget::GetScreenBounds()
1279 return LayoutDeviceIntRect(WidgetToScreenOffset(), mBounds
.Size());
1282 uint32_t PuppetWidget::GetMaxTouchPoints() const
1284 uint32_t maxTouchPoints
= 0;
1286 mTabChild
->GetMaxTouchPoints(&maxTouchPoints
);
1288 return maxTouchPoints
;
1292 PuppetWidget::StartAsyncScrollbarDrag(const AsyncDragMetrics
& aDragMetrics
)
1294 mTabChild
->StartScrollbarDrag(aDragMetrics
);
1297 PuppetScreen::PuppetScreen(void *nativeScreen
)
1301 PuppetScreen::~PuppetScreen()
1305 static ScreenConfiguration
1308 ScreenConfiguration config
;
1309 hal::GetCurrentScreenConfiguration(&config
);
1314 PuppetWidget::GetScreenDimensions()
1316 nsIntRect r
= ScreenConfig().rect();
1317 return nsIntSize(r
.Width(), r
.Height());
1321 PuppetScreen::GetRect(int32_t *outLeft
, int32_t *outTop
,
1322 int32_t *outWidth
, int32_t *outHeight
)
1324 nsIntRect r
= ScreenConfig().rect();
1325 r
.GetRect(outLeft
, outTop
, outWidth
, outHeight
);
1330 PuppetScreen::GetAvailRect(int32_t *outLeft
, int32_t *outTop
,
1331 int32_t *outWidth
, int32_t *outHeight
)
1333 return GetRect(outLeft
, outTop
, outWidth
, outHeight
);
1337 PuppetScreen::GetPixelDepth(int32_t *aPixelDepth
)
1339 *aPixelDepth
= ScreenConfig().pixelDepth();
1344 PuppetScreen::GetColorDepth(int32_t *aColorDepth
)
1346 *aColorDepth
= ScreenConfig().colorDepth();
1350 NS_IMPL_ISUPPORTS(PuppetScreenManager
, nsIScreenManager
)
1352 PuppetScreenManager::PuppetScreenManager()
1354 mOneScreen
= new PuppetScreen(nullptr);
1357 PuppetScreenManager::~PuppetScreenManager()
1362 PuppetScreenManager::GetPrimaryScreen(nsIScreen
** outScreen
)
1364 NS_IF_ADDREF(*outScreen
= mOneScreen
.get());
1369 PuppetScreenManager::ScreenForRect(int32_t inLeft
,
1373 nsIScreen
** outScreen
)
1375 return GetPrimaryScreen(outScreen
);
1379 PuppetWidget::GetCurrentWidgetListener()
1381 if (!mPreviouslyAttachedWidgetListener
||
1382 !mAttachedWidgetListener
) {
1383 return mAttachedWidgetListener
;
1386 if (mAttachedWidgetListener
->GetView()->IsPrimaryFramePaintSuppressed()) {
1387 return mPreviouslyAttachedWidgetListener
;
1390 return mAttachedWidgetListener
;
1394 PuppetWidget::SetCandidateWindowForPlugin(
1395 const CandidateWindowPosition
& aPosition
)
1401 mTabChild
->SendSetCandidateWindowForPlugin(aPosition
);
1405 PuppetWidget::EnableIMEForPlugin(bool aEnable
)
1411 // If current IME state isn't plugin, we ignore this call.
1412 if (NS_WARN_IF(HaveValidInputContextCache() &&
1413 mInputContext
.mIMEState
.mEnabled
!= IMEState::UNKNOWN
&&
1414 mInputContext
.mIMEState
.mEnabled
!= IMEState::PLUGIN
)) {
1418 // We don't have valid state in cache or state is plugin, so delegate to
1420 mTabChild
->SendEnableIMEForPlugin(aEnable
);
1424 PuppetWidget::ZoomToRect(const uint32_t& aPresShellId
,
1425 const FrameMetrics::ViewID
& aViewId
,
1426 const CSSRect
& aRect
,
1427 const uint32_t& aFlags
)
1433 mTabChild
->ZoomToRect(aPresShellId
, aViewId
, aRect
, aFlags
);
1437 PuppetWidget::LookUpDictionary(
1438 const nsAString
& aText
,
1439 const nsTArray
<mozilla::FontRange
>& aFontRangeArray
,
1440 const bool aIsVertical
,
1441 const LayoutDeviceIntPoint
& aPoint
)
1447 mTabChild
->SendLookUpDictionary(nsString(aText
), aFontRangeArray
, aIsVertical
, aPoint
);
1451 PuppetWidget::HasPendingInputEvent()
1459 mTabChild
->GetIPCChannel()->PeekMessages(
1460 [&ret
](const IPC::Message
& aMsg
) -> bool {
1461 if (nsContentUtils::IsMessageInputEvent(aMsg
)) {
1463 return false; // Stop peeking.
1473 PuppetWidget::HandledWindowedPluginKeyEvent(
1474 const NativeEventData
& aKeyEventData
,
1477 if (NS_WARN_IF(mKeyEventInPluginCallbacks
.IsEmpty())) {
1480 nsCOMPtr
<nsIKeyEventInPluginCallback
> callback
=
1481 mKeyEventInPluginCallbacks
[0];
1482 MOZ_ASSERT(callback
);
1483 mKeyEventInPluginCallbacks
.RemoveElementAt(0);
1484 callback
->HandledWindowedPluginKeyEvent(aKeyEventData
, aIsConsumed
);
1488 PuppetWidget::OnWindowedPluginKeyEvent(const NativeEventData
& aKeyEventData
,
1489 nsIKeyEventInPluginCallback
* aCallback
)
1491 if (NS_WARN_IF(!mTabChild
)) {
1492 return NS_ERROR_NOT_AVAILABLE
;
1494 if (NS_WARN_IF(!mTabChild
->SendOnWindowedPluginKeyEvent(aKeyEventData
))) {
1495 return NS_ERROR_FAILURE
;
1497 mKeyEventInPluginCallbacks
.AppendElement(aCallback
);
1498 return NS_SUCCESS_EVENT_HANDLED_ASYNCHRONOUSLY
;
1501 // TextEventDispatcherListener
1504 PuppetWidget::NotifyIME(TextEventDispatcher
* aTextEventDispatcher
,
1505 const IMENotification
& aIMENotification
)
1507 MOZ_ASSERT(aTextEventDispatcher
== mTextEventDispatcher
);
1509 // If there is different text event dispatcher listener for handling
1510 // text event dispatcher, that means that native keyboard events and
1511 // IME events are handled in this process. Therefore, we don't need
1512 // to send any requests and notifications to the parent process.
1513 if (mNativeTextEventDispatcherListener
) {
1514 return NS_ERROR_NOT_IMPLEMENTED
;
1517 switch (aIMENotification
.mMessage
) {
1518 case REQUEST_TO_COMMIT_COMPOSITION
:
1519 return RequestIMEToCommitComposition(false);
1520 case REQUEST_TO_CANCEL_COMPOSITION
:
1521 return RequestIMEToCommitComposition(true);
1522 case NOTIFY_IME_OF_FOCUS
:
1523 case NOTIFY_IME_OF_BLUR
:
1524 return NotifyIMEOfFocusChange(aIMENotification
);
1525 case NOTIFY_IME_OF_SELECTION_CHANGE
:
1526 return NotifyIMEOfSelectionChange(aIMENotification
);
1527 case NOTIFY_IME_OF_TEXT_CHANGE
:
1528 return NotifyIMEOfTextChange(aIMENotification
);
1529 case NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED
:
1530 return NotifyIMEOfCompositionUpdate(aIMENotification
);
1531 case NOTIFY_IME_OF_MOUSE_BUTTON_EVENT
:
1532 return NotifyIMEOfMouseButtonEvent(aIMENotification
);
1533 case NOTIFY_IME_OF_POSITION_CHANGE
:
1534 return NotifyIMEOfPositionChange(aIMENotification
);
1536 return NS_ERROR_NOT_IMPLEMENTED
;
1539 return NS_ERROR_NOT_IMPLEMENTED
;
1542 NS_IMETHODIMP_(IMENotificationRequests
)
1543 PuppetWidget::GetIMENotificationRequests()
1545 if (mInputContext
.mIMEState
.mEnabled
== IMEState::PLUGIN
) {
1546 // If a plugin has focus, we cannot receive text nor selection change
1547 // in the plugin. Therefore, PuppetWidget needs to receive only position
1548 // change event for updating the editor rect cache.
1549 return IMENotificationRequests(
1550 mIMENotificationRequestsOfParent
.mWantUpdates
|
1551 IMENotificationRequests::NOTIFY_POSITION_CHANGE
);
1553 return IMENotificationRequests(
1554 mIMENotificationRequestsOfParent
.mWantUpdates
|
1555 IMENotificationRequests::NOTIFY_TEXT_CHANGE
|
1556 IMENotificationRequests::NOTIFY_POSITION_CHANGE
);
1559 NS_IMETHODIMP_(void)
1560 PuppetWidget::OnRemovedFrom(TextEventDispatcher
* aTextEventDispatcher
)
1562 MOZ_ASSERT(aTextEventDispatcher
== mTextEventDispatcher
);
1565 NS_IMETHODIMP_(void)
1566 PuppetWidget::WillDispatchKeyboardEvent(
1567 TextEventDispatcher
* aTextEventDispatcher
,
1568 WidgetKeyboardEvent
& aKeyboardEvent
,
1569 uint32_t aIndexOfKeypress
,
1572 MOZ_ASSERT(aTextEventDispatcher
== mTextEventDispatcher
);
1575 } // namespace widget
1576 } // namespace mozilla