Home | History | Annotate | Download | only in wx
      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