| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/renderer/render_widget.h" | 5 #include "chrome/renderer/render_widget.h" |
| 6 | 6 |
| 7 #include "app/surface/transport_dib.h" | 7 #include "app/surface/transport_dib.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 needs_repainting_on_restore_(false), | 70 needs_repainting_on_restore_(false), |
| 71 has_focus_(false), | 71 has_focus_(false), |
| 72 handling_input_event_(false), | 72 handling_input_event_(false), |
| 73 closing_(false), | 73 closing_(false), |
| 74 input_method_is_active_(false), | 74 input_method_is_active_(false), |
| 75 text_input_type_(WebKit::WebTextInputTypeNone), | 75 text_input_type_(WebKit::WebTextInputTypeNone), |
| 76 popup_type_(popup_type), | 76 popup_type_(popup_type), |
| 77 pending_window_rect_count_(0), | 77 pending_window_rect_count_(0), |
| 78 suppress_next_char_events_(false), | 78 suppress_next_char_events_(false), |
| 79 is_accelerated_compositing_active_(false), | 79 is_accelerated_compositing_active_(false), |
| 80 animation_update_pending_(false) { | 80 animation_update_pending_(false), |
| 81 animation_waiting_for_paint_(false) { |
| 81 RenderProcess::current()->AddRefProcess(); | 82 RenderProcess::current()->AddRefProcess(); |
| 82 DCHECK(render_thread_); | 83 DCHECK(render_thread_); |
| 83 } | 84 } |
| 84 | 85 |
| 85 RenderWidget::~RenderWidget() { | 86 RenderWidget::~RenderWidget() { |
| 86 DCHECK(!webwidget_) << "Leaking our WebWidget!"; | 87 DCHECK(!webwidget_) << "Leaking our WebWidget!"; |
| 87 if (current_paint_buf_) { | 88 if (current_paint_buf_) { |
| 88 RenderProcess::current()->ReleaseTransportDIB(current_paint_buf_); | 89 RenderProcess::current()->ReleaseTransportDIB(current_paint_buf_); |
| 89 current_paint_buf_ = NULL; | 90 current_paint_buf_ = NULL; |
| 90 } | 91 } |
| (...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 481 } | 482 } |
| 482 | 483 |
| 483 void RenderWidget::CallDoDeferredUpdate() { | 484 void RenderWidget::CallDoDeferredUpdate() { |
| 484 DoDeferredUpdate(); | 485 DoDeferredUpdate(); |
| 485 | 486 |
| 486 if (pending_input_event_ack_.get()) | 487 if (pending_input_event_ack_.get()) |
| 487 Send(pending_input_event_ack_.release()); | 488 Send(pending_input_event_ack_.release()); |
| 488 } | 489 } |
| 489 | 490 |
| 490 void RenderWidget::UpdateAnimationsIfNeeded() { | 491 void RenderWidget::UpdateAnimationsIfNeeded() { |
| 491 if (!is_hidden() && animation_update_pending_) { | 492 if (webwidget_ && !is_hidden() && animation_update_pending_ && |
| 493 !animation_waiting_for_paint_) { |
| 492 base::Time now = base::Time::Now(); | 494 base::Time now = base::Time::Now(); |
| 493 if (now >= animation_floor_time_) { | 495 if (now >= animation_floor_time_) { |
| 494 animation_update_pending_ = false; | 496 UpdateAnimationsAndFloorTime(); |
| 495 webwidget_->animate(); | 497 // If updating the animation caused invalidations, make sure that we paint |
| 498 // at least once before we call animate() again. |
| 499 // Update layout first as that might cause further invalidations. |
| 500 webwidget_->layout(); |
| 501 if (paint_aggregator_.HasPendingUpdate()) |
| 502 animation_waiting_for_paint_ = true; |
| 496 } else { | 503 } else { |
| 497 // This code uses base::Time::Now() to calculate the floor and next fire | 504 // This code uses base::Time::Now() to calculate the floor and next fire |
| 498 // time because javascript's Date object uses base::Time::Now(). The | 505 // time because javascript's Date object uses base::Time::Now(). The |
| 499 // message loop uses base::TimeTicks, which on windows can have a | 506 // message loop uses base::TimeTicks, which on windows can have a |
| 500 // different granularity than base::Time. | 507 // different granularity than base::Time. |
| 501 // The upshot of all this is that this function might be called before | 508 // The upshot of all this is that this function might be called before |
| 502 // base::Time::Now() has advanced past the animation_floor_time_. To | 509 // base::Time::Now() has advanced past the animation_floor_time_. To |
| 503 // avoid exposing this delay to javascript, we keep posting delayed | 510 // avoid exposing this delay to javascript, we keep posting delayed |
| 504 // tasks until we observe base::Time::Now() advancing far enough. | 511 // tasks until base::Time::Now() has advanced far enough. |
| 505 int64 delay = (animation_floor_time_ - now).InMillisecondsRoundedUp(); | 512 int64 delay = (animation_floor_time_ - now).InMillisecondsRoundedUp(); |
| 506 MessageLoop::current()->PostDelayedTask(FROM_HERE, NewRunnableMethod( | 513 MessageLoop::current()->PostDelayedTask(FROM_HERE, NewRunnableMethod( |
| 507 this, &RenderWidget::UpdateAnimationsIfNeeded), delay); | 514 this, &RenderWidget::UpdateAnimationsIfNeeded), delay); |
| 508 } | 515 } |
| 509 } | 516 } |
| 510 } | 517 } |
| 511 | 518 |
| 519 void RenderWidget::UpdateAnimationsAndFloorTime() { |
| 520 animation_update_pending_ = false; |
| 521 animation_floor_time_ = |
| 522 base::Time::Now() + base::TimeDelta::FromMilliseconds(16); |
| 523 webwidget_->animate(); |
| 524 } |
| 525 |
| 512 void RenderWidget::DoDeferredUpdate() { | 526 void RenderWidget::DoDeferredUpdate() { |
| 513 if (!webwidget_ || update_reply_pending()) | 527 if (!webwidget_ || update_reply_pending()) |
| 514 return; | 528 return; |
| 515 | 529 |
| 516 // Suppress updating when we are hidden. | 530 // Suppress updating when we are hidden. |
| 517 if (is_hidden_ || size_.IsEmpty()) { | 531 if (is_hidden_ || size_.IsEmpty()) { |
| 518 paint_aggregator_.ClearPendingUpdate(); | 532 paint_aggregator_.ClearPendingUpdate(); |
| 519 needs_repainting_on_restore_ = true; | 533 needs_repainting_on_restore_ = true; |
| 520 return; | 534 return; |
| 521 } | 535 } |
| 522 | 536 |
| 523 if (base::Time::Now() > animation_floor_time_) | 537 if (animation_update_pending_) { |
| 524 UpdateAnimationsIfNeeded(); | 538 if (animation_waiting_for_paint_) { |
| 539 // If we have pending animation updates but need to paint before updating |
| 540 // them, post a task to UpdateAnimationsIfNeeded that will either update |
| 541 // animations directly (if the animation floor time has passed by the time |
| 542 // the function runs) or post a delayed task if the floor time is not yet |
| 543 // reached. |
| 544 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( |
| 545 this, &RenderWidget::UpdateAnimationsIfNeeded)); |
| 546 } else if (base::Time::Now() > animation_floor_time_) { |
| 547 // Otherwise, if it's time to update the animations go ahead. |
| 548 UpdateAnimationsAndFloorTime(); |
| 549 } |
| 550 } |
| 551 animation_waiting_for_paint_ = false; |
| 525 | 552 |
| 526 // Layout may generate more invalidation. It may also enable the | 553 // Layout may generate more invalidation. It may also enable the |
| 527 // GPU acceleration, so make sure to run layout before we send the | 554 // GPU acceleration, so make sure to run layout before we send the |
| 528 // GpuRenderingActivated message. | 555 // GpuRenderingActivated message. |
| 529 webwidget_->layout(); | 556 webwidget_->layout(); |
| 530 | 557 |
| 531 // Suppress painting if nothing is dirty. This has to be done after updating | 558 // Suppress painting if nothing is dirty. This has to be done after updating |
| 532 // animations running layout as these may generate further invalidations. | 559 // animations running layout as these may generate further invalidations. |
| 533 if (!paint_aggregator_.HasPendingUpdate()) | 560 if (!paint_aggregator_.HasPendingUpdate()) |
| 534 return; | 561 return; |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 708 // TODO(nduca): replace with something a little less hacky. The reason this | 735 // TODO(nduca): replace with something a little less hacky. The reason this |
| 709 // hack is still used is because the Invalidate-DoDeferredUpdate loop | 736 // hack is still used is because the Invalidate-DoDeferredUpdate loop |
| 710 // contains a lot of host-renderer synchronization logic that is still | 737 // contains a lot of host-renderer synchronization logic that is still |
| 711 // important for the accelerated compositing case. The option of simply | 738 // important for the accelerated compositing case. The option of simply |
| 712 // duplicating all that code is less desirable than "faking out" the | 739 // duplicating all that code is less desirable than "faking out" the |
| 713 // invalidation path using a magical damage rect. | 740 // invalidation path using a magical damage rect. |
| 714 didInvalidateRect(WebRect(0, 0, 1, 1)); | 741 didInvalidateRect(WebRect(0, 0, 1, 1)); |
| 715 } | 742 } |
| 716 | 743 |
| 717 void RenderWidget::scheduleAnimation() { | 744 void RenderWidget::scheduleAnimation() { |
| 718 if (!animation_update_pending_) { | 745 if (!animation_update_pending_) { |
| 719 animation_update_pending_ = true; | 746 animation_update_pending_ = true; |
| 720 animation_floor_time_ = | 747 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( |
| 721 base::Time::Now() + base::TimeDelta::FromMilliseconds(10); | 748 this, &RenderWidget::UpdateAnimationsIfNeeded)); |
| 722 MessageLoop::current()->PostDelayedTask(FROM_HERE, NewRunnableMethod( | 749 } |
| 723 this, &RenderWidget::UpdateAnimationsIfNeeded), 10); | |
| 724 } | |
| 725 } | 750 } |
| 726 | 751 |
| 727 void RenderWidget::didChangeCursor(const WebCursorInfo& cursor_info) { | 752 void RenderWidget::didChangeCursor(const WebCursorInfo& cursor_info) { |
| 728 // TODO(darin): Eliminate this temporary. | 753 // TODO(darin): Eliminate this temporary. |
| 729 WebCursor cursor(cursor_info); | 754 WebCursor cursor(cursor_info); |
| 730 | 755 |
| 731 // Only send a SetCursor message if we need to make a change. | 756 // Only send a SetCursor message if we need to make a change. |
| 732 if (!current_cursor_.IsEqual(cursor)) { | 757 if (!current_cursor_.IsEqual(cursor)) { |
| 733 current_cursor_ = cursor; | 758 current_cursor_ = cursor; |
| 734 Send(new ViewHostMsg_SetCursor(routing_id_, cursor)); | 759 Send(new ViewHostMsg_SetCursor(routing_id_, cursor)); |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1069 | 1094 |
| 1070 void RenderWidget::CleanupWindowInPluginMoves(gfx::PluginWindowHandle window) { | 1095 void RenderWidget::CleanupWindowInPluginMoves(gfx::PluginWindowHandle window) { |
| 1071 for (WebPluginGeometryVector::iterator i = plugin_window_moves_.begin(); | 1096 for (WebPluginGeometryVector::iterator i = plugin_window_moves_.begin(); |
| 1072 i != plugin_window_moves_.end(); ++i) { | 1097 i != plugin_window_moves_.end(); ++i) { |
| 1073 if (i->window == window) { | 1098 if (i->window == window) { |
| 1074 plugin_window_moves_.erase(i); | 1099 plugin_window_moves_.erase(i); |
| 1075 break; | 1100 break; |
| 1076 } | 1101 } |
| 1077 } | 1102 } |
| 1078 } | 1103 } |
| OLD | NEW |