blob: 03beb8f7756aa483fb3bdb1e648cd153dc424682 [file] [log] [blame]
[email protected]05d478752009-04-08 23:38:161// Copyright (c) 2009 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
5#include "chrome/renderer/render_widget.h"
6
[email protected]4fb66842009-12-04 21:41:007#include "base/command_line.h"
initial.commit09911bf2008-07-26 23:55:298#include "base/gfx/point.h"
9#include "base/gfx/size.h"
10#include "base/logging.h"
11#include "base/message_loop.h"
initial.commit09911bf2008-07-26 23:55:2912#include "base/scoped_ptr.h"
[email protected]661eb9d2009-02-03 02:11:4813#include "build/build_config.h"
[email protected]4fb66842009-12-04 21:41:0014#include "chrome/common/chrome_switches.h"
[email protected]674741932009-02-04 23:44:4615#include "chrome/common/render_messages.h"
[email protected]e68e62fa2009-02-20 02:00:0416#include "chrome/common/transport_dib.h"
[email protected]8085dbc82008-09-26 22:53:4417#include "chrome/renderer/render_process.h"
[email protected]661eb9d2009-02-03 02:11:4818#include "skia/ext/platform_canvas.h"
[email protected]d5282e72009-05-13 13:16:5219#include "third_party/skia/include/core/SkShader.h"
[email protected]418ed5ab2009-11-12 01:14:4920#include "third_party/WebKit/WebKit/chromium/public/WebCursorInfo.h"
21#include "third_party/WebKit/WebKit/chromium/public/WebPopupMenu.h"
22#include "third_party/WebKit/WebKit/chromium/public/WebPopupMenuInfo.h"
23#include "third_party/WebKit/WebKit/chromium/public/WebRect.h"
24#include "third_party/WebKit/WebKit/chromium/public/WebScreenInfo.h"
25#include "third_party/WebKit/WebKit/chromium/public/WebSize.h"
[email protected]8c89e7792009-08-19 21:18:3426#include "webkit/glue/webkit_glue.h"
[email protected]661eb9d2009-02-03 02:11:4827
28#if defined(OS_POSIX)
[email protected]d5282e72009-05-13 13:16:5229#include "third_party/skia/include/core/SkPixelRef.h"
30#include "third_party/skia/include/core/SkMallocPixelRef.h"
[email protected]661eb9d2009-02-03 02:11:4831#endif // defined(OS_POSIX)
[email protected]8085dbc82008-09-26 22:53:4432
[email protected]418ed5ab2009-11-12 01:14:4933#include "third_party/WebKit/WebKit/chromium/public/WebWidget.h"
initial.commit09911bf2008-07-26 23:55:2934
[email protected]4873c7d2009-07-16 06:36:2835using WebKit::WebCompositionCommand;
[email protected]7c51b0ee2009-07-08 21:49:3036using WebKit::WebCursorInfo;
[email protected]62cb33cae2009-03-27 23:30:2237using WebKit::WebInputEvent;
[email protected]4873c7d2009-07-16 06:36:2838using WebKit::WebNavigationPolicy;
39using WebKit::WebPopupMenu;
[email protected]88efb7ec2009-07-14 16:32:5940using WebKit::WebPopupMenuInfo;
[email protected]b3f2b912009-04-09 16:18:5241using WebKit::WebRect;
[email protected]12456fa2009-04-01 23:07:1942using WebKit::WebScreenInfo;
[email protected]b3f2b912009-04-09 16:18:5243using WebKit::WebSize;
[email protected]4873c7d2009-07-16 06:36:2844using WebKit::WebTextDirection;
[email protected]62cb33cae2009-03-27 23:30:2245
[email protected]cfd727f2009-01-09 20:21:1146RenderWidget::RenderWidget(RenderThreadBase* render_thread, bool activatable)
initial.commit09911bf2008-07-26 23:55:2947 : routing_id_(MSG_ROUTING_NONE),
[email protected]c5b3b5e2009-02-13 06:41:1148 webwidget_(NULL),
initial.commit09911bf2008-07-26 23:55:2949 opener_id_(MSG_ROUTING_NONE),
[email protected]8085dbc82008-09-26 22:53:4450 render_thread_(render_thread),
[email protected]659f73f2009-10-13 13:43:4251 host_window_(0),
initial.commit09911bf2008-07-26 23:55:2952 current_paint_buf_(NULL),
initial.commit09911bf2008-07-26 23:55:2953 next_paint_flags_(0),
[email protected]53d3f302009-12-21 04:42:0554 update_reply_pending_(false),
initial.commit09911bf2008-07-26 23:55:2955 did_show_(false),
initial.commit09911bf2008-07-26 23:55:2956 is_hidden_(false),
57 needs_repainting_on_restore_(false),
58 has_focus_(false),
[email protected]5dd768212009-08-13 23:34:4959 handling_input_event_(false),
[email protected]661eb9d2009-02-03 02:11:4860 closing_(false),
initial.commit09911bf2008-07-26 23:55:2961 ime_is_active_(false),
62 ime_control_enable_ime_(true),
63 ime_control_x_(-1),
64 ime_control_y_(-1),
65 ime_control_new_state_(false),
[email protected]0ebf3872008-11-07 21:35:0366 ime_control_updated_(false),
[email protected]9f23f592008-11-17 08:36:3467 ime_control_busy_(false),
[email protected]2533ce12009-05-09 00:02:2468 activatable_(activatable),
[email protected]867125a02009-12-10 06:01:4869 pending_window_rect_count_(0),
70 suppress_next_char_events_(false) {
[email protected]8930d472009-02-21 08:05:2871 RenderProcess::current()->AddRefProcess();
[email protected]8085dbc82008-09-26 22:53:4472 DCHECK(render_thread_);
initial.commit09911bf2008-07-26 23:55:2973}
74
75RenderWidget::~RenderWidget() {
[email protected]c5b3b5e2009-02-13 06:41:1176 DCHECK(!webwidget_) << "Leaking our WebWidget!";
initial.commit09911bf2008-07-26 23:55:2977 if (current_paint_buf_) {
[email protected]8930d472009-02-21 08:05:2878 RenderProcess::current()->ReleaseTransportDIB(current_paint_buf_);
initial.commit09911bf2008-07-26 23:55:2979 current_paint_buf_ = NULL;
80 }
[email protected]8930d472009-02-21 08:05:2881 RenderProcess::current()->ReleaseProcess();
initial.commit09911bf2008-07-26 23:55:2982}
83
84/*static*/
[email protected]8085dbc82008-09-26 22:53:4485RenderWidget* RenderWidget::Create(int32 opener_id,
[email protected]0ebf3872008-11-07 21:35:0386 RenderThreadBase* render_thread,
[email protected]cfd727f2009-01-09 20:21:1187 bool activatable) {
initial.commit09911bf2008-07-26 23:55:2988 DCHECK(opener_id != MSG_ROUTING_NONE);
[email protected]0ebf3872008-11-07 21:35:0389 scoped_refptr<RenderWidget> widget = new RenderWidget(render_thread,
[email protected]cfd727f2009-01-09 20:21:1190 activatable);
initial.commit09911bf2008-07-26 23:55:2991 widget->Init(opener_id); // adds reference
92 return widget;
93}
94
[email protected]88efb7ec2009-07-14 16:32:5995void RenderWidget::ConfigureAsExternalPopupMenu(const WebPopupMenuInfo& info) {
96 popup_params_.reset(new ViewHostMsg_ShowPopup_Params);
97 popup_params_->item_height = info.itemHeight;
98 popup_params_->selected_item = info.selectedIndex;
99 for (size_t i = 0; i < info.items.size(); ++i)
100 popup_params_->popup_items.push_back(WebMenuItem(info.items[i]));
101}
102
initial.commit09911bf2008-07-26 23:55:29103void RenderWidget::Init(int32 opener_id) {
104 DCHECK(!webwidget_);
105
106 if (opener_id != MSG_ROUTING_NONE)
107 opener_id_ = opener_id;
108
[email protected]4873c7d2009-07-16 06:36:28109 webwidget_ = WebPopupMenu::create(this);
initial.commit09911bf2008-07-26 23:55:29110
[email protected]8085dbc82008-09-26 22:53:44111 bool result = render_thread_->Send(
[email protected]cfd727f2009-01-09 20:21:11112 new ViewHostMsg_CreateWidget(opener_id, activatable_, &routing_id_));
initial.commit09911bf2008-07-26 23:55:29113 if (result) {
[email protected]8085dbc82008-09-26 22:53:44114 render_thread_->AddRoute(routing_id_, this);
initial.commit09911bf2008-07-26 23:55:29115 // Take a reference on behalf of the RenderThread. This will be balanced
116 // when we receive ViewMsg_Close.
117 AddRef();
118 } else {
119 DCHECK(false);
120 }
121}
122
123// This is used to complete pending inits and non-pending inits. For non-
124// pending cases, the parent will be the same as the current parent. This
125// indicates we do not need to reparent or anything.
[email protected]18bcc3c2009-01-27 21:39:15126void RenderWidget::CompleteInit(gfx::NativeViewId parent_hwnd) {
initial.commit09911bf2008-07-26 23:55:29127 DCHECK(routing_id_ != MSG_ROUTING_NONE);
initial.commit09911bf2008-07-26 23:55:29128
129 host_window_ = parent_hwnd;
130
[email protected]6de74452009-02-25 18:04:59131 Send(new ViewHostMsg_RenderViewReady(routing_id_));
initial.commit09911bf2008-07-26 23:55:29132}
133
134IPC_DEFINE_MESSAGE_MAP(RenderWidget)
135 IPC_MESSAGE_HANDLER(ViewMsg_Close, OnClose)
136 IPC_MESSAGE_HANDLER(ViewMsg_CreatingNew_ACK, OnCreatingNewAck)
137 IPC_MESSAGE_HANDLER(ViewMsg_Resize, OnResize)
138 IPC_MESSAGE_HANDLER(ViewMsg_WasHidden, OnWasHidden)
139 IPC_MESSAGE_HANDLER(ViewMsg_WasRestored, OnWasRestored)
[email protected]53d3f302009-12-21 04:42:05140 IPC_MESSAGE_HANDLER(ViewMsg_UpdateRect_ACK, OnUpdateRectAck)
initial.commit09911bf2008-07-26 23:55:29141 IPC_MESSAGE_HANDLER(ViewMsg_HandleInputEvent, OnHandleInputEvent)
142 IPC_MESSAGE_HANDLER(ViewMsg_MouseCaptureLost, OnMouseCaptureLost)
143 IPC_MESSAGE_HANDLER(ViewMsg_SetFocus, OnSetFocus)
144 IPC_MESSAGE_HANDLER(ViewMsg_ImeSetInputMode, OnImeSetInputMode)
145 IPC_MESSAGE_HANDLER(ViewMsg_ImeSetComposition, OnImeSetComposition)
[email protected]ec7dc112008-08-06 05:30:12146 IPC_MESSAGE_HANDLER(ViewMsg_Repaint, OnMsgRepaint)
[email protected]07f953332009-03-25 04:31:11147 IPC_MESSAGE_HANDLER(ViewMsg_SetTextDirection, OnSetTextDirection)
[email protected]2533ce12009-05-09 00:02:24148 IPC_MESSAGE_HANDLER(ViewMsg_Move_ACK, OnRequestMoveAck)
initial.commit09911bf2008-07-26 23:55:29149 IPC_MESSAGE_UNHANDLED_ERROR()
150IPC_END_MESSAGE_MAP()
151
152bool RenderWidget::Send(IPC::Message* message) {
153 // Don't send any messages after the browser has told us to close.
154 if (closing_) {
155 delete message;
156 return false;
157 }
158
159 // If given a messsage without a routing ID, then assign our routing ID.
160 if (message->routing_id() == MSG_ROUTING_NONE)
161 message->set_routing_id(routing_id_);
162
[email protected]d3fc25652009-02-24 22:31:25163 return render_thread_->Send(message);
[email protected]8085dbc82008-09-26 22:53:44164}
165
initial.commit09911bf2008-07-26 23:55:29166// Got a response from the browser after the renderer decided to create a new
167// view.
[email protected]18bcc3c2009-01-27 21:39:15168void RenderWidget::OnCreatingNewAck(gfx::NativeViewId parent) {
initial.commit09911bf2008-07-26 23:55:29169 DCHECK(routing_id_ != MSG_ROUTING_NONE);
170
171 CompleteInit(parent);
172}
173
174void RenderWidget::OnClose() {
175 if (closing_)
176 return;
177 closing_ = true;
178
179 // Browser correspondence is no longer needed at this point.
[email protected]bee16aab2009-08-26 15:55:03180 if (routing_id_ != MSG_ROUTING_NONE) {
[email protected]8085dbc82008-09-26 22:53:44181 render_thread_->RemoveRoute(routing_id_);
[email protected]bee16aab2009-08-26 15:55:03182 SetHidden(false);
183 }
initial.commit09911bf2008-07-26 23:55:29184
initial.commit09911bf2008-07-26 23:55:29185 // If there is a Send call on the stack, then it could be dangerous to close
[email protected]d3fc25652009-02-24 22:31:25186 // now. Post a task that only gets invoked when there are no nested message
187 // loops.
188 MessageLoop::current()->PostNonNestableTask(FROM_HERE,
189 NewRunnableMethod(this, &RenderWidget::Close));
190
191 // Balances the AddRef taken when we called AddRoute.
192 Release();
initial.commit09911bf2008-07-26 23:55:29193}
194
[email protected]f21c613a2009-02-12 14:46:17195void RenderWidget::OnResize(const gfx::Size& new_size,
196 const gfx::Rect& resizer_rect) {
initial.commit09911bf2008-07-26 23:55:29197 // During shutdown we can just ignore this message.
198 if (!webwidget_)
199 return;
200
[email protected]f21c613a2009-02-12 14:46:17201 // Remember the rect where the resize corner will be drawn.
202 resizer_rect_ = resizer_rect;
203
initial.commit09911bf2008-07-26 23:55:29204 // TODO(darin): We should not need to reset this here.
[email protected]bee16aab2009-08-26 15:55:03205 SetHidden(false);
initial.commit09911bf2008-07-26 23:55:29206 needs_repainting_on_restore_ = false;
207
208 // We shouldn't be asked to resize to our current size.
209 DCHECK(size_ != new_size);
210 size_ = new_size;
211
212 // We should not be sent a Resize message if we have not ACK'd the previous
213 DCHECK(!next_paint_is_resize_ack());
214
[email protected]552e6002009-11-19 05:24:57215 paint_aggregator_.ClearPendingUpdate();
216
initial.commit09911bf2008-07-26 23:55:29217 // When resizing, we want to wait to paint before ACK'ing the resize. This
218 // ensures that we only resize as fast as we can paint. We only need to send
219 // an ACK if we are resized to a non-empty rect.
[email protected]4873c7d2009-07-16 06:36:28220 webwidget_->resize(new_size);
initial.commit09911bf2008-07-26 23:55:29221 if (!new_size.IsEmpty()) {
[email protected]552e6002009-11-19 05:24:57222 // Resize should have caused an invalidation of the entire view.
223 DCHECK(paint_aggregator_.HasPendingUpdate());
[email protected]2d5d09d52009-06-15 14:29:21224
initial.commit09911bf2008-07-26 23:55:29225 // We will send the Resize_ACK flag once we paint again.
226 set_next_paint_is_resize_ack();
227 }
228}
229
230void RenderWidget::OnWasHidden() {
231 // Go into a mode where we stop generating paint and scrolling events.
[email protected]bee16aab2009-08-26 15:55:03232 SetHidden(true);
initial.commit09911bf2008-07-26 23:55:29233}
234
235void RenderWidget::OnWasRestored(bool needs_repainting) {
236 // During shutdown we can just ignore this message.
237 if (!webwidget_)
238 return;
239
240 // See OnWasHidden
[email protected]bee16aab2009-08-26 15:55:03241 SetHidden(false);
initial.commit09911bf2008-07-26 23:55:29242
243 if (!needs_repainting && !needs_repainting_on_restore_)
244 return;
245 needs_repainting_on_restore_ = false;
246
[email protected]4fb66842009-12-04 21:41:00247 // Tag the next paint as a restore ack, which is picked up by DoDeferredUpdate
initial.commit09911bf2008-07-26 23:55:29248 // when it sends out the next PaintRect message.
249 set_next_paint_is_restore_ack();
250
251 // Generate a full repaint.
[email protected]4873c7d2009-07-16 06:36:28252 didInvalidateRect(gfx::Rect(size_.width(), size_.height()));
initial.commit09911bf2008-07-26 23:55:29253}
254
[email protected]53d3f302009-12-21 04:42:05255void RenderWidget::OnRequestMoveAck() {
256 DCHECK(pending_window_rect_count_);
257 pending_window_rect_count_--;
258}
259
260void RenderWidget::OnUpdateRectAck() {
261 DCHECK(update_reply_pending());
262 update_reply_pending_ = false;
263
264 // If we sent an UpdateRect message with a zero-sized bitmap, then we should
265 // have no current update buf.
[email protected]b7fce1f2008-08-14 05:01:07266 if (current_paint_buf_) {
[email protected]8930d472009-02-21 08:05:28267 RenderProcess::current()->ReleaseTransportDIB(current_paint_buf_);
[email protected]b7fce1f2008-08-14 05:01:07268 current_paint_buf_ = NULL;
initial.commit09911bf2008-07-26 23:55:29269 }
[email protected]e68e62fa2009-02-20 02:00:04270
[email protected]a2f6bc112009-06-27 16:27:25271 // Notify subclasses
272 DidPaint();
273
initial.commit09911bf2008-07-26 23:55:29274 // Continue painting if necessary...
[email protected]552e6002009-11-19 05:24:57275 CallDoDeferredUpdate();
initial.commit09911bf2008-07-26 23:55:29276}
277
initial.commit09911bf2008-07-26 23:55:29278void RenderWidget::OnHandleInputEvent(const IPC::Message& message) {
279 void* iter = NULL;
280
281 const char* data;
282 int data_length;
[email protected]5dd768212009-08-13 23:34:49283 handling_input_event_ = true;
284 if (!message.ReadData(&iter, &data, &data_length)) {
285 handling_input_event_ = false;
initial.commit09911bf2008-07-26 23:55:29286 return;
[email protected]5dd768212009-08-13 23:34:49287 }
initial.commit09911bf2008-07-26 23:55:29288
289 const WebInputEvent* input_event =
290 reinterpret_cast<const WebInputEvent*>(data);
[email protected]867125a02009-12-10 06:01:48291
292 bool is_keyboard_shortcut = false;
293 // is_keyboard_shortcut flag is only available for RawKeyDown events.
294 if (input_event->type == WebInputEvent::RawKeyDown)
295 message.ReadBool(&iter, &is_keyboard_shortcut);
296
initial.commit09911bf2008-07-26 23:55:29297 bool processed = false;
[email protected]867125a02009-12-10 06:01:48298 if (input_event->type != WebInputEvent::Char || !suppress_next_char_events_) {
299 suppress_next_char_events_ = false;
300 if (webwidget_)
301 processed = webwidget_->handleInputEvent(*input_event);
302 }
303
304 // If this RawKeyDown event corresponds to a browser keyboard shortcut and
305 // it's not processed by webkit, then we need to suppress the upcoming Char
306 // events.
307 if (!processed && is_keyboard_shortcut)
308 suppress_next_char_events_ = true;
initial.commit09911bf2008-07-26 23:55:29309
310 IPC::Message* response = new ViewHostMsg_HandleInputEvent_ACK(routing_id_);
311 response->WriteInt(input_event->type);
[email protected]e2824412009-02-27 01:57:05312 response->WriteBool(processed);
313
[email protected]12fbad812009-09-01 18:21:24314 if (input_event->type == WebInputEvent::MouseMove &&
[email protected]552e6002009-11-19 05:24:57315 paint_aggregator_.HasPendingUpdate()) {
[email protected]12fbad812009-09-01 18:21:24316 // We want to rate limit the input events in this case, so we'll wait for
317 // painting to finish before ACKing this message.
318 pending_input_event_ack_.reset(response);
319 } else {
320 Send(response);
321 }
322
[email protected]5dd768212009-08-13 23:34:49323 handling_input_event_ = false;
[email protected]446705872009-09-10 07:22:48324
[email protected]867125a02009-12-10 06:01:48325 if (WebInputEvent::isKeyboardEventType(input_event->type))
[email protected]446705872009-09-10 07:22:48326 DidHandleKeyEvent();
initial.commit09911bf2008-07-26 23:55:29327}
328
329void RenderWidget::OnMouseCaptureLost() {
330 if (webwidget_)
[email protected]4873c7d2009-07-16 06:36:28331 webwidget_->mouseCaptureLost();
initial.commit09911bf2008-07-26 23:55:29332}
333
334void RenderWidget::OnSetFocus(bool enable) {
335 has_focus_ = enable;
336 if (webwidget_)
[email protected]4873c7d2009-07-16 06:36:28337 webwidget_->setFocus(enable);
initial.commit09911bf2008-07-26 23:55:29338 if (enable) {
339 // Force to retrieve the state of the focused widget to determine if we
340 // should activate IMEs next time when this process calls the UpdateIME()
341 // function.
342 ime_control_updated_ = true;
343 ime_control_new_state_ = true;
344 }
345}
346
347void RenderWidget::ClearFocus() {
348 // We may have got the focus from the browser before this gets processed, in
349 // which case we do not want to unfocus ourself.
350 if (!has_focus_ && webwidget_)
[email protected]4873c7d2009-07-16 06:36:28351 webwidget_->setFocus(false);
initial.commit09911bf2008-07-26 23:55:29352}
353
[email protected]2d5d09d52009-06-15 14:29:21354void RenderWidget::PaintRect(const gfx::Rect& rect,
[email protected]4fb66842009-12-04 21:41:00355 const gfx::Point& canvas_origin,
[email protected]2d5d09d52009-06-15 14:29:21356 skia::PlatformCanvas* canvas) {
[email protected]4fb66842009-12-04 21:41:00357 canvas->save();
[email protected]2d5d09d52009-06-15 14:29:21358
359 // Bring the canvas into the coordinate system of the paint rect.
[email protected]4fb66842009-12-04 21:41:00360 canvas->translate(static_cast<SkScalar>(-canvas_origin.x()),
361 static_cast<SkScalar>(-canvas_origin.y()));
[email protected]96c3499a2009-05-02 18:31:03362
[email protected]699ab0d2009-04-23 23:19:14363 // If there is a custom background, tile it.
364 if (!background_.empty()) {
[email protected]699ab0d2009-04-23 23:19:14365 SkPaint paint;
366 SkShader* shader = SkShader::CreateBitmapShader(background_,
367 SkShader::kRepeat_TileMode,
368 SkShader::kRepeat_TileMode);
369 paint.setShader(shader)->unref();
[email protected]8860e4f52009-06-25 01:01:52370 paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
[email protected]699ab0d2009-04-23 23:19:14371 canvas->drawPaint(paint);
[email protected]699ab0d2009-04-23 23:19:14372 }
373
[email protected]8c89e7792009-08-19 21:18:34374 webwidget_->paint(webkit_glue::ToWebCanvas(canvas), rect);
initial.commit09911bf2008-07-26 23:55:29375
[email protected]4fb66842009-12-04 21:41:00376 PaintDebugBorder(rect, canvas);
377
initial.commit09911bf2008-07-26 23:55:29378 // Flush to underlying bitmap. TODO(darin): is this needed?
[email protected]661eb9d2009-02-03 02:11:48379 canvas->getTopPlatformDevice().accessBitmap(false);
[email protected]4fb66842009-12-04 21:41:00380
381 canvas->restore();
382}
383
384void RenderWidget::PaintDebugBorder(const gfx::Rect& rect,
385 skia::PlatformCanvas* canvas) {
386 static bool kPaintBorder =
387 CommandLine::ForCurrentProcess()->HasSwitch(switches::kShowPaintRects);
388 if (!kPaintBorder)
389 return;
390
[email protected]53d3f302009-12-21 04:42:05391 // Cycle through these colors to help distinguish new paint rects.
392 const SkColor colors[] = {
393 SkColorSetARGB(0x3F, 0xFF, 0, 0),
394 SkColorSetARGB(0x3F, 0xFF, 0, 0xFF),
395 SkColorSetARGB(0x3F, 0, 0, 0xFF),
396 };
397 static int color_selector = 0;
398
[email protected]4fb66842009-12-04 21:41:00399 SkPaint paint;
400 paint.setStyle(SkPaint::kStroke_Style);
[email protected]53d3f302009-12-21 04:42:05401 paint.setColor(colors[color_selector++ % arraysize(colors)]);
[email protected]4fb66842009-12-04 21:41:00402 paint.setStrokeWidth(1);
403
404 SkIRect irect;
405 irect.set(rect.x(), rect.y(), rect.right() - 1, rect.bottom() - 1);
406 canvas->drawIRect(irect, paint);
initial.commit09911bf2008-07-26 23:55:29407}
408
[email protected]552e6002009-11-19 05:24:57409void RenderWidget::CallDoDeferredUpdate() {
410 DoDeferredUpdate();
[email protected]12fbad812009-09-01 18:21:24411
412 if (pending_input_event_ack_.get()) {
413 Send(pending_input_event_ack_.get());
414 pending_input_event_ack_.release();
415 }
416}
417
[email protected]552e6002009-11-19 05:24:57418void RenderWidget::DoDeferredUpdate() {
419 if (!webwidget_ || !paint_aggregator_.HasPendingUpdate() ||
[email protected]53d3f302009-12-21 04:42:05420 update_reply_pending())
initial.commit09911bf2008-07-26 23:55:29421 return;
422
[email protected]552e6002009-11-19 05:24:57423 // Suppress updating when we are hidden.
initial.commit09911bf2008-07-26 23:55:29424 if (is_hidden_ || size_.IsEmpty()) {
[email protected]552e6002009-11-19 05:24:57425 paint_aggregator_.ClearPendingUpdate();
initial.commit09911bf2008-07-26 23:55:29426 needs_repainting_on_restore_ = true;
427 return;
428 }
429
[email protected]552e6002009-11-19 05:24:57430 // Layout may generate more invalidation.
[email protected]4873c7d2009-07-16 06:36:28431 webwidget_->layout();
initial.commit09911bf2008-07-26 23:55:29432
[email protected]552e6002009-11-19 05:24:57433 // OK, save the pending update to a local since painting may cause more
initial.commit09911bf2008-07-26 23:55:29434 // invalidation. Some WebCore rendering objects only layout when painted.
[email protected]552e6002009-11-19 05:24:57435 PaintAggregator::PendingUpdate update = paint_aggregator_.GetPendingUpdate();
436 paint_aggregator_.ClearPendingUpdate();
initial.commit09911bf2008-07-26 23:55:29437
[email protected]53d3f302009-12-21 04:42:05438 gfx::Rect scroll_damage = update.GetScrollDamage();
439 gfx::Rect bounds = update.GetPaintBounds().Union(scroll_damage);
initial.commit09911bf2008-07-26 23:55:29440
[email protected]53d3f302009-12-21 04:42:05441 // Compute a buffer for painting and cache it.
442 scoped_ptr<skia::PlatformCanvas> canvas(
443 RenderProcess::current()->GetDrawingCanvas(&current_paint_buf_, bounds));
444 if (!canvas.get()) {
445 NOTREACHED();
446 return;
[email protected]552e6002009-11-19 05:24:57447 }
448
[email protected]53d3f302009-12-21 04:42:05449 // We may get back a smaller canvas than we asked for.
450 // TODO(darin): This seems like it could cause painting problems!
451 DCHECK_EQ(bounds.width(), canvas->getDevice()->width());
452 DCHECK_EQ(bounds.height(), canvas->getDevice()->height());
453 bounds.set_width(canvas->getDevice()->width());
454 bounds.set_height(canvas->getDevice()->height());
[email protected]552e6002009-11-19 05:24:57455
[email protected]53d3f302009-12-21 04:42:05456 HISTOGRAM_COUNTS_100("MPArch.RW_PaintRectCount", update.paint_rects.size());
[email protected]552e6002009-11-19 05:24:57457
[email protected]53d3f302009-12-21 04:42:05458 // TODO(darin): Re-enable painting multiple damage rects once the
459 // page-cycler regressions are resolved. See bug 29589.
460 if (update.scroll_rect.IsEmpty()) {
461 update.paint_rects.clear();
462 update.paint_rects.push_back(bounds);
initial.commit09911bf2008-07-26 23:55:29463 }
464
[email protected]cef3362f2009-12-21 17:48:45465 // The scroll damage is just another rectangle to paint and copy.
466 std::vector<gfx::Rect> copy_rects;
467 copy_rects.swap(update.paint_rects);
468 if (!scroll_damage.IsEmpty())
469 copy_rects.push_back(scroll_damage);
470
[email protected]53d3f302009-12-21 04:42:05471 for (size_t i = 0; i < copy_rects.size(); ++i)
472 PaintRect(copy_rects[i], bounds.origin(), canvas.get());
473
474 ViewHostMsg_UpdateRect_Params params;
475 params.bitmap = current_paint_buf_->id();
476 params.bitmap_rect = bounds;
477 params.dx = update.scroll_delta.x();
478 params.dy = update.scroll_delta.y();
479 params.scroll_rect = update.scroll_rect;
480 params.copy_rects.swap(copy_rects); // TODO(darin): clip to bounds?
481 params.view_size = size_;
482 params.plugin_window_moves.swap(plugin_window_moves_);
483 params.flags = next_paint_flags_;
484
485 update_reply_pending_ = true;
486 Send(new ViewHostMsg_UpdateRect(routing_id_, params));
487 next_paint_flags_ = 0;
488
initial.commit09911bf2008-07-26 23:55:29489 UpdateIME();
490}
491
492///////////////////////////////////////////////////////////////////////////////
493// WebWidgetDelegate
494
[email protected]4873c7d2009-07-16 06:36:28495void RenderWidget::didInvalidateRect(const WebRect& rect) {
[email protected]552e6002009-11-19 05:24:57496 // We only want one pending DoDeferredUpdate call at any time...
497 bool update_pending = paint_aggregator_.HasPendingUpdate();
initial.commit09911bf2008-07-26 23:55:29498
[email protected]552e6002009-11-19 05:24:57499 // The invalidated rect might be outside the bounds of the view.
[email protected]2d5d09d52009-06-15 14:29:21500 gfx::Rect view_rect(0, 0, size_.width(), size_.height());
[email protected]552e6002009-11-19 05:24:57501 gfx::Rect damaged_rect = view_rect.Intersect(rect);
502 if (damaged_rect.IsEmpty())
initial.commit09911bf2008-07-26 23:55:29503 return;
504
[email protected]552e6002009-11-19 05:24:57505 paint_aggregator_.InvalidateRect(damaged_rect);
506
507 // We may not need to schedule another call to DoDeferredUpdate.
508 if (update_pending)
509 return;
510 if (!paint_aggregator_.HasPendingUpdate())
511 return;
[email protected]53d3f302009-12-21 04:42:05512 if (update_reply_pending())
[email protected]552e6002009-11-19 05:24:57513 return;
514
515 // Perform updating asynchronously. This serves two purposes:
initial.commit09911bf2008-07-26 23:55:29516 // 1) Ensures that we call WebView::Paint without a bunch of other junk
517 // on the call stack.
518 // 2) Allows us to collect more damage rects before painting to help coalesce
519 // the work that we will need to do.
520 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
[email protected]552e6002009-11-19 05:24:57521 this, &RenderWidget::CallDoDeferredUpdate));
initial.commit09911bf2008-07-26 23:55:29522}
523
[email protected]4873c7d2009-07-16 06:36:28524void RenderWidget::didScrollRect(int dx, int dy, const WebRect& clip_rect) {
[email protected]552e6002009-11-19 05:24:57525 // We only want one pending DoDeferredUpdate call at any time...
526 bool update_pending = paint_aggregator_.HasPendingUpdate();
initial.commit09911bf2008-07-26 23:55:29527
[email protected]552e6002009-11-19 05:24:57528 // The scrolled rect might be outside the bounds of the view.
529 gfx::Rect view_rect(0, 0, size_.width(), size_.height());
530 gfx::Rect damaged_rect = view_rect.Intersect(clip_rect);
531 if (damaged_rect.IsEmpty())
initial.commit09911bf2008-07-26 23:55:29532 return;
533
[email protected]552e6002009-11-19 05:24:57534 paint_aggregator_.ScrollRect(dx, dy, damaged_rect);
535
536 // We may not need to schedule another call to DoDeferredUpdate.
537 if (update_pending)
538 return;
539 if (!paint_aggregator_.HasPendingUpdate())
540 return;
[email protected]53d3f302009-12-21 04:42:05541 if (update_reply_pending())
[email protected]552e6002009-11-19 05:24:57542 return;
543
544 // Perform updating asynchronously. This serves two purposes:
545 // 1) Ensures that we call WebView::Paint without a bunch of other junk
546 // on the call stack.
547 // 2) Allows us to collect more damage rects before painting to help coalesce
548 // the work that we will need to do.
initial.commit09911bf2008-07-26 23:55:29549 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
[email protected]552e6002009-11-19 05:24:57550 this, &RenderWidget::CallDoDeferredUpdate));
initial.commit09911bf2008-07-26 23:55:29551}
552
[email protected]4873c7d2009-07-16 06:36:28553void RenderWidget::didChangeCursor(const WebCursorInfo& cursor_info) {
[email protected]7c51b0ee2009-07-08 21:49:30554 // TODO(darin): Eliminate this temporary.
555 WebCursor cursor(cursor_info);
556
initial.commit09911bf2008-07-26 23:55:29557 // Only send a SetCursor message if we need to make a change.
558 if (!current_cursor_.IsEqual(cursor)) {
559 current_cursor_ = cursor;
560 Send(new ViewHostMsg_SetCursor(routing_id_, cursor));
561 }
562}
563
564// We are supposed to get a single call to Show for a newly created RenderWidget
565// that was created via RenderWidget::CreateWebView. So, we wait until this
566// point to dispatch the ShowWidget message.
567//
568// This method provides us with the information about how to display the newly
569// created RenderWidget (i.e., as a constrained popup or as a new tab).
570//
[email protected]4873c7d2009-07-16 06:36:28571void RenderWidget::show(WebNavigationPolicy) {
initial.commit09911bf2008-07-26 23:55:29572 DCHECK(!did_show_) << "received extraneous Show call";
573 DCHECK(routing_id_ != MSG_ROUTING_NONE);
574 DCHECK(opener_id_ != MSG_ROUTING_NONE);
575
576 if (!did_show_) {
577 did_show_ = true;
578 // NOTE: initial_pos_ may still have its default values at this point, but
579 // that's okay. It'll be ignored if as_popup is false, or the browser
580 // process will impose a default position otherwise.
[email protected]88efb7ec2009-07-14 16:32:59581 if (popup_params_.get()) {
582 popup_params_->bounds = initial_pos_;
583 Send(new ViewHostMsg_ShowPopup(routing_id_, *popup_params_));
584 popup_params_.reset();
585 } else {
586 Send(new ViewHostMsg_ShowWidget(opener_id_, routing_id_, initial_pos_));
587 }
[email protected]2533ce12009-05-09 00:02:24588 SetPendingWindowRect(initial_pos_);
initial.commit09911bf2008-07-26 23:55:29589 }
590}
591
[email protected]4873c7d2009-07-16 06:36:28592void RenderWidget::didFocus() {
[email protected]130efb02009-09-18 18:54:35593 // Note that didFocus() is invoked everytime a new node is focused in the
594 // page. It could be expected that it would be called only when the widget
595 // gets the focus. If the current behavior was to change in WebKit for the
596 // expected one, the following notification would not work anymore.
597 Send(new ViewHostMsg_FocusedNodeChanged(routing_id_));
598
initial.commit09911bf2008-07-26 23:55:29599 // Prevent the widget from stealing the focus if it does not have focus
600 // already. We do this by explicitely setting the focus to false again.
601 // We only let the browser focus the renderer.
602 if (!has_focus_ && webwidget_) {
603 MessageLoop::current()->PostTask(FROM_HERE,
604 NewRunnableMethod(this, &RenderWidget::ClearFocus));
605 }
606}
607
[email protected]4873c7d2009-07-16 06:36:28608void RenderWidget::didBlur() {
initial.commit09911bf2008-07-26 23:55:29609 Send(new ViewHostMsg_Blur(routing_id_));
610}
611
[email protected]2533ce12009-05-09 00:02:24612void RenderWidget::DoDeferredClose() {
613 Send(new ViewHostMsg_Close(routing_id_));
614}
615
[email protected]4873c7d2009-07-16 06:36:28616void RenderWidget::closeWidgetSoon() {
initial.commit09911bf2008-07-26 23:55:29617 // If a page calls window.close() twice, we'll end up here twice, but that's
618 // OK. It is safe to send multiple Close messages.
619
[email protected]2533ce12009-05-09 00:02:24620 // Ask the RenderWidgetHost to initiate close. We could be called from deep
621 // in Javascript. If we ask the RendwerWidgetHost to close now, the window
622 // could be closed before the JS finishes executing. So instead, post a
623 // message back to the message loop, which won't run until the JS is
624 // complete, and then the Close message can be sent.
[email protected]75ae4492009-07-10 00:05:15625 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
[email protected]2533ce12009-05-09 00:02:24626 this, &RenderWidget::DoDeferredClose));
initial.commit09911bf2008-07-26 23:55:29627}
628
[email protected]b4b967e2009-04-22 11:33:05629void RenderWidget::GenerateFullRepaint() {
[email protected]4873c7d2009-07-16 06:36:28630 didInvalidateRect(gfx::Rect(size_.width(), size_.height()));
[email protected]b4b967e2009-04-22 11:33:05631}
632
initial.commit09911bf2008-07-26 23:55:29633void RenderWidget::Close() {
634 if (webwidget_) {
[email protected]4873c7d2009-07-16 06:36:28635 webwidget_->close();
initial.commit09911bf2008-07-26 23:55:29636 webwidget_ = NULL;
637 }
638}
639
[email protected]4873c7d2009-07-16 06:36:28640WebRect RenderWidget::windowRect() {
641 if (pending_window_rect_count_)
642 return pending_window_rect_;
[email protected]2533ce12009-05-09 00:02:24643
[email protected]b3f2b912009-04-09 16:18:52644 gfx::Rect rect;
645 Send(new ViewHostMsg_GetWindowRect(routing_id_, host_window_, &rect));
[email protected]4873c7d2009-07-16 06:36:28646 return rect;
initial.commit09911bf2008-07-26 23:55:29647}
648
[email protected]4873c7d2009-07-16 06:36:28649void RenderWidget::setWindowRect(const WebRect& pos) {
initial.commit09911bf2008-07-26 23:55:29650 if (did_show_) {
651 Send(new ViewHostMsg_RequestMove(routing_id_, pos));
[email protected]2533ce12009-05-09 00:02:24652 SetPendingWindowRect(pos);
initial.commit09911bf2008-07-26 23:55:29653 } else {
654 initial_pos_ = pos;
655 }
656}
657
[email protected]2533ce12009-05-09 00:02:24658void RenderWidget::SetPendingWindowRect(const WebRect& rect) {
659 pending_window_rect_ = rect;
660 pending_window_rect_count_++;
661}
662
[email protected]4873c7d2009-07-16 06:36:28663WebRect RenderWidget::rootWindowRect() {
[email protected]2533ce12009-05-09 00:02:24664 if (pending_window_rect_count_) {
665 // NOTE(mbelshe): If there is a pending_window_rect_, then getting
666 // the RootWindowRect is probably going to return wrong results since the
667 // browser may not have processed the Move yet. There isn't really anything
668 // good to do in this case, and it shouldn't happen - since this size is
669 // only really needed for windowToScreen, which is only used for Popups.
[email protected]4873c7d2009-07-16 06:36:28670 return pending_window_rect_;
[email protected]2533ce12009-05-09 00:02:24671 }
672
[email protected]b3f2b912009-04-09 16:18:52673 gfx::Rect rect;
674 Send(new ViewHostMsg_GetRootWindowRect(routing_id_, host_window_, &rect));
[email protected]4873c7d2009-07-16 06:36:28675 return rect;
[email protected]d4547452008-08-28 18:36:37676}
677
[email protected]4873c7d2009-07-16 06:36:28678WebRect RenderWidget::windowResizerRect() {
679 return resizer_rect_;
[email protected]c04b6362008-11-21 18:54:19680}
681
initial.commit09911bf2008-07-26 23:55:29682void RenderWidget::OnImeSetInputMode(bool is_active) {
[email protected]c4bb35a2008-10-31 17:54:03683 // To prevent this renderer process from sending unnecessary IPC messages to
684 // a browser process, we permit the renderer process to send IPC messages
685 // only during the IME attached to the browser process is active.
initial.commit09911bf2008-07-26 23:55:29686 ime_is_active_ = is_active;
initial.commit09911bf2008-07-26 23:55:29687}
688
[email protected]4873c7d2009-07-16 06:36:28689void RenderWidget::OnImeSetComposition(WebCompositionCommand command,
initial.commit09911bf2008-07-26 23:55:29690 int cursor_position,
691 int target_start, int target_end,
[email protected]4873c7d2009-07-16 06:36:28692 const string16& ime_string) {
693 if (!webwidget_)
694 return;
695 ime_control_busy_ = true;
696 webwidget_->handleCompositionEvent(command, cursor_position,
697 target_start, target_end,
698 ime_string);
699 ime_control_busy_ = false;
initial.commit09911bf2008-07-26 23:55:29700}
701
[email protected]ec7dc112008-08-06 05:30:12702void RenderWidget::OnMsgRepaint(const gfx::Size& size_to_paint) {
703 // During shutdown we can just ignore this message.
704 if (!webwidget_)
705 return;
706
707 set_next_paint_is_repaint_ack();
708 gfx::Rect repaint_rect(size_to_paint.width(), size_to_paint.height());
[email protected]4873c7d2009-07-16 06:36:28709 didInvalidateRect(repaint_rect);
[email protected]ec7dc112008-08-06 05:30:12710}
711
[email protected]4873c7d2009-07-16 06:36:28712void RenderWidget::OnSetTextDirection(WebTextDirection direction) {
[email protected]07f953332009-03-25 04:31:11713 if (!webwidget_)
714 return;
[email protected]4873c7d2009-07-16 06:36:28715 webwidget_->setTextDirection(direction);
[email protected]07f953332009-03-25 04:31:11716}
717
[email protected]bee16aab2009-08-26 15:55:03718void RenderWidget::SetHidden(bool hidden) {
719 if (is_hidden_ == hidden)
720 return;
721
722 // The status has changed. Tell the RenderThread about it.
723 is_hidden_ = hidden;
724 if (is_hidden_)
725 render_thread_->WidgetHidden();
726 else
727 render_thread_->WidgetRestored();
728}
729
[email protected]699ab0d2009-04-23 23:19:14730void RenderWidget::SetBackground(const SkBitmap& background) {
731 background_ = background;
732 // Generate a full repaint.
[email protected]4873c7d2009-07-16 06:36:28733 didInvalidateRect(gfx::Rect(size_.width(), size_.height()));
[email protected]699ab0d2009-04-23 23:19:14734}
735
[email protected]674741932009-02-04 23:44:46736bool RenderWidget::next_paint_is_resize_ack() const {
[email protected]53d3f302009-12-21 04:42:05737 return ViewHostMsg_UpdateRect_Flags::is_resize_ack(next_paint_flags_);
[email protected]674741932009-02-04 23:44:46738}
739
740bool RenderWidget::next_paint_is_restore_ack() const {
[email protected]53d3f302009-12-21 04:42:05741 return ViewHostMsg_UpdateRect_Flags::is_restore_ack(next_paint_flags_);
[email protected]674741932009-02-04 23:44:46742}
743
744void RenderWidget::set_next_paint_is_resize_ack() {
[email protected]53d3f302009-12-21 04:42:05745 next_paint_flags_ |= ViewHostMsg_UpdateRect_Flags::IS_RESIZE_ACK;
[email protected]674741932009-02-04 23:44:46746}
747
748void RenderWidget::set_next_paint_is_restore_ack() {
[email protected]53d3f302009-12-21 04:42:05749 next_paint_flags_ |= ViewHostMsg_UpdateRect_Flags::IS_RESTORE_ACK;
[email protected]674741932009-02-04 23:44:46750}
751
752void RenderWidget::set_next_paint_is_repaint_ack() {
[email protected]53d3f302009-12-21 04:42:05753 next_paint_flags_ |= ViewHostMsg_UpdateRect_Flags::IS_REPAINT_ACK;
[email protected]674741932009-02-04 23:44:46754}
755
initial.commit09911bf2008-07-26 23:55:29756void RenderWidget::UpdateIME() {
757 // If a browser process does not have IMEs, its IMEs are not active, or there
758 // are not any attached widgets.
759 // a renderer process does not have to retrieve information of the focused
760 // control or send notification messages to a browser process.
761 if (!ime_is_active_) {
762 return;
763 }
[email protected]34f6bc12008-11-06 07:40:53764 // Retrieve the caret position from the focused widget and verify we should
765 // enabled IMEs attached to the browser process.
766 bool enable_ime = false;
[email protected]b3f2b912009-04-09 16:18:52767 WebRect caret_rect;
[email protected]34f6bc12008-11-06 07:40:53768 if (!webwidget_ ||
[email protected]4873c7d2009-07-16 06:36:28769 !webwidget_->queryCompositionStatus(&enable_ime, &caret_rect)) {
initial.commit09911bf2008-07-26 23:55:29770 // There are not any editable widgets attached to this process.
771 // We should disable the IME to prevent it from sending CJK strings to
772 // non-editable widgets.
773 ime_control_updated_ = true;
774 ime_control_new_state_ = false;
775 }
[email protected]9f23f592008-11-17 08:36:34776 if (ime_control_new_state_ != enable_ime) {
777 ime_control_updated_ = true;
778 ime_control_new_state_ = enable_ime;
779 }
initial.commit09911bf2008-07-26 23:55:29780 if (ime_control_updated_) {
781 // The input focus has been changed.
782 // Compare the current state with the updated state and choose actions.
783 if (ime_control_enable_ime_) {
784 if (ime_control_new_state_) {
785 // Case 1: a text input -> another text input
786 // Complete the current composition and notify the caret position.
[email protected]34f6bc12008-11-06 07:40:53787 Send(new ViewHostMsg_ImeUpdateStatus(routing_id(),
788 IME_COMPLETE_COMPOSITION,
789 caret_rect));
initial.commit09911bf2008-07-26 23:55:29790 } else {
791 // Case 2: a text input -> a password input (or a static control)
792 // Complete the current composition and disable the IME.
[email protected]34f6bc12008-11-06 07:40:53793 Send(new ViewHostMsg_ImeUpdateStatus(routing_id(), IME_DISABLE,
794 caret_rect));
initial.commit09911bf2008-07-26 23:55:29795 }
796 } else {
797 if (ime_control_new_state_) {
798 // Case 3: a password input (or a static control) -> a text input
799 // Enable the IME and notify the caret position.
[email protected]34f6bc12008-11-06 07:40:53800 Send(new ViewHostMsg_ImeUpdateStatus(routing_id(),
801 IME_COMPLETE_COMPOSITION,
802 caret_rect));
initial.commit09911bf2008-07-26 23:55:29803 } else {
804 // Case 4: a password input (or a static contol) -> another password
805 // input (or another static control).
806 // The IME has been already disabled and we don't have to do anything.
807 }
808 }
809 } else {
810 // The input focus is not changed.
811 // Notify the caret position to a browser process only if it is changed.
812 if (ime_control_enable_ime_) {
[email protected]b3f2b912009-04-09 16:18:52813 if (caret_rect.x != ime_control_x_ ||
814 caret_rect.y != ime_control_y_) {
[email protected]34f6bc12008-11-06 07:40:53815 Send(new ViewHostMsg_ImeUpdateStatus(routing_id(), IME_MOVE_WINDOWS,
816 caret_rect));
initial.commit09911bf2008-07-26 23:55:29817 }
818 }
819 }
820 // Save the updated IME status to prevent from sending the same IPC messages.
821 ime_control_updated_ = false;
822 ime_control_enable_ime_ = ime_control_new_state_;
[email protected]b3f2b912009-04-09 16:18:52823 ime_control_x_ = caret_rect.x;
824 ime_control_y_ = caret_rect.y;
initial.commit09911bf2008-07-26 23:55:29825}
826
[email protected]4873c7d2009-07-16 06:36:28827WebScreenInfo RenderWidget::screenInfo() {
828 WebScreenInfo results;
829 Send(new ViewHostMsg_GetScreenInfo(routing_id_, host_window_, &results));
830 return results;
831}
832
[email protected]f103ab72009-09-02 17:10:59833void RenderWidget::SchedulePluginMove(
834 const webkit_glue::WebPluginGeometry& move) {
initial.commit09911bf2008-07-26 23:55:29835 size_t i = 0;
836 for (; i < plugin_window_moves_.size(); ++i) {
837 if (plugin_window_moves_[i].window == move.window) {
[email protected]16f89d02009-08-26 17:17:58838 if (move.rects_valid) {
839 plugin_window_moves_[i] = move;
840 } else {
841 plugin_window_moves_[i].visible = move.visible;
842 }
initial.commit09911bf2008-07-26 23:55:29843 break;
844 }
845 }
846
847 if (i == plugin_window_moves_.size())
848 plugin_window_moves_.push_back(move);
849}
[email protected]268654772009-08-06 23:02:04850
851void RenderWidget::CleanupWindowInPluginMoves(gfx::PluginWindowHandle window) {
852 for (WebPluginGeometryVector::iterator i = plugin_window_moves_.begin();
853 i != plugin_window_moves_.end(); ++i) {
854 if (i->window == window) {
855 plugin_window_moves_.erase(i);
856 break;
857 }
858 }
859}