2006-11-22 00:48:57 +00:00
|
|
|
/* -*- Mode: objc; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2001-11-06 15:35:24 +00:00
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
2004-08-25 23:02:50 +00:00
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
2001-11-06 15:35:24 +00:00
|
|
|
*
|
2004-08-25 23:02:50 +00:00
|
|
|
* The contents of this file are subject to the Mozilla Public License
|
2001-11-06 15:35:24 +00:00
|
|
|
* 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
|
2004-08-25 23:02:50 +00:00
|
|
|
* http://www.mozilla.org/MPL/
|
2001-11-06 15:35:24 +00:00
|
|
|
*
|
|
|
|
* 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):
|
2006-04-12 17:51:32 +00:00
|
|
|
* Josh Aas <josh@mozilla.com>
|
2006-05-22 18:15:06 +00:00
|
|
|
* Mark Mentovai <mark@moxienet.com>
|
2006-09-07 18:53:59 +00:00
|
|
|
* Håkan Waara <hwaara@gmail.com>
|
2006-11-09 14:00:08 +00:00
|
|
|
* Stuart Morgan <stuart.morgan@alumni.case.edu>
|
2008-01-15 23:11:55 +00:00
|
|
|
* Mats Palmgren <mats.palmgren@bredband.net>
|
2008-12-15 20:56:29 +00:00
|
|
|
* Thomas K. Dyas <tdyas@zecador.org>
|
2001-11-06 15:35:24 +00:00
|
|
|
*
|
|
|
|
* 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
|
2004-08-25 23:02:50 +00:00
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
2001-11-06 15:35:24 +00:00
|
|
|
* 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
|
2004-08-25 23:02:50 +00:00
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
2001-11-06 15:35:24 +00:00
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
2005-06-26 03:25:52 +00:00
|
|
|
#include <unistd.h>
|
2006-09-21 16:25:01 +00:00
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
#include "nsChildView.h"
|
2007-07-17 20:29:39 +00:00
|
|
|
#include "nsCocoaWindow.h"
|
2005-06-26 03:25:52 +00:00
|
|
|
|
2008-02-20 23:47:05 +00:00
|
|
|
#include "nsObjCExceptions.h"
|
2001-11-06 15:35:24 +00:00
|
|
|
#include "nsCOMPtr.h"
|
|
|
|
#include "nsToolkit.h"
|
2002-12-13 08:43:18 +00:00
|
|
|
#include "nsCRT.h"
|
2008-02-28 15:58:33 +00:00
|
|
|
#include "nsIPrefService.h"
|
|
|
|
#include "nsIPrefBranch.h"
|
2005-06-26 03:25:52 +00:00
|
|
|
|
|
|
|
#include "nsIFontMetrics.h"
|
|
|
|
#include "nsIDeviceContext.h"
|
2003-06-17 22:54:50 +00:00
|
|
|
#include "nsIRegion.h"
|
2001-11-06 15:35:24 +00:00
|
|
|
#include "nsIRollupListener.h"
|
2007-02-12 19:38:10 +00:00
|
|
|
#include "nsIViewManager.h"
|
2004-09-20 12:51:31 +00:00
|
|
|
#include "nsIInterfaceRequestor.h"
|
2005-10-13 16:48:15 +00:00
|
|
|
#include "nsIServiceManager.h"
|
2007-07-17 02:24:05 +00:00
|
|
|
#include "nsILocalFile.h"
|
|
|
|
#include "nsILocalFileMac.h"
|
2006-11-09 22:58:11 +00:00
|
|
|
#include "nsGfxCIID.h"
|
2007-11-26 23:19:04 +00:00
|
|
|
#include "nsIMenuRollup.h"
|
2009-06-18 03:39:22 +00:00
|
|
|
#include "nsIDOMSimpleGestureEvent.h"
|
2009-06-30 05:55:05 +00:00
|
|
|
#include "nsIPluginInstance.h"
|
2006-11-09 22:58:11 +00:00
|
|
|
|
2006-10-25 22:45:22 +00:00
|
|
|
#include "nsDragService.h"
|
2009-03-18 02:04:01 +00:00
|
|
|
#include "nsClipboard.h"
|
2006-12-20 02:13:57 +00:00
|
|
|
#include "nsCursorManager.h"
|
|
|
|
#include "nsWindowMap.h"
|
2007-02-22 21:56:50 +00:00
|
|
|
#include "nsCocoaUtils.h"
|
2008-10-30 05:36:01 +00:00
|
|
|
#include "nsMenuUtilsX.h"
|
2008-01-29 06:11:06 +00:00
|
|
|
#include "nsMenuBarX.h"
|
2010-06-10 00:56:17 +00:00
|
|
|
#ifdef __LP64__
|
|
|
|
#include "ComplexTextInputPanel.h"
|
|
|
|
#endif
|
2006-11-09 22:58:11 +00:00
|
|
|
|
2006-02-22 01:31:14 +00:00
|
|
|
#include "gfxContext.h"
|
|
|
|
#include "gfxQuartzSurface.h"
|
2009-11-10 01:00:36 +00:00
|
|
|
#include "nsRegion.h"
|
2010-04-27 22:29:29 +00:00
|
|
|
#include "Layers.h"
|
|
|
|
#include "LayerManagerOGL.h"
|
2006-08-30 22:06:44 +00:00
|
|
|
|
2008-05-08 22:03:46 +00:00
|
|
|
#include <dlfcn.h>
|
|
|
|
|
2009-04-21 23:53:52 +00:00
|
|
|
#include <ApplicationServices/ApplicationServices.h>
|
|
|
|
|
2010-04-27 22:29:29 +00:00
|
|
|
using namespace mozilla::layers;
|
2006-12-20 02:13:57 +00:00
|
|
|
#undef DEBUG_IME
|
2006-08-30 22:06:44 +00:00
|
|
|
#undef DEBUG_UPDATE
|
2006-12-20 02:13:57 +00:00
|
|
|
#undef INVALIDATE_DEBUGGING // flash areas as they are invalidated
|
2006-08-30 22:06:44 +00:00
|
|
|
|
2009-02-16 01:06:52 +00:00
|
|
|
// Don't put more than this many rects in the dirty region, just fluff
|
|
|
|
// out to the bounding-box if there are more
|
|
|
|
#define MAX_RECTS_IN_REGION 100
|
|
|
|
|
2007-09-05 06:58:16 +00:00
|
|
|
#ifdef MOZ_LOGGING
|
|
|
|
#define FORCE_PR_LOG
|
|
|
|
#endif
|
|
|
|
#include "prlog.h"
|
|
|
|
|
2007-07-17 02:24:05 +00:00
|
|
|
#ifdef PR_LOGGING
|
|
|
|
PRLogModuleInfo* sCocoaLog = nsnull;
|
|
|
|
#endif
|
|
|
|
|
2006-12-20 02:13:57 +00:00
|
|
|
extern "C" {
|
|
|
|
CG_EXTERN void CGContextResetCTM(CGContextRef);
|
|
|
|
CG_EXTERN void CGContextSetCTM(CGContextRef, CGAffineTransform);
|
|
|
|
CG_EXTERN void CGContextResetClip(CGContextRef);
|
2009-12-30 15:18:36 +00:00
|
|
|
|
|
|
|
// CGSPrivate.h
|
|
|
|
typedef NSInteger CGSConnection;
|
|
|
|
typedef NSInteger CGSWindow;
|
|
|
|
extern CGSConnection _CGSDefaultConnection();
|
|
|
|
extern CGError CGSGetScreenRectForWindow(const CGSConnection cid, CGSWindow wid, CGRect *outRect);
|
|
|
|
extern CGError CGSGetWindowLevel(const CGSConnection cid, CGSWindow wid, CGWindowLevel *level);
|
2006-12-20 02:13:57 +00:00
|
|
|
}
|
2006-09-11 15:47:35 +00:00
|
|
|
|
2009-05-14 20:13:22 +00:00
|
|
|
// these are defined in nsCocoaWindow.mm
|
|
|
|
extern PRBool gConsumeRollupEvent;
|
2008-02-13 15:57:12 +00:00
|
|
|
|
2009-02-06 17:36:04 +00:00
|
|
|
PRBool gChildViewMethodsSwizzled = PR_FALSE;
|
|
|
|
|
2007-07-17 23:02:40 +00:00
|
|
|
extern nsISupportsArray *gDraggedTransferables;
|
|
|
|
|
2009-09-23 02:31:37 +00:00
|
|
|
ChildView* ChildViewMouseTracker::sLastMouseEventView = nil;
|
2007-04-15 13:43:55 +00:00
|
|
|
|
2006-12-20 02:13:57 +00:00
|
|
|
static NS_DEFINE_CID(kRegionCID, NS_REGION_CID);
|
|
|
|
#ifdef INVALIDATE_DEBUGGING
|
|
|
|
static void blinkRect(Rect* r);
|
|
|
|
static void blinkRgn(RgnHandle rgn);
|
2006-09-11 15:47:35 +00:00
|
|
|
#endif
|
|
|
|
|
2006-12-20 02:13:57 +00:00
|
|
|
nsIRollupListener * gRollupListener = nsnull;
|
2009-12-22 23:49:33 +00:00
|
|
|
nsIMenuRollup * gMenuRollup = nsnull;
|
2006-12-20 02:13:57 +00:00
|
|
|
nsIWidget * gRollupWidget = nsnull;
|
2006-03-29 18:51:35 +00:00
|
|
|
|
2008-12-16 16:50:19 +00:00
|
|
|
PRUint32 gLastModifierState = 0;
|
|
|
|
|
2009-02-17 15:51:12 +00:00
|
|
|
PRBool gUserCancelledDrag = PR_FALSE;
|
2005-02-08 17:34:09 +00:00
|
|
|
|
2009-04-21 23:53:52 +00:00
|
|
|
PRUint32 nsChildView::sLastInputEventCount = 0;
|
|
|
|
|
2002-12-13 08:43:18 +00:00
|
|
|
@interface ChildView(Private)
|
|
|
|
|
2006-12-20 02:13:57 +00:00
|
|
|
// sets up our view, attaching it to its owning gecko view
|
2007-10-09 18:46:30 +00:00
|
|
|
- (id)initWithFrame:(NSRect)inFrame geckoChild:(nsChildView*)inChild;
|
2005-09-30 00:59:29 +00:00
|
|
|
|
2002-12-13 08:43:18 +00:00
|
|
|
// sends gecko an ime composition event
|
2010-04-10 09:24:35 +00:00
|
|
|
- (void) sendCompositionEvent:(PRInt32)aEventType;
|
2002-12-13 08:43:18 +00:00
|
|
|
|
|
|
|
// sends gecko an ime text event
|
|
|
|
- (void) sendTextEvent:(PRUnichar*) aBuffer
|
|
|
|
attributedString:(NSAttributedString*) aString
|
|
|
|
selectedRange:(NSRange)selRange
|
|
|
|
markedRange:(NSRange)markRange
|
|
|
|
doCommit:(BOOL)doCommit;
|
|
|
|
|
2007-06-12 20:28:26 +00:00
|
|
|
// do generic gecko event setup with a generic cocoa event. accepts nil inEvent.
|
|
|
|
- (void) convertGenericCocoaEvent:(NSEvent*)inEvent toGeckoEvent:(nsInputEvent*)outGeckoEvent;
|
2002-12-13 08:43:18 +00:00
|
|
|
|
2007-06-12 20:28:26 +00:00
|
|
|
// set up a gecko mouse event based on a cocoa mouse event
|
|
|
|
- (void) convertCocoaMouseEvent:(NSEvent*)aMouseEvent toGeckoEvent:(nsInputEvent*)outGeckoEvent;
|
|
|
|
|
|
|
|
// set up a gecko key event based on a cocoa key event
|
|
|
|
- (void) convertCocoaKeyEvent:(NSEvent*)aKeyEvent toGeckoEvent:(nsKeyEvent*)outGeckoEvent;
|
2002-12-13 08:43:18 +00:00
|
|
|
|
2006-07-30 22:55:37 +00:00
|
|
|
- (NSMenu*)contextMenu;
|
2002-12-13 08:43:18 +00:00
|
|
|
|
|
|
|
- (void)setIsPluginView:(BOOL)aIsPlugin;
|
2007-03-27 01:07:57 +00:00
|
|
|
- (BOOL)isPluginView;
|
2009-09-01 01:00:13 +00:00
|
|
|
- (void)setPluginEventModel:(NPEventModel)eventModel;
|
|
|
|
- (NPEventModel)pluginEventModel;
|
2002-12-13 08:43:18 +00:00
|
|
|
|
2005-07-15 20:53:13 +00:00
|
|
|
- (BOOL)isRectObscuredBySubview:(NSRect)inRect;
|
2005-03-30 04:05:54 +00:00
|
|
|
|
2006-11-09 14:00:08 +00:00
|
|
|
- (void)processPendingRedraws;
|
|
|
|
|
2008-05-05 23:01:07 +00:00
|
|
|
- (PRBool)processKeyDownEvent:(NSEvent*)theEvent keyEquiv:(BOOL)isKeyEquiv;
|
|
|
|
|
2007-07-17 20:29:39 +00:00
|
|
|
- (void)maybeInitContextMenuTracking;
|
|
|
|
|
2008-05-05 23:01:07 +00:00
|
|
|
+ (NSEvent*)makeNewCocoaEventWithType:(NSEventType)type fromEvent:(NSEvent*)theEvent;
|
|
|
|
|
2010-03-01 08:03:49 +00:00
|
|
|
- (BOOL)beginMaybeResetUnifiedToolbar:(nsIntRegion*)aRegion context:(CGContextRef)aContext;
|
2010-01-13 16:08:06 +00:00
|
|
|
- (void)endMaybeResetUnifiedToolbar:(BOOL)aReset;
|
|
|
|
|
2004-02-18 16:18:38 +00:00
|
|
|
#if USE_CLICK_HOLD_CONTEXTMENU
|
2004-01-15 19:01:49 +00:00
|
|
|
// 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;
|
2004-02-18 16:18:38 +00:00
|
|
|
#endif
|
2004-01-15 19:01:49 +00:00
|
|
|
|
2006-09-11 15:47:35 +00:00
|
|
|
#ifdef ACCESSIBILITY
|
|
|
|
- (id<mozAccessible>)accessible;
|
|
|
|
#endif
|
|
|
|
|
2008-10-13 18:07:27 +00:00
|
|
|
- (BOOL)isFirstResponder;
|
|
|
|
|
2010-03-08 12:35:25 +00:00
|
|
|
- (BOOL)isDragInProgress;
|
|
|
|
|
2008-10-13 18:07:27 +00:00
|
|
|
- (void)fireKeyEventForFlagsChanged:(NSEvent*)theEvent keyDown:(BOOL)isKeyDown;
|
|
|
|
|
2002-12-13 08:43:18 +00:00
|
|
|
@end
|
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
#pragma mark -
|
|
|
|
|
2008-10-16 03:04:39 +00:00
|
|
|
// Key code constants
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
kEscapeKeyCode = 0x35,
|
|
|
|
kRCommandKeyCode = 0x36, // right command key
|
|
|
|
kCommandKeyCode = 0x37,
|
|
|
|
kShiftKeyCode = 0x38,
|
|
|
|
kCapsLockKeyCode = 0x39,
|
|
|
|
kOptionkeyCode = 0x3A,
|
|
|
|
kControlKeyCode = 0x3B,
|
|
|
|
kRShiftKeyCode = 0x3C, // right shift key
|
|
|
|
kROptionKeyCode = 0x3D, // right option key
|
|
|
|
kRControlKeyCode = 0x3E, // right control key
|
|
|
|
kClearKeyCode = 0x47,
|
|
|
|
|
|
|
|
// function keys
|
|
|
|
kF1KeyCode = 0x7A,
|
|
|
|
kF2KeyCode = 0x78,
|
|
|
|
kF3KeyCode = 0x63,
|
|
|
|
kF4KeyCode = 0x76,
|
|
|
|
kF5KeyCode = 0x60,
|
|
|
|
kF6KeyCode = 0x61,
|
|
|
|
kF7KeyCode = 0x62,
|
|
|
|
kF8KeyCode = 0x64,
|
|
|
|
kF9KeyCode = 0x65,
|
|
|
|
kF10KeyCode = 0x6D,
|
|
|
|
kF11KeyCode = 0x67,
|
|
|
|
kF12KeyCode = 0x6F,
|
|
|
|
kF13KeyCode = 0x69,
|
|
|
|
kF14KeyCode = 0x6B,
|
|
|
|
kF15KeyCode = 0x71,
|
|
|
|
|
|
|
|
kPrintScreenKeyCode = kF13KeyCode,
|
|
|
|
kScrollLockKeyCode = kF14KeyCode,
|
|
|
|
kPauseKeyCode = kF15KeyCode,
|
|
|
|
|
|
|
|
// keypad
|
|
|
|
kKeypad0KeyCode = 0x52,
|
|
|
|
kKeypad1KeyCode = 0x53,
|
|
|
|
kKeypad2KeyCode = 0x54,
|
|
|
|
kKeypad3KeyCode = 0x55,
|
|
|
|
kKeypad4KeyCode = 0x56,
|
|
|
|
kKeypad5KeyCode = 0x57,
|
|
|
|
kKeypad6KeyCode = 0x58,
|
|
|
|
kKeypad7KeyCode = 0x59,
|
|
|
|
kKeypad8KeyCode = 0x5B,
|
|
|
|
kKeypad9KeyCode = 0x5C,
|
|
|
|
|
|
|
|
kKeypadMultiplyKeyCode = 0x43,
|
|
|
|
kKeypadAddKeyCode = 0x45,
|
|
|
|
kKeypadSubtractKeyCode = 0x4E,
|
|
|
|
kKeypadDecimalKeyCode = 0x41,
|
|
|
|
kKeypadDivideKeyCode = 0x4B,
|
|
|
|
kKeypadEqualsKeyCode = 0x51, // no correpsonding gecko key code
|
|
|
|
kEnterKeyCode = 0x4C,
|
|
|
|
kReturnKeyCode = 0x24,
|
|
|
|
kPowerbookEnterKeyCode = 0x34, // Enter on Powerbook's keyboard is different
|
|
|
|
|
|
|
|
kInsertKeyCode = 0x72, // also help key
|
|
|
|
kDeleteKeyCode = 0x75, // also forward delete key
|
|
|
|
kTabKeyCode = 0x30,
|
|
|
|
kTildeKeyCode = 0x32,
|
|
|
|
kBackspaceKeyCode = 0x33,
|
|
|
|
kHomeKeyCode = 0x73,
|
|
|
|
kEndKeyCode = 0x77,
|
|
|
|
kPageUpKeyCode = 0x74,
|
|
|
|
kPageDownKeyCode = 0x79,
|
|
|
|
kLeftArrowKeyCode = 0x7B,
|
|
|
|
kRightArrowKeyCode = 0x7C,
|
|
|
|
kUpArrowKeyCode = 0x7E,
|
|
|
|
kDownArrowKeyCode = 0x7D
|
|
|
|
};
|
|
|
|
|
2006-03-10 20:51:48 +00:00
|
|
|
/* Convenience routines to go from a gecko rect to cocoa NSRects and back
|
|
|
|
*
|
|
|
|
* Gecko rects (nsRect) contain an origin (x,y) in a coordinate
|
|
|
|
* system with (0,0) in the top-left of the screen. Cocoa rects
|
|
|
|
* (NSRect) contain an origin (x,y) in a coordinate system with
|
|
|
|
* (0,0) in the bottom-left of the screen. Both nsRect and NSRect
|
|
|
|
* contain width/height info, with no difference in their use.
|
|
|
|
* If a Cocoa rect is from a flipped view, there is no need to
|
|
|
|
* convert coordinate systems.
|
|
|
|
*/
|
|
|
|
|
2002-12-13 08:43:18 +00:00
|
|
|
static inline void
|
2009-01-15 03:27:09 +00:00
|
|
|
GeckoRectToNSRect(const nsIntRect & inGeckoRect, NSRect & outCocoaRect)
|
2001-11-06 15:35:24 +00:00
|
|
|
{
|
|
|
|
outCocoaRect.origin.x = inGeckoRect.x;
|
|
|
|
outCocoaRect.origin.y = inGeckoRect.y;
|
|
|
|
outCocoaRect.size.width = inGeckoRect.width;
|
|
|
|
outCocoaRect.size.height = inGeckoRect.height;
|
|
|
|
}
|
|
|
|
|
2002-12-13 08:43:18 +00:00
|
|
|
static inline void
|
2009-01-15 03:27:09 +00:00
|
|
|
NSRectToGeckoRect(const NSRect & inCocoaRect, nsIntRect & outGeckoRect)
|
2001-11-06 15:35:24 +00:00
|
|
|
{
|
2009-01-15 03:27:09 +00:00
|
|
|
outGeckoRect.x = NSToIntRound(inCocoaRect.origin.x);
|
|
|
|
outGeckoRect.y = NSToIntRound(inCocoaRect.origin.y);
|
|
|
|
outGeckoRect.width = NSToIntRound(inCocoaRect.origin.x + inCocoaRect.size.width) - outGeckoRect.x;
|
|
|
|
outGeckoRect.height = NSToIntRound(inCocoaRect.origin.y + inCocoaRect.size.height) - outGeckoRect.y;
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
2002-12-13 08:43:18 +00:00
|
|
|
static inline void
|
2009-01-15 03:27:09 +00:00
|
|
|
ConvertGeckoRectToMacRect(const nsIntRect& aRect, Rect& outMacRect)
|
2001-11-06 15:35:24 +00:00
|
|
|
{
|
|
|
|
outMacRect.left = aRect.x;
|
|
|
|
outMacRect.top = aRect.y;
|
|
|
|
outMacRect.right = aRect.x + aRect.width;
|
|
|
|
outMacRect.bottom = aRect.y + aRect.height;
|
|
|
|
}
|
|
|
|
|
2006-09-07 18:53:59 +00:00
|
|
|
// Flips a screen coordinate from a point in the cocoa coordinate system (bottom-left rect) to a point
|
|
|
|
// that is a "flipped" cocoa coordinate system (starts in the top-left).
|
|
|
|
static inline void
|
2009-06-19 16:15:23 +00:00
|
|
|
FlipCocoaScreenCoordinate(NSPoint &inPoint)
|
2007-02-22 21:56:50 +00:00
|
|
|
{
|
2007-12-05 23:17:08 +00:00
|
|
|
inPoint.y = nsCocoaUtils::FlippedScreenY(inPoint.y);
|
2006-09-07 18:53:59 +00:00
|
|
|
}
|
|
|
|
|
2009-08-27 00:29:47 +00:00
|
|
|
static void
|
|
|
|
InitNPCocoaEvent(NPCocoaEvent* event)
|
|
|
|
{
|
|
|
|
memset(event, 0, sizeof(NPCocoaEvent));
|
|
|
|
}
|
|
|
|
|
2005-02-03 07:15:55 +00:00
|
|
|
static PRUint32
|
|
|
|
UnderlineAttributeToTextRangeType(PRUint32 aUnderlineStyle, NSRange selRange)
|
2002-12-13 08:43:18 +00:00
|
|
|
{
|
|
|
|
#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
|
|
|
|
//
|
2008-10-08 05:18:07 +00:00
|
|
|
// It probably means show 1-pixel thickness underline vs 2-pixel thickness.
|
2005-02-03 07:15:55 +00:00
|
|
|
|
|
|
|
PRUint32 attr;
|
|
|
|
if (selRange.length == 0) {
|
|
|
|
switch (aUnderlineStyle) {
|
|
|
|
case 1:
|
|
|
|
attr = NS_TEXTRANGE_RAWINPUT;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
default:
|
|
|
|
attr = NS_TEXTRANGE_SELECTEDRAWTEXT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
switch (aUnderlineStyle) {
|
|
|
|
case 1:
|
|
|
|
attr = NS_TEXTRANGE_CONVERTEDTEXT;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
default:
|
|
|
|
attr = NS_TEXTRANGE_SELECTEDCONVERTEDTEXT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return attr;
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
|
|
|
|
2005-02-03 07:15:55 +00:00
|
|
|
static PRUint32
|
|
|
|
CountRanges(NSAttributedString *aString)
|
2002-12-13 08:43:18 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
|
|
|
|
2002-12-13 08:43:18 +00:00
|
|
|
// 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
|
2006-12-20 02:13:57 +00:00
|
|
|
atIndex:limitRange.location
|
|
|
|
longestEffectiveRange:&effectiveRange
|
|
|
|
inRange:limitRange];
|
2002-12-13 08:43:18 +00:00
|
|
|
limitRange = NSMakeRange(NSMaxRange(effectiveRange),
|
|
|
|
NSMaxRange(limitRange) - NSMaxRange(effectiveRange));
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
return count;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0);
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
|
|
|
|
2005-02-03 07:15:55 +00:00
|
|
|
static void
|
|
|
|
ConvertAttributeToGeckoRange(NSAttributedString *aString, NSRange markRange, NSRange selRange, PRUint32 inCount, nsTextRange* aRanges)
|
2002-12-13 08:43:18 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2002-12-13 08:43:18 +00:00
|
|
|
// 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);
|
2005-02-03 07:15:55 +00:00
|
|
|
aRanges[i].mRangeType = UnderlineAttributeToTextRangeType([attributeValue intValue], selRange);
|
2002-12-13 08:43:18 +00:00
|
|
|
limitRange = NSMakeRange(NSMaxRange(effectiveRange),
|
|
|
|
NSMaxRange(limitRange) - NSMaxRange(effectiveRange));
|
|
|
|
i++;
|
|
|
|
}
|
2004-12-23 17:59:53 +00:00
|
|
|
// Get current caret position.
|
|
|
|
// Caret is indicator of insertion point, so mEndOffset = 0.
|
|
|
|
aRanges[i].mStartOffset = selRange.location + selRange.length;
|
|
|
|
aRanges[i].mEndOffset = 0;
|
|
|
|
aRanges[i].mRangeType = NS_TEXTRANGE_CARETPOSITION;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
|
|
|
|
2005-02-03 07:15:55 +00:00
|
|
|
static void
|
|
|
|
FillTextRangeInTextEvent(nsTextEvent *aTextEvent, NSAttributedString* aString, NSRange markRange, NSRange selRange)
|
2008-02-20 23:47:05 +00:00
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2004-12-23 17:59:53 +00:00
|
|
|
// Count the number of segments in the attributed string and add one more count for sending current caret position to Gecko.
|
|
|
|
// Allocate the right size of nsTextRange and draw caret at right position.
|
|
|
|
// Convert the attributed string into an array of nsTextRange and get current caret position by calling above functions.
|
2005-02-03 07:15:55 +00:00
|
|
|
PRUint32 count = CountRanges(aString) + 1;
|
2002-12-13 08:43:18 +00:00
|
|
|
aTextEvent->rangeArray = new nsTextRange[count];
|
2008-02-20 23:47:05 +00:00
|
|
|
if (aTextEvent->rangeArray) {
|
2002-12-13 08:43:18 +00:00
|
|
|
aTextEvent->rangeCount = count;
|
2005-02-03 07:15:55 +00:00
|
|
|
ConvertAttributeToGeckoRange(aString, markRange, selRange, aTextEvent->rangeCount, aTextEvent->rangeArray);
|
2008-02-20 23:47:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
2001-11-06 15:35:24 +00:00
|
|
|
|
2009-09-21 13:24:57 +00:00
|
|
|
#if defined(DEBUG) && defined(PR_LOGGING)
|
|
|
|
|
|
|
|
static void DebugPrintAllKeyboardLayouts()
|
|
|
|
{
|
2009-10-01 02:52:50 +00:00
|
|
|
nsCocoaTextInputHandler::DebugPrintAllKeyboardLayouts(sCocoaLog);
|
|
|
|
nsCocoaIMEHandler::DebugPrintAllIMEModes(sCocoaLog);
|
2009-09-21 13:24:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif // defined(DEBUG) && defined(PR_LOGGING)
|
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
#pragma mark -
|
|
|
|
|
2003-04-21 22:24:12 +00:00
|
|
|
nsChildView::nsChildView() : nsBaseWidget()
|
2002-12-13 08:43:18 +00:00
|
|
|
, mView(nsnull)
|
|
|
|
, mParentView(nsnull)
|
|
|
|
, mParentWidget(nsnull)
|
|
|
|
, mVisible(PR_FALSE)
|
|
|
|
, mDrawing(PR_FALSE)
|
|
|
|
, mPluginDrawing(PR_FALSE)
|
2007-03-27 01:07:57 +00:00
|
|
|
, mPluginIsCG(PR_FALSE)
|
2010-03-20 15:05:47 +00:00
|
|
|
, mPluginInstanceOwner(nsnull)
|
2001-11-06 15:35:24 +00:00
|
|
|
{
|
2007-07-17 02:24:05 +00:00
|
|
|
#ifdef PR_LOGGING
|
2008-05-08 22:41:13 +00:00
|
|
|
if (!sCocoaLog) {
|
2007-07-17 02:24:05 +00:00
|
|
|
sCocoaLog = PR_NewLogModule("nsCocoaWidgets");
|
2009-09-21 13:24:57 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
DebugPrintAllKeyboardLayouts();
|
|
|
|
#endif // DEBUG
|
2008-05-08 22:41:13 +00:00
|
|
|
}
|
2009-09-08 05:38:42 +00:00
|
|
|
#endif // PR_LOGGING
|
2007-07-17 02:24:05 +00:00
|
|
|
|
2010-03-25 19:36:44 +00:00
|
|
|
memset(&mPluginCGContext, 0, sizeof(mPluginCGContext));
|
|
|
|
memset(&mPluginQDPort, 0, sizeof(mPluginQDPort));
|
|
|
|
|
2007-09-05 06:58:16 +00:00
|
|
|
SetBackgroundColor(NS_RGB(255, 255, 255));
|
|
|
|
SetForegroundColor(NS_RGB(0, 0, 0));
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsChildView::~nsChildView()
|
|
|
|
{
|
2009-07-20 15:02:31 +00:00
|
|
|
// Notify the children that we're gone. childView->ResetParent() can change
|
|
|
|
// our list of children while it's being iterated, so the way we iterate the
|
|
|
|
// list must allow for this.
|
|
|
|
for (nsIWidget* kid = mLastChild; kid;) {
|
2007-07-08 07:08:04 +00:00
|
|
|
nsChildView* childView = static_cast<nsChildView*>(kid);
|
2009-07-20 15:02:31 +00:00
|
|
|
kid = kid->GetPrevSibling();
|
2009-04-23 15:54:50 +00:00
|
|
|
childView->ResetParent();
|
2005-07-08 17:55:32 +00:00
|
|
|
}
|
|
|
|
|
2008-06-27 17:11:24 +00:00
|
|
|
NS_WARN_IF_FALSE(mOnDestroyCalled, "nsChildView object destroyed without calling Destroy()");
|
|
|
|
|
|
|
|
// An nsChildView object that was in use can be destroyed without Destroy()
|
|
|
|
// ever being called on it. So we also need to do a quick, safe cleanup
|
|
|
|
// here (it's too late to just call Destroy(), which can cause crashes).
|
|
|
|
// It's particularly important to make sure widgetDestroyed is called on our
|
|
|
|
// mView -- this method NULLs mView's mGeckoChild, and NULL checks on
|
|
|
|
// mGeckoChild are used throughout the ChildView class to tell if it's safe
|
|
|
|
// to use a ChildView object.
|
|
|
|
[mView widgetDestroyed]; // Safe if mView is nil.
|
|
|
|
mParentWidget = nil;
|
|
|
|
TearDownView(); // Safe if called twice.
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
2008-07-14 02:56:18 +00:00
|
|
|
NS_IMPL_ISUPPORTS_INHERITED1(nsChildView, nsBaseWidget, nsIPluginWidget)
|
2001-11-06 15:35:24 +00:00
|
|
|
|
2009-09-24 06:18:10 +00:00
|
|
|
nsresult nsChildView::Create(nsIWidget *aParent,
|
|
|
|
nsNativeWidget aNativeParent,
|
|
|
|
const nsIntRect &aRect,
|
|
|
|
EVENT_CALLBACK aHandleEventFunction,
|
|
|
|
nsIDeviceContext *aContext,
|
|
|
|
nsIAppShell *aAppShell,
|
|
|
|
nsIToolkit *aToolkit,
|
|
|
|
nsWidgetInitData *aInitData)
|
2001-11-06 15:35:24 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2010-04-13 20:36:03 +00:00
|
|
|
// Because the hidden window is created outside of an event loop,
|
|
|
|
// we need to provide an autorelease pool to avoid leaking cocoa objects
|
|
|
|
// (see bug 559075).
|
|
|
|
nsAutoreleasePool localPool;
|
|
|
|
|
2009-02-06 17:36:04 +00:00
|
|
|
// See NSView (MethodSwizzling) below.
|
2010-02-23 20:10:25 +00:00
|
|
|
if (!gChildViewMethodsSwizzled) {
|
2009-02-06 17:36:04 +00:00
|
|
|
nsToolkit::SwizzleMethods([NSView class], @selector(mouseDownCanMoveWindow),
|
|
|
|
@selector(nsChildView_NSView_mouseDownCanMoveWindow));
|
|
|
|
gChildViewMethodsSwizzled = PR_TRUE;
|
|
|
|
}
|
2008-02-13 15:57:12 +00:00
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
mBounds = aRect;
|
|
|
|
|
|
|
|
BaseCreate(aParent, aRect, aHandleEventFunction,
|
2009-09-24 06:18:10 +00:00
|
|
|
aContext, aAppShell, aToolkit, aInitData);
|
2001-11-06 15:35:24 +00:00
|
|
|
|
|
|
|
// inherit things from the parent view and create our parallel
|
|
|
|
// NSView in the Cocoa display system
|
2002-02-12 08:30:01 +00:00
|
|
|
mParentView = nil;
|
2006-11-20 05:37:49 +00:00
|
|
|
if (aParent) {
|
2009-09-24 06:18:10 +00:00
|
|
|
// This is the case when we're the popup content view of a popup window.
|
2001-11-08 21:47:44 +00:00
|
|
|
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).
|
2002-12-13 08:43:18 +00:00
|
|
|
mParentView = (NSView*)aParent->GetNativeData(NS_NATIVE_WIDGET);
|
|
|
|
mParentWidget = aParent;
|
2009-09-24 06:18:10 +00:00
|
|
|
} else {
|
|
|
|
// This is the normal case. When we're the root widget of the view hiararchy,
|
|
|
|
// aNativeParent will be the contentView of our window, since that's what
|
|
|
|
// nsCocoaWindow returns when asked for an NS_NATIVE_VIEW.
|
2007-07-08 07:08:04 +00:00
|
|
|
mParentView = reinterpret_cast<NSView*>(aNativeParent);
|
2009-09-24 06:18:10 +00:00
|
|
|
}
|
2001-11-08 21:47:44 +00:00
|
|
|
|
|
|
|
// create our parallel NSView and hook it up to our parent. Recall
|
|
|
|
// that NS_NATIVE_WIDGET is the NSView.
|
|
|
|
NSRect r;
|
2006-09-07 18:53:59 +00:00
|
|
|
GeckoRectToNSRect(mBounds, r);
|
2005-06-29 19:39:39 +00:00
|
|
|
mView = [CreateCocoaView(r) retain];
|
2002-12-13 08:43:18 +00:00
|
|
|
if (!mView) return NS_ERROR_FAILURE;
|
|
|
|
|
2010-01-24 06:00:39 +00:00
|
|
|
[(ChildView*)mView setIsPluginView:(mWindowType == eWindowType_plugin)];
|
|
|
|
|
2006-05-22 18:15:06 +00:00
|
|
|
// If this view was created in a Gecko view hierarchy, the initial state
|
|
|
|
// is hidden. If the view is attached only to a native NSView but has
|
|
|
|
// no Gecko parent (as in embedding), the initial state is visible.
|
|
|
|
if (mParentWidget)
|
|
|
|
[mView setHidden:YES];
|
|
|
|
else
|
|
|
|
mVisible = PR_TRUE;
|
2002-12-13 08:43:18 +00:00
|
|
|
|
2006-05-22 18:15:06 +00:00
|
|
|
// Hook it up in the NSView hierarchy.
|
|
|
|
if (mParentView) {
|
|
|
|
[mParentView addSubview:mView];
|
2001-11-08 21:47:44 +00:00
|
|
|
}
|
2006-05-22 18:15:06 +00:00
|
|
|
|
2005-06-26 03:25:52 +00:00
|
|
|
// if this is a ChildView, make sure that our per-window data
|
|
|
|
// is set up
|
|
|
|
if ([mView isKindOfClass:[ChildView class]])
|
2009-06-17 18:13:12 +00:00
|
|
|
[[WindowDataMap sharedWindowDataMap] ensureDataForWindow:[mView window]];
|
2005-06-26 03:25:52 +00:00
|
|
|
|
2009-10-01 02:52:50 +00:00
|
|
|
mTextInputHandler.Init(this);
|
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
return NS_OK;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
2001-11-14 22:29:25 +00:00
|
|
|
// Creates the appropriate child view. Override to create something other than
|
|
|
|
// our |ChildView| object. Autoreleases, so caller must retain.
|
|
|
|
NSView*
|
2005-06-29 19:39:39 +00:00
|
|
|
nsChildView::CreateCocoaView(NSRect inFrame)
|
2001-11-14 22:29:25 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
|
|
|
|
2007-10-09 18:46:30 +00:00
|
|
|
return [[[ChildView alloc] initWithFrame:inFrame geckoChild:this] autorelease];
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
2001-11-14 22:29:25 +00:00
|
|
|
}
|
|
|
|
|
2004-02-24 03:40:27 +00:00
|
|
|
void nsChildView::TearDownView()
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2006-10-19 23:19:50 +00:00
|
|
|
if (!mView)
|
|
|
|
return;
|
2004-02-24 03:40:27 +00:00
|
|
|
|
2006-10-19 23:19:50 +00:00
|
|
|
NSWindow* win = [mView window];
|
|
|
|
NSResponder* responder = [win firstResponder];
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
|
2006-10-19 23:19:50 +00:00
|
|
|
// We're being unhooked from the view hierarchy, don't leave our view
|
|
|
|
// or a child view as the window first responder.
|
|
|
|
if (responder && [responder isKindOfClass:[NSView class]] &&
|
|
|
|
[(NSView*)responder isDescendantOf:mView]) {
|
2008-01-15 23:11:55 +00:00
|
|
|
[win makeFirstResponder:[mView superview]];
|
2004-02-24 03:40:27 +00:00
|
|
|
}
|
2007-05-30 18:25:44 +00:00
|
|
|
|
|
|
|
// If mView is win's contentView, win (mView's NSWindow) "owns" mView --
|
|
|
|
// win has retained mView, and will detach it from the view hierarchy and
|
|
|
|
// release it when necessary (when win is itself destroyed (in a call to
|
|
|
|
// [win dealloc])). So all we need to do here is call [mView release] (to
|
|
|
|
// match the call to [mView retain] in nsChildView::StandardCreate()).
|
|
|
|
// Also calling [mView removeFromSuperviewWithoutNeedingDisplay] causes
|
|
|
|
// mView to be released again and dealloced, while remaining win's
|
|
|
|
// contentView. So if we do that here, win will (for a short while) have
|
|
|
|
// an invalid contentView (for the consequences see bmo bugs 381087 and
|
|
|
|
// 374260).
|
|
|
|
if ([mView isEqual:[win contentView]]) {
|
|
|
|
[mView release];
|
|
|
|
} else {
|
|
|
|
// Stop NSView hierarchy being changed during [ChildView drawRect:]
|
|
|
|
[mView performSelectorOnMainThread:@selector(delayedTearDown) withObject:nil waitUntilDone:false];
|
|
|
|
}
|
2006-10-19 23:19:50 +00:00
|
|
|
mView = nil;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2004-02-24 03:40:27 +00:00
|
|
|
}
|
2001-11-14 22:29:25 +00:00
|
|
|
|
2009-08-13 22:06:49 +00:00
|
|
|
nsCocoaWindow*
|
|
|
|
nsChildView::GetXULWindowWidget()
|
|
|
|
{
|
2009-09-15 21:56:44 +00:00
|
|
|
id windowDelegate = [[mView window] delegate];
|
2009-08-13 22:06:49 +00:00
|
|
|
if (windowDelegate && [windowDelegate isKindOfClass:[WindowDelegate class]]) {
|
|
|
|
return [(WindowDelegate *)windowDelegate geckoWidget];
|
|
|
|
}
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
NS_IMETHODIMP nsChildView::Destroy()
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2006-01-24 04:01:54 +00:00
|
|
|
if (mOnDestroyCalled)
|
2001-11-06 15:35:24 +00:00
|
|
|
return NS_OK;
|
2006-01-24 04:01:54 +00:00
|
|
|
mOnDestroyCalled = PR_TRUE;
|
2001-11-06 15:35:24 +00:00
|
|
|
|
2005-09-30 00:59:29 +00:00
|
|
|
[mView widgetDestroyed];
|
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
nsBaseWidget::Destroy();
|
|
|
|
|
2008-01-15 23:11:55 +00:00
|
|
|
ReportDestroyEvent();
|
2002-12-13 08:43:18 +00:00
|
|
|
mParentWidget = nil;
|
2001-11-06 15:35:24 +00:00
|
|
|
|
2004-02-24 03:40:27 +00:00
|
|
|
TearDownView();
|
|
|
|
|
2009-03-09 16:59:29 +00:00
|
|
|
nsBaseWidget::OnDestroy();
|
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
return NS_OK;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark -
|
2001-11-08 21:47:44 +00:00
|
|
|
|
2006-06-29 01:33:57 +00:00
|
|
|
#if 0
|
2006-12-06 17:04:13 +00:00
|
|
|
static void PrintViewHierarchy(NSView *view)
|
2002-12-13 08:43:18 +00:00
|
|
|
{
|
2006-10-19 23:19:50 +00:00
|
|
|
while (view) {
|
2006-12-06 17:04:13 +00:00
|
|
|
NSLog(@" view is %x, frame %@", view, NSStringFromRect([view frame]));
|
2005-06-27 23:44:09 +00:00
|
|
|
view = [view superview];
|
|
|
|
}
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-12-20 02:13:57 +00:00
|
|
|
// Return native data according to aDataType
|
2001-11-06 15:35:24 +00:00
|
|
|
void* nsChildView::GetNativeData(PRUint32 aDataType)
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSNULL;
|
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
void* retVal = nsnull;
|
|
|
|
|
|
|
|
switch (aDataType)
|
|
|
|
{
|
2007-09-17 22:55:20 +00:00
|
|
|
case NS_NATIVE_WIDGET:
|
2001-11-08 21:47:44 +00:00
|
|
|
case NS_NATIVE_DISPLAY:
|
2001-11-06 15:35:24 +00:00
|
|
|
retVal = (void*)mView;
|
|
|
|
break;
|
|
|
|
|
2001-11-08 21:47:44 +00:00
|
|
|
case NS_NATIVE_WINDOW:
|
2009-09-15 21:56:44 +00:00
|
|
|
retVal = [mView window];
|
2001-11-08 21:47:44 +00:00
|
|
|
break;
|
2007-09-17 22:55:20 +00:00
|
|
|
|
|
|
|
case NS_NATIVE_GRAPHIC:
|
2009-08-14 14:09:00 +00:00
|
|
|
NS_ERROR("Requesting NS_NATIVE_GRAPHIC on a Mac OS X child view!");
|
2007-09-17 22:55:20 +00:00
|
|
|
retVal = nsnull;
|
2001-11-06 15:35:24 +00:00
|
|
|
break;
|
2007-09-17 22:55:20 +00:00
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
case NS_NATIVE_OFFSETX:
|
2001-11-19 15:02:23 +00:00
|
|
|
retVal = 0;
|
2001-11-06 15:35:24 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_NATIVE_OFFSETY:
|
2001-11-19 15:02:23 +00:00
|
|
|
retVal = 0;
|
2001-11-06 15:35:24 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_NATIVE_PLUGIN_PORT:
|
2007-03-27 01:07:57 +00:00
|
|
|
case NS_NATIVE_PLUGIN_PORT_QD:
|
|
|
|
case NS_NATIVE_PLUGIN_PORT_CG:
|
|
|
|
{
|
2009-07-22 08:57:39 +00:00
|
|
|
#ifdef NP_NO_QUICKDRAW
|
|
|
|
aDataType = NS_NATIVE_PLUGIN_PORT_CG;
|
|
|
|
#endif
|
|
|
|
mPluginIsCG = (aDataType == NS_NATIVE_PLUGIN_PORT_CG);
|
2010-01-24 06:00:39 +00:00
|
|
|
|
|
|
|
// The NP_CGContext pointer should always be NULL in the Cocoa event model.
|
|
|
|
if ([(ChildView*)mView pluginEventModel] == NPEventModelCocoa)
|
|
|
|
return nsnull;
|
2007-03-27 01:07:57 +00:00
|
|
|
|
2009-07-22 08:57:39 +00:00
|
|
|
UpdatePluginPort();
|
2009-09-17 01:30:26 +00:00
|
|
|
if (mPluginIsCG)
|
|
|
|
retVal = (void*)&mPluginCGContext;
|
|
|
|
else
|
|
|
|
retVal = (void*)&mPluginQDPort;
|
2002-12-13 08:43:18 +00:00
|
|
|
break;
|
2006-11-22 00:48:57 +00:00
|
|
|
}
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return retVal;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSNULL;
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark -
|
|
|
|
|
2008-08-13 00:44:14 +00:00
|
|
|
nsTransparencyMode nsChildView::GetTransparencyMode()
|
2007-12-19 19:40:18 +00:00
|
|
|
{
|
2009-11-13 22:58:15 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
2009-11-13 22:58:15 +00:00
|
|
|
nsCocoaWindow* windowWidget = GetXULWindowWidget();
|
|
|
|
return windowWidget ? windowWidget->GetTransparencyMode() : eTransparencyOpaque;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
2009-11-13 22:58:15 +00:00
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(eTransparencyOpaque);
|
2007-12-19 19:40:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// This is called by nsContainerFrame on the root widget for all window types
|
2008-08-13 00:44:14 +00:00
|
|
|
// except popup windows (when nsCocoaWindow::SetTransparencyMode is used instead).
|
|
|
|
void nsChildView::SetTransparencyMode(nsTransparencyMode aMode)
|
2007-12-19 19:40:18 +00:00
|
|
|
{
|
2008-08-13 00:44:14 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
2009-11-13 22:58:15 +00:00
|
|
|
nsCocoaWindow* windowWidget = GetXULWindowWidget();
|
|
|
|
if (windowWidget) {
|
|
|
|
windowWidget->SetTransparencyMode(aMode);
|
2007-12-19 19:40:18 +00:00
|
|
|
}
|
2008-02-20 23:47:05 +00:00
|
|
|
|
2008-08-13 00:44:14 +00:00
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2007-12-19 19:40:18 +00:00
|
|
|
}
|
|
|
|
|
2006-05-22 18:15:06 +00:00
|
|
|
NS_IMETHODIMP nsChildView::IsVisible(PRBool& outState)
|
2001-11-06 15:35:24 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2006-08-25 20:36:18 +00:00
|
|
|
if (!mVisible) {
|
2006-05-22 18:15:06 +00:00
|
|
|
outState = mVisible;
|
2006-08-25 20:36:18 +00:00
|
|
|
}
|
|
|
|
else {
|
2002-12-13 08:43:18 +00:00
|
|
|
// mVisible does not accurately reflect the state of a hidden tabbed view
|
|
|
|
// so verify that the view has a window as well
|
2006-05-22 18:15:06 +00:00
|
|
|
outState = ([mView window] != nil);
|
2006-08-25 20:36:18 +00:00
|
|
|
// now check native widget hierarchy visibility
|
|
|
|
if (outState && NSIsEmptyRect([mView visibleRect])) {
|
|
|
|
outState = PR_FALSE;
|
|
|
|
}
|
|
|
|
}
|
2006-05-22 18:15:06 +00:00
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
return NS_OK;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
2008-04-23 22:56:40 +00:00
|
|
|
void nsChildView::HidePlugin()
|
|
|
|
{
|
2009-09-24 09:32:20 +00:00
|
|
|
NS_ASSERTION(mWindowType == eWindowType_plugin,
|
|
|
|
"HidePlugin called on non-plugin view");
|
2008-04-23 22:56:40 +00:00
|
|
|
|
|
|
|
if (mPluginInstanceOwner && !mPluginIsCG) {
|
2009-09-17 01:30:26 +00:00
|
|
|
NPWindow* window;
|
2008-04-23 22:56:40 +00:00
|
|
|
mPluginInstanceOwner->GetWindow(window);
|
|
|
|
nsCOMPtr<nsIPluginInstance> instance;
|
|
|
|
mPluginInstanceOwner->GetInstance(*getter_AddRefs(instance));
|
|
|
|
if (window && instance) {
|
|
|
|
window->clipRect.top = 0;
|
|
|
|
window->clipRect.left = 0;
|
|
|
|
window->clipRect.bottom = 0;
|
|
|
|
window->clipRect.right = 0;
|
|
|
|
instance->SetWindow(window);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-22 08:57:39 +00:00
|
|
|
void nsChildView::UpdatePluginPort()
|
|
|
|
{
|
2009-09-24 09:32:20 +00:00
|
|
|
NS_ASSERTION(mWindowType == eWindowType_plugin,
|
|
|
|
"UpdatePluginPort called on non-plugin view");
|
2009-07-22 08:57:39 +00:00
|
|
|
|
2009-09-15 21:56:44 +00:00
|
|
|
NSWindow* cocoaWindow = [mView window];
|
2009-09-01 01:00:13 +00:00
|
|
|
#if !defined(NP_NO_CARBON) || !defined(NP_NO_QUICKDRAW)
|
2009-08-27 00:29:47 +00:00
|
|
|
WindowRef carbonWindow = cocoaWindow ? (WindowRef)[cocoaWindow windowRef] : NULL;
|
2009-09-01 01:00:13 +00:00
|
|
|
#endif
|
2009-08-27 00:29:47 +00:00
|
|
|
|
2009-07-22 08:57:39 +00:00
|
|
|
if (mPluginIsCG) {
|
2009-08-27 00:29:47 +00:00
|
|
|
// [NSGraphicsContext currentContext] is supposed to "return the
|
|
|
|
// current graphics context of the current thread." But sometimes
|
|
|
|
// (when called while mView isn't focused for drawing) it returns a
|
|
|
|
// graphics context for the wrong window. [window graphicsContext]
|
|
|
|
// (which "provides the graphics context associated with the window
|
|
|
|
// for the current thread") seems always to return the "right"
|
|
|
|
// graphics context. See bug 500130.
|
2009-09-17 01:30:26 +00:00
|
|
|
mPluginCGContext.context = NULL;
|
|
|
|
mPluginCGContext.window = NULL;
|
2009-09-01 01:00:13 +00:00
|
|
|
#ifndef NP_NO_CARBON
|
2010-01-24 06:00:39 +00:00
|
|
|
if (carbonWindow) {
|
|
|
|
mPluginCGContext.context = (CGContextRef)[[cocoaWindow graphicsContext] graphicsPort];
|
|
|
|
mPluginCGContext.window = carbonWindow;
|
2009-09-01 01:00:13 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#ifndef NP_NO_QUICKDRAW
|
|
|
|
else {
|
2009-08-27 00:29:47 +00:00
|
|
|
if (carbonWindow) {
|
2009-09-17 01:30:26 +00:00
|
|
|
mPluginQDPort.port = ::GetWindowPort(carbonWindow);
|
2009-07-22 08:57:39 +00:00
|
|
|
|
|
|
|
NSPoint viewOrigin = [mView convertPoint:NSZeroPoint toView:nil];
|
2009-08-27 00:29:47 +00:00
|
|
|
NSRect frame = [[cocoaWindow contentView] frame];
|
2009-07-22 08:57:39 +00:00
|
|
|
viewOrigin.y = frame.size.height - viewOrigin.y;
|
|
|
|
|
|
|
|
// need to convert view's origin to window coordinates.
|
|
|
|
// then, encode as "SetOrigin" ready values.
|
2009-09-17 01:30:26 +00:00
|
|
|
mPluginQDPort.portx = (PRInt32)-viewOrigin.x;
|
|
|
|
mPluginQDPort.porty = (PRInt32)-viewOrigin.y;
|
2009-07-22 08:57:39 +00:00
|
|
|
} else {
|
2009-09-17 01:30:26 +00:00
|
|
|
mPluginQDPort.port = NULL;
|
2009-07-22 08:57:39 +00:00
|
|
|
}
|
|
|
|
}
|
2009-09-01 01:00:13 +00:00
|
|
|
#endif
|
2009-07-22 08:57:39 +00:00
|
|
|
}
|
|
|
|
|
2008-04-23 22:56:40 +00:00
|
|
|
static void HideChildPluginViews(NSView* aView)
|
|
|
|
{
|
|
|
|
NSArray* subviews = [aView subviews];
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < [subviews count]; ++i) {
|
|
|
|
NSView* view = [subviews objectAtIndex: i];
|
|
|
|
|
|
|
|
if (![view isKindOfClass:[ChildView class]])
|
|
|
|
continue;
|
|
|
|
|
|
|
|
ChildView* childview = static_cast<ChildView*>(view);
|
|
|
|
if ([childview isPluginView]) {
|
|
|
|
nsChildView* widget = static_cast<nsChildView*>([childview widget]);
|
|
|
|
if (widget) {
|
|
|
|
widget->HidePlugin();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
HideChildPluginViews(view);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
// Hide or show this component
|
2006-05-22 18:15:06 +00:00
|
|
|
NS_IMETHODIMP nsChildView::Show(PRBool aState)
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2006-05-22 18:15:06 +00:00
|
|
|
if (aState != mVisible) {
|
2010-04-13 20:36:03 +00:00
|
|
|
// Provide an autorelease pool because this gets called during startup
|
|
|
|
// on the "hidden window", resulting in cocoa object leakage if there's
|
|
|
|
// no pool in place.
|
|
|
|
nsAutoreleasePool localPool;
|
|
|
|
|
2006-05-22 18:15:06 +00:00
|
|
|
[mView setHidden:!aState];
|
|
|
|
mVisible = aState;
|
2008-04-23 22:56:40 +00:00
|
|
|
if (!mVisible)
|
|
|
|
HideChildPluginViews(mView);
|
2002-02-12 08:30:01 +00:00
|
|
|
}
|
2001-11-06 15:35:24 +00:00
|
|
|
return NS_OK;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
2009-04-23 15:54:50 +00:00
|
|
|
// Change the parent of this widget
|
2008-10-29 05:19:42 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsChildView::SetParent(nsIWidget* aNewParent)
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
|
|
|
NS_ENSURE_ARG(aNewParent);
|
|
|
|
NSView<mozView>* newParentView =
|
|
|
|
(NSView*)aNewParent->GetNativeData(NS_NATIVE_WIDGET);
|
|
|
|
NS_ENSURE_TRUE(newParentView, NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
if (mOnDestroyCalled)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
// make sure we stay alive
|
|
|
|
nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
|
|
|
|
|
|
|
|
// remove us from our existing parent
|
|
|
|
if (mParentWidget)
|
|
|
|
mParentWidget->RemoveChild(this);
|
|
|
|
// we hold a ref to mView, so this is safe
|
|
|
|
[mView removeFromSuperview];
|
|
|
|
|
|
|
|
// add us to the new parent
|
|
|
|
aNewParent->AddChild(this);
|
|
|
|
mParentWidget = aNewParent;
|
|
|
|
mParentView = newParentView;
|
|
|
|
[mParentView addSubview:mView];
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
}
|
2006-12-20 02:13:57 +00:00
|
|
|
|
2009-04-23 15:54:50 +00:00
|
|
|
void nsChildView::ResetParent()
|
|
|
|
{
|
|
|
|
if (!mOnDestroyCalled) {
|
|
|
|
if (mParentWidget)
|
|
|
|
mParentWidget->RemoveChild(this);
|
|
|
|
if (mView)
|
|
|
|
[mView removeFromSuperview];
|
|
|
|
}
|
|
|
|
mParentWidget = nsnull;
|
|
|
|
}
|
|
|
|
|
2008-10-21 14:56:35 +00:00
|
|
|
nsIWidget*
|
2010-04-25 20:58:03 +00:00
|
|
|
nsChildView::GetParent()
|
2002-02-12 08:30:01 +00:00
|
|
|
{
|
2002-12-13 08:43:18 +00:00
|
|
|
return mParentWidget;
|
2002-02-12 08:30:01 +00:00
|
|
|
}
|
2006-12-20 02:13:57 +00:00
|
|
|
|
2010-04-27 22:29:29 +00:00
|
|
|
LayerManager*
|
|
|
|
nsChildView::GetLayerManager()
|
|
|
|
{
|
|
|
|
nsCocoaWindow* window = GetXULWindowWidget();
|
|
|
|
if (window->GetAcceleratedRendering() != mUseAcceleratedRendering) {
|
|
|
|
mLayerManager = NULL;
|
|
|
|
mUseAcceleratedRendering = window->GetAcceleratedRendering();
|
|
|
|
}
|
|
|
|
return nsBaseWidget::GetLayerManager();
|
|
|
|
}
|
|
|
|
|
2002-02-28 23:10:04 +00:00
|
|
|
NS_IMETHODIMP nsChildView::Enable(PRBool aState)
|
2001-11-06 15:35:24 +00:00
|
|
|
{
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2002-02-28 23:10:04 +00:00
|
|
|
NS_IMETHODIMP nsChildView::IsEnabled(PRBool *aState)
|
|
|
|
{
|
2002-04-02 23:01:05 +00:00
|
|
|
// unimplemented
|
|
|
|
if (aState)
|
2002-03-04 22:50:11 +00:00
|
|
|
*aState = PR_TRUE;
|
2002-02-28 23:10:04 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
NS_IMETHODIMP nsChildView::SetFocus(PRBool aRaise)
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2009-08-13 20:20:25 +00:00
|
|
|
// Don't so anything if we're invisible (if Show(PR_FALSE) has been
|
|
|
|
// called on us, or if Show(PR_TRUE) hasn't yet been called). This
|
|
|
|
// resolves bug 504450.
|
|
|
|
if (mView && ![mView isHidden]) {
|
|
|
|
NSWindow* window = [mView window];
|
|
|
|
if (window)
|
|
|
|
[window makeFirstResponder:mView];
|
|
|
|
}
|
2001-11-06 15:35:24 +00:00
|
|
|
return NS_OK;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Override to set the cursor on the mac
|
2005-09-30 00:59:29 +00:00
|
|
|
NS_IMETHODIMP nsChildView::SetCursor(nsCursor aCursor)
|
2001-11-06 15:35:24 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2010-03-08 12:35:25 +00:00
|
|
|
if ([mView isDragInProgress])
|
|
|
|
return NS_OK; // Don't change the cursor during dragging.
|
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
nsBaseWidget::SetCursor(aCursor);
|
2010-03-11 16:44:31 +00:00
|
|
|
return [[nsCursorManager sharedInstance] setCursor:aCursor];
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2005-09-30 00:59:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// implement to fix "hidden virtual function" warning
|
|
|
|
NS_IMETHODIMP nsChildView::SetCursor(imgIContainer* aCursor,
|
|
|
|
PRUint32 aHotspotX, PRUint32 aHotspotY)
|
|
|
|
{
|
2010-03-11 16:44:31 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
|
|
|
nsBaseWidget::SetCursor(aCursor, aHotspotX, aHotspotY);
|
|
|
|
return [[nsCursorManager sharedInstance] setCursorWithImage:aCursor hotSpotX:aHotspotX hotSpotY:aHotspotY];
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2005-09-30 00:59:29 +00:00
|
|
|
}
|
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
#pragma mark -
|
2006-12-20 02:13:57 +00:00
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
// Get this component dimension
|
2009-01-15 03:27:09 +00:00
|
|
|
NS_IMETHODIMP nsChildView::GetBounds(nsIntRect &aRect)
|
2001-11-06 15:35:24 +00:00
|
|
|
{
|
|
|
|
aRect = mBounds;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2002-01-09 01:29:18 +00:00
|
|
|
NS_IMETHODIMP nsChildView::ConstrainPosition(PRBool aAllowSlop,
|
|
|
|
PRInt32 *aX, PRInt32 *aY)
|
2001-11-06 15:35:24 +00:00
|
|
|
{
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2006-12-20 02:13:57 +00:00
|
|
|
// Move this component, aX and aY are in the parent widget coordinate system
|
2001-11-06 15:35:24 +00:00
|
|
|
NS_IMETHODIMP nsChildView::Move(PRInt32 aX, PRInt32 aY)
|
2002-04-06 19:50:30 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2007-11-07 07:36:10 +00:00
|
|
|
if (!mView || (mBounds.x == aX && mBounds.y == aY))
|
|
|
|
return NS_OK;
|
2002-04-06 19:50:30 +00:00
|
|
|
|
2007-11-07 07:36:10 +00:00
|
|
|
mBounds.x = aX;
|
|
|
|
mBounds.y = aY;
|
2006-12-20 02:13:57 +00:00
|
|
|
|
2007-11-07 07:36:10 +00:00
|
|
|
NSRect r;
|
|
|
|
GeckoRectToNSRect(mBounds, r);
|
|
|
|
[mView setFrame:r];
|
2002-02-12 08:30:01 +00:00
|
|
|
|
2007-11-07 07:36:10 +00:00
|
|
|
if (mVisible)
|
|
|
|
[mView setNeedsDisplay:YES];
|
|
|
|
|
|
|
|
ReportMoveEvent();
|
2002-12-13 08:43:18 +00:00
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
return NS_OK;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsChildView::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2007-11-07 07:36:10 +00:00
|
|
|
if (!mView || (mBounds.width == aWidth && mBounds.height == aHeight))
|
|
|
|
return NS_OK;
|
2001-11-06 15:35:24 +00:00
|
|
|
|
2007-11-07 07:36:10 +00:00
|
|
|
mBounds.width = aWidth;
|
|
|
|
mBounds.height = aHeight;
|
2002-02-12 08:30:01 +00:00
|
|
|
|
2007-11-07 07:36:10 +00:00
|
|
|
NSRect r;
|
|
|
|
GeckoRectToNSRect(mBounds, r);
|
|
|
|
[mView setFrame:r];
|
|
|
|
|
|
|
|
if (mVisible && aRepaint)
|
|
|
|
[mView setNeedsDisplay:YES];
|
|
|
|
|
|
|
|
ReportSizeEvent();
|
2001-11-06 15:35:24 +00:00
|
|
|
|
|
|
|
return NS_OK;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsChildView::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2007-11-07 07:36:10 +00:00
|
|
|
BOOL isMoving = (mBounds.x != aX || mBounds.y != aY);
|
|
|
|
BOOL isResizing = (mBounds.width != aWidth || mBounds.height != aHeight);
|
|
|
|
if (!mView || (!isMoving && !isResizing))
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
if (isMoving) {
|
|
|
|
mBounds.x = aX;
|
|
|
|
mBounds.y = aY;
|
|
|
|
}
|
|
|
|
if (isResizing) {
|
|
|
|
mBounds.width = aWidth;
|
|
|
|
mBounds.height = aHeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
NSRect r;
|
|
|
|
GeckoRectToNSRect(mBounds, r);
|
|
|
|
[mView setFrame:r];
|
|
|
|
|
|
|
|
if (mVisible && aRepaint)
|
|
|
|
[mView setNeedsDisplay:YES];
|
|
|
|
|
2008-01-15 23:11:55 +00:00
|
|
|
if (isMoving) {
|
2007-11-07 07:36:10 +00:00
|
|
|
ReportMoveEvent();
|
2008-01-15 23:11:55 +00:00
|
|
|
if (mOnDestroyCalled)
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-11-07 07:36:10 +00:00
|
|
|
if (isResizing)
|
|
|
|
ReportSizeEvent();
|
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
return NS_OK;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
2008-08-08 16:11:54 +00:00
|
|
|
static const PRInt32 resizeIndicatorWidth = 15;
|
|
|
|
static const PRInt32 resizeIndicatorHeight = 15;
|
|
|
|
PRBool nsChildView::ShowsResizeIndicator(nsIntRect* aResizerRect)
|
|
|
|
{
|
|
|
|
NSView *topLevelView = mView, *superView = nil;
|
2008-08-20 04:23:19 +00:00
|
|
|
while ((superView = [topLevelView superview]))
|
2008-08-08 16:11:54 +00:00
|
|
|
topLevelView = superView;
|
|
|
|
|
2009-09-07 21:52:59 +00:00
|
|
|
if (![[topLevelView window] showsResizeIndicator] ||
|
|
|
|
!([[topLevelView window] styleMask] & NSResizableWindowMask))
|
2008-08-08 16:11:54 +00:00
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
if (aResizerRect) {
|
|
|
|
NSSize bounds = [topLevelView bounds].size;
|
|
|
|
NSPoint corner = NSMakePoint(bounds.width, [topLevelView isFlipped] ? bounds.height : 0);
|
|
|
|
corner = [topLevelView convertPoint:corner toView:mView];
|
|
|
|
aResizerRect->SetRect(NSToIntRound(corner.x) - resizeIndicatorWidth,
|
|
|
|
NSToIntRound(corner.y) - resizeIndicatorHeight,
|
|
|
|
resizeIndicatorWidth, resizeIndicatorHeight);
|
|
|
|
}
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
2009-02-05 23:31:00 +00:00
|
|
|
// In QuickDraw mode the coordinate system used here should be that of the
|
|
|
|
// browser window's content region (defined as everything but the 22-pixel
|
|
|
|
// high titlebar). But in CoreGraphics mode the coordinate system should be
|
|
|
|
// that of the browser window as a whole (including its titlebar). Both
|
|
|
|
// coordinate systems have a top-left origin. See bmo bug 474491.
|
|
|
|
//
|
|
|
|
// There's a bug in this method's code -- it currently uses the QuickDraw
|
|
|
|
// coordinate system for both the QuickDraw and CoreGraphics drawing modes.
|
|
|
|
// This bug is fixed by the patch for bug 474491. But the Flash plugin (both
|
|
|
|
// version 10.0.12.36 from Adobe and version 9.0 r151 from Apple) has Mozilla-
|
|
|
|
// specific code to work around this bug, which breaks when we fix it (see bmo
|
|
|
|
// bug 477077). So we'll need to coordinate releasing a fix for this bug with
|
|
|
|
// Adobe and other major plugin vendors that support the CoreGraphics mode.
|
2009-01-15 03:27:09 +00:00
|
|
|
NS_IMETHODIMP nsChildView::GetPluginClipRect(nsIntRect& outClipRect, nsIntPoint& outOrigin, PRBool& outWidgetVisible)
|
2002-12-13 08:43:18 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2009-09-24 09:32:20 +00:00
|
|
|
NS_ASSERTION(mWindowType == eWindowType_plugin,
|
|
|
|
"GetPluginClipRect must only be called on a plugin widget");
|
|
|
|
if (mWindowType != eWindowType_plugin) return NS_ERROR_FAILURE;
|
2002-12-13 08:43:18 +00:00
|
|
|
|
2009-09-15 21:56:44 +00:00
|
|
|
NSWindow* window = [mView window];
|
2002-12-13 08:43:18 +00:00
|
|
|
if (!window) return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
NSPoint viewOrigin = [mView convertPoint:NSZeroPoint toView:nil];
|
2009-02-05 23:05:53 +00:00
|
|
|
NSRect frame = [[window contentView] frame];
|
2002-12-13 08:43:18 +00:00
|
|
|
viewOrigin.y = frame.size.height - viewOrigin.y;
|
|
|
|
|
|
|
|
// set up the clipping region for plugins.
|
|
|
|
NSRect visibleBounds = [mView visibleRect];
|
|
|
|
NSPoint clipOrigin = [mView convertPoint:visibleBounds.origin toView:nil];
|
|
|
|
|
2009-02-05 23:05:53 +00:00
|
|
|
// Convert from cocoa to QuickDraw coordinates
|
2002-12-13 08:43:18 +00:00
|
|
|
clipOrigin.y = frame.size.height - clipOrigin.y;
|
|
|
|
|
2009-01-15 03:27:09 +00:00
|
|
|
outClipRect.x = NSToIntRound(clipOrigin.x);
|
|
|
|
outClipRect.y = NSToIntRound(clipOrigin.y);
|
2009-07-22 00:44:55 +00:00
|
|
|
|
|
|
|
// need to convert view's origin to window coordinates.
|
|
|
|
// then, encode as "SetOrigin" ready values.
|
|
|
|
outOrigin.x = -NSToIntRound(viewOrigin.x);
|
|
|
|
outOrigin.y = -NSToIntRound(viewOrigin.y);
|
|
|
|
|
2006-08-25 20:36:18 +00:00
|
|
|
PRBool isVisible;
|
|
|
|
IsVisible(isVisible);
|
|
|
|
if (isVisible && [mView window] != nil) {
|
2009-01-15 03:27:09 +00:00
|
|
|
outClipRect.width = NSToIntRound(visibleBounds.origin.x + visibleBounds.size.width) - NSToIntRound(visibleBounds.origin.x);
|
|
|
|
outClipRect.height = NSToIntRound(visibleBounds.origin.y + visibleBounds.size.height) - NSToIntRound(visibleBounds.origin.y);
|
2009-07-22 00:44:55 +00:00
|
|
|
|
|
|
|
if (mClipRects) {
|
|
|
|
nsIntRect clipBounds;
|
2009-09-01 01:00:13 +00:00
|
|
|
for (PRInt32 i = 0; i < mClipRectCount; ++i) {
|
2009-07-22 00:44:55 +00:00
|
|
|
clipBounds.UnionRect(clipBounds, mClipRects[i]);
|
|
|
|
}
|
|
|
|
outClipRect.IntersectRect(outClipRect, clipBounds - outOrigin);
|
|
|
|
}
|
|
|
|
|
|
|
|
// XXXroc should this be !outClipRect.IsEmpty()?
|
2003-02-28 22:59:12 +00:00
|
|
|
outWidgetVisible = PR_TRUE;
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
2006-08-25 20:36:18 +00:00
|
|
|
else {
|
2002-12-13 08:43:18 +00:00
|
|
|
outClipRect.width = 0;
|
|
|
|
outClipRect.height = 0;
|
2003-02-28 22:59:12 +00:00
|
|
|
outWidgetVisible = PR_FALSE;
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsChildView::StartDrawPlugin()
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2009-09-24 09:32:20 +00:00
|
|
|
NS_ASSERTION(mWindowType == eWindowType_plugin,
|
|
|
|
"StartDrawPlugin must only be called on a plugin widget");
|
|
|
|
if (mWindowType != eWindowType_plugin) return NS_ERROR_FAILURE;
|
2007-03-27 01:07:57 +00:00
|
|
|
|
2009-09-01 01:00:13 +00:00
|
|
|
// This code is necessary for both Quickdraw and CoreGraphics in 32-bit builds.
|
|
|
|
// See comments below about why. In 64-bit CoreGraphics mode we will not keep
|
|
|
|
// this region up to date, plugins should not depend on it.
|
|
|
|
#ifndef __LP64__
|
2009-09-15 21:56:44 +00:00
|
|
|
NSWindow* window = [mView window];
|
2006-11-20 05:37:49 +00:00
|
|
|
if (!window)
|
|
|
|
return NS_ERROR_FAILURE;
|
2009-08-27 00:29:47 +00:00
|
|
|
|
|
|
|
// In QuickDraw drawing mode, prevent reentrant handling of any plugin event
|
|
|
|
// (this emulates behavior on the 1.8 branch, where only QuickDraw mode is
|
|
|
|
// supported). But in CoreGraphics drawing mode only do this if the current
|
|
|
|
// plugin event isn't an update/paint event. This allows popupcontextmenu()
|
|
|
|
// to work properly from a plugin that supports the Cocoa event model,
|
|
|
|
// without regressing bug 409615. See bug 435041. (StartDrawPlugin() and
|
|
|
|
// EndDrawPlugin() wrap every call to nsIPluginInstance::HandleEvent() --
|
|
|
|
// not just calls that "draw" or paint.)
|
|
|
|
if (!mPluginIsCG || (mView != [NSView focusView])) {
|
|
|
|
if (mPluginDrawing)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2006-11-20 05:37:49 +00:00
|
|
|
// It appears that the WindowRef from which we get the plugin port undergoes the
|
|
|
|
// traditional BeginUpdate/EndUpdate cycle, which, if you recall, sets the visible
|
|
|
|
// region to the intersection of the visible region and the update region. Since
|
|
|
|
// we don't know here if we're being drawn inside a BeginUpdate/EndUpdate pair
|
|
|
|
// (which seem to occur in [NSWindow display]), and we don't want to have the burden
|
|
|
|
// of correctly doing Carbon invalidates of the plugin rect, we manually set the
|
2008-04-08 05:45:06 +00:00
|
|
|
// visible region to be the entire port every time. It is necessary to set up our
|
|
|
|
// window's port even for CoreGraphics plugins, because they may still use Carbon
|
|
|
|
// internally (see bug #420527 for details).
|
|
|
|
CGrafPtr port = ::GetWindowPort(WindowRef([window windowRef]));
|
|
|
|
if (!mPluginIsCG)
|
2009-09-17 01:30:26 +00:00
|
|
|
port = mPluginQDPort.port;
|
2008-04-08 05:45:06 +00:00
|
|
|
|
2006-11-20 05:37:49 +00:00
|
|
|
RgnHandle pluginRegion = ::NewRgn();
|
|
|
|
if (pluginRegion) {
|
2008-04-08 05:45:06 +00:00
|
|
|
PRBool portChanged = (port != CGrafPtr(GetQDGlobalsThePort()));
|
2006-11-22 00:48:57 +00:00
|
|
|
CGrafPtr oldPort;
|
|
|
|
GDHandle oldDevice;
|
|
|
|
|
|
|
|
if (portChanged) {
|
|
|
|
::GetGWorld(&oldPort, &oldDevice);
|
2008-04-08 05:45:06 +00:00
|
|
|
::SetGWorld(port, ::IsPortOffscreen(port) ? nsnull : ::GetMainDevice());
|
2006-11-22 00:48:57 +00:00
|
|
|
}
|
|
|
|
|
2006-11-20 05:37:49 +00:00
|
|
|
::SetOrigin(0, 0);
|
|
|
|
|
2009-01-15 03:27:09 +00:00
|
|
|
nsIntRect clipRect; // this is in native window coordinates
|
|
|
|
nsIntPoint origin;
|
2006-11-20 05:37:49 +00:00
|
|
|
PRBool visible;
|
|
|
|
GetPluginClipRect(clipRect, origin, visible);
|
|
|
|
|
|
|
|
// XXX if we're not visible, set an empty clip region?
|
|
|
|
Rect pluginRect;
|
|
|
|
ConvertGeckoRectToMacRect(clipRect, pluginRect);
|
|
|
|
|
|
|
|
::RectRgn(pluginRegion, &pluginRect);
|
2008-04-08 05:45:06 +00:00
|
|
|
::SetPortVisibleRegion(port, pluginRegion);
|
|
|
|
::SetPortClipRegion(port, pluginRegion);
|
2006-11-20 05:37:49 +00:00
|
|
|
|
|
|
|
// now set up the origin for the plugin
|
|
|
|
::SetOrigin(origin.x, origin.y);
|
|
|
|
|
|
|
|
::DisposeRgn(pluginRegion);
|
2006-11-22 00:48:57 +00:00
|
|
|
|
|
|
|
if (portChanged)
|
|
|
|
::SetGWorld(oldPort, oldDevice);
|
2006-11-20 05:37:49 +00:00
|
|
|
}
|
2009-09-01 01:00:13 +00:00
|
|
|
#endif
|
2006-11-20 05:37:49 +00:00
|
|
|
|
|
|
|
mPluginDrawing = PR_TRUE;
|
|
|
|
return NS_OK;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsChildView::EndDrawPlugin()
|
|
|
|
{
|
2009-09-24 09:32:20 +00:00
|
|
|
NS_ASSERTION(mWindowType == eWindowType_plugin,
|
|
|
|
"EndDrawPlugin must only be called on a plugin widget");
|
|
|
|
if (mWindowType != eWindowType_plugin) return NS_ERROR_FAILURE;
|
2007-03-27 01:07:57 +00:00
|
|
|
|
2002-12-13 08:43:18 +00:00
|
|
|
mPluginDrawing = PR_FALSE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2008-04-23 22:56:40 +00:00
|
|
|
NS_IMETHODIMP nsChildView::SetPluginInstanceOwner(nsIPluginInstanceOwner* aInstanceOwner)
|
|
|
|
{
|
|
|
|
mPluginInstanceOwner = aInstanceOwner;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-08-27 00:29:47 +00:00
|
|
|
NS_IMETHODIMP nsChildView::SetPluginEventModel(int inEventModel)
|
|
|
|
{
|
2009-09-01 01:00:13 +00:00
|
|
|
[(ChildView*)mView setPluginEventModel:(NPEventModel)inEventModel];
|
2009-08-27 00:29:47 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsChildView::GetPluginEventModel(int* outEventModel)
|
|
|
|
{
|
2009-09-01 01:00:13 +00:00
|
|
|
*outEventModel = [(ChildView*)mView pluginEventModel];
|
2009-08-27 00:29:47 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-06-10 00:56:17 +00:00
|
|
|
NS_IMETHODIMP nsChildView::StartComplexTextInputForCurrentEvent()
|
|
|
|
{
|
|
|
|
[(ChildView*)mView pluginRequestsComplexTextInputForCurrentEvent];
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2008-05-05 23:01:07 +00:00
|
|
|
static NSString* ToNSString(const nsAString& aString)
|
|
|
|
{
|
|
|
|
return [NSString stringWithCharacters:aString.BeginReading()
|
|
|
|
length:aString.Length()];
|
|
|
|
}
|
|
|
|
|
2008-05-09 23:14:57 +00:00
|
|
|
struct KeyboardLayoutOverride {
|
|
|
|
PRInt32 mKeyboardLayout;
|
|
|
|
PRBool mOverrideEnabled;
|
|
|
|
};
|
|
|
|
|
|
|
|
static KeyboardLayoutOverride gOverrideKeyboardLayout;
|
2008-05-05 23:01:07 +00:00
|
|
|
|
|
|
|
static const PRUint32 sModifierFlagMap[][2] = {
|
|
|
|
{ nsIWidget::CAPS_LOCK, NSAlphaShiftKeyMask },
|
|
|
|
{ nsIWidget::SHIFT_L, NSShiftKeyMask },
|
2008-10-18 08:37:59 +00:00
|
|
|
{ nsIWidget::SHIFT_R, NSShiftKeyMask },
|
2008-05-05 23:01:07 +00:00
|
|
|
{ nsIWidget::CTRL_L, NSControlKeyMask },
|
2008-10-18 08:37:59 +00:00
|
|
|
{ nsIWidget::CTRL_R, NSControlKeyMask },
|
2008-05-05 23:01:07 +00:00
|
|
|
{ nsIWidget::ALT_L, NSAlternateKeyMask },
|
2008-10-18 08:37:59 +00:00
|
|
|
{ nsIWidget::ALT_R, NSAlternateKeyMask },
|
|
|
|
{ nsIWidget::COMMAND_L, NSCommandKeyMask },
|
|
|
|
{ nsIWidget::COMMAND_R, NSCommandKeyMask },
|
2008-05-05 23:01:07 +00:00
|
|
|
{ nsIWidget::NUMERIC_KEY_PAD, NSNumericPadKeyMask },
|
|
|
|
{ nsIWidget::HELP, NSHelpKeyMask },
|
|
|
|
{ nsIWidget::FUNCTION, NSFunctionKeyMask }
|
|
|
|
};
|
2008-05-07 05:17:40 +00:00
|
|
|
nsresult nsChildView::SynthesizeNativeKeyEvent(PRInt32 aNativeKeyboardLayout,
|
|
|
|
PRInt32 aNativeKeyCode,
|
|
|
|
PRUint32 aModifierFlags,
|
|
|
|
const nsAString& aCharacters,
|
|
|
|
const nsAString& aUnmodifiedCharacters)
|
2008-05-05 23:01:07 +00:00
|
|
|
{
|
2008-05-07 05:17:40 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
2008-05-05 23:01:07 +00:00
|
|
|
|
|
|
|
PRUint32 modifierFlags = 0;
|
|
|
|
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(sModifierFlagMap); ++i) {
|
|
|
|
if (aModifierFlags & sModifierFlagMap[i][0]) {
|
|
|
|
modifierFlags |= sModifierFlagMap[i][1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int windowNumber = [[mView window] windowNumber];
|
2008-10-18 08:37:59 +00:00
|
|
|
BOOL sendFlagsChangedEvent = NO;
|
|
|
|
switch (aNativeKeyCode) {
|
|
|
|
case kCapsLockKeyCode:
|
|
|
|
case kRCommandKeyCode:
|
|
|
|
case kCommandKeyCode:
|
|
|
|
case kShiftKeyCode:
|
|
|
|
case kOptionkeyCode:
|
|
|
|
case kControlKeyCode:
|
|
|
|
case kRShiftKeyCode:
|
|
|
|
case kROptionKeyCode:
|
|
|
|
case kRControlKeyCode:
|
|
|
|
sendFlagsChangedEvent = YES;
|
|
|
|
}
|
2008-10-16 03:04:39 +00:00
|
|
|
NSEventType eventType = sendFlagsChangedEvent ? NSFlagsChanged : NSKeyDown;
|
|
|
|
NSEvent* downEvent = [NSEvent keyEventWithType:eventType
|
2008-05-05 23:01:07 +00:00
|
|
|
location:NSMakePoint(0,0)
|
|
|
|
modifierFlags:modifierFlags
|
|
|
|
timestamp:0
|
|
|
|
windowNumber:windowNumber
|
|
|
|
context:[NSGraphicsContext currentContext]
|
|
|
|
characters:ToNSString(aCharacters)
|
|
|
|
charactersIgnoringModifiers:ToNSString(aUnmodifiedCharacters)
|
|
|
|
isARepeat:NO
|
|
|
|
keyCode:aNativeKeyCode];
|
|
|
|
|
2008-10-16 03:04:39 +00:00
|
|
|
NSEvent* upEvent = sendFlagsChangedEvent ? nil :
|
|
|
|
[ChildView makeNewCocoaEventWithType:NSKeyUp
|
|
|
|
fromEvent:downEvent];
|
2008-05-05 23:01:07 +00:00
|
|
|
|
2008-10-16 03:04:39 +00:00
|
|
|
if (downEvent && (sendFlagsChangedEvent || upEvent)) {
|
2008-05-09 23:14:57 +00:00
|
|
|
KeyboardLayoutOverride currentLayout = gOverrideKeyboardLayout;
|
|
|
|
gOverrideKeyboardLayout.mKeyboardLayout = aNativeKeyboardLayout;
|
|
|
|
gOverrideKeyboardLayout.mOverrideEnabled = PR_TRUE;
|
2008-05-06 21:00:59 +00:00
|
|
|
[NSApp sendEvent:downEvent];
|
2008-10-16 03:04:39 +00:00
|
|
|
if (upEvent)
|
|
|
|
[NSApp sendEvent:upEvent];
|
2008-05-05 23:01:07 +00:00
|
|
|
// processKeyDownEvent and keyUp block exceptions so we're sure to
|
|
|
|
// reach here to restore gOverrideKeyboardLayout
|
|
|
|
gOverrideKeyboardLayout = currentLayout;
|
|
|
|
}
|
|
|
|
|
2008-05-07 05:17:40 +00:00
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2008-05-05 23:01:07 +00:00
|
|
|
}
|
2001-11-06 15:35:24 +00:00
|
|
|
|
2009-09-23 02:31:37 +00:00
|
|
|
nsresult nsChildView::SynthesizeNativeMouseEvent(nsIntPoint aPoint,
|
|
|
|
PRUint32 aNativeMessage,
|
|
|
|
PRUint32 aModifierFlags)
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
|
|
|
// Move the mouse cursor to the requested position and reconnect it to the mouse.
|
|
|
|
CGWarpMouseCursorPosition(CGPointMake(aPoint.x, aPoint.y));
|
|
|
|
CGAssociateMouseAndMouseCursorPosition(true);
|
|
|
|
|
|
|
|
// aPoint is given with the origin on the top left, but convertScreenToBase
|
|
|
|
// expects a point in a coordinate system that has its origin on the bottom left.
|
|
|
|
NSPoint screenPoint = NSMakePoint(aPoint.x, [[NSScreen mainScreen] frame].size.height - aPoint.y);
|
|
|
|
NSPoint windowPoint = [[mView window] convertScreenToBase:screenPoint];
|
|
|
|
|
2009-10-21 15:09:19 +00:00
|
|
|
NSEvent* event = [NSEvent mouseEventWithType:aNativeMessage
|
|
|
|
location:windowPoint
|
|
|
|
modifierFlags:aModifierFlags
|
|
|
|
timestamp:[NSDate timeIntervalSinceReferenceDate]
|
|
|
|
windowNumber:[[mView window] windowNumber]
|
|
|
|
context:nil
|
|
|
|
eventNumber:0
|
|
|
|
clickCount:1
|
|
|
|
pressure:0.0];
|
2009-09-23 02:31:37 +00:00
|
|
|
|
|
|
|
if (!event)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
[NSApp sendEvent:event];
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
}
|
|
|
|
|
2008-10-30 05:36:01 +00:00
|
|
|
// First argument has to be an NSMenu representing the application's top-level
|
|
|
|
// menu bar. The returned item is *not* retained.
|
|
|
|
static NSMenuItem* NativeMenuItemWithLocation(NSMenu* menubar, NSString* locationString)
|
|
|
|
{
|
|
|
|
NSArray* indexes = [locationString componentsSeparatedByString:@"|"];
|
2008-06-28 07:55:30 +00:00
|
|
|
unsigned int indexCount = [indexes count];
|
|
|
|
if (indexCount == 0)
|
2008-10-30 05:36:01 +00:00
|
|
|
return nil;
|
|
|
|
|
2008-06-28 07:55:30 +00:00
|
|
|
NSMenu* currentSubmenu = [NSApp mainMenu];
|
2008-10-30 05:36:01 +00:00
|
|
|
for (unsigned int i = 0; i < indexCount; i++) {
|
2008-06-28 07:55:30 +00:00
|
|
|
int targetIndex;
|
|
|
|
// We remove the application menu from consideration for the top-level menu
|
|
|
|
if (i == 0)
|
|
|
|
targetIndex = [[indexes objectAtIndex:i] intValue] + 1;
|
|
|
|
else
|
|
|
|
targetIndex = [[indexes objectAtIndex:i] intValue];
|
|
|
|
int itemCount = [currentSubmenu numberOfItems];
|
|
|
|
if (targetIndex < itemCount) {
|
|
|
|
NSMenuItem* menuItem = [currentSubmenu itemAtIndex:targetIndex];
|
2008-10-30 05:36:01 +00:00
|
|
|
// if this is the last index just return the menu item
|
|
|
|
if (i == (indexCount - 1))
|
|
|
|
return menuItem;
|
|
|
|
// if this is not the last index find the submenu and keep going
|
2008-06-28 07:55:30 +00:00
|
|
|
if ([menuItem hasSubmenu])
|
2008-10-30 05:36:01 +00:00
|
|
|
currentSubmenu = [menuItem submenu];
|
|
|
|
else
|
|
|
|
return nil;
|
2008-06-28 07:55:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-30 05:36:01 +00:00
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Used for testing native menu system structure and event handling.
|
|
|
|
NS_IMETHODIMP nsChildView::ActivateNativeMenuItemAt(const nsAString& indexString)
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
|
|
|
NSString* locationString = [NSString stringWithCharacters:indexString.BeginReading() length:indexString.Length()];
|
|
|
|
NSMenuItem* item = NativeMenuItemWithLocation([NSApp mainMenu], locationString);
|
2008-07-28 04:46:33 +00:00
|
|
|
// We can't perform an action on an item with a submenu, that will raise
|
|
|
|
// an obj-c exception.
|
2008-10-30 05:36:01 +00:00
|
|
|
if (item && ![item hasSubmenu]) {
|
|
|
|
NSMenu* parent = [item menu];
|
|
|
|
if (parent) {
|
2008-07-28 04:46:33 +00:00
|
|
|
// NSLog(@"Performing action for native menu item titled: %@\n",
|
|
|
|
// [[currentSubmenu itemAtIndex:targetIndex] title]);
|
2008-10-30 05:36:01 +00:00
|
|
|
[parent performActionForItemAtIndex:[parent indexOfItem:item]];
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2008-06-28 07:55:30 +00:00
|
|
|
}
|
2008-10-30 05:36:01 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
2008-07-28 04:46:33 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
}
|
|
|
|
|
2008-10-30 05:36:01 +00:00
|
|
|
// Used for testing native menu system structure and event handling.
|
|
|
|
NS_IMETHODIMP nsChildView::ForceUpdateNativeMenuAt(const nsAString& indexString)
|
2008-07-28 04:46:33 +00:00
|
|
|
{
|
2008-10-30 05:36:01 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2009-08-13 22:06:49 +00:00
|
|
|
nsCocoaWindow *widget = GetXULWindowWidget();
|
|
|
|
if (widget) {
|
|
|
|
nsMenuBarX* mb = widget->GetMenuBar();
|
|
|
|
if (mb) {
|
|
|
|
if (indexString.IsEmpty())
|
|
|
|
mb->ForceNativeMenuReload();
|
|
|
|
else
|
|
|
|
mb->ForceUpdateNativeMenuAt(indexString);
|
2008-07-28 04:46:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_OK;
|
2008-10-30 05:36:01 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2008-06-28 07:55:30 +00:00
|
|
|
}
|
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
#pragma mark -
|
|
|
|
|
2006-12-20 02:13:57 +00:00
|
|
|
#ifdef INVALIDATE_DEBUGGING
|
2002-12-13 08:43:18 +00:00
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
static Boolean KeyDown(const UInt8 theKey)
|
|
|
|
{
|
|
|
|
KeyMap map;
|
|
|
|
GetKeys(map);
|
|
|
|
return ((*((UInt8 *)map + (theKey >> 3)) >> (theKey & 7)) & 1) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Boolean caps_lock()
|
|
|
|
{
|
|
|
|
return KeyDown(0x39);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void blinkRect(Rect* r)
|
|
|
|
{
|
|
|
|
StRegionFromPool oldClip;
|
|
|
|
if (oldClip != NULL)
|
|
|
|
::GetClip(oldClip);
|
|
|
|
|
|
|
|
::ClipRect(r);
|
|
|
|
::InvertRect(r);
|
|
|
|
UInt32 end = ::TickCount() + 5;
|
|
|
|
while (::TickCount() < end) ;
|
|
|
|
::InvertRect(r);
|
|
|
|
|
|
|
|
if (oldClip != NULL)
|
|
|
|
::SetClip(oldClip);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void blinkRgn(RgnHandle rgn)
|
|
|
|
{
|
|
|
|
StRegionFromPool oldClip;
|
|
|
|
if (oldClip != NULL)
|
|
|
|
::GetClip(oldClip);
|
|
|
|
|
|
|
|
::SetClip(rgn);
|
|
|
|
::InvertRgn(rgn);
|
|
|
|
UInt32 end = ::TickCount() + 5;
|
|
|
|
while (::TickCount() < end) ;
|
|
|
|
::InvertRgn(rgn);
|
|
|
|
|
|
|
|
if (oldClip != NULL)
|
|
|
|
::SetClip(oldClip);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Invalidate this component's visible area
|
2009-01-15 03:27:09 +00:00
|
|
|
NS_IMETHODIMP nsChildView::Invalidate(const nsIntRect &aRect, PRBool aIsSynchronous)
|
2001-11-06 15:35:24 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2005-06-16 12:49:43 +00:00
|
|
|
if (!mView || !mVisible)
|
2001-11-06 15:35:24 +00:00
|
|
|
return NS_OK;
|
2005-06-16 12:49:43 +00:00
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
NSRect r;
|
2006-09-11 17:09:47 +00:00
|
|
|
GeckoRectToNSRect(aRect, r);
|
2001-11-06 15:35:24 +00:00
|
|
|
|
2006-09-11 17:09:47 +00:00
|
|
|
if (aIsSynchronous) {
|
2006-09-14 22:39:58 +00:00
|
|
|
[mView displayRect:r];
|
|
|
|
}
|
|
|
|
else if ([NSView focusView]) {
|
|
|
|
// if a view is focussed (i.e. being drawn), then postpone the invalidate so that we
|
|
|
|
// don't lose it.
|
2006-11-09 14:00:08 +00:00
|
|
|
[mView setNeedsPendingDisplayInRect:r];
|
2006-09-14 22:39:58 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
[mView setNeedsDisplayInRect:r];
|
2006-09-11 17:09:47 +00:00
|
|
|
}
|
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
return NS_OK;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inline PRUint16 COLOR8TOCOLOR16(PRUint8 color8)
|
|
|
|
{
|
|
|
|
// return (color8 == 0xFF ? 0xFFFF : (color8 << 8));
|
|
|
|
return (color8 << 8) | color8; /* (color8 * 257) == (color8 * 0x0101) */
|
|
|
|
}
|
|
|
|
|
2008-12-18 21:37:16 +00:00
|
|
|
// The OS manages repaints well enough on its own, so we don't have to
|
|
|
|
// flush them out here. In other words, the OS will automatically call
|
|
|
|
// displayIfNeeded at the appropriate times, so we don't need to do it
|
|
|
|
// ourselves. See bmo bug 459319.
|
2001-11-06 15:35:24 +00:00
|
|
|
NS_IMETHODIMP nsChildView::Update()
|
|
|
|
{
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark -
|
|
|
|
|
2009-07-22 00:44:55 +00:00
|
|
|
void nsChildView::ApplyConfiguration(nsIWidget* aExpectedParent,
|
|
|
|
const nsIWidget::Configuration& aConfiguration,
|
|
|
|
PRBool aRepaint)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
nsWindowType kidType;
|
|
|
|
aConfiguration.mChild->GetWindowType(kidType);
|
|
|
|
#endif
|
2009-09-24 09:32:20 +00:00
|
|
|
NS_ASSERTION(kidType == eWindowType_plugin || kidType == eWindowType_child,
|
|
|
|
"Configured widget is not a child or plugin type");
|
2009-07-22 00:44:55 +00:00
|
|
|
NS_ASSERTION(aConfiguration.mChild->GetParent() == aExpectedParent,
|
|
|
|
"Configured widget is not a child of the right widget");
|
|
|
|
aConfiguration.mChild->Resize(
|
|
|
|
aConfiguration.mBounds.x, aConfiguration.mBounds.y,
|
|
|
|
aConfiguration.mBounds.width, aConfiguration.mBounds.height,
|
|
|
|
aRepaint);
|
|
|
|
// On Mac we don't use the clip region here, we just store it
|
|
|
|
// in case GetPluginClipRect needs it.
|
|
|
|
static_cast<nsChildView*>(aConfiguration.mChild)->
|
|
|
|
StoreWindowClipRegion(aConfiguration.mClipRegion);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsChildView::ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
|
|
|
|
{
|
|
|
|
for (PRUint32 i = 0; i < aConfigurations.Length(); ++i) {
|
|
|
|
nsChildView::ApplyConfiguration(this, aConfigurations[i], PR_TRUE);
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-11-03 18:39:42 +00:00
|
|
|
static PRInt32
|
|
|
|
PickValueForSign(PRInt32 aSign, PRInt32 aLessThanZero, PRInt32 aZero,
|
|
|
|
PRInt32 aGreaterThanZero)
|
|
|
|
{
|
|
|
|
if (aSign < 0) {
|
|
|
|
return aLessThanZero;
|
|
|
|
}
|
|
|
|
if (aSign > 0) {
|
|
|
|
return aGreaterThanZero;
|
|
|
|
}
|
|
|
|
return aZero;
|
|
|
|
}
|
|
|
|
|
2009-08-14 02:09:51 +00:00
|
|
|
void nsChildView::Scroll(const nsIntPoint& aDelta,
|
|
|
|
const nsTArray<nsIntRect>& aDestRects,
|
2009-07-22 00:45:13 +00:00
|
|
|
const nsTArray<Configuration>& aConfigurations)
|
2001-11-06 15:35:24 +00:00
|
|
|
{
|
2009-07-22 00:45:13 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
2008-09-22 20:44:46 +00:00
|
|
|
NS_ASSERTION(mParentView, "Attempting to scroll a view that does not have a parent");
|
|
|
|
if (!mParentView)
|
2009-07-22 00:45:13 +00:00
|
|
|
return;
|
2008-09-22 20:44:46 +00:00
|
|
|
|
2009-09-22 07:50:45 +00:00
|
|
|
BOOL viewWasDirty = mVisible && [mView needsDisplay];
|
2009-11-03 18:39:42 +00:00
|
|
|
if (mVisible && !aDestRects.IsEmpty()) {
|
2009-11-10 01:00:36 +00:00
|
|
|
// Union of all source and destination rects
|
|
|
|
nsIntRegion destRegion;
|
|
|
|
NSSize scrollVector = {aDelta.x, aDelta.y};
|
2009-12-13 21:01:33 +00:00
|
|
|
nsIntRect destRect; // keep the last rect
|
|
|
|
for (BlitRectIter iter(aDelta, aDestRects); !iter.IsDone(); ++iter) {
|
|
|
|
destRect = iter.Rect();
|
2009-08-14 02:09:51 +00:00
|
|
|
NSRect rect;
|
2009-12-13 21:01:33 +00:00
|
|
|
GeckoRectToNSRect(destRect - aDelta, rect);
|
2009-08-14 02:09:51 +00:00
|
|
|
[mView scrollRect:rect by:scrollVector];
|
2009-12-13 21:01:33 +00:00
|
|
|
destRegion.Or(destRegion, destRect);
|
2009-11-10 01:00:36 +00:00
|
|
|
}
|
2010-02-23 20:10:25 +00:00
|
|
|
|
2009-11-10 01:00:36 +00:00
|
|
|
if (viewWasDirty) {
|
|
|
|
nsIntRect allRects = destRegion.GetBounds();
|
|
|
|
allRects.UnionRect(allRects, allRects - aDelta);
|
|
|
|
NSRect all;
|
|
|
|
GeckoRectToNSRect(allRects, all);
|
|
|
|
[mView translateRectsNeedingDisplayInRect:all by:scrollVector];
|
|
|
|
|
|
|
|
// Areas that could be affected by the
|
|
|
|
// translateRectsNeedingDisplayInRect but aren't in any destination
|
|
|
|
// may have had their invalidation moved incorrectly. So just
|
|
|
|
// invalidate them now. Unfortunately Apple hasn't given us an API
|
|
|
|
// to do exactly what we need here.
|
|
|
|
nsIntRegion needsInvalidation;
|
|
|
|
needsInvalidation.Sub(allRects, destRegion);
|
|
|
|
const nsIntRect* invalidate;
|
|
|
|
for (nsIntRegionRectIterator iter(needsInvalidation);
|
|
|
|
(invalidate = iter.Next()) != nsnull;) {
|
|
|
|
NSRect rect;
|
|
|
|
GeckoRectToNSRect(*invalidate, rect);
|
|
|
|
[mView setNeedsDisplayInRect:rect];
|
|
|
|
}
|
2009-08-14 02:09:51 +00:00
|
|
|
}
|
2010-02-23 20:10:25 +00:00
|
|
|
|
2010-02-01 23:16:09 +00:00
|
|
|
// Invalidate the area that was scrolled into view from outside the window
|
|
|
|
// First, compute the destination region whose source was outside the
|
|
|
|
// window. We do this by subtracting from destRegion the window bounds,
|
|
|
|
// translated by the scroll amount.
|
|
|
|
NSView* rootView = [[mView window] contentView];
|
|
|
|
NSRect rootViewRect = [mView convertRect:[rootView bounds] fromView: rootView];
|
|
|
|
nsIntRect windowBounds;
|
|
|
|
NSRectToGeckoRect(rootViewRect, windowBounds);
|
|
|
|
destRegion.Sub(destRegion, windowBounds + aDelta);
|
|
|
|
nsIntRegionRectIterator iter(destRegion);
|
|
|
|
const nsIntRect* invalidate;
|
|
|
|
while ((invalidate = iter.Next()) != nsnull) {
|
|
|
|
NSRect rect;
|
|
|
|
GeckoRectToNSRect(*invalidate, rect);
|
|
|
|
[mView setNeedsDisplayInRect:rect];
|
|
|
|
}
|
2009-11-10 01:00:36 +00:00
|
|
|
|
2009-11-03 18:39:42 +00:00
|
|
|
// Leopard, at least, has a nasty bug where calling scrollRect:by: doesn't
|
|
|
|
// actually trigger a window update. A window update is only triggered
|
|
|
|
// if you actually paint something. In some cases Gecko might optimize
|
|
|
|
// scrolling in such a way that nothing actually gets repainted.
|
|
|
|
// So let's invalidate one pixel. We'll pick a pixel on the trailing edge
|
|
|
|
// of the last destination rectangle, since in most situations that's going
|
|
|
|
// to be invalidated anyway.
|
2009-12-13 21:01:33 +00:00
|
|
|
nsIntRect lastRect = destRect + aDelta;
|
2009-11-03 18:39:42 +00:00
|
|
|
nsIntPoint pointToInvalidate(
|
|
|
|
PickValueForSign(aDelta.x, lastRect.XMost(), lastRect.x, lastRect.x - 1),
|
|
|
|
PickValueForSign(aDelta.y, lastRect.YMost(), lastRect.y, lastRect.y - 1));
|
|
|
|
if (!nsIntRect(0,0,mBounds.width,mBounds.height).Contains(pointToInvalidate)) {
|
|
|
|
pointToInvalidate = nsIntPoint(0, 0);
|
|
|
|
}
|
|
|
|
Invalidate(nsIntRect(pointToInvalidate, nsIntSize(1,1)), PR_FALSE);
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
2009-07-22 00:45:13 +00:00
|
|
|
|
|
|
|
// Don't force invalidation of the child if it's moving by the scroll
|
|
|
|
// amount and not changing size
|
|
|
|
for (PRUint32 i = 0; i < aConfigurations.Length(); ++i) {
|
|
|
|
const Configuration& configuration = aConfigurations[i];
|
|
|
|
nsIntRect oldBounds;
|
|
|
|
configuration.mChild->GetBounds(oldBounds);
|
|
|
|
ApplyConfiguration(this, aConfigurations[i],
|
|
|
|
oldBounds + aDelta != configuration.mBounds);
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
2002-03-07 03:15:21 +00:00
|
|
|
|
2008-01-15 23:11:55 +00:00
|
|
|
if (mOnDestroyCalled)
|
2009-07-22 00:45:13 +00:00
|
|
|
return;
|
2008-01-15 23:11:55 +00:00
|
|
|
|
2009-07-22 00:45:13 +00:00
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
2007-09-19 22:15:48 +00:00
|
|
|
// Invokes callback and ProcessEvent methods on Event Listener object
|
2001-11-06 15:35:24 +00:00
|
|
|
NS_IMETHODIMP nsChildView::DispatchEvent(nsGUIEvent* event, nsEventStatus& aStatus)
|
|
|
|
{
|
2008-03-12 22:44:45 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
debug_DumpEvent(stdout, event->widget, event, nsCAutoString("something"), 0);
|
|
|
|
#endif
|
|
|
|
|
2009-10-01 02:52:50 +00:00
|
|
|
NS_ASSERTION(!(IME_IsComposing() && NS_IS_KEY_EVENT(event)),
|
2008-12-06 09:23:55 +00:00
|
|
|
"Any key events should not be fired during IME composing");
|
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
aStatus = nsEventStatus_eIgnore;
|
2006-07-25 18:51:41 +00:00
|
|
|
|
2009-07-01 18:41:34 +00:00
|
|
|
nsCOMPtr<nsIWidget> kungFuDeathGrip = do_QueryInterface(mParentWidget ? mParentWidget : this);
|
2006-10-19 23:19:50 +00:00
|
|
|
if (mParentWidget) {
|
|
|
|
nsWindowType type;
|
|
|
|
mParentWidget->GetWindowType(type);
|
|
|
|
if (type == eWindowType_popup) {
|
2007-08-02 18:43:31 +00:00
|
|
|
// use the parent popup's widget if there is no view
|
|
|
|
void* clientData = nsnull;
|
|
|
|
if (event->widget)
|
|
|
|
event->widget->GetClientData(clientData);
|
2008-01-15 23:11:55 +00:00
|
|
|
if (!clientData)
|
2007-08-02 18:43:31 +00:00
|
|
|
event->widget = mParentWidget;
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
}
|
2007-09-20 08:56:42 +00:00
|
|
|
|
2006-10-19 23:19:50 +00:00
|
|
|
if (mEventCallback)
|
|
|
|
aStatus = (*mEventCallback)(event);
|
2007-09-20 08:56:42 +00:00
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool nsChildView::DispatchWindowEvent(nsGUIEvent &event)
|
|
|
|
{
|
|
|
|
nsEventStatus status;
|
|
|
|
DispatchEvent(&event, status);
|
|
|
|
return ConvertStatus(status);
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark -
|
|
|
|
|
|
|
|
PRBool nsChildView::ReportDestroyEvent()
|
|
|
|
{
|
2005-04-28 23:48:28 +00:00
|
|
|
nsGUIEvent event(PR_TRUE, NS_DESTROY, this);
|
2006-03-29 00:49:15 +00:00
|
|
|
event.time = PR_IntervalNow();
|
2007-07-19 00:56:33 +00:00
|
|
|
return DispatchWindowEvent(event);
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PRBool nsChildView::ReportMoveEvent()
|
|
|
|
{
|
2005-04-28 23:48:28 +00:00
|
|
|
nsGUIEvent moveEvent(PR_TRUE, NS_MOVE, this);
|
2007-07-19 00:56:33 +00:00
|
|
|
moveEvent.refPoint.x = mBounds.x;
|
|
|
|
moveEvent.refPoint.y = mBounds.y;
|
|
|
|
moveEvent.time = PR_IntervalNow();
|
|
|
|
return DispatchWindowEvent(moveEvent);
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PRBool nsChildView::ReportSizeEvent()
|
|
|
|
{
|
2005-04-28 23:48:28 +00:00
|
|
|
nsSizeEvent sizeEvent(PR_TRUE, NS_SIZE, this);
|
2001-11-06 15:35:24 +00:00
|
|
|
sizeEvent.time = PR_IntervalNow();
|
|
|
|
sizeEvent.windowSize = &mBounds;
|
|
|
|
sizeEvent.mWinWidth = mBounds.width;
|
|
|
|
sizeEvent.mWinHeight = mBounds.height;
|
2007-07-19 00:56:33 +00:00
|
|
|
return DispatchWindowEvent(sizeEvent);
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark -
|
|
|
|
|
2009-02-19 00:11:49 +00:00
|
|
|
// Return the offset between this child view and the screen.
|
|
|
|
// @return -- widget origin in screen coordinates
|
|
|
|
nsIntPoint nsChildView::WidgetToScreenOffset()
|
2001-11-06 15:35:24 +00:00
|
|
|
{
|
2009-02-19 00:11:49 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
2009-02-19 00:11:49 +00:00
|
|
|
NSPoint temp;
|
|
|
|
temp.x = 0;
|
|
|
|
temp.y = 0;
|
2005-02-08 17:34:09 +00:00
|
|
|
|
2009-02-19 00:11:49 +00:00
|
|
|
// 1. First translate this point into window coords. The returned point is always in
|
2006-09-21 16:22:44 +00:00
|
|
|
// bottom-left coordinates.
|
2009-02-19 00:11:49 +00:00
|
|
|
temp = [mView convertPoint:temp toView:nil];
|
2006-09-21 16:22:44 +00:00
|
|
|
|
|
|
|
// 2. We turn the window-coord rect's origin into screen (still bottom-left) coords.
|
2009-09-15 21:56:44 +00:00
|
|
|
temp = [[mView window] convertBaseToScreen:temp];
|
2005-02-08 17:34:09 +00:00
|
|
|
|
2006-09-21 16:22:44 +00:00
|
|
|
// 3. Since we're dealing in bottom-left coords, we need to make it top-left coords
|
|
|
|
// before we pass it back to Gecko.
|
2009-02-19 00:11:49 +00:00
|
|
|
FlipCocoaScreenCoordinate(temp);
|
2005-02-08 17:34:09 +00:00
|
|
|
|
2009-02-19 00:11:49 +00:00
|
|
|
return nsIntPoint(NSToIntRound(temp.x), NSToIntRound(temp.y));
|
2008-02-20 23:47:05 +00:00
|
|
|
|
2009-02-19 00:11:49 +00:00
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(nsIntPoint(0,0));
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsChildView::CaptureRollupEvents(nsIRollupListener * aListener,
|
2009-12-22 23:49:33 +00:00
|
|
|
nsIMenuRollup * aMenuRollup,
|
2006-03-07 20:02:09 +00:00
|
|
|
PRBool aDoCapture,
|
|
|
|
PRBool aConsumeRollupEvent)
|
2001-11-06 15:35:24 +00:00
|
|
|
{
|
2006-06-29 01:33:57 +00:00
|
|
|
// this never gets called, only top-level windows can be rollup widgets
|
2001-11-06 15:35:24 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2004-04-18 23:18:23 +00:00
|
|
|
NS_IMETHODIMP nsChildView::SetTitle(const nsAString& title)
|
2001-11-06 15:35:24 +00:00
|
|
|
{
|
2007-07-19 00:56:33 +00:00
|
|
|
// child views don't have titles
|
2001-11-06 15:35:24 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2004-02-11 03:46:30 +00:00
|
|
|
NS_IMETHODIMP nsChildView::GetAttention(PRInt32 aCycleCount)
|
2001-11-06 15:35:24 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2006-07-11 19:51:56 +00:00
|
|
|
[NSApp requestUserAttention:NSInformationalRequest];
|
2001-11-06 15:35:24 +00:00
|
|
|
return NS_OK;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
2009-04-21 23:53:52 +00:00
|
|
|
/* static */
|
|
|
|
PRBool nsChildView::DoHasPendingInputEvent()
|
|
|
|
{
|
|
|
|
return sLastInputEventCount != GetCurrentInputEventCount();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
PRUint32 nsChildView::GetCurrentInputEventCount()
|
|
|
|
{
|
|
|
|
// Can't use kCGAnyInputEventType because that updates too rarely for us (and
|
|
|
|
// always in increments of 30+!) and because apparently it's sort of broken
|
|
|
|
// on Tiger. So just go ahead and query the counters we care about.
|
|
|
|
static const CGEventType eventTypes[] = {
|
|
|
|
kCGEventLeftMouseDown,
|
|
|
|
kCGEventLeftMouseUp,
|
|
|
|
kCGEventRightMouseDown,
|
|
|
|
kCGEventRightMouseUp,
|
|
|
|
kCGEventMouseMoved,
|
|
|
|
kCGEventLeftMouseDragged,
|
|
|
|
kCGEventRightMouseDragged,
|
|
|
|
kCGEventKeyDown,
|
|
|
|
kCGEventKeyUp,
|
|
|
|
kCGEventScrollWheel,
|
|
|
|
kCGEventTabletPointer,
|
|
|
|
kCGEventOtherMouseDown,
|
|
|
|
kCGEventOtherMouseUp,
|
|
|
|
kCGEventOtherMouseDragged
|
|
|
|
};
|
|
|
|
|
|
|
|
PRUint32 eventCount = 0;
|
|
|
|
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(eventTypes); ++i) {
|
|
|
|
eventCount +=
|
|
|
|
CGEventSourceCounterForEventType(kCGEventSourceStateCombinedSessionState,
|
|
|
|
eventTypes[i]);
|
|
|
|
}
|
|
|
|
return eventCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
void nsChildView::UpdateCurrentInputEventCount()
|
|
|
|
{
|
|
|
|
sLastInputEventCount = GetCurrentInputEventCount();
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool nsChildView::HasPendingInputEvent()
|
|
|
|
{
|
|
|
|
return DoHasPendingInputEvent();
|
|
|
|
}
|
2006-12-20 02:13:57 +00:00
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
#pragma mark -
|
|
|
|
|
2009-01-11 23:51:40 +00:00
|
|
|
// Force Input Method Editor to commit the uncommitted input
|
2008-07-14 02:56:18 +00:00
|
|
|
// Note that this and other IME methods don't necessarily
|
2005-07-25 15:56:25 +00:00
|
|
|
// get called on the same ChildView that input is going through.
|
2001-11-06 15:35:24 +00:00
|
|
|
NS_IMETHODIMP nsChildView::ResetInputState()
|
|
|
|
{
|
2005-06-26 03:25:52 +00:00
|
|
|
#ifdef DEBUG_IME
|
|
|
|
NSLog(@"**** ResetInputState");
|
2001-11-08 21:47:44 +00:00
|
|
|
#endif
|
2005-06-26 03:25:52 +00:00
|
|
|
|
2009-10-01 02:52:50 +00:00
|
|
|
IME_CommitComposition();
|
2005-06-26 03:25:52 +00:00
|
|
|
return NS_OK;
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
2005-06-26 03:25:52 +00:00
|
|
|
// 'open' means that it can take non-ASCII chars
|
2004-09-12 05:00:57 +00:00
|
|
|
NS_IMETHODIMP nsChildView::SetIMEOpenState(PRBool aState)
|
|
|
|
{
|
2007-04-15 13:43:55 +00:00
|
|
|
#ifdef DEBUG_IME
|
|
|
|
NSLog(@"**** SetIMEOpenState aState = %d", aState);
|
|
|
|
#endif
|
|
|
|
|
2009-10-01 02:52:50 +00:00
|
|
|
IME_SetOpenState(aState);
|
2007-04-15 13:43:55 +00:00
|
|
|
return NS_OK;
|
2004-09-12 05:00:57 +00:00
|
|
|
}
|
|
|
|
|
2005-06-26 03:25:52 +00:00
|
|
|
// 'open' means that it can take non-ASCII chars
|
2004-09-12 05:00:57 +00:00
|
|
|
NS_IMETHODIMP nsChildView::GetIMEOpenState(PRBool* aState)
|
|
|
|
{
|
2007-04-15 13:43:55 +00:00
|
|
|
#ifdef DEBUG_IME
|
|
|
|
NSLog(@"**** GetIMEOpenState");
|
|
|
|
#endif
|
|
|
|
|
2009-10-01 02:52:50 +00:00
|
|
|
*aState = IME_IsOpened();
|
2007-04-15 13:43:55 +00:00
|
|
|
return NS_OK;
|
2004-09-12 05:00:57 +00:00
|
|
|
}
|
|
|
|
|
2007-04-15 13:43:55 +00:00
|
|
|
NS_IMETHODIMP nsChildView::SetIMEEnabled(PRUint32 aState)
|
2005-08-23 14:32:09 +00:00
|
|
|
{
|
2007-04-15 13:43:55 +00:00
|
|
|
#ifdef DEBUG_IME
|
|
|
|
NSLog(@"**** SetIMEEnabled aState = %d", aState);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
switch (aState) {
|
2008-07-14 02:56:18 +00:00
|
|
|
case nsIWidget::IME_STATUS_ENABLED:
|
2008-12-15 03:54:54 +00:00
|
|
|
case nsIWidget::IME_STATUS_PLUGIN:
|
2009-10-01 02:52:50 +00:00
|
|
|
IME_SetASCIICapableOnly(PR_FALSE);
|
|
|
|
IME_Enable(PR_TRUE);
|
2007-04-15 13:43:55 +00:00
|
|
|
break;
|
2008-07-14 02:56:18 +00:00
|
|
|
case nsIWidget::IME_STATUS_DISABLED:
|
2009-10-01 02:52:50 +00:00
|
|
|
IME_SetASCIICapableOnly(PR_FALSE);
|
|
|
|
IME_Enable(PR_FALSE);
|
2007-04-15 13:43:55 +00:00
|
|
|
break;
|
2008-07-14 02:56:18 +00:00
|
|
|
case nsIWidget::IME_STATUS_PASSWORD:
|
2009-10-01 02:52:50 +00:00
|
|
|
IME_SetASCIICapableOnly(PR_TRUE);
|
|
|
|
IME_Enable(PR_FALSE);
|
2007-04-15 13:43:55 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
NS_ERROR("not implemented!");
|
|
|
|
}
|
|
|
|
return NS_OK;
|
2005-08-23 14:32:09 +00:00
|
|
|
}
|
|
|
|
|
2007-04-15 13:43:55 +00:00
|
|
|
NS_IMETHODIMP nsChildView::GetIMEEnabled(PRUint32* aState)
|
2005-08-23 14:32:09 +00:00
|
|
|
{
|
2007-04-15 13:43:55 +00:00
|
|
|
#ifdef DEBUG_IME
|
|
|
|
NSLog(@"**** GetIMEEnabled");
|
|
|
|
#endif
|
|
|
|
|
2009-10-01 02:52:50 +00:00
|
|
|
if (IME_IsEnabled())
|
2008-07-14 02:56:18 +00:00
|
|
|
*aState = nsIWidget::IME_STATUS_ENABLED;
|
2009-10-01 02:52:50 +00:00
|
|
|
else if (IME_IsASCIICapableOnly())
|
2008-07-14 02:56:18 +00:00
|
|
|
*aState = nsIWidget::IME_STATUS_PASSWORD;
|
2007-04-15 13:43:55 +00:00
|
|
|
else
|
2008-07-14 02:56:18 +00:00
|
|
|
*aState = nsIWidget::IME_STATUS_DISABLED;
|
2007-04-15 13:43:55 +00:00
|
|
|
return NS_OK;
|
2005-08-23 14:32:09 +00:00
|
|
|
}
|
|
|
|
|
2005-06-26 03:25:52 +00:00
|
|
|
// Destruct and don't commit the IME composition string.
|
2004-11-13 11:27:09 +00:00
|
|
|
NS_IMETHODIMP nsChildView::CancelIMEComposition()
|
|
|
|
{
|
2004-12-29 18:27:46 +00:00
|
|
|
#ifdef DEBUG_IME
|
2005-06-26 03:25:52 +00:00
|
|
|
NSLog(@"**** CancelIMEComposition");
|
2004-12-29 18:27:46 +00:00
|
|
|
#endif
|
2006-10-25 11:49:49 +00:00
|
|
|
|
2009-10-01 02:52:50 +00:00
|
|
|
IME_CancelComposition();
|
2004-12-29 18:27:46 +00:00
|
|
|
return NS_OK;
|
2004-11-13 11:27:09 +00:00
|
|
|
}
|
|
|
|
|
2007-06-16 19:19:46 +00:00
|
|
|
NS_IMETHODIMP nsChildView::GetToggledKeyState(PRUint32 aKeyCode,
|
|
|
|
PRBool* aLEDState)
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2007-06-16 19:19:46 +00:00
|
|
|
#ifdef DEBUG_IME
|
|
|
|
NSLog(@"**** GetToggledKeyState");
|
|
|
|
#endif
|
|
|
|
NS_ENSURE_ARG_POINTER(aLEDState);
|
|
|
|
PRUint32 key;
|
|
|
|
switch (aKeyCode) {
|
|
|
|
case NS_VK_CAPS_LOCK:
|
|
|
|
key = alphaLock;
|
|
|
|
break;
|
|
|
|
case NS_VK_NUM_LOCK:
|
|
|
|
key = kEventKeyModifierNumLockMask;
|
|
|
|
break;
|
|
|
|
// Mac doesn't support SCROLL_LOCK state.
|
|
|
|
default:
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
2009-09-25 20:10:04 +00:00
|
|
|
PRUint32 modifierFlags = ::GetCurrentKeyModifiers();
|
2007-06-16 19:19:46 +00:00
|
|
|
*aLEDState = (modifierFlags & key) != 0;
|
|
|
|
return NS_OK;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2007-06-16 19:19:46 +00:00
|
|
|
}
|
|
|
|
|
2009-10-01 02:52:50 +00:00
|
|
|
NS_IMETHODIMP nsChildView::OnIMEFocusChange(PRBool aFocus)
|
|
|
|
{
|
|
|
|
mTextInputHandler.OnFocusChangeInGecko(aFocus);
|
|
|
|
// XXX Return NS_ERROR_NOT_IMPLEMENTED, see bug 496360.
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
NSView<mozView>* nsChildView::GetEditorView()
|
|
|
|
{
|
|
|
|
NSView<mozView>* editorView = mView;
|
|
|
|
// We need to get editor's view. E.g., when the focus is in the bookmark
|
|
|
|
// dialog, the view is <panel> element of the dialog. At this time, the key
|
|
|
|
// events are processed the parent window's view that has native focus.
|
|
|
|
nsQueryContentEvent textContent(PR_TRUE, NS_QUERY_TEXT_CONTENT, this);
|
|
|
|
textContent.InitForQueryTextContent(0, 0);
|
|
|
|
DispatchWindowEvent(textContent);
|
|
|
|
if (textContent.mSucceeded && textContent.mReply.mFocusedWidget) {
|
|
|
|
NSView<mozView>* view = static_cast<NSView<mozView>*>(
|
|
|
|
textContent.mReply.mFocusedWidget->GetNativeData(NS_NATIVE_WIDGET));
|
|
|
|
if (view)
|
|
|
|
editorView = view;
|
|
|
|
}
|
|
|
|
return editorView;
|
|
|
|
}
|
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
#pragma mark -
|
|
|
|
|
2006-02-22 01:31:14 +00:00
|
|
|
gfxASurface*
|
|
|
|
nsChildView::GetThebesSurface()
|
|
|
|
{
|
2006-08-30 22:06:44 +00:00
|
|
|
if (!mTempThebesSurface) {
|
2007-02-08 21:18:08 +00:00
|
|
|
mTempThebesSurface = new gfxQuartzSurface(gfxSize(1, 1), gfxASurface::ImageFormatARGB32);
|
2006-08-30 22:06:44 +00:00
|
|
|
}
|
|
|
|
|
2007-05-17 06:52:35 +00:00
|
|
|
return mTempThebesSurface;
|
2006-02-22 01:31:14 +00:00
|
|
|
}
|
2006-12-19 20:47:53 +00:00
|
|
|
|
2007-09-27 16:01:32 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsChildView::BeginSecureKeyboardInput()
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2007-09-27 16:01:32 +00:00
|
|
|
nsresult rv = nsBaseWidget::BeginSecureKeyboardInput();
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
::EnableSecureEventInput();
|
|
|
|
return rv;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2007-09-27 16:01:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsChildView::EndSecureKeyboardInput()
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2007-09-27 16:01:32 +00:00
|
|
|
nsresult rv = nsBaseWidget::EndSecureKeyboardInput();
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
::DisableSecureEventInput();
|
|
|
|
return rv;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2007-09-27 16:01:32 +00:00
|
|
|
}
|
|
|
|
|
2006-09-11 15:47:35 +00:00
|
|
|
#ifdef ACCESSIBILITY
|
2010-05-12 06:47:35 +00:00
|
|
|
already_AddRefed<nsAccessible>
|
|
|
|
nsChildView::GetDocumentAccessible()
|
2006-09-11 15:47:35 +00:00
|
|
|
{
|
2010-05-12 06:47:35 +00:00
|
|
|
nsAccessible *docAccessible = nsnull;
|
|
|
|
if (mAccessible) {
|
|
|
|
CallQueryReferent(mAccessible.get(), &docAccessible);
|
|
|
|
return docAccessible;
|
2006-09-27 07:53:07 +00:00
|
|
|
}
|
|
|
|
|
2010-05-12 06:47:35 +00:00
|
|
|
// need to fetch the accessible anew, because it has gone away.
|
|
|
|
nsEventStatus status;
|
|
|
|
nsAccessibleEvent event(PR_TRUE, NS_GETACCESSIBLE, this);
|
|
|
|
DispatchEvent(&event, status);
|
|
|
|
|
|
|
|
// cache the accessible in our weak ptr
|
|
|
|
mAccessible =
|
|
|
|
do_GetWeakReference(static_cast<nsIAccessible*>(event.mAccessible));
|
|
|
|
|
|
|
|
NS_IF_ADDREF(event.mAccessible);
|
|
|
|
return event.mAccessible;
|
2006-09-11 15:47:35 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2002-04-23 03:55:19 +00:00
|
|
|
#pragma mark -
|
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
@implementation ChildView
|
|
|
|
|
2006-10-25 22:45:22 +00:00
|
|
|
// globalDragPboard is non-null during native drag sessions that did not originate
|
|
|
|
// in our native NSView (it is set in |draggingEntered:|). It is unset when the
|
|
|
|
// drag session ends for this view, either with the mouse exiting or when a drop
|
|
|
|
// occurs in this view.
|
|
|
|
NSPasteboard* globalDragPboard = nil;
|
|
|
|
|
2009-11-06 10:21:41 +00:00
|
|
|
// gLastDragView and gLastDragMouseDownEvent are used to communicate information
|
|
|
|
// to the drag service during drag invocation (starting a drag in from the view).
|
|
|
|
// gLastDragView is only non-null while mouseDragged is on the call stack.
|
2007-09-24 00:01:04 +00:00
|
|
|
NSView* gLastDragView = nil;
|
2009-11-06 10:21:41 +00:00
|
|
|
NSEvent* gLastDragMouseDownEvent = nil;
|
2006-10-25 22:45:22 +00:00
|
|
|
|
2008-12-15 20:56:29 +00:00
|
|
|
+ (void)initialize
|
|
|
|
{
|
|
|
|
static BOOL initialized = NO;
|
|
|
|
|
|
|
|
if (!initialized) {
|
|
|
|
// Inform the OS about the types of services (from the "Services" menu)
|
|
|
|
// that we can handle.
|
2009-03-18 02:04:01 +00:00
|
|
|
|
|
|
|
NSArray *sendTypes = [[NSArray alloc] initWithObjects:NSStringPboardType,NSHTMLPboardType,nil];
|
2010-01-11 01:45:45 +00:00
|
|
|
NSArray *returnTypes = [[NSArray alloc] initWithObjects:NSStringPboardType,NSHTMLPboardType,nil];
|
|
|
|
|
2008-12-15 20:56:29 +00:00
|
|
|
[NSApp registerServicesMenuSendTypes:sendTypes returnTypes:returnTypes];
|
|
|
|
|
2009-03-18 02:04:01 +00:00
|
|
|
[sendTypes release];
|
|
|
|
[returnTypes release];
|
|
|
|
|
2008-12-15 20:56:29 +00:00
|
|
|
initialized = YES;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-09 18:46:30 +00:00
|
|
|
// initWithFrame:geckoChild:
|
|
|
|
- (id)initWithFrame:(NSRect)inFrame geckoChild:(nsChildView*)inChild
|
2002-03-09 22:43:04 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
|
|
|
|
2006-01-24 04:01:54 +00:00
|
|
|
if ((self = [super initWithFrame:inFrame])) {
|
2005-06-16 12:49:43 +00:00
|
|
|
mGeckoChild = inChild;
|
|
|
|
mIsPluginView = NO;
|
2009-09-01 01:00:13 +00:00
|
|
|
#ifndef NP_NO_CARBON
|
|
|
|
mPluginEventModel = NPEventModelCarbon;
|
|
|
|
#else
|
|
|
|
mPluginEventModel = NPEventModelCocoa;
|
|
|
|
#endif
|
2005-10-13 17:00:18 +00:00
|
|
|
mCurKeyEvent = nil;
|
2007-11-26 18:09:38 +00:00
|
|
|
mKeyDownHandled = PR_FALSE;
|
2008-03-14 01:08:04 +00:00
|
|
|
mKeyPressHandled = NO;
|
2008-02-29 05:47:41 +00:00
|
|
|
mKeyPressSent = NO;
|
2010-06-09 04:11:42 +00:00
|
|
|
mPendingDisplay = NO;
|
2008-02-29 05:47:41 +00:00
|
|
|
|
2005-06-16 12:49:43 +00:00
|
|
|
// initialization for NSTextInput
|
|
|
|
mMarkedRange.location = NSNotFound;
|
|
|
|
mMarkedRange.length = 0;
|
2008-02-29 05:47:41 +00:00
|
|
|
|
2008-04-06 23:52:05 +00:00
|
|
|
mLastMouseDownEvent = nil;
|
2006-10-25 22:45:22 +00:00
|
|
|
mDragService = nsnull;
|
2008-06-30 16:30:22 +00:00
|
|
|
|
2010-03-20 15:05:47 +00:00
|
|
|
#ifndef NP_NO_CARBON
|
2008-06-30 16:30:22 +00:00
|
|
|
mPluginTSMDoc = nil;
|
2010-03-20 15:05:47 +00:00
|
|
|
#endif
|
2010-06-10 00:56:17 +00:00
|
|
|
mPluginComplexTextInputRequested = NO;
|
2008-10-23 20:15:20 +00:00
|
|
|
|
|
|
|
mGestureState = eGestureState_None;
|
|
|
|
mCumulativeMagnification = 0.0;
|
|
|
|
mCumulativeRotation = 0.0;
|
2009-09-16 22:06:16 +00:00
|
|
|
|
|
|
|
[self setFocusRingType:NSFocusRingTypeNone];
|
2005-06-16 12:49:43 +00:00
|
|
|
}
|
2002-03-09 22:58:13 +00:00
|
|
|
|
2006-10-25 22:45:22 +00:00
|
|
|
// register for things we'll take from other applications
|
2007-07-17 02:24:05 +00:00
|
|
|
PR_LOG(sCocoaLog, PR_LOG_ALWAYS, ("ChildView initWithFrame: registering drag types\n"));
|
2006-10-25 22:45:22 +00:00
|
|
|
[self registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType,
|
|
|
|
NSStringPboardType,
|
2008-11-07 01:08:35 +00:00
|
|
|
NSHTMLPboardType,
|
2006-10-25 22:45:22 +00:00
|
|
|
NSURLPboardType,
|
2007-07-17 02:24:05 +00:00
|
|
|
NSFilesPromisePboardType,
|
2007-05-29 05:06:12 +00:00
|
|
|
kWildcardPboardType,
|
2007-09-24 22:41:10 +00:00
|
|
|
kCorePboardType_url,
|
2007-09-28 01:50:09 +00:00
|
|
|
kCorePboardType_urld,
|
2007-09-24 22:41:10 +00:00
|
|
|
kCorePboardType_urln,
|
2006-10-25 22:45:22 +00:00
|
|
|
nil]];
|
2010-04-21 06:21:46 +00:00
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
|
|
selector:@selector(windowBecameMain:)
|
|
|
|
name:NSWindowDidBecomeMainNotification
|
|
|
|
object:nil];
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
|
|
selector:@selector(windowResignedMain:)
|
|
|
|
name:NSWindowDidResignMainNotification
|
|
|
|
object:nil];
|
2008-09-17 16:26:57 +00:00
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
2008-10-14 13:31:09 +00:00
|
|
|
selector:@selector(systemMetricsChanged)
|
2008-09-17 16:26:57 +00:00
|
|
|
name:NSControlTintDidChangeNotification
|
|
|
|
object:nil];
|
2008-09-22 09:09:32 +00:00
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
2008-10-14 13:31:09 +00:00
|
|
|
selector:@selector(systemMetricsChanged)
|
2008-09-22 09:09:32 +00:00
|
|
|
name:NSSystemColorsDidChangeNotification
|
|
|
|
object:nil];
|
2008-10-14 13:31:09 +00:00
|
|
|
[[NSDistributedNotificationCenter defaultCenter] addObserver:self
|
|
|
|
selector:@selector(systemMetricsChanged)
|
|
|
|
name:@"AppleAquaScrollBarVariantChanged"
|
|
|
|
object:nil
|
|
|
|
suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately];
|
2010-04-27 22:29:29 +00:00
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
|
|
selector:@selector(_surfaceNeedsUpdate:)
|
|
|
|
name:NSViewGlobalFrameDidChangeNotification
|
|
|
|
object:self];
|
2006-10-25 22:45:22 +00:00
|
|
|
|
2005-06-16 12:49:43 +00:00
|
|
|
return self;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
2002-03-09 22:43:04 +00:00
|
|
|
}
|
|
|
|
|
2005-06-16 12:49:43 +00:00
|
|
|
- (void)dealloc
|
2002-04-12 09:39:59 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2006-11-19 13:59:46 +00:00
|
|
|
[mPendingDirtyRects release];
|
2008-04-06 23:52:05 +00:00
|
|
|
[mLastMouseDownEvent release];
|
2009-10-21 07:02:13 +00:00
|
|
|
ChildViewMouseTracker::OnDestroyView(self);
|
2009-10-01 04:15:05 +00:00
|
|
|
#ifndef NP_NO_CARBON
|
2008-06-30 16:30:22 +00:00
|
|
|
if (mPluginTSMDoc)
|
|
|
|
::DeleteTSMDocument(mPluginTSMDoc);
|
2009-10-01 04:15:05 +00:00
|
|
|
#endif
|
2007-09-17 22:55:20 +00:00
|
|
|
|
2008-09-17 16:26:57 +00:00
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
2008-10-14 13:31:09 +00:00
|
|
|
[[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
|
2008-09-17 16:26:57 +00:00
|
|
|
|
2007-09-17 22:55:20 +00:00
|
|
|
[super dealloc];
|
|
|
|
|
2009-09-01 01:00:13 +00:00
|
|
|
#ifndef NP_NO_QUICKDRAW
|
2007-09-17 22:55:20 +00:00
|
|
|
// This sets the current port to _savePort.
|
|
|
|
// todo: Only do if a Quickdraw plugin is present in the hierarchy!
|
|
|
|
::SetPort(NULL);
|
2009-09-01 01:00:13 +00:00
|
|
|
#endif
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2002-04-12 09:39:59 +00:00
|
|
|
}
|
2001-11-06 15:35:24 +00:00
|
|
|
|
2010-04-21 06:21:46 +00:00
|
|
|
- (void)updatePluginTopLevelWindowStatus:(BOOL)hasMain
|
|
|
|
{
|
2010-04-25 20:58:03 +00:00
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
|
|
|
|
2010-04-21 06:21:46 +00:00
|
|
|
nsGUIEvent pluginEvent(PR_TRUE, NS_NON_RETARGETED_PLUGIN_EVENT, mGeckoChild);
|
|
|
|
NPCocoaEvent cocoaEvent;
|
|
|
|
InitNPCocoaEvent(&cocoaEvent);
|
|
|
|
cocoaEvent.type = NPCocoaEventWindowFocusChanged;
|
|
|
|
cocoaEvent.data.focus.hasFocus = hasMain;
|
|
|
|
pluginEvent.pluginEvent = &cocoaEvent;
|
|
|
|
mGeckoChild->DispatchWindowEvent(pluginEvent);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)windowBecameMain:(NSNotification*)inNotification
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
|
|
|
if (mIsPluginView && mPluginEventModel == NPEventModelCocoa) {
|
|
|
|
if ((NSWindow*)[inNotification object] == [self window]) {
|
|
|
|
[self updatePluginTopLevelWindowStatus:YES];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)windowResignedMain:(NSNotification*)inNotification
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
|
|
|
if (mIsPluginView && mPluginEventModel == NPEventModelCocoa) {
|
|
|
|
if ((NSWindow*)[inNotification object] == [self window]) {
|
|
|
|
[self updatePluginTopLevelWindowStatus:NO];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
|
|
|
|
2005-09-30 00:59:29 +00:00
|
|
|
- (void)widgetDestroyed
|
|
|
|
{
|
2009-10-01 02:52:50 +00:00
|
|
|
mGeckoChild->IME_OnDestroyView(self);
|
2005-09-30 00:59:29 +00:00
|
|
|
mGeckoChild = nsnull;
|
2008-10-21 22:15:08 +00:00
|
|
|
|
2007-10-10 12:19:47 +00:00
|
|
|
// Just in case we're destroyed abruptly and missed the draggingExited
|
|
|
|
// or performDragOperation message.
|
|
|
|
NS_IF_RELEASE(mDragService);
|
2005-09-30 00:59:29 +00:00
|
|
|
}
|
|
|
|
|
2006-12-20 02:13:57 +00:00
|
|
|
// mozView method, return our gecko child view widget. Note this does not AddRef.
|
2005-06-16 12:49:43 +00:00
|
|
|
- (nsIWidget*) widget
|
2001-11-06 15:35:24 +00:00
|
|
|
{
|
2007-07-08 07:08:04 +00:00
|
|
|
return static_cast<nsIWidget*>(mGeckoChild);
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
2008-10-14 13:31:09 +00:00
|
|
|
- (void)systemMetricsChanged
|
2008-09-17 16:26:57 +00:00
|
|
|
{
|
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsGUIEvent guiEvent(PR_TRUE, NS_THEMECHANGED, mGeckoChild);
|
|
|
|
mGeckoChild->DispatchWindowEvent(guiEvent);
|
|
|
|
}
|
|
|
|
|
2006-11-09 14:00:08 +00:00
|
|
|
- (void)setNeedsPendingDisplay
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2006-11-09 14:00:08 +00:00
|
|
|
mPendingFullDisplay = YES;
|
2010-06-09 04:11:42 +00:00
|
|
|
if (!mPendingDisplay) {
|
|
|
|
[self performSelector:@selector(processPendingRedraws) withObject:nil afterDelay:0];
|
|
|
|
mPendingDisplay = YES;
|
|
|
|
}
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2006-11-09 14:00:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setNeedsPendingDisplayInRect:(NSRect)invalidRect
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2006-11-09 14:00:08 +00:00
|
|
|
if (!mPendingDirtyRects)
|
|
|
|
mPendingDirtyRects = [[NSMutableArray alloc] initWithCapacity:1];
|
|
|
|
[mPendingDirtyRects addObject:[NSValue valueWithRect:invalidRect]];
|
2010-06-09 04:11:42 +00:00
|
|
|
if (!mPendingDisplay) {
|
|
|
|
[self performSelector:@selector(processPendingRedraws) withObject:nil afterDelay:0];
|
|
|
|
mPendingDisplay = YES;
|
|
|
|
}
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2006-11-09 14:00:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Clears the queue of any pending invalides
|
|
|
|
- (void)processPendingRedraws
|
2001-11-06 15:35:24 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2006-11-09 14:00:08 +00:00
|
|
|
if (mPendingFullDisplay) {
|
|
|
|
[self setNeedsDisplay:YES];
|
2005-06-16 12:49:43 +00:00
|
|
|
}
|
2010-06-09 04:11:42 +00:00
|
|
|
else if (mPendingDirtyRects) {
|
2006-11-09 14:00:08 +00:00
|
|
|
unsigned int count = [mPendingDirtyRects count];
|
|
|
|
for (unsigned int i = 0; i < count; ++i) {
|
|
|
|
[self setNeedsDisplayInRect:[[mPendingDirtyRects objectAtIndex:i] rectValue]];
|
|
|
|
}
|
2005-06-16 12:49:43 +00:00
|
|
|
}
|
2006-11-09 14:00:08 +00:00
|
|
|
mPendingFullDisplay = NO;
|
2010-06-09 04:11:42 +00:00
|
|
|
mPendingDisplay = NO;
|
2006-11-09 14:00:08 +00:00
|
|
|
[mPendingDirtyRects release];
|
|
|
|
mPendingDirtyRects = nil;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
2009-10-21 07:05:39 +00:00
|
|
|
- (void)setNeedsDisplayInRect:(NSRect)aRect
|
|
|
|
{
|
|
|
|
[super setNeedsDisplayInRect:aRect];
|
|
|
|
|
|
|
|
if ([[self window] isKindOfClass:[ToolbarWindow class]]) {
|
|
|
|
ToolbarWindow* window = (ToolbarWindow*)[self window];
|
|
|
|
if ([window drawsContentsIntoWindowFrame]) {
|
|
|
|
// Tell it to mark the rect in the titlebar as dirty.
|
|
|
|
NSView* borderView = [[window contentView] superview];
|
|
|
|
[window setTitlebarNeedsDisplayInRect:[self convertRect:aRect toView:borderView]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-13 04:51:36 +00:00
|
|
|
- (NSString*)description
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
|
|
|
|
2005-04-13 04:51:36 +00:00
|
|
|
return [NSString stringWithFormat:@"ChildView %p, gecko child %p, frame %@", self, mGeckoChild, NSStringFromRect([self frame])];
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
2005-04-13 04:51:36 +00:00
|
|
|
}
|
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
// Make the origin of this view the topLeft corner (gecko origin) rather
|
|
|
|
// than the bottomLeft corner (standard cocoa origin).
|
|
|
|
- (BOOL)isFlipped
|
|
|
|
{
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
2002-02-20 01:07:39 +00:00
|
|
|
- (BOOL)isOpaque
|
|
|
|
{
|
2009-11-13 22:58:15 +00:00
|
|
|
return [[self window] isOpaque];
|
2002-04-27 00:19:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
-(void)setIsPluginView:(BOOL)aIsPlugin
|
|
|
|
{
|
|
|
|
mIsPluginView = aIsPlugin;
|
2002-02-20 01:07:39 +00:00
|
|
|
}
|
2001-11-06 15:35:24 +00:00
|
|
|
|
2006-12-20 02:13:57 +00:00
|
|
|
|
2007-03-27 01:07:57 +00:00
|
|
|
-(BOOL)isPluginView
|
2002-12-13 08:43:18 +00:00
|
|
|
{
|
|
|
|
return mIsPluginView;
|
|
|
|
}
|
|
|
|
|
2009-09-01 01:00:13 +00:00
|
|
|
- (void)setPluginEventModel:(NPEventModel)eventModel
|
2009-08-27 00:29:47 +00:00
|
|
|
{
|
2009-09-01 01:00:13 +00:00
|
|
|
mPluginEventModel = eventModel;
|
2009-08-27 00:29:47 +00:00
|
|
|
}
|
|
|
|
|
2009-09-01 01:00:13 +00:00
|
|
|
- (NPEventModel)pluginEventModel;
|
2009-08-27 00:29:47 +00:00
|
|
|
{
|
2009-09-01 01:00:13 +00:00
|
|
|
return mPluginEventModel;
|
2009-08-27 00:29:47 +00:00
|
|
|
}
|
|
|
|
|
2007-08-02 23:01:32 +00:00
|
|
|
- (void)sendFocusEvent:(PRUint32)eventType
|
|
|
|
{
|
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsEventStatus status = nsEventStatus_eIgnore;
|
|
|
|
nsGUIEvent focusGuiEvent(PR_TRUE, eventType, mGeckoChild);
|
|
|
|
focusGuiEvent.time = PR_IntervalNow();
|
|
|
|
mGeckoChild->DispatchEvent(&focusGuiEvent, status);
|
|
|
|
}
|
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
// We accept key and mouse events, so don't keep passing them up the chain. Allow
|
2010-04-25 20:58:03 +00:00
|
|
|
// this to be a 'focused' widget for event dispatch.
|
2001-11-06 15:35:24 +00:00
|
|
|
- (BOOL)acceptsFirstResponder
|
|
|
|
{
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
2008-11-14 10:24:16 +00:00
|
|
|
- (void)viewWillMoveToWindow:(NSWindow *)newWindow
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
|
|
|
if (!newWindow)
|
|
|
|
HideChildPluginViews(self);
|
|
|
|
|
|
|
|
[super viewWillMoveToWindow:newWindow];
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
|
|
|
|
2009-09-15 21:56:44 +00:00
|
|
|
- (void)viewDidMoveToWindow
|
|
|
|
{
|
2010-01-24 06:00:39 +00:00
|
|
|
if (mPluginEventModel == NPEventModelCocoa &&
|
|
|
|
[self window] && [self isPluginView] && mGeckoChild) {
|
2009-09-15 21:56:44 +00:00
|
|
|
mGeckoChild->UpdatePluginPort();
|
|
|
|
}
|
|
|
|
|
|
|
|
[super viewDidMoveToWindow];
|
|
|
|
}
|
|
|
|
|
2006-11-09 14:00:08 +00:00
|
|
|
- (void)scrollRect:(NSRect)aRect by:(NSSize)offset
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2006-11-09 14:00:08 +00:00
|
|
|
// Update any pending dirty rects to reflect the new scroll position
|
|
|
|
if (mPendingDirtyRects) {
|
|
|
|
unsigned int count = [mPendingDirtyRects count];
|
|
|
|
for (unsigned int i = 0; i < count; ++i) {
|
|
|
|
NSRect oldRect = [[mPendingDirtyRects objectAtIndex:i] rectValue];
|
|
|
|
NSRect newRect = NSOffsetRect(oldRect, offset.width, offset.height);
|
|
|
|
[mPendingDirtyRects replaceObjectAtIndex:i
|
|
|
|
withObject:[NSValue valueWithRect:newRect]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
[super scrollRect:aRect by:offset];
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2006-11-09 14:00:08 +00:00
|
|
|
}
|
|
|
|
|
2002-12-13 08:43:18 +00:00
|
|
|
- (BOOL)mouseDownCanMoveWindow
|
|
|
|
{
|
|
|
|
return NO;
|
|
|
|
}
|
2001-11-06 15:35:24 +00:00
|
|
|
|
2005-07-06 19:51:31 +00:00
|
|
|
- (void)lockFocus
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2009-09-08 21:25:55 +00:00
|
|
|
#ifndef NP_NO_QUICKDRAW
|
2005-07-06 19:51:31 +00:00
|
|
|
// Set the current GrafPort to a "safe" port before calling [NSQuickDrawView lockFocus],
|
|
|
|
// so that the NSQuickDrawView stashes a pointer to this known-good port internally.
|
|
|
|
// It will set the port back to this port on destruction.
|
2007-09-17 22:55:20 +00:00
|
|
|
::SetPort(NULL); // todo: only do if a Quickdraw plugin is present in the hierarchy!
|
2009-09-08 21:25:55 +00:00
|
|
|
#endif
|
|
|
|
|
2005-07-06 19:51:31 +00:00
|
|
|
[super lockFocus];
|
2008-02-20 23:47:05 +00:00
|
|
|
|
2010-04-27 22:29:29 +00:00
|
|
|
if (mContext) {
|
|
|
|
if ([mContext view] != self) {
|
|
|
|
[mContext setView:self];
|
|
|
|
}
|
|
|
|
|
|
|
|
[mContext makeCurrentContext];
|
|
|
|
}
|
|
|
|
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2005-07-06 19:51:31 +00:00
|
|
|
}
|
|
|
|
|
2010-01-13 16:08:06 +00:00
|
|
|
// Unified toolbar height resetting
|
|
|
|
// This fixes the following problem:
|
|
|
|
// The window gets notified about the height of its unified toolbar when the
|
|
|
|
// toolbar is drawn. But when the toolbar suddenly vanishes, it's not drawn,
|
|
|
|
// and the window is never notified about its absence.
|
|
|
|
// So we bracket drawing operations to the pixel strip under the title bar
|
|
|
|
// with notifications to the window.
|
|
|
|
static BOOL DrawingAtWindowTop(CGContextRef aContext)
|
|
|
|
{
|
|
|
|
// Ignore all non-trivial transforms.
|
|
|
|
CGAffineTransform ctm = CGContextGetCTM(aContext);
|
|
|
|
if (ctm.a != 1.0f || ctm.b != 0.0f || ctm.c != 0.0f || ctm.d != -1.0f)
|
|
|
|
return NO;
|
|
|
|
|
|
|
|
// ctm.ty contains the vertical offset from the window's bottom edge.
|
|
|
|
return ctm.ty >= [[[[NSView focusView] window] contentView] bounds].size.height;
|
|
|
|
}
|
|
|
|
|
2010-03-01 08:03:49 +00:00
|
|
|
- (BOOL)beginMaybeResetUnifiedToolbar:(nsIntRegion*)aRegion context:(CGContextRef)aContext
|
2010-01-13 16:08:06 +00:00
|
|
|
{
|
|
|
|
if (![[self window] isKindOfClass:[ToolbarWindow class]] ||
|
|
|
|
!DrawingAtWindowTop(aContext) ||
|
2010-03-01 08:03:49 +00:00
|
|
|
!aRegion->Contains(nsIntRect(0, 0, (int)[self bounds].size.width, 1)))
|
2010-01-13 16:08:06 +00:00
|
|
|
return NO;
|
|
|
|
|
|
|
|
[(ToolbarWindow*)[self window] beginMaybeResetUnifiedToolbar];
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)endMaybeResetUnifiedToolbar:(BOOL)aReset
|
|
|
|
{
|
|
|
|
if (aReset) {
|
|
|
|
[(ToolbarWindow*)[self window] endMaybeResetUnifiedToolbar];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-27 22:29:29 +00:00
|
|
|
-(void)update
|
|
|
|
{
|
|
|
|
if (mContext) {
|
|
|
|
[mContext update];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) _surfaceNeedsUpdate:(NSNotification*)notification
|
|
|
|
{
|
|
|
|
[self update];
|
|
|
|
}
|
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
// The display system has told us that a portion of our view is dirty. Tell
|
|
|
|
// gecko to paint it
|
|
|
|
- (void)drawRect:(NSRect)aRect
|
|
|
|
{
|
2009-10-21 07:05:39 +00:00
|
|
|
CGContextRef cgContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
|
|
|
|
[self drawRect:aRect inContext:cgContext];
|
|
|
|
|
2009-12-11 21:53:22 +00:00
|
|
|
// If we're a transparent window and our contents have changed, we need
|
2009-10-21 07:05:39 +00:00
|
|
|
// to make sure the shadow is updated to the new contents.
|
2009-12-11 21:53:22 +00:00
|
|
|
if ([[self window] isKindOfClass:[BaseWindow class]]) {
|
|
|
|
[(BaseWindow*)[self window] deferredInvalidateShadow];
|
|
|
|
}
|
2009-10-21 07:05:39 +00:00
|
|
|
}
|
2008-02-20 23:47:05 +00:00
|
|
|
|
2009-10-21 07:05:39 +00:00
|
|
|
- (void)drawRect:(NSRect)aRect inContext:(CGContextRef)aContext
|
|
|
|
{
|
2002-02-17 19:09:07 +00:00
|
|
|
PRBool isVisible;
|
2008-09-16 08:21:06 +00:00
|
|
|
if (!mGeckoChild || NS_FAILED(mGeckoChild->IsVisible(isVisible)) ||
|
2009-08-03 23:13:08 +00:00
|
|
|
!isVisible)
|
2002-02-17 19:09:07 +00:00
|
|
|
return;
|
2006-02-22 01:31:14 +00:00
|
|
|
|
2009-10-21 07:05:39 +00:00
|
|
|
#ifdef DEBUG_UPDATE
|
2009-01-15 03:27:09 +00:00
|
|
|
nsIntRect geckoBounds;
|
2006-02-22 01:31:14 +00:00
|
|
|
mGeckoChild->GetBounds(geckoBounds);
|
2006-08-30 22:06:44 +00:00
|
|
|
|
|
|
|
fprintf (stderr, "---- Update[%p][%p] [%f %f %f %f] cgc: %p\n gecko bounds: [%d %d %d %d]\n",
|
|
|
|
self, mGeckoChild,
|
2009-10-21 07:05:39 +00:00
|
|
|
aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height, aContext,
|
2006-08-30 22:06:44 +00:00
|
|
|
geckoBounds.x, geckoBounds.y, geckoBounds.width, geckoBounds.height);
|
2006-02-22 01:31:14 +00:00
|
|
|
|
2009-10-21 07:05:39 +00:00
|
|
|
CGAffineTransform xform = CGContextGetCTM(aContext);
|
2006-08-30 22:06:44 +00:00
|
|
|
fprintf (stderr, " xform in: [%f %f %f %f %f %f]\n", xform.a, xform.b, xform.c, xform.d, xform.tx, xform.ty);
|
|
|
|
#endif
|
2010-03-01 08:03:49 +00:00
|
|
|
// Create the event so we can fill in its region
|
|
|
|
nsPaintEvent paintEvent(PR_TRUE, NS_PAINT, mGeckoChild);
|
2006-11-28 00:11:42 +00:00
|
|
|
|
2006-02-22 01:31:14 +00:00
|
|
|
const NSRect *rects;
|
2009-09-01 01:00:13 +00:00
|
|
|
NSInteger count, i;
|
2009-10-21 07:05:39 +00:00
|
|
|
[[NSView focusView] getRectsBeingDrawn:&rects count:&count];
|
2009-02-16 01:06:52 +00:00
|
|
|
if (count < MAX_RECTS_IN_REGION) {
|
|
|
|
for (i = 0; i < count; ++i) {
|
2009-10-21 07:05:39 +00:00
|
|
|
// Add the rect to the region.
|
|
|
|
const NSRect& r = [self convertRect:rects[i] fromView:[NSView focusView]];
|
2010-03-01 08:03:49 +00:00
|
|
|
paintEvent.region.Or(paintEvent.region,
|
|
|
|
nsIntRect(r.origin.x, r.origin.y, r.size.width, r.size.height));
|
2009-02-16 01:06:52 +00:00
|
|
|
}
|
|
|
|
} else {
|
2010-03-01 08:03:49 +00:00
|
|
|
paintEvent.region =
|
|
|
|
nsIntRect(aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height);
|
2006-02-22 01:31:14 +00:00
|
|
|
}
|
2009-07-22 00:44:55 +00:00
|
|
|
|
|
|
|
// Subtract child view rectangles from the region
|
|
|
|
NSArray* subviews = [self subviews];
|
|
|
|
for (int i = 0; i < int([subviews count]); ++i) {
|
|
|
|
NSView* view = [subviews objectAtIndex:i];
|
|
|
|
if (![view isKindOfClass:[ChildView class]] || [view isHidden])
|
|
|
|
continue;
|
|
|
|
NSRect frame = [view frame];
|
2010-03-01 08:03:49 +00:00
|
|
|
paintEvent.region.Sub(paintEvent.region,
|
|
|
|
nsIntRect(frame.origin.x, frame.origin.y, frame.size.width, frame.size.height));
|
2009-07-22 00:44:55 +00:00
|
|
|
}
|
2010-04-27 22:29:29 +00:00
|
|
|
|
|
|
|
if (mGeckoChild->GetLayerManager()->GetBackendType() == LayerManager::LAYERS_OPENGL) {
|
|
|
|
LayerManagerOGL *manager = static_cast<LayerManagerOGL*>(mGeckoChild->GetLayerManager());
|
|
|
|
manager->SetClippingRegion(paintEvent.region);
|
|
|
|
if (!mContext) {
|
2010-05-18 04:04:22 +00:00
|
|
|
mContext = (NSOpenGLContext *)manager->gl()->GetNativeData(mozilla::gl::GLContext::NativeGLContext);
|
2010-04-27 22:29:29 +00:00
|
|
|
}
|
|
|
|
[mContext makeCurrentContext];
|
|
|
|
mGeckoChild->DispatchWindowEvent(paintEvent);
|
|
|
|
[mContext flushBuffer];
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create Cairo objects.
|
|
|
|
NSSize bufferSize = [self bounds].size;
|
|
|
|
nsRefPtr<gfxQuartzSurface> targetSurface =
|
|
|
|
new gfxQuartzSurface(aContext, gfxSize(bufferSize.width, bufferSize.height));
|
|
|
|
|
|
|
|
nsRefPtr<gfxContext> targetContext = new gfxContext(targetSurface);
|
2009-07-22 00:44:55 +00:00
|
|
|
|
2009-10-21 07:05:39 +00:00
|
|
|
// Set up the clip region.
|
2010-03-01 08:03:49 +00:00
|
|
|
nsIntRegionRectIterator iter(paintEvent.region);
|
|
|
|
targetContext->NewPath();
|
|
|
|
for (;;) {
|
|
|
|
const nsIntRect* r = iter.Next();
|
|
|
|
if (!r)
|
|
|
|
break;
|
|
|
|
targetContext->Rectangle(gfxRect(r->x, r->y, r->width, r->height));
|
2009-10-21 07:05:39 +00:00
|
|
|
}
|
|
|
|
targetContext->Clip();
|
|
|
|
|
2010-03-01 08:03:49 +00:00
|
|
|
BOOL resetUnifiedToolbar =
|
|
|
|
[self beginMaybeResetUnifiedToolbar:&paintEvent.region context:aContext];
|
2010-01-13 16:08:06 +00:00
|
|
|
|
2008-04-08 04:38:52 +00:00
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
2010-03-01 08:03:49 +00:00
|
|
|
PRBool painted;
|
|
|
|
{
|
|
|
|
nsBaseWidget::AutoLayerManagerSetup setupLayerManager(mGeckoChild, targetContext);
|
|
|
|
painted = mGeckoChild->DispatchWindowEvent(paintEvent);
|
|
|
|
}
|
|
|
|
|
2009-11-06 10:17:45 +00:00
|
|
|
if (!painted && [self isOpaque]) {
|
|
|
|
// Gecko refused to draw, but we've claimed to be opaque, so we have to
|
|
|
|
// draw something--fill with white.
|
|
|
|
CGContextSetRGBFillColor(aContext, 1, 1, 1, 1);
|
|
|
|
CGContextFillRect(aContext, CGRectMake(aRect.origin.x, aRect.origin.y,
|
|
|
|
aRect.size.width, aRect.size.height));
|
|
|
|
}
|
2010-01-13 16:08:06 +00:00
|
|
|
|
|
|
|
[self endMaybeResetUnifiedToolbar:resetUnifiedToolbar];
|
|
|
|
|
2006-08-30 22:06:44 +00:00
|
|
|
// note that the cairo surface *MUST* be destroyed at this point,
|
|
|
|
// or bad things will happen (since we can't keep the cgContext around
|
|
|
|
// beyond this drawRect message handler)
|
|
|
|
|
|
|
|
#ifdef DEBUG_UPDATE
|
|
|
|
fprintf (stderr, "---- update done ----\n");
|
|
|
|
|
2007-01-31 18:43:34 +00:00
|
|
|
#if 0
|
2009-10-21 07:05:39 +00:00
|
|
|
CGContextSetRGBStrokeColor (aContext,
|
2006-08-30 22:06:44 +00:00
|
|
|
((((unsigned long)self) & 0xff)) / 255.0,
|
|
|
|
((((unsigned long)self) & 0xff00) >> 8) / 255.0,
|
|
|
|
((((unsigned long)self) & 0xff0000) >> 16) / 255.0,
|
|
|
|
0.5);
|
2007-01-31 18:43:34 +00:00
|
|
|
#endif
|
2009-10-21 07:05:39 +00:00
|
|
|
CGContextSetRGBStrokeColor(aContext, 1, 0, 0, 0.8);
|
|
|
|
CGContextSetLineWidth(aContext, 4.0);
|
|
|
|
CGContextStrokeRect(aContext,
|
|
|
|
CGRectMake(aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height));
|
2006-08-30 22:06:44 +00:00
|
|
|
#endif
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
2009-11-13 23:03:46 +00:00
|
|
|
- (void)viewWillDraw
|
|
|
|
{
|
2009-12-11 19:31:42 +00:00
|
|
|
if (mGeckoChild) {
|
|
|
|
nsPaintEvent paintEvent(PR_TRUE, NS_WILL_PAINT, mGeckoChild);
|
|
|
|
mGeckoChild->DispatchWindowEvent(paintEvent);
|
|
|
|
}
|
|
|
|
[super viewWillDraw];
|
2009-11-13 23:03:46 +00:00
|
|
|
}
|
|
|
|
|
2007-07-18 00:07:36 +00:00
|
|
|
// Allows us to turn off setting up the clip region
|
2004-05-07 07:17:41 +00:00
|
|
|
// before each drawRect. We already clip within gecko.
|
|
|
|
- (BOOL)wantsDefaultClipping
|
|
|
|
{
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
2004-02-18 16:18:38 +00:00
|
|
|
#if USE_CLICK_HOLD_CONTEXTMENU
|
2004-01-15 19:01:49 +00:00
|
|
|
//
|
|
|
|
// -clickHoldCallback:
|
|
|
|
//
|
|
|
|
// called from a timer two seconds after a mouse down to see if we should display
|
|
|
|
// a context menu (click-hold). |anEvent| is the original mouseDown event. If we're
|
|
|
|
// still in that mouseDown by this time, put up the context menu, otherwise just
|
|
|
|
// fuhgeddaboutit. |anEvent| has been retained by the OS until after this callback
|
|
|
|
// fires so we're ok there.
|
|
|
|
//
|
2004-02-18 16:18:38 +00:00
|
|
|
// This code currently messes in a bunch of edge cases (bugs 234751, 232964, 232314)
|
|
|
|
// so removing it until we get it straightened out.
|
|
|
|
//
|
2004-01-15 19:01:49 +00:00
|
|
|
- (void)clickHoldCallback:(id)theEvent;
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2004-01-15 19:01:49 +00:00
|
|
|
if( theEvent == [NSApp currentEvent] ) {
|
|
|
|
// we're still in the middle of the same mousedown event here, activate
|
|
|
|
// click-hold context menu by triggering the right mouseDown action.
|
|
|
|
NSEvent* clickHoldEvent = [NSEvent mouseEventWithType:NSRightMouseDown
|
|
|
|
location:[theEvent locationInWindow]
|
2010-02-23 23:30:39 +00:00
|
|
|
modifierFlags:[theEvent modifierFlags]
|
2004-01-15 19:01:49 +00:00
|
|
|
timestamp:[theEvent timestamp]
|
|
|
|
windowNumber:[theEvent windowNumber]
|
|
|
|
context:[theEvent context]
|
|
|
|
eventNumber:[theEvent eventNumber]
|
|
|
|
clickCount:[theEvent clickCount]
|
|
|
|
pressure:[theEvent pressure]];
|
|
|
|
[self rightMouseDown:clickHoldEvent];
|
|
|
|
}
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2004-01-15 19:01:49 +00:00
|
|
|
}
|
2004-02-18 16:18:38 +00:00
|
|
|
#endif
|
2004-01-15 19:01:49 +00:00
|
|
|
|
2007-07-17 20:29:39 +00:00
|
|
|
// If we've just created a non-native context menu, we need to mark it as
|
|
|
|
// such and let the OS (and other programs) know when it opens and closes
|
|
|
|
// (this is how the OS knows to close other programs' context menus when
|
|
|
|
// ours open). We send the initial notification here, but others are sent
|
|
|
|
// in nsCocoaWindow::Show().
|
|
|
|
- (void)maybeInitContextMenuTracking
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-07-17 20:29:39 +00:00
|
|
|
if (!gRollupWidget)
|
|
|
|
return;
|
2008-03-04 08:06:47 +00:00
|
|
|
|
|
|
|
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
|
|
|
if (prefs) {
|
|
|
|
PRBool useNativeContextMenus;
|
|
|
|
nsresult rv = prefs->GetBoolPref("ui.use_native_popup_windows", &useNativeContextMenus);
|
|
|
|
if (NS_SUCCEEDED(rv) && useNativeContextMenus)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-11-07 07:53:24 +00:00
|
|
|
NSWindow *popupWindow = (NSWindow*)gRollupWidget->GetNativeData(NS_NATIVE_WINDOW);
|
|
|
|
if (!popupWindow || ![popupWindow isKindOfClass:[PopupWindow class]])
|
2007-07-17 20:29:39 +00:00
|
|
|
return;
|
2007-11-07 07:53:24 +00:00
|
|
|
|
2007-07-17 20:29:39 +00:00
|
|
|
[[NSDistributedNotificationCenter defaultCenter]
|
|
|
|
postNotificationName:@"com.apple.HIToolbox.beginMenuTrackingNotification"
|
|
|
|
object:@"org.mozilla.gecko.PopupWindow"];
|
2007-11-07 07:53:24 +00:00
|
|
|
[(PopupWindow*)popupWindow setIsContextMenu:YES];
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2007-07-17 20:29:39 +00:00
|
|
|
}
|
|
|
|
|
2009-05-14 20:13:22 +00:00
|
|
|
// Returns true if the event should no longer be processed, false otherwise.
|
|
|
|
// This does not return whether or not anything was rolled up.
|
2007-11-26 23:19:04 +00:00
|
|
|
- (BOOL)maybeRollup:(NSEvent*)theEvent
|
2001-11-06 15:35:24 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
|
|
|
|
2009-05-14 20:13:22 +00:00
|
|
|
BOOL consumeEvent = NO;
|
|
|
|
|
2007-11-26 23:19:04 +00:00
|
|
|
if (gRollupWidget && gRollupListener) {
|
|
|
|
NSWindow* currentPopup = static_cast<NSWindow*>(gRollupWidget->GetNativeData(NS_NATIVE_WINDOW));
|
2007-12-05 23:17:08 +00:00
|
|
|
if (!nsCocoaUtils::IsEventOverWindow(theEvent, currentPopup)) {
|
2009-05-14 20:13:22 +00:00
|
|
|
// event is not over the rollup window, default is to roll up
|
|
|
|
PRBool shouldRollup = PR_TRUE;
|
|
|
|
|
|
|
|
// check to see if scroll events should roll up the popup
|
2007-11-26 23:19:04 +00:00
|
|
|
if ([theEvent type] == NSScrollWheel) {
|
2009-05-14 20:13:22 +00:00
|
|
|
gRollupListener->ShouldRollupOnMouseWheelEvent(&shouldRollup);
|
|
|
|
// always consume scroll events that aren't over the popup
|
|
|
|
consumeEvent = YES;
|
2007-11-26 23:19:04 +00:00
|
|
|
}
|
2009-05-14 20:13:22 +00:00
|
|
|
|
2007-11-26 23:19:04 +00:00
|
|
|
// if we're dealing with menus, we probably have submenus and
|
2008-04-06 23:52:05 +00:00
|
|
|
// we don't want to rollup if the click is in a parent menu of
|
2007-11-26 23:19:04 +00:00
|
|
|
// the current submenu
|
2009-06-12 18:23:16 +00:00
|
|
|
PRUint32 popupsToRollup = PR_UINT32_MAX;
|
2009-12-22 23:49:33 +00:00
|
|
|
if (gMenuRollup) {
|
2008-01-17 06:57:13 +00:00
|
|
|
nsAutoTArray<nsIWidget*, 5> widgetChain;
|
2009-12-22 23:49:33 +00:00
|
|
|
gMenuRollup->GetSubmenuWidgetChain(&widgetChain);
|
|
|
|
PRUint32 sameTypeCount = gMenuRollup->GetSubmenuWidgetChain(&widgetChain);
|
2008-01-17 07:06:43 +00:00
|
|
|
for (PRUint32 i = 0; i < widgetChain.Length(); i++) {
|
|
|
|
nsIWidget* widget = widgetChain[i];
|
|
|
|
NSWindow* currWindow = (NSWindow*)widget->GetNativeData(NS_NATIVE_WINDOW);
|
|
|
|
if (nsCocoaUtils::IsEventOverWindow(theEvent, currWindow)) {
|
2010-05-13 12:19:50 +00:00
|
|
|
// don't roll up if the mouse event occurred within a menu of the
|
|
|
|
// same type. If the mouse event occurred in a menu higher than
|
2009-06-12 18:23:16 +00:00
|
|
|
// that, roll up, but pass the number of popups to Rollup so
|
|
|
|
// that only those of the same type close up.
|
|
|
|
if (i < sameTypeCount) {
|
|
|
|
shouldRollup = PR_FALSE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
popupsToRollup = sameTypeCount;
|
|
|
|
}
|
2008-01-17 07:06:43 +00:00
|
|
|
break;
|
|
|
|
}
|
2009-05-14 20:13:22 +00:00
|
|
|
}
|
|
|
|
}
|
2007-11-07 07:53:24 +00:00
|
|
|
|
2009-05-14 20:13:22 +00:00
|
|
|
if (shouldRollup) {
|
2009-06-12 18:23:16 +00:00
|
|
|
gRollupListener->Rollup(popupsToRollup, nsnull);
|
2009-05-14 20:13:22 +00:00
|
|
|
consumeEvent = (BOOL)gConsumeRollupEvent;
|
2006-04-12 15:10:00 +00:00
|
|
|
}
|
2006-04-06 19:14:02 +00:00
|
|
|
}
|
|
|
|
}
|
2007-11-26 23:19:04 +00:00
|
|
|
|
2009-05-14 20:13:22 +00:00
|
|
|
return consumeEvent;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO);
|
2007-11-26 23:19:04 +00:00
|
|
|
}
|
|
|
|
|
2008-10-23 20:15:20 +00:00
|
|
|
/*
|
|
|
|
* XXX - The swipeWithEvent, beginGestureWithEvent, magnifyWithEvent,
|
|
|
|
* rotateWithEvent, and endGestureWithEvent methods are part of a
|
|
|
|
* PRIVATE interface exported by nsResponder and reverse-engineering
|
|
|
|
* was necessary to obtain the methods' prototypes. Thus, Apple may
|
|
|
|
* change the interface in the future without notice.
|
|
|
|
*
|
|
|
|
* The prototypes were obtained from the following link:
|
|
|
|
* http://cocoadex.com/2008/02/nsevent-modifications-swipe-ro.html
|
|
|
|
*/
|
|
|
|
|
|
|
|
- (void)swipeWithEvent:(NSEvent *)anEvent
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
|
|
|
if (!anEvent || !mGeckoChild)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
|
|
|
|
|
|
|
float deltaX = [anEvent deltaX]; // left=1.0, right=-1.0
|
|
|
|
float deltaY = [anEvent deltaY]; // up=1.0, down=-1.0
|
|
|
|
|
|
|
|
// Setup the "swipe" event.
|
|
|
|
nsSimpleGestureEvent geckoEvent(PR_TRUE, NS_SIMPLE_GESTURE_SWIPE, mGeckoChild, 0, 0.0);
|
2009-01-03 12:40:26 +00:00
|
|
|
[self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent];
|
2008-10-23 20:15:20 +00:00
|
|
|
|
|
|
|
// Record the left/right direction.
|
|
|
|
if (deltaX > 0.0)
|
|
|
|
geckoEvent.direction |= nsIDOMSimpleGestureEvent::DIRECTION_LEFT;
|
|
|
|
else if (deltaX < 0.0)
|
|
|
|
geckoEvent.direction |= nsIDOMSimpleGestureEvent::DIRECTION_RIGHT;
|
|
|
|
|
|
|
|
// Record the up/down direction.
|
|
|
|
if (deltaY > 0.0)
|
|
|
|
geckoEvent.direction |= nsIDOMSimpleGestureEvent::DIRECTION_UP;
|
|
|
|
else if (deltaY < 0.0)
|
|
|
|
geckoEvent.direction |= nsIDOMSimpleGestureEvent::DIRECTION_DOWN;
|
|
|
|
|
|
|
|
// Send the event.
|
|
|
|
mGeckoChild->DispatchWindowEvent(geckoEvent);
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)beginGestureWithEvent:(NSEvent *)anEvent
|
|
|
|
{
|
|
|
|
NS_ASSERTION(mGestureState == eGestureState_None, "mGestureState should be eGestureState_None");
|
|
|
|
|
|
|
|
if (!anEvent)
|
|
|
|
return;
|
|
|
|
|
|
|
|
mGestureState = eGestureState_StartGesture;
|
|
|
|
mCumulativeMagnification = 0;
|
|
|
|
mCumulativeRotation = 0.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)magnifyWithEvent:(NSEvent *)anEvent
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
|
|
|
if (!anEvent || !mGeckoChild)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
|
|
|
|
|
|
|
float deltaZ = [anEvent deltaZ];
|
|
|
|
|
|
|
|
PRUint32 msg;
|
|
|
|
switch (mGestureState) {
|
|
|
|
case eGestureState_StartGesture:
|
|
|
|
msg = NS_SIMPLE_GESTURE_MAGNIFY_START;
|
|
|
|
mGestureState = eGestureState_MagnifyGesture;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eGestureState_MagnifyGesture:
|
|
|
|
msg = NS_SIMPLE_GESTURE_MAGNIFY_UPDATE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eGestureState_None:
|
|
|
|
case eGestureState_RotateGesture:
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Setup the event.
|
|
|
|
nsSimpleGestureEvent geckoEvent(PR_TRUE, msg, mGeckoChild, 0, deltaZ);
|
2009-01-03 12:40:26 +00:00
|
|
|
[self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent];
|
2008-10-23 20:15:20 +00:00
|
|
|
|
|
|
|
// Send the event.
|
|
|
|
mGeckoChild->DispatchWindowEvent(geckoEvent);
|
|
|
|
|
|
|
|
// Keep track of the cumulative magnification for the final "magnify" event.
|
|
|
|
mCumulativeMagnification += deltaZ;
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)rotateWithEvent:(NSEvent *)anEvent
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
|
|
|
if (!anEvent || !mGeckoChild)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
|
|
|
|
|
|
|
float rotation = [anEvent rotation];
|
|
|
|
|
|
|
|
PRUint32 msg;
|
|
|
|
switch (mGestureState) {
|
|
|
|
case eGestureState_StartGesture:
|
|
|
|
msg = NS_SIMPLE_GESTURE_ROTATE_START;
|
|
|
|
mGestureState = eGestureState_RotateGesture;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eGestureState_RotateGesture:
|
|
|
|
msg = NS_SIMPLE_GESTURE_ROTATE_UPDATE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eGestureState_None:
|
|
|
|
case eGestureState_MagnifyGesture:
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Setup the event.
|
|
|
|
nsSimpleGestureEvent geckoEvent(PR_TRUE, msg, mGeckoChild, 0, 0.0);
|
2009-01-03 12:40:26 +00:00
|
|
|
[self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent];
|
2008-10-23 20:15:20 +00:00
|
|
|
geckoEvent.delta = -rotation;
|
|
|
|
if (rotation > 0.0) {
|
2009-04-02 19:34:31 +00:00
|
|
|
geckoEvent.direction = nsIDOMSimpleGestureEvent::ROTATION_COUNTERCLOCKWISE;
|
2008-10-23 20:15:20 +00:00
|
|
|
} else {
|
2009-04-02 19:34:31 +00:00
|
|
|
geckoEvent.direction = nsIDOMSimpleGestureEvent::ROTATION_CLOCKWISE;
|
2008-10-23 20:15:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Send the event.
|
|
|
|
mGeckoChild->DispatchWindowEvent(geckoEvent);
|
|
|
|
|
|
|
|
// Keep track of the cumulative rotation for the final "rotate" event.
|
|
|
|
mCumulativeRotation += rotation;
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)endGestureWithEvent:(NSEvent *)anEvent
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
|
|
|
if (!anEvent || !mGeckoChild) {
|
|
|
|
// Clear the gestures state if we cannot send an event.
|
|
|
|
mGestureState = eGestureState_None;
|
|
|
|
mCumulativeMagnification = 0.0;
|
|
|
|
mCumulativeRotation = 0.0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
|
|
|
|
|
|
|
switch (mGestureState) {
|
|
|
|
case eGestureState_MagnifyGesture:
|
|
|
|
{
|
|
|
|
// Setup the "magnify" event.
|
|
|
|
nsSimpleGestureEvent geckoEvent(PR_TRUE, NS_SIMPLE_GESTURE_MAGNIFY,
|
|
|
|
mGeckoChild, 0, mCumulativeMagnification);
|
2009-01-03 12:40:26 +00:00
|
|
|
[self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent];
|
2008-10-23 20:15:20 +00:00
|
|
|
|
|
|
|
// Send the event.
|
|
|
|
mGeckoChild->DispatchWindowEvent(geckoEvent);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eGestureState_RotateGesture:
|
|
|
|
{
|
|
|
|
// Setup the "rotate" event.
|
|
|
|
nsSimpleGestureEvent geckoEvent(PR_TRUE, NS_SIMPLE_GESTURE_ROTATE, mGeckoChild, 0, 0.0);
|
2009-01-03 12:40:26 +00:00
|
|
|
[self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent];
|
2008-10-23 20:15:20 +00:00
|
|
|
geckoEvent.delta = -mCumulativeRotation;
|
|
|
|
if (mCumulativeRotation > 0.0) {
|
2009-04-02 19:34:31 +00:00
|
|
|
geckoEvent.direction = nsIDOMSimpleGestureEvent::ROTATION_COUNTERCLOCKWISE;
|
2008-10-23 20:15:20 +00:00
|
|
|
} else {
|
2009-04-02 19:34:31 +00:00
|
|
|
geckoEvent.direction = nsIDOMSimpleGestureEvent::ROTATION_CLOCKWISE;
|
2008-10-23 20:15:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Send the event.
|
|
|
|
mGeckoChild->DispatchWindowEvent(geckoEvent);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eGestureState_None:
|
|
|
|
case eGestureState_StartGesture:
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clear the gestures state.
|
|
|
|
mGestureState = eGestureState_None;
|
|
|
|
mCumulativeMagnification = 0.0;
|
|
|
|
mCumulativeRotation = 0.0;
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
|
|
|
|
2009-12-11 21:57:40 +00:00
|
|
|
// Returning NO from this method only disallows ordering on mousedown - in order
|
|
|
|
// to prevent it for mouseup too, we need to call [NSApp preventWindowOrdering]
|
|
|
|
// when handling the mousedown event.
|
|
|
|
- (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent*)aEvent
|
|
|
|
{
|
|
|
|
// Always using system-provided window ordering for normal windows.
|
|
|
|
if (![[self window] isKindOfClass:[PopupWindow class]])
|
|
|
|
return NO;
|
|
|
|
|
|
|
|
// Don't reorder when we're already accepting mouse events, for example
|
|
|
|
// because we're a context menu.
|
|
|
|
return ChildViewMouseTracker::WindowAcceptsEvent([self window], aEvent);
|
|
|
|
}
|
|
|
|
|
2007-11-26 23:19:04 +00:00
|
|
|
- (void)mouseDown:(NSEvent*)theEvent
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2009-12-11 21:57:40 +00:00
|
|
|
if ([self shouldDelayWindowOrderingForEvent:theEvent]) {
|
|
|
|
[NSApp preventWindowOrdering];
|
|
|
|
}
|
|
|
|
|
2008-04-06 23:52:05 +00:00
|
|
|
// If we've already seen this event due to direct dispatch from menuForEvent:
|
|
|
|
// just bail; if not, remember it.
|
|
|
|
if (mLastMouseDownEvent == theEvent) {
|
|
|
|
[mLastMouseDownEvent release];
|
|
|
|
mLastMouseDownEvent = nil;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
[mLastMouseDownEvent release];
|
|
|
|
mLastMouseDownEvent = [theEvent retain];
|
|
|
|
}
|
|
|
|
|
2009-11-06 10:21:41 +00:00
|
|
|
[gLastDragMouseDownEvent release];
|
|
|
|
gLastDragMouseDownEvent = [theEvent retain];
|
|
|
|
|
2008-04-08 04:38:52 +00:00
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
2008-01-15 23:11:55 +00:00
|
|
|
|
2009-09-23 02:31:37 +00:00
|
|
|
if ([self maybeRollup:theEvent] ||
|
|
|
|
!ChildViewMouseTracker::WindowAcceptsEvent([self window], theEvent))
|
2007-11-26 23:19:04 +00:00
|
|
|
return;
|
|
|
|
|
2004-02-18 16:18:38 +00:00
|
|
|
#if USE_CLICK_HOLD_CONTEXTMENU
|
2004-01-15 19:01:49 +00:00
|
|
|
// fire off timer to check for click-hold after two seconds. retains |theEvent|
|
|
|
|
[self performSelector:@selector(clickHoldCallback:) withObject:theEvent afterDelay:2.0];
|
2004-02-18 16:18:38 +00:00
|
|
|
#endif
|
2004-01-15 19:01:49 +00:00
|
|
|
|
2007-04-19 20:18:46 +00:00
|
|
|
// in order to send gecko events we'll need a gecko widget
|
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
|
|
|
|
2010-02-23 23:30:39 +00:00
|
|
|
NSUInteger modifierFlags = [theEvent modifierFlags];
|
2009-08-27 00:29:47 +00:00
|
|
|
|
2007-02-27 17:23:58 +00:00
|
|
|
nsMouseEvent geckoEvent(PR_TRUE, NS_MOUSE_BUTTON_DOWN, nsnull, nsMouseEvent::eReal);
|
2007-06-12 20:28:26 +00:00
|
|
|
[self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
|
2001-11-06 15:35:24 +00:00
|
|
|
geckoEvent.clickCount = [theEvent clickCount];
|
2009-08-27 00:29:47 +00:00
|
|
|
if (modifierFlags & NSControlKeyMask)
|
2006-12-05 18:38:17 +00:00
|
|
|
geckoEvent.button = nsMouseEvent::eRightButton;
|
|
|
|
else
|
|
|
|
geckoEvent.button = nsMouseEvent::eLeftButton;
|
2002-04-27 00:19:49 +00:00
|
|
|
|
2009-08-27 00:29:47 +00:00
|
|
|
// Create event for use by plugins.
|
|
|
|
// This is going to our child view so we don't need to look up the destination
|
|
|
|
// event type.
|
2009-09-01 01:00:13 +00:00
|
|
|
#ifndef NP_NO_CARBON
|
2009-08-27 00:29:47 +00:00
|
|
|
EventRecord carbonEvent;
|
2009-09-01 01:00:13 +00:00
|
|
|
if (mPluginEventModel == NPEventModelCarbon) {
|
2009-08-27 00:29:47 +00:00
|
|
|
carbonEvent.what = mouseDown;
|
|
|
|
carbonEvent.message = 0;
|
|
|
|
carbonEvent.when = ::TickCount();
|
|
|
|
::GetGlobalMouse(&carbonEvent.where);
|
2009-09-25 20:10:04 +00:00
|
|
|
carbonEvent.modifiers = ::GetCurrentKeyModifiers();
|
2009-11-10 21:55:38 +00:00
|
|
|
geckoEvent.pluginEvent = &carbonEvent;
|
2009-08-27 00:29:47 +00:00
|
|
|
}
|
2009-09-01 01:00:13 +00:00
|
|
|
#endif
|
|
|
|
NPCocoaEvent cocoaEvent;
|
|
|
|
if (mPluginEventModel == NPEventModelCocoa) {
|
2009-08-27 00:29:47 +00:00
|
|
|
InitNPCocoaEvent(&cocoaEvent);
|
|
|
|
NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
|
|
|
cocoaEvent.type = NPCocoaEventMouseDown;
|
|
|
|
cocoaEvent.data.mouse.modifierFlags = modifierFlags;
|
|
|
|
cocoaEvent.data.mouse.pluginX = point.x;
|
|
|
|
cocoaEvent.data.mouse.pluginY = point.y;
|
|
|
|
cocoaEvent.data.mouse.buttonNumber = [theEvent buttonNumber];
|
|
|
|
cocoaEvent.data.mouse.clickCount = [theEvent clickCount];
|
|
|
|
cocoaEvent.data.mouse.deltaX = [theEvent deltaX];
|
|
|
|
cocoaEvent.data.mouse.deltaY = [theEvent deltaY];
|
|
|
|
cocoaEvent.data.mouse.deltaZ = [theEvent deltaZ];
|
2009-11-10 21:55:38 +00:00
|
|
|
geckoEvent.pluginEvent = &cocoaEvent;
|
2009-08-27 00:29:47 +00:00
|
|
|
}
|
2002-04-27 00:19:49 +00:00
|
|
|
|
2008-08-26 00:02:26 +00:00
|
|
|
mGeckoChild->DispatchWindowEvent(geckoEvent);
|
2007-04-19 20:18:46 +00:00
|
|
|
|
2005-06-26 03:25:52 +00:00
|
|
|
// XXX maybe call markedTextSelectionChanged:client: here?
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2005-06-26 03:25:52 +00:00
|
|
|
}
|
2001-11-06 15:35:24 +00:00
|
|
|
|
|
|
|
- (void)mouseUp:(NSEvent *)theEvent
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-06-12 20:28:26 +00:00
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
|
|
|
|
2010-01-22 20:57:04 +00:00
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
|
|
|
|
2007-02-27 17:23:58 +00:00
|
|
|
nsMouseEvent geckoEvent(PR_TRUE, NS_MOUSE_BUTTON_UP, nsnull, nsMouseEvent::eReal);
|
2007-06-12 20:28:26 +00:00
|
|
|
[self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
|
2010-02-23 23:30:39 +00:00
|
|
|
if ([theEvent modifierFlags] & NSControlKeyMask)
|
2008-09-15 12:50:59 +00:00
|
|
|
geckoEvent.button = nsMouseEvent::eRightButton;
|
|
|
|
else
|
|
|
|
geckoEvent.button = nsMouseEvent::eLeftButton;
|
2002-04-27 00:19:49 +00:00
|
|
|
|
2009-08-27 00:29:47 +00:00
|
|
|
// Create event for use by plugins.
|
|
|
|
// This is going to our child view so we don't need to look up the destination
|
|
|
|
// event type.
|
2010-01-22 20:57:04 +00:00
|
|
|
if (mIsPluginView) {
|
2009-09-01 01:00:13 +00:00
|
|
|
#ifndef NP_NO_CARBON
|
2010-01-22 20:57:04 +00:00
|
|
|
EventRecord carbonEvent;
|
|
|
|
if (mPluginEventModel == NPEventModelCarbon) {
|
|
|
|
carbonEvent.what = mouseUp;
|
|
|
|
carbonEvent.message = 0;
|
|
|
|
carbonEvent.when = ::TickCount();
|
|
|
|
::GetGlobalMouse(&carbonEvent.where);
|
|
|
|
carbonEvent.modifiers = ::GetCurrentKeyModifiers();
|
|
|
|
geckoEvent.pluginEvent = &carbonEvent;
|
|
|
|
}
|
2009-09-01 01:00:13 +00:00
|
|
|
#endif
|
2010-01-22 20:57:04 +00:00
|
|
|
NPCocoaEvent cocoaEvent;
|
|
|
|
if (mPluginEventModel == NPEventModelCocoa) {
|
|
|
|
InitNPCocoaEvent(&cocoaEvent);
|
|
|
|
NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
|
|
|
cocoaEvent.type = NPCocoaEventMouseUp;
|
|
|
|
cocoaEvent.data.mouse.modifierFlags = [theEvent modifierFlags];
|
|
|
|
cocoaEvent.data.mouse.pluginX = point.x;
|
|
|
|
cocoaEvent.data.mouse.pluginY = point.y;
|
|
|
|
cocoaEvent.data.mouse.buttonNumber = [theEvent buttonNumber];
|
|
|
|
cocoaEvent.data.mouse.clickCount = [theEvent clickCount];
|
|
|
|
cocoaEvent.data.mouse.deltaX = [theEvent deltaX];
|
|
|
|
cocoaEvent.data.mouse.deltaY = [theEvent deltaY];
|
|
|
|
cocoaEvent.data.mouse.deltaZ = [theEvent deltaZ];
|
|
|
|
geckoEvent.pluginEvent = &cocoaEvent;
|
|
|
|
}
|
2009-08-27 00:29:47 +00:00
|
|
|
}
|
2002-04-27 00:19:49 +00:00
|
|
|
|
2010-03-02 22:04:13 +00:00
|
|
|
// This might destroy our widget (and null out mGeckoChild).
|
2008-08-26 00:02:26 +00:00
|
|
|
mGeckoChild->DispatchWindowEvent(geckoEvent);
|
2008-02-20 23:47:05 +00:00
|
|
|
|
2010-01-22 20:57:04 +00:00
|
|
|
// If our mouse-up event's location is over some other object (as might
|
|
|
|
// happen if it came at the end of a dragging operation), also send our
|
|
|
|
// Gecko frame a mouse-exit event.
|
2010-03-02 22:04:13 +00:00
|
|
|
if (mGeckoChild && mIsPluginView) {
|
2010-01-22 20:57:04 +00:00
|
|
|
#ifndef NP_NO_CARBON
|
|
|
|
if (mPluginEventModel == NPEventModelCocoa)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
if (ChildViewMouseTracker::ViewForEvent(theEvent) != self) {
|
|
|
|
nsMouseEvent geckoExitEvent(PR_TRUE, NS_MOUSE_EXIT, nsnull, nsMouseEvent::eReal);
|
|
|
|
[self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoExitEvent];
|
|
|
|
|
|
|
|
NPCocoaEvent cocoaEvent;
|
|
|
|
InitNPCocoaEvent(&cocoaEvent);
|
|
|
|
NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
|
|
|
cocoaEvent.type = NPCocoaEventMouseExited;
|
|
|
|
cocoaEvent.data.mouse.modifierFlags = [theEvent modifierFlags];
|
|
|
|
cocoaEvent.data.mouse.pluginX = point.x;
|
|
|
|
cocoaEvent.data.mouse.pluginY = point.y;
|
|
|
|
cocoaEvent.data.mouse.buttonNumber = [theEvent buttonNumber];
|
|
|
|
cocoaEvent.data.mouse.deltaX = [theEvent deltaX];
|
|
|
|
cocoaEvent.data.mouse.deltaY = [theEvent deltaY];
|
|
|
|
cocoaEvent.data.mouse.deltaZ = [theEvent deltaZ];
|
|
|
|
geckoExitEvent.pluginEvent = &cocoaEvent;
|
|
|
|
|
|
|
|
mGeckoChild->DispatchWindowEvent(geckoExitEvent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2005-06-26 03:25:52 +00:00
|
|
|
}
|
2001-11-06 15:35:24 +00:00
|
|
|
|
2009-09-23 02:31:37 +00:00
|
|
|
- (void)sendMouseEnterOrExitEvent:(NSEvent*)aEvent
|
|
|
|
enter:(BOOL)aEnter
|
|
|
|
type:(nsMouseEvent::exitType)aType
|
2007-04-10 20:07:49 +00:00
|
|
|
{
|
2009-09-23 02:31:37 +00:00
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
2009-09-23 02:31:37 +00:00
|
|
|
NSPoint windowEventLocation = nsCocoaUtils::EventLocationForWindow(aEvent, [self window]);
|
|
|
|
NSPoint localEventLocation = [self convertPoint:windowEventLocation fromView:nil];
|
2007-06-12 20:28:26 +00:00
|
|
|
|
2009-09-23 02:31:37 +00:00
|
|
|
PRUint32 msg = aEnter ? NS_MOUSE_ENTER : NS_MOUSE_EXIT;
|
|
|
|
nsMouseEvent event(PR_TRUE, msg, mGeckoChild, nsMouseEvent::eReal);
|
|
|
|
event.refPoint.x = nscoord((PRInt32)localEventLocation.x);
|
|
|
|
event.refPoint.y = nscoord((PRInt32)localEventLocation.y);
|
2007-06-12 20:28:26 +00:00
|
|
|
|
2009-08-27 00:29:47 +00:00
|
|
|
// Create event for use by plugins.
|
2009-09-23 02:31:37 +00:00
|
|
|
// This is going to our child view so we don't need to look up the destination
|
|
|
|
// event type.
|
2009-08-27 00:29:47 +00:00
|
|
|
EventRecord carbonEvent;
|
2009-09-01 01:00:13 +00:00
|
|
|
NPCocoaEvent cocoaEvent;
|
2009-11-09 23:08:42 +00:00
|
|
|
if (mIsPluginView) {
|
|
|
|
#ifndef NP_NO_CARBON
|
|
|
|
if (mPluginEventModel == NPEventModelCarbon) {
|
|
|
|
carbonEvent.what = NPEventType_AdjustCursorEvent;
|
|
|
|
carbonEvent.message = 0;
|
|
|
|
carbonEvent.when = ::TickCount();
|
|
|
|
::GetGlobalMouse(&carbonEvent.where);
|
|
|
|
carbonEvent.modifiers = ::GetCurrentKeyModifiers();
|
2009-11-10 21:55:38 +00:00
|
|
|
event.pluginEvent = &carbonEvent;
|
2009-11-09 23:08:42 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (mPluginEventModel == NPEventModelCocoa) {
|
|
|
|
InitNPCocoaEvent(&cocoaEvent);
|
|
|
|
cocoaEvent.type = ((msg == NS_MOUSE_ENTER) ? NPCocoaEventMouseEntered : NPCocoaEventMouseExited);
|
|
|
|
cocoaEvent.data.mouse.modifierFlags = [aEvent modifierFlags];
|
|
|
|
cocoaEvent.data.mouse.pluginX = 5;
|
|
|
|
cocoaEvent.data.mouse.pluginY = 5;
|
|
|
|
cocoaEvent.data.mouse.buttonNumber = [aEvent buttonNumber];
|
|
|
|
cocoaEvent.data.mouse.deltaX = [aEvent deltaX];
|
|
|
|
cocoaEvent.data.mouse.deltaY = [aEvent deltaY];
|
|
|
|
cocoaEvent.data.mouse.deltaZ = [aEvent deltaZ];
|
2009-11-10 21:55:38 +00:00
|
|
|
event.pluginEvent = &cocoaEvent;
|
2010-05-14 17:24:42 +00:00
|
|
|
}
|
2009-08-27 00:29:47 +00:00
|
|
|
}
|
2007-09-06 05:11:35 +00:00
|
|
|
|
2009-09-23 02:31:37 +00:00
|
|
|
event.exit = aType;
|
2008-04-09 17:23:34 +00:00
|
|
|
|
2009-09-23 02:31:37 +00:00
|
|
|
nsEventStatus status; // ignored
|
|
|
|
mGeckoChild->DispatchEvent(&event, status);
|
|
|
|
}
|
2008-02-20 23:47:05 +00:00
|
|
|
|
2009-09-23 02:31:37 +00:00
|
|
|
- (void)mouseMoved:(NSEvent*)aEvent
|
|
|
|
{
|
|
|
|
ChildViewMouseTracker::MouseMoved(aEvent);
|
2007-04-10 20:07:49 +00:00
|
|
|
}
|
|
|
|
|
2009-09-23 02:31:37 +00:00
|
|
|
- (void)handleMouseMoved:(NSEvent*)theEvent
|
2001-11-06 15:35:24 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-06-15 22:34:48 +00:00
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
|
|
|
|
2007-02-27 17:23:58 +00:00
|
|
|
nsMouseEvent geckoEvent(PR_TRUE, NS_MOUSE_MOVE, nsnull, nsMouseEvent::eReal);
|
2007-06-12 20:28:26 +00:00
|
|
|
[self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
|
2001-11-06 15:35:24 +00:00
|
|
|
|
2009-08-27 00:29:47 +00:00
|
|
|
// Create event for use by plugins.
|
|
|
|
// This is going to our child view so we don't need to look up the destination
|
|
|
|
// event type.
|
|
|
|
EventRecord carbonEvent;
|
2009-09-01 01:00:13 +00:00
|
|
|
NPCocoaEvent cocoaEvent;
|
2009-11-09 23:08:42 +00:00
|
|
|
if (mIsPluginView) {
|
|
|
|
#ifndef NP_NO_CARBON
|
|
|
|
if (mPluginEventModel == NPEventModelCarbon) {
|
|
|
|
carbonEvent.what = NPEventType_AdjustCursorEvent;
|
|
|
|
carbonEvent.message = 0;
|
|
|
|
carbonEvent.when = ::TickCount();
|
|
|
|
::GetGlobalMouse(&carbonEvent.where);
|
|
|
|
carbonEvent.modifiers = ::GetCurrentKeyModifiers();
|
2009-11-10 21:55:38 +00:00
|
|
|
geckoEvent.pluginEvent = &carbonEvent;
|
2009-11-09 23:08:42 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (mPluginEventModel == NPEventModelCocoa) {
|
|
|
|
InitNPCocoaEvent(&cocoaEvent);
|
|
|
|
NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
|
|
|
cocoaEvent.type = NPCocoaEventMouseMoved;
|
|
|
|
cocoaEvent.data.mouse.modifierFlags = [theEvent modifierFlags];
|
|
|
|
cocoaEvent.data.mouse.pluginX = point.x;
|
|
|
|
cocoaEvent.data.mouse.pluginY = point.y;
|
|
|
|
cocoaEvent.data.mouse.buttonNumber = [theEvent buttonNumber];
|
|
|
|
cocoaEvent.data.mouse.clickCount = [theEvent clickCount];
|
|
|
|
cocoaEvent.data.mouse.deltaX = [theEvent deltaX];
|
|
|
|
cocoaEvent.data.mouse.deltaY = [theEvent deltaY];
|
|
|
|
cocoaEvent.data.mouse.deltaZ = [theEvent deltaZ];
|
2009-11-10 21:55:38 +00:00
|
|
|
geckoEvent.pluginEvent = &cocoaEvent;
|
2009-11-09 23:08:42 +00:00
|
|
|
}
|
2009-08-27 00:29:47 +00:00
|
|
|
}
|
2008-08-26 00:02:26 +00:00
|
|
|
mGeckoChild->DispatchWindowEvent(geckoEvent);
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)mouseDragged:(NSEvent*)theEvent
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-06-15 22:34:48 +00:00
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
|
|
|
|
2007-09-24 00:01:04 +00:00
|
|
|
gLastDragView = self;
|
2006-10-25 22:45:22 +00:00
|
|
|
|
2007-02-27 17:23:58 +00:00
|
|
|
nsMouseEvent geckoEvent(PR_TRUE, NS_MOUSE_MOVE, nsnull, nsMouseEvent::eReal);
|
2007-06-12 20:28:26 +00:00
|
|
|
[self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
|
2002-12-13 08:43:18 +00:00
|
|
|
|
2009-08-27 00:29:47 +00:00
|
|
|
// create event for use by plugins
|
2010-01-22 20:57:04 +00:00
|
|
|
if (mIsPluginView) {
|
2009-09-01 01:00:13 +00:00
|
|
|
#ifndef NP_NO_CARBON
|
2010-01-22 20:57:04 +00:00
|
|
|
EventRecord carbonEvent;
|
|
|
|
if (mPluginEventModel == NPEventModelCarbon) {
|
|
|
|
carbonEvent.what = NPEventType_AdjustCursorEvent;
|
|
|
|
carbonEvent.message = 0;
|
|
|
|
carbonEvent.when = ::TickCount();
|
|
|
|
::GetGlobalMouse(&carbonEvent.where);
|
|
|
|
carbonEvent.modifiers = btnState | ::GetCurrentKeyModifiers();
|
|
|
|
geckoEvent.pluginEvent = &carbonEvent;
|
|
|
|
}
|
2009-09-01 01:00:13 +00:00
|
|
|
#endif
|
2010-01-22 20:57:04 +00:00
|
|
|
NPCocoaEvent cocoaEvent;
|
|
|
|
if (mPluginEventModel == NPEventModelCocoa) {
|
|
|
|
InitNPCocoaEvent(&cocoaEvent);
|
|
|
|
NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
|
|
|
cocoaEvent.type = NPCocoaEventMouseDragged;
|
|
|
|
cocoaEvent.data.mouse.modifierFlags = [theEvent modifierFlags];
|
|
|
|
cocoaEvent.data.mouse.pluginX = point.x;
|
|
|
|
cocoaEvent.data.mouse.pluginY = point.y;
|
|
|
|
cocoaEvent.data.mouse.buttonNumber = [theEvent buttonNumber];
|
|
|
|
cocoaEvent.data.mouse.clickCount = [theEvent clickCount];
|
|
|
|
cocoaEvent.data.mouse.deltaX = [theEvent deltaX];
|
|
|
|
cocoaEvent.data.mouse.deltaY = [theEvent deltaY];
|
|
|
|
cocoaEvent.data.mouse.deltaZ = [theEvent deltaZ];
|
|
|
|
geckoEvent.pluginEvent = &cocoaEvent;
|
|
|
|
}
|
2009-08-27 00:29:47 +00:00
|
|
|
}
|
2007-06-12 20:28:26 +00:00
|
|
|
|
2008-08-26 00:02:26 +00:00
|
|
|
mGeckoChild->DispatchWindowEvent(geckoEvent);
|
2008-01-15 23:11:55 +00:00
|
|
|
|
|
|
|
// Note, sending the above event might have destroyed our widget since we didn't retain.
|
|
|
|
// Fine so long as we don't access any local variables from here on.
|
2007-09-24 00:01:04 +00:00
|
|
|
gLastDragView = nil;
|
2009-11-06 10:21:41 +00:00
|
|
|
|
2005-06-26 03:25:52 +00:00
|
|
|
// XXX maybe call markedTextSelectionChanged:client: here?
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
2002-12-13 08:43:18 +00:00
|
|
|
- (void)rightMouseDown:(NSEvent *)theEvent
|
2007-11-07 07:53:24 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2008-04-08 04:38:52 +00:00
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
2008-01-15 23:11:21 +00:00
|
|
|
|
2008-01-15 23:11:55 +00:00
|
|
|
[self maybeRollup:theEvent];
|
2007-06-15 22:34:48 +00:00
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
2007-11-26 23:19:04 +00:00
|
|
|
|
2006-06-12 21:05:36 +00:00
|
|
|
// The right mouse went down, fire off a right mouse down event to gecko
|
2007-02-27 17:23:58 +00:00
|
|
|
nsMouseEvent geckoEvent(PR_TRUE, NS_MOUSE_BUTTON_DOWN, nsnull, nsMouseEvent::eReal);
|
2007-06-12 20:28:26 +00:00
|
|
|
[self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
|
2006-11-16 21:35:39 +00:00
|
|
|
geckoEvent.button = nsMouseEvent::eRightButton;
|
2007-06-12 20:28:26 +00:00
|
|
|
geckoEvent.clickCount = [theEvent clickCount];
|
2002-12-13 08:43:18 +00:00
|
|
|
|
2009-08-27 00:29:47 +00:00
|
|
|
// create event for use by plugins
|
2009-09-01 01:00:13 +00:00
|
|
|
#ifndef NP_NO_CARBON
|
2009-08-27 00:29:47 +00:00
|
|
|
EventRecord carbonEvent;
|
2009-09-01 01:00:13 +00:00
|
|
|
if (mPluginEventModel == NPEventModelCarbon) {
|
2009-08-27 00:29:47 +00:00
|
|
|
carbonEvent.what = mouseDown;
|
|
|
|
carbonEvent.message = 0;
|
|
|
|
carbonEvent.when = ::TickCount();
|
|
|
|
::GetGlobalMouse(&carbonEvent.where);
|
|
|
|
carbonEvent.modifiers = controlKey; // fake a context menu click
|
2009-11-10 21:55:38 +00:00
|
|
|
geckoEvent.pluginEvent = &carbonEvent;
|
2009-08-27 00:29:47 +00:00
|
|
|
}
|
2009-09-01 01:00:13 +00:00
|
|
|
#endif
|
|
|
|
NPCocoaEvent cocoaEvent;
|
|
|
|
if (mPluginEventModel == NPEventModelCocoa) {
|
2009-08-27 00:29:47 +00:00
|
|
|
InitNPCocoaEvent(&cocoaEvent);
|
|
|
|
NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
|
|
|
cocoaEvent.type = NPCocoaEventMouseDown;
|
|
|
|
cocoaEvent.data.mouse.modifierFlags = [theEvent modifierFlags];
|
|
|
|
cocoaEvent.data.mouse.pluginX = point.x;
|
|
|
|
cocoaEvent.data.mouse.pluginY = point.y;
|
|
|
|
cocoaEvent.data.mouse.buttonNumber = [theEvent buttonNumber];
|
|
|
|
cocoaEvent.data.mouse.clickCount = [theEvent clickCount];
|
|
|
|
cocoaEvent.data.mouse.deltaX = [theEvent deltaX];
|
|
|
|
cocoaEvent.data.mouse.deltaY = [theEvent deltaY];
|
|
|
|
cocoaEvent.data.mouse.deltaZ = [theEvent deltaZ];
|
2009-11-10 21:55:38 +00:00
|
|
|
geckoEvent.pluginEvent = &cocoaEvent;
|
2009-08-27 00:29:47 +00:00
|
|
|
}
|
2002-12-13 08:43:18 +00:00
|
|
|
|
2008-08-26 00:02:26 +00:00
|
|
|
PRBool handled = mGeckoChild->DispatchWindowEvent(geckoEvent);
|
2008-01-15 23:11:55 +00:00
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
|
|
|
|
2002-12-13 08:43:18 +00:00
|
|
|
if (!handled)
|
2006-12-20 02:13:57 +00:00
|
|
|
[super rightMouseDown:theEvent]; // let the superview do context menu stuff
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)rightMouseUp:(NSEvent *)theEvent
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-06-15 22:34:48 +00:00
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
2008-01-15 23:11:55 +00:00
|
|
|
|
2007-02-27 17:23:58 +00:00
|
|
|
nsMouseEvent geckoEvent(PR_TRUE, NS_MOUSE_BUTTON_UP, nsnull, nsMouseEvent::eReal);
|
2007-06-12 20:28:26 +00:00
|
|
|
[self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
|
2006-11-16 21:35:39 +00:00
|
|
|
geckoEvent.button = nsMouseEvent::eRightButton;
|
2007-06-12 20:28:26 +00:00
|
|
|
geckoEvent.clickCount = [theEvent clickCount];
|
2002-12-13 08:43:18 +00:00
|
|
|
|
2009-08-27 00:29:47 +00:00
|
|
|
// create event for use by plugins
|
2010-01-22 20:57:04 +00:00
|
|
|
if (mIsPluginView) {
|
2009-09-01 01:00:13 +00:00
|
|
|
#ifndef NP_NO_CARBON
|
2010-01-22 20:57:04 +00:00
|
|
|
EventRecord carbonEvent;
|
|
|
|
if (mPluginEventModel == NPEventModelCarbon) {
|
|
|
|
carbonEvent.what = mouseUp;
|
|
|
|
carbonEvent.message = 0;
|
|
|
|
carbonEvent.when = ::TickCount();
|
|
|
|
::GetGlobalMouse(&carbonEvent.where);
|
|
|
|
carbonEvent.modifiers = controlKey; // fake a context menu click
|
|
|
|
geckoEvent.pluginEvent = &carbonEvent;
|
|
|
|
}
|
2009-09-01 01:00:13 +00:00
|
|
|
#endif
|
2010-01-22 20:57:04 +00:00
|
|
|
NPCocoaEvent cocoaEvent;
|
|
|
|
if (mPluginEventModel == NPEventModelCocoa) {
|
|
|
|
InitNPCocoaEvent(&cocoaEvent);
|
|
|
|
NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
|
|
|
cocoaEvent.type = NPCocoaEventMouseUp;
|
|
|
|
cocoaEvent.data.mouse.modifierFlags = [theEvent modifierFlags];
|
|
|
|
cocoaEvent.data.mouse.pluginX = point.x;
|
|
|
|
cocoaEvent.data.mouse.pluginY = point.y;
|
|
|
|
cocoaEvent.data.mouse.buttonNumber = [theEvent buttonNumber];
|
|
|
|
cocoaEvent.data.mouse.clickCount = [theEvent clickCount];
|
|
|
|
cocoaEvent.data.mouse.deltaX = [theEvent deltaX];
|
|
|
|
cocoaEvent.data.mouse.deltaY = [theEvent deltaY];
|
|
|
|
cocoaEvent.data.mouse.deltaZ = [theEvent deltaZ];
|
|
|
|
geckoEvent.pluginEvent = &cocoaEvent;
|
|
|
|
}
|
2009-08-27 00:29:47 +00:00
|
|
|
}
|
2002-12-13 08:43:18 +00:00
|
|
|
|
2008-04-08 04:38:52 +00:00
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
2008-08-26 00:02:26 +00:00
|
|
|
mGeckoChild->DispatchWindowEvent(geckoEvent);
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2001-11-06 15:35:24 +00:00
|
|
|
}
|
|
|
|
|
2007-07-17 20:29:39 +00:00
|
|
|
- (void)rightMouseDragged:(NSEvent*)theEvent
|
|
|
|
{
|
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsMouseEvent geckoEvent(PR_TRUE, NS_MOUSE_MOVE, nsnull, nsMouseEvent::eReal);
|
|
|
|
[self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
|
|
|
|
geckoEvent.button = nsMouseEvent::eRightButton;
|
|
|
|
|
|
|
|
// send event into Gecko by going directly to the
|
|
|
|
// the widget.
|
2008-08-26 00:02:26 +00:00
|
|
|
mGeckoChild->DispatchWindowEvent(geckoEvent);
|
2007-07-17 20:29:39 +00:00
|
|
|
}
|
|
|
|
|
2002-03-09 23:09:34 +00:00
|
|
|
- (void)otherMouseDown:(NSEvent *)theEvent
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2008-04-08 04:38:52 +00:00
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
2008-01-15 23:11:55 +00:00
|
|
|
|
2009-09-23 02:31:37 +00:00
|
|
|
if ([self maybeRollup:theEvent] ||
|
|
|
|
!ChildViewMouseTracker::WindowAcceptsEvent([self window], theEvent))
|
2007-11-26 23:19:04 +00:00
|
|
|
return;
|
2007-07-17 20:29:39 +00:00
|
|
|
|
2007-06-15 22:34:48 +00:00
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
|
|
|
|
2007-02-27 17:23:58 +00:00
|
|
|
nsMouseEvent geckoEvent(PR_TRUE, NS_MOUSE_BUTTON_DOWN, nsnull, nsMouseEvent::eReal);
|
2007-06-12 20:28:26 +00:00
|
|
|
[self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
|
2006-11-16 21:35:39 +00:00
|
|
|
geckoEvent.button = nsMouseEvent::eMiddleButton;
|
2007-06-12 20:28:26 +00:00
|
|
|
geckoEvent.clickCount = [theEvent clickCount];
|
|
|
|
|
2008-08-26 00:02:26 +00:00
|
|
|
mGeckoChild->DispatchWindowEvent(geckoEvent);
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2006-12-20 02:13:57 +00:00
|
|
|
}
|
2002-03-09 23:09:34 +00:00
|
|
|
|
|
|
|
- (void)otherMouseUp:(NSEvent *)theEvent
|
|
|
|
{
|
2007-06-15 22:34:48 +00:00
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
|
|
|
|
2007-02-27 17:23:58 +00:00
|
|
|
nsMouseEvent geckoEvent(PR_TRUE, NS_MOUSE_BUTTON_UP, nsnull, nsMouseEvent::eReal);
|
2007-06-12 20:28:26 +00:00
|
|
|
[self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
|
2006-11-16 21:35:39 +00:00
|
|
|
geckoEvent.button = nsMouseEvent::eMiddleButton;
|
|
|
|
|
2008-08-26 00:02:26 +00:00
|
|
|
mGeckoChild->DispatchWindowEvent(geckoEvent);
|
2006-12-20 02:13:57 +00:00
|
|
|
}
|
|
|
|
|
2007-07-17 20:29:39 +00:00
|
|
|
- (void)otherMouseDragged:(NSEvent*)theEvent
|
|
|
|
{
|
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsMouseEvent geckoEvent(PR_TRUE, NS_MOUSE_MOVE, nsnull, nsMouseEvent::eReal);
|
|
|
|
[self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
|
|
|
|
geckoEvent.button = nsMouseEvent::eMiddleButton;
|
|
|
|
|
|
|
|
// send event into Gecko by going directly to the
|
|
|
|
// the widget.
|
2008-08-26 00:02:26 +00:00
|
|
|
mGeckoChild->DispatchWindowEvent(geckoEvent);
|
2007-07-17 20:29:39 +00:00
|
|
|
}
|
|
|
|
|
2005-07-19 22:54:07 +00:00
|
|
|
// Handle an NSScrollWheel event for a single axis only.
|
|
|
|
-(void)scrollWheel:(NSEvent*)theEvent forAxis:(enum nsMouseScrollEvent::nsMouseScrollFlags)inAxis
|
2002-02-17 19:09:07 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-06-15 22:34:48 +00:00
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
|
|
|
|
2008-09-17 11:27:19 +00:00
|
|
|
float scrollDelta = 0;
|
|
|
|
float scrollDeltaPixels = 0;
|
|
|
|
PRBool checkPixels = PR_TRUE;
|
2003-01-08 06:43:08 +00:00
|
|
|
|
2008-09-17 11:27:19 +00:00
|
|
|
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
|
|
|
if (prefs)
|
|
|
|
prefs->GetBoolPref("mousewheel.enable_pixel_scrolling", &checkPixels);
|
|
|
|
|
|
|
|
// Calling deviceDeltaX or deviceDeltaY on theEvent will trigger a Cocoa
|
|
|
|
// assertion and an Objective-C NSInternalInconsistencyException if the
|
|
|
|
// underlying "Carbon" event doesn't contain pixel scrolling information.
|
|
|
|
// For these events, carbonEventKind is kEventMouseWheelMoved instead of
|
|
|
|
// kEventMouseScroll.
|
2009-09-28 06:01:05 +00:00
|
|
|
if (checkPixels) {
|
|
|
|
EventRef theCarbonEvent = [theEvent _eventRef];
|
|
|
|
UInt32 carbonEventKind = theCarbonEvent ? ::GetEventKind(theCarbonEvent) : 0;
|
2010-02-23 20:10:25 +00:00
|
|
|
if (carbonEventKind != kEventMouseScroll)
|
2009-09-28 06:01:05 +00:00
|
|
|
checkPixels = PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2008-09-17 11:27:19 +00:00
|
|
|
// Some scrolling devices supports pixel scrolling, e.g. a Macbook
|
|
|
|
// touchpad or a Mighty Mouse. On those devices, [event deviceDeltaX/Y]
|
|
|
|
// contains the amount of pixels to scroll.
|
|
|
|
if (inAxis & nsMouseScrollEvent::kIsVertical) {
|
|
|
|
scrollDelta = -[theEvent deltaY];
|
|
|
|
if (checkPixels && (scrollDelta == 0 || scrollDelta != floor(scrollDelta))) {
|
|
|
|
scrollDeltaPixels = -[theEvent deviceDeltaY];
|
|
|
|
}
|
|
|
|
} else if (inAxis & nsMouseScrollEvent::kIsHorizontal) {
|
|
|
|
scrollDelta = -[theEvent deltaX];
|
|
|
|
if (checkPixels && (scrollDelta == 0 || scrollDelta != floor(scrollDelta))) {
|
|
|
|
scrollDeltaPixels = -[theEvent deviceDeltaX];
|
|
|
|
}
|
|
|
|
} else {
|
2008-01-15 23:11:55 +00:00
|
|
|
return; // caller screwed up
|
2008-09-17 11:27:19 +00:00
|
|
|
}
|
2005-07-19 22:54:07 +00:00
|
|
|
|
2008-09-17 11:27:19 +00:00
|
|
|
BOOL hasPixels = (scrollDeltaPixels != 0);
|
2005-07-19 22:54:07 +00:00
|
|
|
|
2008-09-17 11:27:19 +00:00
|
|
|
if (!hasPixels && scrollDelta == 0)
|
|
|
|
// No sense in firing off a Gecko event.
|
|
|
|
return;
|
2003-01-08 06:43:08 +00:00
|
|
|
|
2008-09-17 11:27:19 +00:00
|
|
|
if (scrollDelta != 0) {
|
|
|
|
// Send the line scroll event.
|
|
|
|
nsMouseScrollEvent geckoEvent(PR_TRUE, NS_MOUSE_SCROLL, nsnull);
|
|
|
|
[self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
|
|
|
|
geckoEvent.scrollFlags |= inAxis;
|
2005-07-25 15:56:25 +00:00
|
|
|
|
2008-09-17 11:27:19 +00:00
|
|
|
if (hasPixels)
|
|
|
|
geckoEvent.scrollFlags |= nsMouseScrollEvent::kHasPixels;
|
|
|
|
|
|
|
|
// Gecko only understands how to scroll by an integer value. Using floor
|
|
|
|
// and ceil is better than truncating the fraction, especially when
|
|
|
|
// |delta| < 1.
|
|
|
|
if (scrollDelta < 0)
|
|
|
|
geckoEvent.delta = (PRInt32)floorf(scrollDelta);
|
|
|
|
else
|
|
|
|
geckoEvent.delta = (PRInt32)ceilf(scrollDelta);
|
|
|
|
|
2009-11-08 21:51:46 +00:00
|
|
|
NPCocoaEvent cocoaEvent;
|
|
|
|
if (mPluginEventModel == NPEventModelCocoa) {
|
|
|
|
InitNPCocoaEvent(&cocoaEvent);
|
|
|
|
NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
|
|
|
cocoaEvent.type = NPCocoaEventScrollWheel;
|
|
|
|
cocoaEvent.data.mouse.modifierFlags = [theEvent modifierFlags];
|
|
|
|
cocoaEvent.data.mouse.pluginX = point.x;
|
|
|
|
cocoaEvent.data.mouse.pluginY = point.y;
|
|
|
|
cocoaEvent.data.mouse.buttonNumber = [theEvent buttonNumber];
|
|
|
|
cocoaEvent.data.mouse.clickCount = 0;
|
|
|
|
if (inAxis & nsMouseScrollEvent::kIsHorizontal)
|
|
|
|
cocoaEvent.data.mouse.deltaX = [theEvent deltaX];
|
|
|
|
else
|
|
|
|
cocoaEvent.data.mouse.deltaX = 0.0;
|
|
|
|
if (inAxis & nsMouseScrollEvent::kIsVertical)
|
|
|
|
cocoaEvent.data.mouse.deltaY = [theEvent deltaY];
|
|
|
|
else
|
|
|
|
cocoaEvent.data.mouse.deltaY = 0.0;
|
|
|
|
cocoaEvent.data.mouse.deltaZ = 0.0;
|
2009-11-10 21:55:38 +00:00
|
|
|
geckoEvent.pluginEvent = &cocoaEvent;
|
2009-11-08 21:51:46 +00:00
|
|
|
}
|
|
|
|
|
2008-09-17 11:27:19 +00:00
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
|
|
|
mGeckoChild->DispatchWindowEvent(geckoEvent);
|
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
|
|
|
|
2009-09-28 06:01:05 +00:00
|
|
|
#ifndef NP_NO_CARBON
|
2008-09-17 11:27:19 +00:00
|
|
|
// dispatch scroll wheel carbon event for plugins
|
2009-09-28 06:01:05 +00:00
|
|
|
if (mPluginEventModel == NPEventModelCarbon) {
|
2008-09-17 11:27:19 +00:00
|
|
|
EventRef theEvent;
|
2008-10-30 05:36:01 +00:00
|
|
|
OSStatus err = ::CreateEvent(NULL,
|
|
|
|
kEventClassMouse,
|
|
|
|
kEventMouseWheelMoved,
|
|
|
|
TicksToEventTime(TickCount()),
|
|
|
|
kEventAttributeUserEvent,
|
|
|
|
&theEvent);
|
2008-09-17 11:27:19 +00:00
|
|
|
if (err == noErr) {
|
|
|
|
EventMouseWheelAxis axis;
|
|
|
|
if (inAxis & nsMouseScrollEvent::kIsVertical)
|
|
|
|
axis = kEventMouseWheelAxisY;
|
|
|
|
else if (inAxis & nsMouseScrollEvent::kIsHorizontal)
|
|
|
|
axis = kEventMouseWheelAxisX;
|
|
|
|
|
|
|
|
SetEventParameter(theEvent,
|
|
|
|
kEventParamMouseWheelAxis,
|
|
|
|
typeMouseWheelAxis,
|
|
|
|
sizeof(EventMouseWheelAxis),
|
|
|
|
&axis);
|
|
|
|
|
|
|
|
SInt32 delta = (SInt32)-geckoEvent.delta;
|
|
|
|
SetEventParameter(theEvent,
|
|
|
|
kEventParamMouseWheelDelta,
|
|
|
|
typeLongInteger,
|
|
|
|
sizeof(SInt32),
|
|
|
|
&delta);
|
|
|
|
|
|
|
|
Point mouseLoc;
|
|
|
|
::GetGlobalMouse(&mouseLoc);
|
|
|
|
SetEventParameter(theEvent,
|
|
|
|
kEventParamMouseLocation,
|
|
|
|
typeQDPoint,
|
|
|
|
sizeof(Point),
|
|
|
|
&mouseLoc);
|
|
|
|
|
|
|
|
::SendEventToEventTarget(theEvent, GetWindowEventTarget((WindowRef)[[self window] windowRef]));
|
|
|
|
ReleaseEvent(theEvent);
|
|
|
|
}
|
2005-07-25 15:56:25 +00:00
|
|
|
}
|
2009-09-28 06:01:05 +00:00
|
|
|
#endif
|
2005-07-25 15:56:25 +00:00
|
|
|
}
|
2008-02-20 23:47:05 +00:00
|
|
|
|
2008-09-17 11:27:19 +00:00
|
|
|
if (hasPixels) {
|
|
|
|
// Send the pixel scroll event.
|
|
|
|
nsMouseScrollEvent geckoEvent(PR_TRUE, NS_MOUSE_PIXEL_SCROLL, nsnull);
|
|
|
|
[self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
|
|
|
|
geckoEvent.scrollFlags |= inAxis;
|
|
|
|
geckoEvent.delta = NSToIntRound(scrollDeltaPixels);
|
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
|
|
|
mGeckoChild->DispatchWindowEvent(geckoEvent);
|
|
|
|
}
|
|
|
|
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2002-02-17 19:09:07 +00:00
|
|
|
}
|
2001-11-06 15:35:24 +00:00
|
|
|
|
2005-07-19 22:54:07 +00:00
|
|
|
-(void)scrollWheel:(NSEvent*)theEvent
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2008-04-08 04:38:52 +00:00
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
2008-01-15 23:11:55 +00:00
|
|
|
|
2007-11-26 23:19:04 +00:00
|
|
|
if ([self maybeRollup:theEvent])
|
|
|
|
return;
|
|
|
|
|
2008-01-15 23:11:55 +00:00
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
|
|
|
|
2005-07-19 22:54:07 +00:00
|
|
|
// It's possible for a single NSScrollWheel event to carry both useful
|
|
|
|
// deltaX and deltaY, for example, when the "wheel" is a trackpad.
|
|
|
|
// NSMouseScrollEvent can only carry one axis at a time, so the system
|
|
|
|
// event will be split into two Gecko events if necessary.
|
|
|
|
[self scrollWheel:theEvent forAxis:nsMouseScrollEvent::kIsVertical];
|
2008-01-15 23:11:55 +00:00
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
2005-07-19 22:54:07 +00:00
|
|
|
[self scrollWheel:theEvent forAxis:nsMouseScrollEvent::kIsHorizontal];
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2005-07-19 22:54:07 +00:00
|
|
|
}
|
|
|
|
|
2005-06-16 12:49:43 +00:00
|
|
|
-(NSMenu*)menuForEvent:(NSEvent*)theEvent
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
|
|
|
|
2007-06-15 22:34:48 +00:00
|
|
|
if (!mGeckoChild || [self isPluginView])
|
2005-07-25 15:56:25 +00:00
|
|
|
return nil;
|
2007-08-21 01:02:09 +00:00
|
|
|
|
2008-04-08 04:38:52 +00:00
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
2008-01-15 23:11:55 +00:00
|
|
|
|
2007-11-26 23:19:04 +00:00
|
|
|
[self maybeRollup:theEvent];
|
2008-01-15 23:11:55 +00:00
|
|
|
if (!mGeckoChild)
|
|
|
|
return nil;
|
2007-11-26 23:19:04 +00:00
|
|
|
|
2008-04-06 23:52:05 +00:00
|
|
|
// Cocoa doesn't always dispatch a mouseDown: for a control-click event,
|
|
|
|
// depends on what we return from menuForEvent:. Gecko always expects one
|
|
|
|
// and expects the mouse down event before the context menu event, so
|
|
|
|
// get that event sent first if this is a left mouse click.
|
|
|
|
if ([theEvent type] == NSLeftMouseDown) {
|
|
|
|
[self mouseDown:theEvent];
|
|
|
|
if (!mGeckoChild)
|
|
|
|
return nil;
|
|
|
|
}
|
2008-01-17 04:59:43 +00:00
|
|
|
|
|
|
|
nsMouseEvent geckoEvent(PR_TRUE, NS_CONTEXTMENU, nsnull, nsMouseEvent::eReal);
|
|
|
|
[self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
|
|
|
|
geckoEvent.button = nsMouseEvent::eRightButton;
|
2008-08-26 00:02:26 +00:00
|
|
|
mGeckoChild->DispatchWindowEvent(geckoEvent);
|
2008-01-17 04:59:43 +00:00
|
|
|
if (!mGeckoChild)
|
|
|
|
return nil;
|
|
|
|
|
2008-03-04 08:06:47 +00:00
|
|
|
[self maybeInitContextMenuTracking];
|
2008-02-28 15:58:33 +00:00
|
|
|
|
2005-06-16 12:49:43 +00:00
|
|
|
// Go up our view chain to fetch the correct menu to return.
|
2006-07-30 22:55:37 +00:00
|
|
|
return [self contextMenu];
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
2005-06-16 12:49:43 +00:00
|
|
|
}
|
|
|
|
|
2006-07-30 22:55:37 +00:00
|
|
|
- (NSMenu*)contextMenu
|
2005-06-16 12:49:43 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
|
|
|
|
2005-09-30 00:59:29 +00:00
|
|
|
NSView* superView = [self superview];
|
2006-07-30 22:55:37 +00:00
|
|
|
if ([superView respondsToSelector:@selector(contextMenu)])
|
|
|
|
return [(NSView<mozView>*)superView contextMenu];
|
2005-09-30 00:59:29 +00:00
|
|
|
|
|
|
|
return nil;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
2005-06-16 12:49:43 +00:00
|
|
|
}
|
|
|
|
|
2009-10-01 04:15:05 +00:00
|
|
|
#ifndef NP_NO_CARBON
|
2002-12-13 08:43:18 +00:00
|
|
|
static PRBool ConvertUnicodeToCharCode(PRUnichar inUniChar, unsigned char* outChar)
|
2002-06-11 22:13:03 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
|
|
|
|
2002-12-13 08:43:18 +00:00
|
|
|
UnicodeToTextInfo converterInfo;
|
|
|
|
TextEncoding systemEncoding;
|
|
|
|
Str255 convertedString;
|
|
|
|
OSStatus err;
|
|
|
|
|
|
|
|
*outChar = 0;
|
|
|
|
|
|
|
|
err = ::UpgradeScriptInfoToTextEncoding(smSystemScript, kTextLanguageDontCare, kTextRegionDontCare, NULL, &systemEncoding);
|
|
|
|
if (err != noErr)
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
err = ::CreateUnicodeToTextInfoByEncoding(systemEncoding, &converterInfo);
|
|
|
|
if (err != noErr)
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
err = ::ConvertFromUnicodeToPString(converterInfo, sizeof(PRUnichar), &inUniChar, convertedString);
|
|
|
|
if (err != noErr)
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
*outChar = convertedString[1];
|
|
|
|
::DisposeUnicodeToTextInfo(&converterInfo);
|
|
|
|
return PR_TRUE;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(PR_FALSE);
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
2009-10-01 04:15:05 +00:00
|
|
|
#endif // NP_NO_CARBON
|
2002-12-13 08:43:18 +00:00
|
|
|
|
2009-08-27 00:29:47 +00:00
|
|
|
static void ConvertCocoaKeyEventToNPCocoaEvent(NSEvent* cocoaEvent, NPCocoaEvent& pluginEvent, PRUint32 keyType = 0)
|
|
|
|
{
|
2009-11-11 20:56:43 +00:00
|
|
|
InitNPCocoaEvent(&pluginEvent);
|
2009-08-27 00:29:47 +00:00
|
|
|
NSEventType nativeType = [cocoaEvent type];
|
|
|
|
switch (nativeType) {
|
|
|
|
case NSKeyDown:
|
|
|
|
pluginEvent.type = NPCocoaEventKeyDown;
|
|
|
|
break;
|
|
|
|
case NSKeyUp:
|
|
|
|
pluginEvent.type = NPCocoaEventKeyUp;
|
|
|
|
break;
|
|
|
|
case NSFlagsChanged:
|
|
|
|
pluginEvent.type = NPCocoaEventFlagsChanged;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
printf("Asked to convert key event of unknown type to Cocoa plugin event!");
|
|
|
|
}
|
|
|
|
pluginEvent.data.key.modifierFlags = [cocoaEvent modifierFlags];
|
|
|
|
// don't try to access character data for flags changed events, it will raise an exception
|
|
|
|
if (nativeType != NSFlagsChanged) {
|
|
|
|
pluginEvent.data.key.characters = (NPNSString*)[cocoaEvent characters];
|
|
|
|
pluginEvent.data.key.charactersIgnoringModifiers = (NPNSString*)[cocoaEvent charactersIgnoringModifiers];
|
|
|
|
pluginEvent.data.key.isARepeat = [cocoaEvent isARepeat];
|
|
|
|
pluginEvent.data.key.keyCode = [cocoaEvent keyCode];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-01 04:15:05 +00:00
|
|
|
#ifndef NP_NO_CARBON
|
2009-06-19 16:15:23 +00:00
|
|
|
static void ConvertCocoaKeyEventToCarbonEvent(NSEvent* cocoaEvent, EventRecord& pluginEvent, PRUint32 keyType = 0)
|
2002-12-13 08:43:18 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-03-12 16:04:40 +00:00
|
|
|
UInt32 charCode = 0;
|
|
|
|
if ([cocoaEvent type] == NSFlagsChanged) {
|
2009-06-19 16:15:23 +00:00
|
|
|
pluginEvent.what = keyType == NS_KEY_DOWN ? keyDown : keyUp;
|
2007-03-12 16:04:40 +00:00
|
|
|
} else {
|
2008-03-25 20:44:06 +00:00
|
|
|
if ([[cocoaEvent characters] length] > 0)
|
|
|
|
charCode = [[cocoaEvent characters] characterAtIndex:0];
|
2007-03-12 16:04:40 +00:00
|
|
|
if ([cocoaEvent type] == NSKeyDown)
|
2009-06-19 16:15:23 +00:00
|
|
|
pluginEvent.what = [cocoaEvent isARepeat] ? autoKey : keyDown;
|
2007-03-12 16:04:40 +00:00
|
|
|
else
|
2009-06-19 16:15:23 +00:00
|
|
|
pluginEvent.what = keyUp;
|
2007-03-12 16:04:40 +00:00
|
|
|
}
|
2002-12-13 08:43:18 +00:00
|
|
|
|
2006-10-19 23:19:50 +00:00
|
|
|
if (charCode >= 0x0080) {
|
2002-06-11 22:13:03 +00:00
|
|
|
switch (charCode) {
|
|
|
|
case NSUpArrowFunctionKey:
|
2002-12-13 08:43:18 +00:00
|
|
|
charCode = kUpArrowCharCode;
|
2002-06-11 22:13:03 +00:00
|
|
|
break;
|
|
|
|
case NSDownArrowFunctionKey:
|
2002-12-13 08:43:18 +00:00
|
|
|
charCode = kDownArrowCharCode;
|
2002-06-11 22:13:03 +00:00
|
|
|
break;
|
|
|
|
case NSLeftArrowFunctionKey:
|
2002-12-13 08:43:18 +00:00
|
|
|
charCode = kLeftArrowCharCode;
|
2002-06-11 22:13:03 +00:00
|
|
|
break;
|
|
|
|
case NSRightArrowFunctionKey:
|
2002-12-13 08:43:18 +00:00
|
|
|
charCode = kRightArrowCharCode;
|
2002-06-11 22:13:03 +00:00
|
|
|
break;
|
|
|
|
default:
|
2002-12-13 08:43:18 +00:00
|
|
|
unsigned char convertedCharCode;
|
|
|
|
if (ConvertUnicodeToCharCode(charCode, &convertedCharCode))
|
|
|
|
charCode = convertedCharCode;
|
|
|
|
//NSLog(@"charcode is %d, converted to %c, char is %@", charCode, convertedCharCode, [cocoaEvent characters]);
|
2002-06-11 22:13:03 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2010-02-23 23:30:39 +00:00
|
|
|
pluginEvent.message = (charCode & 0x00FF) | ([cocoaEvent keyCode] << 8);
|
2009-06-19 16:15:23 +00:00
|
|
|
pluginEvent.when = ::TickCount();
|
|
|
|
::GetGlobalMouse(&pluginEvent.where);
|
2009-09-25 20:10:04 +00:00
|
|
|
pluginEvent.modifiers = ::GetCurrentKeyModifiers();
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
2009-10-01 04:15:05 +00:00
|
|
|
#endif // NP_NO_CARBON
|
2002-12-13 08:43:18 +00:00
|
|
|
|
2007-10-25 06:51:10 +00:00
|
|
|
static PRBool IsPrintableChar(PRUnichar aChar)
|
|
|
|
{
|
|
|
|
return (aChar >= 0x20 && aChar <= 0x7E) || aChar >= 0xA0;
|
|
|
|
}
|
|
|
|
|
2007-10-11 08:23:10 +00:00
|
|
|
static PRUint32 GetGeckoKeyCodeFromChar(PRUnichar aChar)
|
|
|
|
{
|
2007-10-15 12:35:57 +00:00
|
|
|
// We don't support the key code for non-ASCII characters
|
2007-10-25 06:51:10 +00:00
|
|
|
if (aChar > 0x7E)
|
2007-10-15 12:35:57 +00:00
|
|
|
return 0;
|
|
|
|
|
2007-10-25 06:51:10 +00:00
|
|
|
if (aChar >= 'a' && aChar <= 'z') // lowercase
|
|
|
|
return PRUint32(toupper(aChar));
|
|
|
|
else if (aChar >= 'A' && aChar <= 'Z') // uppercase
|
|
|
|
return PRUint32(aChar);
|
|
|
|
else if (aChar >= '0' && aChar <= '9')
|
|
|
|
return PRUint32(aChar - '0' + NS_VK_0);
|
|
|
|
|
2007-10-11 08:23:10 +00:00
|
|
|
switch (aChar)
|
|
|
|
{
|
|
|
|
case kReturnCharCode:
|
|
|
|
case kEnterCharCode:
|
|
|
|
case '\n':
|
|
|
|
return NS_VK_RETURN;
|
|
|
|
case '{':
|
|
|
|
case '[':
|
|
|
|
return NS_VK_OPEN_BRACKET;
|
|
|
|
case '}':
|
|
|
|
case ']':
|
|
|
|
return NS_VK_CLOSE_BRACKET;
|
|
|
|
case '\'':
|
|
|
|
case '"':
|
|
|
|
return NS_VK_QUOTE;
|
|
|
|
|
|
|
|
case '\\': return NS_VK_BACK_SLASH;
|
|
|
|
case ' ': return NS_VK_SPACE;
|
|
|
|
case ';': return NS_VK_SEMICOLON;
|
|
|
|
case '=': return NS_VK_EQUALS;
|
|
|
|
case ',': return NS_VK_COMMA;
|
|
|
|
case '.': return NS_VK_PERIOD;
|
|
|
|
case '/': return NS_VK_SLASH;
|
|
|
|
case '`': return NS_VK_BACK_QUOTE;
|
|
|
|
case '\t': return NS_VK_TAB;
|
2007-10-25 06:51:10 +00:00
|
|
|
case '-': return NS_VK_SUBTRACT;
|
|
|
|
case '+': return NS_VK_ADD;
|
2007-10-11 08:23:10 +00:00
|
|
|
|
|
|
|
default:
|
2007-10-25 06:51:10 +00:00
|
|
|
if (!IsPrintableChar(aChar))
|
|
|
|
NS_WARNING("GetGeckoKeyCodeFromChar has failed.");
|
|
|
|
return 0;
|
|
|
|
}
|
2007-10-11 08:23:10 +00:00
|
|
|
}
|
|
|
|
|
2007-06-12 20:28:26 +00:00
|
|
|
static PRUint32 ConvertMacToGeckoKeyCode(UInt32 keyCode, nsKeyEvent* aKeyEvent, NSString* characters)
|
2002-12-13 08:43:18 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
|
|
|
|
2007-06-12 20:28:26 +00:00
|
|
|
PRUint32 geckoKeyCode = 0;
|
2007-06-30 03:26:42 +00:00
|
|
|
|
2007-06-12 20:28:26 +00:00
|
|
|
switch (keyCode)
|
|
|
|
{
|
|
|
|
// modifiers. We don't get separate events for these
|
|
|
|
case kEscapeKeyCode: geckoKeyCode = NS_VK_ESCAPE; break;
|
2007-11-07 07:40:58 +00:00
|
|
|
case kRCommandKeyCode:
|
2007-06-12 20:28:26 +00:00
|
|
|
case kCommandKeyCode: geckoKeyCode = NS_VK_META; break;
|
2007-11-07 07:40:58 +00:00
|
|
|
case kRShiftKeyCode:
|
2007-06-12 20:28:26 +00:00
|
|
|
case kShiftKeyCode: geckoKeyCode = NS_VK_SHIFT; break;
|
|
|
|
case kCapsLockKeyCode: geckoKeyCode = NS_VK_CAPS_LOCK; break;
|
2007-11-07 07:40:58 +00:00
|
|
|
case kRControlKeyCode:
|
2007-06-12 20:28:26 +00:00
|
|
|
case kControlKeyCode: geckoKeyCode = NS_VK_CONTROL; break;
|
2007-11-07 07:40:58 +00:00
|
|
|
case kROptionKeyCode:
|
2007-06-12 20:28:26 +00:00
|
|
|
case kOptionkeyCode: geckoKeyCode = NS_VK_ALT; break;
|
|
|
|
case kClearKeyCode: geckoKeyCode = NS_VK_CLEAR; break;
|
2007-06-30 03:26:42 +00:00
|
|
|
|
|
|
|
// function keys
|
2007-06-12 20:28:26 +00:00
|
|
|
case kF1KeyCode: geckoKeyCode = NS_VK_F1; break;
|
|
|
|
case kF2KeyCode: geckoKeyCode = NS_VK_F2; break;
|
|
|
|
case kF3KeyCode: geckoKeyCode = NS_VK_F3; break;
|
|
|
|
case kF4KeyCode: geckoKeyCode = NS_VK_F4; break;
|
|
|
|
case kF5KeyCode: geckoKeyCode = NS_VK_F5; break;
|
|
|
|
case kF6KeyCode: geckoKeyCode = NS_VK_F6; break;
|
|
|
|
case kF7KeyCode: geckoKeyCode = NS_VK_F7; break;
|
|
|
|
case kF8KeyCode: geckoKeyCode = NS_VK_F8; break;
|
|
|
|
case kF9KeyCode: geckoKeyCode = NS_VK_F9; break;
|
|
|
|
case kF10KeyCode: geckoKeyCode = NS_VK_F10; break;
|
|
|
|
case kF11KeyCode: geckoKeyCode = NS_VK_F11; break;
|
|
|
|
case kF12KeyCode: geckoKeyCode = NS_VK_F12; break;
|
2007-06-30 03:26:42 +00:00
|
|
|
// case kF13KeyCode: geckoKeyCode = NS_VK_F13; break; // clash with the 3 below
|
|
|
|
// case kF14KeyCode: geckoKeyCode = NS_VK_F14; break;
|
|
|
|
// case kF15KeyCode: geckoKeyCode = NS_VK_F15; break;
|
2007-06-12 20:28:26 +00:00
|
|
|
case kPauseKeyCode: geckoKeyCode = NS_VK_PAUSE; break;
|
|
|
|
case kScrollLockKeyCode: geckoKeyCode = NS_VK_SCROLL_LOCK; break;
|
|
|
|
case kPrintScreenKeyCode: geckoKeyCode = NS_VK_PRINTSCREEN; break;
|
2007-06-30 03:26:42 +00:00
|
|
|
|
|
|
|
// keypad
|
2007-06-12 20:28:26 +00:00
|
|
|
case kKeypad0KeyCode: geckoKeyCode = NS_VK_NUMPAD0; break;
|
|
|
|
case kKeypad1KeyCode: geckoKeyCode = NS_VK_NUMPAD1; break;
|
|
|
|
case kKeypad2KeyCode: geckoKeyCode = NS_VK_NUMPAD2; break;
|
|
|
|
case kKeypad3KeyCode: geckoKeyCode = NS_VK_NUMPAD3; break;
|
|
|
|
case kKeypad4KeyCode: geckoKeyCode = NS_VK_NUMPAD4; break;
|
|
|
|
case kKeypad5KeyCode: geckoKeyCode = NS_VK_NUMPAD5; break;
|
|
|
|
case kKeypad6KeyCode: geckoKeyCode = NS_VK_NUMPAD6; break;
|
|
|
|
case kKeypad7KeyCode: geckoKeyCode = NS_VK_NUMPAD7; break;
|
|
|
|
case kKeypad8KeyCode: geckoKeyCode = NS_VK_NUMPAD8; break;
|
|
|
|
case kKeypad9KeyCode: geckoKeyCode = NS_VK_NUMPAD9; break;
|
2007-06-30 03:26:42 +00:00
|
|
|
|
2007-06-12 20:28:26 +00:00
|
|
|
case kKeypadMultiplyKeyCode: geckoKeyCode = NS_VK_MULTIPLY; break;
|
|
|
|
case kKeypadAddKeyCode: geckoKeyCode = NS_VK_ADD; break;
|
|
|
|
case kKeypadSubtractKeyCode: geckoKeyCode = NS_VK_SUBTRACT; break;
|
|
|
|
case kKeypadDecimalKeyCode: geckoKeyCode = NS_VK_DECIMAL; break;
|
|
|
|
case kKeypadDivideKeyCode: geckoKeyCode = NS_VK_DIVIDE; break;
|
2007-06-30 03:26:42 +00:00
|
|
|
|
|
|
|
// these may clash with forward delete and help
|
2007-06-12 20:28:26 +00:00
|
|
|
case kInsertKeyCode: geckoKeyCode = NS_VK_INSERT; break;
|
|
|
|
case kDeleteKeyCode: geckoKeyCode = NS_VK_DELETE; break;
|
2007-06-30 03:26:42 +00:00
|
|
|
|
2007-06-12 20:28:26 +00:00
|
|
|
case kBackspaceKeyCode: geckoKeyCode = NS_VK_BACK; break;
|
|
|
|
case kTabKeyCode: geckoKeyCode = NS_VK_TAB; break;
|
|
|
|
case kHomeKeyCode: geckoKeyCode = NS_VK_HOME; break;
|
|
|
|
case kEndKeyCode: geckoKeyCode = NS_VK_END; break;
|
|
|
|
case kPageUpKeyCode: geckoKeyCode = NS_VK_PAGE_UP; break;
|
|
|
|
case kPageDownKeyCode: geckoKeyCode = NS_VK_PAGE_DOWN; break;
|
|
|
|
case kLeftArrowKeyCode: geckoKeyCode = NS_VK_LEFT; break;
|
|
|
|
case kRightArrowKeyCode: geckoKeyCode = NS_VK_RIGHT; break;
|
|
|
|
case kUpArrowKeyCode: geckoKeyCode = NS_VK_UP; break;
|
|
|
|
case kDownArrowKeyCode: geckoKeyCode = NS_VK_DOWN; break;
|
2007-06-30 03:26:42 +00:00
|
|
|
case kVK_ANSI_1: geckoKeyCode = NS_VK_1; break;
|
|
|
|
case kVK_ANSI_2: geckoKeyCode = NS_VK_2; break;
|
|
|
|
case kVK_ANSI_3: geckoKeyCode = NS_VK_3; break;
|
|
|
|
case kVK_ANSI_4: geckoKeyCode = NS_VK_4; break;
|
|
|
|
case kVK_ANSI_5: geckoKeyCode = NS_VK_5; break;
|
|
|
|
case kVK_ANSI_6: geckoKeyCode = NS_VK_6; break;
|
|
|
|
case kVK_ANSI_7: geckoKeyCode = NS_VK_7; break;
|
|
|
|
case kVK_ANSI_8: geckoKeyCode = NS_VK_8; break;
|
|
|
|
case kVK_ANSI_9: geckoKeyCode = NS_VK_9; break;
|
|
|
|
case kVK_ANSI_0: geckoKeyCode = NS_VK_0; break;
|
|
|
|
|
2007-06-12 20:28:26 +00:00
|
|
|
default:
|
|
|
|
// if we haven't gotten the key code already, look at the char code
|
2009-03-30 00:38:37 +00:00
|
|
|
if ([characters length])
|
|
|
|
geckoKeyCode = GetGeckoKeyCodeFromChar([characters characterAtIndex:0]);
|
2007-06-12 20:28:26 +00:00
|
|
|
}
|
2007-06-30 03:26:42 +00:00
|
|
|
|
2007-06-12 20:28:26 +00:00
|
|
|
return geckoKeyCode;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0);
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
|
|
|
|
2007-06-12 20:28:26 +00:00
|
|
|
static PRBool IsSpecialGeckoKey(UInt32 macKeyCode)
|
2002-12-13 08:43:18 +00:00
|
|
|
{
|
2007-06-12 20:28:26 +00:00
|
|
|
PRBool isSpecial;
|
|
|
|
|
|
|
|
// this table is used to determine which keys are special and should not generate a charCode
|
|
|
|
switch (macKeyCode)
|
|
|
|
{
|
|
|
|
// modifiers - we don't get separate events for these yet
|
|
|
|
case kEscapeKeyCode:
|
|
|
|
case kShiftKeyCode:
|
2007-11-07 07:40:58 +00:00
|
|
|
case kRShiftKeyCode:
|
2007-06-12 20:28:26 +00:00
|
|
|
case kCommandKeyCode:
|
2007-11-07 07:40:58 +00:00
|
|
|
case kRCommandKeyCode:
|
2007-06-12 20:28:26 +00:00
|
|
|
case kCapsLockKeyCode:
|
|
|
|
case kControlKeyCode:
|
2007-11-07 07:40:58 +00:00
|
|
|
case kRControlKeyCode:
|
2007-06-12 20:28:26 +00:00
|
|
|
case kOptionkeyCode:
|
2007-11-07 07:40:58 +00:00
|
|
|
case kROptionKeyCode:
|
2007-06-12 20:28:26 +00:00
|
|
|
case kClearKeyCode:
|
|
|
|
|
|
|
|
// function keys
|
|
|
|
case kF1KeyCode:
|
|
|
|
case kF2KeyCode:
|
|
|
|
case kF3KeyCode:
|
|
|
|
case kF4KeyCode:
|
|
|
|
case kF5KeyCode:
|
|
|
|
case kF6KeyCode:
|
|
|
|
case kF7KeyCode:
|
|
|
|
case kF8KeyCode:
|
|
|
|
case kF9KeyCode:
|
|
|
|
case kF10KeyCode:
|
|
|
|
case kF11KeyCode:
|
|
|
|
case kF12KeyCode:
|
|
|
|
case kPauseKeyCode:
|
|
|
|
case kScrollLockKeyCode:
|
|
|
|
case kPrintScreenKeyCode:
|
|
|
|
|
|
|
|
case kInsertKeyCode:
|
|
|
|
case kDeleteKeyCode:
|
|
|
|
case kTabKeyCode:
|
|
|
|
case kBackspaceKeyCode:
|
|
|
|
|
|
|
|
case kHomeKeyCode:
|
|
|
|
case kEndKeyCode:
|
|
|
|
case kPageUpKeyCode:
|
|
|
|
case kPageDownKeyCode:
|
|
|
|
case kLeftArrowKeyCode:
|
|
|
|
case kRightArrowKeyCode:
|
|
|
|
case kUpArrowKeyCode:
|
|
|
|
case kDownArrowKeyCode:
|
|
|
|
case kReturnKeyCode:
|
|
|
|
case kEnterKeyCode:
|
|
|
|
case kPowerbookEnterKeyCode:
|
|
|
|
isSpecial = PR_TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
isSpecial = PR_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return isSpecial;
|
|
|
|
}
|
|
|
|
|
2008-03-30 09:17:50 +00:00
|
|
|
static PRBool IsNormalCharInputtingEvent(const nsKeyEvent& aEvent)
|
|
|
|
{
|
|
|
|
// this is not character inputting event, simply.
|
|
|
|
if (!aEvent.isChar || !aEvent.charCode)
|
|
|
|
return PR_FALSE;
|
|
|
|
// if this is unicode char inputting event, we don't need to check
|
|
|
|
// ctrl/alt/command keys
|
|
|
|
if (aEvent.charCode > 0x7F)
|
|
|
|
return PR_TRUE;
|
|
|
|
// ASCII chars should be inputted without ctrl/alt/command keys
|
|
|
|
return !aEvent.isControl && !aEvent.isAlt && !aEvent.isMeta;
|
|
|
|
}
|
|
|
|
|
2007-06-12 20:28:26 +00:00
|
|
|
// Basic conversion for cocoa to gecko events, common to all conversions.
|
|
|
|
// Note that it is OK for inEvent to be nil.
|
|
|
|
- (void) convertGenericCocoaEvent:(NSEvent*)inEvent toGeckoEvent:(nsInputEvent*)outGeckoEvent
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-06-12 20:28:26 +00:00
|
|
|
NS_ASSERTION(outGeckoEvent, "convertGenericCocoaEvent:toGeckoEvent: requires non-null outGeckoEvent");
|
|
|
|
if (!outGeckoEvent)
|
|
|
|
return;
|
|
|
|
|
|
|
|
outGeckoEvent->widget = [self widget];
|
|
|
|
outGeckoEvent->time = PR_IntervalNow();
|
|
|
|
|
|
|
|
if (inEvent) {
|
2010-02-23 23:30:39 +00:00
|
|
|
unsigned int modifiers = [inEvent modifierFlags];
|
2007-06-12 20:28:26 +00:00
|
|
|
outGeckoEvent->isShift = ((modifiers & NSShiftKeyMask) != 0);
|
|
|
|
outGeckoEvent->isControl = ((modifiers & NSControlKeyMask) != 0);
|
|
|
|
outGeckoEvent->isAlt = ((modifiers & NSAlternateKeyMask) != 0);
|
|
|
|
outGeckoEvent->isMeta = ((modifiers & NSCommandKeyMask) != 0);
|
|
|
|
}
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2007-06-12 20:28:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) convertCocoaMouseEvent:(NSEvent*)aMouseEvent toGeckoEvent:(nsInputEvent*)outGeckoEvent
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-06-12 20:28:26 +00:00
|
|
|
NS_ASSERTION(aMouseEvent && outGeckoEvent, "convertCocoaMouseEvent:toGeckoEvent: requires non-null arguments");
|
|
|
|
if (!aMouseEvent || !outGeckoEvent)
|
|
|
|
return;
|
|
|
|
|
|
|
|
[self convertGenericCocoaEvent:aMouseEvent toGeckoEvent:outGeckoEvent];
|
|
|
|
|
|
|
|
// convert point to view coordinate system
|
2009-09-15 21:56:44 +00:00
|
|
|
NSPoint locationInWindow = nsCocoaUtils::EventLocationForWindow(aMouseEvent, [self window]);
|
2009-08-18 02:36:15 +00:00
|
|
|
NSPoint localPoint = [self convertPoint:locationInWindow fromView:nil];
|
2007-07-08 07:08:04 +00:00
|
|
|
outGeckoEvent->refPoint.x = static_cast<nscoord>(localPoint.x);
|
|
|
|
outGeckoEvent->refPoint.y = static_cast<nscoord>(localPoint.y);
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2007-06-12 20:28:26 +00:00
|
|
|
}
|
|
|
|
|
2009-09-08 05:38:42 +00:00
|
|
|
// #define DEBUG_KB 1
|
|
|
|
|
2008-05-07 21:54:21 +00:00
|
|
|
static PRUint32
|
2008-05-08 22:03:46 +00:00
|
|
|
UCKeyTranslateToUnicode(const UCKeyboardLayout* aHandle, UInt32 aKeyCode, UInt32 aModifiers,
|
2008-05-07 21:54:21 +00:00
|
|
|
UInt32 aKbType)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_KB
|
|
|
|
NSLog(@"**** UCKeyTranslateToUnicode: aHandle: %p, aKeyCode: %X, aModifiers: %X, aKbType: %X",
|
|
|
|
aHandle, aKeyCode, aModifiers, aKbType);
|
|
|
|
PRBool isShift = aModifiers & shiftKey;
|
|
|
|
PRBool isCtrl = aModifiers & controlKey;
|
|
|
|
PRBool isOpt = aModifiers & optionKey;
|
|
|
|
PRBool isCmd = aModifiers & cmdKey;
|
|
|
|
PRBool isCL = aModifiers & alphaLock;
|
|
|
|
PRBool isNL = aModifiers & kEventKeyModifierNumLockMask;
|
|
|
|
NSLog(@" Shift: %s, Ctrl: %s, Opt: %s, Cmd: %s, CapsLock: %s, NumLock: %s",
|
|
|
|
isShift ? "ON" : "off", isCtrl ? "ON" : "off", isOpt ? "ON" : "off",
|
|
|
|
isCmd ? "ON" : "off", isCL ? "ON" : "off", isNL ? "ON" : "off");
|
|
|
|
#endif
|
|
|
|
UInt32 deadKeyState = 0;
|
|
|
|
UniCharCount len;
|
|
|
|
UniChar chars[5];
|
|
|
|
OSStatus err = ::UCKeyTranslate(aHandle, aKeyCode,
|
|
|
|
kUCKeyActionDown, aModifiers >> 8,
|
|
|
|
aKbType, kUCKeyTranslateNoDeadKeysMask,
|
|
|
|
&deadKeyState, 5, &len, chars);
|
|
|
|
PRUint32 ch = (err == noErr && len == 1) ? PRUint32(chars[0]) : 0;
|
|
|
|
#ifdef DEBUG_KB
|
|
|
|
NSLog(@" result: %X(%C)", ch, ch > ' ' ? ch : ' ');
|
|
|
|
#endif
|
|
|
|
return ch;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct KeyTranslateData {
|
|
|
|
KeyTranslateData() {
|
|
|
|
mUchr.mLayout = nsnull;
|
|
|
|
mUchr.mKbType = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct {
|
2008-05-08 22:03:46 +00:00
|
|
|
const UCKeyboardLayout* mLayout;
|
2008-05-07 21:54:21 +00:00
|
|
|
UInt32 mKbType;
|
|
|
|
} mUchr;
|
|
|
|
};
|
|
|
|
|
|
|
|
static PRUint32
|
|
|
|
GetUniCharFromKeyTranslate(KeyTranslateData& aData,
|
|
|
|
UInt32 aKeyCode, UInt32 aModifiers)
|
|
|
|
{
|
|
|
|
if (aData.mUchr.mLayout) {
|
|
|
|
return UCKeyTranslateToUnicode(aData.mUchr.mLayout, aKeyCode, aModifiers,
|
|
|
|
aData.mUchr.mKbType);
|
|
|
|
}
|
2009-08-18 04:47:53 +00:00
|
|
|
|
2010-02-23 20:10:25 +00:00
|
|
|
return 0;
|
2009-08-18 04:47:53 +00:00
|
|
|
}
|
|
|
|
|
2008-05-09 00:01:29 +00:00
|
|
|
static PRUint32
|
|
|
|
GetUSLayoutCharFromKeyTranslate(UInt32 aKeyCode, UInt32 aModifiers)
|
|
|
|
{
|
2009-09-08 05:38:42 +00:00
|
|
|
static const UCKeyboardLayout* sUSLayout = nsnull;
|
|
|
|
if (!sUSLayout) {
|
|
|
|
nsTISInputSource tis("com.apple.keylayout.US");
|
|
|
|
sUSLayout = tis.GetUCKeyboardLayout();
|
|
|
|
NS_ENSURE_TRUE(sUSLayout, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
UInt32 kbType = 40; // ANSI, don't use actual layout
|
|
|
|
return UCKeyTranslateToUnicode(sUSLayout, aKeyCode, aModifiers, kbType);
|
2008-05-09 00:01:29 +00:00
|
|
|
}
|
2008-05-07 21:54:21 +00:00
|
|
|
|
2007-06-12 20:28:26 +00:00
|
|
|
- (void) convertCocoaKeyEvent:(NSEvent*)aKeyEvent toGeckoEvent:(nsKeyEvent*)outGeckoEvent
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-06-12 20:28:26 +00:00
|
|
|
NS_ASSERTION(aKeyEvent && outGeckoEvent, "convertCocoaKeyEvent:toGeckoEvent: requires non-null arguments");
|
|
|
|
if (!aKeyEvent || !outGeckoEvent)
|
|
|
|
return;
|
|
|
|
|
|
|
|
[self convertGenericCocoaEvent:aKeyEvent toGeckoEvent:outGeckoEvent];
|
|
|
|
|
|
|
|
// coords for key events are always 0,0
|
|
|
|
outGeckoEvent->refPoint.x = outGeckoEvent->refPoint.y = 0;
|
|
|
|
|
|
|
|
// Initialize whether or not we are using charCodes to false.
|
|
|
|
outGeckoEvent->isChar = PR_FALSE;
|
|
|
|
|
|
|
|
// Check to see if the message is a key press that does not involve
|
|
|
|
// one of our special key codes.
|
2008-09-25 14:54:01 +00:00
|
|
|
if (outGeckoEvent->message == NS_KEY_PRESS &&
|
2010-02-23 23:30:39 +00:00
|
|
|
!IsSpecialGeckoKey([aKeyEvent keyCode])) {
|
2007-06-12 20:28:26 +00:00
|
|
|
outGeckoEvent->isChar = PR_TRUE; // this is not a special key
|
|
|
|
|
|
|
|
outGeckoEvent->charCode = 0;
|
2008-02-29 05:47:41 +00:00
|
|
|
outGeckoEvent->keyCode = 0; // not set for key press events
|
2007-06-12 20:28:26 +00:00
|
|
|
|
2008-04-15 04:16:24 +00:00
|
|
|
NSString* chars = [aKeyEvent characters];
|
|
|
|
if ([chars length] > 0)
|
|
|
|
outGeckoEvent->charCode = [chars characterAtIndex:0];
|
2007-06-12 20:28:26 +00:00
|
|
|
|
|
|
|
// convert control-modified charCode to raw charCode (with appropriate case)
|
|
|
|
if (outGeckoEvent->isControl && outGeckoEvent->charCode <= 26)
|
|
|
|
outGeckoEvent->charCode += (outGeckoEvent->isShift) ? ('A' - 1) : ('a' - 1);
|
2008-07-08 02:19:56 +00:00
|
|
|
|
|
|
|
// Accel and access key handling needs to know the characters that this
|
|
|
|
// key produces with Shift up or down. So, provide this information
|
|
|
|
// when Ctrl or Command or Alt is pressed.
|
2008-04-19 15:09:50 +00:00
|
|
|
if (outGeckoEvent->isControl || outGeckoEvent->isMeta ||
|
|
|
|
outGeckoEvent->isAlt) {
|
2008-05-07 21:54:21 +00:00
|
|
|
KeyTranslateData kt;
|
2008-05-08 22:03:46 +00:00
|
|
|
|
2009-09-08 05:38:42 +00:00
|
|
|
PRBool isRomanKeyboardLayout;
|
2010-02-23 20:10:25 +00:00
|
|
|
|
2009-09-08 05:38:42 +00:00
|
|
|
nsTISInputSource tis;
|
|
|
|
if (gOverrideKeyboardLayout.mOverrideEnabled) {
|
|
|
|
tis.InitByLayoutID(gOverrideKeyboardLayout.mKeyboardLayout);
|
|
|
|
} else {
|
|
|
|
tis.InitByCurrentKeyboardLayout();
|
|
|
|
}
|
|
|
|
kt.mUchr.mLayout = tis.GetUCKeyboardLayout();
|
|
|
|
isRomanKeyboardLayout = tis.IsASCIICapable();
|
2009-08-18 04:47:53 +00:00
|
|
|
|
2008-05-09 23:14:57 +00:00
|
|
|
// If a keyboard layout override is set, we also need to force the
|
|
|
|
// keyboard type to something ANSI to avoid test failures on machines
|
|
|
|
// with JIS keyboards (since the pair of keyboard layout and physical
|
|
|
|
// keyboard type form the actual key layout). This assumes that the
|
|
|
|
// test setting the override was written assuming an ANSI keyboard.
|
|
|
|
if (kt.mUchr.mLayout)
|
|
|
|
kt.mUchr.mKbType = gOverrideKeyboardLayout.mOverrideEnabled ? 40 : ::LMGetKbdType();
|
|
|
|
|
2010-02-23 23:30:39 +00:00
|
|
|
UInt32 key = [aKeyEvent keyCode];
|
2008-05-07 21:54:21 +00:00
|
|
|
|
2008-05-09 01:51:46 +00:00
|
|
|
// Caps lock and num lock modifier state:
|
|
|
|
UInt32 lockState = 0;
|
2010-02-23 23:30:39 +00:00
|
|
|
if ([aKeyEvent modifierFlags] & NSAlphaShiftKeyMask)
|
2008-05-09 01:51:46 +00:00
|
|
|
lockState |= alphaLock;
|
2010-02-23 23:30:39 +00:00
|
|
|
if ([aKeyEvent modifierFlags] & NSNumericPadKeyMask)
|
2008-05-09 01:51:46 +00:00
|
|
|
lockState |= kEventKeyModifierNumLockMask;
|
2008-05-09 00:01:29 +00:00
|
|
|
|
2008-05-07 21:54:21 +00:00
|
|
|
// normal chars
|
2008-05-09 01:51:46 +00:00
|
|
|
PRUint32 unshiftedChar = GetUniCharFromKeyTranslate(kt, key, lockState);
|
2008-05-09 01:58:17 +00:00
|
|
|
UInt32 shiftLockMod = shiftKey | lockState;
|
2008-05-09 01:51:46 +00:00
|
|
|
PRUint32 shiftedChar = GetUniCharFromKeyTranslate(kt, key, shiftLockMod);
|
|
|
|
|
|
|
|
// characters generated with Cmd key
|
|
|
|
// XXX we should remove CapsLock state, which changes characters from
|
|
|
|
// Latin to Cyrillic with Russian layout on 10.4 only when Cmd key
|
2008-05-09 00:01:29 +00:00
|
|
|
// is pressed.
|
2008-05-09 01:56:36 +00:00
|
|
|
UInt32 numState = (lockState & ~alphaLock); // only num lock state
|
2008-05-09 01:51:46 +00:00
|
|
|
PRUint32 uncmdedChar = GetUniCharFromKeyTranslate(kt, key, numState);
|
2008-05-09 23:10:40 +00:00
|
|
|
UInt32 shiftNumMod = numState | shiftKey;
|
|
|
|
PRUint32 uncmdedShiftChar =
|
|
|
|
GetUniCharFromKeyTranslate(kt, key, shiftNumMod);
|
2008-05-09 01:51:46 +00:00
|
|
|
PRUint32 uncmdedUSChar = GetUSLayoutCharFromKeyTranslate(key, numState);
|
2008-05-09 01:56:36 +00:00
|
|
|
UInt32 cmdNumMod = cmdKey | numState;
|
2008-05-09 01:51:46 +00:00
|
|
|
PRUint32 cmdedChar = GetUniCharFromKeyTranslate(kt, key, cmdNumMod);
|
2008-05-09 01:56:36 +00:00
|
|
|
UInt32 cmdShiftNumMod = shiftKey | cmdNumMod;
|
2008-05-09 01:51:46 +00:00
|
|
|
PRUint32 cmdedShiftChar =
|
|
|
|
GetUniCharFromKeyTranslate(kt, key, cmdShiftNumMod);
|
2008-05-07 21:54:21 +00:00
|
|
|
|
|
|
|
// Is the keyboard layout changed by Cmd key?
|
|
|
|
// E.g., Arabic, Russian, Hebrew, Greek and Dvorak-QWERTY.
|
2008-05-09 00:01:29 +00:00
|
|
|
PRBool isCmdSwitchLayout = uncmdedChar != cmdedChar;
|
2008-05-07 21:54:21 +00:00
|
|
|
// Is the keyboard layout for Latin, but Cmd key switches the layout?
|
|
|
|
// I.e., Dvorak-QWERTY
|
2009-09-08 05:38:42 +00:00
|
|
|
PRBool isDvorakQWERTY = isCmdSwitchLayout && isRomanKeyboardLayout;
|
2008-05-07 21:54:21 +00:00
|
|
|
|
|
|
|
// If the current keyboard is not Dvorak-QWERTY or Cmd is not pressed,
|
|
|
|
// we should append unshiftedChar and shiftedChar for handling the
|
2008-07-08 02:19:56 +00:00
|
|
|
// normal characters. These are the characters that the user is most
|
|
|
|
// likely to associate with this key.
|
2008-04-15 04:16:24 +00:00
|
|
|
if ((unshiftedChar || shiftedChar) &&
|
2008-05-07 21:54:21 +00:00
|
|
|
(!outGeckoEvent->isMeta || !isDvorakQWERTY)) {
|
2008-04-15 04:16:24 +00:00
|
|
|
nsAlternativeCharCode altCharCodes(unshiftedChar, shiftedChar);
|
|
|
|
outGeckoEvent->alternativeCharCodes.AppendElement(altCharCodes);
|
|
|
|
}
|
2008-05-09 00:01:29 +00:00
|
|
|
|
2008-07-08 02:19:56 +00:00
|
|
|
// Most keyboard layouts provide the same characters in the NSEvents
|
|
|
|
// with Command+Shift as with Command. However, with Command+Shift we
|
|
|
|
// want the character on the second level. e.g. With a US QWERTY
|
|
|
|
// layout, we want "?" when the "/","?" key is pressed with
|
|
|
|
// Command+Shift.
|
2008-05-09 23:10:40 +00:00
|
|
|
|
|
|
|
// On a German layout, the OS gives us '/' with Cmd+Shift+SS(eszett)
|
|
|
|
// even though Cmd+SS is 'SS' and Shift+'SS' is '?'. This '/' seems
|
|
|
|
// like a hack to make the Cmd+"?" event look the same as the Cmd+"?"
|
|
|
|
// event on a US keyboard. The user thinks they are typing Cmd+"?", so
|
|
|
|
// we'll prefer the "?" character, replacing charCode with shiftedChar
|
|
|
|
// when Shift is pressed. However, in case there is a layout where the
|
|
|
|
// character unique to Cmd+Shift is the character that the user expects,
|
|
|
|
// we'll send it as an alternative char.
|
|
|
|
PRBool hasCmdShiftOnlyChar =
|
|
|
|
cmdedChar != cmdedShiftChar && uncmdedShiftChar != cmdedShiftChar;
|
|
|
|
PRUint32 originalCmdedShiftChar = cmdedShiftChar;
|
|
|
|
|
2008-07-08 02:19:56 +00:00
|
|
|
// If we can make a good guess at the characters that the user would
|
|
|
|
// expect this key combination to produce (with and without Shift) then
|
|
|
|
// use those characters. This also corrects for CapsLock, which was
|
|
|
|
// ignored above.
|
2008-05-09 00:01:29 +00:00
|
|
|
if (!isCmdSwitchLayout) {
|
2008-07-08 02:19:56 +00:00
|
|
|
// The characters produced with Command seem similar to those without
|
|
|
|
// Command.
|
2008-05-09 01:51:46 +00:00
|
|
|
if (unshiftedChar)
|
|
|
|
cmdedChar = unshiftedChar;
|
2008-05-09 23:10:40 +00:00
|
|
|
if (shiftedChar)
|
2008-05-09 00:01:29 +00:00
|
|
|
cmdedShiftChar = shiftedChar;
|
|
|
|
} else if (uncmdedUSChar == cmdedChar) {
|
2008-07-08 02:19:56 +00:00
|
|
|
// It looks like characters from a US layout are provided when Command
|
|
|
|
// is down.
|
2008-05-09 01:51:46 +00:00
|
|
|
PRUint32 ch = GetUSLayoutCharFromKeyTranslate(key, lockState);
|
2008-05-09 00:01:29 +00:00
|
|
|
if (ch)
|
|
|
|
cmdedChar = ch;
|
2008-05-09 01:51:46 +00:00
|
|
|
ch = GetUSLayoutCharFromKeyTranslate(key, shiftLockMod);
|
2008-05-09 23:10:40 +00:00
|
|
|
if (ch)
|
2008-05-09 01:51:46 +00:00
|
|
|
cmdedShiftChar = ch;
|
2008-05-09 00:01:29 +00:00
|
|
|
}
|
|
|
|
|
2008-07-08 02:19:56 +00:00
|
|
|
// Only charCode (not alternativeCharCodes) is available to javascript,
|
|
|
|
// so attempt to set this to the most likely intended (or most useful)
|
|
|
|
// character. Note that cmdedChar and cmdedShiftChar are usually
|
|
|
|
// Latin/ASCII characters and that is what is wanted here as accel
|
|
|
|
// keys are expected to be Latin characters.
|
|
|
|
//
|
2008-05-09 00:01:29 +00:00
|
|
|
// XXX We should do something similar when Control is down (bug 429510).
|
|
|
|
if (outGeckoEvent->isMeta &&
|
|
|
|
!(outGeckoEvent->isControl || outGeckoEvent->isAlt)) {
|
|
|
|
|
|
|
|
// The character to use for charCode.
|
|
|
|
PRUint32 preferredCharCode = 0;
|
|
|
|
preferredCharCode = outGeckoEvent->isShift ? cmdedShiftChar : cmdedChar;
|
|
|
|
|
|
|
|
if (preferredCharCode) {
|
|
|
|
#ifdef DEBUG_KB
|
|
|
|
if (outGeckoEvent->charCode != preferredCharCode) {
|
|
|
|
NSLog(@" charCode replaced: %X(%C) to %X(%C)",
|
|
|
|
outGeckoEvent->charCode,
|
|
|
|
outGeckoEvent->charCode > ' ' ? outGeckoEvent->charCode : ' ',
|
|
|
|
preferredCharCode,
|
|
|
|
preferredCharCode > ' ' ? preferredCharCode : ' ');
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
outGeckoEvent->charCode = preferredCharCode;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-07 21:54:21 +00:00
|
|
|
// If the current keyboard layout is switched by the Cmd key,
|
2008-05-09 00:01:29 +00:00
|
|
|
// we should append cmdedChar and shiftedCmdChar that are
|
2008-05-07 21:54:21 +00:00
|
|
|
// Latin char for the key. But don't append at Dvorak-QWERTY.
|
2008-05-09 00:01:29 +00:00
|
|
|
if ((cmdedChar || cmdedShiftChar) &&
|
2008-05-07 21:54:21 +00:00
|
|
|
isCmdSwitchLayout && !isDvorakQWERTY) {
|
2008-05-09 00:01:29 +00:00
|
|
|
nsAlternativeCharCode altCharCodes(cmdedChar, cmdedShiftChar);
|
2008-05-07 21:54:21 +00:00
|
|
|
outGeckoEvent->alternativeCharCodes.AppendElement(altCharCodes);
|
|
|
|
}
|
2008-05-09 23:10:40 +00:00
|
|
|
// Special case for 'SS' key of German layout. See the comment of
|
|
|
|
// hasCmdShiftOnlyChar definition for the detail.
|
|
|
|
if (hasCmdShiftOnlyChar && originalCmdedShiftChar) {
|
|
|
|
nsAlternativeCharCode altCharCodes(0, originalCmdedShiftChar);
|
|
|
|
outGeckoEvent->alternativeCharCodes.AppendElement(altCharCodes);
|
|
|
|
}
|
2008-04-15 04:16:24 +00:00
|
|
|
}
|
2007-06-12 20:28:26 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
NSString* characters = nil;
|
|
|
|
if ([aKeyEvent type] != NSFlagsChanged)
|
2007-06-30 03:26:42 +00:00
|
|
|
characters = [aKeyEvent charactersIgnoringModifiers];
|
2007-06-12 20:28:26 +00:00
|
|
|
|
2008-09-25 14:54:01 +00:00
|
|
|
outGeckoEvent->keyCode =
|
2010-02-23 23:30:39 +00:00
|
|
|
ConvertMacToGeckoKeyCode([aKeyEvent keyCode], outGeckoEvent, characters);
|
2007-06-12 20:28:26 +00:00
|
|
|
outGeckoEvent->charCode = 0;
|
|
|
|
}
|
|
|
|
|
2008-01-05 23:33:53 +00:00
|
|
|
if (outGeckoEvent->message == NS_KEY_PRESS && !outGeckoEvent->isMeta)
|
2007-06-12 20:28:26 +00:00
|
|
|
[NSCursor setHiddenUntilMouseMoves:YES];
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2007-06-12 20:28:26 +00:00
|
|
|
}
|
|
|
|
|
2009-10-01 04:15:05 +00:00
|
|
|
#ifndef NP_NO_CARBON
|
2008-06-30 16:30:22 +00:00
|
|
|
// Called from PluginKeyEventsHandler() (a handler for Carbon TSM events) to
|
|
|
|
// process a Carbon key event for the currently focused plugin. Both Unicode
|
|
|
|
// characters and "Mac encoding characters" (in the MBCS or "multibyte
|
|
|
|
// character system") are (or should be) available from aKeyEvent, but here we
|
|
|
|
// use the MCBS characters. This is how the WebKit does things, and seems to
|
|
|
|
// be what plugins expect.
|
|
|
|
- (void) processPluginKeyEvent:(EventRef)aKeyEvent
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
|
|
|
|
2010-06-10 00:56:17 +00:00
|
|
|
if (mPluginEventModel == NPEventModelCocoa) {
|
|
|
|
UInt32 size;
|
|
|
|
OSStatus status = ::GetEventParameter(aKeyEvent, kEventParamKeyUnicodes, typeUnicodeText, NULL, 0, &size, NULL);
|
|
|
|
if (status != noErr)
|
|
|
|
return;
|
|
|
|
|
|
|
|
UniChar* chars = (UniChar*)malloc(size);
|
|
|
|
if (!chars)
|
|
|
|
return;
|
|
|
|
|
|
|
|
status = ::GetEventParameter(aKeyEvent, kEventParamKeyUnicodes, typeUnicodeText, NULL, size, NULL, chars);
|
|
|
|
if (status != noErr) {
|
|
|
|
free(chars);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CFStringRef text = ::CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, chars, (size / sizeof(UniChar)), kCFAllocatorNull);
|
|
|
|
if (!text) {
|
|
|
|
free(chars);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
NPCocoaEvent cocoaTextEvent;
|
|
|
|
InitNPCocoaEvent(&cocoaTextEvent);
|
|
|
|
cocoaTextEvent.type = NPCocoaEventTextInput;
|
|
|
|
cocoaTextEvent.data.text.text = (NPNSString*)text;
|
|
|
|
|
|
|
|
nsGUIEvent pluginTextEvent(PR_TRUE, NS_NON_RETARGETED_PLUGIN_EVENT, mGeckoChild);
|
|
|
|
pluginTextEvent.time = PR_IntervalNow();
|
|
|
|
pluginTextEvent.pluginEvent = (void*)&cocoaTextEvent;
|
|
|
|
mGeckoChild->DispatchWindowEvent(pluginTextEvent);
|
|
|
|
|
|
|
|
::CFRelease(text);
|
|
|
|
free(chars);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-06-30 16:30:22 +00:00
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
|
|
|
|
|
|
|
UInt32 numCharCodes;
|
|
|
|
OSStatus status = ::GetEventParameter(aKeyEvent, kEventParamKeyMacCharCodes,
|
|
|
|
typeChar, NULL, 0, &numCharCodes, NULL);
|
|
|
|
if (status != noErr)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsAutoTArray<unsigned char, 3> charCodes;
|
|
|
|
charCodes.SetLength(numCharCodes);
|
|
|
|
status = ::GetEventParameter(aKeyEvent, kEventParamKeyMacCharCodes,
|
2009-10-01 04:15:05 +00:00
|
|
|
typeChar, NULL, numCharCodes, NULL, charCodes.Elements());
|
2008-06-30 16:30:22 +00:00
|
|
|
if (status != noErr)
|
|
|
|
return;
|
|
|
|
|
|
|
|
UInt32 modifiers;
|
|
|
|
status = ::GetEventParameter(aKeyEvent, kEventParamKeyModifiers,
|
|
|
|
typeUInt32, NULL, sizeof(modifiers), NULL, &modifiers);
|
|
|
|
if (status != noErr)
|
|
|
|
return;
|
|
|
|
|
|
|
|
UInt32 macKeyCode;
|
|
|
|
status = ::GetEventParameter(aKeyEvent, kEventParamKeyCode,
|
|
|
|
typeUInt32, NULL, sizeof(macKeyCode), NULL, &macKeyCode);
|
|
|
|
if (status != noErr)
|
|
|
|
return;
|
|
|
|
|
|
|
|
EventRef cloneEvent = ::CopyEvent(aKeyEvent);
|
|
|
|
for (unsigned int i = 0; i < numCharCodes; ++i) {
|
|
|
|
status = ::SetEventParameter(cloneEvent, kEventParamKeyMacCharCodes,
|
|
|
|
typeChar, 1, charCodes.Elements() + i);
|
|
|
|
if (status != noErr)
|
|
|
|
break;
|
|
|
|
|
|
|
|
EventRecord eventRec;
|
|
|
|
if (::ConvertEventRefToEventRecord(cloneEvent, &eventRec)) {
|
|
|
|
nsKeyEvent keyDownEvent(PR_TRUE, NS_KEY_DOWN, mGeckoChild);
|
|
|
|
|
|
|
|
PRUint32 keyCode(ConvertMacToGeckoKeyCode(macKeyCode, &keyDownEvent, @""));
|
|
|
|
PRUint32 charCode(charCodes.ElementAt(i));
|
|
|
|
|
|
|
|
keyDownEvent.time = PR_IntervalNow();
|
2009-11-10 21:55:38 +00:00
|
|
|
keyDownEvent.pluginEvent = &eventRec;
|
2008-06-30 16:30:22 +00:00
|
|
|
if (IsSpecialGeckoKey(macKeyCode)) {
|
|
|
|
keyDownEvent.keyCode = keyCode;
|
|
|
|
} else {
|
|
|
|
keyDownEvent.charCode = charCode;
|
|
|
|
keyDownEvent.isChar = PR_TRUE;
|
|
|
|
}
|
|
|
|
keyDownEvent.isShift = ((modifiers & shiftKey) != 0);
|
|
|
|
keyDownEvent.isControl = ((modifiers & controlKey) != 0);
|
|
|
|
keyDownEvent.isAlt = ((modifiers & optionKey) != 0);
|
|
|
|
keyDownEvent.isMeta = ((modifiers & cmdKey) != 0); // Should never happen
|
|
|
|
mGeckoChild->DispatchWindowEvent(keyDownEvent);
|
|
|
|
if (!mGeckoChild)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
::ReleaseEvent(cloneEvent);
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
2009-10-01 04:15:05 +00:00
|
|
|
#endif // NP_NO_CARBON
|
2008-06-30 16:30:22 +00:00
|
|
|
|
2010-06-10 00:56:17 +00:00
|
|
|
- (void)pluginRequestsComplexTextInputForCurrentEvent
|
|
|
|
{
|
|
|
|
mPluginComplexTextInputRequested = YES;
|
|
|
|
}
|
|
|
|
|
2010-04-10 09:24:35 +00:00
|
|
|
- (void)sendCompositionEvent:(PRInt32) aEventType
|
2007-06-12 20:28:26 +00:00
|
|
|
{
|
|
|
|
#ifdef DEBUG_IME
|
|
|
|
NSLog(@"****in sendCompositionEvent; type = %d", aEventType);
|
|
|
|
#endif
|
|
|
|
|
2007-06-15 22:34:48 +00:00
|
|
|
if (!mGeckoChild)
|
2010-04-10 09:24:35 +00:00
|
|
|
return;
|
2007-06-15 22:34:48 +00:00
|
|
|
|
2007-06-12 20:28:26 +00:00
|
|
|
// static void init_composition_event( *aEvent, int aType)
|
|
|
|
nsCompositionEvent event(PR_TRUE, aEventType, mGeckoChild);
|
|
|
|
event.time = PR_IntervalNow();
|
|
|
|
mGeckoChild->DispatchWindowEvent(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)sendTextEvent:(PRUnichar*) aBuffer
|
|
|
|
attributedString:(NSAttributedString*) aString
|
|
|
|
selectedRange:(NSRange) selRange
|
|
|
|
markedRange:(NSRange) markRange
|
|
|
|
doCommit:(BOOL) doCommit
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_IME
|
|
|
|
NSLog(@"****in sendTextEvent; string = '%@'", aString);
|
|
|
|
NSLog(@" markRange = %d, %d; selRange = %d, %d", markRange.location, markRange.length, selRange.location, selRange.length);
|
|
|
|
#endif
|
|
|
|
|
2007-06-15 22:34:48 +00:00
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
|
|
|
|
2007-06-12 20:28:26 +00:00
|
|
|
nsTextEvent textEvent(PR_TRUE, NS_TEXT_TEXT, mGeckoChild);
|
|
|
|
textEvent.time = PR_IntervalNow();
|
|
|
|
textEvent.theText = aBuffer;
|
|
|
|
if (!doCommit)
|
|
|
|
FillTextRangeInTextEvent(&textEvent, aString, markRange, selRange);
|
|
|
|
|
|
|
|
mGeckoChild->DispatchWindowEvent(textEvent);
|
|
|
|
if (textEvent.rangeArray)
|
|
|
|
delete [] textEvent.rangeArray;
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark -
|
|
|
|
// NSTextInput implementation
|
|
|
|
|
|
|
|
#define MAX_BUFFER_SIZE 32
|
|
|
|
|
|
|
|
- (void)insertText:(id)insertString
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-06-12 20:28:26 +00:00
|
|
|
#if DEBUG_IME
|
|
|
|
NSLog(@"****in insertText: '%@'", insertString);
|
2008-02-20 07:40:04 +00:00
|
|
|
NSLog(@" markRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
|
2007-06-12 20:28:26 +00:00
|
|
|
#endif
|
2007-06-15 22:34:48 +00:00
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
2007-06-12 20:28:26 +00:00
|
|
|
|
2009-10-01 02:52:50 +00:00
|
|
|
if (mGeckoChild->TextInputHandler()->IgnoreIMEComposition())
|
|
|
|
return;
|
|
|
|
|
2008-04-08 04:38:52 +00:00
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
2007-08-16 20:30:50 +00:00
|
|
|
|
2007-06-12 20:28:26 +00:00
|
|
|
if (![insertString isKindOfClass:[NSAttributedString class]])
|
|
|
|
insertString = [[[NSAttributedString alloc] initWithString:insertString] autorelease];
|
|
|
|
|
|
|
|
NSString *tmpStr = [insertString string];
|
|
|
|
unsigned int len = [tmpStr length];
|
2009-10-01 02:52:50 +00:00
|
|
|
if (!mGeckoChild->IME_IsComposing() && len == 0)
|
2007-08-16 20:30:50 +00:00
|
|
|
return; // nothing to do
|
2007-06-12 20:28:26 +00:00
|
|
|
PRUnichar buffer[MAX_BUFFER_SIZE];
|
|
|
|
PRUnichar *bufPtr = (len >= MAX_BUFFER_SIZE) ? new PRUnichar[len + 1] : buffer;
|
2007-11-26 23:19:04 +00:00
|
|
|
[tmpStr getCharacters:bufPtr];
|
2007-08-16 20:30:50 +00:00
|
|
|
bufPtr[len] = PRUnichar('\0');
|
2007-06-12 20:28:26 +00:00
|
|
|
|
2009-10-01 02:52:50 +00:00
|
|
|
if (len == 1 && !mGeckoChild->IME_IsComposing()) {
|
2008-03-03 06:29:16 +00:00
|
|
|
// don't let the same event be fired twice when hitting
|
|
|
|
// enter/return! (Bug 420502)
|
|
|
|
if (mKeyPressSent)
|
|
|
|
return;
|
|
|
|
|
2007-06-12 20:28:26 +00:00
|
|
|
// dispatch keypress event with char instead of textEvent
|
|
|
|
nsKeyEvent geckoEvent(PR_TRUE, NS_KEY_PRESS, mGeckoChild);
|
|
|
|
geckoEvent.time = PR_IntervalNow();
|
|
|
|
geckoEvent.charCode = bufPtr[0]; // gecko expects OS-translated unicode
|
2007-10-25 06:51:10 +00:00
|
|
|
geckoEvent.keyCode = 0;
|
2007-06-12 20:28:26 +00:00
|
|
|
geckoEvent.isChar = PR_TRUE;
|
2007-11-26 18:09:38 +00:00
|
|
|
if (mKeyDownHandled)
|
2007-06-12 20:28:26 +00:00
|
|
|
geckoEvent.flags |= NS_EVENT_FLAG_NO_DEFAULT;
|
|
|
|
// don't set other modifiers from the current event, because here in
|
|
|
|
// -insertText: they've already been taken into account in creating
|
|
|
|
// the input string.
|
|
|
|
|
2009-08-27 00:29:47 +00:00
|
|
|
// create event for use by plugins
|
2009-09-01 01:00:13 +00:00
|
|
|
#ifndef NP_NO_CARBON
|
2009-08-27 00:29:47 +00:00
|
|
|
EventRecord carbonEvent;
|
2009-09-01 01:00:13 +00:00
|
|
|
#endif
|
2007-06-12 20:28:26 +00:00
|
|
|
if (mCurKeyEvent) {
|
2008-03-25 20:44:06 +00:00
|
|
|
// XXX The ASCII characters inputting mode of egbridge (Japanese IME)
|
|
|
|
// might send the keyDown event with wrong keyboard layout if other
|
|
|
|
// keyboard layouts are already loaded. In that case, the native event
|
|
|
|
// doesn't match to this gecko event...
|
2009-09-01 01:00:13 +00:00
|
|
|
#ifndef NP_NO_CARBON
|
|
|
|
if (mPluginEventModel == NPEventModelCarbon) {
|
2009-08-27 00:29:47 +00:00
|
|
|
ConvertCocoaKeyEventToCarbonEvent(mCurKeyEvent, carbonEvent);
|
2009-11-10 21:55:38 +00:00
|
|
|
geckoEvent.pluginEvent = &carbonEvent;
|
2010-03-26 00:14:56 +00:00
|
|
|
}
|
2009-09-01 01:00:13 +00:00
|
|
|
#endif
|
2010-03-26 00:14:56 +00:00
|
|
|
|
2010-02-23 23:30:39 +00:00
|
|
|
geckoEvent.isShift = ([mCurKeyEvent modifierFlags] & NSShiftKeyMask) != 0;
|
2007-10-25 06:51:10 +00:00
|
|
|
if (!IsPrintableChar(geckoEvent.charCode)) {
|
|
|
|
geckoEvent.keyCode =
|
2010-02-23 23:30:39 +00:00
|
|
|
ConvertMacToGeckoKeyCode([mCurKeyEvent keyCode], &geckoEvent,
|
2007-10-25 06:51:10 +00:00
|
|
|
[mCurKeyEvent charactersIgnoringModifiers]);
|
|
|
|
geckoEvent.charCode = 0;
|
|
|
|
}
|
2007-10-11 08:23:10 +00:00
|
|
|
} else {
|
|
|
|
// Note that insertText is not called only at key pressing.
|
2007-10-25 06:51:10 +00:00
|
|
|
if (!IsPrintableChar(geckoEvent.charCode)) {
|
|
|
|
geckoEvent.keyCode = GetGeckoKeyCodeFromChar(geckoEvent.charCode);
|
|
|
|
geckoEvent.charCode = 0;
|
|
|
|
}
|
2007-06-12 20:28:26 +00:00
|
|
|
}
|
|
|
|
|
2008-11-12 06:35:00 +00:00
|
|
|
PRBool keyPressHandled = mGeckoChild->DispatchWindowEvent(geckoEvent);
|
2010-01-07 21:06:14 +00:00
|
|
|
// Note: mGeckoChild might have become null here. Don't count on it from here on.
|
2008-11-12 06:35:00 +00:00
|
|
|
// Only record the results of dispatching geckoEvent if we're currently
|
|
|
|
// processing a keyDown event.
|
|
|
|
if (mCurKeyEvent) {
|
|
|
|
mKeyPressHandled = keyPressHandled;
|
|
|
|
mKeyPressSent = YES;
|
|
|
|
}
|
2007-06-12 20:28:26 +00:00
|
|
|
}
|
|
|
|
else {
|
2009-10-01 02:52:50 +00:00
|
|
|
if (!mGeckoChild->IME_IsComposing()) {
|
2007-11-26 23:19:04 +00:00
|
|
|
[self sendCompositionEvent:NS_COMPOSITION_START];
|
2008-01-15 23:11:55 +00:00
|
|
|
// Note: mGeckoChild might have become null here. Don't count on it from here on.
|
2010-01-07 21:06:14 +00:00
|
|
|
if (mGeckoChild) {
|
|
|
|
mGeckoChild->IME_OnStartComposition(self);
|
|
|
|
// Note: mGeckoChild might have become null here. Don't count on it from here on.
|
|
|
|
}
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
|
|
|
|
2010-01-07 21:06:14 +00:00
|
|
|
if (mGeckoChild && mGeckoChild->IME_IgnoreCommit()) {
|
2007-08-16 20:30:50 +00:00
|
|
|
tmpStr = [tmpStr init];
|
|
|
|
len = 0;
|
|
|
|
bufPtr[0] = PRUnichar('\0');
|
|
|
|
insertString =
|
|
|
|
[[[NSAttributedString alloc] initWithString:tmpStr] autorelease];
|
|
|
|
}
|
2002-12-13 08:43:18 +00:00
|
|
|
[self sendTextEvent:bufPtr attributedString:insertString
|
|
|
|
selectedRange:NSMakeRange(0, len)
|
|
|
|
markedRange:mMarkedRange
|
|
|
|
doCommit:YES];
|
2008-01-15 23:11:55 +00:00
|
|
|
// Note: mGeckoChild might have become null here. Don't count on it from here on.
|
2002-12-13 08:43:18 +00:00
|
|
|
|
2007-11-26 23:19:04 +00:00
|
|
|
[self sendCompositionEvent:NS_COMPOSITION_END];
|
2008-01-15 23:11:55 +00:00
|
|
|
// Note: mGeckoChild might have become null here. Don't count on it from here on.
|
2010-01-07 21:06:14 +00:00
|
|
|
if (mGeckoChild) {
|
|
|
|
mGeckoChild->IME_OnEndComposition();
|
|
|
|
// Note: mGeckoChild might have become null here. Don't count on it from here on.
|
|
|
|
}
|
2008-02-20 07:40:04 +00:00
|
|
|
mMarkedRange = NSMakeRange(NSNotFound, 0);
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (bufPtr != buffer)
|
|
|
|
delete[] bufPtr;
|
2007-08-16 20:30:50 +00:00
|
|
|
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)insertNewline:(id)sender
|
|
|
|
{
|
2008-03-04 22:32:55 +00:00
|
|
|
[self insertText:@"\n"];
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
|
|
|
|
2005-05-27 03:49:14 +00:00
|
|
|
- (void) doCommandBySelector:(SEL)aSelector
|
2008-02-20 23:47:05 +00:00
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
2008-03-04 22:32:55 +00:00
|
|
|
|
2005-09-30 00:59:29 +00:00
|
|
|
#if DEBUG_IME
|
2008-03-14 01:08:04 +00:00
|
|
|
NSLog(@"**** in doCommandBySelector %s (ignore %d)", aSelector, mKeyPressHandled);
|
2005-09-30 00:59:29 +00:00
|
|
|
#endif
|
2007-04-22 00:37:27 +00:00
|
|
|
|
2008-03-14 01:08:04 +00:00
|
|
|
if (!mKeyPressHandled)
|
2008-03-04 22:32:55 +00:00
|
|
|
[super doCommandBySelector:aSelector];
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
|
|
|
|
2005-05-27 03:49:14 +00:00
|
|
|
- (void) setMarkedText:(id)aString selectedRange:(NSRange)selRange
|
2002-12-13 08:43:18 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2002-12-13 08:43:18 +00:00
|
|
|
#if DEBUG_IME
|
2005-06-26 03:25:52 +00:00
|
|
|
NSLog(@"****in setMarkedText location: %d, length: %d", selRange.location, selRange.length);
|
2008-02-20 07:40:04 +00:00
|
|
|
NSLog(@" markRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
|
2005-09-30 00:59:29 +00:00
|
|
|
NSLog(@" aString = '%@'", aString);
|
2002-12-13 08:43:18 +00:00
|
|
|
#endif
|
|
|
|
|
2010-01-07 21:06:14 +00:00
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
|
|
|
|
2009-10-01 02:52:50 +00:00
|
|
|
if (mGeckoChild->TextInputHandler()->IgnoreIMEComposition())
|
|
|
|
return;
|
|
|
|
|
2008-04-08 04:38:52 +00:00
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
2007-08-16 20:30:50 +00:00
|
|
|
|
2006-10-19 23:19:50 +00:00
|
|
|
if (![aString isKindOfClass:[NSAttributedString class]])
|
2002-12-13 08:43:18 +00:00
|
|
|
aString = [[[NSAttributedString alloc] initWithString:aString] autorelease];
|
|
|
|
|
|
|
|
NSMutableAttributedString *mutableAttribStr = aString;
|
|
|
|
NSString *tmpStr = [mutableAttribStr string];
|
|
|
|
unsigned int len = [tmpStr length];
|
|
|
|
PRUnichar buffer[MAX_BUFFER_SIZE];
|
2004-01-29 19:42:13 +00:00
|
|
|
PRUnichar *bufPtr = (len >= MAX_BUFFER_SIZE) ? new PRUnichar[len + 1] : buffer;
|
2007-11-26 23:19:04 +00:00
|
|
|
[tmpStr getCharacters:bufPtr];
|
2007-08-16 20:30:50 +00:00
|
|
|
bufPtr[len] = PRUnichar('\0');
|
2002-12-13 08:43:18 +00:00
|
|
|
|
|
|
|
#if DEBUG_IME
|
|
|
|
printf("****in setMarkedText, len = %d, text = ", len);
|
|
|
|
PRUint32 n = 0;
|
|
|
|
PRUint32 maxlen = len > 12 ? 12 : len;
|
2008-02-20 07:40:04 +00:00
|
|
|
for (PRUnichar *a = bufPtr; (*a != PRUnichar('\0')) && n<maxlen; a++, n++)
|
|
|
|
printf((*a&0xff80) ? "\\u%4X" : "%c", *a);
|
2002-12-13 08:43:18 +00:00
|
|
|
printf("\n");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
mMarkedRange.length = len;
|
|
|
|
|
2009-10-01 02:52:50 +00:00
|
|
|
if (!mGeckoChild->IME_IsComposing() && len > 0) {
|
2008-02-20 07:40:04 +00:00
|
|
|
nsQueryContentEvent selection(PR_TRUE, NS_QUERY_SELECTED_TEXT, mGeckoChild);
|
|
|
|
mGeckoChild->DispatchWindowEvent(selection);
|
|
|
|
mMarkedRange.location = selection.mSucceeded ? selection.mReply.mOffset : 0;
|
2002-12-13 08:43:18 +00:00
|
|
|
[self sendCompositionEvent:NS_COMPOSITION_START];
|
2008-01-15 23:11:55 +00:00
|
|
|
// Note: mGeckoChild might have become null here. Don't count on it from here on.
|
2010-01-07 21:06:14 +00:00
|
|
|
if (mGeckoChild) {
|
|
|
|
mGeckoChild->IME_OnStartComposition(self);
|
|
|
|
// Note: mGeckoChild might have become null here. Don't count on it from here on.
|
|
|
|
}
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
|
|
|
|
2009-10-01 02:52:50 +00:00
|
|
|
if (mGeckoChild->IME_IsComposing()) {
|
|
|
|
mGeckoChild->IME_OnUpdateComposition(tmpStr);
|
2007-08-16 20:30:50 +00:00
|
|
|
|
2008-04-22 03:30:45 +00:00
|
|
|
BOOL commit = len == 0;
|
|
|
|
[self sendTextEvent:bufPtr attributedString:aString
|
|
|
|
selectedRange:selRange
|
|
|
|
markedRange:mMarkedRange
|
|
|
|
doCommit:commit];
|
2008-01-15 23:11:55 +00:00
|
|
|
// Note: mGeckoChild might have become null here. Don't count on it from here on.
|
2008-04-22 03:30:45 +00:00
|
|
|
|
|
|
|
if (commit) {
|
|
|
|
[self sendCompositionEvent:NS_COMPOSITION_END];
|
2010-01-07 21:06:14 +00:00
|
|
|
// Note: mGeckoChild might have become null here. Don't count on it from here on.
|
|
|
|
if (mGeckoChild) {
|
|
|
|
mGeckoChild->IME_OnEndComposition();
|
|
|
|
// Note: mGeckoChild might have become null here. Don't count on it from here on.
|
|
|
|
}
|
2008-04-22 03:30:45 +00:00
|
|
|
}
|
2008-01-15 23:11:55 +00:00
|
|
|
}
|
2008-04-22 03:30:45 +00:00
|
|
|
|
2002-12-13 08:43:18 +00:00
|
|
|
if (bufPtr != buffer)
|
|
|
|
delete[] bufPtr;
|
2007-08-16 20:30:50 +00:00
|
|
|
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
|
|
|
|
2005-05-27 03:49:14 +00:00
|
|
|
- (void) unmarkText
|
2002-12-13 08:43:18 +00:00
|
|
|
{
|
|
|
|
#if DEBUG_IME
|
2005-06-26 03:25:52 +00:00
|
|
|
NSLog(@"****in unmarkText");
|
|
|
|
NSLog(@" markedRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
|
2002-12-13 08:43:18 +00:00
|
|
|
#endif
|
2010-01-07 21:06:14 +00:00
|
|
|
if (mGeckoChild)
|
|
|
|
mGeckoChild->IME_CommitComposition();
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
|
|
|
|
2005-05-27 03:49:14 +00:00
|
|
|
- (BOOL) hasMarkedText
|
2002-12-13 08:43:18 +00:00
|
|
|
{
|
2008-02-20 07:40:04 +00:00
|
|
|
#if DEBUG_IME
|
|
|
|
NSLog(@"****in hasMarkText");
|
|
|
|
NSLog(@" markedRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
|
|
|
|
#endif
|
2005-06-26 03:25:52 +00:00
|
|
|
return (mMarkedRange.location != NSNotFound) && (mMarkedRange.length != 0);
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
|
|
|
|
2009-09-01 01:00:13 +00:00
|
|
|
- (NSInteger) conversationIdentifier
|
2002-12-13 08:43:18 +00:00
|
|
|
{
|
2008-02-20 07:40:04 +00:00
|
|
|
#if DEBUG_IME
|
|
|
|
NSLog(@"****in conversationIdentifier");
|
|
|
|
#endif
|
|
|
|
if (!mGeckoChild)
|
|
|
|
return (long)self;
|
|
|
|
nsQueryContentEvent textContent(PR_TRUE, NS_QUERY_TEXT_CONTENT, mGeckoChild);
|
|
|
|
textContent.InitForQueryTextContent(0, 0);
|
|
|
|
mGeckoChild->DispatchWindowEvent(textContent);
|
|
|
|
if (!textContent.mSucceeded)
|
|
|
|
return (long)self;
|
|
|
|
#if DEBUG_IME
|
|
|
|
NSLog(@" the ID = %ld", (long)textContent.mReply.mContentsRoot);
|
|
|
|
#endif
|
|
|
|
return (long)textContent.mReply.mContentsRoot;
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
|
|
|
|
2005-05-27 03:49:14 +00:00
|
|
|
- (NSAttributedString *) attributedSubstringFromRange:(NSRange)theRange
|
2002-12-13 08:43:18 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
|
|
|
|
2002-12-13 08:43:18 +00:00
|
|
|
#if DEBUG_IME
|
2005-06-26 03:25:52 +00:00
|
|
|
NSLog(@"****in attributedSubstringFromRange");
|
|
|
|
NSLog(@" theRange = %d, %d", theRange.location, theRange.length);
|
|
|
|
NSLog(@" markedRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
|
2002-12-13 08:43:18 +00:00
|
|
|
#endif
|
2008-02-20 07:40:04 +00:00
|
|
|
if (!mGeckoChild || theRange.length == 0)
|
2007-06-15 22:34:48 +00:00
|
|
|
return nil;
|
2002-12-13 08:43:18 +00:00
|
|
|
|
2008-02-20 07:40:04 +00:00
|
|
|
nsAutoString str;
|
|
|
|
nsQueryContentEvent textContent(PR_TRUE, NS_QUERY_TEXT_CONTENT, mGeckoChild);
|
|
|
|
textContent.InitForQueryTextContent(theRange.location, theRange.length);
|
|
|
|
mGeckoChild->DispatchWindowEvent(textContent);
|
2002-12-13 08:43:18 +00:00
|
|
|
|
2008-02-20 07:40:04 +00:00
|
|
|
if (!textContent.mSucceeded || textContent.mReply.mString.IsEmpty())
|
|
|
|
return nil;
|
2002-12-13 08:43:18 +00:00
|
|
|
|
2008-05-05 23:01:07 +00:00
|
|
|
NSString* nsstr = ToNSString(textContent.mReply.mString);
|
2008-02-20 07:40:04 +00:00
|
|
|
NSAttributedString* result =
|
|
|
|
[[[NSAttributedString alloc] initWithString:nsstr
|
|
|
|
attributes:nil] autorelease];
|
|
|
|
return result;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
2002-06-11 22:13:03 +00:00
|
|
|
}
|
|
|
|
|
2005-05-27 03:49:14 +00:00
|
|
|
- (NSRange) markedRange
|
2002-12-13 08:43:18 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
|
|
|
|
2002-12-13 08:43:18 +00:00
|
|
|
#if DEBUG_IME
|
2005-06-26 03:25:52 +00:00
|
|
|
NSLog(@"****in markedRange");
|
|
|
|
NSLog(@" markedRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
|
2002-12-13 08:43:18 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if (![self hasMarkedText]) {
|
|
|
|
return NSMakeRange(NSNotFound, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return mMarkedRange;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSMakeRange(0, 0));
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
|
|
|
|
2005-05-27 03:49:14 +00:00
|
|
|
- (NSRange) selectedRange
|
2002-12-13 08:43:18 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
|
|
|
|
2002-12-13 08:43:18 +00:00
|
|
|
#if DEBUG_IME
|
2005-06-26 03:25:52 +00:00
|
|
|
NSLog(@"****in selectedRange");
|
|
|
|
NSLog(@" markedRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
|
2002-12-13 08:43:18 +00:00
|
|
|
#endif
|
2008-02-20 07:40:04 +00:00
|
|
|
if (!mGeckoChild)
|
|
|
|
return NSMakeRange(NSNotFound, 0);
|
|
|
|
nsQueryContentEvent selection(PR_TRUE, NS_QUERY_SELECTED_TEXT, mGeckoChild);
|
|
|
|
mGeckoChild->DispatchWindowEvent(selection);
|
|
|
|
if (!selection.mSucceeded)
|
|
|
|
return NSMakeRange(NSNotFound, 0);
|
2002-12-13 08:43:18 +00:00
|
|
|
|
2008-02-20 07:40:04 +00:00
|
|
|
#if DEBUG_IME
|
|
|
|
NSLog(@" result of selectedRange = %d, %d",
|
|
|
|
selection.mReply.mOffset, selection.mReply.mString.Length());
|
|
|
|
#endif
|
|
|
|
return NSMakeRange(selection.mReply.mOffset,
|
|
|
|
selection.mReply.mString.Length());
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSMakeRange(0, 0));
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
|
|
|
|
2005-05-27 03:49:14 +00:00
|
|
|
- (NSRect) firstRectForCharacterRange:(NSRange)theRange
|
2002-12-13 08:43:18 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
|
|
|
|
2002-12-13 08:43:18 +00:00
|
|
|
#if DEBUG_IME
|
2005-06-26 03:25:52 +00:00
|
|
|
NSLog(@"****in firstRectForCharacterRange");
|
|
|
|
NSLog(@" theRange = %d, %d", theRange.location, theRange.length);
|
|
|
|
NSLog(@" markedRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
|
2002-12-13 08:43:18 +00:00
|
|
|
#endif
|
2008-02-20 07:40:04 +00:00
|
|
|
// XXX this returns first character rect or caret rect, it is limitation of
|
|
|
|
// now. We need more work for returns first line rect. But current
|
|
|
|
// implementation is enough for IMEs.
|
|
|
|
|
|
|
|
NSRect rect;
|
|
|
|
if (!mGeckoChild || theRange.location == NSNotFound)
|
|
|
|
return rect;
|
|
|
|
|
2009-01-15 03:27:09 +00:00
|
|
|
nsIntRect r;
|
2008-02-20 07:40:04 +00:00
|
|
|
PRBool useCaretRect = theRange.length == 0;
|
|
|
|
if (!useCaretRect) {
|
2009-02-10 20:56:51 +00:00
|
|
|
nsQueryContentEvent charRect(PR_TRUE, NS_QUERY_TEXT_RECT, mGeckoChild);
|
|
|
|
charRect.InitForQueryTextRect(theRange.location, 1);
|
2008-02-20 07:40:04 +00:00
|
|
|
mGeckoChild->DispatchWindowEvent(charRect);
|
|
|
|
if (charRect.mSucceeded)
|
|
|
|
r = charRect.mReply.mRect;
|
|
|
|
else
|
|
|
|
useCaretRect = PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (useCaretRect) {
|
|
|
|
nsQueryContentEvent caretRect(PR_TRUE, NS_QUERY_CARET_RECT, mGeckoChild);
|
|
|
|
caretRect.InitForQueryCaretRect(theRange.location);
|
|
|
|
mGeckoChild->DispatchWindowEvent(caretRect);
|
|
|
|
if (!caretRect.mSucceeded)
|
|
|
|
return rect;
|
|
|
|
r = caretRect.mReply.mRect;
|
|
|
|
r.width = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIWidget* rootWidget = mGeckoChild->GetTopLevelWidget();
|
|
|
|
NSWindow* rootWindow =
|
|
|
|
static_cast<NSWindow*>(rootWidget->GetNativeData(NS_NATIVE_WINDOW));
|
|
|
|
NSView* rootView =
|
|
|
|
static_cast<NSView*>(rootWidget->GetNativeData(NS_NATIVE_WIDGET));
|
|
|
|
if (!rootWindow || !rootView)
|
|
|
|
return rect;
|
|
|
|
GeckoRectToNSRect(r, rect);
|
|
|
|
rect = [rootView convertRect:rect toView:nil];
|
|
|
|
rect.origin = [rootWindow convertBaseToScreen:rect.origin];
|
|
|
|
#if DEBUG_IME
|
|
|
|
NSLog(@" result rect (x,y,w,h) = %f, %f, %f, %f",
|
|
|
|
rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
|
|
|
|
#endif
|
|
|
|
return rect;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSMakeRect(0.0, 0.0, 0.0, 0.0));
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
|
|
|
|
2009-09-01 01:00:13 +00:00
|
|
|
- (NSUInteger)characterIndexForPoint:(NSPoint)thePoint
|
2002-12-13 08:43:18 +00:00
|
|
|
{
|
|
|
|
#if DEBUG_IME
|
2005-06-26 03:25:52 +00:00
|
|
|
NSLog(@"****in characterIndexForPoint");
|
2008-02-20 07:40:04 +00:00
|
|
|
NSLog(@" markRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
|
2002-12-13 08:43:18 +00:00
|
|
|
#endif
|
|
|
|
|
2005-10-08 00:20:27 +00:00
|
|
|
// To implement this, we'd have to grovel in text frames looking at text offsets.
|
2002-12-13 08:43:18 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-05-27 03:49:14 +00:00
|
|
|
- (NSArray*) validAttributesForMarkedText
|
2002-12-13 08:43:18 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
|
|
|
|
2002-12-13 08:43:18 +00:00
|
|
|
#if DEBUG_IME
|
2005-06-26 03:25:52 +00:00
|
|
|
NSLog(@"****in validAttributesForMarkedText");
|
2008-02-20 07:40:04 +00:00
|
|
|
NSLog(@" markRange = %d, %d", mMarkedRange.location, mMarkedRange.length);
|
2002-12-13 08:43:18 +00:00
|
|
|
#endif
|
|
|
|
|
2005-09-30 00:59:29 +00:00
|
|
|
//return [NSArray arrayWithObjects:NSUnderlineStyleAttributeName, NSMarkedClauseSegmentAttributeName, NSTextInputReplacementRangeAttributeName, nil];
|
2002-12-13 08:43:18 +00:00
|
|
|
return [NSArray array]; // empty array; we don't support any attributes right now
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
2002-12-13 08:43:18 +00:00
|
|
|
}
|
|
|
|
|
2006-12-20 02:13:57 +00:00
|
|
|
#pragma mark -
|
|
|
|
|
2007-10-23 03:27:48 +00:00
|
|
|
+ (NSEvent*)makeNewCocoaEventWithType:(NSEventType)type fromEvent:(NSEvent*)theEvent
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
|
|
|
|
2007-10-23 03:27:48 +00:00
|
|
|
NSEvent* newEvent = [NSEvent keyEventWithType:type
|
|
|
|
location:[theEvent locationInWindow]
|
2010-02-23 23:30:39 +00:00
|
|
|
modifierFlags:[theEvent modifierFlags]
|
2007-10-23 03:27:48 +00:00
|
|
|
timestamp:[theEvent timestamp]
|
|
|
|
windowNumber:[theEvent windowNumber]
|
|
|
|
context:[theEvent context]
|
|
|
|
characters:[theEvent characters]
|
|
|
|
charactersIgnoringModifiers:[theEvent charactersIgnoringModifiers]
|
|
|
|
isARepeat:[theEvent isARepeat]
|
2010-02-23 23:30:39 +00:00
|
|
|
keyCode:[theEvent keyCode]];
|
2007-10-23 03:27:48 +00:00
|
|
|
return newEvent;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
2007-10-23 03:27:48 +00:00
|
|
|
}
|
|
|
|
|
2008-05-05 23:01:07 +00:00
|
|
|
#ifdef PR_LOGGING
|
|
|
|
static const char* ToEscapedString(NSString* aString, nsCAutoString& aBuf)
|
|
|
|
{
|
|
|
|
for (PRUint32 i = 0; i < [aString length]; ++i) {
|
|
|
|
unichar ch = [aString characterAtIndex:i];
|
|
|
|
if (ch >= 32 && ch < 128) {
|
|
|
|
aBuf.Append(char(ch));
|
|
|
|
} else {
|
|
|
|
aBuf += nsPrintfCString("\\u%04x", ch);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return aBuf.get();
|
|
|
|
}
|
|
|
|
#endif
|
2007-10-23 03:27:48 +00:00
|
|
|
|
2008-03-14 01:08:04 +00:00
|
|
|
// Returns PR_TRUE if Gecko claims to have handled the event, PR_FALSE otherwise.
|
2010-03-26 00:14:56 +00:00
|
|
|
// We only send Carbon plugin events with NS_KEY_DOWN gecko events, and only send
|
|
|
|
// Cocoa plugin events with NS_KEY_PRESS gecko events. This is because we want to
|
|
|
|
// send repeat key down events to Cocoa plugins but not Carbon plugins.
|
2008-03-14 01:08:04 +00:00
|
|
|
- (PRBool)processKeyDownEvent:(NSEvent*)theEvent keyEquiv:(BOOL)isKeyEquiv
|
2002-02-22 08:44:16 +00:00
|
|
|
{
|
2008-03-14 01:08:04 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
2007-06-15 22:34:48 +00:00
|
|
|
if (!mGeckoChild)
|
2008-03-14 01:08:04 +00:00
|
|
|
return NO;
|
2007-06-15 22:34:48 +00:00
|
|
|
|
2008-05-05 23:01:07 +00:00
|
|
|
#ifdef PR_LOGGING
|
|
|
|
nsCAutoString str1;
|
|
|
|
nsCAutoString str2;
|
|
|
|
#endif
|
|
|
|
PR_LOG(sCocoaLog, PR_LOG_ALWAYS,
|
|
|
|
("ChildView processKeyDownEvent: keycode=%d,modifiers=%x,chars=%s,charsIgnoringModifiers=%s\n",
|
2010-02-23 23:30:39 +00:00
|
|
|
[theEvent keyCode],
|
|
|
|
[theEvent modifierFlags],
|
2008-05-05 23:01:07 +00:00
|
|
|
ToEscapedString([theEvent characters], str1),
|
|
|
|
ToEscapedString([theEvent charactersIgnoringModifiers], str2)));
|
|
|
|
|
2008-04-08 04:38:52 +00:00
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
2005-10-13 17:00:18 +00:00
|
|
|
mCurKeyEvent = theEvent;
|
2007-02-27 17:23:58 +00:00
|
|
|
|
|
|
|
BOOL nonDeadKeyPress = [[theEvent characters] length] > 0;
|
2009-10-01 02:52:50 +00:00
|
|
|
if (nonDeadKeyPress && !mGeckoChild->IME_IsComposing()) {
|
2007-11-26 18:09:38 +00:00
|
|
|
if (![theEvent isARepeat]) {
|
|
|
|
NSResponder* firstResponder = [[self window] firstResponder];
|
2007-02-27 17:23:58 +00:00
|
|
|
|
2007-11-26 18:09:38 +00:00
|
|
|
nsKeyEvent geckoEvent(PR_TRUE, NS_KEY_DOWN, nsnull);
|
|
|
|
[self convertCocoaKeyEvent:theEvent toGeckoEvent:&geckoEvent];
|
2002-06-11 22:13:03 +00:00
|
|
|
|
2009-09-01 01:00:13 +00:00
|
|
|
#ifndef NP_NO_CARBON
|
2009-08-27 00:29:47 +00:00
|
|
|
EventRecord carbonEvent;
|
2009-09-01 01:00:13 +00:00
|
|
|
if (mPluginEventModel == NPEventModelCarbon) {
|
2009-08-27 00:29:47 +00:00
|
|
|
ConvertCocoaKeyEventToCarbonEvent(theEvent, carbonEvent);
|
2009-11-10 21:55:38 +00:00
|
|
|
geckoEvent.pluginEvent = &carbonEvent;
|
2009-08-27 00:29:47 +00:00
|
|
|
}
|
2009-09-01 01:00:13 +00:00
|
|
|
#endif
|
2008-02-29 05:47:41 +00:00
|
|
|
|
2007-11-26 18:09:38 +00:00
|
|
|
mKeyDownHandled = mGeckoChild->DispatchWindowEvent(geckoEvent);
|
|
|
|
if (!mGeckoChild)
|
2008-03-14 01:08:04 +00:00
|
|
|
return mKeyDownHandled;
|
2007-01-24 22:49:55 +00:00
|
|
|
|
2007-11-26 18:09:38 +00:00
|
|
|
// The key down event may have shifted the focus, in which
|
|
|
|
// case we should not fire the key press.
|
|
|
|
if (firstResponder != [[self window] firstResponder]) {
|
2008-03-14 01:08:04 +00:00
|
|
|
PRBool handled = mKeyDownHandled;
|
2007-11-26 18:09:38 +00:00
|
|
|
mCurKeyEvent = nil;
|
|
|
|
mKeyDownHandled = PR_FALSE;
|
2008-03-14 01:08:04 +00:00
|
|
|
return handled;
|
2007-11-26 18:09:38 +00:00
|
|
|
}
|
|
|
|
}
|
2007-01-24 22:49:55 +00:00
|
|
|
|
2008-03-04 08:06:47 +00:00
|
|
|
// If this is the context menu key command, send a context menu key event.
|
2010-02-23 23:30:39 +00:00
|
|
|
unsigned int modifierFlags = [theEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask;
|
2008-03-04 08:06:47 +00:00
|
|
|
if (modifierFlags == NSControlKeyMask && [[theEvent charactersIgnoringModifiers] isEqualToString:@" "]) {
|
|
|
|
nsMouseEvent contextMenuEvent(PR_TRUE, NS_CONTEXTMENU, [self widget], nsMouseEvent::eReal, nsMouseEvent::eContextMenuKey);
|
|
|
|
contextMenuEvent.isShift = contextMenuEvent.isControl = contextMenuEvent.isAlt = contextMenuEvent.isMeta = PR_FALSE;
|
2008-03-14 01:08:04 +00:00
|
|
|
PRBool cmEventHandled = mGeckoChild->DispatchWindowEvent(contextMenuEvent);
|
2008-03-04 08:06:47 +00:00
|
|
|
[self maybeInitContextMenuTracking];
|
|
|
|
// Bail, there is nothing else to do here.
|
2008-03-14 01:08:04 +00:00
|
|
|
PRBool handled = (cmEventHandled || mKeyDownHandled);
|
2008-03-04 08:06:47 +00:00
|
|
|
mCurKeyEvent = nil;
|
|
|
|
mKeyDownHandled = PR_FALSE;
|
2008-03-14 01:08:04 +00:00
|
|
|
return handled;
|
2008-03-04 08:06:47 +00:00
|
|
|
}
|
|
|
|
|
2007-02-27 17:23:58 +00:00
|
|
|
nsKeyEvent geckoEvent(PR_TRUE, NS_KEY_PRESS, nsnull);
|
2007-06-12 20:28:26 +00:00
|
|
|
[self convertCocoaKeyEvent:theEvent toGeckoEvent:&geckoEvent];
|
2007-01-24 22:49:55 +00:00
|
|
|
|
2005-10-13 17:00:18 +00:00
|
|
|
// if this is a non-letter keypress, or the control key is down,
|
|
|
|
// dispatch the keydown to gecko, so that we trap delete,
|
|
|
|
// control-letter combinations etc before Cocoa tries to use
|
|
|
|
// them for keybindings.
|
2007-04-15 13:43:55 +00:00
|
|
|
if ((!geckoEvent.isChar || geckoEvent.isControl) &&
|
2009-10-01 02:52:50 +00:00
|
|
|
!mGeckoChild->IME_IsComposing()) {
|
2008-02-29 05:47:41 +00:00
|
|
|
if (mKeyDownHandled)
|
|
|
|
geckoEvent.flags |= NS_EVENT_FLAG_NO_DEFAULT;
|
2008-03-14 01:08:04 +00:00
|
|
|
mKeyPressHandled = mGeckoChild->DispatchWindowEvent(geckoEvent);
|
2008-02-29 05:47:41 +00:00
|
|
|
mKeyPressSent = YES;
|
2008-03-14 01:08:04 +00:00
|
|
|
if (!mGeckoChild)
|
|
|
|
return (mKeyDownHandled || mKeyPressHandled);
|
2002-02-22 08:44:16 +00:00
|
|
|
}
|
|
|
|
}
|
2002-12-13 08:43:18 +00:00
|
|
|
|
2008-02-29 05:47:41 +00:00
|
|
|
// Let Cocoa interpret the key events, caching IsComposing first.
|
|
|
|
// We don't do it if this came from performKeyEquivalent because
|
|
|
|
// interpretKeyEvents isn't set up to handle those key combinations.
|
2009-10-01 02:52:50 +00:00
|
|
|
PRBool wasComposing = mGeckoChild->IME_IsComposing();
|
2008-03-30 09:17:50 +00:00
|
|
|
PRBool interpretKeyEventsCalled = PR_FALSE;
|
2008-04-03 11:41:35 +00:00
|
|
|
if (!isKeyEquiv &&
|
2009-10-01 02:52:50 +00:00
|
|
|
(mGeckoChild->IME_IsEnabled() || mGeckoChild->IME_IsASCIICapableOnly())) {
|
2008-02-29 05:47:41 +00:00
|
|
|
[super interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
|
2008-03-30 09:17:50 +00:00
|
|
|
interpretKeyEventsCalled = PR_TRUE;
|
|
|
|
}
|
2008-02-29 05:47:41 +00:00
|
|
|
|
|
|
|
if (!mGeckoChild)
|
2008-03-14 01:08:04 +00:00
|
|
|
return (mKeyDownHandled || mKeyPressHandled);;
|
2008-02-29 05:47:41 +00:00
|
|
|
|
2009-10-01 02:52:50 +00:00
|
|
|
if (!mKeyPressSent && nonDeadKeyPress && !wasComposing &&
|
|
|
|
!mGeckoChild->IME_IsComposing()) {
|
2008-02-29 05:47:41 +00:00
|
|
|
nsKeyEvent geckoEvent(PR_TRUE, NS_KEY_PRESS, nsnull);
|
|
|
|
[self convertCocoaKeyEvent:theEvent toGeckoEvent:&geckoEvent];
|
|
|
|
|
2008-03-30 09:17:50 +00:00
|
|
|
// If we called interpretKeyEvents and this isn't normal character input
|
|
|
|
// then IME probably ate the event for some reason. We do not want to
|
|
|
|
// send a key press event in that case.
|
|
|
|
if (!(interpretKeyEventsCalled && IsNormalCharInputtingEvent(geckoEvent))) {
|
|
|
|
if (mKeyDownHandled)
|
|
|
|
geckoEvent.flags |= NS_EVENT_FLAG_NO_DEFAULT;
|
|
|
|
mKeyPressHandled = mGeckoChild->DispatchWindowEvent(geckoEvent);
|
|
|
|
}
|
2007-11-12 17:16:15 +00:00
|
|
|
}
|
2002-12-13 08:43:18 +00:00
|
|
|
|
2008-01-15 23:11:55 +00:00
|
|
|
// Note: mGeckoChild might have become null here. Don't count on it from here on.
|
|
|
|
|
2008-03-14 01:08:04 +00:00
|
|
|
PRBool handled = (mKeyDownHandled || mKeyPressHandled);
|
|
|
|
|
2008-02-29 05:47:41 +00:00
|
|
|
// See note about nested event loops where these variables are declared in header.
|
2008-03-14 01:08:04 +00:00
|
|
|
mKeyPressHandled = NO;
|
2008-02-29 05:47:41 +00:00
|
|
|
mKeyPressSent = NO;
|
2005-10-13 17:00:18 +00:00
|
|
|
mCurKeyEvent = nil;
|
2007-11-26 18:09:38 +00:00
|
|
|
mKeyDownHandled = PR_FALSE;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
2008-03-14 01:08:04 +00:00
|
|
|
return handled;
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO);
|
2002-02-22 08:44:16 +00:00
|
|
|
}
|
2001-11-14 22:29:25 +00:00
|
|
|
|
2010-06-10 00:56:17 +00:00
|
|
|
#ifdef NP_NO_CARBON
|
|
|
|
- (NSTextInputContext *)inputContext
|
|
|
|
{
|
|
|
|
if (mIsPluginView && mPluginEventModel == NPEventModelCocoa)
|
|
|
|
return [[ComplexTextInputPanel sharedComplexTextInputPanel] inputContext];
|
|
|
|
else
|
|
|
|
return [super inputContext];
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-10-01 04:15:05 +00:00
|
|
|
#ifndef NP_NO_CARBON
|
2008-06-30 16:30:22 +00:00
|
|
|
// Create a TSM document for use with plugins, so that we can support IME in
|
|
|
|
// them. Once it's created, if need be (re)activate it. Some plugins (e.g.
|
|
|
|
// the Flash plugin running in Camino) don't create their own TSM document --
|
|
|
|
// without which IME can't work. Others (e.g. the Flash plugin running in
|
|
|
|
// Firefox) create a TSM document that (somehow) makes the input window behave
|
|
|
|
// badly when it contains more than one kind of input (say Hiragana and
|
|
|
|
// Romaji). (We can't just use the per-NSView TSM documents that Cocoa
|
2010-03-20 15:05:47 +00:00
|
|
|
// provides (those created and managed by the NSTSMInputContext class) -- for
|
2008-06-30 16:30:22 +00:00
|
|
|
// some reason TSMProcessRawKeyEvent() doesn't work with them.)
|
|
|
|
- (void)activatePluginTSMDoc
|
|
|
|
{
|
|
|
|
if (!mPluginTSMDoc) {
|
|
|
|
// Create a TSM document that supports both non-Unicode and Unicode input.
|
|
|
|
// Though [ChildView processPluginKeyEvent:] only sends Mac char codes to
|
|
|
|
// the plugin, this makes the input window behave better when it contains
|
|
|
|
// more than one kind of input (say Hiragana and Romaji). This is what
|
|
|
|
// the OS does when it creates a TSM document for use by an
|
|
|
|
// NSTSMInputContext class.
|
|
|
|
InterfaceTypeList supportedServices;
|
|
|
|
supportedServices[0] = kTextServiceDocumentInterfaceType;
|
|
|
|
supportedServices[1] = kUnicodeDocumentInterfaceType;
|
|
|
|
::NewTSMDocument(2, supportedServices, &mPluginTSMDoc, 0);
|
|
|
|
// We'll need to use the "input window".
|
|
|
|
::UseInputWindow(mPluginTSMDoc, YES);
|
|
|
|
::ActivateTSMDocument(mPluginTSMDoc);
|
|
|
|
} else if (::TSMGetActiveDocument() != mPluginTSMDoc) {
|
|
|
|
::ActivateTSMDocument(mPluginTSMDoc);
|
|
|
|
}
|
|
|
|
}
|
2009-10-01 04:15:05 +00:00
|
|
|
#endif // NP_NO_CARBON
|
2008-06-30 16:30:22 +00:00
|
|
|
|
2008-02-29 05:47:41 +00:00
|
|
|
- (void)keyDown:(NSEvent*)theEvent
|
|
|
|
{
|
2008-06-30 16:30:22 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2010-06-10 00:56:17 +00:00
|
|
|
if (mGeckoChild && mIsPluginView) {
|
|
|
|
// If a plugin has the focus, we need to use an alternate method for
|
|
|
|
// handling NSKeyDown and NSKeyUp events (otherwise Carbon-based IME won't
|
|
|
|
// work in plugins like the Flash plugin). The same strategy is used by the
|
|
|
|
// WebKit. See PluginKeyEventsHandler() and [ChildView processPluginKeyEvent:]
|
|
|
|
// for more info.
|
|
|
|
if (mPluginEventModel == NPEventModelCocoa) {
|
|
|
|
// Reset complex text input request.
|
|
|
|
mPluginComplexTextInputRequested = NO;
|
|
|
|
|
|
|
|
// Send key down event.
|
|
|
|
nsGUIEvent pluginEvent(PR_TRUE, NS_NON_RETARGETED_PLUGIN_EVENT, mGeckoChild);
|
|
|
|
NPCocoaEvent cocoaEvent;
|
|
|
|
ConvertCocoaKeyEventToNPCocoaEvent(theEvent, cocoaEvent);
|
|
|
|
pluginEvent.pluginEvent = &cocoaEvent;
|
|
|
|
mGeckoChild->DispatchWindowEvent(pluginEvent);
|
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!mPluginComplexTextInputRequested) {
|
|
|
|
// Ideally we'd cancel any TSM composition here.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef NP_NO_CARBON
|
|
|
|
ComplexTextInputPanel* ctInputPanel = [ComplexTextInputPanel sharedComplexTextInputPanel];
|
|
|
|
NSString* textString = nil;
|
|
|
|
[ctInputPanel interpretKeyEvent:theEvent string:&textString];
|
|
|
|
if (textString) {
|
|
|
|
NPCocoaEvent cocoaTextEvent;
|
|
|
|
InitNPCocoaEvent(&cocoaTextEvent);
|
|
|
|
cocoaTextEvent.type = NPCocoaEventTextInput;
|
|
|
|
cocoaTextEvent.data.text.text = (NPNSString*)textString;
|
|
|
|
|
|
|
|
nsGUIEvent pluginTextEvent(PR_TRUE, NS_NON_RETARGETED_PLUGIN_EVENT, mGeckoChild);
|
|
|
|
pluginTextEvent.time = PR_IntervalNow();
|
|
|
|
pluginTextEvent.pluginEvent = (void*)&cocoaTextEvent;
|
|
|
|
mGeckoChild->DispatchWindowEvent(pluginTextEvent);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2009-09-01 01:00:13 +00:00
|
|
|
#ifndef NP_NO_CARBON
|
2010-06-10 00:56:17 +00:00
|
|
|
// This will take care of all Carbon plugin events and also send Cocoa plugin
|
|
|
|
// text events when NSInputContext is not available (ifndef NP_NO_CARBON).
|
2008-06-30 16:30:22 +00:00
|
|
|
[self activatePluginTSMDoc];
|
|
|
|
// We use the active TSM document to pass a pointer to ourselves (the
|
|
|
|
// currently focused ChildView) to PluginKeyEventsHandler(). Because this
|
|
|
|
// pointer is weak, we should retain and release ourselves around the call
|
|
|
|
// to TSMProcessRawKeyEvent().
|
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
|
|
|
::TSMSetDocumentProperty(mPluginTSMDoc, kFocusedChildViewTSMDocPropertyTag,
|
|
|
|
sizeof(ChildView *), &self);
|
|
|
|
::TSMProcessRawKeyEvent([theEvent _eventRef]);
|
|
|
|
::TSMRemoveDocumentProperty(mPluginTSMDoc, kFocusedChildViewTSMDocPropertyTag);
|
|
|
|
return;
|
2009-09-01 01:00:13 +00:00
|
|
|
#endif
|
2010-06-10 00:56:17 +00:00
|
|
|
}
|
2008-06-30 16:30:22 +00:00
|
|
|
|
2008-02-29 05:47:41 +00:00
|
|
|
[self processKeyDownEvent:theEvent keyEquiv:NO];
|
2008-06-30 16:30:22 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2008-02-29 05:47:41 +00:00
|
|
|
}
|
|
|
|
|
2005-05-27 03:49:14 +00:00
|
|
|
- (void)keyUp:(NSEvent*)theEvent
|
2002-02-22 08:44:16 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2008-05-05 23:01:07 +00:00
|
|
|
#ifdef PR_LOGGING
|
|
|
|
nsCAutoString str1;
|
|
|
|
nsCAutoString str2;
|
|
|
|
#endif
|
|
|
|
PR_LOG(sCocoaLog, PR_LOG_ALWAYS,
|
|
|
|
("ChildView keyUp: keycode=%d,modifiers=%x,chars=%s,charsIgnoringModifiers=%s\n",
|
2010-02-23 23:30:39 +00:00
|
|
|
[theEvent keyCode],
|
|
|
|
[theEvent modifierFlags],
|
2008-05-05 23:01:07 +00:00
|
|
|
ToEscapedString([theEvent characters], str1),
|
|
|
|
ToEscapedString([theEvent charactersIgnoringModifiers], str2)));
|
|
|
|
|
2008-06-30 16:30:22 +00:00
|
|
|
if (!mGeckoChild)
|
2002-12-13 08:43:18 +00:00
|
|
|
return;
|
|
|
|
|
2008-04-08 04:38:52 +00:00
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
2008-01-15 23:11:55 +00:00
|
|
|
|
2008-06-30 16:30:22 +00:00
|
|
|
if (mIsPluginView) {
|
2009-09-01 01:00:13 +00:00
|
|
|
if (mPluginEventModel == NPEventModelCocoa) {
|
2009-08-27 00:29:47 +00:00
|
|
|
nsKeyEvent keyUpEvent(PR_TRUE, NS_KEY_UP, nsnull);
|
|
|
|
[self convertCocoaKeyEvent:theEvent toGeckoEvent:&keyUpEvent];
|
|
|
|
NPCocoaEvent pluginEvent;
|
|
|
|
ConvertCocoaKeyEventToNPCocoaEvent(theEvent, pluginEvent);
|
2009-11-10 21:55:38 +00:00
|
|
|
keyUpEvent.pluginEvent = &pluginEvent;
|
2009-08-27 00:29:47 +00:00
|
|
|
mGeckoChild->DispatchWindowEvent(keyUpEvent);
|
|
|
|
}
|
2009-09-01 01:00:13 +00:00
|
|
|
#ifndef NP_NO_CARBON
|
|
|
|
if (mPluginEventModel == NPEventModelCarbon) {
|
|
|
|
// I'm not sure the call to TSMProcessRawKeyEvent() is needed here (though
|
|
|
|
// WebKit makes one).
|
|
|
|
::TSMProcessRawKeyEvent([theEvent _eventRef]);
|
|
|
|
|
|
|
|
// Don't send a keyUp event if the corresponding keyDown event(s) is/are
|
|
|
|
// still being processed (idea borrowed from WebKit).
|
|
|
|
ChildView *keyDownTarget = nil;
|
|
|
|
OSStatus status = ::TSMGetDocumentProperty(mPluginTSMDoc, kFocusedChildViewTSMDocPropertyTag,
|
|
|
|
sizeof(ChildView *), nil, &keyDownTarget);
|
|
|
|
if (status != noErr)
|
|
|
|
keyDownTarget = nil;
|
|
|
|
if (keyDownTarget == self)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// PluginKeyEventsHandler() never sends keyUp events to [ChildView
|
|
|
|
// processPluginKeyEvent:], so we need to send them to Gecko here. (This
|
|
|
|
// means that when commiting text from IME, several keyDown events may be
|
|
|
|
// sent to Gecko (in processPluginKeyEvent) for one keyUp event here.
|
|
|
|
// But this is how the WebKit does it, and games expect a keyUp event to
|
|
|
|
// be sent when it actually happens (they need to be able to detect how
|
|
|
|
// long a key has been held down) -- which wouldn't be possible if we sent
|
|
|
|
// them from processPluginKeyEvent.)
|
|
|
|
nsKeyEvent keyUpEvent(PR_TRUE, NS_KEY_UP, nsnull);
|
|
|
|
[self convertCocoaKeyEvent:theEvent toGeckoEvent:&keyUpEvent];
|
|
|
|
EventRecord macKeyUpEvent;
|
|
|
|
ConvertCocoaKeyEventToCarbonEvent(theEvent, macKeyUpEvent);
|
2009-11-10 21:55:38 +00:00
|
|
|
keyUpEvent.pluginEvent = &macKeyUpEvent;
|
2009-09-01 01:00:13 +00:00
|
|
|
mGeckoChild->DispatchWindowEvent(keyUpEvent);
|
|
|
|
}
|
|
|
|
#endif
|
2008-06-30 16:30:22 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if we don't have any characters we can't generate a keyUp event
|
2009-10-01 02:52:50 +00:00
|
|
|
if ([[theEvent characters] length] == 0 || mGeckoChild->IME_IsComposing())
|
2008-06-30 16:30:22 +00:00
|
|
|
return;
|
|
|
|
|
2007-02-27 17:23:58 +00:00
|
|
|
nsKeyEvent geckoEvent(PR_TRUE, NS_KEY_UP, nsnull);
|
2007-06-12 20:28:26 +00:00
|
|
|
[self convertCocoaKeyEvent:theEvent toGeckoEvent:&geckoEvent];
|
2002-06-11 22:13:03 +00:00
|
|
|
|
2002-02-22 08:44:16 +00:00
|
|
|
mGeckoChild->DispatchWindowEvent(geckoEvent);
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2002-02-22 08:44:16 +00:00
|
|
|
}
|
2001-11-14 22:29:25 +00:00
|
|
|
|
2006-12-06 17:04:13 +00:00
|
|
|
- (BOOL)performKeyEquivalent:(NSEvent*)theEvent
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
|
|
|
|
2008-02-29 05:47:41 +00:00
|
|
|
// don't do anything if we don't have a gecko widget
|
2008-01-31 05:26:55 +00:00
|
|
|
if (!mGeckoChild)
|
2008-02-29 05:47:41 +00:00
|
|
|
return NO;
|
|
|
|
|
2008-04-08 04:38:52 +00:00
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
2008-03-01 19:04:33 +00:00
|
|
|
|
2008-06-27 20:48:03 +00:00
|
|
|
// If we're not the first responder and the first responder is an NSView
|
|
|
|
// object, pass the event on. Otherwise (if, for example, the first
|
|
|
|
// responder is an NSWindow object) we should trust the OS to have called
|
|
|
|
// us correctly.
|
2008-04-08 04:38:52 +00:00
|
|
|
id firstResponder = [[self window] firstResponder];
|
|
|
|
if (firstResponder != self) {
|
2008-06-27 20:48:03 +00:00
|
|
|
// Special handling if the other first responder is a ChildView.
|
2008-04-08 04:38:52 +00:00
|
|
|
if ([firstResponder isKindOfClass:[ChildView class]])
|
|
|
|
return [(ChildView *)firstResponder performKeyEquivalent:theEvent];
|
2008-06-27 20:48:03 +00:00
|
|
|
if ([firstResponder isKindOfClass:[NSView class]])
|
2008-04-08 04:38:52 +00:00
|
|
|
return [super performKeyEquivalent:theEvent];
|
|
|
|
}
|
2006-12-06 17:04:13 +00:00
|
|
|
|
2008-02-29 05:47:41 +00:00
|
|
|
// don't process if we're composing, but don't consume the event
|
2009-10-01 02:52:50 +00:00
|
|
|
if (mGeckoChild->IME_IsComposing())
|
2008-01-31 05:26:55 +00:00
|
|
|
return NO;
|
|
|
|
|
2010-02-23 23:30:39 +00:00
|
|
|
UInt32 modifierFlags = [theEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask;
|
2009-09-21 21:48:55 +00:00
|
|
|
|
2008-08-18 07:10:18 +00:00
|
|
|
// Set to true if embedding menus handled the event when a plugin has focus.
|
|
|
|
// We give menus a crack at handling commands before Gecko in the plugin case.
|
|
|
|
BOOL handledByEmbedding = NO;
|
|
|
|
|
2008-04-08 04:38:52 +00:00
|
|
|
// Perform native menu UI feedback even if we stop the event from propagating to it normally.
|
|
|
|
// Recall that the menu system won't actually execute any commands for keyboard command invocations.
|
2008-04-28 17:43:34 +00:00
|
|
|
//
|
|
|
|
// If this is a plugin, we do actually perform the action on keyboard commands. See bug 428047.
|
|
|
|
// If the action on plugins here changes the first responder, don't continue.
|
2008-04-08 04:38:52 +00:00
|
|
|
NSMenu* mainMenu = [NSApp mainMenu];
|
2008-04-28 17:43:34 +00:00
|
|
|
if (mIsPluginView) {
|
2008-08-18 07:10:18 +00:00
|
|
|
if ([mainMenu isKindOfClass:[GeckoNSMenu class]]) {
|
2009-09-21 21:48:55 +00:00
|
|
|
// Maintain a list of cmd+key combinations that we never act on (in the
|
|
|
|
// browser) when the keyboard focus is in a plugin. What a particular
|
|
|
|
// cmd+key combo means here (to the browser) is governed by browser.dtd,
|
|
|
|
// which "contains the browser main menu items".
|
|
|
|
PRBool dontActOnKeyEquivalent = PR_FALSE;
|
|
|
|
if (modifierFlags == NSCommandKeyMask) {
|
|
|
|
NSString *unmodchars = [theEvent charactersIgnoringModifiers];
|
|
|
|
if ([unmodchars length] == 1) {
|
|
|
|
if ([unmodchars characterAtIndex:0] ==
|
|
|
|
nsMenuBarX::GetLocalizedAccelKey("key_selectAll"))
|
|
|
|
dontActOnKeyEquivalent = PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (dontActOnKeyEquivalent) {
|
|
|
|
[(GeckoNSMenu*)mainMenu performMenuUserInterfaceEffectsForEvent:theEvent];
|
|
|
|
} else {
|
|
|
|
[(GeckoNSMenu*)mainMenu actOnKeyEquivalent:theEvent];
|
|
|
|
}
|
2008-08-18 07:10:18 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
// This is probably an embedding situation. If the native menu handle the event
|
|
|
|
// then return YES from pKE no matter what Gecko or the plugin does.
|
|
|
|
handledByEmbedding = [mainMenu performKeyEquivalent:theEvent];
|
|
|
|
}
|
2008-04-28 17:43:34 +00:00
|
|
|
if ([[self window] firstResponder] != self)
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if ([mainMenu isKindOfClass:[GeckoNSMenu class]])
|
|
|
|
[(GeckoNSMenu*)mainMenu performMenuUserInterfaceEffectsForEvent:theEvent];
|
|
|
|
}
|
2006-12-06 17:04:13 +00:00
|
|
|
|
2008-05-02 04:30:38 +00:00
|
|
|
// With Cmd key or Ctrl+Tab or Ctrl+Esc, keyDown will be never called.
|
|
|
|
// Therefore, we need to call processKeyDownEvent from performKeyEquivalent.
|
2010-02-23 23:30:39 +00:00
|
|
|
UInt32 keyCode = [theEvent keyCode];
|
2008-05-02 04:30:38 +00:00
|
|
|
PRBool keyDownNeverFiredEvent = (modifierFlags & NSCommandKeyMask) ||
|
|
|
|
((modifierFlags & NSControlKeyMask) &&
|
|
|
|
(keyCode == kEscapeKeyCode || keyCode == kTabKeyCode));
|
|
|
|
|
2006-12-11 21:40:32 +00:00
|
|
|
// don't handle this if certain modifiers are down - those should
|
|
|
|
// be sent as normal key up/down events and cocoa will do so automatically
|
|
|
|
// if we reject here
|
2008-05-02 04:30:38 +00:00
|
|
|
if (!keyDownNeverFiredEvent &&
|
|
|
|
(modifierFlags & (NSFunctionKeyMask| NSNumericPadKeyMask)))
|
2008-08-18 07:10:18 +00:00
|
|
|
return handledByEmbedding;
|
2006-12-11 21:40:32 +00:00
|
|
|
|
2008-04-23 03:41:50 +00:00
|
|
|
// Control and option modifiers are used when changing input sources in the
|
|
|
|
// input menu. We need to send such key events via "keyDown:", which will
|
|
|
|
// happen if we return NO here. This only applies to Mac OS X 10.5 and higher,
|
|
|
|
// previous OS versions just call "keyDown:" and not "performKeyEquivalent:"
|
|
|
|
// for such events.
|
2008-05-02 04:30:38 +00:00
|
|
|
if (!keyDownNeverFiredEvent &&
|
|
|
|
(modifierFlags & (NSControlKeyMask | NSAlternateKeyMask)))
|
2008-08-18 07:10:18 +00:00
|
|
|
return handledByEmbedding;
|
2008-04-23 03:41:50 +00:00
|
|
|
|
2010-06-10 00:56:17 +00:00
|
|
|
// At this point we're about to hand the event off to "processKeyDownEvent:keyEquiv:".
|
|
|
|
// Don't bother if this is a Cocoa plugin event, just handle it directly.
|
|
|
|
if (mGeckoChild && mIsPluginView && mPluginEventModel == NPEventModelCocoa) {
|
|
|
|
// Reset complex text input request.
|
|
|
|
mPluginComplexTextInputRequested = NO;
|
|
|
|
|
|
|
|
// Send key down event.
|
|
|
|
nsGUIEvent pluginEvent(PR_TRUE, NS_NON_RETARGETED_PLUGIN_EVENT, mGeckoChild);
|
|
|
|
NPCocoaEvent cocoaEvent;
|
|
|
|
ConvertCocoaKeyEventToNPCocoaEvent(theEvent, cocoaEvent);
|
|
|
|
pluginEvent.pluginEvent = &cocoaEvent;
|
|
|
|
mGeckoChild->DispatchWindowEvent(pluginEvent);
|
|
|
|
if (!mGeckoChild)
|
|
|
|
return YES;
|
|
|
|
|
|
|
|
if (!mPluginComplexTextInputRequested) {
|
|
|
|
// Ideally we'd cancel any TSM composition here.
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We send these events to Carbon TSM but not to the ComplexTextInputPanel.
|
|
|
|
// We assume that events coming in through pKE: are only relevant to TSM.
|
|
|
|
#ifndef NP_NO_CARBON
|
|
|
|
[self activatePluginTSMDoc];
|
|
|
|
// We use the active TSM document to pass a pointer to ourselves (the
|
|
|
|
// currently focused ChildView) to PluginKeyEventsHandler(). Because this
|
|
|
|
// pointer is weak, we should retain and release ourselves around the call
|
|
|
|
// to TSMProcessRawKeyEvent().
|
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
|
|
|
::TSMSetDocumentProperty(mPluginTSMDoc, kFocusedChildViewTSMDocPropertyTag,
|
|
|
|
sizeof(ChildView *), &self);
|
|
|
|
::TSMProcessRawKeyEvent([theEvent _eventRef]);
|
|
|
|
::TSMRemoveDocumentProperty(mPluginTSMDoc, kFocusedChildViewTSMDocPropertyTag);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
2008-03-14 01:08:04 +00:00
|
|
|
if ([theEvent type] == NSKeyDown) {
|
|
|
|
// We trust the Gecko handled status for cmd key events. See bug 417466 for more info.
|
|
|
|
if (modifierFlags & NSCommandKeyMask)
|
2008-08-18 07:10:18 +00:00
|
|
|
return ([self processKeyDownEvent:theEvent keyEquiv:YES] || handledByEmbedding);
|
2008-03-14 01:08:04 +00:00
|
|
|
else
|
|
|
|
[self processKeyDownEvent:theEvent keyEquiv:YES];
|
|
|
|
}
|
2008-01-29 06:11:06 +00:00
|
|
|
|
|
|
|
return YES;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO);
|
2006-12-06 17:04:13 +00:00
|
|
|
}
|
|
|
|
|
2003-03-13 20:37:32 +00:00
|
|
|
- (void)flagsChanged:(NSEvent*)theEvent
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-06-15 22:34:48 +00:00
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
|
|
|
|
2008-04-08 04:38:52 +00:00
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
2008-01-15 23:11:55 +00:00
|
|
|
|
2008-10-13 18:07:27 +00:00
|
|
|
// CapsLock state and other modifier states are different:
|
|
|
|
// CapsLock state does not revert when the CapsLock key goes up, as the
|
2008-12-16 16:50:19 +00:00
|
|
|
// modifier state does for other modifier keys on key up.
|
2008-10-13 18:07:27 +00:00
|
|
|
if ([theEvent keyCode] == kCapsLockKeyCode) {
|
|
|
|
// Fire key down event for caps lock.
|
|
|
|
[self fireKeyEventForFlagsChanged:theEvent keyDown:YES];
|
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
|
|
|
// XXX should we fire keyup event too? The keyup event for CapsLock key
|
|
|
|
// is never sent to gecko.
|
|
|
|
} else if ([theEvent type] == NSFlagsChanged) {
|
|
|
|
// Fire key up/down events for the modifier keys (shift, alt, ctrl, command).
|
2010-02-23 23:30:39 +00:00
|
|
|
unsigned int modifiers = [theEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask;
|
2007-03-12 16:04:40 +00:00
|
|
|
const PRUint32 kModifierMaskTable[] =
|
|
|
|
{ NSShiftKeyMask, NSControlKeyMask, NSAlternateKeyMask, NSCommandKeyMask };
|
|
|
|
const PRUint32 kModifierCount = sizeof(kModifierMaskTable) /
|
|
|
|
sizeof(kModifierMaskTable[0]);
|
|
|
|
|
2007-06-12 20:28:26 +00:00
|
|
|
for (PRUint32 i = 0; i < kModifierCount; i++) {
|
2007-03-12 16:04:40 +00:00
|
|
|
PRUint32 modifierBit = kModifierMaskTable[i];
|
2008-12-16 16:50:19 +00:00
|
|
|
if ((modifiers & modifierBit) != (gLastModifierState & modifierBit)) {
|
2008-10-13 18:07:27 +00:00
|
|
|
BOOL isKeyDown = (modifiers & modifierBit) != 0 ? YES : NO;
|
2007-03-12 16:04:40 +00:00
|
|
|
|
2008-10-13 18:07:27 +00:00
|
|
|
[self fireKeyEventForFlagsChanged:theEvent keyDown:isKeyDown];
|
2007-03-12 16:04:40 +00:00
|
|
|
|
2008-01-15 23:11:55 +00:00
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
2007-03-12 16:04:40 +00:00
|
|
|
|
|
|
|
// Stop if focus has changed.
|
|
|
|
// Check to see if we are still the first responder.
|
2008-10-13 18:07:27 +00:00
|
|
|
if (![self isFirstResponder])
|
2007-03-12 16:04:40 +00:00
|
|
|
break;
|
|
|
|
}
|
2003-03-13 20:37:32 +00:00
|
|
|
}
|
2007-03-12 16:04:40 +00:00
|
|
|
|
2008-12-16 16:50:19 +00:00
|
|
|
gLastModifierState = modifiers;
|
2003-03-13 20:37:32 +00:00
|
|
|
}
|
2007-03-12 16:04:40 +00:00
|
|
|
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2003-03-13 20:37:32 +00:00
|
|
|
}
|
|
|
|
|
2008-10-13 18:07:27 +00:00
|
|
|
- (BOOL) isFirstResponder
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
|
|
|
|
|
|
|
NSResponder* resp = [[self window] firstResponder];
|
|
|
|
return (resp == (NSResponder*)self);
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO);
|
|
|
|
}
|
|
|
|
|
2010-03-08 12:35:25 +00:00
|
|
|
- (BOOL)isDragInProgress
|
|
|
|
{
|
|
|
|
if (!mDragService)
|
|
|
|
return NO;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDragSession> dragSession;
|
|
|
|
mDragService->GetCurrentSession(getter_AddRefs(dragSession));
|
|
|
|
return dragSession != nsnull;
|
|
|
|
}
|
|
|
|
|
2008-10-13 18:07:27 +00:00
|
|
|
- (void)fireKeyEventForFlagsChanged:(NSEvent*)theEvent keyDown:(BOOL)isKeyDown
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2008-12-06 09:23:55 +00:00
|
|
|
if (!mGeckoChild || [theEvent type] != NSFlagsChanged ||
|
2009-10-01 02:52:50 +00:00
|
|
|
mGeckoChild->IME_IsComposing())
|
2008-10-13 18:07:27 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
|
|
|
|
2008-10-18 03:48:09 +00:00
|
|
|
PRUint32 message = isKeyDown ? NS_KEY_DOWN : NS_KEY_UP;
|
2008-10-13 18:07:27 +00:00
|
|
|
|
|
|
|
// Fire a key event.
|
|
|
|
nsKeyEvent geckoEvent(PR_TRUE, message, nsnull);
|
|
|
|
[self convertCocoaKeyEvent:theEvent toGeckoEvent:&geckoEvent];
|
|
|
|
|
2009-08-27 00:29:47 +00:00
|
|
|
// create event for use by plugins
|
2009-09-01 01:00:13 +00:00
|
|
|
#ifndef NP_NO_CARBON
|
2009-08-27 00:29:47 +00:00
|
|
|
EventRecord carbonEvent;
|
2009-09-01 01:00:13 +00:00
|
|
|
if (mPluginEventModel == NPEventModelCarbon) {
|
2009-08-27 00:29:47 +00:00
|
|
|
ConvertCocoaKeyEventToCarbonEvent(theEvent, carbonEvent, message);
|
2009-11-10 21:55:38 +00:00
|
|
|
geckoEvent.pluginEvent = &carbonEvent;
|
2009-08-27 00:29:47 +00:00
|
|
|
}
|
2009-09-01 01:00:13 +00:00
|
|
|
#endif
|
|
|
|
NPCocoaEvent cocoaEvent;
|
|
|
|
if (mPluginEventModel == NPEventModelCocoa) {
|
2009-08-27 00:29:47 +00:00
|
|
|
ConvertCocoaKeyEventToNPCocoaEvent(theEvent, cocoaEvent, message);
|
2009-11-10 21:55:38 +00:00
|
|
|
geckoEvent.pluginEvent = &cocoaEvent;
|
2009-08-27 00:29:47 +00:00
|
|
|
}
|
2008-10-13 18:07:27 +00:00
|
|
|
|
|
|
|
mGeckoChild->DispatchWindowEvent(geckoEvent);
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
2006-12-20 02:13:57 +00:00
|
|
|
|
2010-04-25 20:58:03 +00:00
|
|
|
- (void)updateCocoaPluginFocusStatus:(BOOL)hasFocus
|
|
|
|
{
|
|
|
|
if (!mGeckoChild)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsGUIEvent pluginEvent(PR_TRUE, NS_NON_RETARGETED_PLUGIN_EVENT, mGeckoChild);
|
|
|
|
NPCocoaEvent cocoaEvent;
|
|
|
|
InitNPCocoaEvent(&cocoaEvent);
|
|
|
|
cocoaEvent.type = NPCocoaEventFocusChanged;
|
|
|
|
cocoaEvent.data.focus.hasFocus = hasFocus;
|
|
|
|
pluginEvent.pluginEvent = &cocoaEvent;
|
|
|
|
mGeckoChild->DispatchWindowEvent(pluginEvent);
|
|
|
|
}
|
|
|
|
|
|
|
|
// We must always call through to our superclass, even when mGeckoChild is
|
|
|
|
// nil -- otherwise the keyboard focus can end up in the wrong NSView.
|
|
|
|
- (BOOL)becomeFirstResponder
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
|
|
|
|
|
|
|
if (mIsPluginView && mPluginEventModel == NPEventModelCocoa) {
|
|
|
|
[self updateCocoaPluginFocusStatus:YES];
|
|
|
|
}
|
|
|
|
|
|
|
|
return [super becomeFirstResponder];
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(YES);
|
|
|
|
}
|
|
|
|
|
2007-06-21 23:58:16 +00:00
|
|
|
// We must always call through to our superclass, even when mGeckoChild is
|
|
|
|
// nil -- otherwise the keyboard focus can end up in the wrong NSView.
|
2002-03-09 22:43:04 +00:00
|
|
|
- (BOOL)resignFirstResponder
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
|
|
|
|
2010-04-25 20:58:03 +00:00
|
|
|
if (mIsPluginView && mPluginEventModel == NPEventModelCocoa) {
|
|
|
|
[self updateCocoaPluginFocusStatus:NO];
|
|
|
|
}
|
|
|
|
|
2002-03-09 22:43:04 +00:00
|
|
|
return [super resignFirstResponder];
|
2008-02-20 23:47:05 +00:00
|
|
|
|
2010-04-25 20:58:03 +00:00
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(YES);
|
2002-03-09 22:43:04 +00:00
|
|
|
}
|
|
|
|
|
2005-06-26 03:25:52 +00:00
|
|
|
- (void)viewsWindowDidBecomeKey
|
2005-09-30 00:59:29 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2005-09-30 00:59:29 +00:00
|
|
|
if (!mGeckoChild)
|
2007-06-15 22:34:48 +00:00
|
|
|
return;
|
|
|
|
|
2008-04-08 04:38:52 +00:00
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
2008-01-15 23:11:55 +00:00
|
|
|
|
2005-10-12 17:38:29 +00:00
|
|
|
// check to see if the window implements the mozWindow protocol. This
|
|
|
|
// allows embedders to avoid re-entrant calls to -makeKeyAndOrderFront,
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 18:00:39 +00:00
|
|
|
// which can happen because these activate calls propagate out
|
2005-10-12 17:38:29 +00:00
|
|
|
// to the embedder via nsIEmbeddingSiteWindow::SetFocus().
|
|
|
|
BOOL isMozWindow = [[self window] respondsToSelector:@selector(setSuppressMakeKeyFront:)];
|
|
|
|
if (isMozWindow)
|
|
|
|
[[self window] setSuppressMakeKeyFront:YES];
|
|
|
|
|
2007-08-02 23:01:32 +00:00
|
|
|
[self sendFocusEvent:NS_ACTIVATE];
|
2005-10-12 17:38:29 +00:00
|
|
|
|
|
|
|
if (isMozWindow)
|
|
|
|
[[self window] setSuppressMakeKeyFront:NO];
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2005-06-26 03:25:52 +00:00
|
|
|
}
|
|
|
|
|
2005-10-12 17:38:29 +00:00
|
|
|
- (void)viewsWindowDidResignKey
|
2005-06-26 03:25:52 +00:00
|
|
|
{
|
2005-09-30 00:59:29 +00:00
|
|
|
if (!mGeckoChild)
|
2007-06-15 22:34:48 +00:00
|
|
|
return;
|
|
|
|
|
2008-04-08 04:38:52 +00:00
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
2008-01-15 23:11:55 +00:00
|
|
|
|
2007-08-02 23:01:32 +00:00
|
|
|
[self sendFocusEvent:NS_DEACTIVATE];
|
2005-09-30 00:59:29 +00:00
|
|
|
}
|
2005-06-26 03:25:52 +00:00
|
|
|
|
2007-06-21 23:58:16 +00:00
|
|
|
// If the call to removeFromSuperview isn't delayed from nsChildView::
|
|
|
|
// TearDownView(), the NSView hierarchy might get changed during calls to
|
|
|
|
// [ChildView drawRect:], which leads to "beyond bounds" exceptions in
|
|
|
|
// NSCFArray. For more info see bmo bug 373122. Apple's docs claim that
|
2007-05-30 18:25:44 +00:00
|
|
|
// removeFromSuperviewWithoutNeedingDisplay "can be safely invoked during
|
|
|
|
// display" (whatever "display" means). But it's _not_ true that it can be
|
2007-06-21 23:58:16 +00:00
|
|
|
// safely invoked during calls to [NSView drawRect:]. We use
|
|
|
|
// removeFromSuperview here because there's no longer any danger of being
|
|
|
|
// "invoked during display", and because doing do clears up bmo bug 384343.
|
2007-05-30 18:25:44 +00:00
|
|
|
- (void)delayedTearDown
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-06-21 23:58:16 +00:00
|
|
|
[self removeFromSuperview];
|
2007-05-30 18:25:44 +00:00
|
|
|
[self release];
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2007-05-30 18:25:44 +00:00
|
|
|
}
|
|
|
|
|
2006-10-25 22:45:22 +00:00
|
|
|
#pragma mark -
|
|
|
|
|
2006-12-20 02:13:57 +00:00
|
|
|
// drag'n'drop stuff
|
2006-10-25 22:45:22 +00:00
|
|
|
#define kDragServiceContractID "@mozilla.org/widget/dragservice;1"
|
|
|
|
|
2010-03-08 12:35:25 +00:00
|
|
|
- (NSDragOperation)dragOperationForSession:(nsIDragSession*)aDragSession
|
|
|
|
{
|
|
|
|
PRUint32 dragAction;
|
|
|
|
aDragSession->GetDragAction(&dragAction);
|
|
|
|
if (nsIDragService::DRAGDROP_ACTION_LINK & dragAction)
|
|
|
|
return NSDragOperationLink;
|
|
|
|
if (nsIDragService::DRAGDROP_ACTION_COPY & dragAction)
|
|
|
|
return NSDragOperationCopy;
|
|
|
|
if (nsIDragService::DRAGDROP_ACTION_MOVE & dragAction)
|
|
|
|
return NSDragOperationGeneric;
|
|
|
|
return NSDragOperationNone;
|
|
|
|
}
|
|
|
|
|
2006-10-25 22:45:22 +00:00
|
|
|
// This is a utility function used by NSView drag event methods
|
|
|
|
// to send events. It contains all of the logic needed for Gecko
|
2010-03-08 12:35:25 +00:00
|
|
|
// dragging to work. Returns the appropriate cocoa drag operation code.
|
|
|
|
- (NSDragOperation)doDragAction:(PRUint32)aMessage sender:(id)aSender
|
2006-10-25 22:45:22 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
|
|
|
|
2007-06-30 03:19:41 +00:00
|
|
|
if (!mGeckoChild)
|
2010-03-08 12:35:25 +00:00
|
|
|
return NSDragOperationNone;
|
2006-10-25 22:45:22 +00:00
|
|
|
|
2007-07-17 02:24:05 +00:00
|
|
|
PR_LOG(sCocoaLog, PR_LOG_ALWAYS, ("ChildView doDragAction: entered\n"));
|
|
|
|
|
2007-06-30 03:19:41 +00:00
|
|
|
if (!mDragService) {
|
|
|
|
CallGetService(kDragServiceContractID, &mDragService);
|
|
|
|
NS_ASSERTION(mDragService, "Couldn't get a drag service - big problem!");
|
|
|
|
if (!mDragService)
|
2010-03-08 12:35:25 +00:00
|
|
|
return NSDragOperationNone;
|
2007-06-30 03:19:41 +00:00
|
|
|
}
|
|
|
|
|
2006-10-25 22:45:22 +00:00
|
|
|
if (aMessage == NS_DRAGDROP_ENTER)
|
|
|
|
mDragService->StartDragSession();
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDragSession> dragSession;
|
|
|
|
mDragService->GetCurrentSession(getter_AddRefs(dragSession));
|
|
|
|
if (dragSession) {
|
2007-04-12 04:37:39 +00:00
|
|
|
if (aMessage == NS_DRAGDROP_OVER) {
|
|
|
|
// fire the drag event at the source. Just ignore whether it was
|
|
|
|
// cancelled or not as there isn't actually a means to stop the drag
|
|
|
|
mDragService->FireDragEventAtSource(NS_DRAGDROP_DRAG);
|
2006-10-25 22:45:22 +00:00
|
|
|
dragSession->SetCanDrop(PR_FALSE);
|
2007-04-12 04:37:39 +00:00
|
|
|
}
|
2006-10-25 22:45:22 +00:00
|
|
|
else if (aMessage == NS_DRAGDROP_DROP) {
|
2008-07-21 13:26:34 +00:00
|
|
|
// We make the assumption that the dragOver handlers have correctly set
|
2006-10-25 22:45:22 +00:00
|
|
|
// the |canDrop| property of the Drag Session.
|
|
|
|
PRBool canDrop = PR_FALSE;
|
2008-08-27 12:07:27 +00:00
|
|
|
if (!NS_SUCCEEDED(dragSession->GetCanDrop(&canDrop)) || !canDrop) {
|
2010-02-01 15:11:08 +00:00
|
|
|
[self doDragAction:NS_DRAGDROP_EXIT sender:aSender];
|
|
|
|
|
2008-08-27 12:07:27 +00:00
|
|
|
nsCOMPtr<nsIDOMNode> sourceNode;
|
|
|
|
dragSession->GetSourceNode(getter_AddRefs(sourceNode));
|
|
|
|
if (!sourceNode) {
|
|
|
|
mDragService->EndDragSession(PR_FALSE);
|
|
|
|
}
|
2010-03-08 12:35:25 +00:00
|
|
|
return NSDragOperationNone;
|
2008-08-27 12:07:27 +00:00
|
|
|
}
|
2006-10-25 22:45:22 +00:00
|
|
|
}
|
|
|
|
|
2010-02-23 23:30:39 +00:00
|
|
|
unsigned int modifierFlags = [[NSApp currentEvent] modifierFlags];
|
2006-10-25 22:45:22 +00:00
|
|
|
PRUint32 action = nsIDragService::DRAGDROP_ACTION_MOVE;
|
|
|
|
// force copy = option, alias = cmd-option, default is move
|
|
|
|
if (modifierFlags & NSAlternateKeyMask) {
|
|
|
|
if (modifierFlags & NSCommandKeyMask)
|
|
|
|
action = nsIDragService::DRAGDROP_ACTION_LINK;
|
|
|
|
else
|
|
|
|
action = nsIDragService::DRAGDROP_ACTION_COPY;
|
|
|
|
}
|
|
|
|
dragSession->SetDragAction(action);
|
|
|
|
}
|
|
|
|
|
2007-10-09 18:46:30 +00:00
|
|
|
// set up gecko event
|
2008-08-27 12:07:27 +00:00
|
|
|
nsDragEvent geckoEvent(PR_TRUE, aMessage, nsnull);
|
2010-03-08 12:29:20 +00:00
|
|
|
[self convertGenericCocoaEvent:[NSApp currentEvent] toGeckoEvent:&geckoEvent];
|
2006-10-25 22:45:22 +00:00
|
|
|
|
2007-10-09 18:46:30 +00:00
|
|
|
// Use our own coordinates in the gecko event.
|
|
|
|
// Convert event from gecko global coords to gecko view coords.
|
|
|
|
NSPoint localPoint = [self convertPoint:[aSender draggingLocation] fromView:nil];
|
|
|
|
geckoEvent.refPoint.x = static_cast<nscoord>(localPoint.x);
|
|
|
|
geckoEvent.refPoint.y = static_cast<nscoord>(localPoint.y);
|
|
|
|
|
2008-04-08 04:38:52 +00:00
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
2007-10-09 18:46:30 +00:00
|
|
|
mGeckoChild->DispatchWindowEvent(geckoEvent);
|
2008-01-15 23:11:55 +00:00
|
|
|
if (!mGeckoChild)
|
2010-03-08 12:35:25 +00:00
|
|
|
return NSDragOperationNone;
|
|
|
|
|
|
|
|
if (dragSession) {
|
|
|
|
switch (aMessage) {
|
|
|
|
case NS_DRAGDROP_ENTER:
|
|
|
|
case NS_DRAGDROP_OVER:
|
|
|
|
return [self dragOperationForSession:dragSession];
|
|
|
|
case NS_DRAGDROP_EXIT:
|
|
|
|
case NS_DRAGDROP_DROP: {
|
|
|
|
nsCOMPtr<nsIDOMNode> sourceNode;
|
|
|
|
dragSession->GetSourceNode(getter_AddRefs(sourceNode));
|
|
|
|
if (!sourceNode) {
|
|
|
|
// We're leaving a window while doing a drag that was
|
|
|
|
// initiated in a different app. End the drag session,
|
|
|
|
// since we're done with it for now (until the user
|
|
|
|
// drags back into mozilla).
|
|
|
|
mDragService->EndDragSession(PR_FALSE);
|
|
|
|
}
|
|
|
|
}
|
2006-10-25 22:45:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-08 12:35:25 +00:00
|
|
|
return NSDragOperationGeneric;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
2010-03-08 12:35:25 +00:00
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSDragOperationNone);
|
2006-10-25 22:45:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
|
|
|
|
2007-07-17 02:24:05 +00:00
|
|
|
PR_LOG(sCocoaLog, PR_LOG_ALWAYS, ("ChildView draggingEntered: entered\n"));
|
|
|
|
|
2006-10-25 22:45:22 +00:00
|
|
|
// there should never be a globalDragPboard when "draggingEntered:" is
|
|
|
|
// called, but just in case we'll take care of it here.
|
|
|
|
[globalDragPboard release];
|
|
|
|
|
|
|
|
// Set the global drag pasteboard that will be used for this drag session.
|
|
|
|
// This will be set back to nil when the drag session ends (mouse exits
|
|
|
|
// the view or a drop happens within the view).
|
|
|
|
globalDragPboard = [[sender draggingPasteboard] retain];
|
|
|
|
|
2010-03-08 12:35:25 +00:00
|
|
|
return [self doDragAction:NS_DRAGDROP_ENTER sender:sender];
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSDragOperationNone);
|
2006-10-25 22:45:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
|
|
|
|
{
|
2007-07-17 02:24:05 +00:00
|
|
|
PR_LOG(sCocoaLog, PR_LOG_ALWAYS, ("ChildView draggingUpdated: entered\n"));
|
|
|
|
|
2010-03-08 12:35:25 +00:00
|
|
|
return [self doDragAction:NS_DRAGDROP_OVER sender:sender];
|
2006-10-25 22:45:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)draggingExited:(id <NSDraggingInfo>)sender
|
|
|
|
{
|
2007-07-17 02:24:05 +00:00
|
|
|
PR_LOG(sCocoaLog, PR_LOG_ALWAYS, ("ChildView draggingExited: entered\n"));
|
|
|
|
|
2008-04-08 04:38:52 +00:00
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
2006-10-25 22:45:22 +00:00
|
|
|
[self doDragAction:NS_DRAGDROP_EXIT sender:sender];
|
2007-10-10 12:19:47 +00:00
|
|
|
NS_IF_RELEASE(mDragService);
|
2006-10-25 22:45:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
|
|
|
|
{
|
2008-04-08 04:38:52 +00:00
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
2010-03-08 12:35:25 +00:00
|
|
|
BOOL handled = [self doDragAction:NS_DRAGDROP_DROP sender:sender] != NSDragOperationNone;
|
2007-10-10 12:19:47 +00:00
|
|
|
NS_IF_RELEASE(mDragService);
|
|
|
|
return handled;
|
2007-06-30 03:19:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// NSDraggingSource
|
|
|
|
- (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-07-17 23:02:40 +00:00
|
|
|
gDraggedTransferables = nsnull;
|
|
|
|
|
2009-02-17 15:51:12 +00:00
|
|
|
NSEvent *currentEvent = [NSApp currentEvent];
|
|
|
|
gUserCancelledDrag = ([currentEvent type] == NSKeyDown &&
|
|
|
|
[currentEvent keyCode] == kEscapeKeyCode);
|
|
|
|
|
2007-06-30 03:19:41 +00:00
|
|
|
if (!mDragService) {
|
|
|
|
CallGetService(kDragServiceContractID, &mDragService);
|
|
|
|
NS_ASSERTION(mDragService, "Couldn't get a drag service - big problem!");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mDragService) {
|
2009-04-13 13:00:29 +00:00
|
|
|
// set the dragend point from the current mouse location
|
|
|
|
nsDragService* dragService = static_cast<nsDragService *>(mDragService);
|
|
|
|
NSPoint pnt = [NSEvent mouseLocation];
|
|
|
|
FlipCocoaScreenCoordinate(pnt);
|
2009-04-16 15:58:23 +00:00
|
|
|
dragService->SetDragEndPoint(nsIntPoint(NSToIntRound(pnt.x), NSToIntRound(pnt.y)));
|
2009-04-13 13:00:29 +00:00
|
|
|
|
2009-05-26 23:23:15 +00:00
|
|
|
// XXX: dropEffect should be updated per |operation|.
|
|
|
|
// As things stand though, |operation| isn't well handled within "our"
|
|
|
|
// events, that is, when the drop happens within the window: it is set
|
|
|
|
// either to NSDragOperationGeneric or to NSDragOperationNone.
|
|
|
|
// For that reason, it's not yet possible to override dropEffect per the
|
|
|
|
// given OS value, and it's also unclear what's the correct dropEffect
|
|
|
|
// value for NSDragOperationGeneric that is passed by other applications.
|
|
|
|
// All that said, NSDragOperationNone is still reliable.
|
|
|
|
if (operation == NSDragOperationNone) {
|
|
|
|
nsCOMPtr<nsIDOMDataTransfer> dataTransfer;
|
|
|
|
dragService->GetDataTransfer(getter_AddRefs(dataTransfer));
|
|
|
|
nsCOMPtr<nsIDOMNSDataTransfer> dataTransferNS =
|
|
|
|
do_QueryInterface(dataTransfer);
|
|
|
|
|
|
|
|
if (dataTransferNS)
|
|
|
|
dataTransferNS->SetDropEffectInt(nsIDragService::DRAGDROP_ACTION_NONE);
|
|
|
|
}
|
|
|
|
|
2007-06-30 03:19:41 +00:00
|
|
|
mDragService->EndDragSession(PR_TRUE);
|
|
|
|
NS_RELEASE(mDragService);
|
|
|
|
}
|
2006-10-25 22:45:22 +00:00
|
|
|
|
|
|
|
[globalDragPboard release];
|
|
|
|
globalDragPboard = nil;
|
2009-11-06 10:21:41 +00:00
|
|
|
[gLastDragMouseDownEvent release];
|
|
|
|
gLastDragMouseDownEvent = nil;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2007-06-30 03:19:41 +00:00
|
|
|
}
|
2006-10-25 22:45:22 +00:00
|
|
|
|
2007-06-30 03:19:41 +00:00
|
|
|
// NSDraggingSource
|
|
|
|
// this is just implemented so we comply with the NSDraggingSource informal protocol
|
2009-09-01 01:00:13 +00:00
|
|
|
- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal
|
2007-06-30 03:19:41 +00:00
|
|
|
{
|
|
|
|
return UINT_MAX;
|
2006-10-25 22:45:22 +00:00
|
|
|
}
|
|
|
|
|
2007-07-17 02:24:05 +00:00
|
|
|
// This method is a callback typically invoked in response to a drag ending on the desktop
|
|
|
|
// or a Findow folder window; the argument passed is a path to the drop location, to be used
|
|
|
|
// in constructing a complete pathname for the file(s) we want to create as a result of
|
|
|
|
// the drag.
|
2009-09-01 01:00:13 +00:00
|
|
|
- (NSArray *)namesOfPromisedFilesDroppedAtDestination:(NSURL*)dropDestination
|
2007-07-17 02:24:05 +00:00
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
|
|
|
|
2007-07-17 02:24:05 +00:00
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
PR_LOG(sCocoaLog, PR_LOG_ALWAYS, ("ChildView namesOfPromisedFilesDroppedAtDestination: entering callback for promised files\n"));
|
|
|
|
|
|
|
|
nsCOMPtr<nsILocalFile> targFile;
|
|
|
|
NS_NewLocalFile(EmptyString(), PR_TRUE, getter_AddRefs(targFile));
|
|
|
|
nsCOMPtr<nsILocalFileMac> macLocalFile = do_QueryInterface(targFile);
|
|
|
|
if (!macLocalFile) {
|
|
|
|
NS_ERROR("No Mac local file");
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!NS_SUCCEEDED(macLocalFile->InitWithCFURL((CFURLRef)dropDestination))) {
|
|
|
|
NS_ERROR("failed InitWithCFURL");
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
2007-07-17 23:02:40 +00:00
|
|
|
if (!gDraggedTransferables)
|
|
|
|
return nil;
|
2007-07-17 02:24:05 +00:00
|
|
|
|
|
|
|
PRUint32 transferableCount;
|
2007-07-17 23:02:40 +00:00
|
|
|
rv = gDraggedTransferables->Count(&transferableCount);
|
2007-07-17 02:24:05 +00:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return nil;
|
|
|
|
|
|
|
|
for (PRUint32 i = 0; i < transferableCount; i++) {
|
|
|
|
nsCOMPtr<nsISupports> genericItem;
|
2007-07-17 23:02:40 +00:00
|
|
|
gDraggedTransferables->GetElementAt(i, getter_AddRefs(genericItem));
|
2007-07-17 02:24:05 +00:00
|
|
|
nsCOMPtr<nsITransferable> item(do_QueryInterface(genericItem));
|
|
|
|
if (!item) {
|
|
|
|
NS_ERROR("no transferable");
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
item->SetTransferData(kFilePromiseDirectoryMime, macLocalFile, sizeof(nsILocalFile*));
|
|
|
|
|
|
|
|
// now request the kFilePromiseMime data, which will invoke the data provider
|
|
|
|
// If successful, the returned data is a reference to the resulting file.
|
|
|
|
nsCOMPtr<nsISupports> fileDataPrimitive;
|
|
|
|
PRUint32 dataSize = 0;
|
|
|
|
item->GetTransferData(kFilePromiseMime, getter_AddRefs(fileDataPrimitive), &dataSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
NSPasteboard* generalPboard = [NSPasteboard pasteboardWithName:NSDragPboard];
|
|
|
|
NSData* data = [generalPboard dataForType:@"application/x-moz-file-promise-dest-filename"];
|
|
|
|
NSString* name = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
|
|
|
NSArray* rslt = [NSArray arrayWithObject:name];
|
|
|
|
|
|
|
|
[name release];
|
|
|
|
|
|
|
|
return rslt;
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
2007-07-17 02:24:05 +00:00
|
|
|
}
|
2006-10-25 22:45:22 +00:00
|
|
|
|
2008-12-15 20:56:29 +00:00
|
|
|
#pragma mark -
|
|
|
|
|
|
|
|
// Support for the "Services" menu. We currently only support sending strings
|
2009-03-18 02:04:01 +00:00
|
|
|
// and HTML to system services.
|
2008-12-15 20:56:29 +00:00
|
|
|
|
|
|
|
- (id)validRequestorForSendType:(NSString *)sendType
|
|
|
|
returnType:(NSString *)returnType
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
|
|
|
|
|
|
|
// sendType contains the type of data that the service would like this
|
|
|
|
// application to send to it. sendType is nil if the service is not
|
|
|
|
// requesting any data.
|
|
|
|
//
|
|
|
|
// returnType contains the type of data the the service would like to
|
|
|
|
// return to this application (e.g., to overwrite the selection).
|
|
|
|
// returnType is nil if the service will not return any data.
|
|
|
|
//
|
|
|
|
// The following condition thus triggers when the service expects a string
|
2010-01-11 01:45:45 +00:00
|
|
|
// or HTML from us or no data at all AND when the service will either not
|
|
|
|
// send back any data to us or will send a string or HTML back to us.
|
|
|
|
|
|
|
|
#define IsSupportedType(typeStr) ([typeStr isEqual:NSStringPboardType] || [typeStr isEqual:NSHTMLPboardType])
|
|
|
|
|
|
|
|
id result = nil;
|
2008-12-15 20:56:29 +00:00
|
|
|
|
2010-01-11 01:45:45 +00:00
|
|
|
if ((!sendType || IsSupportedType(sendType)) &&
|
|
|
|
(!returnType || IsSupportedType(returnType))) {
|
2008-12-15 20:56:29 +00:00
|
|
|
if (mGeckoChild) {
|
2010-01-11 01:45:45 +00:00
|
|
|
// Assume that this object will be able to handle this request.
|
|
|
|
result = self;
|
2009-03-18 02:04:01 +00:00
|
|
|
|
2010-01-11 01:45:45 +00:00
|
|
|
// Keep the ChildView alive during this operation.
|
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
|
|
|
|
|
|
|
// Determine if there is a selection (if sending to the service).
|
|
|
|
if (sendType) {
|
|
|
|
nsQueryContentEvent event(PR_TRUE, NS_QUERY_CONTENT_STATE, mGeckoChild);
|
2010-03-10 21:24:40 +00:00
|
|
|
// This might destroy our widget (and null out mGeckoChild).
|
2010-01-11 01:45:45 +00:00
|
|
|
mGeckoChild->DispatchWindowEvent(event);
|
2010-03-10 21:24:40 +00:00
|
|
|
if (!mGeckoChild || !event.mSucceeded || !event.mReply.mHasSelection)
|
2010-01-11 01:45:45 +00:00
|
|
|
result = nil;
|
|
|
|
}
|
2009-12-30 22:29:26 +00:00
|
|
|
|
2010-01-11 01:45:45 +00:00
|
|
|
// Determine if we can paste (if receiving data from the service).
|
2010-03-10 21:24:40 +00:00
|
|
|
if (mGeckoChild && returnType) {
|
2010-01-11 01:45:45 +00:00
|
|
|
nsContentCommandEvent command(PR_TRUE, NS_CONTENT_COMMAND_PASTE_TRANSFERABLE, mGeckoChild, PR_TRUE);
|
2010-03-10 21:24:40 +00:00
|
|
|
// This might possibly destroy our widget (and null out mGeckoChild).
|
2010-01-11 01:45:45 +00:00
|
|
|
mGeckoChild->DispatchWindowEvent(command);
|
2010-03-10 21:24:40 +00:00
|
|
|
if (!mGeckoChild || !command.mSucceeded || !command.mIsEnabled)
|
2010-01-11 01:45:45 +00:00
|
|
|
result = nil;
|
|
|
|
}
|
2009-03-18 02:04:01 +00:00
|
|
|
}
|
2008-12-15 20:56:29 +00:00
|
|
|
}
|
|
|
|
|
2010-01-11 01:45:45 +00:00
|
|
|
#undef IsSupportedType
|
|
|
|
|
|
|
|
// Give the superclass a chance if this object will not handle this request.
|
|
|
|
if (!result)
|
|
|
|
result = [super validRequestorForSendType:sendType returnType:returnType];
|
|
|
|
|
|
|
|
return result;
|
2008-12-15 20:56:29 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard
|
|
|
|
types:(NSArray *)types
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
|
|
|
|
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
2009-03-18 02:04:01 +00:00
|
|
|
|
|
|
|
// Make sure that the service will accept strings or HTML.
|
|
|
|
if ([types containsObject:NSStringPboardType] == NO &&
|
|
|
|
[types containsObject:NSHTMLPboardType] == NO)
|
2008-12-15 20:56:29 +00:00
|
|
|
return NO;
|
|
|
|
|
2009-03-18 02:04:01 +00:00
|
|
|
// Bail out if there is no Gecko object.
|
2008-12-15 20:56:29 +00:00
|
|
|
if (!mGeckoChild)
|
|
|
|
return NO;
|
2009-03-18 02:04:01 +00:00
|
|
|
|
|
|
|
// Obtain the current selection.
|
|
|
|
nsQueryContentEvent event(PR_TRUE,
|
|
|
|
NS_QUERY_SELECTION_AS_TRANSFERABLE,
|
|
|
|
mGeckoChild);
|
|
|
|
mGeckoChild->DispatchWindowEvent(event);
|
|
|
|
if (!event.mSucceeded || !event.mReply.mTransferable)
|
|
|
|
return NO;
|
|
|
|
|
|
|
|
// Transform the transferable to an NSDictionary.
|
|
|
|
NSDictionary* pasteboardOutputDict = nsClipboard::PasteboardDictFromTransferable(event.mReply.mTransferable);
|
|
|
|
if (!pasteboardOutputDict)
|
2008-12-15 20:56:29 +00:00
|
|
|
return NO;
|
|
|
|
|
2009-03-18 02:04:01 +00:00
|
|
|
// Declare the pasteboard types.
|
|
|
|
unsigned int typeCount = [pasteboardOutputDict count];
|
|
|
|
NSMutableArray * types = [NSMutableArray arrayWithCapacity:typeCount];
|
|
|
|
[types addObjectsFromArray:[pasteboardOutputDict allKeys]];
|
|
|
|
[pboard declareTypes:types owner:nil];
|
|
|
|
|
|
|
|
// Write the data to the pasteboard.
|
|
|
|
for (unsigned int i = 0; i < typeCount; i++) {
|
|
|
|
NSString* currentKey = [types objectAtIndex:i];
|
|
|
|
id currentValue = [pasteboardOutputDict valueForKey:currentKey];
|
|
|
|
|
|
|
|
if (currentKey == NSStringPboardType ||
|
|
|
|
currentKey == kCorePboardType_url ||
|
|
|
|
currentKey == kCorePboardType_urld ||
|
|
|
|
currentKey == kCorePboardType_urln) {
|
|
|
|
[pboard setString:currentValue forType:currentKey];
|
|
|
|
} else if (currentKey == NSHTMLPboardType) {
|
|
|
|
[pboard setString:(nsClipboard::WrapHtmlForSystemPasteboard(currentValue)) forType:currentKey];
|
|
|
|
} else if (currentKey == NSTIFFPboardType) {
|
|
|
|
[pboard setData:currentValue forType:currentKey];
|
|
|
|
} else if (currentKey == NSFilesPromisePboardType) {
|
|
|
|
[pboard setPropertyList:currentValue forType:currentKey];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return YES;
|
2008-12-15 20:56:29 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO);
|
|
|
|
}
|
|
|
|
|
2010-01-11 01:45:45 +00:00
|
|
|
// Called if the service wants us to replace the current selection.
|
2008-12-15 20:56:29 +00:00
|
|
|
- (BOOL)readSelectionFromPasteboard:(NSPasteboard *)pboard
|
|
|
|
{
|
2010-01-11 01:45:45 +00:00
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsITransferable> trans = do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return NO;
|
|
|
|
|
|
|
|
trans->AddDataFlavor(kUnicodeMime);
|
|
|
|
trans->AddDataFlavor(kHTMLMime);
|
|
|
|
|
|
|
|
rv = nsClipboard::TransferableFromPasteboard(trans, pboard);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return NO;
|
|
|
|
|
|
|
|
if (!mGeckoChild)
|
|
|
|
return NO;
|
|
|
|
|
|
|
|
nsContentCommandEvent command(PR_TRUE,
|
|
|
|
NS_CONTENT_COMMAND_PASTE_TRANSFERABLE,
|
|
|
|
mGeckoChild);
|
|
|
|
command.mTransferable = trans;
|
|
|
|
mGeckoChild->DispatchWindowEvent(command);
|
|
|
|
|
|
|
|
return command.mSucceeded && command.mIsEnabled;
|
2008-12-15 20:56:29 +00:00
|
|
|
}
|
|
|
|
|
2006-10-25 22:45:22 +00:00
|
|
|
#pragma mark -
|
|
|
|
|
2006-09-11 15:47:35 +00:00
|
|
|
#ifdef ACCESSIBILITY
|
|
|
|
|
|
|
|
/* Every ChildView has a corresponding mozDocAccessible object that is doing all
|
|
|
|
the heavy lifting. The topmost ChildView corresponds to a mozRootAccessible
|
|
|
|
object.
|
|
|
|
|
|
|
|
All ChildView needs to do is to route all accessibility calls (from the NSAccessibility APIs)
|
|
|
|
down to its object, pretending that they are the same.
|
|
|
|
*/
|
|
|
|
- (id<mozAccessible>)accessible
|
|
|
|
{
|
2007-06-15 22:34:48 +00:00
|
|
|
if (!mGeckoChild)
|
|
|
|
return nil;
|
|
|
|
|
2006-09-14 09:29:28 +00:00
|
|
|
id<mozAccessible> nativeAccessible = nil;
|
2008-01-15 23:11:55 +00:00
|
|
|
|
2008-04-08 04:38:52 +00:00
|
|
|
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
2008-01-15 23:11:55 +00:00
|
|
|
nsCOMPtr<nsIWidget> kungFuDeathGrip2(mGeckoChild);
|
2010-05-12 06:47:35 +00:00
|
|
|
nsRefPtr<nsAccessible> accessible = mGeckoChild->GetDocumentAccessible();
|
2008-01-15 23:11:55 +00:00
|
|
|
if (!mGeckoChild)
|
|
|
|
return nil;
|
|
|
|
|
2006-09-14 09:29:28 +00:00
|
|
|
if (accessible)
|
|
|
|
accessible->GetNativeInterface((void**)&nativeAccessible);
|
2006-09-11 15:47:35 +00:00
|
|
|
|
2006-09-13 16:07:14 +00:00
|
|
|
#ifdef DEBUG_hakan
|
2006-11-15 11:08:14 +00:00
|
|
|
NSAssert(![nativeAccessible isExpired], @"native acc is expired!!!");
|
2006-09-11 15:47:35 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return nativeAccessible;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Implementation of formal mozAccessible formal protocol (enabling mozViews
|
|
|
|
to talk to mozAccessible objects in the accessibility module). */
|
|
|
|
|
2006-11-15 11:08:14 +00:00
|
|
|
- (BOOL)hasRepresentedView
|
|
|
|
{
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id)representedView
|
|
|
|
{
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2006-09-19 08:44:03 +00:00
|
|
|
- (BOOL)isRoot
|
2006-09-11 15:47:35 +00:00
|
|
|
{
|
2006-09-19 08:44:03 +00:00
|
|
|
return [[self accessible] isRoot];
|
2006-09-11 15:47:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
- (void)printHierarchy
|
|
|
|
{
|
|
|
|
[[self accessible] printHierarchy];
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#pragma mark -
|
|
|
|
|
|
|
|
// general
|
|
|
|
|
|
|
|
- (BOOL)accessibilityIsIgnored
|
|
|
|
{
|
|
|
|
return [[self accessible] accessibilityIsIgnored];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id)accessibilityHitTest:(NSPoint)point
|
|
|
|
{
|
|
|
|
return [[self accessible] accessibilityHitTest:point];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id)accessibilityFocusedUIElement
|
|
|
|
{
|
|
|
|
return [[self accessible] accessibilityFocusedUIElement];
|
|
|
|
}
|
|
|
|
|
|
|
|
// actions
|
|
|
|
|
|
|
|
- (NSArray*)accessibilityActionNames
|
|
|
|
{
|
|
|
|
return [[self accessible] accessibilityActionNames];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString*)accessibilityActionDescription:(NSString*)action
|
|
|
|
{
|
|
|
|
return [[self accessible] accessibilityActionDescription:action];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)accessibilityPerformAction:(NSString*)action
|
|
|
|
{
|
|
|
|
return [[self accessible] accessibilityPerformAction:action];
|
|
|
|
}
|
|
|
|
|
|
|
|
// attributes
|
|
|
|
|
|
|
|
- (NSArray*)accessibilityAttributeNames
|
|
|
|
{
|
|
|
|
return [[self accessible] accessibilityAttributeNames];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)accessibilityIsAttributeSettable:(NSString*)attribute
|
|
|
|
{
|
|
|
|
return [[self accessible] accessibilityIsAttributeSettable:attribute];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id)accessibilityAttributeValue:(NSString*)attribute
|
|
|
|
{
|
2008-02-20 23:47:05 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
|
|
|
|
2006-09-14 09:29:28 +00:00
|
|
|
id<mozAccessible> accessible = [self accessible];
|
2006-09-11 15:47:35 +00:00
|
|
|
|
|
|
|
// if we're the root (topmost) accessible, we need to return our native AXParent as we
|
|
|
|
// traverse outside to the hierarchy of whoever embeds us. thus, fall back on NSView's
|
|
|
|
// default implementation for this attribute.
|
2006-09-19 08:44:03 +00:00
|
|
|
if ([attribute isEqualToString:NSAccessibilityParentAttribute] && [accessible isRoot]) {
|
2006-09-11 15:47:35 +00:00
|
|
|
id parentAccessible = [super accessibilityAttributeValue:attribute];
|
|
|
|
return parentAccessible;
|
|
|
|
}
|
|
|
|
|
|
|
|
return [accessible accessibilityAttributeValue:attribute];
|
2008-02-20 23:47:05 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
2006-09-11 15:47:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* ACCESSIBILITY */
|
|
|
|
|
2001-11-06 15:35:24 +00:00
|
|
|
@end
|
2007-04-15 13:43:55 +00:00
|
|
|
|
2009-09-23 02:31:37 +00:00
|
|
|
#pragma mark -
|
|
|
|
|
|
|
|
void
|
|
|
|
ChildViewMouseTracker::OnDestroyView(ChildView* aView)
|
|
|
|
{
|
|
|
|
if (sLastMouseEventView == aView)
|
|
|
|
sLastMouseEventView = nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-12-11 21:56:59 +00:00
|
|
|
ChildViewMouseTracker::ReEvaluateMouseEnterState(NSEvent* aEvent)
|
2009-09-23 02:31:37 +00:00
|
|
|
{
|
2009-10-21 07:02:13 +00:00
|
|
|
ChildView* oldView = sLastMouseEventView;
|
2009-12-11 21:56:59 +00:00
|
|
|
sLastMouseEventView = ViewForEvent(aEvent);
|
|
|
|
if (sLastMouseEventView != oldView) {
|
2009-09-23 02:31:37 +00:00
|
|
|
// Send enter and / or exit events.
|
2009-12-11 21:56:59 +00:00
|
|
|
nsMouseEvent::exitType type = [sLastMouseEventView window] == [oldView window] ?
|
2009-09-23 02:31:37 +00:00
|
|
|
nsMouseEvent::eChild : nsMouseEvent::eTopLevel;
|
2009-10-21 07:02:13 +00:00
|
|
|
[oldView sendMouseEnterOrExitEvent:aEvent enter:NO type:type];
|
2009-09-23 02:31:37 +00:00
|
|
|
// After the cursor exits the window set it to a visible regular arrow cursor.
|
|
|
|
if (type == nsMouseEvent::eTopLevel) {
|
|
|
|
[[nsCursorManager sharedInstance] setCursor:eCursor_standard];
|
|
|
|
}
|
2009-12-11 21:56:59 +00:00
|
|
|
[sLastMouseEventView sendMouseEnterOrExitEvent:aEvent enter:YES type:type];
|
2009-09-23 02:31:37 +00:00
|
|
|
}
|
2009-12-11 21:56:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ChildViewMouseTracker::MouseMoved(NSEvent* aEvent)
|
|
|
|
{
|
|
|
|
ReEvaluateMouseEnterState(aEvent);
|
|
|
|
[sLastMouseEventView handleMouseMoved:aEvent];
|
2009-09-23 02:31:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ChildView*
|
|
|
|
ChildViewMouseTracker::ViewForEvent(NSEvent* aEvent)
|
|
|
|
{
|
|
|
|
NSWindow* window = WindowForEvent(aEvent);
|
|
|
|
if (!window || !WindowAcceptsEvent(window, aEvent))
|
|
|
|
return nil;
|
|
|
|
|
|
|
|
NSPoint windowEventLocation = nsCocoaUtils::EventLocationForWindow(aEvent, window);
|
|
|
|
NSView* view = [[[window contentView] superview] hitTest:windowEventLocation];
|
|
|
|
NS_ASSERTION(view, "How can the mouse be over a window but not over a view in that window?");
|
2009-10-21 15:09:19 +00:00
|
|
|
return [view isKindOfClass:[ChildView class]] ? (ChildView*)view : nil;
|
2009-09-23 02:31:37 +00:00
|
|
|
}
|
|
|
|
|
2009-12-30 15:18:36 +00:00
|
|
|
static CGWindowLevel kDockWindowLevel = 0;
|
|
|
|
static CGWindowLevel kPopupWindowLevel = 0;
|
|
|
|
static CGWindowLevel kFloatingWindowLevel = 0;
|
|
|
|
|
|
|
|
static BOOL WindowNumberIsUnderPoint(NSInteger aWindowNumber, NSPoint aPoint) {
|
|
|
|
NSWindow* window = [NSApp windowWithWindowNumber:aWindowNumber];
|
|
|
|
if (window) {
|
|
|
|
// This is one of our own windows.
|
|
|
|
return NSMouseInRect(aPoint, [window frame], NO);
|
|
|
|
}
|
|
|
|
|
|
|
|
CGSConnection cid = _CGSDefaultConnection();
|
|
|
|
|
|
|
|
if (!kDockWindowLevel) {
|
|
|
|
// These constants are in fact function calls, so cache them.
|
|
|
|
kDockWindowLevel = kCGDockWindowLevel;
|
|
|
|
kPopupWindowLevel = kCGPopUpMenuWindowLevel;
|
|
|
|
kFloatingWindowLevel = kCGFloatingWindowLevel;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Some things put transparent windows on top of everything. Ignore them.
|
|
|
|
CGWindowLevel level;
|
|
|
|
if ((kCGErrorSuccess == CGSGetWindowLevel(cid, aWindowNumber, &level)) &&
|
|
|
|
(level == kDockWindowLevel || // Transparent layer, spanning the whole screen
|
|
|
|
level == kFloatingWindowLevel || // invisible Jing window
|
|
|
|
level > kPopupWindowLevel)) // Snapz Pro X while recording a screencast
|
|
|
|
return false;
|
|
|
|
|
|
|
|
CGRect rect;
|
|
|
|
if (kCGErrorSuccess != CGSGetScreenRectForWindow(cid, aWindowNumber, &rect))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
CGPoint point = { aPoint.x, nsCocoaUtils::FlippedScreenY(aPoint.y) };
|
|
|
|
return CGRectContainsPoint(rect, point);
|
|
|
|
}
|
|
|
|
|
|
|
|
@interface NSWindow(SnowLeopardWindowUnderPointAPI)
|
|
|
|
+ (NSInteger)windowNumberAtPoint:(NSPoint)point belowWindowWithWindowNumber:(NSInteger)windowNumber;
|
|
|
|
@end
|
2009-09-23 02:31:37 +00:00
|
|
|
|
2009-12-30 15:18:36 +00:00
|
|
|
// Find the window number of the window under the given point, regardless of
|
|
|
|
// which app the window belongs to. Returns 0 if no window was found.
|
|
|
|
static NSInteger WindowNumberAtPoint(NSPoint aPoint) {
|
|
|
|
// Use the awesome new API on 10.6+.
|
|
|
|
if ([NSWindow respondsToSelector:@selector(windowNumberAtPoint:belowWindowWithWindowNumber:)])
|
|
|
|
return [NSWindow windowNumberAtPoint:aPoint belowWindowWithWindowNumber:0];
|
|
|
|
|
|
|
|
// windowNumberAtPoint is not supported, so we'll have to find the right
|
|
|
|
// window manually by iterating over all windows on the screen and testing
|
|
|
|
// whether the mouse is inside the window's rect. We do this using private CGS
|
|
|
|
// functions.
|
|
|
|
// Another way of doing it would be to use tracking rects, but those are
|
|
|
|
// view-controlled, so they need to be reset whenever an NSView changes its
|
|
|
|
// size or position, which is expensive. See bug 300904 comment 20.
|
|
|
|
// A problem with using the CGS functions is that we only look at the windows'
|
|
|
|
// rects, not at the transparency of the actual pixel the mouse is over. This
|
|
|
|
// means that we won't treat transparent pixels as transparent to mouse
|
|
|
|
// events, which is a disadvantage over using tracking rects and leads to the
|
|
|
|
// crummy window level workarounds in WindowNumberIsUnderPoint.
|
|
|
|
// But speed is more important.
|
|
|
|
|
|
|
|
// Get the window list.
|
2009-09-23 02:31:37 +00:00
|
|
|
NSInteger windowCount;
|
|
|
|
NSCountWindows(&windowCount);
|
|
|
|
NSInteger* windowList = (NSInteger*)malloc(sizeof(NSInteger) * windowCount);
|
|
|
|
if (!windowList)
|
|
|
|
return nil;
|
2009-12-30 15:18:36 +00:00
|
|
|
|
2009-09-23 02:31:37 +00:00
|
|
|
// The list we get back here is in order from front to back.
|
|
|
|
NSWindowList(windowCount, windowList);
|
|
|
|
for (NSInteger i = 0; i < windowCount; i++) {
|
2009-12-30 15:18:36 +00:00
|
|
|
NSInteger windowNumber = windowList[i];
|
|
|
|
if (WindowNumberIsUnderPoint(windowNumber, aPoint)) {
|
2009-09-23 02:31:37 +00:00
|
|
|
free(windowList);
|
2009-12-30 15:18:36 +00:00
|
|
|
return windowNumber;
|
2009-09-23 02:31:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(windowList);
|
2009-12-30 15:18:36 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find Gecko window under the mouse. Returns nil if the mouse isn't over
|
|
|
|
// any of our windows.
|
|
|
|
NSWindow*
|
|
|
|
ChildViewMouseTracker::WindowForEvent(NSEvent* anEvent)
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
|
|
|
|
|
|
|
NSPoint screenPoint = nsCocoaUtils::ScreenLocationForEvent(anEvent);
|
|
|
|
NSInteger windowNumber = WindowNumberAtPoint(screenPoint);
|
|
|
|
|
|
|
|
// This will return nil if windowNumber belongs to a window that we don't own.
|
|
|
|
return [NSApp windowWithWindowNumber:windowNumber];
|
2009-09-23 02:31:37 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
2010-05-14 10:21:25 +00:00
|
|
|
ChildViewMouseTracker::WindowAcceptsEvent(NSWindow* aWindow, NSEvent* aEvent)
|
2009-09-23 02:31:37 +00:00
|
|
|
{
|
|
|
|
// Right mouse down events may get through to all windows, even to a top level
|
|
|
|
// window with an open sheet.
|
2010-05-14 10:21:25 +00:00
|
|
|
if (!aWindow || [aEvent type] == NSRightMouseDown)
|
2009-09-23 02:31:37 +00:00
|
|
|
return YES;
|
|
|
|
|
|
|
|
id delegate = [aWindow delegate];
|
|
|
|
if (!delegate || ![delegate isKindOfClass:[WindowDelegate class]])
|
|
|
|
return YES;
|
|
|
|
|
|
|
|
nsIWidget *windowWidget = [(WindowDelegate *)delegate geckoWidget];
|
|
|
|
if (!windowWidget)
|
|
|
|
return YES;
|
|
|
|
|
|
|
|
nsWindowType windowType;
|
|
|
|
windowWidget->GetWindowType(windowType);
|
|
|
|
|
2010-05-14 10:21:25 +00:00
|
|
|
NSWindow* topLevelWindow = nil;
|
|
|
|
|
2009-09-23 02:31:37 +00:00
|
|
|
switch (windowType) {
|
|
|
|
case eWindowType_popup:
|
|
|
|
// If this is a context menu, it won't have a parent. So we'll always
|
|
|
|
// accept mouse move events on context menus even when none of our windows
|
|
|
|
// is active, which is the right thing to do.
|
|
|
|
// For panels, the parent window is the XUL window that owns the panel.
|
2010-05-14 10:21:25 +00:00
|
|
|
return WindowAcceptsEvent([aWindow parentWindow], aEvent);
|
2009-09-23 02:31:37 +00:00
|
|
|
|
|
|
|
case eWindowType_toplevel:
|
|
|
|
case eWindowType_dialog:
|
2010-05-14 10:21:25 +00:00
|
|
|
if ([aWindow attachedSheet])
|
|
|
|
return NO;
|
2009-09-23 02:31:37 +00:00
|
|
|
|
2010-05-14 10:21:25 +00:00
|
|
|
topLevelWindow = aWindow;
|
|
|
|
break;
|
2009-09-23 02:31:37 +00:00
|
|
|
case eWindowType_sheet: {
|
|
|
|
nsIWidget* parentWidget = windowWidget->GetSheetWindowParent();
|
|
|
|
if (!parentWidget)
|
|
|
|
return YES;
|
|
|
|
|
2010-05-14 10:21:25 +00:00
|
|
|
topLevelWindow = (NSWindow*)parentWidget->GetNativeData(NS_NATIVE_WINDOW);
|
|
|
|
break;
|
2009-09-23 02:31:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
return YES;
|
|
|
|
}
|
2010-05-14 10:21:25 +00:00
|
|
|
|
|
|
|
if (!topLevelWindow ||
|
|
|
|
[topLevelWindow isMainWindow] ||
|
|
|
|
[aEvent type] == NSOtherMouseDown ||
|
|
|
|
(([aEvent modifierFlags] & NSCommandKeyMask) != 0 &&
|
|
|
|
[aEvent type] != NSMouseMoved))
|
|
|
|
return YES;
|
|
|
|
|
|
|
|
// If we're here then we're dealing with a left click or mouse move on an
|
|
|
|
// inactive window or something similar. Return NO for now.
|
|
|
|
return NO;
|
2009-09-23 02:31:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark -
|
|
|
|
|
2009-10-01 04:15:05 +00:00
|
|
|
#ifndef NP_NO_CARBON
|
|
|
|
|
2008-06-30 16:30:22 +00:00
|
|
|
// Target for text services events sent as the result of calls made to
|
|
|
|
// TSMProcessRawKeyEvent() in [ChildView keyDown:] (above) when a plugin has
|
|
|
|
// the focus. The calls to TSMProcessRawKeyEvent() short-circuit Cocoa-based
|
|
|
|
// IME (which would otherwise interfere with our efforts) and allow Carbon-
|
|
|
|
// based IME to work in plugins (via the NPAPI). This strategy doesn't cause
|
|
|
|
// trouble for plugins that (like the Java Embedding Plugin) bypass the NPAPI
|
|
|
|
// to get their keyboard events and do their own Cocoa-based IME.
|
|
|
|
OSStatus PluginKeyEventsHandler(EventHandlerCallRef inHandlerRef,
|
|
|
|
EventRef inEvent, void *userData)
|
|
|
|
{
|
2010-04-13 20:36:03 +00:00
|
|
|
nsAutoreleasePool localPool;
|
2008-06-30 16:30:22 +00:00
|
|
|
|
|
|
|
TSMDocumentID activeDoc = ::TSMGetActiveDocument();
|
|
|
|
if (!activeDoc) {
|
|
|
|
return eventNotHandledErr;
|
|
|
|
}
|
|
|
|
|
|
|
|
ChildView *target = nil;
|
|
|
|
OSStatus status = ::TSMGetDocumentProperty(activeDoc, kFocusedChildViewTSMDocPropertyTag,
|
|
|
|
sizeof(ChildView *), nil, &target);
|
|
|
|
if (status != noErr)
|
|
|
|
target = nil;
|
|
|
|
if (!target) {
|
|
|
|
return eventNotHandledErr;
|
|
|
|
}
|
|
|
|
|
|
|
|
EventRef keyEvent = NULL;
|
|
|
|
status = ::GetEventParameter(inEvent, kEventParamTextInputSendKeyboardEvent,
|
|
|
|
typeEventRef, NULL, sizeof(EventRef), NULL, &keyEvent);
|
|
|
|
if ((status != noErr) || !keyEvent) {
|
|
|
|
return eventNotHandledErr;
|
|
|
|
}
|
|
|
|
|
|
|
|
[target processPluginKeyEvent:keyEvent];
|
|
|
|
|
|
|
|
return noErr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static EventHandlerRef gPluginKeyEventsHandler = NULL;
|
|
|
|
|
|
|
|
// Called from nsAppShell::Init()
|
|
|
|
void NS_InstallPluginKeyEventsHandler()
|
|
|
|
{
|
|
|
|
if (gPluginKeyEventsHandler)
|
|
|
|
return;
|
|
|
|
static const EventTypeSpec sTSMEvents[] =
|
|
|
|
{ { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } };
|
|
|
|
::InstallEventHandler(::GetEventDispatcherTarget(),
|
|
|
|
::NewEventHandlerUPP(PluginKeyEventsHandler),
|
|
|
|
GetEventTypeCount(sTSMEvents),
|
|
|
|
sTSMEvents,
|
|
|
|
NULL,
|
|
|
|
&gPluginKeyEventsHandler);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Called from nsAppShell::Exit()
|
|
|
|
void NS_RemovePluginKeyEventsHandler()
|
|
|
|
{
|
|
|
|
if (!gPluginKeyEventsHandler)
|
|
|
|
return;
|
|
|
|
::RemoveEventHandler(gPluginKeyEventsHandler);
|
|
|
|
gPluginKeyEventsHandler = NULL;
|
|
|
|
}
|
2009-02-06 17:36:04 +00:00
|
|
|
|
2009-10-01 04:15:05 +00:00
|
|
|
#endif // NP_NO_CARBON
|
|
|
|
|
2009-02-06 17:36:04 +00:00
|
|
|
@interface NSView (MethodSwizzling)
|
|
|
|
- (BOOL)nsChildView_NSView_mouseDownCanMoveWindow;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation NSView (MethodSwizzling)
|
|
|
|
|
|
|
|
// All top-level browser windows belong to the ToolbarWindow class and have
|
|
|
|
// NSTexturedBackgroundWindowMask turned on in their "style" (see particularly
|
|
|
|
// [ToolbarWindow initWithContentRect:...] in nsCocoaWindow.mm). This style
|
|
|
|
// normally means the window "may be moved by clicking and dragging anywhere
|
|
|
|
// in the window background", but we've suppressed this by giving the
|
|
|
|
// ChildView class a mouseDownCanMoveWindow method that always returns NO.
|
|
|
|
// Normally a ToolbarWindow's contentView (not a ChildView) returns YES when
|
|
|
|
// NSTexturedBackgroundWindowMask is turned on. But normally this makes no
|
|
|
|
// difference. However, under some (probably very unusual) circumstances
|
|
|
|
// (and only on Leopard) it *does* make a difference -- for example it
|
|
|
|
// triggers bmo bugs 431902 and 476393. So here we make sure that a
|
|
|
|
// ToolbarWindow's contentView always returns NO from the
|
|
|
|
// mouseDownCanMoveWindow method.
|
|
|
|
- (BOOL)nsChildView_NSView_mouseDownCanMoveWindow
|
|
|
|
{
|
|
|
|
NSWindow *ourWindow = [self window];
|
|
|
|
NSView *contentView = [ourWindow contentView];
|
|
|
|
if ([ourWindow isKindOfClass:[ToolbarWindow class]] && (self == contentView))
|
|
|
|
return NO;
|
|
|
|
return [self nsChildView_NSView_mouseDownCanMoveWindow];
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|