[GTK] Add initial gestures support
[WebKit-https.git] / Source / WebKit2 / UIProcess / API / gtk / PageClientImpl.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  * Portions Copyright (c) 2010 Motorola Mobility, Inc.  All rights reserved.
4  * Copyright (C) 2011 Igalia S.L.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
19  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
25  * THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include "config.h"
29 #include "PageClientImpl.h"
30
31 #include "DrawingAreaProxyImpl.h"
32 #include "NativeWebKeyboardEvent.h"
33 #include "NativeWebMouseEvent.h"
34 #include "NotImplemented.h"
35 #include "WebContext.h"
36 #include "WebContextMenuProxyGtk.h"
37 #include "WebEventFactory.h"
38 #include "WebKitWebViewBasePrivate.h"
39 #include "WebPageProxy.h"
40 #include "WebPopupMenuProxyGtk.h"
41 #include <WebCore/Cursor.h>
42 #include <WebCore/EventNames.h>
43 #include <WebCore/GtkUtilities.h>
44 #include <wtf/text/CString.h>
45 #include <wtf/text/WTFString.h>
46
47 using namespace WebCore;
48
49 namespace WebKit {
50
51 PageClientImpl::PageClientImpl(GtkWidget* viewWidget)
52     : m_viewWidget(viewWidget)
53 {
54 }
55
56 void PageClientImpl::getEditorCommandsForKeyEvent(const NativeWebKeyboardEvent& event, const AtomicString& eventType, Vector<WTF::String>& commandList)
57 {
58     ASSERT(eventType == eventNames().keydownEvent || eventType == eventNames().keypressEvent);
59
60     KeyBindingTranslator::EventType type = eventType == eventNames().keydownEvent ?
61         KeyBindingTranslator::KeyDown : KeyBindingTranslator::KeyPress;
62     m_keyBindingTranslator.getEditorCommandsForKeyEvent(const_cast<GdkEventKey*>(&event.nativeEvent()->key), type, commandList);
63 }
64
65 // PageClient's pure virtual functions
66 std::unique_ptr<DrawingAreaProxy> PageClientImpl::createDrawingAreaProxy()
67 {
68     return std::make_unique<DrawingAreaProxyImpl>(*webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(m_viewWidget)));
69 }
70
71 void PageClientImpl::setViewNeedsDisplay(const WebCore::IntRect& rect)
72 {
73     gtk_widget_queue_draw_area(m_viewWidget, rect.x(), rect.y(), rect.width(), rect.height());
74 }
75
76 void PageClientImpl::displayView()
77 {
78     notImplemented();
79 }
80
81 void PageClientImpl::scrollView(const WebCore::IntRect& scrollRect, const WebCore::IntSize& /* scrollOffset */)
82 {
83     setViewNeedsDisplay(scrollRect);
84 }
85
86 void PageClientImpl::requestScroll(const WebCore::FloatPoint&, bool)
87 {
88     notImplemented();
89 }
90
91 WebCore::IntSize PageClientImpl::viewSize()
92 {
93     if (!gtk_widget_get_realized(m_viewWidget))
94         return IntSize();
95     GtkAllocation allocation;
96     gtk_widget_get_allocation(m_viewWidget, &allocation);
97     return IntSize(allocation.width, allocation.height);
98 }
99
100 bool PageClientImpl::isViewWindowActive()
101 {
102     return webkitWebViewBaseIsInWindowActive(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
103 }
104
105 bool PageClientImpl::isViewFocused()
106 {
107     return webkitWebViewBaseIsFocused(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
108 }
109
110 bool PageClientImpl::isViewVisible()
111 {
112     return webkitWebViewBaseIsVisible(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
113 }
114
115 bool PageClientImpl::isViewInWindow()
116 {
117     return webkitWebViewBaseIsInWindow(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
118 }
119
120 void PageClientImpl::PageClientImpl::processDidExit()
121 {
122     notImplemented();
123 }
124
125 void PageClientImpl::didRelaunchProcess()
126 {
127     notImplemented();
128 }
129
130 void PageClientImpl::toolTipChanged(const String&, const String& newToolTip)
131 {
132     webkitWebViewBaseSetTooltipText(WEBKIT_WEB_VIEW_BASE(m_viewWidget), newToolTip.utf8().data());
133 }
134
135 void PageClientImpl::setCursor(const Cursor& cursor)
136 {
137     if (!gtk_widget_get_realized(m_viewWidget))
138         return;
139
140     // [GTK] Widget::setCursor() gets called frequently
141     // http://bugs.webkit.org/show_bug.cgi?id=16388
142     // Setting the cursor may be an expensive operation in some backends,
143     // so don't re-set the cursor if it's already set to the target value.
144     GdkWindow* window = gtk_widget_get_window(m_viewWidget);
145     GdkCursor* currentCursor = gdk_window_get_cursor(window);
146     GdkCursor* newCursor = cursor.platformCursor().get();
147     if (currentCursor != newCursor)
148         gdk_window_set_cursor(window, newCursor);
149 }
150
151 void PageClientImpl::setCursorHiddenUntilMouseMoves(bool /* hiddenUntilMouseMoves */)
152 {
153     notImplemented();
154 }
155
156 void PageClientImpl::didChangeViewportProperties(const WebCore::ViewportAttributes&)
157 {
158     notImplemented();
159 }
160
161 void PageClientImpl::registerEditCommand(PassRefPtr<WebEditCommandProxy> command, WebPageProxy::UndoOrRedo undoOrRedo)
162 {
163     m_undoController.registerEditCommand(command, undoOrRedo);
164 }
165
166 void PageClientImpl::clearAllEditCommands()
167 {
168     m_undoController.clearAllEditCommands();
169 }
170
171 bool PageClientImpl::canUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo)
172 {
173     return m_undoController.canUndoRedo(undoOrRedo);
174 }
175
176 void PageClientImpl::executeUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo)
177 {
178     m_undoController.executeUndoRedo(undoOrRedo);
179 }
180
181 FloatRect PageClientImpl::convertToDeviceSpace(const FloatRect& viewRect)
182 {
183     notImplemented();
184     return viewRect;
185 }
186
187 FloatRect PageClientImpl::convertToUserSpace(const FloatRect& viewRect)
188 {
189     notImplemented();
190     return viewRect;
191 }
192
193 IntPoint PageClientImpl::screenToRootView(const IntPoint& point)
194 {
195     IntPoint widgetPositionOnScreen = convertWidgetPointToScreenPoint(m_viewWidget, IntPoint());
196     IntPoint result(point);
197     result.move(-widgetPositionOnScreen.x(), -widgetPositionOnScreen.y());
198     return result;
199 }
200
201 IntRect PageClientImpl::rootViewToScreen(const IntRect& rect)
202 {
203     return IntRect(convertWidgetPointToScreenPoint(m_viewWidget, rect.location()), rect.size());
204 }
205
206 void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool wasEventHandled)
207 {
208     if (wasEventHandled)
209         return;
210     if (event.isFakeEventForComposition())
211         return;
212
213     WebKitWebViewBase* webkitWebViewBase = WEBKIT_WEB_VIEW_BASE(m_viewWidget);
214     webkitWebViewBaseForwardNextKeyEvent(webkitWebViewBase);
215     gtk_main_do_event(event.nativeEvent());
216 }
217
218 PassRefPtr<WebPopupMenuProxy> PageClientImpl::createPopupMenuProxy(WebPageProxy* page)
219 {
220     return WebPopupMenuProxyGtk::create(m_viewWidget, page);
221 }
222
223 PassRefPtr<WebContextMenuProxy> PageClientImpl::createContextMenuProxy(WebPageProxy* page)
224 {
225     return WebContextMenuProxyGtk::create(m_viewWidget, page);
226 }
227
228 #if ENABLE(INPUT_TYPE_COLOR)
229 PassRefPtr<WebColorPicker> PageClientImpl::createColorPicker(WebPageProxy*, const WebCore::Color&, const WebCore::IntRect&)
230 {
231     notImplemented();
232     return 0;
233 }
234 #endif
235
236 void PageClientImpl::setFindIndicator(PassRefPtr<FindIndicator>, bool /* fadeOut */, bool /* animate */)
237 {
238     notImplemented();
239 }
240
241 void PageClientImpl::enterAcceleratedCompositingMode(const LayerTreeContext&)
242 {
243     notImplemented();
244 }
245
246 void PageClientImpl::exitAcceleratedCompositingMode()
247 {
248     notImplemented();
249 }
250
251 void PageClientImpl::updateAcceleratedCompositingMode(const LayerTreeContext&)
252 {
253     notImplemented();
254 }
255
256 void PageClientImpl::pageClosed()
257 {
258     notImplemented();
259 }
260
261 void PageClientImpl::preferencesDidChange()
262 {
263     notImplemented();
264 }
265
266 void PageClientImpl::updateTextInputState()
267 {
268     webkitWebViewBaseUpdateTextInputState(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
269 }
270
271 #if ENABLE(DRAG_SUPPORT)
272 void PageClientImpl::startDrag(const WebCore::DragData& dragData, PassRefPtr<ShareableBitmap> dragImage)
273 {
274     WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(m_viewWidget);
275     webkitWebViewBaseDragAndDropHandler(webView).startDrag(dragData, dragImage);
276
277     // A drag starting should prevent a double-click from happening. This might
278     // happen if a drag is followed very quickly by another click (like in the WTR).
279     webkitWebViewBaseResetClickCounter(webView);
280 }
281 #endif
282
283 void PageClientImpl::handleDownloadRequest(DownloadProxy* download)
284 {
285     webkitWebViewBaseHandleDownloadRequest(WEBKIT_WEB_VIEW_BASE(m_viewWidget), download);
286 }
287
288 void PageClientImpl::didCommitLoadForMainFrame(const String& /* mimeType */, bool /* useCustomContentProvider */ )
289 {
290     webkitWebViewBaseResetClickCounter(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
291 }
292
293 #if ENABLE(FULLSCREEN_API)
294 WebFullScreenManagerProxyClient& PageClientImpl::fullScreenManagerProxyClient()
295 {
296     return *this;
297 }
298
299 void PageClientImpl::closeFullScreenManager()
300 {
301     notImplemented();
302 }
303
304 bool PageClientImpl::isFullScreen()
305 {
306     notImplemented();
307     return false;
308 }
309
310 void PageClientImpl::enterFullScreen()
311 {
312     if (!m_viewWidget)
313         return;
314
315     webkitWebViewBaseEnterFullScreen(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
316 }
317
318 void PageClientImpl::exitFullScreen()
319 {
320     if (!m_viewWidget)
321         return;
322
323     webkitWebViewBaseExitFullScreen(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
324 }
325
326 void PageClientImpl::beganEnterFullScreen(const IntRect& /* initialFrame */, const IntRect& /* finalFrame */)
327 {
328     notImplemented();
329 }
330
331 void PageClientImpl::beganExitFullScreen(const IntRect& /* initialFrame */, const IntRect& /* finalFrame */)
332 {
333     notImplemented();
334 }
335
336 #endif // ENABLE(FULLSCREEN_API)
337
338 void PageClientImpl::doneWithTouchEvent(const NativeWebTouchEvent& event, bool wasEventHandled)
339 {
340     if (wasEventHandled)
341         return;
342
343 #if HAVE(GTK_GESTURES)
344     GestureController& gestureController = webkitWebViewBaseGestureController(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
345     if (gestureController.handleEvent(event.nativeEvent()))
346         return;
347 #endif
348
349     // Emulate pointer events if unhandled.
350     const GdkEvent* touchEvent = event.nativeEvent();
351
352     if (!touchEvent->touch.emulating_pointer)
353         return;
354
355     GUniquePtr<GdkEvent> pointerEvent;
356
357     if (touchEvent->type == GDK_TOUCH_UPDATE) {
358         pointerEvent.reset(gdk_event_new(GDK_MOTION_NOTIFY));
359         pointerEvent->motion.time = touchEvent->touch.time;
360         pointerEvent->motion.x = touchEvent->touch.x;
361         pointerEvent->motion.y = touchEvent->touch.y;
362         pointerEvent->motion.x_root = touchEvent->touch.x_root;
363         pointerEvent->motion.y_root = touchEvent->touch.y_root;
364         pointerEvent->motion.state = touchEvent->touch.state | GDK_BUTTON1_MASK;
365     } else {
366         switch (touchEvent->type) {
367         case GDK_TOUCH_END:
368             pointerEvent.reset(gdk_event_new(GDK_BUTTON_RELEASE));
369             pointerEvent->button.state = touchEvent->touch.state | GDK_BUTTON1_MASK;
370             break;
371         case GDK_TOUCH_BEGIN:
372             pointerEvent.reset(gdk_event_new(GDK_BUTTON_PRESS));
373             break;
374         default:
375             ASSERT_NOT_REACHED();
376         }
377
378         pointerEvent->button.button = 1;
379         pointerEvent->button.time = touchEvent->touch.time;
380         pointerEvent->button.x = touchEvent->touch.x;
381         pointerEvent->button.y = touchEvent->touch.y;
382         pointerEvent->button.x_root = touchEvent->touch.x_root;
383         pointerEvent->button.y_root = touchEvent->touch.y_root;
384     }
385
386     gdk_event_set_device(pointerEvent.get(), gdk_event_get_device(touchEvent));
387     gdk_event_set_source_device(pointerEvent.get(), gdk_event_get_source_device(touchEvent));
388     pointerEvent->any.window = GDK_WINDOW(g_object_ref(touchEvent->any.window));
389     pointerEvent->any.send_event = TRUE;
390
391     gtk_widget_event(m_viewWidget, pointerEvent.get());
392 }
393
394 void PageClientImpl::didFinishLoadingDataForCustomContentProvider(const String&, const IPC::DataReference&)
395 {
396 }
397
398 void PageClientImpl::navigationGestureDidBegin()
399 {
400 }
401
402 void PageClientImpl::navigationGestureWillEnd(bool, WebBackForwardListItem&)
403 {
404 }
405
406 void PageClientImpl::navigationGestureDidEnd(bool, WebBackForwardListItem&)
407 {
408 }
409
410 void PageClientImpl::willRecordNavigationSnapshot(WebBackForwardListItem&)
411 {
412 }
413
414 void PageClientImpl::didFirstVisuallyNonEmptyLayoutForMainFrame()
415 {
416 }
417
418 void PageClientImpl::didFinishLoadForMainFrame()
419 {
420 }
421
422 void PageClientImpl::didSameDocumentNavigationForMainFrame(SameDocumentNavigationType)
423 {
424 }
425
426 } // namespace WebKit