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