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