|
1 /* |
|
2 * Copyright (C) 2009 Google Inc. All rights reserved. |
|
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 */ |
|
30 |
|
31 #include "config.h" |
|
32 #include "WebPopupMenuImpl.h" |
|
33 |
|
34 #include "Cursor.h" |
|
35 #include "FramelessScrollView.h" |
|
36 #include "FrameView.h" |
|
37 #include "IntRect.h" |
|
38 #include "PlatformContextSkia.h" |
|
39 #include "PlatformKeyboardEvent.h" |
|
40 #include "PlatformMouseEvent.h" |
|
41 #include "PlatformWheelEvent.h" |
|
42 #include "SkiaUtils.h" |
|
43 |
|
44 #include "WebInputEvent.h" |
|
45 #include "WebInputEventConversion.h" |
|
46 #include "WebRect.h" |
|
47 #include "WebWidgetClient.h" |
|
48 |
|
49 #include <skia/ext/platform_canvas.h> |
|
50 |
|
51 using namespace WebCore; |
|
52 |
|
53 namespace WebKit { |
|
54 |
|
55 // WebPopupMenu --------------------------------------------------------------- |
|
56 |
|
57 WebPopupMenu* WebPopupMenu::create(WebWidgetClient* client) |
|
58 { |
|
59 // Pass the WebPopupMenuImpl's self-reference to the caller. |
|
60 return adoptRef(new WebPopupMenuImpl(client)).leakRef(); |
|
61 } |
|
62 |
|
63 // WebWidget ------------------------------------------------------------------ |
|
64 |
|
65 WebPopupMenuImpl::WebPopupMenuImpl(WebWidgetClient* client) |
|
66 : m_client(client) |
|
67 , m_widget(0) |
|
68 { |
|
69 // set to impossible point so we always get the first mouse pos |
|
70 m_lastMousePosition = WebPoint(-1, -1); |
|
71 } |
|
72 |
|
73 WebPopupMenuImpl::~WebPopupMenuImpl() |
|
74 { |
|
75 if (m_widget) |
|
76 m_widget->setClient(0); |
|
77 } |
|
78 |
|
79 void WebPopupMenuImpl::Init(FramelessScrollView* widget, const WebRect& bounds) |
|
80 { |
|
81 m_widget = widget; |
|
82 m_widget->setClient(this); |
|
83 |
|
84 if (m_client) { |
|
85 m_client->setWindowRect(bounds); |
|
86 m_client->show(WebNavigationPolicy()); // Policy is ignored |
|
87 } |
|
88 } |
|
89 |
|
90 void WebPopupMenuImpl::MouseMove(const WebMouseEvent& event) |
|
91 { |
|
92 // don't send mouse move messages if the mouse hasn't moved. |
|
93 if (event.x != m_lastMousePosition.x || event.y != m_lastMousePosition.y) { |
|
94 m_lastMousePosition = WebPoint(event.x, event.y); |
|
95 m_widget->handleMouseMoveEvent(PlatformMouseEventBuilder(m_widget, event)); |
|
96 } |
|
97 } |
|
98 |
|
99 void WebPopupMenuImpl::MouseLeave(const WebMouseEvent& event) |
|
100 { |
|
101 m_widget->handleMouseMoveEvent(PlatformMouseEventBuilder(m_widget, event)); |
|
102 } |
|
103 |
|
104 void WebPopupMenuImpl::MouseDown(const WebMouseEvent& event) |
|
105 { |
|
106 m_widget->handleMouseDownEvent(PlatformMouseEventBuilder(m_widget, event)); |
|
107 } |
|
108 |
|
109 void WebPopupMenuImpl::MouseUp(const WebMouseEvent& event) |
|
110 { |
|
111 mouseCaptureLost(); |
|
112 m_widget->handleMouseReleaseEvent(PlatformMouseEventBuilder(m_widget, event)); |
|
113 } |
|
114 |
|
115 void WebPopupMenuImpl::MouseWheel(const WebMouseWheelEvent& event) |
|
116 { |
|
117 m_widget->handleWheelEvent(PlatformWheelEventBuilder(m_widget, event)); |
|
118 } |
|
119 |
|
120 bool WebPopupMenuImpl::KeyEvent(const WebKeyboardEvent& event) |
|
121 { |
|
122 return m_widget->handleKeyEvent(PlatformKeyboardEventBuilder(event)); |
|
123 } |
|
124 |
|
125 // WebWidget ------------------------------------------------------------------- |
|
126 |
|
127 void WebPopupMenuImpl::close() |
|
128 { |
|
129 if (m_widget) |
|
130 m_widget->hide(); |
|
131 |
|
132 m_client = 0; |
|
133 |
|
134 deref(); // Balances ref() from WebWidget::Create |
|
135 } |
|
136 |
|
137 void WebPopupMenuImpl::resize(const WebSize& newSize) |
|
138 { |
|
139 if (m_size == newSize) |
|
140 return; |
|
141 m_size = newSize; |
|
142 |
|
143 if (m_widget) { |
|
144 IntRect newGeometry(0, 0, m_size.width, m_size.height); |
|
145 m_widget->setFrameRect(newGeometry); |
|
146 } |
|
147 |
|
148 if (m_client) { |
|
149 WebRect damagedRect(0, 0, m_size.width, m_size.height); |
|
150 m_client->didInvalidateRect(damagedRect); |
|
151 } |
|
152 } |
|
153 |
|
154 void WebPopupMenuImpl::layout() |
|
155 { |
|
156 } |
|
157 |
|
158 void WebPopupMenuImpl::paint(WebCanvas* canvas, const WebRect& rect) |
|
159 { |
|
160 if (!m_widget) |
|
161 return; |
|
162 |
|
163 if (!rect.isEmpty()) { |
|
164 #if WEBKIT_USING_CG |
|
165 GraphicsContext gc(canvas); |
|
166 #elif WEBKIT_USING_SKIA |
|
167 PlatformContextSkia context(canvas); |
|
168 // PlatformGraphicsContext is actually a pointer to PlatformContextSkia. |
|
169 GraphicsContext gc(reinterpret_cast<PlatformGraphicsContext*>(&context)); |
|
170 #else |
|
171 notImplemented(); |
|
172 #endif |
|
173 m_widget->paint(&gc, rect); |
|
174 } |
|
175 } |
|
176 |
|
177 bool WebPopupMenuImpl::handleInputEvent(const WebInputEvent& inputEvent) |
|
178 { |
|
179 if (!m_widget) |
|
180 return false; |
|
181 |
|
182 // TODO (jcampan): WebKit seems to always return false on mouse events |
|
183 // methods. For now we'll assume it has processed them (as we are only |
|
184 // interested in whether keyboard events are processed). |
|
185 switch (inputEvent.type) { |
|
186 case WebInputEvent::MouseMove: |
|
187 MouseMove(*static_cast<const WebMouseEvent*>(&inputEvent)); |
|
188 return true; |
|
189 |
|
190 case WebInputEvent::MouseLeave: |
|
191 MouseLeave(*static_cast<const WebMouseEvent*>(&inputEvent)); |
|
192 return true; |
|
193 |
|
194 case WebInputEvent::MouseWheel: |
|
195 MouseWheel(*static_cast<const WebMouseWheelEvent*>(&inputEvent)); |
|
196 return true; |
|
197 |
|
198 case WebInputEvent::MouseDown: |
|
199 MouseDown(*static_cast<const WebMouseEvent*>(&inputEvent)); |
|
200 return true; |
|
201 |
|
202 case WebInputEvent::MouseUp: |
|
203 MouseUp(*static_cast<const WebMouseEvent*>(&inputEvent)); |
|
204 return true; |
|
205 |
|
206 // In Windows, RawKeyDown only has information about the physical key, but |
|
207 // for "selection", we need the information about the character the key |
|
208 // translated into. For English, the physical key value and the character |
|
209 // value are the same, hence, "selection" works for English. But for other |
|
210 // languages, such as Hebrew, the character value is different from the |
|
211 // physical key value. Thus, without accepting Char event type which |
|
212 // contains the key's character value, the "selection" won't work for |
|
213 // non-English languages, such as Hebrew. |
|
214 case WebInputEvent::RawKeyDown: |
|
215 case WebInputEvent::KeyDown: |
|
216 case WebInputEvent::KeyUp: |
|
217 case WebInputEvent::Char: |
|
218 return KeyEvent(*static_cast<const WebKeyboardEvent*>(&inputEvent)); |
|
219 |
|
220 default: |
|
221 break; |
|
222 } |
|
223 return false; |
|
224 } |
|
225 |
|
226 void WebPopupMenuImpl::mouseCaptureLost() |
|
227 { |
|
228 } |
|
229 |
|
230 void WebPopupMenuImpl::setFocus(bool enable) |
|
231 { |
|
232 } |
|
233 |
|
234 bool WebPopupMenuImpl::setComposition( |
|
235 const WebString& text, const WebVector<WebCompositionUnderline>& underlines, |
|
236 int selectionStart, int selectionEnd) |
|
237 { |
|
238 return false; |
|
239 } |
|
240 |
|
241 bool WebPopupMenuImpl::confirmComposition() |
|
242 { |
|
243 return false; |
|
244 } |
|
245 |
|
246 WebTextInputType WebPopupMenuImpl::textInputType() |
|
247 { |
|
248 return WebTextInputTypeNone; |
|
249 } |
|
250 |
|
251 WebRect WebPopupMenuImpl::caretOrSelectionBounds() |
|
252 { |
|
253 return WebRect(); |
|
254 } |
|
255 |
|
256 void WebPopupMenuImpl::setTextDirection(WebTextDirection direction) |
|
257 { |
|
258 } |
|
259 |
|
260 |
|
261 //----------------------------------------------------------------------------- |
|
262 // WebCore::HostWindow |
|
263 |
|
264 void WebPopupMenuImpl::invalidateContents(const IntRect&, bool) |
|
265 { |
|
266 notImplemented(); |
|
267 } |
|
268 |
|
269 void WebPopupMenuImpl::invalidateWindow(const IntRect&, bool) |
|
270 { |
|
271 notImplemented(); |
|
272 } |
|
273 |
|
274 void WebPopupMenuImpl::invalidateContentsAndWindow(const IntRect& paintRect, bool /*immediate*/) |
|
275 { |
|
276 if (paintRect.isEmpty()) |
|
277 return; |
|
278 if (m_client) |
|
279 m_client->didInvalidateRect(paintRect); |
|
280 } |
|
281 |
|
282 void WebPopupMenuImpl::invalidateContentsForSlowScroll(const IntRect& updateRect, bool immediate) |
|
283 { |
|
284 invalidateContentsAndWindow(updateRect, immediate); |
|
285 } |
|
286 |
|
287 void WebPopupMenuImpl::scroll(const IntSize& scrollDelta, |
|
288 const IntRect& scrollRect, |
|
289 const IntRect& clipRect) |
|
290 { |
|
291 if (m_client) { |
|
292 int dx = scrollDelta.width(); |
|
293 int dy = scrollDelta.height(); |
|
294 m_client->didScrollRect(dx, dy, clipRect); |
|
295 } |
|
296 } |
|
297 |
|
298 IntPoint WebPopupMenuImpl::screenToWindow(const IntPoint& point) const |
|
299 { |
|
300 notImplemented(); |
|
301 return IntPoint(); |
|
302 } |
|
303 |
|
304 IntRect WebPopupMenuImpl::windowToScreen(const IntRect& rect) const |
|
305 { |
|
306 notImplemented(); |
|
307 return IntRect(); |
|
308 } |
|
309 |
|
310 void WebPopupMenuImpl::scrollRectIntoView(const IntRect&, const ScrollView*) const |
|
311 { |
|
312 // Nothing to be done here since we do not have the concept of a container |
|
313 // that implements its own scrolling. |
|
314 } |
|
315 |
|
316 void WebPopupMenuImpl::scrollbarsModeDidChange() const |
|
317 { |
|
318 // Nothing to be done since we have no concept of different scrollbar modes. |
|
319 } |
|
320 |
|
321 void WebPopupMenuImpl::setCursor(const WebCore::Cursor&) |
|
322 { |
|
323 } |
|
324 |
|
325 //----------------------------------------------------------------------------- |
|
326 // WebCore::FramelessScrollViewClient |
|
327 |
|
328 void WebPopupMenuImpl::popupClosed(FramelessScrollView* widget) |
|
329 { |
|
330 ASSERT(widget == m_widget); |
|
331 if (m_widget) { |
|
332 m_widget->setClient(0); |
|
333 m_widget = 0; |
|
334 } |
|
335 m_client->closeWidgetSoon(); |
|
336 } |
|
337 |
|
338 } // namespace WebKit |