/* * Copyright (C) 2007 Kevin Ollivier All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "WebView.h" #include "ContextMenu.h" #include "ContextMenuController.h" #include "ContextMenuItem.h" #include "Document.h" #include "Editor.h" #include "Element.h" #include "EmptyClients.h" #include "EventHandler.h" #include "FileChooser.h" #include "FocusController.h" #include "Frame.h" #include "FrameLoader.h" #include "FrameSelection.h" #include "FrameView.h" #include "GraphicsContext.h" #include "HTMLFormElement.h" #include "Logging.h" #include "MemoryCache.h" #include "Page.h" #include "PlatformKeyboardEvent.h" #include "PlatformMouseEvent.h" #include "PlatformWheelEvent.h" #include "RenderObject.h" #include "RenderView.h" #include "ResourceHandleManager.h" #include "Scrollbar.h" #include "Settings.h" #include "SubstituteData.h" #include "Threading.h" #include "markup.h" #if __WXMSW__ #include "WebCoreInstanceHandle.h" #endif #include "ChromeClientWx.h" #include "ContextMenuClientWx.h" #include "DragClientWx.h" #include "EditorClientWx.h" #include "FrameLoaderClientWx.h" #include "InspectorClientWx.h" #include "ScriptController.h" #include "JSDOMBinding.h" #include #include #include #include #include #if ENABLE(SQL_DATABASE) #include "AbstractDatabase.h" #include "DatabaseTracker.h" #endif #include "wx/wxprec.h" #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "WebDOMElement.h" #include "WebDOMNode.h" #include "WebFrame.h" #include "WebViewPrivate.h" #include #include #include #if defined(_MSC_VER) int rint(double val) { return (int)(val < 0 ? val - 0.5 : val + 0.5); } #endif #if OS(DARWIN) // prototype - function is in WebSystemInterface.mm void InitWebCoreSystemInterface(void); #endif // ---------------------------------------------------------------------------- // WebView Events // ---------------------------------------------------------------------------- namespace WebKit { IMPLEMENT_DYNAMIC_CLASS(WebViewLoadEvent, wxCommandEvent) DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_LOAD) WebViewLoadEvent::WebViewLoadEvent(wxWindow* win) { SetEventType( wxEVT_WEBVIEW_LOAD); SetEventObject( win ); if (win) SetId(win->GetId()); } IMPLEMENT_DYNAMIC_CLASS(WebViewBeforeLoadEvent, wxCommandEvent) DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_BEFORE_LOAD) WebViewBeforeLoadEvent::WebViewBeforeLoadEvent(wxWindow* win) { m_cancelled = false; SetEventType(wxEVT_WEBVIEW_BEFORE_LOAD); SetEventObject(win); if (win) SetId(win->GetId()); } IMPLEMENT_DYNAMIC_CLASS(WebViewNewWindowEvent, wxCommandEvent) DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_NEW_WINDOW) WebViewNewWindowEvent::WebViewNewWindowEvent(wxWindow* win) { SetEventType(wxEVT_WEBVIEW_NEW_WINDOW); SetEventObject(win); if (win) SetId(win->GetId()); } IMPLEMENT_DYNAMIC_CLASS(WebViewRightClickEvent, wxCommandEvent) DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_RIGHT_CLICK) WebViewRightClickEvent::WebViewRightClickEvent(wxWindow* win) { SetEventType(wxEVT_WEBVIEW_RIGHT_CLICK); SetEventObject(win); if (win) SetId(win->GetId()); } IMPLEMENT_DYNAMIC_CLASS(WebViewConsoleMessageEvent, wxCommandEvent) DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_CONSOLE_MESSAGE) WebViewConsoleMessageEvent::WebViewConsoleMessageEvent(wxWindow* win) { SetEventType(wxEVT_WEBVIEW_CONSOLE_MESSAGE); SetEventObject(win); if (win) SetId(win->GetId()); } IMPLEMENT_DYNAMIC_CLASS(WebViewAlertEvent, wxCommandEvent) DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_JS_ALERT) WebViewAlertEvent::WebViewAlertEvent(wxWindow* win) { SetEventType(wxEVT_WEBVIEW_JS_ALERT); SetEventObject(win); if (win) SetId(win->GetId()); } IMPLEMENT_DYNAMIC_CLASS(WebViewConfirmEvent, wxCommandEvent) DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_JS_CONFIRM) WebViewConfirmEvent::WebViewConfirmEvent(wxWindow* win) { SetEventType(wxEVT_WEBVIEW_JS_CONFIRM); SetEventObject(win); if (win) SetId(win->GetId()); } IMPLEMENT_DYNAMIC_CLASS(WebViewPromptEvent, wxCommandEvent) DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_JS_PROMPT) WebViewPromptEvent::WebViewPromptEvent(wxWindow* win) { SetEventType(wxEVT_WEBVIEW_JS_PROMPT); SetEventObject(win); if (win) SetId(win->GetId()); } IMPLEMENT_DYNAMIC_CLASS(WebViewReceivedTitleEvent, wxCommandEvent) DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_RECEIVED_TITLE) WebViewReceivedTitleEvent::WebViewReceivedTitleEvent(wxWindow* win) { SetEventType(wxEVT_WEBVIEW_RECEIVED_TITLE); SetEventObject(win); if (win) SetId(win->GetId()); } IMPLEMENT_DYNAMIC_CLASS(WebViewWindowObjectClearedEvent, wxCommandEvent) DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_WINDOW_OBJECT_CLEARED) WebViewWindowObjectClearedEvent::WebViewWindowObjectClearedEvent(wxWindow* win) { SetEventType(wxEVT_WEBVIEW_WINDOW_OBJECT_CLEARED); SetEventObject(win); if (win) SetId(win->GetId()); } IMPLEMENT_DYNAMIC_CLASS(WebViewContentsChangedEvent, wxCommandEvent) DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_CONTENTS_CHANGED) WebViewContentsChangedEvent::WebViewContentsChangedEvent(wxWindow* win) { SetEventType(wxEVT_WEBVIEW_CONTENTS_CHANGED); SetEventObject(win); if (win) SetId(win->GetId()); } IMPLEMENT_DYNAMIC_CLASS(WebViewSelectionChangedEvent, wxCommandEvent) DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_SELECTION_CHANGED) WebViewSelectionChangedEvent::WebViewSelectionChangedEvent(wxWindow* win) { SetEventType(wxEVT_WEBVIEW_SELECTION_CHANGED); SetEventObject(win); if (win) SetId(win->GetId()); } IMPLEMENT_DYNAMIC_CLASS(WebViewPrintFrameEvent, wxCommandEvent) DEFINE_EVENT_TYPE(wxEVT_WEBVIEW_PRINT_FRAME) WebViewPrintFrameEvent::WebViewPrintFrameEvent(wxWindow* win) { SetEventType(wxEVT_WEBVIEW_PRINT_FRAME); SetEventObject(win); if (win) SetId(win->GetId()); } //--------------------------------------------------------- // DOM Element info data type //--------------------------------------------------------- WebViewDOMElementInfo::WebViewDOMElementInfo() : m_isSelected(false), m_text(wxEmptyString), m_imageSrc(wxEmptyString), m_link(wxEmptyString), m_urlElement(0), m_innerNode(0) { } static WebViewCachePolicy gs_cachePolicy; /* static */ void WebView::SetCachePolicy(const WebViewCachePolicy& cachePolicy) { WebCore::MemoryCache* globalCache = WebCore::memoryCache(); globalCache->setCapacities(cachePolicy.GetMinDeadCapacity(), cachePolicy.GetMaxDeadCapacity(), cachePolicy.GetCapacity()); // store a copy since there is no getter for MemoryCache values gs_cachePolicy = cachePolicy; } /* static */ WebViewCachePolicy WebView::GetCachePolicy() { return gs_cachePolicy; } WebViewDOMElementInfo::WebViewDOMElementInfo(const WebViewDOMElementInfo& other) { m_isSelected = other.m_isSelected; m_text = other.m_text; m_imageSrc = other.m_imageSrc; m_link = other.m_link; m_innerNode = other.m_innerNode; m_urlElement = other.m_urlElement; } WebViewDOMElementInfo::~WebViewDOMElementInfo() { if (m_innerNode) delete m_innerNode; if (m_urlElement) delete m_urlElement; } BEGIN_EVENT_TABLE(WebView, wxWindow) EVT_PAINT(WebView::OnPaint) EVT_SIZE(WebView::OnSize) EVT_MOUSE_EVENTS(WebView::OnMouseEvents) EVT_CONTEXT_MENU(WebView::OnContextMenuEvents) EVT_KEY_DOWN(WebView::OnKeyEvents) EVT_KEY_UP(WebView::OnKeyEvents) EVT_CHAR(WebView::OnKeyEvents) EVT_SET_FOCUS(WebView::OnSetFocus) EVT_KILL_FOCUS(WebView::OnKillFocus) EVT_MOUSE_CAPTURE_LOST(WebView::OnMouseCaptureLost) END_EVENT_TABLE() IMPLEMENT_DYNAMIC_CLASS(WebView, wxWindow) const wxChar* WebViewNameStr = wxT("webView"); WebView::WebView() : m_textMagnifier(1.0), m_isInitialized(false), m_beingDestroyed(false), m_mouseWheelZooms(false), m_title(wxEmptyString) { } WebView::WebView(wxWindow* parent, const wxString& url, int id, const wxPoint& position, const wxSize& size, long style, const wxString& name) : m_textMagnifier(1.0), m_isInitialized(false), m_beingDestroyed(false), m_mouseWheelZooms(false), m_title(wxEmptyString) { Create(parent, url, id, position, size, style, name); } bool WebView::Create(wxWindow* parent, const wxString& url, int id, const wxPoint& position, const wxSize& size, long style, const wxString& name) { #if OS(DARWIN) InitWebCoreSystemInterface(); #endif if ( (style & wxBORDER_MASK) == 0) style |= wxBORDER_NONE; if (!wxWindow::Create(parent, id, position, size, style, name)) return false; JSC::initializeThreading(); WTF::initializeMainThread(); // This is necessary because we are using SharedTimerWin.cpp on Windows, // due to a problem with exceptions getting eaten when using the callback // approach to timers (which wx itself uses). #if __WXMSW__ WebCore::setInstanceHandle(wxGetInstance()); #endif // this helps reduce flicker on platforms like MSW SetBackgroundStyle(wxBG_STYLE_CUSTOM); m_impl = new WebViewPrivate(); #if !LOG_DISABLED WebCore::initializeLoggingChannelsIfNecessary(); #endif // !LOG_DISABLED WebCore::HTMLFrameOwnerElement* parentFrame = 0; WebCore::EditorClientWx* editorClient = new WebCore::EditorClientWx(); WebCore::Page::PageClients pageClients; pageClients.chromeClient = new WebCore::ChromeClientWx(this); pageClients.contextMenuClient = new WebCore::ContextMenuClientWx(); pageClients.editorClient = editorClient; pageClients.dragClient = new WebCore::DragClientWx(); pageClients.inspectorClient = new WebCore::InspectorClientWx(); m_impl->page = new WebCore::Page(pageClients); editorClient->setPage(m_impl->page); m_mainFrame = new WebFrame(this); // Default settings - we should have WebViewSettings class for this // eventually WebCore::Settings* settings = m_impl->page->settings(); settings->setLoadsImagesAutomatically(true); settings->setDefaultFixedFontSize(13); settings->setDefaultFontSize(16); settings->setSerifFontFamily("Times New Roman"); settings->setFixedFontFamily("Courier New"); settings->setSansSerifFontFamily("Arial"); settings->setStandardFontFamily("Times New Roman"); settings->setScriptEnabled(true); #if ENABLE(SQL_DATABASE) SetDatabasesEnabled(true); #endif // we need to do this so that objects like the focusController are properly // initialized so that the activate handler is run properly. LoadURL(url); m_isInitialized = true; return true; } WebView::~WebView() { m_beingDestroyed = true; while (HasCapture()) ReleaseMouse(); if (m_mainFrame && m_mainFrame->GetFrame()) m_mainFrame->GetFrame()->loader()->detachFromParent(); delete m_impl->page; m_impl->page = 0; } // NOTE: binding to this event in the WebView constructor is too early in // some cases, but leave the event handler here so that users can bind to it // at a later time if they have activation state problems. void WebView::OnTLWActivated(wxActivateEvent& event) { if (m_impl && m_impl->page && m_impl->page->focusController()) m_impl->page->focusController()->setActive(event.GetActive()); event.Skip(); } void WebView::Stop() { if (m_mainFrame) m_mainFrame->Stop(); } void WebView::Reload() { if (m_mainFrame) m_mainFrame->Reload(); } wxString WebView::GetPageSource() { if (m_mainFrame) return m_mainFrame->GetPageSource(); return wxEmptyString; } void WebView::SetPageSource(const wxString& source, const wxString& baseUrl, const wxString& mimetype) { if (m_mainFrame) m_mainFrame->SetPageSource(source, baseUrl, mimetype); } wxString WebView::GetInnerText() { if (m_mainFrame) return m_mainFrame->GetInnerText(); return wxEmptyString; } wxString WebView::GetAsMarkup() { if (m_mainFrame) return m_mainFrame->GetAsMarkup(); return wxEmptyString; } wxString WebView::GetExternalRepresentation() { if (m_mainFrame) return m_mainFrame->GetExternalRepresentation(); return wxEmptyString; } WebKitSelection WebView::GetSelection() { if (m_mainFrame) return m_mainFrame->GetSelection(); return 0; } wxString WebView::GetSelectionAsHTML() { if (m_mainFrame) return m_mainFrame->GetSelectionAsHTML(); return wxEmptyString; } wxString WebView::GetSelectionAsText() { if (m_mainFrame) return m_mainFrame->GetSelectionAsText(); return wxEmptyString; } void WebView::SetTransparent(bool transparent) { WebCore::Frame* frame = 0; if (m_mainFrame) frame = m_mainFrame->GetFrame(); if (!frame || !frame->view()) return; frame->view()->setTransparent(transparent); } bool WebView::IsTransparent() const { WebCore::Frame* frame = 0; if (m_mainFrame) frame = m_mainFrame->GetFrame(); if (!frame || !frame->view()) return false; return frame->view()->isTransparent(); } wxString WebView::RunScript(const wxString& javascript) { if (m_mainFrame) return m_mainFrame->RunScript(javascript); return wxEmptyString; } bool WebView::ExecuteEditCommand(const wxString& command, const wxString& parameter) { if (m_mainFrame) return m_mainFrame->ExecuteEditCommand(command, parameter); } EditState WebView::GetEditCommandState(const wxString& command) const { if (m_mainFrame) return m_mainFrame->GetEditCommandState(command); } wxString WebView::GetEditCommandValue(const wxString& command) const { if (m_mainFrame) return m_mainFrame->GetEditCommandValue(command); return wxEmptyString; } void WebView::LoadURL(const wxString& url) { if (m_mainFrame) m_mainFrame->LoadURL(url); } wxString WebView::GetMainFrameURL() const { if (m_mainFrame) return m_mainFrame->GetURL(); return wxEmptyString; } bool WebView::GoBack() { if (m_mainFrame) return m_mainFrame->GoBack(); return false; } bool WebView::GoForward() { if (m_mainFrame) return m_mainFrame->GoForward(); return false; } bool WebView::CanGoBack() { if (m_mainFrame) return m_mainFrame->CanGoBack(); return false; } bool WebView::CanGoForward() { if (m_mainFrame) return m_mainFrame->CanGoForward(); return false; } bool WebView::CanIncreaseTextSize() const { if (m_mainFrame) return m_mainFrame->CanIncreaseTextSize(); return false; } void WebView::IncreaseTextSize() { if (m_mainFrame) m_mainFrame->IncreaseTextSize(); } bool WebView::CanDecreaseTextSize() const { if (m_mainFrame) return m_mainFrame->CanDecreaseTextSize(); return false; } void WebView::DecreaseTextSize() { if (m_mainFrame) m_mainFrame->DecreaseTextSize(); } void WebView::ResetTextSize() { if (m_mainFrame) m_mainFrame->ResetTextSize(); } void WebView::MakeEditable(bool enable) { if (m_mainFrame) m_mainFrame->MakeEditable(enable); } bool WebView::IsEditable() const { if (m_mainFrame) return m_mainFrame->IsEditable(); return false; } /* * Event forwarding functions to send events down to WebCore. */ void WebView::OnPaint(wxPaintEvent& event) { if (m_beingDestroyed || !m_mainFrame) return; WebCore::Frame* frame = m_mainFrame->GetFrame(); if (!frame || !frame->view()) return; // we can't use wxAutoBufferedPaintDC here because it will not create // a 32-bit bitmap for its buffer. #if __WXMSW__ wxPaintDC paintdc(this); int width, height; paintdc.GetSize(&width, &height); wxBitmap bitmap(width, height, 32); wxMemoryDC dc(bitmap); #else wxPaintDC dc(this); #endif if (IsShown() && frame->document()) { #if USE(WXGC) #if wxCHECK_VERSION(2, 9, 2) && defined(wxUSE_CAIRO) && wxUSE_CAIRO wxGraphicsRenderer* renderer = wxGraphicsRenderer::GetCairoRenderer(); if (!renderer) renderer = wxGraphicsRenderer::GetDefaultRenderer(); wxGraphicsContext* context = renderer->CreateContext(dc); wxGCDC gcdc(context); #else wxGCDC gcdc(dc); #endif #endif if (dc.IsOk()) { wxRect paintRect = GetUpdateRegion().GetBox(); #if USE(WXGC) WebCore::GraphicsContext gc(&gcdc); #else WebCore::GraphicsContext gc(&dc); #endif if (frame->contentRenderer()) { frame->view()->updateLayoutAndStyleIfNeededRecursive(); frame->view()->paint(&gc, paintRect); #if __WXMSW__ dc.SelectObject(wxNullBitmap); paintdc.DrawBitmap(bitmap, 0, 0); #endif } } } } bool WebView::FindString(const wxString& string, bool forward, bool caseSensitive, bool wrapSelection, bool startInSelection) { if (m_mainFrame) return m_mainFrame->FindString(string, forward, caseSensitive, wrapSelection, startInSelection); return false; } void WebView::OnSize(wxSizeEvent& event) { if (m_isInitialized && m_mainFrame) { WebCore::Frame* frame = m_mainFrame->GetFrame(); frame->view()->resize(event.GetSize()); frame->view()->adjustViewSize(); } event.Skip(); } static int getDoubleClickTime() { #if __WXMSW__ return ::GetDoubleClickTime(); #else return 500; #endif } void WebView::OnMouseEvents(wxMouseEvent& event) { event.Skip(); if (!m_impl->page) return; WebCore::Frame* frame = m_mainFrame->GetFrame(); if (!frame || !frame->view()) return; wxPoint globalPoint = ClientToScreen(event.GetPosition()); wxEventType type = event.GetEventType(); if (type == wxEVT_MOUSEWHEEL) { if (m_mouseWheelZooms && event.ControlDown() && !event.AltDown() && !event.ShiftDown()) { if (event.GetWheelRotation() < 0) DecreaseTextSize(); else if (event.GetWheelRotation() > 0) IncreaseTextSize(); } else { WebCore::PlatformWheelEvent wkEvent(event, globalPoint); frame->eventHandler()->handleWheelEvent(wkEvent); } return; } // If an event, such as a right-click event, leads to a focus change (e.g. it // raises a dialog), WebKit never gets the mouse up event and never relinquishes // mouse capture. This leads to WebKit handling mouse events, such as modifying // the selection, while other controls or top level windows have the focus. // I'm not sure if this is the right place to handle this, but I can't seem to // find a precedent on how to handle this in other ports. if (wxWindow::FindFocus() != this) { while (HasCapture()) ReleaseMouse(); frame->eventHandler()->setMousePressed(false); return; } int clickCount = event.ButtonDClick() ? 2 : 1; if (clickCount == 1 && m_impl->tripleClickTimer.IsRunning()) { wxPoint diff(event.GetPosition() - m_impl->tripleClickPos); if (abs(diff.x) <= wxSystemSettings::GetMetric(wxSYS_DCLICK_X) && abs(diff.y) <= wxSystemSettings::GetMetric(wxSYS_DCLICK_Y)) { clickCount = 3; } } else if (clickCount == 2) { m_impl->tripleClickTimer.Start(getDoubleClickTime(), false); m_impl->tripleClickPos = event.GetPosition(); } WebCore::PlatformMouseEvent wkEvent(event, globalPoint, clickCount); if (type == wxEVT_LEFT_DOWN || type == wxEVT_MIDDLE_DOWN || type == wxEVT_RIGHT_DOWN || type == wxEVT_LEFT_DCLICK || type == wxEVT_MIDDLE_DCLICK || type == wxEVT_RIGHT_DCLICK) { frame->eventHandler()->handleMousePressEvent(wkEvent); if (!HasCapture()) CaptureMouse(); } else if (type == wxEVT_LEFT_UP || type == wxEVT_MIDDLE_UP || type == wxEVT_RIGHT_UP) { frame->eventHandler()->handleMouseReleaseEvent(wkEvent); while (HasCapture()) ReleaseMouse(); } else if (type == wxEVT_MOTION || type == wxEVT_ENTER_WINDOW || type == wxEVT_LEAVE_WINDOW) frame->eventHandler()->mouseMoved(wkEvent); } void WebView::OnContextMenuEvents(wxContextMenuEvent& event) { Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(WebView::OnMenuSelectEvents), 0, this); m_impl->page->contextMenuController()->clearContextMenu(); wxPoint localEventPoint = ScreenToClient(event.GetPosition()); if (!m_impl->page) return; WebCore::Frame* focusedFrame = m_impl->page->focusController()->focusedOrMainFrame(); if (!focusedFrame->view()) return; //Create WebCore mouse event from the wxContextMenuEvent wxMouseEvent mouseEvent(wxEVT_RIGHT_DOWN); mouseEvent.m_x = localEventPoint.x; mouseEvent.m_y = localEventPoint.y; WebCore::PlatformMouseEvent wkEvent(mouseEvent, event.GetPosition(), 1); bool handledEvent = focusedFrame->eventHandler()->sendContextMenuEvent(wkEvent); if (!handledEvent) return; WebCore::ContextMenu* coreMenu = m_impl->page->contextMenuController()->contextMenu(); if (!coreMenu) return; WebCore::PlatformMenuDescription menuWx = coreMenu->platformDescription(); if (!menuWx) return; PopupMenu(menuWx, localEventPoint); Disconnect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(WebView::OnMenuSelectEvents), 0, this); } void WebView::OnMenuSelectEvents(wxCommandEvent& event) { // we shouldn't hit this unless there's a context menu showing WebCore::ContextMenu* coreMenu = m_impl->page->contextMenuController()->contextMenu(); ASSERT(coreMenu); if (!coreMenu) return; WebCore::ContextMenuItem* item = WebCore::ContextMenu::itemWithId (event.GetId()); if (!item) return; m_impl->page->contextMenuController()->contextMenuItemSelected(item); delete item; } void WebView::OnMouseCaptureLost(wxMouseCaptureLostEvent& event) { // do nothing - unfortunately, we MUST handle this event due to wxWidgets rules, // otherwise we will assert, even though there is nothing for us to do here. } bool WebView::CanCopy() { if (m_mainFrame) return m_mainFrame->CanCopy(); return false; } void WebView::Copy() { if (m_mainFrame) m_mainFrame->Copy(); } bool WebView::CanCut() { if (m_mainFrame) return m_mainFrame->CanCut(); return false; } void WebView::Cut() { if (m_mainFrame) m_mainFrame->Cut(); } bool WebView::CanPaste() { if (m_mainFrame) return m_mainFrame->CanPaste(); return false; } void WebView::Paste() { if (m_mainFrame) m_mainFrame->Paste(); } void WebView::OnKeyEvents(wxKeyEvent& event) { WebCore::Frame* frame = 0; if (m_impl->page) frame = m_impl->page->focusController()->focusedOrMainFrame(); if (!(frame && frame->view())) return; WebCore::PlatformKeyboardEvent wkEvent(event); if (frame->eventHandler()->keyEvent(wkEvent)) return; //Some things WebKit won't do for us... Copy/Cut/Paste and KB scrolling if (event.GetEventType() == wxEVT_KEY_DOWN) { switch (event.GetKeyCode()) { case 67: //"C" if (CanCopy() && event.GetModifiers() == wxMOD_CMD) { Copy(); return; } break; case 86: //"V" if (CanPaste() && event.GetModifiers() == wxMOD_CMD) { Paste(); return; } break; case 88: //"X" if (CanCut() && event.GetModifiers() == wxMOD_CMD) { Cut(); return; } break; case WXK_INSERT: if (CanCopy() && event.GetModifiers() == wxMOD_CMD) { Copy(); return; } if (CanPaste() && event.GetModifiers() == wxMOD_SHIFT) { Paste(); return; } return; //Insert shall not become a char case WXK_DELETE: if (CanCut() && event.GetModifiers() == wxMOD_SHIFT) { Cut(); return; } break; case WXK_LEFT: case WXK_NUMPAD_LEFT: frame->view()->scrollBy(WebCore::IntSize(-WebCore::Scrollbar::pixelsPerLineStep(), 0)); return; case WXK_UP: case WXK_NUMPAD_UP: frame->view()->scrollBy(WebCore::IntSize(0, -WebCore::Scrollbar::pixelsPerLineStep())); return; case WXK_RIGHT: case WXK_NUMPAD_RIGHT: frame->view()->scrollBy(WebCore::IntSize(WebCore::Scrollbar::pixelsPerLineStep(), 0)); return; case WXK_DOWN: case WXK_NUMPAD_DOWN: frame->view()->scrollBy(WebCore::IntSize(0, WebCore::Scrollbar::pixelsPerLineStep())); return; case WXK_END: case WXK_NUMPAD_END: frame->view()->setScrollPosition(WebCore::IntPoint(frame->view()->scrollX(), frame->view()->maximumScrollPosition().y())); return; case WXK_HOME: case WXK_NUMPAD_HOME: frame->view()->setScrollPosition(WebCore::IntPoint(frame->view()->scrollX(), 0)); return; case WXK_PAGEUP: case WXK_NUMPAD_PAGEUP: frame->view()->scrollBy(WebCore::IntSize(0, -frame->view()->visibleHeight() * WebCore::Scrollbar::minFractionToStepWhenPaging())); return; case WXK_PAGEDOWN: case WXK_NUMPAD_PAGEDOWN: frame->view()->scrollBy(WebCore::IntSize(0, frame->view()->visibleHeight() * WebCore::Scrollbar::minFractionToStepWhenPaging())); return; //These we don't want turning into char events, stuff 'em case WXK_ESCAPE: case WXK_LBUTTON: case WXK_RBUTTON: case WXK_CANCEL: case WXK_MENU: case WXK_MBUTTON: case WXK_CLEAR: case WXK_PAUSE: case WXK_SELECT: case WXK_PRINT: case WXK_EXECUTE: case WXK_SNAPSHOT: case WXK_HELP: case WXK_F1: case WXK_F2: case WXK_F3: case WXK_F4: case WXK_F5: case WXK_F6: case WXK_F7: case WXK_F8: case WXK_F9: case WXK_F10: case WXK_F11: case WXK_F12: case WXK_F13: case WXK_F14: case WXK_F15: case WXK_F16: case WXK_F17: case WXK_F18: case WXK_F19: case WXK_F20: case WXK_F21: case WXK_F22: case WXK_F23: case WXK_F24: case WXK_NUMPAD_F1: case WXK_NUMPAD_F2: case WXK_NUMPAD_F3: case WXK_NUMPAD_F4: //When numlock is off Numpad 5 becomes BEGIN, or HOME on Char case WXK_NUMPAD_BEGIN: case WXK_NUMPAD_INSERT: return; } } event.Skip(); } void WebView::OnSetFocus(wxFocusEvent& event) { if (m_impl && m_impl->page && m_impl->page->focusController()) { m_impl->page->focusController()->setFocused(true); m_impl->page->focusController()->setActive(true); if (!m_impl->page->focusController()->focusedFrame() && m_mainFrame) m_impl->page->focusController()->setFocusedFrame(m_mainFrame->GetFrame()); } event.Skip(); } void WebView::OnKillFocus(wxFocusEvent& event) { if (m_impl && m_impl->page && m_impl->page->focusController()) { m_impl->page->focusController()->setFocused(false); // We also handle active state in OnTLWActivated, but if a user does not // call event.Skip() in their own EVT_ACTIVATE handler, we won't get those // callbacks. So we handle active state here as well as a fallback. wxTopLevelWindow* tlw = dynamic_cast(wxGetTopLevelParent(this)); if (tlw && tlw->IsActive()) m_impl->page->focusController()->setActive(true); else m_impl->page->focusController()->setActive(false); } while (HasCapture()) ReleaseMouse(); event.Skip(); } WebViewDOMElementInfo WebView::HitTest(const wxPoint& pos) const { if (m_mainFrame) return m_mainFrame->HitTest(pos); return WebViewDOMElementInfo(); } bool WebView::ShouldClose() const { if (m_mainFrame) return m_mainFrame->ShouldClose(); return true; } /* static */ void WebView::SetDatabaseDirectory(const wxString& databaseDirectory) { #if ENABLE(SQL_DATABASE) WebCore::DatabaseTracker::tracker().setDatabaseDirectoryPath(databaseDirectory); #endif } /* static */ wxString WebView::GetDatabaseDirectory() { #if ENABLE(SQL_DATABASE) return WebCore::DatabaseTracker::tracker().databaseDirectoryPath(); #else return wxEmptyString; #endif } /* static */ void WebView::SetDatabasesEnabled(bool enabled) { #if ENABLE(SQL_DATABASE) WebCore::AbstractDatabase::setIsAvailable(enabled); #endif } /* static */ bool WebView::AreDatabasesEnabled() { #if ENABLE(SQL_DATABASE) return WebCore::AbstractDatabase::isAvailable(); #endif return false; } static WebCore::ResourceHandleManager::ProxyType curlProxyType(wxProxyType type) { switch (type) { case HTTP: return WebCore::ResourceHandleManager::HTTP; case Socks4: return WebCore::ResourceHandleManager::Socks4; case Socks4A: return WebCore::ResourceHandleManager::Socks4A; case Socks5: return WebCore::ResourceHandleManager::Socks5; case Socks5Hostname: return WebCore::ResourceHandleManager::Socks5Hostname; default: ASSERT_NOT_REACHED(); return WebCore::ResourceHandleManager::HTTP; } } /* static */ void WebView::SetProxyInfo(const wxString& host, unsigned long port, wxProxyType type, const wxString& username, const wxString& password) { using WebCore::ResourceHandleManager; if (ResourceHandleManager* mgr = ResourceHandleManager::sharedInstance()) mgr->setProxyInfo(host, port, curlProxyType(type), username, password); } WebSettings WebView::GetWebSettings() { ASSERT(m_impl->page); if (m_impl->page) return WebSettings(m_impl->page->settings()); return WebSettings(); } WebKitCompatibilityMode WebView::GetCompatibilityMode() const { if (m_mainFrame) return m_mainFrame->GetCompatibilityMode(); return QuirksMode; } void WebView::GrantUniversalAccess() { if (m_mainFrame) m_mainFrame->GrantUniversalAccess(); } }