8344863facced3899d7996d35b0fdbf06b32564f
[WebKit-https.git] / Source / WebKit / chromium / src / WebPopupMenuImpl.cpp
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 "FrameView.h"
36 #include "FramelessScrollView.h"
37 #include "IntRect.h"
38 #include "NotImplemented.h"
39 #include "PlatformKeyboardEvent.h"
40 #include "PlatformMouseEvent.h"
41 #include "PlatformWheelEvent.h"
42 #include "PopupContainer.h"
43 #include "PopupMenuChromium.h"
44 #include "SkiaUtils.h"
45 #include "WebInputEvent.h"
46 #include "WebInputEventConversion.h"
47 #include "WebRange.h"
48 #include "WebViewClient.h"
49 #include "WebWidgetClient.h"
50 #include "painting/GraphicsContextBuilder.h"
51 #include <public/WebRect.h>
52 #include <skia/ext/platform_canvas.h>
53
54 #if ENABLE(GESTURE_EVENTS)
55 #include "PlatformGestureEvent.h"
56 #endif
57
58 using namespace WebCore;
59
60 namespace WebKit {
61
62 // WebPopupMenu ---------------------------------------------------------------
63
64 WebPopupMenu* WebPopupMenu::create(WebWidgetClient* client)
65 {
66     // Pass the WebPopupMenuImpl's self-reference to the caller.
67     return adoptRef(new WebPopupMenuImpl(client)).leakRef();
68 }
69
70 // WebWidget ------------------------------------------------------------------
71
72 WebPopupMenuImpl::WebPopupMenuImpl(WebWidgetClient* client)
73     : m_client(client)
74     , m_widget(0)
75 {
76     // Set to impossible point so we always get the first mouse position.
77     m_lastMousePosition = WebPoint(-1, -1);
78 }
79
80 WebPopupMenuImpl::~WebPopupMenuImpl()
81 {
82     if (m_widget)
83         m_widget->setClient(0);
84 }
85
86 void WebPopupMenuImpl::initialize(FramelessScrollView* widget, const WebRect& bounds)
87 {
88     m_widget = widget;
89     m_widget->setClient(this);
90
91     if (m_client) {
92         m_client->setWindowRect(bounds);
93         m_client->show(WebNavigationPolicy()); // Policy is ignored.
94     }
95 }
96
97 void WebPopupMenuImpl::handleMouseMove(const WebMouseEvent& event)
98 {
99     // Don't send mouse move messages if the mouse hasn't moved.
100     if (event.x != m_lastMousePosition.x || event.y != m_lastMousePosition.y) {
101         m_lastMousePosition = WebPoint(event.x, event.y);
102         m_widget->handleMouseMoveEvent(PlatformMouseEventBuilder(m_widget, event));
103
104         // We cannot call setToolTipText() in PopupContainer, because PopupContainer is in WebCore, and we cannot refer to WebKit from Webcore.
105         WebCore::PopupContainer* container = static_cast<WebCore::PopupContainer*>(m_widget);
106         client()->setToolTipText(container->getSelectedItemToolTip(), container->menuStyle().textDirection() == WebCore::RTL ? WebTextDirectionRightToLeft : WebTextDirectionLeftToRight);
107     }
108 }
109
110 void WebPopupMenuImpl::handleMouseLeave(const WebMouseEvent& event)
111 {
112     m_widget->handleMouseMoveEvent(PlatformMouseEventBuilder(m_widget, event));
113 }
114
115 void WebPopupMenuImpl::handleMouseDown(const WebMouseEvent& event)
116 {
117     m_widget->handleMouseDownEvent(PlatformMouseEventBuilder(m_widget, event));
118 }
119
120 void WebPopupMenuImpl::handleMouseUp(const WebMouseEvent& event)
121 {
122     mouseCaptureLost();
123     m_widget->handleMouseReleaseEvent(PlatformMouseEventBuilder(m_widget, event));
124 }
125
126 void WebPopupMenuImpl::handleMouseWheel(const WebMouseWheelEvent& event)
127 {
128     m_widget->handleWheelEvent(PlatformWheelEventBuilder(m_widget, event));
129 }
130
131 bool WebPopupMenuImpl::handleGestureEvent(const WebGestureEvent& event)
132 {
133     return m_widget->handleGestureEvent(PlatformGestureEventBuilder(m_widget, event));
134 }
135
136 #if ENABLE(TOUCH_EVENTS)
137 bool WebPopupMenuImpl::handleTouchEvent(const WebTouchEvent& event)
138 {
139
140     PlatformTouchEventBuilder touchEventBuilder(m_widget, event);
141     bool defaultPrevented(m_widget->handleTouchEvent(touchEventBuilder));
142     return defaultPrevented;
143 }
144 #endif
145
146 bool WebPopupMenuImpl::handleKeyEvent(const WebKeyboardEvent& event)
147 {
148     return m_widget->handleKeyEvent(PlatformKeyboardEventBuilder(event));
149 }
150
151 // WebWidget -------------------------------------------------------------------
152
153 void WebPopupMenuImpl::close()
154 {
155     if (m_widget)
156         m_widget->hide();
157
158     m_client = 0;
159
160     deref(); // Balances ref() from WebPopupMenu::create.
161 }
162
163 void WebPopupMenuImpl::willStartLiveResize()
164 {
165 }
166
167 void WebPopupMenuImpl::resize(const WebSize& newSize)
168 {
169     if (m_size == newSize)
170         return;
171     m_size = newSize;
172
173     if (m_widget) {
174         IntRect newGeometry(0, 0, m_size.width, m_size.height);
175         m_widget->setFrameRect(newGeometry);
176     }
177
178     if (m_client) {
179         WebRect damagedRect(0, 0, m_size.width, m_size.height);
180         m_client->didInvalidateRect(damagedRect);
181     }
182 }
183
184 void WebPopupMenuImpl::willEndLiveResize()
185 {
186 }
187
188 void WebPopupMenuImpl::animate(double)
189 {
190 }
191
192 void WebPopupMenuImpl::layout()
193 {
194 }
195
196 void WebPopupMenuImpl::paint(WebCanvas* canvas, const WebRect& rect, PaintOptions)
197 {
198     if (!m_widget)
199         return;
200
201     if (!rect.isEmpty()) {
202         GraphicsContextBuilder builder(canvas);
203         GraphicsContext& context = builder.context();
204         context.applyDeviceScaleFactor(m_client->deviceScaleFactor());
205         m_widget->paint(&context, rect);
206     }
207 }
208
209 void WebPopupMenuImpl::themeChanged()
210 {
211     notImplemented();
212 }
213
214 void WebPopupMenuImpl::setCompositorSurfaceReady()
215 {
216     notImplemented();
217 }
218
219 void WebPopupMenuImpl::composite(bool)
220 {
221     notImplemented();
222 }
223
224 bool WebPopupMenuImpl::handleInputEvent(const WebInputEvent& inputEvent)
225 {
226     if (!m_widget)
227         return false;
228
229     // FIXME: WebKit seems to always return false on mouse events methods. For
230     // now we'll assume it has processed them (as we are only interested in
231     // whether keyboard events are processed).
232     switch (inputEvent.type) {
233     case WebInputEvent::MouseMove:
234         handleMouseMove(*static_cast<const WebMouseEvent*>(&inputEvent));
235         return true;
236
237     case WebInputEvent::MouseLeave:
238         handleMouseLeave(*static_cast<const WebMouseEvent*>(&inputEvent));
239         return true;
240
241     case WebInputEvent::MouseWheel:
242         handleMouseWheel(*static_cast<const WebMouseWheelEvent*>(&inputEvent));
243         return true;
244
245     case WebInputEvent::MouseDown:
246         handleMouseDown(*static_cast<const WebMouseEvent*>(&inputEvent));
247         return true;
248
249     case WebInputEvent::MouseUp:
250         handleMouseUp(*static_cast<const WebMouseEvent*>(&inputEvent));
251         return true;
252
253     // In Windows, RawKeyDown only has information about the physical key, but
254     // for "selection", we need the information about the character the key
255     // translated into. For English, the physical key value and the character
256     // value are the same, hence, "selection" works for English. But for other
257     // languages, such as Hebrew, the character value is different from the
258     // physical key value. Thus, without accepting Char event type which
259     // contains the key's character value, the "selection" won't work for
260     // non-English languages, such as Hebrew.
261     case WebInputEvent::RawKeyDown:
262     case WebInputEvent::KeyDown:
263     case WebInputEvent::KeyUp:
264     case WebInputEvent::Char:
265         return handleKeyEvent(*static_cast<const WebKeyboardEvent*>(&inputEvent));
266
267     case WebInputEvent::TouchStart:
268     case WebInputEvent::TouchMove:
269     case WebInputEvent::TouchEnd:
270     case WebInputEvent::TouchCancel:
271         return handleTouchEvent(*static_cast<const WebTouchEvent*>(&inputEvent));
272
273     case WebInputEvent::GestureScrollBegin:
274     case WebInputEvent::GestureScrollEnd:
275     case WebInputEvent::GestureScrollUpdate:
276     case WebInputEvent::GestureScrollUpdateWithoutPropagation:
277     case WebInputEvent::GestureFlingStart:
278     case WebInputEvent::GestureFlingCancel:
279     case WebInputEvent::GestureTap:
280     case WebInputEvent::GestureTapDown:
281     case WebInputEvent::GestureTapCancel:
282     case WebInputEvent::GestureDoubleTap:
283     case WebInputEvent::GestureTwoFingerTap:
284     case WebInputEvent::GestureLongPress:
285     case WebInputEvent::GestureLongTap:
286     case WebInputEvent::GesturePinchBegin:
287     case WebInputEvent::GesturePinchEnd:
288     case WebInputEvent::GesturePinchUpdate:
289         return handleGestureEvent(*static_cast<const WebGestureEvent*>(&inputEvent));
290
291     case WebInputEvent::Undefined:
292     case WebInputEvent::MouseEnter:
293     case WebInputEvent::ContextMenu:
294         return false;
295     }
296     return false;
297 }
298
299 void WebPopupMenuImpl::mouseCaptureLost()
300 {
301 }
302
303 void WebPopupMenuImpl::setFocus(bool)
304 {
305 }
306
307 void WebPopupMenu::setMinimumRowHeight(int minimumRowHeight)
308 {
309     PopupMenuChromium::setMinimumRowHeight(minimumRowHeight);
310 }
311
312 bool WebPopupMenuImpl::setComposition(const WebString&, const WebVector<WebCompositionUnderline>&, int, int)
313 {
314     return false;
315 }
316
317 bool WebPopupMenuImpl::confirmComposition()
318 {
319     return false;
320 }
321
322 bool WebPopupMenuImpl::confirmComposition(const WebString&)
323 {
324     return false;
325 }
326
327 bool WebPopupMenuImpl::compositionRange(size_t* location, size_t* length)
328 {
329     *location = 0;
330     *length = 0;
331     return false;
332 }
333
334 WebTextInputType WebPopupMenuImpl::textInputType()
335 {
336     return WebTextInputTypeNone;
337 }
338
339 bool WebPopupMenuImpl::caretOrSelectionRange(size_t* location, size_t* length)
340 {
341     *location = 0;
342     *length = 0;
343     return false;
344 }
345
346 void WebPopupMenuImpl::setTextDirection(WebTextDirection)
347 {
348 }
349
350
351 //-----------------------------------------------------------------------------
352 // WebCore::HostWindow
353
354 void WebPopupMenuImpl::invalidateRootView(const IntRect&, bool)
355 {
356     notImplemented();
357 }
358
359 void WebPopupMenuImpl::invalidateContentsAndRootView(const IntRect& paintRect, bool /*immediate*/)
360 {
361     if (paintRect.isEmpty())
362         return;
363     if (m_client)
364         m_client->didInvalidateRect(paintRect);
365 }
366
367 void WebPopupMenuImpl::invalidateContentsForSlowScroll(const IntRect& updateRect, bool immediate)
368 {
369     invalidateContentsAndRootView(updateRect, immediate);
370 }
371
372 void WebPopupMenuImpl::scheduleAnimation()
373 {
374 }
375
376 void WebPopupMenuImpl::scroll(const IntSize& scrollDelta, const IntRect& scrollRect, const IntRect& clipRect)
377 {
378     if (m_client) {
379         int dx = scrollDelta.width();
380         int dy = scrollDelta.height();
381         m_client->didScrollRect(dx, dy, clipRect);
382     }
383 }
384
385 IntPoint WebPopupMenuImpl::screenToRootView(const IntPoint& point) const
386 {
387     notImplemented();
388     return IntPoint();
389 }
390
391 IntRect WebPopupMenuImpl::rootViewToScreen(const IntRect& rect) const
392 {
393     notImplemented();
394     return IntRect();
395 }
396
397 void WebPopupMenuImpl::scrollbarsModeDidChange() const
398 {
399     // Nothing to be done since we have no concept of different scrollbar modes.
400 }
401
402 void WebPopupMenuImpl::setCursor(const WebCore::Cursor&)
403 {
404 }
405
406 void WebPopupMenuImpl::setCursorHiddenUntilMouseMoves(bool)
407 {
408 }
409
410 //-----------------------------------------------------------------------------
411 // WebCore::FramelessScrollViewClient
412
413 void WebPopupMenuImpl::popupClosed(FramelessScrollView* widget)
414 {
415     ASSERT(widget == m_widget);
416     if (m_widget) {
417         m_widget->setClient(0);
418         m_widget = 0;
419     }
420     if (m_client)
421         m_client->closeWidgetSoon();
422 }
423
424 } // namespace WebKit