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 "Cache.h"
28#include "ContextMenu.h"
29#include "ContextMenuItem.h"
30#include "ContextMenuController.h"
31#include "CString.h"
32#include "Document.h"
33#include "Element.h"
34#include "Editor.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 "markup.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
61#include "ChromeClientWx.h"
62#include "ContextMenuClientWx.h"
63#include "DragClientWx.h"
64#include "EditorClientWx.h"
65#include "FrameLoaderClientWx.h"
66#include "InspectorClientWx.h"
67
68#include "ScriptController.h"
69#include "JSDOMBinding.h"
70#include <runtime/JSValue.h>
71#include <runtime/UString.h>
72
73#if ENABLE(DATABASE)
74#include "DatabaseTracker.h"
75#endif
76
77#include "wx/wxprec.h"
78#ifndef WX_PRECOMP
79    #include "wx/wx.h"
80#endif
81
82#include "WebFrame.h"
83#include "WebView.h"
84#include "WebViewPrivate.h"
85
86#include <wx/defs.h>
87#include <wx/dcbuffer.h>
88#include <wx/dcgraph.h>
89
90#if defined(_MSC_VER)
91int rint(double val)
92{
93    return (int)(val < 0 ? val - 0.5 : val + 0.5);
94}
95#endif
96
97// ----------------------------------------------------------------------------
98// wxWebView Events
99// ----------------------------------------------------------------------------
100
101IMPLEMENT_DYNAMIC_CLASS(wxWebViewLoadEvent, wxCommandEvent)
102
103DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_LOAD)
104
105wxWebViewLoadEvent::wxWebViewLoadEvent(wxWindow* win)
106{
107    SetEventType( wxEVT_WEBVIEW_LOAD);
108    SetEventObject( win );
109    if (win)
110        SetId(win->GetId());
111}
112
113IMPLEMENT_DYNAMIC_CLASS(wxWebViewBeforeLoadEvent, wxCommandEvent)
114
115DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_BEFORE_LOAD)
116
117wxWebViewBeforeLoadEvent::wxWebViewBeforeLoadEvent(wxWindow* win)
118{
119    m_cancelled = false;
120    SetEventType(wxEVT_WEBVIEW_BEFORE_LOAD);
121    SetEventObject(win);
122    if (win)
123        SetId(win->GetId());
124}
125
126IMPLEMENT_DYNAMIC_CLASS(wxWebViewNewWindowEvent, wxCommandEvent)
127
128DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_NEW_WINDOW)
129
130wxWebViewNewWindowEvent::wxWebViewNewWindowEvent(wxWindow* win)
131{
132    SetEventType(wxEVT_WEBVIEW_NEW_WINDOW);
133    SetEventObject(win);
134    if (win)
135        SetId(win->GetId());
136}
137
138IMPLEMENT_DYNAMIC_CLASS(wxWebViewRightClickEvent, wxCommandEvent)
139
140DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_RIGHT_CLICK)
141
142wxWebViewRightClickEvent::wxWebViewRightClickEvent(wxWindow* win)
143{
144    SetEventType(wxEVT_WEBVIEW_RIGHT_CLICK);
145    SetEventObject(win);
146    if (win)
147        SetId(win->GetId());
148}
149
150IMPLEMENT_DYNAMIC_CLASS(wxWebViewConsoleMessageEvent, wxCommandEvent)
151
152DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_CONSOLE_MESSAGE)
153
154wxWebViewConsoleMessageEvent::wxWebViewConsoleMessageEvent(wxWindow* win)
155{
156    SetEventType(wxEVT_WEBVIEW_CONSOLE_MESSAGE);
157    SetEventObject(win);
158    if (win)
159        SetId(win->GetId());
160}
161
162IMPLEMENT_DYNAMIC_CLASS(wxWebViewAlertEvent, wxCommandEvent)
163
164DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_JS_ALERT)
165
166wxWebViewAlertEvent::wxWebViewAlertEvent(wxWindow* win)
167{
168    SetEventType(wxEVT_WEBVIEW_JS_ALERT);
169    SetEventObject(win);
170    if (win)
171        SetId(win->GetId());
172}
173
174IMPLEMENT_DYNAMIC_CLASS(wxWebViewConfirmEvent, wxCommandEvent)
175
176DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_JS_CONFIRM)
177
178wxWebViewConfirmEvent::wxWebViewConfirmEvent(wxWindow* win)
179{
180    SetEventType(wxEVT_WEBVIEW_JS_CONFIRM);
181    SetEventObject(win);
182    if (win)
183        SetId(win->GetId());
184}
185
186IMPLEMENT_DYNAMIC_CLASS(wxWebViewPromptEvent, wxCommandEvent)
187
188DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_JS_PROMPT)
189
190wxWebViewPromptEvent::wxWebViewPromptEvent(wxWindow* win)
191{
192    SetEventType(wxEVT_WEBVIEW_JS_PROMPT);
193    SetEventObject(win);
194    if (win)
195        SetId(win->GetId());
196}
197
198IMPLEMENT_DYNAMIC_CLASS(wxWebViewReceivedTitleEvent, wxCommandEvent)
199
200DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_RECEIVED_TITLE)
201
202wxWebViewReceivedTitleEvent::wxWebViewReceivedTitleEvent(wxWindow* win)
203{
204    SetEventType(wxEVT_WEBVIEW_RECEIVED_TITLE);
205    SetEventObject(win);
206    if (win)
207        SetId(win->GetId());
208}
209
210IMPLEMENT_DYNAMIC_CLASS(wxWebViewWindowObjectClearedEvent, wxCommandEvent)
211
212DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_WINDOW_OBJECT_CLEARED)
213
214wxWebViewWindowObjectClearedEvent::wxWebViewWindowObjectClearedEvent(wxWindow* win)
215{
216    SetEventType(wxEVT_WEBVIEW_WINDOW_OBJECT_CLEARED);
217    SetEventObject(win);
218    if (win)
219        SetId(win->GetId());
220}
221
222
223//---------------------------------------------------------
224// DOM Element info data type
225//---------------------------------------------------------
226
227wxWebViewDOMElementInfo::wxWebViewDOMElementInfo() :
228    m_domElement(NULL),
229    m_isSelected(false),
230    m_text(wxEmptyString),
231    m_imageSrc(wxEmptyString),
232    m_link(wxEmptyString)
233{
234}
235
236static wxWebViewCachePolicy gs_cachePolicy;
237
238/* static */
239void wxWebView::SetCachePolicy(const wxWebViewCachePolicy& cachePolicy)
240{
241    WebCore::Cache* globalCache = WebCore::cache();
242    globalCache->setCapacities(cachePolicy.GetMinDeadCapacity(),
243                               cachePolicy.GetMaxDeadCapacity(),
244                               cachePolicy.GetCapacity());
245
246    // store a copy since there is no getter for Cache values
247    gs_cachePolicy = cachePolicy;
248}
249
250/* static */
251wxWebViewCachePolicy wxWebView::GetCachePolicy()
252{
253    return gs_cachePolicy;
254}
255
256BEGIN_EVENT_TABLE(wxWebView, wxWindow)
257    EVT_PAINT(wxWebView::OnPaint)
258    EVT_SIZE(wxWebView::OnSize)
259    EVT_MOUSE_EVENTS(wxWebView::OnMouseEvents)
260    EVT_CONTEXT_MENU(wxWebView::OnContextMenuEvents)
261    EVT_KEY_DOWN(wxWebView::OnKeyEvents)
262    EVT_KEY_UP(wxWebView::OnKeyEvents)
263    EVT_CHAR(wxWebView::OnKeyEvents)
264    EVT_SET_FOCUS(wxWebView::OnSetFocus)
265    EVT_KILL_FOCUS(wxWebView::OnKillFocus)
266END_EVENT_TABLE()
267
268IMPLEMENT_DYNAMIC_CLASS(wxWebView, wxWindow)
269
270const wxChar* wxWebViewNameStr = wxT("webView");
271
272wxWebView::wxWebView() :
273    m_textMagnifier(1.0),
274    m_isEditable(false),
275    m_isInitialized(false),
276    m_beingDestroyed(false),
277    m_mouseWheelZooms(false),
278    m_title(wxEmptyString)
279{
280}
281
282wxWebView::wxWebView(wxWindow* parent, int id, const wxPoint& position,
283                     const wxSize& size, long style, const wxString& name) :
284    m_textMagnifier(1.0),
285    m_isEditable(false),
286    m_isInitialized(false),
287    m_beingDestroyed(false),
288    m_mouseWheelZooms(false),
289    m_title(wxEmptyString)
290{
291    Create(parent, id, position, size, style, name);
292}
293
294bool wxWebView::Create(wxWindow* parent, int id, const wxPoint& position,
295                       const wxSize& size, long style, const wxString& name)
296{
297    if ( (style & wxBORDER_MASK) == 0)
298        style |= wxBORDER_NONE;
299
300    if (!wxWindow::Create(parent, id, position, size, style, name))
301        return false;
302
303    WTF::initializeThreading();
304
305// This is necessary because we are using SharedTimerWin.cpp on Windows,
306// due to a problem with exceptions getting eaten when using the callback
307// approach to timers (which wx itself uses).
308#if __WXMSW__
309    WebCore::Page::setInstanceHandle(wxGetInstance());
310#endif
311
312    // this helps reduce flicker on platforms like MSW
313    SetBackgroundStyle(wxBG_STYLE_CUSTOM);
314
315    m_impl = new WebViewPrivate();
316
317    WebCore::InitializeLoggingChannelsIfNecessary();
318    WebCore::HTMLFrameOwnerElement* parentFrame = 0;
319
320    WebCore::EditorClientWx* editorClient = new WebCore::EditorClientWx();
321    m_impl->page = new WebCore::Page(new WebCore::ChromeClientWx(this), new WebCore::ContextMenuClientWx(), editorClient, new WebCore::DragClientWx(), new WebCore::InspectorClientWx(), 0, 0);
322    editorClient->setPage(m_impl->page);
323
324    m_mainFrame = new wxWebFrame(this);
325
326    // Default settings - we should have wxWebViewSettings class for this
327    // eventually
328    WebCore::Settings* settings = m_impl->page->settings();
329    settings->setLoadsImagesAutomatically(true);
330    settings->setDefaultFixedFontSize(13);
331    settings->setDefaultFontSize(16);
332    settings->setSerifFontFamily("Times New Roman");
333    settings->setFixedFontFamily("Courier New");
334    settings->setSansSerifFontFamily("Arial");
335    settings->setStandardFontFamily("Times New Roman");
336    settings->setJavaScriptEnabled(true);
337
338#if ENABLE(DATABASE)
339    settings->setDatabasesEnabled(true);
340#endif
341
342    m_isInitialized = true;
343
344    return true;
345}
346
347wxWebView::~wxWebView()
348{
349    m_beingDestroyed = true;
350
351    while (HasCapture())
352        ReleaseMouse();
353
354    if (m_mainFrame && m_mainFrame->GetFrame())
355        m_mainFrame->GetFrame()->loader()->detachFromParent();
356
357    delete m_impl->page;
358    m_impl->page = 0;
359}
360
361void wxWebView::Stop()
362{
363    if (m_mainFrame)
364        m_mainFrame->Stop();
365}
366
367void wxWebView::Reload()
368{
369    if (m_mainFrame)
370        m_mainFrame->Reload();
371}
372
373wxString wxWebView::GetPageSource()
374{
375    if (m_mainFrame)
376        return m_mainFrame->GetPageSource();
377
378    return wxEmptyString;
379}
380
381void wxWebView::SetPageSource(const wxString& source, const wxString& baseUrl)
382{
383    if (m_mainFrame)
384        m_mainFrame->SetPageSource(source, baseUrl);
385}
386
387wxString wxWebView::GetInnerText()
388{
389    if (m_mainFrame)
390        return m_mainFrame->GetInnerText();
391
392    return wxEmptyString;
393}
394
395wxString wxWebView::GetAsMarkup()
396{
397    if (m_mainFrame)
398        return m_mainFrame->GetAsMarkup();
399
400    return wxEmptyString;
401}
402
403wxString wxWebView::GetExternalRepresentation()
404{
405    if (m_mainFrame)
406        return m_mainFrame->GetExternalRepresentation();
407
408    return wxEmptyString;
409}
410
411void wxWebView::SetTransparent(bool transparent)
412{
413    WebCore::Frame* frame = 0;
414    if (m_mainFrame)
415        frame = m_mainFrame->GetFrame();
416
417    if (!frame || !frame->view())
418        return;
419
420    frame->view()->setTransparent(transparent);
421}
422
423bool wxWebView::IsTransparent() const
424{
425    WebCore::Frame* frame = 0;
426    if (m_mainFrame)
427        frame = m_mainFrame->GetFrame();
428
429   if (!frame || !frame->view())
430        return false;
431
432    return frame->view()->isTransparent();
433}
434
435wxString wxWebView::RunScript(const wxString& javascript)
436{
437    if (m_mainFrame)
438        return m_mainFrame->RunScript(javascript);
439
440    return wxEmptyString;
441}
442
443void wxWebView::LoadURL(const wxString& url)
444{
445    if (m_mainFrame)
446        m_mainFrame->LoadURL(url);
447}
448
449bool wxWebView::GoBack()
450{
451    if (m_mainFrame)
452        return m_mainFrame->GoBack();
453
454    return false;
455}
456
457bool wxWebView::GoForward()
458{
459    if (m_mainFrame)
460        return m_mainFrame->GoForward();
461
462    return false;
463}
464
465bool wxWebView::CanGoBack()
466{
467    if (m_mainFrame)
468        return m_mainFrame->CanGoBack();
469
470    return false;
471}
472
473bool wxWebView::CanGoForward()
474{
475    if (m_mainFrame)
476        return m_mainFrame->CanGoForward();
477
478    return false;
479}
480
481bool wxWebView::CanIncreaseTextSize() const
482{
483    if (m_mainFrame)
484        return m_mainFrame->CanIncreaseTextSize();
485
486    return false;
487}
488
489void wxWebView::IncreaseTextSize()
490{
491    if (m_mainFrame)
492        m_mainFrame->IncreaseTextSize();
493}
494
495bool wxWebView::CanDecreaseTextSize() const
496{
497    if (m_mainFrame)
498        m_mainFrame->CanDecreaseTextSize();
499
500    return false;
501}
502
503void wxWebView::DecreaseTextSize()
504{
505    if (m_mainFrame)
506        m_mainFrame->DecreaseTextSize();
507}
508
509void wxWebView::ResetTextSize()
510{
511    if (m_mainFrame)
512        m_mainFrame->ResetTextSize();
513}
514
515void wxWebView::MakeEditable(bool enable)
516{
517    m_isEditable = enable;
518}
519
520
521/*
522 * Event forwarding functions to send events down to WebCore.
523 */
524
525void wxWebView::OnPaint(wxPaintEvent& event)
526{
527    if (m_beingDestroyed || !m_mainFrame)
528        return;
529
530    // WebView active state is based on TLW active state.
531    wxTopLevelWindow* tlw = dynamic_cast<wxTopLevelWindow*>(wxGetTopLevelParent(this));
532    if (tlw && tlw->IsActive())
533        m_impl->page->focusController()->setActive(true);
534    else {
535        m_impl->page->focusController()->setActive(false);
536    }
537    WebCore::Frame* frame = m_mainFrame->GetFrame();
538    if (!frame || !frame->view())
539        return;
540
541    wxAutoBufferedPaintDC dc(this);
542
543    if (IsShown() && frame->document()) {
544#if USE(WXGC)
545        wxGCDC gcdc(dc);
546#endif
547
548        if (dc.IsOk()) {
549            wxRect paintRect = GetUpdateRegion().GetBox();
550
551#if USE(WXGC)
552            WebCore::GraphicsContext gc(&gcdc);
553#else
554            WebCore::GraphicsContext gc(&dc);
555#endif
556            if (frame->contentRenderer()) {
557                frame->view()->layoutIfNeededRecursive();
558                frame->view()->paint(&gc, paintRect);
559            }
560        }
561    }
562}
563
564bool wxWebView::FindString(const wxString& string, bool forward, bool caseSensitive, bool wrapSelection, bool startInSelection)
565{
566    if (m_mainFrame)
567        return m_mainFrame->FindString(string, forward, caseSensitive, wrapSelection, startInSelection);
568
569    return false;
570}
571
572void wxWebView::OnSize(wxSizeEvent& event)
573{
574    if (m_isInitialized && m_mainFrame) {
575        WebCore::Frame* frame = m_mainFrame->GetFrame();
576        frame->view()->setFrameRect(wxRect(wxPoint(0,0), event.GetSize()));
577        frame->view()->forceLayout();
578        frame->view()->adjustViewSize();
579    }
580
581    event.Skip();
582}
583
584static int getDoubleClickTime()
585{
586#if __WXMSW__
587    return ::GetDoubleClickTime();
588#else
589    return 500;
590#endif
591}
592
593void wxWebView::OnMouseEvents(wxMouseEvent& event)
594{
595    event.Skip();
596
597    if (!m_impl->page)
598        return;
599
600    WebCore::Frame* frame = m_mainFrame->GetFrame();
601    if (!frame || !frame->view())
602        return;
603
604    wxPoint globalPoint = ClientToScreen(event.GetPosition());
605
606    wxEventType type = event.GetEventType();
607
608    if (type == wxEVT_MOUSEWHEEL) {
609        if (m_mouseWheelZooms && event.ControlDown() && !event.AltDown() && !event.ShiftDown()) {
610            if (event.GetWheelRotation() < 0)
611                DecreaseTextSize();
612            else if (event.GetWheelRotation() > 0)
613                IncreaseTextSize();
614        } else {
615            WebCore::PlatformWheelEvent wkEvent(event, globalPoint);
616            frame->eventHandler()->handleWheelEvent(wkEvent);
617        }
618
619        return;
620    }
621
622    int clickCount = event.ButtonDClick() ? 2 : 1;
623
624    if (clickCount == 1 && m_impl->tripleClickTimer.IsRunning()) {
625        wxPoint diff(event.GetPosition() - m_impl->tripleClickPos);
626        if (abs(diff.x) <= wxSystemSettings::GetMetric(wxSYS_DCLICK_X) &&
627            abs(diff.y) <= wxSystemSettings::GetMetric(wxSYS_DCLICK_Y)) {
628            clickCount = 3;
629        }
630    } else if (clickCount == 2) {
631        m_impl->tripleClickTimer.Start(getDoubleClickTime(), false);
632        m_impl->tripleClickPos = event.GetPosition();
633    }
634
635    WebCore::PlatformMouseEvent wkEvent(event, globalPoint, clickCount);
636
637    if (type == wxEVT_LEFT_DOWN || type == wxEVT_MIDDLE_DOWN || type == wxEVT_RIGHT_DOWN ||
638                type == wxEVT_LEFT_DCLICK || type == wxEVT_MIDDLE_DCLICK || type == wxEVT_RIGHT_DCLICK) {
639        frame->eventHandler()->handleMousePressEvent(wkEvent);
640        if (!HasCapture())
641            CaptureMouse();
642    } else if (type == wxEVT_LEFT_UP || type == wxEVT_MIDDLE_UP || type == wxEVT_RIGHT_UP) {
643        frame->eventHandler()->handleMouseReleaseEvent(wkEvent);
644        while (HasCapture())
645            ReleaseMouse();
646    } else if (type == wxEVT_MOTION || type == wxEVT_ENTER_WINDOW || type == wxEVT_LEAVE_WINDOW)
647        frame->eventHandler()->mouseMoved(wkEvent);
648}
649
650void wxWebView::OnContextMenuEvents(wxContextMenuEvent& event)
651{
652    Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(wxWebView::OnMenuSelectEvents), NULL, this);
653    m_impl->page->contextMenuController()->clearContextMenu();
654    wxPoint localEventPoint = ScreenToClient(event.GetPosition());
655
656    if (!m_impl->page)
657        return;
658
659    WebCore::Frame* focusedFrame = m_impl->page->focusController()->focusedOrMainFrame();
660    if (!focusedFrame->view())
661        return;
662
663    //Create WebCore mouse event from the wxContextMenuEvent
664    wxMouseEvent mouseEvent(wxEVT_RIGHT_DOWN);
665    mouseEvent.m_x = localEventPoint.x;
666    mouseEvent.m_y = localEventPoint.y;
667    WebCore::PlatformMouseEvent wkEvent(mouseEvent, event.GetPosition(), 1);
668
669    bool handledEvent = focusedFrame->eventHandler()->sendContextMenuEvent(wkEvent);
670    if (!handledEvent)
671        return;
672
673    WebCore::ContextMenu* coreMenu = m_impl->page->contextMenuController()->contextMenu();
674    if (!coreMenu)
675        return;
676
677    WebCore::PlatformMenuDescription menuWx = coreMenu->platformDescription();
678    if (!menuWx)
679        return;
680
681    PopupMenu(menuWx, localEventPoint);
682
683    Disconnect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(wxWebView::OnMenuSelectEvents), NULL, this);
684}
685
686void wxWebView::OnMenuSelectEvents(wxCommandEvent& event)
687{
688    // we shouldn't hit this unless there's a context menu showing
689    WebCore::ContextMenu* coreMenu = m_impl->page->contextMenuController()->contextMenu();
690    ASSERT(coreMenu);
691    if (!coreMenu)
692        return;
693
694    WebCore::ContextMenuItem* item = WebCore::ContextMenu::itemWithId (event.GetId());
695    if (!item)
696        return;
697
698    m_impl->page->contextMenuController()->contextMenuItemSelected(item);
699    delete item;
700}
701
702bool wxWebView::CanCopy()
703{
704    if (m_mainFrame)
705        return m_mainFrame->CanCopy();
706
707    return false;
708}
709
710void wxWebView::Copy()
711{
712    if (m_mainFrame)
713        m_mainFrame->Copy();
714}
715
716bool wxWebView::CanCut()
717{
718    if (m_mainFrame)
719        return m_mainFrame->CanCut();
720
721    return false;
722}
723
724void wxWebView::Cut()
725{
726    if (m_mainFrame)
727        m_mainFrame->Cut();
728}
729
730bool wxWebView::CanPaste()
731{
732    if (m_mainFrame)
733        return m_mainFrame->CanPaste();
734
735    return false;
736}
737
738void wxWebView::Paste()
739{
740    if (m_mainFrame)
741        m_mainFrame->Paste();
742}
743
744void wxWebView::OnKeyEvents(wxKeyEvent& event)
745{
746    WebCore::Frame* frame = 0;
747    if (m_impl->page)
748        frame = m_impl->page->focusController()->focusedOrMainFrame();
749
750    if (!(frame && frame->view()))
751        return;
752
753    if (event.GetKeyCode() == WXK_CAPITAL)
754        frame->eventHandler()->capsLockStateMayHaveChanged();
755
756    WebCore::PlatformKeyboardEvent wkEvent(event);
757
758    if (frame->eventHandler()->keyEvent(wkEvent))
759        return;
760
761    //Some things WebKit won't do for us... Copy/Cut/Paste and KB scrolling
762    if (event.GetEventType() == wxEVT_KEY_DOWN) {
763        switch (event.GetKeyCode()) {
764        case 67: //"C"
765            if (CanCopy() && event.GetModifiers() == wxMOD_CMD) {
766                Copy();
767                return;
768            }
769            break;
770        case 86: //"V"
771            if (CanPaste() && event.GetModifiers() == wxMOD_CMD) {
772                Paste();
773                return;
774            }
775            break;
776        case 88: //"X"
777            if (CanCut() && event.GetModifiers() == wxMOD_CMD) {
778                Cut();
779                return;
780            }
781            break;
782        case WXK_INSERT:
783            if (CanCopy() && event.GetModifiers() == wxMOD_CMD) {
784                Copy();
785                return;
786            }
787            if (CanPaste() && event.GetModifiers() == wxMOD_SHIFT) {
788                Paste();
789                return;
790            }
791            return; //Insert shall not become a char
792        case WXK_DELETE:
793            if (CanCut() && event.GetModifiers() == wxMOD_SHIFT) {
794                Cut();
795                return;
796            }
797            break;
798        case WXK_LEFT:
799        case WXK_NUMPAD_LEFT:
800            frame->view()->scrollBy(WebCore::IntSize(-WebCore::Scrollbar::pixelsPerLineStep(), 0));
801            return;
802        case WXK_UP:
803        case WXK_NUMPAD_UP:
804            frame->view()->scrollBy(WebCore::IntSize(0, -WebCore::Scrollbar::pixelsPerLineStep()));
805            return;
806        case WXK_RIGHT:
807        case WXK_NUMPAD_RIGHT:
808            frame->view()->scrollBy(WebCore::IntSize(WebCore::Scrollbar::pixelsPerLineStep(), 0));
809            return;
810        case WXK_DOWN:
811        case WXK_NUMPAD_DOWN:
812            frame->view()->scrollBy(WebCore::IntSize(0, WebCore::Scrollbar::pixelsPerLineStep()));
813            return;
814        case WXK_END:
815        case WXK_NUMPAD_END:
816            frame->view()->setScrollPosition(WebCore::IntPoint(frame->view()->scrollX(), frame->view()->maximumScrollPosition().y()));
817            return;
818        case WXK_HOME:
819        case WXK_NUMPAD_HOME:
820            frame->view()->setScrollPosition(WebCore::IntPoint(frame->view()->scrollX(), 0));
821            return;
822        case WXK_PAGEUP:
823        case WXK_NUMPAD_PAGEUP:
824            frame->view()->scrollBy(WebCore::IntSize(0, -frame->view()->visibleHeight() * WebCore::Scrollbar::minFractionToStepWhenPaging()));
825            return;
826        case WXK_PAGEDOWN:
827        case WXK_NUMPAD_PAGEDOWN:
828            frame->view()->scrollBy(WebCore::IntSize(0, frame->view()->visibleHeight() * WebCore::Scrollbar::minFractionToStepWhenPaging()));
829            return;
830        //These we don't want turning into char events, stuff 'em
831        case WXK_ESCAPE:
832        case WXK_LBUTTON:
833        case WXK_RBUTTON:
834        case WXK_CANCEL:
835        case WXK_MENU:
836        case WXK_MBUTTON:
837        case WXK_CLEAR:
838        case WXK_PAUSE:
839        case WXK_SELECT:
840        case WXK_PRINT:
841        case WXK_EXECUTE:
842        case WXK_SNAPSHOT:
843        case WXK_HELP:
844        case WXK_F1:
845        case WXK_F2:
846        case WXK_F3:
847        case WXK_F4:
848        case WXK_F5:
849        case WXK_F6:
850        case WXK_F7:
851        case WXK_F8:
852        case WXK_F9:
853        case WXK_F10:
854        case WXK_F11:
855        case WXK_F12:
856        case WXK_F13:
857        case WXK_F14:
858        case WXK_F15:
859        case WXK_F16:
860        case WXK_F17:
861        case WXK_F18:
862        case WXK_F19:
863        case WXK_F20:
864        case WXK_F21:
865        case WXK_F22:
866        case WXK_F23:
867        case WXK_F24:
868        case WXK_NUMPAD_F1:
869        case WXK_NUMPAD_F2:
870        case WXK_NUMPAD_F3:
871        case WXK_NUMPAD_F4:
872        //When numlock is off Numpad 5 becomes BEGIN, or HOME on Char
873        case WXK_NUMPAD_BEGIN:
874        case WXK_NUMPAD_INSERT:
875            return;
876        }
877    }
878
879    event.Skip();
880}
881
882void wxWebView::OnSetFocus(wxFocusEvent& event)
883{
884    WebCore::Frame* frame = 0;
885    if (m_mainFrame)
886        frame = m_mainFrame->GetFrame();
887
888    if (frame) {
889        frame->selection()->setFocused(true);
890    }
891
892    event.Skip();
893}
894
895void wxWebView::OnKillFocus(wxFocusEvent& event)
896{
897    WebCore::Frame* frame = 0;
898    if (m_mainFrame)
899        frame = m_mainFrame->GetFrame();
900
901    if (frame) {
902        frame->selection()->setFocused(false);
903    }
904    event.Skip();
905}
906
907wxWebViewDOMElementInfo wxWebView::HitTest(const wxPoint& pos) const
908{
909    if (m_mainFrame)
910        return m_mainFrame->HitTest(pos);
911
912    return wxWebViewDOMElementInfo();
913}
914
915bool wxWebView::ShouldClose() const
916{
917    if (m_mainFrame)
918        return m_mainFrame->ShouldClose();
919
920    return true;
921}
922
923/* static */
924void wxWebView::SetDatabaseDirectory(const wxString& databaseDirectory)
925{
926#if ENABLE(DATABASE)
927    WebCore::DatabaseTracker::tracker().setDatabaseDirectoryPath(databaseDirectory);
928#endif
929}
930
931/* static */
932wxString wxWebView::GetDatabaseDirectory()
933{
934#if ENABLE(DATABASE)
935    return WebCore::DatabaseTracker::tracker().databaseDirectoryPath();
936#else
937    return wxEmptyString;
938#endif
939}
940
941static WebCore::ResourceHandleManager::ProxyType curlProxyType(wxProxyType type)
942{
943    switch (type) {
944        case HTTP: return WebCore::ResourceHandleManager::HTTP;
945        case Socks4: return WebCore::ResourceHandleManager::Socks4;
946        case Socks4A: return WebCore::ResourceHandleManager::Socks4A;
947        case Socks5: return WebCore::ResourceHandleManager::Socks5;
948        case Socks5Hostname: return WebCore::ResourceHandleManager::Socks5Hostname;
949        default:
950            ASSERT_NOT_REACHED();
951            return WebCore::ResourceHandleManager::HTTP;
952    }
953}
954
955/* static */
956void wxWebView::SetProxyInfo(const wxString& host,
957                             unsigned long port,
958                             wxProxyType type,
959                             const wxString& username,
960                             const wxString& password)
961{
962    using WebCore::ResourceHandleManager;
963    if (ResourceHandleManager* mgr = ResourceHandleManager::sharedInstance())
964        mgr->setProxyInfo(host, port, curlProxyType(type), username, password);
965}
966
967wxWebSettings wxWebView::GetWebSettings()
968{
969    ASSERT(m_impl->page);
970    if (m_impl->page)
971        return wxWebSettings(m_impl->page->settings());
972
973    return wxWebSettings();
974}
975
976wxWebKitParseMode wxWebView::GetParseMode() const
977{
978    if (m_mainFrame)
979        return m_mainFrame->GetParseMode();
980
981    return NoDocument;
982}