90c088b88e0908ee253cfa7cd560a5fdb699088b
[WebKit-https.git] / WebKit2 / WebProcess / WebPage / mac / WebPageMac.mm
1 /*
2  * Copyright (C) 2010 Apple 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
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "WebPage.h"
27
28 #include "WebCoreArgumentCoders.h"
29 #include "WebEvent.h"
30 #include "WebPageProxyMessages.h"
31 #include "WebProcess.h"
32 #include <WebCore/FocusController.h>
33 #include <WebCore/Frame.h>
34 #include <WebCore/KeyboardEvent.h>
35 #include <WebCore/Page.h>
36 #include <WebCore/PlatformKeyboardEvent.h>
37 #include <WebCore/WindowsKeyboardCodes.h>
38
39 using namespace WebCore;
40
41 namespace WebKit {
42
43 void WebPage::platformInitialize()
44 {
45     m_page->addSchedulePair(SchedulePair::create([NSRunLoop currentRunLoop], kCFRunLoopCommonModes));
46 }
47
48 void WebPage::platformPreferencesDidChange(const WebPreferencesStore&)
49 {
50 }
51
52 // FIXME: need to add support for input methods
53     
54 bool WebPage::interceptEditingKeyboardEvent(KeyboardEvent* evt, bool shouldSaveCommand)
55 {
56     Node* node = evt->target()->toNode();
57     ASSERT(node);
58     Frame* frame = node->document()->frame();
59     ASSERT(frame);
60     
61     const PlatformKeyboardEvent* keyEvent = evt->keyEvent();
62     if (!keyEvent)
63         return false;
64     const Vector<KeypressCommand>& commands = evt->keypressCommands();
65     bool hasKeypressCommand = !commands.isEmpty();
66     
67     bool eventWasHandled = false;
68     
69     if (shouldSaveCommand && !hasKeypressCommand) {
70         Vector<KeypressCommand> commandsList;        
71         if (!WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::InterpretKeyEvent(keyEvent->type()), Messages::WebPageProxy::InterpretKeyEvent::Reply(commandsList), m_pageID))
72             return false;
73         for (size_t i = 0; i < commandsList.size(); i++)
74             evt->keypressCommands().append(commandsList[i]);
75     } else {
76         size_t size = commands.size();
77         // Are there commands that would just cause text insertion if executed via Editor?
78         // WebKit doesn't have enough information about mode to decide how they should be treated, so we leave it upon WebCore
79         // to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated
80         // (e.g. Tab that inserts a Tab character, or Enter).
81         bool haveTextInsertionCommands = false;
82         for (size_t i = 0; i < size; ++i) {
83             if (frame->editor()->command(commands[i].commandName).isTextInsertion())
84                 haveTextInsertionCommands = true;
85         }
86         if (!haveTextInsertionCommands || keyEvent->type() == PlatformKeyboardEvent::Char) {
87             for (size_t i = 0; i < size; ++i) {
88                 if (commands[i].commandName == "insertText") {
89                     // Don't insert null or control characters as they can result in unexpected behaviour
90                     if (evt->charCode() < ' ')
91                         return false;
92                     eventWasHandled = frame->editor()->insertText(commands[i].text, evt);
93                 } else
94                     if (frame->editor()->command(commands[i].commandName).isSupported())
95                         eventWasHandled = frame->editor()->command(commands[i].commandName).execute(evt);
96             }
97         }
98     }
99     return eventWasHandled;
100 }
101
102 static inline void scroll(Page* page, ScrollDirection direction, ScrollGranularity granularity)
103 {
104     page->focusController()->focusedOrMainFrame()->eventHandler()->scrollRecursively(direction, granularity);
105 }
106
107 bool WebPage::performDefaultBehaviorForKeyEvent(const WebKeyboardEvent& keyboardEvent)
108 {
109     if (keyboardEvent.type() != WebEvent::KeyDown)
110         return false;
111
112     // FIXME: This should be in WebCore.
113
114     switch (keyboardEvent.windowsVirtualKeyCode()) {
115     case VK_BACK:
116         if (keyboardEvent.shiftKey())
117             m_page->goForward();
118         else
119             m_page->goBack();
120         break;
121     case VK_SPACE:
122         if (keyboardEvent.shiftKey())
123             scroll(m_page.get(), ScrollUp, ScrollByPage);
124         else
125             scroll(m_page.get(), ScrollDown, ScrollByPage);
126         break;
127     case VK_PRIOR:
128         scroll(m_page.get(), ScrollUp, ScrollByPage);
129         break;
130     case VK_NEXT:
131         scroll(m_page.get(), ScrollDown, ScrollByPage);
132         break;
133     case VK_HOME:
134         scroll(m_page.get(), ScrollUp, ScrollByDocument);
135         scroll(m_page.get(), ScrollLeft, ScrollByDocument);
136         break;
137     case VK_END:
138         scroll(m_page.get(), ScrollDown, ScrollByDocument);
139         scroll(m_page.get(), ScrollLeft, ScrollByDocument);
140         break;
141     case VK_UP:
142         if (keyboardEvent.shiftKey())
143             return false;
144         if (keyboardEvent.metaKey()) {
145             scroll(m_page.get(), ScrollUp, ScrollByDocument);
146             scroll(m_page.get(), ScrollLeft, ScrollByDocument);
147         } else if (keyboardEvent.altKey() || keyboardEvent.controlKey())
148             scroll(m_page.get(), ScrollUp, ScrollByPage);
149         else
150             scroll(m_page.get(), ScrollUp, ScrollByLine);
151         break;
152     case VK_DOWN:
153         if (keyboardEvent.shiftKey())
154             return false;
155         if (keyboardEvent.metaKey()) {
156             scroll(m_page.get(), ScrollDown, ScrollByDocument);
157             scroll(m_page.get(), ScrollLeft, ScrollByDocument);
158         } else if (keyboardEvent.altKey() || keyboardEvent.controlKey())
159             scroll(m_page.get(), ScrollDown, ScrollByPage);
160         else
161             scroll(m_page.get(), ScrollDown, ScrollByLine);
162         break;
163     case VK_LEFT:
164         if (keyboardEvent.shiftKey())
165             return false;
166         if (keyboardEvent.metaKey())
167             m_page->goBack();
168         else {
169             if (keyboardEvent.altKey()  | keyboardEvent.controlKey())
170                 scroll(m_page.get(), ScrollLeft, ScrollByPage);
171             else
172                 scroll(m_page.get(), ScrollLeft, ScrollByLine);
173         }
174         break;
175     case VK_RIGHT:
176         if (keyboardEvent.shiftKey())
177             return false;
178         if (keyboardEvent.metaKey())
179             m_page->goForward();
180         else {
181             if (keyboardEvent.altKey() || keyboardEvent.controlKey())
182                 scroll(m_page.get(), ScrollRight, ScrollByPage);
183             else
184                 scroll(m_page.get(), ScrollRight, ScrollByLine);
185         }
186         break;
187     default:
188         return false;
189     }
190
191     return true;
192 }
193
194 } // namespace WebKit