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

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

mercurial