widget/xpwidgets/PuppetWidget.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: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     2  * vim: sw=2 ts=8 et :
     3  */
     4 /* This Source Code Form is subject to the terms of the Mozilla Public
     5  * License, v. 2.0. If a copy of the MPL was not distributed with this
     6  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     8 #include "base/basictypes.h"
    10 #include "ClientLayerManager.h"
    11 #include "gfxPlatform.h"
    12 #if defined(MOZ_ENABLE_D3D10_LAYER)
    13 # include "LayerManagerD3D10.h"
    14 #endif
    15 #include "mozilla/dom/TabChild.h"
    16 #include "mozilla/Hal.h"
    17 #include "mozilla/IMEStateManager.h"
    18 #include "mozilla/layers/CompositorChild.h"
    19 #include "mozilla/layers/PLayerTransactionChild.h"
    20 #include "mozilla/TextComposition.h"
    21 #include "mozilla/TextEvents.h"
    22 #include "PuppetWidget.h"
    23 #include "nsIWidgetListener.h"
    25 using namespace mozilla::dom;
    26 using namespace mozilla::hal;
    27 using namespace mozilla::gfx;
    28 using namespace mozilla::layers;
    29 using namespace mozilla::widget;
    31 static void
    32 InvalidateRegion(nsIWidget* aWidget, const nsIntRegion& aRegion)
    33 {
    34   nsIntRegionRectIterator it(aRegion);
    35   while(const nsIntRect* r = it.Next()) {
    36     aWidget->Invalidate(*r);
    37   }
    38 }
    40 /*static*/ already_AddRefed<nsIWidget>
    41 nsIWidget::CreatePuppetWidget(TabChild* aTabChild)
    42 {
    43   NS_ABORT_IF_FALSE(!aTabChild || nsIWidget::UsePuppetWidgets(),
    44                     "PuppetWidgets not allowed in this configuration");
    46   nsCOMPtr<nsIWidget> widget = new PuppetWidget(aTabChild);
    47   return widget.forget();
    48 }
    50 namespace mozilla {
    51 namespace widget {
    53 static bool
    54 IsPopup(const nsWidgetInitData* aInitData)
    55 {
    56   return aInitData && aInitData->mWindowType == eWindowType_popup;
    57 }
    59 static bool
    60 MightNeedIMEFocus(const nsWidgetInitData* aInitData)
    61 {
    62   // In the puppet-widget world, popup widgets are just dummies and
    63   // shouldn't try to mess with IME state.
    64 #ifdef MOZ_CROSS_PROCESS_IME
    65   return !IsPopup(aInitData);
    66 #else
    67   return false;
    68 #endif
    69 }
    72 // Arbitrary, fungible.
    73 const size_t PuppetWidget::kMaxDimension = 4000;
    75 NS_IMPL_ISUPPORTS_INHERITED(PuppetWidget, nsBaseWidget,
    76                             nsISupportsWeakReference)
    78 PuppetWidget::PuppetWidget(TabChild* aTabChild)
    79   : mTabChild(aTabChild)
    80   , mDPI(-1)
    81   , mDefaultScale(-1)
    82   , mNativeKeyCommandsValid(false)
    83 {
    84   MOZ_COUNT_CTOR(PuppetWidget);
    86   mSingleLineCommands.SetCapacity(4);
    87   mMultiLineCommands.SetCapacity(4);
    88   mRichTextCommands.SetCapacity(4);
    89 }
    91 PuppetWidget::~PuppetWidget()
    92 {
    93   MOZ_COUNT_DTOR(PuppetWidget);
    94 }
    96 NS_IMETHODIMP
    97 PuppetWidget::Create(nsIWidget        *aParent,
    98                      nsNativeWidget   aNativeParent,
    99                      const nsIntRect  &aRect,
   100                      nsDeviceContext *aContext,
   101                      nsWidgetInitData *aInitData)
   102 {
   103   NS_ABORT_IF_FALSE(!aNativeParent, "got a non-Puppet native parent");
   105   BaseCreate(nullptr, aRect, aContext, aInitData);
   107   mBounds = aRect;
   108   mEnabled = true;
   109   mVisible = true;
   111   mSurface = gfxPlatform::GetPlatform()
   112              ->CreateOffscreenSurface(IntSize(1, 1),
   113                                       gfxASurface::ContentFromFormat(gfxImageFormat::ARGB32));
   115   mIMEComposing = false;
   116   mNeedIMEStateInit = MightNeedIMEFocus(aInitData);
   118   PuppetWidget* parent = static_cast<PuppetWidget*>(aParent);
   119   if (parent) {
   120     parent->SetChild(this);
   121     mLayerManager = parent->GetLayerManager();
   122   }
   123   else {
   124     Resize(mBounds.x, mBounds.y, mBounds.width, mBounds.height, false);
   125   }
   127   return NS_OK;
   128 }
   130 void
   131 PuppetWidget::InitIMEState()
   132 {
   133   MOZ_ASSERT(mTabChild);
   134   if (mNeedIMEStateInit) {
   135     uint32_t chromeSeqno;
   136     mTabChild->SendNotifyIMEFocus(false, &mIMEPreferenceOfParent, &chromeSeqno);
   137     mIMELastBlurSeqno = mIMELastReceivedSeqno = chromeSeqno;
   138     mNeedIMEStateInit = false;
   139   }
   140 }
   142 already_AddRefed<nsIWidget>
   143 PuppetWidget::CreateChild(const nsIntRect  &aRect,
   144                           nsDeviceContext *aContext,
   145                           nsWidgetInitData *aInitData,
   146                           bool             aForceUseIWidgetParent)
   147 {
   148   bool isPopup = IsPopup(aInitData);
   149   nsCOMPtr<nsIWidget> widget = nsIWidget::CreatePuppetWidget(mTabChild);
   150   return ((widget &&
   151            NS_SUCCEEDED(widget->Create(isPopup ? nullptr: this, nullptr, aRect,
   152                                        aContext, aInitData))) ?
   153           widget.forget() : nullptr);
   154 }
   156 NS_IMETHODIMP
   157 PuppetWidget::Destroy()
   158 {
   159   Base::OnDestroy();
   160   Base::Destroy();
   161   mPaintTask.Revoke();
   162   mChild = nullptr;
   163   if (mLayerManager) {
   164     mLayerManager->Destroy();
   165   }
   166   mLayerManager = nullptr;
   167   mTabChild = nullptr;
   168   return NS_OK;
   169 }
   171 NS_IMETHODIMP
   172 PuppetWidget::Show(bool aState)
   173 {
   174   NS_ASSERTION(mEnabled,
   175                "does it make sense to Show()/Hide() a disabled widget?");
   177   bool wasVisible = mVisible;
   178   mVisible = aState;
   180   if (mChild) {
   181     mChild->mVisible = aState;
   182   }
   184   if (!mVisible && mLayerManager) {
   185     mLayerManager->ClearCachedResources();
   186   }
   188   if (!wasVisible && mVisible) {
   189     Resize(mBounds.width, mBounds.height, false);
   190     Invalidate(mBounds);
   191   }
   193   return NS_OK;
   194 }
   196 NS_IMETHODIMP
   197 PuppetWidget::Resize(double aWidth,
   198                      double aHeight,
   199                      bool   aRepaint)
   200 {
   201   nsIntRect oldBounds = mBounds;
   202   mBounds.SizeTo(nsIntSize(NSToIntRound(aWidth), NSToIntRound(aHeight)));
   204   if (mChild) {
   205     return mChild->Resize(aWidth, aHeight, aRepaint);
   206   }
   208   // XXX: roc says that |aRepaint| dictates whether or not to
   209   // invalidate the expanded area
   210   if (oldBounds.Size() < mBounds.Size() && aRepaint) {
   211     nsIntRegion dirty(mBounds);
   212     dirty.Sub(dirty,  oldBounds);
   213     InvalidateRegion(this, dirty);
   214   }
   216   if (!oldBounds.IsEqualEdges(mBounds) && mAttachedWidgetListener) {
   217     mAttachedWidgetListener->WindowResized(this, mBounds.width, mBounds.height);
   218   }
   220   return NS_OK;
   221 }
   223 NS_IMETHODIMP
   224 PuppetWidget::SetFocus(bool aRaise)
   225 {
   226   // XXX/cjones: someone who knows about event handling needs to
   227   // decide how this should work.
   228   return NS_OK;
   229 }
   231 NS_IMETHODIMP
   232 PuppetWidget::Invalidate(const nsIntRect& aRect)
   233 {
   234 #ifdef DEBUG
   235   debug_DumpInvalidate(stderr, this, &aRect,
   236                        nsAutoCString("PuppetWidget"), 0);
   237 #endif
   239   if (mChild) {
   240     return mChild->Invalidate(aRect);
   241   }
   243   mDirtyRegion.Or(mDirtyRegion, aRect);
   245   if (!mDirtyRegion.IsEmpty() && !mPaintTask.IsPending()) {
   246     mPaintTask = new PaintTask(this);
   247     return NS_DispatchToCurrentThread(mPaintTask.get());
   248   }
   250   return NS_OK;
   251 }
   253 void
   254 PuppetWidget::InitEvent(WidgetGUIEvent& event, nsIntPoint* aPoint)
   255 {
   256   if (nullptr == aPoint) {
   257     event.refPoint.x = 0;
   258     event.refPoint.y = 0;
   259   }
   260   else {
   261     // use the point override if provided
   262     event.refPoint.x = aPoint->x;
   263     event.refPoint.y = aPoint->y;
   264   }
   265   event.time = PR_Now() / 1000;
   266 }
   268 NS_IMETHODIMP
   269 PuppetWidget::DispatchEvent(WidgetGUIEvent* event, nsEventStatus& aStatus)
   270 {
   271 #ifdef DEBUG
   272   debug_DumpEvent(stdout, event->widget, event,
   273                   nsAutoCString("PuppetWidget"), 0);
   274 #endif
   276   NS_ABORT_IF_FALSE(!mChild || mChild->mWindowType == eWindowType_popup,
   277                     "Unexpected event dispatch!");
   279   AutoCacheNativeKeyCommands autoCache(this);
   280   if (event->mFlags.mIsSynthesizedForTests && !mNativeKeyCommandsValid) {
   281     WidgetKeyboardEvent* keyEvent = event->AsKeyboardEvent();
   282     if (keyEvent) {
   283       mTabChild->RequestNativeKeyBindings(&autoCache, keyEvent);
   284     }
   285   }
   287   aStatus = nsEventStatus_eIgnore;
   289   if (event->message == NS_COMPOSITION_START) {
   290     mIMEComposing = true;
   291   }
   292   uint32_t seqno = kLatestSeqno;
   293   switch (event->eventStructType) {
   294   case NS_COMPOSITION_EVENT:
   295     seqno = event->AsCompositionEvent()->mSeqno;
   296     break;
   297   case NS_TEXT_EVENT:
   298     seqno = event->AsTextEvent()->mSeqno;
   299     break;
   300   case NS_SELECTION_EVENT:
   301     seqno = event->AsSelectionEvent()->mSeqno;
   302     break;
   303   default:
   304     break;
   305   }
   306   if (seqno != kLatestSeqno) {
   307     mIMELastReceivedSeqno = seqno;
   308     if (mIMELastReceivedSeqno < mIMELastBlurSeqno) {
   309       return NS_OK;
   310     }
   311   }
   313   if (mAttachedWidgetListener) {
   314     aStatus = mAttachedWidgetListener->HandleEvent(event, mUseAttachedEvents);
   315   }
   317   if (event->message == NS_COMPOSITION_END) {
   318     mIMEComposing = false;
   319   }
   321   return NS_OK;
   322 }
   325 NS_IMETHODIMP_(bool)
   326 PuppetWidget::ExecuteNativeKeyBinding(NativeKeyBindingsType aType,
   327                                       const mozilla::WidgetKeyboardEvent& aEvent,
   328                                       DoCommandCallback aCallback,
   329                                       void* aCallbackData)
   330 {
   331   // B2G doesn't have native key bindings.
   332 #ifdef MOZ_B2G
   333   return false;
   334 #else // #ifdef MOZ_B2G
   335   MOZ_ASSERT(mNativeKeyCommandsValid);
   337   nsTArray<mozilla::CommandInt>& commands = mSingleLineCommands;
   338   switch (aType) {
   339     case nsIWidget::NativeKeyBindingsForSingleLineEditor:
   340       commands = mSingleLineCommands;
   341       break;
   342     case nsIWidget::NativeKeyBindingsForMultiLineEditor:
   343       commands = mMultiLineCommands;
   344       break;
   345     case nsIWidget::NativeKeyBindingsForRichTextEditor:
   346       commands = mRichTextCommands;
   347       break;
   348   }
   350   if (commands.IsEmpty()) {
   351     return false;
   352   }
   354   for (uint32_t i = 0; i < commands.Length(); i++) {
   355     aCallback(static_cast<mozilla::Command>(commands[i]), aCallbackData);
   356   }
   357   return true;
   358 #endif
   359 }
   361 LayerManager*
   362 PuppetWidget::GetLayerManager(PLayerTransactionChild* aShadowManager,
   363                               LayersBackend aBackendHint,
   364                               LayerManagerPersistence aPersistence,
   365                               bool* aAllowRetaining)
   366 {
   367   if (!mLayerManager) {
   368     // The backend hint is a temporary placeholder until Azure, when
   369     // all content-process layer managers will be BasicLayerManagers.
   370 #if defined(MOZ_ENABLE_D3D10_LAYER)
   371     if (mozilla::layers::LayersBackend::LAYERS_D3D10 == aBackendHint) {
   372       nsRefPtr<LayerManagerD3D10> m = new LayerManagerD3D10(this);
   373       m->AsShadowForwarder()->SetShadowManager(aShadowManager);
   374       if (m->Initialize()) {
   375         mLayerManager = m;
   376       }
   377     }
   378 #endif
   379     if (!mLayerManager) {
   380       mLayerManager = new ClientLayerManager(this);
   381     }
   382   }
   383   ShadowLayerForwarder* lf = mLayerManager->AsShadowForwarder();
   384   if (!lf->HasShadowManager() && aShadowManager) {
   385     lf->SetShadowManager(aShadowManager);
   386   }
   387   if (aAllowRetaining) {
   388     *aAllowRetaining = true;
   389   }
   390   return mLayerManager;
   391 }
   393 gfxASurface*
   394 PuppetWidget::GetThebesSurface()
   395 {
   396   return mSurface;
   397 }
   399 nsresult
   400 PuppetWidget::IMEEndComposition(bool aCancel)
   401 {
   402 #ifndef MOZ_CROSS_PROCESS_IME
   403   return NS_OK;
   404 #endif
   406   nsEventStatus status;
   407   WidgetTextEvent textEvent(true, NS_TEXT_TEXT, this);
   408   InitEvent(textEvent, nullptr);
   409   textEvent.mSeqno = mIMELastReceivedSeqno;
   410   // SendEndIMEComposition is always called since ResetInputState
   411   // should always be called even if we aren't composing something.
   412   if (!mTabChild ||
   413       !mTabChild->SendEndIMEComposition(aCancel, &textEvent.theText)) {
   414     return NS_ERROR_FAILURE;
   415   }
   417   if (!mIMEComposing)
   418     return NS_OK;
   420   DispatchEvent(&textEvent, status);
   422   WidgetCompositionEvent compEvent(true, NS_COMPOSITION_END, this);
   423   InitEvent(compEvent, nullptr);
   424   compEvent.mSeqno = mIMELastReceivedSeqno;
   425   DispatchEvent(&compEvent, status);
   426   return NS_OK;
   427 }
   429 NS_IMETHODIMP
   430 PuppetWidget::NotifyIME(const IMENotification& aIMENotification)
   431 {
   432   switch (aIMENotification.mMessage) {
   433     case NOTIFY_IME_OF_CURSOR_POS_CHANGED:
   434     case REQUEST_TO_COMMIT_COMPOSITION:
   435       return IMEEndComposition(false);
   436     case REQUEST_TO_CANCEL_COMPOSITION:
   437       return IMEEndComposition(true);
   438     case NOTIFY_IME_OF_FOCUS:
   439       return NotifyIMEOfFocusChange(true);
   440     case NOTIFY_IME_OF_BLUR:
   441       return NotifyIMEOfFocusChange(false);
   442     case NOTIFY_IME_OF_SELECTION_CHANGE:
   443       return NotifyIMEOfSelectionChange(aIMENotification);
   444     case NOTIFY_IME_OF_TEXT_CHANGE:
   445       return NotifyIMEOfTextChange(aIMENotification);
   446     case NOTIFY_IME_OF_COMPOSITION_UPDATE:
   447       return NotifyIMEOfUpdateComposition();
   448     default:
   449       return NS_ERROR_NOT_IMPLEMENTED;
   450   }
   451 }
   453 NS_IMETHODIMP_(void)
   454 PuppetWidget::SetInputContext(const InputContext& aContext,
   455                               const InputContextAction& aAction)
   456 {
   457 #ifndef MOZ_CROSS_PROCESS_IME
   458   return;
   459 #endif
   461   if (!mTabChild) {
   462     return;
   463   }
   464   mTabChild->SendSetInputContext(
   465     static_cast<int32_t>(aContext.mIMEState.mEnabled),
   466     static_cast<int32_t>(aContext.mIMEState.mOpen),
   467     aContext.mHTMLInputType,
   468     aContext.mHTMLInputInputmode,
   469     aContext.mActionHint,
   470     static_cast<int32_t>(aAction.mCause),
   471     static_cast<int32_t>(aAction.mFocusChange));
   472 }
   474 NS_IMETHODIMP_(InputContext)
   475 PuppetWidget::GetInputContext()
   476 {
   477 #ifndef MOZ_CROSS_PROCESS_IME
   478   return InputContext();
   479 #endif
   481   InputContext context;
   482   if (mTabChild) {
   483     int32_t enabled, open;
   484     intptr_t nativeIMEContext;
   485     mTabChild->SendGetInputContext(&enabled, &open, &nativeIMEContext);
   486     context.mIMEState.mEnabled = static_cast<IMEState::Enabled>(enabled);
   487     context.mIMEState.mOpen = static_cast<IMEState::Open>(open);
   488     context.mNativeIMEContext = reinterpret_cast<void*>(nativeIMEContext);
   489   }
   490   return context;
   491 }
   493 nsresult
   494 PuppetWidget::NotifyIMEOfFocusChange(bool aFocus)
   495 {
   496 #ifndef MOZ_CROSS_PROCESS_IME
   497   return NS_OK;
   498 #endif
   500   if (!mTabChild)
   501     return NS_ERROR_FAILURE;
   503   if (aFocus) {
   504     nsEventStatus status;
   505     WidgetQueryContentEvent queryEvent(true, NS_QUERY_TEXT_CONTENT, this);
   506     InitEvent(queryEvent, nullptr);
   507     // Query entire content
   508     queryEvent.InitForQueryTextContent(0, UINT32_MAX);
   509     DispatchEvent(&queryEvent, status);
   511     if (queryEvent.mSucceeded) {
   512       mTabChild->SendNotifyIMETextHint(queryEvent.mReply.mString);
   513     }
   514   } else {
   515     // Might not have been committed composition yet
   516     IMEEndComposition(false);
   517   }
   519   uint32_t chromeSeqno;
   520   mIMEPreferenceOfParent = nsIMEUpdatePreference();
   521   if (!mTabChild->SendNotifyIMEFocus(aFocus, &mIMEPreferenceOfParent,
   522                                      &chromeSeqno)) {
   523     return NS_ERROR_FAILURE;
   524   }
   526   if (aFocus) {
   527     IMENotification notification(NOTIFY_IME_OF_SELECTION_CHANGE);
   528     notification.mSelectionChangeData.mCausedByComposition = false;
   529     NotifyIMEOfSelectionChange(notification); // Update selection
   530   } else {
   531     mIMELastBlurSeqno = chromeSeqno;
   532   }
   533   return NS_OK;
   534 }
   536 nsresult
   537 PuppetWidget::NotifyIMEOfUpdateComposition()
   538 {
   539 #ifndef MOZ_CROSS_PROCESS_IME
   540   return NS_OK;
   541 #endif
   543   NS_ENSURE_TRUE(mTabChild, NS_ERROR_FAILURE);
   545   nsRefPtr<TextComposition> textComposition =
   546     IMEStateManager::GetTextCompositionFor(this);
   547   NS_ENSURE_TRUE(textComposition, NS_ERROR_FAILURE);
   549   nsEventStatus status;
   550   uint32_t offset = textComposition->OffsetOfTargetClause();
   551   WidgetQueryContentEvent textRect(true, NS_QUERY_TEXT_RECT, this);
   552   InitEvent(textRect, nullptr);
   553   textRect.InitForQueryTextRect(offset, 1);
   554   DispatchEvent(&textRect, status);
   555   NS_ENSURE_TRUE(textRect.mSucceeded, NS_ERROR_FAILURE);
   557   WidgetQueryContentEvent caretRect(true, NS_QUERY_CARET_RECT, this);
   558   InitEvent(caretRect, nullptr);
   559   caretRect.InitForQueryCaretRect(offset);
   560   DispatchEvent(&caretRect, status);
   561   NS_ENSURE_TRUE(caretRect.mSucceeded, NS_ERROR_FAILURE);
   563   mTabChild->SendNotifyIMESelectedCompositionRect(offset,
   564                                                   textRect.mReply.mRect,
   565                                                   caretRect.mReply.mRect);
   566   return NS_OK;
   567 }
   569 nsIMEUpdatePreference
   570 PuppetWidget::GetIMEUpdatePreference()
   571 {
   572 #ifdef MOZ_CROSS_PROCESS_IME
   573   // e10s requires IME information cache into TabParent
   574   return nsIMEUpdatePreference(mIMEPreferenceOfParent.mWantUpdates |
   575                                nsIMEUpdatePreference::NOTIFY_SELECTION_CHANGE |
   576                                nsIMEUpdatePreference::NOTIFY_TEXT_CHANGE);
   577 #else
   578   // B2G doesn't handle IME as widget-level.
   579   return nsIMEUpdatePreference();
   580 #endif
   581 }
   583 nsresult
   584 PuppetWidget::NotifyIMEOfTextChange(const IMENotification& aIMENotification)
   585 {
   586   MOZ_ASSERT(aIMENotification.mMessage == NOTIFY_IME_OF_TEXT_CHANGE,
   587              "Passed wrong notification");
   589 #ifndef MOZ_CROSS_PROCESS_IME
   590   return NS_OK;
   591 #endif
   593   if (!mTabChild)
   594     return NS_ERROR_FAILURE;
   596   nsEventStatus status;
   597   WidgetQueryContentEvent queryEvent(true, NS_QUERY_TEXT_CONTENT, this);
   598   InitEvent(queryEvent, nullptr);
   599   queryEvent.InitForQueryTextContent(0, UINT32_MAX);
   600   DispatchEvent(&queryEvent, status);
   602   if (queryEvent.mSucceeded) {
   603     mTabChild->SendNotifyIMETextHint(queryEvent.mReply.mString);
   604   }
   606   // TabParent doesn't this this to cache.  we don't send the notification
   607   // if parent process doesn't request NOTIFY_TEXT_CHANGE.
   608   if (mIMEPreferenceOfParent.WantTextChange() &&
   609       (mIMEPreferenceOfParent.WantChangesCausedByComposition() ||
   610        !aIMENotification.mTextChangeData.mCausedByComposition)) {
   611     mTabChild->SendNotifyIMETextChange(
   612       aIMENotification.mTextChangeData.mStartOffset,
   613       aIMENotification.mTextChangeData.mOldEndOffset,
   614       aIMENotification.mTextChangeData.mNewEndOffset,
   615       aIMENotification.mTextChangeData.mCausedByComposition);
   616   }
   617   return NS_OK;
   618 }
   620 nsresult
   621 PuppetWidget::NotifyIMEOfSelectionChange(
   622                 const IMENotification& aIMENotification)
   623 {
   624   MOZ_ASSERT(aIMENotification.mMessage == NOTIFY_IME_OF_SELECTION_CHANGE,
   625              "Passed wrong notification");
   627 #ifndef MOZ_CROSS_PROCESS_IME
   628   return NS_OK;
   629 #endif
   631   if (!mTabChild)
   632     return NS_ERROR_FAILURE;
   634   nsEventStatus status;
   635   WidgetQueryContentEvent queryEvent(true, NS_QUERY_SELECTED_TEXT, this);
   636   InitEvent(queryEvent, nullptr);
   637   DispatchEvent(&queryEvent, status);
   639   if (queryEvent.mSucceeded) {
   640     mTabChild->SendNotifyIMESelection(
   641       mIMELastReceivedSeqno,
   642       queryEvent.GetSelectionStart(),
   643       queryEvent.GetSelectionEnd(),
   644       aIMENotification.mSelectionChangeData.mCausedByComposition);
   645   }
   646   return NS_OK;
   647 }
   649 NS_IMETHODIMP
   650 PuppetWidget::SetCursor(nsCursor aCursor)
   651 {
   652   if (mCursor == aCursor) {
   653     return NS_OK;
   654   }
   656   if (mTabChild && !mTabChild->SendSetCursor(aCursor)) {
   657     return NS_ERROR_FAILURE;
   658   }
   660   mCursor = aCursor;
   662   return NS_OK;
   663 }
   665 nsresult
   666 PuppetWidget::Paint()
   667 {
   668   NS_ABORT_IF_FALSE(!mDirtyRegion.IsEmpty(), "paint event logic messed up");
   670   if (!mAttachedWidgetListener)
   671     return NS_OK;
   673   nsIntRegion region = mDirtyRegion;
   675   // reset repaint tracking
   676   mDirtyRegion.SetEmpty();
   677   mPaintTask.Revoke();
   679   mAttachedWidgetListener->WillPaintWindow(this);
   681   if (mAttachedWidgetListener) {
   682 #ifdef DEBUG
   683     debug_DumpPaintEvent(stderr, this, region,
   684                          nsAutoCString("PuppetWidget"), 0);
   685 #endif
   687     if (mozilla::layers::LayersBackend::LAYERS_D3D10 == mLayerManager->GetBackendType()) {
   688       mAttachedWidgetListener->PaintWindow(this, region);
   689     } else if (mozilla::layers::LayersBackend::LAYERS_CLIENT == mLayerManager->GetBackendType()) {
   690       // Do nothing, the compositor will handle drawing
   691       if (mTabChild) {
   692         mTabChild->NotifyPainted();
   693       }
   694     } else {
   695       nsRefPtr<gfxContext> ctx = new gfxContext(mSurface);
   696       ctx->Rectangle(gfxRect(0,0,0,0));
   697       ctx->Clip();
   698       AutoLayerManagerSetup setupLayerManager(this, ctx,
   699                                               BufferMode::BUFFER_NONE);
   700       mAttachedWidgetListener->PaintWindow(this, region);
   701       if (mTabChild) {
   702         mTabChild->NotifyPainted();
   703       }
   704     }
   705   }
   707   if (mAttachedWidgetListener) {
   708     mAttachedWidgetListener->DidPaintWindow();
   709   }
   711   return NS_OK;
   712 }
   714 void
   715 PuppetWidget::SetChild(PuppetWidget* aChild)
   716 {
   717   NS_ABORT_IF_FALSE(this != aChild, "can't parent a widget to itself");
   718   NS_ABORT_IF_FALSE(!aChild->mChild,
   719                     "fake widget 'hierarchy' only expected to have one level");
   721   mChild = aChild;
   722 }
   724 NS_IMETHODIMP
   725 PuppetWidget::PaintTask::Run()
   726 {
   727   if (mWidget) {
   728     mWidget->Paint();
   729   }
   730   return NS_OK;
   731 }
   733 bool
   734 PuppetWidget::NeedsPaint()
   735 {
   736   return mVisible;
   737 }
   739 float
   740 PuppetWidget::GetDPI()
   741 {
   742   if (mDPI < 0) {
   743     if (mTabChild) {
   744       mTabChild->GetDPI(&mDPI);
   745     } else {
   746       mDPI = 96.0;
   747     }
   748   }
   750   return mDPI;
   751 }
   753 double
   754 PuppetWidget::GetDefaultScaleInternal()
   755 {
   756   if (mDefaultScale < 0) {
   757     if (mTabChild) {
   758       mTabChild->GetDefaultScale(&mDefaultScale);
   759     } else {
   760       mDefaultScale = 1;
   761     }
   762   }
   764   return mDefaultScale;
   765 }
   767 void*
   768 PuppetWidget::GetNativeData(uint32_t aDataType)
   769 {
   770   switch (aDataType) {
   771   case NS_NATIVE_SHAREABLE_WINDOW: {
   772     NS_ABORT_IF_FALSE(mTabChild, "Need TabChild to get the nativeWindow from!");
   773     mozilla::WindowsHandle nativeData = 0;
   774     if (mTabChild) {
   775       mTabChild->SendGetWidgetNativeData(&nativeData);
   776     }
   777     return (void*)nativeData;
   778   }
   779   case NS_NATIVE_WINDOW:
   780   case NS_NATIVE_DISPLAY:
   781   case NS_NATIVE_PLUGIN_PORT:
   782   case NS_NATIVE_GRAPHIC:
   783   case NS_NATIVE_SHELLWIDGET:
   784   case NS_NATIVE_WIDGET:
   785     NS_WARNING("nsWindow::GetNativeData not implemented for this type");
   786     break;
   787   default:
   788     NS_WARNING("nsWindow::GetNativeData called with bad value");
   789     break;
   790   }
   791   return nullptr;
   792 }
   794 PuppetScreen::PuppetScreen(void *nativeScreen)
   795 {
   796 }
   798 PuppetScreen::~PuppetScreen()
   799 {
   800 }
   802 static ScreenConfiguration
   803 ScreenConfig()
   804 {
   805   ScreenConfiguration config;
   806   hal::GetCurrentScreenConfiguration(&config);
   807   return config;
   808 }
   810 NS_IMETHODIMP
   811 PuppetScreen::GetRect(int32_t *outLeft,  int32_t *outTop,
   812                       int32_t *outWidth, int32_t *outHeight)
   813 {
   814   nsIntRect r = ScreenConfig().rect();
   815   *outLeft = r.x;
   816   *outTop = r.y;
   817   *outWidth = r.width;
   818   *outHeight = r.height;
   819   return NS_OK;
   820 }
   822 NS_IMETHODIMP
   823 PuppetScreen::GetAvailRect(int32_t *outLeft,  int32_t *outTop,
   824                            int32_t *outWidth, int32_t *outHeight)
   825 {
   826   return GetRect(outLeft, outTop, outWidth, outHeight);
   827 }
   830 NS_IMETHODIMP
   831 PuppetScreen::GetPixelDepth(int32_t *aPixelDepth)
   832 {
   833   *aPixelDepth = ScreenConfig().pixelDepth();
   834   return NS_OK;
   835 }
   837 NS_IMETHODIMP
   838 PuppetScreen::GetColorDepth(int32_t *aColorDepth)
   839 {
   840   *aColorDepth = ScreenConfig().colorDepth();
   841   return NS_OK;
   842 }
   844 NS_IMETHODIMP
   845 PuppetScreen::GetRotation(uint32_t* aRotation)
   846 {
   847   NS_WARNING("Attempt to get screen rotation through nsIScreen::GetRotation().  Nothing should know or care this in sandboxed contexts.  If you want *orientation*, use hal.");
   848   return NS_ERROR_NOT_AVAILABLE;
   849 }
   851 NS_IMETHODIMP
   852 PuppetScreen::SetRotation(uint32_t aRotation)
   853 {
   854   NS_WARNING("Attempt to set screen rotation through nsIScreen::GetRotation().  Nothing should know or care this in sandboxed contexts.  If you want *orientation*, use hal.");
   855   return NS_ERROR_NOT_AVAILABLE;
   856 }
   858 NS_IMPL_ISUPPORTS(PuppetScreenManager, nsIScreenManager)
   860 PuppetScreenManager::PuppetScreenManager()
   861 {
   862     mOneScreen = new PuppetScreen(nullptr);
   863 }
   865 PuppetScreenManager::~PuppetScreenManager()
   866 {
   867 }
   869 NS_IMETHODIMP
   870 PuppetScreenManager::GetPrimaryScreen(nsIScreen** outScreen)
   871 {
   872   NS_IF_ADDREF(*outScreen = mOneScreen.get());
   873   return NS_OK;
   874 }
   876 NS_IMETHODIMP
   877 PuppetScreenManager::ScreenForRect(int32_t inLeft,
   878                                    int32_t inTop,
   879                                    int32_t inWidth,
   880                                    int32_t inHeight,
   881                                    nsIScreen** outScreen)
   882 {
   883   return GetPrimaryScreen(outScreen);
   884 }
   886 NS_IMETHODIMP
   887 PuppetScreenManager::ScreenForNativeWidget(void* aWidget,
   888                                            nsIScreen** outScreen)
   889 {
   890   return GetPrimaryScreen(outScreen);
   891 }
   893 NS_IMETHODIMP
   894 PuppetScreenManager::GetNumberOfScreens(uint32_t* aNumberOfScreens)
   895 {
   896   *aNumberOfScreens = 1;
   897   return NS_OK;
   898 }
   900 NS_IMETHODIMP
   901 PuppetScreenManager::GetSystemDefaultScale(float *aDefaultScale)
   902 {
   903   *aDefaultScale = 1.0f;
   904   return NS_OK;
   905 }
   907 }  // namespace widget
   908 }  // namespace mozilla

mercurial