Example #1
0
void
PuppetWidget::Resize(double aWidth,
                     double aHeight,
                     bool   aRepaint)
{
  LayoutDeviceIntRect oldBounds = mBounds;
  mBounds.SizeTo(LayoutDeviceIntSize(NSToIntRound(aWidth),
                                     NSToIntRound(aHeight)));

  if (mChild) {
    mChild->Resize(aWidth, aHeight, aRepaint);
    return;
  }

  // XXX: roc says that |aRepaint| dictates whether or not to
  // invalidate the expanded area
  if (oldBounds.Size() < mBounds.Size() && aRepaint) {
    LayoutDeviceIntRegion dirty(mBounds);
    dirty.Sub(dirty, oldBounds);
    InvalidateRegion(this, dirty);
  }

  // call WindowResized() on both the current listener, and possibly
  // also the previous one if we're in a state where we're drawing that one
  // because the current one is paint suppressed
  if (!oldBounds.IsEqualEdges(mBounds) && mAttachedWidgetListener) {
    if (GetCurrentWidgetListener() &&
        GetCurrentWidgetListener() != mAttachedWidgetListener) {
      GetCurrentWidgetListener()->WindowResized(this, mBounds.width, mBounds.height);
    }
    mAttachedWidgetListener->WindowResized(this, mBounds.width, mBounds.height);
  }
}
Example #2
0
void
CompositorD3D9::EnsureSize()
{
  LayoutDeviceIntRect rect;
  mWidget->GetClientBounds(rect);

  mSize = rect.Size();
}
Example #3
0
nsresult
PuppetWidget::ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
{
  for (uint32_t i = 0; i < aConfigurations.Length(); ++i) {
    const Configuration& configuration = aConfigurations[i];
    PuppetWidget* w = static_cast<PuppetWidget*>(configuration.mChild.get());
    NS_ASSERTION(w->GetParent() == this,
                 "Configured widget is not a child");
    w->SetWindowClipRegion(configuration.mClipRegion, true);
    LayoutDeviceIntRect bounds = w->GetBounds();
    if (bounds.Size() != configuration.mBounds.Size()) {
      w->Resize(configuration.mBounds.x, configuration.mBounds.y,
                configuration.mBounds.width, configuration.mBounds.height,
                true);
    } else if (bounds.TopLeft() != configuration.mBounds.TopLeft()) {
      w->Move(configuration.mBounds.x, configuration.mBounds.y);
    }
    w->SetWindowClipRegion(configuration.mClipRegion, false);
  }
  return NS_OK;
}
Example #4
0
void nsView::DoResetWidgetBounds(bool aMoveOnly,
                                 bool aInvalidateChangedSize) {
  // The geometry of a root view's widget is controlled externally,
  // NOT by sizing or positioning the view
  if (mViewManager->GetRootView() == this) {
    return;
  }

  NS_PRECONDITION(mWindow, "Why was this called??");

  // Hold this ref to make sure it stays alive.
  nsCOMPtr<nsIWidget> widget = mWindow;

  // Stash a copy of these and use them so we can handle this being deleted (say
  // from sync painting/flushing from Show/Move/Resize on the widget).
  LayoutDeviceIntRect newBounds;
  RefPtr<nsDeviceContext> dx = mViewManager->GetDeviceContext();

  nsWindowType type = widget->WindowType();

  LayoutDeviceIntRect curBounds;
  widget->GetClientBounds(curBounds);
  bool invisiblePopup = type == eWindowType_popup &&
                        ((curBounds.IsEmpty() && mDimBounds.IsEmpty()) ||
                         mVis == nsViewVisibility_kHide);

  if (invisiblePopup) {
    // We're going to hit the early exit below, avoid calling CalcWidgetBounds.
  } else {
    newBounds = LayoutDeviceIntRect::FromUnknownRect(CalcWidgetBounds(type));
  }

  bool curVisibility = widget->IsVisible();
  bool newVisibility = IsEffectivelyVisible();
  if (curVisibility && !newVisibility) {
    widget->Show(false);
  }

  if (invisiblePopup) {
    // Don't manipulate empty or hidden popup widgets. For example there's no
    // point moving hidden comboboxes around, or doing X server roundtrips
    // to compute their true screen position. This could mean that WidgetToScreen
    // operations on these widgets don't return up-to-date values, but popup
    // positions aren't reliable anyway because of correction to be on or off-screen.
    return;
  }

  bool changedPos = curBounds.TopLeft() != newBounds.TopLeft();
  bool changedSize = curBounds.Size() != newBounds.Size();

  // Child views are never attached to top level widgets, this is safe.

  // Coordinates are converted to display pixels for window Move/Resize APIs,
  // because of the potential for device-pixel coordinate spaces for mixed
  // hidpi/lodpi screens to overlap each other and result in bad placement
  // (bug 814434).
  double invScale;

  // Bug 861270: for correct widget manipulation at arbitrary scale factors,
  // prefer to base scaling on widget->GetDefaultScale(). But only do this if
  // it matches the view manager's device context scale after allowing for the
  // quantization to app units, because of OS X multiscreen issues (where the
  // only two scales are 1.0 or 2.0, and so the quantization doesn't actually
  // cause problems anyhow).
  // In the case of a mismatch, fall back to scaling based on the dev context's
  // AppUnitsPerDevPixelAtUnitFullZoom value. On platforms where the device-pixel
  // scale is uniform across all displays (currently all except OS X), we'll
  // always use the precise value from mWindow->GetDefaultScale here.
  CSSToLayoutDeviceScale scale = widget->GetDefaultScale();
  if (NSToIntRound(60.0 / scale.scale) == dx->AppUnitsPerDevPixelAtUnitFullZoom()) {
    invScale = 1.0 / scale.scale;
  } else {
    invScale = dx->AppUnitsPerDevPixelAtUnitFullZoom() / 60.0;
  }

  if (changedPos) {
    if (changedSize && !aMoveOnly) {
      widget->ResizeClient(newBounds.x * invScale,
                           newBounds.y * invScale,
                           newBounds.width * invScale,
                           newBounds.height * invScale,
                           aInvalidateChangedSize);
    } else {
      widget->MoveClient(newBounds.x * invScale,
                         newBounds.y * invScale);
    }
  } else {
    if (changedSize && !aMoveOnly) {
      widget->ResizeClient(newBounds.width * invScale,
                           newBounds.height * invScale,
                           aInvalidateChangedSize);
    } // else do nothing!
  }

  if (!curVisibility && newVisibility) {
    widget->Show(true);
  }
}
Example #5
0
LayoutDeviceIntRect nsView::CalcWidgetBounds(nsWindowType aType)
{
  int32_t p2a = mViewManager->AppUnitsPerDevPixel();

  nsRect viewBounds(mDimBounds);

  nsView* parent = GetParent();
  nsIWidget* parentWidget = nullptr;
  if (parent) {
    nsPoint offset;
    parentWidget = parent->GetNearestWidget(&offset, p2a);
    // make viewBounds be relative to the parent widget, in appunits
    viewBounds += offset;

    if (parentWidget && aType == eWindowType_popup &&
        IsEffectivelyVisible()) {
      // put offset into screen coordinates. (based on client area origin)
      LayoutDeviceIntPoint screenPoint = parentWidget->WidgetToScreenOffset();
      viewBounds += nsPoint(NSIntPixelsToAppUnits(screenPoint.x, p2a),
                            NSIntPixelsToAppUnits(screenPoint.y, p2a));
    }
  }

  // Compute widget bounds in device pixels
  LayoutDeviceIntRect newBounds =
    LayoutDeviceIntRect::FromUnknownRect(viewBounds.ToNearestPixels(p2a));

#if defined(XP_MACOSX) || (MOZ_WIDGET_GTK == 3)
  // cocoa and GTK round widget coordinates to the nearest global "display
  // pixel" integer value. So we avoid fractional display pixel values by
  // rounding to the nearest value that won't yield a fractional display pixel.
  nsIWidget* widget = parentWidget ? parentWidget : mWindow.get();
  uint32_t round;
  if (aType == eWindowType_popup && widget &&
      ((round = widget->RoundsWidgetCoordinatesTo()) > 1)) {
    LayoutDeviceIntSize pixelRoundedSize = newBounds.Size();
    // round the top left and bottom right to the nearest round pixel
    newBounds.x = NSToIntRoundUp(NSAppUnitsToDoublePixels(viewBounds.x, p2a) / round) * round;
    newBounds.y = NSToIntRoundUp(NSAppUnitsToDoublePixels(viewBounds.y, p2a) / round) * round;
    newBounds.width =
      NSToIntRoundUp(NSAppUnitsToDoublePixels(viewBounds.XMost(), p2a) / round) * round - newBounds.x;
    newBounds.height =
      NSToIntRoundUp(NSAppUnitsToDoublePixels(viewBounds.YMost(), p2a) / round) * round - newBounds.y;
    // but if that makes the widget larger then our frame may not paint the
    // extra pixels, so reduce the size to the nearest round value
    if (newBounds.width > pixelRoundedSize.width) {
      newBounds.width -= round;
    }
    if (newBounds.height > pixelRoundedSize.height) {
      newBounds.height -= round;
    }
  }
#endif

  // Compute where the top-left of our widget ended up relative to the parent
  // widget, in appunits.
  nsPoint roundedOffset(NSIntPixelsToAppUnits(newBounds.x, p2a),
                        NSIntPixelsToAppUnits(newBounds.y, p2a));

  // mViewToWidgetOffset is added to coordinates relative to the view origin
  // to get coordinates relative to the widget.
  // The view origin, relative to the parent widget, is at
  // (mPosX,mPosY) - mDimBounds.TopLeft() + viewBounds.TopLeft().
  // Our widget, relative to the parent widget, is roundedOffset.
  mViewToWidgetOffset = nsPoint(mPosX, mPosY)
    - mDimBounds.TopLeft() + viewBounds.TopLeft() - roundedOffset;

  return newBounds;
}
void nsView::DoResetWidgetBounds(bool aMoveOnly,
                                 bool aInvalidateChangedSize) {
  // The geometry of a root view's widget is controlled externally,
  // NOT by sizing or positioning the view
  if (mViewManager->GetRootView() == this) {
    return;
  }

  NS_PRECONDITION(mWindow, "Why was this called??");

  // Hold this ref to make sure it stays alive.
  nsCOMPtr<nsIWidget> widget = mWindow;

  // Stash a copy of these and use them so we can handle this being deleted (say
  // from sync painting/flushing from Show/Move/Resize on the widget).
  LayoutDeviceIntRect newBounds;
  RefPtr<nsDeviceContext> dx = mViewManager->GetDeviceContext();

  nsWindowType type = widget->WindowType();

  LayoutDeviceIntRect curBounds;
  widget->GetClientBounds(curBounds);
  bool invisiblePopup = type == eWindowType_popup &&
                        ((curBounds.IsEmpty() && mDimBounds.IsEmpty()) ||
                         mVis == nsViewVisibility_kHide);

  if (invisiblePopup) {
    // We're going to hit the early exit below, avoid calling CalcWidgetBounds.
  } else {
    newBounds = CalcWidgetBounds(type);
  }

  bool curVisibility = widget->IsVisible();
  bool newVisibility = IsEffectivelyVisible();
  if (curVisibility && !newVisibility) {
    widget->Show(false);
  }

  if (invisiblePopup) {
    // Don't manipulate empty or hidden popup widgets. For example there's no
    // point moving hidden comboboxes around, or doing X server roundtrips
    // to compute their true screen position. This could mean that WidgetToScreen
    // operations on these widgets don't return up-to-date values, but popup
    // positions aren't reliable anyway because of correction to be on or off-screen.
    return;
  }

  bool changedPos = curBounds.TopLeft() != newBounds.TopLeft();
  bool changedSize = curBounds.Size() != newBounds.Size();

  // Child views are never attached to top level widgets, this is safe.

  // Coordinates are converted to desktop pixels for window Move/Resize APIs,
  // because of the potential for device-pixel coordinate spaces for mixed
  // hidpi/lodpi screens to overlap each other and result in bad placement
  // (bug 814434).
  DesktopToLayoutDeviceScale scale = widget->GetDesktopToDeviceScale();

#ifdef XP_MACOSX
  // On OS X, this can be called before Cocoa has updated the backing scale
  // factor of our widget, in which case |scale| is wrong here. To work
  // around this, we check the device context and override |scale| if it
  // doesn't match. (This happens when a popup window that has previously
  // been created and hidden is being moved between hi- and lo-dpi screens,
  // but is not currently visible; Cocoa doesn't notify it of the scale
  // factor change until it gets shown on the new screen, which is too late
  // for us because we'll have already done the computations involving scale
  // here to move/size it.)
  // It might be better to avoid this by keeping calculations such as
  // CalcWidgetBounds entirely in appUnits, rather than using device pixels,
  // but that seems like a more extensive and potentially risky change.
  int32_t appPerDev = dx->AppUnitsPerDevPixelAtUnitFullZoom();
  if (NSToIntRound(60.0 / scale.scale) != appPerDev) {
    scale = DesktopToLayoutDeviceScale(60.0 / appPerDev);
  }
#endif

  DesktopRect deskRect = newBounds / scale;
  if (changedPos) {
    if (changedSize && !aMoveOnly) {
      widget->ResizeClient(deskRect.x, deskRect.y,
                           deskRect.width, deskRect.height,
                           aInvalidateChangedSize);
    } else {
      widget->MoveClient(deskRect.x, deskRect.y);
    }
  } else {
    if (changedSize && !aMoveOnly) {
      widget->ResizeClient(deskRect.width, deskRect.height,
                           aInvalidateChangedSize);
    } // else do nothing!
  }

  if (!curVisibility && newVisibility) {
    widget->Show(true);
  }
}