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 "LayerScope.h"
46 #include "mozilla/unused.h"
49 #include "nsAccessibilityService.h"
53 #include "nsIObserver.h"
55 static void debug_RegisterPrefCallbacks();
59 #ifdef NOISY_WIDGET_LEAKS
60 static int32_t gNumWidgets
;
64 #include "nsCocoaFeatures.h"
67 nsIRollupListener
* nsBaseWidget::gRollupListener
= nullptr;
69 using namespace mozilla::layers
;
70 using namespace mozilla::ipc
;
71 using namespace mozilla
;
74 nsIContent
* nsBaseWidget::mLastRollup
= nullptr;
75 // Global user preference for disabling native theme. Used
76 // in NativeWindowTheme.
77 bool gDisableNativeTheme
= false;
79 // Async pump timer during injected long touch taps
80 #define TOUCH_INJECT_PUMP_TIMER_MSEC 50
81 #define TOUCH_INJECT_LONG_TAP_DEFAULT_MSEC 1500
82 int32_t nsIWidget::sPointerIdCounter
= 0;
85 NS_IMPL_ISUPPORTS(nsBaseWidget
, nsIWidget
)
88 nsAutoRollup::nsAutoRollup()
90 // remember if mLastRollup was null, and only clear it upon destruction
91 // if so. This prevents recursive usage of nsAutoRollup from clearing
92 // mLastRollup when it shouldn't.
93 wasClear
= !nsBaseWidget::mLastRollup
;
96 nsAutoRollup::~nsAutoRollup()
98 if (nsBaseWidget::mLastRollup
&& wasClear
) {
99 NS_RELEASE(nsBaseWidget::mLastRollup
);
103 //-------------------------------------------------------------------------
105 // nsBaseWidget constructor
107 //-------------------------------------------------------------------------
109 nsBaseWidget::nsBaseWidget()
110 : mWidgetListener(nullptr)
111 , mAttachedWidgetListener(nullptr)
113 , mCursor(eCursor_standard
)
114 , mUpdateCursor(true)
115 , mBorderStyle(eBorderStyle_none
)
116 , mUseLayersAcceleration(false)
117 , mForceLayersAcceleration(false)
118 , mTemporarilyUseBasicLayerManager(false)
119 , mUseAttachedEvents(false)
120 , mContextInitialized(false)
122 , mOriginalBounds(nullptr)
124 , mSizeMode(nsSizeMode_Normal
)
125 , mPopupLevel(ePopupLevelTop
)
126 , mPopupType(ePopupTypeAny
)
128 #ifdef NOISY_WIDGET_LEAKS
130 printf("WIDGETS+ = %d\n", gNumWidgets
);
134 debug_RegisterPrefCallbacks();
137 mShutdownObserver
= new WidgetShutdownObserver(this);
138 nsContentUtils::RegisterShutdownObserver(mShutdownObserver
);
141 NS_IMPL_ISUPPORTS(WidgetShutdownObserver
, nsIObserver
)
144 WidgetShutdownObserver::Observe(nsISupports
*aSubject
,
146 const char16_t
*aData
)
148 if (strcmp(aTopic
, NS_XPCOM_SHUTDOWN_OBSERVER_ID
) == 0 &&
151 nsContentUtils::UnregisterShutdownObserver(this);
157 nsBaseWidget::Shutdown()
160 mShutdownObserver
= nullptr;
163 static void DeferredDestroyCompositor(CompositorParent
* aCompositorParent
,
164 CompositorChild
* aCompositorChild
)
166 // Bug 848949 needs to be fixed before
167 // we can close the channel properly
168 //aCompositorChild->Close();
169 aCompositorParent
->Release();
170 aCompositorChild
->Release();
173 void nsBaseWidget::DestroyCompositor()
175 LayerScope::DeInit();
177 if (mCompositorChild
) {
178 mCompositorChild
->SendWillStop();
179 mCompositorChild
->Destroy();
181 // The call just made to SendWillStop can result in IPC from the
182 // CompositorParent to the CompositorChild (e.g. caused by the destruction
183 // of shared memory). We need to ensure this gets processed by the
184 // CompositorChild before it gets destroyed. It suffices to ensure that
185 // events already in the MessageLoop get processed before the
186 // CompositorChild is destroyed, so we add a task to the MessageLoop to
187 // handle compositor desctruction.
188 MessageLoop::current()->PostTask(FROM_HERE
,
189 NewRunnableFunction(DeferredDestroyCompositor
, mCompositorParent
,
191 // The DestroyCompositor task we just added to the MessageLoop will handle
192 // releasing mCompositorParent and mCompositorChild.
193 unused
<< mCompositorParent
.forget();
194 unused
<< mCompositorChild
.forget();
198 //-------------------------------------------------------------------------
200 // nsBaseWidget destructor
202 //-------------------------------------------------------------------------
203 nsBaseWidget::~nsBaseWidget()
206 mLayerManager
->GetBackendType() == LayersBackend::LAYERS_BASIC
) {
207 static_cast<BasicLayerManager
*>(mLayerManager
.get())->ClearRetainerWidget();
211 mLayerManager
->Destroy();
212 mLayerManager
= nullptr;
215 if (mShutdownObserver
) {
216 // If the shutdown observer is currently processing observers,
217 // then UnregisterShutdownObserver won't stop our Observer
218 // function from being called. Make sure we don't try
219 // to reference the dead widget.
220 mShutdownObserver
->mWidget
= nullptr;
221 nsContentUtils::UnregisterShutdownObserver(mShutdownObserver
);
226 #ifdef NOISY_WIDGET_LEAKS
228 printf("WIDGETS- = %d\n", gNumWidgets
);
231 NS_IF_RELEASE(mContext
);
232 delete mOriginalBounds
;
236 //-------------------------------------------------------------------------
240 //-------------------------------------------------------------------------
241 void nsBaseWidget::BaseCreate(nsIWidget
*aParent
,
242 const nsIntRect
&aRect
,
243 nsDeviceContext
*aContext
,
244 nsWidgetInitData
*aInitData
)
246 static bool gDisableNativeThemeCached
= false;
247 if (!gDisableNativeThemeCached
) {
248 Preferences::AddBoolVarCache(&gDisableNativeTheme
,
249 "mozilla.widget.disable-native-theme",
250 gDisableNativeTheme
);
251 gDisableNativeThemeCached
= true;
254 // keep a reference to the device context
260 mContext
= new nsDeviceContext();
262 mContext
->Init(nullptr);
265 if (nullptr != aInitData
) {
266 mWindowType
= aInitData
->mWindowType
;
267 mBorderStyle
= aInitData
->mBorderStyle
;
268 mPopupLevel
= aInitData
->mPopupLevel
;
269 mPopupType
= aInitData
->mPopupHint
;
270 mRequireOffMainThreadCompositing
= aInitData
->mRequireOffMainThreadCompositing
;
274 aParent
->AddChild(this);
278 NS_IMETHODIMP
nsBaseWidget::CaptureMouse(bool aCapture
)
283 //-------------------------------------------------------------------------
285 // Accessor functions to get/set the client data
287 //-------------------------------------------------------------------------
289 nsIWidgetListener
* nsBaseWidget::GetWidgetListener()
291 return mWidgetListener
;
294 void nsBaseWidget::SetWidgetListener(nsIWidgetListener
* aWidgetListener
)
296 mWidgetListener
= aWidgetListener
;
299 already_AddRefed
<nsIWidget
>
300 nsBaseWidget::CreateChild(const nsIntRect
&aRect
,
301 nsDeviceContext
*aContext
,
302 nsWidgetInitData
*aInitData
,
303 bool aForceUseIWidgetParent
)
305 nsIWidget
* parent
= this;
306 nsNativeWidget nativeParent
= nullptr;
308 if (!aForceUseIWidgetParent
) {
309 // Use only either parent or nativeParent, not both, to match
310 // existing code. Eventually Create() should be divested of its
311 // nativeWidget parameter.
312 nativeParent
= parent
? parent
->GetNativeData(NS_NATIVE_WIDGET
) : nullptr;
313 parent
= nativeParent
? nullptr : parent
;
314 NS_ABORT_IF_FALSE(!parent
|| !nativeParent
, "messed up logic");
317 nsCOMPtr
<nsIWidget
> widget
;
318 if (aInitData
&& aInitData
->mWindowType
== eWindowType_popup
) {
319 widget
= AllocateChildPopupWidget();
321 static NS_DEFINE_IID(kCChildCID
, NS_CHILD_CID
);
322 widget
= do_CreateInstance(kCChildCID
);
326 NS_SUCCEEDED(widget
->Create(parent
, nativeParent
, aRect
,
327 aContext
, aInitData
))) {
328 return widget
.forget();
334 // Attach a view to our widget which we'll send events to.
336 nsBaseWidget::AttachViewToTopLevel(bool aUseAttachedEvents
,
337 nsDeviceContext
*aContext
)
339 NS_ASSERTION((mWindowType
== eWindowType_toplevel
||
340 mWindowType
== eWindowType_dialog
||
341 mWindowType
== eWindowType_invisible
||
342 mWindowType
== eWindowType_child
),
343 "Can't attach to window of that type");
345 mUseAttachedEvents
= aUseAttachedEvents
;
349 NS_IF_RELEASE(mContext
);
358 nsIWidgetListener
* nsBaseWidget::GetAttachedWidgetListener()
360 return mAttachedWidgetListener
;
363 void nsBaseWidget::SetAttachedWidgetListener(nsIWidgetListener
* aListener
)
365 mAttachedWidgetListener
= aListener
;
368 //-------------------------------------------------------------------------
370 // Close this nsBaseWidget
372 //-------------------------------------------------------------------------
373 NS_METHOD
nsBaseWidget::Destroy()
375 // Just in case our parent is the only ref to us
376 nsCOMPtr
<nsIWidget
> kungFuDeathGrip(this);
377 // disconnect from the parent
378 nsIWidget
*parent
= GetParent();
380 parent
->RemoveChild(this);
387 //-------------------------------------------------------------------------
389 // Set this nsBaseWidget's parent
391 //-------------------------------------------------------------------------
392 NS_IMETHODIMP
nsBaseWidget::SetParent(nsIWidget
* aNewParent
)
394 return NS_ERROR_NOT_IMPLEMENTED
;
398 //-------------------------------------------------------------------------
400 // Get this nsBaseWidget parent
402 //-------------------------------------------------------------------------
403 nsIWidget
* nsBaseWidget::GetParent(void)
408 //-------------------------------------------------------------------------
410 // Get this nsBaseWidget top level widget
412 //-------------------------------------------------------------------------
413 nsIWidget
* nsBaseWidget::GetTopLevelWidget()
415 nsIWidget
*topLevelWidget
= nullptr, *widget
= this;
417 topLevelWidget
= widget
;
418 widget
= widget
->GetParent();
420 return topLevelWidget
;
423 //-------------------------------------------------------------------------
425 // Get this nsBaseWidget's top (non-sheet) parent (if it's a sheet)
427 //-------------------------------------------------------------------------
428 nsIWidget
* nsBaseWidget::GetSheetWindowParent(void)
433 float nsBaseWidget::GetDPI()
438 CSSToLayoutDeviceScale
nsIWidget::GetDefaultScale()
440 double devPixelsPerCSSPixel
= DefaultScaleOverride();
442 if (devPixelsPerCSSPixel
<= 0.0) {
443 devPixelsPerCSSPixel
= GetDefaultScaleInternal();
446 return CSSToLayoutDeviceScale(devPixelsPerCSSPixel
);
450 double nsIWidget::DefaultScaleOverride()
452 // The number of device pixels per CSS pixel. A value <= 0 means choose
453 // automatically based on the DPI. A positive value is used as-is. This effectively
454 // controls the size of a CSS "px".
455 double devPixelsPerCSSPixel
= -1.0;
457 nsAdoptingCString prefString
= Preferences::GetCString("layout.css.devPixelsPerPx");
458 if (!prefString
.IsEmpty()) {
459 devPixelsPerCSSPixel
= PR_strtod(prefString
, nullptr);
462 return devPixelsPerCSSPixel
;
465 //-------------------------------------------------------------------------
467 // Add a child to the list of children
469 //-------------------------------------------------------------------------
470 void nsBaseWidget::AddChild(nsIWidget
* aChild
)
472 NS_PRECONDITION(!aChild
->GetNextSibling() && !aChild
->GetPrevSibling(),
473 "aChild not properly removed from its old child list");
476 mFirstChild
= mLastChild
= aChild
;
478 // append to the list
479 NS_ASSERTION(mLastChild
, "Bogus state");
480 NS_ASSERTION(!mLastChild
->GetNextSibling(), "Bogus state");
481 mLastChild
->SetNextSibling(aChild
);
482 aChild
->SetPrevSibling(mLastChild
);
488 //-------------------------------------------------------------------------
490 // Remove a child from the list of children
492 //-------------------------------------------------------------------------
493 void nsBaseWidget::RemoveChild(nsIWidget
* aChild
)
497 // nsCocoaWindow doesn't implement GetParent, so in that case parent will be
498 // null and we'll just have to do without this assertion.
499 nsIWidget
* parent
= aChild
->GetParent();
500 NS_ASSERTION(!parent
|| parent
== this, "Not one of our kids!");
502 NS_ASSERTION(aChild
->GetParent() == this, "Not one of our kids!");
506 if (mLastChild
== aChild
) {
507 mLastChild
= mLastChild
->GetPrevSibling();
509 if (mFirstChild
== aChild
) {
510 mFirstChild
= mFirstChild
->GetNextSibling();
513 // Now remove from the list. Make sure that we pass ownership of the tail
514 // of the list correctly before we have aChild let go of it.
515 nsIWidget
* prev
= aChild
->GetPrevSibling();
516 nsIWidget
* next
= aChild
->GetNextSibling();
518 prev
->SetNextSibling(next
);
521 next
->SetPrevSibling(prev
);
524 aChild
->SetNextSibling(nullptr);
525 aChild
->SetPrevSibling(nullptr);
529 //-------------------------------------------------------------------------
531 // Sets widget's position within its parent's child list.
533 //-------------------------------------------------------------------------
534 void nsBaseWidget::SetZIndex(int32_t aZIndex
)
536 // Hold a ref to ourselves just in case, since we're going to remove
538 nsCOMPtr
<nsIWidget
> kungFuDeathGrip(this);
542 // reorder this child in its parent's list.
543 nsBaseWidget
* parent
= static_cast<nsBaseWidget
*>(GetParent());
545 parent
->RemoveChild(this);
546 // Scope sib outside the for loop so we can check it afterward
547 nsIWidget
* sib
= parent
->GetFirstChild();
548 for ( ; sib
; sib
= sib
->GetNextSibling()) {
549 int32_t childZIndex
= GetZIndex();
550 if (aZIndex
< childZIndex
) {
551 // Insert ourselves before sib
552 nsIWidget
* prev
= sib
->GetPrevSibling();
555 sib
->SetPrevSibling(this);
557 prev
->SetNextSibling(this);
559 NS_ASSERTION(sib
== parent
->mFirstChild
, "Broken child list");
560 // We've taken ownership of sib, so it's safe to have parent let
562 parent
->mFirstChild
= this;
564 PlaceBehind(eZPlacementBelow
, sib
, false);
568 // were we added to the list?
570 parent
->AddChild(this);
575 //-------------------------------------------------------------------------
577 // Places widget behind the given widget (platforms must override)
579 //-------------------------------------------------------------------------
580 NS_IMETHODIMP
nsBaseWidget::PlaceBehind(nsTopLevelWidgetZPlacement aPlacement
,
581 nsIWidget
*aWidget
, bool aActivate
)
586 //-------------------------------------------------------------------------
588 // Maximize, minimize or restore the window. The BaseWidget implementation
589 // merely stores the state.
591 //-------------------------------------------------------------------------
592 NS_IMETHODIMP
nsBaseWidget::SetSizeMode(int32_t aMode
)
594 if (aMode
== nsSizeMode_Normal
||
595 aMode
== nsSizeMode_Minimized
||
596 aMode
== nsSizeMode_Maximized
||
597 aMode
== nsSizeMode_Fullscreen
) {
599 mSizeMode
= (nsSizeMode
) aMode
;
602 return NS_ERROR_ILLEGAL_VALUE
;
605 //-------------------------------------------------------------------------
607 // Get this component cursor
609 //-------------------------------------------------------------------------
610 nsCursor
nsBaseWidget::GetCursor()
615 NS_METHOD
nsBaseWidget::SetCursor(nsCursor aCursor
)
621 NS_IMETHODIMP
nsBaseWidget::SetCursor(imgIContainer
* aCursor
,
622 uint32_t aHotspotX
, uint32_t aHotspotY
)
624 return NS_ERROR_NOT_IMPLEMENTED
;
627 //-------------------------------------------------------------------------
629 // Window transparency methods
631 //-------------------------------------------------------------------------
633 void nsBaseWidget::SetTransparencyMode(nsTransparencyMode aMode
) {
636 nsTransparencyMode
nsBaseWidget::GetTransparencyMode() {
637 return eTransparencyOpaque
;
641 nsBaseWidget::StoreWindowClipRegion(const nsTArray
<nsIntRect
>& aRects
)
643 if (mClipRects
&& mClipRectCount
== aRects
.Length() &&
644 memcmp(mClipRects
, aRects
.Elements(), sizeof(nsIntRect
)*mClipRectCount
) == 0)
647 mClipRectCount
= aRects
.Length();
648 mClipRects
= new nsIntRect
[mClipRectCount
];
650 memcpy(mClipRects
, aRects
.Elements(), sizeof(nsIntRect
)*mClipRectCount
);
656 nsBaseWidget::GetWindowClipRegion(nsTArray
<nsIntRect
>* aRects
)
659 aRects
->AppendElements(mClipRects
.get(), mClipRectCount
);
661 aRects
->AppendElement(nsIntRect(0, 0, mBounds
.width
, mBounds
.height
));
666 nsBaseWidget::RegionFromArray(const nsTArray
<nsIntRect
>& aRects
)
669 for (uint32_t i
= 0; i
< aRects
.Length(); ++i
) {
670 region
.Or(region
, aRects
[i
]);
676 nsBaseWidget::ArrayFromRegion(const nsIntRegion
& aRegion
, nsTArray
<nsIntRect
>& aRects
)
679 for (nsIntRegionRectIterator
iter(aRegion
); (r
= iter
.Next());) {
680 aRects
.AppendElement(*r
);
685 nsBaseWidget::SetWindowClipRegion(const nsTArray
<nsIntRect
>& aRects
,
686 bool aIntersectWithExisting
)
688 if (!aIntersectWithExisting
) {
689 nsBaseWidget::StoreWindowClipRegion(aRects
);
691 // In this case still early return if nothing changed.
692 if (mClipRects
&& mClipRectCount
== aRects
.Length() &&
695 sizeof(nsIntRect
)*mClipRectCount
) == 0) {
700 nsTArray
<nsIntRect
> currentRects
;
701 GetWindowClipRegion(¤tRects
);
702 // create region from them
703 nsIntRegion currentRegion
= RegionFromArray(currentRects
);
704 // create region from new rects
705 nsIntRegion newRegion
= RegionFromArray(aRects
);
707 nsIntRegion intersection
;
708 intersection
.And(currentRegion
, newRegion
);
709 // create int rect array from intersection
710 nsTArray
<nsIntRect
> rects
;
711 ArrayFromRegion(intersection
, rects
);
713 nsBaseWidget::StoreWindowClipRegion(rects
);
718 //-------------------------------------------------------------------------
720 // Set window shadow style
722 //-------------------------------------------------------------------------
724 NS_IMETHODIMP
nsBaseWidget::SetWindowShadowStyle(int32_t aMode
)
726 return NS_ERROR_NOT_IMPLEMENTED
;
729 //-------------------------------------------------------------------------
731 // Hide window borders/decorations for this widget
733 //-------------------------------------------------------------------------
734 NS_IMETHODIMP
nsBaseWidget::HideWindowChrome(bool aShouldHide
)
736 return NS_ERROR_NOT_IMPLEMENTED
;
739 //-------------------------------------------------------------------------
741 // Put the window into full-screen mode
743 //-------------------------------------------------------------------------
744 NS_IMETHODIMP
nsBaseWidget::MakeFullScreen(bool aFullScreen
)
746 HideWindowChrome(aFullScreen
);
749 if (!mOriginalBounds
)
750 mOriginalBounds
= new nsIntRect();
751 GetScreenBounds(*mOriginalBounds
);
752 // convert dev pix to display pix for window manipulation
753 CSSToLayoutDeviceScale scale
= GetDefaultScale();
754 mOriginalBounds
->x
= NSToIntRound(mOriginalBounds
->x
/ scale
.scale
);
755 mOriginalBounds
->y
= NSToIntRound(mOriginalBounds
->y
/ scale
.scale
);
756 mOriginalBounds
->width
= NSToIntRound(mOriginalBounds
->width
/ scale
.scale
);
757 mOriginalBounds
->height
= NSToIntRound(mOriginalBounds
->height
/ scale
.scale
);
759 // Move to top-left corner of screen and size to the screen dimensions
760 nsCOMPtr
<nsIScreenManager
> screenManager
;
761 screenManager
= do_GetService("@mozilla.org/gfx/screenmanager;1");
762 NS_ASSERTION(screenManager
, "Unable to grab screenManager.");
764 nsCOMPtr
<nsIScreen
> screen
;
765 screenManager
->ScreenForRect(mOriginalBounds
->x
,
767 mOriginalBounds
->width
,
768 mOriginalBounds
->height
,
769 getter_AddRefs(screen
));
771 int32_t left
, top
, width
, height
;
772 if (NS_SUCCEEDED(screen
->GetRectDisplayPix(&left
, &top
, &width
, &height
))) {
773 Resize(left
, top
, width
, height
, true);
778 } else if (mOriginalBounds
) {
779 Resize(mOriginalBounds
->x
, mOriginalBounds
->y
, mOriginalBounds
->width
,
780 mOriginalBounds
->height
, true);
786 nsBaseWidget::AutoLayerManagerSetup::AutoLayerManagerSetup(
787 nsBaseWidget
* aWidget
, gfxContext
* aTarget
,
788 BufferMode aDoubleBuffering
, ScreenRotation aRotation
)
791 mLayerManager
= static_cast<BasicLayerManager
*>(mWidget
->GetLayerManager());
793 NS_ASSERTION(mLayerManager
->GetBackendType() == LayersBackend::LAYERS_BASIC
,
794 "AutoLayerManagerSetup instantiated for non-basic layer backend!");
795 mLayerManager
->SetDefaultTarget(aTarget
);
796 mLayerManager
->SetDefaultTargetConfiguration(aDoubleBuffering
, aRotation
);
800 nsBaseWidget::AutoLayerManagerSetup::~AutoLayerManagerSetup()
803 NS_ASSERTION(mLayerManager
->GetBackendType() == LayersBackend::LAYERS_BASIC
,
804 "AutoLayerManagerSetup instantiated for non-basic layer backend!");
805 mLayerManager
->SetDefaultTarget(nullptr);
806 mLayerManager
->SetDefaultTargetConfiguration(mozilla::layers::BufferMode::BUFFER_NONE
, ROTATION_0
);
810 nsBaseWidget::AutoUseBasicLayerManager::AutoUseBasicLayerManager(nsBaseWidget
* aWidget
)
813 mPreviousTemporarilyUseBasicLayerManager
=
814 mWidget
->mTemporarilyUseBasicLayerManager
;
815 mWidget
->mTemporarilyUseBasicLayerManager
= true;
818 nsBaseWidget::AutoUseBasicLayerManager::~AutoUseBasicLayerManager()
820 mWidget
->mTemporarilyUseBasicLayerManager
=
821 mPreviousTemporarilyUseBasicLayerManager
;
825 nsBaseWidget::ComputeShouldAccelerate(bool aDefault
)
827 #if defined(XP_WIN) || defined(ANDROID) || \
828 defined(MOZ_GL_PROVIDER) || defined(XP_MACOSX) || defined(MOZ_WIDGET_QT)
829 bool accelerateByDefault
= true;
831 bool accelerateByDefault
= false;
835 // 10.6.2 and lower have a bug involving textures and pixel buffer objects
836 // that caused bug 629016, so we don't allow OpenGL-accelerated layers on
837 // those versions of the OS.
838 // This will still let full-screen video be accelerated on OpenGL, because
839 // that XUL widget opts in to acceleration, but that's probably OK.
840 accelerateByDefault
= nsCocoaFeatures::AccelerateByDefault();
843 // we should use AddBoolPrefVarCache
844 bool disableAcceleration
= gfxPrefs::LayersAccelerationDisabled();
845 mForceLayersAcceleration
= gfxPrefs::LayersAccelerationForceEnabled();
847 const char *acceleratedEnv
= PR_GetEnv("MOZ_ACCELERATED");
848 accelerateByDefault
= accelerateByDefault
||
849 (acceleratedEnv
&& (*acceleratedEnv
!= '0'));
851 nsCOMPtr
<nsIXULRuntime
> xr
= do_GetService("@mozilla.org/xre/runtime;1");
852 bool safeMode
= false;
854 xr
->GetInSafeMode(&safeMode
);
856 bool whitelisted
= false;
858 nsCOMPtr
<nsIGfxInfo
> gfxInfo
= do_GetService("@mozilla.org/gfx/info;1");
860 // bug 655578: on X11 at least, we must always call GetData (even if we don't need that information)
861 // as that's what causes GfxInfo initialization which kills the zombie 'glxtest' process.
862 // initially we relied on the fact that GetFeatureStatus calls GetData for us, but bug 681026 showed
863 // that assumption to be unsafe.
867 if (NS_SUCCEEDED(gfxInfo
->GetFeatureStatus(nsIGfxInfo::FEATURE_OPENGL_LAYERS
, &status
))) {
868 if (status
== nsIGfxInfo::FEATURE_STATUS_OK
) {
874 if (disableAcceleration
|| safeMode
)
877 if (mForceLayersAcceleration
)
881 static int tell_me_once
= 0;
883 NS_WARNING("OpenGL-accelerated layers are not supported on this system");
886 #ifdef MOZ_WIDGET_ANDROID
887 NS_RUNTIMEABORT("OpenGL-accelerated layers are a hard requirement on this platform. "
888 "Cannot continue without support for them");
893 if (accelerateByDefault
)
896 /* use the window acceleration flag */
900 CompositorParent
* nsBaseWidget::NewCompositorParent(int aSurfaceWidth
,
903 return new CompositorParent(this, false, aSurfaceWidth
, aSurfaceHeight
);
906 void nsBaseWidget::CreateCompositor()
910 CreateCompositor(rect
.width
, rect
.height
);
914 nsBaseWidget::GetPreferredCompositorBackends(nsTArray
<LayersBackend
>& aHints
)
916 if (mUseLayersAcceleration
) {
917 aHints
.AppendElement(LayersBackend::LAYERS_OPENGL
);
920 aHints
.AppendElement(LayersBackend::LAYERS_BASIC
);
923 void nsBaseWidget::CreateCompositor(int aWidth
, int aHeight
)
925 // This makes sure that gfxPlatforms gets initialized if it hasn't by now.
926 gfxPlatform::GetPlatform();
928 MOZ_ASSERT(gfxPlatform::UsesOffMainThreadCompositing(),
929 "This function assumes OMTC");
931 // Recreating this is tricky, as we may still have an old and we need
932 // to make sure it's properly destroyed by calling DestroyCompositor!
934 // If we've already received a shutdown notification, don't try
935 // create a new compositor.
936 if (!mShutdownObserver
) {
940 // Initialize LayerScope on the main thread.
943 mCompositorParent
= NewCompositorParent(aWidth
, aHeight
);
944 MessageChannel
*parentChannel
= mCompositorParent
->GetIPCChannel();
945 nsRefPtr
<ClientLayerManager
> lm
= new ClientLayerManager(this);
946 MessageLoop
*childMessageLoop
= CompositorParent::CompositorLoop();
947 mCompositorChild
= new CompositorChild(lm
);
948 mCompositorChild
->Open(parentChannel
, childMessageLoop
, ipc::ChildSide
);
950 TextureFactoryIdentifier textureFactoryIdentifier
;
951 PLayerTransactionChild
* shadowManager
= nullptr;
952 nsTArray
<LayersBackend
> backendHints
;
953 GetPreferredCompositorBackends(backendHints
);
955 #if !defined(MOZ_X11) && !defined(XP_WIN)
956 if (!mRequireOffMainThreadCompositing
&&
957 !Preferences::GetBool("layers.offmainthreadcomposition.force-basic", false)) {
958 for (size_t i
= 0; i
< backendHints
.Length(); ++i
) {
959 if (backendHints
[i
] == LayersBackend::LAYERS_BASIC
) {
960 backendHints
[i
] = LayersBackend::LAYERS_NONE
;
966 bool success
= false;
967 if (!backendHints
.IsEmpty()) {
968 shadowManager
= mCompositorChild
->SendPLayerTransactionConstructor(
969 backendHints
, 0, &textureFactoryIdentifier
, &success
);
973 ShadowLayerForwarder
* lf
= lm
->AsShadowForwarder();
976 mCompositorChild
= nullptr;
979 lf
->SetShadowManager(shadowManager
);
980 lf
->IdentifyTextureHost(textureFactoryIdentifier
);
981 ImageBridgeChild::IdentifyCompositorTextureHost(textureFactoryIdentifier
);
984 mLayerManager
= lm
.forget();
988 NS_WARNING("Failed to create an OMT compositor.");
990 // Compositor child had the only reference to LayerManager and will have
991 // deallocated it when being freed.
994 bool nsBaseWidget::ShouldUseOffMainThreadCompositing()
996 return gfxPlatform::UsesOffMainThreadCompositing();
999 LayerManager
* nsBaseWidget::GetLayerManager(PLayerTransactionChild
* aShadowManager
,
1000 LayersBackend aBackendHint
,
1001 LayerManagerPersistence aPersistence
,
1002 bool* aAllowRetaining
)
1004 if (!mLayerManager
) {
1006 mUseLayersAcceleration
= ComputeShouldAccelerate(mUseLayersAcceleration
);
1008 // Try to use an async compositor first, if possible
1009 if (ShouldUseOffMainThreadCompositing()) {
1010 // e10s uses the parameter to pass in the shadow manager from the TabChild
1011 // so we don't expect to see it there since this doesn't support e10s.
1012 NS_ASSERTION(aShadowManager
== nullptr, "Async Compositor not supported with e10s");
1016 if (!mLayerManager
) {
1017 mLayerManager
= CreateBasicLayerManager();
1020 if (mTemporarilyUseBasicLayerManager
&& !mBasicLayerManager
) {
1021 mBasicLayerManager
= CreateBasicLayerManager();
1023 LayerManager
* usedLayerManager
= mTemporarilyUseBasicLayerManager
?
1024 mBasicLayerManager
: mLayerManager
;
1025 if (aAllowRetaining
) {
1026 *aAllowRetaining
= (usedLayerManager
== mLayerManager
);
1028 return usedLayerManager
;
1031 LayerManager
* nsBaseWidget::CreateBasicLayerManager()
1033 return new BasicLayerManager(this);
1036 CompositorChild
* nsBaseWidget::GetRemoteRenderer()
1038 return mCompositorChild
;
1041 TemporaryRef
<mozilla::gfx::DrawTarget
> nsBaseWidget::StartRemoteDrawing()
1046 //-------------------------------------------------------------------------
1048 // Return the used device context
1050 //-------------------------------------------------------------------------
1051 nsDeviceContext
* nsBaseWidget::GetDeviceContext()
1053 if (!mContextInitialized
) {
1054 mContext
->Init(this);
1055 mContextInitialized
= true;
1060 //-------------------------------------------------------------------------
1062 // Destroy the window
1064 //-------------------------------------------------------------------------
1065 void nsBaseWidget::OnDestroy()
1067 // release references to device context and app shell
1068 NS_IF_RELEASE(mContext
);
1071 NS_METHOD
nsBaseWidget::SetWindowClass(const nsAString
& xulWinType
)
1073 return NS_ERROR_NOT_IMPLEMENTED
;
1076 NS_METHOD
nsBaseWidget::MoveClient(double aX
, double aY
)
1078 nsIntPoint
clientOffset(GetClientOffset());
1080 // GetClientOffset returns device pixels; scale back to display pixels
1081 // if that's what this widget uses for the Move/Resize APIs
1082 CSSToLayoutDeviceScale scale
= BoundsUseDisplayPixels()
1084 : CSSToLayoutDeviceScale(1.0);
1085 aX
-= clientOffset
.x
* 1.0 / scale
.scale
;
1086 aY
-= clientOffset
.y
* 1.0 / scale
.scale
;
1088 return Move(aX
, aY
);
1091 NS_METHOD
nsBaseWidget::ResizeClient(double aWidth
,
1095 NS_ASSERTION((aWidth
>=0) , "Negative width passed to ResizeClient");
1096 NS_ASSERTION((aHeight
>=0), "Negative height passed to ResizeClient");
1098 nsIntRect clientBounds
;
1099 GetClientBounds(clientBounds
);
1101 // GetClientBounds and mBounds are device pixels; scale back to display pixels
1102 // if that's what this widget uses for the Move/Resize APIs
1103 CSSToLayoutDeviceScale scale
= BoundsUseDisplayPixels()
1105 : CSSToLayoutDeviceScale(1.0);
1106 double invScale
= 1.0 / scale
.scale
;
1107 aWidth
= mBounds
.width
* invScale
+ (aWidth
- clientBounds
.width
* invScale
);
1108 aHeight
= mBounds
.height
* invScale
+ (aHeight
- clientBounds
.height
* invScale
);
1110 return Resize(aWidth
, aHeight
, aRepaint
);
1113 NS_METHOD
nsBaseWidget::ResizeClient(double aX
,
1119 NS_ASSERTION((aWidth
>=0) , "Negative width passed to ResizeClient");
1120 NS_ASSERTION((aHeight
>=0), "Negative height passed to ResizeClient");
1122 nsIntRect clientBounds
;
1123 GetClientBounds(clientBounds
);
1125 double scale
= BoundsUseDisplayPixels() ? 1.0 / GetDefaultScale().scale
: 1.0;
1126 aWidth
= mBounds
.width
* scale
+ (aWidth
- clientBounds
.width
* scale
);
1127 aHeight
= mBounds
.height
* scale
+ (aHeight
- clientBounds
.height
* scale
);
1129 nsIntPoint
clientOffset(GetClientOffset());
1130 aX
-= clientOffset
.x
* scale
;
1131 aY
-= clientOffset
.y
* scale
;
1133 return Resize(aX
, aY
, aWidth
, aHeight
, aRepaint
);
1136 //-------------------------------------------------------------------------
1140 //-------------------------------------------------------------------------
1143 * If the implementation of nsWindow supports borders this method MUST be overridden
1146 NS_METHOD
nsBaseWidget::GetClientBounds(nsIntRect
&aRect
)
1148 return GetBounds(aRect
);
1152 * If the implementation of nsWindow supports borders this method MUST be overridden
1155 NS_METHOD
nsBaseWidget::GetBounds(nsIntRect
&aRect
)
1162 * If the implementation of nsWindow uses a local coordinate system within the window,
1163 * this method must be overridden
1166 NS_METHOD
nsBaseWidget::GetScreenBounds(nsIntRect
&aRect
)
1168 return GetBounds(aRect
);
1171 NS_METHOD
nsBaseWidget::GetRestoredBounds(nsIntRect
&aRect
)
1173 if (SizeMode() != nsSizeMode_Normal
) {
1174 return NS_ERROR_FAILURE
;
1176 return GetScreenBounds(aRect
);
1179 nsIntPoint
nsBaseWidget::GetClientOffset()
1181 return nsIntPoint(0, 0);
1185 nsBaseWidget::GetNonClientMargins(nsIntMargin
&margins
)
1187 return NS_ERROR_NOT_IMPLEMENTED
;
1191 nsBaseWidget::SetNonClientMargins(nsIntMargin
&margins
)
1193 return NS_ERROR_NOT_IMPLEMENTED
;
1196 NS_METHOD
nsBaseWidget::EnableDragDrop(bool aEnable
)
1201 uint32_t nsBaseWidget::GetMaxTouchPoints() const
1206 NS_METHOD
nsBaseWidget::SetModal(bool aModal
)
1208 return NS_ERROR_FAILURE
;
1212 nsBaseWidget::GetAttention(int32_t aCycleCount
) {
1217 nsBaseWidget::HasPendingInputEvent()
1223 nsBaseWidget::SetIcon(const nsAString
&)
1229 nsBaseWidget::SetWindowTitlebarColor(nscolor aColor
, bool aActive
)
1231 return NS_ERROR_NOT_IMPLEMENTED
;
1235 nsBaseWidget::ShowsResizeIndicator(nsIntRect
* aResizerRect
)
1241 nsBaseWidget::SetLayersAcceleration(bool aEnabled
)
1243 if (mUseLayersAcceleration
== aEnabled
) {
1247 bool usedAcceleration
= mUseLayersAcceleration
;
1249 mUseLayersAcceleration
= ComputeShouldAccelerate(aEnabled
);
1250 // ComputeShouldAccelerate may have set mUseLayersAcceleration to a value
1251 // different from aEnabled.
1252 if (usedAcceleration
== mUseLayersAcceleration
) {
1255 if (mLayerManager
) {
1256 mLayerManager
->Destroy();
1258 mLayerManager
= nullptr;
1262 NS_METHOD
nsBaseWidget::RegisterTouchWindow()
1264 return NS_ERROR_NOT_IMPLEMENTED
;
1267 NS_METHOD
nsBaseWidget::UnregisterTouchWindow()
1269 return NS_ERROR_NOT_IMPLEMENTED
;
1273 nsBaseWidget::OverrideSystemMouseScrollSpeed(double aOriginalDeltaX
,
1274 double aOriginalDeltaY
,
1275 double& aOverriddenDeltaX
,
1276 double& aOverriddenDeltaY
)
1278 aOverriddenDeltaX
= aOriginalDeltaX
;
1279 aOverriddenDeltaY
= aOriginalDeltaY
;
1281 static bool sInitialized
= false;
1282 static bool sIsOverrideEnabled
= false;
1283 static int32_t sIntFactorX
= 0;
1284 static int32_t sIntFactorY
= 0;
1286 if (!sInitialized
) {
1287 Preferences::AddBoolVarCache(&sIsOverrideEnabled
,
1288 "mousewheel.system_scroll_override_on_root_content.enabled", false);
1289 Preferences::AddIntVarCache(&sIntFactorX
,
1290 "mousewheel.system_scroll_override_on_root_content.horizontal.factor", 0);
1291 Preferences::AddIntVarCache(&sIntFactorY
,
1292 "mousewheel.system_scroll_override_on_root_content.vertical.factor", 0);
1293 sIntFactorX
= std::max(sIntFactorX
, 0);
1294 sIntFactorY
= std::max(sIntFactorY
, 0);
1295 sInitialized
= true;
1298 if (!sIsOverrideEnabled
) {
1302 // The pref value must be larger than 100, otherwise, we don't override the
1304 if (sIntFactorX
> 100) {
1305 double factor
= static_cast<double>(sIntFactorX
) / 100;
1306 aOverriddenDeltaX
*= factor
;
1308 if (sIntFactorY
> 100) {
1309 double factor
= static_cast<double>(sIntFactorY
) / 100;
1310 aOverriddenDeltaY
*= factor
;
1318 * Modifies aFile to point at an icon file with the given name and suffix. The
1319 * suffix may correspond to a file extension with leading '.' if appropriate.
1320 * Returns true if the icon file exists and can be read.
1323 ResolveIconNameHelper(nsIFile
*aFile
,
1324 const nsAString
&aIconName
,
1325 const nsAString
&aIconSuffix
)
1327 aFile
->Append(NS_LITERAL_STRING("icons"));
1328 aFile
->Append(NS_LITERAL_STRING("default"));
1329 aFile
->Append(aIconName
+ aIconSuffix
);
1332 return NS_SUCCEEDED(aFile
->IsReadable(&readable
)) && readable
;
1336 * Resolve the given icon name into a local file object. This method is
1337 * intended to be called by subclasses of nsBaseWidget. aIconSuffix is a
1338 * platform specific icon file suffix (e.g., ".ico" under Win32).
1340 * If no file is found matching the given parameters, then null is returned.
1343 nsBaseWidget::ResolveIconName(const nsAString
&aIconName
,
1344 const nsAString
&aIconSuffix
,
1349 nsCOMPtr
<nsIProperties
> dirSvc
= do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID
);
1353 // first check auxilary chrome directories
1355 nsCOMPtr
<nsISimpleEnumerator
> dirs
;
1356 dirSvc
->Get(NS_APP_CHROME_DIR_LIST
, NS_GET_IID(nsISimpleEnumerator
),
1357 getter_AddRefs(dirs
));
1360 while (NS_SUCCEEDED(dirs
->HasMoreElements(&hasMore
)) && hasMore
) {
1361 nsCOMPtr
<nsISupports
> element
;
1362 dirs
->GetNext(getter_AddRefs(element
));
1365 nsCOMPtr
<nsIFile
> file
= do_QueryInterface(element
);
1368 if (ResolveIconNameHelper(file
, aIconName
, aIconSuffix
)) {
1369 NS_ADDREF(*aResult
= file
);
1375 // then check the main app chrome directory
1377 nsCOMPtr
<nsIFile
> file
;
1378 dirSvc
->Get(NS_APP_CHROME_DIR
, NS_GET_IID(nsIFile
),
1379 getter_AddRefs(file
));
1380 if (file
&& ResolveIconNameHelper(file
, aIconName
, aIconSuffix
))
1381 NS_ADDREF(*aResult
= file
);
1385 nsBaseWidget::BeginResizeDrag(WidgetGUIEvent
* aEvent
,
1386 int32_t aHorizontal
,
1389 return NS_ERROR_NOT_IMPLEMENTED
;
1393 nsBaseWidget::BeginMoveDrag(WidgetMouseEvent
* aEvent
)
1395 return NS_ERROR_NOT_IMPLEMENTED
;
1399 nsBaseWidget::GetGLFrameBufferFormat()
1401 return LOCAL_GL_RGBA
;
1404 void nsBaseWidget::SetSizeConstraints(const SizeConstraints
& aConstraints
)
1406 mSizeConstraints
= aConstraints
;
1407 // We can't ensure that the size is honored at this point because we're
1408 // probably in the middle of a reflow.
1411 const widget::SizeConstraints
& nsBaseWidget::GetSizeConstraints() const
1413 return mSizeConstraints
;
1418 nsBaseWidget::GetActiveRollupListener()
1420 // If set, then this is likely an <html:select> dropdown.
1421 if (gRollupListener
)
1422 return gRollupListener
;
1424 return nsXULPopupManager::GetInstance();
1428 nsBaseWidget::NotifyWindowDestroyed()
1430 if (!mWidgetListener
)
1433 nsCOMPtr
<nsIXULWindow
> window
= mWidgetListener
->GetXULWindow();
1434 nsCOMPtr
<nsIBaseWindow
> xulWindow(do_QueryInterface(window
));
1436 xulWindow
->Destroy();
1441 nsBaseWidget::NotifySizeMoveDone()
1443 if (!mWidgetListener
|| mWidgetListener
->GetXULWindow())
1446 nsIPresShell
* presShell
= mWidgetListener
->GetPresShell();
1448 presShell
->WindowSizeMoveDone();
1453 nsBaseWidget::NotifyWindowMoved(int32_t aX
, int32_t aY
)
1455 if (mWidgetListener
) {
1456 mWidgetListener
->WindowMoved(this, aX
, aY
);
1459 if (GetIMEUpdatePreference().WantPositionChanged()) {
1460 NotifyIME(IMENotification(IMEMessage::NOTIFY_IME_OF_POSITION_CHANGE
));
1465 nsBaseWidget::NotifySysColorChanged()
1467 if (!mWidgetListener
|| mWidgetListener
->GetXULWindow())
1470 nsIPresShell
* presShell
= mWidgetListener
->GetPresShell();
1472 presShell
->SysColorChanged();
1477 nsBaseWidget::NotifyThemeChanged()
1479 if (!mWidgetListener
|| mWidgetListener
->GetXULWindow())
1482 nsIPresShell
* presShell
= mWidgetListener
->GetPresShell();
1484 presShell
->ThemeChanged();
1489 nsBaseWidget::NotifyUIStateChanged(UIStateChangeType aShowAccelerators
,
1490 UIStateChangeType aShowFocusRings
)
1492 if (!mWidgetListener
)
1495 nsIPresShell
* presShell
= mWidgetListener
->GetPresShell();
1499 nsIDocument
* doc
= presShell
->GetDocument();
1501 nsPIDOMWindow
* win
= doc
->GetWindow();
1503 win
->SetKeyboardIndicators(aShowAccelerators
, aShowFocusRings
);
1508 #ifdef ACCESSIBILITY
1511 nsBaseWidget::GetRootAccessible()
1513 NS_ENSURE_TRUE(mWidgetListener
, nullptr);
1515 nsIPresShell
* presShell
= mWidgetListener
->GetPresShell();
1516 NS_ENSURE_TRUE(presShell
, nullptr);
1518 // If container is null then the presshell is not active. This often happens
1519 // when a preshell is being held onto for fastback.
1520 nsPresContext
* presContext
= presShell
->GetPresContext();
1521 NS_ENSURE_TRUE(presContext
->GetContainerWeak(), nullptr);
1523 // Accessible creation might be not safe so use IsSafeToRunScript to
1524 // make sure it's not created at unsafe times.
1525 nsCOMPtr
<nsIAccessibilityService
> accService
=
1526 services::GetAccessibilityService();
1528 return accService
->GetRootDocumentAccessible(presShell
, nsContentUtils::IsSafeToRunScript());
1534 #endif // ACCESSIBILITY
1537 nsIWidget::SynthesizeNativeTouchTap(nsIntPoint aPointerScreenPoint
, bool aLongTap
)
1539 if (sPointerIdCounter
> TOUCH_INJECT_MAX_POINTS
) {
1540 sPointerIdCounter
= 0;
1542 int pointerId
= sPointerIdCounter
;
1543 sPointerIdCounter
++;
1544 nsresult rv
= SynthesizeNativeTouchPoint(pointerId
, TOUCH_CONTACT
,
1545 aPointerScreenPoint
, 1.0, 90);
1546 if (NS_FAILED(rv
)) {
1551 nsresult rv
= SynthesizeNativeTouchPoint(pointerId
, TOUCH_REMOVE
,
1552 aPointerScreenPoint
, 0, 0);
1556 // initiate a long tap
1557 int elapse
= Preferences::GetInt("ui.click_hold_context_menus.delay",
1558 TOUCH_INJECT_LONG_TAP_DEFAULT_MSEC
);
1559 if (!mLongTapTimer
) {
1560 mLongTapTimer
= do_CreateInstance(NS_TIMER_CONTRACTID
, &rv
);
1561 if (NS_FAILED(rv
)) {
1562 SynthesizeNativeTouchPoint(pointerId
, TOUCH_CANCEL
,
1563 aPointerScreenPoint
, 0, 0);
1564 return NS_ERROR_UNEXPECTED
;
1566 // Windows requires recuring events, so we set this to a smaller window
1567 // than the pref value.
1568 int timeout
= elapse
;
1569 if (timeout
> TOUCH_INJECT_PUMP_TIMER_MSEC
) {
1570 timeout
= TOUCH_INJECT_PUMP_TIMER_MSEC
;
1572 mLongTapTimer
->InitWithFuncCallback(OnLongTapTimerCallback
, this,
1574 nsITimer::TYPE_REPEATING_SLACK
);
1577 // If we already have a long tap pending, cancel it. We only allow one long
1578 // tap to be active at a time.
1579 if (mLongTapTouchPoint
) {
1580 SynthesizeNativeTouchPoint(mLongTapTouchPoint
->mPointerId
, TOUCH_CANCEL
,
1581 mLongTapTouchPoint
->mPosition
, 0, 0);
1584 mLongTapTouchPoint
= new LongTapInfo(pointerId
, aPointerScreenPoint
,
1585 TimeDuration::FromMilliseconds(elapse
));
1591 nsIWidget::OnLongTapTimerCallback(nsITimer
* aTimer
, void* aClosure
)
1593 nsIWidget
*self
= static_cast<nsIWidget
*>(aClosure
);
1595 if ((self
->mLongTapTouchPoint
->mStamp
+ self
->mLongTapTouchPoint
->mDuration
) >
1598 // Windows needs us to keep pumping feedback to the digitizer, so update
1599 // the pointer id with the same position.
1600 self
->SynthesizeNativeTouchPoint(self
->mLongTapTouchPoint
->mPointerId
,
1602 self
->mLongTapTouchPoint
->mPosition
,
1608 // finished, remove the touch point
1609 self
->mLongTapTimer
->Cancel();
1610 self
->mLongTapTimer
= nullptr;
1611 self
->SynthesizeNativeTouchPoint(self
->mLongTapTouchPoint
->mPointerId
,
1613 self
->mLongTapTouchPoint
->mPosition
,
1615 self
->mLongTapTouchPoint
= nullptr;
1619 nsIWidget::ClearNativeTouchSequence()
1621 if (!mLongTapTimer
) {
1624 mLongTapTimer
->Cancel();
1625 mLongTapTimer
= nullptr;
1626 SynthesizeNativeTouchPoint(mLongTapTouchPoint
->mPointerId
, TOUCH_CANCEL
,
1627 mLongTapTouchPoint
->mPosition
, 0, 0);
1628 mLongTapTouchPoint
= nullptr;
1633 //////////////////////////////////////////////////////////////
1635 // Convert a GUI event message code to a string.
1636 // Makes it a lot easier to debug events.
1638 // See gtk/nsWidget.cpp and windows/nsWindow.cpp
1639 // for a DebugPrintEvent() function that uses
1642 //////////////////////////////////////////////////////////////
1643 /* static */ nsAutoString
1644 nsBaseWidget::debug_GuiEventToString(WidgetGUIEvent
* aGuiEvent
)
1646 NS_ASSERTION(nullptr != aGuiEvent
,"cmon, null gui event.");
1648 nsAutoString
eventName(NS_LITERAL_STRING("UNKNOWN"));
1650 #define _ASSIGN_eventName(_value,_name)\
1651 case _value: eventName.AssignLiteral(_name) ; break
1653 switch(aGuiEvent
->message
)
1655 _ASSIGN_eventName(NS_BLUR_CONTENT
,"NS_BLUR_CONTENT");
1656 _ASSIGN_eventName(NS_DRAGDROP_GESTURE
,"NS_DND_GESTURE");
1657 _ASSIGN_eventName(NS_DRAGDROP_DROP
,"NS_DND_DROP");
1658 _ASSIGN_eventName(NS_DRAGDROP_ENTER
,"NS_DND_ENTER");
1659 _ASSIGN_eventName(NS_DRAGDROP_EXIT
,"NS_DND_EXIT");
1660 _ASSIGN_eventName(NS_DRAGDROP_OVER
,"NS_DND_OVER");
1661 _ASSIGN_eventName(NS_EDITOR_INPUT
,"NS_EDITOR_INPUT");
1662 _ASSIGN_eventName(NS_FOCUS_CONTENT
,"NS_FOCUS_CONTENT");
1663 _ASSIGN_eventName(NS_FORM_SELECTED
,"NS_FORM_SELECTED");
1664 _ASSIGN_eventName(NS_FORM_CHANGE
,"NS_FORM_CHANGE");
1665 _ASSIGN_eventName(NS_FORM_RESET
,"NS_FORM_RESET");
1666 _ASSIGN_eventName(NS_FORM_SUBMIT
,"NS_FORM_SUBMIT");
1667 _ASSIGN_eventName(NS_IMAGE_ABORT
,"NS_IMAGE_ABORT");
1668 _ASSIGN_eventName(NS_LOAD_ERROR
,"NS_LOAD_ERROR");
1669 _ASSIGN_eventName(NS_KEY_DOWN
,"NS_KEY_DOWN");
1670 _ASSIGN_eventName(NS_KEY_PRESS
,"NS_KEY_PRESS");
1671 _ASSIGN_eventName(NS_KEY_UP
,"NS_KEY_UP");
1672 _ASSIGN_eventName(NS_MOUSE_ENTER
,"NS_MOUSE_ENTER");
1673 _ASSIGN_eventName(NS_MOUSE_EXIT
,"NS_MOUSE_EXIT");
1674 _ASSIGN_eventName(NS_MOUSE_BUTTON_DOWN
,"NS_MOUSE_BUTTON_DOWN");
1675 _ASSIGN_eventName(NS_MOUSE_BUTTON_UP
,"NS_MOUSE_BUTTON_UP");
1676 _ASSIGN_eventName(NS_MOUSE_CLICK
,"NS_MOUSE_CLICK");
1677 _ASSIGN_eventName(NS_MOUSE_DOUBLECLICK
,"NS_MOUSE_DBLCLICK");
1678 _ASSIGN_eventName(NS_MOUSE_MOVE
,"NS_MOUSE_MOVE");
1679 _ASSIGN_eventName(NS_LOAD
,"NS_LOAD");
1680 _ASSIGN_eventName(NS_POPSTATE
,"NS_POPSTATE");
1681 _ASSIGN_eventName(NS_BEFORE_SCRIPT_EXECUTE
,"NS_BEFORE_SCRIPT_EXECUTE");
1682 _ASSIGN_eventName(NS_AFTER_SCRIPT_EXECUTE
,"NS_AFTER_SCRIPT_EXECUTE");
1683 _ASSIGN_eventName(NS_PAGE_UNLOAD
,"NS_PAGE_UNLOAD");
1684 _ASSIGN_eventName(NS_HASHCHANGE
,"NS_HASHCHANGE");
1685 _ASSIGN_eventName(NS_READYSTATECHANGE
,"NS_READYSTATECHANGE");
1686 _ASSIGN_eventName(NS_XUL_BROADCAST
, "NS_XUL_BROADCAST");
1687 _ASSIGN_eventName(NS_XUL_COMMAND_UPDATE
, "NS_XUL_COMMAND_UPDATE");
1689 #undef _ASSIGN_eventName
1695 sprintf(buf
,"UNKNOWN: %d",aGuiEvent
->message
);
1697 CopyASCIItoUTF16(buf
, eventName
);
1702 return nsAutoString(eventName
);
1704 //////////////////////////////////////////////////////////////
1706 // Code to deal with paint and event debug prefs.
1708 //////////////////////////////////////////////////////////////
1715 static PrefPair debug_PrefValues
[] =
1717 { "nglayout.debug.crossing_event_dumping", false },
1718 { "nglayout.debug.event_dumping", false },
1719 { "nglayout.debug.invalidate_dumping", false },
1720 { "nglayout.debug.motion_event_dumping", false },
1721 { "nglayout.debug.paint_dumping", false },
1722 { "nglayout.debug.paint_flashing", false }
1725 //////////////////////////////////////////////////////////////
1727 nsBaseWidget::debug_GetCachedBoolPref(const char * aPrefName
)
1729 NS_ASSERTION(nullptr != aPrefName
,"cmon, pref name is null.");
1731 for (uint32_t i
= 0; i
< ArrayLength(debug_PrefValues
); i
++)
1733 if (strcmp(debug_PrefValues
[i
].name
, aPrefName
) == 0)
1735 return debug_PrefValues
[i
].value
;
1741 //////////////////////////////////////////////////////////////
1742 static void debug_SetCachedBoolPref(const char * aPrefName
,bool aValue
)
1744 NS_ASSERTION(nullptr != aPrefName
,"cmon, pref name is null.");
1746 for (uint32_t i
= 0; i
< ArrayLength(debug_PrefValues
); i
++)
1748 if (strcmp(debug_PrefValues
[i
].name
, aPrefName
) == 0)
1750 debug_PrefValues
[i
].value
= aValue
;
1756 NS_ASSERTION(false, "cmon, this code is not reached dude.");
1759 //////////////////////////////////////////////////////////////
1760 class Debug_PrefObserver MOZ_FINAL
: public nsIObserver
{
1761 ~Debug_PrefObserver() {}
1768 NS_IMPL_ISUPPORTS(Debug_PrefObserver
, nsIObserver
)
1771 Debug_PrefObserver::Observe(nsISupports
* subject
, const char* topic
,
1772 const char16_t
* data
)
1774 NS_ConvertUTF16toUTF8
prefName(data
);
1776 bool value
= Preferences::GetBool(prefName
.get(), false);
1777 debug_SetCachedBoolPref(prefName
.get(), value
);
1781 //////////////////////////////////////////////////////////////
1783 debug_RegisterPrefCallbacks()
1785 static bool once
= true;
1793 nsCOMPtr
<nsIObserver
> obs(new Debug_PrefObserver());
1794 for (uint32_t i
= 0; i
< ArrayLength(debug_PrefValues
); i
++) {
1795 // Initialize the pref values
1796 debug_PrefValues
[i
].value
=
1797 Preferences::GetBool(debug_PrefValues
[i
].name
, false);
1800 // Register callbacks for when these change
1801 Preferences::AddStrongObserver(obs
, debug_PrefValues
[i
].name
);
1805 //////////////////////////////////////////////////////////////
1809 static int32_t sCount
= 0;
1813 //////////////////////////////////////////////////////////////
1815 nsBaseWidget::debug_WantPaintFlashing()
1817 return debug_GetCachedBoolPref("nglayout.debug.paint_flashing");
1819 //////////////////////////////////////////////////////////////
1821 nsBaseWidget::debug_DumpEvent(FILE * aFileOut
,
1822 nsIWidget
* aWidget
,
1823 WidgetGUIEvent
* aGuiEvent
,
1824 const nsAutoCString
& aWidgetName
,
1827 if (aGuiEvent
->message
== NS_MOUSE_MOVE
)
1829 if (!debug_GetCachedBoolPref("nglayout.debug.motion_event_dumping"))
1833 if (aGuiEvent
->message
== NS_MOUSE_ENTER
||
1834 aGuiEvent
->message
== NS_MOUSE_EXIT
)
1836 if (!debug_GetCachedBoolPref("nglayout.debug.crossing_event_dumping"))
1840 if (!debug_GetCachedBoolPref("nglayout.debug.event_dumping"))
1843 NS_LossyConvertUTF16toASCII
tempString(debug_GuiEventToString(aGuiEvent
).get());
1846 "%4d %-26s widget=%-8p name=%-12s id=0x%-6x refpt=%d,%d\n",
1852 aGuiEvent
->refPoint
.x
,
1853 aGuiEvent
->refPoint
.y
);
1855 //////////////////////////////////////////////////////////////
1857 nsBaseWidget::debug_DumpPaintEvent(FILE * aFileOut
,
1858 nsIWidget
* aWidget
,
1859 const nsIntRegion
& aRegion
,
1860 const nsAutoCString
& aWidgetName
,
1863 NS_ASSERTION(nullptr != aFileOut
,"cmon, null output FILE");
1864 NS_ASSERTION(nullptr != aWidget
,"cmon, the widget is null");
1866 if (!debug_GetCachedBoolPref("nglayout.debug.paint_dumping"))
1869 nsIntRect rect
= aRegion
.GetBounds();
1871 "%4d PAINT widget=%p name=%-12s id=0x%-6x bounds-rect=%3d,%-3d %3d,%-3d",
1876 rect
.x
, rect
.y
, rect
.width
, rect
.height
1879 fprintf(aFileOut
,"\n");
1881 //////////////////////////////////////////////////////////////
1883 nsBaseWidget::debug_DumpInvalidate(FILE * aFileOut
,
1884 nsIWidget
* aWidget
,
1885 const nsIntRect
* aRect
,
1886 const nsAutoCString
& aWidgetName
,
1889 if (!debug_GetCachedBoolPref("nglayout.debug.invalidate_dumping"))
1892 NS_ASSERTION(nullptr != aFileOut
,"cmon, null output FILE");
1893 NS_ASSERTION(nullptr != aWidget
,"cmon, the widget is null");
1896 "%4d Invalidate widget=%p name=%-12s id=0x%-6x",
1905 " rect=%3d,%-3d %3d,%-3d",
1918 fprintf(aFileOut
,"\n");
1920 //////////////////////////////////////////////////////////////