mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1092630: Get rid of native widgets for OS X NPAPI plugins, make things work much better under e10s. Patch by Josh Aas, Markus Stange, Steven Michaud, David Parks. r=smichaud/jst/josh (more reviews pending)
This commit is contained in:
parent
4aad711842
commit
6141b5290e
@ -910,7 +910,8 @@ nsFrameLoader::ShowRemoteFrame(const nsIntSize& size,
|
||||
|
||||
// Don't show remote iframe if we are waiting for the completion of reflow.
|
||||
if (!aFrame || !(aFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
|
||||
mRemoteBrowser->UpdateDimensions(dimensions, size);
|
||||
nsIntPoint chromeDisp = aFrame->GetChromeDisplacement();
|
||||
mRemoteBrowser->UpdateDimensions(dimensions, size, chromeDisp);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1942,7 +1943,8 @@ nsFrameLoader::UpdatePositionAndSize(nsSubDocumentFrame *aIFrame)
|
||||
nsIntSize size = aIFrame->GetSubdocumentSize();
|
||||
nsIntRect dimensions;
|
||||
NS_ENSURE_SUCCESS(GetWindowDimensions(dimensions), NS_ERROR_FAILURE);
|
||||
mRemoteBrowser->UpdateDimensions(dimensions, size);
|
||||
nsIntPoint chromeDisp = aIFrame->GetChromeDisplacement();
|
||||
mRemoteBrowser->UpdateDimensions(dimensions, size, chromeDisp);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -440,7 +440,8 @@ child:
|
||||
|
||||
CacheFileDescriptor(nsString path, FileDescriptor fd);
|
||||
|
||||
UpdateDimensions(nsIntRect rect, nsIntSize size, ScreenOrientation orientation) compress;
|
||||
UpdateDimensions(nsIntRect rect, nsIntSize size, ScreenOrientation orientation,
|
||||
nsIntPoint chromeDisp) compress;
|
||||
|
||||
UpdateFrame(FrameMetrics frame);
|
||||
|
||||
|
@ -2010,13 +2010,15 @@ TabChild::RecvShow(const nsIntSize& aSize,
|
||||
}
|
||||
|
||||
bool
|
||||
TabChild::RecvUpdateDimensions(const nsIntRect& rect, const nsIntSize& size, const ScreenOrientation& orientation)
|
||||
TabChild::RecvUpdateDimensions(const nsIntRect& rect, const nsIntSize& size,
|
||||
const ScreenOrientation& orientation, const nsIntPoint& chromeDisp)
|
||||
{
|
||||
if (!mRemoteFrame) {
|
||||
return true;
|
||||
}
|
||||
|
||||
mOuterRect = rect;
|
||||
mChromeDisp = chromeDisp;
|
||||
|
||||
bool initialSizing = !HasValidInnerSize()
|
||||
&& (size.width != 0 && size.height != 0);
|
||||
|
@ -324,7 +324,8 @@ public:
|
||||
PRenderFrameChild* aRenderFrame) MOZ_OVERRIDE;
|
||||
virtual bool RecvUpdateDimensions(const nsIntRect& rect,
|
||||
const nsIntSize& size,
|
||||
const ScreenOrientation& orientation) MOZ_OVERRIDE;
|
||||
const ScreenOrientation& orientation,
|
||||
const nsIntPoint& chromeDisp) MOZ_OVERRIDE;
|
||||
virtual bool RecvUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics) MOZ_OVERRIDE;
|
||||
virtual bool RecvAcknowledgeScrollUpdate(const ViewID& aScrollId,
|
||||
const uint32_t& aScrollGeneration) MOZ_OVERRIDE;
|
||||
@ -495,6 +496,8 @@ public:
|
||||
bool DeallocPPluginWidgetChild(PPluginWidgetChild* aActor) MOZ_OVERRIDE;
|
||||
already_AddRefed<nsIWidget> CreatePluginWidget(nsIWidget* aParent);
|
||||
|
||||
nsIntPoint GetChromeDisplacement() { return mChromeDisp; };
|
||||
|
||||
protected:
|
||||
virtual ~TabChild();
|
||||
|
||||
@ -653,6 +656,8 @@ private:
|
||||
nsRefPtr<ActiveElementManager> mActiveElementManager;
|
||||
bool mHasValidInnerSize;
|
||||
bool mDestroyed;
|
||||
// Position of tab, relative to parent widget (typically the window)
|
||||
nsIntPoint mChromeDisp;
|
||||
TabId mUniqueId;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(TabChild);
|
||||
|
@ -618,7 +618,8 @@ TabParent::Show(const nsIntSize& size)
|
||||
}
|
||||
|
||||
void
|
||||
TabParent::UpdateDimensions(const nsIntRect& rect, const nsIntSize& size)
|
||||
TabParent::UpdateDimensions(const nsIntRect& rect, const nsIntSize& size,
|
||||
const nsIntPoint& aChromeDisp)
|
||||
{
|
||||
if (mIsDestroyed) {
|
||||
return;
|
||||
@ -634,7 +635,7 @@ TabParent::UpdateDimensions(const nsIntRect& rect, const nsIntSize& size)
|
||||
mDimensions = size;
|
||||
mOrientation = orientation;
|
||||
|
||||
unused << SendUpdateDimensions(mRect, mDimensions, mOrientation);
|
||||
unused << SendUpdateDimensions(mRect, mDimensions, mOrientation, aChromeDisp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -225,7 +225,8 @@ public:
|
||||
// message-sending functions under a layer of indirection and
|
||||
// eating the return values
|
||||
void Show(const nsIntSize& size);
|
||||
void UpdateDimensions(const nsIntRect& rect, const nsIntSize& size);
|
||||
void UpdateDimensions(const nsIntRect& rect, const nsIntSize& size,
|
||||
const nsIntPoint& chromeDisp);
|
||||
void UpdateFrame(const layers::FrameMetrics& aFrameMetrics);
|
||||
void UIResolutionChanged();
|
||||
void AcknowledgeScrollUpdate(const ViewID& aScrollId, const uint32_t& aScrollGeneration);
|
||||
|
@ -98,10 +98,12 @@ MSVC_ENABLE_PGO = True
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/dom/base',
|
||||
'/dom/plugins/ipc',
|
||||
'/layout/generic',
|
||||
'/layout/xul',
|
||||
'/widget',
|
||||
'/widget/android',
|
||||
'/widget/cocoa',
|
||||
'/xpcom/base',
|
||||
]
|
||||
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <OpenGL/OpenGL.h>
|
||||
#include "nsCocoaFeatures.h"
|
||||
#include "PluginUtilsOSX.h"
|
||||
#endif
|
||||
|
||||
// needed for nppdf plugin
|
||||
@ -2121,13 +2122,13 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
|
||||
}
|
||||
|
||||
case NPNVsupportsCoreAnimationBool: {
|
||||
*(NPBool*)result = nsCocoaFeatures::SupportCoreAnimationPlugins();
|
||||
*(NPBool*)result = true;
|
||||
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
case NPNVsupportsInvalidatingCoreAnimationBool: {
|
||||
*(NPBool*)result = nsCocoaFeatures::SupportCoreAnimationPlugins();
|
||||
*(NPBool*)result = true;
|
||||
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
@ -2784,11 +2785,50 @@ _unscheduletimer(NPP instance, uint32_t timerID)
|
||||
NPError
|
||||
_popupcontextmenu(NPP instance, NPMenu* menu)
|
||||
{
|
||||
#ifdef MOZ_WIDGET_COCOA
|
||||
nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
|
||||
if (!inst)
|
||||
|
||||
double pluginX, pluginY;
|
||||
double screenX, screenY;
|
||||
|
||||
const NPCocoaEvent* currentEvent = static_cast<NPCocoaEvent*>(inst->GetCurrentEvent());
|
||||
if (!currentEvent) {
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
// Ensure that the events has an x/y value.
|
||||
if (currentEvent->type != NPCocoaEventMouseDown &&
|
||||
currentEvent->type != NPCocoaEventMouseUp &&
|
||||
currentEvent->type != NPCocoaEventMouseMoved &&
|
||||
currentEvent->type != NPCocoaEventMouseEntered &&
|
||||
currentEvent->type != NPCocoaEventMouseExited &&
|
||||
currentEvent->type != NPCocoaEventMouseDragged) {
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
pluginX = currentEvent->data.mouse.pluginX;
|
||||
pluginY = currentEvent->data.mouse.pluginY;
|
||||
|
||||
if ((pluginX < 0.0) || (pluginY < 0.0))
|
||||
return NPERR_GENERIC_ERROR;
|
||||
|
||||
return inst->PopUpContextMenu(menu);
|
||||
NPBool success = _convertpoint(instance,
|
||||
pluginX, pluginY, NPCoordinateSpacePlugin,
|
||||
&screenX, &screenY, NPCoordinateSpaceScreen);
|
||||
|
||||
if (success) {
|
||||
return mozilla::plugins::PluginUtilsOSX::ShowCocoaContextMenu(menu,
|
||||
screenX, screenY,
|
||||
nullptr,
|
||||
nullptr);
|
||||
} else {
|
||||
NS_WARNING("Convertpoint failed, could not created contextmenu.");
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
#else
|
||||
NS_WARNING("Not supported on this platform!");
|
||||
return NPERR_GENERIC_ERROR;
|
||||
#endif
|
||||
}
|
||||
|
||||
NPBool
|
||||
|
@ -173,25 +173,26 @@ static NS_DEFINE_IID(kIOutputStreamIID, NS_IOUTPUTSTREAM_IID);
|
||||
NS_IMPL_ISUPPORTS0(nsNPAPIPluginInstance)
|
||||
|
||||
nsNPAPIPluginInstance::nsNPAPIPluginInstance()
|
||||
:
|
||||
mDrawingModel(kDefaultDrawingModel),
|
||||
: mDrawingModel(kDefaultDrawingModel)
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
mANPDrawingModel(0),
|
||||
mFullScreenOrientation(dom::eScreenOrientation_LandscapePrimary),
|
||||
mWakeLocked(false),
|
||||
mFullScreen(false),
|
||||
mInverted(false),
|
||||
, mANPDrawingModel(0)
|
||||
, mFullScreenOrientation(dom::eScreenOrientation_LandscapePrimary)
|
||||
, mWakeLocked(false)
|
||||
, mFullScreen(false)
|
||||
, mInverted(false)
|
||||
#endif
|
||||
, mRunning(NOT_STARTED)
|
||||
, mWindowless(false)
|
||||
, mTransparent(false)
|
||||
, mCached(false)
|
||||
, mUsesDOMForCursor(false)
|
||||
, mInPluginInitCall(false)
|
||||
, mPlugin(nullptr)
|
||||
, mMIMEType(nullptr)
|
||||
, mOwner(nullptr)
|
||||
#ifdef XP_MACOSX
|
||||
, mCurrentPluginEvent(nullptr)
|
||||
#endif
|
||||
mRunning(NOT_STARTED),
|
||||
mWindowless(false),
|
||||
mTransparent(false),
|
||||
mCached(false),
|
||||
mUsesDOMForCursor(false),
|
||||
mInPluginInitCall(false),
|
||||
mPlugin(nullptr),
|
||||
mMIMEType(nullptr),
|
||||
mOwner(nullptr),
|
||||
mCurrentPluginEvent(nullptr)
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
, mOnScreen(true)
|
||||
#endif
|
||||
@ -671,7 +672,9 @@ nsresult nsNPAPIPluginInstance::HandleEvent(void* event, int16_t* result,
|
||||
int16_t tmpResult = kNPEventNotHandled;
|
||||
|
||||
if (pluginFunctions->event) {
|
||||
#ifdef XP_MACOSX
|
||||
mCurrentPluginEvent = event;
|
||||
#endif
|
||||
#if defined(XP_WIN)
|
||||
NS_TRY_SAFE_CALL_RETURN(tmpResult, (*pluginFunctions->event)(&mNPP, event), this,
|
||||
aSafeToReenterGecko);
|
||||
@ -685,7 +688,9 @@ nsresult nsNPAPIPluginInstance::HandleEvent(void* event, int16_t* result,
|
||||
|
||||
if (result)
|
||||
*result = tmpResult;
|
||||
#ifdef XP_MACOSX
|
||||
mCurrentPluginEvent = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -1152,7 +1157,8 @@ nsNPAPIPluginInstance::ShouldCache()
|
||||
nsresult
|
||||
nsNPAPIPluginInstance::IsWindowless(bool* isWindowless)
|
||||
{
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
#if defined(MOZ_WIDGET_ANDROID) || defined(XP_MACOSX)
|
||||
// All OS X plugins are windowless.
|
||||
// On android, pre-honeycomb, all plugins are treated as windowless.
|
||||
*isWindowless = true;
|
||||
#else
|
||||
@ -1511,23 +1517,13 @@ nsNPAPIPluginInstance::UnscheduleTimer(uint32_t timerID)
|
||||
delete t;
|
||||
}
|
||||
|
||||
// Show the context menu at the location for the current event.
|
||||
// This can only be called from within an NPP_SendEvent call.
|
||||
NPError
|
||||
nsNPAPIPluginInstance::PopUpContextMenu(NPMenu* menu)
|
||||
{
|
||||
if (mOwner && mCurrentPluginEvent)
|
||||
return mOwner->ShowNativeContextMenu(menu, mCurrentPluginEvent);
|
||||
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
NPBool
|
||||
nsNPAPIPluginInstance::ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
|
||||
double *destX, double *destY, NPCoordinateSpace destSpace)
|
||||
{
|
||||
if (mOwner)
|
||||
if (mOwner) {
|
||||
return mOwner->ConvertPoint(sourceX, sourceY, sourceSpace, destX, destY, destSpace);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -134,6 +134,10 @@ public:
|
||||
void RedrawPlugin();
|
||||
#ifdef XP_MACOSX
|
||||
void SetEventModel(NPEventModel aModel);
|
||||
|
||||
void* GetCurrentEvent() {
|
||||
return mCurrentPluginEvent;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
@ -261,7 +265,6 @@ public:
|
||||
nsNPAPITimer* TimerWithID(uint32_t id, uint32_t* index);
|
||||
uint32_t ScheduleTimer(uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID));
|
||||
void UnscheduleTimer(uint32_t timerID);
|
||||
NPError PopUpContextMenu(NPMenu* menu);
|
||||
NPBool ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace);
|
||||
|
||||
|
||||
@ -368,8 +371,10 @@ private:
|
||||
|
||||
nsTArray<nsNPAPITimer*> mTimers;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
// non-null during a HandleEvent call
|
||||
void* mCurrentPluginEvent;
|
||||
#endif
|
||||
|
||||
// Timestamp for the last time this plugin was stopped.
|
||||
// This is only valid when the plugin is actually stopped!
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -33,7 +33,12 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
struct MozPluginParameter;
|
||||
}
|
||||
namespace widget {
|
||||
class PuppetWidget;
|
||||
}
|
||||
}
|
||||
|
||||
using mozilla::widget::PuppetWidget;
|
||||
|
||||
#ifdef MOZ_X11
|
||||
class gfxXlibSurface;
|
||||
@ -62,6 +67,7 @@ public:
|
||||
|
||||
NS_IMETHOD ShowStatus(const char16_t *aStatusMsg) MOZ_OVERRIDE;
|
||||
|
||||
// This can go away, just leaving it here to avoid changing the interface.
|
||||
NPError ShowNativeContextMenu(NPMenu* menu, void* event) MOZ_OVERRIDE;
|
||||
|
||||
NPBool ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
|
||||
@ -108,7 +114,7 @@ public:
|
||||
|
||||
nsresult Init(nsIContent* aContent);
|
||||
|
||||
void* GetPluginPortFromWidget();
|
||||
void* GetPluginPort();
|
||||
void ReleasePluginPort(void* pluginPort);
|
||||
|
||||
nsEventStatus ProcessEvent(const mozilla::WidgetGUIEvent& anEvent);
|
||||
@ -116,6 +122,11 @@ public:
|
||||
#ifdef XP_MACOSX
|
||||
enum { ePluginPaintEnable, ePluginPaintDisable };
|
||||
|
||||
void WindowFocusMayHaveChanged();
|
||||
void ResolutionMayHaveChanged();
|
||||
|
||||
bool WindowIsActive();
|
||||
void SendWindowFocusChanged(bool aIsActive);
|
||||
NPDrawingModel GetDrawingModel();
|
||||
bool IsRemoteDrawingCoreAnimation();
|
||||
nsresult ContentsScaleFactorChanged(double aContentsScaleFactor);
|
||||
@ -124,19 +135,14 @@ public:
|
||||
void AddToCARefreshTimer();
|
||||
void RemoveFromCARefreshTimer();
|
||||
// This calls into the plugin (NPP_SetWindow) and can run script.
|
||||
void* FixUpPluginWindow(int32_t inPaintState);
|
||||
void FixUpPluginWindow(int32_t inPaintState);
|
||||
void HidePluginWindow();
|
||||
// Set a flag that (if true) indicates the plugin port info has changed and
|
||||
// SetWindow() needs to be called.
|
||||
void SetPluginPortChanged(bool aState) { mPluginPortChanged = aState; }
|
||||
// Return a pointer to the internal nsPluginPort structure that's used to
|
||||
// store a copy of plugin port info and to detect when it's been changed.
|
||||
void* GetPluginPortCopy();
|
||||
// Set plugin port info in the plugin (in the 'window' member of the
|
||||
// NPWindow structure passed to the plugin by SetWindow()) and set a
|
||||
// flag (mPluginPortChanged) to indicate whether or not this info has
|
||||
// changed, and SetWindow() needs to be called again.
|
||||
void* SetPluginPortAndDetectChange();
|
||||
// NPWindow structure passed to the plugin by SetWindow()).
|
||||
void SetPluginPort();
|
||||
// Flag when we've set up a Thebes (and CoreGraphics) context in
|
||||
// nsPluginFrame::PaintPlugin(). We need to know this in
|
||||
// FixUpPluginWindow() (i.e. we need to know when FixUpPluginWindow() has
|
||||
@ -288,6 +294,11 @@ private:
|
||||
static nsCOMPtr<nsITimer> *sCATimer;
|
||||
static nsTArray<nsPluginInstanceOwner*> *sCARefreshListeners;
|
||||
bool mSentInitialTopLevelWindowEvent;
|
||||
bool mLastWindowIsActive;
|
||||
bool mLastContentFocused;
|
||||
double mLastScaleFactor;
|
||||
// True if, the next time the window is activated, we should blur ourselves.
|
||||
bool mShouldBlurOnActivate;
|
||||
#endif
|
||||
|
||||
// Initially, the event loop nesting level we were created on, it's updated
|
||||
@ -296,9 +307,6 @@ private:
|
||||
uint32_t mLastEventloopNestingLevel;
|
||||
bool mContentFocused;
|
||||
bool mWidgetVisible; // used on Mac to store our widget's visible state
|
||||
#ifdef XP_MACOSX
|
||||
bool mPluginPortChanged;
|
||||
#endif
|
||||
#ifdef MOZ_X11
|
||||
// Used with windowless plugins only, initialized in CreateWidget().
|
||||
bool mFlash10Quirks;
|
||||
@ -323,6 +331,16 @@ private:
|
||||
bool aAllowPropagate = false);
|
||||
nsresult DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent);
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
static NPBool ConvertPointPuppet(PuppetWidget *widget, nsPluginFrame* pluginFrame,
|
||||
double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
|
||||
double *destX, double *destY, NPCoordinateSpace destSpace);
|
||||
static NPBool ConvertPointNoPuppet(nsIWidget *widget, nsPluginFrame* pluginFrame,
|
||||
double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
|
||||
double *destX, double *destY, NPCoordinateSpace destSpace);
|
||||
void PerformDelayedBlurs();
|
||||
#endif // XP_MACOSX
|
||||
|
||||
int mLastMouseDownButtonType;
|
||||
|
||||
#ifdef MOZ_X11
|
||||
|
@ -388,12 +388,12 @@ PluginInstanceChild::NPN_GetValue(NPNVariable aVar,
|
||||
}
|
||||
|
||||
case NPNVsupportsCoreAnimationBool: {
|
||||
*((NPBool*)aValue) = nsCocoaFeatures::SupportCoreAnimationPlugins();
|
||||
*((NPBool*)aValue) = true;
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
case NPNVsupportsInvalidatingCoreAnimationBool: {
|
||||
*((NPBool*)aValue) = nsCocoaFeatures::SupportCoreAnimationPlugins();
|
||||
*((NPBool*)aValue) = true;
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
|
@ -220,26 +220,32 @@ NPError mozilla::plugins::PluginUtilsOSX::ShowCocoaContextMenu(void* aMenu, int
|
||||
// change to an arrow cursor automatically -- as it does in Chrome.
|
||||
[[NSCursor arrowCursor] set];
|
||||
|
||||
EventProcessor* eventProcessor = nullptr;
|
||||
NSTimer *eventTimer = nullptr;
|
||||
if (pluginModule) {
|
||||
// Create a timer to process browser events while waiting
|
||||
// on the menu. This prevents the browser from hanging
|
||||
// during the lifetime of the menu.
|
||||
EventProcessor* eventProcessor = [[EventProcessor alloc] init];
|
||||
eventProcessor = [[EventProcessor alloc] init];
|
||||
[eventProcessor setRemoteEvents:remoteEvent pluginModule:pluginModule];
|
||||
NSTimer *eventTimer = [NSTimer timerWithTimeInterval:EVENT_PROCESS_DELAY
|
||||
eventTimer = [NSTimer timerWithTimeInterval:EVENT_PROCESS_DELAY
|
||||
target:eventProcessor selector:@selector(onTick)
|
||||
userInfo:nil repeats:TRUE];
|
||||
// Use NSEventTrackingRunLoopMode otherwise the timer will
|
||||
// not fire during the right click menu.
|
||||
[[NSRunLoop currentRunLoop] addTimer:eventTimer
|
||||
forMode:NSEventTrackingRunLoopMode];
|
||||
}
|
||||
|
||||
NSMenu* nsmenu = reinterpret_cast<NSMenu*>(aMenu);
|
||||
NSPoint screen_point = ::NSMakePoint(aX, aY);
|
||||
|
||||
[nsmenu popUpMenuPositioningItem:nil atLocation:screen_point inView:nil];
|
||||
|
||||
if (pluginModule) {
|
||||
[eventTimer invalidate];
|
||||
[eventProcessor release];
|
||||
}
|
||||
|
||||
return NPERR_NO_ERROR;
|
||||
|
||||
|
@ -59,7 +59,7 @@
|
||||
utils.sendNativeMouseEvent(plugin1X, plugin1Y, NSLeftMouseUp, 0, plugin1);
|
||||
expectedEventCount++;
|
||||
|
||||
is(plugin1.getFocusState(), true, "Plugin should have focus.");
|
||||
is(plugin1.getFocusState(), true, "(1) Plugin should have focus.");
|
||||
is(plugin1.getFocusEventCount(), expectedEventCount, "Focus event count should be " + expectedEventCount);
|
||||
|
||||
// Make sure window activation state changes don't spontaneously
|
||||
@ -68,13 +68,13 @@
|
||||
// Blur the window.
|
||||
window.blur();
|
||||
|
||||
is(plugin1.getFocusState(), true, "Plugin should still have focus.");
|
||||
is(plugin1.getFocusState(), true, "(2) Plugin should still have focus.");
|
||||
is(plugin1.getFocusEventCount(), expectedEventCount, "Focus event count should be " + expectedEventCount);
|
||||
|
||||
// Focus the window.
|
||||
window.focus();
|
||||
|
||||
is(plugin1.getFocusState(), true, "Plugin should still have focus.");
|
||||
is(plugin1.getFocusState(), true, "(3) Plugin should still have focus.");
|
||||
is(plugin1.getFocusEventCount(), expectedEventCount, "Focus event count should be " + expectedEventCount);
|
||||
|
||||
// Take focus from the plugin.
|
||||
@ -82,7 +82,7 @@
|
||||
utils.sendNativeMouseEvent(plugin2X, plugin2Y, NSLeftMouseUp, 0, plugin2);
|
||||
expectedEventCount++;
|
||||
|
||||
is(plugin1.getFocusState(), false, "Plugin should not have focus.");
|
||||
is(plugin1.getFocusState(), false, "(4) Plugin should not have focus.");
|
||||
is(plugin1.getFocusEventCount(), expectedEventCount, "Focus event count should be " + expectedEventCount);
|
||||
|
||||
// Make sure window activation causes the plugin to be informed of focus
|
||||
@ -99,14 +99,14 @@
|
||||
// Take focus from the plugin while the window is blurred.
|
||||
plugin2.focus();
|
||||
|
||||
is(plugin1.getFocusState(), true, "Plugin should still have focus.");
|
||||
is(plugin1.getFocusState(), true, "(5) Plugin should still have focus.");
|
||||
is(plugin1.getFocusEventCount(), expectedEventCount, "Focus event count should be " + expectedEventCount);
|
||||
|
||||
// Focus the window.
|
||||
window.focus();
|
||||
expectedEventCount++;
|
||||
|
||||
is(plugin1.getFocusState(), false, "Plugin should not have focus.");
|
||||
is(plugin1.getFocusState(), false, "(6) Plugin should not have focus.");
|
||||
is(plugin1.getFocusEventCount(), expectedEventCount, "Focus event count should be " + expectedEventCount);
|
||||
|
||||
window.opener.testsFinished();
|
||||
|
@ -29,11 +29,10 @@ function runTests() {
|
||||
|
||||
var domWindowUtils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
var devPxPerCSSPx = domWindowUtils.screenPixelsPerCSSPixel;
|
||||
|
||||
var pluginRect = pluginElement.getBoundingClientRect();
|
||||
var pluginX = (pluginRect.left * devPxPerCSSPx) + ((window.mozInnerScreenX * devPxPerCSSPx) - window.screenX);
|
||||
var pluginY = (pluginRect.top * devPxPerCSSPx) + ((window.mozInnerScreenY * devPxPerCSSPx) - window.screenY);
|
||||
var pluginX = pluginRect.left + (window.mozInnerScreenX - window.screenX);
|
||||
var pluginY = pluginRect.top + (window.mozInnerScreenY - window.screenY);
|
||||
|
||||
var windowX = window.screenX;
|
||||
var windowY = window.screenY;
|
||||
|
@ -3394,7 +3394,7 @@ getTopLevelWindowActivationEventCount(NPObject* npobj, const NPVariant* args, ui
|
||||
}
|
||||
|
||||
// Returns top-level window activation state as indicated by Cocoa NPAPI's
|
||||
// NPCocoaEventWindowFocusChanged events - 'true' if active, 'false' if not.
|
||||
// NPCocoaEventFocusChanged events - 'true' if active, 'false' if not.
|
||||
// Throws an exception if no events have been received and thus this state
|
||||
// is unknown.
|
||||
bool
|
||||
|
@ -238,6 +238,7 @@ pluginHandleEvent(InstanceData* instanceData, void* event)
|
||||
case NPCocoaEventMouseDown:
|
||||
case NPCocoaEventMouseUp:
|
||||
case NPCocoaEventMouseMoved:
|
||||
case NPCocoaEventMouseDragged:
|
||||
instanceData->lastMouseX = (int32_t)cocoaEvent->data.mouse.pluginX;
|
||||
instanceData->lastMouseY = (int32_t)cocoaEvent->data.mouse.pluginY;
|
||||
if (cocoaEvent->type == NPCocoaEventMouseUp) {
|
||||
|
@ -2931,6 +2931,8 @@ nsRootPresContext::CancelApplyPluginGeometryTimer()
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef XP_MACOSX
|
||||
|
||||
static bool
|
||||
HasOverlap(const nsIntPoint& aOffset1, const nsTArray<nsIntRect>& aClipRects1,
|
||||
const nsIntPoint& aOffset2, const nsTArray<nsIntRect>& aClipRects2)
|
||||
@ -2999,18 +3001,6 @@ SortConfigurations(nsTArray<nsIWidget::Configuration>* aConfigurations)
|
||||
}
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
PluginDidSetGeometryEnumerator(nsRefPtrHashKey<nsIContent>* aEntry, void* userArg)
|
||||
{
|
||||
nsPluginFrame* f = static_cast<nsPluginFrame*>(aEntry->GetKey()->GetPrimaryFrame());
|
||||
if (!f) {
|
||||
NS_WARNING("Null frame in PluginDidSetGeometryEnumerator");
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
f->DidSetWidgetGeometry();
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
struct PluginGetGeometryUpdateClosure {
|
||||
nsTArray<nsIWidget::Configuration> mConfigurations;
|
||||
};
|
||||
@ -3028,9 +3018,24 @@ PluginGetGeometryUpdate(nsRefPtrHashKey<nsIContent>* aEntry, void* userArg)
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
#endif // #ifndef XP_MACOSX
|
||||
|
||||
static PLDHashOperator
|
||||
PluginDidSetGeometryEnumerator(nsRefPtrHashKey<nsIContent>* aEntry, void* userArg)
|
||||
{
|
||||
nsPluginFrame* f = static_cast<nsPluginFrame*>(aEntry->GetKey()->GetPrimaryFrame());
|
||||
if (!f) {
|
||||
NS_WARNING("Null frame in PluginDidSetGeometryEnumerator");
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
f->DidSetWidgetGeometry();
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
nsRootPresContext::ApplyPluginGeometryUpdates()
|
||||
{
|
||||
#ifndef XP_MACOSX
|
||||
CancelApplyPluginGeometryTimer();
|
||||
|
||||
PluginGetGeometryUpdateClosure closure;
|
||||
@ -3042,6 +3047,8 @@ nsRootPresContext::ApplyPluginGeometryUpdates()
|
||||
SortConfigurations(&closure.mConfigurations);
|
||||
widget->ConfigureChildren(closure.mConfigurations);
|
||||
}
|
||||
#endif // #ifndef XP_MACOSX
|
||||
|
||||
mRegisteredPlugins.EnumerateEntries(PluginDidSetGeometryEnumerator, nullptr);
|
||||
}
|
||||
|
||||
|
@ -106,11 +106,6 @@ SOURCES += [
|
||||
'nsPluginFrame.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
||||
UNIFIED_SOURCES += [
|
||||
'nsPluginUtilsOSX.mm',
|
||||
]
|
||||
|
||||
FAIL_ON_WARNINGS = not CONFIG['_MSC_VER']
|
||||
|
||||
MSVC_ENABLE_PGO = True
|
||||
|
@ -69,7 +69,6 @@
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
#include "gfxQuartzNativeDrawing.h"
|
||||
#include "nsPluginUtilsOSX.h"
|
||||
#include "mozilla/gfx/QuartzSupport.h"
|
||||
#endif
|
||||
|
||||
@ -103,43 +102,6 @@ GetObjectFrameLog()
|
||||
}
|
||||
#endif /* PR_LOGGING */
|
||||
|
||||
#if defined(XP_MACOSX) && !defined(__LP64__)
|
||||
|
||||
// The header files QuickdrawAPI.h and QDOffscreen.h are missing on OS X 10.7
|
||||
// and up (though the QuickDraw APIs defined in them are still present) -- so
|
||||
// we need to supply the relevant parts of their contents here. It's likely
|
||||
// that Apple will eventually remove the APIs themselves (probably in OS X
|
||||
// 10.8), so we need to make them weak imports, and test for their presence
|
||||
// before using them.
|
||||
extern "C" {
|
||||
#if !defined(__QUICKDRAWAPI__)
|
||||
extern void SetRect(
|
||||
Rect * r,
|
||||
short left,
|
||||
short top,
|
||||
short right,
|
||||
short bottom)
|
||||
__attribute__((weak_import));
|
||||
#endif /* __QUICKDRAWAPI__ */
|
||||
|
||||
#if !defined(__QDOFFSCREEN__)
|
||||
extern QDErr NewGWorldFromPtr(
|
||||
GWorldPtr * offscreenGWorld,
|
||||
UInt32 PixelFormat,
|
||||
const Rect * boundsRect,
|
||||
CTabHandle cTable, /* can be nullptr */
|
||||
GDHandle aGDevice, /* can be nullptr */
|
||||
GWorldFlags flags,
|
||||
Ptr newBuffer,
|
||||
SInt32 rowBytes)
|
||||
__attribute__((weak_import));
|
||||
extern void DisposeGWorld(GWorldPtr offscreenGWorld)
|
||||
__attribute__((weak_import));
|
||||
#endif /* __QDOFFSCREEN__ */
|
||||
}
|
||||
|
||||
#endif /* #if defined(XP_MACOSX) && !defined(__LP64__) */
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::layers;
|
||||
@ -220,7 +182,7 @@ nsPluginFrame::AccessibleType()
|
||||
#ifdef XP_WIN
|
||||
NS_IMETHODIMP nsPluginFrame::GetPluginPort(HWND *aPort)
|
||||
{
|
||||
*aPort = (HWND) mInstanceOwner->GetPluginPortFromWidget();
|
||||
*aPort = (HWND) mInstanceOwner->GetPluginPort();
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
@ -388,10 +350,7 @@ nsPluginFrame::PrepForDrawing(nsIWidget *aWidget)
|
||||
} else {
|
||||
// Changing to windowless mode changes the NPWindow geometry.
|
||||
FixupWindow(GetContentRectRelativeToSelf().Size());
|
||||
|
||||
#ifndef XP_MACOSX
|
||||
RegisterPluginForGeometryUpdates();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!IsHidden()) {
|
||||
@ -577,14 +536,6 @@ nsPluginFrame::FixupWindow(const nsSize& aSize)
|
||||
|
||||
NS_ENSURE_TRUE_VOID(window);
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
nsWeakFrame weakFrame(this);
|
||||
mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintDisable);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool windowless = (window->type == NPWindowTypeDrawable);
|
||||
|
||||
nsIntPoint origin = GetWindowOriginInPixels(windowless);
|
||||
@ -600,15 +551,7 @@ nsPluginFrame::FixupWindow(const nsSize& aSize)
|
||||
window->width = presContext->AppUnitsToDevPixels(aSize.width) / intScaleFactor;
|
||||
window->height = presContext->AppUnitsToDevPixels(aSize.height) / intScaleFactor;
|
||||
|
||||
// on the Mac we need to set the clipRect to { 0, 0, 0, 0 } for now. This will keep
|
||||
// us from drawing on screen until the widget is properly positioned, which will not
|
||||
// happen until we have finished the reflow process.
|
||||
#ifdef XP_MACOSX
|
||||
window->clipRect.top = 0;
|
||||
window->clipRect.left = 0;
|
||||
window->clipRect.bottom = 0;
|
||||
window->clipRect.right = 0;
|
||||
#else
|
||||
#ifndef XP_MACOSX
|
||||
mInstanceOwner->UpdateWindowPositionAndClipRect(false);
|
||||
#endif
|
||||
|
||||
@ -630,19 +573,15 @@ nsPluginFrame::CallSetWindow(bool aCheckIsHidden)
|
||||
return rv;
|
||||
|
||||
nsPluginNativeWindow *window = (nsPluginNativeWindow *)win;
|
||||
#ifdef XP_MACOSX
|
||||
nsWeakFrame weakFrame(this);
|
||||
mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintDisable);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (aCheckIsHidden && IsHidden())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// refresh the plugin port as well
|
||||
window->window = mInstanceOwner->GetPluginPortFromWidget();
|
||||
#ifdef XP_MACOSX
|
||||
mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintEnable);
|
||||
#endif
|
||||
window->window = mInstanceOwner->GetPluginPort();
|
||||
|
||||
// Adjust plugin dimensions according to pixel snap results
|
||||
// and reduce amount of SetWindow calls
|
||||
@ -1064,11 +1003,7 @@ nsPluginFrame::NotifyPluginReflowObservers()
|
||||
void
|
||||
nsPluginFrame::DidSetWidgetGeometry()
|
||||
{
|
||||
#if defined(XP_MACOSX)
|
||||
if (mInstanceOwner) {
|
||||
mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintEnable);
|
||||
}
|
||||
#else
|
||||
#ifndef XP_MACOSX
|
||||
if (!mWidget && mInstanceOwner) {
|
||||
// UpdateWindowVisibility will notify the plugin of position changes
|
||||
// by updating the NPWindow and calling NPP_SetWindow/AsyncSetWindow.
|
||||
@ -1079,6 +1014,8 @@ nsPluginFrame::DidSetWidgetGeometry()
|
||||
nsLayoutUtils::IsPopup(nsLayoutUtils::GetDisplayRootFrame(this)) ||
|
||||
!mNextConfigurationBounds.IsEmpty());
|
||||
}
|
||||
#else
|
||||
CallSetWindow(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1086,7 +1023,6 @@ bool
|
||||
nsPluginFrame::IsOpaque() const
|
||||
{
|
||||
#if defined(XP_MACOSX)
|
||||
// ???
|
||||
return false;
|
||||
#elif defined(MOZ_WIDGET_ANDROID)
|
||||
// We don't know, so just assume transparent
|
||||
@ -1100,7 +1036,6 @@ bool
|
||||
nsPluginFrame::IsTransparentMode() const
|
||||
{
|
||||
#if defined(XP_MACOSX)
|
||||
// ???
|
||||
return false;
|
||||
#else
|
||||
if (!mInstanceOwner)
|
||||
@ -1153,7 +1088,12 @@ nsPluginFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
}
|
||||
#endif
|
||||
|
||||
if (aBuilder->IsForPainting() && mInstanceOwner && mInstanceOwner->UseAsyncRendering()) {
|
||||
if (aBuilder->IsForPainting() && mInstanceOwner) {
|
||||
#ifdef XP_MACOSX
|
||||
mInstanceOwner->ResolutionMayHaveChanged();
|
||||
mInstanceOwner->WindowFocusMayHaveChanged();
|
||||
#endif
|
||||
if (mInstanceOwner->UseAsyncRendering()) {
|
||||
NPWindow* window = nullptr;
|
||||
mInstanceOwner->GetWindow(window);
|
||||
bool isVisible = window && window->width > 0 && window->height > 0;
|
||||
@ -1165,6 +1105,7 @@ nsPluginFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
|
||||
mInstanceOwner->NotifyPaintWaiter(aBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox
|
||||
clip(aBuilder, this);
|
||||
@ -1253,117 +1194,10 @@ nsPluginFrame::PrintPlugin(nsRenderingContext& aRenderingContext,
|
||||
window.clipRect.left = 0; window.clipRect.right = 0;
|
||||
|
||||
// platform specific printing code
|
||||
#if defined(XP_MACOSX) && !defined(__LP64__)
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
DrawTarget& aDrawTarget = *aRenderingContext.GetDrawTarget();
|
||||
|
||||
// Don't use this code if any of the QuickDraw APIs it currently requires
|
||||
// are missing (as they probably will be on OS X 10.8 and up).
|
||||
if (!&::SetRect || !&::NewGWorldFromPtr || !&::DisposeGWorld) {
|
||||
NS_WARNING("Cannot print plugin -- required QuickDraw APIs are missing!");
|
||||
return;
|
||||
}
|
||||
|
||||
nsSize contentSize = GetContentRectRelativeToSelf().Size();
|
||||
window.x = 0;
|
||||
window.y = 0;
|
||||
window.width = presContext->AppUnitsToDevPixels(contentSize.width);
|
||||
window.height = presContext->AppUnitsToDevPixels(contentSize.height);
|
||||
|
||||
gfxContext *ctx = aRenderingContext.ThebesContext();
|
||||
if (!ctx)
|
||||
return;
|
||||
gfxContextAutoSaveRestore save(ctx);
|
||||
|
||||
ctx->NewPath();
|
||||
|
||||
gfx::Rect rect(window.x, window.y, window.width, window.height);
|
||||
|
||||
ctx->Rectangle(ThebesRect(rect));
|
||||
ctx->Clip();
|
||||
|
||||
gfxQuartzNativeDrawing nativeDraw(aDrawTarget, rect);
|
||||
CGContextRef cgContext = nativeDraw.BeginNativeDrawing();
|
||||
if (!cgContext) {
|
||||
nativeDraw.EndNativeDrawing();
|
||||
return;
|
||||
}
|
||||
|
||||
window.clipRect.right = window.width;
|
||||
window.clipRect.bottom = window.height;
|
||||
window.type = NPWindowTypeDrawable;
|
||||
|
||||
::Rect gwBounds;
|
||||
::SetRect(&gwBounds, 0, 0, window.width, window.height);
|
||||
|
||||
nsTArray<char> buffer(window.width * window.height * 4);
|
||||
CGColorSpaceRef cspace = ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
|
||||
if (!cspace) {
|
||||
nativeDraw.EndNativeDrawing();
|
||||
return;
|
||||
}
|
||||
CGContextRef cgBuffer =
|
||||
::CGBitmapContextCreate(buffer.Elements(),
|
||||
window.width, window.height, 8, window.width * 4,
|
||||
cspace, kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedFirst);
|
||||
::CGColorSpaceRelease(cspace);
|
||||
if (!cgBuffer) {
|
||||
nativeDraw.EndNativeDrawing();
|
||||
return;
|
||||
}
|
||||
GWorldPtr gWorld;
|
||||
if (::NewGWorldFromPtr(&gWorld, k32ARGBPixelFormat, &gwBounds,
|
||||
nullptr, nullptr, 0,
|
||||
buffer.Elements(), window.width * 4) != noErr) {
|
||||
::CGContextRelease(cgBuffer);
|
||||
nativeDraw.EndNativeDrawing();
|
||||
return;
|
||||
}
|
||||
|
||||
window.clipRect.right = window.width;
|
||||
window.clipRect.bottom = window.height;
|
||||
window.type = NPWindowTypeDrawable;
|
||||
// Setting nsPluginPrint/NPPrint.print.embedPrint.window.window to
|
||||
// &GWorldPtr and nsPluginPrint/NPPrint.print.embedPrint.platformPrint to
|
||||
// GWorldPtr isn't any kind of standard (it's not documented anywhere).
|
||||
// But that's what WebKit does. And it's what the Flash plugin (apparently
|
||||
// the only NPAPI plugin on OS X to support printing) seems to expect. So
|
||||
// we do the same. The Flash plugin uses the CoreGraphics drawing mode.
|
||||
// But a GWorldPtr should be usable in either CoreGraphics or QuickDraw
|
||||
// drawing mode. See bug 191046.
|
||||
window.window = &gWorld;
|
||||
npprint.print.embedPrint.platformPrint = gWorld;
|
||||
npprint.print.embedPrint.window = window;
|
||||
pi->Print(&npprint);
|
||||
|
||||
::CGContextTranslateCTM(cgContext, 0.0f, float(window.height));
|
||||
::CGContextScaleCTM(cgContext, 1.0f, -1.0f);
|
||||
CGImageRef image = ::CGBitmapContextCreateImage(cgBuffer);
|
||||
if (!image) {
|
||||
::CGContextRestoreGState(cgContext);
|
||||
::CGContextRelease(cgBuffer);
|
||||
::DisposeGWorld(gWorld);
|
||||
nativeDraw.EndNativeDrawing();
|
||||
return;
|
||||
}
|
||||
::CGContextDrawImage(cgContext,
|
||||
::CGRectMake(0, 0, window.width, window.height),
|
||||
image);
|
||||
::CGImageRelease(image);
|
||||
::CGContextRelease(cgBuffer);
|
||||
|
||||
::DisposeGWorld(gWorld);
|
||||
|
||||
nativeDraw.EndNativeDrawing();
|
||||
#pragma clang diagnostic warning "-Wdeprecated-declarations"
|
||||
#elif defined(XP_UNIX)
|
||||
|
||||
/* XXX this just flat-out doesn't work in a thebes world --
|
||||
* RenderEPS is a no-op. So don't bother to do any work here.
|
||||
*/
|
||||
#if defined(XP_UNIX) || defined(XP_MACOSX)
|
||||
// Doesn't work in a thebes world, or on OS X.
|
||||
(void)window;
|
||||
(void)npprint;
|
||||
|
||||
#elif defined(XP_WIN)
|
||||
|
||||
/* On Windows, we use the win32 printing surface to print. This, in
|
||||
@ -1861,15 +1695,6 @@ nsPluginFrame::HandleEvent(nsPresContext* aPresContext,
|
||||
return fm->FocusPlugin(GetContent());
|
||||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
if (anEvent->message == NS_PLUGIN_RESOLUTION_CHANGED) {
|
||||
double scaleFactor = 1.0;
|
||||
mInstanceOwner->GetContentsScaleFactor(&scaleFactor);
|
||||
mInstanceOwner->ContentsScaleFactorChanged(scaleFactor);
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mInstanceOwner->SendNativeEvents() &&
|
||||
anEvent->IsNativeEventDelivererForPlugin()) {
|
||||
*anEventStatus = mInstanceOwner->ProcessEvent(*anEvent);
|
||||
@ -2034,14 +1859,8 @@ nsPluginFrame::EndSwapDocShells(nsISupports* aSupports, void*)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
if (objectFrame->mWidget) {
|
||||
objectFrame->RegisterPluginForGeometryUpdates();
|
||||
}
|
||||
#else
|
||||
objectFrame->RegisterPluginForGeometryUpdates();
|
||||
#endif
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
NS_NewObjectFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
|
||||
|
@ -138,6 +138,11 @@ public:
|
||||
configuration->mClipRegion = mNextConfigurationClipRegion;
|
||||
}
|
||||
}
|
||||
|
||||
nsIntRect GetWidgetlessClipRect() {
|
||||
return RegionFromArray(mNextConfigurationClipRegion).GetBounds();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after all widget position/size/clip regions have been changed
|
||||
* (even if there isn't a widget for this plugin).
|
||||
@ -258,6 +263,15 @@ private:
|
||||
// stored in mRootPresContextRegisteredWith.
|
||||
void UnregisterPluginForGeometryUpdates();
|
||||
|
||||
static const nsIntRegion RegionFromArray(const nsTArray<nsIntRect>& aRects)
|
||||
{
|
||||
nsIntRegion region;
|
||||
for (uint32_t i = 0; i < aRects.Length(); ++i) {
|
||||
region.Or(region, aRects[i]);
|
||||
}
|
||||
return region;
|
||||
}
|
||||
|
||||
class PluginEventNotifier : public nsRunnable {
|
||||
public:
|
||||
explicit PluginEventNotifier(const nsString &aEventType) :
|
||||
|
@ -1,37 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
// vim:set ts=2 sts=2 sw=2 et cin:
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// We can use Carbon in this header but not Cocoa. Cocoa pointers must be void.
|
||||
|
||||
#ifndef __LP64__
|
||||
#import <Carbon/Carbon.h>
|
||||
#endif
|
||||
|
||||
#include "nsIWidget.h"
|
||||
#include "npapi.h"
|
||||
|
||||
struct nsRect;
|
||||
|
||||
// We use void pointers to avoid exporting native event types to cross-platform code.
|
||||
|
||||
#ifndef __LP64__
|
||||
// Get the rect for an entire top-level Carbon window in screen coords.
|
||||
void NS_NPAPI_CarbonWindowFrame(WindowRef aWindow, nsRect& outRect);
|
||||
#endif
|
||||
|
||||
// Get the rect for an entire top-level Cocoa window in screen coords.
|
||||
void NS_NPAPI_CocoaWindowFrame(void* aWindow, nsRect& outRect);
|
||||
|
||||
// Returns whether or not a Cocoa NSWindow has main status.
|
||||
bool NS_NPAPI_CocoaWindowIsMain(void* aWindow);
|
||||
|
||||
// Puts up a Cocoa context menu (NSMenu) for a particular NPCocoaEvent.
|
||||
NPError NS_NPAPI_ShowCocoaContextMenu(void* menu, nsIWidget* widget, NPCocoaEvent* event);
|
||||
|
||||
NPBool NS_NPAPI_ConvertPointCocoa(void* inView,
|
||||
double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
|
||||
double *destX, double *destY, NPCoordinateSpace destSpace);
|
||||
|
@ -1,207 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
// vim:set ts=2 sts=2 sw=2 et cin:
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsPluginUtilsOSX.h"
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
#include "nsObjCExceptions.h"
|
||||
|
||||
#ifndef __LP64__
|
||||
void NS_NPAPI_CarbonWindowFrame(WindowRef aWindow, nsRect& outRect)
|
||||
{
|
||||
if (!aWindow)
|
||||
return;
|
||||
|
||||
Rect windowRect;
|
||||
::GetWindowBounds(aWindow, kWindowStructureRgn, &windowRect);
|
||||
outRect.x = windowRect.left;
|
||||
outRect.y = windowRect.top;
|
||||
outRect.width = windowRect.right - windowRect.left;
|
||||
outRect.height = windowRect.bottom - windowRect.top;
|
||||
}
|
||||
#endif
|
||||
|
||||
void NS_NPAPI_CocoaWindowFrame(void* aWindow, nsRect& outRect)
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
if (!aWindow)
|
||||
return;
|
||||
|
||||
NSWindow* window = (NSWindow*)aWindow;
|
||||
|
||||
float menubarScreenHeight;
|
||||
NSArray* allScreens = [NSScreen screens];
|
||||
if ([allScreens count])
|
||||
menubarScreenHeight = [[allScreens objectAtIndex:0] frame].size.height;
|
||||
else
|
||||
return; // If there are no screens, there's not much we can say.
|
||||
|
||||
NSRect frame = [window frame];
|
||||
outRect.x = (nscoord)frame.origin.x;
|
||||
outRect.y = (nscoord)(menubarScreenHeight - (frame.origin.y + frame.size.height));
|
||||
outRect.width = (nscoord)frame.size.width;
|
||||
outRect.height = (nscoord)frame.size.height;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
bool NS_NPAPI_CocoaWindowIsMain(void* aWindow)
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
||||
|
||||
if (!aWindow)
|
||||
return true;
|
||||
|
||||
NSWindow* window = (NSWindow*)aWindow;
|
||||
|
||||
return (bool)[window isMainWindow];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(true);
|
||||
}
|
||||
|
||||
NPError NS_NPAPI_ShowCocoaContextMenu(void* menu, nsIWidget* widget, NPCocoaEvent* event)
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
||||
|
||||
if (!menu || !widget || !event)
|
||||
return NPERR_GENERIC_ERROR;
|
||||
|
||||
NSMenu* cocoaMenu = (NSMenu*)menu;
|
||||
NSView* cocoaView = (NSView*)widget->GetNativeData(NS_NATIVE_WIDGET);
|
||||
|
||||
NSEventType cocoaEventType = NSRightMouseDown;
|
||||
unsigned int cocoaModifierFlags = 0;
|
||||
double x = 0.0; // Coordinates for the context menu in plugin terms, top-left origin.
|
||||
double y = 0.0;
|
||||
|
||||
NPCocoaEventType eventType = event->type;
|
||||
if (eventType == NPCocoaEventMouseDown ||
|
||||
eventType == NPCocoaEventMouseUp ||
|
||||
eventType == NPCocoaEventMouseMoved ||
|
||||
eventType == NPCocoaEventMouseEntered ||
|
||||
eventType == NPCocoaEventMouseExited ||
|
||||
eventType == NPCocoaEventMouseDragged) {
|
||||
x = event->data.mouse.pluginX;
|
||||
y = event->data.mouse.pluginY;
|
||||
if ((x < 0.0) || (y < 0.0))
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
// Flip the coords to bottom-left origin.
|
||||
NSRect viewFrame = [cocoaView frame];
|
||||
double shiftedX = x;
|
||||
double shiftedY = viewFrame.size.height - y;
|
||||
// Shift to window coords.
|
||||
shiftedX += viewFrame.origin.x;
|
||||
shiftedY += [cocoaView convertPoint:NSMakePoint(0,0) toView:nil].y - viewFrame.size.height;
|
||||
|
||||
// Create an NSEvent we can use to show the context menu. Only the location
|
||||
// is important here so just simulate a right mouse down. The coordinates
|
||||
// must be in top-level window terms.
|
||||
NSEvent* cocoaEvent = [NSEvent mouseEventWithType:cocoaEventType
|
||||
location:NSMakePoint(shiftedX, shiftedY)
|
||||
modifierFlags:cocoaModifierFlags
|
||||
timestamp:0
|
||||
windowNumber:[[cocoaView window] windowNumber]
|
||||
context:nil
|
||||
eventNumber:0
|
||||
clickCount:1
|
||||
pressure:0.0];
|
||||
|
||||
[NSMenu popUpContextMenu:cocoaMenu withEvent:cocoaEvent forView:cocoaView];
|
||||
|
||||
return NPERR_NO_ERROR;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NPERR_GENERIC_ERROR);
|
||||
}
|
||||
|
||||
NPBool NS_NPAPI_ConvertPointCocoa(void* inView,
|
||||
double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
|
||||
double *destX, double *destY, NPCoordinateSpace destSpace)
|
||||
{
|
||||
// Plugins don't always have a view/frame. It would be odd to ask for a point conversion
|
||||
// without a view, so we'll warn about it, but it's technically OK.
|
||||
if (!inView) {
|
||||
NS_WARNING("Must have a native view to convert coordinates.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Caller has to want a result.
|
||||
if (!destX && !destY)
|
||||
return false;
|
||||
|
||||
if (sourceSpace == destSpace) {
|
||||
if (destX)
|
||||
*destX = sourceX;
|
||||
if (destY)
|
||||
*destY = sourceY;
|
||||
return true;
|
||||
}
|
||||
|
||||
NSView* view = (NSView*)inView;
|
||||
NSWindow* window = [view window];
|
||||
NSPoint sourcePoint = NSMakePoint(sourceX, sourceY);
|
||||
|
||||
// Convert to screen space.
|
||||
NSPoint screenPoint;
|
||||
switch (sourceSpace) {
|
||||
case NPCoordinateSpacePlugin:
|
||||
screenPoint = [view convertPoint:sourcePoint toView:nil];
|
||||
screenPoint = [window convertBaseToScreen:screenPoint];
|
||||
break;
|
||||
case NPCoordinateSpaceWindow:
|
||||
screenPoint = [window convertBaseToScreen:sourcePoint];
|
||||
break;
|
||||
case NPCoordinateSpaceFlippedWindow:
|
||||
sourcePoint.y = [window frame].size.height - sourcePoint.y;
|
||||
screenPoint = [window convertBaseToScreen:sourcePoint];
|
||||
break;
|
||||
case NPCoordinateSpaceScreen:
|
||||
screenPoint = sourcePoint;
|
||||
break;
|
||||
case NPCoordinateSpaceFlippedScreen:
|
||||
sourcePoint.y = [[[NSScreen screens] objectAtIndex:0] frame].size.height - sourcePoint.y;
|
||||
screenPoint = sourcePoint;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// Convert from screen to dest space.
|
||||
NSPoint destPoint;
|
||||
switch (destSpace) {
|
||||
case NPCoordinateSpacePlugin:
|
||||
destPoint = [window convertScreenToBase:screenPoint];
|
||||
destPoint = [view convertPoint:destPoint fromView:nil];
|
||||
break;
|
||||
case NPCoordinateSpaceWindow:
|
||||
destPoint = [window convertScreenToBase:screenPoint];
|
||||
break;
|
||||
case NPCoordinateSpaceFlippedWindow:
|
||||
destPoint = [window convertScreenToBase:screenPoint];
|
||||
destPoint.y = [window frame].size.height - destPoint.y;
|
||||
break;
|
||||
case NPCoordinateSpaceScreen:
|
||||
destPoint = screenPoint;
|
||||
break;
|
||||
case NPCoordinateSpaceFlippedScreen:
|
||||
destPoint = screenPoint;
|
||||
destPoint.y = [[[NSScreen screens] objectAtIndex:0] frame].size.height - destPoint.y;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (destX)
|
||||
*destX = destPoint.x;
|
||||
if (destY)
|
||||
*destY = destPoint.y;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1259,3 +1259,24 @@ nsSubDocumentFrame::ObtainIntrinsicSizeFrame()
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsIntPoint
|
||||
nsSubDocumentFrame::GetChromeDisplacement()
|
||||
{
|
||||
nsIFrame* nextFrame = nsLayoutUtils::GetCrossDocParentFrame(this);
|
||||
if (!nextFrame) {
|
||||
NS_WARNING("Couldn't find window chrome to calculate displacement to.");
|
||||
return nsIntPoint();
|
||||
}
|
||||
|
||||
nsIFrame* rootFrame = nextFrame;
|
||||
while (nextFrame) {
|
||||
rootFrame = nextFrame;
|
||||
nextFrame = nsLayoutUtils::GetCrossDocParentFrame(rootFrame);
|
||||
}
|
||||
|
||||
nsPoint offset = GetOffsetToCrossDoc(rootFrame);
|
||||
int32_t appUnitsPerDevPixel = rootFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
return nsIntPoint((int)(offset.x/appUnitsPerDevPixel),
|
||||
(int)(offset.y/appUnitsPerDevPixel));
|
||||
}
|
||||
|
@ -127,6 +127,8 @@ public:
|
||||
*/
|
||||
bool PassPointerEventsToChildren();
|
||||
|
||||
nsIntPoint GetChromeDisplacement();
|
||||
|
||||
protected:
|
||||
friend class AsyncFrameInit;
|
||||
|
||||
|
@ -755,8 +755,7 @@ nsViewManager::DispatchEvent(WidgetGUIEvent *aEvent,
|
||||
(dispatchUsingCoordinates || aEvent->HasKeyEventMessage() ||
|
||||
aEvent->IsIMERelatedEvent() ||
|
||||
aEvent->IsNonRetargetedNativeEventDelivererForPlugin() ||
|
||||
aEvent->HasPluginActivationEventMessage() ||
|
||||
aEvent->message == NS_PLUGIN_RESOLUTION_CHANGED)) {
|
||||
aEvent->HasPluginActivationEventMessage())) {
|
||||
while (view && !view->GetFrame()) {
|
||||
view = view->GetParent();
|
||||
}
|
||||
|
@ -65,11 +65,6 @@
|
||||
#define NS_MOZ_USER_IDLE (NS_WINDOW_START + 67)
|
||||
#define NS_MOZ_USER_ACTIVE (NS_WINDOW_START + 68)
|
||||
|
||||
// The resolution at which a plugin should draw has changed, for
|
||||
// example as the result of changing from a HiDPI mode to a non-
|
||||
// HiDPI mode.
|
||||
#define NS_PLUGIN_RESOLUTION_CHANGED (NS_WINDOW_START + 69)
|
||||
|
||||
#define NS_LANGUAGECHANGE (NS_WINDOW_START + 70)
|
||||
|
||||
#define NS_MOUSE_MESSAGE_START 300
|
||||
|
@ -830,6 +830,28 @@ PuppetWidget::GetNativeData(uint32_t aDataType)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsIntPoint
|
||||
PuppetWidget::GetChromeDimensions()
|
||||
{
|
||||
if (!GetOwningTabChild()) {
|
||||
NS_WARNING("PuppetWidget without Tab does not have chrome information.");
|
||||
return nsIntPoint();
|
||||
}
|
||||
return GetOwningTabChild()->GetChromeDisplacement();
|
||||
}
|
||||
|
||||
nsIntPoint
|
||||
PuppetWidget::GetWindowPosition()
|
||||
{
|
||||
if (!GetOwningTabChild()) {
|
||||
return nsIntPoint();
|
||||
}
|
||||
|
||||
int32_t winX, winY, winW, winH;
|
||||
NS_ENSURE_SUCCESS(GetOwningTabChild()->GetDimensions(0, &winX, &winY, &winW, &winH), nsIntPoint());
|
||||
return nsIntPoint(winX, winY);
|
||||
}
|
||||
|
||||
PuppetScreen::PuppetScreen(void *nativeScreen)
|
||||
{
|
||||
}
|
||||
@ -846,6 +868,13 @@ ScreenConfig()
|
||||
return config;
|
||||
}
|
||||
|
||||
nsIntSize
|
||||
PuppetWidget::GetScreenDimensions()
|
||||
{
|
||||
nsIntRect r = ScreenConfig().rect();
|
||||
return nsIntSize(r.width, r.height);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PuppetScreen::GetId(uint32_t *outId)
|
||||
{
|
||||
|
@ -193,6 +193,14 @@ public:
|
||||
mDefaultScale = -1;
|
||||
}
|
||||
|
||||
nsIntSize GetScreenDimensions();
|
||||
|
||||
// Get the size of the chrome of the window that this tab belongs to.
|
||||
nsIntPoint GetChromeDimensions();
|
||||
|
||||
// Get the screen position of the application window.
|
||||
nsIntPoint GetWindowPosition();
|
||||
|
||||
protected:
|
||||
bool mEnabled;
|
||||
bool mVisible;
|
||||
|
@ -97,6 +97,10 @@ public:
|
||||
, mCodeNameIndex(CODE_NAME_INDEX_UNKNOWN)
|
||||
, mNativeKeyEvent(nullptr)
|
||||
, mUniqueId(0)
|
||||
#ifdef XP_MACOSX
|
||||
, mNativeKeyCode(0)
|
||||
, mNativeModifierFlags(0)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
@ -151,6 +155,14 @@ public:
|
||||
// over long periods.
|
||||
uint32_t mUniqueId;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
// Values given by a native NSEvent, for use with Cocoa NPAPI plugins.
|
||||
uint16_t mNativeKeyCode;
|
||||
uint32_t mNativeModifierFlags;
|
||||
nsString mNativeCharacters;
|
||||
nsString mNativeCharactersIgnoringModifiers;
|
||||
#endif
|
||||
|
||||
void GetDOMKeyName(nsAString& aKeyName)
|
||||
{
|
||||
if (mKeyNameIndex == KEY_NAME_INDEX_USE_STRING) {
|
||||
|
@ -191,8 +191,7 @@ WidgetEvent::IsUsingCoordinates() const
|
||||
return !HasKeyEventMessage() && !IsIMERelatedEvent() &&
|
||||
!HasPluginActivationEventMessage() &&
|
||||
!IsNativeEventDelivererForPlugin() &&
|
||||
!IsContentCommandEvent() &&
|
||||
message != NS_PLUGIN_RESOLUTION_CHANGED;
|
||||
!IsContentCommandEvent();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -28,23 +28,19 @@
|
||||
#ifndef ComplexTextInputPanel_h_
|
||||
#define ComplexTextInputPanel_h_
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#include "nsString.h"
|
||||
#include "npapi.h"
|
||||
|
||||
@interface ComplexTextInputPanel : NSPanel {
|
||||
NSTextView *mInputTextView;
|
||||
}
|
||||
class ComplexTextInputPanel
|
||||
{
|
||||
public:
|
||||
static ComplexTextInputPanel* GetSharedComplexTextInputPanel();
|
||||
virtual void PlacePanel(int32_t x, int32_t y) = 0; // Bottom left coordinate of plugin in screen coords
|
||||
virtual void InterpretKeyEvent(NPCocoaEvent* aEvent, nsAString& aOutText) = 0;
|
||||
virtual bool IsInComposition() = 0;
|
||||
|
||||
+ (ComplexTextInputPanel*)sharedComplexTextInputPanel;
|
||||
|
||||
- (NSTextInputContext*)inputContext;
|
||||
- (BOOL)interpretKeyEvent:(NSEvent*)event string:(NSString**)string;
|
||||
- (void)cancelComposition;
|
||||
- (BOOL)inComposition;
|
||||
|
||||
// This places the text input panel fully onscreen and below the lower left
|
||||
// corner of the focused plugin.
|
||||
- (void)adjustTo:(NSView*)view;
|
||||
|
||||
@end
|
||||
protected:
|
||||
virtual ~ComplexTextInputPanel() {};
|
||||
};
|
||||
|
||||
#endif // ComplexTextInputPanel_h_
|
||||
|
@ -27,6 +27,8 @@
|
||||
|
||||
#import "ComplexTextInputPanel.h"
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsChildView.h"
|
||||
@ -34,16 +36,35 @@
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
extern "C" OSStatus TSMProcessRawKeyEvent(EventRef anEvent);
|
||||
|
||||
#define kInputWindowHeight 20
|
||||
|
||||
@implementation ComplexTextInputPanel
|
||||
@interface ComplexTextInputPanelImpl : NSPanel {
|
||||
NSTextView *mInputTextView;
|
||||
}
|
||||
|
||||
+ (ComplexTextInputPanel*)sharedComplexTextInputPanel
|
||||
+ (ComplexTextInputPanelImpl*)sharedComplexTextInputPanelImpl;
|
||||
|
||||
- (NSTextInputContext*)inputContext;
|
||||
- (void)interpretKeyEvent:(NSEvent*)event string:(NSString**)string;
|
||||
- (void)cancelComposition;
|
||||
- (BOOL)inComposition;
|
||||
|
||||
// This places the text input panel fully onscreen and below the lower left
|
||||
// corner of the focused plugin.
|
||||
- (void)adjustTo:(NSPoint)point;
|
||||
|
||||
@end
|
||||
|
||||
@implementation ComplexTextInputPanelImpl
|
||||
|
||||
+ (ComplexTextInputPanelImpl*)sharedComplexTextInputPanelImpl
|
||||
{
|
||||
static ComplexTextInputPanel *sComplexTextInputPanel;
|
||||
if (!sComplexTextInputPanel)
|
||||
sComplexTextInputPanel = [[ComplexTextInputPanel alloc] init];
|
||||
return sComplexTextInputPanel;
|
||||
static ComplexTextInputPanelImpl *sComplexTextInputPanelImpl;
|
||||
if (!sComplexTextInputPanelImpl)
|
||||
sComplexTextInputPanelImpl = [[ComplexTextInputPanelImpl alloc] init];
|
||||
return sComplexTextInputPanelImpl;
|
||||
}
|
||||
|
||||
- (id)init
|
||||
@ -107,31 +128,45 @@ using namespace mozilla;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)interpretKeyEvent:(NSEvent*)event string:(NSString**)string
|
||||
- (void)interpretKeyEvent:(NSEvent*)event string:(NSString**)string
|
||||
{
|
||||
BOOL hadMarkedText = [mInputTextView hasMarkedText];
|
||||
|
||||
*string = nil;
|
||||
|
||||
if (![[mInputTextView inputContext] handleEvent:event])
|
||||
return NO;
|
||||
if (!nsCocoaFeatures::OnMountainLionOrLater()) {
|
||||
// This "works" on OS X 10.7 and below, but at the cost of breaking plugin
|
||||
// IME, even in non-e10s mode: In an IME like Kotoeri Hiragana, every key
|
||||
// gets sent to the plugin individually.
|
||||
if (![[mInputTextView inputContext] handleEvent:event]) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// On OS X 10.8 and above we can't use -[NSTextInputContext handleEvent:]
|
||||
// -- it doesn't work with a synthesized event. We need to activate the
|
||||
// input context and call TSMProcessRawKeyEvent instead. This also allows
|
||||
// plugin IME to work properly in non-e10s mode.
|
||||
[[mInputTextView inputContext] activate];
|
||||
OSErr err = TSMProcessRawKeyEvent((EventRef)[event eventRef]);
|
||||
if (err != noErr) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ([mInputTextView hasMarkedText]) {
|
||||
// Don't show the input method window for dead keys
|
||||
if ([[event characters] length] > 0)
|
||||
if ([[event characters] length] > 0) {
|
||||
[self orderFront:nil];
|
||||
|
||||
return YES;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
[self orderOut:nil];
|
||||
|
||||
NSString *text = [[mInputTextView textStorage] string];
|
||||
if ([text length] > 0)
|
||||
if ([text length] > 0) {
|
||||
*string = [[text copy] autorelease];
|
||||
}
|
||||
}
|
||||
|
||||
[mInputTextView setString:@""];
|
||||
return hadMarkedText;
|
||||
}
|
||||
|
||||
- (NSTextInputContext*)inputContext
|
||||
@ -150,23 +185,13 @@ using namespace mozilla;
|
||||
return [mInputTextView hasMarkedText];
|
||||
}
|
||||
|
||||
- (void)adjustTo:(NSView*)view
|
||||
- (void)adjustTo:(NSPoint)point
|
||||
{
|
||||
NSRect viewRect = [view frame];
|
||||
viewRect.origin.x = 0;
|
||||
viewRect.origin.y = 0;
|
||||
viewRect = [view convertRect:viewRect toView:nil];
|
||||
if (nsCocoaFeatures::OnLionOrLater()) {
|
||||
viewRect = [[view window] convertRectToScreen:viewRect];
|
||||
} else {
|
||||
viewRect.origin = [[view window] convertBaseToScreen:viewRect.origin];
|
||||
}
|
||||
NSRect selfRect = [self frame];
|
||||
CGFloat minWidth = static_cast<CGFloat>(
|
||||
Preferences::GetUint("ui.plugin.panel.min-width", 500));
|
||||
NSRect rect = NSMakeRect(viewRect.origin.x,
|
||||
viewRect.origin.y - selfRect.size.height,
|
||||
std::max(viewRect.size.width, minWidth),
|
||||
CGFloat minWidth = static_cast<CGFloat>(Preferences::GetUint("ui.plugin.panel.min-width", 500));
|
||||
NSRect rect = NSMakeRect(point.x,
|
||||
point.y - selfRect.size.height,
|
||||
500,
|
||||
selfRect.size.height);
|
||||
|
||||
// Adjust to screen.
|
||||
@ -192,3 +217,70 @@ using namespace mozilla;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
class ComplexTextInputPanelPrivate : public ComplexTextInputPanel
|
||||
{
|
||||
public:
|
||||
ComplexTextInputPanelPrivate();
|
||||
|
||||
virtual void InterpretKeyEvent(NPCocoaEvent* aEvent, nsAString& aOutText);
|
||||
virtual bool IsInComposition();
|
||||
virtual void PlacePanel(int32_t x, int32_t y);
|
||||
private:
|
||||
~ComplexTextInputPanelPrivate();
|
||||
ComplexTextInputPanelImpl* mPanel;
|
||||
};
|
||||
|
||||
ComplexTextInputPanelPrivate::ComplexTextInputPanelPrivate()
|
||||
{
|
||||
mPanel = [[ComplexTextInputPanelImpl alloc] init];
|
||||
}
|
||||
|
||||
ComplexTextInputPanelPrivate::~ComplexTextInputPanelPrivate()
|
||||
{
|
||||
[mPanel release];
|
||||
}
|
||||
|
||||
ComplexTextInputPanel*
|
||||
ComplexTextInputPanel::GetSharedComplexTextInputPanel()
|
||||
{
|
||||
static ComplexTextInputPanelPrivate *sComplexTextInputPanelPrivate;
|
||||
if (!sComplexTextInputPanelPrivate) {
|
||||
sComplexTextInputPanelPrivate = new ComplexTextInputPanelPrivate();
|
||||
}
|
||||
return sComplexTextInputPanelPrivate;
|
||||
}
|
||||
|
||||
void
|
||||
ComplexTextInputPanelPrivate::InterpretKeyEvent(NPCocoaEvent* aEvent, nsAString& aOutText)
|
||||
{
|
||||
NSEvent* nativeEvent = [NSEvent keyEventWithType:NSKeyDown
|
||||
location:NSMakePoint(0,0)
|
||||
modifierFlags:aEvent->data.key.modifierFlags
|
||||
timestamp:0
|
||||
windowNumber:[mPanel windowNumber]
|
||||
context:[mPanel graphicsContext]
|
||||
characters:(NSString*)aEvent->data.key.characters
|
||||
charactersIgnoringModifiers:(NSString*)aEvent->data.key.charactersIgnoringModifiers
|
||||
isARepeat:aEvent->data.key.isARepeat
|
||||
keyCode:aEvent->data.key.keyCode];
|
||||
|
||||
NSString* textString = nil;
|
||||
[mPanel interpretKeyEvent:nativeEvent string:&textString];
|
||||
|
||||
if (textString) {
|
||||
nsCocoaUtils::GetStringForNSString(textString, aOutText);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ComplexTextInputPanelPrivate::IsInComposition()
|
||||
{
|
||||
return !![mPanel inComposition];
|
||||
}
|
||||
|
||||
void
|
||||
ComplexTextInputPanelPrivate::PlacePanel(int32_t x, int32_t y)
|
||||
{
|
||||
[mPanel adjustTo:NSMakePoint(x, y)];
|
||||
}
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include "nsString.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsITimer.h"
|
||||
#include "npapi.h"
|
||||
#include "nsTArray.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
|
||||
@ -317,9 +316,8 @@ protected:
|
||||
};
|
||||
|
||||
/**
|
||||
* TextInputHandlerBase is a base class of PluginTextInputHandler,
|
||||
* IMEInputHandler and TextInputHandler. Utility methods should be implemented
|
||||
* this level.
|
||||
* TextInputHandlerBase is a base class of IMEInputHandler and TextInputHandler.
|
||||
* Utility methods should be implemented this level.
|
||||
*/
|
||||
|
||||
class TextInputHandlerBase
|
||||
@ -678,151 +676,6 @@ private:
|
||||
static int32_t sSecureEventInputCount;
|
||||
};
|
||||
|
||||
/**
|
||||
* PluginTextInputHandler handles text input events for plugins.
|
||||
*/
|
||||
|
||||
class PluginTextInputHandler : public TextInputHandlerBase
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* When starting complex text input for current event on plugin, this is
|
||||
* called. See also the comment of StartComplexTextInputForCurrentEvent() of
|
||||
* nsIPluginWidget.
|
||||
*/
|
||||
nsresult StartComplexTextInputForCurrentEvent()
|
||||
{
|
||||
mPluginComplexTextInputRequested = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* HandleKeyDownEventForPlugin() handles aNativeKeyEvent.
|
||||
*
|
||||
* @param aNativeKeyEvent A native NSKeyDown event.
|
||||
*/
|
||||
void HandleKeyDownEventForPlugin(NSEvent* aNativeKeyEvent);
|
||||
|
||||
/**
|
||||
* HandleKeyUpEventForPlugin() handles aNativeKeyEvent.
|
||||
*
|
||||
* @param aNativeKeyEvent A native NSKeyUp event.
|
||||
*/
|
||||
void HandleKeyUpEventForPlugin(NSEvent* aNativeKeyEvent);
|
||||
|
||||
/**
|
||||
* ConvertCocoaKeyEventToNPCocoaEvent() converts aCocoaEvent to NPCocoaEvent.
|
||||
*
|
||||
* @param aCocoaEvent A native key event.
|
||||
* @param aPluginEvent The result.
|
||||
*/
|
||||
static void ConvertCocoaKeyEventToNPCocoaEvent(NSEvent* aCocoaEvent,
|
||||
NPCocoaEvent& aPluginEvent);
|
||||
|
||||
#ifndef __LP64__
|
||||
|
||||
/**
|
||||
* InstallPluginKeyEventsHandler() is called when initializing process.
|
||||
* RemovePluginKeyEventsHandler() is called when finalizing process.
|
||||
* These methods initialize/finalize global resource for handling events for
|
||||
* plugins.
|
||||
*/
|
||||
static void InstallPluginKeyEventsHandler();
|
||||
static void RemovePluginKeyEventsHandler();
|
||||
|
||||
/**
|
||||
* This must be called before first key/IME event for plugins.
|
||||
* This method initializes IMKInputSession methods swizzling.
|
||||
*/
|
||||
static void SwizzleMethods();
|
||||
|
||||
/**
|
||||
* When a composition starts or finishes, this is called.
|
||||
*/
|
||||
void SetPluginTSMInComposition(bool aInComposition)
|
||||
{
|
||||
mPluginTSMInComposition = aInComposition;
|
||||
}
|
||||
|
||||
#endif // #ifndef __LP64__
|
||||
|
||||
protected:
|
||||
bool mIgnoreNextKeyUpEvent;
|
||||
|
||||
PluginTextInputHandler(nsChildView* aWidget, NSView<mozView> *aNativeView);
|
||||
~PluginTextInputHandler();
|
||||
|
||||
private:
|
||||
|
||||
#ifndef __LP64__
|
||||
TSMDocumentID mPluginTSMDoc;
|
||||
|
||||
bool mPluginTSMInComposition;
|
||||
#endif // #ifndef __LP64__
|
||||
|
||||
bool mPluginComplexTextInputRequested;
|
||||
|
||||
/**
|
||||
* DispatchCocoaNPAPITextEvent() dispatches a text event for Cocoa plugin.
|
||||
*
|
||||
* @param aString A string inputted by the dispatching event.
|
||||
* @return TRUE if the dispatched event was consumed.
|
||||
* Otherwise, FALSE.
|
||||
*/
|
||||
bool DispatchCocoaNPAPITextEvent(NSString* aString);
|
||||
|
||||
/**
|
||||
* Whether the plugin is in composition or not.
|
||||
* On 32bit build, this returns the state of mPluginTSMInComposition.
|
||||
* On 64bit build, this returns ComplexTextInputPanel's state.
|
||||
*
|
||||
* @return TRUE if plugin is in composition. Otherwise,
|
||||
* FALSE.
|
||||
*/
|
||||
bool IsInPluginComposition();
|
||||
|
||||
#ifndef __LP64__
|
||||
|
||||
/**
|
||||
* 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
|
||||
* provides (those created and managed by the NSTSMInputContext class) -- for
|
||||
* some reason TSMProcessRawKeyEvent() doesn't work with them.)
|
||||
*/
|
||||
void ActivatePluginTSMDocument();
|
||||
|
||||
/**
|
||||
* HandleCarbonPluginKeyEvent() handles the aKeyEvent. This is called by
|
||||
* PluginKeyEventsHandler().
|
||||
*
|
||||
* @param aKeyEvent A native Carbon event.
|
||||
*/
|
||||
void HandleCarbonPluginKeyEvent(EventRef aKeyEvent);
|
||||
|
||||
/**
|
||||
* Target for text services events sent as the result of calls made to
|
||||
* TSMProcessRawKeyEvent() in HandleKeyDownEventForPlugin() 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.
|
||||
*/
|
||||
static OSStatus PluginKeyEventsHandler(EventHandlerCallRef aHandlerRef,
|
||||
EventRef aEvent,
|
||||
void *aUserData);
|
||||
|
||||
static EventHandlerRef sPluginKeyEventsHandler;
|
||||
|
||||
#endif // #ifndef __LP64__
|
||||
};
|
||||
|
||||
/**
|
||||
* IMEInputHandler manages:
|
||||
* 1. The IME/keyboard layout statement of nsChildView.
|
||||
@ -836,7 +689,7 @@ private:
|
||||
* actual focused view is notified by OnFocusChangeInGecko.
|
||||
*/
|
||||
|
||||
class IMEInputHandler : public PluginTextInputHandler
|
||||
class IMEInputHandler : public TextInputHandlerBase
|
||||
{
|
||||
public:
|
||||
virtual bool OnDestroyWidget(nsChildView* aDestroyingWidget);
|
||||
|
@ -22,34 +22,6 @@
|
||||
#include "WidgetUtils.h"
|
||||
#include "nsPrintfCString.h"
|
||||
|
||||
#ifdef __LP64__
|
||||
#include "ComplexTextInputPanel.h"
|
||||
#include <objc/runtime.h>
|
||||
#endif // __LP64__
|
||||
|
||||
#ifndef __LP64__
|
||||
enum {
|
||||
// Currently focused ChildView (while this TSM document is active).
|
||||
// Transient (only set while TSMProcessRawKeyEvent() is processing a key
|
||||
// event), and the ChildView will be retained and released around the call
|
||||
// to TSMProcessRawKeyEvent() -- so it can be weak.
|
||||
kFocusedChildViewTSMDocPropertyTag = 'GKFV', // type ChildView* [WEAK]
|
||||
};
|
||||
|
||||
// Undocumented HIToolbox function used by WebKit to allow Carbon-based IME
|
||||
// to work in a Cocoa-based browser (like Safari or Cocoa-widgets Firefox).
|
||||
// (Recent WebKit versions actually use a thin wrapper around this function
|
||||
// called WKSendKeyEventToTSM().)
|
||||
//
|
||||
// Calling TSMProcessRawKeyEvent() from ChildView's keyDown: and keyUp:
|
||||
// methods (when the ChildView is a plugin view) bypasses Cocoa's IME
|
||||
// infrastructure and (instead) causes Carbon TSM events to be sent on each
|
||||
// NSKeyDown event. We install a Carbon event handler
|
||||
// (PluginKeyEventsHandler()) to catch these events and pass them to Gecko
|
||||
// (which in turn passes them to the plugin).
|
||||
extern "C" long TSMProcessRawKeyEvent(EventRef carbonEvent);
|
||||
#endif // __LP64__
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::widget;
|
||||
|
||||
@ -804,6 +776,22 @@ TISInputSourceWrapper::InitKeyEvent(NSEvent *aNativeKeyEvent,
|
||||
// call), so there is no need to retain and release this data.
|
||||
aKeyEvent.mNativeKeyEvent = aNativeKeyEvent;
|
||||
|
||||
// Fill in fields used for Cocoa NPAPI plugins
|
||||
if ([aNativeKeyEvent type] == NSKeyDown ||
|
||||
[aNativeKeyEvent type] == NSKeyUp) {
|
||||
aKeyEvent.mNativeKeyCode = [aNativeKeyEvent keyCode];
|
||||
aKeyEvent.mNativeModifierFlags = [aNativeKeyEvent modifierFlags];
|
||||
nsAutoString nativeChars;
|
||||
nsCocoaUtils::GetStringForNSString([aNativeKeyEvent characters], nativeChars);
|
||||
aKeyEvent.mNativeCharacters.Assign(nativeChars);
|
||||
nsAutoString nativeCharsIgnoringModifiers;
|
||||
nsCocoaUtils::GetStringForNSString([aNativeKeyEvent charactersIgnoringModifiers], nativeCharsIgnoringModifiers);
|
||||
aKeyEvent.mNativeCharactersIgnoringModifiers.Assign(nativeCharsIgnoringModifiers);
|
||||
} else if ([aNativeKeyEvent type] == NSFlagsChanged) {
|
||||
aKeyEvent.mNativeKeyCode = [aNativeKeyEvent keyCode];
|
||||
aKeyEvent.mNativeModifierFlags = [aNativeKeyEvent modifierFlags];
|
||||
}
|
||||
|
||||
aKeyEvent.refPoint = LayoutDeviceIntPoint(0, 0);
|
||||
|
||||
// If a keyboard layout override is set, we also need to force the keyboard
|
||||
@ -1641,17 +1629,12 @@ TextInputHandler::HandleKeyUpEvent(NSEvent* aNativeEvent)
|
||||
("%p TextInputHandler::HandleKeyUpEvent, aNativeEvent=%p, "
|
||||
"type=%s, keyCode=%lld (0x%X), modifierFlags=0x%X, characters=\"%s\", "
|
||||
"charactersIgnoringModifiers=\"%s\", "
|
||||
"mIgnoreNextKeyUpEvent=%s, IsIMEComposing()=%s",
|
||||
"IsIMEComposing()=%s",
|
||||
this, aNativeEvent, GetNativeKeyEventType(aNativeEvent),
|
||||
[aNativeEvent keyCode], [aNativeEvent keyCode],
|
||||
[aNativeEvent modifierFlags], GetCharacters([aNativeEvent characters]),
|
||||
GetCharacters([aNativeEvent charactersIgnoringModifiers]),
|
||||
TrueOrFalse(mIgnoreNextKeyUpEvent), TrueOrFalse(IsIMEComposing())));
|
||||
|
||||
if (mIgnoreNextKeyUpEvent) {
|
||||
mIgnoreNextKeyUpEvent = false;
|
||||
return;
|
||||
}
|
||||
TrueOrFalse(IsIMEComposing())));
|
||||
|
||||
if (Destroyed()) {
|
||||
PR_LOG(gLog, PR_LOG_ALWAYS,
|
||||
@ -2011,19 +1994,19 @@ TextInputHandler::DispatchKeyEventForFlagsChanged(NSEvent* aNativeEvent,
|
||||
|
||||
uint32_t message = aDispatchKeyDown ? NS_KEY_DOWN : NS_KEY_UP;
|
||||
|
||||
NPCocoaEvent cocoaEvent;
|
||||
|
||||
// Fire a key event.
|
||||
WidgetKeyboardEvent keyEvent(true, message, mWidget);
|
||||
InitKeyEvent(aNativeEvent, keyEvent);
|
||||
|
||||
// create event for use by plugins
|
||||
if ([mView isPluginView]) {
|
||||
if ([mView pluginEventModel] == NPEventModelCocoa) {
|
||||
ConvertCocoaKeyEventToNPCocoaEvent(aNativeEvent, cocoaEvent);
|
||||
// Attach a plugin event, in case keyEvent gets dispatched to a plugin. Only
|
||||
// one field is needed -- the type. The other fields can be constructed as
|
||||
// the need arises. But Gecko doesn't have anything equivalent to the
|
||||
// NPCocoaEventFlagsChanged type, and this needs to be passed accurately to
|
||||
// any plugin to which this event is sent.
|
||||
NPCocoaEvent cocoaEvent;
|
||||
nsCocoaUtils::InitNPCocoaEvent(&cocoaEvent);
|
||||
cocoaEvent.type = NPCocoaEventFlagsChanged;
|
||||
keyEvent.mPluginEvent.Copy(cocoaEvent);
|
||||
}
|
||||
}
|
||||
|
||||
DispatchEvent(keyEvent);
|
||||
|
||||
@ -3239,7 +3222,7 @@ IMEInputHandler::GetValidAttributesForMarkedText()
|
||||
|
||||
IMEInputHandler::IMEInputHandler(nsChildView* aWidget,
|
||||
NSView<mozView> *aNativeView) :
|
||||
PluginTextInputHandler(aWidget, aNativeView),
|
||||
TextInputHandlerBase(aWidget, aNativeView),
|
||||
mPendingMethods(0), mIMECompositionString(nullptr),
|
||||
mIsIMEComposing(false), mIsIMEEnabled(true),
|
||||
mIsASCIICapableOnly(false), mIgnoreIMECommit(false),
|
||||
@ -3307,10 +3290,6 @@ IMEInputHandler::OnDestroyWidget(nsChildView* aDestroyingWidget)
|
||||
sFocusedIMEHandler->OnDestroyWidget(aDestroyingWidget);
|
||||
}
|
||||
|
||||
if (!PluginTextInputHandler::OnDestroyWidget(aDestroyingWidget)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsIMEComposing()) {
|
||||
// If our view is in the composition, we should clean up it.
|
||||
CancelIMEComposition();
|
||||
@ -3631,587 +3610,6 @@ IMEInputHandler::OpenSystemPreferredLanguageIME()
|
||||
#pragma mark -
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* PluginTextInputHandler implementation
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
PluginTextInputHandler::PluginTextInputHandler(nsChildView* aWidget,
|
||||
NSView<mozView> *aNativeView) :
|
||||
TextInputHandlerBase(aWidget, aNativeView),
|
||||
mIgnoreNextKeyUpEvent(false),
|
||||
#ifndef __LP64__
|
||||
mPluginTSMDoc(0), mPluginTSMInComposition(false),
|
||||
#endif // #ifndef __LP64__
|
||||
mPluginComplexTextInputRequested(false)
|
||||
{
|
||||
}
|
||||
|
||||
PluginTextInputHandler::~PluginTextInputHandler()
|
||||
{
|
||||
#ifndef __LP64__
|
||||
if (mPluginTSMDoc) {
|
||||
::DeleteTSMDocument(mPluginTSMDoc);
|
||||
}
|
||||
#endif // #ifndef __LP64__
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PluginTextInputHandler::ConvertCocoaKeyEventToNPCocoaEvent(
|
||||
NSEvent* aCocoaEvent,
|
||||
NPCocoaEvent& aPluginEvent)
|
||||
{
|
||||
nsCocoaUtils::InitNPCocoaEvent(&aPluginEvent);
|
||||
NSEventType nativeType = [aCocoaEvent type];
|
||||
switch (nativeType) {
|
||||
case NSKeyDown:
|
||||
aPluginEvent.type = NPCocoaEventKeyDown;
|
||||
break;
|
||||
case NSKeyUp:
|
||||
aPluginEvent.type = NPCocoaEventKeyUp;
|
||||
break;
|
||||
case NSFlagsChanged:
|
||||
aPluginEvent.type = NPCocoaEventFlagsChanged;
|
||||
break;
|
||||
default:
|
||||
NS_WARNING("Asked to convert key event of unknown type to Cocoa plugin event!");
|
||||
}
|
||||
aPluginEvent.data.key.modifierFlags = [aCocoaEvent modifierFlags];
|
||||
aPluginEvent.data.key.keyCode = [aCocoaEvent keyCode];
|
||||
// don't try to access character data for flags changed events,
|
||||
// it will raise an exception
|
||||
if (nativeType != NSFlagsChanged) {
|
||||
aPluginEvent.data.key.characters = (NPNSString*)[aCocoaEvent characters];
|
||||
aPluginEvent.data.key.charactersIgnoringModifiers =
|
||||
(NPNSString*)[aCocoaEvent charactersIgnoringModifiers];
|
||||
aPluginEvent.data.key.isARepeat = [aCocoaEvent isARepeat];
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef __LP64__
|
||||
|
||||
EventHandlerRef PluginTextInputHandler::sPluginKeyEventsHandler = NULL;
|
||||
|
||||
/* static */ void
|
||||
PluginTextInputHandler::InstallPluginKeyEventsHandler()
|
||||
{
|
||||
if (sPluginKeyEventsHandler) {
|
||||
return;
|
||||
}
|
||||
static const EventTypeSpec sTSMEvents[] =
|
||||
{ { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } };
|
||||
::InstallEventHandler(::GetEventDispatcherTarget(),
|
||||
::NewEventHandlerUPP(PluginKeyEventsHandler),
|
||||
GetEventTypeCount(sTSMEvents),
|
||||
sTSMEvents,
|
||||
NULL,
|
||||
&sPluginKeyEventsHandler);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PluginTextInputHandler::RemovePluginKeyEventsHandler()
|
||||
{
|
||||
if (!sPluginKeyEventsHandler) {
|
||||
return;
|
||||
}
|
||||
::RemoveEventHandler(sPluginKeyEventsHandler);
|
||||
sPluginKeyEventsHandler = NULL;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PluginTextInputHandler::SwizzleMethods()
|
||||
{
|
||||
Class IMKInputSessionClass = ::NSClassFromString(@"IMKInputSession");
|
||||
nsToolkit::SwizzleMethods(IMKInputSessionClass, @selector(handleEvent:),
|
||||
@selector(PluginTextInputHandler_IMKInputSession_handleEvent:));
|
||||
nsToolkit::SwizzleMethods(IMKInputSessionClass, @selector(commitComposition),
|
||||
@selector(PluginTextInputHandler_IMKInputSession_commitComposition));
|
||||
nsToolkit::SwizzleMethods(IMKInputSessionClass, @selector(finishSession),
|
||||
@selector(PluginTextInputHandler_IMKInputSession_finishSession));
|
||||
}
|
||||
|
||||
/* static */ OSStatus
|
||||
PluginTextInputHandler::PluginKeyEventsHandler(EventHandlerCallRef aHandlerRef,
|
||||
EventRef aEvent,
|
||||
void *aUserData)
|
||||
{
|
||||
nsAutoreleasePool localPool;
|
||||
|
||||
TSMDocumentID activeDoc = ::TSMGetActiveDocument();
|
||||
NS_ENSURE_TRUE(activeDoc, eventNotHandledErr);
|
||||
|
||||
ChildView *target = nil;
|
||||
OSStatus status = ::TSMGetDocumentProperty(activeDoc,
|
||||
kFocusedChildViewTSMDocPropertyTag,
|
||||
sizeof(ChildView *), nil, &target);
|
||||
NS_ENSURE_TRUE(status == noErr, eventNotHandledErr);
|
||||
NS_ENSURE_TRUE(target, eventNotHandledErr);
|
||||
|
||||
EventRef keyEvent = NULL;
|
||||
status = ::GetEventParameter(aEvent, kEventParamTextInputSendKeyboardEvent,
|
||||
typeEventRef, NULL, sizeof(EventRef), NULL,
|
||||
&keyEvent);
|
||||
NS_ENSURE_TRUE(status == noErr, eventNotHandledErr);
|
||||
NS_ENSURE_TRUE(keyEvent, eventNotHandledErr);
|
||||
|
||||
nsIWidget* widget = [target widget];
|
||||
NS_ENSURE_TRUE(widget, eventNotHandledErr);
|
||||
TextInputHandler* handler =
|
||||
static_cast<nsChildView*>(widget)->GetTextInputHandler();
|
||||
NS_ENSURE_TRUE(handler, eventNotHandledErr);
|
||||
handler->HandleCarbonPluginKeyEvent(keyEvent);
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
// 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
|
||||
PluginTextInputHandler::HandleCarbonPluginKeyEvent(EventRef aKeyEvent)
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
if (Destroyed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mView, "mView must not be NULL");
|
||||
|
||||
nsRefPtr<nsChildView> kungFuDeathGrip(mWidget);
|
||||
|
||||
if ([mView pluginEventModel] == NPEventModelCocoa) {
|
||||
UInt32 size;
|
||||
OSStatus status =
|
||||
::GetEventParameter(aKeyEvent, kEventParamKeyUnicodes, typeUnicodeText,
|
||||
NULL, 0, &size, NULL);
|
||||
NS_ENSURE_TRUE(status == noErr, );
|
||||
|
||||
UniChar* chars = (UniChar*)malloc(size);
|
||||
NS_ENSURE_TRUE(chars, );
|
||||
|
||||
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;
|
||||
nsCocoaUtils::InitNPCocoaEvent(&cocoaTextEvent);
|
||||
cocoaTextEvent.type = NPCocoaEventTextInput;
|
||||
cocoaTextEvent.data.text.text = (NPNSString*)text;
|
||||
|
||||
WidgetPluginEvent pluginEvent(true, NS_PLUGIN_INPUT_EVENT, mWidget);
|
||||
nsCocoaUtils::InitPluginEvent(pluginEvent, cocoaTextEvent);
|
||||
DispatchEvent(pluginEvent);
|
||||
|
||||
::CFRelease(text);
|
||||
free(chars);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
UInt32 numCharCodes;
|
||||
OSStatus status = ::GetEventParameter(aKeyEvent, kEventParamKeyMacCharCodes,
|
||||
typeChar, NULL, 0, &numCharCodes, NULL);
|
||||
NS_ENSURE_TRUE(status == noErr, );
|
||||
|
||||
nsAutoTArray<unsigned char, 3> charCodes;
|
||||
charCodes.SetLength(numCharCodes);
|
||||
status = ::GetEventParameter(aKeyEvent, kEventParamKeyMacCharCodes,
|
||||
typeChar, NULL, numCharCodes, NULL,
|
||||
charCodes.Elements());
|
||||
NS_ENSURE_TRUE(status == noErr, );
|
||||
|
||||
UInt32 modifiers;
|
||||
status = ::GetEventParameter(aKeyEvent, kEventParamKeyModifiers,
|
||||
typeUInt32, NULL, sizeof(modifiers), NULL,
|
||||
&modifiers);
|
||||
NS_ENSURE_TRUE(status == noErr, );
|
||||
|
||||
NSUInteger cocoaModifiers = 0;
|
||||
if (modifiers & shiftKey) {
|
||||
cocoaModifiers |= NSShiftKeyMask;
|
||||
}
|
||||
if (modifiers & controlKey) {
|
||||
cocoaModifiers |= NSControlKeyMask;
|
||||
}
|
||||
if (modifiers & optionKey) {
|
||||
cocoaModifiers |= NSAlternateKeyMask;
|
||||
}
|
||||
if (modifiers & cmdKey) { // Should never happen
|
||||
cocoaModifiers |= NSCommandKeyMask;
|
||||
}
|
||||
|
||||
UInt32 macKeyCode;
|
||||
status = ::GetEventParameter(aKeyEvent, kEventParamKeyCode,
|
||||
typeUInt32, NULL, sizeof(macKeyCode), NULL,
|
||||
&macKeyCode);
|
||||
NS_ENSURE_TRUE(status == noErr, );
|
||||
|
||||
TISInputSourceWrapper& currentInputSource =
|
||||
TISInputSourceWrapper::CurrentInputSource();
|
||||
|
||||
EventRef cloneEvent = ::CopyEvent(aKeyEvent);
|
||||
for (uint32_t i = 0; i < numCharCodes; ++i) {
|
||||
status = ::SetEventParameter(cloneEvent, kEventParamKeyMacCharCodes,
|
||||
typeChar, 1, charCodes.Elements() + i);
|
||||
NS_ENSURE_TRUE(status == noErr, );
|
||||
|
||||
EventRecord eventRec;
|
||||
if (::ConvertEventRefToEventRecord(cloneEvent, &eventRec)) {
|
||||
WidgetKeyboardEvent keydownEvent(true, NS_KEY_DOWN, mWidget);
|
||||
nsCocoaUtils::InitInputEvent(keydownEvent, cocoaModifiers);
|
||||
|
||||
uint32_t keyCode =
|
||||
currentInputSource.ComputeGeckoKeyCode(macKeyCode, ::LMGetKbdType(),
|
||||
keydownEvent.IsMeta());
|
||||
uint32_t charCode(charCodes.ElementAt(i));
|
||||
|
||||
keydownEvent.time = PR_IntervalNow();
|
||||
keydownEvent.mPluginEvent.Copy(eventRec);
|
||||
if (IsSpecialGeckoKey(macKeyCode)) {
|
||||
keydownEvent.keyCode = keyCode;
|
||||
} else {
|
||||
// XXX This is wrong. charCode must be 0 for keydown event.
|
||||
keydownEvent.charCode = charCode;
|
||||
keydownEvent.isChar = true;
|
||||
}
|
||||
DispatchEvent(keydownEvent);
|
||||
if (Destroyed()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::ReleaseEvent(cloneEvent);
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
void
|
||||
PluginTextInputHandler::ActivatePluginTSMDocument()
|
||||
{
|
||||
if (!mPluginTSMDoc) {
|
||||
// Create a TSM document that supports both non-Unicode and Unicode input.
|
||||
// Though 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);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #ifndef __LP64__
|
||||
|
||||
void
|
||||
PluginTextInputHandler::HandleKeyDownEventForPlugin(NSEvent* aNativeKeyEvent)
|
||||
{
|
||||
if (Destroyed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mView, "mView must not be NULL");
|
||||
|
||||
#ifdef __LP64__
|
||||
|
||||
if ([mView pluginEventModel] != NPEventModelCocoa) {
|
||||
return;
|
||||
}
|
||||
|
||||
ComplexTextInputPanel* ctiPanel =
|
||||
[ComplexTextInputPanel sharedComplexTextInputPanel];
|
||||
[ctiPanel adjustTo:mView];
|
||||
|
||||
// If a composition is in progress then simply let the input panel continue
|
||||
// it.
|
||||
if (IsInPluginComposition()) {
|
||||
// Don't send key up events for key downs associated with compositions.
|
||||
mIgnoreNextKeyUpEvent = true;
|
||||
|
||||
NSString* textString = nil;
|
||||
[ctiPanel interpretKeyEvent:aNativeKeyEvent string:&textString];
|
||||
if (textString) {
|
||||
DispatchCocoaNPAPITextEvent(textString);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset complex text input request flag.
|
||||
mPluginComplexTextInputRequested = false;
|
||||
|
||||
// Send key down event to the plugin.
|
||||
WidgetPluginEvent pluginEvent(true, NS_PLUGIN_INPUT_EVENT, mWidget);
|
||||
NPCocoaEvent cocoaEvent;
|
||||
ConvertCocoaKeyEventToNPCocoaEvent(aNativeKeyEvent, cocoaEvent);
|
||||
nsCocoaUtils::InitPluginEvent(pluginEvent, cocoaEvent);
|
||||
DispatchEvent(pluginEvent);
|
||||
if (Destroyed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Start complex text composition if requested.
|
||||
if (mPluginComplexTextInputRequested) {
|
||||
// Don't send key up events for key downs associated with compositions.
|
||||
mIgnoreNextKeyUpEvent = true;
|
||||
|
||||
NSString* textString = nil;
|
||||
[ctiPanel interpretKeyEvent:aNativeKeyEvent string:&textString];
|
||||
if (textString) {
|
||||
DispatchCocoaNPAPITextEvent(textString);
|
||||
}
|
||||
}
|
||||
|
||||
#else // #ifdef __LP64__
|
||||
|
||||
bool wasInComposition = false;
|
||||
if ([mView pluginEventModel] == NPEventModelCocoa) {
|
||||
if (IsInPluginComposition()) {
|
||||
wasInComposition = true;
|
||||
|
||||
// Don't send key up events for key downs associated with compositions.
|
||||
mIgnoreNextKeyUpEvent = true;
|
||||
} else {
|
||||
// Reset complex text input request flag.
|
||||
mPluginComplexTextInputRequested = false;
|
||||
|
||||
// Send key down event to the plugin.
|
||||
WidgetPluginEvent pluginEvent(true, NS_PLUGIN_INPUT_EVENT, mWidget);
|
||||
NPCocoaEvent cocoaEvent;
|
||||
ConvertCocoaKeyEventToNPCocoaEvent(aNativeKeyEvent, cocoaEvent);
|
||||
nsCocoaUtils::InitPluginEvent(pluginEvent, cocoaEvent);
|
||||
DispatchEvent(pluginEvent);
|
||||
if (Destroyed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only continue if plugin wants complex text input.
|
||||
if (!mPluginComplexTextInputRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't send key up events for key downs associated with compositions.
|
||||
mIgnoreNextKeyUpEvent = true;
|
||||
}
|
||||
|
||||
// Don't send complex text input to a plugin in Cocoa event mode if
|
||||
// either the Control key or the Command key is pressed -- even if the
|
||||
// plugin has requested it, or we are already in IME composition. This
|
||||
// conforms to our behavior in 64-bit mode and fixes bug 619217.
|
||||
NSUInteger modifierFlags = [aNativeKeyEvent modifierFlags];
|
||||
if ((modifierFlags & NSControlKeyMask) ||
|
||||
(modifierFlags & NSCommandKeyMask)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 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).
|
||||
ActivatePluginTSMDocument();
|
||||
|
||||
// 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(mView);
|
||||
::TSMSetDocumentProperty(mPluginTSMDoc,
|
||||
kFocusedChildViewTSMDocPropertyTag,
|
||||
sizeof(ChildView *), &mView);
|
||||
::TSMProcessRawKeyEvent([aNativeKeyEvent _eventRef]);
|
||||
::TSMRemoveDocumentProperty(mPluginTSMDoc,
|
||||
kFocusedChildViewTSMDocPropertyTag);
|
||||
|
||||
#endif // #ifdef __LP64__ else
|
||||
}
|
||||
|
||||
void
|
||||
PluginTextInputHandler::HandleKeyUpEventForPlugin(NSEvent* aNativeKeyEvent)
|
||||
{
|
||||
if (mIgnoreNextKeyUpEvent) {
|
||||
mIgnoreNextKeyUpEvent = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Destroyed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mView, "mView must not be NULL");
|
||||
|
||||
NPEventModel eventModel = [mView pluginEventModel];
|
||||
if (eventModel == NPEventModelCocoa) {
|
||||
// Don't send key up events to Cocoa plugins during composition.
|
||||
if (IsInPluginComposition()) {
|
||||
return;
|
||||
}
|
||||
|
||||
WidgetKeyboardEvent keyupEvent(true, NS_KEY_UP, mWidget);
|
||||
InitKeyEvent(aNativeKeyEvent, keyupEvent);
|
||||
NPCocoaEvent pluginEvent;
|
||||
ConvertCocoaKeyEventToNPCocoaEvent(aNativeKeyEvent, pluginEvent);
|
||||
keyupEvent.mPluginEvent.Copy(pluginEvent);
|
||||
DispatchEvent(keyupEvent);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
PluginTextInputHandler::IsInPluginComposition()
|
||||
{
|
||||
return
|
||||
#ifdef __LP64__
|
||||
[[ComplexTextInputPanel sharedComplexTextInputPanel] inComposition] != NO;
|
||||
#else // #ifdef __LP64__
|
||||
mPluginTSMInComposition;
|
||||
#endif // #ifdef __LP64__ else
|
||||
}
|
||||
|
||||
bool
|
||||
PluginTextInputHandler::DispatchCocoaNPAPITextEvent(NSString* aString)
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
||||
|
||||
NPCocoaEvent cocoaTextEvent;
|
||||
nsCocoaUtils::InitNPCocoaEvent(&cocoaTextEvent);
|
||||
cocoaTextEvent.type = NPCocoaEventTextInput;
|
||||
cocoaTextEvent.data.text.text = (NPNSString*)aString;
|
||||
|
||||
WidgetPluginEvent pluginEvent(true, NS_PLUGIN_INPUT_EVENT, mWidget);
|
||||
nsCocoaUtils::InitPluginEvent(pluginEvent, cocoaTextEvent);
|
||||
return DispatchEvent(pluginEvent);
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
|
||||
#ifndef __LP64__
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* PluginTextInputHandler_IMKInputSession_* implementation
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
// IMKInputSession is an undocumented class in the HIToolbox framework. It's
|
||||
// present on both Leopard and SnowLeopard, and is used at a low level to
|
||||
// process IME input regardless of which high-level API is used (Text Services
|
||||
// Manager or Cocoa). It works the same way in both 32-bit and 64-bit code.
|
||||
@interface NSObject (IMKInputSessionMethodSwizzling)
|
||||
- (BOOL)PluginTextInputHandler_IMKInputSession_handleEvent:(EventRef)theEvent;
|
||||
- (void)PluginTextInputHandler_IMKInputSession_commitComposition;
|
||||
- (void)PluginTextInputHandler_IMKInputSession_finishSession;
|
||||
@end
|
||||
|
||||
@implementation NSObject (IMKInputSessionMethodSwizzling)
|
||||
|
||||
- (BOOL)PluginTextInputHandler_IMKInputSession_handleEvent:(EventRef)theEvent
|
||||
{
|
||||
[self retain];
|
||||
BOOL retval =
|
||||
[self PluginTextInputHandler_IMKInputSession_handleEvent:theEvent];
|
||||
NSUInteger retainCount = [self retainCount];
|
||||
[self release];
|
||||
// Return without doing anything if we've been deleted.
|
||||
if (retainCount == 1) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
NSWindow *mainWindow = [NSApp mainWindow];
|
||||
NSResponder *firstResponder = [mainWindow firstResponder];
|
||||
if (![firstResponder isKindOfClass:[ChildView class]]) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
// 'charactersEntered' is the length (in bytes) of currently "marked text"
|
||||
// -- text that's been entered in IME but not yet committed. If it's
|
||||
// non-zero we're composing text in an IME session; if it's zero we're
|
||||
// not in an IME session.
|
||||
NSInteger entered = 0;
|
||||
object_getInstanceVariable(self, "charactersEntered",
|
||||
(void **) &entered);
|
||||
nsIWidget* widget = [(ChildView*)firstResponder widget];
|
||||
NS_ENSURE_TRUE(widget, retval);
|
||||
TextInputHandler* handler =
|
||||
static_cast<nsChildView*>(widget)->GetTextInputHandler();
|
||||
NS_ENSURE_TRUE(handler, retval);
|
||||
handler->SetPluginTSMInComposition(entered != 0);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
// This method is called whenever IME input is committed as a result of an
|
||||
// "abnormal" termination -- for example when changing the keyboard focus from
|
||||
// one input field to another.
|
||||
- (void)PluginTextInputHandler_IMKInputSession_commitComposition
|
||||
{
|
||||
NSWindow *mainWindow = [NSApp mainWindow];
|
||||
NSResponder *firstResponder = [mainWindow firstResponder];
|
||||
if ([firstResponder isKindOfClass:[ChildView class]]) {
|
||||
nsIWidget* widget = [(ChildView*)firstResponder widget];
|
||||
if (widget) {
|
||||
TextInputHandler* handler =
|
||||
static_cast<nsChildView*>(widget)->GetTextInputHandler();
|
||||
if (handler) {
|
||||
handler->SetPluginTSMInComposition(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
[self PluginTextInputHandler_IMKInputSession_commitComposition];
|
||||
}
|
||||
|
||||
// This method is called just before we're deallocated.
|
||||
- (void)PluginTextInputHandler_IMKInputSession_finishSession
|
||||
{
|
||||
NSWindow *mainWindow = [NSApp mainWindow];
|
||||
NSResponder *firstResponder = [mainWindow firstResponder];
|
||||
if ([firstResponder isKindOfClass:[ChildView class]]) {
|
||||
nsIWidget* widget = [(ChildView*)firstResponder widget];
|
||||
if (widget) {
|
||||
TextInputHandler* handler =
|
||||
static_cast<nsChildView*>(widget)->GetTextInputHandler();
|
||||
if (handler) {
|
||||
handler->SetPluginTSMInComposition(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
[self PluginTextInputHandler_IMKInputSession_finishSession];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif // #ifndef __LP64__
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* TextInputHandlerBase implementation
|
||||
|
@ -18,6 +18,7 @@ EXPORTS += [
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'ComplexTextInputPanel.mm',
|
||||
'GfxInfo.mm',
|
||||
'NativeKeyBindings.mm',
|
||||
'nsAppShell.mm',
|
||||
@ -65,11 +66,6 @@ SOURCES += [
|
||||
'nsClipboard.mm',
|
||||
]
|
||||
|
||||
if CONFIG['TARGET_CPU'] == 'x86_64':
|
||||
UNIFIED_SOURCES += [
|
||||
'ComplexTextInputPanel.mm',
|
||||
]
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
@ -6,8 +6,6 @@
|
||||
#ifndef mozView_h_
|
||||
#define mozView_h_
|
||||
|
||||
#include "npapi.h"
|
||||
|
||||
#undef DARWIN
|
||||
#import <Cocoa/Cocoa.h>
|
||||
class nsIWidget;
|
||||
@ -46,18 +44,12 @@ class TextInputHandler;
|
||||
|
||||
- (BOOL)isDragInProgress;
|
||||
|
||||
// Gets the plugin event model for the view
|
||||
- (NPEventModel)pluginEventModel;
|
||||
|
||||
// Checks whether the view is first responder or not
|
||||
- (BOOL)isFirstResponder;
|
||||
|
||||
// Call when you dispatch an event which may cause to open context menu.
|
||||
- (void)maybeInitContextMenuTracking;
|
||||
|
||||
// Checks whether the view is for plugin or not
|
||||
- (BOOL)isPluginView;
|
||||
|
||||
@end
|
||||
|
||||
// An informal protocol implemented by the NSWindow of the host application.
|
||||
|
@ -295,10 +295,6 @@ nsAppShell::Init()
|
||||
|
||||
rv = nsBaseAppShell::Init();
|
||||
|
||||
#ifndef __LP64__
|
||||
TextInputHandler::InstallPluginKeyEventsHandler();
|
||||
#endif
|
||||
|
||||
if (!gAppShellMethodsSwizzled) {
|
||||
// We should only replace the original terminate: method if we're not
|
||||
// running in a Cocoa embedder. See bug 604901.
|
||||
@ -672,10 +668,6 @@ nsAppShell::Exit(void)
|
||||
|
||||
mTerminated = true;
|
||||
|
||||
#ifndef __LP64__
|
||||
TextInputHandler::RemovePluginKeyEventsHandler();
|
||||
#endif
|
||||
|
||||
// Quoting from Apple's doc on the [NSApplication stop:] method (from their
|
||||
// doc on the NSApplication class): "If this method is invoked during a
|
||||
// modal event loop, it will break that loop but not the main event loop."
|
||||
|
@ -16,8 +16,6 @@
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsBaseWidget.h"
|
||||
#include "nsIPluginInstanceOwner.h"
|
||||
#include "nsIPluginWidget.h"
|
||||
#include "nsWeakPtr.h"
|
||||
#include "TextInputHandler.h"
|
||||
#include "nsCocoaUtils.h"
|
||||
@ -31,62 +29,13 @@
|
||||
#include "nsString.h"
|
||||
#include "nsIDragService.h"
|
||||
|
||||
#include "npapi.h"
|
||||
|
||||
#import <Carbon/Carbon.h>
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <AppKit/NSOpenGL.h>
|
||||
|
||||
// The header files QuickdrawAPI.h and QDOffscreen.h are missing on OS X 10.7
|
||||
// and up (though the QuickDraw APIs defined in them are still present) -- so
|
||||
// we need to supply the relevant parts of their contents here. It's likely
|
||||
// that Apple will eventually remove the APIs themselves (probably in OS X
|
||||
// 10.8), so we need to make them weak imports, and test for their presence
|
||||
// before using them.
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#if !defined(__QUICKDRAWAPI__)
|
||||
|
||||
extern void SetPort(GrafPtr port)
|
||||
__attribute__((weak_import));
|
||||
extern void SetOrigin(short h, short v)
|
||||
__attribute__((weak_import));
|
||||
extern RgnHandle NewRgn(void)
|
||||
__attribute__((weak_import));
|
||||
extern void DisposeRgn(RgnHandle rgn)
|
||||
__attribute__((weak_import));
|
||||
extern void RectRgn(RgnHandle rgn, const Rect * r)
|
||||
__attribute__((weak_import));
|
||||
extern GDHandle GetMainDevice(void)
|
||||
__attribute__((weak_import));
|
||||
extern Boolean IsPortOffscreen(CGrafPtr port)
|
||||
__attribute__((weak_import));
|
||||
extern void SetPortVisibleRegion(CGrafPtr port, RgnHandle visRgn)
|
||||
__attribute__((weak_import));
|
||||
extern void SetPortClipRegion(CGrafPtr port, RgnHandle clipRgn)
|
||||
__attribute__((weak_import));
|
||||
extern CGrafPtr GetQDGlobalsThePort(void)
|
||||
__attribute__((weak_import));
|
||||
|
||||
#endif /* __QUICKDRAWAPI__ */
|
||||
|
||||
#if !defined(__QDOFFSCREEN__)
|
||||
|
||||
extern void GetGWorld(CGrafPtr * port, GDHandle * gdh)
|
||||
__attribute__((weak_import));
|
||||
extern void SetGWorld(CGrafPtr port, GDHandle gdh)
|
||||
__attribute__((weak_import));
|
||||
|
||||
#endif /* __QDOFFSCREEN__ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
class gfxASurface;
|
||||
class nsChildView;
|
||||
class nsCocoaWindow;
|
||||
union nsPluginPort;
|
||||
|
||||
namespace {
|
||||
class GLPresenter;
|
||||
@ -231,10 +180,6 @@ typedef NSInteger NSEventGestureAxis;
|
||||
// cleared by [mozView uninstallTextInputHandler].
|
||||
mozilla::widget::TextInputHandler* mTextInputHandler; // [WEAK]
|
||||
|
||||
BOOL mIsPluginView;
|
||||
NPEventModel mPluginEventModel;
|
||||
NPDrawingModel mPluginDrawingModel;
|
||||
|
||||
// when mouseDown: is called, we store its event here (strong)
|
||||
NSEvent* mLastMouseDownEvent;
|
||||
|
||||
@ -326,12 +271,6 @@ typedef NSInteger NSEventGestureAxis;
|
||||
- (void)updateGLContext;
|
||||
- (void)_surfaceNeedsUpdate:(NSNotification*)notification;
|
||||
|
||||
- (BOOL)isPluginView;
|
||||
|
||||
// Are we processing an NSLeftMouseDown event that will fail to click through?
|
||||
// If so, we shouldn't focus or unfocus a plugin.
|
||||
- (BOOL)isInFailingLeftClickThrough;
|
||||
|
||||
- (void)setGLContext:(NSOpenGLContext *)aGLContext;
|
||||
- (bool)preRender:(NSOpenGLContext *)aGLContext;
|
||||
- (void)postRender:(NSOpenGLContext *)aGLContext;
|
||||
@ -390,11 +329,6 @@ public:
|
||||
static void ReEvaluateMouseEnterState(NSEvent* aEvent = nil, ChildView* aOldView = nil);
|
||||
static void ResendLastMouseMoveEvent();
|
||||
static ChildView* ViewForEvent(NSEvent* aEvent);
|
||||
static void AttachPluginEvent(mozilla::WidgetMouseEventBase& aMouseEvent,
|
||||
ChildView* aView,
|
||||
NSEvent* aNativeMouseEvent,
|
||||
int aPluginEventType,
|
||||
void* aPluginEventHolder);
|
||||
|
||||
static ChildView* sLastMouseEventView;
|
||||
static NSEvent* sLastMouseMoveEvent;
|
||||
@ -408,8 +342,7 @@ public:
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
class nsChildView : public nsBaseWidget,
|
||||
public nsIPluginWidget
|
||||
class nsChildView : public nsBaseWidget
|
||||
{
|
||||
private:
|
||||
typedef nsBaseWidget Inherited;
|
||||
@ -418,8 +351,6 @@ private:
|
||||
public:
|
||||
nsChildView();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIWidget interface
|
||||
NS_IMETHOD Create(nsIWidget *aParent,
|
||||
nsNativeWidget aNativeParent,
|
||||
@ -515,19 +446,6 @@ public:
|
||||
NS_IMETHOD GetToggledKeyState(uint32_t aKeyCode,
|
||||
bool* aLEDState);
|
||||
|
||||
// nsIPluginWidget
|
||||
// outClipRect and outOrigin are in display pixels (not device pixels)
|
||||
NS_IMETHOD GetPluginClipRect(nsIntRect& outClipRect, nsIntPoint& outOrigin, bool& outWidgetVisible);
|
||||
NS_IMETHOD StartDrawPlugin();
|
||||
NS_IMETHOD EndDrawPlugin();
|
||||
NS_IMETHOD SetPluginInstanceOwner(nsIPluginInstanceOwner* aInstanceOwner);
|
||||
|
||||
NS_IMETHOD SetPluginEventModel(int inEventModel);
|
||||
NS_IMETHOD GetPluginEventModel(int* outEventModel);
|
||||
NS_IMETHOD SetPluginDrawingModel(int inDrawingModel);
|
||||
|
||||
NS_IMETHOD StartComplexTextInputForCurrentEvent();
|
||||
|
||||
virtual nsTransparencyMode GetTransparencyMode();
|
||||
virtual void SetTransparencyMode(nsTransparencyMode aMode);
|
||||
|
||||
@ -568,9 +486,6 @@ public:
|
||||
virtual void UpdateWindowDraggingRegion(const nsIntRegion& aRegion) MOZ_OVERRIDE;
|
||||
const nsIntRegion& GetDraggableRegion() { return mDraggableRegion; }
|
||||
|
||||
void HidePlugin();
|
||||
void UpdatePluginPort();
|
||||
|
||||
void ResetParent();
|
||||
|
||||
static bool DoHasPendingInputEvent();
|
||||
@ -579,8 +494,6 @@ public:
|
||||
|
||||
NSView<mozView>* GetEditorView();
|
||||
|
||||
bool IsPluginView() { return (mWindowType == eWindowType_plugin); }
|
||||
|
||||
nsCocoaWindow* GetXULWindowWidget();
|
||||
|
||||
NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent);
|
||||
@ -710,12 +623,8 @@ protected:
|
||||
|
||||
bool mVisible;
|
||||
bool mDrawing;
|
||||
bool mPluginDrawing;
|
||||
bool mIsDispatchPaint; // Is a paint event being dispatched
|
||||
|
||||
NP_CGContext mPluginCGContext;
|
||||
nsIPluginInstanceOwner* mPluginInstanceOwner; // [WEAK]
|
||||
|
||||
// Used in OMTC BasicLayers mode. Presents the BasicCompositor result
|
||||
// surface to the screen using an OpenGL context.
|
||||
nsAutoPtr<GLPresenter> mGLPresenter;
|
||||
@ -729,7 +638,4 @@ protected:
|
||||
void ReleaseTitlebarCGContext();
|
||||
};
|
||||
|
||||
void NS_InstallPluginKeyEventsHandler();
|
||||
void NS_RemovePluginKeyEventsHandler();
|
||||
|
||||
#endif // nsChildView_h_
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -22,7 +22,6 @@ public:
|
||||
static bool OnMountainLionOrLater();
|
||||
static bool OnMavericksOrLater();
|
||||
static bool OnYosemiteOrLater();
|
||||
static bool SupportCoreAnimationPlugins();
|
||||
static bool AccelerateByDefault();
|
||||
|
||||
static bool IsAtLeastVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFix=0);
|
||||
|
@ -148,14 +148,6 @@ nsCocoaFeatures::OSXVersionBugFix()
|
||||
return ExtractBugFixVersion(OSXVersion());
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
nsCocoaFeatures::SupportCoreAnimationPlugins()
|
||||
{
|
||||
// Disallow Core Animation on 10.5 because of crashes.
|
||||
// See Bug 711564.
|
||||
return (OSXVersion() >= MAC_OS_X_VERSION_10_6_HEX);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
nsCocoaFeatures::OnLionOrLater()
|
||||
{
|
||||
|
@ -320,11 +320,6 @@ public:
|
||||
*/
|
||||
static void InitNPCocoaEvent(NPCocoaEvent* aNPCocoaEvent);
|
||||
|
||||
/**
|
||||
* Initializes aPluginEvent for aCocoaEvent.
|
||||
*/
|
||||
static void InitPluginEvent(mozilla::WidgetPluginEvent &aPluginEvent,
|
||||
NPCocoaEvent &aCocoaEvent);
|
||||
/**
|
||||
* Initializes WidgetInputEvent for aNativeEvent or aModifiers.
|
||||
*/
|
||||
|
@ -606,16 +606,6 @@ nsCocoaUtils::InitNPCocoaEvent(NPCocoaEvent* aNPCocoaEvent)
|
||||
memset(aNPCocoaEvent, 0, sizeof(NPCocoaEvent));
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
nsCocoaUtils::InitPluginEvent(WidgetPluginEvent &aPluginEvent,
|
||||
NPCocoaEvent &aCocoaEvent)
|
||||
{
|
||||
aPluginEvent.time = PR_IntervalNow();
|
||||
aPluginEvent.mPluginEvent.Copy(aCocoaEvent);
|
||||
aPluginEvent.retargetToFocusedDocument = false;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
nsCocoaUtils::InitInputEvent(WidgetInputEvent& aInputEvent,
|
||||
|
@ -141,12 +141,12 @@ nsCocoaWindow::~nsCocoaWindow()
|
||||
|
||||
// Notify the children that we're gone. Popup windows (e.g. tooltips) can
|
||||
// have nsChildView children. 'kid' is an nsChildView object if and only if
|
||||
// its 'type' is 'eWindowType_child' or 'eWindowType_plugin'.
|
||||
// its 'type' is 'eWindowType_child'.
|
||||
// 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;) {
|
||||
nsWindowType kidType = kid->WindowType();
|
||||
if (kidType == eWindowType_child || kidType == eWindowType_plugin) {
|
||||
if (kidType == eWindowType_child) {
|
||||
nsChildView* childView = static_cast<nsChildView*>(kid);
|
||||
kid = kid->GetPrevSibling();
|
||||
childView->ResetParent();
|
||||
@ -2503,8 +2503,9 @@ nsCocoaWindow::ExecuteNativeKeyBinding(NativeKeyBindingsType aType,
|
||||
{
|
||||
if (!mToplevelActiveState && mGeckoWindow) {
|
||||
nsIWidgetListener* listener = mGeckoWindow->GetWidgetListener();
|
||||
if (listener)
|
||||
if (listener) {
|
||||
listener->WindowActivated();
|
||||
}
|
||||
mToplevelActiveState = true;
|
||||
}
|
||||
}
|
||||
@ -2513,8 +2514,9 @@ nsCocoaWindow::ExecuteNativeKeyBinding(NativeKeyBindingsType aType,
|
||||
{
|
||||
if (mToplevelActiveState && mGeckoWindow) {
|
||||
nsIWidgetListener* listener = mGeckoWindow->GetWidgetListener();
|
||||
if (listener)
|
||||
if (listener) {
|
||||
listener->WindowDeactivated();
|
||||
}
|
||||
mToplevelActiveState = false;
|
||||
}
|
||||
}
|
||||
|
@ -832,41 +832,18 @@ static BOOL gMenuItemsExecuteCommands = YES;
|
||||
return [super performKeyEquivalent:theEvent];
|
||||
}
|
||||
|
||||
// Plugins normally eat all keyboard commands, this hack mitigates
|
||||
// the problem.
|
||||
BOOL handleForPluginHack = NO;
|
||||
NSResponder *firstResponder = [keyWindow firstResponder];
|
||||
if (firstResponder &&
|
||||
[firstResponder isKindOfClass:[ChildView class]] &&
|
||||
[(ChildView*)firstResponder isPluginView]) {
|
||||
handleForPluginHack = YES;
|
||||
// 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".
|
||||
UInt32 modifierFlags = [theEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask;
|
||||
if (modifierFlags == NSCommandKeyMask) {
|
||||
NSString *unmodchars = [theEvent charactersIgnoringModifiers];
|
||||
if ([unmodchars length] == 1) {
|
||||
if ([unmodchars characterAtIndex:0] == nsMenuBarX::GetLocalizedAccelKey("key_selectAll")) {
|
||||
handleForPluginHack = NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gMenuItemsExecuteCommands = handleForPluginHack;
|
||||
gMenuItemsExecuteCommands = NO;
|
||||
[super performKeyEquivalent:theEvent];
|
||||
gMenuItemsExecuteCommands = YES; // return to default
|
||||
|
||||
// Return YES if we invoked a command and there is now no key window or we changed
|
||||
// the first responder. In this case we do not want to propagate the event because
|
||||
// we don't want it handled again.
|
||||
if (handleForPluginHack) {
|
||||
if (![NSApp keyWindow] || [[NSApp keyWindow] firstResponder] != firstResponder) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
// Return NO so that we can handle the event via NSView's "keyDown:".
|
||||
return NO;
|
||||
|
@ -331,6 +331,12 @@ struct ParamTraits<mozilla::WidgetKeyboardEvent>
|
||||
WriteParam(aMsg, aParam.mIsRepeat);
|
||||
WriteParam(aMsg, aParam.location);
|
||||
WriteParam(aMsg, aParam.mUniqueId);
|
||||
#ifdef XP_MACOSX
|
||||
WriteParam(aMsg, aParam.mNativeKeyCode);
|
||||
WriteParam(aMsg, aParam.mNativeModifierFlags);
|
||||
WriteParam(aMsg, aParam.mNativeCharacters);
|
||||
WriteParam(aMsg, aParam.mNativeCharactersIgnoringModifiers);
|
||||
#endif
|
||||
// An OS-specific native event might be attached in |mNativeKeyEvent|, but
|
||||
// that cannot be copied across process boundaries.
|
||||
}
|
||||
@ -350,7 +356,14 @@ struct ParamTraits<mozilla::WidgetKeyboardEvent>
|
||||
ReadParam(aMsg, aIter, &aResult->isChar) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mIsRepeat) &&
|
||||
ReadParam(aMsg, aIter, &aResult->location) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mUniqueId))
|
||||
ReadParam(aMsg, aIter, &aResult->mUniqueId)
|
||||
#ifdef XP_MACOSX
|
||||
&& ReadParam(aMsg, aIter, &aResult->mNativeKeyCode)
|
||||
&& ReadParam(aMsg, aIter, &aResult->mNativeModifierFlags)
|
||||
&& ReadParam(aMsg, aIter, &aResult->mNativeCharacters)
|
||||
&& ReadParam(aMsg, aIter, &aResult->mNativeCharactersIgnoringModifiers)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
aResult->mKeyNameIndex = static_cast<mozilla::KeyNameIndex>(keyNameIndex);
|
||||
aResult->mCodeNameIndex =
|
||||
|
Loading…
Reference in New Issue
Block a user