1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/xpwidgets/nsBaseWidget.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1876 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "mozilla/ArrayUtils.h" 1.10 + 1.11 +#include "mozilla/layers/CompositorChild.h" 1.12 +#include "mozilla/layers/CompositorParent.h" 1.13 +#include "mozilla/layers/ImageBridgeChild.h" 1.14 +#include "nsBaseWidget.h" 1.15 +#include "nsDeviceContext.h" 1.16 +#include "nsCOMPtr.h" 1.17 +#include "nsGfxCIID.h" 1.18 +#include "nsWidgetsCID.h" 1.19 +#include "nsServiceManagerUtils.h" 1.20 +#include "nsIScreenManager.h" 1.21 +#include "nsAppDirectoryServiceDefs.h" 1.22 +#include "nsISimpleEnumerator.h" 1.23 +#include "nsIContent.h" 1.24 +#include "nsIDocument.h" 1.25 +#include "nsIPresShell.h" 1.26 +#include "nsIServiceManager.h" 1.27 +#include "mozilla/Preferences.h" 1.28 +#include "BasicLayers.h" 1.29 +#include "ClientLayerManager.h" 1.30 +#include "mozilla/layers/Compositor.h" 1.31 +#include "nsIXULRuntime.h" 1.32 +#include "nsIXULWindow.h" 1.33 +#include "nsIBaseWindow.h" 1.34 +#include "nsXULPopupManager.h" 1.35 +#include "nsIWidgetListener.h" 1.36 +#include "nsIGfxInfo.h" 1.37 +#include "npapi.h" 1.38 +#include "base/thread.h" 1.39 +#include "prdtoa.h" 1.40 +#include "prenv.h" 1.41 +#include "mozilla/Attributes.h" 1.42 +#include "mozilla/unused.h" 1.43 +#include "nsContentUtils.h" 1.44 +#include "gfxPrefs.h" 1.45 +#include "mozilla/gfx/2D.h" 1.46 +#include "mozilla/MouseEvents.h" 1.47 +#include "GLConsts.h" 1.48 +#include "LayerScope.h" 1.49 +#include "mozilla/unused.h" 1.50 + 1.51 +#ifdef ACCESSIBILITY 1.52 +#include "nsAccessibilityService.h" 1.53 +#endif 1.54 + 1.55 +#ifdef DEBUG 1.56 +#include "nsIObserver.h" 1.57 + 1.58 +static void debug_RegisterPrefCallbacks(); 1.59 + 1.60 +#endif 1.61 + 1.62 +#ifdef NOISY_WIDGET_LEAKS 1.63 +static int32_t gNumWidgets; 1.64 +#endif 1.65 + 1.66 +#ifdef XP_MACOSX 1.67 +#include "nsCocoaFeatures.h" 1.68 +#endif 1.69 + 1.70 +nsIRollupListener* nsBaseWidget::gRollupListener = nullptr; 1.71 + 1.72 +using namespace mozilla::layers; 1.73 +using namespace mozilla::ipc; 1.74 +using namespace mozilla; 1.75 +using base::Thread; 1.76 + 1.77 +nsIContent* nsBaseWidget::mLastRollup = nullptr; 1.78 +// Global user preference for disabling native theme. Used 1.79 +// in NativeWindowTheme. 1.80 +bool gDisableNativeTheme = false; 1.81 + 1.82 +// Async pump timer during injected long touch taps 1.83 +#define TOUCH_INJECT_PUMP_TIMER_MSEC 50 1.84 +#define TOUCH_INJECT_LONG_TAP_DEFAULT_MSEC 1500 1.85 +int32_t nsIWidget::sPointerIdCounter = 0; 1.86 + 1.87 +// nsBaseWidget 1.88 +NS_IMPL_ISUPPORTS(nsBaseWidget, nsIWidget) 1.89 + 1.90 + 1.91 +nsAutoRollup::nsAutoRollup() 1.92 +{ 1.93 + // remember if mLastRollup was null, and only clear it upon destruction 1.94 + // if so. This prevents recursive usage of nsAutoRollup from clearing 1.95 + // mLastRollup when it shouldn't. 1.96 + wasClear = !nsBaseWidget::mLastRollup; 1.97 +} 1.98 + 1.99 +nsAutoRollup::~nsAutoRollup() 1.100 +{ 1.101 + if (nsBaseWidget::mLastRollup && wasClear) { 1.102 + NS_RELEASE(nsBaseWidget::mLastRollup); 1.103 + } 1.104 +} 1.105 + 1.106 +//------------------------------------------------------------------------- 1.107 +// 1.108 +// nsBaseWidget constructor 1.109 +// 1.110 +//------------------------------------------------------------------------- 1.111 + 1.112 +nsBaseWidget::nsBaseWidget() 1.113 +: mWidgetListener(nullptr) 1.114 +, mAttachedWidgetListener(nullptr) 1.115 +, mContext(nullptr) 1.116 +, mCursor(eCursor_standard) 1.117 +, mBorderStyle(eBorderStyle_none) 1.118 +, mUseLayersAcceleration(false) 1.119 +, mForceLayersAcceleration(false) 1.120 +, mTemporarilyUseBasicLayerManager(false) 1.121 +, mUseAttachedEvents(false) 1.122 +, mContextInitialized(false) 1.123 +, mBounds(0,0,0,0) 1.124 +, mOriginalBounds(nullptr) 1.125 +, mClipRectCount(0) 1.126 +, mSizeMode(nsSizeMode_Normal) 1.127 +, mPopupLevel(ePopupLevelTop) 1.128 +, mPopupType(ePopupTypeAny) 1.129 +{ 1.130 +#ifdef NOISY_WIDGET_LEAKS 1.131 + gNumWidgets++; 1.132 + printf("WIDGETS+ = %d\n", gNumWidgets); 1.133 +#endif 1.134 + 1.135 +#ifdef DEBUG 1.136 + debug_RegisterPrefCallbacks(); 1.137 +#endif 1.138 + 1.139 + mShutdownObserver = new WidgetShutdownObserver(this); 1.140 + nsContentUtils::RegisterShutdownObserver(mShutdownObserver); 1.141 +} 1.142 + 1.143 +NS_IMPL_ISUPPORTS(WidgetShutdownObserver, nsIObserver) 1.144 + 1.145 +NS_IMETHODIMP 1.146 +WidgetShutdownObserver::Observe(nsISupports *aSubject, 1.147 + const char *aTopic, 1.148 + const char16_t *aData) 1.149 +{ 1.150 + if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0 && 1.151 + mWidget) { 1.152 + mWidget->Shutdown(); 1.153 + nsContentUtils::UnregisterShutdownObserver(this); 1.154 + } 1.155 + return NS_OK; 1.156 +} 1.157 + 1.158 +void 1.159 +nsBaseWidget::Shutdown() 1.160 +{ 1.161 + DestroyCompositor(); 1.162 + mShutdownObserver = nullptr; 1.163 +} 1.164 + 1.165 +static void DeferredDestroyCompositor(CompositorParent* aCompositorParent, 1.166 + CompositorChild* aCompositorChild) 1.167 +{ 1.168 + // Bug 848949 needs to be fixed before 1.169 + // we can close the channel properly 1.170 + //aCompositorChild->Close(); 1.171 + aCompositorParent->Release(); 1.172 + aCompositorChild->Release(); 1.173 +} 1.174 + 1.175 +void nsBaseWidget::DestroyCompositor() 1.176 +{ 1.177 + LayerScope::DestroyServerSocket(); 1.178 + 1.179 + if (mCompositorChild) { 1.180 + mCompositorChild->SendWillStop(); 1.181 + mCompositorChild->Destroy(); 1.182 + 1.183 + // The call just made to SendWillStop can result in IPC from the 1.184 + // CompositorParent to the CompositorChild (e.g. caused by the destruction 1.185 + // of shared memory). We need to ensure this gets processed by the 1.186 + // CompositorChild before it gets destroyed. It suffices to ensure that 1.187 + // events already in the MessageLoop get processed before the 1.188 + // CompositorChild is destroyed, so we add a task to the MessageLoop to 1.189 + // handle compositor desctruction. 1.190 + MessageLoop::current()->PostTask(FROM_HERE, 1.191 + NewRunnableFunction(DeferredDestroyCompositor, mCompositorParent, 1.192 + mCompositorChild)); 1.193 + // The DestroyCompositor task we just added to the MessageLoop will handle 1.194 + // releasing mCompositorParent and mCompositorChild. 1.195 + unused << mCompositorParent.forget(); 1.196 + unused << mCompositorChild.forget(); 1.197 + } 1.198 +} 1.199 + 1.200 +//------------------------------------------------------------------------- 1.201 +// 1.202 +// nsBaseWidget destructor 1.203 +// 1.204 +//------------------------------------------------------------------------- 1.205 +nsBaseWidget::~nsBaseWidget() 1.206 +{ 1.207 + if (mLayerManager && 1.208 + mLayerManager->GetBackendType() == LayersBackend::LAYERS_BASIC) { 1.209 + static_cast<BasicLayerManager*>(mLayerManager.get())->ClearRetainerWidget(); 1.210 + } 1.211 + 1.212 + if (mLayerManager) { 1.213 + mLayerManager->Destroy(); 1.214 + mLayerManager = nullptr; 1.215 + } 1.216 + 1.217 + if (mShutdownObserver) { 1.218 + // If the shutdown observer is currently processing observers, 1.219 + // then UnregisterShutdownObserver won't stop our Observer 1.220 + // function from being called. Make sure we don't try 1.221 + // to reference the dead widget. 1.222 + mShutdownObserver->mWidget = nullptr; 1.223 + nsContentUtils::UnregisterShutdownObserver(mShutdownObserver); 1.224 + } 1.225 + 1.226 + DestroyCompositor(); 1.227 + 1.228 +#ifdef NOISY_WIDGET_LEAKS 1.229 + gNumWidgets--; 1.230 + printf("WIDGETS- = %d\n", gNumWidgets); 1.231 +#endif 1.232 + 1.233 + NS_IF_RELEASE(mContext); 1.234 + delete mOriginalBounds; 1.235 +} 1.236 + 1.237 + 1.238 +//------------------------------------------------------------------------- 1.239 +// 1.240 +// Basic create. 1.241 +// 1.242 +//------------------------------------------------------------------------- 1.243 +void nsBaseWidget::BaseCreate(nsIWidget *aParent, 1.244 + const nsIntRect &aRect, 1.245 + nsDeviceContext *aContext, 1.246 + nsWidgetInitData *aInitData) 1.247 +{ 1.248 + static bool gDisableNativeThemeCached = false; 1.249 + if (!gDisableNativeThemeCached) { 1.250 + Preferences::AddBoolVarCache(&gDisableNativeTheme, 1.251 + "mozilla.widget.disable-native-theme", 1.252 + gDisableNativeTheme); 1.253 + gDisableNativeThemeCached = true; 1.254 + } 1.255 + 1.256 + // keep a reference to the device context 1.257 + if (aContext) { 1.258 + mContext = aContext; 1.259 + NS_ADDREF(mContext); 1.260 + } 1.261 + else { 1.262 + mContext = new nsDeviceContext(); 1.263 + NS_ADDREF(mContext); 1.264 + mContext->Init(nullptr); 1.265 + } 1.266 + 1.267 + if (nullptr != aInitData) { 1.268 + mWindowType = aInitData->mWindowType; 1.269 + mBorderStyle = aInitData->mBorderStyle; 1.270 + mPopupLevel = aInitData->mPopupLevel; 1.271 + mPopupType = aInitData->mPopupHint; 1.272 + mRequireOffMainThreadCompositing = aInitData->mRequireOffMainThreadCompositing; 1.273 + } 1.274 + 1.275 + if (aParent) { 1.276 + aParent->AddChild(this); 1.277 + } 1.278 +} 1.279 + 1.280 +NS_IMETHODIMP nsBaseWidget::CaptureMouse(bool aCapture) 1.281 +{ 1.282 + return NS_OK; 1.283 +} 1.284 + 1.285 +//------------------------------------------------------------------------- 1.286 +// 1.287 +// Accessor functions to get/set the client data 1.288 +// 1.289 +//------------------------------------------------------------------------- 1.290 + 1.291 +nsIWidgetListener* nsBaseWidget::GetWidgetListener() 1.292 +{ 1.293 + return mWidgetListener; 1.294 +} 1.295 + 1.296 +void nsBaseWidget::SetWidgetListener(nsIWidgetListener* aWidgetListener) 1.297 +{ 1.298 + mWidgetListener = aWidgetListener; 1.299 +} 1.300 + 1.301 +already_AddRefed<nsIWidget> 1.302 +nsBaseWidget::CreateChild(const nsIntRect &aRect, 1.303 + nsDeviceContext *aContext, 1.304 + nsWidgetInitData *aInitData, 1.305 + bool aForceUseIWidgetParent) 1.306 +{ 1.307 + nsIWidget* parent = this; 1.308 + nsNativeWidget nativeParent = nullptr; 1.309 + 1.310 + if (!aForceUseIWidgetParent) { 1.311 + // Use only either parent or nativeParent, not both, to match 1.312 + // existing code. Eventually Create() should be divested of its 1.313 + // nativeWidget parameter. 1.314 + nativeParent = parent ? parent->GetNativeData(NS_NATIVE_WIDGET) : nullptr; 1.315 + parent = nativeParent ? nullptr : parent; 1.316 + NS_ABORT_IF_FALSE(!parent || !nativeParent, "messed up logic"); 1.317 + } 1.318 + 1.319 + nsCOMPtr<nsIWidget> widget; 1.320 + if (aInitData && aInitData->mWindowType == eWindowType_popup) { 1.321 + widget = AllocateChildPopupWidget(); 1.322 + } else { 1.323 + static NS_DEFINE_IID(kCChildCID, NS_CHILD_CID); 1.324 + widget = do_CreateInstance(kCChildCID); 1.325 + } 1.326 + 1.327 + if (widget && 1.328 + NS_SUCCEEDED(widget->Create(parent, nativeParent, aRect, 1.329 + aContext, aInitData))) { 1.330 + return widget.forget(); 1.331 + } 1.332 + 1.333 + return nullptr; 1.334 +} 1.335 + 1.336 +// Attach a view to our widget which we'll send events to. 1.337 +NS_IMETHODIMP 1.338 +nsBaseWidget::AttachViewToTopLevel(bool aUseAttachedEvents, 1.339 + nsDeviceContext *aContext) 1.340 +{ 1.341 + NS_ASSERTION((mWindowType == eWindowType_toplevel || 1.342 + mWindowType == eWindowType_dialog || 1.343 + mWindowType == eWindowType_invisible || 1.344 + mWindowType == eWindowType_child), 1.345 + "Can't attach to window of that type"); 1.346 + 1.347 + mUseAttachedEvents = aUseAttachedEvents; 1.348 + 1.349 + if (aContext) { 1.350 + if (mContext) { 1.351 + NS_IF_RELEASE(mContext); 1.352 + } 1.353 + mContext = aContext; 1.354 + NS_ADDREF(mContext); 1.355 + } 1.356 + 1.357 + return NS_OK; 1.358 +} 1.359 + 1.360 +nsIWidgetListener* nsBaseWidget::GetAttachedWidgetListener() 1.361 + { 1.362 + return mAttachedWidgetListener; 1.363 + } 1.364 + 1.365 +void nsBaseWidget::SetAttachedWidgetListener(nsIWidgetListener* aListener) 1.366 + { 1.367 + mAttachedWidgetListener = aListener; 1.368 + } 1.369 + 1.370 +//------------------------------------------------------------------------- 1.371 +// 1.372 +// Close this nsBaseWidget 1.373 +// 1.374 +//------------------------------------------------------------------------- 1.375 +NS_METHOD nsBaseWidget::Destroy() 1.376 +{ 1.377 + // Just in case our parent is the only ref to us 1.378 + nsCOMPtr<nsIWidget> kungFuDeathGrip(this); 1.379 + // disconnect from the parent 1.380 + nsIWidget *parent = GetParent(); 1.381 + if (parent) { 1.382 + parent->RemoveChild(this); 1.383 + } 1.384 + 1.385 + return NS_OK; 1.386 +} 1.387 + 1.388 + 1.389 +//------------------------------------------------------------------------- 1.390 +// 1.391 +// Set this nsBaseWidget's parent 1.392 +// 1.393 +//------------------------------------------------------------------------- 1.394 +NS_IMETHODIMP nsBaseWidget::SetParent(nsIWidget* aNewParent) 1.395 +{ 1.396 + return NS_ERROR_NOT_IMPLEMENTED; 1.397 +} 1.398 + 1.399 + 1.400 +//------------------------------------------------------------------------- 1.401 +// 1.402 +// Get this nsBaseWidget parent 1.403 +// 1.404 +//------------------------------------------------------------------------- 1.405 +nsIWidget* nsBaseWidget::GetParent(void) 1.406 +{ 1.407 + return nullptr; 1.408 +} 1.409 + 1.410 +//------------------------------------------------------------------------- 1.411 +// 1.412 +// Get this nsBaseWidget top level widget 1.413 +// 1.414 +//------------------------------------------------------------------------- 1.415 +nsIWidget* nsBaseWidget::GetTopLevelWidget() 1.416 +{ 1.417 + nsIWidget *topLevelWidget = nullptr, *widget = this; 1.418 + while (widget) { 1.419 + topLevelWidget = widget; 1.420 + widget = widget->GetParent(); 1.421 + } 1.422 + return topLevelWidget; 1.423 +} 1.424 + 1.425 +//------------------------------------------------------------------------- 1.426 +// 1.427 +// Get this nsBaseWidget's top (non-sheet) parent (if it's a sheet) 1.428 +// 1.429 +//------------------------------------------------------------------------- 1.430 +nsIWidget* nsBaseWidget::GetSheetWindowParent(void) 1.431 +{ 1.432 + return nullptr; 1.433 +} 1.434 + 1.435 +float nsBaseWidget::GetDPI() 1.436 +{ 1.437 + return 96.0f; 1.438 +} 1.439 + 1.440 +CSSToLayoutDeviceScale nsIWidget::GetDefaultScale() 1.441 +{ 1.442 + double devPixelsPerCSSPixel = DefaultScaleOverride(); 1.443 + 1.444 + if (devPixelsPerCSSPixel <= 0.0) { 1.445 + devPixelsPerCSSPixel = GetDefaultScaleInternal(); 1.446 + } 1.447 + 1.448 + return CSSToLayoutDeviceScale(devPixelsPerCSSPixel); 1.449 +} 1.450 + 1.451 +/* static */ 1.452 +double nsIWidget::DefaultScaleOverride() 1.453 +{ 1.454 + // The number of device pixels per CSS pixel. A value <= 0 means choose 1.455 + // automatically based on the DPI. A positive value is used as-is. This effectively 1.456 + // controls the size of a CSS "px". 1.457 + double devPixelsPerCSSPixel = -1.0; 1.458 + 1.459 + nsAdoptingCString prefString = Preferences::GetCString("layout.css.devPixelsPerPx"); 1.460 + if (!prefString.IsEmpty()) { 1.461 + devPixelsPerCSSPixel = PR_strtod(prefString, nullptr); 1.462 + } 1.463 + 1.464 + return devPixelsPerCSSPixel; 1.465 +} 1.466 + 1.467 +//------------------------------------------------------------------------- 1.468 +// 1.469 +// Add a child to the list of children 1.470 +// 1.471 +//------------------------------------------------------------------------- 1.472 +void nsBaseWidget::AddChild(nsIWidget* aChild) 1.473 +{ 1.474 + NS_PRECONDITION(!aChild->GetNextSibling() && !aChild->GetPrevSibling(), 1.475 + "aChild not properly removed from its old child list"); 1.476 + 1.477 + if (!mFirstChild) { 1.478 + mFirstChild = mLastChild = aChild; 1.479 + } else { 1.480 + // append to the list 1.481 + NS_ASSERTION(mLastChild, "Bogus state"); 1.482 + NS_ASSERTION(!mLastChild->GetNextSibling(), "Bogus state"); 1.483 + mLastChild->SetNextSibling(aChild); 1.484 + aChild->SetPrevSibling(mLastChild); 1.485 + mLastChild = aChild; 1.486 + } 1.487 +} 1.488 + 1.489 + 1.490 +//------------------------------------------------------------------------- 1.491 +// 1.492 +// Remove a child from the list of children 1.493 +// 1.494 +//------------------------------------------------------------------------- 1.495 +void nsBaseWidget::RemoveChild(nsIWidget* aChild) 1.496 +{ 1.497 +#ifdef DEBUG 1.498 +#ifdef XP_MACOSX 1.499 + // nsCocoaWindow doesn't implement GetParent, so in that case parent will be 1.500 + // null and we'll just have to do without this assertion. 1.501 + nsIWidget* parent = aChild->GetParent(); 1.502 + NS_ASSERTION(!parent || parent == this, "Not one of our kids!"); 1.503 +#else 1.504 + NS_ASSERTION(aChild->GetParent() == this, "Not one of our kids!"); 1.505 +#endif 1.506 +#endif 1.507 + 1.508 + if (mLastChild == aChild) { 1.509 + mLastChild = mLastChild->GetPrevSibling(); 1.510 + } 1.511 + if (mFirstChild == aChild) { 1.512 + mFirstChild = mFirstChild->GetNextSibling(); 1.513 + } 1.514 + 1.515 + // Now remove from the list. Make sure that we pass ownership of the tail 1.516 + // of the list correctly before we have aChild let go of it. 1.517 + nsIWidget* prev = aChild->GetPrevSibling(); 1.518 + nsIWidget* next = aChild->GetNextSibling(); 1.519 + if (prev) { 1.520 + prev->SetNextSibling(next); 1.521 + } 1.522 + if (next) { 1.523 + next->SetPrevSibling(prev); 1.524 + } 1.525 + 1.526 + aChild->SetNextSibling(nullptr); 1.527 + aChild->SetPrevSibling(nullptr); 1.528 +} 1.529 + 1.530 + 1.531 +//------------------------------------------------------------------------- 1.532 +// 1.533 +// Sets widget's position within its parent's child list. 1.534 +// 1.535 +//------------------------------------------------------------------------- 1.536 +void nsBaseWidget::SetZIndex(int32_t aZIndex) 1.537 +{ 1.538 + // Hold a ref to ourselves just in case, since we're going to remove 1.539 + // from our parent. 1.540 + nsCOMPtr<nsIWidget> kungFuDeathGrip(this); 1.541 + 1.542 + mZIndex = aZIndex; 1.543 + 1.544 + // reorder this child in its parent's list. 1.545 + nsBaseWidget* parent = static_cast<nsBaseWidget*>(GetParent()); 1.546 + if (parent) { 1.547 + parent->RemoveChild(this); 1.548 + // Scope sib outside the for loop so we can check it afterward 1.549 + nsIWidget* sib = parent->GetFirstChild(); 1.550 + for ( ; sib; sib = sib->GetNextSibling()) { 1.551 + int32_t childZIndex = GetZIndex(); 1.552 + if (aZIndex < childZIndex) { 1.553 + // Insert ourselves before sib 1.554 + nsIWidget* prev = sib->GetPrevSibling(); 1.555 + mNextSibling = sib; 1.556 + mPrevSibling = prev; 1.557 + sib->SetPrevSibling(this); 1.558 + if (prev) { 1.559 + prev->SetNextSibling(this); 1.560 + } else { 1.561 + NS_ASSERTION(sib == parent->mFirstChild, "Broken child list"); 1.562 + // We've taken ownership of sib, so it's safe to have parent let 1.563 + // go of it 1.564 + parent->mFirstChild = this; 1.565 + } 1.566 + PlaceBehind(eZPlacementBelow, sib, false); 1.567 + break; 1.568 + } 1.569 + } 1.570 + // were we added to the list? 1.571 + if (!sib) { 1.572 + parent->AddChild(this); 1.573 + } 1.574 + } 1.575 +} 1.576 + 1.577 +//------------------------------------------------------------------------- 1.578 +// 1.579 +// Places widget behind the given widget (platforms must override) 1.580 +// 1.581 +//------------------------------------------------------------------------- 1.582 +NS_IMETHODIMP nsBaseWidget::PlaceBehind(nsTopLevelWidgetZPlacement aPlacement, 1.583 + nsIWidget *aWidget, bool aActivate) 1.584 +{ 1.585 + return NS_OK; 1.586 +} 1.587 + 1.588 +//------------------------------------------------------------------------- 1.589 +// 1.590 +// Maximize, minimize or restore the window. The BaseWidget implementation 1.591 +// merely stores the state. 1.592 +// 1.593 +//------------------------------------------------------------------------- 1.594 +NS_IMETHODIMP nsBaseWidget::SetSizeMode(int32_t aMode) 1.595 +{ 1.596 + if (aMode == nsSizeMode_Normal || 1.597 + aMode == nsSizeMode_Minimized || 1.598 + aMode == nsSizeMode_Maximized || 1.599 + aMode == nsSizeMode_Fullscreen) { 1.600 + 1.601 + mSizeMode = (nsSizeMode) aMode; 1.602 + return NS_OK; 1.603 + } 1.604 + return NS_ERROR_ILLEGAL_VALUE; 1.605 +} 1.606 + 1.607 +//------------------------------------------------------------------------- 1.608 +// 1.609 +// Get this component cursor 1.610 +// 1.611 +//------------------------------------------------------------------------- 1.612 +nsCursor nsBaseWidget::GetCursor() 1.613 +{ 1.614 + return mCursor; 1.615 +} 1.616 + 1.617 +NS_METHOD nsBaseWidget::SetCursor(nsCursor aCursor) 1.618 +{ 1.619 + mCursor = aCursor; 1.620 + return NS_OK; 1.621 +} 1.622 + 1.623 +NS_IMETHODIMP nsBaseWidget::SetCursor(imgIContainer* aCursor, 1.624 + uint32_t aHotspotX, uint32_t aHotspotY) 1.625 +{ 1.626 + return NS_ERROR_NOT_IMPLEMENTED; 1.627 +} 1.628 + 1.629 +//------------------------------------------------------------------------- 1.630 +// 1.631 +// Window transparency methods 1.632 +// 1.633 +//------------------------------------------------------------------------- 1.634 + 1.635 +void nsBaseWidget::SetTransparencyMode(nsTransparencyMode aMode) { 1.636 +} 1.637 + 1.638 +nsTransparencyMode nsBaseWidget::GetTransparencyMode() { 1.639 + return eTransparencyOpaque; 1.640 +} 1.641 + 1.642 +bool 1.643 +nsBaseWidget::StoreWindowClipRegion(const nsTArray<nsIntRect>& aRects) 1.644 +{ 1.645 + if (mClipRects && mClipRectCount == aRects.Length() && 1.646 + memcmp(mClipRects, aRects.Elements(), sizeof(nsIntRect)*mClipRectCount) == 0) 1.647 + return false; 1.648 + 1.649 + mClipRectCount = aRects.Length(); 1.650 + mClipRects = new nsIntRect[mClipRectCount]; 1.651 + if (mClipRects) { 1.652 + memcpy(mClipRects, aRects.Elements(), sizeof(nsIntRect)*mClipRectCount); 1.653 + } 1.654 + return true; 1.655 +} 1.656 + 1.657 +void 1.658 +nsBaseWidget::GetWindowClipRegion(nsTArray<nsIntRect>* aRects) 1.659 +{ 1.660 + if (mClipRects) { 1.661 + aRects->AppendElements(mClipRects.get(), mClipRectCount); 1.662 + } else { 1.663 + aRects->AppendElement(nsIntRect(0, 0, mBounds.width, mBounds.height)); 1.664 + } 1.665 +} 1.666 + 1.667 +//------------------------------------------------------------------------- 1.668 +// 1.669 +// Set window shadow style 1.670 +// 1.671 +//------------------------------------------------------------------------- 1.672 + 1.673 +NS_IMETHODIMP nsBaseWidget::SetWindowShadowStyle(int32_t aMode) 1.674 +{ 1.675 + return NS_ERROR_NOT_IMPLEMENTED; 1.676 +} 1.677 + 1.678 +//------------------------------------------------------------------------- 1.679 +// 1.680 +// Hide window borders/decorations for this widget 1.681 +// 1.682 +//------------------------------------------------------------------------- 1.683 +NS_IMETHODIMP nsBaseWidget::HideWindowChrome(bool aShouldHide) 1.684 +{ 1.685 + return NS_ERROR_NOT_IMPLEMENTED; 1.686 +} 1.687 + 1.688 +//------------------------------------------------------------------------- 1.689 +// 1.690 +// Put the window into full-screen mode 1.691 +// 1.692 +//------------------------------------------------------------------------- 1.693 +NS_IMETHODIMP nsBaseWidget::MakeFullScreen(bool aFullScreen) 1.694 +{ 1.695 + HideWindowChrome(aFullScreen); 1.696 + 1.697 + if (aFullScreen) { 1.698 + if (!mOriginalBounds) 1.699 + mOriginalBounds = new nsIntRect(); 1.700 + GetScreenBounds(*mOriginalBounds); 1.701 + // convert dev pix to display pix for window manipulation 1.702 + CSSToLayoutDeviceScale scale = GetDefaultScale(); 1.703 + mOriginalBounds->x = NSToIntRound(mOriginalBounds->x / scale.scale); 1.704 + mOriginalBounds->y = NSToIntRound(mOriginalBounds->y / scale.scale); 1.705 + mOriginalBounds->width = NSToIntRound(mOriginalBounds->width / scale.scale); 1.706 + mOriginalBounds->height = NSToIntRound(mOriginalBounds->height / scale.scale); 1.707 + 1.708 + // Move to top-left corner of screen and size to the screen dimensions 1.709 + nsCOMPtr<nsIScreenManager> screenManager; 1.710 + screenManager = do_GetService("@mozilla.org/gfx/screenmanager;1"); 1.711 + NS_ASSERTION(screenManager, "Unable to grab screenManager."); 1.712 + if (screenManager) { 1.713 + nsCOMPtr<nsIScreen> screen; 1.714 + screenManager->ScreenForRect(mOriginalBounds->x, 1.715 + mOriginalBounds->y, 1.716 + mOriginalBounds->width, 1.717 + mOriginalBounds->height, 1.718 + getter_AddRefs(screen)); 1.719 + if (screen) { 1.720 + int32_t left, top, width, height; 1.721 + if (NS_SUCCEEDED(screen->GetRectDisplayPix(&left, &top, &width, &height))) { 1.722 + Resize(left, top, width, height, true); 1.723 + } 1.724 + } 1.725 + } 1.726 + 1.727 + } else if (mOriginalBounds) { 1.728 + Resize(mOriginalBounds->x, mOriginalBounds->y, mOriginalBounds->width, 1.729 + mOriginalBounds->height, true); 1.730 + } 1.731 + 1.732 + return NS_OK; 1.733 +} 1.734 + 1.735 +nsBaseWidget::AutoLayerManagerSetup::AutoLayerManagerSetup( 1.736 + nsBaseWidget* aWidget, gfxContext* aTarget, 1.737 + BufferMode aDoubleBuffering, ScreenRotation aRotation) 1.738 + : mWidget(aWidget) 1.739 +{ 1.740 + mLayerManager = static_cast<BasicLayerManager*>(mWidget->GetLayerManager()); 1.741 + if (mLayerManager) { 1.742 + NS_ASSERTION(mLayerManager->GetBackendType() == LayersBackend::LAYERS_BASIC, 1.743 + "AutoLayerManagerSetup instantiated for non-basic layer backend!"); 1.744 + mLayerManager->SetDefaultTarget(aTarget); 1.745 + mLayerManager->SetDefaultTargetConfiguration(aDoubleBuffering, aRotation); 1.746 + } 1.747 +} 1.748 + 1.749 +nsBaseWidget::AutoLayerManagerSetup::~AutoLayerManagerSetup() 1.750 +{ 1.751 + if (mLayerManager) { 1.752 + NS_ASSERTION(mLayerManager->GetBackendType() == LayersBackend::LAYERS_BASIC, 1.753 + "AutoLayerManagerSetup instantiated for non-basic layer backend!"); 1.754 + mLayerManager->SetDefaultTarget(nullptr); 1.755 + mLayerManager->SetDefaultTargetConfiguration(mozilla::layers::BufferMode::BUFFER_NONE, ROTATION_0); 1.756 + } 1.757 +} 1.758 + 1.759 +nsBaseWidget::AutoUseBasicLayerManager::AutoUseBasicLayerManager(nsBaseWidget* aWidget) 1.760 + : mWidget(aWidget) 1.761 +{ 1.762 + mPreviousTemporarilyUseBasicLayerManager = 1.763 + mWidget->mTemporarilyUseBasicLayerManager; 1.764 + mWidget->mTemporarilyUseBasicLayerManager = true; 1.765 +} 1.766 + 1.767 +nsBaseWidget::AutoUseBasicLayerManager::~AutoUseBasicLayerManager() 1.768 +{ 1.769 + mWidget->mTemporarilyUseBasicLayerManager = 1.770 + mPreviousTemporarilyUseBasicLayerManager; 1.771 +} 1.772 + 1.773 +bool 1.774 +nsBaseWidget::ComputeShouldAccelerate(bool aDefault) 1.775 +{ 1.776 +#if defined(XP_WIN) || defined(ANDROID) || \ 1.777 + defined(MOZ_GL_PROVIDER) || defined(XP_MACOSX) || defined(MOZ_WIDGET_QT) 1.778 + bool accelerateByDefault = true; 1.779 +#else 1.780 + bool accelerateByDefault = false; 1.781 +#endif 1.782 + 1.783 +#ifdef XP_MACOSX 1.784 + // 10.6.2 and lower have a bug involving textures and pixel buffer objects 1.785 + // that caused bug 629016, so we don't allow OpenGL-accelerated layers on 1.786 + // those versions of the OS. 1.787 + // This will still let full-screen video be accelerated on OpenGL, because 1.788 + // that XUL widget opts in to acceleration, but that's probably OK. 1.789 + SInt32 major = nsCocoaFeatures::OSXVersionMajor(); 1.790 + SInt32 minor = nsCocoaFeatures::OSXVersionMinor(); 1.791 + SInt32 bugfix = nsCocoaFeatures::OSXVersionBugFix(); 1.792 + if (major == 10 && minor == 6 && bugfix <= 2) { 1.793 + accelerateByDefault = false; 1.794 + } 1.795 +#endif 1.796 + 1.797 + // we should use AddBoolPrefVarCache 1.798 + bool disableAcceleration = gfxPrefs::LayersAccelerationDisabled(); 1.799 + mForceLayersAcceleration = gfxPrefs::LayersAccelerationForceEnabled(); 1.800 + 1.801 + const char *acceleratedEnv = PR_GetEnv("MOZ_ACCELERATED"); 1.802 + accelerateByDefault = accelerateByDefault || 1.803 + (acceleratedEnv && (*acceleratedEnv != '0')); 1.804 + 1.805 + nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1"); 1.806 + bool safeMode = false; 1.807 + if (xr) 1.808 + xr->GetInSafeMode(&safeMode); 1.809 + 1.810 + bool whitelisted = false; 1.811 + 1.812 + nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1"); 1.813 + if (gfxInfo) { 1.814 + // bug 655578: on X11 at least, we must always call GetData (even if we don't need that information) 1.815 + // as that's what causes GfxInfo initialization which kills the zombie 'glxtest' process. 1.816 + // initially we relied on the fact that GetFeatureStatus calls GetData for us, but bug 681026 showed 1.817 + // that assumption to be unsafe. 1.818 + gfxInfo->GetData(); 1.819 + 1.820 + int32_t status; 1.821 + if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_OPENGL_LAYERS, &status))) { 1.822 + if (status == nsIGfxInfo::FEATURE_NO_INFO) { 1.823 + whitelisted = true; 1.824 + } 1.825 + } 1.826 + } 1.827 + 1.828 + if (disableAcceleration || safeMode) 1.829 + return false; 1.830 + 1.831 + if (mForceLayersAcceleration) 1.832 + return true; 1.833 + 1.834 + if (!whitelisted) { 1.835 + static int tell_me_once = 0; 1.836 + if (!tell_me_once) { 1.837 + NS_WARNING("OpenGL-accelerated layers are not supported on this system"); 1.838 + tell_me_once = 1; 1.839 + } 1.840 +#ifdef MOZ_ANDROID_OMTC 1.841 + NS_RUNTIMEABORT("OpenGL-accelerated layers are a hard requirement on this platform. " 1.842 + "Cannot continue without support for them"); 1.843 +#endif 1.844 + return false; 1.845 + } 1.846 + 1.847 + if (accelerateByDefault) 1.848 + return true; 1.849 + 1.850 + /* use the window acceleration flag */ 1.851 + return aDefault; 1.852 +} 1.853 + 1.854 +CompositorParent* nsBaseWidget::NewCompositorParent(int aSurfaceWidth, 1.855 + int aSurfaceHeight) 1.856 +{ 1.857 + return new CompositorParent(this, false, aSurfaceWidth, aSurfaceHeight); 1.858 +} 1.859 + 1.860 +void nsBaseWidget::CreateCompositor() 1.861 +{ 1.862 + nsIntRect rect; 1.863 + GetBounds(rect); 1.864 + CreateCompositor(rect.width, rect.height); 1.865 +} 1.866 + 1.867 +void 1.868 +nsBaseWidget::GetPreferredCompositorBackends(nsTArray<LayersBackend>& aHints) 1.869 +{ 1.870 + if (mUseLayersAcceleration) { 1.871 + aHints.AppendElement(LayersBackend::LAYERS_OPENGL); 1.872 + } 1.873 + 1.874 + aHints.AppendElement(LayersBackend::LAYERS_BASIC); 1.875 +} 1.876 + 1.877 +static void 1.878 +CheckForBasicBackends(nsTArray<LayersBackend>& aHints) 1.879 +{ 1.880 + for (size_t i = 0; i < aHints.Length(); ++i) { 1.881 + if (aHints[i] == LayersBackend::LAYERS_BASIC && 1.882 + !Preferences::GetBool("layers.offmainthreadcomposition.force-basic", false)) { 1.883 + // basic compositor is not stable enough for regular use 1.884 + aHints[i] = LayersBackend::LAYERS_NONE; 1.885 + } 1.886 + } 1.887 +} 1.888 + 1.889 +void nsBaseWidget::CreateCompositor(int aWidth, int aHeight) 1.890 +{ 1.891 + // Recreating this is tricky, as we may still have an old and we need 1.892 + // to make sure it's properly destroyed by calling DestroyCompositor! 1.893 + 1.894 + // If we've already received a shutdown notification, don't try 1.895 + // create a new compositor. 1.896 + if (!mShutdownObserver) { 1.897 + return; 1.898 + } 1.899 + 1.900 + // The server socket has to be created on the main thread. 1.901 + LayerScope::CreateServerSocket(); 1.902 + 1.903 + mCompositorParent = NewCompositorParent(aWidth, aHeight); 1.904 + MessageChannel *parentChannel = mCompositorParent->GetIPCChannel(); 1.905 + ClientLayerManager* lm = new ClientLayerManager(this); 1.906 + MessageLoop *childMessageLoop = CompositorParent::CompositorLoop(); 1.907 + mCompositorChild = new CompositorChild(lm); 1.908 + mCompositorChild->Open(parentChannel, childMessageLoop, ipc::ChildSide); 1.909 + 1.910 + TextureFactoryIdentifier textureFactoryIdentifier; 1.911 + PLayerTransactionChild* shadowManager = nullptr; 1.912 + nsTArray<LayersBackend> backendHints; 1.913 + GetPreferredCompositorBackends(backendHints); 1.914 + 1.915 + if (!mRequireOffMainThreadCompositing) { 1.916 + CheckForBasicBackends(backendHints); 1.917 + } 1.918 + 1.919 + bool success = false; 1.920 + if (!backendHints.IsEmpty()) { 1.921 + shadowManager = mCompositorChild->SendPLayerTransactionConstructor( 1.922 + backendHints, 0, &textureFactoryIdentifier, &success); 1.923 + } 1.924 + 1.925 + if (success) { 1.926 + ShadowLayerForwarder* lf = lm->AsShadowForwarder(); 1.927 + if (!lf) { 1.928 + delete lm; 1.929 + mCompositorChild = nullptr; 1.930 + return; 1.931 + } 1.932 + lf->SetShadowManager(shadowManager); 1.933 + lf->IdentifyTextureHost(textureFactoryIdentifier); 1.934 + ImageBridgeChild::IdentifyCompositorTextureHost(textureFactoryIdentifier); 1.935 + WindowUsesOMTC(); 1.936 + 1.937 + mLayerManager = lm; 1.938 + return; 1.939 + } 1.940 + 1.941 + NS_WARNING("Failed to create an OMT compositor."); 1.942 + DestroyCompositor(); 1.943 + // Compositor child had the only reference to LayerManager and will have 1.944 + // deallocated it when being freed. 1.945 +} 1.946 + 1.947 +bool nsBaseWidget::ShouldUseOffMainThreadCompositing() 1.948 +{ 1.949 + return CompositorParent::CompositorLoop(); 1.950 +} 1.951 + 1.952 +LayerManager* nsBaseWidget::GetLayerManager(PLayerTransactionChild* aShadowManager, 1.953 + LayersBackend aBackendHint, 1.954 + LayerManagerPersistence aPersistence, 1.955 + bool* aAllowRetaining) 1.956 +{ 1.957 + if (!mLayerManager) { 1.958 + 1.959 + mUseLayersAcceleration = ComputeShouldAccelerate(mUseLayersAcceleration); 1.960 + 1.961 + // Try to use an async compositor first, if possible 1.962 + if (ShouldUseOffMainThreadCompositing()) { 1.963 + // e10s uses the parameter to pass in the shadow manager from the TabChild 1.964 + // so we don't expect to see it there since this doesn't support e10s. 1.965 + NS_ASSERTION(aShadowManager == nullptr, "Async Compositor not supported with e10s"); 1.966 + CreateCompositor(); 1.967 + } 1.968 + 1.969 + if (!mLayerManager) { 1.970 + mLayerManager = CreateBasicLayerManager(); 1.971 + } 1.972 + } 1.973 + if (mTemporarilyUseBasicLayerManager && !mBasicLayerManager) { 1.974 + mBasicLayerManager = CreateBasicLayerManager(); 1.975 + } 1.976 + LayerManager* usedLayerManager = mTemporarilyUseBasicLayerManager ? 1.977 + mBasicLayerManager : mLayerManager; 1.978 + if (aAllowRetaining) { 1.979 + *aAllowRetaining = (usedLayerManager == mLayerManager); 1.980 + } 1.981 + return usedLayerManager; 1.982 +} 1.983 + 1.984 +LayerManager* nsBaseWidget::CreateBasicLayerManager() 1.985 +{ 1.986 + return new BasicLayerManager(this); 1.987 +} 1.988 + 1.989 +CompositorChild* nsBaseWidget::GetRemoteRenderer() 1.990 +{ 1.991 + return mCompositorChild; 1.992 +} 1.993 + 1.994 +TemporaryRef<mozilla::gfx::DrawTarget> nsBaseWidget::StartRemoteDrawing() 1.995 +{ 1.996 + return nullptr; 1.997 +} 1.998 + 1.999 +//------------------------------------------------------------------------- 1.1000 +// 1.1001 +// Return the used device context 1.1002 +// 1.1003 +//------------------------------------------------------------------------- 1.1004 +nsDeviceContext* nsBaseWidget::GetDeviceContext() 1.1005 +{ 1.1006 + if (!mContextInitialized) { 1.1007 + mContext->Init(this); 1.1008 + mContextInitialized = true; 1.1009 + } 1.1010 + return mContext; 1.1011 +} 1.1012 + 1.1013 +//------------------------------------------------------------------------- 1.1014 +// 1.1015 +// Get the thebes surface 1.1016 +// 1.1017 +//------------------------------------------------------------------------- 1.1018 +gfxASurface *nsBaseWidget::GetThebesSurface() 1.1019 +{ 1.1020 + // in theory we should get our parent's surface, 1.1021 + // clone it, and set a device offset before returning 1.1022 + return nullptr; 1.1023 +} 1.1024 + 1.1025 + 1.1026 +//------------------------------------------------------------------------- 1.1027 +// 1.1028 +// Destroy the window 1.1029 +// 1.1030 +//------------------------------------------------------------------------- 1.1031 +void nsBaseWidget::OnDestroy() 1.1032 +{ 1.1033 + // release references to device context and app shell 1.1034 + NS_IF_RELEASE(mContext); 1.1035 +} 1.1036 + 1.1037 +NS_METHOD nsBaseWidget::SetWindowClass(const nsAString& xulWinType) 1.1038 +{ 1.1039 + return NS_ERROR_NOT_IMPLEMENTED; 1.1040 +} 1.1041 + 1.1042 +NS_METHOD nsBaseWidget::MoveClient(double aX, double aY) 1.1043 +{ 1.1044 + nsIntPoint clientOffset(GetClientOffset()); 1.1045 + 1.1046 + // GetClientOffset returns device pixels; scale back to display pixels 1.1047 + // if that's what this widget uses for the Move/Resize APIs 1.1048 + CSSToLayoutDeviceScale scale = BoundsUseDisplayPixels() 1.1049 + ? GetDefaultScale() 1.1050 + : CSSToLayoutDeviceScale(1.0); 1.1051 + aX -= clientOffset.x * 1.0 / scale.scale; 1.1052 + aY -= clientOffset.y * 1.0 / scale.scale; 1.1053 + 1.1054 + return Move(aX, aY); 1.1055 +} 1.1056 + 1.1057 +NS_METHOD nsBaseWidget::ResizeClient(double aWidth, 1.1058 + double aHeight, 1.1059 + bool aRepaint) 1.1060 +{ 1.1061 + NS_ASSERTION((aWidth >=0) , "Negative width passed to ResizeClient"); 1.1062 + NS_ASSERTION((aHeight >=0), "Negative height passed to ResizeClient"); 1.1063 + 1.1064 + nsIntRect clientBounds; 1.1065 + GetClientBounds(clientBounds); 1.1066 + 1.1067 + // GetClientBounds and mBounds are device pixels; scale back to display pixels 1.1068 + // if that's what this widget uses for the Move/Resize APIs 1.1069 + CSSToLayoutDeviceScale scale = BoundsUseDisplayPixels() 1.1070 + ? GetDefaultScale() 1.1071 + : CSSToLayoutDeviceScale(1.0); 1.1072 + double invScale = 1.0 / scale.scale; 1.1073 + aWidth = mBounds.width * invScale + (aWidth - clientBounds.width * invScale); 1.1074 + aHeight = mBounds.height * invScale + (aHeight - clientBounds.height * invScale); 1.1075 + 1.1076 + return Resize(aWidth, aHeight, aRepaint); 1.1077 +} 1.1078 + 1.1079 +NS_METHOD nsBaseWidget::ResizeClient(double aX, 1.1080 + double aY, 1.1081 + double aWidth, 1.1082 + double aHeight, 1.1083 + bool aRepaint) 1.1084 +{ 1.1085 + NS_ASSERTION((aWidth >=0) , "Negative width passed to ResizeClient"); 1.1086 + NS_ASSERTION((aHeight >=0), "Negative height passed to ResizeClient"); 1.1087 + 1.1088 + nsIntRect clientBounds; 1.1089 + GetClientBounds(clientBounds); 1.1090 + 1.1091 + double scale = BoundsUseDisplayPixels() ? 1.0 / GetDefaultScale().scale : 1.0; 1.1092 + aWidth = mBounds.width * scale + (aWidth - clientBounds.width * scale); 1.1093 + aHeight = mBounds.height * scale + (aHeight - clientBounds.height * scale); 1.1094 + 1.1095 + nsIntPoint clientOffset(GetClientOffset()); 1.1096 + aX -= clientOffset.x * scale; 1.1097 + aY -= clientOffset.y * scale; 1.1098 + 1.1099 + return Resize(aX, aY, aWidth, aHeight, aRepaint); 1.1100 +} 1.1101 + 1.1102 +//------------------------------------------------------------------------- 1.1103 +// 1.1104 +// Bounds 1.1105 +// 1.1106 +//------------------------------------------------------------------------- 1.1107 + 1.1108 +/** 1.1109 +* If the implementation of nsWindow supports borders this method MUST be overridden 1.1110 +* 1.1111 +**/ 1.1112 +NS_METHOD nsBaseWidget::GetClientBounds(nsIntRect &aRect) 1.1113 +{ 1.1114 + return GetBounds(aRect); 1.1115 +} 1.1116 + 1.1117 +/** 1.1118 +* If the implementation of nsWindow supports borders this method MUST be overridden 1.1119 +* 1.1120 +**/ 1.1121 +NS_METHOD nsBaseWidget::GetBounds(nsIntRect &aRect) 1.1122 +{ 1.1123 + aRect = mBounds; 1.1124 + return NS_OK; 1.1125 +} 1.1126 + 1.1127 +/** 1.1128 +* If the implementation of nsWindow uses a local coordinate system within the window, 1.1129 +* this method must be overridden 1.1130 +* 1.1131 +**/ 1.1132 +NS_METHOD nsBaseWidget::GetScreenBounds(nsIntRect &aRect) 1.1133 +{ 1.1134 + return GetBounds(aRect); 1.1135 +} 1.1136 + 1.1137 +nsIntPoint nsBaseWidget::GetClientOffset() 1.1138 +{ 1.1139 + return nsIntPoint(0, 0); 1.1140 +} 1.1141 + 1.1142 +NS_IMETHODIMP 1.1143 +nsBaseWidget::GetNonClientMargins(nsIntMargin &margins) 1.1144 +{ 1.1145 + return NS_ERROR_NOT_IMPLEMENTED; 1.1146 +} 1.1147 + 1.1148 +NS_IMETHODIMP 1.1149 +nsBaseWidget::SetNonClientMargins(nsIntMargin &margins) 1.1150 +{ 1.1151 + return NS_ERROR_NOT_IMPLEMENTED; 1.1152 +} 1.1153 + 1.1154 +NS_METHOD nsBaseWidget::EnableDragDrop(bool aEnable) 1.1155 +{ 1.1156 + return NS_OK; 1.1157 +} 1.1158 + 1.1159 +uint32_t nsBaseWidget::GetMaxTouchPoints() const 1.1160 +{ 1.1161 + return 0; 1.1162 +} 1.1163 + 1.1164 +NS_METHOD nsBaseWidget::SetModal(bool aModal) 1.1165 +{ 1.1166 + return NS_ERROR_FAILURE; 1.1167 +} 1.1168 + 1.1169 +NS_IMETHODIMP 1.1170 +nsBaseWidget::GetAttention(int32_t aCycleCount) { 1.1171 + return NS_OK; 1.1172 +} 1.1173 + 1.1174 +bool 1.1175 +nsBaseWidget::HasPendingInputEvent() 1.1176 +{ 1.1177 + return false; 1.1178 +} 1.1179 + 1.1180 +NS_IMETHODIMP 1.1181 +nsBaseWidget::SetIcon(const nsAString&) 1.1182 +{ 1.1183 + return NS_OK; 1.1184 +} 1.1185 + 1.1186 +NS_IMETHODIMP 1.1187 +nsBaseWidget::SetWindowTitlebarColor(nscolor aColor, bool aActive) 1.1188 +{ 1.1189 + return NS_ERROR_NOT_IMPLEMENTED; 1.1190 +} 1.1191 + 1.1192 +bool 1.1193 +nsBaseWidget::ShowsResizeIndicator(nsIntRect* aResizerRect) 1.1194 +{ 1.1195 + return false; 1.1196 +} 1.1197 + 1.1198 +NS_IMETHODIMP 1.1199 +nsBaseWidget::SetLayersAcceleration(bool aEnabled) 1.1200 +{ 1.1201 + if (mUseLayersAcceleration == aEnabled) { 1.1202 + return NS_OK; 1.1203 + } 1.1204 + 1.1205 + bool usedAcceleration = mUseLayersAcceleration; 1.1206 + 1.1207 + mUseLayersAcceleration = ComputeShouldAccelerate(aEnabled); 1.1208 + // ComputeShouldAccelerate may have set mUseLayersAcceleration to a value 1.1209 + // different from aEnabled. 1.1210 + if (usedAcceleration == mUseLayersAcceleration) { 1.1211 + return NS_OK; 1.1212 + } 1.1213 + if (mLayerManager) { 1.1214 + mLayerManager->Destroy(); 1.1215 + } 1.1216 + mLayerManager = nullptr; 1.1217 + return NS_OK; 1.1218 +} 1.1219 + 1.1220 +NS_METHOD nsBaseWidget::RegisterTouchWindow() 1.1221 +{ 1.1222 + return NS_ERROR_NOT_IMPLEMENTED; 1.1223 +} 1.1224 + 1.1225 +NS_METHOD nsBaseWidget::UnregisterTouchWindow() 1.1226 +{ 1.1227 + return NS_ERROR_NOT_IMPLEMENTED; 1.1228 +} 1.1229 + 1.1230 +NS_IMETHODIMP 1.1231 +nsBaseWidget::OverrideSystemMouseScrollSpeed(double aOriginalDeltaX, 1.1232 + double aOriginalDeltaY, 1.1233 + double& aOverriddenDeltaX, 1.1234 + double& aOverriddenDeltaY) 1.1235 +{ 1.1236 + aOverriddenDeltaX = aOriginalDeltaX; 1.1237 + aOverriddenDeltaY = aOriginalDeltaY; 1.1238 + 1.1239 + static bool sInitialized = false; 1.1240 + static bool sIsOverrideEnabled = false; 1.1241 + static int32_t sIntFactorX = 0; 1.1242 + static int32_t sIntFactorY = 0; 1.1243 + 1.1244 + if (!sInitialized) { 1.1245 + Preferences::AddBoolVarCache(&sIsOverrideEnabled, 1.1246 + "mousewheel.system_scroll_override_on_root_content.enabled", false); 1.1247 + Preferences::AddIntVarCache(&sIntFactorX, 1.1248 + "mousewheel.system_scroll_override_on_root_content.horizontal.factor", 0); 1.1249 + Preferences::AddIntVarCache(&sIntFactorY, 1.1250 + "mousewheel.system_scroll_override_on_root_content.vertical.factor", 0); 1.1251 + sIntFactorX = std::max(sIntFactorX, 0); 1.1252 + sIntFactorY = std::max(sIntFactorY, 0); 1.1253 + sInitialized = true; 1.1254 + } 1.1255 + 1.1256 + if (!sIsOverrideEnabled) { 1.1257 + return NS_OK; 1.1258 + } 1.1259 + 1.1260 + // The pref value must be larger than 100, otherwise, we don't override the 1.1261 + // delta value. 1.1262 + if (sIntFactorX > 100) { 1.1263 + double factor = static_cast<double>(sIntFactorX) / 100; 1.1264 + aOverriddenDeltaX *= factor; 1.1265 + } 1.1266 + if (sIntFactorY > 100) { 1.1267 + double factor = static_cast<double>(sIntFactorY) / 100; 1.1268 + aOverriddenDeltaY *= factor; 1.1269 + } 1.1270 + 1.1271 + return NS_OK; 1.1272 +} 1.1273 + 1.1274 + 1.1275 +/** 1.1276 + * Modifies aFile to point at an icon file with the given name and suffix. The 1.1277 + * suffix may correspond to a file extension with leading '.' if appropriate. 1.1278 + * Returns true if the icon file exists and can be read. 1.1279 + */ 1.1280 +static bool 1.1281 +ResolveIconNameHelper(nsIFile *aFile, 1.1282 + const nsAString &aIconName, 1.1283 + const nsAString &aIconSuffix) 1.1284 +{ 1.1285 + aFile->Append(NS_LITERAL_STRING("icons")); 1.1286 + aFile->Append(NS_LITERAL_STRING("default")); 1.1287 + aFile->Append(aIconName + aIconSuffix); 1.1288 + 1.1289 + bool readable; 1.1290 + return NS_SUCCEEDED(aFile->IsReadable(&readable)) && readable; 1.1291 +} 1.1292 + 1.1293 +/** 1.1294 + * Resolve the given icon name into a local file object. This method is 1.1295 + * intended to be called by subclasses of nsBaseWidget. aIconSuffix is a 1.1296 + * platform specific icon file suffix (e.g., ".ico" under Win32). 1.1297 + * 1.1298 + * If no file is found matching the given parameters, then null is returned. 1.1299 + */ 1.1300 +void 1.1301 +nsBaseWidget::ResolveIconName(const nsAString &aIconName, 1.1302 + const nsAString &aIconSuffix, 1.1303 + nsIFile **aResult) 1.1304 +{ 1.1305 + *aResult = nullptr; 1.1306 + 1.1307 + nsCOMPtr<nsIProperties> dirSvc = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID); 1.1308 + if (!dirSvc) 1.1309 + return; 1.1310 + 1.1311 + // first check auxilary chrome directories 1.1312 + 1.1313 + nsCOMPtr<nsISimpleEnumerator> dirs; 1.1314 + dirSvc->Get(NS_APP_CHROME_DIR_LIST, NS_GET_IID(nsISimpleEnumerator), 1.1315 + getter_AddRefs(dirs)); 1.1316 + if (dirs) { 1.1317 + bool hasMore; 1.1318 + while (NS_SUCCEEDED(dirs->HasMoreElements(&hasMore)) && hasMore) { 1.1319 + nsCOMPtr<nsISupports> element; 1.1320 + dirs->GetNext(getter_AddRefs(element)); 1.1321 + if (!element) 1.1322 + continue; 1.1323 + nsCOMPtr<nsIFile> file = do_QueryInterface(element); 1.1324 + if (!file) 1.1325 + continue; 1.1326 + if (ResolveIconNameHelper(file, aIconName, aIconSuffix)) { 1.1327 + NS_ADDREF(*aResult = file); 1.1328 + return; 1.1329 + } 1.1330 + } 1.1331 + } 1.1332 + 1.1333 + // then check the main app chrome directory 1.1334 + 1.1335 + nsCOMPtr<nsIFile> file; 1.1336 + dirSvc->Get(NS_APP_CHROME_DIR, NS_GET_IID(nsIFile), 1.1337 + getter_AddRefs(file)); 1.1338 + if (file && ResolveIconNameHelper(file, aIconName, aIconSuffix)) 1.1339 + NS_ADDREF(*aResult = file); 1.1340 +} 1.1341 + 1.1342 +NS_IMETHODIMP 1.1343 +nsBaseWidget::BeginResizeDrag(WidgetGUIEvent* aEvent, 1.1344 + int32_t aHorizontal, 1.1345 + int32_t aVertical) 1.1346 +{ 1.1347 + return NS_ERROR_NOT_IMPLEMENTED; 1.1348 +} 1.1349 + 1.1350 +NS_IMETHODIMP 1.1351 +nsBaseWidget::BeginMoveDrag(WidgetMouseEvent* aEvent) 1.1352 +{ 1.1353 + return NS_ERROR_NOT_IMPLEMENTED; 1.1354 +} 1.1355 + 1.1356 +uint32_t 1.1357 +nsBaseWidget::GetGLFrameBufferFormat() 1.1358 +{ 1.1359 + return LOCAL_GL_RGBA; 1.1360 +} 1.1361 + 1.1362 +void nsBaseWidget::SetSizeConstraints(const SizeConstraints& aConstraints) 1.1363 +{ 1.1364 + mSizeConstraints = aConstraints; 1.1365 + // We can't ensure that the size is honored at this point because we're 1.1366 + // probably in the middle of a reflow. 1.1367 +} 1.1368 + 1.1369 +const widget::SizeConstraints& nsBaseWidget::GetSizeConstraints() const 1.1370 +{ 1.1371 + return mSizeConstraints; 1.1372 +} 1.1373 + 1.1374 +// static 1.1375 +nsIRollupListener* 1.1376 +nsBaseWidget::GetActiveRollupListener() 1.1377 +{ 1.1378 + // If set, then this is likely an <html:select> dropdown. 1.1379 + if (gRollupListener) 1.1380 + return gRollupListener; 1.1381 + 1.1382 + return nsXULPopupManager::GetInstance(); 1.1383 +} 1.1384 + 1.1385 +void 1.1386 +nsBaseWidget::NotifyWindowDestroyed() 1.1387 +{ 1.1388 + if (!mWidgetListener) 1.1389 + return; 1.1390 + 1.1391 + nsCOMPtr<nsIXULWindow> window = mWidgetListener->GetXULWindow(); 1.1392 + nsCOMPtr<nsIBaseWindow> xulWindow(do_QueryInterface(window)); 1.1393 + if (xulWindow) { 1.1394 + xulWindow->Destroy(); 1.1395 + } 1.1396 +} 1.1397 + 1.1398 +void 1.1399 +nsBaseWidget::NotifySizeMoveDone() 1.1400 +{ 1.1401 + if (!mWidgetListener || mWidgetListener->GetXULWindow()) 1.1402 + return; 1.1403 + 1.1404 + nsIPresShell* presShell = mWidgetListener->GetPresShell(); 1.1405 + if (presShell) { 1.1406 + presShell->WindowSizeMoveDone(); 1.1407 + } 1.1408 +} 1.1409 + 1.1410 +void 1.1411 +nsBaseWidget::NotifyWindowMoved(int32_t aX, int32_t aY) 1.1412 +{ 1.1413 + if (mWidgetListener) { 1.1414 + mWidgetListener->WindowMoved(this, aX, aY); 1.1415 + } 1.1416 + 1.1417 + if (GetIMEUpdatePreference().WantPositionChanged()) { 1.1418 + NotifyIME(IMENotification(IMEMessage::NOTIFY_IME_OF_POSITION_CHANGE)); 1.1419 + } 1.1420 +} 1.1421 + 1.1422 +void 1.1423 +nsBaseWidget::NotifySysColorChanged() 1.1424 +{ 1.1425 + if (!mWidgetListener || mWidgetListener->GetXULWindow()) 1.1426 + return; 1.1427 + 1.1428 + nsIPresShell* presShell = mWidgetListener->GetPresShell(); 1.1429 + if (presShell) { 1.1430 + presShell->SysColorChanged(); 1.1431 + } 1.1432 +} 1.1433 + 1.1434 +void 1.1435 +nsBaseWidget::NotifyThemeChanged() 1.1436 +{ 1.1437 + if (!mWidgetListener || mWidgetListener->GetXULWindow()) 1.1438 + return; 1.1439 + 1.1440 + nsIPresShell* presShell = mWidgetListener->GetPresShell(); 1.1441 + if (presShell) { 1.1442 + presShell->ThemeChanged(); 1.1443 + } 1.1444 +} 1.1445 + 1.1446 +void 1.1447 +nsBaseWidget::NotifyUIStateChanged(UIStateChangeType aShowAccelerators, 1.1448 + UIStateChangeType aShowFocusRings) 1.1449 +{ 1.1450 + if (!mWidgetListener) 1.1451 + return; 1.1452 + 1.1453 + nsIPresShell* presShell = mWidgetListener->GetPresShell(); 1.1454 + if (!presShell) 1.1455 + return; 1.1456 + 1.1457 + nsIDocument* doc = presShell->GetDocument(); 1.1458 + if (doc) { 1.1459 + nsPIDOMWindow* win = doc->GetWindow(); 1.1460 + if (win) { 1.1461 + win->SetKeyboardIndicators(aShowAccelerators, aShowFocusRings); 1.1462 + } 1.1463 + } 1.1464 +} 1.1465 + 1.1466 +#ifdef ACCESSIBILITY 1.1467 + 1.1468 +a11y::Accessible* 1.1469 +nsBaseWidget::GetRootAccessible() 1.1470 +{ 1.1471 + NS_ENSURE_TRUE(mWidgetListener, nullptr); 1.1472 + 1.1473 + nsIPresShell* presShell = mWidgetListener->GetPresShell(); 1.1474 + NS_ENSURE_TRUE(presShell, nullptr); 1.1475 + 1.1476 + // If container is null then the presshell is not active. This often happens 1.1477 + // when a preshell is being held onto for fastback. 1.1478 + nsPresContext* presContext = presShell->GetPresContext(); 1.1479 + NS_ENSURE_TRUE(presContext->GetContainerWeak(), nullptr); 1.1480 + 1.1481 + // Accessible creation might be not safe so use IsSafeToRunScript to 1.1482 + // make sure it's not created at unsafe times. 1.1483 + nsCOMPtr<nsIAccessibilityService> accService = 1.1484 + services::GetAccessibilityService(); 1.1485 + if (accService) { 1.1486 + return accService->GetRootDocumentAccessible(presShell, nsContentUtils::IsSafeToRunScript()); 1.1487 + } 1.1488 + 1.1489 + return nullptr; 1.1490 +} 1.1491 + 1.1492 +#endif // ACCESSIBILITY 1.1493 + 1.1494 +nsresult 1.1495 +nsIWidget::SynthesizeNativeTouchTap(nsIntPoint aPointerScreenPoint, bool aLongTap) 1.1496 +{ 1.1497 + if (sPointerIdCounter > TOUCH_INJECT_MAX_POINTS) { 1.1498 + sPointerIdCounter = 0; 1.1499 + } 1.1500 + int pointerId = sPointerIdCounter; 1.1501 + sPointerIdCounter++; 1.1502 + nsresult rv = SynthesizeNativeTouchPoint(pointerId, TOUCH_CONTACT, 1.1503 + aPointerScreenPoint, 1.0, 90); 1.1504 + if (NS_FAILED(rv)) { 1.1505 + return rv; 1.1506 + } 1.1507 + 1.1508 + if (!aLongTap) { 1.1509 + nsresult rv = SynthesizeNativeTouchPoint(pointerId, TOUCH_REMOVE, 1.1510 + aPointerScreenPoint, 0, 0); 1.1511 + return rv; 1.1512 + } 1.1513 + 1.1514 + // initiate a long tap 1.1515 + int elapse = Preferences::GetInt("ui.click_hold_context_menus.delay", 1.1516 + TOUCH_INJECT_LONG_TAP_DEFAULT_MSEC); 1.1517 + if (!mLongTapTimer) { 1.1518 + mLongTapTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv); 1.1519 + if (NS_FAILED(rv)) { 1.1520 + SynthesizeNativeTouchPoint(pointerId, TOUCH_CANCEL, 1.1521 + aPointerScreenPoint, 0, 0); 1.1522 + return NS_ERROR_UNEXPECTED; 1.1523 + } 1.1524 + // Windows requires recuring events, so we set this to a smaller window 1.1525 + // than the pref value. 1.1526 + int timeout = elapse; 1.1527 + if (timeout > TOUCH_INJECT_PUMP_TIMER_MSEC) { 1.1528 + timeout = TOUCH_INJECT_PUMP_TIMER_MSEC; 1.1529 + } 1.1530 + mLongTapTimer->InitWithFuncCallback(OnLongTapTimerCallback, this, 1.1531 + timeout, 1.1532 + nsITimer::TYPE_REPEATING_SLACK); 1.1533 + } 1.1534 + 1.1535 + // If we already have a long tap pending, cancel it. We only allow one long 1.1536 + // tap to be active at a time. 1.1537 + if (mLongTapTouchPoint) { 1.1538 + SynthesizeNativeTouchPoint(mLongTapTouchPoint->mPointerId, TOUCH_CANCEL, 1.1539 + mLongTapTouchPoint->mPosition, 0, 0); 1.1540 + } 1.1541 + 1.1542 + mLongTapTouchPoint = new LongTapInfo(pointerId, aPointerScreenPoint, 1.1543 + TimeDuration::FromMilliseconds(elapse)); 1.1544 + return NS_OK; 1.1545 +} 1.1546 + 1.1547 +// static 1.1548 +void 1.1549 +nsIWidget::OnLongTapTimerCallback(nsITimer* aTimer, void* aClosure) 1.1550 +{ 1.1551 + nsIWidget *self = static_cast<nsIWidget *>(aClosure); 1.1552 + 1.1553 + if ((self->mLongTapTouchPoint->mStamp + self->mLongTapTouchPoint->mDuration) > 1.1554 + TimeStamp::Now()) { 1.1555 +#ifdef XP_WIN 1.1556 + // Windows needs us to keep pumping feedback to the digitizer, so update 1.1557 + // the pointer id with the same position. 1.1558 + self->SynthesizeNativeTouchPoint(self->mLongTapTouchPoint->mPointerId, 1.1559 + TOUCH_CONTACT, 1.1560 + self->mLongTapTouchPoint->mPosition, 1.1561 + 1.0, 90); 1.1562 +#endif 1.1563 + return; 1.1564 + } 1.1565 + 1.1566 + // finished, remove the touch point 1.1567 + self->mLongTapTimer->Cancel(); 1.1568 + self->mLongTapTimer = nullptr; 1.1569 + self->SynthesizeNativeTouchPoint(self->mLongTapTouchPoint->mPointerId, 1.1570 + TOUCH_REMOVE, 1.1571 + self->mLongTapTouchPoint->mPosition, 1.1572 + 0, 0); 1.1573 + self->mLongTapTouchPoint = nullptr; 1.1574 +} 1.1575 + 1.1576 +nsresult 1.1577 +nsIWidget::ClearNativeTouchSequence() 1.1578 +{ 1.1579 + if (!mLongTapTimer) { 1.1580 + return NS_OK; 1.1581 + } 1.1582 + mLongTapTimer->Cancel(); 1.1583 + mLongTapTimer = nullptr; 1.1584 + SynthesizeNativeTouchPoint(mLongTapTouchPoint->mPointerId, TOUCH_CANCEL, 1.1585 + mLongTapTouchPoint->mPosition, 0, 0); 1.1586 + mLongTapTouchPoint = nullptr; 1.1587 + return NS_OK; 1.1588 +} 1.1589 + 1.1590 +#ifdef DEBUG 1.1591 +////////////////////////////////////////////////////////////// 1.1592 +// 1.1593 +// Convert a GUI event message code to a string. 1.1594 +// Makes it a lot easier to debug events. 1.1595 +// 1.1596 +// See gtk/nsWidget.cpp and windows/nsWindow.cpp 1.1597 +// for a DebugPrintEvent() function that uses 1.1598 +// this. 1.1599 +// 1.1600 +////////////////////////////////////////////////////////////// 1.1601 +/* static */ nsAutoString 1.1602 +nsBaseWidget::debug_GuiEventToString(WidgetGUIEvent* aGuiEvent) 1.1603 +{ 1.1604 + NS_ASSERTION(nullptr != aGuiEvent,"cmon, null gui event."); 1.1605 + 1.1606 + nsAutoString eventName(NS_LITERAL_STRING("UNKNOWN")); 1.1607 + 1.1608 +#define _ASSIGN_eventName(_value,_name)\ 1.1609 +case _value: eventName.AssignLiteral(_name) ; break 1.1610 + 1.1611 + switch(aGuiEvent->message) 1.1612 + { 1.1613 + _ASSIGN_eventName(NS_BLUR_CONTENT,"NS_BLUR_CONTENT"); 1.1614 + _ASSIGN_eventName(NS_DRAGDROP_GESTURE,"NS_DND_GESTURE"); 1.1615 + _ASSIGN_eventName(NS_DRAGDROP_DROP,"NS_DND_DROP"); 1.1616 + _ASSIGN_eventName(NS_DRAGDROP_ENTER,"NS_DND_ENTER"); 1.1617 + _ASSIGN_eventName(NS_DRAGDROP_EXIT,"NS_DND_EXIT"); 1.1618 + _ASSIGN_eventName(NS_DRAGDROP_OVER,"NS_DND_OVER"); 1.1619 + _ASSIGN_eventName(NS_EDITOR_INPUT,"NS_EDITOR_INPUT"); 1.1620 + _ASSIGN_eventName(NS_FOCUS_CONTENT,"NS_FOCUS_CONTENT"); 1.1621 + _ASSIGN_eventName(NS_FORM_SELECTED,"NS_FORM_SELECTED"); 1.1622 + _ASSIGN_eventName(NS_FORM_CHANGE,"NS_FORM_CHANGE"); 1.1623 + _ASSIGN_eventName(NS_FORM_RESET,"NS_FORM_RESET"); 1.1624 + _ASSIGN_eventName(NS_FORM_SUBMIT,"NS_FORM_SUBMIT"); 1.1625 + _ASSIGN_eventName(NS_IMAGE_ABORT,"NS_IMAGE_ABORT"); 1.1626 + _ASSIGN_eventName(NS_LOAD_ERROR,"NS_LOAD_ERROR"); 1.1627 + _ASSIGN_eventName(NS_KEY_DOWN,"NS_KEY_DOWN"); 1.1628 + _ASSIGN_eventName(NS_KEY_PRESS,"NS_KEY_PRESS"); 1.1629 + _ASSIGN_eventName(NS_KEY_UP,"NS_KEY_UP"); 1.1630 + _ASSIGN_eventName(NS_MOUSE_ENTER,"NS_MOUSE_ENTER"); 1.1631 + _ASSIGN_eventName(NS_MOUSE_EXIT,"NS_MOUSE_EXIT"); 1.1632 + _ASSIGN_eventName(NS_MOUSE_BUTTON_DOWN,"NS_MOUSE_BUTTON_DOWN"); 1.1633 + _ASSIGN_eventName(NS_MOUSE_BUTTON_UP,"NS_MOUSE_BUTTON_UP"); 1.1634 + _ASSIGN_eventName(NS_MOUSE_CLICK,"NS_MOUSE_CLICK"); 1.1635 + _ASSIGN_eventName(NS_MOUSE_DOUBLECLICK,"NS_MOUSE_DBLCLICK"); 1.1636 + _ASSIGN_eventName(NS_MOUSE_MOVE,"NS_MOUSE_MOVE"); 1.1637 + _ASSIGN_eventName(NS_LOAD,"NS_LOAD"); 1.1638 + _ASSIGN_eventName(NS_POPSTATE,"NS_POPSTATE"); 1.1639 + _ASSIGN_eventName(NS_BEFORE_SCRIPT_EXECUTE,"NS_BEFORE_SCRIPT_EXECUTE"); 1.1640 + _ASSIGN_eventName(NS_AFTER_SCRIPT_EXECUTE,"NS_AFTER_SCRIPT_EXECUTE"); 1.1641 + _ASSIGN_eventName(NS_PAGE_UNLOAD,"NS_PAGE_UNLOAD"); 1.1642 + _ASSIGN_eventName(NS_HASHCHANGE,"NS_HASHCHANGE"); 1.1643 + _ASSIGN_eventName(NS_READYSTATECHANGE,"NS_READYSTATECHANGE"); 1.1644 + _ASSIGN_eventName(NS_XUL_BROADCAST, "NS_XUL_BROADCAST"); 1.1645 + _ASSIGN_eventName(NS_XUL_COMMAND_UPDATE, "NS_XUL_COMMAND_UPDATE"); 1.1646 + 1.1647 +#undef _ASSIGN_eventName 1.1648 + 1.1649 + default: 1.1650 + { 1.1651 + char buf[32]; 1.1652 + 1.1653 + sprintf(buf,"UNKNOWN: %d",aGuiEvent->message); 1.1654 + 1.1655 + CopyASCIItoUTF16(buf, eventName); 1.1656 + } 1.1657 + break; 1.1658 + } 1.1659 + 1.1660 + return nsAutoString(eventName); 1.1661 +} 1.1662 +////////////////////////////////////////////////////////////// 1.1663 +// 1.1664 +// Code to deal with paint and event debug prefs. 1.1665 +// 1.1666 +////////////////////////////////////////////////////////////// 1.1667 +struct PrefPair 1.1668 +{ 1.1669 + const char * name; 1.1670 + bool value; 1.1671 +}; 1.1672 + 1.1673 +static PrefPair debug_PrefValues[] = 1.1674 +{ 1.1675 + { "nglayout.debug.crossing_event_dumping", false }, 1.1676 + { "nglayout.debug.event_dumping", false }, 1.1677 + { "nglayout.debug.invalidate_dumping", false }, 1.1678 + { "nglayout.debug.motion_event_dumping", false }, 1.1679 + { "nglayout.debug.paint_dumping", false }, 1.1680 + { "nglayout.debug.paint_flashing", false } 1.1681 +}; 1.1682 + 1.1683 +////////////////////////////////////////////////////////////// 1.1684 +bool 1.1685 +nsBaseWidget::debug_GetCachedBoolPref(const char * aPrefName) 1.1686 +{ 1.1687 + NS_ASSERTION(nullptr != aPrefName,"cmon, pref name is null."); 1.1688 + 1.1689 + for (uint32_t i = 0; i < ArrayLength(debug_PrefValues); i++) 1.1690 + { 1.1691 + if (strcmp(debug_PrefValues[i].name, aPrefName) == 0) 1.1692 + { 1.1693 + return debug_PrefValues[i].value; 1.1694 + } 1.1695 + } 1.1696 + 1.1697 + return false; 1.1698 +} 1.1699 +////////////////////////////////////////////////////////////// 1.1700 +static void debug_SetCachedBoolPref(const char * aPrefName,bool aValue) 1.1701 +{ 1.1702 + NS_ASSERTION(nullptr != aPrefName,"cmon, pref name is null."); 1.1703 + 1.1704 + for (uint32_t i = 0; i < ArrayLength(debug_PrefValues); i++) 1.1705 + { 1.1706 + if (strcmp(debug_PrefValues[i].name, aPrefName) == 0) 1.1707 + { 1.1708 + debug_PrefValues[i].value = aValue; 1.1709 + 1.1710 + return; 1.1711 + } 1.1712 + } 1.1713 + 1.1714 + NS_ASSERTION(false, "cmon, this code is not reached dude."); 1.1715 +} 1.1716 + 1.1717 +////////////////////////////////////////////////////////////// 1.1718 +class Debug_PrefObserver MOZ_FINAL : public nsIObserver { 1.1719 + public: 1.1720 + NS_DECL_ISUPPORTS 1.1721 + NS_DECL_NSIOBSERVER 1.1722 +}; 1.1723 + 1.1724 +NS_IMPL_ISUPPORTS(Debug_PrefObserver, nsIObserver) 1.1725 + 1.1726 +NS_IMETHODIMP 1.1727 +Debug_PrefObserver::Observe(nsISupports* subject, const char* topic, 1.1728 + const char16_t* data) 1.1729 +{ 1.1730 + NS_ConvertUTF16toUTF8 prefName(data); 1.1731 + 1.1732 + bool value = Preferences::GetBool(prefName.get(), false); 1.1733 + debug_SetCachedBoolPref(prefName.get(), value); 1.1734 + return NS_OK; 1.1735 +} 1.1736 + 1.1737 +////////////////////////////////////////////////////////////// 1.1738 +/* static */ void 1.1739 +debug_RegisterPrefCallbacks() 1.1740 +{ 1.1741 + static bool once = true; 1.1742 + 1.1743 + if (!once) { 1.1744 + return; 1.1745 + } 1.1746 + 1.1747 + once = false; 1.1748 + 1.1749 + nsCOMPtr<nsIObserver> obs(new Debug_PrefObserver()); 1.1750 + for (uint32_t i = 0; i < ArrayLength(debug_PrefValues); i++) { 1.1751 + // Initialize the pref values 1.1752 + debug_PrefValues[i].value = 1.1753 + Preferences::GetBool(debug_PrefValues[i].name, false); 1.1754 + 1.1755 + if (obs) { 1.1756 + // Register callbacks for when these change 1.1757 + Preferences::AddStrongObserver(obs, debug_PrefValues[i].name); 1.1758 + } 1.1759 + } 1.1760 +} 1.1761 +////////////////////////////////////////////////////////////// 1.1762 +static int32_t 1.1763 +_GetPrintCount() 1.1764 +{ 1.1765 + static int32_t sCount = 0; 1.1766 + 1.1767 + return ++sCount; 1.1768 +} 1.1769 +////////////////////////////////////////////////////////////// 1.1770 +/* static */ bool 1.1771 +nsBaseWidget::debug_WantPaintFlashing() 1.1772 +{ 1.1773 + return debug_GetCachedBoolPref("nglayout.debug.paint_flashing"); 1.1774 +} 1.1775 +////////////////////////////////////////////////////////////// 1.1776 +/* static */ void 1.1777 +nsBaseWidget::debug_DumpEvent(FILE * aFileOut, 1.1778 + nsIWidget * aWidget, 1.1779 + WidgetGUIEvent* aGuiEvent, 1.1780 + const nsAutoCString & aWidgetName, 1.1781 + int32_t aWindowID) 1.1782 +{ 1.1783 + if (aGuiEvent->message == NS_MOUSE_MOVE) 1.1784 + { 1.1785 + if (!debug_GetCachedBoolPref("nglayout.debug.motion_event_dumping")) 1.1786 + return; 1.1787 + } 1.1788 + 1.1789 + if (aGuiEvent->message == NS_MOUSE_ENTER || 1.1790 + aGuiEvent->message == NS_MOUSE_EXIT) 1.1791 + { 1.1792 + if (!debug_GetCachedBoolPref("nglayout.debug.crossing_event_dumping")) 1.1793 + return; 1.1794 + } 1.1795 + 1.1796 + if (!debug_GetCachedBoolPref("nglayout.debug.event_dumping")) 1.1797 + return; 1.1798 + 1.1799 + NS_LossyConvertUTF16toASCII tempString(debug_GuiEventToString(aGuiEvent).get()); 1.1800 + 1.1801 + fprintf(aFileOut, 1.1802 + "%4d %-26s widget=%-8p name=%-12s id=0x%-6x refpt=%d,%d\n", 1.1803 + _GetPrintCount(), 1.1804 + tempString.get(), 1.1805 + (void *) aWidget, 1.1806 + aWidgetName.get(), 1.1807 + aWindowID, 1.1808 + aGuiEvent->refPoint.x, 1.1809 + aGuiEvent->refPoint.y); 1.1810 +} 1.1811 +////////////////////////////////////////////////////////////// 1.1812 +/* static */ void 1.1813 +nsBaseWidget::debug_DumpPaintEvent(FILE * aFileOut, 1.1814 + nsIWidget * aWidget, 1.1815 + const nsIntRegion & aRegion, 1.1816 + const nsAutoCString & aWidgetName, 1.1817 + int32_t aWindowID) 1.1818 +{ 1.1819 + NS_ASSERTION(nullptr != aFileOut,"cmon, null output FILE"); 1.1820 + NS_ASSERTION(nullptr != aWidget,"cmon, the widget is null"); 1.1821 + 1.1822 + if (!debug_GetCachedBoolPref("nglayout.debug.paint_dumping")) 1.1823 + return; 1.1824 + 1.1825 + nsIntRect rect = aRegion.GetBounds(); 1.1826 + fprintf(aFileOut, 1.1827 + "%4d PAINT widget=%p name=%-12s id=0x%-6x bounds-rect=%3d,%-3d %3d,%-3d", 1.1828 + _GetPrintCount(), 1.1829 + (void *) aWidget, 1.1830 + aWidgetName.get(), 1.1831 + aWindowID, 1.1832 + rect.x, rect.y, rect.width, rect.height 1.1833 + ); 1.1834 + 1.1835 + fprintf(aFileOut,"\n"); 1.1836 +} 1.1837 +////////////////////////////////////////////////////////////// 1.1838 +/* static */ void 1.1839 +nsBaseWidget::debug_DumpInvalidate(FILE * aFileOut, 1.1840 + nsIWidget * aWidget, 1.1841 + const nsIntRect * aRect, 1.1842 + const nsAutoCString & aWidgetName, 1.1843 + int32_t aWindowID) 1.1844 +{ 1.1845 + if (!debug_GetCachedBoolPref("nglayout.debug.invalidate_dumping")) 1.1846 + return; 1.1847 + 1.1848 + NS_ASSERTION(nullptr != aFileOut,"cmon, null output FILE"); 1.1849 + NS_ASSERTION(nullptr != aWidget,"cmon, the widget is null"); 1.1850 + 1.1851 + fprintf(aFileOut, 1.1852 + "%4d Invalidate widget=%p name=%-12s id=0x%-6x", 1.1853 + _GetPrintCount(), 1.1854 + (void *) aWidget, 1.1855 + aWidgetName.get(), 1.1856 + aWindowID); 1.1857 + 1.1858 + if (aRect) 1.1859 + { 1.1860 + fprintf(aFileOut, 1.1861 + " rect=%3d,%-3d %3d,%-3d", 1.1862 + aRect->x, 1.1863 + aRect->y, 1.1864 + aRect->width, 1.1865 + aRect->height); 1.1866 + } 1.1867 + else 1.1868 + { 1.1869 + fprintf(aFileOut, 1.1870 + " rect=%-15s", 1.1871 + "none"); 1.1872 + } 1.1873 + 1.1874 + fprintf(aFileOut,"\n"); 1.1875 +} 1.1876 +////////////////////////////////////////////////////////////// 1.1877 + 1.1878 +#endif // DEBUG 1.1879 +