- add sources.
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / render_widget_host_view_win.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/renderer_host/render_widget_host_view_win.h"
6
7 #include <InputScope.h>
8 #include <wtsapi32.h>
9 #pragma comment(lib, "wtsapi32.lib")
10
11 #include <algorithm>
12 #include <map>
13 #include <stack>
14
15 #include "base/basictypes.h"
16 #include "base/bind.h"
17 #include "base/callback_helpers.h"
18 #include "base/command_line.h"
19 #include "base/debug/trace_event.h"
20 #include "base/i18n/rtl.h"
21 #include "base/metrics/histogram.h"
22 #include "base/threading/thread.h"
23 #include "base/win/metro.h"
24 #include "base/win/scoped_comptr.h"
25 #include "base/win/scoped_gdi_object.h"
26 #include "base/win/win_util.h"
27 #include "base/win/windows_version.h"
28 #include "base/win/wrapped_window_proc.h"
29 #include "content/browser/accessibility/browser_accessibility_manager_win.h"
30 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
31 #include "content/browser/accessibility/browser_accessibility_win.h"
32 #include "content/browser/gpu/gpu_data_manager_impl.h"
33 #include "content/browser/gpu/gpu_process_host.h"
34 #include "content/browser/gpu/gpu_process_host_ui_shim.h"
35 #include "content/browser/renderer_host/backing_store.h"
36 #include "content/browser/renderer_host/backing_store_win.h"
37 #include "content/browser/renderer_host/input/web_input_event_builders_win.h"
38 #include "content/browser/renderer_host/render_process_host_impl.h"
39 #include "content/browser/renderer_host/render_widget_host_impl.h"
40 #include "content/browser/renderer_host/ui_events_helper.h"
41 #include "content/common/accessibility_messages.h"
42 #include "content/common/gpu/gpu_messages.h"
43 #include "content/common/plugin_constants_win.h"
44 #include "content/common/view_messages.h"
45 #include "content/common/webplugin_geometry.h"
46 #include "content/public/browser/browser_thread.h"
47 #include "content/public/browser/child_process_data.h"
48 #include "content/public/browser/content_browser_client.h"
49 #include "content/public/browser/native_web_keyboard_event.h"
50 #include "content/public/browser/notification_service.h"
51 #include "content/public/browser/notification_types.h"
52 #include "content/public/browser/render_view_host.h"
53 #include "content/public/common/content_switches.h"
54 #include "content/public/common/page_zoom.h"
55 #include "content/public/common/process_type.h"
56 #include "skia/ext/skia_utils_win.h"
57 #include "third_party/WebKit/public/web/WebCompositionUnderline.h"
58 #include "third_party/WebKit/public/web/WebInputEvent.h"
59 #include "third_party/skia/include/core/SkRegion.h"
60 #include "ui/base/ime/composition_text.h"
61 #include "ui/base/ime/win/imm32_manager.h"
62 #include "ui/base/ime/win/tsf_input_scope.h"
63 #include "ui/base/l10n/l10n_util_win.h"
64 #include "ui/base/touch/touch_device.h"
65 #include "ui/base/touch/touch_enabled.h"
66 #include "ui/base/ui_base_switches.h"
67 #include "ui/base/view_prop.h"
68 #include "ui/base/win/mouse_wheel_util.h"
69 #include "ui/base/win/touch_input.h"
70 #include "ui/events/event.h"
71 #include "ui/events/event_utils.h"
72 #include "ui/gfx/canvas.h"
73 #include "ui/gfx/rect.h"
74 #include "ui/gfx/rect_conversions.h"
75 #include "ui/gfx/screen.h"
76 #include "ui/gfx/sequential_id_generator.h"
77 #include "ui/gfx/text_elider.h"
78 #include "ui/gfx/win/dpi.h"
79 #include "ui/gfx/win/hwnd_util.h"
80 #include "webkit/common/cursors/webcursor.h"
81 #include "win8/util/win8_util.h"
82
83 using base::TimeDelta;
84 using base::TimeTicks;
85 using ui::ViewProp;
86 using WebKit::WebInputEvent;
87 using WebKit::WebMouseEvent;
88 using WebKit::WebTextDirection;
89
90 namespace content {
91 namespace {
92
93 // Tooltips will wrap after this width. Yes, wrap. Imagine that!
94 const int kTooltipMaxWidthPixels = 300;
95
96 // Maximum number of characters we allow in a tooltip.
97 const int kMaxTooltipLength = 1024;
98
99 // A custom MSAA object id used to determine if a screen reader is actively
100 // listening for MSAA events.
101 const int kIdCustom = 1;
102
103 // The delay before the compositor host window is destroyed. This gives the GPU
104 // process a grace period to stop referencing it.
105 const int kDestroyCompositorHostWindowDelay = 10000;
106
107 // In mouse lock mode, we need to prevent the (invisible) cursor from hitting
108 // the border of the view, in order to get valid movement information. However,
109 // forcing the cursor back to the center of the view after each mouse move
110 // doesn't work well. It reduces the frequency of useful WM_MOUSEMOVE messages
111 // significantly. Therefore, we move the cursor to the center of the view only
112 // if it approaches the border. |kMouseLockBorderPercentage| specifies the width
113 // of the border area, in percentage of the corresponding dimension.
114 const int kMouseLockBorderPercentage = 15;
115
116 // A callback function for EnumThreadWindows to enumerate and dismiss
117 // any owned popup windows.
118 BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) {
119   const HWND toplevel_hwnd = reinterpret_cast<HWND>(arg);
120
121   if (::IsWindowVisible(window)) {
122     const HWND owner = ::GetWindow(window, GW_OWNER);
123     if (toplevel_hwnd == owner) {
124       ::PostMessage(window, WM_CANCELMODE, 0, 0);
125     }
126   }
127
128   return TRUE;
129 }
130
131 void SendToGpuProcessHost(int gpu_host_id, scoped_ptr<IPC::Message> message) {
132   GpuProcessHost* gpu_process_host = GpuProcessHost::FromID(gpu_host_id);
133   if (!gpu_process_host)
134     return;
135
136   gpu_process_host->Send(message.release());
137 }
138
139 void PostTaskOnIOThread(const tracked_objects::Location& from_here,
140                         base::Closure task) {
141   BrowserThread::PostTask(BrowserThread::IO, from_here, task);
142 }
143
144 bool DecodeZoomGesture(HWND hwnd, const GESTUREINFO& gi,
145                        PageZoom* zoom, POINT* zoom_center) {
146   static long start = 0;
147   static POINT zoom_first;
148
149   if (gi.dwFlags == GF_BEGIN) {
150     start = gi.ullArguments;
151     zoom_first.x = gi.ptsLocation.x;
152     zoom_first.y = gi.ptsLocation.y;
153     ScreenToClient(hwnd, &zoom_first);
154     return false;
155   }
156
157   if (gi.dwFlags == GF_END)
158     return false;
159
160   POINT zoom_second = {0};
161   zoom_second.x = gi.ptsLocation.x;
162   zoom_second.y = gi.ptsLocation.y;
163   ScreenToClient(hwnd, &zoom_second);
164
165   if (zoom_first.x == zoom_second.x && zoom_first.y == zoom_second.y)
166     return false;
167
168   zoom_center->x = (zoom_first.x + zoom_second.x) / 2;
169   zoom_center->y = (zoom_first.y + zoom_second.y) / 2;
170
171   double zoom_factor =
172       static_cast<double>(gi.ullArguments)/static_cast<double>(start);
173
174   *zoom = zoom_factor >= 1 ? PAGE_ZOOM_IN : PAGE_ZOOM_OUT;
175
176   start = gi.ullArguments;
177   zoom_first = zoom_second;
178   return true;
179 }
180
181 bool DecodeScrollGesture(const GESTUREINFO& gi,
182                          POINT* start,
183                          POINT* delta){
184   // Windows gestures are streams of messages with begin/end messages that
185   // separate each new gesture. We key off the begin message to reset
186   // the static variables.
187   static POINT last_pt;
188   static POINT start_pt;
189
190   if (gi.dwFlags == GF_BEGIN) {
191     delta->x = 0;
192     delta->y = 0;
193     start_pt.x = gi.ptsLocation.x;
194     start_pt.y = gi.ptsLocation.y;
195   } else {
196     delta->x = gi.ptsLocation.x - last_pt.x;
197     delta->y = gi.ptsLocation.y - last_pt.y;
198   }
199   last_pt.x = gi.ptsLocation.x;
200   last_pt.y = gi.ptsLocation.y;
201   *start = start_pt;
202   return true;
203 }
204
205 WebKit::WebMouseWheelEvent MakeFakeScrollWheelEvent(HWND hwnd,
206                                                     POINT start,
207                                                     POINT delta) {
208   WebKit::WebMouseWheelEvent result;
209   result.type = WebInputEvent::MouseWheel;
210   result.timeStampSeconds = ::GetMessageTime() / 1000.0;
211   result.button = WebMouseEvent::ButtonNone;
212   result.globalX = start.x;
213   result.globalY = start.y;
214   // Map to window coordinates.
215   POINT client_point = { result.globalX, result.globalY };
216   MapWindowPoints(0, hwnd, &client_point, 1);
217   result.x = client_point.x;
218   result.y = client_point.y;
219   result.windowX = result.x;
220   result.windowY = result.y;
221   // Note that we support diagonal scrolling.
222   result.deltaX = static_cast<float>(delta.x);
223   result.wheelTicksX = WHEEL_DELTA;
224   result.deltaY = static_cast<float>(delta.y);
225   result.wheelTicksY = WHEEL_DELTA;
226   return result;
227 }
228
229 static const int kTouchMask = 0x7;
230
231 inline int GetTouchType(const TOUCHINPUT& point) {
232   return point.dwFlags & kTouchMask;
233 }
234
235 inline void SetTouchType(TOUCHINPUT* point, int type) {
236   point->dwFlags = (point->dwFlags & kTouchMask) | type;
237 }
238
239 ui::EventType ConvertToUIEvent(WebKit::WebTouchPoint::State t) {
240   switch (t) {
241     case WebKit::WebTouchPoint::StatePressed:
242       return ui::ET_TOUCH_PRESSED;
243     case WebKit::WebTouchPoint::StateMoved:
244       return ui::ET_TOUCH_MOVED;
245     case WebKit::WebTouchPoint::StateStationary:
246       return ui::ET_TOUCH_STATIONARY;
247     case WebKit::WebTouchPoint::StateReleased:
248       return ui::ET_TOUCH_RELEASED;
249     case WebKit::WebTouchPoint::StateCancelled:
250       return ui::ET_TOUCH_CANCELLED;
251     default:
252       DCHECK(false) << "Unexpected ui type. " << t;
253       return ui::ET_UNKNOWN;
254   }
255 }
256
257 // Creates a WebGestureEvent corresponding to the given |gesture|
258 WebKit::WebGestureEvent CreateWebGestureEvent(HWND hwnd,
259                                               const ui::GestureEvent& gesture) {
260   WebKit::WebGestureEvent gesture_event =
261       MakeWebGestureEventFromUIEvent(gesture);
262
263   POINT client_point = gesture.location().ToPOINT();
264   POINT screen_point = gesture.location().ToPOINT();
265   MapWindowPoints(hwnd, HWND_DESKTOP, &screen_point, 1);
266
267   gesture_event.x = client_point.x;
268   gesture_event.y = client_point.y;
269   gesture_event.globalX = screen_point.x;
270   gesture_event.globalY = screen_point.y;
271
272   return gesture_event;
273 }
274
275 WebKit::WebGestureEvent CreateFlingCancelEvent(double time_stamp) {
276   WebKit::WebGestureEvent gesture_event;
277   gesture_event.timeStampSeconds = time_stamp;
278   gesture_event.type = WebKit::WebGestureEvent::GestureFlingCancel;
279   gesture_event.sourceDevice = WebKit::WebGestureEvent::Touchscreen;
280   return gesture_event;
281 }
282
283 class TouchEventFromWebTouchPoint : public ui::TouchEvent {
284  public:
285   TouchEventFromWebTouchPoint(const WebKit::WebTouchPoint& touch_point,
286                               base::TimeDelta& timestamp)
287       : ui::TouchEvent(ConvertToUIEvent(touch_point.state),
288                        touch_point.position,
289                        touch_point.id,
290                        timestamp) {
291     set_radius(touch_point.radiusX, touch_point.radiusY);
292     set_rotation_angle(touch_point.rotationAngle);
293     set_force(touch_point.force);
294     set_flags(ui::GetModifiersFromKeyState());
295   }
296
297   virtual ~TouchEventFromWebTouchPoint() {}
298
299  private:
300   DISALLOW_COPY_AND_ASSIGN(TouchEventFromWebTouchPoint);
301 };
302
303 bool ShouldSendPinchGesture() {
304   static bool pinch_allowed =
305       CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnablePinch);
306   return pinch_allowed;
307 }
308
309 void GetScreenInfoForWindow(gfx::NativeViewId id,
310                             WebKit::WebScreenInfo* results) {
311   HWND window = gfx::NativeViewFromId(id);
312
313   HMONITOR monitor = MonitorFromWindow(window, MONITOR_DEFAULTTOPRIMARY);
314
315   MONITORINFOEX monitor_info;
316   monitor_info.cbSize = sizeof(MONITORINFOEX);
317   if (!base::win::GetMonitorInfoWrapper(monitor, &monitor_info))
318     return;
319
320   DEVMODE dev_mode;
321   dev_mode.dmSize = sizeof(dev_mode);
322   dev_mode.dmDriverExtra = 0;
323   EnumDisplaySettings(monitor_info.szDevice, ENUM_CURRENT_SETTINGS, &dev_mode);
324
325   WebKit::WebScreenInfo screen_info;
326   screen_info.depth = dev_mode.dmBitsPerPel;
327   screen_info.depthPerComponent = 8;
328   screen_info.deviceScaleFactor = gfx::win::GetDeviceScaleFactor();
329   screen_info.isMonochrome = dev_mode.dmColor == DMCOLOR_MONOCHROME;
330   screen_info.rect = gfx::Rect(monitor_info.rcMonitor);
331   screen_info.availableRect = gfx::Rect(monitor_info.rcWork);
332
333   *results = screen_info;
334 }
335
336 }  // namespace
337
338 const wchar_t kRenderWidgetHostHWNDClass[] = L"Chrome_RenderWidgetHostHWND";
339
340 // Wrapper for maintaining touchstate associated with a WebTouchEvent.
341 class WebTouchState {
342  public:
343   explicit WebTouchState(const RenderWidgetHostViewWin* window);
344
345   // Updates the current touchpoint state with the supplied touches.
346   // Touches will be consumed only if they are of the same type (e.g. down,
347   // up, move). Returns the number of consumed touches.
348   size_t UpdateTouchPoints(TOUCHINPUT* points, size_t count);
349
350   // Marks all active touchpoints as released.
351   bool ReleaseTouchPoints();
352
353   // The contained WebTouchEvent.
354   const WebKit::WebTouchEvent& touch_event() { return touch_event_; }
355
356   // Returns if any touches are modified in the event.
357   bool is_changed() { return touch_event_.changedTouchesLength != 0; }
358
359  private:
360   // Adds a touch point or returns NULL if there's not enough space.
361   WebKit::WebTouchPoint* AddTouchPoint(TOUCHINPUT* touch_input);
362
363   // Copy details from a TOUCHINPUT to an existing WebTouchPoint, returning
364   // true if the resulting point is a stationary move.
365   bool UpdateTouchPoint(WebKit::WebTouchPoint* touch_point,
366                         TOUCHINPUT* touch_input);
367
368   // Find (or create) a mapping for _os_touch_id_.
369   unsigned int GetMappedTouch(unsigned int os_touch_id);
370
371   // Remove any mappings that are no longer in use.
372   void RemoveExpiredMappings();
373
374   WebKit::WebTouchEvent touch_event_;
375   const RenderWidgetHostViewWin* const window_;
376
377   ui::SequentialIDGenerator id_generator_;
378
379   DISALLOW_COPY_AND_ASSIGN(WebTouchState);
380 };
381
382 typedef void (*MetroSetFrameWindow)(HWND window);
383 typedef void (*MetroCloseFrameWindow)(HWND window);
384
385 ///////////////////////////////////////////////////////////////////////////////
386 // RenderWidgetHostViewWin, public:
387
388 RenderWidgetHostViewWin::RenderWidgetHostViewWin(RenderWidgetHost* widget)
389     : render_widget_host_(RenderWidgetHostImpl::From(widget)),
390       compositor_host_window_(NULL),
391       hide_compositor_window_at_next_paint_(false),
392       track_mouse_leave_(false),
393       imm32_manager_(new ui::IMM32Manager),
394       ime_notification_(false),
395       capture_enter_key_(false),
396       about_to_validate_and_paint_(false),
397       close_on_deactivate_(false),
398       being_destroyed_(false),
399       tooltip_hwnd_(NULL),
400       tooltip_showing_(false),
401       weak_factory_(this),
402       is_loading_(false),
403       text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
404       text_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT),
405       can_compose_inline_(true),
406       is_fullscreen_(false),
407       ignore_mouse_movement_(true),
408       composition_range_(gfx::Range::InvalidRange()),
409       touch_state_(new WebTouchState(this)),
410       pointer_down_context_(false),
411       last_touch_location_(-1, -1),
412       touch_events_enabled_(ui::AreTouchEventsEnabled()),
413       gesture_recognizer_(ui::GestureRecognizer::Create()) {
414   render_widget_host_->SetView(this);
415   registrar_.Add(this,
416                  NOTIFICATION_RENDERER_PROCESS_TERMINATED,
417                  NotificationService::AllBrowserContextsAndSources());
418   gesture_recognizer_->AddGestureEventHelper(this);
419 }
420
421 RenderWidgetHostViewWin::~RenderWidgetHostViewWin() {
422   gesture_recognizer_->RemoveGestureEventHelper(this);
423   UnlockMouse();
424   ResetTooltip();
425 }
426
427 void RenderWidgetHostViewWin::CreateWnd(HWND parent) {
428   // ATL function to create the window.
429   Create(parent);
430 }
431
432 ///////////////////////////////////////////////////////////////////////////////
433 // RenderWidgetHostViewWin, RenderWidgetHostView implementation:
434
435 void RenderWidgetHostViewWin::InitAsChild(
436     gfx::NativeView parent_view) {
437   CreateWnd(parent_view);
438 }
439
440 void RenderWidgetHostViewWin::InitAsPopup(
441     RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) {
442   close_on_deactivate_ = true;
443   DoPopupOrFullscreenInit(parent_host_view->GetNativeView(), pos,
444                           WS_EX_TOOLWINDOW);
445 }
446
447 void RenderWidgetHostViewWin::InitAsFullscreen(
448     RenderWidgetHostView* reference_host_view) {
449   gfx::Rect pos = gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
450       reference_host_view->GetNativeView()).bounds();
451   is_fullscreen_ = true;
452   DoPopupOrFullscreenInit(gfx::GetWindowToParentTo(true), pos, 0);
453 }
454
455 RenderWidgetHost* RenderWidgetHostViewWin::GetRenderWidgetHost() const {
456   return render_widget_host_;
457 }
458
459 void RenderWidgetHostViewWin::WasShown() {
460   // |render_widget_host_| may be NULL if the WebContentsImpl is in the process
461   // of closing.
462   if (!render_widget_host_)
463     return;
464
465   if (!render_widget_host_->is_hidden())
466     return;
467
468   if (web_contents_switch_paint_time_.is_null())
469     web_contents_switch_paint_time_ = TimeTicks::Now();
470
471   render_widget_host_->WasShown();
472 }
473
474 void RenderWidgetHostViewWin::WasHidden() {
475   // |render_widget_host_| may be NULL if the WebContentsImpl is in the process
476   // of closing.
477   if (!render_widget_host_)
478     return;
479
480   if (render_widget_host_->is_hidden())
481     return;
482
483   ResetTooltip();
484
485   // Inform the renderer that we are being hidden so it can reduce its resource
486   // utilization.
487   render_widget_host_->WasHidden();
488
489   if (accelerated_surface_)
490     accelerated_surface_->WasHidden();
491
492   if (GetBrowserAccessibilityManager())
493     GetBrowserAccessibilityManager()->WasHidden();
494
495   web_contents_switch_paint_time_ = base::TimeTicks();
496 }
497
498 void RenderWidgetHostViewWin::SetSize(const gfx::Size& size) {
499   SetBounds(gfx::Rect(GetPixelBounds().origin(), size));
500 }
501
502 void RenderWidgetHostViewWin::SetBounds(const gfx::Rect& rect) {
503   if (being_destroyed_)
504     return;
505
506   // No SWP_NOREDRAW as autofill popups can move and the underneath window
507   // should redraw in that case.
508   UINT swp_flags = SWP_NOSENDCHANGING | SWP_NOOWNERZORDER | SWP_NOCOPYBITS |
509       SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE;
510
511   // If the style is not popup, you have to convert the point to client
512   // coordinate.
513   POINT point = { rect.x(), rect.y() };
514   if (GetStyle() & WS_CHILD)
515     ScreenToClient(&point);
516
517   SetWindowPos(NULL, point.x, point.y, rect.width(), rect.height(), swp_flags);
518   render_widget_host_->WasResized();
519 }
520
521 gfx::NativeView RenderWidgetHostViewWin::GetNativeView() const {
522   return m_hWnd;
523 }
524
525 gfx::NativeViewId RenderWidgetHostViewWin::GetNativeViewId() const {
526   return reinterpret_cast<gfx::NativeViewId>(m_hWnd);
527 }
528
529 gfx::NativeViewAccessible
530 RenderWidgetHostViewWin::GetNativeViewAccessible() {
531   if (render_widget_host_ &&
532       !BrowserAccessibilityState::GetInstance()->IsAccessibleBrowser()) {
533     // Attempt to detect screen readers by sending an event with our custom id.
534     NotifyWinEvent(EVENT_SYSTEM_ALERT, m_hWnd, kIdCustom, CHILDID_SELF);
535   }
536
537   CreateBrowserAccessibilityManagerIfNeeded();
538
539   return GetBrowserAccessibilityManager()->GetRoot()->
540       ToBrowserAccessibilityWin();
541 }
542
543 void RenderWidgetHostViewWin::CreateBrowserAccessibilityManagerIfNeeded() {
544   if (GetBrowserAccessibilityManager())
545     return;
546
547   HRESULT hr = ::CreateStdAccessibleObject(
548       m_hWnd, OBJID_WINDOW, IID_IAccessible,
549       reinterpret_cast<void **>(&window_iaccessible_));
550   DCHECK(SUCCEEDED(hr));
551
552   SetBrowserAccessibilityManager(
553       new BrowserAccessibilityManagerWin(
554           m_hWnd,
555           window_iaccessible_.get(),
556           BrowserAccessibilityManagerWin::GetEmptyDocument(),
557           this));
558 }
559
560 void RenderWidgetHostViewWin::MovePluginWindows(
561     const gfx::Vector2d& scroll_offset,
562     const std::vector<WebPluginGeometry>& plugin_window_moves) {
563   MovePluginWindowsHelper(m_hWnd, plugin_window_moves);
564 }
565
566 static BOOL CALLBACK AddChildWindowToVector(HWND hwnd, LPARAM lparam) {
567   std::vector<HWND>* vector = reinterpret_cast<std::vector<HWND>*>(lparam);
568   vector->push_back(hwnd);
569   return TRUE;
570 }
571
572 void RenderWidgetHostViewWin::CleanupCompositorWindow() {
573   if (!compositor_host_window_)
574     return;
575
576   gfx::SetWindowUserData(compositor_host_window_, NULL);
577
578   // Hide the compositor and parent it to the desktop rather than destroying
579   // it immediately. The GPU process has a grace period to stop accessing the
580   // window. TODO(apatrick): the GPU process should acknowledge that it has
581   // finished with the window handle and the browser process should destroy it
582   // at that point.
583   ::ShowWindow(compositor_host_window_, SW_HIDE);
584   ::SetParent(compositor_host_window_, NULL);
585
586   BrowserThread::PostDelayedTask(
587       BrowserThread::UI,
588       FROM_HERE,
589       base::Bind(base::IgnoreResult(&::DestroyWindow),
590                  compositor_host_window_),
591       base::TimeDelta::FromMilliseconds(kDestroyCompositorHostWindowDelay));
592
593   compositor_host_window_ = NULL;
594 }
595
596 bool RenderWidgetHostViewWin::IsActivatable() const {
597   // Popups should not be activated.
598   return popup_type_ == WebKit::WebPopupTypeNone;
599 }
600
601 void RenderWidgetHostViewWin::Focus() {
602   if (IsWindow())
603     SetFocus();
604 }
605
606 void RenderWidgetHostViewWin::Blur() {
607   NOTREACHED();
608 }
609
610 bool RenderWidgetHostViewWin::HasFocus() const {
611   return ::GetFocus() == m_hWnd;
612 }
613
614 bool RenderWidgetHostViewWin::IsSurfaceAvailableForCopy() const {
615   if (render_widget_host_->is_accelerated_compositing_active())
616     return accelerated_surface_.get() && accelerated_surface_->IsReadyForCopy();
617   else
618     return !!render_widget_host_->GetBackingStore(false);
619 }
620
621 void RenderWidgetHostViewWin::Show() {
622   ShowWindow(SW_SHOW);
623   WasShown();
624 }
625
626 void RenderWidgetHostViewWin::Hide() {
627   if (!is_fullscreen_ && GetParent() == gfx::GetWindowToParentTo(true)) {
628     LOG(WARNING) << "Hide() called twice in a row: " << this << ":"
629         << GetParent();
630     return;
631   }
632
633   if (::GetFocus() == m_hWnd)
634     ::SetFocus(NULL);
635   ShowWindow(SW_HIDE);
636
637   WasHidden();
638 }
639
640 bool RenderWidgetHostViewWin::IsShowing() {
641   return !!IsWindowVisible();
642 }
643
644 gfx::Rect RenderWidgetHostViewWin::GetViewBounds() const {
645   return gfx::win::ScreenToDIPRect(GetPixelBounds());
646 }
647
648 gfx::Rect RenderWidgetHostViewWin::GetPixelBounds() const {
649   CRect window_rect;
650   GetWindowRect(&window_rect);
651   return gfx::Rect(window_rect);
652 }
653
654 void RenderWidgetHostViewWin::UpdateCursor(const WebCursor& cursor) {
655   current_cursor_ = cursor;
656   UpdateCursorIfOverSelf();
657 }
658
659 void RenderWidgetHostViewWin::UpdateCursorIfOverSelf() {
660   static HCURSOR kCursorArrow = LoadCursor(NULL, IDC_ARROW);
661   static HCURSOR kCursorAppStarting = LoadCursor(NULL, IDC_APPSTARTING);
662   static HINSTANCE module_handle = GetModuleHandle(
663       GetContentClient()->browser()->GetResourceDllName());
664
665   // If the mouse is over our HWND, then update the cursor state immediately.
666   CPoint pt;
667   GetCursorPos(&pt);
668   if (WindowFromPoint(pt) == m_hWnd) {
669     // We cannot pass in NULL as the module handle as this would only work for
670     // standard win32 cursors. We can also receive cursor types which are
671     // defined as webkit resources. We need to specify the module handle of
672     // chrome.dll while loading these cursors.
673     HCURSOR display_cursor = current_cursor_.GetCursor(module_handle);
674
675     // If a page is in the loading state, we want to show the Arrow+Hourglass
676     // cursor only when the current cursor is the ARROW cursor. In all other
677     // cases we should continue to display the current cursor.
678     if (is_loading_ && display_cursor == kCursorArrow)
679       display_cursor = kCursorAppStarting;
680
681     SetCursor(display_cursor);
682   }
683 }
684
685 void RenderWidgetHostViewWin::SetIsLoading(bool is_loading) {
686   is_loading_ = is_loading;
687   UpdateCursorIfOverSelf();
688 }
689
690 void RenderWidgetHostViewWin::TextInputTypeChanged(
691     ui::TextInputType type,
692     ui::TextInputMode input_mode,
693     bool can_compose_inline) {
694   if (text_input_type_ != type ||
695       text_input_mode_ != input_mode ||
696       can_compose_inline_ != can_compose_inline) {
697     const bool text_input_type_changed = (text_input_type_ != type) ||
698                                          (text_input_mode_ != input_mode);
699     text_input_type_ = type;
700     text_input_mode_ = input_mode;
701     can_compose_inline_ = can_compose_inline;
702     UpdateIMEState();
703     if (text_input_type_changed)
704       UpdateInputScopeIfNecessary(text_input_type_);
705   }
706 }
707
708 void RenderWidgetHostViewWin::SelectionBoundsChanged(
709     const ViewHostMsg_SelectionBounds_Params& params) {
710   bool is_enabled = (text_input_type_ != ui::TEXT_INPUT_TYPE_NONE &&
711       text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD);
712   // Only update caret position if the input method is enabled.
713   if (is_enabled) {
714     caret_rect_ = gfx::UnionRects(params.anchor_rect, params.focus_rect);
715     imm32_manager_->UpdateCaretRect(m_hWnd, caret_rect_);
716   }
717 }
718
719 void RenderWidgetHostViewWin::ScrollOffsetChanged() {
720 }
721
722 void RenderWidgetHostViewWin::ImeCancelComposition() {
723   imm32_manager_->CancelIME(m_hWnd);
724 }
725
726 void RenderWidgetHostViewWin::ImeCompositionRangeChanged(
727     const gfx::Range& range,
728     const std::vector<gfx::Rect>& character_bounds) {
729   composition_range_ = range;
730   composition_character_bounds_ = character_bounds;
731 }
732
733 void RenderWidgetHostViewWin::Redraw() {
734   RECT damage_bounds;
735   GetUpdateRect(&damage_bounds, FALSE);
736
737   base::win::ScopedGDIObject<HRGN> damage_region(CreateRectRgn(0, 0, 0, 0));
738   GetUpdateRgn(damage_region, FALSE);
739
740   // Paint the invalid region synchronously.  Our caller will not paint again
741   // until we return, so by painting to the screen here, we ensure effective
742   // rate-limiting of backing store updates.  This helps a lot on pages that
743   // have animations or fairly expensive layout (e.g., google maps).
744   //
745   // We paint this window synchronously, however child windows (i.e. plugins)
746   // are painted asynchronously.  By avoiding synchronous cross-process window
747   // message dispatching we allow scrolling to be smooth, and also avoid the
748   // browser process locking up if the plugin process is hung.
749   //
750   RedrawWindow(NULL, damage_region, RDW_UPDATENOW | RDW_NOCHILDREN);
751
752   // Send the invalid rect in screen coordinates.
753   gfx::Rect invalid_screen_rect(damage_bounds);
754   invalid_screen_rect.Offset(GetPixelBounds().OffsetFromOrigin());
755
756   PaintPluginWindowsHelper(m_hWnd, invalid_screen_rect);
757 }
758
759 void RenderWidgetHostViewWin::DidUpdateBackingStore(
760     const gfx::Rect& scroll_rect,
761     const gfx::Vector2d& scroll_delta,
762     const std::vector<gfx::Rect>& copy_rects,
763     const ui::LatencyInfo& latency_info) {
764   TRACE_EVENT0("content", "RenderWidgetHostViewWin::DidUpdateBackingStore");
765   software_latency_info_.MergeWith(latency_info);
766   if (render_widget_host_->is_hidden())
767     return;
768
769   // Schedule invalidations first so that the ScrollWindowEx call is closer to
770   // Redraw.  That minimizes chances of "flicker" resulting if the screen
771   // refreshes before we have a chance to paint the exposed area.  Somewhat
772   // surprisingly, this ordering matters.
773
774   for (size_t i = 0; i < copy_rects.size(); ++i) {
775     gfx::Rect pixel_rect = gfx::win::DIPToScreenRect(copy_rects[i]);
776     // Damage might not be DIP aligned.
777     pixel_rect.Inset(-1, -1);
778     RECT bounds = pixel_rect.ToRECT();
779     InvalidateRect(&bounds, false);
780   }
781
782   if (!scroll_rect.IsEmpty()) {
783     TRACE_EVENT0("content", "ScrollWindowEx");
784     gfx::Rect pixel_rect = gfx::win::DIPToScreenRect(scroll_rect);
785     // Damage might not be DIP aligned.
786     pixel_rect.Inset(-1, -1);
787     RECT clip_rect = pixel_rect.ToRECT();
788     float scale = gfx::win::GetDeviceScaleFactor();
789     int dx = static_cast<int>(scale * scroll_delta.x());
790     int dy = static_cast<int>(scale * scroll_delta.y());
791     ScrollWindowEx(dx, dy, NULL, &clip_rect, NULL, NULL, SW_INVALIDATE);
792   }
793
794   if (!about_to_validate_and_paint_)
795     Redraw();
796 }
797
798 void RenderWidgetHostViewWin::RenderProcessGone(base::TerminationStatus status,
799                                                 int error_code) {
800   UpdateCursorIfOverSelf();
801   Destroy();
802 }
803
804 bool RenderWidgetHostViewWin::CanSubscribeFrame() const {
805   return render_widget_host_ != NULL;
806 }
807
808 void RenderWidgetHostViewWin::WillWmDestroy() {
809   CleanupCompositorWindow();
810   if (base::win::IsTSFAwareRequired())
811     ui::TSFBridge::GetInstance()->RemoveFocusedClient(this);
812 }
813
814 void RenderWidgetHostViewWin::Destroy() {
815   // We've been told to destroy.
816   // By clearing close_on_deactivate_, we prevent further deactivations
817   // (caused by windows messages resulting from the DestroyWindow) from
818   // triggering further destructions.  The deletion of this is handled by
819   // OnFinalMessage();
820   close_on_deactivate_ = false;
821   render_widget_host_ = NULL;
822   being_destroyed_ = true;
823   CleanupCompositorWindow();
824
825   // This releases the resources associated with input scope.
826   UpdateInputScopeIfNecessary(ui::TEXT_INPUT_TYPE_NONE);
827
828   if (is_fullscreen_ && win8::IsSingleWindowMetroMode()) {
829     MetroCloseFrameWindow close_frame_window =
830         reinterpret_cast<MetroCloseFrameWindow>(
831             ::GetProcAddress(base::win::GetMetroModule(), "CloseFrameWindow"));
832     DCHECK(close_frame_window);
833     close_frame_window(m_hWnd);
834   }
835
836   DestroyWindow();
837 }
838
839 void RenderWidgetHostViewWin::SetTooltipText(const string16& tooltip_text) {
840   if (!render_widget_host_->is_hidden())
841     EnsureTooltip();
842
843   // Clamp the tooltip length to kMaxTooltipLength so that we don't
844   // accidentally DOS the user with a mega tooltip (since Windows doesn't seem
845   // to do this itself).
846   const string16 new_tooltip_text =
847       gfx::TruncateString(tooltip_text, kMaxTooltipLength);
848
849   if (new_tooltip_text != tooltip_text_) {
850     tooltip_text_ = new_tooltip_text;
851
852     // Need to check if the tooltip is already showing so that we don't
853     // immediately show the tooltip with no delay when we move the mouse from
854     // a region with no tooltip to a region with a tooltip.
855     if (::IsWindow(tooltip_hwnd_) && tooltip_showing_) {
856       ::SendMessage(tooltip_hwnd_, TTM_POP, 0, 0);
857       ::SendMessage(tooltip_hwnd_, TTM_POPUP, 0, 0);
858     }
859   } else {
860     // Make sure the tooltip gets closed after TTN_POP gets sent. For some
861     // reason this doesn't happen automatically, so moving the mouse around
862     // within the same link/image/etc doesn't cause the tooltip to re-appear.
863     if (!tooltip_showing_) {
864       if (::IsWindow(tooltip_hwnd_))
865         ::SendMessage(tooltip_hwnd_, TTM_POP, 0, 0);
866     }
867   }
868 }
869
870 BackingStore* RenderWidgetHostViewWin::AllocBackingStore(
871     const gfx::Size& size) {
872   return new BackingStoreWin(render_widget_host_, size);
873 }
874
875 void RenderWidgetHostViewWin::CopyFromCompositingSurface(
876     const gfx::Rect& src_subrect,
877     const gfx::Size& dst_size,
878     const base::Callback<void(bool, const SkBitmap&)>& callback) {
879   base::ScopedClosureRunner scoped_callback_runner(
880       base::Bind(callback, false, SkBitmap()));
881   if (!accelerated_surface_)
882     return;
883
884   if (dst_size.IsEmpty() || src_subrect.IsEmpty())
885     return;
886
887   ignore_result(scoped_callback_runner.Release());
888   accelerated_surface_->AsyncCopyTo(src_subrect, dst_size, callback);
889 }
890
891 void RenderWidgetHostViewWin::CopyFromCompositingSurfaceToVideoFrame(
892     const gfx::Rect& src_subrect,
893     const scoped_refptr<media::VideoFrame>& target,
894     const base::Callback<void(bool)>& callback) {
895   base::ScopedClosureRunner scoped_callback_runner(base::Bind(callback, false));
896   if (!accelerated_surface_)
897     return;
898
899   if (!target || (target->format() != media::VideoFrame::YV12 &&
900                   target->format() != media::VideoFrame::I420))
901     return;
902
903   if (src_subrect.IsEmpty())
904     return;
905
906   ignore_result(scoped_callback_runner.Release());
907   accelerated_surface_->AsyncCopyToVideoFrame(src_subrect, target, callback);
908 }
909
910 bool RenderWidgetHostViewWin::CanCopyToVideoFrame() const {
911   return accelerated_surface_.get() && render_widget_host_ &&
912       render_widget_host_->is_accelerated_compositing_active();
913 }
914
915 void RenderWidgetHostViewWin::SetBackground(const SkBitmap& background) {
916   RenderWidgetHostViewBase::SetBackground(background);
917   render_widget_host_->SetBackground(background);
918 }
919
920 void RenderWidgetHostViewWin::ProcessAckedTouchEvent(
921     const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
922   DCHECK(touch_events_enabled_);
923
924   ScopedVector<ui::TouchEvent> events;
925   if (!MakeUITouchEventsFromWebTouchEvents(touch, &events, LOCAL_COORDINATES))
926     return;
927
928   ui::EventResult result = (ack_result ==
929       INPUT_EVENT_ACK_STATE_CONSUMED) ? ui::ER_HANDLED : ui::ER_UNHANDLED;
930   for (ScopedVector<ui::TouchEvent>::iterator iter = events.begin(),
931       end = events.end(); iter != end; ++iter)  {
932     scoped_ptr<ui::GestureRecognizer::Gestures> gestures;
933     gestures.reset(gesture_recognizer_->ProcessTouchEventForGesture(
934         *(*iter), result, this));
935     ProcessGestures(gestures.get());
936   }
937 }
938
939 void RenderWidgetHostViewWin::UpdateDesiredTouchMode() {
940   // Make sure that touch events even make sense.
941   if (base::win::GetVersion() < base::win::VERSION_WIN7)
942     return;
943   if (touch_events_enabled_) {
944     CHECK(RegisterTouchWindow(m_hWnd, TWF_WANTPALM));
945   }
946 }
947
948 bool RenderWidgetHostViewWin::CanDispatchToConsumer(
949     ui::GestureConsumer* consumer) {
950   CHECK_EQ(static_cast<RenderWidgetHostViewWin*>(consumer), this);
951   return true;
952 }
953
954 void RenderWidgetHostViewWin::DispatchPostponedGestureEvent(
955     ui::GestureEvent* event) {
956   ForwardGestureEventToRenderer(event);
957 }
958
959 void RenderWidgetHostViewWin::DispatchCancelTouchEvent(
960     ui::TouchEvent* event) {
961   if (!render_widget_host_ || !touch_events_enabled_ ||
962       !render_widget_host_->ShouldForwardTouchEvent()) {
963     return;
964   }
965   DCHECK(event->type() == WebKit::WebInputEvent::TouchCancel);
966   WebKit::WebTouchEvent cancel_event;
967   cancel_event.type = WebKit::WebInputEvent::TouchCancel;
968   cancel_event.timeStampSeconds = event->time_stamp().InSecondsF();
969   render_widget_host_->ForwardTouchEventWithLatencyInfo(
970       cancel_event, *event->latency());
971 }
972
973 void RenderWidgetHostViewWin::SetHasHorizontalScrollbar(
974     bool has_horizontal_scrollbar) {
975 }
976
977 void RenderWidgetHostViewWin::SetScrollOffsetPinning(
978     bool is_pinned_to_left, bool is_pinned_to_right) {
979 }
980
981 void RenderWidgetHostViewWin::SetCompositionText(
982     const ui::CompositionText& composition) {
983   if (!base::win::IsTSFAwareRequired()) {
984     NOTREACHED();
985     return;
986   }
987   if (!render_widget_host_)
988      return;
989   // ui::CompositionUnderline should be identical to
990   // WebKit::WebCompositionUnderline, so that we can do reinterpret_cast safely.
991   COMPILE_ASSERT(sizeof(ui::CompositionUnderline) ==
992                  sizeof(WebKit::WebCompositionUnderline),
993                  ui_CompositionUnderline__WebKit_WebCompositionUnderline_diff);
994   const std::vector<WebKit::WebCompositionUnderline>& underlines =
995       reinterpret_cast<const std::vector<WebKit::WebCompositionUnderline>&>(
996           composition.underlines);
997   render_widget_host_->ImeSetComposition(composition.text, underlines,
998                                          composition.selection.end(),
999                                          composition.selection.end());
1000 }
1001
1002 void RenderWidgetHostViewWin::ConfirmCompositionText()  {
1003   if (!base::win::IsTSFAwareRequired()) {
1004     NOTREACHED();
1005     return;
1006   }
1007   // TODO(nona): Implement this function.
1008   NOTIMPLEMENTED();
1009 }
1010
1011 void RenderWidgetHostViewWin::ClearCompositionText() {
1012   if (!base::win::IsTSFAwareRequired()) {
1013     NOTREACHED();
1014     return;
1015   }
1016   // TODO(nona): Implement this function.
1017   NOTIMPLEMENTED();
1018 }
1019
1020 void RenderWidgetHostViewWin::InsertText(const string16& text) {
1021   if (!base::win::IsTSFAwareRequired()) {
1022     NOTREACHED();
1023     return;
1024   }
1025   if (render_widget_host_)
1026     render_widget_host_->ImeConfirmComposition(text,
1027                                                gfx::Range::InvalidRange(),
1028                                                false);
1029 }
1030
1031 void RenderWidgetHostViewWin::InsertChar(char16 ch, int flags) {
1032   if (!base::win::IsTSFAwareRequired()) {
1033     NOTREACHED();
1034     return;
1035   }
1036   // TODO(nona): Implement this function.
1037   NOTIMPLEMENTED();
1038 }
1039
1040 gfx::NativeWindow RenderWidgetHostViewWin::GetAttachedWindow() const {
1041   return m_hWnd;
1042 }
1043
1044 ui::TextInputType RenderWidgetHostViewWin::GetTextInputType() const {
1045   if (!base::win::IsTSFAwareRequired()) {
1046     NOTREACHED();
1047     return ui::TEXT_INPUT_TYPE_NONE;
1048   }
1049   return text_input_type_;
1050 }
1051
1052 ui::TextInputMode RenderWidgetHostViewWin::GetTextInputMode() const {
1053   if (!base::win::IsTSFAwareRequired()) {
1054     NOTREACHED();
1055     return ui::TEXT_INPUT_MODE_DEFAULT;
1056   }
1057   return text_input_mode_;
1058 }
1059
1060 bool RenderWidgetHostViewWin::CanComposeInline() const {
1061   if (!base::win::IsTSFAwareRequired()) {
1062     NOTREACHED();
1063     return false;
1064   }
1065   // TODO(nona): Implement this function.
1066   NOTIMPLEMENTED();
1067   return false;
1068 }
1069
1070 gfx::Rect RenderWidgetHostViewWin::GetCaretBounds() const {
1071   if (!base::win::IsTSFAwareRequired()) {
1072     NOTREACHED();
1073     return gfx::Rect(0, 0, 0, 0);
1074   }
1075   RECT tmp_rect = caret_rect_.ToRECT();
1076   ClientToScreen(&tmp_rect);
1077   return gfx::Rect(tmp_rect);
1078 }
1079
1080 bool RenderWidgetHostViewWin::GetCompositionCharacterBounds(
1081     uint32 index, gfx::Rect* rect) const {
1082   if (!base::win::IsTSFAwareRequired()) {
1083     NOTREACHED();
1084     return false;
1085   }
1086   DCHECK(rect);
1087   if (index >= composition_character_bounds_.size())
1088     return false;
1089   RECT rec = composition_character_bounds_[index].ToRECT();
1090   ClientToScreen(&rec);
1091   *rect = gfx::Rect(rec);
1092   return true;
1093 }
1094
1095 bool RenderWidgetHostViewWin::HasCompositionText() const {
1096   if (!base::win::IsTSFAwareRequired()) {
1097     NOTREACHED();
1098     return false;
1099   }
1100   // TODO(nona): Implement this function.
1101   NOTIMPLEMENTED();
1102   return false;
1103 }
1104
1105 bool RenderWidgetHostViewWin::GetTextRange(gfx::Range* range) const {
1106   if (!base::win::IsTSFAwareRequired()) {
1107     NOTREACHED();
1108     return false;
1109   }
1110   range->set_start(selection_text_offset_);
1111   range->set_end(selection_text_offset_ + selection_text_.length());
1112   return false;
1113 }
1114
1115 bool RenderWidgetHostViewWin::GetCompositionTextRange(gfx::Range* range) const {
1116   if (!base::win::IsTSFAwareRequired()) {
1117     NOTREACHED();
1118     return false;
1119   }
1120   // TODO(nona): Implement this function.
1121   NOTIMPLEMENTED();
1122   return false;
1123 }
1124
1125 bool RenderWidgetHostViewWin::GetSelectionRange(gfx::Range* range) const {
1126   if (!base::win::IsTSFAwareRequired()) {
1127     NOTREACHED();
1128     return false;
1129   }
1130   range->set_start(selection_range_.start());
1131   range->set_end(selection_range_.end());
1132   return false;
1133 }
1134
1135 bool RenderWidgetHostViewWin::SetSelectionRange(const gfx::Range& range) {
1136   if (!base::win::IsTSFAwareRequired()) {
1137     NOTREACHED();
1138     return false;
1139   }
1140   // TODO(nona): Implement this function.
1141   NOTIMPLEMENTED();
1142   return false;
1143 }
1144
1145 bool RenderWidgetHostViewWin::DeleteRange(const gfx::Range& range) {
1146   if (!base::win::IsTSFAwareRequired()) {
1147     NOTREACHED();
1148     return false;
1149   }
1150   // TODO(nona): Implement this function.
1151   NOTIMPLEMENTED();
1152   return false;
1153 }
1154
1155 bool RenderWidgetHostViewWin::GetTextFromRange(const gfx::Range& range,
1156                                                string16* text) const {
1157   if (!base::win::IsTSFAwareRequired()) {
1158     NOTREACHED();
1159     return false;
1160   }
1161   gfx::Range selection_text_range(selection_text_offset_,
1162       selection_text_offset_ + selection_text_.length());
1163   if (!selection_text_range.Contains(range)) {
1164     text->clear();
1165     return false;
1166   }
1167   if (selection_text_range.EqualsIgnoringDirection(range)) {
1168     *text = selection_text_;
1169   } else {
1170     *text = selection_text_.substr(
1171         range.GetMin() - selection_text_offset_,
1172         range.length());
1173   }
1174   return true;
1175 }
1176
1177 void RenderWidgetHostViewWin::OnInputMethodChanged() {
1178   if (!base::win::IsTSFAwareRequired()) {
1179     NOTREACHED();
1180     return;
1181   }
1182   // TODO(nona): Implement this function.
1183   NOTIMPLEMENTED();
1184 }
1185
1186 bool RenderWidgetHostViewWin::ChangeTextDirectionAndLayoutAlignment(
1187       base::i18n::TextDirection direction) {
1188   if (!base::win::IsTSFAwareRequired()) {
1189     NOTREACHED();
1190     return false;
1191   }
1192   // TODO(nona): Implement this function.
1193   NOTIMPLEMENTED();
1194   return false;
1195 }
1196
1197 void RenderWidgetHostViewWin::ExtendSelectionAndDelete(
1198     size_t before,
1199     size_t after) {
1200   if (!base::win::IsTSFAwareRequired()) {
1201     NOTREACHED();
1202     return;
1203   }
1204   if (!render_widget_host_)
1205     return;
1206   render_widget_host_->ExtendSelectionAndDelete(before, after);
1207 }
1208
1209 void RenderWidgetHostViewWin::EnsureCaretInRect(const gfx::Rect& rect) {
1210   // TODO(nona): Implement this function.
1211   NOTIMPLEMENTED();
1212 }
1213
1214 ///////////////////////////////////////////////////////////////////////////////
1215 // RenderWidgetHostViewWin, private:
1216
1217 LRESULT RenderWidgetHostViewWin::OnCreate(CREATESTRUCT* create_struct) {
1218   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnCreate");
1219   // Call the WM_INPUTLANGCHANGE message handler to initialize the input locale
1220   // of a browser process.
1221   OnInputLangChange(0, 0);
1222   // Marks that window as supporting mouse-wheel messages rerouting so it is
1223   // scrolled when under the mouse pointer even if inactive.
1224   props_.push_back(ui::SetWindowSupportsRerouteMouseWheel(m_hWnd));
1225
1226   WTSRegisterSessionNotification(m_hWnd, NOTIFY_FOR_THIS_SESSION);
1227
1228   UpdateDesiredTouchMode();
1229   UpdateIMEState();
1230
1231   return 0;
1232 }
1233
1234 void RenderWidgetHostViewWin::OnActivate(UINT action, BOOL minimized,
1235                                          HWND window) {
1236   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnActivate");
1237   // If the container is a popup, clicking elsewhere on screen should close the
1238   // popup.
1239   if (close_on_deactivate_ && action == WA_INACTIVE) {
1240     // Send a windows message so that any derived classes
1241     // will get a change to override the default handling
1242     SendMessage(WM_CANCELMODE);
1243   }
1244 }
1245
1246 void RenderWidgetHostViewWin::OnDestroy() {
1247   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnDestroy");
1248   DetachPluginsHelper(m_hWnd);
1249
1250   props_.clear();
1251
1252   if (base::win::GetVersion() >= base::win::VERSION_WIN7 &&
1253       IsTouchWindow(m_hWnd, NULL)) {
1254     UnregisterTouchWindow(m_hWnd);
1255   }
1256
1257   CleanupCompositorWindow();
1258
1259   WTSUnRegisterSessionNotification(m_hWnd);
1260
1261   ResetTooltip();
1262   TrackMouseLeave(false);
1263 }
1264
1265 void RenderWidgetHostViewWin::OnPaint(HDC unused_dc) {
1266   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnPaint");
1267
1268   // Grab the region to paint before creation of paint_dc since it clears the
1269   // damage region.
1270   base::win::ScopedGDIObject<HRGN> damage_region(CreateRectRgn(0, 0, 0, 0));
1271   GetUpdateRgn(damage_region, FALSE);
1272
1273   CPaintDC paint_dc(m_hWnd);
1274
1275   if (!render_widget_host_)
1276     return;
1277
1278   DCHECK(render_widget_host_->GetProcess()->HasConnection());
1279
1280   // If the GPU process is rendering to a child window, compositing is
1281   // already triggered by damage to compositor_host_window_, so all we need to
1282   // do here is clear borders during resize.
1283   if (compositor_host_window_ &&
1284       render_widget_host_->is_accelerated_compositing_active()) {
1285     RECT host_rect, child_rect;
1286     GetClientRect(&host_rect);
1287     if (::GetClientRect(compositor_host_window_, &child_rect) &&
1288         (child_rect.right < host_rect.right ||
1289          child_rect.bottom < host_rect.bottom)) {
1290       paint_dc.FillRect(&host_rect,
1291           reinterpret_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)));
1292     }
1293     return;
1294   }
1295
1296   if (accelerated_surface_.get() &&
1297       render_widget_host_->is_accelerated_compositing_active()) {
1298     AcceleratedPaint(paint_dc.m_hDC);
1299     return;
1300   }
1301
1302   about_to_validate_and_paint_ = true;
1303   BackingStoreWin* backing_store = static_cast<BackingStoreWin*>(
1304       render_widget_host_->GetBackingStore(true));
1305
1306   // We initialize |paint_dc| (and thus call BeginPaint()) after calling
1307   // GetBackingStore(), so that if it updates the invalid rect we'll catch the
1308   // changes and repaint them.
1309   about_to_validate_and_paint_ = false;
1310
1311   if (compositor_host_window_ && hide_compositor_window_at_next_paint_) {
1312     ::ShowWindow(compositor_host_window_, SW_HIDE);
1313     hide_compositor_window_at_next_paint_ = false;
1314   }
1315
1316   gfx::Rect damaged_rect(paint_dc.m_ps.rcPaint);
1317   if (damaged_rect.IsEmpty())
1318     return;
1319
1320   if (backing_store) {
1321     gfx::Rect bitmap_rect(gfx::Point(),
1322                           gfx::win::DIPToScreenSize(backing_store->size()));
1323
1324     bool manage_colors = BackingStoreWin::ColorManagementEnabled();
1325     if (manage_colors)
1326       SetICMMode(paint_dc.m_hDC, ICM_ON);
1327
1328     // Blit only the damaged regions from the backing store.
1329     DWORD data_size = GetRegionData(damage_region, 0, NULL);
1330     scoped_ptr<char[]> region_data_buf;
1331     RGNDATA* region_data = NULL;
1332     RECT* region_rects = NULL;
1333
1334     if (data_size) {
1335       region_data_buf.reset(new char[data_size]);
1336       region_data = reinterpret_cast<RGNDATA*>(region_data_buf.get());
1337       region_rects = reinterpret_cast<RECT*>(region_data->Buffer);
1338       data_size = GetRegionData(damage_region, data_size, region_data);
1339     }
1340
1341     if (!data_size) {
1342       // Grabbing the damaged regions failed, fake with the whole rect.
1343       data_size = sizeof(RGNDATAHEADER) + sizeof(RECT);
1344       region_data_buf.reset(new char[data_size]);
1345       region_data = reinterpret_cast<RGNDATA*>(region_data_buf.get());
1346       region_rects = reinterpret_cast<RECT*>(region_data->Buffer);
1347       region_data->rdh.nCount = 1;
1348       region_rects[0] = damaged_rect.ToRECT();
1349     }
1350
1351     for (DWORD i = 0; i < region_data->rdh.nCount; ++i) {
1352       gfx::Rect paint_rect =
1353           gfx::IntersectRects(bitmap_rect, gfx::Rect(region_rects[i]));
1354       if (!paint_rect.IsEmpty()) {
1355         BitBlt(paint_dc.m_hDC,
1356                paint_rect.x(),
1357                paint_rect.y(),
1358                paint_rect.width(),
1359                paint_rect.height(),
1360                backing_store->hdc(),
1361                paint_rect.x(),
1362                paint_rect.y(),
1363                SRCCOPY);
1364       }
1365     }
1366
1367     if (manage_colors)
1368       SetICMMode(paint_dc.m_hDC, ICM_OFF);
1369
1370     // Fill the remaining portion of the damaged_rect with the background
1371     if (damaged_rect.right() > bitmap_rect.right()) {
1372       RECT r;
1373       r.left = std::max(bitmap_rect.right(), damaged_rect.x());
1374       r.right = damaged_rect.right();
1375       r.top = damaged_rect.y();
1376       r.bottom = std::min(bitmap_rect.bottom(), damaged_rect.bottom());
1377       DrawBackground(r, &paint_dc);
1378     }
1379     if (damaged_rect.bottom() > bitmap_rect.bottom()) {
1380       RECT r;
1381       r.left = damaged_rect.x();
1382       r.right = damaged_rect.right();
1383       r.top = std::max(bitmap_rect.bottom(), damaged_rect.y());
1384       r.bottom = damaged_rect.bottom();
1385       DrawBackground(r, &paint_dc);
1386     }
1387     if (!whiteout_start_time_.is_null()) {
1388       TimeDelta whiteout_duration = TimeTicks::Now() - whiteout_start_time_;
1389       UMA_HISTOGRAM_TIMES("MPArch.RWHH_WhiteoutDuration", whiteout_duration);
1390
1391       // Reset the start time to 0 so that we start recording again the next
1392       // time the backing store is NULL...
1393       whiteout_start_time_ = TimeTicks();
1394     }
1395     if (!web_contents_switch_paint_time_.is_null()) {
1396       TimeDelta web_contents_switch_paint_duration = TimeTicks::Now() -
1397           web_contents_switch_paint_time_;
1398       UMA_HISTOGRAM_TIMES("MPArch.RWH_TabSwitchPaintDuration",
1399           web_contents_switch_paint_duration);
1400       // Reset contents_switch_paint_time_ to 0 so future tab selections are
1401       // recorded.
1402       web_contents_switch_paint_time_ = TimeTicks();
1403     }
1404
1405     software_latency_info_.AddLatencyNumber(
1406         ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0);
1407     render_widget_host_->FrameSwapped(software_latency_info_);
1408     software_latency_info_.Clear();
1409   } else {
1410     DrawBackground(paint_dc.m_ps.rcPaint, &paint_dc);
1411     if (whiteout_start_time_.is_null())
1412       whiteout_start_time_ = TimeTicks::Now();
1413   }
1414 }
1415
1416 void RenderWidgetHostViewWin::DrawBackground(const RECT& dirty_rect,
1417                                              CPaintDC* dc) {
1418   if (!background_.empty()) {
1419     gfx::Rect dirty_area(dirty_rect);
1420     gfx::Canvas canvas(dirty_area.size(), 1.0f, true);
1421     canvas.Translate(-dirty_area.OffsetFromOrigin());
1422
1423     gfx::Rect dc_rect(dc->m_ps.rcPaint);
1424     // TODO(pkotwicz): Fix |background_| such that it is an ImageSkia.
1425     canvas.TileImageInt(gfx::ImageSkia::CreateFrom1xBitmap(background_),
1426                         0, 0, dc_rect.width(), dc_rect.height());
1427
1428     skia::DrawToNativeContext(canvas.sk_canvas(), *dc, dirty_area.x(),
1429                               dirty_area.y(), NULL);
1430   } else {
1431     HBRUSH white_brush = reinterpret_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
1432     dc->FillRect(&dirty_rect, white_brush);
1433   }
1434 }
1435
1436 void RenderWidgetHostViewWin::OnNCPaint(HRGN update_region) {
1437   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnNCPaint");
1438   // Do nothing.  This suppresses the resize corner that Windows would
1439   // otherwise draw for us.
1440 }
1441
1442 void RenderWidgetHostViewWin::SetClickthroughRegion(SkRegion* region) {
1443   transparent_region_.reset(region);
1444 }
1445
1446 LRESULT RenderWidgetHostViewWin::OnNCHitTest(const CPoint& point) {
1447   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnNCHitTest");
1448   RECT rc;
1449   GetWindowRect(&rc);
1450   if (transparent_region_.get() &&
1451       transparent_region_->contains(point.x - rc.left, point.y - rc.top)) {
1452     SetMsgHandled(TRUE);
1453     return HTTRANSPARENT;
1454   }
1455   SetMsgHandled(FALSE);
1456   return 0;
1457 }
1458
1459 LRESULT RenderWidgetHostViewWin::OnEraseBkgnd(HDC dc) {
1460   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnEraseBkgnd");
1461   return 1;
1462 }
1463
1464 LRESULT RenderWidgetHostViewWin::OnSetCursor(HWND window, UINT hittest_code,
1465                                              UINT mouse_message_id) {
1466   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnSetCursor");
1467   UpdateCursorIfOverSelf();
1468   return 0;
1469 }
1470
1471 void RenderWidgetHostViewWin::OnSetFocus(HWND window) {
1472   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnSetFocus");
1473   if (!render_widget_host_)
1474     return;
1475
1476   if (GetBrowserAccessibilityManager())
1477     GetBrowserAccessibilityManager()->GotFocus(pointer_down_context_);
1478
1479   render_widget_host_->GotFocus();
1480   render_widget_host_->SetActive(true);
1481
1482   if (base::win::IsTSFAwareRequired())
1483     ui::TSFBridge::GetInstance()->SetFocusedClient(m_hWnd, this);
1484 }
1485
1486 void RenderWidgetHostViewWin::OnKillFocus(HWND window) {
1487   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnKillFocus");
1488   if (!render_widget_host_)
1489     return;
1490
1491   render_widget_host_->SetActive(false);
1492   render_widget_host_->Blur();
1493
1494   last_touch_location_ = gfx::Point(-1, -1);
1495
1496   if (base::win::IsTSFAwareRequired())
1497     ui::TSFBridge::GetInstance()->RemoveFocusedClient(this);
1498 }
1499
1500 void RenderWidgetHostViewWin::OnCaptureChanged(HWND window) {
1501   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnCaptureChanged");
1502   if (render_widget_host_)
1503     render_widget_host_->LostCapture();
1504   pointer_down_context_ = false;
1505 }
1506
1507 void RenderWidgetHostViewWin::OnCancelMode() {
1508   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnCancelMode");
1509   if (render_widget_host_)
1510     render_widget_host_->LostCapture();
1511
1512   if ((is_fullscreen_ || close_on_deactivate_) &&
1513       !weak_factory_.HasWeakPtrs()) {
1514     // Dismiss popups and menus.  We do this asynchronously to avoid changing
1515     // activation within this callstack, which may interfere with another window
1516     // being activated.  We can synchronously hide the window, but we need to
1517     // not change activation while doing so.
1518     SetWindowPos(NULL, 0, 0, 0, 0,
1519                  SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOMOVE |
1520                  SWP_NOREPOSITION | SWP_NOSIZE | SWP_NOZORDER);
1521     base::MessageLoop::current()->PostTask(
1522         FROM_HERE,
1523         base::Bind(&RenderWidgetHostViewWin::ShutdownHost,
1524                    weak_factory_.GetWeakPtr()));
1525   }
1526 }
1527
1528 void RenderWidgetHostViewWin::OnInputLangChange(DWORD character_set,
1529                                                 HKL input_language_id) {
1530   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnInputLangChange");
1531   // Send the given Locale ID to the IMM32Manager object and retrieves whether
1532   // or not the current input context has IMEs.
1533   // If the current input context has IMEs, a browser process has to send a
1534   // request to a renderer process that it needs status messages about
1535   // the focused edit control from the renderer process.
1536   // On the other hand, if the current input context does not have IMEs, the
1537   // browser process also has to send a request to the renderer process that
1538   // it does not need the status messages any longer.
1539   // To minimize the number of this notification request, we should check if
1540   // the browser process is actually retrieving the status messages (this
1541   // state is stored in ime_notification_) and send a request only if the
1542   // browser process has to update this status, its details are listed below:
1543   // * If a browser process is not retrieving the status messages,
1544   //   (i.e. ime_notification_ == false),
1545   //   send this request only if the input context does have IMEs,
1546   //   (i.e. ime_status == true);
1547   //   When it successfully sends the request, toggle its notification status,
1548   //   (i.e.ime_notification_ = !ime_notification_ = true).
1549   // * If a browser process is retrieving the status messages
1550   //   (i.e. ime_notification_ == true),
1551   //   send this request only if the input context does not have IMEs,
1552   //   (i.e. ime_status == false).
1553   //   When it successfully sends the request, toggle its notification status,
1554   //   (i.e.ime_notification_ = !ime_notification_ = false).
1555   // To analyze the above actions, we can optimize them into the ones
1556   // listed below:
1557   // 1 Sending a request only if ime_status_ != ime_notification_, and;
1558   // 2 Copying ime_status to ime_notification_ if it sends the request
1559   //   successfully (because Action 1 shows ime_status = !ime_notification_.)
1560   bool ime_status = imm32_manager_->SetInputLanguage();
1561   if (ime_status != ime_notification_) {
1562     if (render_widget_host_) {
1563       render_widget_host_->SetInputMethodActive(ime_status);
1564       ime_notification_ = ime_status;
1565     }
1566   }
1567   // Call DefWindowProc() for consistency with other Chrome windows.
1568   // TODO(hbono): This is a speculative fix for Bug 36354 and this code may be
1569   // reverted if it does not fix it.
1570   SetMsgHandled(FALSE);
1571 }
1572
1573 void RenderWidgetHostViewWin::OnThemeChanged() {
1574   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnThemeChanged");
1575   if (!render_widget_host_)
1576     return;
1577   render_widget_host_->Send(new ViewMsg_ThemeChanged(
1578       render_widget_host_->GetRoutingID()));
1579 }
1580
1581 LRESULT RenderWidgetHostViewWin::OnNotify(int w_param, NMHDR* header) {
1582   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnNotify");
1583   if (tooltip_hwnd_ == NULL)
1584     return 0;
1585
1586   switch (header->code) {
1587     case TTN_GETDISPINFO: {
1588       NMTTDISPINFOW* tooltip_info = reinterpret_cast<NMTTDISPINFOW*>(header);
1589       tooltip_info->szText[0] = L'\0';
1590       tooltip_info->lpszText = const_cast<WCHAR*>(tooltip_text_.c_str());
1591       ::SendMessage(
1592         tooltip_hwnd_, TTM_SETMAXTIPWIDTH, 0, kTooltipMaxWidthPixels);
1593       SetMsgHandled(TRUE);
1594       break;
1595     }
1596     case TTN_POP:
1597       tooltip_showing_ = false;
1598       SetMsgHandled(TRUE);
1599       break;
1600     case TTN_SHOW:
1601       // Tooltip shouldn't be shown when the mouse is locked.
1602       DCHECK(!mouse_locked_);
1603       tooltip_showing_ = true;
1604       SetMsgHandled(TRUE);
1605       break;
1606   }
1607   return 0;
1608 }
1609
1610 LRESULT RenderWidgetHostViewWin::OnImeSetContext(
1611     UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
1612   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnImeSetContext");
1613   if (!render_widget_host_)
1614     return 0;
1615
1616   // We need status messages about the focused input control from a
1617   // renderer process when:
1618   //   * the current input context has IMEs, and;
1619   //   * an application is activated.
1620   // This seems to tell we should also check if the current input context has
1621   // IMEs before sending a request, however, this WM_IME_SETCONTEXT is
1622   // fortunately sent to an application only while the input context has IMEs.
1623   // Therefore, we just start/stop status messages according to the activation
1624   // status of this application without checks.
1625   bool activated = (wparam == TRUE);
1626   if (render_widget_host_) {
1627     render_widget_host_->SetInputMethodActive(activated);
1628     ime_notification_ = activated;
1629   }
1630
1631   if (ime_notification_)
1632     imm32_manager_->CreateImeWindow(m_hWnd);
1633
1634   imm32_manager_->CleanupComposition(m_hWnd);
1635   return imm32_manager_->SetImeWindowStyle(
1636       m_hWnd, message, wparam, lparam, &handled);
1637 }
1638
1639 LRESULT RenderWidgetHostViewWin::OnImeStartComposition(
1640     UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
1641   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnImeStartComposition");
1642   if (!render_widget_host_)
1643     return 0;
1644
1645   // Reset the composition status and create IME windows.
1646   imm32_manager_->CreateImeWindow(m_hWnd);
1647   imm32_manager_->ResetComposition(m_hWnd);
1648   // When the focus is on an element that does not draw composition by itself
1649   // (i.e., PPAPI plugin not handling IME), let IME to draw the text. Otherwise
1650   // we have to prevent WTL from calling ::DefWindowProc() because the function
1651   // calls ::ImmSetCompositionWindow() and ::ImmSetCandidateWindow() to
1652   // over-write the position of IME windows.
1653   handled = (can_compose_inline_ ? TRUE : FALSE);
1654   return 0;
1655 }
1656
1657 LRESULT RenderWidgetHostViewWin::OnImeComposition(
1658     UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
1659   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnImeComposition");
1660   if (!render_widget_host_)
1661     return 0;
1662
1663   // At first, update the position of the IME window.
1664   imm32_manager_->UpdateImeWindow(m_hWnd);
1665
1666   // ui::CompositionUnderline should be identical to
1667   // WebKit::WebCompositionUnderline, so that we can do reinterpret_cast safely.
1668   COMPILE_ASSERT(sizeof(ui::CompositionUnderline) ==
1669                  sizeof(WebKit::WebCompositionUnderline),
1670                  ui_CompositionUnderline__WebKit_WebCompositionUnderline_diff);
1671
1672   // Retrieve the result string and its attributes of the ongoing composition
1673   // and send it to a renderer process.
1674   ui::CompositionText composition;
1675   if (imm32_manager_->GetResult(m_hWnd, lparam, &composition.text)) {
1676     render_widget_host_->ImeConfirmComposition(
1677         composition.text, gfx::Range::InvalidRange(), false);
1678     imm32_manager_->ResetComposition(m_hWnd);
1679     // Fall though and try reading the composition string.
1680     // Japanese IMEs send a message containing both GCS_RESULTSTR and
1681     // GCS_COMPSTR, which means an ongoing composition has been finished
1682     // by the start of another composition.
1683   }
1684   // Retrieve the composition string and its attributes of the ongoing
1685   // composition and send it to a renderer process.
1686   if (imm32_manager_->GetComposition(m_hWnd, lparam, &composition)) {
1687     // TODO(suzhe): due to a bug of webkit, we can't use selection range with
1688     // composition string. See: https://bugs.webkit.org/show_bug.cgi?id=37788
1689     composition.selection = gfx::Range(composition.selection.end());
1690
1691     // TODO(suzhe): convert both renderer_host and renderer to use
1692     // ui::CompositionText.
1693     const std::vector<WebKit::WebCompositionUnderline>& underlines =
1694         reinterpret_cast<const std::vector<WebKit::WebCompositionUnderline>&>(
1695             composition.underlines);
1696     render_widget_host_->ImeSetComposition(
1697         composition.text, underlines,
1698         composition.selection.start(), composition.selection.end());
1699   }
1700   // We have to prevent WTL from calling ::DefWindowProc() because we do not
1701   // want for the IMM (Input Method Manager) to send WM_IME_CHAR messages.
1702   handled = TRUE;
1703   if (!can_compose_inline_) {
1704     // When the focus is on an element that does not draw composition by itself
1705     // (i.e., PPAPI plugin not handling IME), let IME to draw the text, which
1706     // is the default behavior of DefWindowProc. Note, however, even in this
1707     // case we don't want GCS_RESULTSTR to be converted to WM_IME_CHAR messages.
1708     // Thus we explicitly drop the flag.
1709     return ::DefWindowProc(m_hWnd, message, wparam, lparam & ~GCS_RESULTSTR);
1710   }
1711   return 0;
1712 }
1713
1714 LRESULT RenderWidgetHostViewWin::OnImeEndComposition(
1715     UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
1716   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnImeEndComposition");
1717   if (!render_widget_host_)
1718     return 0;
1719
1720   if (imm32_manager_->is_composing()) {
1721     // A composition has been ended while there is an ongoing composition,
1722     // i.e. the ongoing composition has been canceled.
1723     // We need to reset the composition status both of the IMM32Manager object
1724     // and of the renderer process.
1725     render_widget_host_->ImeCancelComposition();
1726     imm32_manager_->ResetComposition(m_hWnd);
1727   }
1728   imm32_manager_->DestroyImeWindow(m_hWnd);
1729   // Let WTL call ::DefWindowProc() and release its resources.
1730   handled = FALSE;
1731   return 0;
1732 }
1733
1734 LRESULT RenderWidgetHostViewWin::OnImeRequest(
1735     UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
1736   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnImeRequest");
1737   if (!render_widget_host_) {
1738     handled = FALSE;
1739     return 0;
1740   }
1741
1742   // Should not receive WM_IME_REQUEST message, if IME is disabled.
1743   if (text_input_type_ == ui::TEXT_INPUT_TYPE_NONE ||
1744       text_input_type_ == ui::TEXT_INPUT_TYPE_PASSWORD) {
1745     handled = FALSE;
1746     return 0;
1747   }
1748
1749   switch (wparam) {
1750     case IMR_RECONVERTSTRING:
1751       return OnReconvertString(reinterpret_cast<RECONVERTSTRING*>(lparam));
1752     case IMR_DOCUMENTFEED:
1753       return OnDocumentFeed(reinterpret_cast<RECONVERTSTRING*>(lparam));
1754     case IMR_QUERYCHARPOSITION:
1755       return OnQueryCharPosition(reinterpret_cast<IMECHARPOSITION*>(lparam));
1756     default:
1757       handled = FALSE;
1758       return 0;
1759   }
1760 }
1761
1762 LRESULT RenderWidgetHostViewWin::OnMouseEvent(UINT message, WPARAM wparam,
1763                                               LPARAM lparam, BOOL& handled) {
1764   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnMouseEvent");
1765   handled = TRUE;
1766
1767   if (message == WM_MOUSELEAVE)
1768     ignore_mouse_movement_ = true;
1769
1770   if (mouse_locked_) {
1771     HandleLockedMouseEvent(message, wparam, lparam);
1772     MoveCursorToCenterIfNecessary();
1773     return 0;
1774   }
1775
1776   if (::IsWindow(tooltip_hwnd_)) {
1777     // Forward mouse events through to the tooltip window
1778     MSG msg;
1779     msg.hwnd = m_hWnd;
1780     msg.message = message;
1781     msg.wParam = wparam;
1782     msg.lParam = lparam;
1783     SendMessage(tooltip_hwnd_, TTM_RELAYEVENT, NULL,
1784                 reinterpret_cast<LPARAM>(&msg));
1785   }
1786
1787   // Due to a bug in Windows, the simulated mouse events for a touch event
1788   // outside our bounds are delivered to us if we were previously focused
1789   // causing crbug.com/159982. As a workaround, we check if this event is a
1790   // simulated mouse event outside our bounds, and if so, we send it to the
1791   // right window.
1792   if ((message == WM_LBUTTONDOWN || message == WM_LBUTTONUP) &&
1793       ui::IsMouseEventFromTouch(message)) {
1794     CPoint cursor_pos(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam));
1795     ClientToScreen(&cursor_pos);
1796     if (!GetPixelBounds().Contains(cursor_pos.x, cursor_pos.y)) {
1797       HWND window = WindowFromPoint(cursor_pos);
1798       if (window) {
1799         LRESULT nc_hit_result = SendMessage(window, WM_NCHITTEST, 0,
1800             MAKELPARAM(cursor_pos.x, cursor_pos.y));
1801         const bool in_client_area = (nc_hit_result == HTCLIENT);
1802         int event_type;
1803         if (message == WM_LBUTTONDOWN)
1804           event_type = in_client_area ? WM_LBUTTONDOWN : WM_NCLBUTTONDOWN;
1805         else
1806           event_type = in_client_area ? WM_LBUTTONUP : WM_NCLBUTTONUP;
1807
1808         // Convert the coordinates to the target window.
1809         RECT window_bounds;
1810         ::GetWindowRect(window, &window_bounds);
1811         int window_x = cursor_pos.x - window_bounds.left;
1812         int window_y = cursor_pos.y - window_bounds.top;
1813         if (in_client_area) {
1814           ::PostMessage(window, event_type, wparam,
1815               MAKELPARAM(window_x, window_y));
1816         } else {
1817           ::PostMessage(window, event_type, nc_hit_result,
1818               MAKELPARAM(cursor_pos.x, cursor_pos.y));
1819         }
1820         return 0;
1821       }
1822     }
1823   }
1824
1825   // TODO(jcampan): I am not sure if we should forward the message to the
1826   // WebContentsImpl first in the case of popups.  If we do, we would need to
1827   // convert the click from the popup window coordinates to the WebContentsImpl'
1828   // window coordinates. For now we don't forward the message in that case to
1829   // address bug #907474.
1830   // Note: GetParent() on popup windows returns the top window and not the
1831   // parent the window was created with (the parent and the owner of the popup
1832   // is the first non-child view of the view that was specified to the create
1833   // call).  So the WebContentsImpl's window would have to be specified to the
1834   // RenderViewHostHWND as there is no way to retrieve it from the HWND.
1835
1836   // Don't forward if the container is a popup or fullscreen widget.
1837   if (!is_fullscreen_ && !close_on_deactivate_) {
1838     switch (message) {
1839       case WM_LBUTTONDOWN:
1840       case WM_MBUTTONDOWN:
1841       case WM_RBUTTONDOWN:
1842         // Finish the ongoing composition whenever a mouse click happens.
1843         // It matches IE's behavior.
1844         if (base::win::IsTSFAwareRequired()) {
1845           ui::TSFBridge::GetInstance()->CancelComposition();
1846         } else {
1847           imm32_manager_->CleanupComposition(m_hWnd);
1848         }
1849         // Fall through.
1850       case WM_MOUSEMOVE:
1851       case WM_MOUSELEAVE: {
1852         // Give the WebContentsImpl first crack at the message. It may want to
1853         // prevent forwarding to the renderer if some higher level browser
1854         // functionality is invoked.
1855         LPARAM parent_msg_lparam = lparam;
1856         if (message != WM_MOUSELEAVE) {
1857           // For the messages except WM_MOUSELEAVE, before forwarding them to
1858           // parent window, we should adjust cursor position from client
1859           // coordinates in current window to client coordinates in its parent
1860           // window.
1861           CPoint cursor_pos(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam));
1862           ClientToScreen(&cursor_pos);
1863           GetParent().ScreenToClient(&cursor_pos);
1864           parent_msg_lparam = MAKELPARAM(cursor_pos.x, cursor_pos.y);
1865         }
1866         if (SendMessage(GetParent(), message, wparam, parent_msg_lparam) != 0) {
1867           TRACE_EVENT0("browser", "EarlyOut_SentToParent");
1868           return 1;
1869         }
1870       }
1871     }
1872   }
1873
1874   if (message == WM_LBUTTONDOWN && pointer_down_context_ &&
1875       GetBrowserAccessibilityManager()) {
1876     GetBrowserAccessibilityManager()->GotMouseDown();
1877   }
1878
1879   if (message == WM_LBUTTONUP && ui::IsMouseEventFromTouch(message) &&
1880       base::win::IsMetroProcess())
1881     pointer_down_context_ = false;
1882
1883   ForwardMouseEventToRenderer(message, wparam, lparam);
1884   return 0;
1885 }
1886
1887 LRESULT RenderWidgetHostViewWin::OnKeyEvent(UINT message, WPARAM wparam,
1888                                             LPARAM lparam, BOOL& handled) {
1889   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnKeyEvent");
1890   handled = TRUE;
1891
1892   // When Escape is pressed, force fullscreen windows to close if necessary.
1893   if ((message == WM_KEYDOWN || message == WM_KEYUP) && wparam == VK_ESCAPE) {
1894     if (is_fullscreen_) {
1895       SendMessage(WM_CANCELMODE);
1896       return 0;
1897     }
1898   }
1899
1900   // If we are a pop-up, forward tab related messages to our parent HWND, so
1901   // that we are dismissed appropriately and so that the focus advance in our
1902   // parent.
1903   // TODO(jcampan): http://b/issue?id=1192881 Could be abstracted in the
1904   //                FocusManager.
1905   if (close_on_deactivate_ &&
1906       (((message == WM_KEYDOWN || message == WM_KEYUP) && (wparam == VK_TAB)) ||
1907         (message == WM_CHAR && wparam == L'\t'))) {
1908     // First close the pop-up.
1909     SendMessage(WM_CANCELMODE);
1910     // Then move the focus by forwarding the tab key to the parent.
1911     return ::SendMessage(GetParent(), message, wparam, lparam);
1912   }
1913
1914   if (!render_widget_host_)
1915     return 0;
1916
1917   // Bug 1845: we need to update the text direction when a user releases
1918   // either a right-shift key or a right-control key after pressing both of
1919   // them. So, we just update the text direction while a user is pressing the
1920   // keys, and we notify the text direction when a user releases either of them.
1921   // Bug 9718: http://crbug.com/9718 To investigate IE and notepad, this
1922   // shortcut is enabled only on a PC having RTL keyboard layouts installed.
1923   // We should emulate them.
1924   if (ui::IMM32Manager::IsRTLKeyboardLayoutInstalled()) {
1925     if (message == WM_KEYDOWN) {
1926       if (wparam == VK_SHIFT) {
1927         base::i18n::TextDirection dir;
1928         if (ui::IMM32Manager::IsCtrlShiftPressed(&dir)) {
1929           render_widget_host_->UpdateTextDirection(
1930               dir == base::i18n::RIGHT_TO_LEFT ?
1931               WebKit::WebTextDirectionRightToLeft :
1932               WebKit::WebTextDirectionLeftToRight);
1933         }
1934       } else if (wparam != VK_CONTROL) {
1935         // Bug 9762: http://crbug.com/9762 A user pressed a key except shift
1936         // and control keys.
1937         // When a user presses a key while he/she holds control and shift keys,
1938         // we cancel sending an IPC message in NotifyTextDirection() below and
1939         // ignore succeeding UpdateTextDirection() calls while we call
1940         // NotifyTextDirection().
1941         // To cancel it, this call set a flag that prevents sending an IPC
1942         // message in NotifyTextDirection() only if we are going to send it.
1943         // It is harmless to call this function if we aren't going to send it.
1944         render_widget_host_->CancelUpdateTextDirection();
1945       }
1946     } else if (message == WM_KEYUP &&
1947                (wparam == VK_SHIFT || wparam == VK_CONTROL)) {
1948       // We send an IPC message only if we need to update the text direction.
1949       render_widget_host_->NotifyTextDirection();
1950     }
1951   }
1952
1953   // Special processing for enter key: When user hits enter in omnibox
1954   // we change focus to render host after the navigation, so repeat WM_KEYDOWNs
1955   // and WM_KEYUP are going to render host, despite being initiated in other
1956   // window. This code filters out these messages.
1957   bool ignore_keyboard_event = false;
1958   if (wparam == VK_RETURN) {
1959     if (message == WM_KEYDOWN || message == WM_SYSKEYDOWN) {
1960       if (KF_REPEAT & HIWORD(lparam)) {
1961         // this is a repeated key
1962         if (!capture_enter_key_)
1963           ignore_keyboard_event = true;
1964       } else {
1965         capture_enter_key_ = true;
1966       }
1967     } else if (message == WM_KEYUP || message == WM_SYSKEYUP) {
1968       if (!capture_enter_key_)
1969         ignore_keyboard_event = true;
1970       capture_enter_key_ = false;
1971     } else {
1972       // Ignore all other keyboard events for the enter key if not captured.
1973       if (!capture_enter_key_)
1974         ignore_keyboard_event = true;
1975     }
1976   }
1977
1978   if (render_widget_host_ && !ignore_keyboard_event) {
1979     MSG msg = { m_hWnd, message, wparam, lparam };
1980     render_widget_host_->ForwardKeyboardEvent(NativeWebKeyboardEvent(msg));
1981   }
1982
1983   return 0;
1984 }
1985
1986 LRESULT RenderWidgetHostViewWin::OnWheelEvent(UINT message, WPARAM wparam,
1987                                               LPARAM lparam, BOOL& handled) {
1988   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnWheelEvent");
1989   // Forward the mouse-wheel message to the window under the mouse if it belongs
1990   // to us.
1991   if (message == WM_MOUSEWHEEL &&
1992       ui::RerouteMouseWheel(m_hWnd, wparam, lparam)) {
1993     handled = TRUE;
1994     return 0;
1995   }
1996
1997   // We get mouse wheel/scroll messages even if we are not in the foreground.
1998   // So here we check if we have any owned popup windows in the foreground and
1999   // dismiss them.
2000   if (m_hWnd != GetForegroundWindow()) {
2001     HWND toplevel_hwnd = ::GetAncestor(m_hWnd, GA_ROOT);
2002     EnumThreadWindows(
2003         GetCurrentThreadId(),
2004         DismissOwnedPopups,
2005         reinterpret_cast<LPARAM>(toplevel_hwnd));
2006   }
2007
2008   if (render_widget_host_) {
2009     WebKit::WebMouseWheelEvent wheel_event =
2010         WebMouseWheelEventBuilder::Build(m_hWnd, message, wparam, lparam);
2011     float scale = gfx::win::GetDeviceScaleFactor();
2012     wheel_event.x /= scale;
2013     wheel_event.y /= scale;
2014     wheel_event.deltaX /= scale;
2015     wheel_event.deltaY /= scale;
2016
2017     render_widget_host_->ForwardWheelEvent(wheel_event);
2018   }
2019   handled = TRUE;
2020   return 0;
2021 }
2022
2023 WebTouchState::WebTouchState(const RenderWidgetHostViewWin* window)
2024     : window_(window),
2025       id_generator_(0) {
2026 }
2027
2028 size_t WebTouchState::UpdateTouchPoints(
2029     TOUCHINPUT* points, size_t count) {
2030   // First we reset all touch event state. This involves removing any released
2031   // touchpoints and marking the rest as stationary. After that we go through
2032   // and alter/add any touchpoints (from the touch input buffer) that we can
2033   // coalesce into a single message. The return value is the number of consumed
2034   // input message.
2035   WebKit::WebTouchPoint* point = touch_event_.touches;
2036   WebKit::WebTouchPoint* end = point + touch_event_.touchesLength;
2037   while (point < end) {
2038     if (point->state == WebKit::WebTouchPoint::StateReleased) {
2039       *point = *(--end);
2040       --touch_event_.touchesLength;
2041     } else {
2042       point->state = WebKit::WebTouchPoint::StateStationary;
2043       point++;
2044     }
2045   }
2046   touch_event_.changedTouchesLength = 0;
2047   touch_event_.modifiers = content::EventFlagsToWebEventModifiers(
2048       ui::GetModifiersFromKeyState());
2049
2050   // Consume all events of the same type and add them to the changed list.
2051   int last_type = 0;
2052   for (size_t i = 0; i < count; ++i) {
2053     unsigned int mapped_id = GetMappedTouch(points[i].dwID);
2054
2055     WebKit::WebTouchPoint* point = NULL;
2056     for (unsigned j = 0; j < touch_event_.touchesLength; ++j) {
2057       if (static_cast<DWORD>(touch_event_.touches[j].id) == mapped_id) {
2058         point =  &touch_event_.touches[j];
2059         break;
2060       }
2061     }
2062
2063     // Use a move instead if we see a down on a point we already have.
2064     int type = GetTouchType(points[i]);
2065     if (point && type == TOUCHEVENTF_DOWN)
2066       SetTouchType(&points[i], TOUCHEVENTF_MOVE);
2067
2068     // Stop processing when the event type changes.
2069     if (touch_event_.changedTouchesLength && type != last_type)
2070       return i;
2071
2072     touch_event_.timeStampSeconds = points[i].dwTime / 1000.0;
2073
2074     last_type = type;
2075     switch (type) {
2076       case TOUCHEVENTF_DOWN: {
2077         if (!(point = AddTouchPoint(&points[i])))
2078           continue;
2079         touch_event_.type = WebKit::WebInputEvent::TouchStart;
2080         break;
2081       }
2082
2083       case TOUCHEVENTF_UP: {
2084         if (!point)  // Just throw away a stray up.
2085           continue;
2086         point->state = WebKit::WebTouchPoint::StateReleased;
2087         UpdateTouchPoint(point, &points[i]);
2088         touch_event_.type = WebKit::WebInputEvent::TouchEnd;
2089         break;
2090       }
2091
2092       case TOUCHEVENTF_MOVE: {
2093         if (point) {
2094           point->state = WebKit::WebTouchPoint::StateMoved;
2095           // Don't update the message if the point didn't really move.
2096           if (UpdateTouchPoint(point, &points[i]))
2097             continue;
2098           touch_event_.type = WebKit::WebInputEvent::TouchMove;
2099         } else if (touch_event_.changedTouchesLength) {
2100           RemoveExpiredMappings();
2101           // Can't add a point if we're already handling move events.
2102           return i;
2103         } else {
2104           // Treat a move with no existing point as a down.
2105           if (!(point = AddTouchPoint(&points[i])))
2106             continue;
2107           last_type = TOUCHEVENTF_DOWN;
2108           SetTouchType(&points[i], TOUCHEVENTF_DOWN);
2109           touch_event_.type = WebKit::WebInputEvent::TouchStart;
2110         }
2111         break;
2112       }
2113
2114       default:
2115         NOTREACHED();
2116         continue;
2117     }
2118     touch_event_.changedTouches[touch_event_.changedTouchesLength++] = *point;
2119   }
2120
2121   RemoveExpiredMappings();
2122   return count;
2123 }
2124
2125 void WebTouchState::RemoveExpiredMappings() {
2126   WebKit::WebTouchPoint* point = touch_event_.touches;
2127   WebKit::WebTouchPoint* end = point + touch_event_.touchesLength;
2128   for (; point < end; ++point) {
2129     if (point->state == WebKit::WebTouchPoint::StateReleased)
2130       id_generator_.ReleaseGeneratedID(point->id);
2131   }
2132 }
2133
2134
2135 bool WebTouchState::ReleaseTouchPoints() {
2136   if (touch_event_.touchesLength == 0)
2137     return false;
2138   // Mark every active touchpoint as released.
2139   touch_event_.type = WebKit::WebInputEvent::TouchEnd;
2140   touch_event_.changedTouchesLength = touch_event_.touchesLength;
2141   for (unsigned int i = 0; i < touch_event_.touchesLength; ++i) {
2142     touch_event_.touches[i].state = WebKit::WebTouchPoint::StateReleased;
2143     touch_event_.changedTouches[i].state =
2144         WebKit::WebTouchPoint::StateReleased;
2145   }
2146
2147   return true;
2148 }
2149
2150 WebKit::WebTouchPoint* WebTouchState::AddTouchPoint(
2151     TOUCHINPUT* touch_input) {
2152   DCHECK(touch_event_.touchesLength <
2153       WebKit::WebTouchEvent::touchesLengthCap);
2154   if (touch_event_.touchesLength >=
2155       WebKit::WebTouchEvent::touchesLengthCap)
2156     return NULL;
2157   WebKit::WebTouchPoint* point =
2158       &touch_event_.touches[touch_event_.touchesLength++];
2159   point->state = WebKit::WebTouchPoint::StatePressed;
2160   point->id = GetMappedTouch(touch_input->dwID);
2161   UpdateTouchPoint(point, touch_input);
2162   return point;
2163 }
2164
2165 bool WebTouchState::UpdateTouchPoint(
2166     WebKit::WebTouchPoint* touch_point,
2167     TOUCHINPUT* touch_input) {
2168   CPoint coordinates(
2169       TOUCH_COORD_TO_PIXEL(touch_input->x) /
2170       gfx::win::GetUndocumentedDPITouchScale(),
2171       TOUCH_COORD_TO_PIXEL(touch_input->y) /
2172       gfx::win::GetUndocumentedDPITouchScale());
2173   int radius_x = 1;
2174   int radius_y = 1;
2175   if (touch_input->dwMask & TOUCHINPUTMASKF_CONTACTAREA) {
2176     // Some touch drivers send a contact area of "-1", yet flag it as valid.
2177     radius_x = std::max(1,
2178         static_cast<int>(TOUCH_COORD_TO_PIXEL(touch_input->cxContact) /
2179                          gfx::win::GetUndocumentedDPITouchScale()));
2180     radius_y = std::max(1,
2181         static_cast<int>(TOUCH_COORD_TO_PIXEL(touch_input->cyContact) /
2182                          gfx::win::GetUndocumentedDPITouchScale()));
2183   }
2184
2185   // Detect and exclude stationary moves.
2186   if (GetTouchType(*touch_input) == TOUCHEVENTF_MOVE &&
2187       touch_point->screenPosition.x == coordinates.x &&
2188       touch_point->screenPosition.y == coordinates.y &&
2189       touch_point->radiusX == radius_x &&
2190       touch_point->radiusY == radius_y) {
2191     touch_point->state = WebKit::WebTouchPoint::StateStationary;
2192     return true;
2193   }
2194
2195   touch_point->screenPosition.x = coordinates.x;
2196   touch_point->screenPosition.y = coordinates.y;
2197   window_->ScreenToClient(&coordinates);
2198   static float scale = gfx::win::GetDeviceScaleFactor();
2199   touch_point->position.x = coordinates.x / scale;
2200   touch_point->position.y = coordinates.y / scale;
2201   touch_point->radiusX = radius_x;
2202   touch_point->radiusY = radius_y;
2203   touch_point->force = 0;
2204   touch_point->rotationAngle = 0;
2205   return false;
2206 }
2207
2208 // Find (or create) a mapping for _os_touch_id_.
2209 unsigned int WebTouchState::GetMappedTouch(unsigned int os_touch_id) {
2210   return id_generator_.GetGeneratedID(os_touch_id);
2211 }
2212
2213 LRESULT RenderWidgetHostViewWin::OnTouchEvent(UINT message, WPARAM wparam,
2214                                               LPARAM lparam, BOOL& handled) {
2215   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnTouchEvent");
2216   // Finish the ongoing composition whenever a touch event happens.
2217   // It matches IE's behavior.
2218   if (base::win::IsTSFAwareRequired()) {
2219     ui::TSFBridge::GetInstance()->CancelComposition();
2220   } else {
2221     imm32_manager_->CleanupComposition(m_hWnd);
2222   }
2223
2224   // TODO(jschuh): Add support for an arbitrary number of touchpoints.
2225   size_t total = std::min(static_cast<int>(LOWORD(wparam)),
2226       static_cast<int>(WebKit::WebTouchEvent::touchesLengthCap));
2227   TOUCHINPUT points[WebKit::WebTouchEvent::touchesLengthCap];
2228
2229   if (!total || !ui::GetTouchInputInfoWrapper((HTOUCHINPUT)lparam, total,
2230                                               points, sizeof(TOUCHINPUT))) {
2231     TRACE_EVENT0("browser", "EarlyOut_NothingToDo");
2232     return 0;
2233   }
2234
2235   if (total == 1 && (points[0].dwFlags & TOUCHEVENTF_DOWN)) {
2236     pointer_down_context_ = true;
2237     last_touch_location_ = gfx::Point(
2238         TOUCH_COORD_TO_PIXEL(points[0].x) /
2239         gfx::win::GetUndocumentedDPITouchScale(),
2240         TOUCH_COORD_TO_PIXEL(points[0].y) /
2241         gfx::win::GetUndocumentedDPITouchScale());
2242   }
2243
2244   bool should_forward = render_widget_host_->ShouldForwardTouchEvent() &&
2245       touch_events_enabled_;
2246
2247   // Send a copy of the touch events on to the gesture recognizer.
2248   for (size_t start = 0; start < total;) {
2249     start += touch_state_->UpdateTouchPoints(points + start, total - start);
2250     if (should_forward) {
2251       if (touch_state_->is_changed())
2252         render_widget_host_->ForwardTouchEventWithLatencyInfo(
2253             touch_state_->touch_event(), ui::LatencyInfo());
2254     } else {
2255       const WebKit::WebTouchEvent& touch_event = touch_state_->touch_event();
2256       base::TimeDelta timestamp = base::TimeDelta::FromMilliseconds(
2257           touch_event.timeStampSeconds * 1000);
2258       for (size_t i = 0; i < touch_event.touchesLength; ++i) {
2259         scoped_ptr<ui::GestureRecognizer::Gestures> gestures;
2260         gestures.reset(gesture_recognizer_->ProcessTouchEventForGesture(
2261             TouchEventFromWebTouchPoint(touch_event.touches[i], timestamp),
2262             ui::ER_UNHANDLED, this));
2263         ProcessGestures(gestures.get());
2264       }
2265     }
2266   }
2267
2268   CloseTouchInputHandle((HTOUCHINPUT)lparam);
2269
2270   return 0;
2271 }
2272
2273 void RenderWidgetHostViewWin::ProcessGestures(
2274     ui::GestureRecognizer::Gestures* gestures) {
2275   if ((gestures == NULL) || gestures->empty())
2276     return;
2277   for (ui::GestureRecognizer::Gestures::iterator g_it = gestures->begin();
2278       g_it != gestures->end();
2279       ++g_it) {
2280     ForwardGestureEventToRenderer(*g_it);
2281   }
2282 }
2283
2284 LRESULT RenderWidgetHostViewWin::OnMouseActivate(UINT message,
2285                                                  WPARAM wparam,
2286                                                  LPARAM lparam,
2287                                                  BOOL& handled) {
2288   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnMouseActivate");
2289   if (!render_widget_host_)
2290     return MA_NOACTIVATE;
2291
2292   if (!IsActivatable())
2293     return MA_NOACTIVATE;
2294
2295   HWND focus_window = GetFocus();
2296   if (!::IsWindow(focus_window) || !IsChild(focus_window)) {
2297     // We handle WM_MOUSEACTIVATE to set focus to the underlying plugin
2298     // child window. This is to ensure that keyboard events are received
2299     // by the plugin. The correct way to fix this would be send over
2300     // an event to the renderer which would then eventually send over
2301     // a setFocus call to the plugin widget. This would ensure that
2302     // the renderer (webkit) knows about the plugin widget receiving
2303     // focus.
2304     // TODO(iyengar) Do the right thing as per the above comment.
2305     POINT cursor_pos = {0};
2306     ::GetCursorPos(&cursor_pos);
2307     ::ScreenToClient(m_hWnd, &cursor_pos);
2308     HWND child_window = ::RealChildWindowFromPoint(m_hWnd, cursor_pos);
2309     if (::IsWindow(child_window) && child_window != m_hWnd) {
2310       if (gfx::GetClassName(child_window) == kWrapperNativeWindowClassName)
2311         child_window = ::GetWindow(child_window, GW_CHILD);
2312
2313       ::SetFocus(child_window);
2314       return MA_NOACTIVATE;
2315     }
2316   }
2317   handled = FALSE;
2318   render_widget_host_->OnPointerEventActivate();
2319   return MA_ACTIVATE;
2320 }
2321
2322 LRESULT RenderWidgetHostViewWin::OnGestureEvent(
2323       UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
2324   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnGestureEvent");
2325
2326   DCHECK(!touch_events_enabled_);
2327   handled = FALSE;
2328
2329   GESTUREINFO gi = {sizeof(GESTUREINFO)};
2330   HGESTUREINFO gi_handle = reinterpret_cast<HGESTUREINFO>(lparam);
2331   if (!::GetGestureInfo(gi_handle, &gi)) {
2332     DWORD error = GetLastError();
2333     NOTREACHED() << "Unable to get gesture info. Error : " << error;
2334     return 0;
2335   }
2336
2337   if (gi.dwID == GID_ZOOM) {
2338     PageZoom zoom = PAGE_ZOOM_RESET;
2339     POINT zoom_center = {0};
2340     if (DecodeZoomGesture(m_hWnd, gi, &zoom, &zoom_center)) {
2341       handled = TRUE;
2342       Send(new ViewMsg_ZoomFactor(render_widget_host_->GetRoutingID(),
2343                                   zoom, zoom_center.x, zoom_center.y));
2344     }
2345   } else if (gi.dwID == GID_PAN) {
2346     // Right now we only decode scroll gestures and we forward to the page
2347     // as scroll events.
2348     POINT start;
2349     POINT delta;
2350     if (DecodeScrollGesture(gi, &start, &delta)) {
2351       handled = TRUE;
2352       render_widget_host_->ForwardWheelEvent(
2353           MakeFakeScrollWheelEvent(m_hWnd, start, delta));
2354     }
2355   }
2356   ::CloseGestureInfoHandle(gi_handle);
2357   return 0;
2358 }
2359
2360 LRESULT RenderWidgetHostViewWin::OnMoveOrSize(
2361     UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
2362   // Reset the cliping rectangle if the mouse is locked.
2363   if (mouse_locked_) {
2364     CRect rect;
2365     GetWindowRect(&rect);
2366     ::ClipCursor(&rect);
2367   }
2368   return 0;
2369 }
2370
2371 void RenderWidgetHostViewWin::OnAccessibilityEvents(
2372     const std::vector<AccessibilityHostMsg_EventParams>& params) {
2373   CreateBrowserAccessibilityManagerIfNeeded();
2374   GetBrowserAccessibilityManager()->OnAccessibilityEvents(params);
2375 }
2376
2377 bool RenderWidgetHostViewWin::LockMouse() {
2378   if (mouse_locked_)
2379     return true;
2380
2381   mouse_locked_ = true;
2382
2383   // Hide the tooltip window if it is currently visible. When the mouse is
2384   // locked, no mouse message is relayed to the tooltip window, so we don't need
2385   // to worry that it will reappear.
2386   if (::IsWindow(tooltip_hwnd_) && tooltip_showing_) {
2387     ::SendMessage(tooltip_hwnd_, TTM_POP, 0, 0);
2388     // Sending a TTM_POP message doesn't seem to actually hide the tooltip
2389     // window, although we will receive a TTN_POP notification. As a result,
2390     // ShowWindow() is explicitly called to hide the window.
2391     ::ShowWindow(tooltip_hwnd_, SW_HIDE);
2392   }
2393
2394   // TODO(yzshen): ShowCursor(FALSE) causes SetCursorPos() to be ignored on
2395   // Remote Desktop.
2396   ::ShowCursor(FALSE);
2397
2398   move_to_center_request_.pending = false;
2399   last_mouse_position_.locked_global = last_mouse_position_.unlocked_global;
2400
2401   // Must set the clip rectangle before MoveCursorToCenterIfNecessary()
2402   // so that if the cursor is moved it uses the clip rect set to the window
2403   // rect. Otherwise, MoveCursorToCenterIfNecessary() may move the cursor
2404   // to the center of the screen, and then we would clip to the window
2405   // rect, thus moving the cursor and causing a movement delta.
2406   CRect rect;
2407   GetWindowRect(&rect);
2408   ::ClipCursor(&rect);
2409   MoveCursorToCenterIfNecessary();
2410
2411   return true;
2412 }
2413
2414 void RenderWidgetHostViewWin::UnlockMouse() {
2415   if (!mouse_locked_)
2416     return;
2417
2418   mouse_locked_ = false;
2419
2420   ::ClipCursor(NULL);
2421   ::SetCursorPos(last_mouse_position_.unlocked_global.x(),
2422                  last_mouse_position_.unlocked_global.y());
2423   ::ShowCursor(TRUE);
2424
2425   if (render_widget_host_)
2426     render_widget_host_->LostMouseLock();
2427 }
2428
2429 void RenderWidgetHostViewWin::Observe(
2430     int type,
2431     const NotificationSource& source,
2432     const NotificationDetails& details) {
2433   DCHECK(type == NOTIFICATION_RENDERER_PROCESS_TERMINATED);
2434
2435   // Get the RenderProcessHost that posted this notification, and exit
2436   // if it's not the one associated with this host view.
2437   RenderProcessHost* render_process_host =
2438       Source<RenderProcessHost>(source).ptr();
2439   DCHECK(render_process_host);
2440   if (!render_widget_host_ ||
2441       render_process_host != render_widget_host_->GetProcess()) {
2442     return;
2443   }
2444
2445   // If it was our RenderProcessHost that posted the notification,
2446   // clear the BrowserAccessibilityManager, because the renderer is
2447   // dead and any accessibility information we have is now stale.
2448   SetBrowserAccessibilityManager(NULL);
2449 }
2450
2451 static void PaintCompositorHostWindow(HWND hWnd) {
2452   PAINTSTRUCT paint;
2453   BeginPaint(hWnd, &paint);
2454
2455   RenderWidgetHostViewWin* win = static_cast<RenderWidgetHostViewWin*>(
2456       gfx::GetWindowUserData(hWnd));
2457   // Trigger composite to rerender window.
2458   if (win)
2459     win->AcceleratedPaint(paint.hdc);
2460
2461   EndPaint(hWnd, &paint);
2462 }
2463
2464 // WndProc for the compositor host window. We use this instead of Default so
2465 // we can drop WM_PAINT and WM_ERASEBKGD messages on the floor.
2466 static LRESULT CALLBACK CompositorHostWindowProc(HWND hWnd, UINT message,
2467                                                  WPARAM wParam, LPARAM lParam) {
2468   switch (message) {
2469   case WM_ERASEBKGND:
2470     return 0;
2471   case WM_PAINT:
2472     PaintCompositorHostWindow(hWnd);
2473     return 0;
2474   default:
2475     return DefWindowProc(hWnd, message, wParam, lParam);
2476   }
2477 }
2478
2479 void RenderWidgetHostViewWin::AcceleratedPaint(HDC dc) {
2480   if (render_widget_host_)
2481     render_widget_host_->ScheduleComposite();
2482   if (accelerated_surface_)
2483     accelerated_surface_->Present(dc);
2484 }
2485
2486 void RenderWidgetHostViewWin::GetScreenInfo(WebKit::WebScreenInfo* results) {
2487   GetScreenInfoForWindow(GetNativeViewId(), results);
2488 }
2489
2490 gfx::Rect RenderWidgetHostViewWin::GetBoundsInRootWindow() {
2491   RECT window_rect = {0};
2492   HWND root_window = GetAncestor(m_hWnd, GA_ROOT);
2493   ::GetWindowRect(root_window, &window_rect);
2494   gfx::Rect rect(window_rect);
2495
2496   // Maximized windows are outdented from the work area by the frame thickness
2497   // even though this "frame" is not painted.  This confuses code (and people)
2498   // that think of a maximized window as corresponding exactly to the work area.
2499   // Correct for this by subtracting the frame thickness back off.
2500   if (::IsZoomed(root_window)) {
2501     rect.Inset(GetSystemMetrics(SM_CXSIZEFRAME),
2502                GetSystemMetrics(SM_CYSIZEFRAME));
2503   }
2504
2505   return gfx::win::ScreenToDIPRect(rect);
2506 }
2507
2508 // Creates a HWND within the RenderWidgetHostView that will serve as a host
2509 // for a HWND that the GPU process will create. The host window is used
2510 // to Z-position the GPU's window relative to other plugin windows.
2511 gfx::GLSurfaceHandle RenderWidgetHostViewWin::GetCompositingSurface() {
2512   // If the window has been created, don't recreate it a second time
2513   if (compositor_host_window_)
2514     return gfx::GLSurfaceHandle(compositor_host_window_, gfx::NATIVE_TRANSPORT);
2515
2516   // On Vista and later we present directly to the view window rather than a
2517   // child window.
2518   if (GpuDataManagerImpl::GetInstance()->IsUsingAcceleratedSurface()) {
2519     if (!accelerated_surface_)
2520       accelerated_surface_.reset(new AcceleratedSurface(m_hWnd));
2521     return gfx::GLSurfaceHandle(m_hWnd, gfx::NATIVE_TRANSPORT);
2522   }
2523
2524   // On XP we need a child window that can be resized independently of the
2525   // parent.
2526   static ATOM atom = 0;
2527   static HMODULE instance = NULL;
2528   if (!atom) {
2529     WNDCLASSEX window_class;
2530     base::win::InitializeWindowClass(
2531         L"CompositorHostWindowClass",
2532         &base::win::WrappedWindowProc<CompositorHostWindowProc>,
2533         0, 0, 0, NULL, NULL, NULL, NULL, NULL,
2534         &window_class);
2535     instance = window_class.hInstance;
2536     atom = RegisterClassEx(&window_class);
2537     DCHECK(atom);
2538   }
2539
2540   RECT currentRect;
2541   GetClientRect(&currentRect);
2542
2543   // Ensure window does not have zero area because D3D cannot create a zero
2544   // area swap chain.
2545   int width = std::max(1,
2546       static_cast<int>(currentRect.right - currentRect.left));
2547   int height = std::max(1,
2548       static_cast<int>(currentRect.bottom - currentRect.top));
2549
2550   compositor_host_window_ = CreateWindowEx(
2551       WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR,
2552       MAKEINTATOM(atom), 0,
2553       WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_DISABLED,
2554       0, 0, width, height, m_hWnd, 0, instance, 0);
2555   gfx::CheckWindowCreated(compositor_host_window_);
2556
2557   gfx::SetWindowUserData(compositor_host_window_, this);
2558
2559   gfx::GLSurfaceHandle surface_handle(compositor_host_window_,
2560                                       gfx::NATIVE_TRANSPORT);
2561   return surface_handle;
2562 }
2563
2564 void RenderWidgetHostViewWin::ResizeCompositingSurface(const gfx::Size& size) {
2565   // Ensure window does not have zero area because D3D cannot create a zero
2566   // area swap chain.
2567   ::SetWindowPos(compositor_host_window_,
2568       NULL,
2569       0, 0,
2570       std::max(1, size.width()),
2571       std::max(1, size.height()),
2572       SWP_NOSENDCHANGING | SWP_NOCOPYBITS | SWP_NOZORDER |
2573           SWP_NOACTIVATE | SWP_DEFERERASE | SWP_NOMOVE);
2574 }
2575
2576 void RenderWidgetHostViewWin::OnAcceleratedCompositingStateChange() {
2577   bool show = render_widget_host_->is_accelerated_compositing_active();
2578   // When we first create the compositor, we will get a show request from
2579   // the renderer before we have gotten the create request from the GPU. In this
2580   // case, simply ignore the show request.
2581   if (compositor_host_window_ == NULL)
2582     return;
2583
2584   if (show) {
2585     ::ShowWindow(compositor_host_window_, SW_SHOW);
2586
2587     // Get all the child windows of this view, including the compositor window.
2588     std::vector<HWND> all_child_windows;
2589     ::EnumChildWindows(m_hWnd, AddChildWindowToVector,
2590         reinterpret_cast<LPARAM>(&all_child_windows));
2591
2592     // Build a list of just the plugin window handles
2593     std::vector<HWND> plugin_windows;
2594     bool compositor_host_window_found = false;
2595     for (size_t i = 0; i < all_child_windows.size(); ++i) {
2596       if (all_child_windows[i] != compositor_host_window_)
2597         plugin_windows.push_back(all_child_windows[i]);
2598       else
2599         compositor_host_window_found = true;
2600     }
2601     DCHECK(compositor_host_window_found);
2602
2603     // Set all the plugin windows to be "after" the compositor window.
2604     // When the compositor window is created, gets placed above plugins.
2605     for (size_t i = 0; i < plugin_windows.size(); ++i) {
2606       HWND next;
2607       if (i + 1 < plugin_windows.size())
2608         next = plugin_windows[i+1];
2609       else
2610         next = compositor_host_window_;
2611       ::SetWindowPos(plugin_windows[i], next, 0, 0, 0, 0,
2612           SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
2613     }
2614   } else {
2615     // Drop the backing store for the accelerated surface when the accelerated
2616     // compositor is disabled. Otherwise, a flash of the last presented frame
2617     // could appear when it is next enabled.
2618     if (accelerated_surface_)
2619       accelerated_surface_->Suspend();
2620     hide_compositor_window_at_next_paint_ = true;
2621   }
2622 }
2623
2624 void RenderWidgetHostViewWin::AcceleratedSurfaceBuffersSwapped(
2625     const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
2626     int gpu_host_id) {
2627   NOTREACHED();
2628 }
2629
2630 void RenderWidgetHostViewWin::AcceleratedSurfacePostSubBuffer(
2631     const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params,
2632     int gpu_host_id) {
2633   NOTREACHED();
2634 }
2635
2636 void RenderWidgetHostViewWin::AcceleratedSurfaceSuspend() {
2637     if (!accelerated_surface_)
2638       return;
2639
2640     accelerated_surface_->Suspend();
2641 }
2642
2643 void RenderWidgetHostViewWin::AcceleratedSurfaceRelease() {
2644 }
2645
2646 bool RenderWidgetHostViewWin::HasAcceleratedSurface(
2647       const gfx::Size& desired_size) {
2648   // TODO(jbates) Implement this so this view can use GetBackingStore for both
2649   // software and GPU frames. Defaulting to false just makes GetBackingStore
2650   // only useable for software frames.
2651   return false;
2652 }
2653
2654 void RenderWidgetHostViewWin::SetAccessibilityFocus(int acc_obj_id) {
2655   if (!render_widget_host_)
2656     return;
2657
2658   render_widget_host_->AccessibilitySetFocus(acc_obj_id);
2659 }
2660
2661 void RenderWidgetHostViewWin::AccessibilityDoDefaultAction(int acc_obj_id) {
2662   if (!render_widget_host_)
2663     return;
2664
2665   render_widget_host_->AccessibilityDoDefaultAction(acc_obj_id);
2666 }
2667
2668 void RenderWidgetHostViewWin::AccessibilityScrollToMakeVisible(
2669     int acc_obj_id, gfx::Rect subfocus) {
2670   if (!render_widget_host_)
2671     return;
2672
2673   render_widget_host_->AccessibilityScrollToMakeVisible(acc_obj_id, subfocus);
2674 }
2675
2676 void RenderWidgetHostViewWin::AccessibilityScrollToPoint(
2677     int acc_obj_id, gfx::Point point) {
2678   if (!render_widget_host_)
2679     return;
2680
2681   render_widget_host_->AccessibilityScrollToPoint(acc_obj_id, point);
2682 }
2683
2684 void RenderWidgetHostViewWin::AccessibilitySetTextSelection(
2685     int acc_obj_id, int start_offset, int end_offset) {
2686   if (!render_widget_host_)
2687     return;
2688
2689   render_widget_host_->AccessibilitySetTextSelection(
2690       acc_obj_id, start_offset, end_offset);
2691 }
2692
2693 gfx::Point RenderWidgetHostViewWin::GetLastTouchEventLocation() const {
2694   return last_touch_location_;
2695 }
2696
2697 void RenderWidgetHostViewWin::FatalAccessibilityTreeError() {
2698   render_widget_host_->FatalAccessibilityTreeError();
2699   SetBrowserAccessibilityManager(NULL);
2700 }
2701
2702 LRESULT RenderWidgetHostViewWin::OnGetObject(UINT message, WPARAM wparam,
2703                                              LPARAM lparam, BOOL& handled) {
2704   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnGetObject");
2705   if (kIdCustom == lparam) {
2706     // An MSAA client requestes our custom id. Assume that we have detected an
2707     // active windows screen reader.
2708     BrowserAccessibilityState::GetInstance()->OnScreenReaderDetected();
2709     render_widget_host_->SetAccessibilityMode(
2710         BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode());
2711
2712     // Return with failure.
2713     return static_cast<LRESULT>(0L);
2714   }
2715
2716   if (lparam != OBJID_CLIENT) {
2717     handled = false;
2718     return static_cast<LRESULT>(0L);
2719   }
2720
2721   IAccessible* iaccessible = GetNativeViewAccessible();
2722   if (iaccessible)
2723     return LresultFromObject(IID_IAccessible, wparam, iaccessible);
2724
2725   handled = false;
2726   return static_cast<LRESULT>(0L);
2727 }
2728
2729 LRESULT RenderWidgetHostViewWin::OnParentNotify(UINT message, WPARAM wparam,
2730                                                 LPARAM lparam, BOOL& handled) {
2731   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnParentNotify");
2732   handled = FALSE;
2733
2734   if (!render_widget_host_)
2735     return 0;
2736
2737   switch (LOWORD(wparam)) {
2738     case WM_LBUTTONDOWN:
2739     case WM_RBUTTONDOWN:
2740     case WM_MBUTTONDOWN:
2741       render_widget_host_->StartUserGesture();
2742       break;
2743     default:
2744       break;
2745   }
2746   return 0;
2747 }
2748
2749 void RenderWidgetHostViewWin::OnFinalMessage(HWND window) {
2750   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnFinalMessage");
2751   // When the render widget host is being destroyed, it ends up calling
2752   // Destroy() which NULLs render_widget_host_.
2753   // Note: the following bug http://crbug.com/24248 seems to report that
2754   // OnFinalMessage is called with a deleted |render_widget_host_|. It is not
2755   // clear how this could happen, hence the NULLing of render_widget_host_
2756   // above.
2757   if (!render_widget_host_ && !being_destroyed_) {
2758     // If you hit this NOTREACHED, please add a comment to report it on
2759     // http://crbug.com/24248, including what you did when it happened and if
2760     // you can repro.
2761     NOTREACHED();
2762   }
2763   if (render_widget_host_)
2764     render_widget_host_->ViewDestroyed();
2765   if (base::win::IsTSFAwareRequired())
2766     ui::TSFBridge::GetInstance()->RemoveFocusedClient(this);
2767   delete this;
2768 }
2769
2770 LRESULT RenderWidgetHostViewWin::OnSessionChange(UINT message,
2771                                                  WPARAM wparam,
2772                                                  LPARAM lparam,
2773                                                  BOOL& handled) {
2774   handled = FALSE;
2775   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnSessionChange");
2776
2777   if (!accelerated_surface_)
2778     return 0;
2779
2780   switch (wparam) {
2781     case WTS_SESSION_LOCK:
2782       accelerated_surface_->SetIsSessionLocked(true);
2783       break;
2784     case WTS_SESSION_UNLOCK:
2785       // Force a repaint to update the window contents.
2786       if (!render_widget_host_->is_hidden())
2787         InvalidateRect(NULL, FALSE);
2788       accelerated_surface_->SetIsSessionLocked(false);
2789       break;
2790     default:
2791       break;
2792   }
2793
2794   return 0;
2795 }
2796
2797 void RenderWidgetHostViewWin::TrackMouseLeave(bool track) {
2798   if (track == track_mouse_leave_)
2799     return;
2800   track_mouse_leave_ = track;
2801
2802   DCHECK(m_hWnd);
2803
2804   TRACKMOUSEEVENT tme;
2805   tme.cbSize = sizeof(TRACKMOUSEEVENT);
2806   tme.dwFlags = TME_LEAVE;
2807   if (!track_mouse_leave_)
2808     tme.dwFlags |= TME_CANCEL;
2809   tme.hwndTrack = m_hWnd;
2810
2811   TrackMouseEvent(&tme);
2812 }
2813
2814 bool RenderWidgetHostViewWin::Send(IPC::Message* message) {
2815   if (!render_widget_host_)
2816     return false;
2817   return render_widget_host_->Send(message);
2818 }
2819
2820 void RenderWidgetHostViewWin::EnsureTooltip() {
2821   UINT message = TTM_NEWTOOLRECT;
2822
2823   TOOLINFO ti = {0};
2824   ti.cbSize = sizeof(ti);
2825   ti.hwnd = m_hWnd;
2826   ti.uId = 0;
2827   if (!::IsWindow(tooltip_hwnd_)) {
2828     message = TTM_ADDTOOL;
2829     tooltip_hwnd_ = CreateWindowEx(
2830         WS_EX_TRANSPARENT | l10n_util::GetExtendedTooltipStyles(),
2831         TOOLTIPS_CLASS, NULL, TTS_NOPREFIX, 0, 0, 0, 0, m_hWnd, NULL,
2832         NULL, NULL);
2833     if (!tooltip_hwnd_) {
2834       // Tooltip creation can inexplicably fail. See bug 82913 for details.
2835       LOG_GETLASTERROR(WARNING) <<
2836           "Tooltip creation failed, tooltips won't work";
2837       return;
2838     }
2839     ti.uFlags = TTF_TRANSPARENT;
2840     ti.lpszText = LPSTR_TEXTCALLBACK;
2841
2842     // Ensure web content tooltips are displayed for at least this amount of
2843     // time, to give users a chance to read longer messages.
2844     const int kMinimumAutopopDurationMs = 10 * 1000;
2845     int autopop_duration_ms =
2846         SendMessage(tooltip_hwnd_, TTM_GETDELAYTIME, TTDT_AUTOPOP, NULL);
2847     if (autopop_duration_ms < kMinimumAutopopDurationMs) {
2848       SendMessage(tooltip_hwnd_, TTM_SETDELAYTIME, TTDT_AUTOPOP,
2849                   kMinimumAutopopDurationMs);
2850     }
2851   }
2852
2853   CRect cr;
2854   GetClientRect(&ti.rect);
2855   SendMessage(tooltip_hwnd_, message, NULL, reinterpret_cast<LPARAM>(&ti));
2856 }
2857
2858 void RenderWidgetHostViewWin::ResetTooltip() {
2859   if (::IsWindow(tooltip_hwnd_))
2860     ::DestroyWindow(tooltip_hwnd_);
2861   tooltip_hwnd_ = NULL;
2862 }
2863
2864 bool RenderWidgetHostViewWin::ForwardGestureEventToRenderer(
2865     ui::GestureEvent* gesture) {
2866   if (!render_widget_host_)
2867     return false;
2868
2869   // Pinch gestures are disabled by default on windows desktop. See
2870   // crbug.com/128477 and crbug.com/148816
2871   if ((gesture->type() == ui::ET_GESTURE_PINCH_BEGIN ||
2872       gesture->type() == ui::ET_GESTURE_PINCH_UPDATE ||
2873       gesture->type() == ui::ET_GESTURE_PINCH_END) &&
2874       !ShouldSendPinchGesture()) {
2875     return true;
2876   }
2877
2878   WebKit::WebGestureEvent web_gesture = CreateWebGestureEvent(m_hWnd, *gesture);
2879   if (web_gesture.type == WebKit::WebGestureEvent::Undefined)
2880     return false;
2881   if (web_gesture.type == WebKit::WebGestureEvent::GestureTapDown) {
2882     render_widget_host_->ForwardGestureEvent(
2883         CreateFlingCancelEvent(gesture->time_stamp().InSecondsF()));
2884   }
2885   render_widget_host_->ForwardGestureEventWithLatencyInfo(web_gesture,
2886                                                           *gesture->latency());
2887   return true;
2888 }
2889
2890 void RenderWidgetHostViewWin::ForwardMouseEventToRenderer(UINT message,
2891                                                           WPARAM wparam,
2892                                                           LPARAM lparam) {
2893   TRACE_EVENT0("browser",
2894                "RenderWidgetHostViewWin::ForwardMouseEventToRenderer");
2895   if (!render_widget_host_) {
2896     TRACE_EVENT0("browser", "EarlyOut_NoRWH");
2897     return;
2898   }
2899
2900   gfx::Point point = gfx::win::ScreenToDIPPoint(
2901       gfx::Point(static_cast<short>(LOWORD(lparam)),
2902                  static_cast<short>(HIWORD(lparam))));
2903   lparam = MAKELPARAM(point.x(), point.y());
2904
2905   WebMouseEvent event(
2906       WebMouseEventBuilder::Build(m_hWnd, message, wparam, lparam));
2907
2908   if (mouse_locked_) {
2909     event.movementX = event.globalX - last_mouse_position_.locked_global.x();
2910     event.movementY = event.globalY - last_mouse_position_.locked_global.y();
2911     last_mouse_position_.locked_global.SetPoint(event.globalX, event.globalY);
2912
2913     event.x = last_mouse_position_.unlocked.x();
2914     event.y = last_mouse_position_.unlocked.y();
2915     event.windowX = last_mouse_position_.unlocked.x();
2916     event.windowY = last_mouse_position_.unlocked.y();
2917     event.globalX = last_mouse_position_.unlocked_global.x();
2918     event.globalY = last_mouse_position_.unlocked_global.y();
2919   } else {
2920     if (ignore_mouse_movement_) {
2921       ignore_mouse_movement_ = false;
2922       event.movementX = 0;
2923       event.movementY = 0;
2924     } else {
2925       event.movementX =
2926           event.globalX - last_mouse_position_.unlocked_global.x();
2927       event.movementY =
2928           event.globalY - last_mouse_position_.unlocked_global.y();
2929     }
2930
2931     last_mouse_position_.unlocked.SetPoint(event.windowX, event.windowY);
2932     last_mouse_position_.unlocked_global.SetPoint(event.globalX, event.globalY);
2933   }
2934
2935   // Windows sends (fake) mouse messages for touch events. Don't send these to
2936   // the render widget.
2937   if (!touch_events_enabled_ || !ui::IsMouseEventFromTouch(message)) {
2938     // Send the event to the renderer before changing mouse capture, so that
2939     // the capturelost event arrives after mouseup.
2940     render_widget_host_->ForwardMouseEvent(event);
2941
2942     switch (event.type) {
2943       case WebInputEvent::MouseMove:
2944         TrackMouseLeave(true);
2945         break;
2946       case WebInputEvent::MouseLeave:
2947         TrackMouseLeave(false);
2948         break;
2949       case WebInputEvent::MouseDown:
2950         SetCapture();
2951         break;
2952       case WebInputEvent::MouseUp:
2953         if (GetCapture() == m_hWnd)
2954           ReleaseCapture();
2955         break;
2956     }
2957   }
2958
2959   if (IsActivatable() && event.type == WebInputEvent::MouseDown) {
2960     // This is a temporary workaround for bug 765011 to get focus when the
2961     // mouse is clicked. This happens after the mouse down event is sent to
2962     // the renderer because normally Windows does a WM_SETFOCUS after
2963     // WM_LBUTTONDOWN.
2964     SetFocus();
2965   }
2966 }
2967
2968 void RenderWidgetHostViewWin::ShutdownHost() {
2969   weak_factory_.InvalidateWeakPtrs();
2970   if (render_widget_host_)
2971     render_widget_host_->Shutdown();
2972   // Do not touch any members at this point, |this| has been deleted.
2973 }
2974
2975 void RenderWidgetHostViewWin::DoPopupOrFullscreenInit(HWND parent_hwnd,
2976                                                       const gfx::Rect& pos,
2977                                                       DWORD ex_style) {
2978   Create(parent_hwnd, NULL, NULL, WS_POPUP, ex_style);
2979   gfx::Rect screen_rect = gfx::win::DIPToScreenRect(pos);
2980   MoveWindow(screen_rect.x(), screen_rect.y(), screen_rect.width(),
2981       screen_rect.height(), TRUE);
2982   ShowWindow(IsActivatable() ? SW_SHOW : SW_SHOWNA);
2983
2984   if (is_fullscreen_ && win8::IsSingleWindowMetroMode()) {
2985     MetroSetFrameWindow set_frame_window =
2986         reinterpret_cast<MetroSetFrameWindow>(
2987             ::GetProcAddress(base::win::GetMetroModule(), "SetFrameWindow"));
2988     DCHECK(set_frame_window);
2989     set_frame_window(m_hWnd);
2990   }
2991 }
2992
2993 CPoint RenderWidgetHostViewWin::GetClientCenter() const {
2994   CRect rect;
2995   GetClientRect(&rect);
2996   return rect.CenterPoint();
2997 }
2998
2999 void RenderWidgetHostViewWin::MoveCursorToCenterIfNecessary() {
3000   DCHECK(mouse_locked_);
3001
3002   CRect rect;
3003   GetClipCursor(&rect);
3004   int border_x = rect.Width() * kMouseLockBorderPercentage / 100;
3005   int border_y = rect.Height() * kMouseLockBorderPercentage / 100;
3006
3007   bool should_move =
3008       last_mouse_position_.locked_global.x() < rect.left + border_x ||
3009       last_mouse_position_.locked_global.x() > rect.right - border_x ||
3010       last_mouse_position_.locked_global.y() < rect.top + border_y ||
3011       last_mouse_position_.locked_global.y() > rect.bottom - border_y;
3012
3013   if (should_move) {
3014     move_to_center_request_.pending = true;
3015     move_to_center_request_.target = rect.CenterPoint();
3016     if (!::SetCursorPos(move_to_center_request_.target.x(),
3017                         move_to_center_request_.target.y())) {
3018       LOG_GETLASTERROR(WARNING) << "Failed to set cursor position.";
3019     }
3020   }
3021 }
3022
3023 void RenderWidgetHostViewWin::HandleLockedMouseEvent(UINT message,
3024                                                      WPARAM wparam,
3025                                                      LPARAM lparam) {
3026   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::HandleLockedMouseEvent");
3027   DCHECK(mouse_locked_);
3028
3029   if (message == WM_MOUSEMOVE && move_to_center_request_.pending) {
3030     // Ignore WM_MOUSEMOVE messages generated by
3031     // MoveCursorToCenterIfNecessary().
3032     CPoint current_position(LOWORD(lparam), HIWORD(lparam));
3033     ClientToScreen(&current_position);
3034     if (move_to_center_request_.target.x() == current_position.x &&
3035         move_to_center_request_.target.y() == current_position.y) {
3036       move_to_center_request_.pending = false;
3037       last_mouse_position_.locked_global = move_to_center_request_.target;
3038       return;
3039     }
3040   }
3041
3042   ForwardMouseEventToRenderer(message, wparam, lparam);
3043 }
3044
3045 LRESULT RenderWidgetHostViewWin::OnDocumentFeed(RECONVERTSTRING* reconv) {
3046   size_t target_offset;
3047   size_t target_length;
3048   bool has_composition;
3049   if (!composition_range_.is_empty()) {
3050     target_offset = composition_range_.GetMin();
3051     target_length = composition_range_.length();
3052     has_composition = true;
3053   } else if (selection_range_.IsValid()) {
3054     target_offset = selection_range_.GetMin();
3055     target_length = selection_range_.length();
3056     has_composition = false;
3057   } else {
3058     return 0;
3059   }
3060
3061   size_t len = selection_text_.length();
3062   size_t need_size = sizeof(RECONVERTSTRING) + len * sizeof(WCHAR);
3063
3064   if (target_offset < selection_text_offset_ ||
3065       target_offset + target_length > selection_text_offset_ + len) {
3066     return 0;
3067   }
3068
3069   if (!reconv)
3070     return need_size;
3071
3072   if (reconv->dwSize < need_size)
3073     return 0;
3074
3075   reconv->dwVersion = 0;
3076   reconv->dwStrLen = len;
3077   reconv->dwStrOffset = sizeof(RECONVERTSTRING);
3078   reconv->dwCompStrLen = has_composition ? target_length: 0;
3079   reconv->dwCompStrOffset =
3080       (target_offset - selection_text_offset_) * sizeof(WCHAR);
3081   reconv->dwTargetStrLen = target_length;
3082   reconv->dwTargetStrOffset = reconv->dwCompStrOffset;
3083   memcpy(reinterpret_cast<char*>(reconv) + sizeof(RECONVERTSTRING),
3084          selection_text_.c_str(), len * sizeof(WCHAR));
3085
3086   // According to Microsft API document, IMR_RECONVERTSTRING and
3087   // IMR_DOCUMENTFEED should return reconv, but some applications return
3088   // need_size.
3089   return reinterpret_cast<LRESULT>(reconv);
3090 }
3091
3092 LRESULT RenderWidgetHostViewWin::OnReconvertString(RECONVERTSTRING* reconv) {
3093   // If there is a composition string already, we don't allow reconversion.
3094   if (imm32_manager_->is_composing())
3095     return 0;
3096
3097   if (selection_range_.is_empty())
3098     return 0;
3099
3100   if (selection_text_.empty())
3101     return 0;
3102
3103   if (selection_range_.GetMin() < selection_text_offset_ ||
3104       selection_range_.GetMax() >
3105       selection_text_offset_ + selection_text_.length()) {
3106     return 0;
3107   }
3108
3109   size_t len = selection_range_.length();
3110   size_t need_size = sizeof(RECONVERTSTRING) + len * sizeof(WCHAR);
3111
3112   if (!reconv)
3113     return need_size;
3114
3115   if (reconv->dwSize < need_size)
3116     return 0;
3117
3118   reconv->dwVersion = 0;
3119   reconv->dwStrLen = len;
3120   reconv->dwStrOffset = sizeof(RECONVERTSTRING);
3121   reconv->dwCompStrLen = len;
3122   reconv->dwCompStrOffset = 0;
3123   reconv->dwTargetStrLen = len;
3124   reconv->dwTargetStrOffset = 0;
3125
3126   size_t offset = selection_range_.GetMin() - selection_text_offset_;
3127   memcpy(reinterpret_cast<char*>(reconv) + sizeof(RECONVERTSTRING),
3128          selection_text_.c_str() + offset, len * sizeof(WCHAR));
3129
3130   // According to Microsft API document, IMR_RECONVERTSTRING and
3131   // IMR_DOCUMENTFEED should return reconv, but some applications return
3132   // need_size.
3133   return reinterpret_cast<LRESULT>(reconv);
3134 }
3135
3136 LRESULT RenderWidgetHostViewWin::OnQueryCharPosition(
3137     IMECHARPOSITION* position) {
3138   DCHECK(position);
3139
3140   if (position->dwSize < sizeof(IMECHARPOSITION))
3141     return 0;
3142
3143   RECT target_rect = {};
3144   if (imm32_manager_->is_composing() && !composition_range_.is_empty() &&
3145       position->dwCharPos < composition_character_bounds_.size()) {
3146     target_rect =
3147         composition_character_bounds_[position->dwCharPos].ToRECT();
3148   } else if (position->dwCharPos == 0) {
3149     // When there is no on-going composition but |position->dwCharPos| is 0,
3150     // use the caret rect. This behavior is the same to RichEdit. In fact,
3151     // CUAS (Cicero Unaware Application Support) relies on this behavior to
3152     // implement ITfContextView::GetTextExt on top of IMM32-based applications.
3153     target_rect = caret_rect_.ToRECT();
3154   } else {
3155     return 0;
3156   }
3157   ClientToScreen(&target_rect);
3158
3159   RECT document_rect = GetPixelBounds().ToRECT();
3160   ClientToScreen(&document_rect);
3161
3162   position->pt.x = target_rect.left;
3163   position->pt.y = target_rect.top;
3164   position->cLineHeight = target_rect.bottom - target_rect.top;
3165   position->rcDocument = document_rect;
3166   return 1;
3167 }
3168
3169 void RenderWidgetHostViewWin::UpdateIMEState() {
3170   if (base::win::IsTSFAwareRequired()) {
3171     ui::TSFBridge::GetInstance()->OnTextInputTypeChanged(this);
3172     return;
3173   }
3174   if (text_input_type_ != ui::TEXT_INPUT_TYPE_NONE &&
3175       text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD) {
3176     imm32_manager_->EnableIME(m_hWnd);
3177     imm32_manager_->SetUseCompositionWindow(!can_compose_inline_);
3178   } else {
3179     imm32_manager_->DisableIME(m_hWnd);
3180   }
3181
3182   imm32_manager_->SetTextInputMode(m_hWnd, text_input_mode_);
3183 }
3184
3185 void RenderWidgetHostViewWin::UpdateInputScopeIfNecessary(
3186     ui::TextInputType text_input_type) {
3187   // The text store is responsible for handling input scope when TSF-aware is
3188   // required.
3189   if (base::win::IsTSFAwareRequired())
3190     return;
3191
3192   ui::tsf_inputscope::SetInputScopeForTsfUnawareWindow(
3193       m_hWnd, text_input_type, text_input_mode_);
3194 }
3195
3196 ////////////////////////////////////////////////////////////////////////////////
3197 // RenderWidgetHostView, public:
3198
3199 // static
3200 RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget(
3201     RenderWidgetHost* widget) {
3202   return new RenderWidgetHostViewWin(widget);
3203 }
3204
3205 // static
3206 void RenderWidgetHostViewPort::GetDefaultScreenInfo(
3207       WebKit::WebScreenInfo* results) {
3208   GetScreenInfoForWindow(0, results);
3209 }
3210
3211 }  // namespace content