summaryrefslogtreecommitdiffstats
path: root/content/browser
diff options
context:
space:
mode:
authorananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-06 01:31:58 +0000
committerananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-06 01:31:58 +0000
commit9e42bcdcf28bce2eb8fbe869fbc1fde8b4d524b4 (patch)
treeb5a7f5bae30b99fd874fae80effc5230c9269951 /content/browser
parent6c26229a98eebb37554e7aa3e1b2453576e22046 (diff)
downloadchromium_src-9e42bcdcf28bce2eb8fbe869fbc1fde8b4d524b4.zip
chromium_src-9e42bcdcf28bce2eb8fbe869fbc1fde8b4d524b4.tar.gz
chromium_src-9e42bcdcf28bce2eb8fbe869fbc1fde8b4d524b4.tar.bz2
Display the onscreen keyboard on web pages for touch based Windows installations. We use the IPenInputPanel interface to display the
keyboard when the user touches an editable field on the page. The keyboard is only displayed when we are in the context of a WM_POINTERDOWN message. This context is reset in a timer task. BUG=99267 Review URL: http://codereview.chromium.org/9105001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@116618 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser')
-rw-r--r--content/browser/renderer_host/render_widget_host_view_win.cc100
-rw-r--r--content/browser/renderer_host/render_widget_host_view_win.h29
2 files changed, 112 insertions, 17 deletions
diff --git a/content/browser/renderer_host/render_widget_host_view_win.cc b/content/browser/renderer_host/render_widget_host_view_win.cc
index 8b364ab..e4522e7 100644
--- a/content/browser/renderer_host/render_widget_host_view_win.cc
+++ b/content/browser/renderer_host/render_widget_host_view_win.cc
@@ -5,6 +5,7 @@
#include "content/browser/renderer_host/render_widget_host_view_win.h"
#include <algorithm>
+#include <peninputpanel_i.c>
#include "base/bind.h"
#include "base/bind_helpers.h"
@@ -96,6 +97,13 @@ const int kDestroyCompositorHostWindowDelay = 10000;
// of the border area, in percentage of the corresponding dimension.
const int kMouseLockBorderPercentage = 15;
+// We display the onscreen keyboard in the context of a WM_POINTERDOWN message.
+// This context is reset in a delayed task. Theory being that the page should
+// have enough time to change focus before this context is reset.
+// TODO(ananta)
+// Refine this.
+const int kPointerDownContextResetDelay = 200;
+
// A callback function for EnumThreadWindows to enumerate and dismiss
// any owned popup windows.
BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) {
@@ -318,11 +326,17 @@ RenderWidgetHostViewWin::RenderWidgetHostViewWin(RenderWidgetHost* widget)
composition_range_(ui::Range::InvalidRange()),
ignore_next_lbutton_message_at_same_location(false),
last_pointer_down_location_(0),
- touch_state_(this) {
+ touch_state_(this),
+ pointer_down_context_(false),
+ focus_on_editable_field_(false),
+ received_focus_change_after_pointer_down_(false) {
render_widget_host_->SetView(this);
registrar_.Add(this,
content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
content::NotificationService::AllBrowserContextsAndSources());
+ registrar_.Add(this,
+ content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE,
+ content::NotificationService::AllBrowserContextsAndSources());
}
RenderWidgetHostViewWin::~RenderWidgetHostViewWin() {
@@ -333,6 +347,24 @@ RenderWidgetHostViewWin::~RenderWidgetHostViewWin() {
void RenderWidgetHostViewWin::CreateWnd(HWND parent) {
// ATL function to create the window.
Create(parent);
+ if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
+ // MSDN recommends using the ITextInputPanel interface to display the on
+ // screen keyboard. This interface does not work predictably due to focus
+ // and activation bugs. We use the deprecated IPenInputPanel interface for
+ // now which works reliably with the caveat being that the keyboard cannot
+ // be closed via the system close menu. Esc or clicking elsewhere works.
+ // TODO(ananta): Revisit this.
+ virtual_keyboard_.CreateInstance(CLSID_PenInputPanel, NULL, CLSCTX_INPROC);
+ if (virtual_keyboard_) {
+ virtual_keyboard_->put_AttachedEditWindow(
+ reinterpret_cast<int>(m_hWnd));
+ virtual_keyboard_->put_DefaultPanel(PT_Keyboard);
+ virtual_keyboard_->put_Visible(VARIANT_FALSE);
+ virtual_keyboard_->put_AutoShow(VARIANT_FALSE);
+ } else {
+ NOTREACHED() << "Failed to create instance of pen input panel";
+ }
+ }
}
///////////////////////////////////////////////////////////////////////////////
@@ -891,7 +923,6 @@ LRESULT RenderWidgetHostViewWin::OnCreate(CREATESTRUCT* create_struct) {
}
}
}
-
return 0;
}
@@ -1883,21 +1914,30 @@ void RenderWidgetHostViewWin::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
- DCHECK(type == content::NOTIFICATION_RENDERER_PROCESS_TERMINATED);
-
- // Get the RenderProcessHost that posted this notification, and exit
- // if it's not the one associated with this host view.
- content::RenderProcessHost* render_process_host =
- content::Source<content::RenderProcessHost>(source).ptr();
- DCHECK(render_process_host);
- if (!render_widget_host_ ||
- render_process_host != render_widget_host_->process())
- return;
+ DCHECK(type == content::NOTIFICATION_RENDERER_PROCESS_TERMINATED ||
+ type == content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE);
+
+ if (type == content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE) {
+ if (pointer_down_context_)
+ received_focus_change_after_pointer_down_ = true;
+ focus_on_editable_field_ = *content::Details<bool>(details).ptr();
+ if (virtual_keyboard_)
+ DisplayOnScreenKeyboardIfNeeded();
+ } else {
+ // Get the RenderProcessHost that posted this notification, and exit
+ // if it's not the one associated with this host view.
+ content::RenderProcessHost* render_process_host =
+ content::Source<content::RenderProcessHost>(source).ptr();
+ DCHECK(render_process_host);
+ if (!render_widget_host_ ||
+ render_process_host != render_widget_host_->process())
+ 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);
+ // 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) {
@@ -2176,6 +2216,12 @@ LRESULT RenderWidgetHostViewWin::OnPointerMessage(
OnMouseEvent(WM_LBUTTONDOWN, MK_LBUTTON, lparam, handled);
ignore_next_lbutton_message_at_same_location = true;
last_pointer_down_location_ = lparam;
+ SetFocus();
+ pointer_down_context_ = true;
+ received_focus_change_after_pointer_down_ = false;
+ MessageLoop::current()->PostDelayedTask(FROM_HERE,
+ base::Bind(&RenderWidgetHostViewWin::ResetPointerDownContext,
+ weak_factory_.GetWeakPtr()), kPointerDownContextResetDelay);
} else if (message == WM_POINTERUP) {
OnMouseEvent(WM_LBUTTONUP, MK_LBUTTON, lparam, handled);
}
@@ -2504,3 +2550,25 @@ RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget(
RenderWidgetHost* widget) {
return new RenderWidgetHostViewWin(widget);
}
+
+void RenderWidgetHostViewWin::DisplayOnScreenKeyboardIfNeeded() {
+ if (focus_on_editable_field_) {
+ if (pointer_down_context_) {
+ virtual_keyboard_->put_Visible(VARIANT_TRUE);
+ }
+ } else {
+ virtual_keyboard_->put_Visible(VARIANT_FALSE);
+ }
+}
+
+void RenderWidgetHostViewWin::ResetPointerDownContext() {
+ // If the default focus on the page is on an edit field and we did not
+ // receive a focus change in the context of a pointer down message, it means
+ // that the pointer down message occurred on the edit field and we should
+ // display the on screen keyboard
+ if (!received_focus_change_after_pointer_down_ && virtual_keyboard_)
+ DisplayOnScreenKeyboardIfNeeded();
+ received_focus_change_after_pointer_down_ = false;
+ pointer_down_context_ = false;
+}
+
diff --git a/content/browser/renderer_host/render_widget_host_view_win.h b/content/browser/renderer_host/render_widget_host_view_win.h
index 6353294..b5c0930 100644
--- a/content/browser/renderer_host/render_widget_host_view_win.h
+++ b/content/browser/renderer_host/render_widget_host_view_win.h
@@ -10,7 +10,7 @@
#include <atlapp.h>
#include <atlcrack.h>
#include <atlmisc.h>
-
+#include <peninputpanel.h>
#include <vector>
#include "base/compiler_specific.h"
@@ -346,6 +346,13 @@ class RenderWidgetHostViewWin
LRESULT OnDocumentFeed(RECONVERTSTRING* reconv);
LRESULT OnReconvertString(RECONVERTSTRING* reconv);
+ // Displays the on screen keyboard for editable fields.
+ void DisplayOnScreenKeyboardIfNeeded();
+
+ // Invoked in a delayed task to reset the fact that we are in the context of
+ // a WM_POINTERDOWN message.
+ void ResetPointerDownContext();
+
// The associated Model. While |this| is being Destroyed,
// |render_widget_host_| is NULL and the Windows message loop is run one last
// time. Message handlers must check for a NULL |render_widget_host_|.
@@ -506,10 +513,30 @@ class RenderWidgetHostViewWin
// WM_POINTERXX handler. We do this to ensure that we don't send out
// duplicate lbutton down messages to the renderer.
bool ignore_next_lbutton_message_at_same_location;
+
+ // TODO(ananta)
+ // The WM_POINTERDOWN and on screen keyboard handling related members should
+ // be moved to an independent class to reduce the clutter. This includes all
+ // members starting from last_pointer_down_location_ to the
+ // received_focus_change_after_pointer_down_.
+
// The location of the last WM_POINTERDOWN message. We ignore the subsequent
// lbutton down only if the locations match.
LPARAM last_pointer_down_location_;
+ // IPenInputPanel to allow us to show the Windows virtual keyboard when a
+ // user touches an editable field on the page.
+ base::win::ScopedComPtr<IPenInputPanel> virtual_keyboard_;
+
+ // Set to true if we are in the context of a WM_POINTERDOWN message
+ bool pointer_down_context_;
+
+ // Set to true if the focus is currently on an editable field on the page.
+ bool focus_on_editable_field_;
+
+ // Set to true if we received a focus change after a WM_POINTERDOWN message.
+ bool received_focus_change_after_pointer_down_;
+
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewWin);
};