Fri, 16 Jan 2015 04:50:19 +0100
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