Mac: additional repaint fixes related to issue #360.

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@326 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2011-10-18 20:10:22 +00:00
parent 203ca27d27
commit 765e7b4c33

View File

@ -35,13 +35,13 @@ WebWidgetHost* WebWidgetHost::Create(NSView* parent_view,
PaintDelegate* paint_delegate) {
WebWidgetHost* host = new WebWidgetHost();
NSRect content_rect = [parent_view bounds];
host->view_ = [[NSView alloc] initWithFrame:content_rect];
NSRect client_rect = [parent_view bounds];
host->view_ = [[NSView alloc] initWithFrame:client_rect];
[parent_view addSubview:host->view_];
host->webwidget_ = WebPopupMenu::create(client);
host->webwidget_->resize(WebSize(content_rect.size.width,
content_rect.size.height));
host->webwidget_->resize(WebSize(NSWidth(client_rect),
NSHeight(client_rect)));
return host;
}
@ -50,20 +50,36 @@ void WebWidgetHost::DidInvalidateRect(const gfx::Rect& damaged_rect) {
DLOG_IF(WARNING, painting_) << "unexpected invalidation while painting";
#endif
const gfx::Rect client_rect(NSRectToCGRect([view_ bounds]));
paint_rect_ = paint_rect_.Union(damaged_rect);
paint_rect_ = paint_rect_.Intersect(client_rect);
// Convert scroll rectangle to the view's coordinate system.
NSRect r = NSRectFromCGRect(damaged_rect.ToCGRect());
r.origin.y = NSHeight([view_ frame]) - NSMaxY(r);
[view_ setNeedsDisplayInRect:r];
if (!paint_rect_.IsEmpty()) {
// Convert scroll rectangle to the view's coordinate system.
NSRect r = NSRectFromCGRect(damaged_rect.ToCGRect());
r.origin.y = NSHeight([view_ frame]) - NSMaxY(r);
[view_ setNeedsDisplayInRect:r];
}
}
void WebWidgetHost::DidScrollRect(int dx, int dy, const gfx::Rect& clip_rect) {
DCHECK(dx || dy);
const gfx::Rect client_rect(NSRectToCGRect([view_ bounds]));
const gfx::Rect rect = clip_rect.Intersect(client_rect);
gfx::Rect rect = clip_rect.Intersect(client_rect);
// The scrolling rect must not scroll outside the clip rect, because that will
// clobber the scrollbars; so the rectangle is shortened a bit from the
// leading side of the scroll (could be either horizontally or vertically).
if (dx > 0)
rect = gfx::Rect(rect.x(), rect.y(), rect.width() - dx, rect.height());
else if (dx < 0)
rect = gfx::Rect(rect.x() - dx, rect.y(), rect.width() + dx, rect.height());
else if (dy > 0)
rect = gfx::Rect(rect.x(), rect.y(), rect.width(), rect.height() - dy);
else if (dy < 0)
rect = gfx::Rect(rect.x(), rect.y() - dy, rect.width(), rect.height() + dy);
// Convert scroll rectangle to the view's coordinate system, and perform the
// scroll directly, without invalidating the view. In theory this could cause
// some kind of performance issue, since we're not coalescing redraw events,
@ -73,7 +89,9 @@ void WebWidgetHost::DidScrollRect(int dx, int dy, const gfx::Rect& clip_rect) {
r.origin.y = NSHeight([view_ bounds]) - NSMaxY(r);
[view_ scrollRect:r by:NSMakeSize(dx, -dy)];
const bool can_paint = [view_ lockFocusIfCanDraw];
const gfx::Rect saved_paint_rect = paint_rect_;
gfx::Rect dirty_rect_if_cannot_paint = paint_rect_;
// Repaint the rectangle that was revealed when scrolling the given rectangle.
// We don't want to invalidate the rectangle, because that would cause the
@ -89,21 +107,11 @@ void WebWidgetHost::DidScrollRect(int dx, int dy, const gfx::Rect& clip_rect) {
paint_rect_ = gfx::Rect(rect.x(), rect.y(), rect.width(), dy);
else if (dy < 0)
paint_rect_ = gfx::Rect(rect.x(), rect.bottom() + dy, rect.width(), -dy);
Paint();
// Also make sure we repaint the area that the rectangle was pushed over. This
// is required to make sure we don't clobber the scrollbar on that side of the
// view. Also do the repaint immediately here, so that we don't get into the
// L-shaped issue described above.
if (dx > 0)
paint_rect_ = gfx::Rect(rect.right(), rect.y(), dx, rect.height());
else if (dx < 0)
paint_rect_ = gfx::Rect(rect.x() + dx, rect.y(), -dx, rect.height());
else if (dy > 0)
paint_rect_ = gfx::Rect(rect.x(), rect.bottom(), rect.width(), dx);
else if (dy < 0)
paint_rect_ = gfx::Rect(rect.x(), rect.y() + dy, rect.width(), -dx);
Paint();
paint_rect_ = paint_rect_.Intersect(client_rect);
dirty_rect_if_cannot_paint = dirty_rect_if_cannot_paint.Union(paint_rect_);
if (can_paint && !paint_rect_.IsEmpty())
Paint();
// If any part of the scrolled rect was marked as dirty, make sure to redraw
// it in the new scrolled-to location. Otherwise we can end up with artifacts
@ -112,10 +120,18 @@ void WebWidgetHost::DidScrollRect(int dx, int dy, const gfx::Rect& clip_rect) {
if (!moved_paint_rect.IsEmpty()) {
moved_paint_rect.Offset(dx, dy);
paint_rect_ = moved_paint_rect;
Paint();
paint_rect_ = paint_rect_.Intersect(client_rect);
dirty_rect_if_cannot_paint = dirty_rect_if_cannot_paint.Union(paint_rect_);
if (can_paint && !paint_rect_.IsEmpty())
Paint();
}
paint_rect_ = saved_paint_rect;
if (can_paint)
[view_ unlockFocus];
else
DidInvalidateRect(dirty_rect_if_cannot_paint);
}
void WebWidgetHost::ScheduleComposite() {
@ -207,16 +223,12 @@ void WebWidgetHost::Paint() {
[NSGraphicsContext restoreGraphicsState];
// Paint to the screen
if ([view_ lockFocusIfCanDraw]) {
NSGraphicsContext* view_context = [NSGraphicsContext currentContext];
CGContextRef context =
static_cast<CGContextRef>([view_context graphicsPort]);
CGRect bitmap_rect = { { update_rect.x(), update_rect.y() },
{ update_rect.width(), update_rect.height() } };
skia::DrawToNativeContext(canvas_.get(), context, update_rect.x(),
client_rect.height() - update_rect.bottom(), &bitmap_rect);
[view_ unlockFocus];
}
NSGraphicsContext* view_context = [NSGraphicsContext currentContext];
CGContextRef context = static_cast<CGContextRef>([view_context graphicsPort]);
CGRect bitmap_rect = { { update_rect.x(), update_rect.y() },
{ update_rect.width(), update_rect.height() } };
skia::DrawToNativeContext(canvas_.get(), context, update_rect.x(),
client_rect.height() - update_rect.bottom(), &bitmap_rect);
}
void WebWidgetHost::SetTooltipText(const CefString& tooltip_text)