Commit c4cc2991 authored by sadrul@chromium.org's avatar sadrul@chromium.org

touchui: Fine-tune selection-controller visibility.

This makes two changes:
 + Makes sure the selection bound has a minimum size before the controller is
   made visible.
 + Delays updating the touch-selection controller a little bit to account for the
   erroneous selection-change messages from webkit.

BUG=none
TEST=manually

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@99894 0039d316-1c4b-4281-b951-d872f2087c98
parent 896e326f
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
static const int kMaxWindowWidth = 4000; static const int kMaxWindowWidth = 4000;
static const int kMaxWindowHeight = 4000; static const int kMaxWindowHeight = 4000;
static const int kTouchControllerUpdateDelay = 150;
// static // static
const char RenderWidgetHostViewViews::kViewClassName[] = const char RenderWidgetHostViewViews::kViewClassName[] =
...@@ -95,7 +96,8 @@ RenderWidgetHostViewViews::RenderWidgetHostViewViews(RenderWidgetHost* host) ...@@ -95,7 +96,8 @@ RenderWidgetHostViewViews::RenderWidgetHostViewViews(RenderWidgetHost* host)
text_input_type_(ui::TEXT_INPUT_TYPE_NONE), text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
has_composition_text_(false), has_composition_text_(false),
ALLOW_THIS_IN_INITIALIZER_LIST(touch_selection_controller_( ALLOW_THIS_IN_INITIALIZER_LIST(touch_selection_controller_(
views::TouchSelectionController::create(this))) { views::TouchSelectionController::create(this))),
ALLOW_THIS_IN_INITIALIZER_LIST(update_touch_selection_(this)) {
set_focusable(true); set_focusable(true);
host_->SetView(this); host_->SetView(this);
...@@ -156,10 +158,7 @@ void RenderWidgetHostViewViews::DidBecomeSelected() { ...@@ -156,10 +158,7 @@ void RenderWidgetHostViewViews::DidBecomeSelected() {
if (host_) if (host_)
host_->WasRestored(); host_->WasRestored();
if (touch_selection_controller_.get()) { UpdateTouchSelectionController();
touch_selection_controller_->SelectionChanged(selection_start_,
selection_end_);
}
} }
void RenderWidgetHostViewViews::WasHidden() { void RenderWidgetHostViewViews::WasHidden() {
...@@ -176,6 +175,9 @@ void RenderWidgetHostViewViews::WasHidden() { ...@@ -176,6 +175,9 @@ void RenderWidgetHostViewViews::WasHidden() {
if (host_) if (host_)
host_->WasHidden(); host_->WasHidden();
if (!update_touch_selection_.empty())
update_touch_selection_.RevokeAll();
if (touch_selection_controller_.get()) if (touch_selection_controller_.get())
touch_selection_controller_->ClientViewLostFocus(); touch_selection_controller_->ClientViewLostFocus();
} }
...@@ -346,8 +348,21 @@ void RenderWidgetHostViewViews::SelectionChanged(const std::string& text, ...@@ -346,8 +348,21 @@ void RenderWidgetHostViewViews::SelectionChanged(const std::string& text,
NOTIMPLEMENTED(); NOTIMPLEMENTED();
selection_start_ = start; selection_start_ = start;
selection_end_ = end; selection_end_ = end;
if (touch_selection_controller_.get())
touch_selection_controller_->SelectionChanged(start, end); // TODO(sad): This is a workaround for a webkit bug:
// https://bugs.webkit.org/show_bug.cgi?id=67464
// Remove this when the bug gets fixed.
//
// Webkit can send spurious selection-change on text-input (e.g. when
// inserting text at the beginning of a non-empty text control). But in those
// cases, it does send the correct selection information quickly afterwards.
// So delay the notification to the touch-selection controller.
if (update_touch_selection_.empty()) {
MessageLoop::current()->PostDelayedTask(FROM_HERE,
update_touch_selection_.NewRunnableMethod(
&RenderWidgetHostViewViews::UpdateTouchSelectionController),
kTouchControllerUpdateDelay);
}
} }
void RenderWidgetHostViewViews::ShowingContextMenu(bool showing) { void RenderWidgetHostViewViews::ShowingContextMenu(bool showing) {
...@@ -816,3 +831,9 @@ void RenderWidgetHostViewViews::FinishImeCompositionSession() { ...@@ -816,3 +831,9 @@ void RenderWidgetHostViewViews::FinishImeCompositionSession() {
GetInputMethod()->CancelComposition(this); GetInputMethod()->CancelComposition(this);
has_composition_text_ = false; has_composition_text_ = false;
} }
void RenderWidgetHostViewViews::UpdateTouchSelectionController() {
if (touch_selection_controller_.get())
touch_selection_controller_->SelectionChanged(selection_start_,
selection_end_);
}
...@@ -205,6 +205,10 @@ class RenderWidgetHostViewViews : public RenderWidgetHostView, ...@@ -205,6 +205,10 @@ class RenderWidgetHostViewViews : public RenderWidgetHostView,
// to cancel its ongoing composition sesstion. // to cancel its ongoing composition sesstion.
void FinishImeCompositionSession(); void FinishImeCompositionSession();
// Updates the touch-selection controller (e.g. when the selection/focus
// changes).
void UpdateTouchSelectionController();
#if defined(TOOLKIT_USES_GTK) #if defined(TOOLKIT_USES_GTK)
// On some systems, there can be two native views, where an outer native view // On some systems, there can be two native views, where an outer native view
// contains the inner native view (e.g. when using GTK+). This returns the // contains the inner native view (e.g. when using GTK+). This returns the
...@@ -271,6 +275,8 @@ class RenderWidgetHostViewViews : public RenderWidgetHostView, ...@@ -271,6 +275,8 @@ class RenderWidgetHostViewViews : public RenderWidgetHostView,
scoped_ptr<views::TouchSelectionController> touch_selection_controller_; scoped_ptr<views::TouchSelectionController> touch_selection_controller_;
gfx::Point selection_start_; gfx::Point selection_start_;
gfx::Point selection_end_; gfx::Point selection_end_;
ScopedRunnableMethodFactory<RenderWidgetHostViewViews>
update_touch_selection_;
#if defined(TOUCH_UI) #if defined(TOUCH_UI)
std::map<uint64, scoped_refptr<AcceleratedSurfaceContainerTouch> > std::map<uint64, scoped_refptr<AcceleratedSurfaceContainerTouch> >
......
...@@ -31,6 +31,9 @@ const int kSelectionHandleAlpha = 0x7F; ...@@ -31,6 +31,9 @@ const int kSelectionHandleAlpha = 0x7F;
const SkColor kSelectionHandleColor = const SkColor kSelectionHandleColor =
SkColorSetA(SK_ColorBLUE, kSelectionHandleAlpha); SkColorSetA(SK_ColorBLUE, kSelectionHandleAlpha);
// The minimum selection size to trigger selection controller.
const int kMinSelectionSize = 4;
const int kContextMenuCommands[] = {IDS_APP_CUT, const int kContextMenuCommands[] = {IDS_APP_CUT,
IDS_APP_COPY, IDS_APP_COPY,
// TODO(varunjain): PASTE is acting funny due to some gtk clipboard issue. // TODO(varunjain): PASTE is acting funny due to some gtk clipboard issue.
...@@ -78,6 +81,15 @@ void PaintCircle(const Circle& circle, gfx::Canvas* canvas) { ...@@ -78,6 +81,15 @@ void PaintCircle(const Circle& circle, gfx::Canvas* canvas) {
canvas->AsCanvasSkia()->drawPath(path, paint); canvas->AsCanvasSkia()->drawPath(path, paint);
} }
// The points may not match exactly, since the selection range computation may
// introduce some floating point errors. So check for a minimum size to decide
// whether or not there is any selection.
bool IsEmptySelection(const gfx::Point& p1, const gfx::Point& p2) {
int delta_x = p2.x() - p1.x();
int delta_y = p2.y() - p1.y();
return (abs(delta_x) < kMinSelectionSize && abs(delta_y) < kMinSelectionSize);
}
} // namespace } // namespace
namespace views { namespace views {
...@@ -278,7 +290,7 @@ void TouchSelectionControllerImpl::SelectionChanged(const gfx::Point& p1, ...@@ -278,7 +290,7 @@ void TouchSelectionControllerImpl::SelectionChanged(const gfx::Point& p1,
UpdateContextMenu(p1, p2); UpdateContextMenu(p1, p2);
// Check if there is any selection at all. // Check if there is any selection at all.
if (screen_pos_1 == screen_pos_2) { if (IsEmptySelection(screen_pos_2, screen_pos_1)) {
selection_handle_1_->SetVisible(false); selection_handle_1_->SetVisible(false);
selection_handle_2_->SetVisible(false); selection_handle_2_->SetVisible(false);
return; return;
...@@ -386,7 +398,7 @@ void TouchSelectionControllerImpl::UpdateContextMenu(const gfx::Point& p1, ...@@ -386,7 +398,7 @@ void TouchSelectionControllerImpl::UpdateContextMenu(const gfx::Point& p1,
HideContextMenu(); HideContextMenu();
// If there is selection, we restart the context menu timer. // If there is selection, we restart the context menu timer.
if (p1 != p2) { if (!IsEmptySelection(p1, p2)) {
context_menu_timer_.Start( context_menu_timer_.Start(
FROM_HERE, FROM_HERE,
base::TimeDelta::FromMilliseconds(kContextMenuTimoutMs), base::TimeDelta::FromMilliseconds(kContextMenuTimoutMs),
......
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