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 "painting/GraphicsContextBuilder.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
create(WebWidgetClient * client)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
WebPopupMenuImpl(WebWidgetClient * client)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
~WebPopupMenuImpl()73 WebPopupMenuImpl::~WebPopupMenuImpl()
74 {
75 if (m_widget)
76 m_widget->setClient(0);
77 }
78
Init(FramelessScrollView * widget,const WebRect & bounds)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
MouseMove(const WebMouseEvent & event)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
MouseLeave(const WebMouseEvent & event)99 void WebPopupMenuImpl::MouseLeave(const WebMouseEvent& event)
100 {
101 m_widget->handleMouseMoveEvent(PlatformMouseEventBuilder(m_widget, event));
102 }
103
MouseDown(const WebMouseEvent & event)104 void WebPopupMenuImpl::MouseDown(const WebMouseEvent& event)
105 {
106 m_widget->handleMouseDownEvent(PlatformMouseEventBuilder(m_widget, event));
107 }
108
MouseUp(const WebMouseEvent & event)109 void WebPopupMenuImpl::MouseUp(const WebMouseEvent& event)
110 {
111 mouseCaptureLost();
112 m_widget->handleMouseReleaseEvent(PlatformMouseEventBuilder(m_widget, event));
113 }
114
MouseWheel(const WebMouseWheelEvent & event)115 void WebPopupMenuImpl::MouseWheel(const WebMouseWheelEvent& event)
116 {
117 m_widget->handleWheelEvent(PlatformWheelEventBuilder(m_widget, event));
118 }
119
KeyEvent(const WebKeyboardEvent & event)120 bool WebPopupMenuImpl::KeyEvent(const WebKeyboardEvent& event)
121 {
122 return m_widget->handleKeyEvent(PlatformKeyboardEventBuilder(event));
123 }
124
125 // WebWidget -------------------------------------------------------------------
126
close()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
resize(const WebSize & newSize)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
animate()154 void WebPopupMenuImpl::animate()
155 {
156 }
157
layout()158 void WebPopupMenuImpl::layout()
159 {
160 }
161
paint(WebCanvas * canvas,const WebRect & rect)162 void WebPopupMenuImpl::paint(WebCanvas* canvas, const WebRect& rect)
163 {
164 if (!m_widget)
165 return;
166
167 if (!rect.isEmpty())
168 m_widget->paint(&GraphicsContextBuilder(canvas).context(), rect);
169 }
170
themeChanged()171 void WebPopupMenuImpl::themeChanged()
172 {
173 notImplemented();
174 }
175
composite(bool finish)176 void WebPopupMenuImpl::composite(bool finish)
177 {
178 notImplemented();
179 }
180
handleInputEvent(const WebInputEvent & inputEvent)181 bool WebPopupMenuImpl::handleInputEvent(const WebInputEvent& inputEvent)
182 {
183 if (!m_widget)
184 return false;
185
186 // TODO (jcampan): WebKit seems to always return false on mouse events
187 // methods. For now we'll assume it has processed them (as we are only
188 // interested in whether keyboard events are processed).
189 switch (inputEvent.type) {
190 case WebInputEvent::MouseMove:
191 MouseMove(*static_cast<const WebMouseEvent*>(&inputEvent));
192 return true;
193
194 case WebInputEvent::MouseLeave:
195 MouseLeave(*static_cast<const WebMouseEvent*>(&inputEvent));
196 return true;
197
198 case WebInputEvent::MouseWheel:
199 MouseWheel(*static_cast<const WebMouseWheelEvent*>(&inputEvent));
200 return true;
201
202 case WebInputEvent::MouseDown:
203 MouseDown(*static_cast<const WebMouseEvent*>(&inputEvent));
204 return true;
205
206 case WebInputEvent::MouseUp:
207 MouseUp(*static_cast<const WebMouseEvent*>(&inputEvent));
208 return true;
209
210 // In Windows, RawKeyDown only has information about the physical key, but
211 // for "selection", we need the information about the character the key
212 // translated into. For English, the physical key value and the character
213 // value are the same, hence, "selection" works for English. But for other
214 // languages, such as Hebrew, the character value is different from the
215 // physical key value. Thus, without accepting Char event type which
216 // contains the key's character value, the "selection" won't work for
217 // non-English languages, such as Hebrew.
218 case WebInputEvent::RawKeyDown:
219 case WebInputEvent::KeyDown:
220 case WebInputEvent::KeyUp:
221 case WebInputEvent::Char:
222 return KeyEvent(*static_cast<const WebKeyboardEvent*>(&inputEvent));
223
224 default:
225 break;
226 }
227 return false;
228 }
229
mouseCaptureLost()230 void WebPopupMenuImpl::mouseCaptureLost()
231 {
232 }
233
setFocus(bool enable)234 void WebPopupMenuImpl::setFocus(bool enable)
235 {
236 }
237
setComposition(const WebString & text,const WebVector<WebCompositionUnderline> & underlines,int selectionStart,int selectionEnd)238 bool WebPopupMenuImpl::setComposition(
239 const WebString& text, const WebVector<WebCompositionUnderline>& underlines,
240 int selectionStart, int selectionEnd)
241 {
242 return false;
243 }
244
confirmComposition()245 bool WebPopupMenuImpl::confirmComposition()
246 {
247 return false;
248 }
249
confirmComposition(const WebString & text)250 bool WebPopupMenuImpl::confirmComposition(const WebString& text)
251 {
252 return false;
253 }
254
textInputType()255 WebTextInputType WebPopupMenuImpl::textInputType()
256 {
257 return WebTextInputTypeNone;
258 }
259
caretOrSelectionBounds()260 WebRect WebPopupMenuImpl::caretOrSelectionBounds()
261 {
262 return WebRect();
263 }
264
setTextDirection(WebTextDirection direction)265 void WebPopupMenuImpl::setTextDirection(WebTextDirection direction)
266 {
267 }
268
269
270 //-----------------------------------------------------------------------------
271 // WebCore::HostWindow
272
invalidateContents(const IntRect &,bool)273 void WebPopupMenuImpl::invalidateContents(const IntRect&, bool)
274 {
275 notImplemented();
276 }
277
invalidateWindow(const IntRect &,bool)278 void WebPopupMenuImpl::invalidateWindow(const IntRect&, bool)
279 {
280 notImplemented();
281 }
282
invalidateContentsAndWindow(const IntRect & paintRect,bool)283 void WebPopupMenuImpl::invalidateContentsAndWindow(const IntRect& paintRect, bool /*immediate*/)
284 {
285 if (paintRect.isEmpty())
286 return;
287 if (m_client)
288 m_client->didInvalidateRect(paintRect);
289 }
290
invalidateContentsForSlowScroll(const IntRect & updateRect,bool immediate)291 void WebPopupMenuImpl::invalidateContentsForSlowScroll(const IntRect& updateRect, bool immediate)
292 {
293 invalidateContentsAndWindow(updateRect, immediate);
294 }
295
scheduleAnimation()296 void WebPopupMenuImpl::scheduleAnimation()
297 {
298 }
299
scroll(const IntSize & scrollDelta,const IntRect & scrollRect,const IntRect & clipRect)300 void WebPopupMenuImpl::scroll(const IntSize& scrollDelta,
301 const IntRect& scrollRect,
302 const IntRect& clipRect)
303 {
304 if (m_client) {
305 int dx = scrollDelta.width();
306 int dy = scrollDelta.height();
307 m_client->didScrollRect(dx, dy, clipRect);
308 }
309 }
310
screenToWindow(const IntPoint & point) const311 IntPoint WebPopupMenuImpl::screenToWindow(const IntPoint& point) const
312 {
313 notImplemented();
314 return IntPoint();
315 }
316
windowToScreen(const IntRect & rect) const317 IntRect WebPopupMenuImpl::windowToScreen(const IntRect& rect) const
318 {
319 notImplemented();
320 return IntRect();
321 }
322
scrollRectIntoView(const IntRect &,const ScrollView *) const323 void WebPopupMenuImpl::scrollRectIntoView(const IntRect&, const ScrollView*) const
324 {
325 // Nothing to be done here since we do not have the concept of a container
326 // that implements its own scrolling.
327 }
328
scrollbarsModeDidChange() const329 void WebPopupMenuImpl::scrollbarsModeDidChange() const
330 {
331 // Nothing to be done since we have no concept of different scrollbar modes.
332 }
333
setCursor(const WebCore::Cursor &)334 void WebPopupMenuImpl::setCursor(const WebCore::Cursor&)
335 {
336 }
337
338 //-----------------------------------------------------------------------------
339 // WebCore::FramelessScrollViewClient
340
popupClosed(FramelessScrollView * widget)341 void WebPopupMenuImpl::popupClosed(FramelessScrollView* widget)
342 {
343 ASSERT(widget == m_widget);
344 if (m_widget) {
345 m_widget->setClient(0);
346 m_widget = 0;
347 }
348 m_client->closeWidgetSoon();
349 }
350
351 } // namespace WebKit
352