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)
rint(double val)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
IMPLEMENT_DYNAMIC_CLASS(wxWebViewLoadEvent,wxCommandEvent)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
IMPLEMENT_DYNAMIC_CLASS(wxWebViewBeforeLoadEvent,wxCommandEvent)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
IMPLEMENT_DYNAMIC_CLASS(wxWebViewNewWindowEvent,wxCommandEvent)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
IMPLEMENT_DYNAMIC_CLASS(wxWebViewRightClickEvent,wxCommandEvent)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
IMPLEMENT_DYNAMIC_CLASS(wxWebViewConsoleMessageEvent,wxCommandEvent)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
IMPLEMENT_DYNAMIC_CLASS(wxWebViewAlertEvent,wxCommandEvent)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
IMPLEMENT_DYNAMIC_CLASS(wxWebViewConfirmEvent,wxCommandEvent)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
IMPLEMENT_DYNAMIC_CLASS(wxWebViewPromptEvent,wxCommandEvent)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
IMPLEMENT_DYNAMIC_CLASS(wxWebViewReceivedTitleEvent,wxCommandEvent)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
IMPLEMENT_DYNAMIC_CLASS(wxWebViewWindowObjectClearedEvent,wxCommandEvent)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
IMPLEMENT_DYNAMIC_CLASS(wxWebViewContentsChangedEvent,wxCommandEvent)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
IMPLEMENT_DYNAMIC_CLASS(wxWebViewSelectionChangedEvent,wxCommandEvent)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
wxWebViewDOMElementInfo()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 */
SetCachePolicy(const wxWebViewCachePolicy & cachePolicy)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 */
GetCachePolicy()284 wxWebViewCachePolicy wxWebView::GetCachePolicy()
285 {
286 return gs_cachePolicy;
287 }
288
wxWebViewDOMElementInfo(const wxWebViewDOMElementInfo & other)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
~wxWebViewDOMElementInfo()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
wxWebView()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
wxWebView(wxWindow * parent,int id,const wxPoint & position,const wxSize & size,long style,const wxString & name)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
Create(wxWindow * parent,int id,const wxPoint & position,const wxSize & size,long style,const wxString & name)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
~wxWebView()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.
OnTLWActivated(wxActivateEvent & event)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
Stop()444 void wxWebView::Stop()
445 {
446 if (m_mainFrame)
447 m_mainFrame->Stop();
448 }
449
Reload()450 void wxWebView::Reload()
451 {
452 if (m_mainFrame)
453 m_mainFrame->Reload();
454 }
455
GetPageSource()456 wxString wxWebView::GetPageSource()
457 {
458 if (m_mainFrame)
459 return m_mainFrame->GetPageSource();
460
461 return wxEmptyString;
462 }
463
SetPageSource(const wxString & source,const wxString & baseUrl,const wxString & mimetype)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
GetInnerText()470 wxString wxWebView::GetInnerText()
471 {
472 if (m_mainFrame)
473 return m_mainFrame->GetInnerText();
474
475 return wxEmptyString;
476 }
477
GetAsMarkup()478 wxString wxWebView::GetAsMarkup()
479 {
480 if (m_mainFrame)
481 return m_mainFrame->GetAsMarkup();
482
483 return wxEmptyString;
484 }
485
GetExternalRepresentation()486 wxString wxWebView::GetExternalRepresentation()
487 {
488 if (m_mainFrame)
489 return m_mainFrame->GetExternalRepresentation();
490
491 return wxEmptyString;
492 }
493
GetSelection()494 wxWebKitSelection wxWebView::GetSelection()
495 {
496 if (m_mainFrame)
497 return m_mainFrame->GetSelection();
498
499 return 0;
500 }
501
GetSelectionAsHTML()502 wxString wxWebView::GetSelectionAsHTML()
503 {
504 if (m_mainFrame)
505 return m_mainFrame->GetSelectionAsHTML();
506
507 return wxEmptyString;
508 }
509
GetSelectionAsText()510 wxString wxWebView::GetSelectionAsText()
511 {
512 if (m_mainFrame)
513 return m_mainFrame->GetSelectionAsText();
514
515 return wxEmptyString;
516 }
517
SetTransparent(bool transparent)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
IsTransparent() const530 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
RunScript(const wxString & javascript)542 wxString wxWebView::RunScript(const wxString& javascript)
543 {
544 if (m_mainFrame)
545 return m_mainFrame->RunScript(javascript);
546
547 return wxEmptyString;
548 }
549
ExecuteEditCommand(const wxString & command,const wxString & parameter)550 bool wxWebView::ExecuteEditCommand(const wxString& command, const wxString& parameter)
551 {
552 if (m_mainFrame)
553 return m_mainFrame->ExecuteEditCommand(command, parameter);
554 }
555
GetEditCommandState(const wxString & command) const556 EditState wxWebView::GetEditCommandState(const wxString& command) const
557 {
558 if (m_mainFrame)
559 return m_mainFrame->GetEditCommandState(command);
560 }
561
GetEditCommandValue(const wxString & command) const562 wxString wxWebView::GetEditCommandValue(const wxString& command) const
563 {
564 if (m_mainFrame)
565 return m_mainFrame->GetEditCommandValue(command);
566
567 return wxEmptyString;
568 }
569
LoadURL(const wxString & url)570 void wxWebView::LoadURL(const wxString& url)
571 {
572 if (m_mainFrame)
573 m_mainFrame->LoadURL(url);
574 }
575
GoBack()576 bool wxWebView::GoBack()
577 {
578 if (m_mainFrame)
579 return m_mainFrame->GoBack();
580
581 return false;
582 }
583
GoForward()584 bool wxWebView::GoForward()
585 {
586 if (m_mainFrame)
587 return m_mainFrame->GoForward();
588
589 return false;
590 }
591
CanGoBack()592 bool wxWebView::CanGoBack()
593 {
594 if (m_mainFrame)
595 return m_mainFrame->CanGoBack();
596
597 return false;
598 }
599
CanGoForward()600 bool wxWebView::CanGoForward()
601 {
602 if (m_mainFrame)
603 return m_mainFrame->CanGoForward();
604
605 return false;
606 }
607
CanIncreaseTextSize() const608 bool wxWebView::CanIncreaseTextSize() const
609 {
610 if (m_mainFrame)
611 return m_mainFrame->CanIncreaseTextSize();
612
613 return false;
614 }
615
IncreaseTextSize()616 void wxWebView::IncreaseTextSize()
617 {
618 if (m_mainFrame)
619 m_mainFrame->IncreaseTextSize();
620 }
621
CanDecreaseTextSize() const622 bool wxWebView::CanDecreaseTextSize() const
623 {
624 if (m_mainFrame)
625 m_mainFrame->CanDecreaseTextSize();
626
627 return false;
628 }
629
DecreaseTextSize()630 void wxWebView::DecreaseTextSize()
631 {
632 if (m_mainFrame)
633 m_mainFrame->DecreaseTextSize();
634 }
635
ResetTextSize()636 void wxWebView::ResetTextSize()
637 {
638 if (m_mainFrame)
639 m_mainFrame->ResetTextSize();
640 }
641
MakeEditable(bool enable)642 void wxWebView::MakeEditable(bool enable)
643 {
644 if (m_mainFrame)
645 m_mainFrame->MakeEditable(enable);
646 }
647
IsEditable() const648 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
OnPaint(wxPaintEvent & event)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
FindString(const wxString & string,bool forward,bool caseSensitive,bool wrapSelection,bool startInSelection)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
OnSize(wxSizeEvent & event)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
getDoubleClickTime()713 static int getDoubleClickTime()
714 {
715 #if __WXMSW__
716 return ::GetDoubleClickTime();
717 #else
718 return 500;
719 #endif
720 }
721
OnMouseEvents(wxMouseEvent & event)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
OnContextMenuEvents(wxContextMenuEvent & event)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
OnMenuSelectEvents(wxCommandEvent & event)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
CanCopy()846 bool wxWebView::CanCopy()
847 {
848 if (m_mainFrame)
849 return m_mainFrame->CanCopy();
850
851 return false;
852 }
853
Copy()854 void wxWebView::Copy()
855 {
856 if (m_mainFrame)
857 m_mainFrame->Copy();
858 }
859
CanCut()860 bool wxWebView::CanCut()
861 {
862 if (m_mainFrame)
863 return m_mainFrame->CanCut();
864
865 return false;
866 }
867
Cut()868 void wxWebView::Cut()
869 {
870 if (m_mainFrame)
871 m_mainFrame->Cut();
872 }
873
CanPaste()874 bool wxWebView::CanPaste()
875 {
876 if (m_mainFrame)
877 return m_mainFrame->CanPaste();
878
879 return false;
880 }
881
Paste()882 void wxWebView::Paste()
883 {
884 if (m_mainFrame)
885 m_mainFrame->Paste();
886 }
887
OnKeyEvents(wxKeyEvent & event)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
OnSetFocus(wxFocusEvent & event)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
OnKillFocus(wxFocusEvent & event)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
HitTest(const wxPoint & pos) const1057 wxWebViewDOMElementInfo wxWebView::HitTest(const wxPoint& pos) const
1058 {
1059 if (m_mainFrame)
1060 return m_mainFrame->HitTest(pos);
1061
1062 return wxWebViewDOMElementInfo();
1063 }
1064
ShouldClose() const1065 bool wxWebView::ShouldClose() const
1066 {
1067 if (m_mainFrame)
1068 return m_mainFrame->ShouldClose();
1069
1070 return true;
1071 }
1072
1073 /* static */
SetDatabaseDirectory(const wxString & databaseDirectory)1074 void wxWebView::SetDatabaseDirectory(const wxString& databaseDirectory)
1075 {
1076 #if ENABLE(DATABASE)
1077 WebCore::DatabaseTracker::tracker().setDatabaseDirectoryPath(databaseDirectory);
1078 #endif
1079 }
1080
1081 /* static */
GetDatabaseDirectory()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 */
SetDatabasesEnabled(bool enabled)1092 void wxWebView::SetDatabasesEnabled(bool enabled)
1093 {
1094 #if ENABLE(DATABASE)
1095 WebCore::AbstractDatabase::setIsAvailable(enabled);
1096 #endif
1097 }
1098
1099 /* static */
AreDatabasesEnabled()1100 bool wxWebView::AreDatabasesEnabled()
1101 {
1102 #if ENABLE(DATABASE)
1103 return WebCore::AbstractDatabase::isAvailable();
1104 #endif
1105 return false;
1106 }
1107
curlProxyType(wxProxyType type)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 */
SetProxyInfo(const wxString & host,unsigned long port,wxProxyType type,const wxString & username,const wxString & password)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
GetWebSettings()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
GetCompatibilityMode() const1143 wxWebKitCompatibilityMode wxWebView::GetCompatibilityMode() const
1144 {
1145 if (m_mainFrame)
1146 return m_mainFrame->GetCompatibilityMode();
1147
1148 return QuirksMode;
1149 }
1150
GrantUniversalAccess()1151 void wxWebView::GrantUniversalAccess()
1152 {
1153 if (m_mainFrame)
1154 m_mainFrame->GrantUniversalAccess();
1155 }
1156