summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorthakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-29 03:56:51 +0000
committerthakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-29 03:56:51 +0000
commit507b33eab2acbb4e360b5b6eb9f2e666079d0e3b (patch)
tree6fd3dd864e9da3e68efc7ded0dbaf96b597fcd3c
parent529338471fec2ab9b07bac9b07e3477b20e0ae28 (diff)
downloadchromium_src-507b33eab2acbb4e360b5b6eb9f2e666079d0e3b.zip
chromium_src-507b33eab2acbb4e360b5b6eb9f2e666079d0e3b.tar.gz
chromium_src-507b33eab2acbb4e360b5b6eb9f2e666079d0e3b.tar.bz2
Fix cmd-up/cmd-down.
The approach is to special-case moveToBeginningOfDocument and moveToEndOfDocument in WebFrameImpl::executeCommand(). With this (and the cocoa keyboard bindings patch being landed), the special-case code in WebViewImpl::ScrollViewWithKeyboard() can be removed. Also add a test for cmd-up/down. Change chrome.gyp so that it supports osx-only unit tests (_unittest_mac.mm). Move OnPrintPageAsBitmap to the other printing tests. BUG=22585 TEST=Go to a page with both text box and scrollbar (e.g. http://en.wikipedia.org ). Pressing cmd-down should scroll to end of page, cmd-up back to start. Clicking the text box and trying some emacs shortcuts should work (ctrl-a jumps to start of line, cmd-h acts as backspace, etc). Review URL: http://codereview.chromium.org/254002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@27464 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/chrome.gyp5
-rw-r--r--chrome/renderer/render_view.cc7
-rw-r--r--chrome/renderer/render_view.h3
-rw-r--r--chrome/renderer/render_view_unittest.cc84
-rw-r--r--chrome/renderer/render_view_unittest_mac.mm132
-rw-r--r--chrome/test/render_view_test.cc23
-rw-r--r--chrome/test/render_view_test.h4
-rw-r--r--webkit/glue/webframe_impl.cc19
-rw-r--r--webkit/glue/webview_impl.cc33
-rw-r--r--webkit/glue/webview_impl.h5
10 files changed, 234 insertions, 81 deletions
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 7b09ee6..0a39bce 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -166,7 +166,7 @@
'target_defaults': {
'sources/': [
['exclude', '/(cocoa|gtk|win)/'],
- ['exclude', '_(cocoa|gtk|linux|mac|posix|skia|win|views|x)(_unittest)?\\.(cc|mm?)$'],
+ ['exclude', '_(cocoa|gtk|linux|mac|posix|skia|win|views|x)(_unittest)?(_mac)?\\.(cc|mm?)$'],
['exclude', '/(gtk|win|x11)_[^/]*\\.cc$'],
],
'conditions': [
@@ -177,7 +177,7 @@
]}],
['OS=="mac"', {'sources/': [
['include', '/cocoa/'],
- ['include', '_(cocoa|mac|posix)(_unittest)?\\.(cc|mm?)$'],
+ ['include', '_(cocoa|mac|posix)(_unittest)?(_mac)?\\.(cc|mm?)$'],
]}, { # else: OS != "mac"
'sources/': [
['exclude', '\\.mm?$'],
@@ -4434,6 +4434,7 @@
'renderer/render_process_unittest.cc',
'renderer/render_thread_unittest.cc',
'renderer/render_view_unittest.cc',
+ 'renderer/render_view_unittest_mac.mm',
'renderer/render_widget_unittest.cc',
'renderer/renderer_main_unittest.cc',
'test/browser_with_test_window_test.cc',
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 66ac3bf..8d9b3dd 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -1511,13 +1511,18 @@ bool RenderView::handleCurrentKeyboardEvent() {
EditCommands::iterator it = edit_commands_.begin();
EditCommands::iterator end = edit_commands_.end();
+ bool did_execute_command = false;
for (; it != end; ++it) {
+ // In gtk, it's possible to bind multiple edit commands to one key (but it's
+ // the exception). Once one edit command is not executed, it seems safest to
+ // not execute the rest.
if (!frame->executeCommand(WebString::fromUTF8(it->name),
WebString::fromUTF8(it->value)))
break;
+ did_execute_command = true;
}
- return true;
+ return did_execute_command;
}
void RenderView::spellCheck(
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index decad59..ae0732a 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -448,6 +448,9 @@ class RenderView : public RenderWidget,
FRIEND_TEST(RenderViewTest, PrintLayoutTest);
FRIEND_TEST(RenderViewTest, OnHandleKeyboardEvent);
FRIEND_TEST(RenderViewTest, InsertCharacters);
+#if defined(OS_MACOSX)
+ FRIEND_TEST(RenderViewTest, MacTestCmdUp);
+#endif
explicit RenderView(RenderThreadBase* render_thread,
const WebPreferences& webkit_preferences);
diff --git a/chrome/renderer/render_view_unittest.cc b/chrome/renderer/render_view_unittest.cc
index 5e10179..3119996 100644
--- a/chrome/renderer/render_view_unittest.cc
+++ b/chrome/renderer/render_view_unittest.cc
@@ -496,6 +496,48 @@ TEST_F(RenderViewTest, PrintLayoutTest) {
#endif
}
+// Print page as bitmap test.
+TEST_F(RenderViewTest, OnPrintPageAsBitmap) {
+#if defined(OS_WIN)
+ // Lets simulate a print pages with Hello world.
+ LoadHTML("<body><p>Hello world!</p></body>");
+
+ // Grab the printer settings from the printer.
+ ViewMsg_Print_Params print_settings;
+ MockPrinter* printer(render_thread_.printer());
+ printer->GetDefaultPrintSettings(&print_settings);
+ ViewMsg_PrintPage_Params page_params = ViewMsg_PrintPage_Params();
+ page_params.params = print_settings;
+ page_params.page_number = 0;
+
+ // Fetch the image data from the web frame.
+ std::vector<unsigned char> data;
+ view_->print_helper()->PrintPageAsJPEG(page_params,
+ view_->webview()->GetMainFrame(),
+ 1.0f,
+ &data);
+ std::vector<unsigned char> decoded;
+ int w, h;
+ EXPECT_TRUE(JPEGCodec::Decode(&data[0], data.size(), JPEGCodec::FORMAT_RGBA,
+ &decoded, &w, &h));
+
+ // Check if its not 100% white.
+ bool is_white = true;
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++) {
+ unsigned char* px = &decoded[(y * w + x) * 4];
+ if (px[0] != 0xFF && px[1] != 0xFF && px[2] != 0xFF) {
+ is_white = false;
+ break;
+ }
+ }
+ }
+ ASSERT_TRUE(!is_white);
+#else
+ NOTIMPLEMENTED();
+#endif
+}
+
// Test that we can receive correct DOM events when we send input events
// through the RenderWidget::OnHandleInputEvent() function.
TEST_F(RenderViewTest, OnHandleKeyboardEvent) {
@@ -868,45 +910,3 @@ TEST_F(RenderViewTest, DidFailProvisionalLoadWithErrorForCancellation) {
// Frame should stay in view-source mode.
EXPECT_TRUE(web_frame->isViewSourceModeEnabled());
}
-
-// Print page as bitmap test.
-TEST_F(RenderViewTest, OnPrintPageAsBitmap) {
-#if defined(OS_WIN)
- // Lets simulate a print pages with Hello world.
- LoadHTML("<body><p>Hello world!</p></body>");
-
- // Grab the printer settings from the printer.
- ViewMsg_Print_Params print_settings;
- MockPrinter* printer(render_thread_.printer());
- printer->GetDefaultPrintSettings(&print_settings);
- ViewMsg_PrintPage_Params page_params = ViewMsg_PrintPage_Params();
- page_params.params = print_settings;
- page_params.page_number = 0;
-
- // Fetch the image data from the web frame.
- std::vector<unsigned char> data;
- view_->print_helper()->PrintPageAsJPEG(page_params,
- view_->webview()->GetMainFrame(),
- 1.0f,
- &data);
- std::vector<unsigned char> decoded;
- int w, h;
- EXPECT_TRUE(JPEGCodec::Decode(&data[0], data.size(), JPEGCodec::FORMAT_RGBA,
- &decoded, &w, &h));
-
- // Check if its not 100% white.
- bool is_white = true;
- for (int y = 0; y < h; y++) {
- for (int x = 0; x < w; x++) {
- unsigned char* px = &decoded[(y * w + x) * 4];
- if (px[0] != 0xFF && px[1] != 0xFF && px[2] != 0xFF) {
- is_white = false;
- break;
- }
- }
- }
- ASSERT_TRUE(!is_white);
-#else
- NOTIMPLEMENTED();
-#endif
-}
diff --git a/chrome/renderer/render_view_unittest_mac.mm b/chrome/renderer/render_view_unittest_mac.mm
new file mode 100644
index 0000000..e978626
--- /dev/null
+++ b/chrome/renderer/render_view_unittest_mac.mm
@@ -0,0 +1,132 @@
+// Copyright (c) 2009 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.
+
+#include "chrome/common/native_web_keyboard_event.h"
+#include "chrome/common/render_messages.h"
+#include "chrome/test/render_view_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/api/public/WebString.h"
+
+#include <Cocoa/Cocoa.h>
+#include <Carbon/Carbon.h> // for the kVK_* constants.
+
+NSEvent* CmdDeadKeyEvent(NSEventType type, unsigned short code) {
+
+ UniChar uniChar;
+ switch(code) {
+ case kVK_UpArrow: uniChar = NSUpArrowFunctionKey; break;
+ case kVK_DownArrow: uniChar = NSDownArrowFunctionKey; break;
+ default: CHECK(false);
+ }
+ NSString* s = [NSString stringWithFormat:@"%C", uniChar];
+
+ return [NSEvent keyEventWithType:type
+ location:NSMakePoint(0, 0)
+ modifierFlags:NSCommandKeyMask
+ timestamp:0.0
+ windowNumber:0
+ context:nil
+ characters:s
+ charactersIgnoringModifiers:s
+ isARepeat:NO
+ keyCode:code];
+}
+
+// Test that cmd-up/down scrolls the page exactly if it is not intercepted by
+// javascript.
+TEST_F(RenderViewTest, MacTestCmdUp) {
+
+ // Some preprocessor trickery so that we can have literal html in our source,
+ // makes it easier to copy html to and from an html file for testing (the
+ // preprocessor will remove the newlines at the line ends, turning this into
+ // a single long line).
+ #define HTML(s) #s
+ const char* kRawHtml = HTML(
+ <html>
+ <head><title></title>
+ <script type='text/javascript' language='javascript'>
+ function OnKeyEvent(ev) {
+ var result = document.getElementById(ev.type);
+ result.innerText = (ev.which || ev.keyCode) + ',' +
+ ev.shiftKey + ',' +
+ ev.ctrlKey + ',' +
+ ev.metaKey + ',' +
+ ev.altKey;
+ return %s; /* Replace with "return true;" when testing in an html file. */
+ }
+ function OnScroll(ev) {
+ var result = document.getElementById("scroll");
+ result.innerText = window.pageYOffset;
+ return true;
+ }
+ </script>
+ <style type="text/css">
+ p { border-bottom:5000px solid black; } /* enforce vertical scroll bar */
+ </style>
+ </head>
+ <body
+ onscroll='return OnScroll(event);'
+ onkeydown='return OnKeyEvent(event);'>
+ <div id='keydown' contenteditable='true'> </div>
+ <div id='scroll' contenteditable='true'> </div>
+ <p>p1
+ <p>p2
+ </body>
+ </html>
+ );
+ #undef HTML
+
+ const int kMaxOutputCharacters = 1024;
+ string16 output;
+ char htmlBuffer[2048];
+
+ NSEvent* arrowDownKeyDown = CmdDeadKeyEvent(NSKeyDown, kVK_DownArrow);
+ NSEvent* arrowUpKeyDown = CmdDeadKeyEvent(NSKeyDown, kVK_UpArrow);
+
+ // First test when javascript does not eat keypresses -- should scroll.
+ sprintf(htmlBuffer, kRawHtml, "true");
+ view_->set_delay_seconds_for_form_state_sync(0);
+ LoadHTML(htmlBuffer);
+ render_thread_.sink().ClearMessages();
+
+ const char* kArrowDownScrollDown =
+ "40,false,false,true,false\n1936\np1\n\np2";
+ view_->OnSetEditCommandsForNextKeyEvent(
+ EditCommands(1, EditCommand("moveToEndOfDocument", "")));
+ SendNativeKeyEvent(NativeWebKeyboardEvent(arrowDownKeyDown));
+ output = GetMainFrame()->contentAsText(kMaxOutputCharacters);
+ EXPECT_EQ(kArrowDownScrollDown, UTF16ToASCII(output));
+
+ const char* kArrowUpScrollUp =
+ "38,false,false,true,false\n0\np1\n\np2";
+ view_->OnSetEditCommandsForNextKeyEvent(
+ EditCommands(1, EditCommand("moveToBeginningOfDocument", "")));
+ SendNativeKeyEvent(NativeWebKeyboardEvent(arrowUpKeyDown));
+ output = GetMainFrame()->contentAsText(kMaxOutputCharacters);
+ EXPECT_EQ(kArrowUpScrollUp, UTF16ToASCII(output));
+
+
+ // Now let javascript eat the key events -- no scrolling should happen
+ sprintf(htmlBuffer, kRawHtml, "false");
+ view_->set_delay_seconds_for_form_state_sync(0);
+ LoadHTML(htmlBuffer);
+ render_thread_.sink().ClearMessages();
+
+ const char* kArrowDownNoScroll =
+ "40,false,false,true,false\np1\n\np2";
+ view_->OnSetEditCommandsForNextKeyEvent(
+ EditCommands(1, EditCommand("moveToEndOfDocument", "")));
+ SendNativeKeyEvent(NativeWebKeyboardEvent(arrowDownKeyDown));
+ output = GetMainFrame()->contentAsText(kMaxOutputCharacters);
+ EXPECT_EQ(kArrowDownNoScroll, UTF16ToASCII(output));
+
+ const char* kArrowUpNoScroll =
+ "38,false,false,true,false\np1\n\np2";
+ view_->OnSetEditCommandsForNextKeyEvent(
+ EditCommands(1, EditCommand("moveToBeginningOfDocument", "")));
+ SendNativeKeyEvent(NativeWebKeyboardEvent(arrowUpKeyDown));
+ output = GetMainFrame()->contentAsText(kMaxOutputCharacters);
+ EXPECT_EQ(kArrowUpNoScroll, UTF16ToASCII(output));
+}
+
diff --git a/chrome/test/render_view_test.cc b/chrome/test/render_view_test.cc
index 2f12836..e0321c7 100644
--- a/chrome/test/render_view_test.cc
+++ b/chrome/test/render_view_test.cc
@@ -158,22 +158,13 @@ int RenderViewTest::SendKeyEvent(MockKeyboard::Layout layout,
// WM_KEYDOWN and WM_KEYUP sends virtual-key codes. On the other hand,
// WM_CHAR sends a composed Unicode character.
NativeWebKeyboardEvent keydown_event(NULL, WM_KEYDOWN, key_code, 0);
- scoped_ptr<IPC::Message> keydown_message(new ViewMsg_HandleInputEvent(0));
- keydown_message->WriteData(reinterpret_cast<const char*>(&keydown_event),
- sizeof(WebKit::WebKeyboardEvent));
- view_->OnHandleInputEvent(*keydown_message);
+ SendNativeKeyEvent(keydown_event);
NativeWebKeyboardEvent char_event(NULL, WM_CHAR, (*output)[0], 0);
- scoped_ptr<IPC::Message> char_message(new ViewMsg_HandleInputEvent(0));
- char_message->WriteData(reinterpret_cast<const char*>(&char_event),
- sizeof(WebKit::WebKeyboardEvent));
- view_->OnHandleInputEvent(*char_message);
+ SendNativeKeyEvent(char_event);
NativeWebKeyboardEvent keyup_event(NULL, WM_KEYUP, key_code, 0);
- scoped_ptr<IPC::Message> keyup_message(new ViewMsg_HandleInputEvent(0));
- keyup_message->WriteData(reinterpret_cast<const char*>(&keyup_event),
- sizeof(WebKit::WebKeyboardEvent));
- view_->OnHandleInputEvent(*keyup_message);
+ SendNativeKeyEvent(keyup_event);
return length;
#else
@@ -181,3 +172,11 @@ int RenderViewTest::SendKeyEvent(MockKeyboard::Layout layout,
return L'\0';
#endif
}
+
+void RenderViewTest::SendNativeKeyEvent(
+ const NativeWebKeyboardEvent& key_event) {
+ scoped_ptr<IPC::Message> input_message(new ViewMsg_HandleInputEvent(0));
+ input_message->WriteData(reinterpret_cast<const char*>(&key_event),
+ sizeof(WebKit::WebKeyboardEvent));
+ view_->OnHandleInputEvent(*input_message);
+}
diff --git a/chrome/test/render_view_test.h b/chrome/test/render_view_test.h
index 5a9a78a..45f8369 100644
--- a/chrome/test/render_view_test.h
+++ b/chrome/test/render_view_test.h
@@ -11,6 +11,7 @@
#include "base/scoped_ptr.h"
#include "chrome/common/main_function_params.h"
#include "chrome/common/sandbox_init_wrapper.h"
+#include "chrome/common/native_web_keyboard_event.h"
#include "chrome/renderer/mock_keyboard.h"
#include "chrome/renderer/mock_render_process.h"
#include "chrome/renderer/mock_render_thread.h"
@@ -45,6 +46,9 @@ class RenderViewTest : public testing::Test {
MockKeyboard::Modifiers key_modifiers,
std::wstring* output);
+ // Sends one native key event over IPC.
+ void SendNativeKeyEvent(const NativeWebKeyboardEvent& key_event);
+
// testing::Test
virtual void SetUp();
diff --git a/webkit/glue/webframe_impl.cc b/webkit/glue/webframe_impl.cc
index 68c6882..e49fed8 100644
--- a/webkit/glue/webframe_impl.cc
+++ b/webkit/glue/webframe_impl.cc
@@ -121,6 +121,7 @@ MSVC_PUSH_WARNING_LEVEL(0);
#include "ScriptSourceCode.h"
#include "ScriptValue.h"
#include "ScrollbarTheme.h"
+#include "ScrollTypes.h"
#include "SelectionController.h"
#include "Settings.h"
#include "SkiaUtils.h"
@@ -1011,8 +1012,22 @@ bool WebFrameImpl::executeCommand(const WebString& name) {
bool WebFrameImpl::executeCommand(const WebString& name,
const WebString& value) {
ASSERT(frame());
- return frame()->editor()->command(webkit_glue::WebStringToString(name)).
- execute(webkit_glue::WebStringToString(value));
+ WebCore::String web_name = webkit_glue::WebStringToString(name);
+
+ // moveToBeginningOfDocument and moveToEndfDocument are only handled by WebKit
+ // for editable nodes.
+ if (!frame()->editor()->canEdit() &&
+ web_name == "moveToBeginningOfDocument") {
+ return GetWebViewImpl()->PropagateScroll(WebCore::ScrollUp,
+ WebCore::ScrollByDocument);
+ } else if (!frame()->editor()->canEdit() &&
+ web_name == "moveToEndOfDocument") {
+ return GetWebViewImpl()->PropagateScroll(WebCore::ScrollDown,
+ WebCore::ScrollByDocument);
+ } else {
+ return frame()->editor()->command(web_name).
+ execute(webkit_glue::WebStringToString(value));
+ }
}
bool WebFrameImpl::isCommandEnabled(const WebString& name) const {
diff --git a/webkit/glue/webview_impl.cc b/webkit/glue/webview_impl.cc
index 6900853..74a4c3f 100644
--- a/webkit/glue/webview_impl.cc
+++ b/webkit/glue/webview_impl.cc
@@ -862,10 +862,6 @@ bool WebViewImpl::KeyEventDefault(const WebKeyboardEvent& event) {
}
bool WebViewImpl::ScrollViewWithKeyboard(int key_code, int modifiers) {
- Frame* frame = GetFocusedWebCoreFrame();
- if (!frame)
- return false;
-
ScrollDirection scroll_direction;
ScrollGranularity scroll_granularity;
@@ -880,29 +876,11 @@ bool WebViewImpl::ScrollViewWithKeyboard(int key_code, int modifiers) {
break;
case VKEY_UP:
scroll_direction = ScrollUp;
-#if defined(OS_MACOSX)
- // Many Mac applications (such as TextEdit, Safari, Firefox, etc.) scroll
- // to the beginning of a page when typing command+up keys. It is better
- // for Mac Chrome to emulate this behavior to improve compatibility with
- // these applications.
- scroll_granularity = (modifiers == WebInputEvent::MetaKey) ?
- ScrollByDocument : ScrollByLine;
-#else
scroll_granularity = ScrollByLine;
-#endif
break;
case VKEY_DOWN:
scroll_direction = ScrollDown;
-#if defined(OS_MACOSX)
- // Many Mac applications (such as TextEdit, Safari, Firefox, etc.) scroll
- // to the end of a page when typing command+down keys. It is better
- // for Mac Chrome to emulate this behavior to improve compatibility with
- // these applications.
- scroll_granularity = (modifiers == WebInputEvent::MetaKey) ?
- ScrollByDocument : ScrollByLine;
-#else
scroll_granularity = ScrollByLine;
-#endif
break;
case VKEY_HOME:
scroll_direction = ScrollUp;
@@ -924,6 +902,17 @@ bool WebViewImpl::ScrollViewWithKeyboard(int key_code, int modifiers) {
return false;
}
+ return PropagateScroll(scroll_direction, scroll_granularity);
+}
+
+bool WebViewImpl::PropagateScroll(
+ WebCore::ScrollDirection scroll_direction,
+ WebCore::ScrollGranularity scroll_granularity) {
+
+ Frame* frame = GetFocusedWebCoreFrame();
+ if (!frame)
+ return false;
+
bool scroll_handled =
frame->eventHandler()->scrollOverflow(scroll_direction,
scroll_granularity);
diff --git a/webkit/glue/webview_impl.h b/webkit/glue/webview_impl.h
index 5ecb4cc..bb9f077 100644
--- a/webkit/glue/webview_impl.h
+++ b/webkit/glue/webview_impl.h
@@ -256,6 +256,11 @@ class WebViewImpl : public WebView, public base::RefCounted<WebViewImpl> {
WebKit::NotificationPresenterImpl* GetNotificationPresenter();
#endif
+ // Tries to scroll a frame or any parent of a frame. Returns true if the view
+ // was scrolled.
+ bool PropagateScroll(WebCore::ScrollDirection scroll_direction,
+ WebCore::ScrollGranularity scroll_granularity);
+
protected:
friend class WebView; // So WebView::Create can call our constructor
friend class base::RefCounted<WebViewImpl>;