WebPageWin.cpp revision 2fc2651226baac27029e38c9d6ef883fa32084db
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 "config.h" 27#include "WebPage.h" 28 29#include "FontSmoothingLevel.h" 30#include "WebEvent.h" 31#include "WebPreferencesStore.h" 32#include <WebCore/FocusController.h> 33#include <WebCore/FontRenderingMode.h> 34#include <WebCore/Frame.h> 35#include <WebCore/FrameView.h> 36#include <WebCore/KeyboardEvent.h> 37#include <WebCore/Page.h> 38#include <WebCore/PlatformKeyboardEvent.h> 39#include <WebCore/Settings.h> 40#if PLATFORM(CG) 41#include <WebKitSystemInterface/WebKitSystemInterface.h> 42#endif 43#include <WinUser.h> 44 45#if USE(CFNETWORK) 46#include <CFNetwork/CFURLCachePriv.h> 47#include <CFNetwork/CFURLProtocolPriv.h> 48#include <CFNetwork/CFURLRequestPriv.h> 49#endif 50 51using namespace WebCore; 52 53namespace WebKit { 54 55void WebPage::platformInitialize() 56{ 57 m_page->settings()->setFontRenderingMode(AlternateRenderingMode); 58} 59 60void WebPage::platformPreferencesDidChange(const WebPreferencesStore& store) 61{ 62 FontSmoothingLevel fontSmoothingLevel = static_cast<FontSmoothingLevel>(store.getUInt32ValueForKey(WebPreferencesKey::fontSmoothingLevelKey())); 63 64#if PLATFORM(CG) 65 FontSmoothingLevel adjustedLevel = fontSmoothingLevel; 66 if (adjustedLevel == FontSmoothingLevelWindows) 67 adjustedLevel = FontSmoothingLevelMedium; 68 wkSetFontSmoothingLevel(adjustedLevel); 69#endif 70 71 m_page->settings()->setFontRenderingMode(fontSmoothingLevel == FontSmoothingLevelWindows ? AlternateRenderingMode : NormalRenderingMode); 72} 73 74static const unsigned CtrlKey = 1 << 0; 75static const unsigned AltKey = 1 << 1; 76static const unsigned ShiftKey = 1 << 2; 77 78struct KeyDownEntry { 79 unsigned virtualKey; 80 unsigned modifiers; 81 const char* name; 82}; 83 84struct KeyPressEntry { 85 unsigned charCode; 86 unsigned modifiers; 87 const char* name; 88}; 89 90static const KeyDownEntry keyDownEntries[] = { 91 { VK_LEFT, 0, "MoveLeft" }, 92 { VK_LEFT, ShiftKey, "MoveLeftAndModifySelection" }, 93 { VK_LEFT, CtrlKey, "MoveWordLeft" }, 94 { VK_LEFT, CtrlKey | ShiftKey, "MoveWordLeftAndModifySelection" }, 95 { VK_RIGHT, 0, "MoveRight" }, 96 { VK_RIGHT, ShiftKey, "MoveRightAndModifySelection" }, 97 { VK_RIGHT, CtrlKey, "MoveWordRight" }, 98 { VK_RIGHT, CtrlKey | ShiftKey, "MoveWordRightAndModifySelection" }, 99 { VK_UP, 0, "MoveUp" }, 100 { VK_UP, ShiftKey, "MoveUpAndModifySelection" }, 101 { VK_PRIOR, ShiftKey, "MovePageUpAndModifySelection" }, 102 { VK_DOWN, 0, "MoveDown" }, 103 { VK_DOWN, ShiftKey, "MoveDownAndModifySelection" }, 104 { VK_NEXT, ShiftKey, "MovePageDownAndModifySelection" }, 105 { VK_PRIOR, 0, "MovePageUp" }, 106 { VK_NEXT, 0, "MovePageDown" }, 107 { VK_HOME, 0, "MoveToBeginningOfLine" }, 108 { VK_HOME, ShiftKey, "MoveToBeginningOfLineAndModifySelection" }, 109 { VK_HOME, CtrlKey, "MoveToBeginningOfDocument" }, 110 { VK_HOME, CtrlKey | ShiftKey, "MoveToBeginningOfDocumentAndModifySelection" }, 111 112 { VK_END, 0, "MoveToEndOfLine" }, 113 { VK_END, ShiftKey, "MoveToEndOfLineAndModifySelection" }, 114 { VK_END, CtrlKey, "MoveToEndOfDocument" }, 115 { VK_END, CtrlKey | ShiftKey, "MoveToEndOfDocumentAndModifySelection" }, 116 117 { VK_BACK, 0, "DeleteBackward" }, 118 { VK_BACK, ShiftKey, "DeleteBackward" }, 119 { VK_DELETE, 0, "DeleteForward" }, 120 { VK_BACK, CtrlKey, "DeleteWordBackward" }, 121 { VK_DELETE, CtrlKey, "DeleteWordForward" }, 122 123 { 'B', CtrlKey, "ToggleBold" }, 124 { 'I', CtrlKey, "ToggleItalic" }, 125 126 { VK_ESCAPE, 0, "Cancel" }, 127 { VK_OEM_PERIOD, CtrlKey, "Cancel" }, 128 { VK_TAB, 0, "InsertTab" }, 129 { VK_TAB, ShiftKey, "InsertBacktab" }, 130 { VK_RETURN, 0, "InsertNewline" }, 131 { VK_RETURN, CtrlKey, "InsertNewline" }, 132 { VK_RETURN, AltKey, "InsertNewline" }, 133 { VK_RETURN, ShiftKey, "InsertNewline" }, 134 { VK_RETURN, AltKey | ShiftKey, "InsertNewline" }, 135 136 // It's not quite clear whether clipboard shortcuts and Undo/Redo should be handled 137 // in the application or in WebKit. We chose WebKit. 138 { 'C', CtrlKey, "Copy" }, 139 { 'V', CtrlKey, "Paste" }, 140 { 'X', CtrlKey, "Cut" }, 141 { 'A', CtrlKey, "SelectAll" }, 142 { VK_INSERT, CtrlKey, "Copy" }, 143 { VK_DELETE, ShiftKey, "Cut" }, 144 { VK_INSERT, ShiftKey, "Paste" }, 145 { 'Z', CtrlKey, "Undo" }, 146 { 'Z', CtrlKey | ShiftKey, "Redo" }, 147}; 148 149static const KeyPressEntry keyPressEntries[] = { 150 { '\t', 0, "InsertTab" }, 151 { '\t', ShiftKey, "InsertBacktab" }, 152 { '\r', 0, "InsertNewline" }, 153 { '\r', CtrlKey, "InsertNewline" }, 154 { '\r', AltKey, "InsertNewline" }, 155 { '\r', ShiftKey, "InsertNewline" }, 156 { '\r', AltKey | ShiftKey, "InsertNewline" }, 157}; 158 159const char* WebPage::interpretKeyEvent(const KeyboardEvent* evt) 160{ 161 ASSERT(evt->type() == eventNames().keydownEvent || evt->type() == eventNames().keypressEvent); 162 163 static HashMap<int, const char*>* keyDownCommandsMap = 0; 164 static HashMap<int, const char*>* keyPressCommandsMap = 0; 165 166 if (!keyDownCommandsMap) { 167 keyDownCommandsMap = new HashMap<int, const char*>; 168 keyPressCommandsMap = new HashMap<int, const char*>; 169 170 for (size_t i = 0; i < WTF_ARRAY_LENGTH(keyDownEntries); ++i) 171 keyDownCommandsMap->set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name); 172 173 for (size_t i = 0; i < WTF_ARRAY_LENGTH(keyPressEntries); ++i) 174 keyPressCommandsMap->set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name); 175 } 176 177 unsigned modifiers = 0; 178 if (evt->shiftKey()) 179 modifiers |= ShiftKey; 180 if (evt->altKey()) 181 modifiers |= AltKey; 182 if (evt->ctrlKey()) 183 modifiers |= CtrlKey; 184 185 if (evt->type() == eventNames().keydownEvent) { 186 int mapKey = modifiers << 16 | evt->keyCode(); 187 return mapKey ? keyDownCommandsMap->get(mapKey) : 0; 188 } 189 190 int mapKey = modifiers << 16 | evt->charCode(); 191 return mapKey ? keyPressCommandsMap->get(mapKey) : 0; 192} 193 194static inline void scroll(Page* page, ScrollDirection direction, ScrollGranularity granularity) 195{ 196 page->focusController()->focusedOrMainFrame()->eventHandler()->scrollRecursively(direction, granularity); 197} 198 199static inline void logicalScroll(Page* page, ScrollLogicalDirection direction, ScrollGranularity granularity) 200{ 201 page->focusController()->focusedOrMainFrame()->eventHandler()->logicalScrollRecursively(direction, granularity); 202} 203 204bool WebPage::performDefaultBehaviorForKeyEvent(const WebKeyboardEvent& keyboardEvent) 205{ 206 if (keyboardEvent.type() != WebEvent::KeyDown && keyboardEvent.type() != WebEvent::RawKeyDown) 207 return false; 208 209 switch (keyboardEvent.windowsVirtualKeyCode()) { 210 case VK_BACK: 211 if (keyboardEvent.shiftKey()) 212 m_page->goForward(); 213 else 214 m_page->goBack(); 215 break; 216 case VK_LEFT: 217 scroll(m_page.get(), ScrollLeft, ScrollByLine); 218 break; 219 case VK_RIGHT: 220 scroll(m_page.get(), ScrollRight, ScrollByLine); 221 break; 222 case VK_UP: 223 scroll(m_page.get(), ScrollUp, ScrollByLine); 224 break; 225 case VK_DOWN: 226 scroll(m_page.get(), ScrollDown, ScrollByLine); 227 break; 228 case VK_HOME: 229 logicalScroll(m_page.get(), ScrollBlockDirectionBackward, ScrollByDocument); 230 break; 231 case VK_END: 232 logicalScroll(m_page.get(), ScrollBlockDirectionForward, ScrollByDocument); 233 break; 234 case VK_PRIOR: 235 logicalScroll(m_page.get(), ScrollBlockDirectionBackward, ScrollByPage); 236 break; 237 case VK_NEXT: 238 logicalScroll(m_page.get(), ScrollBlockDirectionForward, ScrollByPage); 239 break; 240 default: 241 return false; 242 } 243 244 return true; 245} 246 247bool WebPage::platformHasLocalDataForURL(const WebCore::KURL& url) 248{ 249#if USE(CFNETWORK) 250 RetainPtr<CFURLRef> cfURL(AdoptCF, url.createCFURL()); 251 RetainPtr<CFMutableURLRequestRef> request(AdoptCF, CFURLRequestCreateMutable(0, cfURL.get(), kCFURLRequestCachePolicyReloadIgnoringCache, 60, 0)); 252 253 RetainPtr<CFStringRef> userAgent(AdoptCF, userAgent().createCFString()); 254 CFURLRequestSetHTTPHeaderFieldValue(request.get(), CFSTR("User-Agent"), userAgent.get()); 255 256 RetainPtr<CFURLCacheRef> cache(AdoptCF, CFURLCacheCopySharedURLCache()); 257 258 RetainPtr<CFCachedURLResponseRef> response(AdoptCF, CFURLCacheCopyResponseForRequest(cache.get(), request.get())); 259 return response; 260#else 261 return false; 262#endif 263} 264 265String WebPage::cachedResponseMIMETypeForURL(const WebCore::KURL& url) 266{ 267#if USE(CFNETWORK) 268 RetainPtr<CFURLRef> cfURL(AdoptCF, url.createCFURL()); 269 RetainPtr<CFMutableURLRequestRef> request(AdoptCF, CFURLRequestCreateMutable(0, cfURL.get(), kCFURLRequestCachePolicyReloadIgnoringCache, 60, 0)); 270 271 RetainPtr<CFStringRef> userAgent(AdoptCF, userAgent().createCFString()); 272 CFURLRequestSetHTTPHeaderFieldValue(request.get(), CFSTR("User-Agent"), userAgent.get()); 273 274 RetainPtr<CFURLCacheRef> cache(AdoptCF, CFURLCacheCopySharedURLCache()); 275 276 RetainPtr<CFCachedURLResponseRef> cachedResponse(AdoptCF, CFURLCacheCopyResponseForRequest(cache.get(), request.get())); 277 278 CFURLResponseRef response = CFCachedURLResponseGetWrappedResponse(cachedResponse.get()); 279 280 return response ? CFURLResponseGetMIMEType(response) : String(); 281#else 282 return String(); 283#endif 284} 285 286bool WebPage::canHandleRequest(const WebCore::ResourceRequest& request) 287{ 288#if USE(CFNETWORK) 289 // FIXME: Are there other requests we need to be able to handle? WebKit1's WebView.cpp has a FIXME here as well. 290 return CFURLProtocolCanHandleRequest(request.cfURLRequest()); 291#else 292 return true; 293#endif 294} 295 296void WebPage::confirmComposition(const String& compositionString) 297{ 298 Frame* frame = m_page->focusController()->focusedOrMainFrame(); 299 if (!frame || !frame->editor()->canEdit()) 300 return; 301 frame->editor()->confirmComposition(compositionString); 302} 303 304void WebPage::setComposition(const String& compositionString, const Vector<WebCore::CompositionUnderline>& underlines, uint64_t cursorPosition) 305{ 306 Frame* frame = m_page->focusController()->focusedOrMainFrame(); 307 if (!frame || !frame->editor()->canEdit()) 308 return; 309 frame->editor()->setComposition(compositionString, underlines, cursorPosition, 0); 310} 311 312void WebPage::firstRectForCharacterInSelectedRange(const uint64_t characterPosition, WebCore::IntRect& resultRect) 313{ 314 Frame* frame = m_page->focusController()->focusedOrMainFrame(); 315 IntRect rect; 316 if (RefPtr<Range> range = frame->editor()->hasComposition() ? frame->editor()->compositionRange() : frame->selection()->selection().toNormalizedRange()) { 317 ExceptionCode ec = 0; 318 RefPtr<Range> tempRange = range->cloneRange(ec); 319 tempRange->setStart(tempRange->startContainer(ec), tempRange->startOffset(ec) + characterPosition, ec); 320 rect = frame->editor()->firstRectForRange(tempRange.get()); 321 } 322 resultRect = frame->view()->contentsToWindow(rect); 323} 324 325void WebPage::getSelectedText(String& text) 326{ 327 Frame* frame = m_page->focusController()->focusedOrMainFrame(); 328 RefPtr<Range> selectedRange = frame->selection()->toNormalizedRange(); 329 text = selectedRange->text(); 330} 331 332} // namespace WebKit 333