Chromium Code Reviews| Index: content/browser/renderer_host/render_widget_host_view_win.cc |
| =================================================================== |
| --- content/browser/renderer_host/render_widget_host_view_win.cc (revision 244508) |
| +++ content/browser/renderer_host/render_widget_host_view_win.cc (working copy) |
| @@ -1,3222 +0,0 @@ |
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
|
scottmg
2014/01/14 17:28:33
BOOM
|
| -// Use of this source code is governed by a BSD-style license that can be |
| -// found in the LICENSE file. |
| - |
| -#include "content/browser/renderer_host/render_widget_host_view_win.h" |
| - |
| -#include <InputScope.h> |
| -#include <wtsapi32.h> |
| -#pragma comment(lib, "wtsapi32.lib") |
| - |
| -#include <algorithm> |
| -#include <map> |
| -#include <stack> |
| - |
| -#include "base/basictypes.h" |
| -#include "base/bind.h" |
| -#include "base/callback_helpers.h" |
| -#include "base/command_line.h" |
| -#include "base/debug/trace_event.h" |
| -#include "base/i18n/rtl.h" |
| -#include "base/metrics/histogram.h" |
| -#include "base/threading/thread.h" |
| -#include "base/win/metro.h" |
| -#include "base/win/scoped_comptr.h" |
| -#include "base/win/scoped_gdi_object.h" |
| -#include "base/win/win_util.h" |
| -#include "base/win/windows_version.h" |
| -#include "base/win/wrapped_window_proc.h" |
| -#include "content/browser/accessibility/browser_accessibility_manager_win.h" |
| -#include "content/browser/accessibility/browser_accessibility_state_impl.h" |
| -#include "content/browser/accessibility/browser_accessibility_win.h" |
| -#include "content/browser/gpu/gpu_data_manager_impl.h" |
| -#include "content/browser/gpu/gpu_process_host.h" |
| -#include "content/browser/gpu/gpu_process_host_ui_shim.h" |
| -#include "content/browser/renderer_host/backing_store.h" |
| -#include "content/browser/renderer_host/backing_store_win.h" |
| -#include "content/browser/renderer_host/input/web_input_event_builders_win.h" |
| -#include "content/browser/renderer_host/render_process_host_impl.h" |
| -#include "content/browser/renderer_host/render_widget_host_impl.h" |
| -#include "content/browser/renderer_host/ui_events_helper.h" |
| -#include "content/common/accessibility_messages.h" |
| -#include "content/common/gpu/gpu_messages.h" |
| -#include "content/common/plugin_constants_win.h" |
| -#include "content/common/view_messages.h" |
| -#include "content/common/webplugin_geometry.h" |
| -#include "content/public/browser/browser_thread.h" |
| -#include "content/public/browser/child_process_data.h" |
| -#include "content/public/browser/content_browser_client.h" |
| -#include "content/public/browser/native_web_keyboard_event.h" |
| -#include "content/public/browser/notification_service.h" |
| -#include "content/public/browser/notification_types.h" |
| -#include "content/public/browser/render_view_host.h" |
| -#include "content/public/common/content_switches.h" |
| -#include "content/public/common/page_zoom.h" |
| -#include "content/public/common/process_type.h" |
| -#include "skia/ext/skia_utils_win.h" |
| -#include "third_party/WebKit/public/web/WebCompositionUnderline.h" |
| -#include "third_party/WebKit/public/web/WebInputEvent.h" |
| -#include "third_party/skia/include/core/SkRegion.h" |
| -#include "ui/base/ime/composition_text.h" |
| -#include "ui/base/ime/win/imm32_manager.h" |
| -#include "ui/base/ime/win/tsf_input_scope.h" |
| -#include "ui/base/l10n/l10n_util_win.h" |
| -#include "ui/base/touch/touch_device.h" |
| -#include "ui/base/touch/touch_enabled.h" |
| -#include "ui/base/ui_base_switches.h" |
| -#include "ui/base/view_prop.h" |
| -#include "ui/base/win/mouse_wheel_util.h" |
| -#include "ui/base/win/touch_input.h" |
| -#include "ui/events/event.h" |
| -#include "ui/events/event_utils.h" |
| -#include "ui/gfx/canvas.h" |
| -#include "ui/gfx/rect.h" |
| -#include "ui/gfx/rect_conversions.h" |
| -#include "ui/gfx/screen.h" |
| -#include "ui/gfx/sequential_id_generator.h" |
| -#include "ui/gfx/text_elider.h" |
| -#include "ui/gfx/win/dpi.h" |
| -#include "ui/gfx/win/hwnd_util.h" |
| -#include "webkit/common/cursors/webcursor.h" |
| -#include "win8/util/win8_util.h" |
| - |
| -using base::TimeDelta; |
| -using base::TimeTicks; |
| -using ui::ViewProp; |
| -using blink::WebInputEvent; |
| -using blink::WebMouseEvent; |
| -using blink::WebTextDirection; |
| - |
| -namespace content { |
| -namespace { |
| - |
| -// Tooltips will wrap after this width. Yes, wrap. Imagine that! |
| -const int kTooltipMaxWidthPixels = 300; |
| - |
| -// Maximum number of characters we allow in a tooltip. |
| -const int kMaxTooltipLength = 1024; |
| - |
| -// A custom MSAA object id used to determine if a screen reader is actively |
| -// listening for MSAA events. |
| -const int kIdCustom = 1; |
| - |
| -// The delay before the compositor host window is destroyed. This gives the GPU |
| -// process a grace period to stop referencing it. |
| -const int kDestroyCompositorHostWindowDelay = 10000; |
| - |
| -// In mouse lock mode, we need to prevent the (invisible) cursor from hitting |
| -// the border of the view, in order to get valid movement information. However, |
| -// forcing the cursor back to the center of the view after each mouse move |
| -// doesn't work well. It reduces the frequency of useful WM_MOUSEMOVE messages |
| -// significantly. Therefore, we move the cursor to the center of the view only |
| -// if it approaches the border. |kMouseLockBorderPercentage| specifies the width |
| -// of the border area, in percentage of the corresponding dimension. |
| -const int kMouseLockBorderPercentage = 15; |
| - |
| -// A callback function for EnumThreadWindows to enumerate and dismiss |
| -// any owned popup windows. |
| -BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) { |
| - const HWND toplevel_hwnd = reinterpret_cast<HWND>(arg); |
| - |
| - if (::IsWindowVisible(window)) { |
| - const HWND owner = ::GetWindow(window, GW_OWNER); |
| - if (toplevel_hwnd == owner) { |
| - ::PostMessage(window, WM_CANCELMODE, 0, 0); |
| - } |
| - } |
| - |
| - return TRUE; |
| -} |
| - |
| -void SendToGpuProcessHost(int gpu_host_id, scoped_ptr<IPC::Message> message) { |
| - GpuProcessHost* gpu_process_host = GpuProcessHost::FromID(gpu_host_id); |
| - if (!gpu_process_host) |
| - return; |
| - |
| - gpu_process_host->Send(message.release()); |
| -} |
| - |
| -void PostTaskOnIOThread(const tracked_objects::Location& from_here, |
| - base::Closure task) { |
| - BrowserThread::PostTask(BrowserThread::IO, from_here, task); |
| -} |
| - |
| -bool DecodeZoomGesture(HWND hwnd, const GESTUREINFO& gi, |
| - PageZoom* zoom, POINT* zoom_center) { |
| - static long start = 0; |
| - static POINT zoom_first; |
| - |
| - if (gi.dwFlags == GF_BEGIN) { |
| - start = gi.ullArguments; |
| - zoom_first.x = gi.ptsLocation.x; |
| - zoom_first.y = gi.ptsLocation.y; |
| - ScreenToClient(hwnd, &zoom_first); |
| - return false; |
| - } |
| - |
| - if (gi.dwFlags == GF_END) |
| - return false; |
| - |
| - POINT zoom_second = {0}; |
| - zoom_second.x = gi.ptsLocation.x; |
| - zoom_second.y = gi.ptsLocation.y; |
| - ScreenToClient(hwnd, &zoom_second); |
| - |
| - if (zoom_first.x == zoom_second.x && zoom_first.y == zoom_second.y) |
| - return false; |
| - |
| - zoom_center->x = (zoom_first.x + zoom_second.x) / 2; |
| - zoom_center->y = (zoom_first.y + zoom_second.y) / 2; |
| - |
| - double zoom_factor = |
| - static_cast<double>(gi.ullArguments)/static_cast<double>(start); |
| - |
| - *zoom = zoom_factor >= 1 ? PAGE_ZOOM_IN : PAGE_ZOOM_OUT; |
| - |
| - start = gi.ullArguments; |
| - zoom_first = zoom_second; |
| - return true; |
| -} |
| - |
| -bool DecodeScrollGesture(const GESTUREINFO& gi, |
| - POINT* start, |
| - POINT* delta){ |
| - // Windows gestures are streams of messages with begin/end messages that |
| - // separate each new gesture. We key off the begin message to reset |
| - // the static variables. |
| - static POINT last_pt; |
| - static POINT start_pt; |
| - |
| - if (gi.dwFlags == GF_BEGIN) { |
| - delta->x = 0; |
| - delta->y = 0; |
| - start_pt.x = gi.ptsLocation.x; |
| - start_pt.y = gi.ptsLocation.y; |
| - } else { |
| - delta->x = gi.ptsLocation.x - last_pt.x; |
| - delta->y = gi.ptsLocation.y - last_pt.y; |
| - } |
| - last_pt.x = gi.ptsLocation.x; |
| - last_pt.y = gi.ptsLocation.y; |
| - *start = start_pt; |
| - return true; |
| -} |
| - |
| -blink::WebMouseWheelEvent MakeFakeScrollWheelEvent(HWND hwnd, |
| - POINT start, |
| - POINT delta) { |
| - blink::WebMouseWheelEvent result; |
| - result.type = WebInputEvent::MouseWheel; |
| - result.timeStampSeconds = ::GetMessageTime() / 1000.0; |
| - result.button = WebMouseEvent::ButtonNone; |
| - result.globalX = start.x; |
| - result.globalY = start.y; |
| - // Map to window coordinates. |
| - POINT client_point = { result.globalX, result.globalY }; |
| - MapWindowPoints(0, hwnd, &client_point, 1); |
| - result.x = client_point.x; |
| - result.y = client_point.y; |
| - result.windowX = result.x; |
| - result.windowY = result.y; |
| - // Note that we support diagonal scrolling. |
| - result.deltaX = static_cast<float>(delta.x); |
| - result.wheelTicksX = WHEEL_DELTA; |
| - result.deltaY = static_cast<float>(delta.y); |
| - result.wheelTicksY = WHEEL_DELTA; |
| - return result; |
| -} |
| - |
| -static const int kTouchMask = 0x7; |
| - |
| -inline int GetTouchType(const TOUCHINPUT& point) { |
| - return point.dwFlags & kTouchMask; |
| -} |
| - |
| -inline void SetTouchType(TOUCHINPUT* point, int type) { |
| - point->dwFlags = (point->dwFlags & kTouchMask) | type; |
| -} |
| - |
| -ui::EventType ConvertToUIEvent(blink::WebTouchPoint::State t) { |
| - switch (t) { |
| - case blink::WebTouchPoint::StatePressed: |
| - return ui::ET_TOUCH_PRESSED; |
| - case blink::WebTouchPoint::StateMoved: |
| - return ui::ET_TOUCH_MOVED; |
| - case blink::WebTouchPoint::StateStationary: |
| - return ui::ET_TOUCH_STATIONARY; |
| - case blink::WebTouchPoint::StateReleased: |
| - return ui::ET_TOUCH_RELEASED; |
| - case blink::WebTouchPoint::StateCancelled: |
| - return ui::ET_TOUCH_CANCELLED; |
| - default: |
| - DCHECK(false) << "Unexpected ui type. " << t; |
| - return ui::ET_UNKNOWN; |
| - } |
| -} |
| - |
| -// Creates a WebGestureEvent corresponding to the given |gesture| |
| -blink::WebGestureEvent CreateWebGestureEvent(HWND hwnd, |
| - const ui::GestureEvent& gesture) { |
| - blink::WebGestureEvent gesture_event = |
| - MakeWebGestureEventFromUIEvent(gesture); |
| - |
| - POINT client_point = gesture.location().ToPOINT(); |
| - POINT screen_point = gesture.location().ToPOINT(); |
| - MapWindowPoints(hwnd, HWND_DESKTOP, &screen_point, 1); |
| - |
| - gesture_event.x = client_point.x; |
| - gesture_event.y = client_point.y; |
| - gesture_event.globalX = screen_point.x; |
| - gesture_event.globalY = screen_point.y; |
| - |
| - return gesture_event; |
| -} |
| - |
| -blink::WebGestureEvent CreateFlingCancelEvent(double time_stamp) { |
| - blink::WebGestureEvent gesture_event; |
| - gesture_event.timeStampSeconds = time_stamp; |
| - gesture_event.type = blink::WebGestureEvent::GestureFlingCancel; |
| - gesture_event.sourceDevice = blink::WebGestureEvent::Touchscreen; |
| - return gesture_event; |
| -} |
| - |
| -class TouchEventFromWebTouchPoint : public ui::TouchEvent { |
| - public: |
| - TouchEventFromWebTouchPoint(const blink::WebTouchPoint& touch_point, |
| - base::TimeDelta& timestamp) |
| - : ui::TouchEvent(ConvertToUIEvent(touch_point.state), |
| - touch_point.position, |
| - touch_point.id, |
| - timestamp) { |
| - set_radius(touch_point.radiusX, touch_point.radiusY); |
| - set_rotation_angle(touch_point.rotationAngle); |
| - set_force(touch_point.force); |
| - set_flags(ui::GetModifiersFromKeyState()); |
| - } |
| - |
| - virtual ~TouchEventFromWebTouchPoint() {} |
| - |
| - private: |
| - DISALLOW_COPY_AND_ASSIGN(TouchEventFromWebTouchPoint); |
| -}; |
| - |
| -bool ShouldSendPinchGesture() { |
| - static bool pinch_allowed = |
| - CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnablePinch); |
| - return pinch_allowed; |
| -} |
| - |
| -void GetScreenInfoForWindow(gfx::NativeViewId id, |
| - blink::WebScreenInfo* results) { |
| - HWND window = gfx::NativeViewFromId(id); |
| - |
| - HMONITOR monitor = MonitorFromWindow(window, MONITOR_DEFAULTTOPRIMARY); |
| - |
| - MONITORINFOEX monitor_info; |
| - monitor_info.cbSize = sizeof(MONITORINFOEX); |
| - if (!base::win::GetMonitorInfoWrapper(monitor, &monitor_info)) |
| - return; |
| - |
| - DEVMODE dev_mode; |
| - dev_mode.dmSize = sizeof(dev_mode); |
| - dev_mode.dmDriverExtra = 0; |
| - EnumDisplaySettings(monitor_info.szDevice, ENUM_CURRENT_SETTINGS, &dev_mode); |
| - |
| - blink::WebScreenInfo screen_info; |
| - screen_info.depth = dev_mode.dmBitsPerPel; |
| - screen_info.depthPerComponent = 8; |
| - screen_info.deviceScaleFactor = gfx::win::GetDeviceScaleFactor(); |
| - screen_info.isMonochrome = dev_mode.dmColor == DMCOLOR_MONOCHROME; |
| - screen_info.rect = gfx::Rect(monitor_info.rcMonitor); |
| - screen_info.availableRect = gfx::Rect(monitor_info.rcWork); |
| - |
| - *results = screen_info; |
| -} |
| - |
| -} // namespace |
| - |
| -const wchar_t kRenderWidgetHostHWNDClass[] = L"Chrome_RenderWidgetHostHWND"; |
| - |
| -// Wrapper for maintaining touchstate associated with a WebTouchEvent. |
| -class WebTouchState { |
| - public: |
| - explicit WebTouchState(const RenderWidgetHostViewWin* window); |
| - |
| - // Updates the current touchpoint state with the supplied touches. |
| - // Touches will be consumed only if they are of the same type (e.g. down, |
| - // up, move). Returns the number of consumed touches. |
| - size_t UpdateTouchPoints(TOUCHINPUT* points, size_t count); |
| - |
| - // Marks all active touchpoints as released. |
| - bool ReleaseTouchPoints(); |
| - |
| - // The contained WebTouchEvent. |
| - const blink::WebTouchEvent& touch_event() { return touch_event_; } |
| - |
| - // Returns if any touches are modified in the event. |
| - bool is_changed() { return touch_event_.changedTouchesLength != 0; } |
| - |
| - private: |
| - // Adds a touch point or returns NULL if there's not enough space. |
| - blink::WebTouchPoint* AddTouchPoint(TOUCHINPUT* touch_input); |
| - |
| - // Copy details from a TOUCHINPUT to an existing WebTouchPoint, returning |
| - // true if the resulting point is a stationary move. |
| - bool UpdateTouchPoint(blink::WebTouchPoint* touch_point, |
| - TOUCHINPUT* touch_input); |
| - |
| - // Find (or create) a mapping for _os_touch_id_. |
| - unsigned int GetMappedTouch(unsigned int os_touch_id); |
| - |
| - // Remove any mappings that are no longer in use. |
| - void RemoveExpiredMappings(); |
| - |
| - blink::WebTouchEvent touch_event_; |
| - const RenderWidgetHostViewWin* const window_; |
| - |
| - ui::SequentialIDGenerator id_generator_; |
| - |
| - DISALLOW_COPY_AND_ASSIGN(WebTouchState); |
| -}; |
| - |
| -typedef void (*MetroSetFrameWindow)(HWND window); |
| -typedef void (*MetroCloseFrameWindow)(HWND window); |
| - |
| -/////////////////////////////////////////////////////////////////////////////// |
| -// RenderWidgetHostViewWin, public: |
| - |
| -RenderWidgetHostViewWin::RenderWidgetHostViewWin(RenderWidgetHost* widget) |
| - : render_widget_host_(RenderWidgetHostImpl::From(widget)), |
| - compositor_host_window_(NULL), |
| - hide_compositor_window_at_next_paint_(false), |
| - track_mouse_leave_(false), |
| - imm32_manager_(new ui::IMM32Manager), |
| - ime_notification_(false), |
| - capture_enter_key_(false), |
| - about_to_validate_and_paint_(false), |
| - close_on_deactivate_(false), |
| - being_destroyed_(false), |
| - tooltip_hwnd_(NULL), |
| - tooltip_showing_(false), |
| - weak_factory_(this), |
| - is_loading_(false), |
| - text_input_type_(ui::TEXT_INPUT_TYPE_NONE), |
| - text_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT), |
| - can_compose_inline_(true), |
| - is_fullscreen_(false), |
| - ignore_mouse_movement_(true), |
| - composition_range_(gfx::Range::InvalidRange()), |
| - touch_state_(new WebTouchState(this)), |
| - pointer_down_context_(false), |
| - last_touch_location_(-1, -1), |
| - touch_events_enabled_(ui::AreTouchEventsEnabled()), |
| - gesture_recognizer_(ui::GestureRecognizer::Create()) { |
| - render_widget_host_->SetView(this); |
| - registrar_.Add(this, |
| - NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
| - NotificationService::AllBrowserContextsAndSources()); |
| - gesture_recognizer_->AddGestureEventHelper(this); |
| -} |
| - |
| -RenderWidgetHostViewWin::~RenderWidgetHostViewWin() { |
| - gesture_recognizer_->RemoveGestureEventHelper(this); |
| - UnlockMouse(); |
| - ResetTooltip(); |
| -} |
| - |
| -void RenderWidgetHostViewWin::CreateWnd(HWND parent) { |
| - // ATL function to create the window. |
| - Create(parent); |
| -} |
| - |
| -/////////////////////////////////////////////////////////////////////////////// |
| -// RenderWidgetHostViewWin, RenderWidgetHostView implementation: |
| - |
| -void RenderWidgetHostViewWin::InitAsChild( |
| - gfx::NativeView parent_view) { |
| - CreateWnd(parent_view); |
| -} |
| - |
| -void RenderWidgetHostViewWin::InitAsPopup( |
| - RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) { |
| - close_on_deactivate_ = true; |
| - DoPopupOrFullscreenInit(parent_host_view->GetNativeView(), pos, |
| - WS_EX_TOOLWINDOW); |
| -} |
| - |
| -void RenderWidgetHostViewWin::InitAsFullscreen( |
| - RenderWidgetHostView* reference_host_view) { |
| - gfx::Rect pos = gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow( |
| - reference_host_view->GetNativeView()).bounds(); |
| - is_fullscreen_ = true; |
| - DoPopupOrFullscreenInit(gfx::GetWindowToParentTo(true), pos, 0); |
| -} |
| - |
| -RenderWidgetHost* RenderWidgetHostViewWin::GetRenderWidgetHost() const { |
| - return render_widget_host_; |
| -} |
| - |
| -void RenderWidgetHostViewWin::WasShown() { |
| - // |render_widget_host_| may be NULL if the WebContentsImpl is in the process |
| - // of closing. |
| - if (!render_widget_host_) |
| - return; |
| - |
| - if (!render_widget_host_->is_hidden()) |
| - return; |
| - |
| - if (web_contents_switch_paint_time_.is_null()) |
| - web_contents_switch_paint_time_ = TimeTicks::Now(); |
| - |
| - render_widget_host_->WasShown(); |
| -} |
| - |
| -void RenderWidgetHostViewWin::WasHidden() { |
| - // |render_widget_host_| may be NULL if the WebContentsImpl is in the process |
| - // of closing. |
| - if (!render_widget_host_) |
| - return; |
| - |
| - if (render_widget_host_->is_hidden()) |
| - return; |
| - |
| - ResetTooltip(); |
| - |
| - // Inform the renderer that we are being hidden so it can reduce its resource |
| - // utilization. |
| - render_widget_host_->WasHidden(); |
| - |
| - if (accelerated_surface_) |
| - accelerated_surface_->WasHidden(); |
| - |
| - if (GetBrowserAccessibilityManager()) |
| - GetBrowserAccessibilityManager()->WasHidden(); |
| - |
| - web_contents_switch_paint_time_ = base::TimeTicks(); |
| -} |
| - |
| -void RenderWidgetHostViewWin::SetSize(const gfx::Size& size) { |
| - SetBounds(gfx::Rect(GetPixelBounds().origin(), size)); |
| -} |
| - |
| -void RenderWidgetHostViewWin::SetBounds(const gfx::Rect& rect) { |
| - if (being_destroyed_) |
| - return; |
| - |
| - // No SWP_NOREDRAW as autofill popups can move and the underneath window |
| - // should redraw in that case. |
| - UINT swp_flags = SWP_NOSENDCHANGING | SWP_NOOWNERZORDER | SWP_NOCOPYBITS | |
| - SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE; |
| - |
| - // If the style is not popup, you have to convert the point to client |
| - // coordinate. |
| - POINT point = { rect.x(), rect.y() }; |
| - if (GetStyle() & WS_CHILD) |
| - ScreenToClient(&point); |
| - |
| - SetWindowPos(NULL, point.x, point.y, rect.width(), rect.height(), swp_flags); |
| - render_widget_host_->WasResized(); |
| -} |
| - |
| -gfx::NativeView RenderWidgetHostViewWin::GetNativeView() const { |
| - return m_hWnd; |
| -} |
| - |
| -gfx::NativeViewId RenderWidgetHostViewWin::GetNativeViewId() const { |
| - return reinterpret_cast<gfx::NativeViewId>(m_hWnd); |
| -} |
| - |
| -gfx::NativeViewAccessible |
| -RenderWidgetHostViewWin::GetNativeViewAccessible() { |
| - if (render_widget_host_ && |
| - !BrowserAccessibilityState::GetInstance()->IsAccessibleBrowser()) { |
| - // Attempt to detect screen readers by sending an event with our custom id. |
| - NotifyWinEvent(EVENT_SYSTEM_ALERT, m_hWnd, kIdCustom, CHILDID_SELF); |
| - } |
| - |
| - CreateBrowserAccessibilityManagerIfNeeded(); |
| - |
| - return GetBrowserAccessibilityManager()->GetRoot()-> |
| - ToBrowserAccessibilityWin(); |
| -} |
| - |
| -void RenderWidgetHostViewWin::MovePluginWindows( |
| - const gfx::Vector2d& scroll_offset, |
| - const std::vector<WebPluginGeometry>& plugin_window_moves) { |
| - MovePluginWindowsHelper(m_hWnd, plugin_window_moves); |
| -} |
| - |
| -static BOOL CALLBACK AddChildWindowToVector(HWND hwnd, LPARAM lparam) { |
| - std::vector<HWND>* vector = reinterpret_cast<std::vector<HWND>*>(lparam); |
| - vector->push_back(hwnd); |
| - return TRUE; |
| -} |
| - |
| -void RenderWidgetHostViewWin::CleanupCompositorWindow() { |
| - if (!compositor_host_window_) |
| - return; |
| - |
| - gfx::SetWindowUserData(compositor_host_window_, NULL); |
| - |
| - // Hide the compositor and parent it to the desktop rather than destroying |
| - // it immediately. The GPU process has a grace period to stop accessing the |
| - // window. TODO(apatrick): the GPU process should acknowledge that it has |
| - // finished with the window handle and the browser process should destroy it |
| - // at that point. |
| - ::ShowWindow(compositor_host_window_, SW_HIDE); |
| - ::SetParent(compositor_host_window_, NULL); |
| - |
| - BrowserThread::PostDelayedTask( |
| - BrowserThread::UI, |
| - FROM_HERE, |
| - base::Bind(base::IgnoreResult(&::DestroyWindow), |
| - compositor_host_window_), |
| - base::TimeDelta::FromMilliseconds(kDestroyCompositorHostWindowDelay)); |
| - |
| - compositor_host_window_ = NULL; |
| -} |
| - |
| -bool RenderWidgetHostViewWin::IsActivatable() const { |
| - // Popups should not be activated. |
| - return popup_type_ == blink::WebPopupTypeNone; |
| -} |
| - |
| -void RenderWidgetHostViewWin::Focus() { |
| - if (IsWindow()) |
| - SetFocus(); |
| -} |
| - |
| -void RenderWidgetHostViewWin::Blur() { |
| - NOTREACHED(); |
| -} |
| - |
| -bool RenderWidgetHostViewWin::HasFocus() const { |
| - return ::GetFocus() == m_hWnd; |
| -} |
| - |
| -bool RenderWidgetHostViewWin::IsSurfaceAvailableForCopy() const { |
| - if (render_widget_host_->is_accelerated_compositing_active()) |
| - return accelerated_surface_.get() && accelerated_surface_->IsReadyForCopy(); |
| - else |
| - return !!render_widget_host_->GetBackingStore(false); |
| -} |
| - |
| -void RenderWidgetHostViewWin::Show() { |
| - ShowWindow(SW_SHOW); |
| - WasShown(); |
| -} |
| - |
| -void RenderWidgetHostViewWin::Hide() { |
| - if (!is_fullscreen_ && GetParent() == gfx::GetWindowToParentTo(true)) { |
| - LOG(WARNING) << "Hide() called twice in a row: " << this << ":" |
| - << GetParent(); |
| - return; |
| - } |
| - |
| - if (::GetFocus() == m_hWnd) |
| - ::SetFocus(NULL); |
| - ShowWindow(SW_HIDE); |
| - |
| - WasHidden(); |
| -} |
| - |
| -bool RenderWidgetHostViewWin::IsShowing() { |
| - return !!IsWindowVisible(); |
| -} |
| - |
| -gfx::Rect RenderWidgetHostViewWin::GetViewBounds() const { |
| - return gfx::win::ScreenToDIPRect(GetPixelBounds()); |
| -} |
| - |
| -gfx::Rect RenderWidgetHostViewWin::GetPixelBounds() const { |
| - CRect window_rect; |
| - GetWindowRect(&window_rect); |
| - return gfx::Rect(window_rect); |
| -} |
| - |
| -void RenderWidgetHostViewWin::UpdateCursor(const WebCursor& cursor) { |
| - current_cursor_ = cursor; |
| - UpdateCursorIfOverSelf(); |
| -} |
| - |
| -void RenderWidgetHostViewWin::UpdateCursorIfOverSelf() { |
| - static HCURSOR kCursorArrow = LoadCursor(NULL, IDC_ARROW); |
| - static HCURSOR kCursorAppStarting = LoadCursor(NULL, IDC_APPSTARTING); |
| - static HINSTANCE module_handle = GetModuleHandle( |
| - GetContentClient()->browser()->GetResourceDllName()); |
| - |
| - // If the mouse is over our HWND, then update the cursor state immediately. |
| - CPoint pt; |
| - GetCursorPos(&pt); |
| - if (WindowFromPoint(pt) == m_hWnd) { |
| - // We cannot pass in NULL as the module handle as this would only work for |
| - // standard win32 cursors. We can also receive cursor types which are |
| - // defined as webkit resources. We need to specify the module handle of |
| - // chrome.dll while loading these cursors. |
| - HCURSOR display_cursor = current_cursor_.GetCursor(module_handle); |
| - |
| - // If a page is in the loading state, we want to show the Arrow+Hourglass |
| - // cursor only when the current cursor is the ARROW cursor. In all other |
| - // cases we should continue to display the current cursor. |
| - if (is_loading_ && display_cursor == kCursorArrow) |
| - display_cursor = kCursorAppStarting; |
| - |
| - SetCursor(display_cursor); |
| - } |
| -} |
| - |
| -void RenderWidgetHostViewWin::SetIsLoading(bool is_loading) { |
| - is_loading_ = is_loading; |
| - UpdateCursorIfOverSelf(); |
| -} |
| - |
| -void RenderWidgetHostViewWin::TextInputTypeChanged( |
| - ui::TextInputType type, |
| - ui::TextInputMode input_mode, |
| - bool can_compose_inline) { |
| - if (text_input_type_ != type || |
| - text_input_mode_ != input_mode || |
| - can_compose_inline_ != can_compose_inline) { |
| - const bool text_input_type_changed = (text_input_type_ != type) || |
| - (text_input_mode_ != input_mode); |
| - text_input_type_ = type; |
| - text_input_mode_ = input_mode; |
| - can_compose_inline_ = can_compose_inline; |
| - UpdateIMEState(); |
| - if (text_input_type_changed) |
| - UpdateInputScopeIfNecessary(text_input_type_); |
| - } |
| -} |
| - |
| -void RenderWidgetHostViewWin::SelectionBoundsChanged( |
| - const ViewHostMsg_SelectionBounds_Params& params) { |
| - bool is_enabled = (text_input_type_ != ui::TEXT_INPUT_TYPE_NONE && |
| - text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD); |
| - // Only update caret position if the input method is enabled. |
| - if (is_enabled) { |
| - caret_rect_ = gfx::UnionRects(params.anchor_rect, params.focus_rect); |
| - imm32_manager_->UpdateCaretRect(m_hWnd, caret_rect_); |
| - } |
| -} |
| - |
| -void RenderWidgetHostViewWin::ScrollOffsetChanged() { |
| -} |
| - |
| -void RenderWidgetHostViewWin::ImeCancelComposition() { |
| - imm32_manager_->CancelIME(m_hWnd); |
| -} |
| - |
| -void RenderWidgetHostViewWin::ImeCompositionRangeChanged( |
| - const gfx::Range& range, |
| - const std::vector<gfx::Rect>& character_bounds) { |
| - composition_range_ = range; |
| - composition_character_bounds_ = character_bounds; |
| -} |
| - |
| -void RenderWidgetHostViewWin::Redraw() { |
| - RECT damage_bounds; |
| - GetUpdateRect(&damage_bounds, FALSE); |
| - |
| - base::win::ScopedGDIObject<HRGN> damage_region(CreateRectRgn(0, 0, 0, 0)); |
| - GetUpdateRgn(damage_region, FALSE); |
| - |
| - // Paint the invalid region synchronously. Our caller will not paint again |
| - // until we return, so by painting to the screen here, we ensure effective |
| - // rate-limiting of backing store updates. This helps a lot on pages that |
| - // have animations or fairly expensive layout (e.g., google maps). |
| - // |
| - // We paint this window synchronously, however child windows (i.e. plugins) |
| - // are painted asynchronously. By avoiding synchronous cross-process window |
| - // message dispatching we allow scrolling to be smooth, and also avoid the |
| - // browser process locking up if the plugin process is hung. |
| - // |
| - RedrawWindow(NULL, damage_region, RDW_UPDATENOW | RDW_NOCHILDREN); |
| - |
| - // Send the invalid rect in screen coordinates. |
| - gfx::Rect invalid_screen_rect(damage_bounds); |
| - invalid_screen_rect.Offset(GetPixelBounds().OffsetFromOrigin()); |
| - |
| - PaintPluginWindowsHelper(m_hWnd, invalid_screen_rect); |
| -} |
| - |
| -void RenderWidgetHostViewWin::DidUpdateBackingStore( |
| - const gfx::Rect& scroll_rect, |
| - const gfx::Vector2d& scroll_delta, |
| - const std::vector<gfx::Rect>& copy_rects, |
| - const std::vector<ui::LatencyInfo>& latency_info) { |
| - TRACE_EVENT0("content", "RenderWidgetHostViewWin::DidUpdateBackingStore"); |
| - for (size_t i = 0; i < latency_info.size(); i++) |
| - software_latency_info_.push_back(latency_info[i]); |
| - if (render_widget_host_->is_hidden()) |
| - return; |
| - |
| - // Schedule invalidations first so that the ScrollWindowEx call is closer to |
| - // Redraw. That minimizes chances of "flicker" resulting if the screen |
| - // refreshes before we have a chance to paint the exposed area. Somewhat |
| - // surprisingly, this ordering matters. |
| - |
| - for (size_t i = 0; i < copy_rects.size(); ++i) { |
| - gfx::Rect pixel_rect = gfx::win::DIPToScreenRect(copy_rects[i]); |
| - // Damage might not be DIP aligned. |
| - pixel_rect.Inset(-1, -1); |
| - RECT bounds = pixel_rect.ToRECT(); |
| - InvalidateRect(&bounds, false); |
| - } |
| - |
| - if (!scroll_rect.IsEmpty()) { |
| - TRACE_EVENT0("content", "ScrollWindowEx"); |
| - gfx::Rect pixel_rect = gfx::win::DIPToScreenRect(scroll_rect); |
| - // Damage might not be DIP aligned. |
| - pixel_rect.Inset(-1, -1); |
| - RECT clip_rect = pixel_rect.ToRECT(); |
| - float scale = gfx::win::GetDeviceScaleFactor(); |
| - int dx = static_cast<int>(scale * scroll_delta.x()); |
| - int dy = static_cast<int>(scale * scroll_delta.y()); |
| - ScrollWindowEx(dx, dy, NULL, &clip_rect, NULL, NULL, SW_INVALIDATE); |
| - } |
| - |
| - if (!about_to_validate_and_paint_) |
| - Redraw(); |
| -} |
| - |
| -void RenderWidgetHostViewWin::RenderProcessGone(base::TerminationStatus status, |
| - int error_code) { |
| - UpdateCursorIfOverSelf(); |
| - Destroy(); |
| -} |
| - |
| -bool RenderWidgetHostViewWin::CanSubscribeFrame() const { |
| - return render_widget_host_ != NULL; |
| -} |
| - |
| -void RenderWidgetHostViewWin::WillWmDestroy() { |
| - CleanupCompositorWindow(); |
| - if (base::win::IsTSFAwareRequired()) |
| - ui::TSFBridge::GetInstance()->RemoveFocusedClient(this); |
| -} |
| - |
| -void RenderWidgetHostViewWin::Destroy() { |
| - // We've been told to destroy. |
| - // By clearing close_on_deactivate_, we prevent further deactivations |
| - // (caused by windows messages resulting from the DestroyWindow) from |
| - // triggering further destructions. The deletion of this is handled by |
| - // OnFinalMessage(); |
| - close_on_deactivate_ = false; |
| - render_widget_host_ = NULL; |
| - being_destroyed_ = true; |
| - CleanupCompositorWindow(); |
| - |
| - // This releases the resources associated with input scope. |
| - UpdateInputScopeIfNecessary(ui::TEXT_INPUT_TYPE_NONE); |
| - |
| - if (is_fullscreen_ && win8::IsSingleWindowMetroMode()) { |
| - MetroCloseFrameWindow close_frame_window = |
| - reinterpret_cast<MetroCloseFrameWindow>( |
| - ::GetProcAddress(base::win::GetMetroModule(), "CloseFrameWindow")); |
| - DCHECK(close_frame_window); |
| - close_frame_window(m_hWnd); |
| - } |
| - |
| - DestroyWindow(); |
| -} |
| - |
| -void RenderWidgetHostViewWin::SetTooltipText( |
| - const base::string16& tooltip_text) { |
| - if (!render_widget_host_->is_hidden()) |
| - EnsureTooltip(); |
| - |
| - // Clamp the tooltip length to kMaxTooltipLength so that we don't |
| - // accidentally DOS the user with a mega tooltip (since Windows doesn't seem |
| - // to do this itself). |
| - const base::string16 new_tooltip_text = |
| - gfx::TruncateString(tooltip_text, kMaxTooltipLength); |
| - |
| - if (new_tooltip_text != tooltip_text_) { |
| - tooltip_text_ = new_tooltip_text; |
| - |
| - // Need to check if the tooltip is already showing so that we don't |
| - // immediately show the tooltip with no delay when we move the mouse from |
| - // a region with no tooltip to a region with a tooltip. |
| - if (::IsWindow(tooltip_hwnd_) && tooltip_showing_) { |
| - ::SendMessage(tooltip_hwnd_, TTM_POP, 0, 0); |
| - ::SendMessage(tooltip_hwnd_, TTM_POPUP, 0, 0); |
| - } |
| - } else { |
| - // Make sure the tooltip gets closed after TTN_POP gets sent. For some |
| - // reason this doesn't happen automatically, so moving the mouse around |
| - // within the same link/image/etc doesn't cause the tooltip to re-appear. |
| - if (!tooltip_showing_) { |
| - if (::IsWindow(tooltip_hwnd_)) |
| - ::SendMessage(tooltip_hwnd_, TTM_POP, 0, 0); |
| - } |
| - } |
| -} |
| - |
| -BackingStore* RenderWidgetHostViewWin::AllocBackingStore( |
| - const gfx::Size& size) { |
| - return new BackingStoreWin(render_widget_host_, size); |
| -} |
| - |
| -void RenderWidgetHostViewWin::CopyFromCompositingSurface( |
| - const gfx::Rect& src_subrect, |
| - const gfx::Size& dst_size, |
| - const base::Callback<void(bool, const SkBitmap&)>& callback) { |
| - base::ScopedClosureRunner scoped_callback_runner( |
| - base::Bind(callback, false, SkBitmap())); |
| - if (!accelerated_surface_) |
| - return; |
| - |
| - if (dst_size.IsEmpty() || src_subrect.IsEmpty()) |
| - return; |
| - |
| - ignore_result(scoped_callback_runner.Release()); |
| - accelerated_surface_->AsyncCopyTo(src_subrect, dst_size, callback); |
| -} |
| - |
| -void RenderWidgetHostViewWin::CopyFromCompositingSurfaceToVideoFrame( |
| - const gfx::Rect& src_subrect, |
| - const scoped_refptr<media::VideoFrame>& target, |
| - const base::Callback<void(bool)>& callback) { |
| - base::ScopedClosureRunner scoped_callback_runner(base::Bind(callback, false)); |
| - if (!accelerated_surface_) |
| - return; |
| - |
| - if (!target || (target->format() != media::VideoFrame::YV12 && |
| - target->format() != media::VideoFrame::I420)) |
| - return; |
| - |
| - if (src_subrect.IsEmpty()) |
| - return; |
| - |
| - ignore_result(scoped_callback_runner.Release()); |
| - accelerated_surface_->AsyncCopyToVideoFrame(src_subrect, target, callback); |
| -} |
| - |
| -bool RenderWidgetHostViewWin::CanCopyToVideoFrame() const { |
| - return accelerated_surface_.get() && render_widget_host_ && |
| - render_widget_host_->is_accelerated_compositing_active(); |
| -} |
| - |
| -void RenderWidgetHostViewWin::SetBackground(const SkBitmap& background) { |
| - RenderWidgetHostViewBase::SetBackground(background); |
| - render_widget_host_->SetBackground(background); |
| -} |
| - |
| -void RenderWidgetHostViewWin::ProcessAckedTouchEvent( |
| - const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) { |
| - DCHECK(touch_events_enabled_); |
| - |
| - ScopedVector<ui::TouchEvent> events; |
| - if (!MakeUITouchEventsFromWebTouchEvents(touch, &events, LOCAL_COORDINATES)) |
| - return; |
| - |
| - ui::EventResult result = (ack_result == |
| - INPUT_EVENT_ACK_STATE_CONSUMED) ? ui::ER_HANDLED : ui::ER_UNHANDLED; |
| - for (ScopedVector<ui::TouchEvent>::iterator iter = events.begin(), |
| - end = events.end(); iter != end; ++iter) { |
| - scoped_ptr<ui::GestureRecognizer::Gestures> gestures; |
| - gestures.reset(gesture_recognizer_->ProcessTouchEventForGesture( |
| - *(*iter), result, this)); |
| - ProcessGestures(gestures.get()); |
| - } |
| -} |
| - |
| -void RenderWidgetHostViewWin::UpdateDesiredTouchMode() { |
| - // Make sure that touch events even make sense. |
| - if (base::win::GetVersion() < base::win::VERSION_WIN7) |
| - return; |
| - if (touch_events_enabled_) { |
| - CHECK(RegisterTouchWindow(m_hWnd, TWF_WANTPALM)); |
| - } |
| -} |
| - |
| -bool RenderWidgetHostViewWin::CanDispatchToConsumer( |
| - ui::GestureConsumer* consumer) { |
| - CHECK_EQ(static_cast<RenderWidgetHostViewWin*>(consumer), this); |
| - return true; |
| -} |
| - |
| -void RenderWidgetHostViewWin::DispatchPostponedGestureEvent( |
| - ui::GestureEvent* event) { |
| - ForwardGestureEventToRenderer(event); |
| -} |
| - |
| -void RenderWidgetHostViewWin::DispatchCancelTouchEvent( |
| - ui::TouchEvent* event) { |
| - if (!render_widget_host_ || !touch_events_enabled_ || |
| - !render_widget_host_->ShouldForwardTouchEvent()) { |
| - return; |
| - } |
| - DCHECK(event->type() == blink::WebInputEvent::TouchCancel); |
| - blink::WebTouchEvent cancel_event; |
| - cancel_event.type = blink::WebInputEvent::TouchCancel; |
| - cancel_event.timeStampSeconds = event->time_stamp().InSecondsF(); |
| - render_widget_host_->ForwardTouchEventWithLatencyInfo( |
| - cancel_event, *event->latency()); |
| -} |
| - |
| -void RenderWidgetHostViewWin::SetHasHorizontalScrollbar( |
| - bool has_horizontal_scrollbar) { |
| -} |
| - |
| -void RenderWidgetHostViewWin::SetScrollOffsetPinning( |
| - bool is_pinned_to_left, bool is_pinned_to_right) { |
| -} |
| - |
| -void RenderWidgetHostViewWin::SetCompositionText( |
| - const ui::CompositionText& composition) { |
| - if (!base::win::IsTSFAwareRequired()) { |
| - NOTREACHED(); |
| - return; |
| - } |
| - if (!render_widget_host_) |
| - return; |
| - // ui::CompositionUnderline should be identical to |
| - // blink::WebCompositionUnderline, so that we can do reinterpret_cast safely. |
| - COMPILE_ASSERT(sizeof(ui::CompositionUnderline) == |
| - sizeof(blink::WebCompositionUnderline), |
| - ui_CompositionUnderline__WebKit_WebCompositionUnderline_diff); |
| - const std::vector<blink::WebCompositionUnderline>& underlines = |
| - reinterpret_cast<const std::vector<blink::WebCompositionUnderline>&>( |
| - composition.underlines); |
| - render_widget_host_->ImeSetComposition(composition.text, underlines, |
| - composition.selection.end(), |
| - composition.selection.end()); |
| -} |
| - |
| -void RenderWidgetHostViewWin::ConfirmCompositionText() { |
| - if (!base::win::IsTSFAwareRequired()) { |
| - NOTREACHED(); |
| - return; |
| - } |
| - // TODO(nona): Implement this function. |
| - NOTIMPLEMENTED(); |
| -} |
| - |
| -void RenderWidgetHostViewWin::ClearCompositionText() { |
| - if (!base::win::IsTSFAwareRequired()) { |
| - NOTREACHED(); |
| - return; |
| - } |
| - // TODO(nona): Implement this function. |
| - NOTIMPLEMENTED(); |
| -} |
| - |
| -void RenderWidgetHostViewWin::InsertText(const base::string16& text) { |
| - if (!base::win::IsTSFAwareRequired()) { |
| - NOTREACHED(); |
| - return; |
| - } |
| - if (render_widget_host_) |
| - render_widget_host_->ImeConfirmComposition(text, |
| - gfx::Range::InvalidRange(), |
| - false); |
| -} |
| - |
| -void RenderWidgetHostViewWin::InsertChar(base::char16 ch, int flags) { |
| - if (!base::win::IsTSFAwareRequired()) { |
| - NOTREACHED(); |
| - return; |
| - } |
| - // TODO(nona): Implement this function. |
| - NOTIMPLEMENTED(); |
| -} |
| - |
| -gfx::NativeWindow RenderWidgetHostViewWin::GetAttachedWindow() const { |
| - return m_hWnd; |
| -} |
| - |
| -ui::TextInputType RenderWidgetHostViewWin::GetTextInputType() const { |
| - if (!base::win::IsTSFAwareRequired()) { |
| - NOTREACHED(); |
| - return ui::TEXT_INPUT_TYPE_NONE; |
| - } |
| - return text_input_type_; |
| -} |
| - |
| -ui::TextInputMode RenderWidgetHostViewWin::GetTextInputMode() const { |
| - if (!base::win::IsTSFAwareRequired()) { |
| - NOTREACHED(); |
| - return ui::TEXT_INPUT_MODE_DEFAULT; |
| - } |
| - return text_input_mode_; |
| -} |
| - |
| -bool RenderWidgetHostViewWin::CanComposeInline() const { |
| - if (!base::win::IsTSFAwareRequired()) { |
| - NOTREACHED(); |
| - return false; |
| - } |
| - // TODO(nona): Implement this function. |
| - NOTIMPLEMENTED(); |
| - return false; |
| -} |
| - |
| -gfx::Rect RenderWidgetHostViewWin::GetCaretBounds() const { |
| - if (!base::win::IsTSFAwareRequired()) { |
| - NOTREACHED(); |
| - return gfx::Rect(0, 0, 0, 0); |
| - } |
| - RECT tmp_rect = caret_rect_.ToRECT(); |
| - ClientToScreen(&tmp_rect); |
| - return gfx::Rect(tmp_rect); |
| -} |
| - |
| -bool RenderWidgetHostViewWin::GetCompositionCharacterBounds( |
| - uint32 index, gfx::Rect* rect) const { |
| - if (!base::win::IsTSFAwareRequired()) { |
| - NOTREACHED(); |
| - return false; |
| - } |
| - DCHECK(rect); |
| - if (index >= composition_character_bounds_.size()) |
| - return false; |
| - RECT rec = composition_character_bounds_[index].ToRECT(); |
| - ClientToScreen(&rec); |
| - *rect = gfx::Rect(rec); |
| - return true; |
| -} |
| - |
| -bool RenderWidgetHostViewWin::HasCompositionText() const { |
| - if (!base::win::IsTSFAwareRequired()) { |
| - NOTREACHED(); |
| - return false; |
| - } |
| - // TODO(nona): Implement this function. |
| - NOTIMPLEMENTED(); |
| - return false; |
| -} |
| - |
| -bool RenderWidgetHostViewWin::GetTextRange(gfx::Range* range) const { |
| - if (!base::win::IsTSFAwareRequired()) { |
| - NOTREACHED(); |
| - return false; |
| - } |
| - range->set_start(selection_text_offset_); |
| - range->set_end(selection_text_offset_ + selection_text_.length()); |
| - return false; |
| -} |
| - |
| -bool RenderWidgetHostViewWin::GetCompositionTextRange(gfx::Range* range) const { |
| - if (!base::win::IsTSFAwareRequired()) { |
| - NOTREACHED(); |
| - return false; |
| - } |
| - // TODO(nona): Implement this function. |
| - NOTIMPLEMENTED(); |
| - return false; |
| -} |
| - |
| -bool RenderWidgetHostViewWin::GetSelectionRange(gfx::Range* range) const { |
| - if (!base::win::IsTSFAwareRequired()) { |
| - NOTREACHED(); |
| - return false; |
| - } |
| - range->set_start(selection_range_.start()); |
| - range->set_end(selection_range_.end()); |
| - return false; |
| -} |
| - |
| -bool RenderWidgetHostViewWin::SetSelectionRange(const gfx::Range& range) { |
| - if (!base::win::IsTSFAwareRequired()) { |
| - NOTREACHED(); |
| - return false; |
| - } |
| - // TODO(nona): Implement this function. |
| - NOTIMPLEMENTED(); |
| - return false; |
| -} |
| - |
| -bool RenderWidgetHostViewWin::DeleteRange(const gfx::Range& range) { |
| - if (!base::win::IsTSFAwareRequired()) { |
| - NOTREACHED(); |
| - return false; |
| - } |
| - // TODO(nona): Implement this function. |
| - NOTIMPLEMENTED(); |
| - return false; |
| -} |
| - |
| -bool RenderWidgetHostViewWin::GetTextFromRange(const gfx::Range& range, |
| - base::string16* text) const { |
| - if (!base::win::IsTSFAwareRequired()) { |
| - NOTREACHED(); |
| - return false; |
| - } |
| - gfx::Range selection_text_range(selection_text_offset_, |
| - selection_text_offset_ + selection_text_.length()); |
| - if (!selection_text_range.Contains(range)) { |
| - text->clear(); |
| - return false; |
| - } |
| - if (selection_text_range.EqualsIgnoringDirection(range)) { |
| - *text = selection_text_; |
| - } else { |
| - *text = selection_text_.substr( |
| - range.GetMin() - selection_text_offset_, |
| - range.length()); |
| - } |
| - return true; |
| -} |
| - |
| -void RenderWidgetHostViewWin::OnInputMethodChanged() { |
| - if (!base::win::IsTSFAwareRequired()) { |
| - NOTREACHED(); |
| - return; |
| - } |
| - // TODO(nona): Implement this function. |
| - NOTIMPLEMENTED(); |
| -} |
| - |
| -bool RenderWidgetHostViewWin::ChangeTextDirectionAndLayoutAlignment( |
| - base::i18n::TextDirection direction) { |
| - if (!base::win::IsTSFAwareRequired()) { |
| - NOTREACHED(); |
| - return false; |
| - } |
| - // TODO(nona): Implement this function. |
| - NOTIMPLEMENTED(); |
| - return false; |
| -} |
| - |
| -void RenderWidgetHostViewWin::ExtendSelectionAndDelete( |
| - size_t before, |
| - size_t after) { |
| - if (!base::win::IsTSFAwareRequired()) { |
| - NOTREACHED(); |
| - return; |
| - } |
| - if (!render_widget_host_) |
| - return; |
| - render_widget_host_->ExtendSelectionAndDelete(before, after); |
| -} |
| - |
| -void RenderWidgetHostViewWin::EnsureCaretInRect(const gfx::Rect& rect) { |
| - // TODO(nona): Implement this function. |
| - NOTIMPLEMENTED(); |
| -} |
| - |
| -void RenderWidgetHostViewWin::OnCandidateWindowShown() { |
| -} |
| - |
| -void RenderWidgetHostViewWin::OnCandidateWindowUpdated() { |
| -} |
| - |
| -void RenderWidgetHostViewWin::OnCandidateWindowHidden() { |
| -} |
| - |
| -/////////////////////////////////////////////////////////////////////////////// |
| -// RenderWidgetHostViewWin, private: |
| - |
| -LRESULT RenderWidgetHostViewWin::OnCreate(CREATESTRUCT* create_struct) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnCreate"); |
| - // Call the WM_INPUTLANGCHANGE message handler to initialize the input locale |
| - // of a browser process. |
| - OnInputLangChange(0, 0); |
| - // Marks that window as supporting mouse-wheel messages rerouting so it is |
| - // scrolled when under the mouse pointer even if inactive. |
| - props_.push_back(ui::SetWindowSupportsRerouteMouseWheel(m_hWnd)); |
| - |
| - WTSRegisterSessionNotification(m_hWnd, NOTIFY_FOR_THIS_SESSION); |
| - |
| - UpdateDesiredTouchMode(); |
| - UpdateIMEState(); |
| - |
| - return 0; |
| -} |
| - |
| -void RenderWidgetHostViewWin::OnActivate(UINT action, BOOL minimized, |
| - HWND window) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnActivate"); |
| - // If the container is a popup, clicking elsewhere on screen should close the |
| - // popup. |
| - if (close_on_deactivate_ && action == WA_INACTIVE) { |
| - // Send a windows message so that any derived classes |
| - // will get a change to override the default handling |
| - SendMessage(WM_CANCELMODE); |
| - } |
| -} |
| - |
| -void RenderWidgetHostViewWin::OnDestroy() { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnDestroy"); |
| - DetachPluginsHelper(m_hWnd); |
| - |
| - props_.clear(); |
| - |
| - if (base::win::GetVersion() >= base::win::VERSION_WIN7 && |
| - IsTouchWindow(m_hWnd, NULL)) { |
| - UnregisterTouchWindow(m_hWnd); |
| - } |
| - |
| - CleanupCompositorWindow(); |
| - |
| - WTSUnRegisterSessionNotification(m_hWnd); |
| - |
| - ResetTooltip(); |
| - TrackMouseLeave(false); |
| -} |
| - |
| -void RenderWidgetHostViewWin::OnPaint(HDC unused_dc) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnPaint"); |
| - |
| - // Grab the region to paint before creation of paint_dc since it clears the |
| - // damage region. |
| - base::win::ScopedGDIObject<HRGN> damage_region(CreateRectRgn(0, 0, 0, 0)); |
| - GetUpdateRgn(damage_region, FALSE); |
| - |
| - CPaintDC paint_dc(m_hWnd); |
| - |
| - if (!render_widget_host_) |
| - return; |
| - |
| - DCHECK(render_widget_host_->GetProcess()->HasConnection()); |
| - |
| - // If the GPU process is rendering to a child window, compositing is |
| - // already triggered by damage to compositor_host_window_, so all we need to |
| - // do here is clear borders during resize. |
| - if (compositor_host_window_ && |
| - render_widget_host_->is_accelerated_compositing_active()) { |
| - RECT host_rect, child_rect; |
| - GetClientRect(&host_rect); |
| - if (::GetClientRect(compositor_host_window_, &child_rect) && |
| - (child_rect.right < host_rect.right || |
| - child_rect.bottom < host_rect.bottom)) { |
| - paint_dc.FillRect(&host_rect, |
| - reinterpret_cast<HBRUSH>(GetStockObject(WHITE_BRUSH))); |
| - } |
| - return; |
| - } |
| - |
| - if (accelerated_surface_.get() && |
| - render_widget_host_->is_accelerated_compositing_active()) { |
| - AcceleratedPaint(paint_dc.m_hDC); |
| - return; |
| - } |
| - |
| - about_to_validate_and_paint_ = true; |
| - BackingStoreWin* backing_store = static_cast<BackingStoreWin*>( |
| - render_widget_host_->GetBackingStore(true)); |
| - |
| - // We initialize |paint_dc| (and thus call BeginPaint()) after calling |
| - // GetBackingStore(), so that if it updates the invalid rect we'll catch the |
| - // changes and repaint them. |
| - about_to_validate_and_paint_ = false; |
| - |
| - if (compositor_host_window_ && hide_compositor_window_at_next_paint_) { |
| - ::ShowWindow(compositor_host_window_, SW_HIDE); |
| - hide_compositor_window_at_next_paint_ = false; |
| - } |
| - |
| - gfx::Rect damaged_rect(paint_dc.m_ps.rcPaint); |
| - if (damaged_rect.IsEmpty()) |
| - return; |
| - |
| - if (backing_store) { |
| - gfx::Rect bitmap_rect(gfx::Point(), |
| - gfx::win::DIPToScreenSize(backing_store->size())); |
| - |
| - bool manage_colors = BackingStoreWin::ColorManagementEnabled(); |
| - if (manage_colors) |
| - SetICMMode(paint_dc.m_hDC, ICM_ON); |
| - |
| - // Blit only the damaged regions from the backing store. |
| - DWORD data_size = GetRegionData(damage_region, 0, NULL); |
| - scoped_ptr<char[]> region_data_buf; |
| - RGNDATA* region_data = NULL; |
| - RECT* region_rects = NULL; |
| - |
| - if (data_size) { |
| - region_data_buf.reset(new char[data_size]); |
| - region_data = reinterpret_cast<RGNDATA*>(region_data_buf.get()); |
| - region_rects = reinterpret_cast<RECT*>(region_data->Buffer); |
| - data_size = GetRegionData(damage_region, data_size, region_data); |
| - } |
| - |
| - if (!data_size) { |
| - // Grabbing the damaged regions failed, fake with the whole rect. |
| - data_size = sizeof(RGNDATAHEADER) + sizeof(RECT); |
| - region_data_buf.reset(new char[data_size]); |
| - region_data = reinterpret_cast<RGNDATA*>(region_data_buf.get()); |
| - region_rects = reinterpret_cast<RECT*>(region_data->Buffer); |
| - region_data->rdh.nCount = 1; |
| - region_rects[0] = damaged_rect.ToRECT(); |
| - } |
| - |
| - for (DWORD i = 0; i < region_data->rdh.nCount; ++i) { |
| - gfx::Rect paint_rect = |
| - gfx::IntersectRects(bitmap_rect, gfx::Rect(region_rects[i])); |
| - if (!paint_rect.IsEmpty()) { |
| - BitBlt(paint_dc.m_hDC, |
| - paint_rect.x(), |
| - paint_rect.y(), |
| - paint_rect.width(), |
| - paint_rect.height(), |
| - backing_store->hdc(), |
| - paint_rect.x(), |
| - paint_rect.y(), |
| - SRCCOPY); |
| - } |
| - } |
| - |
| - if (manage_colors) |
| - SetICMMode(paint_dc.m_hDC, ICM_OFF); |
| - |
| - // Fill the remaining portion of the damaged_rect with the background |
| - if (damaged_rect.right() > bitmap_rect.right()) { |
| - RECT r; |
| - r.left = std::max(bitmap_rect.right(), damaged_rect.x()); |
| - r.right = damaged_rect.right(); |
| - r.top = damaged_rect.y(); |
| - r.bottom = std::min(bitmap_rect.bottom(), damaged_rect.bottom()); |
| - DrawBackground(r, &paint_dc); |
| - } |
| - if (damaged_rect.bottom() > bitmap_rect.bottom()) { |
| - RECT r; |
| - r.left = damaged_rect.x(); |
| - r.right = damaged_rect.right(); |
| - r.top = std::max(bitmap_rect.bottom(), damaged_rect.y()); |
| - r.bottom = damaged_rect.bottom(); |
| - DrawBackground(r, &paint_dc); |
| - } |
| - if (!whiteout_start_time_.is_null()) { |
| - TimeDelta whiteout_duration = TimeTicks::Now() - whiteout_start_time_; |
| - UMA_HISTOGRAM_TIMES("MPArch.RWHH_WhiteoutDuration", whiteout_duration); |
| - |
| - // Reset the start time to 0 so that we start recording again the next |
| - // time the backing store is NULL... |
| - whiteout_start_time_ = TimeTicks(); |
| - } |
| - if (!web_contents_switch_paint_time_.is_null()) { |
| - TimeDelta web_contents_switch_paint_duration = TimeTicks::Now() - |
| - web_contents_switch_paint_time_; |
| - UMA_HISTOGRAM_TIMES("MPArch.RWH_TabSwitchPaintDuration", |
| - web_contents_switch_paint_duration); |
| - // Reset contents_switch_paint_time_ to 0 so future tab selections are |
| - // recorded. |
| - web_contents_switch_paint_time_ = TimeTicks(); |
| - } |
| - |
| - for (size_t i = 0; i < software_latency_info_.size(); i++) { |
| - software_latency_info_[i].AddLatencyNumber( |
| - ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0); |
| - render_widget_host_->FrameSwapped(software_latency_info_[i]); |
| - } |
| - software_latency_info_.clear(); |
| - } else { |
| - DrawBackground(paint_dc.m_ps.rcPaint, &paint_dc); |
| - if (whiteout_start_time_.is_null()) |
| - whiteout_start_time_ = TimeTicks::Now(); |
| - } |
| -} |
| - |
| -void RenderWidgetHostViewWin::DrawBackground(const RECT& dirty_rect, |
| - CPaintDC* dc) { |
| - if (!background_.empty()) { |
| - gfx::Rect dirty_area(dirty_rect); |
| - gfx::Canvas canvas(dirty_area.size(), 1.0f, true); |
| - canvas.Translate(-dirty_area.OffsetFromOrigin()); |
| - |
| - gfx::Rect dc_rect(dc->m_ps.rcPaint); |
| - // TODO(pkotwicz): Fix |background_| such that it is an ImageSkia. |
| - canvas.TileImageInt(gfx::ImageSkia::CreateFrom1xBitmap(background_), |
| - 0, 0, dc_rect.width(), dc_rect.height()); |
| - |
| - skia::DrawToNativeContext(canvas.sk_canvas(), *dc, dirty_area.x(), |
| - dirty_area.y(), NULL); |
| - } else { |
| - HBRUSH white_brush = reinterpret_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)); |
| - dc->FillRect(&dirty_rect, white_brush); |
| - } |
| -} |
| - |
| -void RenderWidgetHostViewWin::OnNCPaint(HRGN update_region) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnNCPaint"); |
| - // Do nothing. This suppresses the resize corner that Windows would |
| - // otherwise draw for us. |
| -} |
| - |
| -void RenderWidgetHostViewWin::SetClickthroughRegion(SkRegion* region) { |
| - transparent_region_.reset(region); |
| -} |
| - |
| -LRESULT RenderWidgetHostViewWin::OnNCHitTest(const CPoint& point) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnNCHitTest"); |
| - RECT rc; |
| - GetWindowRect(&rc); |
| - if (transparent_region_.get() && |
| - transparent_region_->contains(point.x - rc.left, point.y - rc.top)) { |
| - SetMsgHandled(TRUE); |
| - return HTTRANSPARENT; |
| - } |
| - SetMsgHandled(FALSE); |
| - return 0; |
| -} |
| - |
| -LRESULT RenderWidgetHostViewWin::OnEraseBkgnd(HDC dc) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnEraseBkgnd"); |
| - return 1; |
| -} |
| - |
| -LRESULT RenderWidgetHostViewWin::OnSetCursor(HWND window, UINT hittest_code, |
| - UINT mouse_message_id) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnSetCursor"); |
| - UpdateCursorIfOverSelf(); |
| - return 0; |
| -} |
| - |
| -void RenderWidgetHostViewWin::OnSetFocus(HWND window) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnSetFocus"); |
| - if (!render_widget_host_) |
| - return; |
| - |
| - if (GetBrowserAccessibilityManager()) |
| - GetBrowserAccessibilityManager()->GotFocus(pointer_down_context_); |
| - |
| - render_widget_host_->GotFocus(); |
| - render_widget_host_->SetActive(true); |
| - |
| - if (base::win::IsTSFAwareRequired()) |
| - ui::TSFBridge::GetInstance()->SetFocusedClient(m_hWnd, this); |
| -} |
| - |
| -void RenderWidgetHostViewWin::OnKillFocus(HWND window) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnKillFocus"); |
| - if (!render_widget_host_) |
| - return; |
| - |
| - render_widget_host_->SetActive(false); |
| - render_widget_host_->Blur(); |
| - |
| - last_touch_location_ = gfx::Point(-1, -1); |
| - |
| - if (base::win::IsTSFAwareRequired()) |
| - ui::TSFBridge::GetInstance()->RemoveFocusedClient(this); |
| -} |
| - |
| -void RenderWidgetHostViewWin::OnCaptureChanged(HWND window) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnCaptureChanged"); |
| - if (render_widget_host_) |
| - render_widget_host_->LostCapture(); |
| - pointer_down_context_ = false; |
| -} |
| - |
| -void RenderWidgetHostViewWin::OnCancelMode() { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnCancelMode"); |
| - if (render_widget_host_) |
| - render_widget_host_->LostCapture(); |
| - |
| - if ((is_fullscreen_ || close_on_deactivate_) && |
| - !weak_factory_.HasWeakPtrs()) { |
| - // Dismiss popups and menus. We do this asynchronously to avoid changing |
| - // activation within this callstack, which may interfere with another window |
| - // being activated. We can synchronously hide the window, but we need to |
| - // not change activation while doing so. |
| - SetWindowPos(NULL, 0, 0, 0, 0, |
| - SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOMOVE | |
| - SWP_NOREPOSITION | SWP_NOSIZE | SWP_NOZORDER); |
| - base::MessageLoop::current()->PostTask( |
| - FROM_HERE, |
| - base::Bind(&RenderWidgetHostViewWin::ShutdownHost, |
| - weak_factory_.GetWeakPtr())); |
| - } |
| -} |
| - |
| -void RenderWidgetHostViewWin::OnInputLangChange(DWORD character_set, |
| - HKL input_language_id) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnInputLangChange"); |
| - // Send the given Locale ID to the IMM32Manager object and retrieves whether |
| - // or not the current input context has IMEs. |
| - // If the current input context has IMEs, a browser process has to send a |
| - // request to a renderer process that it needs status messages about |
| - // the focused edit control from the renderer process. |
| - // On the other hand, if the current input context does not have IMEs, the |
| - // browser process also has to send a request to the renderer process that |
| - // it does not need the status messages any longer. |
| - // To minimize the number of this notification request, we should check if |
| - // the browser process is actually retrieving the status messages (this |
| - // state is stored in ime_notification_) and send a request only if the |
| - // browser process has to update this status, its details are listed below: |
| - // * If a browser process is not retrieving the status messages, |
| - // (i.e. ime_notification_ == false), |
| - // send this request only if the input context does have IMEs, |
| - // (i.e. ime_status == true); |
| - // When it successfully sends the request, toggle its notification status, |
| - // (i.e.ime_notification_ = !ime_notification_ = true). |
| - // * If a browser process is retrieving the status messages |
| - // (i.e. ime_notification_ == true), |
| - // send this request only if the input context does not have IMEs, |
| - // (i.e. ime_status == false). |
| - // When it successfully sends the request, toggle its notification status, |
| - // (i.e.ime_notification_ = !ime_notification_ = false). |
| - // To analyze the above actions, we can optimize them into the ones |
| - // listed below: |
| - // 1 Sending a request only if ime_status_ != ime_notification_, and; |
| - // 2 Copying ime_status to ime_notification_ if it sends the request |
| - // successfully (because Action 1 shows ime_status = !ime_notification_.) |
| - bool ime_status = imm32_manager_->SetInputLanguage(); |
| - if (ime_status != ime_notification_) { |
| - if (render_widget_host_) { |
| - render_widget_host_->SetInputMethodActive(ime_status); |
| - ime_notification_ = ime_status; |
| - } |
| - } |
| - // Call DefWindowProc() for consistency with other Chrome windows. |
| - // TODO(hbono): This is a speculative fix for Bug 36354 and this code may be |
| - // reverted if it does not fix it. |
| - SetMsgHandled(FALSE); |
| -} |
| - |
| -void RenderWidgetHostViewWin::OnThemeChanged() { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnThemeChanged"); |
| - if (!render_widget_host_) |
| - return; |
| - render_widget_host_->Send(new ViewMsg_ThemeChanged( |
| - render_widget_host_->GetRoutingID())); |
| -} |
| - |
| -LRESULT RenderWidgetHostViewWin::OnNotify(int w_param, NMHDR* header) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnNotify"); |
| - if (tooltip_hwnd_ == NULL) |
| - return 0; |
| - |
| - switch (header->code) { |
| - case TTN_GETDISPINFO: { |
| - NMTTDISPINFOW* tooltip_info = reinterpret_cast<NMTTDISPINFOW*>(header); |
| - tooltip_info->szText[0] = L'\0'; |
| - tooltip_info->lpszText = const_cast<WCHAR*>(tooltip_text_.c_str()); |
| - ::SendMessage( |
| - tooltip_hwnd_, TTM_SETMAXTIPWIDTH, 0, kTooltipMaxWidthPixels); |
| - SetMsgHandled(TRUE); |
| - break; |
| - } |
| - case TTN_POP: |
| - tooltip_showing_ = false; |
| - SetMsgHandled(TRUE); |
| - break; |
| - case TTN_SHOW: |
| - // Tooltip shouldn't be shown when the mouse is locked. |
| - DCHECK(!mouse_locked_); |
| - tooltip_showing_ = true; |
| - SetMsgHandled(TRUE); |
| - break; |
| - } |
| - return 0; |
| -} |
| - |
| -LRESULT RenderWidgetHostViewWin::OnImeSetContext( |
| - UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnImeSetContext"); |
| - if (!render_widget_host_) |
| - return 0; |
| - |
| - // We need status messages about the focused input control from a |
| - // renderer process when: |
| - // * the current input context has IMEs, and; |
| - // * an application is activated. |
| - // This seems to tell we should also check if the current input context has |
| - // IMEs before sending a request, however, this WM_IME_SETCONTEXT is |
| - // fortunately sent to an application only while the input context has IMEs. |
| - // Therefore, we just start/stop status messages according to the activation |
| - // status of this application without checks. |
| - bool activated = (wparam == TRUE); |
| - if (render_widget_host_) { |
| - render_widget_host_->SetInputMethodActive(activated); |
| - ime_notification_ = activated; |
| - } |
| - |
| - if (ime_notification_) |
| - imm32_manager_->CreateImeWindow(m_hWnd); |
| - |
| - imm32_manager_->CleanupComposition(m_hWnd); |
| - return imm32_manager_->SetImeWindowStyle( |
| - m_hWnd, message, wparam, lparam, &handled); |
| -} |
| - |
| -LRESULT RenderWidgetHostViewWin::OnImeStartComposition( |
| - UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnImeStartComposition"); |
| - if (!render_widget_host_) |
| - return 0; |
| - |
| - // Reset the composition status and create IME windows. |
| - imm32_manager_->CreateImeWindow(m_hWnd); |
| - imm32_manager_->ResetComposition(m_hWnd); |
| - // When the focus is on an element that does not draw composition by itself |
| - // (i.e., PPAPI plugin not handling IME), let IME to draw the text. Otherwise |
| - // we have to prevent WTL from calling ::DefWindowProc() because the function |
| - // calls ::ImmSetCompositionWindow() and ::ImmSetCandidateWindow() to |
| - // over-write the position of IME windows. |
| - handled = (can_compose_inline_ ? TRUE : FALSE); |
| - return 0; |
| -} |
| - |
| -LRESULT RenderWidgetHostViewWin::OnImeComposition( |
| - UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnImeComposition"); |
| - if (!render_widget_host_) |
| - return 0; |
| - |
| - // At first, update the position of the IME window. |
| - imm32_manager_->UpdateImeWindow(m_hWnd); |
| - |
| - // ui::CompositionUnderline should be identical to |
| - // blink::WebCompositionUnderline, so that we can do reinterpret_cast safely. |
| - COMPILE_ASSERT(sizeof(ui::CompositionUnderline) == |
| - sizeof(blink::WebCompositionUnderline), |
| - ui_CompositionUnderline__WebKit_WebCompositionUnderline_diff); |
| - |
| - // Retrieve the result string and its attributes of the ongoing composition |
| - // and send it to a renderer process. |
| - ui::CompositionText composition; |
| - if (imm32_manager_->GetResult(m_hWnd, lparam, &composition.text)) { |
| - render_widget_host_->ImeConfirmComposition( |
| - composition.text, gfx::Range::InvalidRange(), false); |
| - imm32_manager_->ResetComposition(m_hWnd); |
| - // Fall though and try reading the composition string. |
| - // Japanese IMEs send a message containing both GCS_RESULTSTR and |
| - // GCS_COMPSTR, which means an ongoing composition has been finished |
| - // by the start of another composition. |
| - } |
| - // Retrieve the composition string and its attributes of the ongoing |
| - // composition and send it to a renderer process. |
| - if (imm32_manager_->GetComposition(m_hWnd, lparam, &composition)) { |
| - // TODO(suzhe): due to a bug of webkit, we can't use selection range with |
| - // composition string. See: https://bugs.webkit.org/show_bug.cgi?id=37788 |
| - composition.selection = gfx::Range(composition.selection.end()); |
| - |
| - // TODO(suzhe): convert both renderer_host and renderer to use |
| - // ui::CompositionText. |
| - const std::vector<blink::WebCompositionUnderline>& underlines = |
| - reinterpret_cast<const std::vector<blink::WebCompositionUnderline>&>( |
| - composition.underlines); |
| - render_widget_host_->ImeSetComposition( |
| - composition.text, underlines, |
| - composition.selection.start(), composition.selection.end()); |
| - } |
| - // We have to prevent WTL from calling ::DefWindowProc() because we do not |
| - // want for the IMM (Input Method Manager) to send WM_IME_CHAR messages. |
| - handled = TRUE; |
| - if (!can_compose_inline_) { |
| - // When the focus is on an element that does not draw composition by itself |
| - // (i.e., PPAPI plugin not handling IME), let IME to draw the text, which |
| - // is the default behavior of DefWindowProc. Note, however, even in this |
| - // case we don't want GCS_RESULTSTR to be converted to WM_IME_CHAR messages. |
| - // Thus we explicitly drop the flag. |
| - return ::DefWindowProc(m_hWnd, message, wparam, lparam & ~GCS_RESULTSTR); |
| - } |
| - return 0; |
| -} |
| - |
| -LRESULT RenderWidgetHostViewWin::OnImeEndComposition( |
| - UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnImeEndComposition"); |
| - if (!render_widget_host_) |
| - return 0; |
| - |
| - if (imm32_manager_->is_composing()) { |
| - // A composition has been ended while there is an ongoing composition, |
| - // i.e. the ongoing composition has been canceled. |
| - // We need to reset the composition status both of the IMM32Manager object |
| - // and of the renderer process. |
| - render_widget_host_->ImeCancelComposition(); |
| - imm32_manager_->ResetComposition(m_hWnd); |
| - } |
| - imm32_manager_->DestroyImeWindow(m_hWnd); |
| - // Let WTL call ::DefWindowProc() and release its resources. |
| - handled = FALSE; |
| - return 0; |
| -} |
| - |
| -LRESULT RenderWidgetHostViewWin::OnImeRequest( |
| - UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnImeRequest"); |
| - if (!render_widget_host_) { |
| - handled = FALSE; |
| - return 0; |
| - } |
| - |
| - // Should not receive WM_IME_REQUEST message, if IME is disabled. |
| - if (text_input_type_ == ui::TEXT_INPUT_TYPE_NONE || |
| - text_input_type_ == ui::TEXT_INPUT_TYPE_PASSWORD) { |
| - handled = FALSE; |
| - return 0; |
| - } |
| - |
| - switch (wparam) { |
| - case IMR_RECONVERTSTRING: |
| - return OnReconvertString(reinterpret_cast<RECONVERTSTRING*>(lparam)); |
| - case IMR_DOCUMENTFEED: |
| - return OnDocumentFeed(reinterpret_cast<RECONVERTSTRING*>(lparam)); |
| - case IMR_QUERYCHARPOSITION: |
| - return OnQueryCharPosition(reinterpret_cast<IMECHARPOSITION*>(lparam)); |
| - default: |
| - handled = FALSE; |
| - return 0; |
| - } |
| -} |
| - |
| -LRESULT RenderWidgetHostViewWin::OnMouseEvent(UINT message, WPARAM wparam, |
| - LPARAM lparam, BOOL& handled) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnMouseEvent"); |
| - handled = TRUE; |
| - |
| - if (message == WM_MOUSELEAVE) |
| - ignore_mouse_movement_ = true; |
| - |
| - if (mouse_locked_) { |
| - HandleLockedMouseEvent(message, wparam, lparam); |
| - MoveCursorToCenterIfNecessary(); |
| - return 0; |
| - } |
| - |
| - if (::IsWindow(tooltip_hwnd_)) { |
| - // Forward mouse events through to the tooltip window |
| - MSG msg; |
| - msg.hwnd = m_hWnd; |
| - msg.message = message; |
| - msg.wParam = wparam; |
| - msg.lParam = lparam; |
| - SendMessage(tooltip_hwnd_, TTM_RELAYEVENT, NULL, |
| - reinterpret_cast<LPARAM>(&msg)); |
| - } |
| - |
| - // Due to a bug in Windows, the simulated mouse events for a touch event |
| - // outside our bounds are delivered to us if we were previously focused |
| - // causing crbug.com/159982. As a workaround, we check if this event is a |
| - // simulated mouse event outside our bounds, and if so, we send it to the |
| - // right window. |
| - if ((message == WM_LBUTTONDOWN || message == WM_LBUTTONUP) && |
| - ui::IsMouseEventFromTouch(message)) { |
| - CPoint cursor_pos(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)); |
| - ClientToScreen(&cursor_pos); |
| - if (!GetPixelBounds().Contains(cursor_pos.x, cursor_pos.y)) { |
| - HWND window = WindowFromPoint(cursor_pos); |
| - if (window) { |
| - LRESULT nc_hit_result = SendMessage(window, WM_NCHITTEST, 0, |
| - MAKELPARAM(cursor_pos.x, cursor_pos.y)); |
| - const bool in_client_area = (nc_hit_result == HTCLIENT); |
| - int event_type; |
| - if (message == WM_LBUTTONDOWN) |
| - event_type = in_client_area ? WM_LBUTTONDOWN : WM_NCLBUTTONDOWN; |
| - else |
| - event_type = in_client_area ? WM_LBUTTONUP : WM_NCLBUTTONUP; |
| - |
| - // Convert the coordinates to the target window. |
| - RECT window_bounds; |
| - ::GetWindowRect(window, &window_bounds); |
| - int window_x = cursor_pos.x - window_bounds.left; |
| - int window_y = cursor_pos.y - window_bounds.top; |
| - if (in_client_area) { |
| - ::PostMessage(window, event_type, wparam, |
| - MAKELPARAM(window_x, window_y)); |
| - } else { |
| - ::PostMessage(window, event_type, nc_hit_result, |
| - MAKELPARAM(cursor_pos.x, cursor_pos.y)); |
| - } |
| - return 0; |
| - } |
| - } |
| - } |
| - |
| - // TODO(jcampan): I am not sure if we should forward the message to the |
| - // WebContentsImpl first in the case of popups. If we do, we would need to |
| - // convert the click from the popup window coordinates to the WebContentsImpl' |
| - // window coordinates. For now we don't forward the message in that case to |
| - // address bug #907474. |
| - // Note: GetParent() on popup windows returns the top window and not the |
| - // parent the window was created with (the parent and the owner of the popup |
| - // is the first non-child view of the view that was specified to the create |
| - // call). So the WebContentsImpl's window would have to be specified to the |
| - // RenderViewHostHWND as there is no way to retrieve it from the HWND. |
| - |
| - // Don't forward if the container is a popup or fullscreen widget. |
| - if (!is_fullscreen_ && !close_on_deactivate_) { |
| - switch (message) { |
| - case WM_LBUTTONDOWN: |
| - case WM_MBUTTONDOWN: |
| - case WM_RBUTTONDOWN: |
| - // Finish the ongoing composition whenever a mouse click happens. |
| - // It matches IE's behavior. |
| - if (base::win::IsTSFAwareRequired()) { |
| - ui::TSFBridge::GetInstance()->CancelComposition(); |
| - } else { |
| - imm32_manager_->CleanupComposition(m_hWnd); |
| - } |
| - // Fall through. |
| - case WM_MOUSEMOVE: |
| - case WM_MOUSELEAVE: { |
| - // Give the WebContentsImpl first crack at the message. It may want to |
| - // prevent forwarding to the renderer if some higher level browser |
| - // functionality is invoked. |
| - LPARAM parent_msg_lparam = lparam; |
| - if (message != WM_MOUSELEAVE) { |
| - // For the messages except WM_MOUSELEAVE, before forwarding them to |
| - // parent window, we should adjust cursor position from client |
| - // coordinates in current window to client coordinates in its parent |
| - // window. |
| - CPoint cursor_pos(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)); |
| - ClientToScreen(&cursor_pos); |
| - GetParent().ScreenToClient(&cursor_pos); |
| - parent_msg_lparam = MAKELPARAM(cursor_pos.x, cursor_pos.y); |
| - } |
| - if (SendMessage(GetParent(), message, wparam, parent_msg_lparam) != 0) { |
| - TRACE_EVENT0("browser", "EarlyOut_SentToParent"); |
| - return 1; |
| - } |
| - } |
| - } |
| - } |
| - |
| - if (message == WM_LBUTTONDOWN && pointer_down_context_ && |
| - GetBrowserAccessibilityManager()) { |
| - GetBrowserAccessibilityManager()->GotMouseDown(); |
| - } |
| - |
| - if (message == WM_LBUTTONUP && ui::IsMouseEventFromTouch(message) && |
| - base::win::IsMetroProcess()) |
| - pointer_down_context_ = false; |
| - |
| - ForwardMouseEventToRenderer(message, wparam, lparam); |
| - return 0; |
| -} |
| - |
| -LRESULT RenderWidgetHostViewWin::OnKeyEvent(UINT message, WPARAM wparam, |
| - LPARAM lparam, BOOL& handled) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnKeyEvent"); |
| - handled = TRUE; |
| - |
| - // When Escape is pressed, force fullscreen windows to close if necessary. |
| - if ((message == WM_KEYDOWN || message == WM_KEYUP) && wparam == VK_ESCAPE) { |
| - if (is_fullscreen_) { |
| - SendMessage(WM_CANCELMODE); |
| - return 0; |
| - } |
| - } |
| - |
| - // If we are a pop-up, forward tab related messages to our parent HWND, so |
| - // that we are dismissed appropriately and so that the focus advance in our |
| - // parent. |
| - // TODO(jcampan): http://b/issue?id=1192881 Could be abstracted in the |
| - // FocusManager. |
| - if (close_on_deactivate_ && |
| - (((message == WM_KEYDOWN || message == WM_KEYUP) && (wparam == VK_TAB)) || |
| - (message == WM_CHAR && wparam == L'\t'))) { |
| - // First close the pop-up. |
| - SendMessage(WM_CANCELMODE); |
| - // Then move the focus by forwarding the tab key to the parent. |
| - return ::SendMessage(GetParent(), message, wparam, lparam); |
| - } |
| - |
| - if (!render_widget_host_) |
| - return 0; |
| - |
| - // Bug 1845: we need to update the text direction when a user releases |
| - // either a right-shift key or a right-control key after pressing both of |
| - // them. So, we just update the text direction while a user is pressing the |
| - // keys, and we notify the text direction when a user releases either of them. |
| - // Bug 9718: http://crbug.com/9718 To investigate IE and notepad, this |
| - // shortcut is enabled only on a PC having RTL keyboard layouts installed. |
| - // We should emulate them. |
| - if (ui::IMM32Manager::IsRTLKeyboardLayoutInstalled()) { |
| - if (message == WM_KEYDOWN) { |
| - if (wparam == VK_SHIFT) { |
| - base::i18n::TextDirection dir; |
| - if (ui::IMM32Manager::IsCtrlShiftPressed(&dir)) { |
| - render_widget_host_->UpdateTextDirection( |
| - dir == base::i18n::RIGHT_TO_LEFT ? |
| - blink::WebTextDirectionRightToLeft : |
| - blink::WebTextDirectionLeftToRight); |
| - } |
| - } else if (wparam != VK_CONTROL) { |
| - // Bug 9762: http://crbug.com/9762 A user pressed a key except shift |
| - // and control keys. |
| - // When a user presses a key while he/she holds control and shift keys, |
| - // we cancel sending an IPC message in NotifyTextDirection() below and |
| - // ignore succeeding UpdateTextDirection() calls while we call |
| - // NotifyTextDirection(). |
| - // To cancel it, this call set a flag that prevents sending an IPC |
| - // message in NotifyTextDirection() only if we are going to send it. |
| - // It is harmless to call this function if we aren't going to send it. |
| - render_widget_host_->CancelUpdateTextDirection(); |
| - } |
| - } else if (message == WM_KEYUP && |
| - (wparam == VK_SHIFT || wparam == VK_CONTROL)) { |
| - // We send an IPC message only if we need to update the text direction. |
| - render_widget_host_->NotifyTextDirection(); |
| - } |
| - } |
| - |
| - // Special processing for enter key: When user hits enter in omnibox |
| - // we change focus to render host after the navigation, so repeat WM_KEYDOWNs |
| - // and WM_KEYUP are going to render host, despite being initiated in other |
| - // window. This code filters out these messages. |
| - bool ignore_keyboard_event = false; |
| - if (wparam == VK_RETURN) { |
| - if (message == WM_KEYDOWN || message == WM_SYSKEYDOWN) { |
| - if (KF_REPEAT & HIWORD(lparam)) { |
| - // this is a repeated key |
| - if (!capture_enter_key_) |
| - ignore_keyboard_event = true; |
| - } else { |
| - capture_enter_key_ = true; |
| - } |
| - } else if (message == WM_KEYUP || message == WM_SYSKEYUP) { |
| - if (!capture_enter_key_) |
| - ignore_keyboard_event = true; |
| - capture_enter_key_ = false; |
| - } else { |
| - // Ignore all other keyboard events for the enter key if not captured. |
| - if (!capture_enter_key_) |
| - ignore_keyboard_event = true; |
| - } |
| - } |
| - |
| - if (render_widget_host_ && !ignore_keyboard_event) { |
| - MSG msg = { m_hWnd, message, wparam, lparam }; |
| - render_widget_host_->ForwardKeyboardEvent(NativeWebKeyboardEvent(msg)); |
| - } |
| - |
| - return 0; |
| -} |
| - |
| -LRESULT RenderWidgetHostViewWin::OnWheelEvent(UINT message, WPARAM wparam, |
| - LPARAM lparam, BOOL& handled) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnWheelEvent"); |
| - // Forward the mouse-wheel message to the window under the mouse if it belongs |
| - // to us. |
| - if (message == WM_MOUSEWHEEL && |
| - ui::RerouteMouseWheel(m_hWnd, wparam, lparam)) { |
| - handled = TRUE; |
| - return 0; |
| - } |
| - |
| - // We get mouse wheel/scroll messages even if we are not in the foreground. |
| - // So here we check if we have any owned popup windows in the foreground and |
| - // dismiss them. |
| - if (m_hWnd != GetForegroundWindow()) { |
| - HWND toplevel_hwnd = ::GetAncestor(m_hWnd, GA_ROOT); |
| - EnumThreadWindows( |
| - GetCurrentThreadId(), |
| - DismissOwnedPopups, |
| - reinterpret_cast<LPARAM>(toplevel_hwnd)); |
| - } |
| - |
| - if (render_widget_host_) { |
| - blink::WebMouseWheelEvent wheel_event = |
| - WebMouseWheelEventBuilder::Build(m_hWnd, message, wparam, lparam); |
| - float scale = gfx::win::GetDeviceScaleFactor(); |
| - wheel_event.x /= scale; |
| - wheel_event.y /= scale; |
| - wheel_event.deltaX /= scale; |
| - wheel_event.deltaY /= scale; |
| - |
| - render_widget_host_->ForwardWheelEvent(wheel_event); |
| - } |
| - handled = TRUE; |
| - return 0; |
| -} |
| - |
| -WebTouchState::WebTouchState(const RenderWidgetHostViewWin* window) |
| - : window_(window), |
| - id_generator_(0) { |
| -} |
| - |
| -size_t WebTouchState::UpdateTouchPoints( |
| - TOUCHINPUT* points, size_t count) { |
| - // First we reset all touch event state. This involves removing any released |
| - // touchpoints and marking the rest as stationary. After that we go through |
| - // and alter/add any touchpoints (from the touch input buffer) that we can |
| - // coalesce into a single message. The return value is the number of consumed |
| - // input message. |
| - blink::WebTouchPoint* point = touch_event_.touches; |
| - blink::WebTouchPoint* end = point + touch_event_.touchesLength; |
| - while (point < end) { |
| - if (point->state == blink::WebTouchPoint::StateReleased) { |
| - *point = *(--end); |
| - --touch_event_.touchesLength; |
| - } else { |
| - point->state = blink::WebTouchPoint::StateStationary; |
| - point++; |
| - } |
| - } |
| - touch_event_.changedTouchesLength = 0; |
| - touch_event_.modifiers = content::EventFlagsToWebEventModifiers( |
| - ui::GetModifiersFromKeyState()); |
| - |
| - // Consume all events of the same type and add them to the changed list. |
| - int last_type = 0; |
| - for (size_t i = 0; i < count; ++i) { |
| - unsigned int mapped_id = GetMappedTouch(points[i].dwID); |
| - |
| - blink::WebTouchPoint* point = NULL; |
| - for (unsigned j = 0; j < touch_event_.touchesLength; ++j) { |
| - if (static_cast<DWORD>(touch_event_.touches[j].id) == mapped_id) { |
| - point = &touch_event_.touches[j]; |
| - break; |
| - } |
| - } |
| - |
| - // Use a move instead if we see a down on a point we already have. |
| - int type = GetTouchType(points[i]); |
| - if (point && type == TOUCHEVENTF_DOWN) |
| - SetTouchType(&points[i], TOUCHEVENTF_MOVE); |
| - |
| - // Stop processing when the event type changes. |
| - if (touch_event_.changedTouchesLength && type != last_type) |
| - return i; |
| - |
| - touch_event_.timeStampSeconds = points[i].dwTime / 1000.0; |
| - |
| - last_type = type; |
| - switch (type) { |
| - case TOUCHEVENTF_DOWN: { |
| - if (!(point = AddTouchPoint(&points[i]))) |
| - continue; |
| - touch_event_.type = blink::WebInputEvent::TouchStart; |
| - break; |
| - } |
| - |
| - case TOUCHEVENTF_UP: { |
| - if (!point) // Just throw away a stray up. |
| - continue; |
| - point->state = blink::WebTouchPoint::StateReleased; |
| - UpdateTouchPoint(point, &points[i]); |
| - touch_event_.type = blink::WebInputEvent::TouchEnd; |
| - break; |
| - } |
| - |
| - case TOUCHEVENTF_MOVE: { |
| - if (point) { |
| - point->state = blink::WebTouchPoint::StateMoved; |
| - // Don't update the message if the point didn't really move. |
| - if (UpdateTouchPoint(point, &points[i])) |
| - continue; |
| - touch_event_.type = blink::WebInputEvent::TouchMove; |
| - } else if (touch_event_.changedTouchesLength) { |
| - RemoveExpiredMappings(); |
| - // Can't add a point if we're already handling move events. |
| - return i; |
| - } else { |
| - // Treat a move with no existing point as a down. |
| - if (!(point = AddTouchPoint(&points[i]))) |
| - continue; |
| - last_type = TOUCHEVENTF_DOWN; |
| - SetTouchType(&points[i], TOUCHEVENTF_DOWN); |
| - touch_event_.type = blink::WebInputEvent::TouchStart; |
| - } |
| - break; |
| - } |
| - |
| - default: |
| - NOTREACHED(); |
| - continue; |
| - } |
| - touch_event_.changedTouches[touch_event_.changedTouchesLength++] = *point; |
| - } |
| - |
| - RemoveExpiredMappings(); |
| - return count; |
| -} |
| - |
| -void WebTouchState::RemoveExpiredMappings() { |
| - blink::WebTouchPoint* point = touch_event_.touches; |
| - blink::WebTouchPoint* end = point + touch_event_.touchesLength; |
| - for (; point < end; ++point) { |
| - if (point->state == blink::WebTouchPoint::StateReleased) |
| - id_generator_.ReleaseGeneratedID(point->id); |
| - } |
| -} |
| - |
| - |
| -bool WebTouchState::ReleaseTouchPoints() { |
| - if (touch_event_.touchesLength == 0) |
| - return false; |
| - // Mark every active touchpoint as released. |
| - touch_event_.type = blink::WebInputEvent::TouchEnd; |
| - touch_event_.changedTouchesLength = touch_event_.touchesLength; |
| - for (unsigned int i = 0; i < touch_event_.touchesLength; ++i) { |
| - touch_event_.touches[i].state = blink::WebTouchPoint::StateReleased; |
| - touch_event_.changedTouches[i].state = |
| - blink::WebTouchPoint::StateReleased; |
| - } |
| - |
| - return true; |
| -} |
| - |
| -blink::WebTouchPoint* WebTouchState::AddTouchPoint( |
| - TOUCHINPUT* touch_input) { |
| - DCHECK(touch_event_.touchesLength < |
| - blink::WebTouchEvent::touchesLengthCap); |
| - if (touch_event_.touchesLength >= |
| - blink::WebTouchEvent::touchesLengthCap) |
| - return NULL; |
| - blink::WebTouchPoint* point = |
| - &touch_event_.touches[touch_event_.touchesLength++]; |
| - point->state = blink::WebTouchPoint::StatePressed; |
| - point->id = GetMappedTouch(touch_input->dwID); |
| - UpdateTouchPoint(point, touch_input); |
| - return point; |
| -} |
| - |
| -bool WebTouchState::UpdateTouchPoint( |
| - blink::WebTouchPoint* touch_point, |
| - TOUCHINPUT* touch_input) { |
| - CPoint coordinates( |
| - TOUCH_COORD_TO_PIXEL(touch_input->x) / |
| - gfx::win::GetUndocumentedDPITouchScale(), |
| - TOUCH_COORD_TO_PIXEL(touch_input->y) / |
| - gfx::win::GetUndocumentedDPITouchScale()); |
| - int radius_x = 1; |
| - int radius_y = 1; |
| - if (touch_input->dwMask & TOUCHINPUTMASKF_CONTACTAREA) { |
| - // Some touch drivers send a contact area of "-1", yet flag it as valid. |
| - radius_x = std::max(1, |
| - static_cast<int>(TOUCH_COORD_TO_PIXEL(touch_input->cxContact) / |
| - gfx::win::GetUndocumentedDPITouchScale())); |
| - radius_y = std::max(1, |
| - static_cast<int>(TOUCH_COORD_TO_PIXEL(touch_input->cyContact) / |
| - gfx::win::GetUndocumentedDPITouchScale())); |
| - } |
| - |
| - // Detect and exclude stationary moves. |
| - if (GetTouchType(*touch_input) == TOUCHEVENTF_MOVE && |
| - touch_point->screenPosition.x == coordinates.x && |
| - touch_point->screenPosition.y == coordinates.y && |
| - touch_point->radiusX == radius_x && |
| - touch_point->radiusY == radius_y) { |
| - touch_point->state = blink::WebTouchPoint::StateStationary; |
| - return true; |
| - } |
| - |
| - touch_point->screenPosition.x = coordinates.x; |
| - touch_point->screenPosition.y = coordinates.y; |
| - window_->ScreenToClient(&coordinates); |
| - static float scale = gfx::win::GetDeviceScaleFactor(); |
| - touch_point->position.x = coordinates.x / scale; |
| - touch_point->position.y = coordinates.y / scale; |
| - touch_point->radiusX = radius_x; |
| - touch_point->radiusY = radius_y; |
| - touch_point->force = 0; |
| - touch_point->rotationAngle = 0; |
| - return false; |
| -} |
| - |
| -// Find (or create) a mapping for _os_touch_id_. |
| -unsigned int WebTouchState::GetMappedTouch(unsigned int os_touch_id) { |
| - return id_generator_.GetGeneratedID(os_touch_id); |
| -} |
| - |
| -LRESULT RenderWidgetHostViewWin::OnTouchEvent(UINT message, WPARAM wparam, |
| - LPARAM lparam, BOOL& handled) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnTouchEvent"); |
| - // Finish the ongoing composition whenever a touch event happens. |
| - // It matches IE's behavior. |
| - if (base::win::IsTSFAwareRequired()) { |
| - ui::TSFBridge::GetInstance()->CancelComposition(); |
| - } else { |
| - imm32_manager_->CleanupComposition(m_hWnd); |
| - } |
| - |
| - // TODO(jschuh): Add support for an arbitrary number of touchpoints. |
| - size_t total = std::min(static_cast<int>(LOWORD(wparam)), |
| - static_cast<int>(blink::WebTouchEvent::touchesLengthCap)); |
| - TOUCHINPUT points[blink::WebTouchEvent::touchesLengthCap]; |
| - |
| - if (!total || !ui::GetTouchInputInfoWrapper((HTOUCHINPUT)lparam, total, |
| - points, sizeof(TOUCHINPUT))) { |
| - TRACE_EVENT0("browser", "EarlyOut_NothingToDo"); |
| - return 0; |
| - } |
| - |
| - if (total == 1 && (points[0].dwFlags & TOUCHEVENTF_DOWN)) { |
| - pointer_down_context_ = true; |
| - last_touch_location_ = gfx::Point( |
| - TOUCH_COORD_TO_PIXEL(points[0].x) / |
| - gfx::win::GetUndocumentedDPITouchScale(), |
| - TOUCH_COORD_TO_PIXEL(points[0].y) / |
| - gfx::win::GetUndocumentedDPITouchScale()); |
| - } |
| - |
| - bool should_forward = render_widget_host_->ShouldForwardTouchEvent() && |
| - touch_events_enabled_; |
| - |
| - // Send a copy of the touch events on to the gesture recognizer. |
| - for (size_t start = 0; start < total;) { |
| - start += touch_state_->UpdateTouchPoints(points + start, total - start); |
| - if (should_forward) { |
| - if (touch_state_->is_changed()) |
| - render_widget_host_->ForwardTouchEventWithLatencyInfo( |
| - touch_state_->touch_event(), ui::LatencyInfo()); |
| - } else { |
| - const blink::WebTouchEvent& touch_event = touch_state_->touch_event(); |
| - base::TimeDelta timestamp = base::TimeDelta::FromMilliseconds( |
| - touch_event.timeStampSeconds * 1000); |
| - for (size_t i = 0; i < touch_event.touchesLength; ++i) { |
| - scoped_ptr<ui::GestureRecognizer::Gestures> gestures; |
| - gestures.reset(gesture_recognizer_->ProcessTouchEventForGesture( |
| - TouchEventFromWebTouchPoint(touch_event.touches[i], timestamp), |
| - ui::ER_UNHANDLED, this)); |
| - ProcessGestures(gestures.get()); |
| - } |
| - } |
| - } |
| - |
| - CloseTouchInputHandle((HTOUCHINPUT)lparam); |
| - |
| - return 0; |
| -} |
| - |
| -void RenderWidgetHostViewWin::ProcessGestures( |
| - ui::GestureRecognizer::Gestures* gestures) { |
| - if ((gestures == NULL) || gestures->empty()) |
| - return; |
| - for (ui::GestureRecognizer::Gestures::iterator g_it = gestures->begin(); |
| - g_it != gestures->end(); |
| - ++g_it) { |
| - ForwardGestureEventToRenderer(*g_it); |
| - } |
| -} |
| - |
| -LRESULT RenderWidgetHostViewWin::OnMouseActivate(UINT message, |
| - WPARAM wparam, |
| - LPARAM lparam, |
| - BOOL& handled) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnMouseActivate"); |
| - if (!render_widget_host_) |
| - return MA_NOACTIVATE; |
| - |
| - if (!IsActivatable()) |
| - return MA_NOACTIVATE; |
| - |
| - HWND focus_window = GetFocus(); |
| - if (!::IsWindow(focus_window) || !IsChild(focus_window)) { |
| - // We handle WM_MOUSEACTIVATE to set focus to the underlying plugin |
| - // child window. This is to ensure that keyboard events are received |
| - // by the plugin. The correct way to fix this would be send over |
| - // an event to the renderer which would then eventually send over |
| - // a setFocus call to the plugin widget. This would ensure that |
| - // the renderer (webkit) knows about the plugin widget receiving |
| - // focus. |
| - // TODO(iyengar) Do the right thing as per the above comment. |
| - POINT cursor_pos = {0}; |
| - ::GetCursorPos(&cursor_pos); |
| - ::ScreenToClient(m_hWnd, &cursor_pos); |
| - HWND child_window = ::RealChildWindowFromPoint(m_hWnd, cursor_pos); |
| - if (::IsWindow(child_window) && child_window != m_hWnd) { |
| - if (gfx::GetClassName(child_window) == kWrapperNativeWindowClassName) |
| - child_window = ::GetWindow(child_window, GW_CHILD); |
| - |
| - ::SetFocus(child_window); |
| - return MA_NOACTIVATE; |
| - } |
| - } |
| - handled = FALSE; |
| - render_widget_host_->OnPointerEventActivate(); |
| - return MA_ACTIVATE; |
| -} |
| - |
| -LRESULT RenderWidgetHostViewWin::OnGestureEvent( |
| - UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnGestureEvent"); |
| - |
| - DCHECK(!touch_events_enabled_); |
| - handled = FALSE; |
| - |
| - GESTUREINFO gi = {sizeof(GESTUREINFO)}; |
| - HGESTUREINFO gi_handle = reinterpret_cast<HGESTUREINFO>(lparam); |
| - if (!::GetGestureInfo(gi_handle, &gi)) { |
| - DWORD error = GetLastError(); |
| - NOTREACHED() << "Unable to get gesture info. Error : " << error; |
| - return 0; |
| - } |
| - |
| - if (gi.dwID == GID_ZOOM) { |
| - PageZoom zoom = PAGE_ZOOM_RESET; |
| - POINT zoom_center = {0}; |
| - if (DecodeZoomGesture(m_hWnd, gi, &zoom, &zoom_center)) { |
| - handled = TRUE; |
| - Send(new ViewMsg_ZoomFactor(render_widget_host_->GetRoutingID(), |
| - zoom, zoom_center.x, zoom_center.y)); |
| - } |
| - } else if (gi.dwID == GID_PAN) { |
| - // Right now we only decode scroll gestures and we forward to the page |
| - // as scroll events. |
| - POINT start; |
| - POINT delta; |
| - if (DecodeScrollGesture(gi, &start, &delta)) { |
| - handled = TRUE; |
| - render_widget_host_->ForwardWheelEvent( |
| - MakeFakeScrollWheelEvent(m_hWnd, start, delta)); |
| - } |
| - } |
| - ::CloseGestureInfoHandle(gi_handle); |
| - return 0; |
| -} |
| - |
| -LRESULT RenderWidgetHostViewWin::OnMoveOrSize( |
| - UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) { |
| - // Reset the cliping rectangle if the mouse is locked. |
| - if (mouse_locked_) { |
| - CRect rect; |
| - GetWindowRect(&rect); |
| - ::ClipCursor(&rect); |
| - } |
| - return 0; |
| -} |
| - |
| -void RenderWidgetHostViewWin::CreateBrowserAccessibilityManagerIfNeeded() { |
| - if (GetBrowserAccessibilityManager()) |
| - return; |
| - |
| - HRESULT hr = ::CreateStdAccessibleObject( |
| - m_hWnd, OBJID_WINDOW, IID_IAccessible, |
| - reinterpret_cast<void **>(&window_iaccessible_)); |
| - DCHECK(SUCCEEDED(hr)); |
| - |
| - SetBrowserAccessibilityManager( |
| - new BrowserAccessibilityManagerWin( |
| - m_hWnd, |
| - window_iaccessible_.get(), |
| - BrowserAccessibilityManagerWin::GetEmptyDocument(), |
| - this)); |
| -} |
| - |
| -bool RenderWidgetHostViewWin::LockMouse() { |
| - if (mouse_locked_) |
| - return true; |
| - |
| - mouse_locked_ = true; |
| - |
| - // Hide the tooltip window if it is currently visible. When the mouse is |
| - // locked, no mouse message is relayed to the tooltip window, so we don't need |
| - // to worry that it will reappear. |
| - if (::IsWindow(tooltip_hwnd_) && tooltip_showing_) { |
| - ::SendMessage(tooltip_hwnd_, TTM_POP, 0, 0); |
| - // Sending a TTM_POP message doesn't seem to actually hide the tooltip |
| - // window, although we will receive a TTN_POP notification. As a result, |
| - // ShowWindow() is explicitly called to hide the window. |
| - ::ShowWindow(tooltip_hwnd_, SW_HIDE); |
| - } |
| - |
| - // TODO(yzshen): ShowCursor(FALSE) causes SetCursorPos() to be ignored on |
| - // Remote Desktop. |
| - ::ShowCursor(FALSE); |
| - |
| - move_to_center_request_.pending = false; |
| - last_mouse_position_.locked_global = last_mouse_position_.unlocked_global; |
| - |
| - // Must set the clip rectangle before MoveCursorToCenterIfNecessary() |
| - // so that if the cursor is moved it uses the clip rect set to the window |
| - // rect. Otherwise, MoveCursorToCenterIfNecessary() may move the cursor |
| - // to the center of the screen, and then we would clip to the window |
| - // rect, thus moving the cursor and causing a movement delta. |
| - CRect rect; |
| - GetWindowRect(&rect); |
| - ::ClipCursor(&rect); |
| - MoveCursorToCenterIfNecessary(); |
| - |
| - return true; |
| -} |
| - |
| -void RenderWidgetHostViewWin::UnlockMouse() { |
| - if (!mouse_locked_) |
| - return; |
| - |
| - mouse_locked_ = false; |
| - |
| - ::ClipCursor(NULL); |
| - ::SetCursorPos(last_mouse_position_.unlocked_global.x(), |
| - last_mouse_position_.unlocked_global.y()); |
| - ::ShowCursor(TRUE); |
| - |
| - if (render_widget_host_) |
| - render_widget_host_->LostMouseLock(); |
| -} |
| - |
| -void RenderWidgetHostViewWin::Observe( |
| - int type, |
| - const NotificationSource& source, |
| - const NotificationDetails& details) { |
| - DCHECK(type == NOTIFICATION_RENDERER_PROCESS_TERMINATED); |
| - |
| - // Get the RenderProcessHost that posted this notification, and exit |
| - // if it's not the one associated with this host view. |
| - RenderProcessHost* render_process_host = |
| - Source<RenderProcessHost>(source).ptr(); |
| - DCHECK(render_process_host); |
| - if (!render_widget_host_ || |
| - render_process_host != render_widget_host_->GetProcess()) { |
| - return; |
| - } |
| - |
| - // If it was our RenderProcessHost that posted the notification, |
| - // clear the BrowserAccessibilityManager, because the renderer is |
| - // dead and any accessibility information we have is now stale. |
| - SetBrowserAccessibilityManager(NULL); |
| -} |
| - |
| -static void PaintCompositorHostWindow(HWND hWnd) { |
| - PAINTSTRUCT paint; |
| - BeginPaint(hWnd, &paint); |
| - |
| - RenderWidgetHostViewWin* win = static_cast<RenderWidgetHostViewWin*>( |
| - gfx::GetWindowUserData(hWnd)); |
| - // Trigger composite to rerender window. |
| - if (win) |
| - win->AcceleratedPaint(paint.hdc); |
| - |
| - EndPaint(hWnd, &paint); |
| -} |
| - |
| -// WndProc for the compositor host window. We use this instead of Default so |
| -// we can drop WM_PAINT and WM_ERASEBKGD messages on the floor. |
| -static LRESULT CALLBACK CompositorHostWindowProc(HWND hWnd, UINT message, |
| - WPARAM wParam, LPARAM lParam) { |
| - switch (message) { |
| - case WM_ERASEBKGND: |
| - return 0; |
| - case WM_PAINT: |
| - PaintCompositorHostWindow(hWnd); |
| - return 0; |
| - default: |
| - return DefWindowProc(hWnd, message, wParam, lParam); |
| - } |
| -} |
| - |
| -void RenderWidgetHostViewWin::AcceleratedPaint(HDC dc) { |
| - if (render_widget_host_) |
| - render_widget_host_->ScheduleComposite(); |
| - if (accelerated_surface_) |
| - accelerated_surface_->Present(dc); |
| -} |
| - |
| -void RenderWidgetHostViewWin::GetScreenInfo(blink::WebScreenInfo* results) { |
| - GetScreenInfoForWindow(GetNativeViewId(), results); |
| -} |
| - |
| -gfx::Rect RenderWidgetHostViewWin::GetBoundsInRootWindow() { |
| - RECT window_rect = {0}; |
| - HWND root_window = GetAncestor(m_hWnd, GA_ROOT); |
| - ::GetWindowRect(root_window, &window_rect); |
| - gfx::Rect rect(window_rect); |
| - |
| - // Maximized windows are outdented from the work area by the frame thickness |
| - // even though this "frame" is not painted. This confuses code (and people) |
| - // that think of a maximized window as corresponding exactly to the work area. |
| - // Correct for this by subtracting the frame thickness back off. |
| - if (::IsZoomed(root_window)) { |
| - rect.Inset(GetSystemMetrics(SM_CXSIZEFRAME), |
| - GetSystemMetrics(SM_CYSIZEFRAME)); |
| - } |
| - |
| - return gfx::win::ScreenToDIPRect(rect); |
| -} |
| - |
| -// Creates a HWND within the RenderWidgetHostView that will serve as a host |
| -// for a HWND that the GPU process will create. The host window is used |
| -// to Z-position the GPU's window relative to other plugin windows. |
| -gfx::GLSurfaceHandle RenderWidgetHostViewWin::GetCompositingSurface() { |
| - // If the window has been created, don't recreate it a second time |
| - if (compositor_host_window_) |
| - return gfx::GLSurfaceHandle(compositor_host_window_, gfx::NATIVE_TRANSPORT); |
| - |
| - // On Vista and later we present directly to the view window rather than a |
| - // child window. |
| - if (GpuDataManagerImpl::GetInstance()->IsUsingAcceleratedSurface()) { |
| - if (!accelerated_surface_) |
| - accelerated_surface_.reset(new AcceleratedSurface(m_hWnd)); |
| - return gfx::GLSurfaceHandle(m_hWnd, gfx::NATIVE_TRANSPORT); |
| - } |
| - |
| - // On XP we need a child window that can be resized independently of the |
| - // parent. |
| - static ATOM atom = 0; |
| - static HMODULE instance = NULL; |
| - if (!atom) { |
| - WNDCLASSEX window_class; |
| - base::win::InitializeWindowClass( |
| - L"CompositorHostWindowClass", |
| - &base::win::WrappedWindowProc<CompositorHostWindowProc>, |
| - 0, 0, 0, NULL, NULL, NULL, NULL, NULL, |
| - &window_class); |
| - instance = window_class.hInstance; |
| - atom = RegisterClassEx(&window_class); |
| - DCHECK(atom); |
| - } |
| - |
| - RECT currentRect; |
| - GetClientRect(¤tRect); |
| - |
| - // Ensure window does not have zero area because D3D cannot create a zero |
| - // area swap chain. |
| - int width = std::max(1, |
| - static_cast<int>(currentRect.right - currentRect.left)); |
| - int height = std::max(1, |
| - static_cast<int>(currentRect.bottom - currentRect.top)); |
| - |
| - compositor_host_window_ = CreateWindowEx( |
| - WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR, |
| - MAKEINTATOM(atom), 0, |
| - WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_DISABLED, |
| - 0, 0, width, height, m_hWnd, 0, instance, 0); |
| - gfx::CheckWindowCreated(compositor_host_window_); |
| - |
| - gfx::SetWindowUserData(compositor_host_window_, this); |
| - |
| - gfx::GLSurfaceHandle surface_handle(compositor_host_window_, |
| - gfx::NATIVE_TRANSPORT); |
| - return surface_handle; |
| -} |
| - |
| -void RenderWidgetHostViewWin::ResizeCompositingSurface(const gfx::Size& size) { |
| - // Ensure window does not have zero area because D3D cannot create a zero |
| - // area swap chain. |
| - ::SetWindowPos(compositor_host_window_, |
| - NULL, |
| - 0, 0, |
| - std::max(1, size.width()), |
| - std::max(1, size.height()), |
| - SWP_NOSENDCHANGING | SWP_NOCOPYBITS | SWP_NOZORDER | |
| - SWP_NOACTIVATE | SWP_DEFERERASE | SWP_NOMOVE); |
| -} |
| - |
| -void RenderWidgetHostViewWin::OnAcceleratedCompositingStateChange() { |
| - bool show = render_widget_host_->is_accelerated_compositing_active(); |
| - // When we first create the compositor, we will get a show request from |
| - // the renderer before we have gotten the create request from the GPU. In this |
| - // case, simply ignore the show request. |
| - if (compositor_host_window_ == NULL) |
| - return; |
| - |
| - if (show) { |
| - ::ShowWindow(compositor_host_window_, SW_SHOW); |
| - |
| - // Get all the child windows of this view, including the compositor window. |
| - std::vector<HWND> all_child_windows; |
| - ::EnumChildWindows(m_hWnd, AddChildWindowToVector, |
| - reinterpret_cast<LPARAM>(&all_child_windows)); |
| - |
| - // Build a list of just the plugin window handles |
| - std::vector<HWND> plugin_windows; |
| - bool compositor_host_window_found = false; |
| - for (size_t i = 0; i < all_child_windows.size(); ++i) { |
| - if (all_child_windows[i] != compositor_host_window_) |
| - plugin_windows.push_back(all_child_windows[i]); |
| - else |
| - compositor_host_window_found = true; |
| - } |
| - DCHECK(compositor_host_window_found); |
| - |
| - // Set all the plugin windows to be "after" the compositor window. |
| - // When the compositor window is created, gets placed above plugins. |
| - for (size_t i = 0; i < plugin_windows.size(); ++i) { |
| - HWND next; |
| - if (i + 1 < plugin_windows.size()) |
| - next = plugin_windows[i+1]; |
| - else |
| - next = compositor_host_window_; |
| - ::SetWindowPos(plugin_windows[i], next, 0, 0, 0, 0, |
| - SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); |
| - } |
| - } else { |
| - // Drop the backing store for the accelerated surface when the accelerated |
| - // compositor is disabled. Otherwise, a flash of the last presented frame |
| - // could appear when it is next enabled. |
| - if (accelerated_surface_) |
| - accelerated_surface_->Suspend(); |
| - hide_compositor_window_at_next_paint_ = true; |
| - } |
| -} |
| - |
| -void RenderWidgetHostViewWin::AcceleratedSurfaceInitialized(int host_id, |
| - int route_id) { |
| -} |
| - |
| -void RenderWidgetHostViewWin::AcceleratedSurfaceBuffersSwapped( |
| - const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params, |
| - int gpu_host_id) { |
| - NOTREACHED(); |
| -} |
| - |
| -void RenderWidgetHostViewWin::AcceleratedSurfacePostSubBuffer( |
| - const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params, |
| - int gpu_host_id) { |
| - NOTREACHED(); |
| -} |
| - |
| -void RenderWidgetHostViewWin::AcceleratedSurfaceSuspend() { |
| - if (!accelerated_surface_) |
| - return; |
| - |
| - accelerated_surface_->Suspend(); |
| -} |
| - |
| -void RenderWidgetHostViewWin::AcceleratedSurfaceRelease() { |
| -} |
| - |
| -bool RenderWidgetHostViewWin::HasAcceleratedSurface( |
| - const gfx::Size& desired_size) { |
| - // TODO(jbates) Implement this so this view can use GetBackingStore for both |
| - // software and GPU frames. Defaulting to false just makes GetBackingStore |
| - // only useable for software frames. |
| - return false; |
| -} |
| - |
| -void RenderWidgetHostViewWin::SetAccessibilityFocus(int acc_obj_id) { |
| - if (!render_widget_host_) |
| - return; |
| - |
| - render_widget_host_->AccessibilitySetFocus(acc_obj_id); |
| -} |
| - |
| -void RenderWidgetHostViewWin::AccessibilityDoDefaultAction(int acc_obj_id) { |
| - if (!render_widget_host_) |
| - return; |
| - |
| - render_widget_host_->AccessibilityDoDefaultAction(acc_obj_id); |
| -} |
| - |
| -void RenderWidgetHostViewWin::AccessibilityScrollToMakeVisible( |
| - int acc_obj_id, gfx::Rect subfocus) { |
| - if (!render_widget_host_) |
| - return; |
| - |
| - render_widget_host_->AccessibilityScrollToMakeVisible(acc_obj_id, subfocus); |
| -} |
| - |
| -void RenderWidgetHostViewWin::AccessibilityScrollToPoint( |
| - int acc_obj_id, gfx::Point point) { |
| - if (!render_widget_host_) |
| - return; |
| - |
| - render_widget_host_->AccessibilityScrollToPoint(acc_obj_id, point); |
| -} |
| - |
| -void RenderWidgetHostViewWin::AccessibilitySetTextSelection( |
| - int acc_obj_id, int start_offset, int end_offset) { |
| - if (!render_widget_host_) |
| - return; |
| - |
| - render_widget_host_->AccessibilitySetTextSelection( |
| - acc_obj_id, start_offset, end_offset); |
| -} |
| - |
| -gfx::Point RenderWidgetHostViewWin::GetLastTouchEventLocation() const { |
| - return last_touch_location_; |
| -} |
| - |
| -void RenderWidgetHostViewWin::FatalAccessibilityTreeError() { |
| - render_widget_host_->FatalAccessibilityTreeError(); |
| - SetBrowserAccessibilityManager(NULL); |
| -} |
| - |
| -LRESULT RenderWidgetHostViewWin::OnGetObject(UINT message, WPARAM wparam, |
| - LPARAM lparam, BOOL& handled) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnGetObject"); |
| - if (kIdCustom == lparam) { |
| - // An MSAA client requestes our custom id. Assume that we have detected an |
| - // active windows screen reader. |
| - BrowserAccessibilityState::GetInstance()->OnScreenReaderDetected(); |
| - render_widget_host_->SetAccessibilityMode( |
| - BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode()); |
| - |
| - // Return with failure. |
| - return static_cast<LRESULT>(0L); |
| - } |
| - |
| - if (lparam != OBJID_CLIENT) { |
| - handled = false; |
| - return static_cast<LRESULT>(0L); |
| - } |
| - |
| - IAccessible* iaccessible = GetNativeViewAccessible(); |
| - if (iaccessible) |
| - return LresultFromObject(IID_IAccessible, wparam, iaccessible); |
| - |
| - handled = false; |
| - return static_cast<LRESULT>(0L); |
| -} |
| - |
| -LRESULT RenderWidgetHostViewWin::OnParentNotify(UINT message, WPARAM wparam, |
| - LPARAM lparam, BOOL& handled) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnParentNotify"); |
| - handled = FALSE; |
| - |
| - if (!render_widget_host_) |
| - return 0; |
| - |
| - switch (LOWORD(wparam)) { |
| - case WM_LBUTTONDOWN: |
| - case WM_RBUTTONDOWN: |
| - case WM_MBUTTONDOWN: |
| - render_widget_host_->StartUserGesture(); |
| - break; |
| - default: |
| - break; |
| - } |
| - return 0; |
| -} |
| - |
| -void RenderWidgetHostViewWin::OnFinalMessage(HWND window) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnFinalMessage"); |
| - // When the render widget host is being destroyed, it ends up calling |
| - // Destroy() which NULLs render_widget_host_. |
| - // Note: the following bug http://crbug.com/24248 seems to report that |
| - // OnFinalMessage is called with a deleted |render_widget_host_|. It is not |
| - // clear how this could happen, hence the NULLing of render_widget_host_ |
| - // above. |
| - if (!render_widget_host_ && !being_destroyed_) { |
| - // If you hit this NOTREACHED, please add a comment to report it on |
| - // http://crbug.com/24248, including what you did when it happened and if |
| - // you can repro. |
| - NOTREACHED(); |
| - } |
| - if (render_widget_host_) |
| - render_widget_host_->ViewDestroyed(); |
| - if (base::win::IsTSFAwareRequired()) |
| - ui::TSFBridge::GetInstance()->RemoveFocusedClient(this); |
| - delete this; |
| -} |
| - |
| -LRESULT RenderWidgetHostViewWin::OnSessionChange(UINT message, |
| - WPARAM wparam, |
| - LPARAM lparam, |
| - BOOL& handled) { |
| - handled = FALSE; |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnSessionChange"); |
| - |
| - if (!accelerated_surface_) |
| - return 0; |
| - |
| - switch (wparam) { |
| - case WTS_SESSION_LOCK: |
| - accelerated_surface_->SetIsSessionLocked(true); |
| - break; |
| - case WTS_SESSION_UNLOCK: |
| - // Force a repaint to update the window contents. |
| - if (!render_widget_host_->is_hidden()) |
| - InvalidateRect(NULL, FALSE); |
| - accelerated_surface_->SetIsSessionLocked(false); |
| - break; |
| - default: |
| - break; |
| - } |
| - |
| - return 0; |
| -} |
| - |
| -void RenderWidgetHostViewWin::TrackMouseLeave(bool track) { |
| - if (track == track_mouse_leave_) |
| - return; |
| - track_mouse_leave_ = track; |
| - |
| - DCHECK(m_hWnd); |
| - |
| - TRACKMOUSEEVENT tme; |
| - tme.cbSize = sizeof(TRACKMOUSEEVENT); |
| - tme.dwFlags = TME_LEAVE; |
| - if (!track_mouse_leave_) |
| - tme.dwFlags |= TME_CANCEL; |
| - tme.hwndTrack = m_hWnd; |
| - |
| - TrackMouseEvent(&tme); |
| -} |
| - |
| -bool RenderWidgetHostViewWin::Send(IPC::Message* message) { |
| - if (!render_widget_host_) |
| - return false; |
| - return render_widget_host_->Send(message); |
| -} |
| - |
| -void RenderWidgetHostViewWin::EnsureTooltip() { |
| - UINT message = TTM_NEWTOOLRECT; |
| - |
| - TOOLINFO ti = {0}; |
| - ti.cbSize = sizeof(ti); |
| - ti.hwnd = m_hWnd; |
| - ti.uId = 0; |
| - if (!::IsWindow(tooltip_hwnd_)) { |
| - message = TTM_ADDTOOL; |
| - tooltip_hwnd_ = CreateWindowEx( |
| - WS_EX_TRANSPARENT | l10n_util::GetExtendedTooltipStyles(), |
| - TOOLTIPS_CLASS, NULL, TTS_NOPREFIX, 0, 0, 0, 0, m_hWnd, NULL, |
| - NULL, NULL); |
| - if (!tooltip_hwnd_) { |
| - // Tooltip creation can inexplicably fail. See bug 82913 for details. |
| - LOG_GETLASTERROR(WARNING) << |
| - "Tooltip creation failed, tooltips won't work"; |
| - return; |
| - } |
| - ti.uFlags = TTF_TRANSPARENT; |
| - ti.lpszText = LPSTR_TEXTCALLBACK; |
| - |
| - // Ensure web content tooltips are displayed for at least this amount of |
| - // time, to give users a chance to read longer messages. |
| - const int kMinimumAutopopDurationMs = 10 * 1000; |
| - int autopop_duration_ms = |
| - SendMessage(tooltip_hwnd_, TTM_GETDELAYTIME, TTDT_AUTOPOP, NULL); |
| - if (autopop_duration_ms < kMinimumAutopopDurationMs) { |
| - SendMessage(tooltip_hwnd_, TTM_SETDELAYTIME, TTDT_AUTOPOP, |
| - kMinimumAutopopDurationMs); |
| - } |
| - } |
| - |
| - CRect cr; |
| - GetClientRect(&ti.rect); |
| - SendMessage(tooltip_hwnd_, message, NULL, reinterpret_cast<LPARAM>(&ti)); |
| -} |
| - |
| -void RenderWidgetHostViewWin::ResetTooltip() { |
| - if (::IsWindow(tooltip_hwnd_)) |
| - ::DestroyWindow(tooltip_hwnd_); |
| - tooltip_hwnd_ = NULL; |
| -} |
| - |
| -bool RenderWidgetHostViewWin::ForwardGestureEventToRenderer( |
| - ui::GestureEvent* gesture) { |
| - if (!render_widget_host_) |
| - return false; |
| - |
| - // Pinch gestures are disabled by default on windows desktop. See |
| - // crbug.com/128477 and crbug.com/148816 |
| - if ((gesture->type() == ui::ET_GESTURE_PINCH_BEGIN || |
| - gesture->type() == ui::ET_GESTURE_PINCH_UPDATE || |
| - gesture->type() == ui::ET_GESTURE_PINCH_END) && |
| - !ShouldSendPinchGesture()) { |
| - return true; |
| - } |
| - |
| - blink::WebGestureEvent web_gesture = CreateWebGestureEvent(m_hWnd, *gesture); |
| - if (web_gesture.type == blink::WebGestureEvent::Undefined) |
| - return false; |
| - if (web_gesture.type == blink::WebGestureEvent::GestureTapDown) { |
| - render_widget_host_->ForwardGestureEvent( |
| - CreateFlingCancelEvent(gesture->time_stamp().InSecondsF())); |
| - } |
| - render_widget_host_->ForwardGestureEventWithLatencyInfo(web_gesture, |
| - *gesture->latency()); |
| - return true; |
| -} |
| - |
| -void RenderWidgetHostViewWin::ForwardMouseEventToRenderer(UINT message, |
| - WPARAM wparam, |
| - LPARAM lparam) { |
| - TRACE_EVENT0("browser", |
| - "RenderWidgetHostViewWin::ForwardMouseEventToRenderer"); |
| - if (!render_widget_host_) { |
| - TRACE_EVENT0("browser", "EarlyOut_NoRWH"); |
| - return; |
| - } |
| - |
| - gfx::Point point = gfx::win::ScreenToDIPPoint( |
| - gfx::Point(static_cast<short>(LOWORD(lparam)), |
| - static_cast<short>(HIWORD(lparam)))); |
| - lparam = MAKELPARAM(point.x(), point.y()); |
| - |
| - WebMouseEvent event( |
| - WebMouseEventBuilder::Build(m_hWnd, message, wparam, lparam)); |
| - |
| - if (mouse_locked_) { |
| - event.movementX = event.globalX - last_mouse_position_.locked_global.x(); |
| - event.movementY = event.globalY - last_mouse_position_.locked_global.y(); |
| - last_mouse_position_.locked_global.SetPoint(event.globalX, event.globalY); |
| - |
| - event.x = last_mouse_position_.unlocked.x(); |
| - event.y = last_mouse_position_.unlocked.y(); |
| - event.windowX = last_mouse_position_.unlocked.x(); |
| - event.windowY = last_mouse_position_.unlocked.y(); |
| - event.globalX = last_mouse_position_.unlocked_global.x(); |
| - event.globalY = last_mouse_position_.unlocked_global.y(); |
| - } else { |
| - if (ignore_mouse_movement_) { |
| - ignore_mouse_movement_ = false; |
| - event.movementX = 0; |
| - event.movementY = 0; |
| - } else { |
| - event.movementX = |
| - event.globalX - last_mouse_position_.unlocked_global.x(); |
| - event.movementY = |
| - event.globalY - last_mouse_position_.unlocked_global.y(); |
| - } |
| - |
| - last_mouse_position_.unlocked.SetPoint(event.windowX, event.windowY); |
| - last_mouse_position_.unlocked_global.SetPoint(event.globalX, event.globalY); |
| - } |
| - |
| - // Windows sends (fake) mouse messages for touch events. Don't send these to |
| - // the render widget. |
| - if (!touch_events_enabled_ || !ui::IsMouseEventFromTouch(message)) { |
| - // Send the event to the renderer before changing mouse capture, so that |
| - // the capturelost event arrives after mouseup. |
| - render_widget_host_->ForwardMouseEvent(event); |
| - |
| - switch (event.type) { |
| - case WebInputEvent::MouseMove: |
| - TrackMouseLeave(true); |
| - break; |
| - case WebInputEvent::MouseLeave: |
| - TrackMouseLeave(false); |
| - break; |
| - case WebInputEvent::MouseDown: |
| - SetCapture(); |
| - break; |
| - case WebInputEvent::MouseUp: |
| - if (GetCapture() == m_hWnd) |
| - ReleaseCapture(); |
| - break; |
| - } |
| - } |
| - |
| - if (IsActivatable() && event.type == WebInputEvent::MouseDown) { |
| - // This is a temporary workaround for bug 765011 to get focus when the |
| - // mouse is clicked. This happens after the mouse down event is sent to |
| - // the renderer because normally Windows does a WM_SETFOCUS after |
| - // WM_LBUTTONDOWN. |
| - SetFocus(); |
| - } |
| -} |
| - |
| -void RenderWidgetHostViewWin::ShutdownHost() { |
| - weak_factory_.InvalidateWeakPtrs(); |
| - if (render_widget_host_) |
| - render_widget_host_->Shutdown(); |
| - // Do not touch any members at this point, |this| has been deleted. |
| -} |
| - |
| -void RenderWidgetHostViewWin::DoPopupOrFullscreenInit(HWND parent_hwnd, |
| - const gfx::Rect& pos, |
| - DWORD ex_style) { |
| - Create(parent_hwnd, NULL, NULL, WS_POPUP, ex_style); |
| - gfx::Rect screen_rect = gfx::win::DIPToScreenRect(pos); |
| - MoveWindow(screen_rect.x(), screen_rect.y(), screen_rect.width(), |
| - screen_rect.height(), TRUE); |
| - ShowWindow(IsActivatable() ? SW_SHOW : SW_SHOWNA); |
| - |
| - if (is_fullscreen_ && win8::IsSingleWindowMetroMode()) { |
| - MetroSetFrameWindow set_frame_window = |
| - reinterpret_cast<MetroSetFrameWindow>( |
| - ::GetProcAddress(base::win::GetMetroModule(), "SetFrameWindow")); |
| - DCHECK(set_frame_window); |
| - set_frame_window(m_hWnd); |
| - } |
| -} |
| - |
| -CPoint RenderWidgetHostViewWin::GetClientCenter() const { |
| - CRect rect; |
| - GetClientRect(&rect); |
| - return rect.CenterPoint(); |
| -} |
| - |
| -void RenderWidgetHostViewWin::MoveCursorToCenterIfNecessary() { |
| - DCHECK(mouse_locked_); |
| - |
| - CRect rect; |
| - GetClipCursor(&rect); |
| - int border_x = rect.Width() * kMouseLockBorderPercentage / 100; |
| - int border_y = rect.Height() * kMouseLockBorderPercentage / 100; |
| - |
| - bool should_move = |
| - last_mouse_position_.locked_global.x() < rect.left + border_x || |
| - last_mouse_position_.locked_global.x() > rect.right - border_x || |
| - last_mouse_position_.locked_global.y() < rect.top + border_y || |
| - last_mouse_position_.locked_global.y() > rect.bottom - border_y; |
| - |
| - if (should_move) { |
| - move_to_center_request_.pending = true; |
| - move_to_center_request_.target = rect.CenterPoint(); |
| - if (!::SetCursorPos(move_to_center_request_.target.x(), |
| - move_to_center_request_.target.y())) { |
| - LOG_GETLASTERROR(WARNING) << "Failed to set cursor position."; |
| - } |
| - } |
| -} |
| - |
| -void RenderWidgetHostViewWin::HandleLockedMouseEvent(UINT message, |
| - WPARAM wparam, |
| - LPARAM lparam) { |
| - TRACE_EVENT0("browser", "RenderWidgetHostViewWin::HandleLockedMouseEvent"); |
| - DCHECK(mouse_locked_); |
| - |
| - if (message == WM_MOUSEMOVE && move_to_center_request_.pending) { |
| - // Ignore WM_MOUSEMOVE messages generated by |
| - // MoveCursorToCenterIfNecessary(). |
| - CPoint current_position(LOWORD(lparam), HIWORD(lparam)); |
| - ClientToScreen(¤t_position); |
| - if (move_to_center_request_.target.x() == current_position.x && |
| - move_to_center_request_.target.y() == current_position.y) { |
| - move_to_center_request_.pending = false; |
| - last_mouse_position_.locked_global = move_to_center_request_.target; |
| - return; |
| - } |
| - } |
| - |
| - ForwardMouseEventToRenderer(message, wparam, lparam); |
| -} |
| - |
| -LRESULT RenderWidgetHostViewWin::OnDocumentFeed(RECONVERTSTRING* reconv) { |
| - size_t target_offset; |
| - size_t target_length; |
| - bool has_composition; |
| - if (!composition_range_.is_empty()) { |
| - target_offset = composition_range_.GetMin(); |
| - target_length = composition_range_.length(); |
| - has_composition = true; |
| - } else if (selection_range_.IsValid()) { |
| - target_offset = selection_range_.GetMin(); |
| - target_length = selection_range_.length(); |
| - has_composition = false; |
| - } else { |
| - return 0; |
| - } |
| - |
| - size_t len = selection_text_.length(); |
| - size_t need_size = sizeof(RECONVERTSTRING) + len * sizeof(WCHAR); |
| - |
| - if (target_offset < selection_text_offset_ || |
| - target_offset + target_length > selection_text_offset_ + len) { |
| - return 0; |
| - } |
| - |
| - if (!reconv) |
| - return need_size; |
| - |
| - if (reconv->dwSize < need_size) |
| - return 0; |
| - |
| - reconv->dwVersion = 0; |
| - reconv->dwStrLen = len; |
| - reconv->dwStrOffset = sizeof(RECONVERTSTRING); |
| - reconv->dwCompStrLen = has_composition ? target_length: 0; |
| - reconv->dwCompStrOffset = |
| - (target_offset - selection_text_offset_) * sizeof(WCHAR); |
| - reconv->dwTargetStrLen = target_length; |
| - reconv->dwTargetStrOffset = reconv->dwCompStrOffset; |
| - memcpy(reinterpret_cast<char*>(reconv) + sizeof(RECONVERTSTRING), |
| - selection_text_.c_str(), len * sizeof(WCHAR)); |
| - |
| - // According to Microsft API document, IMR_RECONVERTSTRING and |
| - // IMR_DOCUMENTFEED should return reconv, but some applications return |
| - // need_size. |
| - return reinterpret_cast<LRESULT>(reconv); |
| -} |
| - |
| -LRESULT RenderWidgetHostViewWin::OnReconvertString(RECONVERTSTRING* reconv) { |
| - // If there is a composition string already, we don't allow reconversion. |
| - if (imm32_manager_->is_composing()) |
| - return 0; |
| - |
| - if (selection_range_.is_empty()) |
| - return 0; |
| - |
| - if (selection_text_.empty()) |
| - return 0; |
| - |
| - if (selection_range_.GetMin() < selection_text_offset_ || |
| - selection_range_.GetMax() > |
| - selection_text_offset_ + selection_text_.length()) { |
| - return 0; |
| - } |
| - |
| - size_t len = selection_range_.length(); |
| - size_t need_size = sizeof(RECONVERTSTRING) + len * sizeof(WCHAR); |
| - |
| - if (!reconv) |
| - return need_size; |
| - |
| - if (reconv->dwSize < need_size) |
| - return 0; |
| - |
| - reconv->dwVersion = 0; |
| - reconv->dwStrLen = len; |
| - reconv->dwStrOffset = sizeof(RECONVERTSTRING); |
| - reconv->dwCompStrLen = len; |
| - reconv->dwCompStrOffset = 0; |
| - reconv->dwTargetStrLen = len; |
| - reconv->dwTargetStrOffset = 0; |
| - |
| - size_t offset = selection_range_.GetMin() - selection_text_offset_; |
| - memcpy(reinterpret_cast<char*>(reconv) + sizeof(RECONVERTSTRING), |
| - selection_text_.c_str() + offset, len * sizeof(WCHAR)); |
| - |
| - // According to Microsft API document, IMR_RECONVERTSTRING and |
| - // IMR_DOCUMENTFEED should return reconv, but some applications return |
| - // need_size. |
| - return reinterpret_cast<LRESULT>(reconv); |
| -} |
| - |
| -LRESULT RenderWidgetHostViewWin::OnQueryCharPosition( |
| - IMECHARPOSITION* position) { |
| - DCHECK(position); |
| - |
| - if (position->dwSize < sizeof(IMECHARPOSITION)) |
| - return 0; |
| - |
| - RECT target_rect = {}; |
| - if (imm32_manager_->is_composing() && !composition_range_.is_empty() && |
| - position->dwCharPos < composition_character_bounds_.size()) { |
| - target_rect = |
| - composition_character_bounds_[position->dwCharPos].ToRECT(); |
| - } else if (position->dwCharPos == 0) { |
| - // When there is no on-going composition but |position->dwCharPos| is 0, |
| - // use the caret rect. This behavior is the same to RichEdit. In fact, |
| - // CUAS (Cicero Unaware Application Support) relies on this behavior to |
| - // implement ITfContextView::GetTextExt on top of IMM32-based applications. |
| - target_rect = caret_rect_.ToRECT(); |
| - } else { |
| - return 0; |
| - } |
| - ClientToScreen(&target_rect); |
| - |
| - RECT document_rect = GetPixelBounds().ToRECT(); |
| - ClientToScreen(&document_rect); |
| - |
| - position->pt.x = target_rect.left; |
| - position->pt.y = target_rect.top; |
| - position->cLineHeight = target_rect.bottom - target_rect.top; |
| - position->rcDocument = document_rect; |
| - return 1; |
| -} |
| - |
| -void RenderWidgetHostViewWin::UpdateIMEState() { |
| - if (base::win::IsTSFAwareRequired()) { |
| - ui::TSFBridge::GetInstance()->OnTextInputTypeChanged(this); |
| - return; |
| - } |
| - if (text_input_type_ != ui::TEXT_INPUT_TYPE_NONE && |
| - text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD) { |
| - imm32_manager_->EnableIME(m_hWnd); |
| - imm32_manager_->SetUseCompositionWindow(!can_compose_inline_); |
| - } else { |
| - imm32_manager_->DisableIME(m_hWnd); |
| - } |
| - |
| - imm32_manager_->SetTextInputMode(m_hWnd, text_input_mode_); |
| -} |
| - |
| -void RenderWidgetHostViewWin::UpdateInputScopeIfNecessary( |
| - ui::TextInputType text_input_type) { |
| - // The text store is responsible for handling input scope when TSF-aware is |
| - // required. |
| - if (base::win::IsTSFAwareRequired()) |
| - return; |
| - |
| - ui::tsf_inputscope::SetInputScopeForTsfUnawareWindow( |
| - m_hWnd, text_input_type, text_input_mode_); |
| -} |
| - |
| -//////////////////////////////////////////////////////////////////////////////// |
| -// RenderWidgetHostView, public: |
| - |
| -// static |
| -RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget( |
| - RenderWidgetHost* widget) { |
| - return new RenderWidgetHostViewWin(widget); |
| -} |
| - |
| -// static |
| -void RenderWidgetHostViewPort::GetDefaultScreenInfo( |
| - blink::WebScreenInfo* results) { |
| - GetScreenInfoForWindow(0, results); |
| -} |
| - |
| -} // namespace content |