/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: NPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Netscape Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the NPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the NPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsChildView.h" #include "nsIFontMetrics.h" #include "nsIDeviceContext.h" #include "nsCOMPtr.h" #include "nsToolkit.h" #include "nsIEnumerator.h" #include "prmem.h" #include "nsCRT.h" #include #include #include #include #include "nsplugindefs.h" #include "nsMacResources.h" #include "nsIRegion.h" #include "nsIRollupListener.h" #include "nsIEventSink.h" #include "nsIScrollableView.h" #include "nsCarbonHelpers.h" #include "nsGfxUtils.h" #if PINK_PROFILING #include "profilerutils.h" #endif #include #define NSAppKitVersionNumber10_2 663 @interface ChildView(Private) // sends gecko an ime composition event - (nsRect) sendCompositionEvent:(PRInt32)aEventType; // sends gecko an ime text event - (void) sendTextEvent:(PRUnichar*) aBuffer attributedString:(NSAttributedString*) aString selectedRange:(NSRange)selRange markedRange:(NSRange)markRange doCommit:(BOOL)doCommit; // sets up our view, attaching it to its owning gecko view - (id) initWithGeckoChild:(nsChildView*)child eventSink:(nsIEventSink*)sink; // convert from one event system to the other for event dispatching - (void) convert:(NSEvent*)inEvent message:(PRInt32)inMsg toGeckoEvent:(nsInputEvent*)outGeckoEvent; // create a gecko key event out of a cocoa event - (void) convert:(NSEvent*)aKeyEvent message:(PRUint32)aMessage isChar:(PRBool*)outIsChar toGeckoEvent:(nsKeyEvent*)outGeckoEvent; - (void) convert:(NSPoint)inPoint message:(PRInt32)inMsg modifiers:(unsigned int)inMods toGeckoEvent:(nsInputEvent*)outGeckoEvent; - (NSMenu*)getContextMenu; - (void)setIsPluginView:(BOOL)aIsPlugin; - (BOOL)getIsPluginView; - (BOOL)childViewHasPlugin; #if USE_CLICK_HOLD_CONTEXTMENU // called on a timer two seconds after a mouse down to see if we should display // a context menu (click-hold) - (void)clickHoldCallback:(id)inEvent; #endif @end //////////////////////////////////////////////////// nsIRollupListener * gRollupListener = nsnull; nsIWidget * gRollupWidget = nsnull; // Since we only want a single notification pending for the app we'll declare // these static static NMRec gNMRec; static Boolean gNotificationInstalled = false; #pragma mark - //#define PAINT_DEBUGGING // flash areas as they are painted //#define INVALIDATE_DEBUGGING // flash areas as they are invalidated #if defined(INVALIDATE_DEBUGGING) || defined(PAINT_DEBUGGING) static void blinkRect(Rect* r); static void blinkRgn(RgnHandle rgn); #endif #pragma mark - // // Convenience routines to go from a gecko rect to cocoa NSRects and back // static inline void ConvertGeckoToCocoaRect ( const nsRect & inGeckoRect, NSRect & outCocoaRect ) { outCocoaRect.origin.x = inGeckoRect.x; outCocoaRect.origin.y = inGeckoRect.y; outCocoaRect.size.width = inGeckoRect.width; outCocoaRect.size.height = inGeckoRect.height; } static inline void ConvertCocoaToGeckoRect ( const NSRect & inCocoaRect, nsRect & outGeckoRect ) { outGeckoRect.x = NS_STATIC_CAST(nscoord, inCocoaRect.origin.x); outGeckoRect.y = NS_STATIC_CAST(nscoord, inCocoaRect.origin.y); outGeckoRect.width = NS_STATIC_CAST(nscoord, inCocoaRect.size.width); outGeckoRect.height = NS_STATIC_CAST(nscoord, inCocoaRect.size.height); } static inline void ConvertGeckoRectToMacRect(const nsRect& aRect, Rect& outMacRect) { outMacRect.left = aRect.x; outMacRect.top = aRect.y; outMacRect.right = aRect.x + aRect.width; outMacRect.bottom = aRect.y + aRect.height; } static PRUint32 underlineAttributeToTextRangeType(PRUint32 aUnderlineStyle) { #ifdef DEBUG_IME NSLog(@"****in underlineAttributeToTextRangeType = %d", aUnderlineStyle); #endif // For more info on the underline attribute, please see: // http://developer.apple.com/techpubs/macosx/Cocoa/TasksAndConcepts/ProgrammingTopics/AttributedStrings/Tasks/AccessingAttrs.html // We are not clear where the define for value 2 is right now. // To see this value in japanese ime, type 'aaaaaaaaa' and hit space to make the // ime send you some part of text in 1 (NSSingleUnderlineStyle) and some part in 2. // ftang will ask apple for more details // // it probably means show 1-pixel thickness underline vs 2-pixel thickness return aUnderlineStyle == 1 ? NS_TEXTRANGE_CONVERTEDTEXT : NS_TEXTRANGE_SELECTEDCONVERTEDTEXT; } static PRUint32 countRanges(NSAttributedString *aString) { // Iterate through aString for the NSUnderlineStyleAttributeName and count the // different segments adjusting limitRange as we go. PRUint32 count = 0; NSRange effectiveRange; NSRange limitRange = NSMakeRange(0, [aString length]); while (limitRange.length > 0) { [aString attribute:NSUnderlineStyleAttributeName atIndex:limitRange.location longestEffectiveRange:&effectiveRange inRange:limitRange]; limitRange = NSMakeRange(NSMaxRange(effectiveRange), NSMaxRange(limitRange) - NSMaxRange(effectiveRange)); count++; } return count; } static void convertAttributeToGeckoRange(NSAttributedString *aString, NSRange markRange, PRUint32 inCount, nsTextRange* aRanges) { // Convert the Cocoa range into the nsTextRange Array used in Gecko. // Iterate through the attributed string and map the underline attribute to Gecko IME textrange attributes. // We may need to change the code here if we change the implementation of validAttributesForMarkedText. PRUint32 i = 0; NSRange effectiveRange; NSRange limitRange = NSMakeRange(0, [aString length]); while ((limitRange.length > 0) && (i < inCount)) { id attributeValue = [aString attribute:NSUnderlineStyleAttributeName atIndex:limitRange.location longestEffectiveRange:&effectiveRange inRange:limitRange]; aRanges[i].mStartOffset = effectiveRange.location; aRanges[i].mEndOffset = NSMaxRange(effectiveRange); aRanges[i].mRangeType = underlineAttributeToTextRangeType([attributeValue intValue]); limitRange = NSMakeRange(NSMaxRange(effectiveRange), NSMaxRange(limitRange) - NSMaxRange(effectiveRange)); i++; } } static void fillTextRangeInTextEvent(nsTextEvent *aTextEvent, NSAttributedString* aString, NSRange markRange) { // Count the number of segments in the attributed string. Allocate the right size of nsTextRange. // Convert the attributed string into an array of nsTextRange by calling above functions. PRUint32 count = countRanges(aString); aTextEvent->rangeArray = new nsTextRange[count]; if (aTextEvent->rangeArray) { aTextEvent->rangeCount = count; convertAttributeToGeckoRange(aString, markRange, aTextEvent->rangeCount, aTextEvent->rangeArray); } } #pragma mark - //------------------------------------------------------------------------- // // nsChildView constructor // //------------------------------------------------------------------------- nsChildView::nsChildView() : nsBaseWidget() , mView(nsnull) , mParentView(nsnull) , mParentWidget(nsnull) , mFontMetrics(nsnull) , mTempRenderingContext(nsnull) , mDestroyCalled(PR_FALSE) , mDestructorCalled(PR_FALSE) , mVisible(PR_FALSE) , mInWindow(PR_FALSE) , mDrawing(PR_FALSE) , mTempRenderingContextMadeHere(PR_FALSE) , mAcceptFocusOnClick(PR_TRUE) , mLiveResizeInProgress(PR_FALSE) , mPluginDrawing(PR_FALSE) , mPluginPort(nsnull) , mVisRgn(nsnull) { WIDGET_SET_CLASSNAME("nsChildView"); SetBackgroundColor(NS_RGB(255, 255, 255)); SetForegroundColor(NS_RGB(0, 0, 0)); } //------------------------------------------------------------------------- // // nsChildView destructor // //------------------------------------------------------------------------- nsChildView::~nsChildView() { TearDownView(); // should have already been done from Destroy NS_IF_RELEASE(mTempRenderingContext); NS_IF_RELEASE(mFontMetrics); delete mPluginPort; if (mVisRgn) { ::DisposeRgn(mVisRgn); mVisRgn = nsnull; } } NS_IMPL_ISUPPORTS_INHERITED3(nsChildView, nsBaseWidget, nsIPluginWidget, nsIKBStateControl, nsIEventSink) //------------------------------------------------------------------------- // // Utility method for implementing both Create(nsIWidget ...) and // Create(nsNativeWidget...) //------------------------------------------------------------------------- nsresult nsChildView::StandardCreate(nsIWidget *aParent, const nsRect &aRect, EVENT_CALLBACK aHandleEventFunction, nsIDeviceContext *aContext, nsIAppShell *aAppShell, nsIToolkit *aToolkit, nsWidgetInitData *aInitData, nsNativeWidget aNativeParent) { mBounds = aRect; // CalcWindowRegions(); BaseCreate(aParent, aRect, aHandleEventFunction, aContext, aAppShell, aToolkit, aInitData); // inherit things from the parent view and create our parallel // NSView in the Cocoa display system mParentView = nil; if ( aParent ) { SetBackgroundColor(aParent->GetBackgroundColor()); SetForegroundColor(aParent->GetForegroundColor()); // inherit the top-level window. NS_NATIVE_WIDGET is always a NSView // regardless of if we're asking a window or a view (for compatibility // with windows). mParentView = (NSView*)aParent->GetNativeData(NS_NATIVE_WIDGET); mParentWidget = aParent; } else mParentView = NS_REINTERPRET_CAST(NSView*,aNativeParent); // create our parallel NSView and hook it up to our parent. Recall // that NS_NATIVE_WIDGET is the NSView. NSRect r; ConvertGeckoToCocoaRect(mBounds, r); mView = [CreateCocoaView() retain]; if (!mView) return NS_ERROR_FAILURE; [mView setFrame:r]; #if DEBUG // if our parent is a popup window, we're most certainly coming from a