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