зеркало из https://github.com/mozilla/pjs.git
Fix bug 182783, bug 292473 and bug 280894. Add a per-window class that registers for window activate/deactivate notifications, and sends appropriate activate events to gecko. Also fix up interaction with the NSInputManager (aka IME/TSM). r=pinkerton. Only affects Camino.
This commit is contained in:
Родитель
ce057b7855
Коммит
3c621d4c4e
|
@ -111,6 +111,7 @@ CMMSRCS = \
|
|||
nsAppShellCocoa.mm \
|
||||
nsCocoaWindow.mm \
|
||||
nsChildView.mm \
|
||||
nsWindowMap.mm \
|
||||
nsWidgetFactory.mm \
|
||||
nsNativeScrollbar.mm \
|
||||
nsCursorManager.mm \
|
||||
|
|
|
@ -102,6 +102,11 @@ class nsChildView;
|
|||
nscoord mHandScrollStartScrollX, mHandScrollStartScrollY;
|
||||
}
|
||||
|
||||
// these are sent to the first responder when the window key status
|
||||
// changes
|
||||
- (void)viewsWindowDidBecomeKey;
|
||||
- (void)viewsWindowDidResignKey;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
|
|
@ -35,22 +35,19 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#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 <Appearance.h>
|
||||
#include <Timer.h>
|
||||
#include <Icons.h>
|
||||
#include <Errors.h>
|
||||
|
||||
#include "nsplugindefs.h"
|
||||
#include "nsMacResources.h"
|
||||
|
||||
#include "nsIFontMetrics.h"
|
||||
#include "nsIDeviceContext.h"
|
||||
#include "nsIEnumerator.h"
|
||||
#include "nsIRegion.h"
|
||||
#include "nsIRollupListener.h"
|
||||
#include "nsIEventSink.h"
|
||||
|
@ -59,13 +56,10 @@
|
|||
|
||||
#include "nsCarbonHelpers.h"
|
||||
#include "nsGfxUtils.h"
|
||||
#include "nsMacResources.h"
|
||||
|
||||
#if PINK_PROFILING
|
||||
#include "profilerutils.h"
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include "nsCursorManager.h"
|
||||
#import "nsCursorManager.h"
|
||||
#import "nsWindowMap.h"
|
||||
|
||||
#define NSAppKitVersionNumber10_2 663
|
||||
|
||||
|
@ -80,8 +74,7 @@
|
|||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
//#define DEBUG_IME 1
|
||||
|
||||
@interface ChildView(Private)
|
||||
|
||||
|
@ -109,6 +102,7 @@
|
|||
modifiers:(unsigned int)inMods toGeckoEvent:(nsInputEvent*)outGeckoEvent;
|
||||
|
||||
- (NSMenu*)getContextMenu;
|
||||
- (TopLevelWindowData*)ensureWindowData;
|
||||
|
||||
- (void)setIsPluginView:(BOOL)aIsPlugin;
|
||||
- (BOOL)getIsPluginView;
|
||||
|
@ -125,6 +119,7 @@
|
|||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
nsIRollupListener * gRollupListener = nsnull;
|
||||
|
@ -435,6 +430,11 @@ nsresult nsChildView::StandardCreate(nsIWidget *aParent,
|
|||
mInWindow = PR_FALSE;
|
||||
}
|
||||
|
||||
// if this is a ChildView, make sure that our per-window data
|
||||
// is set up
|
||||
if ([mView isKindOfClass:[ChildView class]])
|
||||
[mView ensureWindowData];
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2044,45 +2044,52 @@ NS_IMETHODIMP nsChildView::GetAttention(PRInt32 aCycleCount)
|
|||
|
||||
#pragma mark -
|
||||
|
||||
|
||||
//
|
||||
// Force Input Method Editor to commit the uncommited input
|
||||
//
|
||||
NS_IMETHODIMP nsChildView::ResetInputState()
|
||||
{
|
||||
#if 0
|
||||
// currently, the nsMacEventHandler is owned by nsCocoaWindow, which is the top level window
|
||||
// we delegate this call to its parent
|
||||
nsCOMPtr<nsIWidget> parent = getter_AddRefs(GetParent());
|
||||
NS_ASSERTION(parent, "cannot get parent");
|
||||
if(parent)
|
||||
{
|
||||
nsCOMPtr<nsIKBStateControl> kb = do_QueryInterface(parent);
|
||||
NS_ASSERTION(kb, "cannot get parent");
|
||||
if(kb) {
|
||||
return kb->ResetInputState();
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_IME
|
||||
NSLog(@"**** ResetInputState");
|
||||
#endif
|
||||
return NS_ERROR_ABORT;
|
||||
|
||||
NSInputManager *currentIM = [NSInputManager currentInputManager];
|
||||
|
||||
// commit the current text
|
||||
[currentIM unmarkText];
|
||||
|
||||
// and clear the input manager's string
|
||||
[currentIM markedTextAbandoned:mView];
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//
|
||||
// 'open' means that it can take non-ASCII chars
|
||||
//
|
||||
NS_IMETHODIMP nsChildView::SetIMEOpenState(PRBool aState)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
//
|
||||
// 'open' means that it can take non-ASCII chars
|
||||
//
|
||||
NS_IMETHODIMP nsChildView::GetIMEOpenState(PRBool* aState)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Destruct and don't commit the IME composition string.
|
||||
//
|
||||
NS_IMETHODIMP nsChildView::CancelIMEComposition()
|
||||
{
|
||||
#ifdef DEBUG_IME
|
||||
NSLog(@"**** CancelIMEComposition\n");
|
||||
NSLog(@"**** CancelIMEComposition");
|
||||
#endif
|
||||
// Flush InputManager's markedText
|
||||
NSInputManager *currentIM = [NSInputManager currentInputManager];
|
||||
[currentIM markedTextAbandoned:mView];
|
||||
[currentIM unmarkText];
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -2633,7 +2640,8 @@ nsChildView::Idle()
|
|||
// the widget.
|
||||
mGeckoChild->DispatchMouseEvent(geckoEvent);
|
||||
|
||||
} // mouseDown
|
||||
// XXX maybe call markedTextSelectionChanged:client: here?
|
||||
}
|
||||
|
||||
|
||||
- (void)mouseUp:(NSEvent *)theEvent
|
||||
|
@ -2662,7 +2670,7 @@ nsChildView::Idle()
|
|||
// the widget.
|
||||
mGeckoChild->DispatchMouseEvent(geckoEvent);
|
||||
|
||||
} // mouseUp
|
||||
}
|
||||
|
||||
- (void)mouseMoved:(NSEvent*)theEvent
|
||||
{
|
||||
|
@ -2721,6 +2729,8 @@ nsChildView::Idle()
|
|||
// send event into Gecko by going directly to the
|
||||
// the widget.
|
||||
mGeckoChild->DispatchMouseEvent(geckoEvent);
|
||||
|
||||
// XXX maybe call markedTextSelectionChanged:client: here?
|
||||
}
|
||||
|
||||
- (void)mouseEntered:(NSEvent*)theEvent
|
||||
|
@ -2866,6 +2876,20 @@ const PRInt32 kNumLines = 4;
|
|||
return [[self superview] getContextMenu];
|
||||
}
|
||||
|
||||
- (TopLevelWindowData*)ensureWindowData
|
||||
{
|
||||
WindowDataMap* windowMap = [WindowDataMap sharedWindowDataMap];
|
||||
|
||||
TopLevelWindowData* windowData = [windowMap dataForWindow:mWindow];
|
||||
if (mWindow && !windowData)
|
||||
{
|
||||
windowData = [[TopLevelWindowData alloc] initWithWindow:mWindow];
|
||||
[windowMap setData:windowData forWindow:mWindow]; // takes ownership
|
||||
[windowData release];
|
||||
}
|
||||
return windowData;
|
||||
}
|
||||
|
||||
//
|
||||
// -convert:message:toGeckoEvent:
|
||||
//
|
||||
|
@ -2968,7 +2992,7 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac
|
|||
- (nsRect)sendCompositionEvent:(PRInt32) aEventType
|
||||
{
|
||||
#ifdef DEBUG_IME
|
||||
NSLog(@"****in sendCompositionEvent; type = %d\n", aEventType);
|
||||
NSLog(@"****in sendCompositionEvent; type = %d", aEventType);
|
||||
#endif
|
||||
|
||||
// static void init_composition_event( *aEvent, int aType)
|
||||
|
@ -2985,8 +3009,8 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac
|
|||
doCommit:(BOOL) doCommit
|
||||
{
|
||||
#ifdef DEBUG_IME
|
||||
NSLog(@"****in sendTextEvent; string = %@\n", aString);
|
||||
NSLog(@" markRange = %d, %d; selRange = %d, %d\n", markRange.location, markRange.length, selRange.location, selRange.length);
|
||||
NSLog(@"****in sendTextEvent; string = %@", aString);
|
||||
NSLog(@" markRange = %d, %d; selRange = %d, %d", markRange.location, markRange.length, selRange.location, selRange.length);
|
||||
#endif
|
||||
|
||||
nsTextEvent textEvent(PR_TRUE, NS_TEXT_TEXT, mGeckoChild);
|
||||
|
@ -3007,13 +3031,13 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac
|
|||
- (void)insertText:(id)insertString
|
||||
{
|
||||
#if DEBUG_IME
|
||||
NSLog(@"****in insertText: %@\n", insertString);
|
||||
NSLog(@" markRange = %d, %d; selRange = %d, %d\n", mMarkedRange.location, mMarkedRange.length, mSelectedRange.location, mSelectedRange.length);
|
||||
NSLog(@"****in insertText: %@", insertString);
|
||||
NSLog(@" markRange = %d, %d; selRange = %d, %d", mMarkedRange.location, mMarkedRange.length, mSelectedRange.location, mSelectedRange.length);
|
||||
#endif
|
||||
|
||||
if ( ! [insertString isKindOfClass:[NSAttributedString class]])
|
||||
insertString = [[[NSAttributedString alloc] initWithString:insertString] autorelease];
|
||||
|
||||
|
||||
NSString *tmpStr = [insertString string];
|
||||
unsigned int len = [tmpStr length];
|
||||
PRUnichar buffer[MAX_BUFFER_SIZE];
|
||||
|
@ -3078,9 +3102,9 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac
|
|||
- (void) setMarkedText:(id)aString selectedRange:(NSRange)selRange
|
||||
{
|
||||
#if DEBUG_IME
|
||||
NSLog(@"****in setMarkedText location: %d, length: %d\n", selRange.location, selRange.length);
|
||||
NSLog(@" markRange = %d, %d; selRange = %d, %d\n", mMarkedRange.location, mMarkedRange.length, mSelectedRange.location, mSelectedRange.length);
|
||||
NSLog(@" aString = %@\n", aString);
|
||||
NSLog(@"****in setMarkedText location: %d, length: %d", selRange.location, selRange.length);
|
||||
NSLog(@" markRange = %d, %d; selRange = %d, %d", mMarkedRange.location, mMarkedRange.length, mSelectedRange.location, mSelectedRange.length);
|
||||
NSLog(@" aString = %@", aString);
|
||||
#endif
|
||||
|
||||
if ( ![aString isKindOfClass:[NSAttributedString class]] )
|
||||
|
@ -3128,9 +3152,9 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac
|
|||
- (void) unmarkText
|
||||
{
|
||||
#if DEBUG_IME
|
||||
NSLog(@"****in unmarkText\n");
|
||||
NSLog(@" markedRange = %d, %d\n", mMarkedRange.location, mMarkedRange.length);
|
||||
NSLog(@" selectedRange = %d, %d\n", mSelectedRange.location, mSelectedRange.length);
|
||||
NSLog(@"****in unmarkText");
|
||||
NSLog(@" markedRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
|
||||
NSLog(@" selectedRange = %d, %d", mSelectedRange.location, mSelectedRange.length);
|
||||
#endif
|
||||
|
||||
mSelectedRange = mMarkedRange = NSMakeRange(NSNotFound, 0);
|
||||
|
@ -3142,7 +3166,7 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac
|
|||
|
||||
- (BOOL) hasMarkedText
|
||||
{
|
||||
return mMarkedRange.location != NSNotFound && mMarkedRange.length != 0;
|
||||
return (mMarkedRange.location != NSNotFound) && (mMarkedRange.length != 0);
|
||||
}
|
||||
|
||||
- (long) conversationIdentifier
|
||||
|
@ -3153,10 +3177,10 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac
|
|||
- (NSAttributedString *) attributedSubstringFromRange:(NSRange)theRange
|
||||
{
|
||||
#if DEBUG_IME
|
||||
NSLog(@"****in attributedSubstringFromRange\n");
|
||||
NSLog(@" theRange = %d, %d\n", theRange.location, theRange.length);
|
||||
NSLog(@" markedRange = %d, %d\n", mMarkedRange.location, mMarkedRange.length);
|
||||
NSLog(@" selectedRange = %d, %d\n", mSelectedRange.location, mSelectedRange.length);
|
||||
NSLog(@"****in attributedSubstringFromRange");
|
||||
NSLog(@" theRange = %d, %d", theRange.location, theRange.length);
|
||||
NSLog(@" markedRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
|
||||
NSLog(@" selectedRange = %d, %d", mSelectedRange.location, mSelectedRange.length);
|
||||
#endif
|
||||
|
||||
nsReconversionEvent reconversionEvent(PR_TRUE, NS_RECONVERSION_QUERY,
|
||||
|
@ -3178,9 +3202,9 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac
|
|||
- (NSRange) markedRange
|
||||
{
|
||||
#if DEBUG_IME
|
||||
NSLog(@"****in markedRange\n");
|
||||
NSLog(@" markedRange = %d, %d\n", mMarkedRange.location, mMarkedRange.length);
|
||||
NSLog(@" selectedRange = %d, %d\n", mSelectedRange.location, mSelectedRange.length);
|
||||
NSLog(@"****in markedRange");
|
||||
NSLog(@" markedRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
|
||||
NSLog(@" selectedRange = %d, %d", mSelectedRange.location, mSelectedRange.length);
|
||||
#endif
|
||||
|
||||
if (![self hasMarkedText]) {
|
||||
|
@ -3193,9 +3217,9 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac
|
|||
- (NSRange) selectedRange
|
||||
{
|
||||
#if DEBUG_IME
|
||||
NSLog(@"****in selectedRange\n");
|
||||
NSLog(@" markedRange = %d, %d\n", mMarkedRange.location, mMarkedRange.length);
|
||||
NSLog(@" selectedRange = %d, %d\n", mSelectedRange.location, mSelectedRange.length);
|
||||
NSLog(@"****in selectedRange");
|
||||
NSLog(@" markedRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
|
||||
NSLog(@" selectedRange = %d, %d", mSelectedRange.location, mSelectedRange.length);
|
||||
#endif
|
||||
|
||||
return mSelectedRange;
|
||||
|
@ -3205,10 +3229,10 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac
|
|||
- (NSRect) firstRectForCharacterRange:(NSRange)theRange
|
||||
{
|
||||
#if DEBUG_IME
|
||||
NSLog(@"****in firstRectForCharacterRange\n");
|
||||
NSLog(@" theRange = %d, %d\n", theRange.location, theRange.length);
|
||||
NSLog(@" markedRange = %d, %d\n", mMarkedRange.location, mMarkedRange.length);
|
||||
NSLog(@" selectedRange = %d, %d\n", mSelectedRange.location, mSelectedRange.length);
|
||||
NSLog(@"****in firstRectForCharacterRange");
|
||||
NSLog(@" theRange = %d, %d", theRange.location, theRange.length);
|
||||
NSLog(@" markedRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
|
||||
NSLog(@" selectedRange = %d, %d", mSelectedRange.location, mSelectedRange.length);
|
||||
#endif
|
||||
|
||||
#if BRADE_GETS_THIS_WORKING
|
||||
|
@ -3226,7 +3250,7 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac
|
|||
#endif
|
||||
|
||||
#if DEBUG_IME
|
||||
NSLog(@"********** cocoa rect (x, y, w, h): %f %f, %f, %f\n", temp.origin.x, temp.origin.y, temp.size.width, temp.size.height);
|
||||
NSLog(@"********** cocoa rect (x, y, w, h): %f %f, %f, %f", temp.origin.x, temp.origin.y, temp.size.width, temp.size.height);
|
||||
#endif
|
||||
return temp;
|
||||
}
|
||||
|
@ -3235,8 +3259,8 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac
|
|||
- (unsigned int)characterIndexForPoint:(NSPoint)thePoint
|
||||
{
|
||||
#if DEBUG_IME
|
||||
NSLog(@"****in characterIndexForPoint\n");
|
||||
NSLog(@" markRange = %d, %d; selectRange = %d, %d\n", mMarkedRange.location, mMarkedRange.length, mSelectedRange.location, mSelectedRange.length);
|
||||
NSLog(@"****in characterIndexForPoint");
|
||||
NSLog(@" markRange = %d, %d; selectRange = %d, %d", mMarkedRange.location, mMarkedRange.length, mSelectedRange.location, mSelectedRange.length);
|
||||
#endif
|
||||
|
||||
// short regionClass;
|
||||
|
@ -3247,8 +3271,8 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac
|
|||
- (NSArray*) validAttributesForMarkedText
|
||||
{
|
||||
#if DEBUG_IME
|
||||
NSLog(@"****in validAttributesForMarkedText\n");
|
||||
NSLog(@" markRange = %d, %d; selectRange = %d, %d\n", mMarkedRange.location, mMarkedRange.length, mSelectedRange.location, mSelectedRange.length);
|
||||
NSLog(@"****in validAttributesForMarkedText");
|
||||
NSLog(@" markRange = %d, %d; selectRange = %d, %d", mMarkedRange.location, mMarkedRange.length, mSelectedRange.location, mSelectedRange.length);
|
||||
#endif
|
||||
|
||||
return [NSArray array]; // empty array; we don't support any attributes right now
|
||||
|
@ -3408,8 +3432,8 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac
|
|||
- (BOOL)becomeFirstResponder
|
||||
{
|
||||
nsFocusEvent event(PR_TRUE, NS_GOTFOCUS, mGeckoChild);
|
||||
|
||||
mGeckoChild->DispatchWindowEvent(event);
|
||||
|
||||
return [super becomeFirstResponder];
|
||||
}
|
||||
|
||||
|
@ -3417,12 +3441,28 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac
|
|||
- (BOOL)resignFirstResponder
|
||||
{
|
||||
nsFocusEvent event(PR_TRUE, NS_LOSTFOCUS, mGeckoChild);
|
||||
|
||||
mGeckoChild->DispatchWindowEvent(event);
|
||||
|
||||
return [super resignFirstResponder];
|
||||
}
|
||||
|
||||
- (void)viewsWindowDidBecomeKey
|
||||
{
|
||||
nsFocusEvent focusEvent(PR_TRUE, NS_GOTFOCUS, mGeckoChild);
|
||||
mGeckoChild->DispatchWindowEvent(focusEvent);
|
||||
|
||||
nsFocusEvent activateEvent(PR_TRUE, NS_ACTIVATE, mGeckoChild);
|
||||
mGeckoChild->DispatchWindowEvent(activateEvent);
|
||||
|
||||
}
|
||||
|
||||
- (void)viewsWindowDidResignKey
|
||||
{
|
||||
nsFocusEvent event(PR_TRUE, NS_LOSTFOCUS, mGeckoChild);
|
||||
mGeckoChild->DispatchWindowEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// ConvertMacToRaptorKeyCode
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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):
|
||||
* Simon Fraser <smfr@smfr.org>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
//
|
||||
// WindowDataMap
|
||||
//
|
||||
// In both mozilla and embedding apps, we need to have a place to put
|
||||
// per-top-level-window logic and data, to handle such things as IME
|
||||
// commit when the window gains/loses focus. We can't use a window
|
||||
// delegate, because an embeddor probably already has one. Nor can we
|
||||
// subclass NSWindow, again because we can't impose that burden on the
|
||||
// embeddor.
|
||||
//
|
||||
// So we have a global map of NSWindow -> TopLevelWindowData, and set
|
||||
// up TopLevelWindowData as a notification observer etc.
|
||||
//
|
||||
|
||||
@interface WindowDataMap : NSObject
|
||||
{
|
||||
@private
|
||||
NSMutableDictionary* mWindowMap; // dict of TopLevelWindowData keyed by address of NSWindow
|
||||
}
|
||||
|
||||
+ (WindowDataMap*)sharedWindowDataMap;
|
||||
|
||||
- (id)dataForWindow:(NSWindow*)inWindow;
|
||||
|
||||
// set data for a given window. inData is retained (and any previously set data
|
||||
// is released).
|
||||
- (void)setData:(id)inData forWindow:(NSWindow*)inWindow;
|
||||
|
||||
// remove the data for the given window. the data is released.
|
||||
- (void)removeDataForWindow:(NSWindow*)inWindow;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
//
|
||||
// TopLevelWindowData
|
||||
//
|
||||
// Class to hold per-window data, and handle window state changes.
|
||||
//
|
||||
|
||||
@interface TopLevelWindowData : NSObject
|
||||
{
|
||||
@private
|
||||
|
||||
}
|
||||
|
||||
- (id)initWithWindow:(NSWindow*)inWindow;
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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):
|
||||
* Simon Fraser <smfr@smfr.org>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#import "nsWindowMap.h"
|
||||
|
||||
#import "nsChildView.h"
|
||||
|
||||
@interface WindowDataMap(Private)
|
||||
|
||||
- (NSString*)keyForWindow:(NSWindow*)inWindow;
|
||||
|
||||
@end
|
||||
|
||||
@interface TopLevelWindowData(Private)
|
||||
|
||||
- (void)windowResignedKey:(NSNotification*)inNotification;
|
||||
- (void)windowBecameKey:(NSNotification*)inNotification;
|
||||
- (void)windowWillClose:(NSNotification*)inNotification;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@implementation WindowDataMap
|
||||
|
||||
+ (WindowDataMap*)sharedWindowDataMap
|
||||
{
|
||||
static WindowDataMap* sWindowMap = nil;
|
||||
if (!sWindowMap)
|
||||
sWindowMap = [[WindowDataMap alloc] init];
|
||||
|
||||
return sWindowMap;
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
mWindowMap = [[NSMutableDictionary alloc] initWithCapacity:10];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[mWindowMap release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (id)dataForWindow:(NSWindow*)inWindow
|
||||
{
|
||||
return [mWindowMap objectForKey:[self keyForWindow:inWindow]];
|
||||
}
|
||||
|
||||
- (void)setData:(id)inData forWindow:(NSWindow*)inWindow
|
||||
{
|
||||
[mWindowMap setObject:inData forKey:[self keyForWindow:inWindow]];
|
||||
}
|
||||
|
||||
- (void)removeDataForWindow:(NSWindow*)inWindow
|
||||
{
|
||||
[mWindowMap removeObjectForKey:[self keyForWindow:inWindow]];
|
||||
}
|
||||
|
||||
- (NSString*)keyForWindow:(NSWindow*)inWindow
|
||||
{
|
||||
return [NSString stringWithFormat:@"%p", inWindow];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
//
|
||||
// TopLevelWindowData
|
||||
//
|
||||
// This class holds data about top-level windows. We can't use a window
|
||||
// delegate, because an embedder may already have one.
|
||||
//
|
||||
|
||||
@implementation TopLevelWindowData
|
||||
|
||||
- (id)initWithWindow:(NSWindow*)inWindow
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(windowBecameKey:)
|
||||
name:NSWindowDidBecomeKeyNotification
|
||||
object:inWindow];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(windowResignedKey:)
|
||||
name:NSWindowDidResignKeyNotification
|
||||
object:inWindow];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(windowWillClose:)
|
||||
name:NSWindowWillCloseNotification
|
||||
object:inWindow];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)windowBecameKey:(NSNotification*)inNotification
|
||||
{
|
||||
id firstResponder = [[inNotification object] firstResponder];
|
||||
if ([firstResponder isKindOfClass:[ChildView class]])
|
||||
{
|
||||
[firstResponder viewsWindowDidBecomeKey];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)windowResignedKey:(NSNotification*)inNotification
|
||||
{
|
||||
id firstResponder = [[inNotification object] firstResponder];
|
||||
if ([firstResponder isKindOfClass:[ChildView class]])
|
||||
{
|
||||
[firstResponder viewsWindowDidResignKey];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)windowWillClose:(NSNotification*)inNotification
|
||||
{
|
||||
// postpone our destruction
|
||||
[[self retain] autorelease];
|
||||
|
||||
// remove ourselves from the window map (which owns us)
|
||||
[[WindowDataMap sharedWindowDataMap] removeDataForWindow:[inNotification object]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
Загрузка…
Ссылка в новой задаче