blob: 3aa58e3f2ae5f157c50a861a20c3fcf3938bc2f4 [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
initial.commit09911bf2008-07-26 23:55:297#include "base/gfx/point.h"
8#include "base/gfx/size.h"
9#include "base/logging.h"
10#include "base/message_loop.h"
initial.commit09911bf2008-07-26 23:55:2911#include "base/scoped_ptr.h"
[email protected]661eb9d2009-02-03 02:11:4812#include "build/build_config.h"
[email protected]674741932009-02-04 23:44:4613#include "chrome/common/render_messages.h"
[email protected]e68e62fa2009-02-20 02:00:0414#include "chrome/common/transport_dib.h"
[email protected]8085dbc82008-09-26 22:53:4415#include "chrome/renderer/render_process.h"
[email protected]661eb9d2009-02-03 02:11:4816#include "skia/ext/platform_canvas.h"
[email protected]d5282e72009-05-13 13:16:5217#include "third_party/skia/include/core/SkShader.h"
[email protected]7c51b0ee2009-07-08 21:49:3018#include "webkit/api/public/WebCursorInfo.h"
[email protected]4873c7d2009-07-16 06:36:2819#include "webkit/api/public/WebPopupMenu.h"
[email protected]88efb7ec2009-07-14 16:32:5920#include "webkit/api/public/WebPopupMenuInfo.h"
[email protected]afdcf5c2009-05-10 20:30:4121#include "webkit/api/public/WebRect.h"
22#include "webkit/api/public/WebScreenInfo.h"
23#include "webkit/api/public/WebSize.h"
[email protected]8c89e7792009-08-19 21:18:3424#include "webkit/glue/webkit_glue.h"
[email protected]661eb9d2009-02-03 02:11:4825
26#if defined(OS_POSIX)
[email protected]d5282e72009-05-13 13:16:5227#include "third_party/skia/include/core/SkPixelRef.h"
28#include "third_party/skia/include/core/SkMallocPixelRef.h"
[email protected]661eb9d2009-02-03 02:11:4829#endif // defined(OS_POSIX)
[email protected]8085dbc82008-09-26 22:53:4430
[email protected]4873c7d2009-07-16 06:36:2831#include "webkit/api/public/WebWidget.h"
initial.commit09911bf2008-07-26 23:55:2932
[email protected]4873c7d2009-07-16 06:36:2833using WebKit::WebCompositionCommand;
[email protected]7c51b0ee2009-07-08 21:49:3034using WebKit::WebCursorInfo;
[email protected]62cb33cae2009-03-27 23:30:2235using WebKit::WebInputEvent;
[email protected]4873c7d2009-07-16 06:36:2836using WebKit::WebNavigationPolicy;
37using WebKit::WebPopupMenu;
[email protected]88efb7ec2009-07-14 16:32:5938using WebKit::WebPopupMenuInfo;
[email protected]b3f2b912009-04-09 16:18:5239using WebKit::WebRect;
[email protected]12456fa2009-04-01 23:07:1940using WebKit::WebScreenInfo;
[email protected]b3f2b912009-04-09 16:18:5241using WebKit::WebSize;
[email protected]4873c7d2009-07-16 06:36:2842using WebKit::WebTextDirection;
[email protected]62cb33cae2009-03-27 23:30:2243
[email protected]cfd727f2009-01-09 20:21:1144RenderWidget::RenderWidget(RenderThreadBase* render_thread, bool activatable)
initial.commit09911bf2008-07-26 23:55:2945 : routing_id_(MSG_ROUTING_NONE),
[email protected]c5b3b5e2009-02-13 06:41:1146 webwidget_(NULL),
initial.commit09911bf2008-07-26 23:55:2947 opener_id_(MSG_ROUTING_NONE),
[email protected]8085dbc82008-09-26 22:53:4448 render_thread_(render_thread),
[email protected]5a3b9142009-08-28 21:03:1749 host_window_(NULL),
initial.commit09911bf2008-07-26 23:55:2950 current_paint_buf_(NULL),
51 current_scroll_buf_(NULL),
52 next_paint_flags_(0),
53 paint_reply_pending_(false),
54 did_show_(false),
initial.commit09911bf2008-07-26 23:55:2955 is_hidden_(false),
56 needs_repainting_on_restore_(false),
57 has_focus_(false),
[email protected]5dd768212009-08-13 23:34:4958 handling_input_event_(false),
[email protected]661eb9d2009-02-03 02:11:4859 closing_(false),
initial.commit09911bf2008-07-26 23:55:2960 ime_is_active_(false),
61 ime_control_enable_ime_(true),
62 ime_control_x_(-1),
63 ime_control_y_(-1),
64 ime_control_new_state_(false),
[email protected]0ebf3872008-11-07 21:35:0365 ime_control_updated_(false),
[email protected]9f23f592008-11-17 08:36:3466 ime_control_busy_(false),
[email protected]2533ce12009-05-09 00:02:2467 activatable_(activatable),
68 pending_window_rect_count_(0) {
[email protected]8930d472009-02-21 08:05:2869 RenderProcess::current()->AddRefProcess();
[email protected]8085dbc82008-09-26 22:53:4470 DCHECK(render_thread_);
initial.commit09911bf2008-07-26 23:55:2971}
72
73RenderWidget::~RenderWidget() {
[email protected]c5b3b5e2009-02-13 06:41:1174 DCHECK(!webwidget_) << "Leaking our WebWidget!";
initial.commit09911bf2008-07-26 23:55:2975 if (current_paint_buf_) {
[email protected]8930d472009-02-21 08:05:2876 RenderProcess::current()->ReleaseTransportDIB(current_paint_buf_);
initial.commit09911bf2008-07-26 23:55:2977 current_paint_buf_ = NULL;
78 }
79 if (current_scroll_buf_) {
[email protected]8930d472009-02-21 08:05:2880 RenderProcess::current()->ReleaseTransportDIB(current_scroll_buf_);
initial.commit09911bf2008-07-26 23:55:2981 current_scroll_buf_ = NULL;
82 }
[email protected]8930d472009-02-21 08:05:2883 RenderProcess::current()->ReleaseProcess();
initial.commit09911bf2008-07-26 23:55:2984}
85
86/*static*/
[email protected]8085dbc82008-09-26 22:53:4487RenderWidget* RenderWidget::Create(int32 opener_id,
[email protected]0ebf3872008-11-07 21:35:0388 RenderThreadBase* render_thread,
[email protected]cfd727f2009-01-09 20:21:1189 bool activatable) {
initial.commit09911bf2008-07-26 23:55:2990 DCHECK(opener_id != MSG_ROUTING_NONE);
[email protected]0ebf3872008-11-07 21:35:0391 scoped_refptr<RenderWidget> widget = new RenderWidget(render_thread,
[email protected]cfd727f2009-01-09 20:21:1192 activatable);
initial.commit09911bf2008-07-26 23:55:2993 widget->Init(opener_id); // adds reference
94 return widget;
95}
96
[email protected]88efb7ec2009-07-14 16:32:5997void RenderWidget::ConfigureAsExternalPopupMenu(const WebPopupMenuInfo& info) {
98 popup_params_.reset(new ViewHostMsg_ShowPopup_Params);
99 popup_params_->item_height = info.itemHeight;
100 popup_params_->selected_item = info.selectedIndex;
101 for (size_t i = 0; i < info.items.size(); ++i)
102 popup_params_->popup_items.push_back(WebMenuItem(info.items[i]));
103}
104
initial.commit09911bf2008-07-26 23:55:29105void RenderWidget::Init(int32 opener_id) {
106 DCHECK(!webwidget_);
107
108 if (opener_id != MSG_ROUTING_NONE)
109 opener_id_ = opener_id;
110
[email protected]4873c7d2009-07-16 06:36:28111 webwidget_ = WebPopupMenu::create(this);
initial.commit09911bf2008-07-26 23:55:29112
[email protected]8085dbc82008-09-26 22:53:44113 bool result = render_thread_->Send(
[email protected]cfd727f2009-01-09 20:21:11114 new ViewHostMsg_CreateWidget(opener_id, activatable_, &routing_id_));
initial.commit09911bf2008-07-26 23:55:29115 if (result) {
[email protected]8085dbc82008-09-26 22:53:44116 render_thread_->AddRoute(routing_id_, this);
initial.commit09911bf2008-07-26 23:55:29117 // Take a reference on behalf of the RenderThread. This will be balanced
118 // when we receive ViewMsg_Close.
119 AddRef();
120 } else {
121 DCHECK(false);
122 }
123}
124
125// This is used to complete pending inits and non-pending inits. For non-
126// pending cases, the parent will be the same as the current parent. This
127// indicates we do not need to reparent or anything.
[email protected]18bcc3c2009-01-27 21:39:15128void RenderWidget::CompleteInit(gfx::NativeViewId parent_hwnd) {
initial.commit09911bf2008-07-26 23:55:29129 DCHECK(routing_id_ != MSG_ROUTING_NONE);
initial.commit09911bf2008-07-26 23:55:29130
131 host_window_ = parent_hwnd;
132
[email protected]6de74452009-02-25 18:04:59133 Send(new ViewHostMsg_RenderViewReady(routing_id_));
initial.commit09911bf2008-07-26 23:55:29134}
135
136IPC_DEFINE_MESSAGE_MAP(RenderWidget)
137 IPC_MESSAGE_HANDLER(ViewMsg_Close, OnClose)
138 IPC_MESSAGE_HANDLER(ViewMsg_CreatingNew_ACK, OnCreatingNewAck)
139 IPC_MESSAGE_HANDLER(ViewMsg_Resize, OnResize)
140 IPC_MESSAGE_HANDLER(ViewMsg_WasHidden, OnWasHidden)
141 IPC_MESSAGE_HANDLER(ViewMsg_WasRestored, OnWasRestored)
142 IPC_MESSAGE_HANDLER(ViewMsg_PaintRect_ACK, OnPaintRectAck)
143 IPC_MESSAGE_HANDLER(ViewMsg_ScrollRect_ACK, OnScrollRectAck)
144 IPC_MESSAGE_HANDLER(ViewMsg_HandleInputEvent, OnHandleInputEvent)
145 IPC_MESSAGE_HANDLER(ViewMsg_MouseCaptureLost, OnMouseCaptureLost)
146 IPC_MESSAGE_HANDLER(ViewMsg_SetFocus, OnSetFocus)
147 IPC_MESSAGE_HANDLER(ViewMsg_ImeSetInputMode, OnImeSetInputMode)
148 IPC_MESSAGE_HANDLER(ViewMsg_ImeSetComposition, OnImeSetComposition)
[email protected]ec7dc112008-08-06 05:30:12149 IPC_MESSAGE_HANDLER(ViewMsg_Repaint, OnMsgRepaint)
[email protected]07f953332009-03-25 04:31:11150 IPC_MESSAGE_HANDLER(ViewMsg_SetTextDirection, OnSetTextDirection)
[email protected]2533ce12009-05-09 00:02:24151 IPC_MESSAGE_HANDLER(ViewMsg_Move_ACK, OnRequestMoveAck)
initial.commit09911bf2008-07-26 23:55:29152 IPC_MESSAGE_UNHANDLED_ERROR()
153IPC_END_MESSAGE_MAP()
154
155bool RenderWidget::Send(IPC::Message* message) {
156 // Don't send any messages after the browser has told us to close.
157 if (closing_) {
158 delete message;
159 return false;
160 }
161
162 // If given a messsage without a routing ID, then assign our routing ID.
163 if (message->routing_id() == MSG_ROUTING_NONE)
164 message->set_routing_id(routing_id_);
165
[email protected]d3fc25652009-02-24 22:31:25166 return render_thread_->Send(message);
[email protected]8085dbc82008-09-26 22:53:44167}
168
initial.commit09911bf2008-07-26 23:55:29169// Got a response from the browser after the renderer decided to create a new
170// view.
[email protected]18bcc3c2009-01-27 21:39:15171void RenderWidget::OnCreatingNewAck(gfx::NativeViewId parent) {
initial.commit09911bf2008-07-26 23:55:29172 DCHECK(routing_id_ != MSG_ROUTING_NONE);
173
174 CompleteInit(parent);
175}
176
177void RenderWidget::OnClose() {
178 if (closing_)
179 return;
180 closing_ = true;
181
182 // Browser correspondence is no longer needed at this point.
[email protected]bee16aab2009-08-26 15:55:03183 if (routing_id_ != MSG_ROUTING_NONE) {
[email protected]8085dbc82008-09-26 22:53:44184 render_thread_->RemoveRoute(routing_id_);
[email protected]bee16aab2009-08-26 15:55:03185 SetHidden(false);
186 }
initial.commit09911bf2008-07-26 23:55:29187
initial.commit09911bf2008-07-26 23:55:29188 // If there is a Send call on the stack, then it could be dangerous to close
[email protected]d3fc25652009-02-24 22:31:25189 // now. Post a task that only gets invoked when there are no nested message
190 // loops.
191 MessageLoop::current()->PostNonNestableTask(FROM_HERE,
192 NewRunnableMethod(this, &RenderWidget::Close));
193
194 // Balances the AddRef taken when we called AddRoute.
195 Release();
initial.commit09911bf2008-07-26 23:55:29196}
197
[email protected]f21c613a2009-02-12 14:46:17198void RenderWidget::OnResize(const gfx::Size& new_size,
199 const gfx::Rect& resizer_rect) {
initial.commit09911bf2008-07-26 23:55:29200 // During shutdown we can just ignore this message.
201 if (!webwidget_)
202 return;
203
[email protected]f21c613a2009-02-12 14:46:17204 // Remember the rect where the resize corner will be drawn.
205 resizer_rect_ = resizer_rect;
206
initial.commit09911bf2008-07-26 23:55:29207 // TODO(darin): We should not need to reset this here.
[email protected]bee16aab2009-08-26 15:55:03208 SetHidden(false);
initial.commit09911bf2008-07-26 23:55:29209 needs_repainting_on_restore_ = false;
210
211 // We shouldn't be asked to resize to our current size.
212 DCHECK(size_ != new_size);
213 size_ = new_size;
214
215 // We should not be sent a Resize message if we have not ACK'd the previous
216 DCHECK(!next_paint_is_resize_ack());
217
218 // When resizing, we want to wait to paint before ACK'ing the resize. This
219 // ensures that we only resize as fast as we can paint. We only need to send
220 // an ACK if we are resized to a non-empty rect.
[email protected]4873c7d2009-07-16 06:36:28221 webwidget_->resize(new_size);
initial.commit09911bf2008-07-26 23:55:29222 if (!new_size.IsEmpty()) {
[email protected]2d5d09d52009-06-15 14:29:21223 DCHECK(!paint_rect_.IsEmpty());
initial.commit09911bf2008-07-26 23:55:29224
225 // This should have caused an invalidation of the entire view. The damaged
226 // rect could be larger than new_size if we are being made smaller.
[email protected]2d5d09d52009-06-15 14:29:21227 DCHECK_GE(paint_rect_.width(), new_size.width());
228 DCHECK_GE(paint_rect_.height(), new_size.height());
229
initial.commit09911bf2008-07-26 23:55:29230 // We will send the Resize_ACK flag once we paint again.
231 set_next_paint_is_resize_ack();
232 }
233}
234
235void RenderWidget::OnWasHidden() {
236 // Go into a mode where we stop generating paint and scrolling events.
[email protected]bee16aab2009-08-26 15:55:03237 SetHidden(true);
initial.commit09911bf2008-07-26 23:55:29238}
239
240void RenderWidget::OnWasRestored(bool needs_repainting) {
241 // During shutdown we can just ignore this message.
242 if (!webwidget_)
243 return;
244
245 // See OnWasHidden
[email protected]bee16aab2009-08-26 15:55:03246 SetHidden(false);
initial.commit09911bf2008-07-26 23:55:29247
248 if (!needs_repainting && !needs_repainting_on_restore_)
249 return;
250 needs_repainting_on_restore_ = false;
251
252 // Tag the next paint as a restore ack, which is picked up by DoDeferredPaint
253 // when it sends out the next PaintRect message.
254 set_next_paint_is_restore_ack();
255
256 // Generate a full repaint.
[email protected]4873c7d2009-07-16 06:36:28257 didInvalidateRect(gfx::Rect(size_.width(), size_.height()));
initial.commit09911bf2008-07-26 23:55:29258}
259
[email protected]b7fce1f2008-08-14 05:01:07260void RenderWidget::OnPaintRectAck() {
initial.commit09911bf2008-07-26 23:55:29261 DCHECK(paint_reply_pending());
262 paint_reply_pending_ = false;
[email protected]b7fce1f2008-08-14 05:01:07263 // If we sent a PaintRect message with a zero-sized bitmap, then
264 // we should have no current paint buf.
265 if (current_paint_buf_) {
[email protected]8930d472009-02-21 08:05:28266 RenderProcess::current()->ReleaseTransportDIB(current_paint_buf_);
[email protected]b7fce1f2008-08-14 05:01:07267 current_paint_buf_ = NULL;
initial.commit09911bf2008-07-26 23:55:29268 }
[email protected]e68e62fa2009-02-20 02:00:04269
[email protected]a2f6bc112009-06-27 16:27:25270 // Notify subclasses
271 DidPaint();
272
initial.commit09911bf2008-07-26 23:55:29273 // Continue painting if necessary...
[email protected]12fbad812009-09-01 18:21:24274 CallDoDeferredPaint();
initial.commit09911bf2008-07-26 23:55:29275}
276
[email protected]2533ce12009-05-09 00:02:24277void RenderWidget::OnRequestMoveAck() {
278 DCHECK(pending_window_rect_count_);
279 pending_window_rect_count_--;
280}
281
initial.commit09911bf2008-07-26 23:55:29282void RenderWidget::OnScrollRectAck() {
283 DCHECK(scroll_reply_pending());
284
[email protected]e68e62fa2009-02-20 02:00:04285 if (current_scroll_buf_) {
[email protected]8930d472009-02-21 08:05:28286 RenderProcess::current()->ReleaseTransportDIB(current_scroll_buf_);
[email protected]e68e62fa2009-02-20 02:00:04287 current_scroll_buf_ = NULL;
288 }
initial.commit09911bf2008-07-26 23:55:29289
290 // Continue scrolling if necessary...
[email protected]12fbad812009-09-01 18:21:24291 CallDoDeferredScroll();
292}
293
294void RenderWidget::CallDoDeferredScroll() {
initial.commit09911bf2008-07-26 23:55:29295 DoDeferredScroll();
[email protected]12fbad812009-09-01 18:21:24296
297 if (pending_input_event_ack_.get()) {
298 Send(pending_input_event_ack_.get());
299 pending_input_event_ack_.release();
300 }
initial.commit09911bf2008-07-26 23:55:29301}
302
303void RenderWidget::OnHandleInputEvent(const IPC::Message& message) {
304 void* iter = NULL;
305
306 const char* data;
307 int data_length;
[email protected]5dd768212009-08-13 23:34:49308 handling_input_event_ = true;
309 if (!message.ReadData(&iter, &data, &data_length)) {
310 handling_input_event_ = false;
initial.commit09911bf2008-07-26 23:55:29311 return;
[email protected]5dd768212009-08-13 23:34:49312 }
initial.commit09911bf2008-07-26 23:55:29313
314 const WebInputEvent* input_event =
315 reinterpret_cast<const WebInputEvent*>(data);
316 bool processed = false;
317 if (webwidget_)
[email protected]4873c7d2009-07-16 06:36:28318 processed = webwidget_->handleInputEvent(*input_event);
initial.commit09911bf2008-07-26 23:55:29319
320 IPC::Message* response = new ViewHostMsg_HandleInputEvent_ACK(routing_id_);
321 response->WriteInt(input_event->type);
[email protected]e2824412009-02-27 01:57:05322 response->WriteBool(processed);
323
[email protected]12fbad812009-09-01 18:21:24324 if (input_event->type == WebInputEvent::MouseMove &&
325 (!paint_rect_.IsEmpty() || !scroll_rect_.IsEmpty())) {
326 // We want to rate limit the input events in this case, so we'll wait for
327 // painting to finish before ACKing this message.
328 pending_input_event_ack_.reset(response);
329 } else {
330 Send(response);
331 }
332
[email protected]5dd768212009-08-13 23:34:49333 handling_input_event_ = false;
[email protected]446705872009-09-10 07:22:48334
335 WebInputEvent::Type type = input_event->type;
336 if (type == WebInputEvent::RawKeyDown || type == WebInputEvent::KeyDown ||
337 type == WebInputEvent::KeyUp || type == WebInputEvent::Char)
338 DidHandleKeyEvent();
initial.commit09911bf2008-07-26 23:55:29339}
340
341void RenderWidget::OnMouseCaptureLost() {
342 if (webwidget_)
[email protected]4873c7d2009-07-16 06:36:28343 webwidget_->mouseCaptureLost();
initial.commit09911bf2008-07-26 23:55:29344}
345
346void RenderWidget::OnSetFocus(bool enable) {
347 has_focus_ = enable;
348 if (webwidget_)
[email protected]4873c7d2009-07-16 06:36:28349 webwidget_->setFocus(enable);
initial.commit09911bf2008-07-26 23:55:29350 if (enable) {
351 // Force to retrieve the state of the focused widget to determine if we
352 // should activate IMEs next time when this process calls the UpdateIME()
353 // function.
354 ime_control_updated_ = true;
355 ime_control_new_state_ = true;
356 }
357}
358
359void RenderWidget::ClearFocus() {
360 // We may have got the focus from the browser before this gets processed, in
361 // which case we do not want to unfocus ourself.
362 if (!has_focus_ && webwidget_)
[email protected]4873c7d2009-07-16 06:36:28363 webwidget_->setFocus(false);
initial.commit09911bf2008-07-26 23:55:29364}
365
[email protected]2d5d09d52009-06-15 14:29:21366void RenderWidget::PaintRect(const gfx::Rect& rect,
367 skia::PlatformCanvas* canvas) {
368
369 // Bring the canvas into the coordinate system of the paint rect.
370 canvas->translate(static_cast<SkScalar>(-rect.x()),
371 static_cast<SkScalar>(-rect.y()));
[email protected]96c3499a2009-05-02 18:31:03372
[email protected]699ab0d2009-04-23 23:19:14373 // If there is a custom background, tile it.
374 if (!background_.empty()) {
[email protected]699ab0d2009-04-23 23:19:14375 SkPaint paint;
376 SkShader* shader = SkShader::CreateBitmapShader(background_,
377 SkShader::kRepeat_TileMode,
378 SkShader::kRepeat_TileMode);
379 paint.setShader(shader)->unref();
[email protected]8860e4f52009-06-25 01:01:52380 paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
[email protected]699ab0d2009-04-23 23:19:14381 canvas->drawPaint(paint);
[email protected]699ab0d2009-04-23 23:19:14382 }
383
[email protected]8c89e7792009-08-19 21:18:34384 webwidget_->paint(webkit_glue::ToWebCanvas(canvas), rect);
initial.commit09911bf2008-07-26 23:55:29385
386 // Flush to underlying bitmap. TODO(darin): is this needed?
[email protected]661eb9d2009-02-03 02:11:48387 canvas->getTopPlatformDevice().accessBitmap(false);
initial.commit09911bf2008-07-26 23:55:29388}
389
[email protected]12fbad812009-09-01 18:21:24390void RenderWidget::CallDoDeferredPaint() {
391 DoDeferredPaint();
392
393 if (pending_input_event_ack_.get()) {
394 Send(pending_input_event_ack_.get());
395 pending_input_event_ack_.release();
396 }
397}
398
initial.commit09911bf2008-07-26 23:55:29399void RenderWidget::DoDeferredPaint() {
[email protected]2d5d09d52009-06-15 14:29:21400 if (!webwidget_ || paint_reply_pending() || paint_rect_.IsEmpty())
initial.commit09911bf2008-07-26 23:55:29401 return;
402
403 // When we are hidden, we want to suppress painting, but we still need to
404 // mark this DoDeferredPaint as complete.
405 if (is_hidden_ || size_.IsEmpty()) {
[email protected]2d5d09d52009-06-15 14:29:21406 paint_rect_ = gfx::Rect();
initial.commit09911bf2008-07-26 23:55:29407 needs_repainting_on_restore_ = true;
408 return;
409 }
410
411 // Layout may generate more invalidation...
[email protected]4873c7d2009-07-16 06:36:28412 webwidget_->layout();
initial.commit09911bf2008-07-26 23:55:29413
414 // OK, save the current paint_rect to a local since painting may cause more
415 // invalidation. Some WebCore rendering objects only layout when painted.
[email protected]2d5d09d52009-06-15 14:29:21416 gfx::Rect damaged_rect = paint_rect_;
417 paint_rect_ = gfx::Rect();
initial.commit09911bf2008-07-26 23:55:29418
419 // Compute a buffer for painting and cache it.
[email protected]e68e62fa2009-02-20 02:00:04420 skia::PlatformCanvas* canvas =
[email protected]f09c7182009-03-10 12:54:04421 RenderProcess::current()->GetDrawingCanvas(&current_paint_buf_,
[email protected]2d5d09d52009-06-15 14:29:21422 damaged_rect);
[email protected]e68e62fa2009-02-20 02:00:04423 if (!canvas) {
initial.commit09911bf2008-07-26 23:55:29424 NOTREACHED();
425 return;
426 }
427
[email protected]955ee6d62009-06-17 21:53:03428 // We may get back a smaller canvas than we asked for.
429 damaged_rect.set_width(canvas->getDevice()->width());
430 damaged_rect.set_height(canvas->getDevice()->height());
431
[email protected]2d5d09d52009-06-15 14:29:21432 PaintRect(damaged_rect, canvas);
initial.commit09911bf2008-07-26 23:55:29433
434 ViewHostMsg_PaintRect_Params params;
[email protected]2d5d09d52009-06-15 14:29:21435 params.bitmap_rect = damaged_rect;
initial.commit09911bf2008-07-26 23:55:29436 params.view_size = size_;
437 params.plugin_window_moves = plugin_window_moves_;
438 params.flags = next_paint_flags_;
[email protected]2d5d09d52009-06-15 14:29:21439 params.bitmap = current_paint_buf_->id();
initial.commit09911bf2008-07-26 23:55:29440
[email protected]e68e62fa2009-02-20 02:00:04441 delete canvas;
[email protected]661eb9d2009-02-03 02:11:48442
initial.commit09911bf2008-07-26 23:55:29443 plugin_window_moves_.clear();
444
445 paint_reply_pending_ = true;
446 Send(new ViewHostMsg_PaintRect(routing_id_, params));
447 next_paint_flags_ = 0;
448
449 UpdateIME();
450}
451
452void RenderWidget::DoDeferredScroll() {
453 if (!webwidget_ || scroll_reply_pending() || scroll_rect_.IsEmpty())
454 return;
455
456 // When we are hidden, we want to suppress scrolling, but we still need to
457 // mark this DoDeferredScroll as complete.
458 if (is_hidden_ || size_.IsEmpty()) {
459 scroll_rect_ = gfx::Rect();
460 needs_repainting_on_restore_ = true;
461 return;
462 }
463
464 // Layout may generate more invalidation, so we might have to bail on
465 // optimized scrolling...
[email protected]4873c7d2009-07-16 06:36:28466 webwidget_->layout();
initial.commit09911bf2008-07-26 23:55:29467
468 if (scroll_rect_.IsEmpty())
469 return;
470
471 gfx::Rect damaged_rect;
472
473 // Compute the region we will expose by scrolling, and paint that into a
474 // shared memory section.
475 if (scroll_delta_.x()) {
476 int dx = scroll_delta_.x();
477 damaged_rect.set_y(scroll_rect_.y());
478 damaged_rect.set_height(scroll_rect_.height());
479 if (dx > 0) {
480 damaged_rect.set_x(scroll_rect_.x());
481 damaged_rect.set_width(dx);
482 } else {
483 damaged_rect.set_x(scroll_rect_.right() + dx);
484 damaged_rect.set_width(-dx);
485 }
486 } else {
487 int dy = scroll_delta_.y();
488 damaged_rect.set_x(scroll_rect_.x());
489 damaged_rect.set_width(scroll_rect_.width());
490 if (dy > 0) {
491 damaged_rect.set_y(scroll_rect_.y());
492 damaged_rect.set_height(dy);
493 } else {
494 damaged_rect.set_y(scroll_rect_.bottom() + dy);
495 damaged_rect.set_height(-dy);
496 }
497 }
498
499 // In case the scroll offset exceeds the width/height of the scroll rect
500 damaged_rect = scroll_rect_.Intersect(damaged_rect);
501
[email protected]e68e62fa2009-02-20 02:00:04502 skia::PlatformCanvas* canvas =
[email protected]f09c7182009-03-10 12:54:04503 RenderProcess::current()->GetDrawingCanvas(&current_scroll_buf_,
504 damaged_rect);
[email protected]e68e62fa2009-02-20 02:00:04505 if (!canvas) {
initial.commit09911bf2008-07-26 23:55:29506 NOTREACHED();
507 return;
508 }
509
[email protected]955ee6d62009-06-17 21:53:03510 // We may get back a smaller canvas than we asked for.
511 damaged_rect.set_width(canvas->getDevice()->width());
512 damaged_rect.set_height(canvas->getDevice()->height());
513
initial.commit09911bf2008-07-26 23:55:29514 // Set these parameters before calling Paint, since that could result in
515 // further invalidates (uncommon).
516 ViewHostMsg_ScrollRect_Params params;
initial.commit09911bf2008-07-26 23:55:29517 params.bitmap_rect = damaged_rect;
518 params.dx = scroll_delta_.x();
519 params.dy = scroll_delta_.y();
520 params.clip_rect = scroll_rect_;
521 params.view_size = size_;
522 params.plugin_window_moves = plugin_window_moves_;
[email protected]e68e62fa2009-02-20 02:00:04523 params.bitmap = current_scroll_buf_->id();
[email protected]661eb9d2009-02-03 02:11:48524
initial.commit09911bf2008-07-26 23:55:29525 plugin_window_moves_.clear();
526
527 // Mark the scroll operation as no longer pending.
528 scroll_rect_ = gfx::Rect();
529
[email protected]e68e62fa2009-02-20 02:00:04530 PaintRect(damaged_rect, canvas);
initial.commit09911bf2008-07-26 23:55:29531 Send(new ViewHostMsg_ScrollRect(routing_id_, params));
[email protected]e68e62fa2009-02-20 02:00:04532 delete canvas;
initial.commit09911bf2008-07-26 23:55:29533 UpdateIME();
534}
535
536///////////////////////////////////////////////////////////////////////////////
537// WebWidgetDelegate
538
[email protected]4873c7d2009-07-16 06:36:28539void RenderWidget::didInvalidateRect(const WebRect& rect) {
initial.commit09911bf2008-07-26 23:55:29540 // We only want one pending DoDeferredPaint call at any time...
[email protected]2d5d09d52009-06-15 14:29:21541 bool paint_pending = !paint_rect_.IsEmpty();
initial.commit09911bf2008-07-26 23:55:29542
543 // If this invalidate overlaps with a pending scroll, then we have to
544 // downgrade to invalidating the scroll rect.
[email protected]b3f2b912009-04-09 16:18:52545 if (gfx::Rect(rect).Intersects(scroll_rect_)) {
[email protected]2d5d09d52009-06-15 14:29:21546 paint_rect_ = paint_rect_.Union(scroll_rect_);
initial.commit09911bf2008-07-26 23:55:29547 scroll_rect_ = gfx::Rect();
548 }
549
[email protected]2d5d09d52009-06-15 14:29:21550 gfx::Rect view_rect(0, 0, size_.width(), size_.height());
551 // TODO(iyengar) Investigate why we have painting issues when
552 // we ignore invalid regions outside the view.
553 // Ignore invalidates that occur outside the bounds of the view
554 // TODO(darin): maybe this should move into the paint code?
555 // paint_rect_ = view_rect.Intersect(paint_rect_.Union(rect));
556 paint_rect_ = paint_rect_.Union(view_rect.Intersect(rect));
initial.commit09911bf2008-07-26 23:55:29557
[email protected]2d5d09d52009-06-15 14:29:21558 if (paint_rect_.IsEmpty() || paint_reply_pending() || paint_pending)
initial.commit09911bf2008-07-26 23:55:29559 return;
560
561 // Perform painting asynchronously. This serves two purposes:
562 // 1) Ensures that we call WebView::Paint without a bunch of other junk
563 // on the call stack.
564 // 2) Allows us to collect more damage rects before painting to help coalesce
565 // the work that we will need to do.
566 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
[email protected]12fbad812009-09-01 18:21:24567 this, &RenderWidget::CallDoDeferredPaint));
initial.commit09911bf2008-07-26 23:55:29568}
569
[email protected]4873c7d2009-07-16 06:36:28570void RenderWidget::didScrollRect(int dx, int dy, const WebRect& clip_rect) {
[email protected]f911f742009-02-27 02:17:02571 if (dx != 0 && dy != 0) {
572 // We only support scrolling along one axis at a time.
[email protected]4873c7d2009-07-16 06:36:28573 didScrollRect(0, dy, clip_rect);
[email protected]f911f742009-02-27 02:17:02574 dy = 0;
575 }
initial.commit09911bf2008-07-26 23:55:29576
[email protected]2d5d09d52009-06-15 14:29:21577 bool intersects_with_painting = paint_rect_.Intersects(clip_rect);
initial.commit09911bf2008-07-26 23:55:29578
579 // If we already have a pending scroll operation or if this scroll operation
580 // intersects the existing paint region, then just failover to invalidating.
581 if (!scroll_rect_.IsEmpty() || intersects_with_painting) {
[email protected]b3f2b912009-04-09 16:18:52582 if (!intersects_with_painting && scroll_rect_ == gfx::Rect(clip_rect)) {
initial.commit09911bf2008-07-26 23:55:29583 // OK, we can just update the scroll delta (requires same scrolling axis)
584 if (!dx && !scroll_delta_.x()) {
585 scroll_delta_.set_y(scroll_delta_.y() + dy);
586 return;
587 }
588 if (!dy && !scroll_delta_.y()) {
589 scroll_delta_.set_x(scroll_delta_.x() + dx);
590 return;
591 }
592 }
[email protected]4873c7d2009-07-16 06:36:28593 didInvalidateRect(scroll_rect_);
initial.commit09911bf2008-07-26 23:55:29594 DCHECK(scroll_rect_.IsEmpty());
[email protected]4873c7d2009-07-16 06:36:28595 didInvalidateRect(clip_rect);
initial.commit09911bf2008-07-26 23:55:29596 return;
597 }
598
599 // We only want one pending DoDeferredScroll call at any time...
600 bool scroll_pending = !scroll_rect_.IsEmpty();
601
602 scroll_rect_ = clip_rect;
603 scroll_delta_.SetPoint(dx, dy);
604
605 if (scroll_pending)
606 return;
607
608 // Perform scrolling asynchronously since we need to call WebView::Paint
609 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
[email protected]12fbad812009-09-01 18:21:24610 this, &RenderWidget::CallDoDeferredScroll));
initial.commit09911bf2008-07-26 23:55:29611}
612
[email protected]4873c7d2009-07-16 06:36:28613void RenderWidget::didChangeCursor(const WebCursorInfo& cursor_info) {
[email protected]7c51b0ee2009-07-08 21:49:30614 // TODO(darin): Eliminate this temporary.
615 WebCursor cursor(cursor_info);
616
initial.commit09911bf2008-07-26 23:55:29617 // Only send a SetCursor message if we need to make a change.
618 if (!current_cursor_.IsEqual(cursor)) {
619 current_cursor_ = cursor;
620 Send(new ViewHostMsg_SetCursor(routing_id_, cursor));
621 }
622}
623
624// We are supposed to get a single call to Show for a newly created RenderWidget
625// that was created via RenderWidget::CreateWebView. So, we wait until this
626// point to dispatch the ShowWidget message.
627//
628// This method provides us with the information about how to display the newly
629// created RenderWidget (i.e., as a constrained popup or as a new tab).
630//
[email protected]4873c7d2009-07-16 06:36:28631void RenderWidget::show(WebNavigationPolicy) {
initial.commit09911bf2008-07-26 23:55:29632 DCHECK(!did_show_) << "received extraneous Show call";
633 DCHECK(routing_id_ != MSG_ROUTING_NONE);
634 DCHECK(opener_id_ != MSG_ROUTING_NONE);
635
636 if (!did_show_) {
637 did_show_ = true;
638 // NOTE: initial_pos_ may still have its default values at this point, but
639 // that's okay. It'll be ignored if as_popup is false, or the browser
640 // process will impose a default position otherwise.
[email protected]88efb7ec2009-07-14 16:32:59641 if (popup_params_.get()) {
642 popup_params_->bounds = initial_pos_;
643 Send(new ViewHostMsg_ShowPopup(routing_id_, *popup_params_));
644 popup_params_.reset();
645 } else {
646 Send(new ViewHostMsg_ShowWidget(opener_id_, routing_id_, initial_pos_));
647 }
[email protected]2533ce12009-05-09 00:02:24648 SetPendingWindowRect(initial_pos_);
initial.commit09911bf2008-07-26 23:55:29649 }
650}
651
[email protected]4873c7d2009-07-16 06:36:28652void RenderWidget::didFocus() {
initial.commit09911bf2008-07-26 23:55:29653 // Prevent the widget from stealing the focus if it does not have focus
654 // already. We do this by explicitely setting the focus to false again.
655 // We only let the browser focus the renderer.
656 if (!has_focus_ && webwidget_) {
657 MessageLoop::current()->PostTask(FROM_HERE,
658 NewRunnableMethod(this, &RenderWidget::ClearFocus));
659 }
660}
661
[email protected]4873c7d2009-07-16 06:36:28662void RenderWidget::didBlur() {
initial.commit09911bf2008-07-26 23:55:29663 Send(new ViewHostMsg_Blur(routing_id_));
664}
665
[email protected]2533ce12009-05-09 00:02:24666void RenderWidget::DoDeferredClose() {
667 Send(new ViewHostMsg_Close(routing_id_));
668}
669
[email protected]4873c7d2009-07-16 06:36:28670void RenderWidget::closeWidgetSoon() {
initial.commit09911bf2008-07-26 23:55:29671 // If a page calls window.close() twice, we'll end up here twice, but that's
672 // OK. It is safe to send multiple Close messages.
673
[email protected]2533ce12009-05-09 00:02:24674 // Ask the RenderWidgetHost to initiate close. We could be called from deep
675 // in Javascript. If we ask the RendwerWidgetHost to close now, the window
676 // could be closed before the JS finishes executing. So instead, post a
677 // message back to the message loop, which won't run until the JS is
678 // complete, and then the Close message can be sent.
[email protected]75ae4492009-07-10 00:05:15679 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
[email protected]2533ce12009-05-09 00:02:24680 this, &RenderWidget::DoDeferredClose));
initial.commit09911bf2008-07-26 23:55:29681}
682
[email protected]b4b967e2009-04-22 11:33:05683void RenderWidget::GenerateFullRepaint() {
[email protected]4873c7d2009-07-16 06:36:28684 didInvalidateRect(gfx::Rect(size_.width(), size_.height()));
[email protected]b4b967e2009-04-22 11:33:05685}
686
initial.commit09911bf2008-07-26 23:55:29687void RenderWidget::Close() {
688 if (webwidget_) {
[email protected]4873c7d2009-07-16 06:36:28689 webwidget_->close();
initial.commit09911bf2008-07-26 23:55:29690 webwidget_ = NULL;
691 }
692}
693
[email protected]4873c7d2009-07-16 06:36:28694WebRect RenderWidget::windowRect() {
695 if (pending_window_rect_count_)
696 return pending_window_rect_;
[email protected]2533ce12009-05-09 00:02:24697
[email protected]b3f2b912009-04-09 16:18:52698 gfx::Rect rect;
699 Send(new ViewHostMsg_GetWindowRect(routing_id_, host_window_, &rect));
[email protected]4873c7d2009-07-16 06:36:28700 return rect;
initial.commit09911bf2008-07-26 23:55:29701}
702
[email protected]4873c7d2009-07-16 06:36:28703void RenderWidget::setWindowRect(const WebRect& pos) {
initial.commit09911bf2008-07-26 23:55:29704 if (did_show_) {
705 Send(new ViewHostMsg_RequestMove(routing_id_, pos));
[email protected]2533ce12009-05-09 00:02:24706 SetPendingWindowRect(pos);
initial.commit09911bf2008-07-26 23:55:29707 } else {
708 initial_pos_ = pos;
709 }
710}
711
[email protected]2533ce12009-05-09 00:02:24712void RenderWidget::SetPendingWindowRect(const WebRect& rect) {
713 pending_window_rect_ = rect;
714 pending_window_rect_count_++;
715}
716
[email protected]4873c7d2009-07-16 06:36:28717WebRect RenderWidget::rootWindowRect() {
[email protected]2533ce12009-05-09 00:02:24718 if (pending_window_rect_count_) {
719 // NOTE(mbelshe): If there is a pending_window_rect_, then getting
720 // the RootWindowRect is probably going to return wrong results since the
721 // browser may not have processed the Move yet. There isn't really anything
722 // good to do in this case, and it shouldn't happen - since this size is
723 // only really needed for windowToScreen, which is only used for Popups.
[email protected]4873c7d2009-07-16 06:36:28724 return pending_window_rect_;
[email protected]2533ce12009-05-09 00:02:24725 }
726
[email protected]b3f2b912009-04-09 16:18:52727 gfx::Rect rect;
728 Send(new ViewHostMsg_GetRootWindowRect(routing_id_, host_window_, &rect));
[email protected]4873c7d2009-07-16 06:36:28729 return rect;
[email protected]d4547452008-08-28 18:36:37730}
731
[email protected]4873c7d2009-07-16 06:36:28732WebRect RenderWidget::windowResizerRect() {
733 return resizer_rect_;
[email protected]c04b6362008-11-21 18:54:19734}
735
initial.commit09911bf2008-07-26 23:55:29736void RenderWidget::OnImeSetInputMode(bool is_active) {
[email protected]c4bb35a2008-10-31 17:54:03737 // To prevent this renderer process from sending unnecessary IPC messages to
738 // a browser process, we permit the renderer process to send IPC messages
739 // only during the IME attached to the browser process is active.
initial.commit09911bf2008-07-26 23:55:29740 ime_is_active_ = is_active;
initial.commit09911bf2008-07-26 23:55:29741}
742
[email protected]4873c7d2009-07-16 06:36:28743void RenderWidget::OnImeSetComposition(WebCompositionCommand command,
initial.commit09911bf2008-07-26 23:55:29744 int cursor_position,
745 int target_start, int target_end,
[email protected]4873c7d2009-07-16 06:36:28746 const string16& ime_string) {
747 if (!webwidget_)
748 return;
749 ime_control_busy_ = true;
750 webwidget_->handleCompositionEvent(command, cursor_position,
751 target_start, target_end,
752 ime_string);
753 ime_control_busy_ = false;
initial.commit09911bf2008-07-26 23:55:29754}
755
[email protected]ec7dc112008-08-06 05:30:12756void RenderWidget::OnMsgRepaint(const gfx::Size& size_to_paint) {
757 // During shutdown we can just ignore this message.
758 if (!webwidget_)
759 return;
760
761 set_next_paint_is_repaint_ack();
762 gfx::Rect repaint_rect(size_to_paint.width(), size_to_paint.height());
[email protected]4873c7d2009-07-16 06:36:28763 didInvalidateRect(repaint_rect);
[email protected]ec7dc112008-08-06 05:30:12764}
765
[email protected]4873c7d2009-07-16 06:36:28766void RenderWidget::OnSetTextDirection(WebTextDirection direction) {
[email protected]07f953332009-03-25 04:31:11767 if (!webwidget_)
768 return;
[email protected]4873c7d2009-07-16 06:36:28769 webwidget_->setTextDirection(direction);
[email protected]07f953332009-03-25 04:31:11770}
771
[email protected]bee16aab2009-08-26 15:55:03772void RenderWidget::SetHidden(bool hidden) {
773 if (is_hidden_ == hidden)
774 return;
775
776 // The status has changed. Tell the RenderThread about it.
777 is_hidden_ = hidden;
778 if (is_hidden_)
779 render_thread_->WidgetHidden();
780 else
781 render_thread_->WidgetRestored();
782}
783
[email protected]699ab0d2009-04-23 23:19:14784void RenderWidget::SetBackground(const SkBitmap& background) {
785 background_ = background;
786 // Generate a full repaint.
[email protected]4873c7d2009-07-16 06:36:28787 didInvalidateRect(gfx::Rect(size_.width(), size_.height()));
[email protected]699ab0d2009-04-23 23:19:14788}
789
[email protected]674741932009-02-04 23:44:46790bool RenderWidget::next_paint_is_resize_ack() const {
791 return ViewHostMsg_PaintRect_Flags::is_resize_ack(next_paint_flags_);
792}
793
794bool RenderWidget::next_paint_is_restore_ack() const {
795 return ViewHostMsg_PaintRect_Flags::is_restore_ack(next_paint_flags_);
796}
797
798void RenderWidget::set_next_paint_is_resize_ack() {
799 next_paint_flags_ |= ViewHostMsg_PaintRect_Flags::IS_RESIZE_ACK;
800}
801
802void RenderWidget::set_next_paint_is_restore_ack() {
803 next_paint_flags_ |= ViewHostMsg_PaintRect_Flags::IS_RESTORE_ACK;
804}
805
806void RenderWidget::set_next_paint_is_repaint_ack() {
807 next_paint_flags_ |= ViewHostMsg_PaintRect_Flags::IS_REPAINT_ACK;
808}
809
initial.commit09911bf2008-07-26 23:55:29810void RenderWidget::UpdateIME() {
811 // If a browser process does not have IMEs, its IMEs are not active, or there
812 // are not any attached widgets.
813 // a renderer process does not have to retrieve information of the focused
814 // control or send notification messages to a browser process.
815 if (!ime_is_active_) {
816 return;
817 }
[email protected]34f6bc12008-11-06 07:40:53818 // Retrieve the caret position from the focused widget and verify we should
819 // enabled IMEs attached to the browser process.
820 bool enable_ime = false;
[email protected]b3f2b912009-04-09 16:18:52821 WebRect caret_rect;
[email protected]34f6bc12008-11-06 07:40:53822 if (!webwidget_ ||
[email protected]4873c7d2009-07-16 06:36:28823 !webwidget_->queryCompositionStatus(&enable_ime, &caret_rect)) {
initial.commit09911bf2008-07-26 23:55:29824 // There are not any editable widgets attached to this process.
825 // We should disable the IME to prevent it from sending CJK strings to
826 // non-editable widgets.
827 ime_control_updated_ = true;
828 ime_control_new_state_ = false;
829 }
[email protected]9f23f592008-11-17 08:36:34830 if (ime_control_new_state_ != enable_ime) {
831 ime_control_updated_ = true;
832 ime_control_new_state_ = enable_ime;
833 }
initial.commit09911bf2008-07-26 23:55:29834 if (ime_control_updated_) {
835 // The input focus has been changed.
836 // Compare the current state with the updated state and choose actions.
837 if (ime_control_enable_ime_) {
838 if (ime_control_new_state_) {
839 // Case 1: a text input -> another text input
840 // Complete the current composition and notify the caret position.
[email protected]34f6bc12008-11-06 07:40:53841 Send(new ViewHostMsg_ImeUpdateStatus(routing_id(),
842 IME_COMPLETE_COMPOSITION,
843 caret_rect));
initial.commit09911bf2008-07-26 23:55:29844 } else {
845 // Case 2: a text input -> a password input (or a static control)
846 // Complete the current composition and disable the IME.
[email protected]34f6bc12008-11-06 07:40:53847 Send(new ViewHostMsg_ImeUpdateStatus(routing_id(), IME_DISABLE,
848 caret_rect));
initial.commit09911bf2008-07-26 23:55:29849 }
850 } else {
851 if (ime_control_new_state_) {
852 // Case 3: a password input (or a static control) -> a text input
853 // Enable the IME and notify the caret position.
[email protected]34f6bc12008-11-06 07:40:53854 Send(new ViewHostMsg_ImeUpdateStatus(routing_id(),
855 IME_COMPLETE_COMPOSITION,
856 caret_rect));
initial.commit09911bf2008-07-26 23:55:29857 } else {
858 // Case 4: a password input (or a static contol) -> another password
859 // input (or another static control).
860 // The IME has been already disabled and we don't have to do anything.
861 }
862 }
863 } else {
864 // The input focus is not changed.
865 // Notify the caret position to a browser process only if it is changed.
866 if (ime_control_enable_ime_) {
[email protected]b3f2b912009-04-09 16:18:52867 if (caret_rect.x != ime_control_x_ ||
868 caret_rect.y != ime_control_y_) {
[email protected]34f6bc12008-11-06 07:40:53869 Send(new ViewHostMsg_ImeUpdateStatus(routing_id(), IME_MOVE_WINDOWS,
870 caret_rect));
initial.commit09911bf2008-07-26 23:55:29871 }
872 }
873 }
874 // Save the updated IME status to prevent from sending the same IPC messages.
875 ime_control_updated_ = false;
876 ime_control_enable_ime_ = ime_control_new_state_;
[email protected]b3f2b912009-04-09 16:18:52877 ime_control_x_ = caret_rect.x;
878 ime_control_y_ = caret_rect.y;
initial.commit09911bf2008-07-26 23:55:29879}
880
[email protected]4873c7d2009-07-16 06:36:28881WebScreenInfo RenderWidget::screenInfo() {
882 WebScreenInfo results;
883 Send(new ViewHostMsg_GetScreenInfo(routing_id_, host_window_, &results));
884 return results;
885}
886
[email protected]f103ab72009-09-02 17:10:59887void RenderWidget::SchedulePluginMove(
888 const webkit_glue::WebPluginGeometry& move) {
initial.commit09911bf2008-07-26 23:55:29889 size_t i = 0;
890 for (; i < plugin_window_moves_.size(); ++i) {
891 if (plugin_window_moves_[i].window == move.window) {
[email protected]16f89d02009-08-26 17:17:58892 if (move.rects_valid) {
893 plugin_window_moves_[i] = move;
894 } else {
895 plugin_window_moves_[i].visible = move.visible;
896 }
initial.commit09911bf2008-07-26 23:55:29897 break;
898 }
899 }
900
901 if (i == plugin_window_moves_.size())
902 plugin_window_moves_.push_back(move);
903}
[email protected]268654772009-08-06 23:02:04904
905void RenderWidget::CleanupWindowInPluginMoves(gfx::PluginWindowHandle window) {
906 for (WebPluginGeometryVector::iterator i = plugin_window_moves_.begin();
907 i != plugin_window_moves_.end(); ++i) {
908 if (i->window == window) {
909 plugin_window_moves_.erase(i);
910 break;
911 }
912 }
913}