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 51using namespace WebCore; 52 53namespace WebKit { 54 55// WebPopupMenu --------------------------------------------------------------- 56 57WebPopupMenu* 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 65WebPopupMenuImpl::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 73WebPopupMenuImpl::~WebPopupMenuImpl() 74{ 75 if (m_widget) 76 m_widget->setClient(0); 77} 78 79void 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 90void 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 99void WebPopupMenuImpl::MouseLeave(const WebMouseEvent& event) 100{ 101 m_widget->handleMouseMoveEvent(PlatformMouseEventBuilder(m_widget, event)); 102} 103 104void WebPopupMenuImpl::MouseDown(const WebMouseEvent& event) 105{ 106 m_widget->handleMouseDownEvent(PlatformMouseEventBuilder(m_widget, event)); 107} 108 109void WebPopupMenuImpl::MouseUp(const WebMouseEvent& event) 110{ 111 mouseCaptureLost(); 112 m_widget->handleMouseReleaseEvent(PlatformMouseEventBuilder(m_widget, event)); 113} 114 115void WebPopupMenuImpl::MouseWheel(const WebMouseWheelEvent& event) 116{ 117 m_widget->handleWheelEvent(PlatformWheelEventBuilder(m_widget, event)); 118} 119 120bool WebPopupMenuImpl::KeyEvent(const WebKeyboardEvent& event) 121{ 122 return m_widget->handleKeyEvent(PlatformKeyboardEventBuilder(event)); 123} 124 125// WebWidget ------------------------------------------------------------------- 126 127void 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 137void 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 154void WebPopupMenuImpl::animate() 155{ 156} 157 158void WebPopupMenuImpl::layout() 159{ 160} 161 162void 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 171void WebPopupMenuImpl::themeChanged() 172{ 173 notImplemented(); 174} 175 176void WebPopupMenuImpl::composite(bool finish) 177{ 178 notImplemented(); 179} 180 181bool 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 230void WebPopupMenuImpl::mouseCaptureLost() 231{ 232} 233 234void WebPopupMenuImpl::setFocus(bool enable) 235{ 236} 237 238bool WebPopupMenuImpl::setComposition( 239 const WebString& text, const WebVector<WebCompositionUnderline>& underlines, 240 int selectionStart, int selectionEnd) 241{ 242 return false; 243} 244 245bool WebPopupMenuImpl::confirmComposition() 246{ 247 return false; 248} 249 250bool WebPopupMenuImpl::confirmComposition(const WebString& text) 251{ 252 return false; 253} 254 255WebTextInputType WebPopupMenuImpl::textInputType() 256{ 257 return WebTextInputTypeNone; 258} 259 260WebRect WebPopupMenuImpl::caretOrSelectionBounds() 261{ 262 return WebRect(); 263} 264 265void WebPopupMenuImpl::setTextDirection(WebTextDirection direction) 266{ 267} 268 269 270//----------------------------------------------------------------------------- 271// WebCore::HostWindow 272 273void WebPopupMenuImpl::invalidateContents(const IntRect&, bool) 274{ 275 notImplemented(); 276} 277 278void WebPopupMenuImpl::invalidateWindow(const IntRect&, bool) 279{ 280 notImplemented(); 281} 282 283void 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 291void WebPopupMenuImpl::invalidateContentsForSlowScroll(const IntRect& updateRect, bool immediate) 292{ 293 invalidateContentsAndWindow(updateRect, immediate); 294} 295 296void WebPopupMenuImpl::scheduleAnimation() 297{ 298} 299 300void 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 311IntPoint WebPopupMenuImpl::screenToWindow(const IntPoint& point) const 312{ 313 notImplemented(); 314 return IntPoint(); 315} 316 317IntRect WebPopupMenuImpl::windowToScreen(const IntRect& rect) const 318{ 319 notImplemented(); 320 return IntRect(); 321} 322 323void 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 329void WebPopupMenuImpl::scrollbarsModeDidChange() const 330{ 331 // Nothing to be done since we have no concept of different scrollbar modes. 332} 333 334void WebPopupMenuImpl::setCursor(const WebCore::Cursor&) 335{ 336} 337 338//----------------------------------------------------------------------------- 339// WebCore::FramelessScrollViewClient 340 341void 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