1/*
2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24 * THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "config.h"
28#include "WebPage.h"
29
30#include "WebEvent.h"
31#include <WebCore/FocusController.h>
32#include <WebCore/Frame.h>
33#include <WebCore/KeyboardEvent.h>
34#include <WebCore/Page.h>
35#include <WebCore/PlatformKeyboardEvent.h>
36#include <WebCore/Settings.h>
37
38#ifndef VK_UNKNOWN
39#define VK_UNKNOWN 0
40#define VK_BACK 0x08
41#define VK_TAB 0x09
42#define VK_CLEAR 0x0C
43#define VK_RETURN 0x0D
44#define VK_SHIFT 0x10
45#define VK_CONTROL 0x11 // CTRL key
46#define VK_MENU 0x12 // ALT key
47#define VK_PAUSE 0x13 // PAUSE key
48#define VK_CAPITAL 0x14 // CAPS LOCK key
49#define VK_KANA 0x15 // Input Method Editor (IME) Kana mode
50#define VK_HANGUL 0x15 // IME Hangul mode
51#define VK_JUNJA 0x17 // IME Junja mode
52#define VK_FINAL 0x18 // IME final mode
53#define VK_HANJA 0x19 // IME Hanja mode
54#define VK_KANJI 0x19 // IME Kanji mode
55#define VK_ESCAPE 0x1B // ESC key
56#define VK_CONVERT 0x1C // IME convert
57#define VK_NONCONVERT 0x1D // IME nonconvert
58#define VK_ACCEPT 0x1E // IME accept
59#define VK_MODECHANGE 0x1F // IME mode change request
60#define VK_SPACE 0x20 // SPACE key
61#define VK_PRIOR 0x21 // PAGE UP key
62#define VK_NEXT 0x22 // PAGE DOWN key
63#define VK_END 0x23 // END key
64#define VK_HOME 0x24 // HOME key
65#define VK_LEFT 0x25 // LEFT ARROW key
66#define VK_UP 0x26 // UP ARROW key
67#define VK_RIGHT 0x27 // RIGHT ARROW key
68#define VK_DOWN 0x28 // DOWN ARROW key
69#define VK_SELECT 0x29 // SELECT key
70#define VK_PRINT 0x2A // PRINT key
71#define VK_EXECUTE 0x2B // EXECUTE key
72#define VK_SNAPSHOT 0x2C // PRINT SCREEN key
73#define VK_INSERT 0x2D // INS key
74#define VK_DELETE 0x2E // DEL key
75#define VK_HELP 0x2F // HELP key
76// Windows 2000/XP: For any country/region, the '.' key
77#define VK_OEM_PERIOD 0xBE
78#endif
79
80using namespace WebCore;
81
82namespace WebKit {
83
84void WebPage::platformInitialize()
85{
86}
87
88void WebPage::platformPreferencesDidChange(const WebPreferencesStore&)
89{
90}
91
92static const unsigned CtrlKey = 1 << 0;
93static const unsigned AltKey = 1 << 1;
94static const unsigned ShiftKey = 1 << 2;
95
96struct KeyDownEntry {
97    unsigned virtualKey;
98    unsigned modifiers;
99    const char* name;
100};
101
102struct KeyPressEntry {
103    unsigned charCode;
104    unsigned modifiers;
105    const char* name;
106};
107
108static const KeyDownEntry keyDownEntries[] = {
109    { VK_LEFT,   0,                  "MoveLeft"                                    },
110    { VK_LEFT,   ShiftKey,           "MoveLeftAndModifySelection"                  },
111    { VK_LEFT,   CtrlKey,            "MoveWordLeft"                                },
112    { VK_LEFT,   CtrlKey | ShiftKey, "MoveWordLeftAndModifySelection"              },
113    { VK_RIGHT,  0,                  "MoveRight"                                   },
114    { VK_RIGHT,  ShiftKey,           "MoveRightAndModifySelection"                 },
115    { VK_RIGHT,  CtrlKey,            "MoveWordRight"                               },
116    { VK_RIGHT,  CtrlKey | ShiftKey, "MoveWordRightAndModifySelection"             },
117    { VK_UP,     0,                  "MoveUp"                                      },
118    { VK_UP,     ShiftKey,           "MoveUpAndModifySelection"                    },
119    { VK_PRIOR,  ShiftKey,           "MovePageUpAndModifySelection"                },
120    { VK_DOWN,   0,                  "MoveDown"                                    },
121    { VK_DOWN,   ShiftKey,           "MoveDownAndModifySelection"                  },
122    { VK_NEXT,   ShiftKey,           "MovePageDownAndModifySelection"              },
123    { VK_PRIOR,  0,                  "MovePageUp"                                  },
124    { VK_NEXT,   0,                  "MovePageDown"                                },
125    { VK_HOME,   0,                  "MoveToBeginningOfLine"                       },
126    { VK_HOME,   ShiftKey,           "MoveToBeginningOfLineAndModifySelection"     },
127    { VK_HOME,   CtrlKey,            "MoveToBeginningOfDocument"                   },
128    { VK_HOME,   CtrlKey | ShiftKey, "MoveToBeginningOfDocumentAndModifySelection" },
129
130    { VK_END,    0,                  "MoveToEndOfLine"                             },
131    { VK_END,    ShiftKey,           "MoveToEndOfLineAndModifySelection"           },
132    { VK_END,    CtrlKey,            "MoveToEndOfDocument"                         },
133    { VK_END,    CtrlKey | ShiftKey, "MoveToEndOfDocumentAndModifySelection"       },
134
135    { VK_BACK,   0,                  "DeleteBackward"                              },
136    { VK_BACK,   ShiftKey,           "DeleteBackward"                              },
137    { VK_DELETE, 0,                  "DeleteForward"                               },
138    { VK_BACK,   CtrlKey,            "DeleteWordBackward"                          },
139    { VK_DELETE, CtrlKey,            "DeleteWordForward"                           },
140
141    { 'B',       CtrlKey,            "ToggleBold"                                  },
142    { 'I',       CtrlKey,            "ToggleItalic"                                },
143
144    { VK_ESCAPE, 0,                  "Cancel"                                      },
145    { VK_OEM_PERIOD, CtrlKey,        "Cancel"                                      },
146    { VK_TAB,    0,                  "InsertTab"                                   },
147    { VK_TAB,    ShiftKey,           "InsertBacktab"                               },
148    { VK_RETURN, 0,                  "InsertNewline"                               },
149    { VK_RETURN, CtrlKey,            "InsertNewline"                               },
150    { VK_RETURN, AltKey,             "InsertNewline"                               },
151    { VK_RETURN, ShiftKey,           "InsertNewline"                               },
152    { VK_RETURN, AltKey | ShiftKey,  "InsertNewline"                               },
153
154    // It's not quite clear whether clipboard shortcuts and Undo/Redo should be handled
155    // in the application or in WebKit. We chose WebKit.
156    { 'C',       CtrlKey,            "Copy"                                        },
157    { 'V',       CtrlKey,            "Paste"                                       },
158    { 'X',       CtrlKey,            "Cut"                                         },
159    { 'A',       CtrlKey,            "SelectAll"                                   },
160    { VK_INSERT, CtrlKey,            "Copy"                                        },
161    { VK_DELETE, ShiftKey,           "Cut"                                         },
162    { VK_INSERT, ShiftKey,           "Paste"                                       },
163    { 'Z',       CtrlKey,            "Undo"                                        },
164    { 'Z',       CtrlKey | ShiftKey, "Redo"                                        },
165};
166
167static const KeyPressEntry keyPressEntries[] = {
168    { '\t',   0,                  "InsertTab"                                   },
169    { '\t',   ShiftKey,           "InsertBacktab"                               },
170    { '\r',   0,                  "InsertNewline"                               },
171    { '\r',   CtrlKey,            "InsertNewline"                               },
172    { '\r',   AltKey,             "InsertNewline"                               },
173    { '\r',   ShiftKey,           "InsertNewline"                               },
174    { '\r',   AltKey | ShiftKey,  "InsertNewline"                               },
175};
176
177const char* WebPage::interpretKeyEvent(const KeyboardEvent* evt)
178{
179    ASSERT(evt->type() == eventNames().keydownEvent || evt->type() == eventNames().keypressEvent);
180
181    static HashMap<int, const char*>* keyDownCommandsMap = 0;
182    static HashMap<int, const char*>* keyPressCommandsMap = 0;
183
184    if (!keyDownCommandsMap) {
185        keyDownCommandsMap = new HashMap<int, const char*>;
186        keyPressCommandsMap = new HashMap<int, const char*>;
187
188        for (unsigned i = 0; i < (sizeof(keyDownEntries) / sizeof(keyDownEntries[0])); i++)
189            keyDownCommandsMap->set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name);
190
191        for (unsigned i = 0; i < (sizeof(keyPressEntries) / sizeof(keyPressEntries[0])); i++)
192            keyPressCommandsMap->set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name);
193    }
194
195    unsigned modifiers = 0;
196    if (evt->shiftKey())
197        modifiers |= ShiftKey;
198    if (evt->altKey())
199        modifiers |= AltKey;
200    if (evt->ctrlKey())
201        modifiers |= CtrlKey;
202
203    if (evt->type() == eventNames().keydownEvent) {
204        int mapKey = modifiers << 16 | evt->keyEvent()->windowsVirtualKeyCode();
205        return mapKey ? keyDownCommandsMap->get(mapKey) : 0;
206    }
207
208    int mapKey = modifiers << 16 | evt->charCode();
209    return mapKey ? keyPressCommandsMap->get(mapKey) : 0;
210}
211
212static inline void scroll(Page* page, ScrollDirection direction, ScrollGranularity granularity)
213{
214    page->focusController()->focusedOrMainFrame()->eventHandler()->scrollRecursively(direction, granularity);
215}
216
217static inline void logicalScroll(Page* page, ScrollLogicalDirection direction, ScrollGranularity granularity)
218{
219    page->focusController()->focusedOrMainFrame()->eventHandler()->logicalScrollRecursively(direction, granularity);
220}
221
222bool WebPage::performDefaultBehaviorForKeyEvent(const WebKeyboardEvent& keyboardEvent)
223{
224    if (keyboardEvent.type() != WebEvent::KeyDown && keyboardEvent.type() != WebEvent::RawKeyDown)
225        return false;
226
227    switch (keyboardEvent.windowsVirtualKeyCode()) {
228    case VK_BACK:
229        if (keyboardEvent.shiftKey())
230            m_page->goForward();
231        else
232            m_page->goBack();
233        break;
234    case VK_SPACE:
235        logicalScroll(m_page.get(), keyboardEvent.shiftKey() ? ScrollBlockDirectionBackward : ScrollBlockDirectionForward, ScrollByPage);
236        break;
237    case VK_LEFT:
238        scroll(m_page.get(), ScrollLeft, ScrollByLine);
239        break;
240    case VK_RIGHT:
241        scroll(m_page.get(), ScrollRight, ScrollByLine);
242        break;
243    case VK_UP:
244        scroll(m_page.get(), ScrollUp, ScrollByLine);
245        break;
246    case VK_DOWN:
247        scroll(m_page.get(), ScrollDown, ScrollByLine);
248        break;
249    case VK_HOME:
250        logicalScroll(m_page.get(), ScrollBlockDirectionBackward, ScrollByDocument);
251        break;
252    case VK_END:
253        logicalScroll(m_page.get(), ScrollBlockDirectionForward, ScrollByDocument);
254        break;
255    case VK_PRIOR:
256        logicalScroll(m_page.get(), ScrollBlockDirectionBackward, ScrollByPage);
257        break;
258    case VK_NEXT:
259        logicalScroll(m_page.get(), ScrollBlockDirectionForward, ScrollByPage);
260        break;
261    default:
262        return false;
263    }
264
265    return true;
266}
267
268bool WebPage::platformHasLocalDataForURL(const WebCore::KURL&)
269{
270    // FIXME: Implement
271    return false;
272}
273
274String WebPage::cachedResponseMIMETypeForURL(const WebCore::KURL&)
275{
276    // FIXME: Implement
277    return String();
278}
279
280bool WebPage::platformCanHandleRequest(const WebCore::ResourceRequest&)
281{
282    // FIXME: Implement
283    return true;
284}
285
286} // namespace WebKit
287