OLD | NEW |
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 Loading... |
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 ¬ification_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 |
OLD | NEW |