#ifdef __WXCOCOA__
#include "wx/cocoa/autorelease.h"
#else
-#include "wx/mac/uma.h"
+#include "wx/osx/uma.h"
#include <Carbon/Carbon.h>
#include <WebKit/WebKit.h>
#include <WebKit/HIWebView.h>
{ kEventClassMouse, kEventMouseDown },
{ kEventClassMouse, kEventMouseMoved },
{ kEventClassMouse, kEventMouseDragged },
+
+ { kEventClassKeyboard, kEventRawKeyDown } ,
+ { kEventClassKeyboard, kEventRawKeyRepeat } ,
+ { kEventClassKeyboard, kEventRawKeyUp } ,
+ { kEventClassKeyboard, kEventRawKeyModifiersChanged } ,
+
+ { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } ,
+ { kEventClassTextInput, kEventTextInputUpdateActiveInputArea } ,
+
#if DEBUG_WEBKIT_SIZING == 1
{ kEventClassControl, kEventControlBoundsChanged } ,
#endif
};
+// mix this in from window.cpp
+pascal OSStatus wxMacUnicodeTextEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) ;
+
+// NOTE: This is mostly taken from KeyboardEventHandler in toplevel.cpp, but
+// that expects the data pointer is a top-level window, so I needed to change
+// that in this case. However, once 2.8 is out, we should factor out the common logic
+// among the two functions and merge them.
+static pascal OSStatus wxWebKitKeyEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
+{
+ OSStatus result = eventNotHandledErr ;
+ wxMacCarbonEvent cEvent( event ) ;
+
+ wxWebKitCtrl* thisWindow = (wxWebKitCtrl*) data ;
+ wxWindow* focus = thisWindow ;
+
+ unsigned char charCode ;
+ wxChar uniChar[2] ;
+ uniChar[0] = 0;
+ uniChar[1] = 0;
+
+ UInt32 keyCode ;
+ UInt32 modifiers ;
+ Point point ;
+ UInt32 when = EventTimeToTicks( GetEventTime( event ) ) ;
+
+#if wxUSE_UNICODE
+ ByteCount dataSize = 0 ;
+ if ( GetEventParameter( event, kEventParamKeyUnicodes, typeUnicodeText, NULL, 0 , &dataSize, NULL ) == noErr )
+ {
+ UniChar buf[2] ;
+ int numChars = dataSize / sizeof( UniChar) + 1;
+
+ UniChar* charBuf = buf ;
+
+ if ( numChars * 2 > 4 )
+ charBuf = new UniChar[ numChars ] ;
+ GetEventParameter( event, kEventParamKeyUnicodes, typeUnicodeText, NULL, dataSize , NULL , charBuf ) ;
+ charBuf[ numChars - 1 ] = 0;
+
+#if SIZEOF_WCHAR_T == 2
+ uniChar = charBuf[0] ;
+#else
+ wxMBConvUTF16 converter ;
+ converter.MB2WC( uniChar , (const char*)charBuf , 2 ) ;
+#endif
+
+ if ( numChars * 2 > 4 )
+ delete[] charBuf ;
+ }
+#endif
+
+ GetEventParameter( event, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &charCode );
+ GetEventParameter( event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode );
+ GetEventParameter( event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers );
+ GetEventParameter( event, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &point );
+
+ UInt32 message = (keyCode << 8) + charCode;
+ switch ( GetEventKind( event ) )
+ {
+ case kEventRawKeyRepeat :
+ case kEventRawKeyDown :
+ {
+ WXEVENTREF formerEvent = wxTheApp->MacGetCurrentEvent() ;
+ WXEVENTHANDLERCALLREF formerHandler = wxTheApp->MacGetCurrentEventHandlerCallRef() ;
+ wxTheApp->MacSetCurrentEvent( event , handler ) ;
+ if ( /* focus && */ wxTheApp->MacSendKeyDownEvent(
+ focus , message , modifiers , when , point.h , point.v , uniChar[0] ) )
+ {
+ result = noErr ;
+ }
+ wxTheApp->MacSetCurrentEvent( formerEvent , formerHandler ) ;
+ }
+ break ;
+
+ case kEventRawKeyUp :
+ if ( /* focus && */ wxTheApp->MacSendKeyUpEvent(
+ focus , message , modifiers , when , point.h , point.v , uniChar[0] ) )
+ {
+ result = noErr ;
+ }
+ break ;
+
+ case kEventRawKeyModifiersChanged :
+ {
+ wxKeyEvent event(wxEVT_KEY_DOWN);
+
+ event.m_shiftDown = modifiers & shiftKey;
+ event.m_controlDown = modifiers & controlKey;
+ event.m_altDown = modifiers & optionKey;
+ event.m_metaDown = modifiers & cmdKey;
+ event.m_x = point.h;
+ event.m_y = point.v;
+
+#if wxUSE_UNICODE
+ event.m_uniChar = uniChar[0] ;
+#endif
+
+ event.SetTimestamp(when);
+ event.SetEventObject(focus);
+
+ if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & controlKey )
+ {
+ event.m_keyCode = WXK_CONTROL ;
+ event.SetEventType( ( modifiers & controlKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ;
+ focus->GetEventHandler()->ProcessEvent( event ) ;
+ }
+ if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & shiftKey )
+ {
+ event.m_keyCode = WXK_SHIFT ;
+ event.SetEventType( ( modifiers & shiftKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ;
+ focus->GetEventHandler()->ProcessEvent( event ) ;
+ }
+ if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & optionKey )
+ {
+ event.m_keyCode = WXK_ALT ;
+ event.SetEventType( ( modifiers & optionKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ;
+ focus->GetEventHandler()->ProcessEvent( event ) ;
+ }
+ if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & cmdKey )
+ {
+ event.m_keyCode = WXK_COMMAND ;
+ event.SetEventType( ( modifiers & cmdKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ;
+ focus->GetEventHandler()->ProcessEvent( event ) ;
+ }
+
+ wxApp::s_lastModifiers = modifiers ;
+ }
+ break ;
+
+ default:
+ break;
+ }
+
+ return result ;
+}
+
static pascal OSStatus wxWebKitCtrlEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
{
OSStatus result = eventNotHandledErr ;
ControlRef controlRef ;
wxWebKitCtrl* thisWindow = (wxWebKitCtrl*) data ;
- wxTopLevelWindowMac* tlw = NULL;
+ wxNonOwnedWindow* tlw = NULL;
if (thisWindow)
tlw = thisWindow->MacGetTopLevelWindow();
cEvent.GetParameter( kEventParamDirectObject , &controlRef ) ;
-
+
wxWindow* currentMouseWindow = thisWindow ;
-
+
if ( wxApp::s_captureWindow )
currentMouseWindow = wxApp::s_captureWindow;
- switch ( GetEventKind( event ) )
+ switch ( GetEventClass( event ) )
{
- case kEventMouseDragged :
- case kEventMouseMoved :
+ case kEventClassKeyboard:
+ {
+ result = wxWebKitKeyEventHandler(handler, event, data);
+ break;
+ }
+
+ case kEventClassTextInput:
+ {
+ result = wxMacUnicodeTextEventHandler(handler, event, data);
+ break;
+ }
+
+ case kEventClassMouse:
+ {
+ switch ( GetEventKind( event ) )
{
- wxMouseEvent wxevent(wxEVT_LEFT_DOWN);
- SetupMouseEvent( wxevent , cEvent ) ;
-
- currentMouseWindow->ScreenToClient( &wxevent.m_x , &wxevent.m_y ) ;
- wxevent.SetEventObject( currentMouseWindow ) ;
- wxevent.SetId( currentMouseWindow->GetId() ) ;
-
- if ( currentMouseWindow->GetEventHandler()->ProcessEvent(wxevent) )
+ case kEventMouseDragged :
+ case kEventMouseMoved :
+ case kEventMouseDown :
+ case kEventMouseUp :
{
- result = noErr;
- }
+ wxMouseEvent wxevent(wxEVT_LEFT_DOWN);
+ SetupMouseEvent( wxevent , cEvent ) ;
- break; // this should enable WebKit to fire mouse dragged and mouse up events...
- }
+ currentMouseWindow->ScreenToClient( &wxevent.m_x , &wxevent.m_y ) ;
+ wxevent.SetEventObject( currentMouseWindow ) ;
+ wxevent.SetId( currentMouseWindow->GetId() ) ;
- case kEventControlBoundsChanged:
- {
- // this is just here for debugging, so we can note any differences between
- // native event sizes and the sizes the wxWindow receives.
- Rect origBounds = cEvent.GetParameter<Rect>(kEventParamOriginalBounds, typeQDRectangle) ;
- Rect prevBounds = cEvent.GetParameter<Rect>(kEventParamPreviousBounds, typeQDRectangle) ;
- Rect curBounds = cEvent.GetParameter<Rect>(kEventParamCurrentBounds, typeQDRectangle) ;
-
- fprintf(stderr, "Orig bounds x=%d, y=%d, height=%d, width=%d\n", origBounds.left, origBounds.top, origBounds.bottom -origBounds.top, origBounds.right - origBounds.left);
- fprintf(stderr, "Prev bounds x=%d, y=%d, height=%d, width=%d\n", prevBounds.left, prevBounds.top, prevBounds.bottom -prevBounds.top, prevBounds.right - prevBounds.left);
- fprintf(stderr, "Cur bounds x=%d, y=%d, height=%d, width=%d\n", curBounds.left, curBounds.top, curBounds.bottom -curBounds.top, curBounds.right - curBounds.left);
+ if ( currentMouseWindow->GetEventHandler()->ProcessEvent(wxevent) )
+ {
+ result = noErr;
+ }
+
+ break; // this should enable WebKit to fire mouse dragged and mouse up events...
+ }
+ default :
+ break ;
}
- default :
- break ;
+ }
+ default:
+ break;
}
result = CallNextEventHandler(handler, event);
SetId(win->GetId());
}
+
+IMPLEMENT_DYNAMIC_CLASS( wxWebKitNewWindowEvent, wxCommandEvent )
+
+DEFINE_EVENT_TYPE( wxEVT_WEBKIT_NEW_WINDOW )
+
+wxWebKitNewWindowEvent::wxWebKitNewWindowEvent( wxWindow* win )
+{
+ SetEventType( wxEVT_WEBKIT_NEW_WINDOW);
+ SetEventObject( win );
+ SetId(win->GetId());
+}
+
+
+
//---------------------------------------------------------
// helper functions for NSString<->wxString conversion
//---------------------------------------------------------
inline int wxNavTypeFromWebNavType(int type){
if (type == WebNavigationTypeLinkClicked)
return wxWEBKIT_NAV_LINK_CLICKED;
-
+
if (type == WebNavigationTypeFormSubmitted)
return wxWEBKIT_NAV_FORM_SUBMITTED;
-
+
if (type == WebNavigationTypeBackForward)
return wxWEBKIT_NAV_BACK_NEXT;
-
+
if (type == WebNavigationTypeReload)
return wxWEBKIT_NAV_RELOAD;
-
+
if (type == WebNavigationTypeFormResubmitted)
return wxWEBKIT_NAV_FORM_RESUBMITTED;
-
+
return wxWEBKIT_NAV_OTHER;
}
HIWebViewCreate( m_peer->GetControlRefAddr() );
m_webView = (WebView*) HIWebViewGetWebView( m_peer->GetControlRef() );
-
+
MacPostControlCreate(pos, size);
HIViewSetVisible( m_peer->GetControlRef(), true );
[m_webView setHidden:false];
// Register event listener interfaces
MyFrameLoadMonitor* myFrameLoadMonitor = [[MyFrameLoadMonitor alloc] initWithWxWindow: this];
[m_webView setFrameLoadDelegate:myFrameLoadMonitor];
-
+
// this is used to veto page loads, etc.
MyPolicyDelegate* myPolicyDelegate = [[MyPolicyDelegate alloc] initWithWxWindow: this];
[m_webView setPolicyDelegate:myPolicyDelegate];
-
+
LoadURL(m_currentURL);
return true;
}
wxString wxWebKitCtrl::GetSelection(){
if ( !m_webView )
return wxEmptyString;
-
+
NSString* selectedText = [[m_webView selectedDOMRange] toString];
return wxStringWithNSString( selectedText );
}
bool wxWebKitCtrl::CanIncreaseTextSize(){
if ( !m_webView )
return false;
-
+
if ([m_webView canMakeTextLarger])
return true;
else
void wxWebKitCtrl::IncreaseTextSize(){
if ( !m_webView )
return;
-
+
if (CanIncreaseTextSize())
[m_webView makeTextLarger:(WebView*)m_webView];
}
bool wxWebKitCtrl::CanDecreaseTextSize(){
if ( !m_webView )
return false;
-
+
if ([m_webView canMakeTextSmaller])
return true;
else
void wxWebKitCtrl::DecreaseTextSize(){
if ( !m_webView )
return;
-
+
if (CanDecreaseTextSize())
[m_webView makeTextSmaller:(WebView*)m_webView];
}
void wxWebKitCtrl::Print(bool showPrompt){
if ( !m_webView )
return;
-
- id view = [[[m_webView mainFrame] frameView] documentView];
- NSPrintOperation *op = [NSPrintOperation printOperationWithView:view printInfo: [NSPrintInfo sharedPrintInfo]];
+
+ id view = [[[m_webView mainFrame] frameView] documentView];
+ NSPrintOperation *op = [NSPrintOperation printOperationWithView:view printInfo: [NSPrintInfo sharedPrintInfo]];
if (showPrompt){
[op setShowsPrintPanel: showPrompt];
// in my tests, the progress bar always freezes and it stops the whole print operation.
// do not turn this to true unless there is a workaround for the bug.
[op setShowsProgressPanel: false];
}
- // Print it.
- [op runOperation];
+ // Print it.
+ [op runOperation];
}
void wxWebKitCtrl::MakeEditable(bool enable){
int wxWebKitCtrl::GetScrollPos(){
id result = [[m_webView windowScriptObject] evaluateWebScript:@"document.body.scrollTop"];
return [result intValue];
-}
+}
void wxWebKitCtrl::SetScrollPos(int pos){
if ( !m_webView )
return;
-
- wxString javascript;
+
+ wxString javascript;
javascript.Printf(wxT("document.body.scrollTop = %d;"), pos);
[[m_webView windowScriptObject] evaluateWebScript:(NSString*)wxNSStringWithWxString( javascript )];
}
wxString wxWebKitCtrl::RunScript(const wxString& javascript){
if ( !m_webView )
- return wxEmptyString;
-
+ return wxEmptyString;
+
id result = [[m_webView windowScriptObject] evaluateWebScript:(NSString*)wxNSStringWithWxString( javascript )];
-
+
NSString* resultAsString;
wxString resultAsWxString = wxEmptyString;
NSString* className = NSStringFromClass([result class]);
wxWindow* tlw = MacGetTopLevelWindow();
- NSRect frame = [m_webView frame];
- NSRect bounds = [m_webView bounds];
-
+ NSRect frame = [(WebView*)m_webView frame];
+ NSRect bounds = [(WebView*)m_webView bounds];
+
#if DEBUG_WEBKIT_SIZING
fprintf(stderr,"Carbon window x=%d, y=%d, width=%d, height=%d\n", GetPosition().x, GetPosition().y, GetSize().x, GetSize().y);
fprintf(stderr, "Cocoa window frame x=%G, y=%G, width=%G, height=%G\n", frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
return;
}
- int x = GetPosition().x;
- int y = GetPosition().y;
-
+ // since we no longer use parent coordinates, we always want 0,0.
+ int x = 0;
+ int y = 0;
+
HIRect rect;
rect.origin.x = x;
rect.origin.y = y;
// NB: In most cases, when calling HIViewConvertRect, what people want is to use GetRootControl(),
// and this tripped me up at first. But in fact, what we want is the root view, because we need to
- // make the y origin relative to the very top of the window, not its contents, since we later flip
- // the y coordinate for Cocoa.
- HIViewConvertRect (&rect, HIViewGetSuperview( m_peer->GetControlRef() ),
+ // make the y origin relative to the very top of the window, not its contents, since we later flip
+ // the y coordinate for Cocoa.
+ HIViewConvertRect (&rect, m_peer->GetControlRef(),
HIViewGetRoot( (WindowRef) MacGetTopLevelWindowRef() ) );
x = (int)rect.origin.x;
frame.origin.x = x;
frame.origin.y = y;
- [m_webView setFrame:frame];
-
+ [(WebView*)m_webView setFrame:frame];
+
if (IsShown())
[(WebView*)m_webView display];
event.Skip();
// Listener interfaces
//------------------------------------------------------------
+// NB: I'm still tracking this down, but it appears the Cocoa window
+// still has these events fired on it while the Carbon control is being
+// destroyed. Therefore, we must be careful to check both the existence
+// of the Carbon control and the event handler before firing events.
+
@implementation MyFrameLoadMonitor
- initWithWxWindow: (wxWebKitCtrl*)inWindow
- (void)webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame
{
- if (frame == [sender mainFrame]){
+ if (webKitWindow && frame == [sender mainFrame]){
NSString *url = [[[[frame provisionalDataSource] request] URL] absoluteString];
wxWebKitStateChangedEvent thisEvent(webKitWindow);
thisEvent.SetState(wxWEBKIT_STATE_NEGOTIATING);
thisEvent.SetURL( wxStringWithNSString( url ) );
- webKitWindow->GetEventHandler()->ProcessEvent( thisEvent );
+ if (webKitWindow->GetEventHandler())
+ webKitWindow->GetEventHandler()->ProcessEvent( thisEvent );
}
}
- (void)webView:(WebView *)sender didCommitLoadForFrame:(WebFrame *)frame
{
- if (frame == [sender mainFrame]){
+ if (webKitWindow && frame == [sender mainFrame]){
NSString *url = [[[[frame dataSource] request] URL] absoluteString];
wxWebKitStateChangedEvent thisEvent(webKitWindow);
thisEvent.SetState(wxWEBKIT_STATE_TRANSFERRING);
thisEvent.SetURL( wxStringWithNSString( url ) );
- webKitWindow->GetEventHandler()->ProcessEvent( thisEvent );
+ if (webKitWindow->GetEventHandler())
+ webKitWindow->GetEventHandler()->ProcessEvent( thisEvent );
}
}
- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame
{
- if (frame == [sender mainFrame]){
+ if (webKitWindow && frame == [sender mainFrame]){
NSString *url = [[[[frame dataSource] request] URL] absoluteString];
wxWebKitStateChangedEvent thisEvent(webKitWindow);
thisEvent.SetState(wxWEBKIT_STATE_STOP);
thisEvent.SetURL( wxStringWithNSString( url ) );
- webKitWindow->GetEventHandler()->ProcessEvent( thisEvent );
+ if (webKitWindow->GetEventHandler())
+ webKitWindow->GetEventHandler()->ProcessEvent( thisEvent );
}
}
- (void)webView:(WebView *)sender didFailLoadWithError:(NSError*) error forFrame:(WebFrame *)frame
{
- if (frame == [sender mainFrame]){
+ wxUnusedVar(error);
+
+ if (webKitWindow && frame == [sender mainFrame]){
NSString *url = [[[[frame dataSource] request] URL] absoluteString];
wxWebKitStateChangedEvent thisEvent(webKitWindow);
thisEvent.SetState(wxWEBKIT_STATE_FAILED);
thisEvent.SetURL( wxStringWithNSString( url ) );
- webKitWindow->GetEventHandler()->ProcessEvent( thisEvent );
+ if (webKitWindow->GetEventHandler())
+ webKitWindow->GetEventHandler()->ProcessEvent( thisEvent );
}
}
- (void)webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError*) error forFrame:(WebFrame *)frame
{
- if (frame == [sender mainFrame]){
+ wxUnusedVar(error);
+
+ if (webKitWindow && frame == [sender mainFrame]){
NSString *url = [[[[frame provisionalDataSource] request] URL] absoluteString];
wxWebKitStateChangedEvent thisEvent(webKitWindow);
thisEvent.SetState(wxWEBKIT_STATE_FAILED);
thisEvent.SetURL( wxStringWithNSString( url ) );
- webKitWindow->GetEventHandler()->ProcessEvent( thisEvent );
+ if (webKitWindow->GetEventHandler())
+ webKitWindow->GetEventHandler()->ProcessEvent( thisEvent );
}
}
- (void)webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame
{
- if (frame == [sender mainFrame]){
+ if (webKitWindow && frame == [sender mainFrame]){
webKitWindow->SetPageTitle(wxStringWithNSString( title ));
}
}
- (void)webView:(WebView *)sender decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener
{
+ wxUnusedVar(sender);
+ wxUnusedVar(frame);
+
wxWebKitBeforeLoadEvent thisEvent(webKitWindow);
- // Get the navigation type.
- NSNumber *n = [actionInformation objectForKey:WebActionNavigationTypeKey];
+ // Get the navigation type.
+ NSNumber *n = [actionInformation objectForKey:WebActionNavigationTypeKey];
int actionType = [n intValue];
thisEvent.SetNavigationType( wxNavTypeFromWebNavType(actionType) );
-
+
NSString *url = [[request URL] absoluteString];
thisEvent.SetURL( wxStringWithNSString( url ) );
-
- webKitWindow->GetEventHandler()->ProcessEvent(thisEvent);
- if (thisEvent.IsCancelled())
+ if (webKitWindow && webKitWindow->GetEventHandler())
+ webKitWindow->GetEventHandler()->ProcessEvent(thisEvent);
+
+ if (thisEvent.IsCancelled())
[listener ignore];
else
[listener use];
}
+- (void)webView:(WebView *)sender decidePolicyForNewWindowAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request newFrameName:(NSString *)frameName decisionListener:(id < WebPolicyDecisionListener >)listener
+{
+ wxWebKitNewWindowEvent thisEvent(webKitWindow);
+
+ NSString *url = [[request URL] absoluteString];
+ thisEvent.SetURL( wxStringWithNSString( url ) );
+ thisEvent.SetTargetName( wxStringWithNSString( frameName ) );
+
+ if (webKitWindow && webKitWindow->GetEventHandler())
+ webKitWindow->GetEventHandler()->ProcessEvent(thisEvent);
+
+ [listener use];
+}
@end
#endif //wxUSE_WEBKIT