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 "WebPage.h"
30
31#include "EditorState.h"
32#include "WebEvent.h"
33#include "WebFrame.h"
34#include "WebKitWebPageAccessibilityObject.h"
35#include "WebPageProxyMessages.h"
36#include "WebProcess.h"
37#include <WebCore/BackForwardController.h>
38#include <WebCore/Editor.h>
39#include <WebCore/EventHandler.h>
40#include <WebCore/FocusController.h>
41#include <WebCore/Frame.h>
42#include <WebCore/FrameView.h>
43#include <WebCore/KeyboardEvent.h>
44#include <WebCore/NotImplemented.h>
45#include <WebCore/Page.h>
46#include <WebCore/PasteboardHelper.h>
47#include <WebCore/PlatformKeyboardEvent.h>
48#include <WebCore/Settings.h>
49#include <WebCore/SharedBuffer.h>
50#include <WebCore/UserAgent.h>
51#include <WebCore/WindowsKeyboardCodes.h>
52#include <wtf/glib/GUniquePtr.h>
53
54namespace WebKit {
55using namespace WebCore;
56
57void WebPage::platformInitialize()
58{
59#if HAVE(ACCESSIBILITY)
60 // Create the accessible object (the plug) that will serve as the
61 // entry point to the Web process, and send a message to the UI
62 // process to connect the two worlds through the accessibility
63 // object there specifically placed for that purpose (the socket).
64 m_accessibilityObject = adoptGRef(webkitWebPageAccessibilityObjectNew(this));
65 GUniquePtr<gchar> plugID(atk_plug_get_id(ATK_PLUG(m_accessibilityObject.get())));
66 send(Messages::WebPageProxy::BindAccessibilityTree(String(plugID.get())));
67#endif
68}
69
70void WebPage::platformReinitialize()
71{
72}
73
74void WebPage::platformDetach()
75{
76}
77
78void WebPage::platformEditorState(Frame& frame, EditorState& result, IncludePostLayoutDataHint shouldIncludePostLayoutData) const
79{
80 if (shouldIncludePostLayoutData == IncludePostLayoutDataHint::No || !frame.view() || frame.view()->needsLayout()) {
81 result.isMissingPostLayoutData = true;
82 return;
83 }
84
85 auto& postLayoutData = result.postLayoutData();
86 postLayoutData.caretRectAtStart = frame.selection().absoluteCaretBounds();
87
88 const VisibleSelection& selection = frame.selection().selection();
89 if (selection.isNone())
90 return;
91
92 const Editor& editor = frame.editor();
93 if (selection.isRange()) {
94 if (editor.selectionHasStyle(CSSPropertyFontWeight, "bold") == TrueTriState)
95 postLayoutData.typingAttributes |= AttributeBold;
96 if (editor.selectionHasStyle(CSSPropertyFontStyle, "italic") == TrueTriState)
97 postLayoutData.typingAttributes |= AttributeItalics;
98 if (editor.selectionHasStyle(CSSPropertyWebkitTextDecorationsInEffect, "underline") == TrueTriState)
99 postLayoutData.typingAttributes |= AttributeUnderline;
100 if (editor.selectionHasStyle(CSSPropertyWebkitTextDecorationsInEffect, "line-through") == TrueTriState)
101 postLayoutData.typingAttributes |= AttributeStrikeThrough;
102 } else if (selection.isCaret()) {
103 if (editor.selectionStartHasStyle(CSSPropertyFontWeight, "bold"))
104 postLayoutData.typingAttributes |= AttributeBold;
105 if (editor.selectionStartHasStyle(CSSPropertyFontStyle, "italic"))
106 postLayoutData.typingAttributes |= AttributeItalics;
107 if (editor.selectionStartHasStyle(CSSPropertyWebkitTextDecorationsInEffect, "underline"))
108 postLayoutData.typingAttributes |= AttributeUnderline;
109 if (editor.selectionStartHasStyle(CSSPropertyWebkitTextDecorationsInEffect, "line-through"))
110 postLayoutData.typingAttributes |= AttributeStrikeThrough;
111 }
112}
113
114bool WebPage::performDefaultBehaviorForKeyEvent(const WebKeyboardEvent& keyboardEvent)
115{
116 if (keyboardEvent.type() != WebEvent::KeyDown && keyboardEvent.type() != WebEvent::RawKeyDown)
117 return false;
118
119 switch (keyboardEvent.windowsVirtualKeyCode()) {
120 case VK_SPACE:
121 scroll(m_page.get(), keyboardEvent.shiftKey() ? ScrollUp : ScrollDown, ScrollByPage);
122 break;
123 case VK_LEFT:
124 scroll(m_page.get(), ScrollLeft, ScrollByLine);
125 break;
126 case VK_RIGHT:
127 scroll(m_page.get(), ScrollRight, ScrollByLine);
128 break;
129 case VK_UP:
130 scroll(m_page.get(), ScrollUp, ScrollByLine);
131 break;
132 case VK_DOWN:
133 scroll(m_page.get(), ScrollDown, ScrollByLine);
134 break;
135 case VK_HOME:
136 scroll(m_page.get(), ScrollUp, ScrollByDocument);
137 break;
138 case VK_END:
139 scroll(m_page.get(), ScrollDown, ScrollByDocument);
140 break;
141 case VK_PRIOR:
142 scroll(m_page.get(), ScrollUp, ScrollByPage);
143 break;
144 case VK_NEXT:
145 scroll(m_page.get(), ScrollDown, ScrollByPage);
146 break;
147 default:
148 return false;
149 }
150
151 return true;
152}
153
154bool WebPage::platformCanHandleRequest(const ResourceRequest&)
155{
156 notImplemented();
157 return false;
158}
159
160String WebPage::platformUserAgent(const URL& url) const
161{
162 if (url.isNull() || !m_page->settings().needsSiteSpecificQuirks())
163 return String();
164
165 return WebCore::standardUserAgentForURL(url);
166}
167
168#if HAVE(GTK_GESTURES)
169void WebPage::getCenterForZoomGesture(const IntPoint& centerInViewCoordinates, CompletionHandler<void(WebCore::IntPoint&&)>&& completionHandler)
170{
171 IntPoint result = mainFrameView()->rootViewToContents(centerInViewCoordinates);
172 double scale = m_page->pageScaleFactor();
173 result.scale(1 / scale, 1 / scale);
174 completionHandler(WTFMove(result));
175}
176#endif
177
178void WebPage::setInputMethodState(bool enabled)
179{
180 if (m_inputMethodEnabled == enabled)
181 return;
182
183 m_inputMethodEnabled = enabled;
184 send(Messages::WebPageProxy::SetInputMethodState(enabled));
185}
186
187void WebPage::collapseSelectionInFrame(uint64_t frameID)
188{
189 WebFrame* frame = WebProcess::singleton().webFrame(frameID);
190 if (!frame || !frame->coreFrame())
191 return;
192
193 // Collapse the selection without clearing it.
194 const VisibleSelection& selection = frame->coreFrame()->selection().selection();
195 frame->coreFrame()->selection().setBase(selection.extent(), selection.affinity());
196}
197
198void WebPage::showEmojiPicker(Frame& frame)
199{
200 CompletionHandler<void(String)> completionHandler = [frame = makeRef(frame)](String result) {
201 if (!result.isEmpty())
202 frame->editor().insertText(result, nullptr);
203 };
204 sendWithAsyncReply(Messages::WebPageProxy::ShowEmojiPicker(frame.selection().absoluteCaretBounds()), WTFMove(completionHandler));
205}
206
207void WebPage::effectiveAppearanceDidChange(bool useDarkAppearance, bool useInactiveAppearance)
208{
209#if 0
210 if (auto* settings = gtk_settings_get_default())
211 g_object_set(settings, "gtk-application-prefer-dark-theme", useDarkAppearance, nullptr);
212#endif
213 corePage()->effectiveAppearanceDidChange(useDarkAppearance, useInactiveAppearance);
214}
215
216} // namespace WebKit
217