1 /* 2 * Copyright (C) 2007 Kevin Ollivier 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 COMPUTER, INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "WebView.h" 28 29 #include "ContextMenu.h" 30 #include "ContextMenuController.h" 31 #include "ContextMenuItem.h" 32 #include "Document.h" 33 #include "Editor.h" 34 #include "Element.h" 35 #include "EmptyClients.h" 36 #include "EventHandler.h" 37 #include "FileChooser.h" 38 #include "FocusController.h" 39 #include "Frame.h" 40 #include "FrameLoader.h" 41 #include "FrameView.h" 42 #include "GraphicsContext.h" 43 #include "HTMLFormElement.h" 44 #include "Logging.h" 45 #include "MemoryCache.h" 46 #include "Page.h" 47 #include "PlatformKeyboardEvent.h" 48 #include "PlatformMouseEvent.h" 49 #include "PlatformString.h" 50 #include "PlatformWheelEvent.h" 51 #include "PluginHalterClient.h" 52 #include "RenderObject.h" 53 #include "RenderView.h" 54 #include "ResourceHandleManager.h" 55 #include "Scrollbar.h" 56 #include "SelectionController.h" 57 #include "Settings.h" 58 #include "SubstituteData.h" 59 #include "Threading.h" 60 #include "markup.h" 61 #if __WXMSW__ 62 #include "WebCoreInstanceHandle.h" 63 #endif 64 65 #include "ChromeClientWx.h" 66 #include "ContextMenuClientWx.h" 67 #include "DragClientWx.h" 68 #include "EditorClientWx.h" 69 #include "FrameLoaderClientWx.h" 70 #include "InspectorClientWx.h" 71 72 #include "ScriptController.h" 73 #include "JSDOMBinding.h" 74 #include <runtime/initializeThreading.h> 75 #include <runtime/JSValue.h> 76 #include <runtime/UString.h> 77 #include <wtf/text/CString.h> 78 79 #if ENABLE(DATABASE) 80 #include "AbstractDatabase.h" 81 #include "DatabaseTracker.h" 82 #endif 83 84 #include "wx/wxprec.h" 85 #ifndef WX_PRECOMP 86 #include "wx/wx.h" 87 #endif 88 89 #include "WebDOMElement.h" 90 #include "WebDOMNode.h" 91 92 #include "WebFrame.h" 93 #include "WebViewPrivate.h" 94 95 #include <wx/defs.h> 96 #include <wx/dcbuffer.h> 97 #include <wx/dcgraph.h> 98 99 #if defined(_MSC_VER) 100 int rint(double val) 101 { 102 return (int)(val < 0 ? val - 0.5 : val + 0.5); 103 } 104 #endif 105 106 // ---------------------------------------------------------------------------- 107 // wxWebView Events 108 // ---------------------------------------------------------------------------- 109 110 IMPLEMENT_DYNAMIC_CLASS(wxWebViewLoadEvent, wxCommandEvent) 111 112 DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_LOAD) 113 114 wxWebViewLoadEvent::wxWebViewLoadEvent(wxWindow* win) 115 { 116 SetEventType( wxEVT_WEBVIEW_LOAD); 117 SetEventObject( win ); 118 if (win) 119 SetId(win->GetId()); 120 } 121 122 IMPLEMENT_DYNAMIC_CLASS(wxWebViewBeforeLoadEvent, wxCommandEvent) 123 124 DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_BEFORE_LOAD) 125 126 wxWebViewBeforeLoadEvent::wxWebViewBeforeLoadEvent(wxWindow* win) 127 { 128 m_cancelled = false; 129 SetEventType(wxEVT_WEBVIEW_BEFORE_LOAD); 130 SetEventObject(win); 131 if (win) 132 SetId(win->GetId()); 133 } 134 135 IMPLEMENT_DYNAMIC_CLASS(wxWebViewNewWindowEvent, wxCommandEvent) 136 137 DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_NEW_WINDOW) 138 139 wxWebViewNewWindowEvent::wxWebViewNewWindowEvent(wxWindow* win) 140 { 141 SetEventType(wxEVT_WEBVIEW_NEW_WINDOW); 142 SetEventObject(win); 143 if (win) 144 SetId(win->GetId()); 145 } 146 147 IMPLEMENT_DYNAMIC_CLASS(wxWebViewRightClickEvent, wxCommandEvent) 148 149 DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_RIGHT_CLICK) 150 151 wxWebViewRightClickEvent::wxWebViewRightClickEvent(wxWindow* win) 152 { 153 SetEventType(wxEVT_WEBVIEW_RIGHT_CLICK); 154 SetEventObject(win); 155 if (win) 156 SetId(win->GetId()); 157 } 158 159 IMPLEMENT_DYNAMIC_CLASS(wxWebViewConsoleMessageEvent, wxCommandEvent) 160 161 DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_CONSOLE_MESSAGE) 162 163 wxWebViewConsoleMessageEvent::wxWebViewConsoleMessageEvent(wxWindow* win) 164 { 165 SetEventType(wxEVT_WEBVIEW_CONSOLE_MESSAGE); 166 SetEventObject(win); 167 if (win) 168 SetId(win->GetId()); 169 } 170 171 IMPLEMENT_DYNAMIC_CLASS(wxWebViewAlertEvent, wxCommandEvent) 172 173 DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_JS_ALERT) 174 175 wxWebViewAlertEvent::wxWebViewAlertEvent(wxWindow* win) 176 { 177 SetEventType(wxEVT_WEBVIEW_JS_ALERT); 178 SetEventObject(win); 179 if (win) 180 SetId(win->GetId()); 181 } 182 183 IMPLEMENT_DYNAMIC_CLASS(wxWebViewConfirmEvent, wxCommandEvent) 184 185 DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_JS_CONFIRM) 186 187 wxWebViewConfirmEvent::wxWebViewConfirmEvent(wxWindow* win) 188 { 189 SetEventType(wxEVT_WEBVIEW_JS_CONFIRM); 190 SetEventObject(win); 191 if (win) 192 SetId(win->GetId()); 193 } 194 195 IMPLEMENT_DYNAMIC_CLASS(wxWebViewPromptEvent, wxCommandEvent) 196 197 DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_JS_PROMPT) 198 199 wxWebViewPromptEvent::wxWebViewPromptEvent(wxWindow* win) 200 { 201 SetEventType(wxEVT_WEBVIEW_JS_PROMPT); 202 SetEventObject(win); 203 if (win) 204 SetId(win->GetId()); 205 } 206 207 IMPLEMENT_DYNAMIC_CLASS(wxWebViewReceivedTitleEvent, wxCommandEvent) 208 209 DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_RECEIVED_TITLE) 210 211 wxWebViewReceivedTitleEvent::wxWebViewReceivedTitleEvent(wxWindow* win) 212 { 213 SetEventType(wxEVT_WEBVIEW_RECEIVED_TITLE); 214 SetEventObject(win); 215 if (win) 216 SetId(win->GetId()); 217 } 218 219 IMPLEMENT_DYNAMIC_CLASS(wxWebViewWindowObjectClearedEvent, wxCommandEvent) 220 221 DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_WINDOW_OBJECT_CLEARED) 222 223 wxWebViewWindowObjectClearedEvent::wxWebViewWindowObjectClearedEvent(wxWindow* win) 224 { 225 SetEventType(wxEVT_WEBVIEW_WINDOW_OBJECT_CLEARED); 226 SetEventObject(win); 227 if (win) 228 SetId(win->GetId()); 229 } 230 231 IMPLEMENT_DYNAMIC_CLASS(wxWebViewContentsChangedEvent, wxCommandEvent) 232 233 DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_CONTENTS_CHANGED) 234 235 wxWebViewContentsChangedEvent::wxWebViewContentsChangedEvent(wxWindow* win) 236 { 237 SetEventType(wxEVT_WEBVIEW_CONTENTS_CHANGED); 238 SetEventObject(win); 239 if (win) 240 SetId(win->GetId()); 241 } 242 243 IMPLEMENT_DYNAMIC_CLASS(wxWebViewSelectionChangedEvent, wxCommandEvent) 244 245 DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_SELECTION_CHANGED) 246 247 wxWebViewSelectionChangedEvent::wxWebViewSelectionChangedEvent(wxWindow* win) 248 { 249 SetEventType(wxEVT_WEBVIEW_SELECTION_CHANGED); 250 SetEventObject(win); 251 if (win) 252 SetId(win->GetId()); 253 } 254 255 //--------------------------------------------------------- 256 // DOM Element info data type 257 //--------------------------------------------------------- 258 259 wxWebViewDOMElementInfo::wxWebViewDOMElementInfo() : 260 m_isSelected(false), 261 m_text(wxEmptyString), 262 m_imageSrc(wxEmptyString), 263 m_link(wxEmptyString), 264 m_urlElement(NULL), 265 m_innerNode(NULL) 266 { 267 } 268 269 static wxWebViewCachePolicy gs_cachePolicy; 270 271 /* static */ 272 void wxWebView::SetCachePolicy(const wxWebViewCachePolicy& cachePolicy) 273 { 274 WebCore::MemoryCache* globalCache = WebCore::memoryCache(); 275 globalCache->setCapacities(cachePolicy.GetMinDeadCapacity(), 276 cachePolicy.GetMaxDeadCapacity(), 277 cachePolicy.GetCapacity()); 278 279 // store a copy since there is no getter for MemoryCache values 280 gs_cachePolicy = cachePolicy; 281 } 282 283 /* static */ 284 wxWebViewCachePolicy wxWebView::GetCachePolicy() 285 { 286 return gs_cachePolicy; 287 } 288 289 wxWebViewDOMElementInfo::wxWebViewDOMElementInfo(const wxWebViewDOMElementInfo& other) 290 { 291 m_isSelected = other.m_isSelected; 292 m_text = other.m_text; 293 m_imageSrc = other.m_imageSrc; 294 m_link = other.m_link; 295 m_innerNode = other.m_innerNode; 296 m_urlElement = other.m_urlElement; 297 } 298 299 wxWebViewDOMElementInfo::~wxWebViewDOMElementInfo() 300 { 301 if (m_innerNode) 302 delete m_innerNode; 303 304 if (m_urlElement) 305 delete m_urlElement; 306 } 307 308 #if OS(DARWIN) 309 // prototype - function is in WebSystemInterface.mm 310 void InitWebCoreSystemInterface(void); 311 #endif 312 313 BEGIN_EVENT_TABLE(wxWebView, wxWindow) 314 EVT_PAINT(wxWebView::OnPaint) 315 EVT_SIZE(wxWebView::OnSize) 316 EVT_MOUSE_EVENTS(wxWebView::OnMouseEvents) 317 EVT_CONTEXT_MENU(wxWebView::OnContextMenuEvents) 318 EVT_KEY_DOWN(wxWebView::OnKeyEvents) 319 EVT_KEY_UP(wxWebView::OnKeyEvents) 320 EVT_CHAR(wxWebView::OnKeyEvents) 321 EVT_SET_FOCUS(wxWebView::OnSetFocus) 322 EVT_KILL_FOCUS(wxWebView::OnKillFocus) 323 END_EVENT_TABLE() 324 325 IMPLEMENT_DYNAMIC_CLASS(wxWebView, wxWindow) 326 327 const wxChar* wxWebViewNameStr = wxT("webView"); 328 329 wxWebView::wxWebView() : 330 m_textMagnifier(1.0), 331 m_isInitialized(false), 332 m_beingDestroyed(false), 333 m_mouseWheelZooms(false), 334 m_title(wxEmptyString) 335 { 336 } 337 338 wxWebView::wxWebView(wxWindow* parent, int id, const wxPoint& position, 339 const wxSize& size, long style, const wxString& name) : 340 m_textMagnifier(1.0), 341 m_isInitialized(false), 342 m_beingDestroyed(false), 343 m_mouseWheelZooms(false), 344 m_title(wxEmptyString) 345 { 346 Create(parent, id, position, size, style, name); 347 } 348 349 bool wxWebView::Create(wxWindow* parent, int id, const wxPoint& position, 350 const wxSize& size, long style, const wxString& name) 351 { 352 #if OS(DARWIN) 353 InitWebCoreSystemInterface(); 354 #endif 355 356 if ( (style & wxBORDER_MASK) == 0) 357 style |= wxBORDER_NONE; 358 359 if (!wxWindow::Create(parent, id, position, size, style, name)) 360 return false; 361 362 JSC::initializeThreading(); 363 WTF::initializeMainThread(); 364 365 // This is necessary because we are using SharedTimerWin.cpp on Windows, 366 // due to a problem with exceptions getting eaten when using the callback 367 // approach to timers (which wx itself uses). 368 #if __WXMSW__ 369 WebCore::setInstanceHandle(wxGetInstance()); 370 #endif 371 372 // this helps reduce flicker on platforms like MSW 373 SetBackgroundStyle(wxBG_STYLE_CUSTOM); 374 375 m_impl = new WebViewPrivate(); 376 377 WebCore::InitializeLoggingChannelsIfNecessary(); 378 WebCore::HTMLFrameOwnerElement* parentFrame = 0; 379 380 WebCore::EditorClientWx* editorClient = new WebCore::EditorClientWx(); 381 382 WebCore::Page::PageClients pageClients; 383 pageClients.chromeClient = new WebCore::ChromeClientWx(this); 384 pageClients.contextMenuClient = new WebCore::ContextMenuClientWx(); 385 pageClients.editorClient = editorClient; 386 pageClients.dragClient = new WebCore::DragClientWx(); 387 pageClients.inspectorClient = new WebCore::InspectorClientWx(); 388 m_impl->page = new WebCore::Page(pageClients); 389 editorClient->setPage(m_impl->page); 390 391 m_mainFrame = new wxWebFrame(this); 392 393 // Default settings - we should have wxWebViewSettings class for this 394 // eventually 395 WebCore::Settings* settings = m_impl->page->settings(); 396 settings->setLoadsImagesAutomatically(true); 397 settings->setDefaultFixedFontSize(13); 398 settings->setDefaultFontSize(16); 399 settings->setSerifFontFamily("Times New Roman"); 400 settings->setFixedFontFamily("Courier New"); 401 settings->setSansSerifFontFamily("Arial"); 402 settings->setStandardFontFamily("Times New Roman"); 403 settings->setJavaScriptEnabled(true); 404 405 #if ENABLE(DATABASE) 406 SetDatabasesEnabled(true); 407 #endif 408 409 // we need to do this so that objects like the focusController are properly 410 // initialized so that the activate handler is run properly. 411 LoadURL(wxT("about:blank")); 412 413 m_isInitialized = true; 414 415 return true; 416 } 417 418 wxWebView::~wxWebView() 419 { 420 m_beingDestroyed = true; 421 422 while (HasCapture()) 423 ReleaseMouse(); 424 425 if (m_mainFrame && m_mainFrame->GetFrame()) 426 m_mainFrame->GetFrame()->loader()->detachFromParent(); 427 428 delete m_impl->page; 429 m_impl->page = 0; 430 } 431 432 // NOTE: binding to this event in the wxWebView constructor is too early in 433 // some cases, but leave the event handler here so that users can bind to it 434 // at a later time if they have activation state problems. 435 void wxWebView::OnTLWActivated(wxActivateEvent& event) 436 { 437 if (m_impl && m_impl->page && m_impl->page->focusController()) 438 m_impl->page->focusController()->setActive(event.GetActive()); 439 440 event.Skip(); 441 442 } 443 444 void wxWebView::Stop() 445 { 446 if (m_mainFrame) 447 m_mainFrame->Stop(); 448 } 449 450 void wxWebView::Reload() 451 { 452 if (m_mainFrame) 453 m_mainFrame->Reload(); 454 } 455 456 wxString wxWebView::GetPageSource() 457 { 458 if (m_mainFrame) 459 return m_mainFrame->GetPageSource(); 460 461 return wxEmptyString; 462 } 463 464 void wxWebView::SetPageSource(const wxString& source, const wxString& baseUrl, const wxString& mimetype) 465 { 466 if (m_mainFrame) 467 m_mainFrame->SetPageSource(source, baseUrl, mimetype); 468 } 469 470 wxString wxWebView::GetInnerText() 471 { 472 if (m_mainFrame) 473 return m_mainFrame->GetInnerText(); 474 475 return wxEmptyString; 476 } 477 478 wxString wxWebView::GetAsMarkup() 479 { 480 if (m_mainFrame) 481 return m_mainFrame->GetAsMarkup(); 482 483 return wxEmptyString; 484 } 485 486 wxString wxWebView::GetExternalRepresentation() 487 { 488 if (m_mainFrame) 489 return m_mainFrame->GetExternalRepresentation(); 490 491 return wxEmptyString; 492 } 493 494 wxWebKitSelection wxWebView::GetSelection() 495 { 496 if (m_mainFrame) 497 return m_mainFrame->GetSelection(); 498 499 return 0; 500 } 501 502 wxString wxWebView::GetSelectionAsHTML() 503 { 504 if (m_mainFrame) 505 return m_mainFrame->GetSelectionAsHTML(); 506 507 return wxEmptyString; 508 } 509 510 wxString wxWebView::GetSelectionAsText() 511 { 512 if (m_mainFrame) 513 return m_mainFrame->GetSelectionAsText(); 514 515 return wxEmptyString; 516 } 517 518 void wxWebView::SetTransparent(bool transparent) 519 { 520 WebCore::Frame* frame = 0; 521 if (m_mainFrame) 522 frame = m_mainFrame->GetFrame(); 523 524 if (!frame || !frame->view()) 525 return; 526 527 frame->view()->setTransparent(transparent); 528 } 529 530 bool wxWebView::IsTransparent() const 531 { 532 WebCore::Frame* frame = 0; 533 if (m_mainFrame) 534 frame = m_mainFrame->GetFrame(); 535 536 if (!frame || !frame->view()) 537 return false; 538 539 return frame->view()->isTransparent(); 540 } 541 542 wxString wxWebView::RunScript(const wxString& javascript) 543 { 544 if (m_mainFrame) 545 return m_mainFrame->RunScript(javascript); 546 547 return wxEmptyString; 548 } 549 550 bool wxWebView::ExecuteEditCommand(const wxString& command, const wxString& parameter) 551 { 552 if (m_mainFrame) 553 return m_mainFrame->ExecuteEditCommand(command, parameter); 554 } 555 556 EditState wxWebView::GetEditCommandState(const wxString& command) const 557 { 558 if (m_mainFrame) 559 return m_mainFrame->GetEditCommandState(command); 560 } 561 562 wxString wxWebView::GetEditCommandValue(const wxString& command) const 563 { 564 if (m_mainFrame) 565 return m_mainFrame->GetEditCommandValue(command); 566 567 return wxEmptyString; 568 } 569 570 void wxWebView::LoadURL(const wxString& url) 571 { 572 if (m_mainFrame) 573 m_mainFrame->LoadURL(url); 574 } 575 576 bool wxWebView::GoBack() 577 { 578 if (m_mainFrame) 579 return m_mainFrame->GoBack(); 580 581 return false; 582 } 583 584 bool wxWebView::GoForward() 585 { 586 if (m_mainFrame) 587 return m_mainFrame->GoForward(); 588 589 return false; 590 } 591 592 bool wxWebView::CanGoBack() 593 { 594 if (m_mainFrame) 595 return m_mainFrame->CanGoBack(); 596 597 return false; 598 } 599 600 bool wxWebView::CanGoForward() 601 { 602 if (m_mainFrame) 603 return m_mainFrame->CanGoForward(); 604 605 return false; 606 } 607 608 bool wxWebView::CanIncreaseTextSize() const 609 { 610 if (m_mainFrame) 611 return m_mainFrame->CanIncreaseTextSize(); 612 613 return false; 614 } 615 616 void wxWebView::IncreaseTextSize() 617 { 618 if (m_mainFrame) 619 m_mainFrame->IncreaseTextSize(); 620 } 621 622 bool wxWebView::CanDecreaseTextSize() const 623 { 624 if (m_mainFrame) 625 m_mainFrame->CanDecreaseTextSize(); 626 627 return false; 628 } 629 630 void wxWebView::DecreaseTextSize() 631 { 632 if (m_mainFrame) 633 m_mainFrame->DecreaseTextSize(); 634 } 635 636 void wxWebView::ResetTextSize() 637 { 638 if (m_mainFrame) 639 m_mainFrame->ResetTextSize(); 640 } 641 642 void wxWebView::MakeEditable(bool enable) 643 { 644 if (m_mainFrame) 645 m_mainFrame->MakeEditable(enable); 646 } 647 648 bool wxWebView::IsEditable() const 649 { 650 if (m_mainFrame) 651 return m_mainFrame->IsEditable(); 652 653 return false; 654 } 655 656 657 658 /* 659 * Event forwarding functions to send events down to WebCore. 660 */ 661 662 void wxWebView::OnPaint(wxPaintEvent& event) 663 { 664 if (m_beingDestroyed || !m_mainFrame) 665 return; 666 667 WebCore::Frame* frame = m_mainFrame->GetFrame(); 668 if (!frame || !frame->view()) 669 return; 670 671 wxAutoBufferedPaintDC dc(this); 672 673 if (IsShown() && frame->document()) { 674 #if USE(WXGC) 675 wxGCDC gcdc(dc); 676 #endif 677 678 if (dc.IsOk()) { 679 wxRect paintRect = GetUpdateRegion().GetBox(); 680 681 #if USE(WXGC) 682 WebCore::GraphicsContext gc(&gcdc); 683 #else 684 WebCore::GraphicsContext gc(&dc); 685 #endif 686 if (frame->contentRenderer()) { 687 frame->view()->updateLayoutAndStyleIfNeededRecursive(); 688 frame->view()->paint(&gc, paintRect); 689 } 690 } 691 } 692 } 693 694 bool wxWebView::FindString(const wxString& string, bool forward, bool caseSensitive, bool wrapSelection, bool startInSelection) 695 { 696 if (m_mainFrame) 697 return m_mainFrame->FindString(string, forward, caseSensitive, wrapSelection, startInSelection); 698 699 return false; 700 } 701 702 void wxWebView::OnSize(wxSizeEvent& event) 703 { 704 if (m_isInitialized && m_mainFrame) { 705 WebCore::Frame* frame = m_mainFrame->GetFrame(); 706 frame->view()->resize(event.GetSize()); 707 frame->view()->adjustViewSize(); 708 } 709 710 event.Skip(); 711 } 712 713 static int getDoubleClickTime() 714 { 715 #if __WXMSW__ 716 return ::GetDoubleClickTime(); 717 #else 718 return 500; 719 #endif 720 } 721 722 void wxWebView::OnMouseEvents(wxMouseEvent& event) 723 { 724 event.Skip(); 725 726 if (!m_impl->page) 727 return; 728 729 WebCore::Frame* frame = m_mainFrame->GetFrame(); 730 if (!frame || !frame->view()) 731 return; 732 733 wxPoint globalPoint = ClientToScreen(event.GetPosition()); 734 735 wxEventType type = event.GetEventType(); 736 737 if (type == wxEVT_MOUSEWHEEL) { 738 if (m_mouseWheelZooms && event.ControlDown() && !event.AltDown() && !event.ShiftDown()) { 739 if (event.GetWheelRotation() < 0) 740 DecreaseTextSize(); 741 else if (event.GetWheelRotation() > 0) 742 IncreaseTextSize(); 743 } else { 744 WebCore::PlatformWheelEvent wkEvent(event, globalPoint); 745 frame->eventHandler()->handleWheelEvent(wkEvent); 746 } 747 748 return; 749 } 750 751 // If an event, such as a right-click event, leads to a focus change (e.g. it 752 // raises a dialog), WebKit never gets the mouse up event and never relinquishes 753 // mouse capture. This leads to WebKit handling mouse events, such as modifying 754 // the selection, while other controls or top level windows have the focus. 755 // I'm not sure if this is the right place to handle this, but I can't seem to 756 // find a precedent on how to handle this in other ports. 757 if (wxWindow::FindFocus() != this) { 758 while (HasCapture()) 759 ReleaseMouse(); 760 761 frame->eventHandler()->setMousePressed(false); 762 763 return; 764 } 765 766 int clickCount = event.ButtonDClick() ? 2 : 1; 767 768 if (clickCount == 1 && m_impl->tripleClickTimer.IsRunning()) { 769 wxPoint diff(event.GetPosition() - m_impl->tripleClickPos); 770 if (abs(diff.x) <= wxSystemSettings::GetMetric(wxSYS_DCLICK_X) && 771 abs(diff.y) <= wxSystemSettings::GetMetric(wxSYS_DCLICK_Y)) { 772 clickCount = 3; 773 } 774 } else if (clickCount == 2) { 775 m_impl->tripleClickTimer.Start(getDoubleClickTime(), false); 776 m_impl->tripleClickPos = event.GetPosition(); 777 } 778 779 WebCore::PlatformMouseEvent wkEvent(event, globalPoint, clickCount); 780 781 if (type == wxEVT_LEFT_DOWN || type == wxEVT_MIDDLE_DOWN || type == wxEVT_RIGHT_DOWN || 782 type == wxEVT_LEFT_DCLICK || type == wxEVT_MIDDLE_DCLICK || type == wxEVT_RIGHT_DCLICK) { 783 frame->eventHandler()->handleMousePressEvent(wkEvent); 784 if (!HasCapture()) 785 CaptureMouse(); 786 } else if (type == wxEVT_LEFT_UP || type == wxEVT_MIDDLE_UP || type == wxEVT_RIGHT_UP) { 787 frame->eventHandler()->handleMouseReleaseEvent(wkEvent); 788 while (HasCapture()) 789 ReleaseMouse(); 790 } else if (type == wxEVT_MOTION || type == wxEVT_ENTER_WINDOW || type == wxEVT_LEAVE_WINDOW) 791 frame->eventHandler()->mouseMoved(wkEvent); 792 } 793 794 void wxWebView::OnContextMenuEvents(wxContextMenuEvent& event) 795 { 796 Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(wxWebView::OnMenuSelectEvents), NULL, this); 797 m_impl->page->contextMenuController()->clearContextMenu(); 798 wxPoint localEventPoint = ScreenToClient(event.GetPosition()); 799 800 if (!m_impl->page) 801 return; 802 803 WebCore::Frame* focusedFrame = m_impl->page->focusController()->focusedOrMainFrame(); 804 if (!focusedFrame->view()) 805 return; 806 807 //Create WebCore mouse event from the wxContextMenuEvent 808 wxMouseEvent mouseEvent(wxEVT_RIGHT_DOWN); 809 mouseEvent.m_x = localEventPoint.x; 810 mouseEvent.m_y = localEventPoint.y; 811 WebCore::PlatformMouseEvent wkEvent(mouseEvent, event.GetPosition(), 1); 812 813 bool handledEvent = focusedFrame->eventHandler()->sendContextMenuEvent(wkEvent); 814 if (!handledEvent) 815 return; 816 817 WebCore::ContextMenu* coreMenu = m_impl->page->contextMenuController()->contextMenu(); 818 if (!coreMenu) 819 return; 820 821 WebCore::PlatformMenuDescription menuWx = coreMenu->platformDescription(); 822 if (!menuWx) 823 return; 824 825 PopupMenu(menuWx, localEventPoint); 826 827 Disconnect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(wxWebView::OnMenuSelectEvents), NULL, this); 828 } 829 830 void wxWebView::OnMenuSelectEvents(wxCommandEvent& event) 831 { 832 // we shouldn't hit this unless there's a context menu showing 833 WebCore::ContextMenu* coreMenu = m_impl->page->contextMenuController()->contextMenu(); 834 ASSERT(coreMenu); 835 if (!coreMenu) 836 return; 837 838 WebCore::ContextMenuItem* item = WebCore::ContextMenu::itemWithId (event.GetId()); 839 if (!item) 840 return; 841 842 m_impl->page->contextMenuController()->contextMenuItemSelected(item); 843 delete item; 844 } 845 846 bool wxWebView::CanCopy() 847 { 848 if (m_mainFrame) 849 return m_mainFrame->CanCopy(); 850 851 return false; 852 } 853 854 void wxWebView::Copy() 855 { 856 if (m_mainFrame) 857 m_mainFrame->Copy(); 858 } 859 860 bool wxWebView::CanCut() 861 { 862 if (m_mainFrame) 863 return m_mainFrame->CanCut(); 864 865 return false; 866 } 867 868 void wxWebView::Cut() 869 { 870 if (m_mainFrame) 871 m_mainFrame->Cut(); 872 } 873 874 bool wxWebView::CanPaste() 875 { 876 if (m_mainFrame) 877 return m_mainFrame->CanPaste(); 878 879 return false; 880 } 881 882 void wxWebView::Paste() 883 { 884 if (m_mainFrame) 885 m_mainFrame->Paste(); 886 } 887 888 void wxWebView::OnKeyEvents(wxKeyEvent& event) 889 { 890 WebCore::Frame* frame = 0; 891 if (m_impl->page) 892 frame = m_impl->page->focusController()->focusedOrMainFrame(); 893 894 if (!(frame && frame->view())) 895 return; 896 897 WebCore::PlatformKeyboardEvent wkEvent(event); 898 899 if (frame->eventHandler()->keyEvent(wkEvent)) 900 return; 901 902 //Some things WebKit won't do for us... Copy/Cut/Paste and KB scrolling 903 if (event.GetEventType() == wxEVT_KEY_DOWN) { 904 switch (event.GetKeyCode()) { 905 case 67: //"C" 906 if (CanCopy() && event.GetModifiers() == wxMOD_CMD) { 907 Copy(); 908 return; 909 } 910 break; 911 case 86: //"V" 912 if (CanPaste() && event.GetModifiers() == wxMOD_CMD) { 913 Paste(); 914 return; 915 } 916 break; 917 case 88: //"X" 918 if (CanCut() && event.GetModifiers() == wxMOD_CMD) { 919 Cut(); 920 return; 921 } 922 break; 923 case WXK_INSERT: 924 if (CanCopy() && event.GetModifiers() == wxMOD_CMD) { 925 Copy(); 926 return; 927 } 928 if (CanPaste() && event.GetModifiers() == wxMOD_SHIFT) { 929 Paste(); 930 return; 931 } 932 return; //Insert shall not become a char 933 case WXK_DELETE: 934 if (CanCut() && event.GetModifiers() == wxMOD_SHIFT) { 935 Cut(); 936 return; 937 } 938 break; 939 case WXK_LEFT: 940 case WXK_NUMPAD_LEFT: 941 frame->view()->scrollBy(WebCore::IntSize(-WebCore::Scrollbar::pixelsPerLineStep(), 0)); 942 return; 943 case WXK_UP: 944 case WXK_NUMPAD_UP: 945 frame->view()->scrollBy(WebCore::IntSize(0, -WebCore::Scrollbar::pixelsPerLineStep())); 946 return; 947 case WXK_RIGHT: 948 case WXK_NUMPAD_RIGHT: 949 frame->view()->scrollBy(WebCore::IntSize(WebCore::Scrollbar::pixelsPerLineStep(), 0)); 950 return; 951 case WXK_DOWN: 952 case WXK_NUMPAD_DOWN: 953 frame->view()->scrollBy(WebCore::IntSize(0, WebCore::Scrollbar::pixelsPerLineStep())); 954 return; 955 case WXK_END: 956 case WXK_NUMPAD_END: 957 frame->view()->setScrollPosition(WebCore::IntPoint(frame->view()->scrollX(), frame->view()->maximumScrollPosition().y())); 958 return; 959 case WXK_HOME: 960 case WXK_NUMPAD_HOME: 961 frame->view()->setScrollPosition(WebCore::IntPoint(frame->view()->scrollX(), 0)); 962 return; 963 case WXK_PAGEUP: 964 case WXK_NUMPAD_PAGEUP: 965 frame->view()->scrollBy(WebCore::IntSize(0, -frame->view()->visibleHeight() * WebCore::Scrollbar::minFractionToStepWhenPaging())); 966 return; 967 case WXK_PAGEDOWN: 968 case WXK_NUMPAD_PAGEDOWN: 969 frame->view()->scrollBy(WebCore::IntSize(0, frame->view()->visibleHeight() * WebCore::Scrollbar::minFractionToStepWhenPaging())); 970 return; 971 //These we don't want turning into char events, stuff 'em 972 case WXK_ESCAPE: 973 case WXK_LBUTTON: 974 case WXK_RBUTTON: 975 case WXK_CANCEL: 976 case WXK_MENU: 977 case WXK_MBUTTON: 978 case WXK_CLEAR: 979 case WXK_PAUSE: 980 case WXK_SELECT: 981 case WXK_PRINT: 982 case WXK_EXECUTE: 983 case WXK_SNAPSHOT: 984 case WXK_HELP: 985 case WXK_F1: 986 case WXK_F2: 987 case WXK_F3: 988 case WXK_F4: 989 case WXK_F5: 990 case WXK_F6: 991 case WXK_F7: 992 case WXK_F8: 993 case WXK_F9: 994 case WXK_F10: 995 case WXK_F11: 996 case WXK_F12: 997 case WXK_F13: 998 case WXK_F14: 999 case WXK_F15: 1000 case WXK_F16: 1001 case WXK_F17: 1002 case WXK_F18: 1003 case WXK_F19: 1004 case WXK_F20: 1005 case WXK_F21: 1006 case WXK_F22: 1007 case WXK_F23: 1008 case WXK_F24: 1009 case WXK_NUMPAD_F1: 1010 case WXK_NUMPAD_F2: 1011 case WXK_NUMPAD_F3: 1012 case WXK_NUMPAD_F4: 1013 //When numlock is off Numpad 5 becomes BEGIN, or HOME on Char 1014 case WXK_NUMPAD_BEGIN: 1015 case WXK_NUMPAD_INSERT: 1016 return; 1017 } 1018 } 1019 1020 event.Skip(); 1021 } 1022 1023 void wxWebView::OnSetFocus(wxFocusEvent& event) 1024 { 1025 if (m_impl && m_impl->page && m_impl->page->focusController()) { 1026 m_impl->page->focusController()->setFocused(true); 1027 m_impl->page->focusController()->setActive(true); 1028 1029 if (!m_impl->page->focusController()->focusedFrame() && m_mainFrame) 1030 m_impl->page->focusController()->setFocusedFrame(m_mainFrame->GetFrame()); 1031 } 1032 1033 event.Skip(); 1034 } 1035 1036 void wxWebView::OnKillFocus(wxFocusEvent& event) 1037 { 1038 if (m_impl && m_impl->page && m_impl->page->focusController()) { 1039 m_impl->page->focusController()->setFocused(false); 1040 1041 // We also handle active state in OnTLWActivated, but if a user does not 1042 // call event.Skip() in their own EVT_ACTIVATE handler, we won't get those 1043 // callbacks. So we handle active state here as well as a fallback. 1044 wxTopLevelWindow* tlw = dynamic_cast<wxTopLevelWindow*>(wxGetTopLevelParent(this)); 1045 if (tlw && tlw->IsActive()) 1046 m_impl->page->focusController()->setActive(true); 1047 else 1048 m_impl->page->focusController()->setActive(false); 1049 } 1050 1051 while (HasCapture()) 1052 ReleaseMouse(); 1053 1054 event.Skip(); 1055 } 1056 1057 wxWebViewDOMElementInfo wxWebView::HitTest(const wxPoint& pos) const 1058 { 1059 if (m_mainFrame) 1060 return m_mainFrame->HitTest(pos); 1061 1062 return wxWebViewDOMElementInfo(); 1063 } 1064 1065 bool wxWebView::ShouldClose() const 1066 { 1067 if (m_mainFrame) 1068 return m_mainFrame->ShouldClose(); 1069 1070 return true; 1071 } 1072 1073 /* static */ 1074 void wxWebView::SetDatabaseDirectory(const wxString& databaseDirectory) 1075 { 1076 #if ENABLE(DATABASE) 1077 WebCore::DatabaseTracker::tracker().setDatabaseDirectoryPath(databaseDirectory); 1078 #endif 1079 } 1080 1081 /* static */ 1082 wxString wxWebView::GetDatabaseDirectory() 1083 { 1084 #if ENABLE(DATABASE) 1085 return WebCore::DatabaseTracker::tracker().databaseDirectoryPath(); 1086 #else 1087 return wxEmptyString; 1088 #endif 1089 } 1090 1091 /* static */ 1092 void wxWebView::SetDatabasesEnabled(bool enabled) 1093 { 1094 #if ENABLE(DATABASE) 1095 WebCore::AbstractDatabase::setIsAvailable(enabled); 1096 #endif 1097 } 1098 1099 /* static */ 1100 bool wxWebView::AreDatabasesEnabled() 1101 { 1102 #if ENABLE(DATABASE) 1103 return WebCore::AbstractDatabase::isAvailable(); 1104 #endif 1105 return false; 1106 } 1107 1108 static WebCore::ResourceHandleManager::ProxyType curlProxyType(wxProxyType type) 1109 { 1110 switch (type) { 1111 case HTTP: return WebCore::ResourceHandleManager::HTTP; 1112 case Socks4: return WebCore::ResourceHandleManager::Socks4; 1113 case Socks4A: return WebCore::ResourceHandleManager::Socks4A; 1114 case Socks5: return WebCore::ResourceHandleManager::Socks5; 1115 case Socks5Hostname: return WebCore::ResourceHandleManager::Socks5Hostname; 1116 default: 1117 ASSERT_NOT_REACHED(); 1118 return WebCore::ResourceHandleManager::HTTP; 1119 } 1120 } 1121 1122 /* static */ 1123 void wxWebView::SetProxyInfo(const wxString& host, 1124 unsigned long port, 1125 wxProxyType type, 1126 const wxString& username, 1127 const wxString& password) 1128 { 1129 using WebCore::ResourceHandleManager; 1130 if (ResourceHandleManager* mgr = ResourceHandleManager::sharedInstance()) 1131 mgr->setProxyInfo(host, port, curlProxyType(type), username, password); 1132 } 1133 1134 wxWebSettings wxWebView::GetWebSettings() 1135 { 1136 ASSERT(m_impl->page); 1137 if (m_impl->page) 1138 return wxWebSettings(m_impl->page->settings()); 1139 1140 return wxWebSettings(); 1141 } 1142 1143 wxWebKitCompatibilityMode wxWebView::GetCompatibilityMode() const 1144 { 1145 if (m_mainFrame) 1146 return m_mainFrame->GetCompatibilityMode(); 1147 1148 return QuirksMode; 1149 } 1150 1151 void wxWebView::GrantUniversalAccess() 1152 { 1153 if (m_mainFrame) 1154 m_mainFrame->GrantUniversalAccess(); 1155 } 1156