diff options
author | sail@chromium.org <sail@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-03 18:45:22 +0000 |
---|---|---|
committer | sail@chromium.org <sail@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-03 18:45:22 +0000 |
commit | de41fbf33b50d8aabcfeafe61b748a9eba34c3e3 (patch) | |
tree | 0b362d54b3f44b220a037759d025f5eda82d0f74 /chrome | |
parent | b1404393bdc369782ec995a9fa5f89d084ce487e (diff) | |
download | chromium_src-de41fbf33b50d8aabcfeafe61b748a9eba34c3e3.zip chromium_src-de41fbf33b50d8aabcfeafe61b748a9eba34c3e3.tar.gz chromium_src-de41fbf33b50d8aabcfeafe61b748a9eba34c3e3.tar.bz2 |
Mac: Enable "Check Spelling While Typing" in Edit menu
Currently the "Edit -> Spelling and Grammar -> Check Spelling While Typing" menu item is always disabled.
The problem is that the logic to enable / disable this item lives in the render process and not in the UI.
This patch implements a generic message that the render process can send to the browser to update the state of view commands. This is used to enable and disable the "Check Spelling While Typing" menu item.
BUG=38440
TEST=Clicked in an edit box and verified that the "Check Spelling While Typing" menu item was enabled. Verified that changing the value from the context menu correctly updates the Edit menu as well.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@73641 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/renderer_host/render_view_host.cc | 41 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_view_host.h | 13 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host_view_mac.mm | 38 | ||||
-rw-r--r-- | chrome/chrome_common.gypi | 1 | ||||
-rw-r--r-- | chrome/common/render_messages_internal.h | 8 | ||||
-rw-r--r-- | chrome/common/render_view_commands.h | 23 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 59 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 7 |
8 files changed, 177 insertions, 13 deletions
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc index 3c84f8c..3749f12 100644 --- a/chrome/browser/renderer_host/render_view_host.cc +++ b/chrome/browser/renderer_host/render_view_host.cc @@ -44,6 +44,7 @@ #include "chrome/common/notification_type.h" #include "chrome/common/render_messages.h" #include "chrome/common/render_messages_params.h" +#include "chrome/common/render_view_commands.h" #include "chrome/common/result_codes.h" #include "chrome/common/thumbnail_score.h" #include "chrome/common/translate_errors.h" @@ -340,6 +341,22 @@ int RenderViewHost::GetPendingRequestId() { return pending_request_id_; } +RenderViewHost::CommandState RenderViewHost::GetStateForCommand( + RenderViewCommand command) const { + if (command != RENDER_VIEW_COMMAND_TOGGLE_SPELL_CHECK) + LOG(DFATAL) << "Unknown command " << command; + + std::map<RenderViewCommand, CommandState>::const_iterator it = + command_states_.find(command); + if (it == command_states_.end()) { + CommandState state; + state.is_enabled = false; + state.checked_state = RENDER_VIEW_COMMAND_CHECKED_STATE_UNCHECKED; + return state; + } + return it->second; +} + void RenderViewHost::Stop() { Send(new ViewMsg_Stop(routing_id())); } @@ -806,6 +823,8 @@ bool RenderViewHost::OnMessageReceived(const IPC::Message& msg) { #endif IPC_MESSAGE_HANDLER(ViewHostMsg_PagesReadyForPreview, OnPagesReadyForPreview) + IPC_MESSAGE_HANDLER(ViewHostMsg_CommandStateChanged, + OnCommandStateChanged) // Have the super handle all other messages. IPC_MESSAGE_UNHANDLED(handled = RenderWidgetHost::OnMessageReceived(msg)) IPC_END_MESSAGE_MAP_EX() @@ -1738,3 +1757,25 @@ void RenderViewHost::OnPagesReadyForPreview( // Send the printingDone msg for now. Send(new ViewMsg_PrintingDone(routing_id(), params.document_cookie, true)); } + +void RenderViewHost::OnCommandStateChanged(int command, + bool is_enabled, + int checked_state) { + if (command != RENDER_VIEW_COMMAND_TOGGLE_SPELL_CHECK) { + LOG(DFATAL) << "Unknown command " << command; + return; + } + + if (checked_state != RENDER_VIEW_COMMAND_CHECKED_STATE_UNCHECKED && + checked_state != RENDER_VIEW_COMMAND_CHECKED_STATE_CHECKED && + checked_state != RENDER_VIEW_COMMAND_CHECKED_STATE_MIXED) { + LOG(DFATAL) << "Invalid checked state " << checked_state; + return; + } + + CommandState state; + state.is_enabled = is_enabled; + state.checked_state = + static_cast<RenderViewCommandCheckedState>(checked_state); + command_states_[static_cast<RenderViewCommand>(command)] = state; +} diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h index 5ceddd7..e56a03b 100644 --- a/chrome/browser/renderer_host/render_view_host.h +++ b/chrome/browser/renderer_host/render_view_host.h @@ -15,6 +15,7 @@ #include "chrome/browser/ui/find_bar/find_bar_controller.h" #include "chrome/common/content_settings_types.h" #include "chrome/common/page_zoom.h" +#include "chrome/common/render_view_commands.h" #include "chrome/common/translate_errors.h" #include "chrome/common/view_types.h" #include "chrome/common/window_container_type.h" @@ -199,6 +200,12 @@ class RenderViewHost : public RenderWidgetHost { // hangs, in which case we need to swap to the pending RenderViewHost. int GetPendingRequestId(); + struct CommandState { + bool is_enabled; + RenderViewCommandCheckedState checked_state; + }; + CommandState GetStateForCommand(RenderViewCommand command) const; + // Stops the current load. void Stop(); @@ -641,6 +648,9 @@ class RenderViewHost : public RenderWidgetHost { void OnScriptEvalResponse(int id, const ListValue& result); void OnPagesReadyForPreview( const ViewHostMsg_DidPreviewDocument_Params& params); + void OnCommandStateChanged(int command, + bool is_enabled, + int checked_state); #if defined(OS_MACOSX) void OnMsgShowPopup(const ViewHostMsg_ShowPopup_Params& params); @@ -729,6 +739,9 @@ class RenderViewHost : public RenderWidgetHost { // The termination status of the last render view that terminated. base::TerminationStatus render_view_termination_status_; + // The enabled/disabled states of various commands. + std::map<RenderViewCommand, CommandState> command_states_; + DISALLOW_COPY_AND_ASSIGN(RenderViewHost); }; diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.mm b/chrome/browser/renderer_host/render_widget_host_view_mac.mm index 7c84fb3..5f65e6d 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm +++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm @@ -1969,10 +1969,38 @@ void RenderWidgetHostViewMac::SetTextInputActive(bool active) { action == @selector(copy:) || action == @selector(copyToFindPboard:) || action == @selector(paste:) || - action == @selector(pasteAsPlainText:)) { + action == @selector(pasteAsPlainText:) || + action == @selector(checkSpelling:)) { return renderWidgetHostView_->render_widget_host_->IsRenderView(); } + if (action == @selector(toggleContinuousSpellChecking:)) { + RenderViewHost::CommandState state; + state.is_enabled = false; + state.checked_state = RENDER_VIEW_COMMAND_CHECKED_STATE_UNCHECKED; + if (renderWidgetHostView_->render_widget_host_->IsRenderView()) { + state = static_cast<RenderViewHost*>( + renderWidgetHostView_->render_widget_host_)-> + GetStateForCommand(RENDER_VIEW_COMMAND_TOGGLE_SPELL_CHECK); + } + if ([(id)item respondsToSelector:@selector(setState:)]) { + NSCellStateValue checked_state; + switch (state.checked_state) { + case RENDER_VIEW_COMMAND_CHECKED_STATE_UNCHECKED: + checked_state = NSOffState; + break; + case RENDER_VIEW_COMMAND_CHECKED_STATE_CHECKED: + checked_state = NSOnState; + break; + case RENDER_VIEW_COMMAND_CHECKED_STATE_MIXED: + checked_state = NSMixedState; + break; + } + [(id)item setState:checked_state]; + } + return state.is_enabled; + } + return editCommand_helper_->IsMenuItemEnabled(action, self); } @@ -2124,6 +2152,7 @@ void RenderWidgetHostViewMac::SetTextInputActive(bool active) { // other spelling panel methods. This is probably because Apple assumes that the // the spelling panel will be used with an NSText, which will automatically // catch this and advance to the next word for you. Thanks Apple. +// This is also called from the Edit -> Spelling -> Check Spelling menu item. - (void)checkSpelling:(id)sender { RenderWidgetHostViewMac* thisHostView = [self renderWidgetHostViewMac]; thisHostView->GetRenderWidgetHost()->AdvanceToNextMisspelling(); @@ -2146,6 +2175,13 @@ void RenderWidgetHostViewMac::SetTextInputActive(bool active) { SpellCheckerPlatform::SpellingPanelVisible()); } +- (void)toggleContinuousSpellChecking:(id)sender { + if (renderWidgetHostView_->render_widget_host_->IsRenderView()) { + static_cast<RenderViewHost*>(renderWidgetHostView_->render_widget_host_)-> + ToggleSpellCheck(); + } +} + // END Spellchecking methods // Below is the nasty tooltip stuff -- copied from WebKit's WebHTMLView.mm diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi index 390c610..deff90d 100644 --- a/chrome/chrome_common.gypi +++ b/chrome/chrome_common.gypi @@ -345,6 +345,7 @@ 'common/render_messages_internal.h', 'common/render_messages_params.cc', 'common/render_messages_params.h', + 'common/render_view_commands.h', 'common/renderer_preferences.cc', 'common/renderer_preferences.h', 'common/resource_dispatcher.cc', diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index 466f619..dada88c 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -2048,6 +2048,14 @@ IPC_MESSAGE_CONTROL2(ViewHostMsg_ExtensionRemoveListener, std::string /* extension_id */, std::string /* name */) +// Message sent from renderer to the browser to update the state of a command. +// The |command| parameter is a RenderViewCommand. The |checked_state| parameter +// is a CommandCheckedState. +IPC_MESSAGE_ROUTED3(ViewHostMsg_CommandStateChanged, + int /* command */, + bool /* is_enabled */, + int /* checked_state */) + #if defined(OS_MACOSX) // On OSX, we cannot allocated shared memory from within the sandbox, so // this call exists for the renderer to ask the browser to allocate memory diff --git a/chrome/common/render_view_commands.h b/chrome/common/render_view_commands.h new file mode 100644 index 0000000..541e7ea --- /dev/null +++ b/chrome/common/render_view_commands.h @@ -0,0 +1,23 @@ +// Copyright (c) 2011 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 CHROME_COMMON_RENDER_VIEW_COMMANDS_H_ +#define CHROME_COMMON_RENDER_VIEW_COMMANDS_H_ +#pragma once + +// These identify commands that the renderer process enables or disables +// in the browser process. For example, this is used on the Mac to keep +// the spell check menu commands in sync with the renderer state. +enum RenderViewCommand { + RENDER_VIEW_COMMAND_TOGGLE_SPELL_CHECK, +}; + +enum RenderViewCommandCheckedState { + RENDER_VIEW_COMMAND_CHECKED_STATE_UNCHECKED, + RENDER_VIEW_COMMAND_CHECKED_STATE_CHECKED, + RENDER_VIEW_COMMAND_CHECKED_STATE_MIXED, +}; + + +#endif // CHROME_COMMON_RENDER_VIEW_COMMANDS_H_ diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 4de9a22..9ea2b85 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -41,6 +41,7 @@ #include "chrome/common/pepper_messages.h" #include "chrome/common/pepper_plugin_registry.h" #include "chrome/common/render_messages.h" +#include "chrome/common/render_view_commands.h" #include "chrome/common/renderer_preferences.h" #include "chrome/common/thumbnail_score.h" #include "chrome/common/url_constants.h" @@ -1632,18 +1633,12 @@ void RenderView::OnSetInitialFocus(bool reverse) { } void RenderView::OnScrollFocusedEditableNodeIntoView() { - if (!webview()) - return; - WebFrame* focused_frame = webview()->focusedFrame(); - if (focused_frame) { - WebDocument doc = focused_frame->document(); - if (!doc.isNull()) { - WebNode node = doc.focusedNode(); - if (IsEditableNode(node)) - // TODO(varunjain): Change webkit API to scroll a particular node into - // view and use that API here instead. - webview()->scrollFocusedNodeIntoView(); - } + WebKit::WebNode node = GetFocusedNode(); + if (!node.isNull()) { + if (IsEditableNode(node)) + // TODO(varunjain): Change webkit API to scroll a particular node into + // view and use that API here instead. + webview()->scrollFocusedNodeIntoView(); } } @@ -2374,6 +2369,10 @@ void RenderView::updateSpellingUIWithMisspelledWord(const WebString& word) { word)); } +void RenderView::continuousSpellCheckingEnabledStateChanged() { + UpdateToggleSpellCheckCommandState(); +} + bool RenderView::runFileChooser( const WebKit::WebFileChooserParams& params, WebFileChooserCompletion* chooser_completion) { @@ -2500,6 +2499,27 @@ void RenderView::UpdateTargetURL(const GURL& url, const GURL& fallback_url) { } } +void RenderView::UpdateToggleSpellCheckCommandState() { + bool is_enabled = false; + WebKit::WebNode node = GetFocusedNode(); + if (!node.isNull()) + is_enabled = IsEditableNode(node); + + RenderViewCommandCheckedState checked_state = + RENDER_VIEW_COMMAND_CHECKED_STATE_UNCHECKED; + if (is_enabled && webview()) { + WebFrame* frame = webview()->focusedFrame(); + if (frame->isContinuousSpellCheckingEnabled()) + checked_state = RENDER_VIEW_COMMAND_CHECKED_STATE_CHECKED; + } + + Send(new ViewHostMsg_CommandStateChanged( + routing_id_, + RENDER_VIEW_COMMAND_TOGGLE_SPELL_CHECK, + is_enabled, + checked_state)); +} + void RenderView::StartNavStateSyncTimerIfNecessary() { int delay; if (send_content_state_immediately_) @@ -2576,6 +2596,8 @@ void RenderView::focusedNodeChanged(const WebNode& node) { webview()->accessibilityObject(), WebKit::WebAccessibilityNotificationFocusedUIElementChanged); } + + UpdateToggleSpellCheckCommandState(); } void RenderView::navigateBackForwardSoon(int offset) { @@ -4516,6 +4538,19 @@ WebFrame* RenderView::GetChildFrame(const std::wstring& xpath) const { return frame; } +WebNode RenderView::GetFocusedNode() const { + if (!webview()) + return WebNode(); + WebFrame* focused_frame = webview()->focusedFrame(); + if (focused_frame) { + WebDocument doc = focused_frame->document(); + if (!doc.isNull()) + return doc.focusedNode(); + } + + return WebNode(); +} + void RenderView::SetSuggestions(const std::vector<std::string>& suggestions) { // Explicitly allow empty vector to be sent to the browser. Send(new ViewHostMsg_SetSuggestions(routing_id_, page_id_, suggestions)); diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index 2540ba0..4ffaea9 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -434,6 +434,7 @@ class RenderView : public RenderWidget, virtual bool isShowingSpellingUI(); virtual void updateSpellingUIWithMisspelledWord( const WebKit::WebString& word); + virtual void continuousSpellCheckingEnabledStateChanged(); virtual bool runFileChooser( const WebKit::WebFileChooserParams& params, WebKit::WebFileChooserCompletion* chooser_completion); @@ -1057,6 +1058,9 @@ class RenderView : public RenderWidget, // Locates a sub frame with given xpath WebKit::WebFrame* GetChildFrame(const std::wstring& frame_xpath) const; + // Gets the focused node. If no such node exists then the node will be isNull. + WebKit::WebNode GetFocusedNode() const; + WebUIBindings* GetWebUIBindings(); ExternalHostBindings* GetExternalHostBindings(); @@ -1115,6 +1119,9 @@ class RenderView : public RenderWidget, // If |url| is empty, show |fallback_url|. void UpdateTargetURL(const GURL& url, const GURL& fallback_url); + // Updates the state of the toggle spell check command in the browser process. + void UpdateToggleSpellCheckCommandState(); + // Helper to add an error message to the root frame's console. void AddErrorToRootConsole(const string16& message); |