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 "PlatformContextSkia.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 return new WebPopupMenuImpl(client);
60 }
61
62 // WebWidget ------------------------------------------------------------------
63
WebPopupMenuImpl(WebWidgetClient * client)64 WebPopupMenuImpl::WebPopupMenuImpl(WebWidgetClient* client)
65 : m_client(client)
66 , m_widget(0)
67 {
68 // set to impossible point so we always get the first mouse pos
69 m_lastMousePosition = WebPoint(-1, -1);
70 }
71
~WebPopupMenuImpl()72 WebPopupMenuImpl::~WebPopupMenuImpl()
73 {
74 if (m_widget)
75 m_widget->setClient(0);
76 }
77
Init(FramelessScrollView * widget,const WebRect & bounds)78 void WebPopupMenuImpl::Init(FramelessScrollView* widget, const WebRect& bounds)
79 {
80 m_widget = widget;
81 m_widget->setClient(this);
82
83 if (m_client) {
84 m_client->setWindowRect(bounds);
85 m_client->show(WebNavigationPolicy()); // Policy is ignored
86 }
87 }
88
MouseMove(const WebMouseEvent & event)89 void WebPopupMenuImpl::MouseMove(const WebMouseEvent& event)
90 {
91 // don't send mouse move messages if the mouse hasn't moved.
92 if (event.x != m_lastMousePosition.x || event.y != m_lastMousePosition.y) {
93 m_lastMousePosition = WebPoint(event.x, event.y);
94 m_widget->handleMouseMoveEvent(PlatformMouseEventBuilder(m_widget, event));
95 }
96 }
97
MouseLeave(const WebMouseEvent & event)98 void WebPopupMenuImpl::MouseLeave(const WebMouseEvent& event)
99 {
100 m_widget->handleMouseMoveEvent(PlatformMouseEventBuilder(m_widget, event));
101 }
102
MouseDown(const WebMouseEvent & event)103 void WebPopupMenuImpl::MouseDown(const WebMouseEvent& event)
104 {
105 m_widget->handleMouseDownEvent(PlatformMouseEventBuilder(m_widget, event));
106 }
107
MouseUp(const WebMouseEvent & event)108 void WebPopupMenuImpl::MouseUp(const WebMouseEvent& event)
109 {
110 mouseCaptureLost();
111 m_widget->handleMouseReleaseEvent(PlatformMouseEventBuilder(m_widget, event));
112 }
113
MouseWheel(const WebMouseWheelEvent & event)114 void WebPopupMenuImpl::MouseWheel(const WebMouseWheelEvent& event)
115 {
116 m_widget->handleWheelEvent(PlatformWheelEventBuilder(m_widget, event));
117 }
118
KeyEvent(const WebKeyboardEvent & event)119 bool WebPopupMenuImpl::KeyEvent(const WebKeyboardEvent& event)
120 {
121 return m_widget->handleKeyEvent(PlatformKeyboardEventBuilder(event));
122 }
123
124 // WebWidget -------------------------------------------------------------------
125
close()126 void WebPopupMenuImpl::close()
127 {
128 if (m_widget)
129 m_widget->hide();
130
131 m_client = 0;
132
133 deref(); // Balances ref() from WebWidget::Create
134 }
135
resize(const WebSize & newSize)136 void WebPopupMenuImpl::resize(const WebSize& newSize)
137 {
138 if (m_size == newSize)
139 return;
140 m_size = newSize;
141
142 if (m_widget) {
143 IntRect newGeometry(0, 0, m_size.width, m_size.height);
144 m_widget->setFrameRect(newGeometry);
145 }
146
147 if (m_client) {
148 WebRect damagedRect(0, 0, m_size.width, m_size.height);
149 m_client->didInvalidateRect(damagedRect);
150 }
151 }
152
layout()153 void WebPopupMenuImpl::layout()
154 {
155 }
156
paint(WebCanvas * canvas,const WebRect & rect)157 void WebPopupMenuImpl::paint(WebCanvas* canvas, const WebRect& rect)
158 {
159 if (!m_widget)
160 return;
161
162 if (!rect.isEmpty()) {
163 #if WEBKIT_USING_CG
164 GraphicsContext gc(canvas);
165 #elif WEBKIT_USING_SKIA
166 PlatformContextSkia context(canvas);
167 // PlatformGraphicsContext is actually a pointer to PlatformContextSkia.
168 GraphicsContext gc(reinterpret_cast<PlatformGraphicsContext*>(&context));
169 #else
170 notImplemented();
171 #endif
172 m_widget->paint(&gc, rect);
173 }
174 }
175
handleInputEvent(const WebInputEvent & inputEvent)176 bool WebPopupMenuImpl::handleInputEvent(const WebInputEvent& inputEvent)
177 {
178 if (!m_widget)
179 return false;
180
181 // TODO (jcampan): WebKit seems to always return false on mouse events
182 // methods. For now we'll assume it has processed them (as we are only
183 // interested in whether keyboard events are processed).
184 switch (inputEvent.type) {
185 case WebInputEvent::MouseMove:
186 MouseMove(*static_cast<const WebMouseEvent*>(&inputEvent));
187 return true;
188
189 case WebInputEvent::MouseLeave:
190 MouseLeave(*static_cast<const WebMouseEvent*>(&inputEvent));
191 return true;
192
193 case WebInputEvent::MouseWheel:
194 MouseWheel(*static_cast<const WebMouseWheelEvent*>(&inputEvent));
195 return true;
196
197 case WebInputEvent::MouseDown:
198 MouseDown(*static_cast<const WebMouseEvent*>(&inputEvent));
199 return true;
200
201 case WebInputEvent::MouseUp:
202 MouseUp(*static_cast<const WebMouseEvent*>(&inputEvent));
203 return true;
204
205 // In Windows, RawKeyDown only has information about the physical key, but
206 // for "selection", we need the information about the character the key
207 // translated into. For English, the physical key value and the character
208 // value are the same, hence, "selection" works for English. But for other
209 // languages, such as Hebrew, the character value is different from the
210 // physical key value. Thus, without accepting Char event type which
211 // contains the key's character value, the "selection" won't work for
212 // non-English languages, such as Hebrew.
213 case WebInputEvent::RawKeyDown:
214 case WebInputEvent::KeyDown:
215 case WebInputEvent::KeyUp:
216 case WebInputEvent::Char:
217 return KeyEvent(*static_cast<const WebKeyboardEvent*>(&inputEvent));
218
219 default:
220 break;
221 }
222 return false;
223 }
224
mouseCaptureLost()225 void WebPopupMenuImpl::mouseCaptureLost()
226 {
227 }
228
setFocus(bool enable)229 void WebPopupMenuImpl::setFocus(bool enable)
230 {
231 }
232
handleCompositionEvent(WebCompositionCommand command,int cursorPosition,int targetStart,int targetEnd,const WebString & imeString)233 bool WebPopupMenuImpl::handleCompositionEvent(
234 WebCompositionCommand command, int cursorPosition, int targetStart,
235 int targetEnd, const WebString& imeString)
236 {
237 return false;
238 }
239
queryCompositionStatus(bool * enabled,WebRect * caretRect)240 bool WebPopupMenuImpl::queryCompositionStatus(bool* enabled, WebRect* caretRect)
241 {
242 return false;
243 }
244
setTextDirection(WebTextDirection direction)245 void WebPopupMenuImpl::setTextDirection(WebTextDirection direction)
246 {
247 }
248
249
250 //-----------------------------------------------------------------------------
251 // WebCore::HostWindow
252
repaint(const IntRect & paintRect,bool contentChanged,bool immediate,bool repaintContentOnly)253 void WebPopupMenuImpl::repaint(const IntRect& paintRect,
254 bool contentChanged,
255 bool immediate,
256 bool repaintContentOnly)
257 {
258 // Ignore spurious calls.
259 if (!contentChanged || paintRect.isEmpty())
260 return;
261 if (m_client)
262 m_client->didInvalidateRect(paintRect);
263 }
264
scroll(const IntSize & scrollDelta,const IntRect & scrollRect,const IntRect & clipRect)265 void WebPopupMenuImpl::scroll(const IntSize& scrollDelta,
266 const IntRect& scrollRect,
267 const IntRect& clipRect)
268 {
269 if (m_client) {
270 int dx = scrollDelta.width();
271 int dy = scrollDelta.height();
272 m_client->didScrollRect(dx, dy, clipRect);
273 }
274 }
275
screenToWindow(const IntPoint & point) const276 IntPoint WebPopupMenuImpl::screenToWindow(const IntPoint& point) const
277 {
278 notImplemented();
279 return IntPoint();
280 }
281
windowToScreen(const IntRect & rect) const282 IntRect WebPopupMenuImpl::windowToScreen(const IntRect& rect) const
283 {
284 notImplemented();
285 return IntRect();
286 }
287
scrollRectIntoView(const IntRect &,const ScrollView *) const288 void WebPopupMenuImpl::scrollRectIntoView(const IntRect&, const ScrollView*) const
289 {
290 // Nothing to be done here since we do not have the concept of a container
291 // that implements its own scrolling.
292 }
293
scrollbarsModeDidChange() const294 void WebPopupMenuImpl::scrollbarsModeDidChange() const
295 {
296 // Nothing to be done since we have no concept of different scrollbar modes.
297 }
298
299 //-----------------------------------------------------------------------------
300 // WebCore::FramelessScrollViewClient
301
popupClosed(FramelessScrollView * widget)302 void WebPopupMenuImpl::popupClosed(FramelessScrollView* widget)
303 {
304 ASSERT(widget == m_widget);
305 if (m_widget) {
306 m_widget->setClient(0);
307 m_widget = 0;
308 }
309 m_client->closeWidgetSoon();
310 }
311
312 } // namespace WebKit
313