diff options
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host.cc | 18 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host.h | 37 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host_view_win.cc | 20 | ||||
-rw-r--r-- | chrome/common/render_messages_internal.h | 11 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 1 | ||||
-rw-r--r-- | chrome/renderer/render_view_unittest.cc | 48 | ||||
-rw-r--r-- | chrome/renderer/render_widget.cc | 16 | ||||
-rw-r--r-- | chrome/renderer/render_widget.h | 1 | ||||
-rw-r--r-- | webkit/glue/webtextdirection.h | 22 | ||||
-rw-r--r-- | webkit/glue/webview_impl.cc | 31 | ||||
-rw-r--r-- | webkit/glue/webview_impl.h | 1 | ||||
-rw-r--r-- | webkit/glue/webwidget.h | 4 | ||||
-rw-r--r-- | webkit/glue/webwidget_impl.cc | 3 | ||||
-rw-r--r-- | webkit/glue/webwidget_impl.h | 1 |
14 files changed, 213 insertions, 1 deletions
diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc index 83d7bcf..b761d42 100644 --- a/chrome/browser/renderer_host/render_widget_host.cc +++ b/chrome/browser/renderer_host/render_widget_host.cc @@ -17,6 +17,7 @@ #include "chrome/views/view.h" #include "webkit/glue/webcursor.h" #include "webkit/glue/webinputevent.h" +#include "webkit/glue/webtextdirection.h" #if defined(OS_WIN) #include "base/gfx/gdi_util.h" @@ -53,7 +54,9 @@ RenderWidgetHost::RenderWidgetHost(RenderProcessHost* process, mouse_move_pending_(false), needs_repainting_on_restore_(false), is_unresponsive_(false), - view_being_painted_(false) { + view_being_painted_(false), + text_direction_updated_(false), + text_direction_(WEB_TEXT_DIRECTION_LTR) { if (routing_id_ == MSG_ROUTING_NONE) routing_id_ = process_->GetNextRoutingID(); @@ -352,6 +355,19 @@ void RenderWidgetHost::RendererExited() { BackingStoreManager::RemoveBackingStore(this); } +void RenderWidgetHost::UpdateTextDirection(WebTextDirection direction) { + text_direction_updated_ = true; + text_direction_ = direction; +} + +void RenderWidgetHost::NotifyTextDirection() { + if (text_direction_updated_) { + text_direction_updated_ = false; + Send(new ViewMsg_SetTextDirection(routing_id(), + static_cast<int>(text_direction_))); + } +} + gfx::Rect RenderWidgetHost::GetRootWindowResizerRect() const { return gfx::Rect(); } diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h index 59235d0..7ec1638 100644 --- a/chrome/browser/renderer_host/render_widget_host.h +++ b/chrome/browser/renderer_host/render_widget_host.h @@ -15,6 +15,7 @@ #include "chrome/common/native_web_keyboard_event.h" #include "testing/gtest/include/gtest/gtest_prod.h" #include "webkit/glue/webinputevent.h" +#include "webkit/glue/webtextdirection.h" namespace gfx { class Rect; @@ -211,6 +212,38 @@ class RenderWidgetHost : public IPC::Channel::Listener { void ForwardWheelEvent(const WebMouseWheelEvent& wheel_event); void ForwardKeyboardEvent(const NativeWebKeyboardEvent& key_event); + // Update the text direction of the focused input element and notify it to a + // renderer process. + // These functions have two usage scenarios: changing the text direction + // from a menu (as Safari does), and; changing the text direction when a user + // presses a set of keys (as IE and Firefox do). + // 1. Change the text direction from a menu. + // In this scenario, we receive a menu event only once and we should update + // the text direction immediately when a user chooses a menu item. So, we + // should call both functions at once as listed in the following snippet. + // void RenderViewHost::SetTextDirection(WebTextDirection direction) { + // UpdateTextDirection(direction); + // NotifyTextDirection(); + // } + // 2. Change the text direction when pressing a set of keys. + // Becauses of auto-repeat, we may receive the same key-press event many + // times while we presses the keys and it is nonsense to send the same IPC + // messsage every time when we receive a key-press event. + // To suppress the number of IPC messages, we just update the text direction + // when receiving a key-press event and send an IPC message when we release + // the keys as listed in the following snippet. + // if (key_event.type == WebKeyboardEvent::KEY_DOWN) { + // if (key_event.windows_key_code == 'A' && + // key_event.modifiers == WebKeyboardEvent::CTRL_KEY) { + // UpdateTextDirection(dir); + // } + // } else if (key_event.type == WebKeyboardEvent::KEY_UP) { + // NotifyTextDirection(); + // } + // Note: we cannot undo this change for compatibility with Firefox and IE. + void UpdateTextDirection(WebTextDirection direction); + void NotifyTextDirection(); + // This is for derived classes to give us access to the resizer rect. // And to also expose it to the RenderWidgetHostView. virtual gfx::Rect GetRootWindowResizerRect() const; @@ -363,6 +396,10 @@ class RenderWidgetHost : public IPC::Channel::Listener { // back to whatever unhandled handler instead of the returned version. KeyQueue key_queue_; + // Set when we update the text direction of the selected input element. + bool text_direction_updated_; + WebTextDirection text_direction_; + DISALLOW_COPY_AND_ASSIGN(RenderWidgetHost); }; diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.cc b/chrome/browser/renderer_host/render_widget_host_view_win.cc index 12dc1ba..52751ea 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_win.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_win.cc @@ -823,6 +823,26 @@ LRESULT RenderWidgetHostViewWin::OnKeyEvent(UINT message, WPARAM wparam, return ::SendMessage(parent_hwnd_, message, wparam, lparam); } + if (wparam == VK_SHIFT || wparam == VK_CONTROL) { + // 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. + if (message == WM_KEYDOWN) { + const int kKeyDownMask = 0x8000; + if ((GetKeyState(VK_RSHIFT) & kKeyDownMask) && + (GetKeyState(VK_RCONTROL) & kKeyDownMask)) { + render_widget_host_->UpdateTextDirection(WEB_TEXT_DIRECTION_RTL); + } else if ((GetKeyState(VK_LSHIFT) & kKeyDownMask) && + (GetKeyState(VK_LCONTROL) & kKeyDownMask)) { + render_widget_host_->UpdateTextDirection(WEB_TEXT_DIRECTION_LTR); + } + } else if (message == WM_KEYUP) { + render_widget_host_->NotifyTextDirection(); + } + } + render_widget_host_->ForwardKeyboardEvent( NativeWebKeyboardEvent(m_hWnd, message, wparam, lparam)); return 0; diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index 271d470..8cd2d33 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -529,6 +529,17 @@ IPC_BEGIN_MESSAGES(View) IPC_MESSAGE_ROUTED2(ViewMsg_HandleExtensionMessage, std::string /* message */, int /* channel_id */) + + // Changes the text direction of a selected input field. + // * direction (int) + // Represents the new text direction. + // Its possible values are listed below: + // Value New Text Direction + // WEB_TEXT_DIRECTION_DEFAULT NaturalWritingDirection ("inherit") + // WEB_TEXT_DIRECTION_LTR LeftToRightWritingDirection ("rtl") + // WEB_TEXT_DIRECTION_RTL RightToLeftWritingDirection ("ltr") + IPC_MESSAGE_ROUTED1(ViewMsg_SetTextDirection, + int /* direction */) IPC_END_MESSAGES(View) diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index 5ed66520..b2a7759 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -386,6 +386,7 @@ class RenderView : public RenderWidget, FRIEND_TEST(RenderViewTest, OnNavStateChanged); FRIEND_TEST(RenderViewTest, OnImeStateChanged); FRIEND_TEST(RenderViewTest, ImeComposition); + FRIEND_TEST(RenderViewTest, OnSetTextDirection); explicit RenderView(RenderThreadBase* render_thread); diff --git a/chrome/renderer/render_view_unittest.cc b/chrome/renderer/render_view_unittest.cc index 9fa394a..fa26b44 100644 --- a/chrome/renderer/render_view_unittest.cc +++ b/chrome/renderer/render_view_unittest.cc @@ -316,3 +316,51 @@ TEST_F(RenderViewTest, ImeComposition) { } } } + +// Test that the RenderView::OnSetTextDirection() function can change the text +// direction of the selected input element. +TEST_F(RenderViewTest, OnSetTextDirection) { + // Load an HTML page consisting of a <textarea> element and a <div> element. + // This test changes the text direction of the <textarea> element, and + // writes the values of its 'dir' attribute and its 'direction' property to + // verify that the text direction is changed. + view_->set_delay_seconds_for_form_state_sync(0); + LoadHTML("<html>" + "<head>" + "</head>" + "<body>" + "<textarea id=\"test\"></textarea>" + "<div id=\"result\" contenteditable=\"true\"></div>" + "</body>" + "</html>"); + render_thread_.sink().ClearMessages(); + + static const struct { + WebTextDirection direction; + const wchar_t* expected_result; + } kTextDirection[] = { + {WEB_TEXT_DIRECTION_RTL, L"\x000A" L"rtl,rtl"}, + {WEB_TEXT_DIRECTION_LTR, L"\x000A" L"ltr,ltr"}, + }; + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTextDirection); ++i) { + // Set the text direction of the <textarea> element. + ExecuteJavaScript("document.getElementById('test').focus();"); + view_->OnSetTextDirection(kTextDirection[i].direction); + + // Write the values of its DOM 'dir' attribute and its CSS 'direction' + // property to the <div> element. + ExecuteJavaScript("var result = document.getElementById('result');" + "var node = document.getElementById('test');" + "var style = getComputedStyle(node, null);" + "result.innerText =" + " node.getAttribute('dir') + ',' +" + " style.getPropertyValue('direction');"); + + // Copy the document content to std::wstring and compare with the + // expected result. + const int kMaxOutputCharacters = 16; + std::wstring output; + GetMainFrame()->GetContentAsPlainText(kMaxOutputCharacters, &output); + EXPECT_EQ(output, kTextDirection[i].expected_result); + } +} diff --git a/chrome/renderer/render_widget.cc b/chrome/renderer/render_widget.cc index 92d4920..b5b9942 100644 --- a/chrome/renderer/render_widget.cc +++ b/chrome/renderer/render_widget.cc @@ -21,6 +21,7 @@ #endif // defined(OS_POSIX) #include "webkit/glue/webinputevent.h" +#include "webkit/glue/webtextdirection.h" #include "webkit/glue/webwidget.h" RenderWidget::RenderWidget(RenderThreadBase* render_thread, bool activatable) @@ -119,6 +120,7 @@ IPC_DEFINE_MESSAGE_MAP(RenderWidget) IPC_MESSAGE_HANDLER(ViewMsg_ImeSetInputMode, OnImeSetInputMode) IPC_MESSAGE_HANDLER(ViewMsg_ImeSetComposition, OnImeSetComposition) IPC_MESSAGE_HANDLER(ViewMsg_Repaint, OnMsgRepaint) + IPC_MESSAGE_HANDLER(ViewMsg_SetTextDirection, OnSetTextDirection) IPC_MESSAGE_UNHANDLED_ERROR() IPC_END_MESSAGE_MAP() @@ -644,6 +646,20 @@ void RenderWidget::OnMsgRepaint(const gfx::Size& size_to_paint) { DidInvalidateRect(webwidget_, repaint_rect); } +void RenderWidget::OnSetTextDirection(int direction) { + if (!webwidget_) + return; + + WebTextDirection new_direction = static_cast<WebTextDirection>(direction); + if (new_direction == WEB_TEXT_DIRECTION_DEFAULT || + new_direction == WEB_TEXT_DIRECTION_LTR || + new_direction == WEB_TEXT_DIRECTION_RTL) { + webwidget_->SetTextDirection(new_direction); + } else { + NOTREACHED(); + } +} + bool RenderWidget::next_paint_is_resize_ack() const { return ViewHostMsg_PaintRect_Flags::is_resize_ack(next_paint_flags_); } diff --git a/chrome/renderer/render_widget.h b/chrome/renderer/render_widget.h index 08073ea..d7e28fa 100644 --- a/chrome/renderer/render_widget.h +++ b/chrome/renderer/render_widget.h @@ -133,6 +133,7 @@ class RenderWidget : public IPC::Channel::Listener, int target_start, int target_end, const std::wstring& ime_string); void OnMsgRepaint(const gfx::Size& size_to_paint); + void OnSetTextDirection(int direction); // True if a PaintRect_ACK message is pending. bool paint_reply_pending() const { diff --git a/webkit/glue/webtextdirection.h b/webkit/glue/webtextdirection.h new file mode 100644 index 0000000..822eb34 --- /dev/null +++ b/webkit/glue/webtextdirection.h @@ -0,0 +1,22 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WEBKIT_GLUE_WEBTEXTDIRECTION_H_ +#define WEBKIT_GLUE_WEBTEXTDIRECTION_H_ + +// Represents text directions (or writing directions) of a DOM node. +// This type is used as the input parameter of WebWidget::SetTextDirection(). +// This function converts these values to WebCore::WritingDirection values and +// call the Editor::setBaseWritingDirection() function. +// TODO(hbono): Add WEB_TEXT_DIRECTION_ORIGINAL that represents "revert the +// previous changes and set back to the original one" and implement it. +// TODO(hbono): Add WEB_TEXT_DIRECTION_TOGGLE that represents "toggle the text +// direction" and implement it. +enum WebTextDirection { + WEB_TEXT_DIRECTION_DEFAULT, // WebCore::NaturalWritingDirection + WEB_TEXT_DIRECTION_LTR, // WebCore::LeftToRightWritingDirection + WEB_TEXT_DIRECTION_RTL, // WebCore::RightToLeftWritingDirection +}; + +#endif // WEBKIT_GLUE_WEBTEXTDIRECTION_H_ diff --git a/webkit/glue/webview_impl.cc b/webkit/glue/webview_impl.cc index 98c33fe..27d66c6 100644 --- a/webkit/glue/webview_impl.cc +++ b/webkit/glue/webview_impl.cc @@ -1236,6 +1236,37 @@ bool WebViewImpl::ImeUpdateStatus(bool* enable_ime, return true; } +void WebViewImpl::SetTextDirection(WebTextDirection direction) { + // The Editor::setBaseWritingDirection() function checks if we can change + // the text direction of the selected node and updates its DOM "dir" + // attribute and its CSS "direction" property. + // So, we just call the function as Safari does. + const Frame* focused = GetFocusedWebCoreFrame(); + if (!focused) + return; + Editor* editor = focused->editor(); + if (!editor || !editor->canEdit()) + return; + + switch (direction) { + case WEB_TEXT_DIRECTION_DEFAULT: + editor->setBaseWritingDirection(WebCore::NaturalWritingDirection); + break; + + case WEB_TEXT_DIRECTION_LTR: + editor->setBaseWritingDirection(WebCore::LeftToRightWritingDirection); + break; + + case WEB_TEXT_DIRECTION_RTL: + editor->setBaseWritingDirection(WebCore::RightToLeftWritingDirection); + break; + + default: + NOTIMPLEMENTED(); + break; + } +} + void WebViewImpl::RestoreFocus() { if (last_focused_frame_.get()) { if (last_focused_frame_->page()) { diff --git a/webkit/glue/webview_impl.h b/webkit/glue/webview_impl.h index 465f174..4ac01fb 100644 --- a/webkit/glue/webview_impl.h +++ b/webkit/glue/webview_impl.h @@ -76,6 +76,7 @@ class WebViewImpl : public WebView, public base::RefCounted<WebViewImpl> { const std::wstring& ime_string); virtual bool ImeUpdateStatus(bool* enable_ime, gfx::Rect* caret_rect); + virtual void SetTextDirection(WebTextDirection direction); virtual void StopLoading(); virtual void SetBackForwardListSize(int size); virtual void RestoreFocus(); diff --git a/webkit/glue/webwidget.h b/webkit/glue/webwidget.h index 23046e8..b1b011d 100644 --- a/webkit/glue/webwidget.h +++ b/webkit/glue/webwidget.h @@ -6,6 +6,7 @@ #define WEBKIT_GLUE_WEBWIDGET_H__ #include "skia/ext/platform_canvas.h" +#include "webkit/glue/webtextdirection.h" namespace gfx { class Rect; @@ -64,6 +65,9 @@ class WebWidget { // Retrieve the status of this widget required by IME APIs. virtual bool ImeUpdateStatus(bool* enable_ime, gfx::Rect* caret_rect) = 0; + // Changes the text direction of the selected input node. + virtual void SetTextDirection(WebTextDirection direction) = 0; + protected: virtual ~WebWidget() {} diff --git a/webkit/glue/webwidget_impl.cc b/webkit/glue/webwidget_impl.cc index 5cf6bbe..52e5ed0 100644 --- a/webkit/glue/webwidget_impl.cc +++ b/webkit/glue/webwidget_impl.cc @@ -216,6 +216,9 @@ bool WebWidgetImpl::ImeUpdateStatus(bool* enable_ime, return false; } +void WebWidgetImpl::SetTextDirection(WebTextDirection direction) { +} + //----------------------------------------------------------------------------- // WebCore::HostWindow diff --git a/webkit/glue/webwidget_impl.h b/webkit/glue/webwidget_impl.h index e6decf4..83fc23b 100644 --- a/webkit/glue/webwidget_impl.h +++ b/webkit/glue/webwidget_impl.h @@ -51,6 +51,7 @@ class WebWidgetImpl : public WebWidget, const std::wstring& ime_string); virtual bool ImeUpdateStatus(bool* enable_ime, gfx::Rect* caret_rect); + virtual void SetTextDirection(WebTextDirection direction); // WebWidgetImpl void Init(WebCore::FramelessScrollView* widget, const gfx::Rect& bounds); |