Adjust virtual keyboard size base on input method candidates.

Known issue:
Because we use javascript to show/hide candidates and re-size the virtual keyboard container, so it is difficult to make them happen at same time. When we hide the candidates and shrink the keyboard container, you may see two steps: 1. Candidates are hidden and keyboard jumps up. 2. The container is shrank.

Solution:
We plan to make virtual keyboard as a toplevel window instead of a child view. It will overlay the browser. And we will make candidates always visible in html and use SetBounds (0, -height_of_candidates, w, h) to hide it.


BUG=None
TEST=Manually


Review URL: http://codereview.chromium.org/7058046

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@88605 0039d316-1c4b-4281-b951-d872f2087c98
parent 15420f62
......@@ -280,6 +280,7 @@ void FactoryRegistry::ResetFunctions() {
#if defined(TOUCH_UI)
RegisterFunction<HideKeyboardFunction>();
RegisterFunction<SetKeyboardHeightFunction>();
#endif
#if defined(OS_CHROMEOS) && defined(TOUCH_UI)
......
......@@ -45,6 +45,7 @@ const char kUnknownOrUnsupportedKeyIdentiferError[] = "Unknown or unsupported "
const char kUnsupportedModifier[] = "Unsupported modifier.";
const char kNoValidRecipientError[] = "No valid recipient for event.";
const char kKeyEventUnprocessedError[] = "Event was not handled.";
const char kInvalidHeight[] = "Invalid height.";
#if defined(OS_CHROMEOS) && defined(TOUCH_UI)
const char kCrosLibraryNotLoadedError[] = "Cros shared library not loaded.";
#endif
......@@ -144,6 +145,25 @@ bool HideKeyboardFunction::RunImpl() {
NotificationService::NoDetails());
return true;
}
bool SetKeyboardHeightFunction::RunImpl() {
int height = 0;
EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &height));
if (height < 0) {
error_ = kInvalidHeight;
return false;
}
// TODO(penghuang) Check the height is not greater than height of browser view
// and set the height of virtual keyboard directly instead of using
// notification.
NotificationService::current()->Notify(
NotificationType::SET_KEYBOARD_HEIGHT_INVOKED,
Source<SetKeyboardHeightFunction>(this),
Details<int>(&height));
return true;
}
#endif
#if defined(OS_CHROMEOS) && defined(TOUCH_UI)
......
......@@ -39,6 +39,12 @@ class HideKeyboardFunction : public AsyncExtensionFunction {
virtual bool RunImpl();
DECLARE_EXTENSION_FUNCTION_NAME("experimental.input.hideKeyboard");
};
class SetKeyboardHeightFunction : public AsyncExtensionFunction {
public:
virtual bool RunImpl();
DECLARE_EXTENSION_FUNCTION_NAME("experimental.input.setKeyboardHeight");
};
#endif
#if defined(OS_CHROMEOS) && defined(TOUCH_UI)
......
......@@ -9,6 +9,7 @@
/**
* Const variables
*/
const IME_KEYBOARD_HEIGHT = 300;
const IME_HEIGHT = 48;
const IME_VMARGIN = 12;
const IME_HMARGIN = 16;
......@@ -123,6 +124,15 @@ ImeUi.prototype = {
}
this.appendChild(this.pageDown_);
this.update();
},
/**
* Returns true if Ime Ui is visible.
* @return {boolean}
*/
get visible() {
return this.style.display != 'none';
},
/**
......@@ -171,14 +181,21 @@ ImeUi.prototype = {
},
update : function() {
// TODO(penghuang) Add API for show and hide ImeUI.
// Currently, ImeUi is always visible.
if (true || (this.table_ && this.table_.visible) || this.auxiliary_.text_) {
this.style.display = 'block';
var visible =
(this.table_ && this.table_.visible) || this.auxiliary_.text_;
if (visible == this.visible) {
return;
}
if (visible) {
chrome.experimental.input.setKeyboardHeight(
IME_KEYBOARD_HEIGHT + IME_HEIGHT);
this.style.display = 'inline-block';
} else {
this.style.display = 'none';
chrome.experimental.input.setKeyboardHeight(IME_KEYBOARD_HEIGHT);
}
// TODO(penghuang) Adjust the width of all items in ImeUi to fill the width
// of keyboard.
},
......
......@@ -8,6 +8,7 @@ body {
background: -webkit-linear-gradient(#131925, #04070B);
color: white;
margin: 0;
overflow: hidden;
padding: 0;
-webkit-user-select: none;
}
......
......@@ -463,7 +463,7 @@ Row.prototype = {
for (var j = 0; j < this.keys_.length; ++j) {
var key = this.keys_[j];
for (var i = 0; i < MODES.length; ++i) {
this.modeElements_[MODES[i]].appendChild(key.makeDOM(MODES[i]), height);
this.modeElements_[MODES[i]].appendChild(key.makeDOM(MODES[i], height));
}
}
......@@ -578,7 +578,7 @@ var allRows = []; // Populated during start()
*/
function getRowHeight() {
var x = window.innerWidth;
var y = window.innerHeight - (imeui ? IME_HEIGHT - 2 : 0);
var y = window.innerHeight - ((imeui && imeui.visible) ? IME_HEIGHT : 0);
return (x > kKeyboardAspect * y) ?
(height = Math.floor(y / 4)) :
(height = Math.floor(x / (kKeyboardAspect * 4)));
......@@ -647,6 +647,8 @@ function sendKeyFunction(key) {
}
}
var oldHeight = 0;
var oldX = 0;
/**
* Resize the keyboard according to the new window size.
* @return {void}
......@@ -655,16 +657,23 @@ window.onresize = function() {
var height = getRowHeight();
var newX = document.documentElement.clientWidth;
// All rows should have the same aspect, so just use the first one
var totalWidth = Math.floor(height * allRows[0].aspect);
var leftPadding = Math.floor((newX - totalWidth) / 2);
document.getElementById('b').style.paddingLeft = leftPadding + 'px';
if (newX != oldX || height != oldHeight) {
// All rows should have the same aspect, so just use the first one
var totalWidth = Math.floor(height * allRows[0].aspect);
var leftPadding = Math.floor((newX - totalWidth) / 2);
document.getElementById('b').style.paddingLeft = leftPadding + 'px';
}
for (var i = 0; i < allRows.length; ++i) {
allRows[i].resize(height);
if (height != oldHeight) {
for (var i = 0; i < allRows.length; ++i) {
allRows[i].resize(height);
}
}
updateIme();
oldHeight = height;
oldX = newX;
}
/**
......@@ -680,11 +689,12 @@ window.onload = function() {
allRows.push(new Row(i, KEYS[i]));
}
height = getRowHeight();
for (var i = 0; i < allRows.length; ++i) {
body.appendChild(allRows[i].makeDOM(getRowHeight()));
body.appendChild(allRows[i].makeDOM(height));
allRows[i].showMode(KEY_MODE);
}
oldHeight = height;
window.onresize();
// Restore the keyboard to the default state when it is hidden.
......
......@@ -28,7 +28,7 @@
namespace {
const int kKeyboardHeight = 360;
const int kDefaultKeyboardHeight = 300;
const int kKeyboardSlideDuration = 500; // In milliseconds
PropertyAccessor<bool>* GetFocusedStateAccessor() {
......@@ -54,6 +54,7 @@ TouchBrowserFrameView::TouchBrowserFrameView(BrowserFrame* frame,
BrowserView* browser_view)
: OpaqueBrowserFrameView(frame, browser_view),
keyboard_showing_(false),
keyboard_height_(kDefaultKeyboardHeight),
focus_listener_added_(false),
keyboard_(NULL) {
registrar_.Add(this,
......@@ -68,6 +69,9 @@ TouchBrowserFrameView::TouchBrowserFrameView(BrowserFrame* frame,
registrar_.Add(this,
NotificationType::HIDE_KEYBOARD_INVOKED,
NotificationService::AllSources());
registrar_.Add(this,
NotificationType::SET_KEYBOARD_HEIGHT_INVOKED,
NotificationService::AllSources());
browser_view->browser()->tabstrip_model()->AddObserver(this);
......@@ -97,8 +101,8 @@ void TouchBrowserFrameView::Layout() {
// same bounds as when the keyboard is visible. But
// |GetBoundsForReservedArea| should not take this into account so that the
// render view gets the entire area to relayout itself.
bounds.set_y(bounds.y() - kKeyboardHeight);
bounds.set_height(kKeyboardHeight);
bounds.set_y(bounds.y() - keyboard_height_);
bounds.set_height(keyboard_height_);
}
keyboard_->SetBoundsRect(bounds);
}
......@@ -117,7 +121,7 @@ void TouchBrowserFrameView::FocusWillChange(views::View* focused_before,
// TouchBrowserFrameView, protected:
int TouchBrowserFrameView::GetReservedHeight() const {
return keyboard_showing_ ? kKeyboardHeight : 0;
return keyboard_showing_ ? keyboard_height_ : 0;
}
void TouchBrowserFrameView::ViewHierarchyChanged(bool is_add,
......@@ -179,7 +183,7 @@ void TouchBrowserFrameView::UpdateKeyboardAndLayout(bool should_show_keyboard) {
animation_->Hide();
browser_view()->set_clip_y(ui::Tween::ValueBetween(
animation_->GetCurrentValue(), 0, kKeyboardHeight));
animation_->GetCurrentValue(), 0, keyboard_height_));
parent()->Layout();
}
}
......@@ -291,6 +295,17 @@ void TouchBrowserFrameView::Observe(NotificationType type,
false);
}
UpdateKeyboardAndLayout(false);
} else if (type == NotificationType::SET_KEYBOARD_HEIGHT_INVOKED) {
// TODO(penghuang) Allow extension conrtol the virtual keyboard directly
// instead of using Notification.
int height = *reinterpret_cast<int*>(details.map_key());
if (height != keyboard_height_) {
DCHECK_GE(height, 0) << "Height of the keyboard is less than 0.";
DCHECK_LE(height, View::height()) << "Height of the keyboard is greater "
"than the height of frame view.";
keyboard_height_ = height;
parent()->Layout();
}
}
}
......@@ -299,10 +314,10 @@ void TouchBrowserFrameView::Observe(NotificationType type,
void TouchBrowserFrameView::AnimationProgressed(const ui::Animation* anim) {
ui::Transform transform;
transform.SetTranslateY(
ui::Tween::ValueBetween(anim->GetCurrentValue(), kKeyboardHeight, 0));
ui::Tween::ValueBetween(anim->GetCurrentValue(), keyboard_height_, 0));
keyboard_->SetTransform(transform);
browser_view()->set_clip_y(
ui::Tween::ValueBetween(anim->GetCurrentValue(), 0, kKeyboardHeight));
ui::Tween::ValueBetween(anim->GetCurrentValue(), 0, keyboard_height_));
SchedulePaint();
}
......
......@@ -80,6 +80,7 @@ class TouchBrowserFrameView : public OpaqueBrowserFrameView,
virtual void AnimationEnded(const ui::Animation* animation);
bool keyboard_showing_;
int keyboard_height_;
bool focus_listener_added_;
KeyboardContainerView* keyboard_;
NotificationRegistrar registrar_;
......
......@@ -2447,6 +2447,25 @@
}
]
},
{
"name": "setKeyboardHeight",
"type": "function",
"description": "Set the height of the keyboard UI.",
"parameters": [
{ "type": "integer",
"name": "height",
"minimum": 0,
"optional": false,
"description": "The height of the keyboard UI."
},
{ "type": "function",
"name": "callback",
"optional": true,
"description": "This function is called when the event processing is completed but the resizeing may be not finished.",
"parameters": []
}
]
},
{
"name": "sendHandwritingStroke",
"type": "function",
......
......@@ -1309,6 +1309,10 @@ class NotificationType {
#if defined(TOUCH_UI)
// Sent when an API for hiding the keyboard is invoked from JavaScript code.
HIDE_KEYBOARD_INVOKED,
// Sent when an API for set height of the keyboard is invoked from
// JavaScript code.
SET_KEYBOARD_HEIGHT_INVOKED,
#endif
// Protocol Handler Registry -----------------------------------------------
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment