widget/xpwidgets/nsBaseWidget.cpp

changeset 0
6474c204b198
     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 +

mercurial