зеркало из https://github.com/mozilla/pjs.git
Mouse-down doesn't always change focus appropriately. b=413882 r=joshmoz sr=roc
This commit is contained in:
Родитель
7bcf1c47a2
Коммит
70b9f0657b
|
@ -96,6 +96,8 @@ extern "C" {
|
|||
CG_EXTERN void CGContextResetClip(CGContextRef);
|
||||
}
|
||||
|
||||
extern PRBool gCocoaWindowMethodsSwizzled; // Defined in nsCocoaWindow.mm
|
||||
|
||||
extern nsISupportsArray *gDraggedTransferables;
|
||||
|
||||
PRBool nsTSMManager::sIsIMEEnabled = PR_TRUE;
|
||||
|
@ -391,6 +393,13 @@ nsresult nsChildView::StandardCreate(nsIWidget *aParent,
|
|||
nsWidgetInitData *aInitData,
|
||||
nsNativeWidget aNativeParent)
|
||||
{
|
||||
// See NSWindow (MethodSwizzling) in nsCocoaWindow.mm.
|
||||
if (!gCocoaWindowMethodsSwizzled) {
|
||||
nsToolkit::SwizzleMethods([NSWindow class], @selector(sendEvent:),
|
||||
@selector(nsCocoaWindow_NSWindow_sendEvent:));
|
||||
gCocoaWindowMethodsSwizzled = PR_TRUE;
|
||||
}
|
||||
|
||||
mBounds = aRect;
|
||||
|
||||
BaseCreate(aParent, aRect, aHandleEventFunction,
|
||||
|
|
|
@ -54,9 +54,12 @@
|
|||
#include "nsIPrefBranch.h"
|
||||
#include "nsToolkit.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
PRInt32 gXULModalLevel = 0;
|
||||
|
||||
PRBool gCocoaWindowMethodsSwizzled = PR_FALSE;
|
||||
|
||||
// defined in nsMenuBarX.mm
|
||||
extern NSMenu* sApplicationMenu; // Application menu shared by all menubars
|
||||
|
||||
|
@ -1750,6 +1753,42 @@ void patternDraw(void* aInfo, CGContextRef aContext)
|
|||
@end
|
||||
|
||||
|
||||
@interface NSWindow (MethodSwizzling)
|
||||
- (void)nsCocoaWindow_NSWindow_sendEvent:(NSEvent *)anEvent;
|
||||
@end
|
||||
|
||||
@implementation NSWindow (MethodSwizzling)
|
||||
|
||||
// A mouseDown event can change the focus, and (if this happens) we may need
|
||||
// to send NS_LOSTFOCUS and NS_GOTFOCUS events to Gecko. Otherwise other
|
||||
// Gecko events may be sent to the wrong nsChildView, or the "right"
|
||||
// nsChildView may not be focused. This resolves bmo bug 413882.
|
||||
// For non-embedders (e.g. Firefox and Seamonkey), it would probably only be
|
||||
// necessary to add a sendEvent: method to the ToolbarWindow class. But
|
||||
// embedders (like Camino) generally create their own NSWindows. So in order
|
||||
// to fix this problem everywhere, it's necessary to "hook" NSWindow's own
|
||||
// sendEvent: method.
|
||||
- (void)nsCocoaWindow_NSWindow_sendEvent:(NSEvent *)anEvent
|
||||
{
|
||||
NSResponder *oldFirstResponder = nil;
|
||||
NSEventType type = [anEvent type];
|
||||
if (type == NSLeftMouseDown)
|
||||
oldFirstResponder = [[self firstResponder] retain];
|
||||
[self nsCocoaWindow_NSWindow_sendEvent:anEvent];
|
||||
if (type == NSLeftMouseDown) {
|
||||
NSResponder *newFirstResponder = [self firstResponder];
|
||||
if (oldFirstResponder != newFirstResponder) {
|
||||
if ([oldFirstResponder isKindOfClass:[ChildView class]])
|
||||
[(ChildView *)oldFirstResponder sendFocusEvent:NS_LOSTFOCUS];
|
||||
if ([newFirstResponder isKindOfClass:[ChildView class]])
|
||||
[(ChildView *)newFirstResponder sendFocusEvent:NS_GOTFOCUS];
|
||||
}
|
||||
[oldFirstResponder release];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation PopupWindow
|
||||
|
||||
// The OS treats our custom popup windows very strangely -- many mouse events
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
#include "nsIToolkit.h"
|
||||
|
||||
#import <Carbon/Carbon.h>
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <objc/Object.h>
|
||||
#import <IOKit/IOKitLib.h>
|
||||
|
||||
#define MAC_OS_X_VERSION_10_4_HEX 0x00001040
|
||||
|
@ -64,6 +66,8 @@ public:
|
|||
|
||||
static void PostSleepWakeNotification(const char* aNotification);
|
||||
|
||||
static nsresult SwizzleMethods(Class aClass, SEL orgMethod, SEL posedMethod);
|
||||
|
||||
protected:
|
||||
|
||||
nsresult RegisterForSleepWakeNotifcations();
|
||||
|
|
|
@ -382,3 +382,37 @@ PRBool nsToolkit::OnLeopardOrLater()
|
|||
{
|
||||
return (OSXVersion() >= MAC_OS_X_VERSION_10_5_HEX) ? PR_TRUE : PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
// An alternative to [NSObject poseAsClass:] that isn't deprecated on OS X
|
||||
// Leopard and is available to 64-bit binaries on Leopard and above. Based on
|
||||
// ideas and code from http://www.cocoadev.com/index.pl?MethodSwizzling.
|
||||
// Since the Method type becomes an opaque type as of Objective-C 2.0, we'll
|
||||
// have to switch to using accessor methods like method_exchangeImplementations()
|
||||
// when we build 64-bit binaries that use Objective-C 2.0 (on and for Leopard
|
||||
// and above). But these accessor methods aren't available in Objective-C 1
|
||||
// (or on Tiger). So we need to access Method's members directly for (Tiger-
|
||||
// capable) binaries (32-bit or 64-bit) that use Objective-C 1 (as long as we
|
||||
// keep supporting Tiger).
|
||||
//
|
||||
// Be aware that, if aClass doesn't have an orgMethod selector but one of its
|
||||
// superclasses does, the method substitution will (in effect) take place in
|
||||
// that superclass (rather than in aClass itself). The substitution has
|
||||
// effect on the class where it takes place and all of that class's
|
||||
// subclasses. In order for method swizzling to work properly, posedMethod
|
||||
// needs to be unique in the class where the substitution takes place and all
|
||||
// of its subclasses.
|
||||
nsresult nsToolkit::SwizzleMethods(Class aClass, SEL orgMethod, SEL posedMethod)
|
||||
{
|
||||
Method original = class_getInstanceMethod(aClass, orgMethod);
|
||||
Method posed = class_getInstanceMethod(aClass, posedMethod);
|
||||
|
||||
if (!original || !posed)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
IMP aMethodImp = original->method_imp;
|
||||
original->method_imp = posed->method_imp;
|
||||
posed->method_imp = aMethodImp;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче