📄 hiwebview.m
字号:
GetControlBounds( inView->fViewRef, &bounds ); OffsetRect( &bounds, -(**portPix).bounds.left, -(**portPix).bounds.top );// printf( "control lives at %d %d %d %d in window-coords\n", bounds.top, bounds.left,// bounds.bottom, bounds.right ); HIViewGetFrame( HIViewGetRoot( GetControlOwner( inView->fViewRef ) ), &rootFrame ); frame.origin.x = bounds.left; frame.origin.y = rootFrame.size.height - bounds.bottom; frame.size.width = bounds.right - bounds.left; frame.size.height = bounds.bottom - bounds.top;// printf( " before frame convert (%g %g) (%g %g)\n", frame.origin.x, frame.origin.y,// frame.size.width, frame.size.height ); [inView->fWebView convertRect:*(NSRect*)&frame fromView:nil];// printf( " moving web view to (%g %g) (%g %g)\n", frame.origin.x, frame.origin.y,// frame.size.width, frame.size.height ); [inView->fWebView setFrameOrigin: *(NSPoint*)&frame.origin]; [inView->fWebView setFrameSize: *(NSSize*)&frame.size]; } }}//----------------------------------------------------------------------------------// SetFocusPart//----------------------------------------------------------------------------------//static OSStatusSetFocusPart( HIWebView* view, ControlPartCode desiredFocus, RgnHandle invalidRgn, Boolean focusEverything, ControlPartCode* actualFocus ){ NSView * freshlyMadeFirstResponderView; SInt32 partCodeToReturn; // Do what Carbon is telling us to do. if ( desiredFocus == kControlFocusNoPart ) { // Relinquish the keyboard focus. RelinquishFocus( view, true ); //(autodisplay ? YES : NO)); freshlyMadeFirstResponderView = nil; partCodeToReturn = kControlFocusNoPart; //NSLog(@"Relinquished the key focus because we have no choice."); } else if ( desiredFocus == kControlFocusNextPart || desiredFocus == kControlFocusPrevPart ) { BOOL goForward = (desiredFocus == kControlFocusNextPart ); // Advance the keyboard focus, maybe right off of this view. Maybe a subview of this one already has the keyboard focus, maybe not. freshlyMadeFirstResponderView = AdvanceFocus( view, goForward ); if (freshlyMadeFirstResponderView) partCodeToReturn = desiredFocus; else partCodeToReturn = kControlFocusNoPart; //NSLog(freshlyMadeFirstResponderView ? @"Advanced the key focus." : @"Relinquished the key focus."); } else { // What's this? if (desiredFocus != kControlIndicatorPart) { check(false); } freshlyMadeFirstResponderView = nil; partCodeToReturn = desiredFocus; } view->fFirstResponder = freshlyMadeFirstResponderView; *actualFocus = partCodeToReturn; // Done. return noErr;}//----------------------------------------------------------------------------------// AdvanceFocus//----------------------------------------------------------------------------------//static NSView*AdvanceFocus( HIWebView* view, bool forward ){ NSResponder* oldFirstResponder; NSView* currentKeyView; NSView* viewWeMadeFirstResponder; // Focus on some part (subview) of this control (view). Maybe // a subview of this one already has the keyboard focus, maybe not. oldFirstResponder = [view->fKitWindow firstResponder]; // If we tab out of our NSView, it will no longer be the responder // when we get here. We'll try this trick for now. We might need to // tag the view appropriately. if ( view->fFirstResponder && ( (NSResponder*)view->fFirstResponder != oldFirstResponder ) ) { return NULL; } if ( [oldFirstResponder isKindOfClass:[NSView class]] ) { NSView* tentativeNewKeyView; // Some view in this window already has the keyboard focus. It better at least be a subview of this one. NSView* oldFirstResponderView = (NSView *)oldFirstResponder; check( [oldFirstResponderView isDescendantOf:view->fWebView] ); if ( oldFirstResponderView != view->fFirstResponder && ![oldFirstResponderView isDescendantOf:view->fFirstResponder] ) { // Despite our efforts to record what view we made the first responder // (for use in the next paragraph) we couldn't keep up because the user // has clicked in a text field to make it the key focus, instead of using // the tab key. Find a control on which it's reasonable to invoke // -[NSView nextValidKeyView], taking into account the fact that // NSTextFields always pass on first-respondership to a temporarily- // contained NSTextView. NSView *viewBeingTested; currentKeyView = oldFirstResponderView; viewBeingTested = currentKeyView; while ( viewBeingTested != view->fWebView ) { if ( [viewBeingTested isKindOfClass:[NSTextField class]] ) { currentKeyView = viewBeingTested; break; } else { viewBeingTested = [viewBeingTested superview]; } } } else { // We recorded which view we made into the first responder the // last time the user hit the tab key, and nothing has invalidated // our recorded value since. currentKeyView = view->fFirstResponder; } // Try to move on to the next or previous key view. We use the laboriously // recorded/figured currentKeyView instead of just oldFirstResponder as the // jumping-off-point when searching for the next valid key view. This is so // we don't get fooled if we recently made some view the first responder, but // it passed on first-responder-ness to some temporary subview. // You can't put normal views in a window with Carbon-control-wrapped views. // Stuff like this would break. M.P. Notice - 12/2/00 tentativeNewKeyView = forward ? [currentKeyView nextValidKeyView] : [currentKeyView previousValidKeyView]; if ( tentativeNewKeyView && [tentativeNewKeyView isDescendantOf:view->fWebView] ) { // The user has tabbed to another subview of this control view. Change the keyboard focus. //NSLog(@"Tabbed to the next or previous key view."); [view->fKitWindow makeFirstResponder:tentativeNewKeyView]; viewWeMadeFirstResponder = tentativeNewKeyView; } else { // The user has tabbed past the subviews of this control view. The window is the first responder now. //NSLog(@"Tabbed past the first or last key view."); [view->fKitWindow makeFirstResponder:view->fKitWindow]; viewWeMadeFirstResponder = nil; } } else { // No view in this window has the keyboard focus. This view should // try to select one of its key subviews. We're not interested in // the subviews of sibling views here. //NSLog(@"No keyboard focus in window. Attempting to set..."); NSView *tentativeNewKeyView; check(oldFirstResponder==fKitWindow); if ( [view->fWebView acceptsFirstResponder] ) tentativeNewKeyView = view->fWebView; else tentativeNewKeyView = [view->fWebView nextValidKeyView]; if ( tentativeNewKeyView && [tentativeNewKeyView isDescendantOf:view->fWebView] ) { // This control view has at least one subview that can take the keyboard focus. if ( !forward ) { // The user has tabbed into this control view backwards. Find // and select the last subview of this one that can take the // keyboard focus. Watch out for loops of valid key views. NSView *firstTentativeNewKeyView = tentativeNewKeyView; NSView *nextTentativeNewKeyView = [tentativeNewKeyView nextValidKeyView]; while ( nextTentativeNewKeyView && [nextTentativeNewKeyView isDescendantOf:view->fWebView] && nextTentativeNewKeyView!=firstTentativeNewKeyView) { tentativeNewKeyView = nextTentativeNewKeyView; nextTentativeNewKeyView = [tentativeNewKeyView nextValidKeyView]; } } // Set the keyboard focus. //NSLog(@"Tabbed into the first or last key view."); [view->fKitWindow makeFirstResponder:tentativeNewKeyView]; viewWeMadeFirstResponder = tentativeNewKeyView; } else { // This control view has no subviews that can take the keyboard focus. //NSLog(@"Can't tab into this view."); viewWeMadeFirstResponder = nil; } } // Done. return viewWeMadeFirstResponder;}//----------------------------------------------------------------------------------// RelinquishFocus//----------------------------------------------------------------------------------//static voidRelinquishFocus( HIWebView* view, bool inAutodisplay ){ NSResponder* firstResponder; // Apparently Carbon thinks that some subview of this control view has the keyboard focus, // or we wouldn't be being asked to relinquish focus. firstResponder = [view->fKitWindow firstResponder]; if ( [firstResponder isKindOfClass:[NSView class]] ) { // Some subview of this control view really is the first responder right now. check( [(NSView *)firstResponder isDescendantOf:view->fWebView] ); // Make the window the first responder, so that no view is the key view. [view->fKitWindow makeFirstResponder:view->fKitWindow]; // If this control is not allowed to do autodisplay, don't let // it autodisplay any just-changed focus rings or text on the // next go around the event loop. I'm probably clearing more // dirty rects than I have to, but it doesn't seem to hurt in // the print panel accessory view case, and I don't have time // to figure out exactly what -[NSCell _setKeyboardFocusRingNeedsDisplay] // is doing when invoked indirectly from -makeFirstResponder up above. M.P. Notice - 12/4/00 if ( !inAutodisplay ) [[view->fWebView opaqueAncestor] _clearDirtyRectsForTree]; } else { // The Cocoa first responder does not correspond to the Carbon // control that has the keyboard focus. This can happen when // you've closed a dialog by hitting return in an NSTextView // that's a subview of this one; Cocoa closed the window, and // now Carbon is telling this control to relinquish the focus // as it's being disposed. There's nothing to do. check(firstResponder==window); }}//----------------------------------------------------------------------------------// ActiveStateChanged//----------------------------------------------------------------------------------//static voidActiveStateChanged( HIWebView* view ){ if ( [view->fWebView respondsToSelector:@selector(setEnabled)] ) { [(NSControl*)view->fWebView setEnabled: IsControlEnabled( view->fViewRef )]; HIViewSetNeedsDisplay( view->fViewRef, true ); }}//----------------------------------------------------------------------------------// ProcessCommand//----------------------------------------------------------------------------------//static OSStatusProcessCommand( HIWebView* inView, const HICommand* inCommand ){ OSStatus result = eventNotHandledErr; NSResponder* resp; resp = [inView->fKitWindow firstResponder]; if ( [resp isKindOfClass:[NSView class]] ) { NSView* respView = (NSView*)resp; if ( respView == inView->fWebView || [respView isDescendantOf: inView->fWebView] ) { switch ( inCommand->commandID ) { case kHICommandCut: case kHICommandCopy: case kHICommandPaste: case kHICommandClear: case kHICommandSelectAll: { SEL selector = _NSSelectorForHICommand( inCommand ); if ( [respView respondsToSelector:selector] ) { [respView performSelector:selector withObject:nil]; result = noErr; } } break; } } } return result;}//----------------------------------------------------------------------------------// UpdateCommandStatus//----------------------------------------------------------------------------------//static OSStatusUpdateCommandStatus( HIWebView* inView, const HICommand* inCommand ){ OSStatus result = eventNotHandledErr; MenuItemProxy* proxy = NULL; NSResponder* resp; resp = [inView->fKitWindow firstResponder]; if ( [resp isKindOfClass:[NSView class]] ) { NSView* respView = (NSView*)resp; if ( respView == inView->fWebView || [respView isDescendantOf: inView->fWebView] ) { if ( inCommand->attributes & kHICommandFromMenu ) { SEL selector = _NSSelectorForHICommand( inCommand ); if ( selector ) { if ( [resp respondsToSelector: selector] ) { proxy = [[MenuItemProxy alloc] initWithAction: selector]; // Can't use -performSelector:withObject: here because the method we're calling returns BOOL, while // -performSelector:withObject:'s return value is assumed to be an id. BOOL (*validationFunction)(id, SEL, id) = (BOOL (*)(id, SEL, id))objc_msgSend; if (validationFunction(resp, @selector(validateUserInterfaceItem:), proxy)) EnableMenuItem( inCommand->menu.menuRef, inCommand->menu.menuItemIndex ); else DisableMenuItem( inCommand->menu.menuRef, inCommand->menu.menuItemIndex ); result = noErr; } } } } } if ( proxy ) [proxy release]; return result;}// Blatantly stolen from AppKit and cropped a bit//----------------------------------------------------------------------------------// _NSSelectorForHICommand//----------------------------------------------------------------------------------//static SEL_NSSelectorForHICommand( const HICommand* inCommand ){ switch ( inCommand->commandID ) { case kHICommandUndo: return @selector(undo:); case kHICommandRedo: return @selector(redo:); case kHICommandCut : return @selector(cut:); case kHICommandCopy : return @selector(copy:); case kHICommandPaste: return @selector(paste:); case kHICommandClear: return @selector(delete:); case kHICommandSelectAll: return @selector(selectAll:); default: return NULL; } return NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -