view/src/nsView.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "nsView.h"
michael@0 7
michael@0 8 #include "mozilla/Attributes.h"
michael@0 9 #include "mozilla/BasicEvents.h"
michael@0 10 #include "mozilla/DebugOnly.h"
michael@0 11 #include "mozilla/IntegerPrintfMacros.h"
michael@0 12 #include "mozilla/Likely.h"
michael@0 13 #include "mozilla/Poison.h"
michael@0 14 #include "nsIWidget.h"
michael@0 15 #include "nsViewManager.h"
michael@0 16 #include "nsIFrame.h"
michael@0 17 #include "nsPresArena.h"
michael@0 18 #include "nsXULPopupManager.h"
michael@0 19 #include "nsIWidgetListener.h"
michael@0 20 #include "nsContentUtils.h" // for nsAutoScriptBlocker
michael@0 21
michael@0 22 using namespace mozilla;
michael@0 23
michael@0 24 nsView::nsView(nsViewManager* aViewManager, nsViewVisibility aVisibility)
michael@0 25 {
michael@0 26 MOZ_COUNT_CTOR(nsView);
michael@0 27
michael@0 28 mVis = aVisibility;
michael@0 29 // Views should be transparent by default. Not being transparent is
michael@0 30 // a promise that the view will paint all its pixels opaquely. Views
michael@0 31 // should make this promise explicitly by calling
michael@0 32 // SetViewContentTransparency.
michael@0 33 mVFlags = 0;
michael@0 34 mViewManager = aViewManager;
michael@0 35 mDirtyRegion = nullptr;
michael@0 36 mWidgetIsTopLevel = false;
michael@0 37 }
michael@0 38
michael@0 39 void nsView::DropMouseGrabbing()
michael@0 40 {
michael@0 41 nsIPresShell* presShell = mViewManager->GetPresShell();
michael@0 42 if (presShell)
michael@0 43 presShell->ClearMouseCaptureOnView(this);
michael@0 44 }
michael@0 45
michael@0 46 nsView::~nsView()
michael@0 47 {
michael@0 48 MOZ_COUNT_DTOR(nsView);
michael@0 49
michael@0 50 while (GetFirstChild())
michael@0 51 {
michael@0 52 nsView* child = GetFirstChild();
michael@0 53 if (child->GetViewManager() == mViewManager) {
michael@0 54 child->Destroy();
michael@0 55 } else {
michael@0 56 // just unhook it. Someone else will want to destroy this.
michael@0 57 RemoveChild(child);
michael@0 58 }
michael@0 59 }
michael@0 60
michael@0 61 if (mViewManager)
michael@0 62 {
michael@0 63 DropMouseGrabbing();
michael@0 64
michael@0 65 nsView *rootView = mViewManager->GetRootView();
michael@0 66
michael@0 67 if (rootView)
michael@0 68 {
michael@0 69 // Root views can have parents!
michael@0 70 if (mParent)
michael@0 71 {
michael@0 72 mViewManager->RemoveChild(this);
michael@0 73 }
michael@0 74
michael@0 75 if (rootView == this)
michael@0 76 {
michael@0 77 // Inform the view manager that the root view has gone away...
michael@0 78 mViewManager->SetRootView(nullptr);
michael@0 79 }
michael@0 80 }
michael@0 81 else if (mParent)
michael@0 82 {
michael@0 83 mParent->RemoveChild(this);
michael@0 84 }
michael@0 85
michael@0 86 mViewManager = nullptr;
michael@0 87 }
michael@0 88 else if (mParent)
michael@0 89 {
michael@0 90 mParent->RemoveChild(this);
michael@0 91 }
michael@0 92
michael@0 93 // Destroy and release the widget
michael@0 94 DestroyWidget();
michael@0 95
michael@0 96 delete mDirtyRegion;
michael@0 97 }
michael@0 98
michael@0 99 class DestroyWidgetRunnable : public nsRunnable {
michael@0 100 public:
michael@0 101 NS_DECL_NSIRUNNABLE
michael@0 102
michael@0 103 explicit DestroyWidgetRunnable(nsIWidget* aWidget) : mWidget(aWidget) {}
michael@0 104
michael@0 105 private:
michael@0 106 nsCOMPtr<nsIWidget> mWidget;
michael@0 107 };
michael@0 108
michael@0 109 NS_IMETHODIMP DestroyWidgetRunnable::Run()
michael@0 110 {
michael@0 111 mWidget->Destroy();
michael@0 112 mWidget = nullptr;
michael@0 113 return NS_OK;
michael@0 114 }
michael@0 115
michael@0 116
michael@0 117 void nsView::DestroyWidget()
michael@0 118 {
michael@0 119 if (mWindow)
michael@0 120 {
michael@0 121 // If we are not attached to a base window, we're going to tear down our
michael@0 122 // widget here. However, if we're attached to somebody elses widget, we
michael@0 123 // want to leave the widget alone: don't reset the client data or call
michael@0 124 // Destroy. Just clear our event view ptr and free our reference to it.
michael@0 125 if (mWidgetIsTopLevel) {
michael@0 126 mWindow->SetAttachedWidgetListener(nullptr);
michael@0 127 }
michael@0 128 else {
michael@0 129 mWindow->SetWidgetListener(nullptr);
michael@0 130
michael@0 131 nsCOMPtr<nsIRunnable> widgetDestroyer =
michael@0 132 new DestroyWidgetRunnable(mWindow);
michael@0 133
michael@0 134 NS_DispatchToMainThread(widgetDestroyer);
michael@0 135 }
michael@0 136
michael@0 137 NS_RELEASE(mWindow);
michael@0 138 }
michael@0 139 }
michael@0 140
michael@0 141 nsView* nsView::GetViewFor(nsIWidget* aWidget)
michael@0 142 {
michael@0 143 NS_PRECONDITION(nullptr != aWidget, "null widget ptr");
michael@0 144
michael@0 145 nsIWidgetListener* listener = aWidget->GetWidgetListener();
michael@0 146 if (listener) {
michael@0 147 nsView* view = listener->GetView();
michael@0 148 if (view)
michael@0 149 return view;
michael@0 150 }
michael@0 151
michael@0 152 listener = aWidget->GetAttachedWidgetListener();
michael@0 153 return listener ? listener->GetView() : nullptr;
michael@0 154 }
michael@0 155
michael@0 156 void nsView::Destroy()
michael@0 157 {
michael@0 158 this->~nsView();
michael@0 159 mozWritePoison(this, sizeof(*this));
michael@0 160 nsView::operator delete(this);
michael@0 161 }
michael@0 162
michael@0 163 void nsView::SetPosition(nscoord aX, nscoord aY)
michael@0 164 {
michael@0 165 mDimBounds.x += aX - mPosX;
michael@0 166 mDimBounds.y += aY - mPosY;
michael@0 167 mPosX = aX;
michael@0 168 mPosY = aY;
michael@0 169
michael@0 170 NS_ASSERTION(GetParent() || (aX == 0 && aY == 0),
michael@0 171 "Don't try to move the root widget to something non-zero");
michael@0 172
michael@0 173 ResetWidgetBounds(true, false);
michael@0 174 }
michael@0 175
michael@0 176 void nsView::ResetWidgetBounds(bool aRecurse, bool aForceSync)
michael@0 177 {
michael@0 178 if (mWindow) {
michael@0 179 if (!aForceSync) {
michael@0 180 // Don't change widget geometry synchronously, since that can
michael@0 181 // cause synchronous painting.
michael@0 182 mViewManager->PostPendingUpdate();
michael@0 183 } else {
michael@0 184 DoResetWidgetBounds(false, true);
michael@0 185 }
michael@0 186 return;
michael@0 187 }
michael@0 188
michael@0 189 if (aRecurse) {
michael@0 190 // reposition any widgets under this view
michael@0 191 for (nsView* v = GetFirstChild(); v; v = v->GetNextSibling()) {
michael@0 192 v->ResetWidgetBounds(true, aForceSync);
michael@0 193 }
michael@0 194 }
michael@0 195 }
michael@0 196
michael@0 197 bool nsView::IsEffectivelyVisible()
michael@0 198 {
michael@0 199 for (nsView* v = this; v; v = v->mParent) {
michael@0 200 if (v->GetVisibility() == nsViewVisibility_kHide)
michael@0 201 return false;
michael@0 202 }
michael@0 203 return true;
michael@0 204 }
michael@0 205
michael@0 206 nsIntRect nsView::CalcWidgetBounds(nsWindowType aType)
michael@0 207 {
michael@0 208 int32_t p2a = mViewManager->AppUnitsPerDevPixel();
michael@0 209
michael@0 210 nsRect viewBounds(mDimBounds);
michael@0 211
michael@0 212 nsView* parent = GetParent();
michael@0 213 nsIWidget* parentWidget = nullptr;
michael@0 214 if (parent) {
michael@0 215 nsPoint offset;
michael@0 216 parentWidget = parent->GetNearestWidget(&offset, p2a);
michael@0 217 // make viewBounds be relative to the parent widget, in appunits
michael@0 218 viewBounds += offset;
michael@0 219
michael@0 220 if (parentWidget && aType == eWindowType_popup &&
michael@0 221 IsEffectivelyVisible()) {
michael@0 222 // put offset into screen coordinates. (based on client area origin)
michael@0 223 nsIntPoint screenPoint = parentWidget->WidgetToScreenOffset();
michael@0 224 viewBounds += nsPoint(NSIntPixelsToAppUnits(screenPoint.x, p2a),
michael@0 225 NSIntPixelsToAppUnits(screenPoint.y, p2a));
michael@0 226 }
michael@0 227 }
michael@0 228
michael@0 229 // Compute widget bounds in device pixels
michael@0 230 nsIntRect newBounds = viewBounds.ToNearestPixels(p2a);
michael@0 231
michael@0 232 #ifdef XP_MACOSX
michael@0 233 // cocoa rounds widget coordinates to the nearest global "display pixel"
michael@0 234 // integer value. So we avoid fractional display pixel values by rounding
michael@0 235 // to the nearest value that won't yield a fractional display pixel.
michael@0 236 nsIWidget* widget = parentWidget ? parentWidget : mWindow;
michael@0 237 uint32_t round;
michael@0 238 if (aType == eWindowType_popup && widget &&
michael@0 239 ((round = widget->RoundsWidgetCoordinatesTo()) > 1)) {
michael@0 240 nsIntSize pixelRoundedSize = newBounds.Size();
michael@0 241 // round the top left and bottom right to the nearest round pixel
michael@0 242 newBounds.x = NSToIntRoundUp(NSAppUnitsToDoublePixels(viewBounds.x, p2a) / round) * round;
michael@0 243 newBounds.y = NSToIntRoundUp(NSAppUnitsToDoublePixels(viewBounds.y, p2a) / round) * round;
michael@0 244 newBounds.width =
michael@0 245 NSToIntRoundUp(NSAppUnitsToDoublePixels(viewBounds.XMost(), p2a) / round) * round - newBounds.x;
michael@0 246 newBounds.height =
michael@0 247 NSToIntRoundUp(NSAppUnitsToDoublePixels(viewBounds.YMost(), p2a) / round) * round - newBounds.y;
michael@0 248 // but if that makes the widget larger then our frame may not paint the
michael@0 249 // extra pixels, so reduce the size to the nearest round value
michael@0 250 if (newBounds.width > pixelRoundedSize.width) {
michael@0 251 newBounds.width -= round;
michael@0 252 }
michael@0 253 if (newBounds.height > pixelRoundedSize.height) {
michael@0 254 newBounds.height -= round;
michael@0 255 }
michael@0 256 }
michael@0 257 #endif
michael@0 258
michael@0 259 // Compute where the top-left of our widget ended up relative to the parent
michael@0 260 // widget, in appunits.
michael@0 261 nsPoint roundedOffset(NSIntPixelsToAppUnits(newBounds.x, p2a),
michael@0 262 NSIntPixelsToAppUnits(newBounds.y, p2a));
michael@0 263
michael@0 264 // mViewToWidgetOffset is added to coordinates relative to the view origin
michael@0 265 // to get coordinates relative to the widget.
michael@0 266 // The view origin, relative to the parent widget, is at
michael@0 267 // (mPosX,mPosY) - mDimBounds.TopLeft() + viewBounds.TopLeft().
michael@0 268 // Our widget, relative to the parent widget, is roundedOffset.
michael@0 269 mViewToWidgetOffset = nsPoint(mPosX, mPosY)
michael@0 270 - mDimBounds.TopLeft() + viewBounds.TopLeft() - roundedOffset;
michael@0 271
michael@0 272 return newBounds;
michael@0 273 }
michael@0 274
michael@0 275 void nsView::DoResetWidgetBounds(bool aMoveOnly,
michael@0 276 bool aInvalidateChangedSize) {
michael@0 277 // The geometry of a root view's widget is controlled externally,
michael@0 278 // NOT by sizing or positioning the view
michael@0 279 if (mViewManager->GetRootView() == this) {
michael@0 280 return;
michael@0 281 }
michael@0 282
michael@0 283 NS_PRECONDITION(mWindow, "Why was this called??");
michael@0 284
michael@0 285 // Hold this ref to make sure it stays alive.
michael@0 286 nsCOMPtr<nsIWidget> widget = mWindow;
michael@0 287
michael@0 288 // Stash a copy of these and use them so we can handle this being deleted (say
michael@0 289 // from sync painting/flushing from Show/Move/Resize on the widget).
michael@0 290 nsIntRect newBounds;
michael@0 291 nsRefPtr<nsDeviceContext> dx = mViewManager->GetDeviceContext();
michael@0 292
michael@0 293 nsWindowType type = widget->WindowType();
michael@0 294
michael@0 295 nsIntRect curBounds;
michael@0 296 widget->GetClientBounds(curBounds);
michael@0 297 bool invisiblePopup = type == eWindowType_popup &&
michael@0 298 ((curBounds.IsEmpty() && mDimBounds.IsEmpty()) ||
michael@0 299 mVis == nsViewVisibility_kHide);
michael@0 300
michael@0 301 if (invisiblePopup) {
michael@0 302 // We're going to hit the early exit below, avoid calling CalcWidgetBounds.
michael@0 303 } else {
michael@0 304 newBounds = CalcWidgetBounds(type);
michael@0 305 }
michael@0 306
michael@0 307 bool curVisibility = widget->IsVisible();
michael@0 308 bool newVisibility = IsEffectivelyVisible();
michael@0 309 if (curVisibility && !newVisibility) {
michael@0 310 widget->Show(false);
michael@0 311 }
michael@0 312
michael@0 313 if (invisiblePopup) {
michael@0 314 // Don't manipulate empty or hidden popup widgets. For example there's no
michael@0 315 // point moving hidden comboboxes around, or doing X server roundtrips
michael@0 316 // to compute their true screen position. This could mean that WidgetToScreen
michael@0 317 // operations on these widgets don't return up-to-date values, but popup
michael@0 318 // positions aren't reliable anyway because of correction to be on or off-screen.
michael@0 319 return;
michael@0 320 }
michael@0 321
michael@0 322 bool changedPos = curBounds.TopLeft() != newBounds.TopLeft();
michael@0 323 bool changedSize = curBounds.Size() != newBounds.Size();
michael@0 324
michael@0 325 // Child views are never attached to top level widgets, this is safe.
michael@0 326
michael@0 327 // Coordinates are converted to display pixels for window Move/Resize APIs,
michael@0 328 // because of the potential for device-pixel coordinate spaces for mixed
michael@0 329 // hidpi/lodpi screens to overlap each other and result in bad placement
michael@0 330 // (bug 814434).
michael@0 331 double invScale;
michael@0 332
michael@0 333 // Bug 861270: for correct widget manipulation at arbitrary scale factors,
michael@0 334 // prefer to base scaling on widget->GetDefaultScale(). But only do this if
michael@0 335 // it matches the view manager's device context scale after allowing for the
michael@0 336 // quantization to app units, because of OS X multiscreen issues (where the
michael@0 337 // only two scales are 1.0 or 2.0, and so the quantization doesn't actually
michael@0 338 // cause problems anyhow).
michael@0 339 // In the case of a mismatch, fall back to scaling based on the dev context's
michael@0 340 // unscaledAppUnitsPerDevPixel value. On platforms where the device-pixel
michael@0 341 // scale is uniform across all displays (currently all except OS X), we'll
michael@0 342 // always use the precise value from mWindow->GetDefaultScale here.
michael@0 343 CSSToLayoutDeviceScale scale = widget->GetDefaultScale();
michael@0 344 if (NSToIntRound(60.0 / scale.scale) == dx->UnscaledAppUnitsPerDevPixel()) {
michael@0 345 invScale = 1.0 / scale.scale;
michael@0 346 } else {
michael@0 347 invScale = dx->UnscaledAppUnitsPerDevPixel() / 60.0;
michael@0 348 }
michael@0 349
michael@0 350 if (changedPos) {
michael@0 351 if (changedSize && !aMoveOnly) {
michael@0 352 widget->ResizeClient(newBounds.x * invScale,
michael@0 353 newBounds.y * invScale,
michael@0 354 newBounds.width * invScale,
michael@0 355 newBounds.height * invScale,
michael@0 356 aInvalidateChangedSize);
michael@0 357 } else {
michael@0 358 widget->MoveClient(newBounds.x * invScale,
michael@0 359 newBounds.y * invScale);
michael@0 360 }
michael@0 361 } else {
michael@0 362 if (changedSize && !aMoveOnly) {
michael@0 363 widget->ResizeClient(newBounds.width * invScale,
michael@0 364 newBounds.height * invScale,
michael@0 365 aInvalidateChangedSize);
michael@0 366 } // else do nothing!
michael@0 367 }
michael@0 368
michael@0 369 if (!curVisibility && newVisibility) {
michael@0 370 widget->Show(true);
michael@0 371 }
michael@0 372 }
michael@0 373
michael@0 374 void nsView::SetDimensions(const nsRect& aRect, bool aPaint, bool aResizeWidget)
michael@0 375 {
michael@0 376 nsRect dims = aRect;
michael@0 377 dims.MoveBy(mPosX, mPosY);
michael@0 378
michael@0 379 // Don't use nsRect's operator== here, since it returns true when
michael@0 380 // both rects are empty even if they have different widths and we
michael@0 381 // have cases where that sort of thing matters to us.
michael@0 382 if (mDimBounds.TopLeft() == dims.TopLeft() &&
michael@0 383 mDimBounds.Size() == dims.Size()) {
michael@0 384 return;
michael@0 385 }
michael@0 386
michael@0 387 mDimBounds = dims;
michael@0 388
michael@0 389 if (aResizeWidget) {
michael@0 390 ResetWidgetBounds(false, false);
michael@0 391 }
michael@0 392 }
michael@0 393
michael@0 394 void nsView::NotifyEffectiveVisibilityChanged(bool aEffectivelyVisible)
michael@0 395 {
michael@0 396 if (!aEffectivelyVisible)
michael@0 397 {
michael@0 398 DropMouseGrabbing();
michael@0 399 }
michael@0 400
michael@0 401 SetForcedRepaint(true);
michael@0 402
michael@0 403 if (nullptr != mWindow)
michael@0 404 {
michael@0 405 ResetWidgetBounds(false, false);
michael@0 406 }
michael@0 407
michael@0 408 for (nsView* child = mFirstChild; child; child = child->mNextSibling) {
michael@0 409 if (child->mVis == nsViewVisibility_kHide) {
michael@0 410 // It was effectively hidden and still is
michael@0 411 continue;
michael@0 412 }
michael@0 413 // Our child is visible if we are
michael@0 414 child->NotifyEffectiveVisibilityChanged(aEffectivelyVisible);
michael@0 415 }
michael@0 416 }
michael@0 417
michael@0 418 void nsView::SetVisibility(nsViewVisibility aVisibility)
michael@0 419 {
michael@0 420 mVis = aVisibility;
michael@0 421 NotifyEffectiveVisibilityChanged(IsEffectivelyVisible());
michael@0 422 }
michael@0 423
michael@0 424 void nsView::SetFloating(bool aFloatingView)
michael@0 425 {
michael@0 426 if (aFloatingView)
michael@0 427 mVFlags |= NS_VIEW_FLAG_FLOATING;
michael@0 428 else
michael@0 429 mVFlags &= ~NS_VIEW_FLAG_FLOATING;
michael@0 430 }
michael@0 431
michael@0 432 void nsView::InvalidateHierarchy(nsViewManager *aViewManagerParent)
michael@0 433 {
michael@0 434 if (mViewManager->GetRootView() == this)
michael@0 435 mViewManager->InvalidateHierarchy();
michael@0 436
michael@0 437 for (nsView *child = mFirstChild; child; child = child->GetNextSibling())
michael@0 438 child->InvalidateHierarchy(aViewManagerParent);
michael@0 439 }
michael@0 440
michael@0 441 void nsView::InsertChild(nsView *aChild, nsView *aSibling)
michael@0 442 {
michael@0 443 NS_PRECONDITION(nullptr != aChild, "null ptr");
michael@0 444
michael@0 445 if (nullptr != aChild)
michael@0 446 {
michael@0 447 if (nullptr != aSibling)
michael@0 448 {
michael@0 449 #ifdef DEBUG
michael@0 450 NS_ASSERTION(aSibling->GetParent() == this, "tried to insert view with invalid sibling");
michael@0 451 #endif
michael@0 452 //insert after sibling
michael@0 453 aChild->SetNextSibling(aSibling->GetNextSibling());
michael@0 454 aSibling->SetNextSibling(aChild);
michael@0 455 }
michael@0 456 else
michael@0 457 {
michael@0 458 aChild->SetNextSibling(mFirstChild);
michael@0 459 mFirstChild = aChild;
michael@0 460 }
michael@0 461 aChild->SetParent(this);
michael@0 462
michael@0 463 // If we just inserted a root view, then update the RootViewManager
michael@0 464 // on all view managers in the new subtree.
michael@0 465
michael@0 466 nsViewManager *vm = aChild->GetViewManager();
michael@0 467 if (vm->GetRootView() == aChild)
michael@0 468 {
michael@0 469 aChild->InvalidateHierarchy(nullptr); // don't care about releasing grabs
michael@0 470 }
michael@0 471 }
michael@0 472 }
michael@0 473
michael@0 474 void nsView::RemoveChild(nsView *child)
michael@0 475 {
michael@0 476 NS_PRECONDITION(nullptr != child, "null ptr");
michael@0 477
michael@0 478 if (nullptr != child)
michael@0 479 {
michael@0 480 nsView* prevKid = nullptr;
michael@0 481 nsView* kid = mFirstChild;
michael@0 482 DebugOnly<bool> found = false;
michael@0 483 while (nullptr != kid) {
michael@0 484 if (kid == child) {
michael@0 485 if (nullptr != prevKid) {
michael@0 486 prevKid->SetNextSibling(kid->GetNextSibling());
michael@0 487 } else {
michael@0 488 mFirstChild = kid->GetNextSibling();
michael@0 489 }
michael@0 490 child->SetParent(nullptr);
michael@0 491 found = true;
michael@0 492 break;
michael@0 493 }
michael@0 494 prevKid = kid;
michael@0 495 kid = kid->GetNextSibling();
michael@0 496 }
michael@0 497 NS_ASSERTION(found, "tried to remove non child");
michael@0 498
michael@0 499 // If we just removed a root view, then update the RootViewManager
michael@0 500 // on all view managers in the removed subtree.
michael@0 501
michael@0 502 nsViewManager *vm = child->GetViewManager();
michael@0 503 if (vm->GetRootView() == child)
michael@0 504 {
michael@0 505 child->InvalidateHierarchy(GetViewManager());
michael@0 506 }
michael@0 507 }
michael@0 508 }
michael@0 509
michael@0 510 // Native widgets ultimately just can't deal with the awesome power of
michael@0 511 // CSS2 z-index. However, we set the z-index on the widget anyway
michael@0 512 // because in many simple common cases the widgets do end up in the
michael@0 513 // right order. We set each widget's z-index to the z-index of the
michael@0 514 // nearest ancestor that has non-auto z-index.
michael@0 515 static void UpdateNativeWidgetZIndexes(nsView* aView, int32_t aZIndex)
michael@0 516 {
michael@0 517 if (aView->HasWidget()) {
michael@0 518 nsIWidget* widget = aView->GetWidget();
michael@0 519 if (widget->GetZIndex() != aZIndex) {
michael@0 520 widget->SetZIndex(aZIndex);
michael@0 521 }
michael@0 522 } else {
michael@0 523 for (nsView* v = aView->GetFirstChild(); v; v = v->GetNextSibling()) {
michael@0 524 if (v->GetZIndexIsAuto()) {
michael@0 525 UpdateNativeWidgetZIndexes(v, aZIndex);
michael@0 526 }
michael@0 527 }
michael@0 528 }
michael@0 529 }
michael@0 530
michael@0 531 static int32_t FindNonAutoZIndex(nsView* aView)
michael@0 532 {
michael@0 533 while (aView) {
michael@0 534 if (!aView->GetZIndexIsAuto()) {
michael@0 535 return aView->GetZIndex();
michael@0 536 }
michael@0 537 aView = aView->GetParent();
michael@0 538 }
michael@0 539 return 0;
michael@0 540 }
michael@0 541
michael@0 542 struct DefaultWidgetInitData : public nsWidgetInitData {
michael@0 543 DefaultWidgetInitData() : nsWidgetInitData()
michael@0 544 {
michael@0 545 mWindowType = eWindowType_child;
michael@0 546 clipChildren = true;
michael@0 547 clipSiblings = true;
michael@0 548 }
michael@0 549 };
michael@0 550
michael@0 551 nsresult nsView::CreateWidget(nsWidgetInitData *aWidgetInitData,
michael@0 552 bool aEnableDragDrop,
michael@0 553 bool aResetVisibility)
michael@0 554 {
michael@0 555 AssertNoWindow();
michael@0 556 NS_ABORT_IF_FALSE(!aWidgetInitData ||
michael@0 557 aWidgetInitData->mWindowType != eWindowType_popup,
michael@0 558 "Use CreateWidgetForPopup");
michael@0 559
michael@0 560 DefaultWidgetInitData defaultInitData;
michael@0 561 bool initDataPassedIn = !!aWidgetInitData;
michael@0 562 aWidgetInitData = aWidgetInitData ? aWidgetInitData : &defaultInitData;
michael@0 563 defaultInitData.mListenForResizes =
michael@0 564 (!initDataPassedIn && GetParent() &&
michael@0 565 GetParent()->GetViewManager() != mViewManager);
michael@0 566
michael@0 567 nsIntRect trect = CalcWidgetBounds(aWidgetInitData->mWindowType);
michael@0 568
michael@0 569 nsRefPtr<nsDeviceContext> dx = mViewManager->GetDeviceContext();
michael@0 570
michael@0 571 nsIWidget* parentWidget =
michael@0 572 GetParent() ? GetParent()->GetNearestWidget(nullptr) : nullptr;
michael@0 573 if (!parentWidget) {
michael@0 574 NS_ERROR("nsView::CreateWidget without suitable parent widget??");
michael@0 575 return NS_ERROR_FAILURE;
michael@0 576 }
michael@0 577
michael@0 578 // XXX: using aForceUseIWidgetParent=true to preserve previous
michael@0 579 // semantics. It's not clear that it's actually needed.
michael@0 580 mWindow = parentWidget->CreateChild(trect, dx, aWidgetInitData,
michael@0 581 true).take();
michael@0 582 if (!mWindow) {
michael@0 583 return NS_ERROR_FAILURE;
michael@0 584 }
michael@0 585
michael@0 586 InitializeWindow(aEnableDragDrop, aResetVisibility);
michael@0 587
michael@0 588 return NS_OK;
michael@0 589 }
michael@0 590
michael@0 591 nsresult nsView::CreateWidgetForParent(nsIWidget* aParentWidget,
michael@0 592 nsWidgetInitData *aWidgetInitData,
michael@0 593 bool aEnableDragDrop,
michael@0 594 bool aResetVisibility)
michael@0 595 {
michael@0 596 AssertNoWindow();
michael@0 597 NS_ABORT_IF_FALSE(!aWidgetInitData ||
michael@0 598 aWidgetInitData->mWindowType != eWindowType_popup,
michael@0 599 "Use CreateWidgetForPopup");
michael@0 600 NS_ABORT_IF_FALSE(aParentWidget, "Parent widget required");
michael@0 601
michael@0 602 DefaultWidgetInitData defaultInitData;
michael@0 603 aWidgetInitData = aWidgetInitData ? aWidgetInitData : &defaultInitData;
michael@0 604
michael@0 605 nsIntRect trect = CalcWidgetBounds(aWidgetInitData->mWindowType);
michael@0 606
michael@0 607 nsRefPtr<nsDeviceContext> dx = mViewManager->GetDeviceContext();
michael@0 608
michael@0 609 mWindow =
michael@0 610 aParentWidget->CreateChild(trect, dx, aWidgetInitData).take();
michael@0 611 if (!mWindow) {
michael@0 612 return NS_ERROR_FAILURE;
michael@0 613 }
michael@0 614
michael@0 615 InitializeWindow(aEnableDragDrop, aResetVisibility);
michael@0 616
michael@0 617 return NS_OK;
michael@0 618 }
michael@0 619
michael@0 620 nsresult nsView::CreateWidgetForPopup(nsWidgetInitData *aWidgetInitData,
michael@0 621 nsIWidget* aParentWidget,
michael@0 622 bool aEnableDragDrop,
michael@0 623 bool aResetVisibility)
michael@0 624 {
michael@0 625 AssertNoWindow();
michael@0 626 NS_ABORT_IF_FALSE(aWidgetInitData, "Widget init data required");
michael@0 627 NS_ABORT_IF_FALSE(aWidgetInitData->mWindowType == eWindowType_popup,
michael@0 628 "Use one of the other CreateWidget methods");
michael@0 629
michael@0 630 nsIntRect trect = CalcWidgetBounds(aWidgetInitData->mWindowType);
michael@0 631
michael@0 632 nsRefPtr<nsDeviceContext> dx = mViewManager->GetDeviceContext();
michael@0 633
michael@0 634 // XXX/cjones: having these two separate creation cases seems ... um
michael@0 635 // ... unnecessary, but it's the way the old code did it. Please
michael@0 636 // unify them by first finding a suitable parent nsIWidget, then
michael@0 637 // getting rid of aForceUseIWidgetParent.
michael@0 638 if (aParentWidget) {
michael@0 639 // XXX: using aForceUseIWidgetParent=true to preserve previous
michael@0 640 // semantics. It's not clear that it's actually needed.
michael@0 641 mWindow = aParentWidget->CreateChild(trect, dx, aWidgetInitData,
michael@0 642 true).take();
michael@0 643 }
michael@0 644 else {
michael@0 645 nsIWidget* nearestParent = GetParent() ? GetParent()->GetNearestWidget(nullptr)
michael@0 646 : nullptr;
michael@0 647 if (!nearestParent) {
michael@0 648 // Without a parent, we can't make a popup. This can happen
michael@0 649 // when printing
michael@0 650 return NS_ERROR_FAILURE;
michael@0 651 }
michael@0 652
michael@0 653 mWindow =
michael@0 654 nearestParent->CreateChild(trect, dx, aWidgetInitData).take();
michael@0 655 }
michael@0 656 if (!mWindow) {
michael@0 657 return NS_ERROR_FAILURE;
michael@0 658 }
michael@0 659
michael@0 660 InitializeWindow(aEnableDragDrop, aResetVisibility);
michael@0 661
michael@0 662 return NS_OK;
michael@0 663 }
michael@0 664
michael@0 665 void
michael@0 666 nsView::InitializeWindow(bool aEnableDragDrop, bool aResetVisibility)
michael@0 667 {
michael@0 668 NS_ABORT_IF_FALSE(mWindow, "Must have a window to initialize");
michael@0 669
michael@0 670 mWindow->SetWidgetListener(this);
michael@0 671
michael@0 672 if (aEnableDragDrop) {
michael@0 673 mWindow->EnableDragDrop(true);
michael@0 674 }
michael@0 675
michael@0 676 // propagate the z-index to the widget.
michael@0 677 UpdateNativeWidgetZIndexes(this, FindNonAutoZIndex(this));
michael@0 678
michael@0 679 //make sure visibility state is accurate
michael@0 680
michael@0 681 if (aResetVisibility) {
michael@0 682 SetVisibility(GetVisibility());
michael@0 683 }
michael@0 684 }
michael@0 685
michael@0 686 // Attach to a top level widget and start receiving mirrored events.
michael@0 687 nsresult nsView::AttachToTopLevelWidget(nsIWidget* aWidget)
michael@0 688 {
michael@0 689 NS_PRECONDITION(nullptr != aWidget, "null widget ptr");
michael@0 690 /// XXXjimm This is a temporary workaround to an issue w/document
michael@0 691 // viewer (bug 513162).
michael@0 692 nsIWidgetListener* listener = aWidget->GetAttachedWidgetListener();
michael@0 693 if (listener) {
michael@0 694 nsView *oldView = listener->GetView();
michael@0 695 if (oldView) {
michael@0 696 oldView->DetachFromTopLevelWidget();
michael@0 697 }
michael@0 698 }
michael@0 699
michael@0 700 nsRefPtr<nsDeviceContext> dx = mViewManager->GetDeviceContext();
michael@0 701
michael@0 702 // Note, the previous device context will be released. Detaching
michael@0 703 // will not restore the old one.
michael@0 704 nsresult rv = aWidget->AttachViewToTopLevel(!nsIWidget::UsePuppetWidgets(), dx);
michael@0 705 if (NS_FAILED(rv))
michael@0 706 return rv;
michael@0 707
michael@0 708 mWindow = aWidget;
michael@0 709 NS_ADDREF(mWindow);
michael@0 710
michael@0 711 mWindow->SetAttachedWidgetListener(this);
michael@0 712 mWindow->EnableDragDrop(true);
michael@0 713 mWidgetIsTopLevel = true;
michael@0 714
michael@0 715 // Refresh the view bounds
michael@0 716 CalcWidgetBounds(mWindow->WindowType());
michael@0 717
michael@0 718 return NS_OK;
michael@0 719 }
michael@0 720
michael@0 721 // Detach this view from an attached widget.
michael@0 722 nsresult nsView::DetachFromTopLevelWidget()
michael@0 723 {
michael@0 724 NS_PRECONDITION(mWidgetIsTopLevel, "Not attached currently!");
michael@0 725 NS_PRECONDITION(mWindow, "null mWindow for DetachFromTopLevelWidget!");
michael@0 726
michael@0 727 mWindow->SetAttachedWidgetListener(nullptr);
michael@0 728 NS_RELEASE(mWindow);
michael@0 729
michael@0 730 mWidgetIsTopLevel = false;
michael@0 731
michael@0 732 return NS_OK;
michael@0 733 }
michael@0 734
michael@0 735 void nsView::SetZIndex(bool aAuto, int32_t aZIndex)
michael@0 736 {
michael@0 737 bool oldIsAuto = GetZIndexIsAuto();
michael@0 738 mVFlags = (mVFlags & ~NS_VIEW_FLAG_AUTO_ZINDEX) | (aAuto ? NS_VIEW_FLAG_AUTO_ZINDEX : 0);
michael@0 739 mZIndex = aZIndex;
michael@0 740
michael@0 741 if (HasWidget() || !oldIsAuto || !aAuto) {
michael@0 742 UpdateNativeWidgetZIndexes(this, FindNonAutoZIndex(this));
michael@0 743 }
michael@0 744 }
michael@0 745
michael@0 746 void nsView::AssertNoWindow()
michael@0 747 {
michael@0 748 // XXX: it would be nice to make this a strong assert
michael@0 749 if (MOZ_UNLIKELY(mWindow)) {
michael@0 750 NS_ERROR("We already have a window for this view? BAD");
michael@0 751 mWindow->SetWidgetListener(nullptr);
michael@0 752 mWindow->Destroy();
michael@0 753 NS_RELEASE(mWindow);
michael@0 754 }
michael@0 755 }
michael@0 756
michael@0 757 //
michael@0 758 // internal window creation functions
michael@0 759 //
michael@0 760 void nsView::AttachWidgetEventHandler(nsIWidget* aWidget)
michael@0 761 {
michael@0 762 #ifdef DEBUG
michael@0 763 NS_ASSERTION(!aWidget->GetWidgetListener(), "Already have a widget listener");
michael@0 764 #endif
michael@0 765
michael@0 766 aWidget->SetWidgetListener(this);
michael@0 767 }
michael@0 768
michael@0 769 void nsView::DetachWidgetEventHandler(nsIWidget* aWidget)
michael@0 770 {
michael@0 771 NS_ASSERTION(!aWidget->GetWidgetListener() ||
michael@0 772 aWidget->GetWidgetListener()->GetView() == this, "Wrong view");
michael@0 773 aWidget->SetWidgetListener(nullptr);
michael@0 774 }
michael@0 775
michael@0 776 #ifdef DEBUG
michael@0 777 void nsView::List(FILE* out, int32_t aIndent) const
michael@0 778 {
michael@0 779 int32_t i;
michael@0 780 for (i = aIndent; --i >= 0; ) fputs(" ", out);
michael@0 781 fprintf(out, "%p ", (void*)this);
michael@0 782 if (nullptr != mWindow) {
michael@0 783 nscoord p2a = mViewManager->AppUnitsPerDevPixel();
michael@0 784 nsIntRect rect;
michael@0 785 mWindow->GetClientBounds(rect);
michael@0 786 nsRect windowBounds = rect.ToAppUnits(p2a);
michael@0 787 mWindow->GetBounds(rect);
michael@0 788 nsRect nonclientBounds = rect.ToAppUnits(p2a);
michael@0 789 nsrefcnt widgetRefCnt = mWindow->AddRef() - 1;
michael@0 790 mWindow->Release();
michael@0 791 int32_t Z = mWindow->GetZIndex();
michael@0 792 fprintf(out, "(widget=%p[%" PRIuPTR "] z=%d pos={%d,%d,%d,%d}) ",
michael@0 793 (void*)mWindow, widgetRefCnt, Z,
michael@0 794 nonclientBounds.x, nonclientBounds.y,
michael@0 795 windowBounds.width, windowBounds.height);
michael@0 796 }
michael@0 797 nsRect brect = GetBounds();
michael@0 798 fprintf(out, "{%d,%d,%d,%d}",
michael@0 799 brect.x, brect.y, brect.width, brect.height);
michael@0 800 fprintf(out, " z=%d vis=%d frame=%p <\n",
michael@0 801 mZIndex, mVis, static_cast<void*>(mFrame));
michael@0 802 for (nsView* kid = mFirstChild; kid; kid = kid->GetNextSibling()) {
michael@0 803 NS_ASSERTION(kid->GetParent() == this, "incorrect parent");
michael@0 804 kid->List(out, aIndent + 1);
michael@0 805 }
michael@0 806 for (i = aIndent; --i >= 0; ) fputs(" ", out);
michael@0 807 fputs(">\n", out);
michael@0 808 }
michael@0 809 #endif // DEBUG
michael@0 810
michael@0 811 nsPoint nsView::GetOffsetTo(const nsView* aOther) const
michael@0 812 {
michael@0 813 return GetOffsetTo(aOther, GetViewManager()->AppUnitsPerDevPixel());
michael@0 814 }
michael@0 815
michael@0 816 nsPoint nsView::GetOffsetTo(const nsView* aOther, const int32_t aAPD) const
michael@0 817 {
michael@0 818 NS_ABORT_IF_FALSE(GetParent() || !aOther || aOther->GetParent() ||
michael@0 819 this == aOther, "caller of (outer) GetOffsetTo must not "
michael@0 820 "pass unrelated views");
michael@0 821 // We accumulate the final result in offset
michael@0 822 nsPoint offset(0, 0);
michael@0 823 // The offset currently accumulated at the current APD
michael@0 824 nsPoint docOffset(0, 0);
michael@0 825 const nsView* v = this;
michael@0 826 nsViewManager* currVM = v->GetViewManager();
michael@0 827 int32_t currAPD = currVM->AppUnitsPerDevPixel();
michael@0 828 const nsView* root = nullptr;
michael@0 829 for ( ; v != aOther && v; root = v, v = v->GetParent()) {
michael@0 830 nsViewManager* newVM = v->GetViewManager();
michael@0 831 if (newVM != currVM) {
michael@0 832 int32_t newAPD = newVM->AppUnitsPerDevPixel();
michael@0 833 if (newAPD != currAPD) {
michael@0 834 offset += docOffset.ConvertAppUnits(currAPD, aAPD);
michael@0 835 docOffset.x = docOffset.y = 0;
michael@0 836 currAPD = newAPD;
michael@0 837 }
michael@0 838 currVM = newVM;
michael@0 839 }
michael@0 840 docOffset += v->GetPosition();
michael@0 841 }
michael@0 842 offset += docOffset.ConvertAppUnits(currAPD, aAPD);
michael@0 843
michael@0 844 if (v != aOther) {
michael@0 845 // Looks like aOther wasn't an ancestor of |this|. So now we have
michael@0 846 // the root-VM-relative position of |this| in |offset|. Get the
michael@0 847 // root-VM-relative position of aOther and subtract it.
michael@0 848 nsPoint negOffset = aOther->GetOffsetTo(root, aAPD);
michael@0 849 offset -= negOffset;
michael@0 850 }
michael@0 851
michael@0 852 return offset;
michael@0 853 }
michael@0 854
michael@0 855 nsPoint nsView::GetOffsetToWidget(nsIWidget* aWidget) const
michael@0 856 {
michael@0 857 nsPoint pt;
michael@0 858 // Get the view for widget
michael@0 859 nsView* widgetView = GetViewFor(aWidget);
michael@0 860 if (!widgetView) {
michael@0 861 return pt;
michael@0 862 }
michael@0 863
michael@0 864 // Get the offset to the widget view in the widget view's APD
michael@0 865 // We get the offset in the widget view's APD first and then convert to our
michael@0 866 // APD afterwards so that we can include the widget view's ViewToWidgetOffset
michael@0 867 // in the sum in its native APD, and then convert the whole thing to our APD
michael@0 868 // so that we don't have to convert the APD of the relatively small
michael@0 869 // ViewToWidgetOffset by itself with a potentially large relative rounding
michael@0 870 // error.
michael@0 871 pt = -widgetView->GetOffsetTo(this);
michael@0 872 // Add in the offset to the widget.
michael@0 873 pt += widgetView->ViewToWidgetOffset();
michael@0 874
michael@0 875 // Convert to our appunits.
michael@0 876 int32_t widgetAPD = widgetView->GetViewManager()->AppUnitsPerDevPixel();
michael@0 877 int32_t ourAPD = GetViewManager()->AppUnitsPerDevPixel();
michael@0 878 pt = pt.ConvertAppUnits(widgetAPD, ourAPD);
michael@0 879 return pt;
michael@0 880 }
michael@0 881
michael@0 882 nsIWidget* nsView::GetNearestWidget(nsPoint* aOffset) const
michael@0 883 {
michael@0 884 return GetNearestWidget(aOffset, GetViewManager()->AppUnitsPerDevPixel());
michael@0 885 }
michael@0 886
michael@0 887 nsIWidget* nsView::GetNearestWidget(nsPoint* aOffset, const int32_t aAPD) const
michael@0 888 {
michael@0 889 // aOffset is based on the view's position, which ignores any chrome on
michael@0 890 // attached parent widgets.
michael@0 891
michael@0 892 // We accumulate the final result in pt
michael@0 893 nsPoint pt(0, 0);
michael@0 894 // The offset currently accumulated at the current APD
michael@0 895 nsPoint docPt(0,0);
michael@0 896 const nsView* v = this;
michael@0 897 nsViewManager* currVM = v->GetViewManager();
michael@0 898 int32_t currAPD = currVM->AppUnitsPerDevPixel();
michael@0 899 for ( ; v && !v->HasWidget(); v = v->GetParent()) {
michael@0 900 nsViewManager* newVM = v->GetViewManager();
michael@0 901 if (newVM != currVM) {
michael@0 902 int32_t newAPD = newVM->AppUnitsPerDevPixel();
michael@0 903 if (newAPD != currAPD) {
michael@0 904 pt += docPt.ConvertAppUnits(currAPD, aAPD);
michael@0 905 docPt.x = docPt.y = 0;
michael@0 906 currAPD = newAPD;
michael@0 907 }
michael@0 908 currVM = newVM;
michael@0 909 }
michael@0 910 docPt += v->GetPosition();
michael@0 911 }
michael@0 912 if (!v) {
michael@0 913 if (aOffset) {
michael@0 914 pt += docPt.ConvertAppUnits(currAPD, aAPD);
michael@0 915 *aOffset = pt;
michael@0 916 }
michael@0 917 return nullptr;
michael@0 918 }
michael@0 919
michael@0 920 // pt is now the offset from v's origin to this view's origin.
michael@0 921 // We add the ViewToWidgetOffset to get the offset to the widget.
michael@0 922 if (aOffset) {
michael@0 923 docPt += v->ViewToWidgetOffset();
michael@0 924 pt += docPt.ConvertAppUnits(currAPD, aAPD);
michael@0 925 *aOffset = pt;
michael@0 926 }
michael@0 927 return v->GetWidget();
michael@0 928 }
michael@0 929
michael@0 930 bool nsView::IsRoot() const
michael@0 931 {
michael@0 932 NS_ASSERTION(mViewManager != nullptr," View manager is null in nsView::IsRoot()");
michael@0 933 return mViewManager->GetRootView() == this;
michael@0 934 }
michael@0 935
michael@0 936 nsRect
michael@0 937 nsView::GetBoundsInParentUnits() const
michael@0 938 {
michael@0 939 nsView* parent = GetParent();
michael@0 940 nsViewManager* VM = GetViewManager();
michael@0 941 if (this != VM->GetRootView() || !parent) {
michael@0 942 return mDimBounds;
michael@0 943 }
michael@0 944 int32_t ourAPD = VM->AppUnitsPerDevPixel();
michael@0 945 int32_t parentAPD = parent->GetViewManager()->AppUnitsPerDevPixel();
michael@0 946 return mDimBounds.ConvertAppUnitsRoundOut(ourAPD, parentAPD);
michael@0 947 }
michael@0 948
michael@0 949 nsPoint
michael@0 950 nsView::ConvertFromParentCoords(nsPoint aPt) const
michael@0 951 {
michael@0 952 const nsView* parent = GetParent();
michael@0 953 if (parent) {
michael@0 954 aPt = aPt.ConvertAppUnits(parent->GetViewManager()->AppUnitsPerDevPixel(),
michael@0 955 GetViewManager()->AppUnitsPerDevPixel());
michael@0 956 }
michael@0 957 aPt -= GetPosition();
michael@0 958 return aPt;
michael@0 959 }
michael@0 960
michael@0 961 static bool
michael@0 962 IsPopupWidget(nsIWidget* aWidget)
michael@0 963 {
michael@0 964 return (aWidget->WindowType() == eWindowType_popup);
michael@0 965 }
michael@0 966
michael@0 967 nsIPresShell*
michael@0 968 nsView::GetPresShell()
michael@0 969 {
michael@0 970 return GetViewManager()->GetPresShell();
michael@0 971 }
michael@0 972
michael@0 973 bool
michael@0 974 nsView::WindowMoved(nsIWidget* aWidget, int32_t x, int32_t y)
michael@0 975 {
michael@0 976 nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
michael@0 977 if (pm && IsPopupWidget(aWidget)) {
michael@0 978 pm->PopupMoved(mFrame, nsIntPoint(x, y));
michael@0 979 return true;
michael@0 980 }
michael@0 981
michael@0 982 return false;
michael@0 983 }
michael@0 984
michael@0 985 bool
michael@0 986 nsView::WindowResized(nsIWidget* aWidget, int32_t aWidth, int32_t aHeight)
michael@0 987 {
michael@0 988 // The root view may not be set if this is the resize associated with
michael@0 989 // window creation
michael@0 990 SetForcedRepaint(true);
michael@0 991 if (this == mViewManager->GetRootView()) {
michael@0 992 nsRefPtr<nsDeviceContext> devContext = mViewManager->GetDeviceContext();
michael@0 993 // ensure DPI is up-to-date, in case of window being opened and sized
michael@0 994 // on a non-default-dpi display (bug 829963)
michael@0 995 devContext->CheckDPIChange();
michael@0 996 int32_t p2a = devContext->AppUnitsPerDevPixel();
michael@0 997 mViewManager->SetWindowDimensions(NSIntPixelsToAppUnits(aWidth, p2a),
michael@0 998 NSIntPixelsToAppUnits(aHeight, p2a));
michael@0 999
michael@0 1000 nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
michael@0 1001 if (pm) {
michael@0 1002 nsIPresShell* presShell = mViewManager->GetPresShell();
michael@0 1003 if (presShell && presShell->GetDocument()) {
michael@0 1004 pm->AdjustPopupsOnWindowChange(presShell);
michael@0 1005 }
michael@0 1006 }
michael@0 1007
michael@0 1008 return true;
michael@0 1009 }
michael@0 1010 else if (IsPopupWidget(aWidget)) {
michael@0 1011 nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
michael@0 1012 if (pm) {
michael@0 1013 pm->PopupResized(mFrame, nsIntSize(aWidth, aHeight));
michael@0 1014 return true;
michael@0 1015 }
michael@0 1016 }
michael@0 1017
michael@0 1018 return false;
michael@0 1019 }
michael@0 1020
michael@0 1021 bool
michael@0 1022 nsView::RequestWindowClose(nsIWidget* aWidget)
michael@0 1023 {
michael@0 1024 if (mFrame && IsPopupWidget(aWidget) &&
michael@0 1025 mFrame->GetType() == nsGkAtoms::menuPopupFrame) {
michael@0 1026 nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
michael@0 1027 if (pm) {
michael@0 1028 pm->HidePopup(mFrame->GetContent(), false, true, false, false);
michael@0 1029 return true;
michael@0 1030 }
michael@0 1031 }
michael@0 1032
michael@0 1033 return false;
michael@0 1034 }
michael@0 1035
michael@0 1036 void
michael@0 1037 nsView::WillPaintWindow(nsIWidget* aWidget)
michael@0 1038 {
michael@0 1039 nsRefPtr<nsViewManager> vm = mViewManager;
michael@0 1040 vm->WillPaintWindow(aWidget);
michael@0 1041 }
michael@0 1042
michael@0 1043 bool
michael@0 1044 nsView::PaintWindow(nsIWidget* aWidget, nsIntRegion aRegion)
michael@0 1045 {
michael@0 1046 NS_ASSERTION(this == nsView::GetViewFor(aWidget), "wrong view for widget?");
michael@0 1047
michael@0 1048 nsRefPtr<nsViewManager> vm = mViewManager;
michael@0 1049 bool result = vm->PaintWindow(aWidget, aRegion);
michael@0 1050 return result;
michael@0 1051 }
michael@0 1052
michael@0 1053 void
michael@0 1054 nsView::DidPaintWindow()
michael@0 1055 {
michael@0 1056 nsRefPtr<nsViewManager> vm = mViewManager;
michael@0 1057 vm->DidPaintWindow();
michael@0 1058 }
michael@0 1059
michael@0 1060 void
michael@0 1061 nsView::DidCompositeWindow()
michael@0 1062 {
michael@0 1063 nsIPresShell* presShell = mViewManager->GetPresShell();
michael@0 1064 if (presShell) {
michael@0 1065 nsAutoScriptBlocker scriptBlocker;
michael@0 1066 presShell->GetPresContext()->GetDisplayRootPresContext()->GetRootPresContext()->NotifyDidPaintForSubtree(nsIPresShell::PAINT_COMPOSITE);
michael@0 1067 }
michael@0 1068 }
michael@0 1069
michael@0 1070 void
michael@0 1071 nsView::RequestRepaint()
michael@0 1072 {
michael@0 1073 nsIPresShell* presShell = mViewManager->GetPresShell();
michael@0 1074 if (presShell) {
michael@0 1075 presShell->ScheduleViewManagerFlush();
michael@0 1076 }
michael@0 1077 }
michael@0 1078
michael@0 1079 nsEventStatus
michael@0 1080 nsView::HandleEvent(WidgetGUIEvent* aEvent,
michael@0 1081 bool aUseAttachedEvents)
michael@0 1082 {
michael@0 1083 NS_PRECONDITION(nullptr != aEvent->widget, "null widget ptr");
michael@0 1084
michael@0 1085 nsEventStatus result = nsEventStatus_eIgnore;
michael@0 1086 nsView* view;
michael@0 1087 if (aUseAttachedEvents) {
michael@0 1088 nsIWidgetListener* listener = aEvent->widget->GetAttachedWidgetListener();
michael@0 1089 view = listener ? listener->GetView() : nullptr;
michael@0 1090 }
michael@0 1091 else {
michael@0 1092 view = GetViewFor(aEvent->widget);
michael@0 1093 }
michael@0 1094
michael@0 1095 if (view) {
michael@0 1096 nsRefPtr<nsViewManager> vm = view->GetViewManager();
michael@0 1097 vm->DispatchEvent(aEvent, view, &result);
michael@0 1098 }
michael@0 1099
michael@0 1100 return result;
michael@0 1101 }

mercurial