widget/xpwidgets/nsBaseWidget.cpp

Fri, 16 Jan 2015 04:50:19 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 04:50:19 +0100
branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
permissions
-rw-r--r--

Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "mozilla/ArrayUtils.h"
     8 #include "mozilla/layers/CompositorChild.h"
     9 #include "mozilla/layers/CompositorParent.h"
    10 #include "mozilla/layers/ImageBridgeChild.h"
    11 #include "nsBaseWidget.h"
    12 #include "nsDeviceContext.h"
    13 #include "nsCOMPtr.h"
    14 #include "nsGfxCIID.h"
    15 #include "nsWidgetsCID.h"
    16 #include "nsServiceManagerUtils.h"
    17 #include "nsIScreenManager.h"
    18 #include "nsAppDirectoryServiceDefs.h"
    19 #include "nsISimpleEnumerator.h"
    20 #include "nsIContent.h"
    21 #include "nsIDocument.h"
    22 #include "nsIPresShell.h"
    23 #include "nsIServiceManager.h"
    24 #include "mozilla/Preferences.h"
    25 #include "BasicLayers.h"
    26 #include "ClientLayerManager.h"
    27 #include "mozilla/layers/Compositor.h"
    28 #include "nsIXULRuntime.h"
    29 #include "nsIXULWindow.h"
    30 #include "nsIBaseWindow.h"
    31 #include "nsXULPopupManager.h"
    32 #include "nsIWidgetListener.h"
    33 #include "nsIGfxInfo.h"
    34 #include "npapi.h"
    35 #include "base/thread.h"
    36 #include "prdtoa.h"
    37 #include "prenv.h"
    38 #include "mozilla/Attributes.h"
    39 #include "mozilla/unused.h"
    40 #include "nsContentUtils.h"
    41 #include "gfxPrefs.h"
    42 #include "mozilla/gfx/2D.h"
    43 #include "mozilla/MouseEvents.h"
    44 #include "GLConsts.h"
    45 #include "LayerScope.h"
    46 #include "mozilla/unused.h"
    48 #ifdef ACCESSIBILITY
    49 #include "nsAccessibilityService.h"
    50 #endif
    52 #ifdef DEBUG
    53 #include "nsIObserver.h"
    55 static void debug_RegisterPrefCallbacks();
    57 #endif
    59 #ifdef NOISY_WIDGET_LEAKS
    60 static int32_t gNumWidgets;
    61 #endif
    63 #ifdef XP_MACOSX
    64 #include "nsCocoaFeatures.h"
    65 #endif
    67 nsIRollupListener* nsBaseWidget::gRollupListener = nullptr;
    69 using namespace mozilla::layers;
    70 using namespace mozilla::ipc;
    71 using namespace mozilla;
    72 using base::Thread;
    74 nsIContent* nsBaseWidget::mLastRollup = nullptr;
    75 // Global user preference for disabling native theme. Used
    76 // in NativeWindowTheme.
    77 bool            gDisableNativeTheme               = false;
    79 // Async pump timer during injected long touch taps
    80 #define TOUCH_INJECT_PUMP_TIMER_MSEC 50
    81 #define TOUCH_INJECT_LONG_TAP_DEFAULT_MSEC 1500
    82 int32_t nsIWidget::sPointerIdCounter = 0;
    84 // nsBaseWidget
    85 NS_IMPL_ISUPPORTS(nsBaseWidget, nsIWidget)
    88 nsAutoRollup::nsAutoRollup()
    89 {
    90   // remember if mLastRollup was null, and only clear it upon destruction
    91   // if so. This prevents recursive usage of nsAutoRollup from clearing
    92   // mLastRollup when it shouldn't.
    93   wasClear = !nsBaseWidget::mLastRollup;
    94 }
    96 nsAutoRollup::~nsAutoRollup()
    97 {
    98   if (nsBaseWidget::mLastRollup && wasClear) {
    99     NS_RELEASE(nsBaseWidget::mLastRollup);
   100   }
   101 }
   103 //-------------------------------------------------------------------------
   104 //
   105 // nsBaseWidget constructor
   106 //
   107 //-------------------------------------------------------------------------
   109 nsBaseWidget::nsBaseWidget()
   110 : mWidgetListener(nullptr)
   111 , mAttachedWidgetListener(nullptr)
   112 , mContext(nullptr)
   113 , mCursor(eCursor_standard)
   114 , mBorderStyle(eBorderStyle_none)
   115 , mUseLayersAcceleration(false)
   116 , mForceLayersAcceleration(false)
   117 , mTemporarilyUseBasicLayerManager(false)
   118 , mUseAttachedEvents(false)
   119 , mContextInitialized(false)
   120 , mBounds(0,0,0,0)
   121 , mOriginalBounds(nullptr)
   122 , mClipRectCount(0)
   123 , mSizeMode(nsSizeMode_Normal)
   124 , mPopupLevel(ePopupLevelTop)
   125 , mPopupType(ePopupTypeAny)
   126 {
   127 #ifdef NOISY_WIDGET_LEAKS
   128   gNumWidgets++;
   129   printf("WIDGETS+ = %d\n", gNumWidgets);
   130 #endif
   132 #ifdef DEBUG
   133   debug_RegisterPrefCallbacks();
   134 #endif
   136   mShutdownObserver = new WidgetShutdownObserver(this);
   137   nsContentUtils::RegisterShutdownObserver(mShutdownObserver);
   138 }
   140 NS_IMPL_ISUPPORTS(WidgetShutdownObserver, nsIObserver)
   142 NS_IMETHODIMP
   143 WidgetShutdownObserver::Observe(nsISupports *aSubject,
   144                                 const char *aTopic,
   145                                 const char16_t *aData)
   146 {
   147   if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0 &&
   148       mWidget) {
   149     mWidget->Shutdown();
   150     nsContentUtils::UnregisterShutdownObserver(this);
   151   }
   152  return NS_OK;
   153 }
   155 void
   156 nsBaseWidget::Shutdown()
   157 {
   158   DestroyCompositor();
   159   mShutdownObserver = nullptr;
   160 }
   162 static void DeferredDestroyCompositor(CompositorParent* aCompositorParent,
   163                               CompositorChild* aCompositorChild)
   164 {
   165     // Bug 848949 needs to be fixed before
   166     // we can close the channel properly
   167     //aCompositorChild->Close();
   168     aCompositorParent->Release();
   169     aCompositorChild->Release();
   170 }
   172 void nsBaseWidget::DestroyCompositor()
   173 {
   174   LayerScope::DestroyServerSocket();
   176   if (mCompositorChild) {
   177     mCompositorChild->SendWillStop();
   178     mCompositorChild->Destroy();
   180     // The call just made to SendWillStop can result in IPC from the
   181     // CompositorParent to the CompositorChild (e.g. caused by the destruction
   182     // of shared memory). We need to ensure this gets processed by the
   183     // CompositorChild before it gets destroyed. It suffices to ensure that
   184     // events already in the MessageLoop get processed before the
   185     // CompositorChild is destroyed, so we add a task to the MessageLoop to
   186     // handle compositor desctruction.
   187     MessageLoop::current()->PostTask(FROM_HERE,
   188                NewRunnableFunction(DeferredDestroyCompositor, mCompositorParent,
   189                                    mCompositorChild));
   190     // The DestroyCompositor task we just added to the MessageLoop will handle
   191     // releasing mCompositorParent and mCompositorChild.
   192     unused << mCompositorParent.forget();
   193     unused << mCompositorChild.forget();
   194   }
   195 }
   197 //-------------------------------------------------------------------------
   198 //
   199 // nsBaseWidget destructor
   200 //
   201 //-------------------------------------------------------------------------
   202 nsBaseWidget::~nsBaseWidget()
   203 {
   204   if (mLayerManager &&
   205       mLayerManager->GetBackendType() == LayersBackend::LAYERS_BASIC) {
   206     static_cast<BasicLayerManager*>(mLayerManager.get())->ClearRetainerWidget();
   207   }
   209   if (mLayerManager) {
   210     mLayerManager->Destroy();
   211     mLayerManager = nullptr;
   212   }
   214   if (mShutdownObserver) {
   215     // If the shutdown observer is currently processing observers,
   216     // then UnregisterShutdownObserver won't stop our Observer
   217     // function from being called. Make sure we don't try
   218     // to reference the dead widget.
   219     mShutdownObserver->mWidget = nullptr;
   220     nsContentUtils::UnregisterShutdownObserver(mShutdownObserver);
   221   }
   223   DestroyCompositor();
   225 #ifdef NOISY_WIDGET_LEAKS
   226   gNumWidgets--;
   227   printf("WIDGETS- = %d\n", gNumWidgets);
   228 #endif
   230   NS_IF_RELEASE(mContext);
   231   delete mOriginalBounds;
   232 }
   235 //-------------------------------------------------------------------------
   236 //
   237 // Basic create.
   238 //
   239 //-------------------------------------------------------------------------
   240 void nsBaseWidget::BaseCreate(nsIWidget *aParent,
   241                               const nsIntRect &aRect,
   242                               nsDeviceContext *aContext,
   243                               nsWidgetInitData *aInitData)
   244 {
   245   static bool gDisableNativeThemeCached = false;
   246   if (!gDisableNativeThemeCached) {
   247     Preferences::AddBoolVarCache(&gDisableNativeTheme,
   248                                  "mozilla.widget.disable-native-theme",
   249                                  gDisableNativeTheme);
   250     gDisableNativeThemeCached = true;
   251   }
   253   // keep a reference to the device context
   254   if (aContext) {
   255     mContext = aContext;
   256     NS_ADDREF(mContext);
   257   }
   258   else {
   259     mContext = new nsDeviceContext();
   260     NS_ADDREF(mContext);
   261     mContext->Init(nullptr);
   262   }
   264   if (nullptr != aInitData) {
   265     mWindowType = aInitData->mWindowType;
   266     mBorderStyle = aInitData->mBorderStyle;
   267     mPopupLevel = aInitData->mPopupLevel;
   268     mPopupType = aInitData->mPopupHint;
   269     mRequireOffMainThreadCompositing = aInitData->mRequireOffMainThreadCompositing;
   270   }
   272   if (aParent) {
   273     aParent->AddChild(this);
   274   }
   275 }
   277 NS_IMETHODIMP nsBaseWidget::CaptureMouse(bool aCapture)
   278 {
   279   return NS_OK;
   280 }
   282 //-------------------------------------------------------------------------
   283 //
   284 // Accessor functions to get/set the client data
   285 //
   286 //-------------------------------------------------------------------------
   288 nsIWidgetListener* nsBaseWidget::GetWidgetListener()
   289 {
   290   return mWidgetListener;
   291 }
   293 void nsBaseWidget::SetWidgetListener(nsIWidgetListener* aWidgetListener)
   294 {
   295   mWidgetListener = aWidgetListener;
   296 }
   298 already_AddRefed<nsIWidget>
   299 nsBaseWidget::CreateChild(const nsIntRect  &aRect,
   300                           nsDeviceContext *aContext,
   301                           nsWidgetInitData *aInitData,
   302                           bool             aForceUseIWidgetParent)
   303 {
   304   nsIWidget* parent = this;
   305   nsNativeWidget nativeParent = nullptr;
   307   if (!aForceUseIWidgetParent) {
   308     // Use only either parent or nativeParent, not both, to match
   309     // existing code.  Eventually Create() should be divested of its
   310     // nativeWidget parameter.
   311     nativeParent = parent ? parent->GetNativeData(NS_NATIVE_WIDGET) : nullptr;
   312     parent = nativeParent ? nullptr : parent;
   313     NS_ABORT_IF_FALSE(!parent || !nativeParent, "messed up logic");
   314   }
   316   nsCOMPtr<nsIWidget> widget;
   317   if (aInitData && aInitData->mWindowType == eWindowType_popup) {
   318     widget = AllocateChildPopupWidget();
   319   } else {
   320     static NS_DEFINE_IID(kCChildCID, NS_CHILD_CID);
   321     widget = do_CreateInstance(kCChildCID);
   322   }
   324   if (widget &&
   325       NS_SUCCEEDED(widget->Create(parent, nativeParent, aRect,
   326                                   aContext, aInitData))) {
   327     return widget.forget();
   328   }
   330   return nullptr;
   331 }
   333 // Attach a view to our widget which we'll send events to.
   334 NS_IMETHODIMP
   335 nsBaseWidget::AttachViewToTopLevel(bool aUseAttachedEvents,
   336                                    nsDeviceContext *aContext)
   337 {
   338   NS_ASSERTION((mWindowType == eWindowType_toplevel ||
   339                 mWindowType == eWindowType_dialog ||
   340                 mWindowType == eWindowType_invisible ||
   341                 mWindowType == eWindowType_child),
   342                "Can't attach to window of that type");
   344   mUseAttachedEvents = aUseAttachedEvents;
   346   if (aContext) {
   347     if (mContext) {
   348       NS_IF_RELEASE(mContext);
   349     }
   350     mContext = aContext;
   351     NS_ADDREF(mContext);
   352   }
   354   return NS_OK;
   355 }
   357 nsIWidgetListener* nsBaseWidget::GetAttachedWidgetListener()
   358  {
   359    return mAttachedWidgetListener;
   360  }
   362 void nsBaseWidget::SetAttachedWidgetListener(nsIWidgetListener* aListener)
   363  {
   364    mAttachedWidgetListener = aListener;
   365  }
   367 //-------------------------------------------------------------------------
   368 //
   369 // Close this nsBaseWidget
   370 //
   371 //-------------------------------------------------------------------------
   372 NS_METHOD nsBaseWidget::Destroy()
   373 {
   374   // Just in case our parent is the only ref to us
   375   nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
   376   // disconnect from the parent
   377   nsIWidget *parent = GetParent();
   378   if (parent) {
   379     parent->RemoveChild(this);
   380   }
   382   return NS_OK;
   383 }
   386 //-------------------------------------------------------------------------
   387 //
   388 // Set this nsBaseWidget's parent
   389 //
   390 //-------------------------------------------------------------------------
   391 NS_IMETHODIMP nsBaseWidget::SetParent(nsIWidget* aNewParent)
   392 {
   393   return NS_ERROR_NOT_IMPLEMENTED;
   394 }
   397 //-------------------------------------------------------------------------
   398 //
   399 // Get this nsBaseWidget parent
   400 //
   401 //-------------------------------------------------------------------------
   402 nsIWidget* nsBaseWidget::GetParent(void)
   403 {
   404   return nullptr;
   405 }
   407 //-------------------------------------------------------------------------
   408 //
   409 // Get this nsBaseWidget top level widget
   410 //
   411 //-------------------------------------------------------------------------
   412 nsIWidget* nsBaseWidget::GetTopLevelWidget()
   413 {
   414   nsIWidget *topLevelWidget = nullptr, *widget = this;
   415   while (widget) {
   416     topLevelWidget = widget;
   417     widget = widget->GetParent();
   418   }
   419   return topLevelWidget;
   420 }
   422 //-------------------------------------------------------------------------
   423 //
   424 // Get this nsBaseWidget's top (non-sheet) parent (if it's a sheet)
   425 //
   426 //-------------------------------------------------------------------------
   427 nsIWidget* nsBaseWidget::GetSheetWindowParent(void)
   428 {
   429   return nullptr;
   430 }
   432 float nsBaseWidget::GetDPI()
   433 {
   434   return 96.0f;
   435 }
   437 CSSToLayoutDeviceScale nsIWidget::GetDefaultScale()
   438 {
   439   double devPixelsPerCSSPixel = DefaultScaleOverride();
   441   if (devPixelsPerCSSPixel <= 0.0) {
   442     devPixelsPerCSSPixel = GetDefaultScaleInternal();
   443   }
   445   return CSSToLayoutDeviceScale(devPixelsPerCSSPixel);
   446 }
   448 /* static */
   449 double nsIWidget::DefaultScaleOverride()
   450 {
   451   // The number of device pixels per CSS pixel. A value <= 0 means choose
   452   // automatically based on the DPI. A positive value is used as-is. This effectively
   453   // controls the size of a CSS "px".
   454   double devPixelsPerCSSPixel = -1.0;
   456   nsAdoptingCString prefString = Preferences::GetCString("layout.css.devPixelsPerPx");
   457   if (!prefString.IsEmpty()) {
   458     devPixelsPerCSSPixel = PR_strtod(prefString, nullptr);
   459   }
   461   return devPixelsPerCSSPixel;
   462 }
   464 //-------------------------------------------------------------------------
   465 //
   466 // Add a child to the list of children
   467 //
   468 //-------------------------------------------------------------------------
   469 void nsBaseWidget::AddChild(nsIWidget* aChild)
   470 {
   471   NS_PRECONDITION(!aChild->GetNextSibling() && !aChild->GetPrevSibling(),
   472                   "aChild not properly removed from its old child list");
   474   if (!mFirstChild) {
   475     mFirstChild = mLastChild = aChild;
   476   } else {
   477     // append to the list
   478     NS_ASSERTION(mLastChild, "Bogus state");
   479     NS_ASSERTION(!mLastChild->GetNextSibling(), "Bogus state");
   480     mLastChild->SetNextSibling(aChild);
   481     aChild->SetPrevSibling(mLastChild);
   482     mLastChild = aChild;
   483   }
   484 }
   487 //-------------------------------------------------------------------------
   488 //
   489 // Remove a child from the list of children
   490 //
   491 //-------------------------------------------------------------------------
   492 void nsBaseWidget::RemoveChild(nsIWidget* aChild)
   493 {
   494 #ifdef DEBUG
   495 #ifdef XP_MACOSX
   496   // nsCocoaWindow doesn't implement GetParent, so in that case parent will be
   497   // null and we'll just have to do without this assertion.
   498   nsIWidget* parent = aChild->GetParent();
   499   NS_ASSERTION(!parent || parent == this, "Not one of our kids!");
   500 #else
   501   NS_ASSERTION(aChild->GetParent() == this, "Not one of our kids!");
   502 #endif
   503 #endif
   505   if (mLastChild == aChild) {
   506     mLastChild = mLastChild->GetPrevSibling();
   507   }
   508   if (mFirstChild == aChild) {
   509     mFirstChild = mFirstChild->GetNextSibling();
   510   }
   512   // Now remove from the list.  Make sure that we pass ownership of the tail
   513   // of the list correctly before we have aChild let go of it.
   514   nsIWidget* prev = aChild->GetPrevSibling();
   515   nsIWidget* next = aChild->GetNextSibling();
   516   if (prev) {
   517     prev->SetNextSibling(next);
   518   }
   519   if (next) {
   520     next->SetPrevSibling(prev);
   521   }
   523   aChild->SetNextSibling(nullptr);
   524   aChild->SetPrevSibling(nullptr);
   525 }
   528 //-------------------------------------------------------------------------
   529 //
   530 // Sets widget's position within its parent's child list.
   531 //
   532 //-------------------------------------------------------------------------
   533 void nsBaseWidget::SetZIndex(int32_t aZIndex)
   534 {
   535   // Hold a ref to ourselves just in case, since we're going to remove
   536   // from our parent.
   537   nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
   539   mZIndex = aZIndex;
   541   // reorder this child in its parent's list.
   542   nsBaseWidget* parent = static_cast<nsBaseWidget*>(GetParent());
   543   if (parent) {
   544     parent->RemoveChild(this);
   545     // Scope sib outside the for loop so we can check it afterward
   546     nsIWidget* sib = parent->GetFirstChild();
   547     for ( ; sib; sib = sib->GetNextSibling()) {
   548       int32_t childZIndex = GetZIndex();
   549       if (aZIndex < childZIndex) {
   550         // Insert ourselves before sib
   551         nsIWidget* prev = sib->GetPrevSibling();
   552         mNextSibling = sib;
   553         mPrevSibling = prev;
   554         sib->SetPrevSibling(this);
   555         if (prev) {
   556           prev->SetNextSibling(this);
   557         } else {
   558           NS_ASSERTION(sib == parent->mFirstChild, "Broken child list");
   559           // We've taken ownership of sib, so it's safe to have parent let
   560           // go of it
   561           parent->mFirstChild = this;
   562         }
   563         PlaceBehind(eZPlacementBelow, sib, false);
   564         break;
   565       }
   566     }
   567     // were we added to the list?
   568     if (!sib) {
   569       parent->AddChild(this);
   570     }
   571   }
   572 }
   574 //-------------------------------------------------------------------------
   575 //
   576 // Places widget behind the given widget (platforms must override)
   577 //
   578 //-------------------------------------------------------------------------
   579 NS_IMETHODIMP nsBaseWidget::PlaceBehind(nsTopLevelWidgetZPlacement aPlacement,
   580                                         nsIWidget *aWidget, bool aActivate)
   581 {
   582   return NS_OK;
   583 }
   585 //-------------------------------------------------------------------------
   586 //
   587 // Maximize, minimize or restore the window. The BaseWidget implementation
   588 // merely stores the state.
   589 //
   590 //-------------------------------------------------------------------------
   591 NS_IMETHODIMP nsBaseWidget::SetSizeMode(int32_t aMode)
   592 {
   593   if (aMode == nsSizeMode_Normal ||
   594       aMode == nsSizeMode_Minimized ||
   595       aMode == nsSizeMode_Maximized ||
   596       aMode == nsSizeMode_Fullscreen) {
   598     mSizeMode = (nsSizeMode) aMode;
   599     return NS_OK;
   600   }
   601   return NS_ERROR_ILLEGAL_VALUE;
   602 }
   604 //-------------------------------------------------------------------------
   605 //
   606 // Get this component cursor
   607 //
   608 //-------------------------------------------------------------------------
   609 nsCursor nsBaseWidget::GetCursor()
   610 {
   611   return mCursor;
   612 }
   614 NS_METHOD nsBaseWidget::SetCursor(nsCursor aCursor)
   615 {
   616   mCursor = aCursor;
   617   return NS_OK;
   618 }
   620 NS_IMETHODIMP nsBaseWidget::SetCursor(imgIContainer* aCursor,
   621                                       uint32_t aHotspotX, uint32_t aHotspotY)
   622 {
   623   return NS_ERROR_NOT_IMPLEMENTED;
   624 }
   626 //-------------------------------------------------------------------------
   627 //
   628 // Window transparency methods
   629 //
   630 //-------------------------------------------------------------------------
   632 void nsBaseWidget::SetTransparencyMode(nsTransparencyMode aMode) {
   633 }
   635 nsTransparencyMode nsBaseWidget::GetTransparencyMode() {
   636   return eTransparencyOpaque;
   637 }
   639 bool
   640 nsBaseWidget::StoreWindowClipRegion(const nsTArray<nsIntRect>& aRects)
   641 {
   642   if (mClipRects && mClipRectCount == aRects.Length() &&
   643       memcmp(mClipRects, aRects.Elements(), sizeof(nsIntRect)*mClipRectCount) == 0)
   644     return false;
   646   mClipRectCount = aRects.Length();
   647   mClipRects = new nsIntRect[mClipRectCount];
   648   if (mClipRects) {
   649     memcpy(mClipRects, aRects.Elements(), sizeof(nsIntRect)*mClipRectCount);
   650   }
   651   return true;
   652 }
   654 void
   655 nsBaseWidget::GetWindowClipRegion(nsTArray<nsIntRect>* aRects)
   656 {
   657   if (mClipRects) {
   658     aRects->AppendElements(mClipRects.get(), mClipRectCount);
   659   } else {
   660     aRects->AppendElement(nsIntRect(0, 0, mBounds.width, mBounds.height));
   661   }
   662 }
   664 //-------------------------------------------------------------------------
   665 //
   666 // Set window shadow style
   667 //
   668 //-------------------------------------------------------------------------
   670 NS_IMETHODIMP nsBaseWidget::SetWindowShadowStyle(int32_t aMode)
   671 {
   672   return NS_ERROR_NOT_IMPLEMENTED;
   673 }
   675 //-------------------------------------------------------------------------
   676 //
   677 // Hide window borders/decorations for this widget
   678 //
   679 //-------------------------------------------------------------------------
   680 NS_IMETHODIMP nsBaseWidget::HideWindowChrome(bool aShouldHide)
   681 {
   682   return NS_ERROR_NOT_IMPLEMENTED;
   683 }
   685 //-------------------------------------------------------------------------
   686 //
   687 // Put the window into full-screen mode
   688 //
   689 //-------------------------------------------------------------------------
   690 NS_IMETHODIMP nsBaseWidget::MakeFullScreen(bool aFullScreen)
   691 {
   692   HideWindowChrome(aFullScreen);
   694   if (aFullScreen) {
   695     if (!mOriginalBounds)
   696       mOriginalBounds = new nsIntRect();
   697     GetScreenBounds(*mOriginalBounds);
   698     // convert dev pix to display pix for window manipulation
   699     CSSToLayoutDeviceScale scale = GetDefaultScale();
   700     mOriginalBounds->x = NSToIntRound(mOriginalBounds->x / scale.scale);
   701     mOriginalBounds->y = NSToIntRound(mOriginalBounds->y / scale.scale);
   702     mOriginalBounds->width = NSToIntRound(mOriginalBounds->width / scale.scale);
   703     mOriginalBounds->height = NSToIntRound(mOriginalBounds->height / scale.scale);
   705     // Move to top-left corner of screen and size to the screen dimensions
   706     nsCOMPtr<nsIScreenManager> screenManager;
   707     screenManager = do_GetService("@mozilla.org/gfx/screenmanager;1");
   708     NS_ASSERTION(screenManager, "Unable to grab screenManager.");
   709     if (screenManager) {
   710       nsCOMPtr<nsIScreen> screen;
   711       screenManager->ScreenForRect(mOriginalBounds->x,
   712                                    mOriginalBounds->y,
   713                                    mOriginalBounds->width,
   714                                    mOriginalBounds->height,
   715                                    getter_AddRefs(screen));
   716       if (screen) {
   717         int32_t left, top, width, height;
   718         if (NS_SUCCEEDED(screen->GetRectDisplayPix(&left, &top, &width, &height))) {
   719           Resize(left, top, width, height, true);
   720         }
   721       }
   722     }
   724   } else if (mOriginalBounds) {
   725     Resize(mOriginalBounds->x, mOriginalBounds->y, mOriginalBounds->width,
   726            mOriginalBounds->height, true);
   727   }
   729   return NS_OK;
   730 }
   732 nsBaseWidget::AutoLayerManagerSetup::AutoLayerManagerSetup(
   733     nsBaseWidget* aWidget, gfxContext* aTarget,
   734     BufferMode aDoubleBuffering, ScreenRotation aRotation)
   735   : mWidget(aWidget)
   736 {
   737   mLayerManager = static_cast<BasicLayerManager*>(mWidget->GetLayerManager());
   738   if (mLayerManager) {
   739     NS_ASSERTION(mLayerManager->GetBackendType() == LayersBackend::LAYERS_BASIC,
   740       "AutoLayerManagerSetup instantiated for non-basic layer backend!");
   741     mLayerManager->SetDefaultTarget(aTarget);
   742     mLayerManager->SetDefaultTargetConfiguration(aDoubleBuffering, aRotation);
   743   }
   744 }
   746 nsBaseWidget::AutoLayerManagerSetup::~AutoLayerManagerSetup()
   747 {
   748   if (mLayerManager) {
   749     NS_ASSERTION(mLayerManager->GetBackendType() == LayersBackend::LAYERS_BASIC,
   750       "AutoLayerManagerSetup instantiated for non-basic layer backend!");
   751     mLayerManager->SetDefaultTarget(nullptr);
   752     mLayerManager->SetDefaultTargetConfiguration(mozilla::layers::BufferMode::BUFFER_NONE, ROTATION_0);
   753   }
   754 }
   756 nsBaseWidget::AutoUseBasicLayerManager::AutoUseBasicLayerManager(nsBaseWidget* aWidget)
   757   : mWidget(aWidget)
   758 {
   759   mPreviousTemporarilyUseBasicLayerManager =
   760     mWidget->mTemporarilyUseBasicLayerManager;
   761   mWidget->mTemporarilyUseBasicLayerManager = true;
   762 }
   764 nsBaseWidget::AutoUseBasicLayerManager::~AutoUseBasicLayerManager()
   765 {
   766   mWidget->mTemporarilyUseBasicLayerManager =
   767     mPreviousTemporarilyUseBasicLayerManager;
   768 }
   770 bool
   771 nsBaseWidget::ComputeShouldAccelerate(bool aDefault)
   772 {
   773 #if defined(XP_WIN) || defined(ANDROID) || \
   774     defined(MOZ_GL_PROVIDER) || defined(XP_MACOSX) || defined(MOZ_WIDGET_QT)
   775   bool accelerateByDefault = true;
   776 #else
   777   bool accelerateByDefault = false;
   778 #endif
   780 #ifdef XP_MACOSX
   781   // 10.6.2 and lower have a bug involving textures and pixel buffer objects
   782   // that caused bug 629016, so we don't allow OpenGL-accelerated layers on
   783   // those versions of the OS.
   784   // This will still let full-screen video be accelerated on OpenGL, because
   785   // that XUL widget opts in to acceleration, but that's probably OK.
   786   SInt32 major = nsCocoaFeatures::OSXVersionMajor();
   787   SInt32 minor = nsCocoaFeatures::OSXVersionMinor();
   788   SInt32 bugfix = nsCocoaFeatures::OSXVersionBugFix();
   789   if (major == 10 && minor == 6 && bugfix <= 2) {
   790     accelerateByDefault = false;
   791   }
   792 #endif
   794   // we should use AddBoolPrefVarCache
   795   bool disableAcceleration = gfxPrefs::LayersAccelerationDisabled();
   796   mForceLayersAcceleration = gfxPrefs::LayersAccelerationForceEnabled();
   798   const char *acceleratedEnv = PR_GetEnv("MOZ_ACCELERATED");
   799   accelerateByDefault = accelerateByDefault ||
   800                         (acceleratedEnv && (*acceleratedEnv != '0'));
   802   nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1");
   803   bool safeMode = false;
   804   if (xr)
   805     xr->GetInSafeMode(&safeMode);
   807   bool whitelisted = false;
   809   nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
   810   if (gfxInfo) {
   811     // bug 655578: on X11 at least, we must always call GetData (even if we don't need that information)
   812     // as that's what causes GfxInfo initialization which kills the zombie 'glxtest' process.
   813     // initially we relied on the fact that GetFeatureStatus calls GetData for us, but bug 681026 showed
   814     // that assumption to be unsafe.
   815     gfxInfo->GetData();
   817     int32_t status;
   818     if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_OPENGL_LAYERS, &status))) {
   819       if (status == nsIGfxInfo::FEATURE_NO_INFO) {
   820         whitelisted = true;
   821       }
   822     }
   823   }
   825   if (disableAcceleration || safeMode)
   826     return false;
   828   if (mForceLayersAcceleration)
   829     return true;
   831   if (!whitelisted) {
   832     static int tell_me_once = 0;
   833     if (!tell_me_once) {
   834       NS_WARNING("OpenGL-accelerated layers are not supported on this system");
   835       tell_me_once = 1;
   836     }
   837 #ifdef MOZ_ANDROID_OMTC
   838     NS_RUNTIMEABORT("OpenGL-accelerated layers are a hard requirement on this platform. "
   839                     "Cannot continue without support for them");
   840 #endif
   841     return false;
   842   }
   844   if (accelerateByDefault)
   845     return true;
   847   /* use the window acceleration flag */
   848   return aDefault;
   849 }
   851 CompositorParent* nsBaseWidget::NewCompositorParent(int aSurfaceWidth,
   852                                                     int aSurfaceHeight)
   853 {
   854   return new CompositorParent(this, false, aSurfaceWidth, aSurfaceHeight);
   855 }
   857 void nsBaseWidget::CreateCompositor()
   858 {
   859   nsIntRect rect;
   860   GetBounds(rect);
   861   CreateCompositor(rect.width, rect.height);
   862 }
   864 void
   865 nsBaseWidget::GetPreferredCompositorBackends(nsTArray<LayersBackend>& aHints)
   866 {
   867   if (mUseLayersAcceleration) {
   868     aHints.AppendElement(LayersBackend::LAYERS_OPENGL);
   869   }
   871   aHints.AppendElement(LayersBackend::LAYERS_BASIC);
   872 }
   874 static void
   875 CheckForBasicBackends(nsTArray<LayersBackend>& aHints)
   876 {
   877   for (size_t i = 0; i < aHints.Length(); ++i) {
   878     if (aHints[i] == LayersBackend::LAYERS_BASIC &&
   879         !Preferences::GetBool("layers.offmainthreadcomposition.force-basic", false)) {
   880       // basic compositor is not stable enough for regular use
   881       aHints[i] = LayersBackend::LAYERS_NONE;
   882     }
   883   }
   884 }
   886 void nsBaseWidget::CreateCompositor(int aWidth, int aHeight)
   887 {
   888   // Recreating this is tricky, as we may still have an old and we need
   889   // to make sure it's properly destroyed by calling DestroyCompositor!
   891   // If we've already received a shutdown notification, don't try
   892   // create a new compositor.
   893   if (!mShutdownObserver) {
   894     return;
   895   }
   897   // The server socket has to be created on the main thread.
   898   LayerScope::CreateServerSocket();
   900   mCompositorParent = NewCompositorParent(aWidth, aHeight);
   901   MessageChannel *parentChannel = mCompositorParent->GetIPCChannel();
   902   ClientLayerManager* lm = new ClientLayerManager(this);
   903   MessageLoop *childMessageLoop = CompositorParent::CompositorLoop();
   904   mCompositorChild = new CompositorChild(lm);
   905   mCompositorChild->Open(parentChannel, childMessageLoop, ipc::ChildSide);
   907   TextureFactoryIdentifier textureFactoryIdentifier;
   908   PLayerTransactionChild* shadowManager = nullptr;
   909   nsTArray<LayersBackend> backendHints;
   910   GetPreferredCompositorBackends(backendHints);
   912   if (!mRequireOffMainThreadCompositing) {
   913     CheckForBasicBackends(backendHints);
   914   }
   916   bool success = false;
   917   if (!backendHints.IsEmpty()) {
   918     shadowManager = mCompositorChild->SendPLayerTransactionConstructor(
   919       backendHints, 0, &textureFactoryIdentifier, &success);
   920   }
   922   if (success) {
   923     ShadowLayerForwarder* lf = lm->AsShadowForwarder();
   924     if (!lf) {
   925       delete lm;
   926       mCompositorChild = nullptr;
   927       return;
   928     }
   929     lf->SetShadowManager(shadowManager);
   930     lf->IdentifyTextureHost(textureFactoryIdentifier);
   931     ImageBridgeChild::IdentifyCompositorTextureHost(textureFactoryIdentifier);
   932     WindowUsesOMTC();
   934     mLayerManager = lm;
   935     return;
   936   }
   938   NS_WARNING("Failed to create an OMT compositor.");
   939   DestroyCompositor();
   940   // Compositor child had the only reference to LayerManager and will have
   941   // deallocated it when being freed.
   942 }
   944 bool nsBaseWidget::ShouldUseOffMainThreadCompositing()
   945 {
   946   return CompositorParent::CompositorLoop();
   947 }
   949 LayerManager* nsBaseWidget::GetLayerManager(PLayerTransactionChild* aShadowManager,
   950                                             LayersBackend aBackendHint,
   951                                             LayerManagerPersistence aPersistence,
   952                                             bool* aAllowRetaining)
   953 {
   954   if (!mLayerManager) {
   956     mUseLayersAcceleration = ComputeShouldAccelerate(mUseLayersAcceleration);
   958     // Try to use an async compositor first, if possible
   959     if (ShouldUseOffMainThreadCompositing()) {
   960       // e10s uses the parameter to pass in the shadow manager from the TabChild
   961       // so we don't expect to see it there since this doesn't support e10s.
   962       NS_ASSERTION(aShadowManager == nullptr, "Async Compositor not supported with e10s");
   963       CreateCompositor();
   964     }
   966     if (!mLayerManager) {
   967       mLayerManager = CreateBasicLayerManager();
   968     }
   969   }
   970   if (mTemporarilyUseBasicLayerManager && !mBasicLayerManager) {
   971     mBasicLayerManager = CreateBasicLayerManager();
   972   }
   973   LayerManager* usedLayerManager = mTemporarilyUseBasicLayerManager ?
   974                                      mBasicLayerManager : mLayerManager;
   975   if (aAllowRetaining) {
   976     *aAllowRetaining = (usedLayerManager == mLayerManager);
   977   }
   978   return usedLayerManager;
   979 }
   981 LayerManager* nsBaseWidget::CreateBasicLayerManager()
   982 {
   983   return new BasicLayerManager(this);
   984 }
   986 CompositorChild* nsBaseWidget::GetRemoteRenderer()
   987 {
   988   return mCompositorChild;
   989 }
   991 TemporaryRef<mozilla::gfx::DrawTarget> nsBaseWidget::StartRemoteDrawing()
   992 {
   993   return nullptr;
   994 }
   996 //-------------------------------------------------------------------------
   997 //
   998 // Return the used device context
   999 //
  1000 //-------------------------------------------------------------------------
  1001 nsDeviceContext* nsBaseWidget::GetDeviceContext()
  1003   if (!mContextInitialized) {
  1004     mContext->Init(this);
  1005     mContextInitialized = true;
  1007   return mContext;
  1010 //-------------------------------------------------------------------------
  1011 //
  1012 // Get the thebes surface
  1013 //
  1014 //-------------------------------------------------------------------------
  1015 gfxASurface *nsBaseWidget::GetThebesSurface()
  1017   // in theory we should get our parent's surface,
  1018   // clone it, and set a device offset before returning
  1019   return nullptr;
  1023 //-------------------------------------------------------------------------
  1024 //
  1025 // Destroy the window
  1026 //
  1027 //-------------------------------------------------------------------------
  1028 void nsBaseWidget::OnDestroy()
  1030   // release references to device context and app shell
  1031   NS_IF_RELEASE(mContext);
  1034 NS_METHOD nsBaseWidget::SetWindowClass(const nsAString& xulWinType)
  1036   return NS_ERROR_NOT_IMPLEMENTED;
  1039 NS_METHOD nsBaseWidget::MoveClient(double aX, double aY)
  1041   nsIntPoint clientOffset(GetClientOffset());
  1043   // GetClientOffset returns device pixels; scale back to display pixels
  1044   // if that's what this widget uses for the Move/Resize APIs
  1045   CSSToLayoutDeviceScale scale = BoundsUseDisplayPixels()
  1046                                     ? GetDefaultScale()
  1047                                     : CSSToLayoutDeviceScale(1.0);
  1048   aX -= clientOffset.x * 1.0 / scale.scale;
  1049   aY -= clientOffset.y * 1.0 / scale.scale;
  1051   return Move(aX, aY);
  1054 NS_METHOD nsBaseWidget::ResizeClient(double aWidth,
  1055                                      double aHeight,
  1056                                      bool aRepaint)
  1058   NS_ASSERTION((aWidth >=0) , "Negative width passed to ResizeClient");
  1059   NS_ASSERTION((aHeight >=0), "Negative height passed to ResizeClient");
  1061   nsIntRect clientBounds;
  1062   GetClientBounds(clientBounds);
  1064   // GetClientBounds and mBounds are device pixels; scale back to display pixels
  1065   // if that's what this widget uses for the Move/Resize APIs
  1066   CSSToLayoutDeviceScale scale = BoundsUseDisplayPixels()
  1067                                     ? GetDefaultScale()
  1068                                     : CSSToLayoutDeviceScale(1.0);
  1069   double invScale = 1.0 / scale.scale;
  1070   aWidth = mBounds.width * invScale + (aWidth - clientBounds.width * invScale);
  1071   aHeight = mBounds.height * invScale + (aHeight - clientBounds.height * invScale);
  1073   return Resize(aWidth, aHeight, aRepaint);
  1076 NS_METHOD nsBaseWidget::ResizeClient(double aX,
  1077                                      double aY,
  1078                                      double aWidth,
  1079                                      double aHeight,
  1080                                      bool aRepaint)
  1082   NS_ASSERTION((aWidth >=0) , "Negative width passed to ResizeClient");
  1083   NS_ASSERTION((aHeight >=0), "Negative height passed to ResizeClient");
  1085   nsIntRect clientBounds;
  1086   GetClientBounds(clientBounds);
  1088   double scale = BoundsUseDisplayPixels() ? 1.0 / GetDefaultScale().scale : 1.0;
  1089   aWidth = mBounds.width * scale + (aWidth - clientBounds.width * scale);
  1090   aHeight = mBounds.height * scale + (aHeight - clientBounds.height * scale);
  1092   nsIntPoint clientOffset(GetClientOffset());
  1093   aX -= clientOffset.x * scale;
  1094   aY -= clientOffset.y * scale;
  1096   return Resize(aX, aY, aWidth, aHeight, aRepaint);
  1099 //-------------------------------------------------------------------------
  1100 //
  1101 // Bounds
  1102 //
  1103 //-------------------------------------------------------------------------
  1105 /**
  1106 * If the implementation of nsWindow supports borders this method MUST be overridden
  1108 **/
  1109 NS_METHOD nsBaseWidget::GetClientBounds(nsIntRect &aRect)
  1111   return GetBounds(aRect);
  1114 /**
  1115 * If the implementation of nsWindow supports borders this method MUST be overridden
  1117 **/
  1118 NS_METHOD nsBaseWidget::GetBounds(nsIntRect &aRect)
  1120   aRect = mBounds;
  1121   return NS_OK;
  1124 /**
  1125 * If the implementation of nsWindow uses a local coordinate system within the window,
  1126 * this method must be overridden
  1128 **/
  1129 NS_METHOD nsBaseWidget::GetScreenBounds(nsIntRect &aRect)
  1131   return GetBounds(aRect);
  1134 nsIntPoint nsBaseWidget::GetClientOffset()
  1136   return nsIntPoint(0, 0);
  1139 NS_IMETHODIMP
  1140 nsBaseWidget::GetNonClientMargins(nsIntMargin &margins)
  1142   return NS_ERROR_NOT_IMPLEMENTED;
  1145 NS_IMETHODIMP
  1146 nsBaseWidget::SetNonClientMargins(nsIntMargin &margins)
  1148   return NS_ERROR_NOT_IMPLEMENTED;
  1151 NS_METHOD nsBaseWidget::EnableDragDrop(bool aEnable)
  1153   return NS_OK;
  1156 uint32_t nsBaseWidget::GetMaxTouchPoints() const
  1158   return 0;
  1161 NS_METHOD nsBaseWidget::SetModal(bool aModal)
  1163   return NS_ERROR_FAILURE;
  1166 NS_IMETHODIMP
  1167 nsBaseWidget::GetAttention(int32_t aCycleCount) {
  1168     return NS_OK;
  1171 bool
  1172 nsBaseWidget::HasPendingInputEvent()
  1174   return false;
  1177 NS_IMETHODIMP
  1178 nsBaseWidget::SetIcon(const nsAString&)
  1180   return NS_OK;
  1183 NS_IMETHODIMP
  1184 nsBaseWidget::SetWindowTitlebarColor(nscolor aColor, bool aActive)
  1186   return NS_ERROR_NOT_IMPLEMENTED;
  1189 bool
  1190 nsBaseWidget::ShowsResizeIndicator(nsIntRect* aResizerRect)
  1192   return false;
  1195 NS_IMETHODIMP
  1196 nsBaseWidget::SetLayersAcceleration(bool aEnabled)
  1198   if (mUseLayersAcceleration == aEnabled) {
  1199     return NS_OK;
  1202   bool usedAcceleration = mUseLayersAcceleration;
  1204   mUseLayersAcceleration = ComputeShouldAccelerate(aEnabled);
  1205   // ComputeShouldAccelerate may have set mUseLayersAcceleration to a value
  1206   // different from aEnabled.
  1207   if (usedAcceleration == mUseLayersAcceleration) {
  1208     return NS_OK;
  1210   if (mLayerManager) {
  1211     mLayerManager->Destroy();
  1213   mLayerManager = nullptr;
  1214   return NS_OK;
  1217 NS_METHOD nsBaseWidget::RegisterTouchWindow()
  1219   return NS_ERROR_NOT_IMPLEMENTED;
  1222 NS_METHOD nsBaseWidget::UnregisterTouchWindow()
  1224   return NS_ERROR_NOT_IMPLEMENTED;
  1227 NS_IMETHODIMP
  1228 nsBaseWidget::OverrideSystemMouseScrollSpeed(double aOriginalDeltaX,
  1229                                              double aOriginalDeltaY,
  1230                                              double& aOverriddenDeltaX,
  1231                                              double& aOverriddenDeltaY)
  1233   aOverriddenDeltaX = aOriginalDeltaX;
  1234   aOverriddenDeltaY = aOriginalDeltaY;
  1236   static bool sInitialized = false;
  1237   static bool sIsOverrideEnabled = false;
  1238   static int32_t sIntFactorX = 0;
  1239   static int32_t sIntFactorY = 0;
  1241   if (!sInitialized) {
  1242     Preferences::AddBoolVarCache(&sIsOverrideEnabled,
  1243       "mousewheel.system_scroll_override_on_root_content.enabled", false);
  1244     Preferences::AddIntVarCache(&sIntFactorX,
  1245       "mousewheel.system_scroll_override_on_root_content.horizontal.factor", 0);
  1246     Preferences::AddIntVarCache(&sIntFactorY,
  1247       "mousewheel.system_scroll_override_on_root_content.vertical.factor", 0);
  1248     sIntFactorX = std::max(sIntFactorX, 0);
  1249     sIntFactorY = std::max(sIntFactorY, 0);
  1250     sInitialized = true;
  1253   if (!sIsOverrideEnabled) {
  1254     return NS_OK;
  1257   // The pref value must be larger than 100, otherwise, we don't override the
  1258   // delta value.
  1259   if (sIntFactorX > 100) {
  1260     double factor = static_cast<double>(sIntFactorX) / 100;
  1261     aOverriddenDeltaX *= factor;
  1263   if (sIntFactorY > 100) {
  1264     double factor = static_cast<double>(sIntFactorY) / 100;
  1265     aOverriddenDeltaY *= factor;
  1268   return NS_OK;
  1272 /**
  1273  * Modifies aFile to point at an icon file with the given name and suffix.  The
  1274  * suffix may correspond to a file extension with leading '.' if appropriate.
  1275  * Returns true if the icon file exists and can be read.
  1276  */
  1277 static bool
  1278 ResolveIconNameHelper(nsIFile *aFile,
  1279                       const nsAString &aIconName,
  1280                       const nsAString &aIconSuffix)
  1282   aFile->Append(NS_LITERAL_STRING("icons"));
  1283   aFile->Append(NS_LITERAL_STRING("default"));
  1284   aFile->Append(aIconName + aIconSuffix);
  1286   bool readable;
  1287   return NS_SUCCEEDED(aFile->IsReadable(&readable)) && readable;
  1290 /**
  1291  * Resolve the given icon name into a local file object.  This method is
  1292  * intended to be called by subclasses of nsBaseWidget.  aIconSuffix is a
  1293  * platform specific icon file suffix (e.g., ".ico" under Win32).
  1295  * If no file is found matching the given parameters, then null is returned.
  1296  */
  1297 void
  1298 nsBaseWidget::ResolveIconName(const nsAString &aIconName,
  1299                               const nsAString &aIconSuffix,
  1300                               nsIFile **aResult)
  1302   *aResult = nullptr;
  1304   nsCOMPtr<nsIProperties> dirSvc = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
  1305   if (!dirSvc)
  1306     return;
  1308   // first check auxilary chrome directories
  1310   nsCOMPtr<nsISimpleEnumerator> dirs;
  1311   dirSvc->Get(NS_APP_CHROME_DIR_LIST, NS_GET_IID(nsISimpleEnumerator),
  1312               getter_AddRefs(dirs));
  1313   if (dirs) {
  1314     bool hasMore;
  1315     while (NS_SUCCEEDED(dirs->HasMoreElements(&hasMore)) && hasMore) {
  1316       nsCOMPtr<nsISupports> element;
  1317       dirs->GetNext(getter_AddRefs(element));
  1318       if (!element)
  1319         continue;
  1320       nsCOMPtr<nsIFile> file = do_QueryInterface(element);
  1321       if (!file)
  1322         continue;
  1323       if (ResolveIconNameHelper(file, aIconName, aIconSuffix)) {
  1324         NS_ADDREF(*aResult = file);
  1325         return;
  1330   // then check the main app chrome directory
  1332   nsCOMPtr<nsIFile> file;
  1333   dirSvc->Get(NS_APP_CHROME_DIR, NS_GET_IID(nsIFile),
  1334               getter_AddRefs(file));
  1335   if (file && ResolveIconNameHelper(file, aIconName, aIconSuffix))
  1336     NS_ADDREF(*aResult = file);
  1339 NS_IMETHODIMP
  1340 nsBaseWidget::BeginResizeDrag(WidgetGUIEvent* aEvent,
  1341                               int32_t aHorizontal,
  1342                               int32_t aVertical)
  1344   return NS_ERROR_NOT_IMPLEMENTED;
  1347 NS_IMETHODIMP
  1348 nsBaseWidget::BeginMoveDrag(WidgetMouseEvent* aEvent)
  1350   return NS_ERROR_NOT_IMPLEMENTED;
  1353 uint32_t
  1354 nsBaseWidget::GetGLFrameBufferFormat()
  1356   return LOCAL_GL_RGBA;
  1359 void nsBaseWidget::SetSizeConstraints(const SizeConstraints& aConstraints)
  1361   mSizeConstraints = aConstraints;
  1362   // We can't ensure that the size is honored at this point because we're
  1363   // probably in the middle of a reflow.
  1366 const widget::SizeConstraints& nsBaseWidget::GetSizeConstraints() const
  1368   return mSizeConstraints;
  1371 // static
  1372 nsIRollupListener*
  1373 nsBaseWidget::GetActiveRollupListener()
  1375   // If set, then this is likely an <html:select> dropdown.
  1376   if (gRollupListener)
  1377     return gRollupListener;
  1379   return nsXULPopupManager::GetInstance();
  1382 void
  1383 nsBaseWidget::NotifyWindowDestroyed()
  1385   if (!mWidgetListener)
  1386     return;
  1388   nsCOMPtr<nsIXULWindow> window = mWidgetListener->GetXULWindow();
  1389   nsCOMPtr<nsIBaseWindow> xulWindow(do_QueryInterface(window));
  1390   if (xulWindow) {
  1391     xulWindow->Destroy();
  1395 void
  1396 nsBaseWidget::NotifySizeMoveDone()
  1398   if (!mWidgetListener || mWidgetListener->GetXULWindow())
  1399     return;
  1401   nsIPresShell* presShell = mWidgetListener->GetPresShell();
  1402   if (presShell) {
  1403     presShell->WindowSizeMoveDone();
  1407 void
  1408 nsBaseWidget::NotifyWindowMoved(int32_t aX, int32_t aY)
  1410   if (mWidgetListener) {
  1411     mWidgetListener->WindowMoved(this, aX, aY);
  1414   if (GetIMEUpdatePreference().WantPositionChanged()) {
  1415     NotifyIME(IMENotification(IMEMessage::NOTIFY_IME_OF_POSITION_CHANGE));
  1419 void
  1420 nsBaseWidget::NotifySysColorChanged()
  1422   if (!mWidgetListener || mWidgetListener->GetXULWindow())
  1423     return;
  1425   nsIPresShell* presShell = mWidgetListener->GetPresShell();
  1426   if (presShell) {
  1427     presShell->SysColorChanged();
  1431 void
  1432 nsBaseWidget::NotifyThemeChanged()
  1434   if (!mWidgetListener || mWidgetListener->GetXULWindow())
  1435     return;
  1437   nsIPresShell* presShell = mWidgetListener->GetPresShell();
  1438   if (presShell) {
  1439     presShell->ThemeChanged();
  1443 void
  1444 nsBaseWidget::NotifyUIStateChanged(UIStateChangeType aShowAccelerators,
  1445                                    UIStateChangeType aShowFocusRings)
  1447   if (!mWidgetListener)
  1448     return;
  1450   nsIPresShell* presShell = mWidgetListener->GetPresShell();
  1451   if (!presShell)
  1452     return;
  1454   nsIDocument* doc = presShell->GetDocument();
  1455   if (doc) {
  1456     nsPIDOMWindow* win = doc->GetWindow();
  1457     if (win) {
  1458       win->SetKeyboardIndicators(aShowAccelerators, aShowFocusRings);
  1463 #ifdef ACCESSIBILITY
  1465 a11y::Accessible*
  1466 nsBaseWidget::GetRootAccessible()
  1468   NS_ENSURE_TRUE(mWidgetListener, nullptr);
  1470   nsIPresShell* presShell = mWidgetListener->GetPresShell();
  1471   NS_ENSURE_TRUE(presShell, nullptr);
  1473   // If container is null then the presshell is not active. This often happens
  1474   // when a preshell is being held onto for fastback.
  1475   nsPresContext* presContext = presShell->GetPresContext();
  1476   NS_ENSURE_TRUE(presContext->GetContainerWeak(), nullptr);
  1478   // Accessible creation might be not safe so use IsSafeToRunScript to
  1479   // make sure it's not created at unsafe times.
  1480   nsCOMPtr<nsIAccessibilityService> accService =
  1481     services::GetAccessibilityService();
  1482   if (accService) {
  1483     return accService->GetRootDocumentAccessible(presShell, nsContentUtils::IsSafeToRunScript());
  1486   return nullptr;
  1489 #endif // ACCESSIBILITY
  1491 nsresult
  1492 nsIWidget::SynthesizeNativeTouchTap(nsIntPoint aPointerScreenPoint, bool aLongTap)
  1494   if (sPointerIdCounter > TOUCH_INJECT_MAX_POINTS) {
  1495     sPointerIdCounter = 0;
  1497   int pointerId = sPointerIdCounter;
  1498   sPointerIdCounter++;
  1499   nsresult rv = SynthesizeNativeTouchPoint(pointerId, TOUCH_CONTACT,
  1500                                            aPointerScreenPoint, 1.0, 90);
  1501   if (NS_FAILED(rv)) {
  1502     return rv;
  1505   if (!aLongTap) {
  1506     nsresult rv = SynthesizeNativeTouchPoint(pointerId, TOUCH_REMOVE,
  1507                                              aPointerScreenPoint, 0, 0);
  1508     return rv;
  1511   // initiate a long tap
  1512   int elapse = Preferences::GetInt("ui.click_hold_context_menus.delay",
  1513                                    TOUCH_INJECT_LONG_TAP_DEFAULT_MSEC);
  1514   if (!mLongTapTimer) {
  1515     mLongTapTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
  1516     if (NS_FAILED(rv)) {
  1517       SynthesizeNativeTouchPoint(pointerId, TOUCH_CANCEL,
  1518                                  aPointerScreenPoint, 0, 0);
  1519       return NS_ERROR_UNEXPECTED;
  1521     // Windows requires recuring events, so we set this to a smaller window
  1522     // than the pref value.
  1523     int timeout = elapse;
  1524     if (timeout > TOUCH_INJECT_PUMP_TIMER_MSEC) {
  1525       timeout = TOUCH_INJECT_PUMP_TIMER_MSEC;
  1527     mLongTapTimer->InitWithFuncCallback(OnLongTapTimerCallback, this,
  1528                                         timeout,
  1529                                         nsITimer::TYPE_REPEATING_SLACK);
  1532   // If we already have a long tap pending, cancel it. We only allow one long
  1533   // tap to be active at a time.
  1534   if (mLongTapTouchPoint) {
  1535     SynthesizeNativeTouchPoint(mLongTapTouchPoint->mPointerId, TOUCH_CANCEL,
  1536                                mLongTapTouchPoint->mPosition, 0, 0);
  1539   mLongTapTouchPoint = new LongTapInfo(pointerId, aPointerScreenPoint,
  1540                                        TimeDuration::FromMilliseconds(elapse));
  1541   return NS_OK;
  1544 // static
  1545 void
  1546 nsIWidget::OnLongTapTimerCallback(nsITimer* aTimer, void* aClosure)
  1548   nsIWidget *self = static_cast<nsIWidget *>(aClosure);
  1550   if ((self->mLongTapTouchPoint->mStamp + self->mLongTapTouchPoint->mDuration) >
  1551       TimeStamp::Now()) {
  1552 #ifdef XP_WIN
  1553     // Windows needs us to keep pumping feedback to the digitizer, so update
  1554     // the pointer id with the same position.
  1555     self->SynthesizeNativeTouchPoint(self->mLongTapTouchPoint->mPointerId,
  1556                                      TOUCH_CONTACT,
  1557                                      self->mLongTapTouchPoint->mPosition,
  1558                                      1.0, 90);
  1559 #endif
  1560     return;
  1563   // finished, remove the touch point
  1564   self->mLongTapTimer->Cancel();
  1565   self->mLongTapTimer = nullptr;
  1566   self->SynthesizeNativeTouchPoint(self->mLongTapTouchPoint->mPointerId,
  1567                                    TOUCH_REMOVE,
  1568                                    self->mLongTapTouchPoint->mPosition,
  1569                                    0, 0);
  1570   self->mLongTapTouchPoint = nullptr;
  1573 nsresult
  1574 nsIWidget::ClearNativeTouchSequence()
  1576   if (!mLongTapTimer) {
  1577     return NS_OK;
  1579   mLongTapTimer->Cancel();
  1580   mLongTapTimer = nullptr;
  1581   SynthesizeNativeTouchPoint(mLongTapTouchPoint->mPointerId, TOUCH_CANCEL,
  1582                              mLongTapTouchPoint->mPosition, 0, 0);
  1583   mLongTapTouchPoint = nullptr;
  1584   return NS_OK;
  1587 #ifdef DEBUG
  1588 //////////////////////////////////////////////////////////////
  1589 //
  1590 // Convert a GUI event message code to a string.
  1591 // Makes it a lot easier to debug events.
  1592 //
  1593 // See gtk/nsWidget.cpp and windows/nsWindow.cpp
  1594 // for a DebugPrintEvent() function that uses
  1595 // this.
  1596 //
  1597 //////////////////////////////////////////////////////////////
  1598 /* static */ nsAutoString
  1599 nsBaseWidget::debug_GuiEventToString(WidgetGUIEvent* aGuiEvent)
  1601   NS_ASSERTION(nullptr != aGuiEvent,"cmon, null gui event.");
  1603   nsAutoString eventName(NS_LITERAL_STRING("UNKNOWN"));
  1605 #define _ASSIGN_eventName(_value,_name)\
  1606 case _value: eventName.AssignLiteral(_name) ; break
  1608   switch(aGuiEvent->message)
  1610     _ASSIGN_eventName(NS_BLUR_CONTENT,"NS_BLUR_CONTENT");
  1611     _ASSIGN_eventName(NS_DRAGDROP_GESTURE,"NS_DND_GESTURE");
  1612     _ASSIGN_eventName(NS_DRAGDROP_DROP,"NS_DND_DROP");
  1613     _ASSIGN_eventName(NS_DRAGDROP_ENTER,"NS_DND_ENTER");
  1614     _ASSIGN_eventName(NS_DRAGDROP_EXIT,"NS_DND_EXIT");
  1615     _ASSIGN_eventName(NS_DRAGDROP_OVER,"NS_DND_OVER");
  1616     _ASSIGN_eventName(NS_EDITOR_INPUT,"NS_EDITOR_INPUT");
  1617     _ASSIGN_eventName(NS_FOCUS_CONTENT,"NS_FOCUS_CONTENT");
  1618     _ASSIGN_eventName(NS_FORM_SELECTED,"NS_FORM_SELECTED");
  1619     _ASSIGN_eventName(NS_FORM_CHANGE,"NS_FORM_CHANGE");
  1620     _ASSIGN_eventName(NS_FORM_RESET,"NS_FORM_RESET");
  1621     _ASSIGN_eventName(NS_FORM_SUBMIT,"NS_FORM_SUBMIT");
  1622     _ASSIGN_eventName(NS_IMAGE_ABORT,"NS_IMAGE_ABORT");
  1623     _ASSIGN_eventName(NS_LOAD_ERROR,"NS_LOAD_ERROR");
  1624     _ASSIGN_eventName(NS_KEY_DOWN,"NS_KEY_DOWN");
  1625     _ASSIGN_eventName(NS_KEY_PRESS,"NS_KEY_PRESS");
  1626     _ASSIGN_eventName(NS_KEY_UP,"NS_KEY_UP");
  1627     _ASSIGN_eventName(NS_MOUSE_ENTER,"NS_MOUSE_ENTER");
  1628     _ASSIGN_eventName(NS_MOUSE_EXIT,"NS_MOUSE_EXIT");
  1629     _ASSIGN_eventName(NS_MOUSE_BUTTON_DOWN,"NS_MOUSE_BUTTON_DOWN");
  1630     _ASSIGN_eventName(NS_MOUSE_BUTTON_UP,"NS_MOUSE_BUTTON_UP");
  1631     _ASSIGN_eventName(NS_MOUSE_CLICK,"NS_MOUSE_CLICK");
  1632     _ASSIGN_eventName(NS_MOUSE_DOUBLECLICK,"NS_MOUSE_DBLCLICK");
  1633     _ASSIGN_eventName(NS_MOUSE_MOVE,"NS_MOUSE_MOVE");
  1634     _ASSIGN_eventName(NS_LOAD,"NS_LOAD");
  1635     _ASSIGN_eventName(NS_POPSTATE,"NS_POPSTATE");
  1636     _ASSIGN_eventName(NS_BEFORE_SCRIPT_EXECUTE,"NS_BEFORE_SCRIPT_EXECUTE");
  1637     _ASSIGN_eventName(NS_AFTER_SCRIPT_EXECUTE,"NS_AFTER_SCRIPT_EXECUTE");
  1638     _ASSIGN_eventName(NS_PAGE_UNLOAD,"NS_PAGE_UNLOAD");
  1639     _ASSIGN_eventName(NS_HASHCHANGE,"NS_HASHCHANGE");
  1640     _ASSIGN_eventName(NS_READYSTATECHANGE,"NS_READYSTATECHANGE");
  1641     _ASSIGN_eventName(NS_XUL_BROADCAST, "NS_XUL_BROADCAST");
  1642     _ASSIGN_eventName(NS_XUL_COMMAND_UPDATE, "NS_XUL_COMMAND_UPDATE");
  1644 #undef _ASSIGN_eventName
  1646   default:
  1648       char buf[32];
  1650       sprintf(buf,"UNKNOWN: %d",aGuiEvent->message);
  1652       CopyASCIItoUTF16(buf, eventName);
  1654     break;
  1657   return nsAutoString(eventName);
  1659 //////////////////////////////////////////////////////////////
  1660 //
  1661 // Code to deal with paint and event debug prefs.
  1662 //
  1663 //////////////////////////////////////////////////////////////
  1664 struct PrefPair
  1666   const char * name;
  1667   bool value;
  1668 };
  1670 static PrefPair debug_PrefValues[] =
  1672   { "nglayout.debug.crossing_event_dumping", false },
  1673   { "nglayout.debug.event_dumping", false },
  1674   { "nglayout.debug.invalidate_dumping", false },
  1675   { "nglayout.debug.motion_event_dumping", false },
  1676   { "nglayout.debug.paint_dumping", false },
  1677   { "nglayout.debug.paint_flashing", false }
  1678 };
  1680 //////////////////////////////////////////////////////////////
  1681 bool
  1682 nsBaseWidget::debug_GetCachedBoolPref(const char * aPrefName)
  1684   NS_ASSERTION(nullptr != aPrefName,"cmon, pref name is null.");
  1686   for (uint32_t i = 0; i < ArrayLength(debug_PrefValues); i++)
  1688     if (strcmp(debug_PrefValues[i].name, aPrefName) == 0)
  1690       return debug_PrefValues[i].value;
  1694   return false;
  1696 //////////////////////////////////////////////////////////////
  1697 static void debug_SetCachedBoolPref(const char * aPrefName,bool aValue)
  1699   NS_ASSERTION(nullptr != aPrefName,"cmon, pref name is null.");
  1701   for (uint32_t i = 0; i < ArrayLength(debug_PrefValues); i++)
  1703     if (strcmp(debug_PrefValues[i].name, aPrefName) == 0)
  1705       debug_PrefValues[i].value = aValue;
  1707       return;
  1711   NS_ASSERTION(false, "cmon, this code is not reached dude.");
  1714 //////////////////////////////////////////////////////////////
  1715 class Debug_PrefObserver MOZ_FINAL : public nsIObserver {
  1716   public:
  1717     NS_DECL_ISUPPORTS
  1718     NS_DECL_NSIOBSERVER
  1719 };
  1721 NS_IMPL_ISUPPORTS(Debug_PrefObserver, nsIObserver)
  1723 NS_IMETHODIMP
  1724 Debug_PrefObserver::Observe(nsISupports* subject, const char* topic,
  1725                             const char16_t* data)
  1727   NS_ConvertUTF16toUTF8 prefName(data);
  1729   bool value = Preferences::GetBool(prefName.get(), false);
  1730   debug_SetCachedBoolPref(prefName.get(), value);
  1731   return NS_OK;
  1734 //////////////////////////////////////////////////////////////
  1735 /* static */ void
  1736 debug_RegisterPrefCallbacks()
  1738   static bool once = true;
  1740   if (!once) {
  1741     return;
  1744   once = false;
  1746   nsCOMPtr<nsIObserver> obs(new Debug_PrefObserver());
  1747   for (uint32_t i = 0; i < ArrayLength(debug_PrefValues); i++) {
  1748     // Initialize the pref values
  1749     debug_PrefValues[i].value =
  1750       Preferences::GetBool(debug_PrefValues[i].name, false);
  1752     if (obs) {
  1753       // Register callbacks for when these change
  1754       Preferences::AddStrongObserver(obs, debug_PrefValues[i].name);
  1758 //////////////////////////////////////////////////////////////
  1759 static int32_t
  1760 _GetPrintCount()
  1762   static int32_t sCount = 0;
  1764   return ++sCount;
  1766 //////////////////////////////////////////////////////////////
  1767 /* static */ bool
  1768 nsBaseWidget::debug_WantPaintFlashing()
  1770   return debug_GetCachedBoolPref("nglayout.debug.paint_flashing");
  1772 //////////////////////////////////////////////////////////////
  1773 /* static */ void
  1774 nsBaseWidget::debug_DumpEvent(FILE *                aFileOut,
  1775                               nsIWidget *           aWidget,
  1776                               WidgetGUIEvent*       aGuiEvent,
  1777                               const nsAutoCString & aWidgetName,
  1778                               int32_t               aWindowID)
  1780   if (aGuiEvent->message == NS_MOUSE_MOVE)
  1782     if (!debug_GetCachedBoolPref("nglayout.debug.motion_event_dumping"))
  1783       return;
  1786   if (aGuiEvent->message == NS_MOUSE_ENTER ||
  1787       aGuiEvent->message == NS_MOUSE_EXIT)
  1789     if (!debug_GetCachedBoolPref("nglayout.debug.crossing_event_dumping"))
  1790       return;
  1793   if (!debug_GetCachedBoolPref("nglayout.debug.event_dumping"))
  1794     return;
  1796   NS_LossyConvertUTF16toASCII tempString(debug_GuiEventToString(aGuiEvent).get());
  1798   fprintf(aFileOut,
  1799           "%4d %-26s widget=%-8p name=%-12s id=0x%-6x refpt=%d,%d\n",
  1800           _GetPrintCount(),
  1801           tempString.get(),
  1802           (void *) aWidget,
  1803           aWidgetName.get(),
  1804           aWindowID,
  1805           aGuiEvent->refPoint.x,
  1806           aGuiEvent->refPoint.y);
  1808 //////////////////////////////////////////////////////////////
  1809 /* static */ void
  1810 nsBaseWidget::debug_DumpPaintEvent(FILE *                aFileOut,
  1811                                    nsIWidget *           aWidget,
  1812                                    const nsIntRegion &   aRegion,
  1813                                    const nsAutoCString & aWidgetName,
  1814                                    int32_t               aWindowID)
  1816   NS_ASSERTION(nullptr != aFileOut,"cmon, null output FILE");
  1817   NS_ASSERTION(nullptr != aWidget,"cmon, the widget is null");
  1819   if (!debug_GetCachedBoolPref("nglayout.debug.paint_dumping"))
  1820     return;
  1822   nsIntRect rect = aRegion.GetBounds();
  1823   fprintf(aFileOut,
  1824           "%4d PAINT      widget=%p name=%-12s id=0x%-6x bounds-rect=%3d,%-3d %3d,%-3d",
  1825           _GetPrintCount(),
  1826           (void *) aWidget,
  1827           aWidgetName.get(),
  1828           aWindowID,
  1829           rect.x, rect.y, rect.width, rect.height
  1830     );
  1832   fprintf(aFileOut,"\n");
  1834 //////////////////////////////////////////////////////////////
  1835 /* static */ void
  1836 nsBaseWidget::debug_DumpInvalidate(FILE *                aFileOut,
  1837                                    nsIWidget *           aWidget,
  1838                                    const nsIntRect *     aRect,
  1839                                    const nsAutoCString & aWidgetName,
  1840                                    int32_t               aWindowID)
  1842   if (!debug_GetCachedBoolPref("nglayout.debug.invalidate_dumping"))
  1843     return;
  1845   NS_ASSERTION(nullptr != aFileOut,"cmon, null output FILE");
  1846   NS_ASSERTION(nullptr != aWidget,"cmon, the widget is null");
  1848   fprintf(aFileOut,
  1849           "%4d Invalidate widget=%p name=%-12s id=0x%-6x",
  1850           _GetPrintCount(),
  1851           (void *) aWidget,
  1852           aWidgetName.get(),
  1853           aWindowID);
  1855   if (aRect)
  1857     fprintf(aFileOut,
  1858             " rect=%3d,%-3d %3d,%-3d",
  1859             aRect->x,
  1860             aRect->y,
  1861             aRect->width,
  1862             aRect->height);
  1864   else
  1866     fprintf(aFileOut,
  1867             " rect=%-15s",
  1868             "none");
  1871   fprintf(aFileOut,"\n");
  1873 //////////////////////////////////////////////////////////////
  1875 #endif // DEBUG

mercurial