Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(387)

Side by Side Diff: webkit/api/src/WebViewImpl.cpp

Issue 341030: Moves webview_impl.cc, webframe_impl.cc and webframeloaderclient_impl.cc into... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « webkit/api/src/WebViewImpl.h ('k') | webkit/api/src/WebWorkerClientImpl.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2007-2009 The Chromium Authors. All rights reserved. 1 /*
2 // Use of this source code is governed by a BSD-style license that can be 2 * Copyright (C) 2009 Google Inc. All rights reserved.
3 // found in the LICENSE file. 3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
4 30
5 #include "config.h" 31 #include "config.h"
32 #include "WebViewImpl.h"
6 33
34 #include "AutocompletePopupMenuClient.h"
7 #include "AXObjectCache.h" 35 #include "AXObjectCache.h"
8 #include "CSSStyleSelector.h" 36 #include "CSSStyleSelector.h"
9 #include "CSSValueKeywords.h" 37 #include "CSSValueKeywords.h"
10 #include "Cursor.h" 38 #include "Cursor.h"
11 #include "Document.h" 39 #include "Document.h"
12 #include "DocumentLoader.h" 40 #include "DocumentLoader.h"
41 #include "DOMUtilitiesPrivate.h"
13 #include "DragController.h" 42 #include "DragController.h"
14 #include "DragData.h" 43 #include "DragData.h"
15 #include "Editor.h" 44 #include "Editor.h"
16 #include "EventHandler.h" 45 #include "EventHandler.h"
17 #include "FocusController.h" 46 #include "FocusController.h"
18 #include "FontDescription.h" 47 #include "FontDescription.h"
19 #include "FrameLoader.h" 48 #include "FrameLoader.h"
20 #include "FrameTree.h" 49 #include "FrameTree.h"
21 #include "FrameView.h" 50 #include "FrameView.h"
22 #include "GraphicsContext.h" 51 #include "GraphicsContext.h"
(...skipping 17 matching lines...) Expand all
40 #include "PlatformWheelEvent.h" 69 #include "PlatformWheelEvent.h"
41 #include "PluginInfoStore.h" 70 #include "PluginInfoStore.h"
42 #include "PopupMenuChromium.h" 71 #include "PopupMenuChromium.h"
43 #include "PopupMenuClient.h" 72 #include "PopupMenuClient.h"
44 #include "RenderView.h" 73 #include "RenderView.h"
45 #include "ResourceHandle.h" 74 #include "ResourceHandle.h"
46 #include "SecurityOrigin.h" 75 #include "SecurityOrigin.h"
47 #include "SelectionController.h" 76 #include "SelectionController.h"
48 #include "Settings.h" 77 #include "Settings.h"
49 #include "TypingCommand.h" 78 #include "TypingCommand.h"
79 #include "WebAccessibilityObject.h"
80 #include "WebDragData.h"
81 #include "WebFrameImpl.h"
82 #include "WebInputEvent.h"
83 #include "WebInputEventConversion.h"
84 #include "WebMediaPlayerAction.h"
85 #include "WebNode.h"
86 #include "WebPoint.h"
87 #include "WebPopupMenuImpl.h"
88 #include "WebRect.h"
89 #include "WebSettingsImpl.h"
90 #include "WebString.h"
91 #include "WebVector.h"
92 #include "WebViewClient.h"
93
50 #if PLATFORM(WIN_OS) 94 #if PLATFORM(WIN_OS)
51 #include "KeyboardCodesWin.h" 95 #include "KeyboardCodesWin.h"
52 #include "RenderThemeChromiumWin.h" 96 #include "RenderThemeChromiumWin.h"
53 #else 97 #else
54 #include "KeyboardCodesPosix.h" 98 #include "KeyboardCodesPosix.h"
55 #include "RenderTheme.h" 99 #include "RenderTheme.h"
56 #endif 100 #endif
57 #undef LOG
58 101
59 #include "webkit/api/public/WebAccessibilityObject.h" 102 // FIXME
60 #include "webkit/api/public/WebDragData.h"
61 #include "webkit/api/public/WebInputEvent.h"
62 #include "webkit/api/public/WebMediaPlayerAction.h"
63 #include "webkit/api/public/WebPoint.h"
64 #include "webkit/api/public/WebRect.h"
65 #include "webkit/api/public/WebString.h"
66 #include "webkit/api/public/WebVector.h"
67 #include "webkit/api/public/WebViewClient.h"
68 #include "webkit/api/src/DOMUtilitiesPrivate.h"
69 #include "webkit/api/src/WebInputEventConversion.h"
70 #include "webkit/api/src/WebPopupMenuImpl.h"
71 #include "webkit/api/src/WebSettingsImpl.h"
72 #include "webkit/glue/glue_util.h"
73 #include "webkit/glue/webdevtoolsagent_impl.h" 103 #include "webkit/glue/webdevtoolsagent_impl.h"
74 #include "webkit/glue/webkit_glue.h"
75 #include "webkit/glue/webview_impl.h"
76 104
77 // Get rid of WTF's pow define so we can use std::pow. 105 // Get rid of WTF's pow define so we can use std::pow.
78 #undef pow 106 #undef pow
79 #include <cmath> // for std::pow 107 #include <cmath> // for std::pow
80 108
81 using namespace WebCore; 109 using namespace WebCore;
82 110
83 using WebKit::ChromeClientImpl; 111 namespace WebKit {
84 using WebKit::EditorClientImpl;
85 using WebKit::PlatformKeyboardEventBuilder;
86 using WebKit::PlatformMouseEventBuilder;
87 using WebKit::PlatformWheelEventBuilder;
88 using WebKit::WebAccessibilityObject;
89 using WebKit::WebCanvas;
90 using WebKit::WebCompositionCommand;
91 using WebKit::WebCompositionCommandConfirm;
92 using WebKit::WebCompositionCommandDiscard;
93 using WebKit::WebDevToolsAgent;
94 using WebKit::WebDevToolsAgentClient;
95 using WebKit::WebDragData;
96 using WebKit::WebDragOperation;
97 using WebKit::WebDragOperationCopy;
98 using WebKit::WebDragOperationNone;
99 using WebKit::WebDragOperationsMask;
100 using WebKit::WebFrame;
101 using WebKit::WebFrameClient;
102 using WebKit::WebInputEvent;
103 using WebKit::WebKeyboardEvent;
104 using WebKit::WebMediaPlayerAction;
105 using WebKit::WebMouseEvent;
106 using WebKit::WebMouseWheelEvent;
107 using WebKit::WebNavigationPolicy;
108 using WebKit::WebNode;
109 using WebKit::WebPoint;
110 using WebKit::WebPopupMenuImpl;
111 using WebKit::WebRect;
112 using WebKit::WebSettings;
113 using WebKit::WebSettingsImpl;
114 using WebKit::WebSize;
115 using WebKit::WebString;
116 using WebKit::WebTextDirection;
117 using WebKit::WebTextDirectionDefault;
118 using WebKit::WebTextDirectionLeftToRight;
119 using WebKit::WebTextDirectionRightToLeft;
120 using WebKit::WebURL;
121 using WebKit::WebVector;
122 using WebKit::WebViewClient;
123
124 using webkit_glue::AccessibilityObjectToWebAccessibilityObject;
125 112
126 // Change the text zoom level by kTextSizeMultiplierRatio each time the user 113 // Change the text zoom level by kTextSizeMultiplierRatio each time the user
127 // zooms text in or out (ie., change by 20%). The min and max values limit 114 // zooms text in or out (ie., change by 20%). The min and max values limit
128 // text zoom to half and 3x the original text size. These three values match 115 // text zoom to half and 3x the original text size. These three values match
129 // those in Apple's port in WebKit/WebKit/WebView/WebView.mm 116 // those in Apple's port in WebKit/WebKit/WebView/WebView.mm
130 static const double kTextSizeMultiplierRatio = 1.2; 117 static const double textSizeMultiplierRatio = 1.2;
131 static const double kMinTextSizeMultiplier = 0.5; 118 static const double minTextSizeMultiplier = 0.5;
132 static const double kMaxTextSizeMultiplier = 3.0; 119 static const double maxTextSizeMultiplier = 3.0;
133 120
134 // The group name identifies a namespace of pages. Page group is used on OSX 121 // The group name identifies a namespace of pages. Page group is used on OSX
135 // for some programs that use HTML views to display things that don't seem like 122 // for some programs that use HTML views to display things that don't seem like
136 // web pages to the user (so shouldn't have visited link coloring). We only use 123 // web pages to the user (so shouldn't have visited link coloring). We only use
137 // one page group. 124 // one page group.
138 // FIXME: This needs to go into the WebKit API implementation and be hidden
139 // from the API's users.
140 const char* pageGroupName = "default"; 125 const char* pageGroupName = "default";
141 126
142 // Ensure that the WebKit::WebDragOperation enum values stay in sync with 127 // Ensure that the WebDragOperation enum values stay in sync with the original
143 // the original WebCore::DragOperation constants. 128 // DragOperation constants.
144 #define COMPILE_ASSERT_MATCHING_ENUM(webcore_name) \ 129 #define COMPILE_ASSERT_MATCHING_ENUM(coreName) \
145 COMPILE_ASSERT(int(WebCore::webcore_name) == int(WebKit::Web##webcore_name),\ 130 COMPILE_ASSERT(int(coreName) == int(Web##coreName), dummy##coreName)
146 dummy##webcore_name)
147 COMPILE_ASSERT_MATCHING_ENUM(DragOperationNone); 131 COMPILE_ASSERT_MATCHING_ENUM(DragOperationNone);
148 COMPILE_ASSERT_MATCHING_ENUM(DragOperationCopy); 132 COMPILE_ASSERT_MATCHING_ENUM(DragOperationCopy);
149 COMPILE_ASSERT_MATCHING_ENUM(DragOperationLink); 133 COMPILE_ASSERT_MATCHING_ENUM(DragOperationLink);
150 COMPILE_ASSERT_MATCHING_ENUM(DragOperationGeneric); 134 COMPILE_ASSERT_MATCHING_ENUM(DragOperationGeneric);
151 COMPILE_ASSERT_MATCHING_ENUM(DragOperationPrivate); 135 COMPILE_ASSERT_MATCHING_ENUM(DragOperationPrivate);
152 COMPILE_ASSERT_MATCHING_ENUM(DragOperationMove); 136 COMPILE_ASSERT_MATCHING_ENUM(DragOperationMove);
153 COMPILE_ASSERT_MATCHING_ENUM(DragOperationDelete); 137 COMPILE_ASSERT_MATCHING_ENUM(DragOperationDelete);
154 COMPILE_ASSERT_MATCHING_ENUM(DragOperationEvery); 138 COMPILE_ASSERT_MATCHING_ENUM(DragOperationEvery);
155 139
156 // AutocompletePopupMenuClient
157 class AutocompletePopupMenuClient : public WebCore::PopupMenuClient {
158 public:
159 AutocompletePopupMenuClient(WebViewImpl* webview) : text_field_(NULL),
160 selected_index_(0),
161 webview_(webview) {
162 }
163
164 void Init(WebCore::HTMLInputElement* text_field,
165 const WebVector<WebString>& suggestions,
166 int default_suggestion_index) {
167 ASSERT(default_suggestion_index < static_cast<int>(suggestions.size()));
168 text_field_ = text_field;
169 selected_index_ = default_suggestion_index;
170 SetSuggestions(suggestions);
171
172 FontDescription font_description;
173 webview_->theme()->systemFont(CSSValueWebkitControl, font_description);
174 // Use a smaller font size to match IE/Firefox.
175 // TODO(jcampan): http://crbug.com/7376 use the system size instead of a
176 // fixed font size value.
177 font_description.setComputedSize(12.0);
178 Font font(font_description, 0, 0);
179 font.update(text_field->document()->styleSelector()->fontSelector());
180 // The direction of text in popup menu is set the same as the direction of
181 // the input element: text_field.
182 style_.set(new PopupMenuStyle(Color::black, Color::white, font, true,
183 Length(WebCore::Fixed), text_field->renderer()->style()->direction()));
184 }
185
186 virtual ~AutocompletePopupMenuClient() {
187 }
188
189 // WebCore::PopupMenuClient implementation.
190 virtual void valueChanged(unsigned listIndex, bool fireEvents = true) {
191 text_field_->setValue(suggestions_[listIndex]);
192 EditorClientImpl* editor =
193 static_cast<EditorClientImpl*>(webview_->page()->editorClient());
194 ASSERT(editor);
195 editor->onAutofillSuggestionAccepted(
196 static_cast<WebCore::HTMLInputElement*>(text_field_.get()));
197 }
198
199 virtual WebCore::String itemText(unsigned list_index) const {
200 return suggestions_[list_index];
201 }
202
203 virtual WebCore::String itemToolTip(unsigned last_index) const {
204 notImplemented();
205 return WebCore::String();
206 }
207
208 virtual bool itemIsEnabled(unsigned listIndex) const {
209 return true;
210 }
211
212 virtual PopupMenuStyle itemStyle(unsigned listIndex) const {
213 return *style_;
214 }
215
216 virtual PopupMenuStyle menuStyle() const {
217 return *style_;
218 }
219
220 virtual int clientInsetLeft() const {
221 return 0;
222 }
223 virtual int clientInsetRight() const {
224 return 0;
225 }
226 virtual int clientPaddingLeft() const {
227 // Bug http://crbug.com/7708 seems to indicate the style can be NULL.
228 WebCore::RenderStyle* style = GetTextFieldStyle();
229 return style ? webview_->theme()->popupInternalPaddingLeft(style) : 0;
230 }
231 virtual int clientPaddingRight() const {
232 // Bug http://crbug.com/7708 seems to indicate the style can be NULL.
233 WebCore::RenderStyle* style = GetTextFieldStyle();
234 return style ? webview_->theme()->popupInternalPaddingRight(style) : 0;
235 }
236 virtual int listSize() const {
237 return suggestions_.size();
238 }
239 virtual int selectedIndex() const {
240 return selected_index_;
241 }
242 virtual void popupDidHide() {
243 webview_->AutoCompletePopupDidHide();
244 }
245 virtual bool itemIsSeparator(unsigned listIndex) const {
246 return false;
247 }
248 virtual bool itemIsLabel(unsigned listIndex) const {
249 return false;
250 }
251 virtual bool itemIsSelected(unsigned listIndex) const {
252 return false;
253 }
254 virtual bool shouldPopOver() const {
255 return false;
256 }
257 virtual bool valueShouldChangeOnHotTrack() const {
258 return false;
259 }
260
261 virtual void setTextFromItem(unsigned listIndex) {
262 text_field_->setValue(suggestions_[listIndex]);
263 }
264
265 virtual FontSelector* fontSelector() const {
266 return text_field_->document()->styleSelector()->fontSelector();
267 }
268
269 virtual HostWindow* hostWindow() const {
270 return text_field_->document()->view()->hostWindow();
271 }
272
273 virtual PassRefPtr<Scrollbar> createScrollbar(
274 ScrollbarClient* client,
275 ScrollbarOrientation orientation,
276 ScrollbarControlSize size) {
277 RefPtr<Scrollbar> widget = Scrollbar::createNativeScrollbar(client,
278 orientation,
279 size);
280 return widget.release();
281 }
282
283 // AutocompletePopupMenuClient specific methods:
284 void SetSuggestions(const WebVector<WebString>& suggestions) {
285 suggestions_.clear();
286 for (size_t i = 0; i < suggestions.size(); ++i)
287 suggestions_.append(webkit_glue::WebStringToString(suggestions[i]));
288 // Try to preserve selection if possible.
289 if (selected_index_ >= static_cast<int>(suggestions.size()))
290 selected_index_ = -1;
291 }
292
293 void RemoveItemAtIndex(int index) {
294 ASSERT(index >= 0 && index < static_cast<int>(suggestions_.size()));
295 suggestions_.remove(index);
296 }
297
298 WebCore::HTMLInputElement* text_field() const {
299 return text_field_.get();
300 }
301
302 WebCore::RenderStyle* GetTextFieldStyle() const {
303 WebCore::RenderStyle* style = text_field_->computedStyle();
304 if (!style) {
305 // It seems we can only have an NULL style in a TextField if the node is
306 // dettached, in which case we the popup shoud not be showing. Please
307 // report this in http://crbug.com/7708 and include the page you were
308 // visiting.
309 ASSERT_NOT_REACHED();
310 }
311 return style;
312 }
313
314 private:
315 RefPtr<WebCore::HTMLInputElement> text_field_;
316 Vector<WebCore::String> suggestions_;
317 int selected_index_;
318 WebViewImpl* webview_;
319 OwnPtr<PopupMenuStyle> style_;
320 };
321
322 // Note that focusOnShow is false so that the autocomplete popup is shown not 140 // Note that focusOnShow is false so that the autocomplete popup is shown not
323 // activated. We need the page to still have focus so the user can keep typing 141 // activated. We need the page to still have focus so the user can keep typing
324 // while the popup is showing. 142 // while the popup is showing.
325 static const WebCore::PopupContainerSettings kAutocompletePopupSettings = { 143 static const PopupContainerSettings autocompletePopupSettings = {
326 false, // focusOnShow 144 false, // focusOnShow
327 false, // setTextOnIndexChange 145 false, // setTextOnIndexChange
328 false, // acceptOnAbandon 146 false, // acceptOnAbandon
329 true, // loopSelectionNavigation 147 true, // loopSelectionNavigation
330 true, // restrictWidthOfListBox. Same as other browser (Fx, IE, and safari) 148 true, // restrictWidthOfListBox. Same as other browser (Fx, IE, and safari)
331 // For autocomplete, we use the direction of the input field as the direction 149 // For autocomplete, we use the direction of the input field as the direction
332 // of the popup items. The main reason is to keep the display of items in 150 // of the popup items. The main reason is to keep the display of items in
333 // drop-down the same as the items in the input field. 151 // drop-down the same as the items in the input field.
334 WebCore::PopupContainerSettings::DOMElementDirection, 152 PopupContainerSettings::DOMElementDirection,
335 }; 153 };
336 154
337 // WebView ---------------------------------------------------------------- 155 // WebView ----------------------------------------------------------------
338 156
339 namespace WebKit { 157 WebView* WebView::create(WebViewClient* client)
340 158 {
341 // static 159 return new WebViewImpl(client);
342 WebView* WebView::create(WebViewClient* client) { 160 }
343 return new WebViewImpl(client); 161
344 } 162 void WebView::updateVisitedLinkState(unsigned long long linkHash)
345 163 {
346 // static 164 Page::visitedStateChanged(PageGroup::pageGroup(pageGroupName), linkHash);
347 void WebView::updateVisitedLinkState(unsigned long long link_hash) { 165 }
348 WebCore::Page::visitedStateChanged( 166
349 WebCore::PageGroup::pageGroup(pageGroupName), link_hash); 167 void WebView::resetVisitedLinkState()
350 } 168 {
351 169 Page::allVisitedStateChanged(PageGroup::pageGroup(pageGroupName));
352 // static 170 }
353 void WebView::resetVisitedLinkState() { 171
354 WebCore::Page::allVisitedStateChanged( 172 void WebViewImpl::initializeMainFrame(WebFrameClient* frameClient) {
355 WebCore::PageGroup::pageGroup(pageGroupName)); 173 // NOTE: The WebFrameImpl takes a reference to itself within InitMainFrame
356 } 174 // and releases that reference once the corresponding Frame is destroyed.
357 175 RefPtr<WebFrameImpl> frame = WebFrameImpl::create(frameClient);
358 } // namespace WebKit 176
359 177 frame->initializeAsMainFrame(this);
360 void WebViewImpl::initializeMainFrame(WebFrameClient* frame_client) { 178
361 // NOTE: The WebFrameImpl takes a reference to itself within InitMainFrame 179 if (m_client) {
362 // and releases that reference once the corresponding Frame is destroyed. 180 WebDevToolsAgentClient* toolsClient = m_client->devToolsAgentClient();
363 RefPtr<WebFrameImpl> main_frame = WebFrameImpl::create(frame_client); 181 if (toolsClient)
364 182 m_devToolsAgent.set(new WebDevToolsAgentImpl(this, toolsClient));
365 main_frame->InitMainFrame(this); 183 }
366 184
367 if (client_) { 185 // Restrict the access to the local file system
368 WebDevToolsAgentClient* tools_client = client_->devToolsAgentClient(); 186 // (see WebView.mm WebView::_commonInitializationWithFrameName).
369 if (tools_client) 187 SecurityOrigin::setLocalLoadPolicy(SecurityOrigin::AllowLocalLoadsForLocalOnly);
370 devtools_agent_.set(new WebDevToolsAgentImpl(this, tools_client));
371 }
372
373 // Restrict the access to the local file system
374 // (see WebView.mm WebView::_commonInitializationWithFrameName).
375 SecurityOrigin::setLocalLoadPolicy(
376 SecurityOrigin::AllowLocalLoadsForLocalOnly);
377 } 188 }
378 189
379 WebViewImpl::WebViewImpl(WebViewClient* client) 190 WebViewImpl::WebViewImpl(WebViewClient* client)
380 : client_(client), 191 : m_client(client)
381 ALLOW_THIS_IN_INITIALIZER_LIST(back_forward_list_client_impl_(this)), 192 , m_backForwardListClientImpl(this)
382 ALLOW_THIS_IN_INITIALIZER_LIST(chrome_client_impl_(this)), 193 , m_chromeClientImpl(this)
383 ALLOW_THIS_IN_INITIALIZER_LIST(context_menu_client_impl_(this)), 194 , m_contextMenuClientImpl(this)
384 ALLOW_THIS_IN_INITIALIZER_LIST(drag_client_impl_(this)), 195 , m_dragClientImpl(this)
385 ALLOW_THIS_IN_INITIALIZER_LIST(editor_client_impl_(this)), 196 , m_editorClientImpl(this)
386 ALLOW_THIS_IN_INITIALIZER_LIST(inspector_client_impl_(this)), 197 , m_inspectorClientImpl(this)
387 observed_new_navigation_(false), 198 , m_observedNewNavigation(false)
388 #ifndef NDEBUG 199 #ifndef NDEBUG
389 new_navigation_loader_(NULL), 200 , m_newNavigationLoader(0)
390 #endif 201 #endif
391 zoom_level_(0), 202 , m_zoomLevel(0)
392 context_menu_allowed_(false), 203 , m_contextMenuAllowed(false)
393 doing_drag_and_drop_(false), 204 , m_doingDragAndDrop(false)
394 ignore_input_events_(false), 205 , m_ignoreInputEvents(false)
395 suppress_next_keypress_event_(false), 206 , m_suppressNextKeypressEvent(false)
396 initial_navigation_policy_(WebKit::WebNavigationPolicyIgnore), 207 , m_initialNavigationPolicy(WebNavigationPolicyIgnore)
397 ime_accept_events_(true), 208 , m_imeAcceptEvents(true)
398 drag_target_dispatch_(false), 209 , m_dragTargetDispatch(false)
399 drag_identity_(0), 210 , m_dragIdentity(0)
400 drop_effect_(DROP_EFFECT_DEFAULT), 211 , m_dropEffect(DropEffectDefault)
401 operations_allowed_(WebKit::WebDragOperationNone), 212 , m_operationsAllowed(WebDragOperationNone)
402 drag_operation_(WebKit::WebDragOperationNone), 213 , m_dragOperation(WebDragOperationNone)
403 autocomplete_popup_showing_(false), 214 , m_autocompletePopupShowing(false)
404 is_transparent_(false), 215 , m_isTransparent(false)
405 tabs_to_links_(false) { 216 , m_tabsToLinks(false)
406 // WebKit/win/WebView.cpp does the same thing, except they call the 217 {
407 // KJS specific wrapper around this method. We need to have threading 218 // WebKit/win/WebView.cpp does the same thing, except they call the
408 // initialized because CollatorICU requires it. 219 // KJS specific wrapper around this method. We need to have threading
409 WTF::initializeThreading(); 220 // initialized because CollatorICU requires it.
410 221 WTF::initializeThreading();
411 // set to impossible point so we always get the first mouse pos 222
412 last_mouse_position_ = WebPoint(-1, -1); 223 // set to impossible point so we always get the first mouse pos
413 224 m_lastMousePosition = WebPoint(-1, -1);
414 // the page will take ownership of the various clients 225
415 page_.set(new Page(&chrome_client_impl_, 226 // the page will take ownership of the various clients
416 &context_menu_client_impl_, 227 m_page.set(new Page(&m_chromeClientImpl,
417 &editor_client_impl_, 228 &m_contextMenuClientImpl,
418 &drag_client_impl_, 229 &m_editorClientImpl,
419 &inspector_client_impl_, 230 &m_dragClientImpl,
420 NULL)); 231 &m_inspectorClientImpl,
421 232 0));
422 page_->backForwardList()->setClient(&back_forward_list_client_impl_); 233
423 page_->setGroupName(pageGroupName); 234 m_page->backForwardList()->setClient(&m_backForwardListClientImpl);
424 } 235 m_page->setGroupName(pageGroupName);
425 236 }
426 WebViewImpl::~WebViewImpl() { 237
427 ASSERT(page_ == NULL); 238 WebViewImpl::~WebViewImpl()
428 } 239 {
429 240 ASSERT(!m_page);
430 RenderTheme* WebViewImpl::theme() const { 241 }
431 return page_.get() ? page_->theme() : RenderTheme::defaultTheme().get(); 242
432 } 243 RenderTheme* WebViewImpl::theme() const
433 244 {
434 bool WebViewImpl::tabKeyCyclesThroughElements() const { 245 return m_page.get() ? m_page->theme() : RenderTheme::defaultTheme().get();
435 ASSERT(page_.get()); 246 }
436 return page_->tabKeyCyclesThroughElements(); 247
437 } 248 WebFrameImpl* WebViewImpl::mainFrameImpl()
438 249 {
439 void WebViewImpl::setTabKeyCyclesThroughElements(bool value) { 250 return m_page.get() ? WebFrameImpl::fromFrame(m_page->mainFrame()) : 0;
440 if (page_ != NULL) { 251 }
441 page_->setTabKeyCyclesThroughElements(value); 252
442 } 253 bool WebViewImpl::tabKeyCyclesThroughElements() const
443 } 254 {
444 255 ASSERT(m_page.get());
445 void WebViewImpl::MouseMove(const WebMouseEvent& event) { 256 return m_page->tabKeyCyclesThroughElements();
446 if (!main_frame() || !main_frame()->frameview()) 257 }
447 return; 258
448 259 void WebViewImpl::setTabKeyCyclesThroughElements(bool value)
449 last_mouse_position_ = WebPoint(event.x, event.y); 260 {
450 261 if (m_page)
451 // We call mouseMoved here instead of handleMouseMovedEvent because we need 262 m_page->setTabKeyCyclesThroughElements(value);
452 // our ChromeClientImpl to receive changes to the mouse position and 263 }
453 // tooltip text, and mouseMoved handles all of that. 264
454 main_frame()->frame()->eventHandler()->mouseMoved( 265 void WebViewImpl::mouseMove(const WebMouseEvent& event)
455 PlatformMouseEventBuilder(main_frame()->frameview(), event)); 266 {
456 } 267 if (!mainFrameImpl() || !mainFrameImpl()->frameView())
457 268 return;
458 void WebViewImpl::MouseLeave(const WebMouseEvent& event) { 269
459 // This event gets sent as the main frame is closing. In that case, just 270 m_lastMousePosition = WebPoint(event.x, event.y);
460 // ignore it. 271
461 if (!main_frame() || !main_frame()->frameview()) 272 // We call mouseMoved here instead of handleMouseMovedEvent because we need
462 return; 273 // our ChromeClientImpl to receive changes to the mouse position and
463 274 // tooltip text, and mouseMoved handles all of that.
464 client_->setMouseOverURL(WebURL()); 275 mainFrameImpl()->frame()->eventHandler()->mouseMoved(
465 276 PlatformMouseEventBuilder(mainFrameImpl()->frameView(), event));
466 main_frame()->frame()->eventHandler()->handleMouseMoveEvent( 277 }
467 PlatformMouseEventBuilder(main_frame()->frameview(), event)); 278
468 } 279 void WebViewImpl::mouseLeave(const WebMouseEvent& event)
469 280 {
470 void WebViewImpl::MouseDown(const WebMouseEvent& event) { 281 // This event gets sent as the main frame is closing. In that case, just
471 if (!main_frame() || !main_frame()->frameview()) 282 // ignore it.
472 return; 283 if (!mainFrameImpl() || !mainFrameImpl()->frameView())
473 284 return;
474 last_mouse_down_point_ = WebPoint(event.x, event.y); 285
475 286 m_client->setMouseOverURL(WebURL());
476 // If a text field that has focus is clicked again, we should display the 287
477 // autocomplete popup. 288 mainFrameImpl()->frame()->eventHandler()->handleMouseMoveEvent(
478 RefPtr<Node> clicked_node; 289 PlatformMouseEventBuilder(mainFrameImpl()->frameView(), event));
479 if (event.button == WebMouseEvent::ButtonLeft) { 290 }
480 RefPtr<Node> focused_node = GetFocusedNode(); 291
481 if (focused_node.get() && 292 void WebViewImpl::mouseDown(const WebMouseEvent& event)
482 WebKit::toHTMLInputElement(focused_node.get())) { 293 {
483 IntPoint point(event.x, event.y); 294 if (!mainFrameImpl() || !mainFrameImpl()->frameView())
484 point = page_->mainFrame()->view()->windowToContents(point); 295 return;
485 HitTestResult result(point); 296
486 result = page_->mainFrame()->eventHandler()->hitTestResultAtPoint(point, 297 m_lastMouseDownPoint = WebPoint(event.x, event.y);
487 false); 298
488 if (result.innerNonSharedNode() == focused_node) { 299 // If a text field that has focus is clicked again, we should display the
489 // Already focused text field was clicked, let's remember this. If 300 // autocomplete popup.
490 // focus has not changed after the mouse event is processed, we'll 301 RefPtr<Node> clickedNode;
491 // trigger the autocomplete. 302 if (event.button == WebMouseEvent::ButtonLeft) {
492 clicked_node = focused_node; 303 RefPtr<Node> focusedNode = focusedWebCoreNode();
493 } 304 if (focusedNode.get() && toHTMLInputElement(focusedNode.get())) {
494 } 305 IntPoint point(event.x, event.y);
495 } 306 point = m_page->mainFrame()->view()->windowToContents(point);
496 307 HitTestResult result(point);
497 main_frame()->frame()->eventHandler()->handleMousePressEvent( 308 result = m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(point, false);
498 PlatformMouseEventBuilder(main_frame()->frameview(), event)); 309 if (result.innerNonSharedNode() == focusedNode) {
499 310 // Already focused text field was clicked, let's remember this. If
500 if (clicked_node.get() && clicked_node == GetFocusedNode()) { 311 // focus has not changed after the mouse event is processed, we'll
501 // Focus has not changed, show the autocomplete popup. 312 // trigger the autocomplete.
502 static_cast<EditorClientImpl*>(page_->editorClient())-> 313 clickedNode = focusedNode;
503 showFormAutofillForNode(clicked_node.get()); 314 }
504 } 315 }
505 316 }
506 // Dispatch the contextmenu event regardless of if the click was swallowed. 317
507 // On Windows, we handle it on mouse up, not down. 318 mainFrameImpl()->frame()->eventHandler()->handleMousePressEvent(
319 PlatformMouseEventBuilder(mainFrameImpl()->frameView(), event));
320
321 if (clickedNode.get() && clickedNode == focusedWebCoreNode()) {
322 // Focus has not changed, show the autocomplete popup.
323 static_cast<EditorClientImpl*>(m_page->editorClient())->
324 showFormAutofillForNode(clickedNode.get());
325 }
326
327 // Dispatch the contextmenu event regardless of if the click was swallowed.
328 // On Windows, we handle it on mouse up, not down.
508 #if PLATFORM(DARWIN) 329 #if PLATFORM(DARWIN)
509 if (event.button == WebMouseEvent::ButtonRight || 330 if (event.button == WebMouseEvent::ButtonRight
510 (event.button == WebMouseEvent::ButtonLeft && 331 || (event.button == WebMouseEvent::ButtonLeft
511 event.modifiers & WebMouseEvent::ControlKey)) { 332 && event.modifiers & WebMouseEvent::ControlKey))
512 MouseContextMenu(event); 333 mouseContextMenu(event);
513 }
514 #elif PLATFORM(LINUX) 334 #elif PLATFORM(LINUX)
515 if (event.button == WebMouseEvent::ButtonRight) 335 if (event.button == WebMouseEvent::ButtonRight)
516 MouseContextMenu(event); 336 mouseContextMenu(event);
517 #endif 337 #endif
518 } 338 }
519 339
520 void WebViewImpl::MouseContextMenu(const WebMouseEvent& event) { 340 void WebViewImpl::mouseContextMenu(const WebMouseEvent& event)
521 if (!main_frame() || !main_frame()->frameview()) 341 {
522 return; 342 if (!mainFrameImpl() || !mainFrameImpl()->frameView())
523 343 return;
524 page_->contextMenuController()->clearContextMenu(); 344
525 345 m_page->contextMenuController()->clearContextMenu();
526 PlatformMouseEventBuilder pme(main_frame()->frameview(), event); 346
527 347 PlatformMouseEventBuilder pme(mainFrameImpl()->frameView(), event);
528 // Find the right target frame. See issue 1186900. 348
529 HitTestResult result = HitTestResultForWindowPos(pme.pos()); 349 // Find the right target frame. See issue 1186900.
530 Frame* target_frame; 350 HitTestResult result = hitTestResultForWindowPos(pme.pos());
531 if (result.innerNonSharedNode()) 351 Frame* targetFrame;
532 target_frame = result.innerNonSharedNode()->document()->frame(); 352 if (result.innerNonSharedNode())
533 else 353 targetFrame = result.innerNonSharedNode()->document()->frame();
534 target_frame = page_->focusController()->focusedOrMainFrame(); 354 else
355 targetFrame = m_page->focusController()->focusedOrMainFrame();
535 356
536 #if PLATFORM(WIN_OS) 357 #if PLATFORM(WIN_OS)
537 target_frame->view()->setCursor(pointerCursor()); 358 targetFrame->view()->setCursor(pointerCursor());
538 #endif 359 #endif
539 360
540 context_menu_allowed_ = true; 361 m_contextMenuAllowed = true;
541 target_frame->eventHandler()->sendContextMenuEvent(pme); 362 targetFrame->eventHandler()->sendContextMenuEvent(pme);
542 context_menu_allowed_ = false; 363 m_contextMenuAllowed = false;
543 // Actually showing the context menu is handled by the ContextMenuClient 364 // Actually showing the context menu is handled by the ContextMenuClient
544 // implementation... 365 // implementation...
545 } 366 }
546 367
547 void WebViewImpl::MouseUp(const WebMouseEvent& event) { 368 void WebViewImpl::mouseUp(const WebMouseEvent& event)
548 if (!main_frame() || !main_frame()->frameview()) 369 {
549 return; 370 if (!mainFrameImpl() || !mainFrameImpl()->frameView())
371 return;
550 372
551 #if PLATFORM(LINUX) 373 #if PLATFORM(LINUX)
552 // If the event was a middle click, attempt to copy text into the focused 374 // If the event was a middle click, attempt to copy text into the focused
553 // frame. We execute this before we let the page have a go at the event 375 // frame. We execute this before we let the page have a go at the event
554 // because the page may change what is focused during in its event handler. 376 // because the page may change what is focused during in its event handler.
555 // 377 //
556 // This code is in the mouse up handler. There is some debate about putting 378 // This code is in the mouse up handler. There is some debate about putting
557 // this here, as opposed to the mouse down handler. 379 // this here, as opposed to the mouse down handler.
558 // xterm: pastes on up. 380 // xterm: pastes on up.
559 // GTK: pastes on down. 381 // GTK: pastes on down.
560 // Firefox: pastes on up. 382 // Firefox: pastes on up.
561 // Midori: couldn't paste at all with 0.1.2 383 // Midori: couldn't paste at all with 0.1.2
562 // 384 //
563 // There is something of a webcompat angle to this well, as highlighted by 385 // There is something of a webcompat angle to this well, as highlighted by
564 // crbug.com/14608. Pages can clear text boxes 'onclick' and, if we paste on 386 // crbug.com/14608. Pages can clear text boxes 'onclick' and, if we paste on
565 // down then the text is pasted just before the onclick handler runs and 387 // down then the text is pasted just before the onclick handler runs and
566 // clears the text box. So it's important this happens after the 388 // clears the text box. So it's important this happens after the
567 // handleMouseReleaseEvent() earlier in this function 389 // handleMouseReleaseEvent() earlier in this function
568 if (event.button == WebMouseEvent::ButtonMiddle) { 390 if (event.button == WebMouseEvent::ButtonMiddle) {
569 Frame* focused = GetFocusedWebCoreFrame(); 391 Frame* focused = focusedWebCoreFrame();
570 IntPoint click_point(last_mouse_down_point_.x, last_mouse_down_point_.y); 392 IntPoint clickPoint(m_lastMouseDownPoint.x, m_lastMouseDownPoint.y);
571 click_point = page_->mainFrame()->view()->windowToContents(click_point); 393 clickPoint = m_page->mainFrame()->view()->windowToContents(clickPoint);
572 HitTestResult hit_test_result = 394 HitTestResult hitTestResult =
573 focused->eventHandler()->hitTestResultAtPoint(click_point, false, false, 395 focused->eventHandler()->hitTestResultAtPoint(clickPoint, false, false,
574 ShouldHitTestScrollbars); 396 ShouldHitTestScrollbars);
575 // We don't want to send a paste when middle clicking a scroll bar or a 397 // We don't want to send a paste when middle clicking a scroll bar or a
576 // link (which will navigate later in the code). 398 // link (which will navigate later in the code).
577 if (!hit_test_result.scrollbar() && !hit_test_result.isLiveLink() && 399 if (!hitTestResult.scrollbar() && !hitTestResult.isLiveLink() && focused) {
578 focused) { 400 Editor* editor = focused->editor();
579 Editor* editor = focused->editor(); 401 Pasteboard* pasteboard = Pasteboard::generalPasteboard();
580 Pasteboard* pasteboard = Pasteboard::generalPasteboard(); 402 bool oldSelectionMode = pasteboard->isSelectionMode();
581 bool oldSelectionMode = pasteboard->isSelectionMode(); 403 pasteboard->setSelectionMode(true);
582 pasteboard->setSelectionMode(true); 404 editor->command(AtomicString("Paste")).execute();
583 editor->command(AtomicString("Paste")).execute(); 405 pasteboard->setSelectionMode(oldSelectionMode);
584 pasteboard->setSelectionMode(oldSelectionMode); 406 }
585 } 407 }
586 }
587 #endif 408 #endif
588 409
589 mouseCaptureLost(); 410 mouseCaptureLost();
590 main_frame()->frame()->eventHandler()->handleMouseReleaseEvent( 411 mainFrameImpl()->frame()->eventHandler()->handleMouseReleaseEvent(
591 PlatformMouseEventBuilder(main_frame()->frameview(), event)); 412 PlatformMouseEventBuilder(mainFrameImpl()->frameView(), event));
592 413
593 #if PLATFORM(WIN_OS) 414 #if PLATFORM(WIN_OS)
594 // Dispatch the contextmenu event regardless of if the click was swallowed. 415 // Dispatch the contextmenu event regardless of if the click was swallowed.
595 // On Mac/Linux, we handle it on mouse down, not up. 416 // On Mac/Linux, we handle it on mouse down, not up.
596 if (event.button == WebMouseEvent::ButtonRight) 417 if (event.button == WebMouseEvent::ButtonRight)
597 MouseContextMenu(event); 418 mouseContextMenu(event);
598 #endif 419 #endif
599 } 420 }
600 421
601 void WebViewImpl::MouseWheel(const WebMouseWheelEvent& event) { 422 void WebViewImpl::mouseWheel(const WebMouseWheelEvent& event)
602 PlatformWheelEventBuilder platform_event(main_frame()->frameview(), event); 423 {
603 main_frame()->frame()->eventHandler()->handleWheelEvent(platform_event); 424 PlatformWheelEventBuilder platformEvent(mainFrameImpl()->frameView(), event);
604 } 425 mainFrameImpl()->frame()->eventHandler()->handleWheelEvent(platformEvent);
605 426 }
606 bool WebViewImpl::KeyEvent(const WebKeyboardEvent& event) { 427
607 ASSERT((event.type == WebInputEvent::RawKeyDown) || 428 bool WebViewImpl::keyEvent(const WebKeyboardEvent& event)
608 (event.type == WebInputEvent::KeyDown) || 429 {
609 (event.type == WebInputEvent::KeyUp)); 430 ASSERT((event.type == WebInputEvent::RawKeyDown)
610 431 || (event.type == WebInputEvent::KeyDown)
611 // Please refer to the comments explaining the suppress_next_keypress_event_ 432 || (event.type == WebInputEvent::KeyUp));
612 // member. 433
613 // The suppress_next_keypress_event_ is set if the KeyDown is handled by 434 // Please refer to the comments explaining the m_suppressNextKeypressEvent
614 // Webkit. A keyDown event is typically associated with a keyPress(char) 435 // member.
615 // event and a keyUp event. We reset this flag here as this is a new keyDown 436 // The m_suppressNextKeypressEvent is set if the KeyDown is handled by
616 // event. 437 // Webkit. A keyDown event is typically associated with a keyPress(char)
617 suppress_next_keypress_event_ = false; 438 // event and a keyUp event. We reset this flag here as this is a new keyDown
618 439 // event.
619 // Give autocomplete a chance to consume the key events it is interested in. 440 m_suppressNextKeypressEvent = false;
620 if (AutocompleteHandleKeyEvent(event)) 441
621 return true; 442 // Give autocomplete a chance to consume the key events it is interested in.
622 443 if (autocompleteHandleKeyEvent(event))
623 Frame* frame = GetFocusedWebCoreFrame(); 444 return true;
624 if (!frame) 445
625 return false; 446 Frame* frame = focusedWebCoreFrame();
626 447 if (!frame)
627 EventHandler* handler = frame->eventHandler(); 448 return false;
628 if (!handler) 449
629 return KeyEventDefault(event); 450 EventHandler* handler = frame->eventHandler();
451 if (!handler)
452 return keyEventDefault(event);
630 453
631 #if PLATFORM(WIN_OS) || PLATFORM(LINUX) 454 #if PLATFORM(WIN_OS) || PLATFORM(LINUX)
632 if (((event.modifiers == 0) && (event.windowsKeyCode == VKEY_APPS)) || 455 if (((event.modifiers == 0) && (event.windowsKeyCode == VKEY_APPS))
633 ((event.modifiers == WebInputEvent::ShiftKey) && 456 || ((event.modifiers == WebInputEvent::ShiftKey) && (event.windowsKeyCode == VKEY_F10))) {
634 (event.windowsKeyCode == VKEY_F10))) { 457 sendContextMenuEvent(event);
635 SendContextMenuEvent(event); 458 return true;
636 return true; 459 }
637 }
638 #endif 460 #endif
639 461
640 // It's not clear if we should continue after detecting a capslock keypress. 462 // It's not clear if we should continue after detecting a capslock keypress.
641 // I'll err on the side of continuing, which is the pre-existing behaviour. 463 // I'll err on the side of continuing, which is the pre-existing behaviour.
642 if (event.windowsKeyCode == VKEY_CAPITAL) 464 if (event.windowsKeyCode == VKEY_CAPITAL)
643 handler->capsLockStateMayHaveChanged(); 465 handler->capsLockStateMayHaveChanged();
644 466
645 PlatformKeyboardEventBuilder evt(event); 467 PlatformKeyboardEventBuilder evt(event);
646 468
647 if (handler->keyEvent(evt)) { 469 if (handler->keyEvent(evt)) {
648 if (WebInputEvent::RawKeyDown == event.type && !evt.isSystemKey()) 470 if (WebInputEvent::RawKeyDown == event.type && !evt.isSystemKey())
649 suppress_next_keypress_event_ = true; 471 m_suppressNextKeypressEvent = true;
650 return true; 472 return true;
651 } 473 }
652 474
653 return KeyEventDefault(event); 475 return keyEventDefault(event);
654 } 476 }
655 477
656 bool WebViewImpl::AutocompleteHandleKeyEvent(const WebKeyboardEvent& event) { 478 bool WebViewImpl::autocompleteHandleKeyEvent(const WebKeyboardEvent& event)
657 if (!autocomplete_popup_showing_ || 479 {
658 // Home and End should be left to the text field to process. 480 if (!m_autocompletePopupShowing
659 event.windowsKeyCode == VKEY_HOME || 481 // Home and End should be left to the text field to process.
660 event.windowsKeyCode == VKEY_END) { 482 || event.windowsKeyCode == VKEY_HOME
661 return false; 483 || event.windowsKeyCode == VKEY_END)
662 }
663
664 // Pressing delete triggers the removal of the selected suggestion from the
665 // DB.
666 if (event.windowsKeyCode == VKEY_DELETE &&
667 autocomplete_popup_->selectedIndex() != -1) {
668 Node* node = GetFocusedNode();
669 if (!node || (node->nodeType() != WebCore::Node::ELEMENT_NODE)) {
670 ASSERT_NOT_REACHED();
671 return false; 484 return false;
672 } 485
673 WebCore::Element* element = static_cast<WebCore::Element*>(node); 486 // Pressing delete triggers the removal of the selected suggestion from the DB.
674 if (!element->hasLocalName(WebCore::HTMLNames::inputTag)) { 487 if (event.windowsKeyCode == VKEY_DELETE
675 ASSERT_NOT_REACHED(); 488 && m_autocompletePopup->selectedIndex() != -1) {
676 return false; 489 Node* node = focusedWebCoreNode();
677 } 490 if (!node || (node->nodeType() != Node::ELEMENT_NODE)) {
678 491 ASSERT_NOT_REACHED();
679 int selected_index = autocomplete_popup_->selectedIndex();
680 WebCore::HTMLInputElement* input_element =
681 static_cast<WebCore::HTMLInputElement*>(element);
682 const WebString& name = webkit_glue::StringToWebString(
683 input_element->name());
684 const WebString& value = webkit_glue::StringToWebString(
685 autocomplete_popup_client_->itemText(selected_index));
686 client_->removeAutofillSuggestions(name, value);
687 // Update the entries in the currently showing popup to reflect the
688 // deletion.
689 autocomplete_popup_client_->RemoveItemAtIndex(selected_index);
690 RefreshAutofillPopup();
691 return false;
692 }
693
694 if (!autocomplete_popup_->isInterestedInEventForKey(event.windowsKeyCode))
695 return false;
696
697 if (autocomplete_popup_->handleKeyEvent(
698 PlatformKeyboardEventBuilder(event))) {
699 // We need to ignore the next Char event after this otherwise pressing
700 // enter when selecting an item in the menu will go to the page.
701 if (WebInputEvent::RawKeyDown == event.type)
702 suppress_next_keypress_event_ = true;
703 return true;
704 }
705
706 return false;
707 }
708
709 bool WebViewImpl::CharEvent(const WebKeyboardEvent& event) {
710 ASSERT(event.type == WebInputEvent::Char);
711
712 // Please refer to the comments explaining the suppress_next_keypress_event_
713 // member.
714 // The suppress_next_keypress_event_ is set if the KeyDown is handled by
715 // Webkit. A keyDown event is typically associated with a keyPress(char)
716 // event and a keyUp event. We reset this flag here as it only applies
717 // to the current keyPress event.
718 if (suppress_next_keypress_event_) {
719 suppress_next_keypress_event_ = false;
720 return true;
721 }
722
723 Frame* frame = GetFocusedWebCoreFrame();
724 if (!frame)
725 return false;
726
727 EventHandler* handler = frame->eventHandler();
728 if (!handler)
729 return KeyEventDefault(event);
730
731 PlatformKeyboardEventBuilder evt(event);
732 if (!evt.isCharacterKey())
733 return true;
734
735 // Safari 3.1 does not pass off windows system key messages (WM_SYSCHAR) to
736 // the eventHandler::keyEvent. We mimic this behavior on all platforms since
737 // for now we are converting other platform's key events to windows key
738 // events.
739 if (evt.isSystemKey())
740 return handler->handleAccessKey(evt);
741
742 if (!handler->keyEvent(evt))
743 return KeyEventDefault(event);
744
745 return true;
746 }
747
748 /*
749 * The WebViewImpl::SendContextMenuEvent function is based on the Webkit
750 * function
751 * bool WebView::handleContextMenuEvent(WPARAM wParam, LPARAM lParam) in
752 * webkit\webkit\win\WebView.cpp. The only significant change in this
753 * function is the code to convert from a Keyboard event to the Right
754 * Mouse button up event.
755 *
756 * This function is an ugly copy/paste and should be cleaned up when the
757 * WebKitWin version is cleaned: https://bugs.webkit.org/show_bug.cgi?id=20438
758 */
759 #if PLATFORM(WIN_OS) || PLATFORM(LINUX)
760 // TODO(pinkerton): implement on non-windows
761 bool WebViewImpl::SendContextMenuEvent(const WebKeyboardEvent& event) {
762 static const int kContextMenuMargin = 1;
763 Frame* main_frame = page()->mainFrame();
764 FrameView* view = main_frame->view();
765 if (!view)
766 return false;
767
768 IntPoint coords(-1, -1);
769 #if PLATFORM(WIN_OS)
770 int right_aligned = ::GetSystemMetrics(SM_MENUDROPALIGNMENT);
771 #else
772 int right_aligned = 0;
773 #endif
774 IntPoint location;
775
776 // The context menu event was generated from the keyboard, so show the
777 // context menu by the current selection.
778 Position start = main_frame->selection()->selection().start();
779 Position end = main_frame->selection()->selection().end();
780
781 if (!start.node() || !end.node()) {
782 location =
783 IntPoint(right_aligned ? view->contentsWidth() - kContextMenuMargin
784 : kContextMenuMargin, kContextMenuMargin);
785 } else {
786 RenderObject* renderer = start.node()->renderer();
787 if (!renderer)
788 return false;
789
790 RefPtr<Range> selection = main_frame->selection()->toNormalizedRange();
791 IntRect first_rect = main_frame->firstRectForRange(selection.get());
792
793 int x = right_aligned ? first_rect.right() : first_rect.x();
794 location = IntPoint(x, first_rect.bottom());
795 }
796
797 location = view->contentsToWindow(location);
798 // FIXME: The IntSize(0, -1) is a hack to get the hit-testing to result in
799 // the selected element. Ideally we'd have the position of a context menu
800 // event be separate from its target node.
801 coords = location + IntSize(0, -1);
802
803 // The contextMenuController() holds onto the last context menu that was
804 // popped up on the page until a new one is created. We need to clear
805 // this menu before propagating the event through the DOM so that we can
806 // detect if we create a new menu for this event, since we won't create
807 // a new menu if the DOM swallows the event and the defaultEventHandler does
808 // not run.
809 page()->contextMenuController()->clearContextMenu();
810
811 Frame* focused_frame = page()->focusController()->focusedOrMainFrame();
812 focused_frame->view()->setCursor(pointerCursor());
813 WebMouseEvent mouse_event;
814 mouse_event.button = WebMouseEvent::ButtonRight;
815 mouse_event.x = coords.x();
816 mouse_event.y = coords.y();
817 mouse_event.type = WebInputEvent::MouseUp;
818
819 PlatformMouseEventBuilder platform_event(view, mouse_event);
820
821 context_menu_allowed_ = true;
822 bool handled =
823 focused_frame->eventHandler()->sendContextMenuEvent(platform_event);
824 context_menu_allowed_ = false;
825 return handled;
826 }
827 #endif
828
829 bool WebViewImpl::KeyEventDefault(const WebKeyboardEvent& event) {
830 Frame* frame = GetFocusedWebCoreFrame();
831 if (!frame)
832 return false;
833
834 switch (event.type) {
835 case WebInputEvent::Char: {
836 if (event.windowsKeyCode == VKEY_SPACE) {
837 int key_code = ((event.modifiers & WebInputEvent::ShiftKey) ?
838 VKEY_PRIOR : VKEY_NEXT);
839 return ScrollViewWithKeyboard(key_code, event.modifiers);
840 }
841 break;
842 }
843
844 case WebInputEvent::RawKeyDown: {
845 if (event.modifiers == WebInputEvent::ControlKey) {
846 switch (event.windowsKeyCode) {
847 case 'A':
848 focusedFrame()->executeCommand(WebString::fromUTF8("SelectAll"));
849 return true;
850 case VKEY_INSERT:
851 case 'C':
852 focusedFrame()->executeCommand(WebString::fromUTF8("Copy"));
853 return true;
854 // Match FF behavior in the sense that Ctrl+home/end are the only Ctrl
855 // key combinations which affect scrolling. Safari is buggy in the
856 // sense that it scrolls the page for all Ctrl+scrolling key
857 // combinations. For e.g. Ctrl+pgup/pgdn/up/down, etc.
858 case VKEY_HOME:
859 case VKEY_END:
860 break;
861 default:
862 return false; 492 return false;
863 } 493 }
864 } 494 Element* element = static_cast<Element*>(node);
865 if (!event.isSystemKey && !(event.modifiers & WebInputEvent::ShiftKey)) { 495 if (!element->hasLocalName(HTMLNames::inputTag)) {
866 return ScrollViewWithKeyboard(event.windowsKeyCode, event.modifiers); 496 ASSERT_NOT_REACHED();
867 } 497 return false;
868 break; 498 }
869 } 499
870 500 int selectedIndex = m_autocompletePopup->selectedIndex();
501 HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(element);
502 WebString name = inputElement->name();
503 WebString value = m_autocompletePopupClient->itemText(selectedIndex);
504 m_client->removeAutofillSuggestions(name, value);
505 // Update the entries in the currently showing popup to reflect the
506 // deletion.
507 m_autocompletePopupClient->removeItemAtIndex(selectedIndex);
508 refreshAutofillPopup();
509 return false;
510 }
511
512 if (!m_autocompletePopup->isInterestedInEventForKey(event.windowsKeyCode))
513 return false;
514
515 if (m_autocompletePopup->handleKeyEvent(PlatformKeyboardEventBuilder(event))) {
516 // We need to ignore the next Char event after this otherwise pressing
517 // enter when selecting an item in the menu will go to the page.
518 if (WebInputEvent::RawKeyDown == event.type)
519 m_suppressNextKeypressEvent = true;
520 return true;
521 }
522
523 return false;
524 }
525
526 bool WebViewImpl::charEvent(const WebKeyboardEvent& event)
527 {
528 ASSERT(event.type == WebInputEvent::Char);
529
530 // Please refer to the comments explaining the m_suppressNextKeypressEvent
531 // member. The m_suppressNextKeypressEvent is set if the KeyDown is
532 // handled by Webkit. A keyDown event is typically associated with a
533 // keyPress(char) event and a keyUp event. We reset this flag here as it
534 // only applies to the current keyPress event.
535 if (m_suppressNextKeypressEvent) {
536 m_suppressNextKeypressEvent = false;
537 return true;
538 }
539
540 Frame* frame = focusedWebCoreFrame();
541 if (!frame)
542 return false;
543
544 EventHandler* handler = frame->eventHandler();
545 if (!handler)
546 return keyEventDefault(event);
547
548 PlatformKeyboardEventBuilder evt(event);
549 if (!evt.isCharacterKey())
550 return true;
551
552 // Safari 3.1 does not pass off windows system key messages (WM_SYSCHAR) to
553 // the eventHandler::keyEvent. We mimic this behavior on all platforms since
554 // for now we are converting other platform's key events to windows key
555 // events.
556 if (evt.isSystemKey())
557 return handler->handleAccessKey(evt);
558
559 if (!handler->keyEvent(evt))
560 return keyEventDefault(event);
561
562 return true;
563 }
564
565 // The WebViewImpl::SendContextMenuEvent function is based on the Webkit
566 // function
567 // bool WebView::handleContextMenuEvent(WPARAM wParam, LPARAM lParam) in
568 // webkit\webkit\win\WebView.cpp. The only significant change in this
569 // function is the code to convert from a Keyboard event to the Right
570 // Mouse button up event.
571 //
572 // This function is an ugly copy/paste and should be cleaned up when the
573 // WebKitWin version is cleaned: https://bugs.webkit.org/show_bug.cgi?id=20438
574 #if PLATFORM(WIN_OS) || PLATFORM(LINUX)
575 // FIXME: implement on Mac
576 bool WebViewImpl::sendContextMenuEvent(const WebKeyboardEvent& event)
577 {
578 static const int kContextMenuMargin = 1;
579 Frame* mainFrameImpl = page()->mainFrame();
580 FrameView* view = mainFrameImpl->view();
581 if (!view)
582 return false;
583
584 IntPoint coords(-1, -1);
585 #if PLATFORM(WIN_OS)
586 int rightAligned = ::GetSystemMetrics(SM_MENUDROPALIGNMENT);
587 #else
588 int rightAligned = 0;
589 #endif
590 IntPoint location;
591
592 // The context menu event was generated from the keyboard, so show the
593 // context menu by the current selection.
594 Position start = mainFrameImpl->selection()->selection().start();
595 Position end = mainFrameImpl->selection()->selection().end();
596
597 if (!start.node() || !end.node()) {
598 location = IntPoint(
599 rightAligned ? view->contentsWidth() - kContextMenuMargin : kContextMenuMargin,
600 kContextMenuMargin);
601 } else {
602 RenderObject* renderer = start.node()->renderer();
603 if (!renderer)
604 return false;
605
606 RefPtr<Range> selection = mainFrameImpl->selection()->toNormalizedRange();
607 IntRect firstRect = mainFrameImpl->firstRectForRange(selection.get());
608
609 int x = rightAligned ? firstRect.right() : firstRect.x();
610 location = IntPoint(x, firstRect.bottom());
611 }
612
613 location = view->contentsToWindow(location);
614 // FIXME: The IntSize(0, -1) is a hack to get the hit-testing to result in
615 // the selected element. Ideally we'd have the position of a context menu
616 // event be separate from its target node.
617 coords = location + IntSize(0, -1);
618
619 // The contextMenuController() holds onto the last context menu that was
620 // popped up on the page until a new one is created. We need to clear
621 // this menu before propagating the event through the DOM so that we can
622 // detect if we create a new menu for this event, since we won't create
623 // a new menu if the DOM swallows the event and the defaultEventHandler does
624 // not run.
625 page()->contextMenuController()->clearContextMenu();
626
627 Frame* focusedFrame = page()->focusController()->focusedOrMainFrame();
628 focusedFrame->view()->setCursor(pointerCursor());
629 WebMouseEvent mouseEvent;
630 mouseEvent.button = WebMouseEvent::ButtonRight;
631 mouseEvent.x = coords.x();
632 mouseEvent.y = coords.y();
633 mouseEvent.type = WebInputEvent::MouseUp;
634
635 PlatformMouseEventBuilder platformEvent(view, mouseEvent);
636
637 m_contextMenuAllowed = true;
638 bool handled = focusedFrame->eventHandler()->sendContextMenuEvent(platformEvent);
639 m_contextMenuAllowed = false;
640 return handled;
641 }
642 #endif
643
644 bool WebViewImpl::keyEventDefault(const WebKeyboardEvent& event)
645 {
646 Frame* frame = focusedWebCoreFrame();
647 if (!frame)
648 return false;
649
650 switch (event.type) {
651 case WebInputEvent::Char:
652 if (event.windowsKeyCode == VKEY_SPACE) {
653 int keyCode = ((event.modifiers & WebInputEvent::ShiftKey) ? VKEY_PRIOR : VKEY_NEXT);
654 return scrollViewWithKeyboard(keyCode, event.modifiers);
655 }
656 break;
657 case WebInputEvent::RawKeyDown:
658 if (event.modifiers == WebInputEvent::ControlKey) {
659 switch (event.windowsKeyCode) {
660 case 'A':
661 focusedFrame()->executeCommand(WebString::fromUTF8("SelectAll"));
662 return true;
663 case VKEY_INSERT:
664 case 'C':
665 focusedFrame()->executeCommand(WebString::fromUTF8("Copy"));
666 return true;
667 // Match FF behavior in the sense that Ctrl+home/end are the only Ctrl
668 // key combinations which affect scrolling. Safari is buggy in the
669 // sense that it scrolls the page for all Ctrl+scrolling key
670 // combinations. For e.g. Ctrl+pgup/pgdn/up/down, etc.
671 case VKEY_HOME:
672 case VKEY_END:
673 break;
674 default:
675 return false;
676 }
677 }
678 if (!event.isSystemKey && !(event.modifiers & WebInputEvent::ShiftKey))
679 return scrollViewWithKeyboard(event.windowsKeyCode, event.modifiers);
680 break;
871 default: 681 default:
872 break; 682 break;
873 } 683 }
874 return false; 684 return false;
875 } 685 }
876 686
877 bool WebViewImpl::ScrollViewWithKeyboard(int key_code, int modifiers) { 687 bool WebViewImpl::scrollViewWithKeyboard(int keyCode, int modifiers)
878 ScrollDirection scroll_direction; 688 {
879 ScrollGranularity scroll_granularity; 689 ScrollDirection scrollDirection;
880 690 ScrollGranularity scrollGranularity;
881 switch (key_code) { 691
692 switch (keyCode) {
882 case VKEY_LEFT: 693 case VKEY_LEFT:
883 scroll_direction = ScrollLeft; 694 scrollDirection = ScrollLeft;
884 scroll_granularity = ScrollByLine; 695 scrollGranularity = ScrollByLine;
885 break; 696 break;
886 case VKEY_RIGHT: 697 case VKEY_RIGHT:
887 scroll_direction = ScrollRight; 698 scrollDirection = ScrollRight;
888 scroll_granularity = ScrollByLine; 699 scrollGranularity = ScrollByLine;
889 break; 700 break;
890 case VKEY_UP: 701 case VKEY_UP:
891 scroll_direction = ScrollUp; 702 scrollDirection = ScrollUp;
892 scroll_granularity = ScrollByLine; 703 scrollGranularity = ScrollByLine;
893 break; 704 break;
894 case VKEY_DOWN: 705 case VKEY_DOWN:
895 scroll_direction = ScrollDown; 706 scrollDirection = ScrollDown;
896 scroll_granularity = ScrollByLine; 707 scrollGranularity = ScrollByLine;
897 break; 708 break;
898 case VKEY_HOME: 709 case VKEY_HOME:
899 scroll_direction = ScrollUp; 710 scrollDirection = ScrollUp;
900 scroll_granularity = ScrollByDocument; 711 scrollGranularity = ScrollByDocument;
901 break; 712 break;
902 case VKEY_END: 713 case VKEY_END:
903 scroll_direction = ScrollDown; 714 scrollDirection = ScrollDown;
904 scroll_granularity = ScrollByDocument; 715 scrollGranularity = ScrollByDocument;
905 break; 716 break;
906 case VKEY_PRIOR: // page up 717 case VKEY_PRIOR: // page up
907 scroll_direction = ScrollUp; 718 scrollDirection = ScrollUp;
908 scroll_granularity = ScrollByPage; 719 scrollGranularity = ScrollByPage;
909 break; 720 break;
910 case VKEY_NEXT: // page down 721 case VKEY_NEXT: // page down
911 scroll_direction = ScrollDown; 722 scrollDirection = ScrollDown;
912 scroll_granularity = ScrollByPage; 723 scrollGranularity = ScrollByPage;
913 break; 724 break;
914 default: 725 default:
915 return false; 726 return false;
916 } 727 }
917 728
918 return PropagateScroll(scroll_direction, scroll_granularity); 729 return propagateScroll(scrollDirection, scrollGranularity);
919 } 730 }
920 731
921 bool WebViewImpl::PropagateScroll( 732 bool WebViewImpl::propagateScroll(ScrollDirection scrollDirection,
922 WebCore::ScrollDirection scroll_direction, 733 ScrollGranularity scrollGranularity)
923 WebCore::ScrollGranularity scroll_granularity) { 734 {
924 735 Frame* frame = focusedWebCoreFrame();
925 Frame* frame = GetFocusedWebCoreFrame(); 736 if (!frame)
926 if (!frame) 737 return false;
927 return false; 738
928 739 bool scrollHandled =
929 bool scroll_handled = 740 frame->eventHandler()->scrollOverflow(scrollDirection,
930 frame->eventHandler()->scrollOverflow(scroll_direction, 741 scrollGranularity);
931 scroll_granularity); 742 Frame* currentFrame = frame;
932 Frame* current_frame = frame; 743 while (!scrollHandled && currentFrame) {
933 while (!scroll_handled && current_frame) { 744 scrollHandled = currentFrame->view()->scroll(scrollDirection,
934 scroll_handled = current_frame->view()->scroll(scroll_direction, 745 scrollGranularity);
935 scroll_granularity); 746 currentFrame = currentFrame->tree()->parent();
936 current_frame = current_frame->tree()->parent(); 747 }
937 } 748 return scrollHandled;
938 return scroll_handled; 749 }
939 } 750
940 751 Frame* WebViewImpl::focusedWebCoreFrame()
941 Frame* WebViewImpl::GetFocusedWebCoreFrame() { 752 {
942 return page_.get() ? page_->focusController()->focusedOrMainFrame() : NULL; 753 return m_page.get() ? m_page->focusController()->focusedOrMainFrame() : 0;
943 } 754 }
944 755
945 // static 756 WebViewImpl* WebViewImpl::fromPage(Page* page)
946 WebViewImpl* WebViewImpl::FromPage(WebCore::Page* page) { 757 {
947 if (!page) 758 if (!page)
948 return NULL; 759 return 0;
949 760
950 return static_cast<ChromeClientImpl*>(page->chrome()->client())->webview(); 761 return static_cast<ChromeClientImpl*>(page->chrome()->client())->webview();
951 } 762 }
952 763
953 // WebWidget ------------------------------------------------------------------ 764 // WebWidget ------------------------------------------------------------------
954 765
955 void WebViewImpl::close() { 766 void WebViewImpl::close()
956 RefPtr<WebFrameImpl> main_frame; 767 {
957 768 RefPtr<WebFrameImpl> mainFrameImpl;
958 if (page_.get()) { 769
959 // Initiate shutdown for the entire frameset. This will cause a lot of 770 if (m_page.get()) {
960 // notifications to be sent. 771 // Initiate shutdown for the entire frameset. This will cause a lot of
961 if (page_->mainFrame()) { 772 // notifications to be sent.
962 main_frame = WebFrameImpl::FromFrame(page_->mainFrame()); 773 if (m_page->mainFrame()) {
963 page_->mainFrame()->loader()->frameDetached(); 774 mainFrameImpl = WebFrameImpl::fromFrame(m_page->mainFrame());
964 } 775 m_page->mainFrame()->loader()->frameDetached();
965 page_.clear(); 776 }
966 } 777 m_page.clear();
967 778 }
968 // Should happen after page_.reset(). 779
969 if (devtools_agent_.get()) 780 // Should happen after m_page.reset().
970 devtools_agent_.clear(); 781 if (m_devToolsAgent.get())
971 782 m_devToolsAgent.clear();
972 // We drop the client after the page has been destroyed to support the 783
973 // WebFrameClient::didDestroyScriptContext method. 784 // We drop the client after the page has been destroyed to support the
974 if (main_frame) 785 // WebFrameClient::didDestroyScriptContext method.
975 main_frame->drop_client(); 786 if (mainFrameImpl)
976 787 mainFrameImpl->dropClient();
977 // Reset the delegate to prevent notifications being sent as we're being 788
978 // deleted. 789 // Reset the delegate to prevent notifications being sent as we're being
979 client_ = NULL; 790 // deleted.
980 791 m_client = 0;
981 deref(); // Balances ref() acquired in WebView::create 792
982 } 793 deref(); // Balances ref() acquired in WebView::create
983 794 }
984 void WebViewImpl::resize(const WebSize& new_size) { 795
985 if (size_ == new_size) 796 void WebViewImpl::resize(const WebSize& newSize)
986 return; 797 {
987 size_ = new_size; 798 if (m_size == newSize)
988 799 return;
989 if (main_frame()->frameview()) { 800 m_size = newSize;
990 main_frame()->frameview()->resize(size_.width, size_.height); 801
991 main_frame()->frame()->eventHandler()->sendResizeEvent(); 802 if (mainFrameImpl()->frameView()) {
992 } 803 mainFrameImpl()->frameView()->resize(m_size.width, m_size.height);
993 804 mainFrameImpl()->frame()->eventHandler()->sendResizeEvent();
994 if (client_) { 805 }
995 WebRect damaged_rect(0, 0, size_.width, size_.height); 806
996 client_->didInvalidateRect(damaged_rect); 807 if (m_client) {
997 } 808 WebRect damagedRect(0, 0, m_size.width, m_size.height);
998 } 809 m_client->didInvalidateRect(damagedRect);
999 810 }
1000 void WebViewImpl::layout() { 811 }
1001 WebFrameImpl* webframe = main_frame(); 812
1002 if (webframe) { 813 void WebViewImpl::layout()
1003 // In order for our child HWNDs (NativeWindowWidgets) to update properly, 814 {
1004 // they need to be told that we are updating the screen. The problem is 815 WebFrameImpl* webframe = mainFrameImpl();
1005 // that the native widgets need to recalculate their clip region and not 816 if (webframe) {
1006 // overlap any of our non-native widgets. To force the resizing, call 817 // In order for our child HWNDs (NativeWindowWidgets) to update properly,
1007 // setFrameRect(). This will be a quick operation for most frames, but 818 // they need to be told that we are updating the screen. The problem is
1008 // the NativeWindowWidgets will update a proper clipping region. 819 // that the native widgets need to recalculate their clip region and not
1009 FrameView* view = webframe->frameview(); 820 // overlap any of our non-native widgets. To force the resizing, call
1010 if (view) 821 // setFrameRect(). This will be a quick operation for most frames, but
1011 view->setFrameRect(view->frameRect()); 822 // the NativeWindowWidgets will update a proper clipping region.
1012 823 FrameView* view = webframe->frameView();
1013 // setFrameRect may have the side-effect of causing existing page 824 if (view)
1014 // layout to be invalidated, so layout needs to be called last. 825 view->setFrameRect(view->frameRect());
1015 826
1016 webframe->Layout(); 827 // setFrameRect may have the side-effect of causing existing page
1017 } 828 // layout to be invalidated, so layout needs to be called last.
1018 } 829
1019 830 webframe->layout();
1020 void WebViewImpl::paint(WebCanvas* canvas, const WebRect& rect) { 831 }
1021 WebFrameImpl* webframe = main_frame(); 832 }
1022 if (webframe) 833
1023 webframe->Paint(canvas, rect); 834 void WebViewImpl::paint(WebCanvas* canvas, const WebRect& rect)
1024 } 835 {
1025 836 WebFrameImpl* webframe = mainFrameImpl();
1026 // TODO(eseidel): g_current_input_event should be removed once 837 if (webframe)
1027 // ChromeClient:show() can get the current-event information from WebCore. 838 webframe->paint(canvas, rect);
1028 /* static */ 839 }
1029 const WebInputEvent* WebViewImpl::g_current_input_event = NULL; 840
1030 841 // FIXME: m_currentInputEvent should be removed once ChromeClient::show() can
1031 bool WebViewImpl::handleInputEvent(const WebInputEvent& input_event) { 842 // get the current-event information from WebCore.
1032 // If we've started a drag and drop operation, ignore input events until 843 const WebInputEvent* WebViewImpl::m_currentInputEvent = 0;
1033 // we're done. 844
1034 if (doing_drag_and_drop_) 845 bool WebViewImpl::handleInputEvent(const WebInputEvent& inputEvent)
1035 return true; 846 {
1036 847 // If we've started a drag and drop operation, ignore input events until
1037 if (ignore_input_events_) 848 // we're done.
1038 return true; 849 if (m_doingDragAndDrop)
1039 850 return true;
1040 // TODO(eseidel): Remove g_current_input_event. 851
1041 // This only exists to allow ChromeClient::show() to know which mouse button 852 if (m_ignoreInputEvents)
1042 // triggered a window.open event. 853 return true;
1043 // Safari must perform a similar hack, ours is in our WebKit glue layer 854
1044 // theirs is in the application. This should go when WebCore can be fixed 855 // FIXME: Remove m_currentInputEvent.
1045 // to pass more event information to ChromeClient::show() 856 // This only exists to allow ChromeClient::show() to know which mouse button
1046 g_current_input_event = &input_event; 857 // triggered a window.open event.
1047 858 // Safari must perform a similar hack, ours is in our WebKit glue layer
1048 bool handled = true; 859 // theirs is in the application. This should go when WebCore can be fixed
1049 860 // to pass more event information to ChromeClient::show()
1050 // TODO(jcampan): WebKit seems to always return false on mouse events 861 m_currentInputEvent = &inputEvent;
1051 // processing methods. For now we'll assume it has processed them (as we are 862
1052 // only interested in whether keyboard events are processed). 863 bool handled = true;
1053 switch (input_event.type) { 864
865 // FIXME: WebKit seems to always return false on mouse events processing
866 // methods. For now we'll assume it has processed them (as we are only
867 // interested in whether keyboard events are processed).
868 switch (inputEvent.type) {
1054 case WebInputEvent::MouseMove: 869 case WebInputEvent::MouseMove:
1055 MouseMove(*static_cast<const WebMouseEvent*>(&input_event)); 870 mouseMove(*static_cast<const WebMouseEvent*>(&inputEvent));
1056 break; 871 break;
1057 872
1058 case WebInputEvent::MouseLeave: 873 case WebInputEvent::MouseLeave:
1059 MouseLeave(*static_cast<const WebMouseEvent*>(&input_event)); 874 mouseLeave(*static_cast<const WebMouseEvent*>(&inputEvent));
1060 break; 875 break;
1061 876
1062 case WebInputEvent::MouseWheel: 877 case WebInputEvent::MouseWheel:
1063 MouseWheel(*static_cast<const WebMouseWheelEvent*>(&input_event)); 878 mouseWheel(*static_cast<const WebMouseWheelEvent*>(&inputEvent));
1064 break; 879 break;
1065 880
1066 case WebInputEvent::MouseDown: 881 case WebInputEvent::MouseDown:
1067 MouseDown(*static_cast<const WebMouseEvent*>(&input_event)); 882 mouseDown(*static_cast<const WebMouseEvent*>(&inputEvent));
1068 break; 883 break;
1069 884
1070 case WebInputEvent::MouseUp: 885 case WebInputEvent::MouseUp:
1071 MouseUp(*static_cast<const WebMouseEvent*>(&input_event)); 886 mouseUp(*static_cast<const WebMouseEvent*>(&inputEvent));
1072 break; 887 break;
1073 888
1074 case WebInputEvent::RawKeyDown: 889 case WebInputEvent::RawKeyDown:
1075 case WebInputEvent::KeyDown: 890 case WebInputEvent::KeyDown:
1076 case WebInputEvent::KeyUp: 891 case WebInputEvent::KeyUp:
1077 handled = KeyEvent(*static_cast<const WebKeyboardEvent*>(&input_event)); 892 handled = keyEvent(*static_cast<const WebKeyboardEvent*>(&inputEvent));
1078 break; 893 break;
1079 894
1080 case WebInputEvent::Char: 895 case WebInputEvent::Char:
1081 handled = CharEvent(*static_cast<const WebKeyboardEvent*>(&input_event)); 896 handled = charEvent(*static_cast<const WebKeyboardEvent*>(&inputEvent));
1082 break; 897 break;
898
1083 default: 899 default:
1084 handled = false; 900 handled = false;
1085 } 901 }
1086 902
1087 g_current_input_event = NULL; 903 m_currentInputEvent = 0;
1088 904
1089 return handled; 905 return handled;
1090 } 906 }
1091 907
1092 void WebViewImpl::mouseCaptureLost() { 908 void WebViewImpl::mouseCaptureLost()
1093 } 909 {
1094 910 }
1095 void WebViewImpl::setFocus(bool enable) { 911
1096 page_->focusController()->setFocused(enable); 912 void WebViewImpl::setFocus(bool enable)
1097 if (enable) { 913 {
1098 // Note that we don't call setActive() when disabled as this cause extra 914 m_page->focusController()->setFocused(enable);
1099 // focus/blur events to be dispatched. 915 if (enable) {
1100 page_->focusController()->setActive(true); 916 // Note that we don't call setActive() when disabled as this cause extra
1101 ime_accept_events_ = true; 917 // focus/blur events to be dispatched.
1102 } else { 918 m_page->focusController()->setActive(true);
1103 HideAutoCompletePopup(); 919 m_imeAcceptEvents = true;
1104 920 } else {
1105 // Clear focus on the currently focused frame if any. 921 hideAutoCompletePopup();
1106 if (!page_.get()) 922
923 // Clear focus on the currently focused frame if any.
924 if (!m_page.get())
925 return;
926
927 Frame* frame = m_page->mainFrame();
928 if (!frame)
929 return;
930
931 RefPtr<Frame> focusedFrame = m_page->focusController()->focusedFrame();
932 if (focusedFrame.get()) {
933 // Finish an ongoing composition to delete the composition node.
934 Editor* editor = focusedFrame->editor();
935 if (editor && editor->hasComposition())
936 editor->confirmComposition();
937 m_imeAcceptEvents = false;
938 }
939 }
940 }
941
942 bool WebViewImpl::handleCompositionEvent(WebCompositionCommand command,
943 int cursorPosition,
944 int targetStart,
945 int targetEnd,
946 const WebString& imeString)
947 {
948 Frame* focused = focusedWebCoreFrame();
949 if (!focused || !m_imeAcceptEvents)
950 return false;
951 Editor* editor = focused->editor();
952 if (!editor)
953 return false;
954 if (!editor->canEdit()) {
955 // The input focus has been moved to another WebWidget object.
956 // We should use this |editor| object only to complete the ongoing
957 // composition.
958 if (!editor->hasComposition())
959 return false;
960 }
961
962 // We should verify the parent node of this IME composition node are
963 // editable because JavaScript may delete a parent node of the composition
964 // node. In this case, WebKit crashes while deleting texts from the parent
965 // node, which doesn't exist any longer.
966 PassRefPtr<Range> range = editor->compositionRange();
967 if (range) {
968 const Node* node = range->startPosition().node();
969 if (!node || !node->isContentEditable())
970 return false;
971 }
972
973 if (command == WebCompositionCommandDiscard) {
974 // A browser process sent an IPC message which does not contain a valid
975 // string, which means an ongoing composition has been canceled.
976 // If the ongoing composition has been canceled, replace the ongoing
977 // composition string with an empty string and complete it.
978 String emptyString;
979 Vector<CompositionUnderline> emptyUnderlines;
980 editor->setComposition(emptyString, emptyUnderlines, 0, 0);
981 } else {
982 // A browser process sent an IPC message which contains a string to be
983 // displayed in this Editor object.
984 // To display the given string, set the given string to the
985 // m_compositionNode member of this Editor object and display it.
986 if (targetStart < 0)
987 targetStart = 0;
988 if (targetEnd < 0)
989 targetEnd = static_cast<int>(imeString.length());
990 String compositionString(imeString);
991 // Create custom underlines.
992 // To emphasize the selection, the selected region uses a solid black
993 // for its underline while other regions uses a pale gray for theirs.
994 Vector<CompositionUnderline> underlines(3);
995 underlines[0].startOffset = 0;
996 underlines[0].endOffset = targetStart;
997 underlines[0].thick = true;
998 underlines[0].color.setRGB(0xd3, 0xd3, 0xd3);
999 underlines[1].startOffset = targetStart;
1000 underlines[1].endOffset = targetEnd;
1001 underlines[1].thick = true;
1002 underlines[1].color.setRGB(0x00, 0x00, 0x00);
1003 underlines[2].startOffset = targetEnd;
1004 underlines[2].endOffset = static_cast<int>(imeString.length());
1005 underlines[2].thick = true;
1006 underlines[2].color.setRGB(0xd3, 0xd3, 0xd3);
1007 // When we use custom underlines, WebKit ("InlineTextBox.cpp" Line 282)
1008 // prevents from writing a text in between 'selectionStart' and
1009 // 'selectionEnd' somehow.
1010 // Therefore, we use the 'cursorPosition' for these arguments so that
1011 // there are not any characters in the above region.
1012 editor->setComposition(compositionString, underlines,
1013 cursorPosition, cursorPosition);
1014 // The given string is a result string, which means the ongoing
1015 // composition has been completed. I have to call the
1016 // Editor::confirmCompletion() and complete this composition.
1017 if (command == WebCompositionCommandConfirm)
1018 editor->confirmComposition();
1019 }
1020
1021 return editor->hasComposition();
1022 }
1023
1024 bool WebViewImpl::queryCompositionStatus(bool* enableIME, WebRect* caretRect)
1025 {
1026 // Store whether the selected node needs IME and the caret rectangle.
1027 // This process consists of the following four steps:
1028 // 1. Retrieve the selection controller of the focused frame;
1029 // 2. Retrieve the caret rectangle from the controller;
1030 // 3. Convert the rectangle, which is relative to the parent view, to the
1031 // one relative to the client window, and;
1032 // 4. Store the converted rectangle.
1033 const Frame* focused = focusedWebCoreFrame();
1034 if (!focused)
1035 return false;
1036
1037 const Editor* editor = focused->editor();
1038 if (!editor || !editor->canEdit())
1039 return false;
1040
1041 SelectionController* controller = focused->selection();
1042 if (!controller)
1043 return false;
1044
1045 const Node* node = controller->start().node();
1046 if (!node)
1047 return false;
1048
1049 *enableIME = node->shouldUseInputMethod() && !controller->isInPasswordField();
1050 const FrameView* view = node->document()->view();
1051 if (!view)
1052 return false;
1053
1054 *caretRect = view->contentsToWindow(controller->absoluteCaretBounds());
1055 return true;
1056 }
1057
1058 void WebViewImpl::setTextDirection(WebTextDirection direction)
1059 {
1060 // The Editor::setBaseWritingDirection() function checks if we can change
1061 // the text direction of the selected node and updates its DOM "dir"
1062 // attribute and its CSS "direction" property.
1063 // So, we just call the function as Safari does.
1064 const Frame* focused = focusedWebCoreFrame();
1065 if (!focused)
1066 return;
1067
1068 Editor* editor = focused->editor();
1069 if (!editor || !editor->canEdit())
1070 return;
1071
1072 switch (direction) {
1073 case WebTextDirectionDefault:
1074 editor->setBaseWritingDirection(NaturalWritingDirection);
1075 break;
1076
1077 case WebTextDirectionLeftToRight:
1078 editor->setBaseWritingDirection(LeftToRightWritingDirection);
1079 break;
1080
1081 case WebTextDirectionRightToLeft:
1082 editor->setBaseWritingDirection(RightToLeftWritingDirection);
1083 break;
1084
1085 default:
1086 notImplemented();
1087 break;
1088 }
1089 }
1090
1091 // WebView --------------------------------------------------------------------
1092
1093 WebSettings* WebViewImpl::settings()
1094 {
1095 if (!m_webSettings.get())
1096 m_webSettings.set(new WebSettingsImpl(m_page->settings()));
1097 ASSERT(m_webSettings.get());
1098 return m_webSettings.get();
1099 }
1100
1101 WebString WebViewImpl::pageEncoding() const
1102 {
1103 if (!m_page.get())
1104 return WebString();
1105
1106 return m_page->mainFrame()->loader()->encoding();
1107 }
1108
1109 void WebViewImpl::setPageEncoding(const WebString& encodingName)
1110 {
1111 if (!m_page.get())
1112 return;
1113
1114 // Only change override encoding, don't change default encoding.
1115 // Note that the new encoding must be 0 if it isn't supposed to be set.
1116 String newEncodingName;
1117 if (!encodingName.isEmpty())
1118 newEncodingName = encodingName;
1119 m_page->mainFrame()->loader()->reloadWithOverrideEncoding(newEncodingName);
1120 }
1121
1122 bool WebViewImpl::dispatchBeforeUnloadEvent()
1123 {
1124 // FIXME: This should really cause a recursive depth-first walk of all
1125 // frames in the tree, calling each frame's onbeforeunload. At the moment,
1126 // we're consistent with Safari 3.1, not IE/FF.
1127 Frame* frame = m_page->focusController()->focusedOrMainFrame();
1128 if (!frame)
1129 return true;
1130
1131 return frame->shouldClose();
1132 }
1133
1134 void WebViewImpl::dispatchUnloadEvent()
1135 {
1136 // Run unload handlers.
1137 m_page->mainFrame()->loader()->closeURL();
1138 }
1139
1140 WebFrame* WebViewImpl::mainFrame()
1141 {
1142 return mainFrameImpl();
1143 }
1144
1145 WebFrame* WebViewImpl::findFrameByName(
1146 const WebString& name, WebFrame* relativeToFrame)
1147 {
1148 if (!relativeToFrame)
1149 relativeToFrame = mainFrame();
1150 Frame* frame = static_cast<WebFrameImpl*>(relativeToFrame)->frame();
1151 frame = frame->tree()->find(name);
1152 return WebFrameImpl::fromFrame(frame);
1153 }
1154
1155 WebFrame* WebViewImpl::focusedFrame()
1156 {
1157 return WebFrameImpl::fromFrame(focusedWebCoreFrame());
1158 }
1159
1160 void WebViewImpl::setFocusedFrame(WebFrame* frame)
1161 {
1162 if (!frame) {
1163 // Clears the focused frame if any.
1164 Frame* frame = focusedWebCoreFrame();
1165 if (frame)
1166 frame->selection()->setFocused(false);
1167 return;
1168 }
1169 WebFrameImpl* frameImpl = static_cast<WebFrameImpl*>(frame);
1170 Frame* webcoreFrame = frameImpl->frame();
1171 webcoreFrame->page()->focusController()->setFocusedFrame(webcoreFrame);
1172 }
1173
1174 void WebViewImpl::setInitialFocus(bool reverse)
1175 {
1176 if (!m_page.get())
1177 return;
1178
1179 // Since we don't have a keyboard event, we'll create one.
1180 WebKeyboardEvent keyboardEvent;
1181 keyboardEvent.type = WebInputEvent::RawKeyDown;
1182 if (reverse)
1183 keyboardEvent.modifiers = WebInputEvent::ShiftKey;
1184
1185 // VK_TAB which is only defined on Windows.
1186 keyboardEvent.windowsKeyCode = 0x09;
1187 PlatformKeyboardEventBuilder platformEvent(keyboardEvent);
1188 RefPtr<KeyboardEvent> webkitEvent = KeyboardEvent::create(platformEvent, 0);
1189 page()->focusController()->setInitialFocus(
1190 reverse ? FocusDirectionBackward : FocusDirectionForward,
1191 webkitEvent.get());
1192 }
1193
1194 void WebViewImpl::clearFocusedNode()
1195 {
1196 if (!m_page.get())
1197 return;
1198
1199 RefPtr<Frame> frame = m_page->mainFrame();
1200 if (!frame.get())
1201 return;
1202
1203 RefPtr<Document> document = frame->document();
1204 if (!document.get())
1205 return;
1206
1207 RefPtr<Node> oldFocusedNode = document->focusedNode();
1208
1209 // Clear the focused node.
1210 document->setFocusedNode(0);
1211
1212 if (!oldFocusedNode.get())
1213 return;
1214
1215 // If a text field has focus, we need to make sure the selection controller
1216 // knows to remove selection from it. Otherwise, the text field is still
1217 // processing keyboard events even though focus has been moved to the page and
1218 // keystrokes get eaten as a result.
1219 if (oldFocusedNode->hasTagName(HTMLNames::textareaTag)
1220 || (oldFocusedNode->hasTagName(HTMLNames::inputTag)
1221 && static_cast<HTMLInputElement*>(oldFocusedNode.get())->isTextField())) {
1222 // Clear the selection.
1223 SelectionController* selection = frame->selection();
1224 selection->clear();
1225 }
1226 }
1227
1228 void WebViewImpl::zoomIn(bool textOnly)
1229 {
1230 Frame* frame = mainFrameImpl()->frame();
1231 double multiplier = std::min(std::pow(textSizeMultiplierRatio, m_zoomLevel + 1),
1232 maxTextSizeMultiplier);
1233 float zoomFactor = static_cast<float>(multiplier);
1234 if (zoomFactor != frame->zoomFactor()) {
1235 ++m_zoomLevel;
1236 frame->setZoomFactor(zoomFactor, textOnly);
1237 }
1238 }
1239
1240 void WebViewImpl::zoomOut(bool textOnly)
1241 {
1242 Frame* frame = mainFrameImpl()->frame();
1243 double multiplier = std::max(std::pow(textSizeMultiplierRatio, m_zoomLevel - 1),
1244 minTextSizeMultiplier);
1245 float zoomFactor = static_cast<float>(multiplier);
1246 if (zoomFactor != frame->zoomFactor()) {
1247 --m_zoomLevel;
1248 frame->setZoomFactor(zoomFactor, textOnly);
1249 }
1250 }
1251
1252 void WebViewImpl::zoomDefault()
1253 {
1254 // We don't change the zoom mode (text only vs. full page) here. We just want
1255 // to reset whatever is already set.
1256 m_zoomLevel = 0;
1257 mainFrameImpl()->frame()->setZoomFactor(
1258 1.0f, mainFrameImpl()->frame()->isZoomFactorTextOnly());
1259 }
1260
1261 void WebViewImpl::performMediaPlayerAction(const WebMediaPlayerAction& action,
1262 const WebPoint& location)
1263 {
1264 HitTestResult result =
1265 hitTestResultForWindowPos(location);
1266 RefPtr<Node> node = result.innerNonSharedNode();
1267 if (!node->hasTagName(HTMLNames::videoTag) && !node->hasTagName(HTMLNames::audioTag))
1107 return; 1268 return;
1108 1269
1109 Frame* frame = page_->mainFrame(); 1270 RefPtr<HTMLMediaElement> mediaElement =
1110 if (!frame) 1271 static_pointer_cast<HTMLMediaElement>(node);
1111 return; 1272 switch (action.type) {
1112 1273 case WebMediaPlayerAction::Play:
1113 RefPtr<Frame> focused_frame = page_->focusController()->focusedFrame(); 1274 if (action.enable)
1114 if (focused_frame.get()) { 1275 mediaElement->play();
1115 // Finish an ongoing composition to delete the composition node. 1276 else
1116 Editor* editor = focused_frame->editor(); 1277 mediaElement->pause();
1117 if (editor && editor->hasComposition()) 1278 break;
1118 editor->confirmComposition(); 1279 case WebMediaPlayerAction::Mute:
1119 ime_accept_events_ = false; 1280 mediaElement->setMuted(action.enable);
1120 } 1281 break;
1121 } 1282 case WebMediaPlayerAction::Loop:
1122 } 1283 mediaElement->setLoop(action.enable);
1123 1284 break;
1124 bool WebViewImpl::handleCompositionEvent(WebCompositionCommand command,
1125 int cursor_position,
1126 int target_start,
1127 int target_end,
1128 const WebString& ime_string) {
1129 Frame* focused = GetFocusedWebCoreFrame();
1130 if (!focused || !ime_accept_events_) {
1131 return false;
1132 }
1133 Editor* editor = focused->editor();
1134 if (!editor)
1135 return false;
1136 if (!editor->canEdit()) {
1137 // The input focus has been moved to another WebWidget object.
1138 // We should use this |editor| object only to complete the ongoing
1139 // composition.
1140 if (!editor->hasComposition())
1141 return false;
1142 }
1143
1144 // We should verify the parent node of this IME composition node are
1145 // editable because JavaScript may delete a parent node of the composition
1146 // node. In this case, WebKit crashes while deleting texts from the parent
1147 // node, which doesn't exist any longer.
1148 PassRefPtr<Range> range = editor->compositionRange();
1149 if (range) {
1150 const Node* node = range->startPosition().node();
1151 if (!node || !node->isContentEditable())
1152 return false;
1153 }
1154
1155 if (command == WebCompositionCommandDiscard) {
1156 // A browser process sent an IPC message which does not contain a valid
1157 // string, which means an ongoing composition has been canceled.
1158 // If the ongoing composition has been canceled, replace the ongoing
1159 // composition string with an empty string and complete it.
1160 WebCore::String empty_string;
1161 WTF::Vector<WebCore::CompositionUnderline> empty_underlines;
1162 editor->setComposition(empty_string, empty_underlines, 0, 0);
1163 } else {
1164 // A browser process sent an IPC message which contains a string to be
1165 // displayed in this Editor object.
1166 // To display the given string, set the given string to the
1167 // m_compositionNode member of this Editor object and display it.
1168 if (target_start < 0)
1169 target_start = 0;
1170 if (target_end < 0)
1171 target_end = static_cast<int>(ime_string.length());
1172 WebCore::String composition_string(
1173 webkit_glue::WebStringToString(ime_string));
1174 // Create custom underlines.
1175 // To emphasize the selection, the selected region uses a solid black
1176 // for its underline while other regions uses a pale gray for theirs.
1177 WTF::Vector<WebCore::CompositionUnderline> underlines(3);
1178 underlines[0].startOffset = 0;
1179 underlines[0].endOffset = target_start;
1180 underlines[0].thick = true;
1181 underlines[0].color.setRGB(0xd3, 0xd3, 0xd3);
1182 underlines[1].startOffset = target_start;
1183 underlines[1].endOffset = target_end;
1184 underlines[1].thick = true;
1185 underlines[1].color.setRGB(0x00, 0x00, 0x00);
1186 underlines[2].startOffset = target_end;
1187 underlines[2].endOffset = static_cast<int>(ime_string.length());
1188 underlines[2].thick = true;
1189 underlines[2].color.setRGB(0xd3, 0xd3, 0xd3);
1190 // When we use custom underlines, WebKit ("InlineTextBox.cpp" Line 282)
1191 // prevents from writing a text in between 'selectionStart' and
1192 // 'selectionEnd' somehow.
1193 // Therefore, we use the 'cursor_position' for these arguments so that
1194 // there are not any characters in the above region.
1195 editor->setComposition(composition_string, underlines,
1196 cursor_position, cursor_position);
1197 // The given string is a result string, which means the ongoing
1198 // composition has been completed. I have to call the
1199 // Editor::confirmCompletion() and complete this composition.
1200 if (command == WebCompositionCommandConfirm)
1201 editor->confirmComposition();
1202 }
1203
1204 return editor->hasComposition();
1205 }
1206
1207 bool WebViewImpl::queryCompositionStatus(bool* enable_ime,
1208 WebRect* caret_rect) {
1209 // Store whether the selected node needs IME and the caret rectangle.
1210 // This process consists of the following four steps:
1211 // 1. Retrieve the selection controller of the focused frame;
1212 // 2. Retrieve the caret rectangle from the controller;
1213 // 3. Convert the rectangle, which is relative to the parent view, to the
1214 // one relative to the client window, and;
1215 // 4. Store the converted rectangle.
1216 const Frame* focused = GetFocusedWebCoreFrame();
1217 if (!focused)
1218 return false;
1219
1220 const Editor* editor = focused->editor();
1221 if (!editor || !editor->canEdit())
1222 return false;
1223
1224 SelectionController* controller = focused->selection();
1225 if (!controller)
1226 return false;
1227
1228 const Node* node = controller->start().node();
1229 if (!node)
1230 return false;
1231
1232 *enable_ime = node->shouldUseInputMethod() &&
1233 !controller->isInPasswordField();
1234 const FrameView* view = node->document()->view();
1235 if (!view)
1236 return false;
1237
1238 *caret_rect = webkit_glue::IntRectToWebRect(
1239 view->contentsToWindow(controller->absoluteCaretBounds()));
1240 return true;
1241 }
1242
1243 void WebViewImpl::setTextDirection(WebTextDirection direction) {
1244 // The Editor::setBaseWritingDirection() function checks if we can change
1245 // the text direction of the selected node and updates its DOM "dir"
1246 // attribute and its CSS "direction" property.
1247 // So, we just call the function as Safari does.
1248 const Frame* focused = GetFocusedWebCoreFrame();
1249 if (!focused)
1250 return;
1251
1252 Editor* editor = focused->editor();
1253 if (!editor || !editor->canEdit())
1254 return;
1255
1256 switch (direction) {
1257 case WebTextDirectionDefault:
1258 editor->setBaseWritingDirection(WebCore::NaturalWritingDirection);
1259 break;
1260
1261 case WebTextDirectionLeftToRight:
1262 editor->setBaseWritingDirection(WebCore::LeftToRightWritingDirection);
1263 break;
1264
1265 case WebTextDirectionRightToLeft:
1266 editor->setBaseWritingDirection(WebCore::RightToLeftWritingDirection);
1267 break;
1268
1269 default: 1285 default:
1270 notImplemented(); 1286 ASSERT_NOT_REACHED();
1271 break; 1287 }
1272 } 1288 }
1273 } 1289
1274 1290 void WebViewImpl::copyImageAt(const WebPoint& point)
1275 // WebView -------------------------------------------------------------------- 1291 {
1276 1292 if (!m_page.get())
1277 WebSettings* WebViewImpl::settings() { 1293 return;
1278 if (!web_settings_.get()) 1294
1279 web_settings_.set(new WebSettingsImpl(page_->settings())); 1295 HitTestResult result = hitTestResultForWindowPos(point);
1280 ASSERT(web_settings_.get()); 1296
1281 return web_settings_.get(); 1297 if (result.absoluteImageURL().isEmpty()) {
1282 } 1298 // There isn't actually an image at these coordinates. Might be because
1283 1299 // the window scrolled while the context menu was open or because the page
1284 WebString WebViewImpl::pageEncoding() const { 1300 // changed itself between when we thought there was an image here and when
1285 if (!page_.get()) 1301 // we actually tried to retreive the image.
1286 return WebString(); 1302 //
1287 1303 // FIXME: implement a cache of the most recent HitTestResult to avoid having
1288 String encoding_name = page_->mainFrame()->loader()->encoding(); 1304 // to do two hit tests.
1289 return webkit_glue::StringToWebString(encoding_name); 1305 return;
1290 } 1306 }
1291 1307
1292 void WebViewImpl::setPageEncoding(const WebString& encoding_name) { 1308 m_page->mainFrame()->editor()->copyImage(result);
1293 if (!page_.get())
1294 return;
1295
1296 // Only change override encoding, don't change default encoding.
1297 // Note that the new encoding must be NULL if it isn't supposed to be set.
1298 String new_encoding_name;
1299 if (!encoding_name.isEmpty())
1300 new_encoding_name = webkit_glue::WebStringToString(encoding_name);
1301 page_->mainFrame()->loader()->reloadWithOverrideEncoding(new_encoding_name);
1302 }
1303
1304 bool WebViewImpl::dispatchBeforeUnloadEvent() {
1305 // TODO(creis): This should really cause a recursive depth-first walk of all
1306 // frames in the tree, calling each frame's onbeforeunload. At the moment,
1307 // we're consistent with Safari 3.1, not IE/FF.
1308 Frame* frame = page_->focusController()->focusedOrMainFrame();
1309 if (!frame)
1310 return true;
1311
1312 return frame->shouldClose();
1313 }
1314
1315 void WebViewImpl::dispatchUnloadEvent() {
1316 // Run unload handlers.
1317 page_->mainFrame()->loader()->closeURL();
1318 }
1319
1320 WebFrame* WebViewImpl::mainFrame() {
1321 return main_frame();
1322 }
1323
1324 WebFrame* WebViewImpl::findFrameByName(
1325 const WebString& name, WebFrame* relative_to_frame) {
1326 String name_str = webkit_glue::WebStringToString(name);
1327 if (!relative_to_frame)
1328 relative_to_frame = mainFrame();
1329 Frame* frame = static_cast<WebFrameImpl*>(relative_to_frame)->frame();
1330 frame = frame->tree()->find(name_str);
1331 return WebFrameImpl::FromFrame(frame);
1332 }
1333
1334 WebFrame* WebViewImpl::focusedFrame() {
1335 return WebFrameImpl::FromFrame(GetFocusedWebCoreFrame());
1336 }
1337
1338 void WebViewImpl::setFocusedFrame(WebFrame* frame) {
1339 if (!frame) {
1340 // Clears the focused frame if any.
1341 Frame* frame = GetFocusedWebCoreFrame();
1342 if (frame)
1343 frame->selection()->setFocused(false);
1344 return;
1345 }
1346 WebFrameImpl* frame_impl = static_cast<WebFrameImpl*>(frame);
1347 WebCore::Frame* webcore_frame = frame_impl->frame();
1348 webcore_frame->page()->focusController()->setFocusedFrame(webcore_frame);
1349 }
1350
1351 void WebViewImpl::setInitialFocus(bool reverse) {
1352 if (!page_.get())
1353 return;
1354
1355 // Since we don't have a keyboard event, we'll create one.
1356 WebKeyboardEvent keyboard_event;
1357 keyboard_event.type = WebInputEvent::RawKeyDown;
1358 if (reverse)
1359 keyboard_event.modifiers = WebInputEvent::ShiftKey;
1360
1361 // VK_TAB which is only defined on Windows.
1362 keyboard_event.windowsKeyCode = 0x09;
1363 PlatformKeyboardEventBuilder platform_event(keyboard_event);
1364 RefPtr<KeyboardEvent> webkit_event =
1365 KeyboardEvent::create(platform_event, NULL);
1366 page()->focusController()->setInitialFocus(
1367 reverse ? WebCore::FocusDirectionBackward :
1368 WebCore::FocusDirectionForward,
1369 webkit_event.get());
1370 }
1371
1372 void WebViewImpl::clearFocusedNode() {
1373 if (!page_.get())
1374 return;
1375
1376 RefPtr<Frame> frame = page_->mainFrame();
1377 if (!frame.get())
1378 return;
1379
1380 RefPtr<Document> document = frame->document();
1381 if (!document.get())
1382 return;
1383
1384 RefPtr<Node> old_focused_node = document->focusedNode();
1385
1386 // Clear the focused node.
1387 document->setFocusedNode(NULL);
1388
1389 if (!old_focused_node.get())
1390 return;
1391
1392 // If a text field has focus, we need to make sure the selection controller
1393 // knows to remove selection from it. Otherwise, the text field is still
1394 // processing keyboard events even though focus has been moved to the page and
1395 // keystrokes get eaten as a result.
1396 if (old_focused_node->hasTagName(HTMLNames::textareaTag) ||
1397 (old_focused_node->hasTagName(HTMLNames::inputTag) &&
1398 static_cast<HTMLInputElement*>(old_focused_node.get())->isTextField())) {
1399 // Clear the selection.
1400 SelectionController* selection = frame->selection();
1401 selection->clear();
1402 }
1403 }
1404
1405 void WebViewImpl::zoomIn(bool text_only) {
1406 Frame* frame = main_frame()->frame();
1407 double multiplier = std::min(std::pow(kTextSizeMultiplierRatio,
1408 zoom_level_ + 1),
1409 kMaxTextSizeMultiplier);
1410 float zoom_factor = static_cast<float>(multiplier);
1411 if (zoom_factor != frame->zoomFactor()) {
1412 ++zoom_level_;
1413 frame->setZoomFactor(zoom_factor, text_only);
1414 }
1415 }
1416
1417 void WebViewImpl::zoomOut(bool text_only) {
1418 Frame* frame = main_frame()->frame();
1419 double multiplier = std::max(std::pow(kTextSizeMultiplierRatio,
1420 zoom_level_ - 1),
1421 kMinTextSizeMultiplier);
1422 float zoom_factor = static_cast<float>(multiplier);
1423 if (zoom_factor != frame->zoomFactor()) {
1424 --zoom_level_;
1425 frame->setZoomFactor(zoom_factor, text_only);
1426 }
1427 }
1428
1429 void WebViewImpl::zoomDefault() {
1430 // We don't change the zoom mode (text only vs. full page) here. We just want
1431 // to reset whatever is already set.
1432 zoom_level_ = 0;
1433 main_frame()->frame()->setZoomFactor(
1434 1.0f,
1435 main_frame()->frame()->isZoomFactorTextOnly());
1436 }
1437
1438 void WebViewImpl::performMediaPlayerAction(const WebMediaPlayerAction& action,
1439 const WebPoint& location) {
1440 HitTestResult result =
1441 HitTestResultForWindowPos(webkit_glue::WebPointToIntPoint(location));
1442 WTF::RefPtr<WebCore::Node> node = result.innerNonSharedNode();
1443 if (!node->hasTagName(WebCore::HTMLNames::videoTag) &&
1444 !node->hasTagName(WebCore::HTMLNames::audioTag))
1445 return;
1446
1447 WTF::RefPtr<WebCore::HTMLMediaElement> media_element =
1448 static_pointer_cast<WebCore::HTMLMediaElement>(node);
1449 switch (action.type) {
1450 case WebMediaPlayerAction::Play:
1451 if (action.enable) {
1452 media_element->play();
1453 } else {
1454 media_element->pause();
1455 }
1456 break;
1457 case WebMediaPlayerAction::Mute:
1458 media_element->setMuted(action.enable);
1459 break;
1460 case WebMediaPlayerAction::Loop:
1461 media_element->setLoop(action.enable);
1462 break;
1463 default:
1464 ASSERT_NOT_REACHED();
1465 }
1466 }
1467
1468 void WebViewImpl::copyImageAt(const WebPoint& point) {
1469 if (!page_.get())
1470 return;
1471
1472 HitTestResult result =
1473 HitTestResultForWindowPos(webkit_glue::WebPointToIntPoint(point));
1474
1475 if (result.absoluteImageURL().isEmpty()) {
1476 // There isn't actually an image at these coordinates. Might be because
1477 // the window scrolled while the context menu was open or because the page
1478 // changed itself between when we thought there was an image here and when
1479 // we actually tried to retreive the image.
1480 //
1481 // TODO: implement a cache of the most recent HitTestResult to avoid having
1482 // to do two hit tests.
1483 return;
1484 }
1485
1486 page_->mainFrame()->editor()->copyImage(result);
1487 } 1309 }
1488 1310
1489 void WebViewImpl::dragSourceEndedAt( 1311 void WebViewImpl::dragSourceEndedAt(
1490 const WebPoint& client_point, 1312 const WebPoint& clientPoint,
1491 const WebPoint& screen_point, 1313 const WebPoint& screenPoint,
1492 WebDragOperation operation) { 1314 WebDragOperation operation)
1493 PlatformMouseEvent pme(webkit_glue::WebPointToIntPoint(client_point), 1315 {
1494 webkit_glue::WebPointToIntPoint(screen_point), 1316 PlatformMouseEvent pme(clientPoint,
1495 LeftButton, MouseEventMoved, 0, false, false, false, 1317 screenPoint,
1496 false, 0); 1318 LeftButton, MouseEventMoved, 0, false, false, false,
1497 page_->mainFrame()->eventHandler()->dragSourceEndedAt(pme, 1319 false, 0);
1498 static_cast<WebCore::DragOperation>(operation)); 1320 m_page->mainFrame()->eventHandler()->dragSourceEndedAt(pme,
1321 static_cast<DragOperation>(operation));
1499 } 1322 }
1500 1323
1501 void WebViewImpl::dragSourceMovedTo( 1324 void WebViewImpl::dragSourceMovedTo(
1502 const WebPoint& client_point, 1325 const WebPoint& clientPoint,
1503 const WebPoint& screen_point) { 1326 const WebPoint& screenPoint)
1504 PlatformMouseEvent pme(webkit_glue::WebPointToIntPoint(client_point), 1327 {
1505 webkit_glue::WebPointToIntPoint(screen_point), 1328 PlatformMouseEvent pme(clientPoint,
1506 LeftButton, MouseEventMoved, 0, false, false, false, 1329 screenPoint,
1507 false, 0); 1330 LeftButton, MouseEventMoved, 0, false, false, false,
1508 page_->mainFrame()->eventHandler()->dragSourceMovedTo(pme); 1331 false, 0);
1509 } 1332 m_page->mainFrame()->eventHandler()->dragSourceMovedTo(pme);
1510 1333 }
1511 void WebViewImpl::dragSourceSystemDragEnded() { 1334
1512 // It's possible for us to get this callback while not doing a drag if 1335 void WebViewImpl::dragSourceSystemDragEnded()
1513 // it's from a previous page that got unloaded. 1336 {
1514 if (doing_drag_and_drop_) { 1337 // It's possible for us to get this callback while not doing a drag if
1515 page_->dragController()->dragEnded(); 1338 // it's from a previous page that got unloaded.
1516 doing_drag_and_drop_ = false; 1339 if (m_doingDragAndDrop) {
1517 } 1340 m_page->dragController()->dragEnded();
1341 m_doingDragAndDrop = false;
1342 }
1518 } 1343 }
1519 1344
1520 WebDragOperation WebViewImpl::dragTargetDragEnter( 1345 WebDragOperation WebViewImpl::dragTargetDragEnter(
1521 const WebDragData& web_drag_data, int identity, 1346 const WebDragData& webDragData, int identity,
1522 const WebPoint& client_point, 1347 const WebPoint& clientPoint,
1523 const WebPoint& screen_point, 1348 const WebPoint& screenPoint,
1524 WebDragOperationsMask operations_allowed) { 1349 WebDragOperationsMask operationsAllowed)
1525 ASSERT(!current_drag_data_.get()); 1350 {
1526 1351 ASSERT(!m_currentDragData.get());
1527 current_drag_data_ = 1352
1528 webkit_glue::WebDragDataToChromiumDataObject(web_drag_data); 1353 m_currentDragData = webDragData;
1529 drag_identity_ = identity; 1354 m_dragIdentity = identity;
1530 operations_allowed_ = operations_allowed; 1355 m_operationsAllowed = operationsAllowed;
1531 1356
1532 DragData drag_data( 1357 DragData dragData(
1533 current_drag_data_.get(), 1358 m_currentDragData.get(),
1534 webkit_glue::WebPointToIntPoint(client_point), 1359 clientPoint,
1535 webkit_glue::WebPointToIntPoint(screen_point), 1360 screenPoint,
1536 static_cast<WebCore::DragOperation>(operations_allowed)); 1361 static_cast<DragOperation>(operationsAllowed));
1537 1362
1538 drop_effect_ = DROP_EFFECT_DEFAULT; 1363 m_dropEffect = DropEffectDefault;
1539 drag_target_dispatch_ = true; 1364 m_dragTargetDispatch = true;
1540 DragOperation effect = page_->dragController()->dragEntered(&drag_data); 1365 DragOperation effect = m_page->dragController()->dragEntered(&dragData);
1541 // Mask the operation against the drag source's allowed operations. 1366 // Mask the operation against the drag source's allowed operations.
1542 if ((effect & drag_data.draggingSourceOperationMask()) != effect) { 1367 if ((effect & dragData.draggingSourceOperationMask()) != effect)
1543 effect = DragOperationNone; 1368 effect = DragOperationNone;
1544 } 1369 m_dragTargetDispatch = false;
1545 drag_target_dispatch_ = false; 1370
1546 1371 if (m_dropEffect != DropEffectDefault) {
1547 if (drop_effect_ != DROP_EFFECT_DEFAULT) 1372 m_dragOperation = (m_dropEffect != DropEffectNone) ? WebDragOperationCopy
1548 drag_operation_ = (drop_effect_ != DROP_EFFECT_NONE) ? 1373 : WebDragOperationNone;
1549 WebDragOperationCopy : WebDragOperationNone; 1374 } else
1550 else 1375 m_dragOperation = static_cast<WebDragOperation>(effect);
1551 drag_operation_ = static_cast<WebDragOperation>(effect); 1376 return m_dragOperation;
1552 return drag_operation_;
1553 } 1377 }
1554 1378
1555 WebDragOperation WebViewImpl::dragTargetDragOver( 1379 WebDragOperation WebViewImpl::dragTargetDragOver(
1556 const WebPoint& client_point, 1380 const WebPoint& clientPoint,
1557 const WebPoint& screen_point, 1381 const WebPoint& screenPoint,
1558 WebDragOperationsMask operations_allowed) { 1382 WebDragOperationsMask operationsAllowed)
1559 ASSERT(current_drag_data_.get()); 1383 {
1560 1384 ASSERT(m_currentDragData.get());
1561 operations_allowed_ = operations_allowed; 1385
1562 DragData drag_data( 1386 m_operationsAllowed = operationsAllowed;
1563 current_drag_data_.get(), 1387 DragData dragData(
1564 webkit_glue::WebPointToIntPoint(client_point), 1388 m_currentDragData.get(),
1565 webkit_glue::WebPointToIntPoint(screen_point), 1389 clientPoint,
1566 static_cast<WebCore::DragOperation>(operations_allowed)); 1390 screenPoint,
1567 1391 static_cast<DragOperation>(operationsAllowed));
1568 drop_effect_ = DROP_EFFECT_DEFAULT; 1392
1569 drag_target_dispatch_ = true; 1393 m_dropEffect = DropEffectDefault;
1570 DragOperation effect = page_->dragController()->dragUpdated(&drag_data); 1394 m_dragTargetDispatch = true;
1571 // Mask the operation against the drag source's allowed operations. 1395 DragOperation effect = m_page->dragController()->dragUpdated(&dragData);
1572 if ((effect & drag_data.draggingSourceOperationMask()) != effect) { 1396 // Mask the operation against the drag source's allowed operations.
1573 effect = DragOperationNone; 1397 if ((effect & dragData.draggingSourceOperationMask()) != effect)
1574 } 1398 effect = DragOperationNone;
1575 drag_target_dispatch_ = false; 1399 m_dragTargetDispatch = false;
1576 1400
1577 if (drop_effect_ != DROP_EFFECT_DEFAULT) 1401 if (m_dropEffect != DropEffectDefault) {
1578 drag_operation_ = (drop_effect_ != DROP_EFFECT_NONE) ? 1402 m_dragOperation = (m_dropEffect != DropEffectNone) ? WebDragOperationCopy
1579 WebDragOperationCopy : WebDragOperationNone; 1403 : WebDragOperationNone;
1580 else 1404 } else
1581 drag_operation_ = static_cast<WebDragOperation>(effect); 1405 m_dragOperation = static_cast<WebDragOperation>(effect);
1582 return drag_operation_; 1406 return m_dragOperation;
1583 } 1407 }
1584 1408
1585 void WebViewImpl::dragTargetDragLeave() { 1409 void WebViewImpl::dragTargetDragLeave()
1586 ASSERT(current_drag_data_.get()); 1410 {
1587 1411 ASSERT(m_currentDragData.get());
1588 DragData drag_data( 1412
1589 current_drag_data_.get(), 1413 DragData dragData(
1590 IntPoint(), 1414 m_currentDragData.get(),
1591 IntPoint(), 1415 IntPoint(),
1592 static_cast<WebCore::DragOperation>(operations_allowed_)); 1416 IntPoint(),
1593 1417 static_cast<DragOperation>(m_operationsAllowed));
1594 drag_target_dispatch_ = true; 1418
1595 page_->dragController()->dragExited(&drag_data); 1419 m_dragTargetDispatch = true;
1596 drag_target_dispatch_ = false; 1420 m_page->dragController()->dragExited(&dragData);
1597 1421 m_dragTargetDispatch = false;
1598 current_drag_data_ = NULL; 1422
1599 drop_effect_ = DROP_EFFECT_DEFAULT; 1423 m_currentDragData = 0;
1600 drag_operation_ = WebDragOperationNone; 1424 m_dropEffect = DropEffectDefault;
1601 drag_identity_ = 0; 1425 m_dragOperation = WebDragOperationNone;
1602 } 1426 m_dragIdentity = 0;
1603 1427 }
1604 void WebViewImpl::dragTargetDrop(const WebPoint& client_point, 1428
1605 const WebPoint& screen_point) { 1429 void WebViewImpl::dragTargetDrop(const WebPoint& clientPoint,
1606 ASSERT(current_drag_data_.get()); 1430 const WebPoint& screenPoint)
1607 1431 {
1608 // If this webview transitions from the "drop accepting" state to the "not 1432 ASSERT(m_currentDragData.get());
1609 // accepting" state, then our IPC message reply indicating that may be in- 1433
1610 // flight, or else delayed by javascript processing in this webview. If a 1434 // If this webview transitions from the "drop accepting" state to the "not
1611 // drop happens before our IPC reply has reached the browser process, then 1435 // accepting" state, then our IPC message reply indicating that may be in-
1612 // the browser forwards the drop to this webview. So only allow a drop to 1436 // flight, or else delayed by javascript processing in this webview. If a
1613 // proceed if our webview drag_operation_ state is not DragOperationNone. 1437 // drop happens before our IPC reply has reached the browser process, then
1614 1438 // the browser forwards the drop to this webview. So only allow a drop to
1615 if (drag_operation_ == WebDragOperationNone) { // IPC RACE CONDITION: do not allow this drop. 1439 // proceed if our webview m_dragOperation state is not DragOperationNone.
1616 dragTargetDragLeave(); 1440
1617 return; 1441 if (m_dragOperation == WebDragOperationNone) { // IPC RACE CONDITION: do not allow this drop.
1618 } 1442 dragTargetDragLeave();
1619 1443 return;
1620 DragData drag_data( 1444 }
1621 current_drag_data_.get(), 1445
1622 webkit_glue::WebPointToIntPoint(client_point), 1446 DragData dragData(
1623 webkit_glue::WebPointToIntPoint(screen_point), 1447 m_currentDragData.get(),
1624 static_cast<WebCore::DragOperation>(operations_allowed_)); 1448 clientPoint,
1625 1449 screenPoint,
1626 drag_target_dispatch_ = true; 1450 static_cast<DragOperation>(m_operationsAllowed));
1627 page_->dragController()->performDrag(&drag_data); 1451
1628 drag_target_dispatch_ = false; 1452 m_dragTargetDispatch = true;
1629 1453 m_page->dragController()->performDrag(&dragData);
1630 current_drag_data_ = NULL; 1454 m_dragTargetDispatch = false;
1631 drop_effect_ = DROP_EFFECT_DEFAULT; 1455
1632 drag_operation_ = WebDragOperationNone; 1456 m_currentDragData = 0;
1633 drag_identity_ = 0; 1457 m_dropEffect = DropEffectDefault;
1634 } 1458 m_dragOperation = WebDragOperationNone;
1635 1459 m_dragIdentity = 0;
1636 int WebViewImpl::dragIdentity() { 1460 }
1637 if (drag_target_dispatch_) 1461
1638 return drag_identity_; 1462 int WebViewImpl::dragIdentity()
1639 return 0; 1463 {
1640 } 1464 if (m_dragTargetDispatch)
1641 1465 return m_dragIdentity;
1642 void WebViewImpl::inspectElementAt(const WebPoint& point) { 1466 return 0;
1643 if (!page_.get()) 1467 }
1644 return; 1468
1645 1469 void WebViewImpl::inspectElementAt(const WebPoint& point)
1646 if (point.x == -1 || point.y == -1) { 1470 {
1647 page_->inspectorController()->inspect(NULL); 1471 if (!m_page.get())
1648 } else { 1472 return;
1649 HitTestResult result = 1473
1650 HitTestResultForWindowPos(webkit_glue::WebPointToIntPoint(point)); 1474 if (point.x == -1 || point.y == -1)
1651 1475 m_page->inspectorController()->inspect(0);
1652 if (!result.innerNonSharedNode()) 1476 else {
1653 return; 1477 HitTestResult result = hitTestResultForWindowPos(point);
1654 1478
1655 page_->inspectorController()->inspect(result.innerNonSharedNode()); 1479 if (!result.innerNonSharedNode())
1656 } 1480 return;
1657 } 1481
1658 1482 m_page->inspectorController()->inspect(result.innerNonSharedNode());
1659 WebString WebViewImpl::inspectorSettings() const { 1483 }
1660 return inspector_settings_; 1484 }
1661 } 1485
1662 1486 WebString WebViewImpl::inspectorSettings() const
1663 void WebViewImpl::setInspectorSettings(const WebString& settings) { 1487 {
1664 inspector_settings_ = settings; 1488 return m_inspectorSettings;
1665 } 1489 }
1666 1490
1667 WebDevToolsAgent* WebViewImpl::devToolsAgent() { 1491 void WebViewImpl::setInspectorSettings(const WebString& settings)
1668 return devtools_agent_.get(); 1492 {
1669 } 1493 m_inspectorSettings = settings;
1670 1494 }
1671 WebAccessibilityObject WebViewImpl::accessibilityObject() { 1495
1672 if (!main_frame()) 1496 WebDevToolsAgent* WebViewImpl::devToolsAgent()
1673 return WebAccessibilityObject(); 1497 {
1674 1498 return m_devToolsAgent.get();
1675 WebCore::Document* document = main_frame()->frame()->document(); 1499 }
1676 1500
1677 return AccessibilityObjectToWebAccessibilityObject( 1501 WebAccessibilityObject WebViewImpl::accessibilityObject()
1678 document->axObjectCache()->getOrCreate(document->renderer())); 1502 {
1503 if (!mainFrameImpl())
1504 return WebAccessibilityObject();
1505
1506 Document* document = mainFrameImpl()->frame()->document();
1507 return WebAccessibilityObject(
1508 document->axObjectCache()->getOrCreate(document->renderer()));
1679 } 1509 }
1680 1510
1681 void WebViewImpl::applyAutofillSuggestions( 1511 void WebViewImpl::applyAutofillSuggestions(
1682 const WebNode& node, 1512 const WebNode& node,
1683 const WebVector<WebString>& suggestions, 1513 const WebVector<WebString>& suggestions,
1684 int default_suggestion_index) { 1514 int defaultSuggestionIndex)
1685 if (!page_.get() || suggestions.isEmpty()) { 1515 {
1686 HideAutoCompletePopup(); 1516 if (!m_page.get() || suggestions.isEmpty()) {
1687 return; 1517 hideAutoCompletePopup();
1688 } 1518 return;
1689 1519 }
1690 ASSERT(default_suggestion_index < static_cast<int>(suggestions.size())); 1520
1691 1521 ASSERT(defaultSuggestionIndex < static_cast<int>(suggestions.size()));
1692 if (RefPtr<Frame> focused = page_->focusController()->focusedFrame()) { 1522
1693 RefPtr<Document> document = focused->document(); 1523 if (RefPtr<Frame> focused = m_page->focusController()->focusedFrame()) {
1694 if (!document.get()) { 1524 RefPtr<Document> document = focused->document();
1695 HideAutoCompletePopup(); 1525 if (!document.get()) {
1696 return; 1526 hideAutoCompletePopup();
1697 } 1527 return;
1698 1528 }
1699 RefPtr<Node> focused_node = document->focusedNode(); 1529
1700 // If the node for which we queried the autofill suggestions is not the 1530 RefPtr<Node> focusedNode = document->focusedNode();
1701 // focused node, then we have nothing to do. 1531 // If the node for which we queried the autofill suggestions is not the
1702 // TODO(jcampan): also check the carret is at the end and that the text has 1532 // focused node, then we have nothing to do. FIXME: also check the
1703 // not changed. 1533 // carret is at the end and that the text has not changed.
1704 if (!focused_node.get() || 1534 if (!focusedNode.get() || focusedNode != PassRefPtr<Node>(node)) {
1705 focused_node != webkit_glue::WebNodeToNode(node)) { 1535 hideAutoCompletePopup();
1706 HideAutoCompletePopup(); 1536 return;
1707 return; 1537 }
1708 } 1538
1709 1539 if (!focusedNode->hasTagName(HTMLNames::inputTag)) {
1710 if (!focused_node->hasTagName(WebCore::HTMLNames::inputTag)) { 1540 ASSERT_NOT_REACHED();
1711 ASSERT_NOT_REACHED(); 1541 return;
1712 return; 1542 }
1713 } 1543
1714 1544 HTMLInputElement* inputElem =
1715 WebCore::HTMLInputElement* input_elem = 1545 static_cast<HTMLInputElement*>(focusedNode.get());
1716 static_cast<WebCore::HTMLInputElement*>(focused_node.get()); 1546
1717 1547 // The first time the autocomplete is shown we'll create the client and the
1718 // The first time the autocomplete is shown we'll create the client and the 1548 // popup.
1719 // popup. 1549 if (!m_autocompletePopupClient.get())
1720 if (!autocomplete_popup_client_.get()) 1550 m_autocompletePopupClient.set(new AutocompletePopupMenuClient(this));
1721 autocomplete_popup_client_.set(new AutocompletePopupMenuClient(this)); 1551 m_autocompletePopupClient->initialize(inputElem,
1722 autocomplete_popup_client_->Init(input_elem, 1552 suggestions,
1723 suggestions, 1553 defaultSuggestionIndex);
1724 default_suggestion_index); 1554 if (!m_autocompletePopup.get()) {
1725 if (!autocomplete_popup_.get()) { 1555 m_autocompletePopup =
1726 autocomplete_popup_ = 1556 PopupContainer::create(m_autocompletePopupClient.get(),
1727 WebCore::PopupContainer::create(autocomplete_popup_client_.get(), 1557 autocompletePopupSettings);
1728 kAutocompletePopupSettings); 1558 }
1729 } 1559
1730 1560 if (m_autocompletePopupShowing) {
1731 if (autocomplete_popup_showing_) { 1561 m_autocompletePopupClient->setSuggestions(suggestions);
1732 autocomplete_popup_client_->SetSuggestions(suggestions); 1562 refreshAutofillPopup();
1733 RefreshAutofillPopup(); 1563 } else {
1734 } else { 1564 m_autocompletePopup->show(focusedNode->getRect(),
1735 autocomplete_popup_->show(focused_node->getRect(), 1565 focusedNode->ownerDocument()->view(), 0);
1736 focused_node->ownerDocument()->view(), 0); 1566 m_autocompletePopupShowing = true;
1737 autocomplete_popup_showing_ = true; 1567 }
1738 } 1568 }
1739 } 1569 }
1740 } 1570
1741 1571 void WebViewImpl::hideAutofillPopup()
1742 void WebViewImpl::hideAutofillPopup() { 1572 {
1743 HideAutoCompletePopup(); 1573 hideAutoCompletePopup();
1744 } 1574 }
1745 1575
1746 // WebView -------------------------------------------------------------------- 1576 // WebView --------------------------------------------------------------------
1747 1577
1748 bool WebViewImpl::setDropEffect(bool accept) { 1578 bool WebViewImpl::setDropEffect(bool accept) {
1749 if (drag_target_dispatch_) { 1579 if (m_dragTargetDispatch) {
1750 drop_effect_ = accept ? DROP_EFFECT_COPY : DROP_EFFECT_NONE; 1580 m_dropEffect = accept ? DropEffectCopy : DropEffectNone;
1751 return true; 1581 return true;
1752 } else { 1582 }
1753 return false; 1583 return false;
1754 } 1584 }
1755 } 1585
1756 1586 WebDevToolsAgentImpl* WebViewImpl::devToolsAgentImpl()
1757 WebDevToolsAgentImpl* WebViewImpl::GetWebDevToolsAgentImpl() { 1587 {
1758 return devtools_agent_.get(); 1588 return m_devToolsAgent.get();
1759 } 1589 }
1760 1590
1761 void WebViewImpl::setIsTransparent(bool is_transparent) { 1591 void WebViewImpl::setIsTransparent(bool isTransparent)
1762 // Set any existing frames to be transparent. 1592 {
1763 WebCore::Frame* frame = page_->mainFrame(); 1593 // Set any existing frames to be transparent.
1764 while (frame) { 1594 Frame* frame = m_page->mainFrame();
1765 frame->view()->setTransparent(is_transparent); 1595 while (frame) {
1766 frame = frame->tree()->traverseNext(); 1596 frame->view()->setTransparent(isTransparent);
1767 } 1597 frame = frame->tree()->traverseNext();
1768 1598 }
1769 // Future frames check this to know whether to be transparent. 1599
1770 is_transparent_ = is_transparent; 1600 // Future frames check this to know whether to be transparent.
1771 } 1601 m_isTransparent = isTransparent;
1772 1602 }
1773 bool WebViewImpl::isTransparent() const { 1603
1774 return is_transparent_; 1604 bool WebViewImpl::isTransparent() const
1775 } 1605 {
1776 1606 return m_isTransparent;
1777 void WebViewImpl::setIsActive(bool active) { 1607 }
1778 if (page() && page()->focusController()) 1608
1779 page()->focusController()->setActive(active); 1609 void WebViewImpl::setIsActive(bool active)
1780 } 1610 {
1781 1611 if (page() && page()->focusController())
1782 bool WebViewImpl::isActive() const { 1612 page()->focusController()->setActive(active);
1783 return (page() && page()->focusController()) 1613 }
1784 ? page()->focusController()->isActive() 1614
1785 : false; 1615 bool WebViewImpl::isActive() const
1786 } 1616 {
1787 1617 return (page() && page()->focusController()) ? page()->focusController()->isActive() : false;
1788 void WebViewImpl::DidCommitLoad(bool* is_new_navigation) { 1618 }
1789 if (is_new_navigation) 1619
1790 *is_new_navigation = observed_new_navigation_; 1620 void WebViewImpl::didCommitLoad(bool* isNewNavigation)
1621 {
1622 if (isNewNavigation)
1623 *isNewNavigation = m_observedNewNavigation;
1791 1624
1792 #ifndef NDEBUG 1625 #ifndef NDEBUG
1793 ASSERT(!observed_new_navigation_ || 1626 ASSERT(!m_observedNewNavigation
1794 page_->mainFrame()->loader()->documentLoader() == new_navigation_loader_); 1627 || m_page->mainFrame()->loader()->documentLoader() == m_newNavigationLoader);
1795 new_navigation_loader_ = NULL; 1628 m_newNavigationLoader = 0;
1796 #endif 1629 #endif
1797 observed_new_navigation_ = false; 1630 m_observedNewNavigation = false;
1798 } 1631 }
1799 1632
1800 // static 1633 bool WebViewImpl::navigationPolicyFromMouseEvent(unsigned short button,
1801 bool WebViewImpl::NavigationPolicyFromMouseEvent(unsigned short button,
1802 bool ctrl, bool shift, 1634 bool ctrl, bool shift,
1803 bool alt, bool meta, 1635 bool alt, bool meta,
1804 WebNavigationPolicy* policy) { 1636 WebNavigationPolicy* policy)
1637 {
1805 #if PLATFORM(WIN_OS) || PLATFORM(LINUX) || PLATFORM(FREEBSD) 1638 #if PLATFORM(WIN_OS) || PLATFORM(LINUX) || PLATFORM(FREEBSD)
1806 const bool new_tab_modifier = (button == 1) || ctrl; 1639 const bool newTabModifier = (button == 1) || ctrl;
1807 #elif PLATFORM(DARWIN) 1640 #elif PLATFORM(DARWIN)
1808 const bool new_tab_modifier = (button == 1) || meta; 1641 const bool newTabModifier = (button == 1) || meta;
1809 #endif 1642 #endif
1810 if (!new_tab_modifier && !shift && !alt) 1643 if (!newTabModifier && !shift && !alt)
1811 return false; 1644 return false;
1812 1645
1813 ASSERT(policy); 1646 ASSERT(policy);
1814 if (new_tab_modifier) { 1647 if (newTabModifier) {
1815 if (shift) { 1648 if (shift)
1816 *policy = WebKit::WebNavigationPolicyNewForegroundTab; 1649 *policy = WebNavigationPolicyNewForegroundTab;
1650 else
1651 *policy = WebNavigationPolicyNewBackgroundTab;
1817 } else { 1652 } else {
1818 *policy = WebKit::WebNavigationPolicyNewBackgroundTab; 1653 if (shift)
1819 } 1654 *policy = WebNavigationPolicyNewWindow;
1820 } else { 1655 else
1821 if (shift) { 1656 *policy = WebNavigationPolicyDownload;
1822 *policy = WebKit::WebNavigationPolicyNewWindow; 1657 }
1823 } else { 1658 return true;
1824 *policy = WebKit::WebNavigationPolicyDownload; 1659 }
1825 } 1660
1826 } 1661 void WebViewImpl::startDragging(const WebPoint& eventPos,
1827 return true; 1662 const WebDragData& dragData,
1828 } 1663 WebDragOperationsMask mask)
1829 1664 {
1830 void WebViewImpl::StartDragging(const WebPoint& event_pos, 1665 if (!m_client)
1831 const WebDragData& drag_data, 1666 return;
1832 WebDragOperationsMask mask) { 1667 ASSERT(!m_doingDragAndDrop);
1833 if (!client_) 1668 m_doingDragAndDrop = true;
1834 return; 1669 m_client->startDragging(eventPos, dragData, mask);
1835 ASSERT(!doing_drag_and_drop_); 1670 }
1836 doing_drag_and_drop_ = true; 1671
1837 client_->startDragging(event_pos, drag_data, mask); 1672 void WebViewImpl::setCurrentHistoryItem(HistoryItem* item)
1838 } 1673 {
1839 1674 m_backForwardListClientImpl.setCurrentHistoryItem(item);
1840 void WebViewImpl::SetCurrentHistoryItem(WebCore::HistoryItem* item) { 1675 }
1841 back_forward_list_client_impl_.SetCurrentHistoryItem(item); 1676
1842 } 1677 HistoryItem* WebViewImpl::previousHistoryItem()
1843 1678 {
1844 WebCore::HistoryItem* WebViewImpl::GetPreviousHistoryItem() { 1679 return m_backForwardListClientImpl.previousHistoryItem();
1845 return back_forward_list_client_impl_.GetPreviousHistoryItem(); 1680 }
1846 } 1681
1847 1682 void WebViewImpl::observeNewNavigation()
1848 void WebViewImpl::ObserveNewNavigation() { 1683 {
1849 observed_new_navigation_ = true; 1684 m_observedNewNavigation = true;
1850 #ifndef NDEBUG 1685 #ifndef NDEBUG
1851 new_navigation_loader_ = page_->mainFrame()->loader()->documentLoader(); 1686 m_newNavigationLoader = m_page->mainFrame()->loader()->documentLoader();
1852 #endif 1687 #endif
1853 } 1688 }
1854 1689
1855 void WebViewImpl::HideAutoCompletePopup() { 1690 void WebViewImpl::hideAutoCompletePopup()
1856 if (autocomplete_popup_showing_) { 1691 {
1857 autocomplete_popup_->hidePopup(); 1692 if (m_autocompletePopupShowing) {
1858 AutoCompletePopupDidHide(); 1693 m_autocompletePopup->hidePopup();
1859 } 1694 autoCompletePopupDidHide();
1860 } 1695 }
1861 1696 }
1862 void WebViewImpl::AutoCompletePopupDidHide() { 1697
1863 autocomplete_popup_showing_ = false; 1698 void WebViewImpl::autoCompletePopupDidHide()
1864 } 1699 {
1865 1700 m_autocompletePopupShowing = false;
1866 void WebViewImpl::SetIgnoreInputEvents(bool new_value) { 1701 }
1867 ASSERT(ignore_input_events_ != new_value); 1702
1868 ignore_input_events_ = new_value; 1703 void WebViewImpl::setIgnoreInputEvents(bool newValue)
1704 {
1705 ASSERT(m_ignoreInputEvents != newValue);
1706 m_ignoreInputEvents = newValue;
1869 } 1707 }
1870 1708
1871 #if ENABLE(NOTIFICATIONS) 1709 #if ENABLE(NOTIFICATIONS)
1872 WebKit::NotificationPresenterImpl* WebViewImpl::GetNotificationPresenter() { 1710 NotificationPresenterImpl* WebViewImpl::notificationPresenterImpl()
1873 if (!notification_presenter_.isInitialized() && client_) 1711 {
1874 notification_presenter_.initialize(client_->notificationPresenter()); 1712 if (!m_notificationPresenter.isInitialized() && m_client)
1875 return &notification_presenter_; 1713 m_notificationPresenter.initialize(m_client->notificationPresenter());
1714 return &m_notificationPresenter;
1876 } 1715 }
1877 #endif 1716 #endif
1878 1717
1879 void WebViewImpl::RefreshAutofillPopup() { 1718 void WebViewImpl::refreshAutofillPopup() {
1880 ASSERT(autocomplete_popup_showing_); 1719 ASSERT(m_autocompletePopupShowing);
1881 1720
1882 // Hide the popup if it has become empty. 1721 // Hide the popup if it has become empty.
1883 if (autocomplete_popup_client_->listSize() == 0) { 1722 if (m_autocompletePopupClient->listSize() == 0) {
1884 HideAutoCompletePopup(); 1723 hideAutoCompletePopup();
1885 return; 1724 return;
1886 } 1725 }
1887 1726
1888 IntRect old_bounds = autocomplete_popup_->boundsRect(); 1727 IntRect oldBounds = m_autocompletePopup->boundsRect();
1889 autocomplete_popup_->refresh(); 1728 m_autocompletePopup->refresh();
1890 IntRect new_bounds = autocomplete_popup_->boundsRect(); 1729 IntRect newBounds = m_autocompletePopup->boundsRect();
1891 // Let's resize the backing window if necessary. 1730 // Let's resize the backing window if necessary.
1892 if (old_bounds != new_bounds) { 1731 if (oldBounds != newBounds) {
1893 WebPopupMenuImpl* popup_menu = 1732 WebPopupMenuImpl* popupMenu =
1894 static_cast<WebPopupMenuImpl*>(autocomplete_popup_->client()); 1733 static_cast<WebPopupMenuImpl*>(m_autocompletePopup->client());
1895 popup_menu->client()->setWindowRect( 1734 popupMenu->client()->setWindowRect(newBounds);
1896 webkit_glue::IntRectToWebRect(new_bounds)); 1735 }
1897 } 1736 }
1898 } 1737
1899 1738 Node* WebViewImpl::focusedWebCoreNode()
1900 Node* WebViewImpl::GetFocusedNode() { 1739 {
1901 Frame* frame = page_->focusController()->focusedFrame(); 1740 Frame* frame = m_page->focusController()->focusedFrame();
1902 if (!frame) 1741 if (!frame)
1903 return NULL; 1742 return 0;
1904 1743
1905 Document* document = frame->document(); 1744 Document* document = frame->document();
1906 if (!document) 1745 if (!document)
1907 return NULL; 1746 return 0;
1908 1747
1909 return document->focusedNode(); 1748 return document->focusedNode();
1910 } 1749 }
1911 1750
1912 HitTestResult WebViewImpl::HitTestResultForWindowPos(const IntPoint& pos) { 1751 HitTestResult WebViewImpl::hitTestResultForWindowPos(const IntPoint& pos)
1913 IntPoint doc_point( 1752 {
1914 page_->mainFrame()->view()->windowToContents(pos)); 1753 IntPoint docPoint(m_page->mainFrame()->view()->windowToContents(pos));
1915 return page_->mainFrame()->eventHandler()-> 1754 return m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(docPoint, false);
1916 hitTestResultAtPoint(doc_point, false); 1755 }
1917 } 1756
1918 1757 void WebViewImpl::setTabsToLinks(bool enable)
1919 void WebViewImpl::setTabsToLinks(bool enable) { 1758 {
1920 tabs_to_links_ = enable; 1759 m_tabsToLinks = enable;
1921 } 1760 }
1922 1761
1923 bool WebViewImpl::tabsToLinks() const { 1762 bool WebViewImpl::tabsToLinks() const
1924 return tabs_to_links_; 1763 {
1925 } 1764 return m_tabsToLinks;
1765 }
1766
1767 } // namespace WebKit
OLDNEW
« no previous file with comments | « webkit/api/src/WebViewImpl.h ('k') | webkit/api/src/WebWorkerClientImpl.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698