1 /* -*- Mode: C++; tab-width: 2; 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/. */
6 #include "mozilla/ArrayUtils.h"
8 #include "mozilla/layers/CompositorChild.h"
9 #include "mozilla/layers/CompositorParent.h"
10 #include "mozilla/layers/ImageBridgeChild.h"
11 #include "nsBaseWidget.h"
12 #include "nsDeviceContext.h"
14 #include "nsGfxCIID.h"
15 #include "nsWidgetsCID.h"
16 #include "nsServiceManagerUtils.h"
17 #include "nsIScreenManager.h"
18 #include "nsAppDirectoryServiceDefs.h"
19 #include "nsISimpleEnumerator.h"
20 #include "nsIContent.h"
21 #include "nsIDocument.h"
22 #include "nsIPresShell.h"
23 #include "nsIServiceManager.h"
24 #include "mozilla/Preferences.h"
25 #include "BasicLayers.h"
26 #include "ClientLayerManager.h"
27 #include "mozilla/layers/Compositor.h"
28 #include "nsIXULRuntime.h"
29 #include "nsIXULWindow.h"
30 #include "nsIBaseWindow.h"
31 #include "nsXULPopupManager.h"
32 #include "nsIWidgetListener.h"
33 #include "nsIGfxInfo.h"
35 #include "base/thread.h"
38 #include "mozilla/Attributes.h"
39 #include "mozilla/unused.h"
40 #include "nsContentUtils.h"
42 #include "mozilla/gfx/2D.h"
43 #include "mozilla/MouseEvents.h"
45 #include "mozilla/unused.h"
46 #include "mozilla/VsyncDispatcher.h"
47 #include "mozilla/layers/APZCTreeManager.h"
48 #include "mozilla/layers/APZEventState.h"
49 #include "mozilla/layers/APZThreadUtils.h"
50 #include "mozilla/layers/ChromeProcessController.h"
51 #include "mozilla/layers/InputAPZContext.h"
52 #include "mozilla/layers/APZCCallbackHelper.h"
53 #include "mozilla/dom/TabParent.h"
54 #include "TouchEvents.h"
56 #include "nsAccessibilityService.h"
60 #include "nsIObserver.h"
62 static void debug_RegisterPrefCallbacks();
66 #ifdef NOISY_WIDGET_LEAKS
67 static int32_t gNumWidgets
;
71 #include "nsCocoaFeatures.h"
74 nsIRollupListener
* nsBaseWidget::gRollupListener
= nullptr;
76 using namespace mozilla::layers
;
77 using namespace mozilla::ipc
;
78 using namespace mozilla
;
81 nsIContent
* nsBaseWidget::mLastRollup
= nullptr;
82 // Global user preference for disabling native theme. Used
83 // in NativeWindowTheme.
84 bool gDisableNativeTheme
= false;
86 // Async pump timer during injected long touch taps
87 #define TOUCH_INJECT_PUMP_TIMER_MSEC 50
88 #define TOUCH_INJECT_LONG_TAP_DEFAULT_MSEC 1500
89 int32_t nsIWidget::sPointerIdCounter
= 0;
92 NS_IMPL_ISUPPORTS(nsBaseWidget
, nsIWidget
)
95 nsAutoRollup::nsAutoRollup()
97 // remember if mLastRollup was null, and only clear it upon destruction
98 // if so. This prevents recursive usage of nsAutoRollup from clearing
99 // mLastRollup when it shouldn't.
100 wasClear
= !nsBaseWidget::mLastRollup
;
103 nsAutoRollup::~nsAutoRollup()
105 if (nsBaseWidget::mLastRollup
&& wasClear
) {
106 NS_RELEASE(nsBaseWidget::mLastRollup
);
110 //-------------------------------------------------------------------------
112 // nsBaseWidget constructor
114 //-------------------------------------------------------------------------
116 nsBaseWidget::nsBaseWidget()
117 : mWidgetListener(nullptr)
118 , mAttachedWidgetListener(nullptr)
120 , mCompositorVsyncDispatcher(nullptr)
121 , mCursor(eCursor_standard
)
122 , mUpdateCursor(true)
123 , mBorderStyle(eBorderStyle_none
)
124 , mUseLayersAcceleration(false)
125 , mForceLayersAcceleration(false)
126 , mTemporarilyUseBasicLayerManager(false)
127 , mUseAttachedEvents(false)
128 , mContextInitialized(false)
130 , mOriginalBounds(nullptr)
132 , mSizeMode(nsSizeMode_Normal
)
133 , mPopupLevel(ePopupLevelTop
)
134 , mPopupType(ePopupTypeAny
)
136 #ifdef NOISY_WIDGET_LEAKS
138 printf("WIDGETS+ = %d\n", gNumWidgets
);
142 debug_RegisterPrefCallbacks();
145 mShutdownObserver
= new WidgetShutdownObserver(this);
146 nsContentUtils::RegisterShutdownObserver(mShutdownObserver
);
149 NS_IMPL_ISUPPORTS(WidgetShutdownObserver
, nsIObserver
)
152 WidgetShutdownObserver::Observe(nsISupports
*aSubject
,
154 const char16_t
*aData
)
156 if (strcmp(aTopic
, NS_XPCOM_SHUTDOWN_OBSERVER_ID
) == 0 &&
159 nsContentUtils::UnregisterShutdownObserver(this);
165 nsBaseWidget::Shutdown()
168 mShutdownObserver
= nullptr;
171 static void DeferredDestroyCompositor(nsRefPtr
<CompositorParent
> aCompositorParent
,
172 nsRefPtr
<CompositorChild
> aCompositorChild
)
174 // Bug 848949 needs to be fixed before
175 // we can close the channel properly
176 //aCompositorChild->Close();
179 void nsBaseWidget::DestroyCompositor()
181 if (mCompositorChild
) {
182 nsRefPtr
<CompositorChild
> compositorChild
= mCompositorChild
.forget();
183 nsRefPtr
<CompositorParent
> compositorParent
= mCompositorParent
.forget();
185 compositorChild
->SendWillStop();
186 // New LayerManager, CompositorParent and CompositorChild might be created
187 // as a result of internal GetLayerManager() call.
188 compositorChild
->Destroy();
190 // The call just made to SendWillStop can result in IPC from the
191 // CompositorParent to the CompositorChild (e.g. caused by the destruction
192 // of shared memory). We need to ensure this gets processed by the
193 // CompositorChild before it gets destroyed. It suffices to ensure that
194 // events already in the MessageLoop get processed before the
195 // CompositorChild is destroyed, so we add a task to the MessageLoop to
196 // handle compositor desctruction.
198 // The DefferedDestroyCompositor task takes ownership of compositorParent and
199 // will release them when it runs.
200 MessageLoop::current()->PostTask(FROM_HERE
,
201 NewRunnableFunction(DeferredDestroyCompositor
, compositorParent
,
206 //-------------------------------------------------------------------------
208 // nsBaseWidget destructor
210 //-------------------------------------------------------------------------
211 nsBaseWidget::~nsBaseWidget()
214 mLayerManager
->GetBackendType() == LayersBackend::LAYERS_BASIC
) {
215 static_cast<BasicLayerManager
*>(mLayerManager
.get())->ClearRetainerWidget();
219 mLayerManager
->Destroy();
220 mLayerManager
= nullptr;
223 if (mShutdownObserver
) {
224 // If the shutdown observer is currently processing observers,
225 // then UnregisterShutdownObserver won't stop our Observer
226 // function from being called. Make sure we don't try
227 // to reference the dead widget.
228 mShutdownObserver
->mWidget
= nullptr;
229 nsContentUtils::UnregisterShutdownObserver(mShutdownObserver
);
234 #ifdef NOISY_WIDGET_LEAKS
236 printf("WIDGETS- = %d\n", gNumWidgets
);
239 NS_IF_RELEASE(mContext
);
240 delete mOriginalBounds
;
242 // Can have base widgets that are things like tooltips which don't have CompositorVsyncDispatchers
243 if (mCompositorVsyncDispatcher
) {
244 mCompositorVsyncDispatcher
->Shutdown();
248 //-------------------------------------------------------------------------
252 //-------------------------------------------------------------------------
253 void nsBaseWidget::BaseCreate(nsIWidget
*aParent
,
254 const nsIntRect
&aRect
,
255 nsDeviceContext
*aContext
,
256 nsWidgetInitData
*aInitData
)
258 static bool gDisableNativeThemeCached
= false;
259 if (!gDisableNativeThemeCached
) {
260 Preferences::AddBoolVarCache(&gDisableNativeTheme
,
261 "mozilla.widget.disable-native-theme",
262 gDisableNativeTheme
);
263 gDisableNativeThemeCached
= true;
266 // keep a reference to the device context
272 mContext
= new nsDeviceContext();
274 mContext
->Init(nullptr);
277 if (nullptr != aInitData
) {
278 mWindowType
= aInitData
->mWindowType
;
279 mBorderStyle
= aInitData
->mBorderStyle
;
280 mPopupLevel
= aInitData
->mPopupLevel
;
281 mPopupType
= aInitData
->mPopupHint
;
282 mRequireOffMainThreadCompositing
= aInitData
->mRequireOffMainThreadCompositing
;
286 aParent
->AddChild(this);
290 NS_IMETHODIMP
nsBaseWidget::CaptureMouse(bool aCapture
)
295 //-------------------------------------------------------------------------
297 // Accessor functions to get/set the client data
299 //-------------------------------------------------------------------------
301 nsIWidgetListener
* nsBaseWidget::GetWidgetListener()
303 return mWidgetListener
;
306 void nsBaseWidget::SetWidgetListener(nsIWidgetListener
* aWidgetListener
)
308 mWidgetListener
= aWidgetListener
;
311 already_AddRefed
<nsIWidget
>
312 nsBaseWidget::CreateChild(const nsIntRect
&aRect
,
313 nsDeviceContext
*aContext
,
314 nsWidgetInitData
*aInitData
,
315 bool aForceUseIWidgetParent
)
317 nsIWidget
* parent
= this;
318 nsNativeWidget nativeParent
= nullptr;
320 if (!aForceUseIWidgetParent
) {
321 // Use only either parent or nativeParent, not both, to match
322 // existing code. Eventually Create() should be divested of its
323 // nativeWidget parameter.
324 nativeParent
= parent
? parent
->GetNativeData(NS_NATIVE_WIDGET
) : nullptr;
325 parent
= nativeParent
? nullptr : parent
;
326 NS_ABORT_IF_FALSE(!parent
|| !nativeParent
, "messed up logic");
329 nsCOMPtr
<nsIWidget
> widget
;
330 if (aInitData
&& aInitData
->mWindowType
== eWindowType_popup
) {
331 widget
= AllocateChildPopupWidget();
333 static NS_DEFINE_IID(kCChildCID
, NS_CHILD_CID
);
334 widget
= do_CreateInstance(kCChildCID
);
338 NS_SUCCEEDED(widget
->Create(parent
, nativeParent
, aRect
,
339 aContext
, aInitData
))) {
340 return widget
.forget();
346 // Attach a view to our widget which we'll send events to.
348 nsBaseWidget::AttachViewToTopLevel(bool aUseAttachedEvents
,
349 nsDeviceContext
*aContext
)
351 NS_ASSERTION((mWindowType
== eWindowType_toplevel
||
352 mWindowType
== eWindowType_dialog
||
353 mWindowType
== eWindowType_invisible
||
354 mWindowType
== eWindowType_child
),
355 "Can't attach to window of that type");
357 mUseAttachedEvents
= aUseAttachedEvents
;
361 NS_IF_RELEASE(mContext
);
370 nsIWidgetListener
* nsBaseWidget::GetAttachedWidgetListener()
372 return mAttachedWidgetListener
;
375 void nsBaseWidget::SetAttachedWidgetListener(nsIWidgetListener
* aListener
)
377 mAttachedWidgetListener
= aListener
;
380 //-------------------------------------------------------------------------
382 // Close this nsBaseWidget
384 //-------------------------------------------------------------------------
385 NS_METHOD
nsBaseWidget::Destroy()
387 // Just in case our parent is the only ref to us
388 nsCOMPtr
<nsIWidget
> kungFuDeathGrip(this);
389 // disconnect from the parent
390 nsIWidget
*parent
= GetParent();
392 parent
->RemoveChild(this);
399 //-------------------------------------------------------------------------
401 // Set this nsBaseWidget's parent
403 //-------------------------------------------------------------------------
404 NS_IMETHODIMP
nsBaseWidget::SetParent(nsIWidget
* aNewParent
)
406 return NS_ERROR_NOT_IMPLEMENTED
;
410 //-------------------------------------------------------------------------
412 // Get this nsBaseWidget parent
414 //-------------------------------------------------------------------------
415 nsIWidget
* nsBaseWidget::GetParent(void)
420 //-------------------------------------------------------------------------
422 // Get this nsBaseWidget top level widget
424 //-------------------------------------------------------------------------
425 nsIWidget
* nsBaseWidget::GetTopLevelWidget()
427 nsIWidget
*topLevelWidget
= nullptr, *widget
= this;
429 topLevelWidget
= widget
;
430 widget
= widget
->GetParent();
432 return topLevelWidget
;
435 //-------------------------------------------------------------------------
437 // Get this nsBaseWidget's top (non-sheet) parent (if it's a sheet)
439 //-------------------------------------------------------------------------
440 nsIWidget
* nsBaseWidget::GetSheetWindowParent(void)
445 float nsBaseWidget::GetDPI()
450 CSSToLayoutDeviceScale
nsIWidget::GetDefaultScale()
452 double devPixelsPerCSSPixel
= DefaultScaleOverride();
454 if (devPixelsPerCSSPixel
<= 0.0) {
455 devPixelsPerCSSPixel
= GetDefaultScaleInternal();
458 return CSSToLayoutDeviceScale(devPixelsPerCSSPixel
);
462 double nsIWidget::DefaultScaleOverride()
464 // The number of device pixels per CSS pixel. A value <= 0 means choose
465 // automatically based on the DPI. A positive value is used as-is. This effectively
466 // controls the size of a CSS "px".
467 double devPixelsPerCSSPixel
= -1.0;
469 nsAdoptingCString prefString
= Preferences::GetCString("layout.css.devPixelsPerPx");
470 if (!prefString
.IsEmpty()) {
471 devPixelsPerCSSPixel
= PR_strtod(prefString
, nullptr);
474 return devPixelsPerCSSPixel
;
477 //-------------------------------------------------------------------------
479 // Add a child to the list of children
481 //-------------------------------------------------------------------------
482 void nsBaseWidget::AddChild(nsIWidget
* aChild
)
484 NS_PRECONDITION(!aChild
->GetNextSibling() && !aChild
->GetPrevSibling(),
485 "aChild not properly removed from its old child list");
488 mFirstChild
= mLastChild
= aChild
;
490 // append to the list
491 NS_ASSERTION(mLastChild
, "Bogus state");
492 NS_ASSERTION(!mLastChild
->GetNextSibling(), "Bogus state");
493 mLastChild
->SetNextSibling(aChild
);
494 aChild
->SetPrevSibling(mLastChild
);
500 //-------------------------------------------------------------------------
502 // Remove a child from the list of children
504 //-------------------------------------------------------------------------
505 void nsBaseWidget::RemoveChild(nsIWidget
* aChild
)
509 // nsCocoaWindow doesn't implement GetParent, so in that case parent will be
510 // null and we'll just have to do without this assertion.
511 nsIWidget
* parent
= aChild
->GetParent();
512 NS_ASSERTION(!parent
|| parent
== this, "Not one of our kids!");
514 NS_ASSERTION(aChild
->GetParent() == this, "Not one of our kids!");
518 if (mLastChild
== aChild
) {
519 mLastChild
= mLastChild
->GetPrevSibling();
521 if (mFirstChild
== aChild
) {
522 mFirstChild
= mFirstChild
->GetNextSibling();
525 // Now remove from the list. Make sure that we pass ownership of the tail
526 // of the list correctly before we have aChild let go of it.
527 nsIWidget
* prev
= aChild
->GetPrevSibling();
528 nsIWidget
* next
= aChild
->GetNextSibling();
530 prev
->SetNextSibling(next
);
533 next
->SetPrevSibling(prev
);
536 aChild
->SetNextSibling(nullptr);
537 aChild
->SetPrevSibling(nullptr);
541 //-------------------------------------------------------------------------
543 // Sets widget's position within its parent's child list.
545 //-------------------------------------------------------------------------
546 void nsBaseWidget::SetZIndex(int32_t aZIndex
)
548 // Hold a ref to ourselves just in case, since we're going to remove
550 nsCOMPtr
<nsIWidget
> kungFuDeathGrip(this);
554 // reorder this child in its parent's list.
555 nsBaseWidget
* parent
= static_cast<nsBaseWidget
*>(GetParent());
557 parent
->RemoveChild(this);
558 // Scope sib outside the for loop so we can check it afterward
559 nsIWidget
* sib
= parent
->GetFirstChild();
560 for ( ; sib
; sib
= sib
->GetNextSibling()) {
561 int32_t childZIndex
= GetZIndex();
562 if (aZIndex
< childZIndex
) {
563 // Insert ourselves before sib
564 nsIWidget
* prev
= sib
->GetPrevSibling();
567 sib
->SetPrevSibling(this);
569 prev
->SetNextSibling(this);
571 NS_ASSERTION(sib
== parent
->mFirstChild
, "Broken child list");
572 // We've taken ownership of sib, so it's safe to have parent let
574 parent
->mFirstChild
= this;
576 PlaceBehind(eZPlacementBelow
, sib
, false);
580 // were we added to the list?
582 parent
->AddChild(this);
587 //-------------------------------------------------------------------------
589 // Places widget behind the given widget (platforms must override)
591 //-------------------------------------------------------------------------
592 NS_IMETHODIMP
nsBaseWidget::PlaceBehind(nsTopLevelWidgetZPlacement aPlacement
,
593 nsIWidget
*aWidget
, bool aActivate
)
598 //-------------------------------------------------------------------------
600 // Maximize, minimize or restore the window. The BaseWidget implementation
601 // merely stores the state.
603 //-------------------------------------------------------------------------
604 NS_IMETHODIMP
nsBaseWidget::SetSizeMode(int32_t aMode
)
606 if (aMode
== nsSizeMode_Normal
||
607 aMode
== nsSizeMode_Minimized
||
608 aMode
== nsSizeMode_Maximized
||
609 aMode
== nsSizeMode_Fullscreen
) {
611 mSizeMode
= (nsSizeMode
) aMode
;
614 return NS_ERROR_ILLEGAL_VALUE
;
617 //-------------------------------------------------------------------------
619 // Get this component cursor
621 //-------------------------------------------------------------------------
622 nsCursor
nsBaseWidget::GetCursor()
627 NS_METHOD
nsBaseWidget::SetCursor(nsCursor aCursor
)
633 NS_IMETHODIMP
nsBaseWidget::SetCursor(imgIContainer
* aCursor
,
634 uint32_t aHotspotX
, uint32_t aHotspotY
)
636 return NS_ERROR_NOT_IMPLEMENTED
;
639 //-------------------------------------------------------------------------
641 // Window transparency methods
643 //-------------------------------------------------------------------------
645 void nsBaseWidget::SetTransparencyMode(nsTransparencyMode aMode
) {
648 nsTransparencyMode
nsBaseWidget::GetTransparencyMode() {
649 return eTransparencyOpaque
;
653 nsBaseWidget::IsWindowClipRegionEqual(const nsTArray
<nsIntRect
>& aRects
)
656 mClipRectCount
== aRects
.Length() &&
657 memcmp(mClipRects
, aRects
.Elements(), sizeof(nsIntRect
)*mClipRectCount
) == 0;
661 nsBaseWidget::StoreWindowClipRegion(const nsTArray
<nsIntRect
>& aRects
)
663 mClipRectCount
= aRects
.Length();
664 mClipRects
= new nsIntRect
[mClipRectCount
];
666 memcpy(mClipRects
, aRects
.Elements(), sizeof(nsIntRect
)*mClipRectCount
);
671 nsBaseWidget::GetWindowClipRegion(nsTArray
<nsIntRect
>* aRects
)
674 aRects
->AppendElements(mClipRects
.get(), mClipRectCount
);
676 aRects
->AppendElement(nsIntRect(0, 0, mBounds
.width
, mBounds
.height
));
681 nsBaseWidget::RegionFromArray(const nsTArray
<nsIntRect
>& aRects
)
684 for (uint32_t i
= 0; i
< aRects
.Length(); ++i
) {
685 region
.Or(region
, aRects
[i
]);
691 nsBaseWidget::ArrayFromRegion(const nsIntRegion
& aRegion
, nsTArray
<nsIntRect
>& aRects
)
694 for (nsIntRegionRectIterator
iter(aRegion
); (r
= iter
.Next());) {
695 aRects
.AppendElement(*r
);
700 nsBaseWidget::SetWindowClipRegion(const nsTArray
<nsIntRect
>& aRects
,
701 bool aIntersectWithExisting
)
703 if (!aIntersectWithExisting
) {
704 StoreWindowClipRegion(aRects
);
707 nsTArray
<nsIntRect
> currentRects
;
708 GetWindowClipRegion(¤tRects
);
709 // create region from them
710 nsIntRegion currentRegion
= RegionFromArray(currentRects
);
711 // create region from new rects
712 nsIntRegion newRegion
= RegionFromArray(aRects
);
714 nsIntRegion intersection
;
715 intersection
.And(currentRegion
, newRegion
);
716 // create int rect array from intersection
717 nsTArray
<nsIntRect
> rects
;
718 ArrayFromRegion(intersection
, rects
);
720 StoreWindowClipRegion(rects
);
725 //-------------------------------------------------------------------------
727 // Set window shadow style
729 //-------------------------------------------------------------------------
731 NS_IMETHODIMP
nsBaseWidget::SetWindowShadowStyle(int32_t aMode
)
733 return NS_ERROR_NOT_IMPLEMENTED
;
736 //-------------------------------------------------------------------------
738 // Hide window borders/decorations for this widget
740 //-------------------------------------------------------------------------
741 NS_IMETHODIMP
nsBaseWidget::HideWindowChrome(bool aShouldHide
)
743 return NS_ERROR_NOT_IMPLEMENTED
;
746 //-------------------------------------------------------------------------
748 // Put the window into full-screen mode
750 //-------------------------------------------------------------------------
751 NS_IMETHODIMP
nsBaseWidget::MakeFullScreen(bool aFullScreen
, nsIScreen
* aScreen
)
753 HideWindowChrome(aFullScreen
);
756 if (!mOriginalBounds
)
757 mOriginalBounds
= new nsIntRect();
758 GetScreenBounds(*mOriginalBounds
);
759 // convert dev pix to display pix for window manipulation
760 CSSToLayoutDeviceScale scale
= GetDefaultScale();
761 mOriginalBounds
->x
= NSToIntRound(mOriginalBounds
->x
/ scale
.scale
);
762 mOriginalBounds
->y
= NSToIntRound(mOriginalBounds
->y
/ scale
.scale
);
763 mOriginalBounds
->width
= NSToIntRound(mOriginalBounds
->width
/ scale
.scale
);
764 mOriginalBounds
->height
= NSToIntRound(mOriginalBounds
->height
/ scale
.scale
);
766 // Move to top-left corner of screen and size to the screen dimensions
767 nsCOMPtr
<nsIScreenManager
> screenManager
;
768 screenManager
= do_GetService("@mozilla.org/gfx/screenmanager;1");
769 NS_ASSERTION(screenManager
, "Unable to grab screenManager.");
771 nsCOMPtr
<nsIScreen
> screen
= aScreen
;
773 // no screen was passed in, use the one that the window is on
774 screenManager
->ScreenForRect(mOriginalBounds
->x
,
776 mOriginalBounds
->width
,
777 mOriginalBounds
->height
,
778 getter_AddRefs(screen
));
782 int32_t left
, top
, width
, height
;
783 if (NS_SUCCEEDED(screen
->GetRectDisplayPix(&left
, &top
, &width
, &height
))) {
784 Resize(left
, top
, width
, height
, true);
789 } else if (mOriginalBounds
) {
790 Resize(mOriginalBounds
->x
, mOriginalBounds
->y
, mOriginalBounds
->width
,
791 mOriginalBounds
->height
, true);
797 nsBaseWidget::AutoLayerManagerSetup::AutoLayerManagerSetup(
798 nsBaseWidget
* aWidget
, gfxContext
* aTarget
,
799 BufferMode aDoubleBuffering
, ScreenRotation aRotation
)
802 mLayerManager
= static_cast<BasicLayerManager
*>(mWidget
->GetLayerManager());
804 NS_ASSERTION(mLayerManager
->GetBackendType() == LayersBackend::LAYERS_BASIC
,
805 "AutoLayerManagerSetup instantiated for non-basic layer backend!");
806 mLayerManager
->SetDefaultTarget(aTarget
);
807 mLayerManager
->SetDefaultTargetConfiguration(aDoubleBuffering
, aRotation
);
811 nsBaseWidget::AutoLayerManagerSetup::~AutoLayerManagerSetup()
814 NS_ASSERTION(mLayerManager
->GetBackendType() == LayersBackend::LAYERS_BASIC
,
815 "AutoLayerManagerSetup instantiated for non-basic layer backend!");
816 mLayerManager
->SetDefaultTarget(nullptr);
817 mLayerManager
->SetDefaultTargetConfiguration(mozilla::layers::BufferMode::BUFFER_NONE
, ROTATION_0
);
821 nsBaseWidget::AutoUseBasicLayerManager::AutoUseBasicLayerManager(nsBaseWidget
* aWidget
)
824 mPreviousTemporarilyUseBasicLayerManager
=
825 mWidget
->mTemporarilyUseBasicLayerManager
;
826 mWidget
->mTemporarilyUseBasicLayerManager
= true;
829 nsBaseWidget::AutoUseBasicLayerManager::~AutoUseBasicLayerManager()
831 mWidget
->mTemporarilyUseBasicLayerManager
=
832 mPreviousTemporarilyUseBasicLayerManager
;
836 nsBaseWidget::ComputeShouldAccelerate(bool aDefault
)
838 #if defined(XP_WIN) || defined(ANDROID) || \
839 defined(MOZ_GL_PROVIDER) || defined(XP_MACOSX) || defined(MOZ_WIDGET_QT)
840 bool accelerateByDefault
= true;
842 bool accelerateByDefault
= false;
846 // 10.6.2 and lower have a bug involving textures and pixel buffer objects
847 // that caused bug 629016, so we don't allow OpenGL-accelerated layers on
848 // those versions of the OS.
849 // This will still let full-screen video be accelerated on OpenGL, because
850 // that XUL widget opts in to acceleration, but that's probably OK.
851 accelerateByDefault
= nsCocoaFeatures::AccelerateByDefault();
854 // we should use AddBoolPrefVarCache
855 bool disableAcceleration
= gfxPrefs::LayersAccelerationDisabled();
856 mForceLayersAcceleration
= gfxPrefs::LayersAccelerationForceEnabled();
858 const char *acceleratedEnv
= PR_GetEnv("MOZ_ACCELERATED");
859 accelerateByDefault
= accelerateByDefault
||
860 (acceleratedEnv
&& (*acceleratedEnv
!= '0'));
862 nsCOMPtr
<nsIXULRuntime
> xr
= do_GetService("@mozilla.org/xre/runtime;1");
863 bool safeMode
= false;
865 xr
->GetInSafeMode(&safeMode
);
867 bool whitelisted
= false;
869 nsCOMPtr
<nsIGfxInfo
> gfxInfo
= do_GetService("@mozilla.org/gfx/info;1");
871 // bug 655578: on X11 at least, we must always call GetData (even if we don't need that information)
872 // as that's what causes GfxInfo initialization which kills the zombie 'glxtest' process.
873 // initially we relied on the fact that GetFeatureStatus calls GetData for us, but bug 681026 showed
874 // that assumption to be unsafe.
878 if (NS_SUCCEEDED(gfxInfo
->GetFeatureStatus(nsIGfxInfo::FEATURE_OPENGL_LAYERS
, &status
))) {
879 if (status
== nsIGfxInfo::FEATURE_STATUS_OK
) {
885 if (disableAcceleration
|| safeMode
)
888 if (mForceLayersAcceleration
)
892 static int tell_me_once
= 0;
894 NS_WARNING("OpenGL-accelerated layers are not supported on this system");
897 #ifdef MOZ_WIDGET_ANDROID
898 NS_RUNTIMEABORT("OpenGL-accelerated layers are a hard requirement on this platform. "
899 "Cannot continue without support for them");
904 if (accelerateByDefault
)
907 /* use the window acceleration flag */
911 CompositorParent
* nsBaseWidget::NewCompositorParent(int aSurfaceWidth
,
914 return new CompositorParent(this, false, aSurfaceWidth
, aSurfaceHeight
);
917 void nsBaseWidget::CreateCompositor()
921 CreateCompositor(rect
.width
, rect
.height
);
924 already_AddRefed
<GeckoContentController
>
925 nsBaseWidget::CreateRootContentController()
927 nsRefPtr
<GeckoContentController
> controller
= new ChromeProcessController(this, mAPZEventState
);
928 return controller
.forget();
931 class ChromeProcessSetTargetAPZCCallback
: public SetTargetAPZCCallback
{
933 explicit ChromeProcessSetTargetAPZCCallback(APZCTreeManager
* aTreeManager
)
934 : mTreeManager(aTreeManager
)
937 void Run(uint64_t aInputBlockId
, const nsTArray
<ScrollableLayerGuid
>& aTargets
) const MOZ_OVERRIDE
{
938 MOZ_ASSERT(NS_IsMainThread());
939 // need a local var to disambiguate between the SetTargetAPZC overloads.
940 void (APZCTreeManager::*setTargetApzcFunc
)(uint64_t, const nsTArray
<ScrollableLayerGuid
>&)
941 = &APZCTreeManager::SetTargetAPZC
;
942 APZThreadUtils::RunOnControllerThread(NewRunnableMethod(
943 mTreeManager
.get(), setTargetApzcFunc
, aInputBlockId
, aTargets
));
947 nsRefPtr
<APZCTreeManager
> mTreeManager
;
950 class ChromeProcessContentReceivedInputBlockCallback
: public ContentReceivedInputBlockCallback
{
952 explicit ChromeProcessContentReceivedInputBlockCallback(APZCTreeManager
* aTreeManager
)
953 : mTreeManager(aTreeManager
)
956 void Run(const ScrollableLayerGuid
& aGuid
, uint64_t aInputBlockId
, bool aPreventDefault
) const MOZ_OVERRIDE
{
957 MOZ_ASSERT(NS_IsMainThread());
958 APZThreadUtils::RunOnControllerThread(NewRunnableMethod(
959 mTreeManager
.get(), &APZCTreeManager::ContentReceivedInputBlock
,
960 aInputBlockId
, aPreventDefault
));
964 nsRefPtr
<APZCTreeManager
> mTreeManager
;
968 void nsBaseWidget::ConfigureAPZCTreeManager()
970 uint64_t rootLayerTreeId
= mCompositorParent
->RootLayerTreeId();
971 mAPZC
= CompositorParent::GetAPZCTreeManager(rootLayerTreeId
);
974 mAPZC
->SetDPI(GetDPI());
975 mAPZEventState
= new APZEventState(this,
976 new ChromeProcessContentReceivedInputBlockCallback(mAPZC
));
977 mSetTargetAPZCCallback
= new ChromeProcessSetTargetAPZCCallback(mAPZC
);
979 nsRefPtr
<GeckoContentController
> controller
= CreateRootContentController();
981 CompositorParent::SetControllerForLayerTree(rootLayerTreeId
, controller
);
986 nsBaseWidget::DispatchEventForAPZ(WidgetGUIEvent
* aEvent
,
987 const ScrollableLayerGuid
& aGuid
,
988 uint64_t aInputBlockId
)
990 MOZ_ASSERT(NS_IsMainThread());
991 InputAPZContext
context(aGuid
, aInputBlockId
);
993 // If this is a touch event and APZ has targeted it to an APZC in the root
994 // process, apply that APZC's callback-transform before dispatching the
995 // event. If the event is instead targeted to an APZC in the child process,
996 // the transform will be applied in the child process before dispatching
997 // the event there (see e.g. TabChild::RecvRealTouchEvent()).
998 // TODO: Do other types of events (than touch) need this?
999 if (aEvent
->AsTouchEvent() && aGuid
.mLayersId
== mCompositorParent
->RootLayerTreeId()) {
1000 APZCCallbackHelper::ApplyCallbackTransform(*aEvent
->AsTouchEvent(), aGuid
,
1001 GetDefaultScale(), 1.0f
);
1004 nsEventStatus status
;
1005 DispatchEvent(aEvent
, status
);
1007 if (mAPZC
&& !context
.WasRoutedToChildProcess()) {
1008 // EventStateManager did not route the event into the child process.
1009 // It's safe to communicate to APZ that the event has been processed.
1010 // TODO: Eventually we'll be able to move the SendSetTargetAPZCNotification
1011 // call into APZEventState::Process*Event() as well.
1012 if (WidgetTouchEvent
* touchEvent
= aEvent
->AsTouchEvent()) {
1013 if (touchEvent
->message
== NS_TOUCH_START
) {
1014 APZCCallbackHelper::SendSetTargetAPZCNotification(this, GetDocument(), *aEvent
,
1015 aGuid
, aInputBlockId
, mSetTargetAPZCCallback
);
1017 mAPZEventState
->ProcessTouchEvent(*touchEvent
, aGuid
, aInputBlockId
);
1018 } else if (WidgetWheelEvent
* wheelEvent
= aEvent
->AsWheelEvent()) {
1019 APZCCallbackHelper::SendSetTargetAPZCNotification(this, GetDocument(), *aEvent
,
1020 aGuid
, aInputBlockId
, mSetTargetAPZCCallback
);
1021 mAPZEventState
->ProcessWheelEvent(*wheelEvent
, aGuid
, aInputBlockId
);
1029 nsBaseWidget::GetPreferredCompositorBackends(nsTArray
<LayersBackend
>& aHints
)
1031 if (mUseLayersAcceleration
) {
1032 aHints
.AppendElement(LayersBackend::LAYERS_OPENGL
);
1035 aHints
.AppendElement(LayersBackend::LAYERS_BASIC
);
1039 nsBaseWidget::GetDocument() const
1041 if (mWidgetListener
) {
1042 if (nsIPresShell
* presShell
= mWidgetListener
->GetPresShell()) {
1043 return presShell
->GetDocument();
1049 void nsBaseWidget::CreateCompositorVsyncDispatcher()
1051 if (gfxPrefs::HardwareVsyncEnabled()) {
1052 // Parent directly listens to the vsync source whereas
1053 // child process communicate via IPC
1054 // Should be called AFTER gfxPlatform is initialized
1055 if (XRE_IsParentProcess()) {
1056 mCompositorVsyncDispatcher
= new CompositorVsyncDispatcher();
1061 CompositorVsyncDispatcher
*
1062 nsBaseWidget::GetCompositorVsyncDispatcher()
1064 return mCompositorVsyncDispatcher
;
1067 void nsBaseWidget::CreateCompositor(int aWidth
, int aHeight
)
1069 // This makes sure that gfxPlatforms gets initialized if it hasn't by now.
1070 gfxPlatform::GetPlatform();
1072 MOZ_ASSERT(gfxPlatform::UsesOffMainThreadCompositing(),
1073 "This function assumes OMTC");
1075 MOZ_ASSERT(!mCompositorParent
,
1076 "Should have properly cleaned up the previous CompositorParent beforehand");
1078 // Recreating this is tricky, as we may still have an old and we need
1079 // to make sure it's properly destroyed by calling DestroyCompositor!
1081 // If we've already received a shutdown notification, don't try
1082 // create a new compositor.
1083 if (!mShutdownObserver
) {
1087 CreateCompositorVsyncDispatcher();
1088 mCompositorParent
= NewCompositorParent(aWidth
, aHeight
);
1089 MessageChannel
*parentChannel
= mCompositorParent
->GetIPCChannel();
1090 nsRefPtr
<ClientLayerManager
> lm
= new ClientLayerManager(this);
1091 MessageLoop
*childMessageLoop
= CompositorParent::CompositorLoop();
1092 mCompositorChild
= new CompositorChild(lm
);
1093 mCompositorChild
->Open(parentChannel
, childMessageLoop
, ipc::ChildSide
);
1095 if (gfxPrefs::AsyncPanZoomEnabled() &&
1096 (WindowType() == eWindowType_toplevel
|| WindowType() == eWindowType_child
)) {
1097 ConfigureAPZCTreeManager();
1100 TextureFactoryIdentifier textureFactoryIdentifier
;
1101 PLayerTransactionChild
* shadowManager
= nullptr;
1102 nsTArray
<LayersBackend
> backendHints
;
1103 GetPreferredCompositorBackends(backendHints
);
1105 #if !defined(MOZ_X11) && !defined(XP_WIN)
1106 if (!mRequireOffMainThreadCompositing
&&
1107 !Preferences::GetBool("layers.offmainthreadcomposition.force-basic", false)) {
1108 for (size_t i
= 0; i
< backendHints
.Length(); ++i
) {
1109 if (backendHints
[i
] == LayersBackend::LAYERS_BASIC
) {
1110 backendHints
[i
] = LayersBackend::LAYERS_NONE
;
1116 bool success
= false;
1117 if (!backendHints
.IsEmpty()) {
1118 shadowManager
= mCompositorChild
->SendPLayerTransactionConstructor(
1119 backendHints
, 0, &textureFactoryIdentifier
, &success
);
1123 ShadowLayerForwarder
* lf
= lm
->AsShadowForwarder();
1126 mCompositorChild
= nullptr;
1129 lf
->SetShadowManager(shadowManager
);
1130 lf
->IdentifyTextureHost(textureFactoryIdentifier
);
1131 ImageBridgeChild::IdentifyCompositorTextureHost(textureFactoryIdentifier
);
1134 mLayerManager
= lm
.forget();
1138 NS_WARNING("Failed to create an OMT compositor.");
1139 DestroyCompositor();
1140 // Compositor child had the only reference to LayerManager and will have
1141 // deallocated it when being freed.
1144 bool nsBaseWidget::ShouldUseOffMainThreadCompositing()
1146 return gfxPlatform::UsesOffMainThreadCompositing();
1149 LayerManager
* nsBaseWidget::GetLayerManager(PLayerTransactionChild
* aShadowManager
,
1150 LayersBackend aBackendHint
,
1151 LayerManagerPersistence aPersistence
,
1152 bool* aAllowRetaining
)
1154 if (!mLayerManager
) {
1156 mUseLayersAcceleration
= ComputeShouldAccelerate(mUseLayersAcceleration
);
1158 // Try to use an async compositor first, if possible
1159 if (ShouldUseOffMainThreadCompositing()) {
1160 // e10s uses the parameter to pass in the shadow manager from the TabChild
1161 // so we don't expect to see it there since this doesn't support e10s.
1162 NS_ASSERTION(aShadowManager
== nullptr, "Async Compositor not supported with e10s");
1166 if (!mLayerManager
) {
1167 mLayerManager
= CreateBasicLayerManager();
1170 if (mTemporarilyUseBasicLayerManager
&& !mBasicLayerManager
) {
1171 mBasicLayerManager
= CreateBasicLayerManager();
1173 LayerManager
* usedLayerManager
= mTemporarilyUseBasicLayerManager
?
1174 mBasicLayerManager
: mLayerManager
;
1175 if (aAllowRetaining
) {
1176 *aAllowRetaining
= (usedLayerManager
== mLayerManager
);
1178 return usedLayerManager
;
1181 LayerManager
* nsBaseWidget::CreateBasicLayerManager()
1183 return new BasicLayerManager(this);
1186 CompositorChild
* nsBaseWidget::GetRemoteRenderer()
1188 return mCompositorChild
;
1191 TemporaryRef
<mozilla::gfx::DrawTarget
> nsBaseWidget::StartRemoteDrawing()
1196 //-------------------------------------------------------------------------
1198 // Return the used device context
1200 //-------------------------------------------------------------------------
1201 nsDeviceContext
* nsBaseWidget::GetDeviceContext()
1203 if (!mContextInitialized
) {
1204 mContext
->Init(this);
1205 mContextInitialized
= true;
1210 //-------------------------------------------------------------------------
1212 // Destroy the window
1214 //-------------------------------------------------------------------------
1215 void nsBaseWidget::OnDestroy()
1217 // release references to device context and app shell
1218 NS_IF_RELEASE(mContext
);
1221 NS_METHOD
nsBaseWidget::SetWindowClass(const nsAString
& xulWinType
)
1223 return NS_ERROR_NOT_IMPLEMENTED
;
1226 NS_METHOD
nsBaseWidget::MoveClient(double aX
, double aY
)
1228 nsIntPoint
clientOffset(GetClientOffset());
1230 // GetClientOffset returns device pixels; scale back to display pixels
1231 // if that's what this widget uses for the Move/Resize APIs
1232 CSSToLayoutDeviceScale scale
= BoundsUseDisplayPixels()
1234 : CSSToLayoutDeviceScale(1.0);
1235 aX
-= clientOffset
.x
* 1.0 / scale
.scale
;
1236 aY
-= clientOffset
.y
* 1.0 / scale
.scale
;
1238 return Move(aX
, aY
);
1241 NS_METHOD
nsBaseWidget::ResizeClient(double aWidth
,
1245 NS_ASSERTION((aWidth
>=0) , "Negative width passed to ResizeClient");
1246 NS_ASSERTION((aHeight
>=0), "Negative height passed to ResizeClient");
1248 nsIntRect clientBounds
;
1249 GetClientBounds(clientBounds
);
1251 // GetClientBounds and mBounds are device pixels; scale back to display pixels
1252 // if that's what this widget uses for the Move/Resize APIs
1253 CSSToLayoutDeviceScale scale
= BoundsUseDisplayPixels()
1255 : CSSToLayoutDeviceScale(1.0);
1256 double invScale
= 1.0 / scale
.scale
;
1257 aWidth
= mBounds
.width
* invScale
+ (aWidth
- clientBounds
.width
* invScale
);
1258 aHeight
= mBounds
.height
* invScale
+ (aHeight
- clientBounds
.height
* invScale
);
1260 return Resize(aWidth
, aHeight
, aRepaint
);
1263 NS_METHOD
nsBaseWidget::ResizeClient(double aX
,
1269 NS_ASSERTION((aWidth
>=0) , "Negative width passed to ResizeClient");
1270 NS_ASSERTION((aHeight
>=0), "Negative height passed to ResizeClient");
1272 nsIntRect clientBounds
;
1273 GetClientBounds(clientBounds
);
1275 double scale
= BoundsUseDisplayPixels() ? 1.0 / GetDefaultScale().scale
: 1.0;
1276 aWidth
= mBounds
.width
* scale
+ (aWidth
- clientBounds
.width
* scale
);
1277 aHeight
= mBounds
.height
* scale
+ (aHeight
- clientBounds
.height
* scale
);
1279 nsIntPoint
clientOffset(GetClientOffset());
1280 aX
-= clientOffset
.x
* scale
;
1281 aY
-= clientOffset
.y
* scale
;
1283 return Resize(aX
, aY
, aWidth
, aHeight
, aRepaint
);
1286 //-------------------------------------------------------------------------
1290 //-------------------------------------------------------------------------
1293 * If the implementation of nsWindow supports borders this method MUST be overridden
1296 NS_METHOD
nsBaseWidget::GetClientBounds(nsIntRect
&aRect
)
1298 return GetBounds(aRect
);
1302 * If the implementation of nsWindow supports borders this method MUST be overridden
1305 NS_METHOD
nsBaseWidget::GetBounds(nsIntRect
&aRect
)
1312 * If the implementation of nsWindow uses a local coordinate system within the window,
1313 * this method must be overridden
1316 NS_METHOD
nsBaseWidget::GetScreenBounds(nsIntRect
&aRect
)
1318 return GetBounds(aRect
);
1321 NS_METHOD
nsBaseWidget::GetRestoredBounds(nsIntRect
&aRect
)
1323 if (SizeMode() != nsSizeMode_Normal
) {
1324 return NS_ERROR_FAILURE
;
1326 return GetScreenBounds(aRect
);
1329 nsIntPoint
nsBaseWidget::GetClientOffset()
1331 return nsIntPoint(0, 0);
1335 nsBaseWidget::GetNonClientMargins(nsIntMargin
&margins
)
1337 return NS_ERROR_NOT_IMPLEMENTED
;
1341 nsBaseWidget::SetNonClientMargins(nsIntMargin
&margins
)
1343 return NS_ERROR_NOT_IMPLEMENTED
;
1346 NS_METHOD
nsBaseWidget::EnableDragDrop(bool aEnable
)
1351 uint32_t nsBaseWidget::GetMaxTouchPoints() const
1356 NS_METHOD
nsBaseWidget::SetModal(bool aModal
)
1358 return NS_ERROR_FAILURE
;
1362 nsBaseWidget::GetAttention(int32_t aCycleCount
) {
1367 nsBaseWidget::HasPendingInputEvent()
1373 nsBaseWidget::SetIcon(const nsAString
&)
1379 nsBaseWidget::SetWindowTitlebarColor(nscolor aColor
, bool aActive
)
1381 return NS_ERROR_NOT_IMPLEMENTED
;
1385 nsBaseWidget::ShowsResizeIndicator(nsIntRect
* aResizerRect
)
1390 NS_METHOD
nsBaseWidget::RegisterTouchWindow()
1392 return NS_ERROR_NOT_IMPLEMENTED
;
1395 NS_METHOD
nsBaseWidget::UnregisterTouchWindow()
1397 return NS_ERROR_NOT_IMPLEMENTED
;
1401 nsBaseWidget::OverrideSystemMouseScrollSpeed(double aOriginalDeltaX
,
1402 double aOriginalDeltaY
,
1403 double& aOverriddenDeltaX
,
1404 double& aOverriddenDeltaY
)
1406 aOverriddenDeltaX
= aOriginalDeltaX
;
1407 aOverriddenDeltaY
= aOriginalDeltaY
;
1409 static bool sInitialized
= false;
1410 static bool sIsOverrideEnabled
= false;
1411 static int32_t sIntFactorX
= 0;
1412 static int32_t sIntFactorY
= 0;
1414 if (!sInitialized
) {
1415 Preferences::AddBoolVarCache(&sIsOverrideEnabled
,
1416 "mousewheel.system_scroll_override_on_root_content.enabled", false);
1417 Preferences::AddIntVarCache(&sIntFactorX
,
1418 "mousewheel.system_scroll_override_on_root_content.horizontal.factor", 0);
1419 Preferences::AddIntVarCache(&sIntFactorY
,
1420 "mousewheel.system_scroll_override_on_root_content.vertical.factor", 0);
1421 sIntFactorX
= std::max(sIntFactorX
, 0);
1422 sIntFactorY
= std::max(sIntFactorY
, 0);
1423 sInitialized
= true;
1426 if (!sIsOverrideEnabled
) {
1430 // The pref value must be larger than 100, otherwise, we don't override the
1432 if (sIntFactorX
> 100) {
1433 double factor
= static_cast<double>(sIntFactorX
) / 100;
1434 aOverriddenDeltaX
*= factor
;
1436 if (sIntFactorY
> 100) {
1437 double factor
= static_cast<double>(sIntFactorY
) / 100;
1438 aOverriddenDeltaY
*= factor
;
1446 * Modifies aFile to point at an icon file with the given name and suffix. The
1447 * suffix may correspond to a file extension with leading '.' if appropriate.
1448 * Returns true if the icon file exists and can be read.
1451 ResolveIconNameHelper(nsIFile
*aFile
,
1452 const nsAString
&aIconName
,
1453 const nsAString
&aIconSuffix
)
1455 aFile
->Append(NS_LITERAL_STRING("icons"));
1456 aFile
->Append(NS_LITERAL_STRING("default"));
1457 aFile
->Append(aIconName
+ aIconSuffix
);
1460 return NS_SUCCEEDED(aFile
->IsReadable(&readable
)) && readable
;
1464 * Resolve the given icon name into a local file object. This method is
1465 * intended to be called by subclasses of nsBaseWidget. aIconSuffix is a
1466 * platform specific icon file suffix (e.g., ".ico" under Win32).
1468 * If no file is found matching the given parameters, then null is returned.
1471 nsBaseWidget::ResolveIconName(const nsAString
&aIconName
,
1472 const nsAString
&aIconSuffix
,
1477 nsCOMPtr
<nsIProperties
> dirSvc
= do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID
);
1481 // first check auxilary chrome directories
1483 nsCOMPtr
<nsISimpleEnumerator
> dirs
;
1484 dirSvc
->Get(NS_APP_CHROME_DIR_LIST
, NS_GET_IID(nsISimpleEnumerator
),
1485 getter_AddRefs(dirs
));
1488 while (NS_SUCCEEDED(dirs
->HasMoreElements(&hasMore
)) && hasMore
) {
1489 nsCOMPtr
<nsISupports
> element
;
1490 dirs
->GetNext(getter_AddRefs(element
));
1493 nsCOMPtr
<nsIFile
> file
= do_QueryInterface(element
);
1496 if (ResolveIconNameHelper(file
, aIconName
, aIconSuffix
)) {
1497 NS_ADDREF(*aResult
= file
);
1503 // then check the main app chrome directory
1505 nsCOMPtr
<nsIFile
> file
;
1506 dirSvc
->Get(NS_APP_CHROME_DIR
, NS_GET_IID(nsIFile
),
1507 getter_AddRefs(file
));
1508 if (file
&& ResolveIconNameHelper(file
, aIconName
, aIconSuffix
))
1509 NS_ADDREF(*aResult
= file
);
1513 nsBaseWidget::BeginResizeDrag(WidgetGUIEvent
* aEvent
,
1514 int32_t aHorizontal
,
1517 return NS_ERROR_NOT_IMPLEMENTED
;
1521 nsBaseWidget::BeginMoveDrag(WidgetMouseEvent
* aEvent
)
1523 return NS_ERROR_NOT_IMPLEMENTED
;
1527 nsBaseWidget::GetGLFrameBufferFormat()
1529 return LOCAL_GL_RGBA
;
1532 void nsBaseWidget::SetSizeConstraints(const SizeConstraints
& aConstraints
)
1534 mSizeConstraints
= aConstraints
;
1535 // We can't ensure that the size is honored at this point because we're
1536 // probably in the middle of a reflow.
1539 const widget::SizeConstraints
& nsBaseWidget::GetSizeConstraints() const
1541 return mSizeConstraints
;
1546 nsBaseWidget::GetActiveRollupListener()
1548 // If set, then this is likely an <html:select> dropdown.
1549 if (gRollupListener
)
1550 return gRollupListener
;
1552 return nsXULPopupManager::GetInstance();
1556 nsBaseWidget::NotifyWindowDestroyed()
1558 if (!mWidgetListener
)
1561 nsCOMPtr
<nsIXULWindow
> window
= mWidgetListener
->GetXULWindow();
1562 nsCOMPtr
<nsIBaseWindow
> xulWindow(do_QueryInterface(window
));
1564 xulWindow
->Destroy();
1569 nsBaseWidget::NotifySizeMoveDone()
1571 if (!mWidgetListener
|| mWidgetListener
->GetXULWindow())
1574 nsIPresShell
* presShell
= mWidgetListener
->GetPresShell();
1576 presShell
->WindowSizeMoveDone();
1581 nsBaseWidget::NotifyWindowMoved(int32_t aX
, int32_t aY
)
1583 if (mWidgetListener
) {
1584 mWidgetListener
->WindowMoved(this, aX
, aY
);
1587 if (GetIMEUpdatePreference().WantPositionChanged()) {
1588 NotifyIME(IMENotification(IMEMessage::NOTIFY_IME_OF_POSITION_CHANGE
));
1593 nsBaseWidget::NotifySysColorChanged()
1595 if (!mWidgetListener
|| mWidgetListener
->GetXULWindow())
1598 nsIPresShell
* presShell
= mWidgetListener
->GetPresShell();
1600 presShell
->SysColorChanged();
1605 nsBaseWidget::NotifyThemeChanged()
1607 if (!mWidgetListener
|| mWidgetListener
->GetXULWindow())
1610 nsIPresShell
* presShell
= mWidgetListener
->GetPresShell();
1612 presShell
->ThemeChanged();
1617 nsBaseWidget::NotifyUIStateChanged(UIStateChangeType aShowAccelerators
,
1618 UIStateChangeType aShowFocusRings
)
1620 if (nsIDocument
* doc
= GetDocument()) {
1621 nsPIDOMWindow
* win
= doc
->GetWindow();
1623 win
->SetKeyboardIndicators(aShowAccelerators
, aShowFocusRings
);
1628 #ifdef ACCESSIBILITY
1631 nsBaseWidget::GetRootAccessible()
1633 NS_ENSURE_TRUE(mWidgetListener
, nullptr);
1635 nsIPresShell
* presShell
= mWidgetListener
->GetPresShell();
1636 NS_ENSURE_TRUE(presShell
, nullptr);
1638 // If container is null then the presshell is not active. This often happens
1639 // when a preshell is being held onto for fastback.
1640 nsPresContext
* presContext
= presShell
->GetPresContext();
1641 NS_ENSURE_TRUE(presContext
->GetContainerWeak(), nullptr);
1643 // Accessible creation might be not safe so use IsSafeToRunScript to
1644 // make sure it's not created at unsafe times.
1645 nsCOMPtr
<nsIAccessibilityService
> accService
=
1646 services::GetAccessibilityService();
1648 return accService
->GetRootDocumentAccessible(presShell
, nsContentUtils::IsSafeToRunScript());
1654 #endif // ACCESSIBILITY
1657 nsIWidget::SynthesizeNativeTouchTap(nsIntPoint aPointerScreenPoint
, bool aLongTap
)
1659 if (sPointerIdCounter
> TOUCH_INJECT_MAX_POINTS
) {
1660 sPointerIdCounter
= 0;
1662 int pointerId
= sPointerIdCounter
;
1663 sPointerIdCounter
++;
1664 nsresult rv
= SynthesizeNativeTouchPoint(pointerId
, TOUCH_CONTACT
,
1665 aPointerScreenPoint
, 1.0, 90);
1666 if (NS_FAILED(rv
)) {
1671 nsresult rv
= SynthesizeNativeTouchPoint(pointerId
, TOUCH_REMOVE
,
1672 aPointerScreenPoint
, 0, 0);
1676 // initiate a long tap
1677 int elapse
= Preferences::GetInt("ui.click_hold_context_menus.delay",
1678 TOUCH_INJECT_LONG_TAP_DEFAULT_MSEC
);
1679 if (!mLongTapTimer
) {
1680 mLongTapTimer
= do_CreateInstance(NS_TIMER_CONTRACTID
, &rv
);
1681 if (NS_FAILED(rv
)) {
1682 SynthesizeNativeTouchPoint(pointerId
, TOUCH_CANCEL
,
1683 aPointerScreenPoint
, 0, 0);
1684 return NS_ERROR_UNEXPECTED
;
1686 // Windows requires recuring events, so we set this to a smaller window
1687 // than the pref value.
1688 int timeout
= elapse
;
1689 if (timeout
> TOUCH_INJECT_PUMP_TIMER_MSEC
) {
1690 timeout
= TOUCH_INJECT_PUMP_TIMER_MSEC
;
1692 mLongTapTimer
->InitWithFuncCallback(OnLongTapTimerCallback
, this,
1694 nsITimer::TYPE_REPEATING_SLACK
);
1697 // If we already have a long tap pending, cancel it. We only allow one long
1698 // tap to be active at a time.
1699 if (mLongTapTouchPoint
) {
1700 SynthesizeNativeTouchPoint(mLongTapTouchPoint
->mPointerId
, TOUCH_CANCEL
,
1701 mLongTapTouchPoint
->mPosition
, 0, 0);
1704 mLongTapTouchPoint
= new LongTapInfo(pointerId
, aPointerScreenPoint
,
1705 TimeDuration::FromMilliseconds(elapse
));
1711 nsIWidget::OnLongTapTimerCallback(nsITimer
* aTimer
, void* aClosure
)
1713 nsIWidget
*self
= static_cast<nsIWidget
*>(aClosure
);
1715 if ((self
->mLongTapTouchPoint
->mStamp
+ self
->mLongTapTouchPoint
->mDuration
) >
1718 // Windows needs us to keep pumping feedback to the digitizer, so update
1719 // the pointer id with the same position.
1720 self
->SynthesizeNativeTouchPoint(self
->mLongTapTouchPoint
->mPointerId
,
1722 self
->mLongTapTouchPoint
->mPosition
,
1728 // finished, remove the touch point
1729 self
->mLongTapTimer
->Cancel();
1730 self
->mLongTapTimer
= nullptr;
1731 self
->SynthesizeNativeTouchPoint(self
->mLongTapTouchPoint
->mPointerId
,
1733 self
->mLongTapTouchPoint
->mPosition
,
1735 self
->mLongTapTouchPoint
= nullptr;
1739 nsIWidget::ClearNativeTouchSequence()
1741 if (!mLongTapTimer
) {
1744 mLongTapTimer
->Cancel();
1745 mLongTapTimer
= nullptr;
1746 SynthesizeNativeTouchPoint(mLongTapTouchPoint
->mPointerId
, TOUCH_CANCEL
,
1747 mLongTapTouchPoint
->mPosition
, 0, 0);
1748 mLongTapTouchPoint
= nullptr;
1753 //////////////////////////////////////////////////////////////
1755 // Convert a GUI event message code to a string.
1756 // Makes it a lot easier to debug events.
1758 // See gtk/nsWidget.cpp and windows/nsWindow.cpp
1759 // for a DebugPrintEvent() function that uses
1762 //////////////////////////////////////////////////////////////
1763 /* static */ nsAutoString
1764 nsBaseWidget::debug_GuiEventToString(WidgetGUIEvent
* aGuiEvent
)
1766 NS_ASSERTION(nullptr != aGuiEvent
,"cmon, null gui event.");
1768 nsAutoString
eventName(NS_LITERAL_STRING("UNKNOWN"));
1770 #define _ASSIGN_eventName(_value,_name)\
1771 case _value: eventName.AssignLiteral(_name) ; break
1773 switch(aGuiEvent
->message
)
1775 _ASSIGN_eventName(NS_BLUR_CONTENT
,"NS_BLUR_CONTENT");
1776 _ASSIGN_eventName(NS_DRAGDROP_GESTURE
,"NS_DND_GESTURE");
1777 _ASSIGN_eventName(NS_DRAGDROP_DROP
,"NS_DND_DROP");
1778 _ASSIGN_eventName(NS_DRAGDROP_ENTER
,"NS_DND_ENTER");
1779 _ASSIGN_eventName(NS_DRAGDROP_EXIT
,"NS_DND_EXIT");
1780 _ASSIGN_eventName(NS_DRAGDROP_OVER
,"NS_DND_OVER");
1781 _ASSIGN_eventName(NS_EDITOR_INPUT
,"NS_EDITOR_INPUT");
1782 _ASSIGN_eventName(NS_FOCUS_CONTENT
,"NS_FOCUS_CONTENT");
1783 _ASSIGN_eventName(NS_FORM_SELECTED
,"NS_FORM_SELECTED");
1784 _ASSIGN_eventName(NS_FORM_CHANGE
,"NS_FORM_CHANGE");
1785 _ASSIGN_eventName(NS_FORM_RESET
,"NS_FORM_RESET");
1786 _ASSIGN_eventName(NS_FORM_SUBMIT
,"NS_FORM_SUBMIT");
1787 _ASSIGN_eventName(NS_IMAGE_ABORT
,"NS_IMAGE_ABORT");
1788 _ASSIGN_eventName(NS_LOAD_ERROR
,"NS_LOAD_ERROR");
1789 _ASSIGN_eventName(NS_KEY_DOWN
,"NS_KEY_DOWN");
1790 _ASSIGN_eventName(NS_KEY_PRESS
,"NS_KEY_PRESS");
1791 _ASSIGN_eventName(NS_KEY_UP
,"NS_KEY_UP");
1792 _ASSIGN_eventName(NS_MOUSE_ENTER
,"NS_MOUSE_ENTER");
1793 _ASSIGN_eventName(NS_MOUSE_EXIT
,"NS_MOUSE_EXIT");
1794 _ASSIGN_eventName(NS_MOUSE_BUTTON_DOWN
,"NS_MOUSE_BUTTON_DOWN");
1795 _ASSIGN_eventName(NS_MOUSE_BUTTON_UP
,"NS_MOUSE_BUTTON_UP");
1796 _ASSIGN_eventName(NS_MOUSE_CLICK
,"NS_MOUSE_CLICK");
1797 _ASSIGN_eventName(NS_MOUSE_DOUBLECLICK
,"NS_MOUSE_DBLCLICK");
1798 _ASSIGN_eventName(NS_MOUSE_MOVE
,"NS_MOUSE_MOVE");
1799 _ASSIGN_eventName(NS_LOAD
,"NS_LOAD");
1800 _ASSIGN_eventName(NS_POPSTATE
,"NS_POPSTATE");
1801 _ASSIGN_eventName(NS_BEFORE_SCRIPT_EXECUTE
,"NS_BEFORE_SCRIPT_EXECUTE");
1802 _ASSIGN_eventName(NS_AFTER_SCRIPT_EXECUTE
,"NS_AFTER_SCRIPT_EXECUTE");
1803 _ASSIGN_eventName(NS_PAGE_UNLOAD
,"NS_PAGE_UNLOAD");
1804 _ASSIGN_eventName(NS_HASHCHANGE
,"NS_HASHCHANGE");
1805 _ASSIGN_eventName(NS_READYSTATECHANGE
,"NS_READYSTATECHANGE");
1806 _ASSIGN_eventName(NS_XUL_BROADCAST
, "NS_XUL_BROADCAST");
1807 _ASSIGN_eventName(NS_XUL_COMMAND_UPDATE
, "NS_XUL_COMMAND_UPDATE");
1809 #undef _ASSIGN_eventName
1815 sprintf(buf
,"UNKNOWN: %d",aGuiEvent
->message
);
1817 CopyASCIItoUTF16(buf
, eventName
);
1822 return nsAutoString(eventName
);
1824 //////////////////////////////////////////////////////////////
1826 // Code to deal with paint and event debug prefs.
1828 //////////////////////////////////////////////////////////////
1835 static PrefPair debug_PrefValues
[] =
1837 { "nglayout.debug.crossing_event_dumping", false },
1838 { "nglayout.debug.event_dumping", false },
1839 { "nglayout.debug.invalidate_dumping", false },
1840 { "nglayout.debug.motion_event_dumping", false },
1841 { "nglayout.debug.paint_dumping", false },
1842 { "nglayout.debug.paint_flashing", false }
1845 //////////////////////////////////////////////////////////////
1847 nsBaseWidget::debug_GetCachedBoolPref(const char * aPrefName
)
1849 NS_ASSERTION(nullptr != aPrefName
,"cmon, pref name is null.");
1851 for (uint32_t i
= 0; i
< ArrayLength(debug_PrefValues
); i
++)
1853 if (strcmp(debug_PrefValues
[i
].name
, aPrefName
) == 0)
1855 return debug_PrefValues
[i
].value
;
1861 //////////////////////////////////////////////////////////////
1862 static void debug_SetCachedBoolPref(const char * aPrefName
,bool aValue
)
1864 NS_ASSERTION(nullptr != aPrefName
,"cmon, pref name is null.");
1866 for (uint32_t i
= 0; i
< ArrayLength(debug_PrefValues
); i
++)
1868 if (strcmp(debug_PrefValues
[i
].name
, aPrefName
) == 0)
1870 debug_PrefValues
[i
].value
= aValue
;
1876 NS_ASSERTION(false, "cmon, this code is not reached dude.");
1879 //////////////////////////////////////////////////////////////
1880 class Debug_PrefObserver MOZ_FINAL
: public nsIObserver
{
1881 ~Debug_PrefObserver() {}
1888 NS_IMPL_ISUPPORTS(Debug_PrefObserver
, nsIObserver
)
1891 Debug_PrefObserver::Observe(nsISupports
* subject
, const char* topic
,
1892 const char16_t
* data
)
1894 NS_ConvertUTF16toUTF8
prefName(data
);
1896 bool value
= Preferences::GetBool(prefName
.get(), false);
1897 debug_SetCachedBoolPref(prefName
.get(), value
);
1901 //////////////////////////////////////////////////////////////
1903 debug_RegisterPrefCallbacks()
1905 static bool once
= true;
1913 nsCOMPtr
<nsIObserver
> obs(new Debug_PrefObserver());
1914 for (uint32_t i
= 0; i
< ArrayLength(debug_PrefValues
); i
++) {
1915 // Initialize the pref values
1916 debug_PrefValues
[i
].value
=
1917 Preferences::GetBool(debug_PrefValues
[i
].name
, false);
1920 // Register callbacks for when these change
1921 Preferences::AddStrongObserver(obs
, debug_PrefValues
[i
].name
);
1925 //////////////////////////////////////////////////////////////
1929 static int32_t sCount
= 0;
1933 //////////////////////////////////////////////////////////////
1935 nsBaseWidget::debug_WantPaintFlashing()
1937 return debug_GetCachedBoolPref("nglayout.debug.paint_flashing");
1939 //////////////////////////////////////////////////////////////
1941 nsBaseWidget::debug_DumpEvent(FILE * aFileOut
,
1942 nsIWidget
* aWidget
,
1943 WidgetGUIEvent
* aGuiEvent
,
1944 const nsAutoCString
& aWidgetName
,
1947 if (aGuiEvent
->message
== NS_MOUSE_MOVE
)
1949 if (!debug_GetCachedBoolPref("nglayout.debug.motion_event_dumping"))
1953 if (aGuiEvent
->message
== NS_MOUSE_ENTER
||
1954 aGuiEvent
->message
== NS_MOUSE_EXIT
)
1956 if (!debug_GetCachedBoolPref("nglayout.debug.crossing_event_dumping"))
1960 if (!debug_GetCachedBoolPref("nglayout.debug.event_dumping"))
1963 NS_LossyConvertUTF16toASCII
tempString(debug_GuiEventToString(aGuiEvent
).get());
1966 "%4d %-26s widget=%-8p name=%-12s id=0x%-6x refpt=%d,%d\n",
1972 aGuiEvent
->refPoint
.x
,
1973 aGuiEvent
->refPoint
.y
);
1975 //////////////////////////////////////////////////////////////
1977 nsBaseWidget::debug_DumpPaintEvent(FILE * aFileOut
,
1978 nsIWidget
* aWidget
,
1979 const nsIntRegion
& aRegion
,
1980 const nsAutoCString
& aWidgetName
,
1983 NS_ASSERTION(nullptr != aFileOut
,"cmon, null output FILE");
1984 NS_ASSERTION(nullptr != aWidget
,"cmon, the widget is null");
1986 if (!debug_GetCachedBoolPref("nglayout.debug.paint_dumping"))
1989 nsIntRect rect
= aRegion
.GetBounds();
1991 "%4d PAINT widget=%p name=%-12s id=0x%-6x bounds-rect=%3d,%-3d %3d,%-3d",
1996 rect
.x
, rect
.y
, rect
.width
, rect
.height
1999 fprintf(aFileOut
,"\n");
2001 //////////////////////////////////////////////////////////////
2003 nsBaseWidget::debug_DumpInvalidate(FILE * aFileOut
,
2004 nsIWidget
* aWidget
,
2005 const nsIntRect
* aRect
,
2006 const nsAutoCString
& aWidgetName
,
2009 if (!debug_GetCachedBoolPref("nglayout.debug.invalidate_dumping"))
2012 NS_ASSERTION(nullptr != aFileOut
,"cmon, null output FILE");
2013 NS_ASSERTION(nullptr != aWidget
,"cmon, the widget is null");
2016 "%4d Invalidate widget=%p name=%-12s id=0x%-6x",
2025 " rect=%3d,%-3d %3d,%-3d",
2038 fprintf(aFileOut
,"\n");
2040 //////////////////////////////////////////////////////////////