mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-02 13:27:33 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
1186
widget/BasicEvents.h
Normal file
1186
widget/BasicEvents.h
Normal file
File diff suppressed because it is too large
Load diff
52
widget/CommandList.h
Normal file
52
widget/CommandList.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
/**
|
||||
* Define NS_DEFIVE_COMMAND(aName, aCommandStr) before including this.
|
||||
* @param aName The name useful in C++ of the command.
|
||||
* @param aCommandStr The command string in JS.
|
||||
*/
|
||||
|
||||
NS_DEFINE_COMMAND(BeginLine, cmd_beginLine)
|
||||
NS_DEFINE_COMMAND(CharNext, cmd_charNext)
|
||||
NS_DEFINE_COMMAND(CharPrevious, cmd_charPrevious)
|
||||
NS_DEFINE_COMMAND(Copy, cmd_copy)
|
||||
NS_DEFINE_COMMAND(Cut, cmd_cut)
|
||||
NS_DEFINE_COMMAND(Delete, cmd_delete)
|
||||
NS_DEFINE_COMMAND(DeleteCharBackward, cmd_deleteCharBackward)
|
||||
NS_DEFINE_COMMAND(DeleteCharForward, cmd_deleteCharForward)
|
||||
NS_DEFINE_COMMAND(DeleteToBeginningOfLine, cmd_deleteToBeginningOfLine)
|
||||
NS_DEFINE_COMMAND(DeleteToEndOfLine, cmd_deleteToEndOfLine)
|
||||
NS_DEFINE_COMMAND(DeleteWordBackward, cmd_deleteWordBackward)
|
||||
NS_DEFINE_COMMAND(DeleteWordForward, cmd_deleteWordForward)
|
||||
NS_DEFINE_COMMAND(EndLine, cmd_endLine)
|
||||
NS_DEFINE_COMMAND(LineNext, cmd_lineNext)
|
||||
NS_DEFINE_COMMAND(LinePrevious, cmd_linePrevious)
|
||||
NS_DEFINE_COMMAND(MoveBottom, cmd_moveBottom)
|
||||
NS_DEFINE_COMMAND(MovePageDown, cmd_movePageDown)
|
||||
NS_DEFINE_COMMAND(MovePageUp, cmd_movePageUp)
|
||||
NS_DEFINE_COMMAND(MoveTop, cmd_moveTop)
|
||||
NS_DEFINE_COMMAND(Paste, cmd_paste)
|
||||
NS_DEFINE_COMMAND(ScrollBottom, cmd_scrollBottom)
|
||||
NS_DEFINE_COMMAND(ScrollLineDown, cmd_scrollLineDown)
|
||||
NS_DEFINE_COMMAND(ScrollLineUp, cmd_scrollLineUp)
|
||||
NS_DEFINE_COMMAND(ScrollPageDown, cmd_scrollPageDown)
|
||||
NS_DEFINE_COMMAND(ScrollPageUp, cmd_scrollPageUp)
|
||||
NS_DEFINE_COMMAND(ScrollTop, cmd_scrollTop)
|
||||
NS_DEFINE_COMMAND(SelectAll, cmd_selectAll)
|
||||
NS_DEFINE_COMMAND(SelectBeginLine, cmd_selectBeginLine)
|
||||
NS_DEFINE_COMMAND(SelectBottom, cmd_selectBottom)
|
||||
NS_DEFINE_COMMAND(SelectCharNext, cmd_selectCharNext)
|
||||
NS_DEFINE_COMMAND(SelectCharPrevious, cmd_selectCharPrevious)
|
||||
NS_DEFINE_COMMAND(SelectEndLine, cmd_selectEndLine)
|
||||
NS_DEFINE_COMMAND(SelectLineNext, cmd_selectLineNext)
|
||||
NS_DEFINE_COMMAND(SelectLinePrevious, cmd_selectLinePrevious)
|
||||
NS_DEFINE_COMMAND(SelectPageDown, cmd_selectPageDown)
|
||||
NS_DEFINE_COMMAND(SelectPageUp, cmd_selectPageUp)
|
||||
NS_DEFINE_COMMAND(SelectTop, cmd_selectTop)
|
||||
NS_DEFINE_COMMAND(SelectWordNext, cmd_selectWordNext)
|
||||
NS_DEFINE_COMMAND(SelectWordPrevious, cmd_selectWordPrevious)
|
||||
NS_DEFINE_COMMAND(WordNext, cmd_wordNext)
|
||||
NS_DEFINE_COMMAND(WordPrevious, cmd_wordPrevious)
|
||||
84
widget/CompositorWidget.cpp
Normal file
84
widget/CompositorWidget.cpp
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/* 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 "CompositorWidget.h"
|
||||
#include "GLConsts.h"
|
||||
#include "nsBaseWidget.h"
|
||||
#include "VsyncDispatcher.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
CompositorWidget::~CompositorWidget()
|
||||
{
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::DrawTarget>
|
||||
CompositorWidget::StartRemoteDrawing()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
CompositorWidget::CleanupRemoteDrawing()
|
||||
{
|
||||
mLastBackBuffer = nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::DrawTarget>
|
||||
CompositorWidget::GetBackBufferDrawTarget(gfx::DrawTarget* aScreenTarget,
|
||||
const LayoutDeviceIntRect& aRect,
|
||||
const LayoutDeviceIntRect& aClearRect)
|
||||
{
|
||||
MOZ_ASSERT(aScreenTarget);
|
||||
gfx::SurfaceFormat format =
|
||||
aScreenTarget->GetFormat() == gfx::SurfaceFormat::B8G8R8X8 ? gfx::SurfaceFormat::B8G8R8X8 : gfx::SurfaceFormat::B8G8R8A8;
|
||||
gfx::IntSize size = aRect.ToUnknownRect().Size();
|
||||
gfx::IntSize clientSize(GetClientSize().ToUnknownSize());
|
||||
|
||||
RefPtr<gfx::DrawTarget> target;
|
||||
// Re-use back buffer if possible
|
||||
if (mLastBackBuffer &&
|
||||
mLastBackBuffer->GetBackendType() == aScreenTarget->GetBackendType() &&
|
||||
mLastBackBuffer->GetFormat() == format &&
|
||||
size <= mLastBackBuffer->GetSize() &&
|
||||
mLastBackBuffer->GetSize() <= clientSize) {
|
||||
target = mLastBackBuffer;
|
||||
target->SetTransform(gfx::Matrix());
|
||||
if (!aClearRect.IsEmpty()) {
|
||||
gfx::IntRect clearRect = aClearRect.ToUnknownRect() - aRect.ToUnknownRect().TopLeft();
|
||||
target->ClearRect(gfx::Rect(clearRect.x, clearRect.y, clearRect.width, clearRect.height));
|
||||
}
|
||||
} else {
|
||||
target = aScreenTarget->CreateSimilarDrawTarget(size, format);
|
||||
mLastBackBuffer = target;
|
||||
}
|
||||
return target.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::SourceSurface>
|
||||
CompositorWidget::EndBackBufferDrawing()
|
||||
{
|
||||
RefPtr<gfx::SourceSurface> surface = mLastBackBuffer ? mLastBackBuffer->Snapshot() : nullptr;
|
||||
return surface.forget();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
CompositorWidget::GetGLFrameBufferFormat()
|
||||
{
|
||||
return LOCAL_GL_RGBA;
|
||||
}
|
||||
|
||||
RefPtr<VsyncObserver>
|
||||
CompositorWidget::GetVsyncObserver() const
|
||||
{
|
||||
// This should only used when the widget is in the GPU process, and should be
|
||||
// implemented by IPDL-enabled CompositorWidgets.
|
||||
// GPU process does not have a CompositorVsyncDispatcher.
|
||||
MOZ_ASSERT_UNREACHABLE("Must be implemented by derived class");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
286
widget/CompositorWidget.h
Normal file
286
widget/CompositorWidget.h
Normal file
|
|
@ -0,0 +1,286 @@
|
|||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_widget_CompositorWidget_h__
|
||||
#define mozilla_widget_CompositorWidget_h__
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "Units.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/layers/LayersTypes.h"
|
||||
|
||||
class nsIWidget;
|
||||
class nsBaseWidget;
|
||||
|
||||
namespace mozilla {
|
||||
class VsyncObserver;
|
||||
namespace layers {
|
||||
class Compositor;
|
||||
class LayerManagerComposite;
|
||||
class Compositor;
|
||||
class Composer2D;
|
||||
} // namespace layers
|
||||
namespace gfx {
|
||||
class DrawTarget;
|
||||
class SourceSurface;
|
||||
} // namespace gfx
|
||||
namespace widget {
|
||||
|
||||
class WinCompositorWidget;
|
||||
class X11CompositorWidget;
|
||||
class AndroidCompositorWidget;
|
||||
class CompositorWidgetInitData;
|
||||
|
||||
// Gecko widgets usually need to communicate with the CompositorWidget with
|
||||
// platform-specific messages (for example to update the window size or
|
||||
// transparency). This functionality is controlled through a "host". Since
|
||||
// this functionality is platform-dependent, it is only forward declared
|
||||
// here.
|
||||
class CompositorWidgetDelegate;
|
||||
|
||||
// Platforms that support out-of-process widgets.
|
||||
#if defined(XP_WIN) || defined(MOZ_X11)
|
||||
// CompositorWidgetParent should implement CompositorWidget and
|
||||
// PCompositorWidgetParent.
|
||||
class CompositorWidgetParent;
|
||||
|
||||
// CompositorWidgetChild should implement CompositorWidgetDelegate and
|
||||
// PCompositorWidgetChild.
|
||||
class CompositorWidgetChild;
|
||||
|
||||
# define MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
|
||||
#endif
|
||||
|
||||
class WidgetRenderingContext
|
||||
{
|
||||
public:
|
||||
#if defined(XP_MACOSX)
|
||||
WidgetRenderingContext() : mLayerManager(nullptr) {}
|
||||
layers::LayerManagerComposite* mLayerManager;
|
||||
#elif defined(MOZ_WIDGET_ANDROID)
|
||||
WidgetRenderingContext() : mCompositor(nullptr) {}
|
||||
layers::Compositor* mCompositor;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* Access to a widget from the compositor is restricted to these methods.
|
||||
*/
|
||||
class CompositorWidget
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(mozilla::widget::CompositorWidget)
|
||||
|
||||
/**
|
||||
* Create an in-process compositor widget. aWidget may be ignored if the
|
||||
* platform does not require it.
|
||||
*/
|
||||
static RefPtr<CompositorWidget> CreateLocal(const CompositorWidgetInitData& aInitData, nsIWidget* aWidget);
|
||||
|
||||
/**
|
||||
* Called before rendering using OMTC. Returns false when the widget is
|
||||
* not ready to be rendered (for example while the window is closed).
|
||||
*
|
||||
* Always called from the compositing thread, which may be the main-thread if
|
||||
* OMTC is not enabled.
|
||||
*/
|
||||
virtual bool PreRender(WidgetRenderingContext* aContext) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after rendering using OMTC. Not called when rendering was
|
||||
* cancelled by a negative return value from PreRender.
|
||||
*
|
||||
* Always called from the compositing thread, which may be the main-thread if
|
||||
* OMTC is not enabled.
|
||||
*/
|
||||
virtual void PostRender(WidgetRenderingContext* aContext)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Called before the LayerManager draws the layer tree.
|
||||
*
|
||||
* Always called from the compositing thread.
|
||||
*/
|
||||
virtual void DrawWindowUnderlay(WidgetRenderingContext* aContext,
|
||||
LayoutDeviceIntRect aRect)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Called after the LayerManager draws the layer tree
|
||||
*
|
||||
* Always called from the compositing thread.
|
||||
*/
|
||||
virtual void DrawWindowOverlay(WidgetRenderingContext* aContext,
|
||||
LayoutDeviceIntRect aRect)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Return a DrawTarget for the window which can be composited into.
|
||||
*
|
||||
* Called by BasicCompositor on the compositor thread for OMTC drawing
|
||||
* before each composition.
|
||||
*
|
||||
* The window may specify its buffer mode. If unspecified, it is assumed
|
||||
* to require double-buffering.
|
||||
*/
|
||||
virtual already_AddRefed<gfx::DrawTarget> StartRemoteDrawing();
|
||||
virtual already_AddRefed<gfx::DrawTarget>
|
||||
StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion,
|
||||
layers::BufferMode* aBufferMode)
|
||||
{
|
||||
return StartRemoteDrawing();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that what was painted into the DrawTarget returned from
|
||||
* StartRemoteDrawing reaches the screen.
|
||||
*
|
||||
* Called by BasicCompositor on the compositor thread for OMTC drawing
|
||||
* after each composition.
|
||||
*/
|
||||
virtual void EndRemoteDrawing()
|
||||
{}
|
||||
virtual void EndRemoteDrawingInRegion(gfx::DrawTarget* aDrawTarget,
|
||||
LayoutDeviceIntRegion& aInvalidRegion)
|
||||
{
|
||||
EndRemoteDrawing();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true when it is better to defer EndRemoteDrawing().
|
||||
*
|
||||
* Called by BasicCompositor on the compositor thread for OMTC drawing
|
||||
* after each composition.
|
||||
*/
|
||||
virtual bool NeedsToDeferEndRemoteDrawing() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when shutting down the LayerManager to clean-up any cached resources.
|
||||
*
|
||||
* Always called from the compositing thread.
|
||||
*/
|
||||
virtual void CleanupWindowEffects()
|
||||
{}
|
||||
|
||||
/**
|
||||
* A hook for the widget to prepare a Compositor, during the latter's initialization.
|
||||
*
|
||||
* If this method returns true, it means that the widget will be able to
|
||||
* present frames from the compoositor.
|
||||
*
|
||||
* Returning false will cause the compositor's initialization to fail, and
|
||||
* a different compositor backend will be used (if any).
|
||||
*/
|
||||
virtual bool InitCompositor(layers::Compositor* aCompositor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the size of the drawable area of the widget.
|
||||
*/
|
||||
virtual LayoutDeviceIntSize GetClientSize() = 0;
|
||||
|
||||
/**
|
||||
* Return the internal format of the default framebuffer for this
|
||||
* widget.
|
||||
*/
|
||||
virtual uint32_t GetGLFrameBufferFormat();
|
||||
|
||||
/**
|
||||
* If this widget has a more efficient composer available for its
|
||||
* native framebuffer, return it.
|
||||
*
|
||||
* This can be called from a non-main thread, but that thread must
|
||||
* hold a strong reference to this.
|
||||
*/
|
||||
virtual layers::Composer2D* GetComposer2D() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Access the underlying nsIWidget. This method will be removed when the compositor no longer
|
||||
* depends on nsIWidget on any platform.
|
||||
*/
|
||||
virtual nsIWidget* RealWidget() = 0;
|
||||
|
||||
/**
|
||||
* Clean up any resources used by Start/EndRemoteDrawing.
|
||||
*
|
||||
* Called by BasicCompositor on the compositor thread for OMTC drawing
|
||||
* when the compositor is destroyed.
|
||||
*/
|
||||
virtual void CleanupRemoteDrawing();
|
||||
|
||||
/**
|
||||
* Return a key that can represent the widget object round-trip across the
|
||||
* CompositorBridge channel. This only needs to be implemented on GTK and
|
||||
* Windows.
|
||||
*
|
||||
* The key must be the nsIWidget pointer cast to a uintptr_t. See
|
||||
* CompositorBridgeChild::RecvHideAllPlugins and
|
||||
* CompositorBridgeParent::SendHideAllPlugins.
|
||||
*/
|
||||
virtual uintptr_t GetWidgetKey() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a backbuffer for the software compositor.
|
||||
*/
|
||||
virtual already_AddRefed<gfx::DrawTarget>
|
||||
GetBackBufferDrawTarget(gfx::DrawTarget* aScreenTarget,
|
||||
const LayoutDeviceIntRect& aRect,
|
||||
const LayoutDeviceIntRect& aClearRect);
|
||||
|
||||
/**
|
||||
* Ensure end of composition to back buffer.
|
||||
*
|
||||
* Called by BasicCompositor on the compositor thread for OMTC drawing
|
||||
* after each composition to back buffer.
|
||||
*/
|
||||
virtual already_AddRefed<gfx::SourceSurface> EndBackBufferDrawing();
|
||||
|
||||
/**
|
||||
* Observe or unobserve vsync.
|
||||
*/
|
||||
virtual void ObserveVsync(VsyncObserver* aObserver) = 0;
|
||||
|
||||
/**
|
||||
* This is only used by out-of-process compositors.
|
||||
*/
|
||||
virtual RefPtr<VsyncObserver> GetVsyncObserver() const;
|
||||
|
||||
virtual WinCompositorWidget* AsWindows() {
|
||||
return nullptr;
|
||||
}
|
||||
virtual X11CompositorWidget* AsX11() {
|
||||
return nullptr;
|
||||
}
|
||||
virtual AndroidCompositorWidget* AsAndroid() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the platform-specific delegate for the widget, if any.
|
||||
*/
|
||||
virtual CompositorWidgetDelegate* AsDelegate() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~CompositorWidget();
|
||||
|
||||
// Back buffer of BasicCompositor
|
||||
RefPtr<gfx::DrawTarget> mLastBackBuffer;
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
1381
widget/ContentCache.cpp
Normal file
1381
widget/ContentCache.cpp
Normal file
File diff suppressed because it is too large
Load diff
449
widget/ContentCache.h
Normal file
449
widget/ContentCache.h
Normal file
|
|
@ -0,0 +1,449 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_ContentCache_h
|
||||
#define mozilla_ContentCache_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "mozilla/WritingModes.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "Units.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ContentCacheInParent;
|
||||
|
||||
/**
|
||||
* ContentCache stores various information of the child content.
|
||||
* This class has members which are necessary both in parent process and
|
||||
* content process.
|
||||
*/
|
||||
|
||||
class ContentCache
|
||||
{
|
||||
public:
|
||||
typedef InfallibleTArray<LayoutDeviceIntRect> RectArray;
|
||||
typedef widget::IMENotification IMENotification;
|
||||
|
||||
ContentCache();
|
||||
|
||||
protected:
|
||||
// Whole text in the target
|
||||
nsString mText;
|
||||
|
||||
// Start offset of the composition string.
|
||||
uint32_t mCompositionStart;
|
||||
|
||||
enum
|
||||
{
|
||||
ePrevCharRect = 1,
|
||||
eNextCharRect = 0
|
||||
};
|
||||
|
||||
struct Selection final
|
||||
{
|
||||
// Following values are offset in "flat text".
|
||||
uint32_t mAnchor;
|
||||
uint32_t mFocus;
|
||||
|
||||
WritingMode mWritingMode;
|
||||
|
||||
// Character rects at previous and next character of mAnchor and mFocus.
|
||||
// The reason why ContentCache needs to store each previous character of
|
||||
// them is IME may query character rect of the last character of a line
|
||||
// when caret is at the end of the line.
|
||||
// Note that use ePrevCharRect and eNextCharRect for accessing each item.
|
||||
LayoutDeviceIntRect mAnchorCharRects[2];
|
||||
LayoutDeviceIntRect mFocusCharRects[2];
|
||||
|
||||
// Whole rect of selected text. This is empty if the selection is collapsed.
|
||||
LayoutDeviceIntRect mRect;
|
||||
|
||||
Selection()
|
||||
: mAnchor(UINT32_MAX)
|
||||
, mFocus(UINT32_MAX)
|
||||
{
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
mAnchor = mFocus = UINT32_MAX;
|
||||
mWritingMode = WritingMode();
|
||||
ClearAnchorCharRects();
|
||||
ClearFocusCharRects();
|
||||
mRect.SetEmpty();
|
||||
}
|
||||
|
||||
void ClearAnchorCharRects()
|
||||
{
|
||||
for (size_t i = 0; i < ArrayLength(mAnchorCharRects); i++) {
|
||||
mAnchorCharRects[i].SetEmpty();
|
||||
}
|
||||
}
|
||||
void ClearFocusCharRects()
|
||||
{
|
||||
for (size_t i = 0; i < ArrayLength(mFocusCharRects); i++) {
|
||||
mFocusCharRects[i].SetEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return mAnchor != UINT32_MAX && mFocus != UINT32_MAX;
|
||||
}
|
||||
bool Collapsed() const
|
||||
{
|
||||
NS_ASSERTION(IsValid(),
|
||||
"The caller should check if the selection is valid");
|
||||
return mFocus == mAnchor;
|
||||
}
|
||||
bool Reversed() const
|
||||
{
|
||||
NS_ASSERTION(IsValid(),
|
||||
"The caller should check if the selection is valid");
|
||||
return mFocus < mAnchor;
|
||||
}
|
||||
uint32_t StartOffset() const
|
||||
{
|
||||
NS_ASSERTION(IsValid(),
|
||||
"The caller should check if the selection is valid");
|
||||
return Reversed() ? mFocus : mAnchor;
|
||||
}
|
||||
uint32_t EndOffset() const
|
||||
{
|
||||
NS_ASSERTION(IsValid(),
|
||||
"The caller should check if the selection is valid");
|
||||
return Reversed() ? mAnchor : mFocus;
|
||||
}
|
||||
uint32_t Length() const
|
||||
{
|
||||
NS_ASSERTION(IsValid(),
|
||||
"The caller should check if the selection is valid");
|
||||
return Reversed() ? mAnchor - mFocus : mFocus - mAnchor;
|
||||
}
|
||||
LayoutDeviceIntRect StartCharRect() const
|
||||
{
|
||||
NS_ASSERTION(IsValid(),
|
||||
"The caller should check if the selection is valid");
|
||||
return Reversed() ? mFocusCharRects[eNextCharRect] :
|
||||
mAnchorCharRects[eNextCharRect];
|
||||
}
|
||||
LayoutDeviceIntRect EndCharRect() const
|
||||
{
|
||||
NS_ASSERTION(IsValid(),
|
||||
"The caller should check if the selection is valid");
|
||||
return Reversed() ? mAnchorCharRects[eNextCharRect] :
|
||||
mFocusCharRects[eNextCharRect];
|
||||
}
|
||||
} mSelection;
|
||||
|
||||
bool IsSelectionValid() const
|
||||
{
|
||||
return mSelection.IsValid() && mSelection.EndOffset() <= mText.Length();
|
||||
}
|
||||
|
||||
// Stores first char rect because Yosemite's Japanese IME sometimes tries
|
||||
// to query it. If there is no text, this is caret rect.
|
||||
LayoutDeviceIntRect mFirstCharRect;
|
||||
|
||||
struct Caret final
|
||||
{
|
||||
uint32_t mOffset;
|
||||
LayoutDeviceIntRect mRect;
|
||||
|
||||
Caret()
|
||||
: mOffset(UINT32_MAX)
|
||||
{
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
mOffset = UINT32_MAX;
|
||||
mRect.SetEmpty();
|
||||
}
|
||||
|
||||
bool IsValid() const { return mOffset != UINT32_MAX; }
|
||||
|
||||
uint32_t Offset() const
|
||||
{
|
||||
NS_ASSERTION(IsValid(),
|
||||
"The caller should check if the caret is valid");
|
||||
return mOffset;
|
||||
}
|
||||
} mCaret;
|
||||
|
||||
struct TextRectArray final
|
||||
{
|
||||
uint32_t mStart;
|
||||
RectArray mRects;
|
||||
|
||||
TextRectArray()
|
||||
: mStart(UINT32_MAX)
|
||||
{
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
mStart = UINT32_MAX;
|
||||
mRects.Clear();
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
if (mStart == UINT32_MAX) {
|
||||
return false;
|
||||
}
|
||||
CheckedInt<uint32_t> endOffset =
|
||||
CheckedInt<uint32_t>(mStart) + mRects.Length();
|
||||
return endOffset.isValid();
|
||||
}
|
||||
bool HasRects() const
|
||||
{
|
||||
return IsValid() && !mRects.IsEmpty();
|
||||
}
|
||||
uint32_t StartOffset() const
|
||||
{
|
||||
NS_ASSERTION(IsValid(),
|
||||
"The caller should check if the caret is valid");
|
||||
return mStart;
|
||||
}
|
||||
uint32_t EndOffset() const
|
||||
{
|
||||
NS_ASSERTION(IsValid(),
|
||||
"The caller should check if the caret is valid");
|
||||
if (!IsValid()) {
|
||||
return UINT32_MAX;
|
||||
}
|
||||
return mStart + mRects.Length();
|
||||
}
|
||||
bool InRange(uint32_t aOffset) const
|
||||
{
|
||||
return IsValid() &&
|
||||
StartOffset() <= aOffset && aOffset < EndOffset();
|
||||
}
|
||||
bool InRange(uint32_t aOffset, uint32_t aLength) const
|
||||
{
|
||||
CheckedInt<uint32_t> endOffset =
|
||||
CheckedInt<uint32_t>(aOffset) + aLength;
|
||||
if (NS_WARN_IF(!endOffset.isValid())) {
|
||||
return false;
|
||||
}
|
||||
return InRange(aOffset) && aOffset + aLength <= EndOffset();
|
||||
}
|
||||
bool IsOverlappingWith(uint32_t aOffset, uint32_t aLength) const
|
||||
{
|
||||
if (!HasRects() || aOffset == UINT32_MAX || !aLength) {
|
||||
return false;
|
||||
}
|
||||
CheckedInt<uint32_t> endOffset =
|
||||
CheckedInt<uint32_t>(aOffset) + aLength;
|
||||
if (NS_WARN_IF(!endOffset.isValid())) {
|
||||
return false;
|
||||
}
|
||||
return aOffset < EndOffset() && endOffset.value() > mStart;
|
||||
}
|
||||
LayoutDeviceIntRect GetRect(uint32_t aOffset) const;
|
||||
LayoutDeviceIntRect GetUnionRect(uint32_t aOffset, uint32_t aLength) const;
|
||||
LayoutDeviceIntRect GetUnionRectAsFarAsPossible(
|
||||
uint32_t aOffset, uint32_t aLength,
|
||||
bool aRoundToExistingOffset) const;
|
||||
} mTextRectArray;
|
||||
|
||||
LayoutDeviceIntRect mEditorRect;
|
||||
|
||||
friend class ContentCacheInParent;
|
||||
friend struct IPC::ParamTraits<ContentCache>;
|
||||
};
|
||||
|
||||
class ContentCacheInChild final : public ContentCache
|
||||
{
|
||||
public:
|
||||
ContentCacheInChild();
|
||||
|
||||
/**
|
||||
* When IME loses focus, this should be called and making this forget the
|
||||
* content for reducing footprint.
|
||||
*/
|
||||
void Clear();
|
||||
|
||||
/**
|
||||
* Cache*() retrieves the latest content information and store them.
|
||||
* Be aware, CacheSelection() calls CacheTextRects(), and also CacheText()
|
||||
* calls CacheSelection(). So, related data is also retrieved automatically.
|
||||
*/
|
||||
bool CacheEditorRect(nsIWidget* aWidget,
|
||||
const IMENotification* aNotification = nullptr);
|
||||
bool CacheSelection(nsIWidget* aWidget,
|
||||
const IMENotification* aNotification = nullptr);
|
||||
bool CacheText(nsIWidget* aWidget,
|
||||
const IMENotification* aNotification = nullptr);
|
||||
|
||||
bool CacheAll(nsIWidget* aWidget,
|
||||
const IMENotification* aNotification = nullptr);
|
||||
|
||||
/**
|
||||
* SetSelection() modifies selection with specified raw data. And also this
|
||||
* tries to retrieve text rects too.
|
||||
*/
|
||||
void SetSelection(nsIWidget* aWidget,
|
||||
uint32_t aStartOffset,
|
||||
uint32_t aLength,
|
||||
bool aReversed,
|
||||
const WritingMode& aWritingMode);
|
||||
|
||||
private:
|
||||
bool QueryCharRect(nsIWidget* aWidget,
|
||||
uint32_t aOffset,
|
||||
LayoutDeviceIntRect& aCharRect) const;
|
||||
bool QueryCharRectArray(nsIWidget* aWidget,
|
||||
uint32_t aOffset,
|
||||
uint32_t aLength,
|
||||
RectArray& aCharRectArray) const;
|
||||
bool CacheCaret(nsIWidget* aWidget,
|
||||
const IMENotification* aNotification = nullptr);
|
||||
bool CacheTextRects(nsIWidget* aWidget,
|
||||
const IMENotification* aNotification = nullptr);
|
||||
};
|
||||
|
||||
class ContentCacheInParent final : public ContentCache
|
||||
{
|
||||
public:
|
||||
ContentCacheInParent();
|
||||
|
||||
/**
|
||||
* AssignContent() is called when TabParent receives ContentCache from
|
||||
* the content process. This doesn't copy composition information because
|
||||
* it's managed by TabParent itself.
|
||||
*/
|
||||
void AssignContent(const ContentCache& aOther,
|
||||
nsIWidget* aWidget,
|
||||
const IMENotification* aNotification = nullptr);
|
||||
|
||||
/**
|
||||
* HandleQueryContentEvent() sets content data to aEvent.mReply.
|
||||
*
|
||||
* For eQuerySelectedText, fail if the cache doesn't contain the whole
|
||||
* selected range. (This shouldn't happen because PuppetWidget should have
|
||||
* already sent the whole selection.)
|
||||
*
|
||||
* For eQueryTextContent, fail only if the cache doesn't overlap with
|
||||
* the queried range. Note the difference from above. We use
|
||||
* this behavior because a normal eQueryTextContent event is allowed to
|
||||
* have out-of-bounds offsets, so that widget can request content without
|
||||
* knowing the exact length of text. It's up to widget to handle cases when
|
||||
* the returned offset/length are different from the queried offset/length.
|
||||
*
|
||||
* For eQueryTextRect, fail if cached offset/length aren't equals to input.
|
||||
* Cocoa widget always queries selected offset, so it works on it.
|
||||
*
|
||||
* For eQueryCaretRect, fail if cached offset isn't equals to input
|
||||
*
|
||||
* For eQueryEditorRect, always success
|
||||
*/
|
||||
bool HandleQueryContentEvent(WidgetQueryContentEvent& aEvent,
|
||||
nsIWidget* aWidget) const;
|
||||
|
||||
/**
|
||||
* OnCompositionEvent() should be called before sending composition string.
|
||||
* This returns true if the event should be sent. Otherwise, false.
|
||||
*/
|
||||
bool OnCompositionEvent(const WidgetCompositionEvent& aCompositionEvent);
|
||||
|
||||
/**
|
||||
* OnSelectionEvent() should be called before sending selection event.
|
||||
*/
|
||||
void OnSelectionEvent(const WidgetSelectionEvent& aSelectionEvent);
|
||||
|
||||
/**
|
||||
* OnEventNeedingAckHandled() should be called after the child process
|
||||
* handles a sent event which needs acknowledging.
|
||||
*
|
||||
* WARNING: This may send notifications to IME. That might cause destroying
|
||||
* TabParent or aWidget. Therefore, the caller must not destroy
|
||||
* this instance during a call of this method.
|
||||
*/
|
||||
void OnEventNeedingAckHandled(nsIWidget* aWidget, EventMessage aMessage);
|
||||
|
||||
/**
|
||||
* RequestIMEToCommitComposition() requests aWidget to commit or cancel
|
||||
* composition. If it's handled synchronously, this returns true.
|
||||
*
|
||||
* @param aWidget The widget to be requested to commit or cancel
|
||||
* the composition.
|
||||
* @param aCancel When the caller tries to cancel the composition, true.
|
||||
* Otherwise, i.e., tries to commit the composition, false.
|
||||
* @param aCommittedString The committed string (i.e., the last data of
|
||||
* dispatched composition events during requesting
|
||||
* IME to commit composition.
|
||||
* @return Whether the composition is actually committed
|
||||
* synchronously.
|
||||
*/
|
||||
bool RequestIMEToCommitComposition(nsIWidget* aWidget,
|
||||
bool aCancel,
|
||||
nsAString& aCommittedString);
|
||||
|
||||
/**
|
||||
* MaybeNotifyIME() may notify IME of the notification. If child process
|
||||
* hasn't been handled all sending events yet, this stores the notification
|
||||
* and flush it later.
|
||||
*/
|
||||
void MaybeNotifyIME(nsIWidget* aWidget,
|
||||
const IMENotification& aNotification);
|
||||
|
||||
private:
|
||||
IMENotification mPendingSelectionChange;
|
||||
IMENotification mPendingTextChange;
|
||||
IMENotification mPendingLayoutChange;
|
||||
IMENotification mPendingCompositionUpdate;
|
||||
|
||||
// This is not nullptr only while the instance is requesting IME to
|
||||
// composition. Then, data value of dispatched composition events should
|
||||
// be stored into the instance.
|
||||
nsAString* mCommitStringByRequest;
|
||||
// mPendingEventsNeedingAck is increased before sending a composition event or
|
||||
// a selection event and decreased after they are received in the child
|
||||
// process.
|
||||
uint32_t mPendingEventsNeedingAck;
|
||||
// mCompositionStartInChild stores current composition start offset in the
|
||||
// remote process.
|
||||
uint32_t mCompositionStartInChild;
|
||||
// mPendingCompositionCount is number of compositions which started in widget
|
||||
// but not yet handled in the child process.
|
||||
uint8_t mPendingCompositionCount;
|
||||
// mWidgetHasComposition is true when the widget in this process thinks that
|
||||
// IME has composition. So, this is set to true when eCompositionStart is
|
||||
// dispatched and set to false when eCompositionCommit(AsIs) is dispatched.
|
||||
bool mWidgetHasComposition;
|
||||
|
||||
/**
|
||||
* When following methods' aRoundToExistingOffset is true, even if specified
|
||||
* offset or range is out of bounds, the result is computed with the existing
|
||||
* cache forcibly.
|
||||
*/
|
||||
bool GetCaretRect(uint32_t aOffset,
|
||||
bool aRoundToExistingOffset,
|
||||
LayoutDeviceIntRect& aCaretRect) const;
|
||||
bool GetTextRect(uint32_t aOffset,
|
||||
bool aRoundToExistingOffset,
|
||||
LayoutDeviceIntRect& aTextRect) const;
|
||||
bool GetUnionTextRects(uint32_t aOffset,
|
||||
uint32_t aLength,
|
||||
bool aRoundToExistingOffset,
|
||||
LayoutDeviceIntRect& aUnionTextRect) const;
|
||||
|
||||
void FlushPendingNotifications(nsIWidget* aWidget);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_ContentCache_h
|
||||
388
widget/ContentEvents.h
Normal file
388
widget/ContentEvents.h
Normal file
|
|
@ -0,0 +1,388 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_ContentEvents_h__
|
||||
#define mozilla_ContentEvents_h__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mozilla/BasicEvents.h"
|
||||
#include "mozilla/dom/DataTransfer.h"
|
||||
#include "mozilla/dom/EventTarget.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsRect.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
class nsIContent;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::InternalScrollPortEvent
|
||||
******************************************************************************/
|
||||
|
||||
class InternalScrollPortEvent : public WidgetGUIEvent
|
||||
{
|
||||
public:
|
||||
virtual InternalScrollPortEvent* AsScrollPortEvent() override
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
enum OrientType
|
||||
{
|
||||
eVertical,
|
||||
eHorizontal,
|
||||
eBoth
|
||||
};
|
||||
|
||||
InternalScrollPortEvent(bool aIsTrusted, EventMessage aMessage,
|
||||
nsIWidget* aWidget)
|
||||
: WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eScrollPortEventClass)
|
||||
, mOrient(eVertical)
|
||||
{
|
||||
}
|
||||
|
||||
virtual WidgetEvent* Duplicate() const override
|
||||
{
|
||||
MOZ_ASSERT(mClass == eScrollPortEventClass,
|
||||
"Duplicate() must be overridden by sub class");
|
||||
// Not copying widget, it is a weak reference.
|
||||
InternalScrollPortEvent* result =
|
||||
new InternalScrollPortEvent(false, mMessage, nullptr);
|
||||
result->AssignScrollPortEventData(*this, true);
|
||||
result->mFlags = mFlags;
|
||||
return result;
|
||||
}
|
||||
|
||||
OrientType mOrient;
|
||||
|
||||
void AssignScrollPortEventData(const InternalScrollPortEvent& aEvent,
|
||||
bool aCopyTargets)
|
||||
{
|
||||
AssignGUIEventData(aEvent, aCopyTargets);
|
||||
|
||||
mOrient = aEvent.mOrient;
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::InternalScrollPortEvent
|
||||
******************************************************************************/
|
||||
|
||||
class InternalScrollAreaEvent : public WidgetGUIEvent
|
||||
{
|
||||
public:
|
||||
virtual InternalScrollAreaEvent* AsScrollAreaEvent() override
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
InternalScrollAreaEvent(bool aIsTrusted, EventMessage aMessage,
|
||||
nsIWidget* aWidget)
|
||||
: WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eScrollAreaEventClass)
|
||||
{
|
||||
}
|
||||
|
||||
virtual WidgetEvent* Duplicate() const override
|
||||
{
|
||||
MOZ_ASSERT(mClass == eScrollAreaEventClass,
|
||||
"Duplicate() must be overridden by sub class");
|
||||
// Not copying widget, it is a weak reference.
|
||||
InternalScrollAreaEvent* result =
|
||||
new InternalScrollAreaEvent(false, mMessage, nullptr);
|
||||
result->AssignScrollAreaEventData(*this, true);
|
||||
result->mFlags = mFlags;
|
||||
return result;
|
||||
}
|
||||
|
||||
nsRect mArea;
|
||||
|
||||
void AssignScrollAreaEventData(const InternalScrollAreaEvent& aEvent,
|
||||
bool aCopyTargets)
|
||||
{
|
||||
AssignGUIEventData(aEvent, aCopyTargets);
|
||||
|
||||
mArea = aEvent.mArea;
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::InternalFormEvent
|
||||
*
|
||||
* We hold the originating form control for form submit and reset events.
|
||||
* mOriginator is a weak pointer (does not hold a strong reference).
|
||||
******************************************************************************/
|
||||
|
||||
class InternalFormEvent : public WidgetEvent
|
||||
{
|
||||
public:
|
||||
virtual InternalFormEvent* AsFormEvent() override { return this; }
|
||||
|
||||
InternalFormEvent(bool aIsTrusted, EventMessage aMessage)
|
||||
: WidgetEvent(aIsTrusted, aMessage, eFormEventClass)
|
||||
, mOriginator(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
virtual WidgetEvent* Duplicate() const override
|
||||
{
|
||||
MOZ_ASSERT(mClass == eFormEventClass,
|
||||
"Duplicate() must be overridden by sub class");
|
||||
InternalFormEvent* result = new InternalFormEvent(false, mMessage);
|
||||
result->AssignFormEventData(*this, true);
|
||||
result->mFlags = mFlags;
|
||||
return result;
|
||||
}
|
||||
|
||||
nsIContent* mOriginator;
|
||||
|
||||
void AssignFormEventData(const InternalFormEvent& aEvent, bool aCopyTargets)
|
||||
{
|
||||
AssignEventData(aEvent, aCopyTargets);
|
||||
|
||||
// Don't copy mOriginator due to a weak pointer.
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::InternalClipboardEvent
|
||||
******************************************************************************/
|
||||
|
||||
class InternalClipboardEvent : public WidgetEvent
|
||||
{
|
||||
public:
|
||||
virtual InternalClipboardEvent* AsClipboardEvent() override
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
InternalClipboardEvent(bool aIsTrusted, EventMessage aMessage)
|
||||
: WidgetEvent(aIsTrusted, aMessage, eClipboardEventClass)
|
||||
{
|
||||
}
|
||||
|
||||
virtual WidgetEvent* Duplicate() const override
|
||||
{
|
||||
MOZ_ASSERT(mClass == eClipboardEventClass,
|
||||
"Duplicate() must be overridden by sub class");
|
||||
InternalClipboardEvent* result =
|
||||
new InternalClipboardEvent(false, mMessage);
|
||||
result->AssignClipboardEventData(*this, true);
|
||||
result->mFlags = mFlags;
|
||||
return result;
|
||||
}
|
||||
|
||||
nsCOMPtr<dom::DataTransfer> mClipboardData;
|
||||
|
||||
void AssignClipboardEventData(const InternalClipboardEvent& aEvent,
|
||||
bool aCopyTargets)
|
||||
{
|
||||
AssignEventData(aEvent, aCopyTargets);
|
||||
|
||||
mClipboardData = aEvent.mClipboardData;
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::InternalFocusEvent
|
||||
******************************************************************************/
|
||||
|
||||
class InternalFocusEvent : public InternalUIEvent
|
||||
{
|
||||
public:
|
||||
virtual InternalFocusEvent* AsFocusEvent() override { return this; }
|
||||
|
||||
InternalFocusEvent(bool aIsTrusted, EventMessage aMessage)
|
||||
: InternalUIEvent(aIsTrusted, aMessage, eFocusEventClass)
|
||||
, mFromRaise(false)
|
||||
, mIsRefocus(false)
|
||||
{
|
||||
}
|
||||
|
||||
virtual WidgetEvent* Duplicate() const override
|
||||
{
|
||||
MOZ_ASSERT(mClass == eFocusEventClass,
|
||||
"Duplicate() must be overridden by sub class");
|
||||
InternalFocusEvent* result = new InternalFocusEvent(false, mMessage);
|
||||
result->AssignFocusEventData(*this, true);
|
||||
result->mFlags = mFlags;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// The possible related target
|
||||
nsCOMPtr<dom::EventTarget> mRelatedTarget;
|
||||
|
||||
bool mFromRaise;
|
||||
bool mIsRefocus;
|
||||
|
||||
void AssignFocusEventData(const InternalFocusEvent& aEvent, bool aCopyTargets)
|
||||
{
|
||||
AssignUIEventData(aEvent, aCopyTargets);
|
||||
|
||||
mRelatedTarget = aCopyTargets ? aEvent.mRelatedTarget : nullptr;
|
||||
mFromRaise = aEvent.mFromRaise;
|
||||
mIsRefocus = aEvent.mIsRefocus;
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::InternalTransitionEvent
|
||||
******************************************************************************/
|
||||
|
||||
class InternalTransitionEvent : public WidgetEvent
|
||||
{
|
||||
public:
|
||||
virtual InternalTransitionEvent* AsTransitionEvent() override
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
InternalTransitionEvent(bool aIsTrusted, EventMessage aMessage)
|
||||
: WidgetEvent(aIsTrusted, aMessage, eTransitionEventClass)
|
||||
, mElapsedTime(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual WidgetEvent* Duplicate() const override
|
||||
{
|
||||
MOZ_ASSERT(mClass == eTransitionEventClass,
|
||||
"Duplicate() must be overridden by sub class");
|
||||
InternalTransitionEvent* result =
|
||||
new InternalTransitionEvent(false, mMessage);
|
||||
result->AssignTransitionEventData(*this, true);
|
||||
result->mFlags = mFlags;
|
||||
return result;
|
||||
}
|
||||
|
||||
nsString mPropertyName;
|
||||
nsString mPseudoElement;
|
||||
float mElapsedTime;
|
||||
|
||||
void AssignTransitionEventData(const InternalTransitionEvent& aEvent,
|
||||
bool aCopyTargets)
|
||||
{
|
||||
AssignEventData(aEvent, aCopyTargets);
|
||||
|
||||
mPropertyName = aEvent.mPropertyName;
|
||||
mElapsedTime = aEvent.mElapsedTime;
|
||||
mPseudoElement = aEvent.mPseudoElement;
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::InternalAnimationEvent
|
||||
******************************************************************************/
|
||||
|
||||
class InternalAnimationEvent : public WidgetEvent
|
||||
{
|
||||
public:
|
||||
virtual InternalAnimationEvent* AsAnimationEvent() override
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
InternalAnimationEvent(bool aIsTrusted, EventMessage aMessage)
|
||||
: WidgetEvent(aIsTrusted, aMessage, eAnimationEventClass)
|
||||
, mElapsedTime(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual WidgetEvent* Duplicate() const override
|
||||
{
|
||||
MOZ_ASSERT(mClass == eAnimationEventClass,
|
||||
"Duplicate() must be overridden by sub class");
|
||||
InternalAnimationEvent* result =
|
||||
new InternalAnimationEvent(false, mMessage);
|
||||
result->AssignAnimationEventData(*this, true);
|
||||
result->mFlags = mFlags;
|
||||
return result;
|
||||
}
|
||||
|
||||
nsString mAnimationName;
|
||||
nsString mPseudoElement;
|
||||
float mElapsedTime;
|
||||
|
||||
void AssignAnimationEventData(const InternalAnimationEvent& aEvent,
|
||||
bool aCopyTargets)
|
||||
{
|
||||
AssignEventData(aEvent, aCopyTargets);
|
||||
|
||||
mAnimationName = aEvent.mAnimationName;
|
||||
mElapsedTime = aEvent.mElapsedTime;
|
||||
mPseudoElement = aEvent.mPseudoElement;
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::InternalSVGZoomEvent
|
||||
******************************************************************************/
|
||||
|
||||
class InternalSVGZoomEvent : public WidgetGUIEvent
|
||||
{
|
||||
public:
|
||||
virtual InternalSVGZoomEvent* AsSVGZoomEvent() override { return this; }
|
||||
|
||||
InternalSVGZoomEvent(bool aIsTrusted, EventMessage aMessage)
|
||||
: WidgetGUIEvent(aIsTrusted, aMessage, nullptr, eSVGZoomEventClass)
|
||||
{
|
||||
}
|
||||
|
||||
virtual WidgetEvent* Duplicate() const override
|
||||
{
|
||||
MOZ_ASSERT(mClass == eSVGZoomEventClass,
|
||||
"Duplicate() must be overridden by sub class");
|
||||
// Not copying widget, it is a weak reference.
|
||||
InternalSVGZoomEvent* result = new InternalSVGZoomEvent(false, mMessage);
|
||||
result->AssignSVGZoomEventData(*this, true);
|
||||
result->mFlags = mFlags;
|
||||
return result;
|
||||
}
|
||||
|
||||
void AssignSVGZoomEventData(const InternalSVGZoomEvent& aEvent,
|
||||
bool aCopyTargets)
|
||||
{
|
||||
AssignGUIEventData(aEvent, aCopyTargets);
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::InternalSMILTimeEvent
|
||||
******************************************************************************/
|
||||
|
||||
class InternalSMILTimeEvent : public InternalUIEvent
|
||||
{
|
||||
public:
|
||||
virtual InternalSMILTimeEvent* AsSMILTimeEvent() override
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
InternalSMILTimeEvent(bool aIsTrusted, EventMessage aMessage)
|
||||
: InternalUIEvent(aIsTrusted, aMessage, eSMILTimeEventClass)
|
||||
{
|
||||
}
|
||||
|
||||
virtual WidgetEvent* Duplicate() const override
|
||||
{
|
||||
MOZ_ASSERT(mClass == eSMILTimeEventClass,
|
||||
"Duplicate() must be overridden by sub class");
|
||||
InternalSMILTimeEvent* result = new InternalSMILTimeEvent(false, mMessage);
|
||||
result->AssignSMILTimeEventData(*this, true);
|
||||
result->mFlags = mFlags;
|
||||
return result;
|
||||
}
|
||||
|
||||
void AssignSMILTimeEventData(const InternalSMILTimeEvent& aEvent,
|
||||
bool aCopyTargets)
|
||||
{
|
||||
AssignUIEventData(aEvent, aCopyTargets);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_ContentEvents_h__
|
||||
61
widget/EventClassList.h
Normal file
61
widget/EventClassList.h
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
/**
|
||||
* This header file lists up all event classes and related structs.
|
||||
* Define NS_EVENT_CLASS(aPrefix, aName) and NS_ROOT_EVENT_CLASS(aPrefix, aName)
|
||||
* before including this.
|
||||
* If an event name is WidgetInputEvent, aPrefix is "Widget" and aName is
|
||||
* "InputEvent". NS_ROOT_EVENT_CLASS() is only used for WidgetEvent for
|
||||
* allowing special handling for it. If you don't need such special handling,
|
||||
* you can define it as:
|
||||
* #define NS_ROOT_EVENT_CLASS(aPrefix, aName) NS_EVENT_CLASS(aPrefix, aName)
|
||||
*/
|
||||
|
||||
// BasicEvents.h
|
||||
NS_ROOT_EVENT_CLASS(Widget, Event)
|
||||
NS_EVENT_CLASS(Widget, GUIEvent)
|
||||
NS_EVENT_CLASS(Widget, InputEvent)
|
||||
NS_EVENT_CLASS(Internal, UIEvent)
|
||||
|
||||
// TextEvents.h
|
||||
NS_EVENT_CLASS(Widget, KeyboardEvent)
|
||||
NS_EVENT_CLASS(Widget, CompositionEvent)
|
||||
NS_EVENT_CLASS(Widget, QueryContentEvent)
|
||||
NS_EVENT_CLASS(Widget, SelectionEvent)
|
||||
NS_EVENT_CLASS(Internal, EditorInputEvent)
|
||||
NS_EVENT_CLASS(Internal, BeforeAfterKeyboardEvent)
|
||||
|
||||
// MouseEvents.h
|
||||
NS_EVENT_CLASS(Widget, MouseEventBase)
|
||||
NS_EVENT_CLASS(Widget, MouseEvent)
|
||||
NS_EVENT_CLASS(Widget, DragEvent)
|
||||
NS_EVENT_CLASS(Widget, MouseScrollEvent)
|
||||
NS_EVENT_CLASS(Widget, WheelEvent)
|
||||
NS_EVENT_CLASS(Widget, PointerEvent)
|
||||
|
||||
// TouchEvents.h
|
||||
NS_EVENT_CLASS(Widget, GestureNotifyEvent)
|
||||
NS_EVENT_CLASS(Widget, SimpleGestureEvent)
|
||||
NS_EVENT_CLASS(Widget, TouchEvent)
|
||||
|
||||
// ContentEvents.h
|
||||
NS_EVENT_CLASS(Internal, ScrollPortEvent)
|
||||
NS_EVENT_CLASS(Internal, ScrollAreaEvent)
|
||||
NS_EVENT_CLASS(Internal, FormEvent)
|
||||
NS_EVENT_CLASS(Internal, ClipboardEvent)
|
||||
NS_EVENT_CLASS(Internal, FocusEvent)
|
||||
NS_EVENT_CLASS(Internal, TransitionEvent)
|
||||
NS_EVENT_CLASS(Internal, AnimationEvent)
|
||||
NS_EVENT_CLASS(Internal, SVGZoomEvent)
|
||||
NS_EVENT_CLASS(Internal, SMILTimeEvent)
|
||||
|
||||
// MiscEvents.h
|
||||
NS_EVENT_CLASS(Widget, CommandEvent)
|
||||
NS_EVENT_CLASS(Widget, ContentCommandEvent)
|
||||
NS_EVENT_CLASS(Widget, PluginEvent)
|
||||
|
||||
// InternalMutationEvent.h (dom/events)
|
||||
NS_EVENT_CLASS(Internal, MutationEvent)
|
||||
173
widget/EventForwards.h
Normal file
173
widget/EventForwards.h
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_EventForwards_h__
|
||||
#define mozilla_EventForwards_h__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "nsTArray.h"
|
||||
|
||||
class nsCString;
|
||||
|
||||
/**
|
||||
* XXX Following enums should be in BasicEvents.h. However, currently, it's
|
||||
* impossible to use foward delearation for enum.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Return status for event processors.
|
||||
*/
|
||||
enum nsEventStatus
|
||||
{
|
||||
// The event is ignored, do default processing
|
||||
nsEventStatus_eIgnore,
|
||||
// The event is consumed, don't do default processing
|
||||
nsEventStatus_eConsumeNoDefault,
|
||||
// The event is consumed, but do default processing
|
||||
nsEventStatus_eConsumeDoDefault,
|
||||
// Value is not for use, only for serialization
|
||||
nsEventStatus_eSentinel
|
||||
};
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* Event messages
|
||||
*/
|
||||
|
||||
typedef uint16_t EventMessageType;
|
||||
|
||||
enum EventMessage : EventMessageType
|
||||
{
|
||||
|
||||
#define NS_EVENT_MESSAGE(aMessage) aMessage,
|
||||
#define NS_EVENT_MESSAGE_FIRST_LAST(aMessage, aFirst, aLast) \
|
||||
aMessage##First = aFirst, aMessage##Last = aLast,
|
||||
|
||||
#include "mozilla/EventMessageList.h"
|
||||
|
||||
#undef NS_EVENT_MESSAGE
|
||||
#undef NS_EVENT_MESSAGE_FIRST_LAST
|
||||
|
||||
// For preventing bustage due to "," after the last item.
|
||||
eEventMessage_MaxValue
|
||||
};
|
||||
|
||||
const char* ToChar(EventMessage aEventMessage);
|
||||
|
||||
/**
|
||||
* Event class IDs
|
||||
*/
|
||||
|
||||
typedef uint8_t EventClassIDType;
|
||||
|
||||
enum EventClassID : EventClassIDType
|
||||
{
|
||||
// The event class name will be:
|
||||
// eBasicEventClass for WidgetEvent
|
||||
// eFooEventClass for WidgetFooEvent or InternalFooEvent
|
||||
#define NS_ROOT_EVENT_CLASS(aPrefix, aName) eBasic##aName##Class
|
||||
#define NS_EVENT_CLASS(aPrefix, aName) , e##aName##Class
|
||||
|
||||
#include "mozilla/EventClassList.h"
|
||||
|
||||
#undef NS_EVENT_CLASS
|
||||
#undef NS_ROOT_EVENT_CLASS
|
||||
};
|
||||
|
||||
const char* ToChar(EventClassID aEventClassID);
|
||||
|
||||
typedef uint16_t Modifiers;
|
||||
|
||||
#define NS_DEFINE_KEYNAME(aCPPName, aDOMKeyName) \
|
||||
KEY_NAME_INDEX_##aCPPName,
|
||||
|
||||
typedef uint16_t KeyNameIndexType;
|
||||
enum KeyNameIndex : KeyNameIndexType
|
||||
{
|
||||
#include "mozilla/KeyNameList.h"
|
||||
// If a DOM keyboard event is synthesized by script, this is used. Then,
|
||||
// specified key name should be stored and use it as .key value.
|
||||
KEY_NAME_INDEX_USE_STRING
|
||||
};
|
||||
|
||||
#undef NS_DEFINE_KEYNAME
|
||||
|
||||
const nsCString ToString(KeyNameIndex aKeyNameIndex);
|
||||
|
||||
#define NS_DEFINE_PHYSICAL_KEY_CODE_NAME(aCPPName, aDOMCodeName) \
|
||||
CODE_NAME_INDEX_##aCPPName,
|
||||
|
||||
typedef uint8_t CodeNameIndexType;
|
||||
enum CodeNameIndex : CodeNameIndexType
|
||||
{
|
||||
#include "mozilla/PhysicalKeyCodeNameList.h"
|
||||
// If a DOM keyboard event is synthesized by script, this is used. Then,
|
||||
// specified code name should be stored and use it as .code value.
|
||||
CODE_NAME_INDEX_USE_STRING
|
||||
};
|
||||
|
||||
#undef NS_DEFINE_PHYSICAL_KEY_CODE_NAME
|
||||
|
||||
const nsCString ToString(CodeNameIndex aCodeNameIndex);
|
||||
|
||||
#define NS_DEFINE_COMMAND(aName, aCommandStr) , Command##aName
|
||||
|
||||
typedef int8_t CommandInt;
|
||||
enum Command : CommandInt
|
||||
{
|
||||
CommandDoNothing
|
||||
|
||||
#include "mozilla/CommandList.h"
|
||||
};
|
||||
#undef NS_DEFINE_COMMAND
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
/**
|
||||
* All header files should include this header instead of *Events.h.
|
||||
*/
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
#define NS_EVENT_CLASS(aPrefix, aName) class aPrefix##aName;
|
||||
#define NS_ROOT_EVENT_CLASS(aPrefix, aName) NS_EVENT_CLASS(aPrefix, aName)
|
||||
|
||||
#include "mozilla/EventClassList.h"
|
||||
|
||||
#undef NS_EVENT_CLASS
|
||||
#undef NS_ROOT_EVENT_CLASS
|
||||
|
||||
// BasicEvents.h
|
||||
struct BaseEventFlags;
|
||||
struct EventFlags;
|
||||
|
||||
class WidgetEventTime;
|
||||
|
||||
class NativeEventData;
|
||||
|
||||
// TextEvents.h
|
||||
struct AlternativeCharCode;
|
||||
struct ShortcutKeyCandidate;
|
||||
|
||||
typedef nsTArray<ShortcutKeyCandidate> ShortcutKeyCandidateArray;
|
||||
typedef AutoTArray<ShortcutKeyCandidate, 10> AutoShortcutKeyCandidateArray;
|
||||
|
||||
// TextRange.h
|
||||
typedef uint8_t RawTextRangeType;
|
||||
enum class TextRangeType : RawTextRangeType;
|
||||
|
||||
struct TextRangeStyle;
|
||||
struct TextRange;
|
||||
|
||||
class TextRangeArray;
|
||||
|
||||
// FontRange.h
|
||||
struct FontRange;
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_EventForwards_h__
|
||||
457
widget/EventMessageList.h
Normal file
457
widget/EventMessageList.h
Normal file
|
|
@ -0,0 +1,457 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
/**
|
||||
* This header file lists up all event messages.
|
||||
* Before including this header file, you should define:
|
||||
* NS_EVENT_MESSAGE(aMessage)
|
||||
*
|
||||
* Additionally, you can specify following macro for e*First and e*Last.
|
||||
* NS_EVENT_MESSAGE_FIRST_LAST(aMessage, aFirst, aLast)
|
||||
* This is optional, if you need only actual event messages, you don't need
|
||||
* to define this macro.
|
||||
*
|
||||
* Naming rules of the event messages:
|
||||
* 0. Starting with "e" prefix and use camelcase.
|
||||
* 1. Basically, use same name as the DOM name which is fired at dispatching
|
||||
* the event.
|
||||
* 2. If the event message name becomes too generic, e.g., "eInvalid", that may
|
||||
* conflict with another enum's item name, append something after the "e"
|
||||
* prefix, e.g., "eFormInvalid".
|
||||
*/
|
||||
|
||||
#ifndef NS_EVENT_MESSAGE_FIRST_LAST
|
||||
#define UNDEF_NS_EVENT_MESSAGE_FIRST_LAST 1
|
||||
#define NS_EVENT_MESSAGE_FIRST_LAST(aMessage, aFirst, aLast)
|
||||
#endif
|
||||
|
||||
NS_EVENT_MESSAGE(eVoidEvent)
|
||||
|
||||
// This is a dummy event message for all event listener implementation in
|
||||
// EventListenerManager.
|
||||
NS_EVENT_MESSAGE(eAllEvents)
|
||||
|
||||
// Widget may be destroyed
|
||||
NS_EVENT_MESSAGE(eWindowClose)
|
||||
|
||||
NS_EVENT_MESSAGE(eKeyPress)
|
||||
NS_EVENT_MESSAGE(eKeyUp)
|
||||
NS_EVENT_MESSAGE(eKeyDown)
|
||||
|
||||
// These messages are dispatched when PluginInstaceChild receives native
|
||||
// keyboard events directly and it posts the information to the widget.
|
||||
// These messages shouldn't be handled by content and non-reserved chrome
|
||||
// event handlers.
|
||||
NS_EVENT_MESSAGE(eKeyDownOnPlugin)
|
||||
NS_EVENT_MESSAGE(eKeyUpOnPlugin)
|
||||
|
||||
NS_EVENT_MESSAGE(eBeforeKeyDown)
|
||||
NS_EVENT_MESSAGE(eAfterKeyDown)
|
||||
NS_EVENT_MESSAGE(eBeforeKeyUp)
|
||||
NS_EVENT_MESSAGE(eAfterKeyUp)
|
||||
|
||||
// This message is sent after a content process handles a key event or accesskey
|
||||
// to indicate that an potential accesskey was not found. The parent process may
|
||||
// then respond by, for example, opening menus and processing other shortcuts.
|
||||
// It inherits its properties from a keypress event.
|
||||
NS_EVENT_MESSAGE(eAccessKeyNotFound)
|
||||
|
||||
NS_EVENT_MESSAGE(eResize)
|
||||
NS_EVENT_MESSAGE(eScroll)
|
||||
|
||||
// Application installation
|
||||
NS_EVENT_MESSAGE(eInstall)
|
||||
NS_EVENT_MESSAGE(eAppInstalled)
|
||||
|
||||
// A plugin was clicked or otherwise focused. ePluginActivate should be
|
||||
// used when the window is not active. ePluginFocus should be used when
|
||||
// the window is active. In the latter case, the dispatcher of the event
|
||||
// is expected to ensure that the plugin's widget is focused beforehand.
|
||||
NS_EVENT_MESSAGE(ePluginActivate)
|
||||
NS_EVENT_MESSAGE(ePluginFocus)
|
||||
|
||||
NS_EVENT_MESSAGE(eOffline)
|
||||
NS_EVENT_MESSAGE(eOnline)
|
||||
|
||||
NS_EVENT_MESSAGE(eLanguageChange)
|
||||
|
||||
NS_EVENT_MESSAGE(eMouseMove)
|
||||
NS_EVENT_MESSAGE(eMouseUp)
|
||||
NS_EVENT_MESSAGE(eMouseDown)
|
||||
NS_EVENT_MESSAGE(eMouseEnterIntoWidget)
|
||||
NS_EVENT_MESSAGE(eMouseExitFromWidget)
|
||||
NS_EVENT_MESSAGE(eMouseDoubleClick)
|
||||
NS_EVENT_MESSAGE(eMouseClick)
|
||||
// eMouseActivate is fired when the widget is activated by a click.
|
||||
NS_EVENT_MESSAGE(eMouseActivate)
|
||||
NS_EVENT_MESSAGE(eMouseOver)
|
||||
NS_EVENT_MESSAGE(eMouseOut)
|
||||
NS_EVENT_MESSAGE(eMouseHitTest)
|
||||
NS_EVENT_MESSAGE(eMouseEnter)
|
||||
NS_EVENT_MESSAGE(eMouseLeave)
|
||||
NS_EVENT_MESSAGE(eMouseTouchDrag)
|
||||
NS_EVENT_MESSAGE(eMouseLongTap)
|
||||
NS_EVENT_MESSAGE_FIRST_LAST(eMouseEvent, eMouseMove, eMouseLongTap)
|
||||
|
||||
// Pointer spec events
|
||||
NS_EVENT_MESSAGE(ePointerMove)
|
||||
NS_EVENT_MESSAGE(ePointerUp)
|
||||
NS_EVENT_MESSAGE(ePointerDown)
|
||||
NS_EVENT_MESSAGE(ePointerOver)
|
||||
NS_EVENT_MESSAGE(ePointerOut)
|
||||
NS_EVENT_MESSAGE(ePointerEnter)
|
||||
NS_EVENT_MESSAGE(ePointerLeave)
|
||||
NS_EVENT_MESSAGE(ePointerCancel)
|
||||
NS_EVENT_MESSAGE(ePointerGotCapture)
|
||||
NS_EVENT_MESSAGE(ePointerLostCapture)
|
||||
NS_EVENT_MESSAGE_FIRST_LAST(ePointerEvent, ePointerMove, ePointerLostCapture)
|
||||
|
||||
NS_EVENT_MESSAGE(eContextMenu)
|
||||
|
||||
NS_EVENT_MESSAGE(eLoad)
|
||||
NS_EVENT_MESSAGE(eUnload)
|
||||
NS_EVENT_MESSAGE(eHashChange)
|
||||
NS_EVENT_MESSAGE(eImageAbort)
|
||||
NS_EVENT_MESSAGE(eLoadError)
|
||||
NS_EVENT_MESSAGE(eLoadEnd)
|
||||
NS_EVENT_MESSAGE(ePopState)
|
||||
NS_EVENT_MESSAGE(eStorage)
|
||||
NS_EVENT_MESSAGE(eBeforeUnload)
|
||||
NS_EVENT_MESSAGE(eReadyStateChange)
|
||||
|
||||
NS_EVENT_MESSAGE(eFormSubmit)
|
||||
NS_EVENT_MESSAGE(eFormReset)
|
||||
NS_EVENT_MESSAGE(eFormChange)
|
||||
NS_EVENT_MESSAGE(eFormSelect)
|
||||
NS_EVENT_MESSAGE(eFormInvalid)
|
||||
|
||||
//Need separate focus/blur notifications for non-native widgets
|
||||
NS_EVENT_MESSAGE(eFocus)
|
||||
NS_EVENT_MESSAGE(eBlur)
|
||||
NS_EVENT_MESSAGE(eFocusIn)
|
||||
NS_EVENT_MESSAGE(eFocusOut)
|
||||
|
||||
NS_EVENT_MESSAGE(eDragEnter)
|
||||
NS_EVENT_MESSAGE(eDragOver)
|
||||
NS_EVENT_MESSAGE(eDragExit)
|
||||
NS_EVENT_MESSAGE(eDrag)
|
||||
NS_EVENT_MESSAGE(eDragEnd)
|
||||
NS_EVENT_MESSAGE(eDragStart)
|
||||
NS_EVENT_MESSAGE(eDrop)
|
||||
NS_EVENT_MESSAGE(eDragLeave)
|
||||
NS_EVENT_MESSAGE_FIRST_LAST(eDragDropEvent, eDragEnter, eDragLeave)
|
||||
|
||||
// XUL specific events
|
||||
NS_EVENT_MESSAGE(eXULPopupShowing)
|
||||
NS_EVENT_MESSAGE(eXULPopupShown)
|
||||
NS_EVENT_MESSAGE(eXULPopupPositioned)
|
||||
NS_EVENT_MESSAGE(eXULPopupHiding)
|
||||
NS_EVENT_MESSAGE(eXULPopupHidden)
|
||||
NS_EVENT_MESSAGE(eXULBroadcast)
|
||||
NS_EVENT_MESSAGE(eXULCommandUpdate)
|
||||
|
||||
// Legacy mouse scroll (wheel) events
|
||||
NS_EVENT_MESSAGE(eLegacyMouseLineOrPageScroll)
|
||||
NS_EVENT_MESSAGE(eLegacyMousePixelScroll)
|
||||
|
||||
NS_EVENT_MESSAGE(eScrollPortUnderflow)
|
||||
NS_EVENT_MESSAGE(eScrollPortOverflow)
|
||||
|
||||
NS_EVENT_MESSAGE(eLegacySubtreeModified)
|
||||
NS_EVENT_MESSAGE(eLegacyNodeInserted)
|
||||
NS_EVENT_MESSAGE(eLegacyNodeRemoved)
|
||||
NS_EVENT_MESSAGE(eLegacyNodeRemovedFromDocument)
|
||||
NS_EVENT_MESSAGE(eLegacyNodeInsertedIntoDocument)
|
||||
NS_EVENT_MESSAGE(eLegacyAttrModified)
|
||||
NS_EVENT_MESSAGE(eLegacyCharacterDataModified)
|
||||
NS_EVENT_MESSAGE_FIRST_LAST(eLegacyMutationEvent,
|
||||
eLegacySubtreeModified, eLegacyCharacterDataModified)
|
||||
|
||||
NS_EVENT_MESSAGE(eUnidentifiedEvent)
|
||||
|
||||
// composition events
|
||||
NS_EVENT_MESSAGE(eCompositionStart)
|
||||
// eCompositionEnd is the message for DOM compositionend event.
|
||||
// This event should NOT be dispatched from widget if eCompositionCommit
|
||||
// is available.
|
||||
NS_EVENT_MESSAGE(eCompositionEnd)
|
||||
// eCompositionUpdate is the message for DOM compositionupdate event.
|
||||
// This event should NOT be dispatched from widget since it will be dispatched
|
||||
// by mozilla::TextComposition automatically if eCompositionChange event
|
||||
// will change composition string.
|
||||
NS_EVENT_MESSAGE(eCompositionUpdate)
|
||||
// eCompositionChange is the message for representing a change of
|
||||
// composition string. This should be dispatched from widget even if
|
||||
// composition string isn't changed but the ranges are changed. This causes
|
||||
// a DOM "text" event which is a non-standard DOM event.
|
||||
NS_EVENT_MESSAGE(eCompositionChange)
|
||||
// eCompositionCommitAsIs is the message for representing a commit of
|
||||
// composition string. TextComposition will commit composition with the
|
||||
// last data. TextComposition will dispatch this event to the DOM tree as
|
||||
// eCompositionChange without clause information. After that,
|
||||
// eCompositionEnd will be dispatched automatically.
|
||||
// Its mData and mRanges should be empty and nullptr.
|
||||
NS_EVENT_MESSAGE(eCompositionCommitAsIs)
|
||||
// eCompositionCommit is the message for representing a commit of
|
||||
// composition string with its mData value. TextComposition will dispatch this
|
||||
// event to the DOM tree as eCompositionChange without clause information.
|
||||
// After that, eCompositionEnd will be dispatched automatically.
|
||||
// Its mRanges should be nullptr.
|
||||
NS_EVENT_MESSAGE(eCompositionCommit)
|
||||
|
||||
// Following events are defined for deprecated DOM events which are using
|
||||
// InternalUIEvent class.
|
||||
// DOMActivate (mapped with the DOM event and used internally)
|
||||
NS_EVENT_MESSAGE(eLegacyDOMActivate)
|
||||
// DOMFocusIn (only mapped with the DOM event)
|
||||
NS_EVENT_MESSAGE(eLegacyDOMFocusIn)
|
||||
// DOMFocusOut (only mapped with the DOM event)
|
||||
NS_EVENT_MESSAGE(eLegacyDOMFocusOut)
|
||||
|
||||
// pagetransition events
|
||||
NS_EVENT_MESSAGE(ePageShow)
|
||||
NS_EVENT_MESSAGE(ePageHide)
|
||||
|
||||
// SVG events
|
||||
NS_EVENT_MESSAGE(eSVGLoad)
|
||||
NS_EVENT_MESSAGE(eSVGUnload)
|
||||
NS_EVENT_MESSAGE(eSVGResize)
|
||||
NS_EVENT_MESSAGE(eSVGScroll)
|
||||
|
||||
// SVG Zoom events
|
||||
NS_EVENT_MESSAGE(eSVGZoom)
|
||||
|
||||
// XUL command events
|
||||
NS_EVENT_MESSAGE(eXULCommand)
|
||||
|
||||
// Cut, copy, paste events
|
||||
NS_EVENT_MESSAGE(eCopy)
|
||||
NS_EVENT_MESSAGE(eCut)
|
||||
NS_EVENT_MESSAGE(ePaste)
|
||||
|
||||
// Query for the selected text information, it return the selection offset,
|
||||
// selection length and selected text.
|
||||
NS_EVENT_MESSAGE(eQuerySelectedText)
|
||||
// Query for the text content of specified range, it returns actual lengh (if
|
||||
// the specified range is too long) and the text of the specified range.
|
||||
// Returns the entire text if requested length > actual length.
|
||||
NS_EVENT_MESSAGE(eQueryTextContent)
|
||||
// Query for the caret rect of nth insertion point. The offset of the result is
|
||||
// relative position from the top level widget.
|
||||
NS_EVENT_MESSAGE(eQueryCaretRect)
|
||||
// Query for the bounding rect of a range of characters. This works on any
|
||||
// valid character range given offset and length. Result is relative to top
|
||||
// level widget coordinates
|
||||
NS_EVENT_MESSAGE(eQueryTextRect)
|
||||
// Query for the bounding rect array of a range of characters.
|
||||
// Thiis similar event of eQueryTextRect.
|
||||
NS_EVENT_MESSAGE(eQueryTextRectArray)
|
||||
// Query for the bounding rect of the current focused frame. Result is relative
|
||||
// to top level widget coordinates
|
||||
NS_EVENT_MESSAGE(eQueryEditorRect)
|
||||
// Query for the current state of the content. The particular members of
|
||||
// mReply that are set for each query content event will be valid on success.
|
||||
NS_EVENT_MESSAGE(eQueryContentState)
|
||||
// Query for the selection in the form of a nsITransferable.
|
||||
NS_EVENT_MESSAGE(eQuerySelectionAsTransferable)
|
||||
// Query for character at a point. This returns the character offset, its
|
||||
// rect and also tentative caret point if the point is clicked. The point is
|
||||
// specified by Event::mRefPoint.
|
||||
NS_EVENT_MESSAGE(eQueryCharacterAtPoint)
|
||||
// Query if the DOM element under Event::mRefPoint belongs to our widget
|
||||
// or not.
|
||||
NS_EVENT_MESSAGE(eQueryDOMWidgetHittest)
|
||||
|
||||
// Video events
|
||||
NS_EVENT_MESSAGE(eLoadStart)
|
||||
NS_EVENT_MESSAGE(eProgress)
|
||||
NS_EVENT_MESSAGE(eSuspend)
|
||||
NS_EVENT_MESSAGE(eEmptied)
|
||||
NS_EVENT_MESSAGE(eStalled)
|
||||
NS_EVENT_MESSAGE(ePlay)
|
||||
NS_EVENT_MESSAGE(ePause)
|
||||
NS_EVENT_MESSAGE(eLoadedMetaData)
|
||||
NS_EVENT_MESSAGE(eLoadedData)
|
||||
NS_EVENT_MESSAGE(eWaiting)
|
||||
NS_EVENT_MESSAGE(ePlaying)
|
||||
NS_EVENT_MESSAGE(eCanPlay)
|
||||
NS_EVENT_MESSAGE(eCanPlayThrough)
|
||||
NS_EVENT_MESSAGE(eSeeking)
|
||||
NS_EVENT_MESSAGE(eSeeked)
|
||||
NS_EVENT_MESSAGE(eTimeUpdate)
|
||||
NS_EVENT_MESSAGE(eEnded)
|
||||
NS_EVENT_MESSAGE(eRateChange)
|
||||
NS_EVENT_MESSAGE(eDurationChange)
|
||||
NS_EVENT_MESSAGE(eVolumeChange)
|
||||
|
||||
// paint notification events
|
||||
NS_EVENT_MESSAGE(eAfterPaint)
|
||||
|
||||
// Simple gesture events
|
||||
NS_EVENT_MESSAGE(eSwipeGestureMayStart)
|
||||
NS_EVENT_MESSAGE(eSwipeGestureStart)
|
||||
NS_EVENT_MESSAGE(eSwipeGestureUpdate)
|
||||
NS_EVENT_MESSAGE(eSwipeGestureEnd)
|
||||
NS_EVENT_MESSAGE(eSwipeGesture)
|
||||
NS_EVENT_MESSAGE(eMagnifyGestureStart)
|
||||
NS_EVENT_MESSAGE(eMagnifyGestureUpdate)
|
||||
NS_EVENT_MESSAGE(eMagnifyGesture)
|
||||
NS_EVENT_MESSAGE(eRotateGestureStart)
|
||||
NS_EVENT_MESSAGE(eRotateGestureUpdate)
|
||||
NS_EVENT_MESSAGE(eRotateGesture)
|
||||
NS_EVENT_MESSAGE(eTapGesture)
|
||||
NS_EVENT_MESSAGE(ePressTapGesture)
|
||||
NS_EVENT_MESSAGE(eEdgeUIStarted)
|
||||
NS_EVENT_MESSAGE(eEdgeUICanceled)
|
||||
NS_EVENT_MESSAGE(eEdgeUICompleted)
|
||||
|
||||
// These are used to send native events to plugins.
|
||||
NS_EVENT_MESSAGE(ePluginInputEvent)
|
||||
|
||||
// Events to manipulate selection (WidgetSelectionEvent)
|
||||
// Clear any previous selection and set the given range as the selection
|
||||
NS_EVENT_MESSAGE(eSetSelection)
|
||||
|
||||
// Events of commands for the contents
|
||||
NS_EVENT_MESSAGE(eContentCommandCut)
|
||||
NS_EVENT_MESSAGE(eContentCommandCopy)
|
||||
NS_EVENT_MESSAGE(eContentCommandPaste)
|
||||
NS_EVENT_MESSAGE(eContentCommandDelete)
|
||||
NS_EVENT_MESSAGE(eContentCommandUndo)
|
||||
NS_EVENT_MESSAGE(eContentCommandRedo)
|
||||
NS_EVENT_MESSAGE(eContentCommandPasteTransferable)
|
||||
NS_EVENT_MESSAGE(eContentCommandLookUpDictionary)
|
||||
// eContentCommandScroll scrolls the nearest scrollable element to the
|
||||
// currently focused content or latest DOM selection. This would normally be
|
||||
// the same element scrolled by keyboard scroll commands, except that this event
|
||||
// will scroll an element scrollable in either direction. I.e., if the nearest
|
||||
// scrollable ancestor element can only be scrolled vertically, and horizontal
|
||||
// scrolling is requested using this event, no scrolling will occur.
|
||||
NS_EVENT_MESSAGE(eContentCommandScroll)
|
||||
|
||||
// Event to gesture notification
|
||||
NS_EVENT_MESSAGE(eGestureNotify)
|
||||
|
||||
NS_EVENT_MESSAGE(eScrolledAreaChanged)
|
||||
|
||||
// CSS Transition & Animation events:
|
||||
NS_EVENT_MESSAGE(eTransitionStart)
|
||||
NS_EVENT_MESSAGE(eTransitionRun)
|
||||
NS_EVENT_MESSAGE(eTransitionEnd)
|
||||
NS_EVENT_MESSAGE(eAnimationStart)
|
||||
NS_EVENT_MESSAGE(eAnimationEnd)
|
||||
NS_EVENT_MESSAGE(eAnimationIteration)
|
||||
|
||||
// Webkit-prefixed versions of Transition & Animation events, for web compat:
|
||||
NS_EVENT_MESSAGE(eWebkitTransitionEnd)
|
||||
NS_EVENT_MESSAGE(eWebkitAnimationStart)
|
||||
NS_EVENT_MESSAGE(eWebkitAnimationEnd)
|
||||
NS_EVENT_MESSAGE(eWebkitAnimationIteration)
|
||||
|
||||
NS_EVENT_MESSAGE(eSMILBeginEvent)
|
||||
NS_EVENT_MESSAGE(eSMILEndEvent)
|
||||
NS_EVENT_MESSAGE(eSMILRepeatEvent)
|
||||
|
||||
NS_EVENT_MESSAGE(eAudioProcess)
|
||||
NS_EVENT_MESSAGE(eAudioComplete)
|
||||
|
||||
// script notification events
|
||||
NS_EVENT_MESSAGE(eBeforeScriptExecute)
|
||||
NS_EVENT_MESSAGE(eAfterScriptExecute)
|
||||
|
||||
NS_EVENT_MESSAGE(eBeforePrint)
|
||||
NS_EVENT_MESSAGE(eAfterPrint)
|
||||
|
||||
NS_EVENT_MESSAGE(eMessage)
|
||||
|
||||
// Menu open event
|
||||
NS_EVENT_MESSAGE(eOpen)
|
||||
|
||||
// Device motion and orientation
|
||||
NS_EVENT_MESSAGE(eDeviceOrientation)
|
||||
NS_EVENT_MESSAGE(eAbsoluteDeviceOrientation)
|
||||
NS_EVENT_MESSAGE(eDeviceMotion)
|
||||
NS_EVENT_MESSAGE(eDeviceProximity)
|
||||
NS_EVENT_MESSAGE(eUserProximity)
|
||||
NS_EVENT_MESSAGE(eDeviceLight)
|
||||
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
|
||||
NS_EVENT_MESSAGE(eOrientationChange)
|
||||
#endif
|
||||
|
||||
// WebVR events
|
||||
NS_EVENT_MESSAGE(eVRDisplayConnect)
|
||||
NS_EVENT_MESSAGE(eVRDisplayDisconnect)
|
||||
NS_EVENT_MESSAGE(eVRDisplayPresentChange)
|
||||
|
||||
NS_EVENT_MESSAGE(eShow)
|
||||
|
||||
// Fullscreen DOM API
|
||||
NS_EVENT_MESSAGE(eFullscreenChange)
|
||||
NS_EVENT_MESSAGE(eFullscreenError)
|
||||
NS_EVENT_MESSAGE(eMozFullscreenChange)
|
||||
NS_EVENT_MESSAGE(eMozFullscreenError)
|
||||
|
||||
NS_EVENT_MESSAGE(eTouchStart)
|
||||
NS_EVENT_MESSAGE(eTouchMove)
|
||||
NS_EVENT_MESSAGE(eTouchEnd)
|
||||
NS_EVENT_MESSAGE(eTouchCancel)
|
||||
|
||||
// Pointerlock DOM API
|
||||
NS_EVENT_MESSAGE(ePointerLockChange)
|
||||
NS_EVENT_MESSAGE(ePointerLockError)
|
||||
NS_EVENT_MESSAGE(eMozPointerLockChange)
|
||||
NS_EVENT_MESSAGE(eMozPointerLockError)
|
||||
|
||||
// eWheel is the event message of DOM wheel event.
|
||||
NS_EVENT_MESSAGE(eWheel)
|
||||
// eWheelOperationStart may be dispatched when user starts to operate mouse
|
||||
// wheel. This won't be fired on some platforms which don't have corresponding
|
||||
// native event.
|
||||
NS_EVENT_MESSAGE(eWheelOperationStart)
|
||||
// eWheelOperationEnd may be dispatched when user ends or cancels operating
|
||||
// mouse wheel. This won't be fired on some platforms which don't have
|
||||
// corresponding native event.
|
||||
NS_EVENT_MESSAGE(eWheelOperationEnd)
|
||||
|
||||
//System time is changed
|
||||
NS_EVENT_MESSAGE(eTimeChange)
|
||||
|
||||
// Network packet events.
|
||||
NS_EVENT_MESSAGE(eNetworkUpload)
|
||||
NS_EVENT_MESSAGE(eNetworkDownload)
|
||||
|
||||
// MediaRecorder events.
|
||||
NS_EVENT_MESSAGE(eMediaRecorderDataAvailable)
|
||||
NS_EVENT_MESSAGE(eMediaRecorderWarning)
|
||||
NS_EVENT_MESSAGE(eMediaRecorderStop)
|
||||
|
||||
// SpeakerManager events
|
||||
NS_EVENT_MESSAGE(eSpeakerForcedChange)
|
||||
|
||||
#ifdef MOZ_GAMEPAD
|
||||
// Gamepad input events
|
||||
NS_EVENT_MESSAGE(eGamepadButtonDown)
|
||||
NS_EVENT_MESSAGE(eGamepadButtonUp)
|
||||
NS_EVENT_MESSAGE(eGamepadAxisMove)
|
||||
NS_EVENT_MESSAGE(eGamepadConnected)
|
||||
NS_EVENT_MESSAGE(eGamepadDisconnected)
|
||||
NS_EVENT_MESSAGE_FIRST_LAST(eGamepadEvent,
|
||||
eGamepadButtonDown, eGamepadDisconnected)
|
||||
#endif
|
||||
|
||||
// input and beforeinput events.
|
||||
NS_EVENT_MESSAGE(eEditorInput)
|
||||
|
||||
// selection events
|
||||
NS_EVENT_MESSAGE(eSelectStart)
|
||||
NS_EVENT_MESSAGE(eSelectionChange)
|
||||
|
||||
// Details element events.
|
||||
NS_EVENT_MESSAGE(eToggle)
|
||||
|
||||
#ifdef UNDEF_NS_EVENT_MESSAGE_FIRST_LAST
|
||||
#undef UNDEF_NS_EVENT_MESSAGE_FIRST_LAST
|
||||
#undef NS_EVENT_MESSAGE_FIRST_LAST
|
||||
#endif
|
||||
27
widget/FontRange.h
Normal file
27
widget/FontRange.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_FontRange_h_
|
||||
#define mozilla_FontRange_h_
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
struct FontRange
|
||||
{
|
||||
FontRange()
|
||||
: mStartOffset(0)
|
||||
, mFontSize(0)
|
||||
{
|
||||
}
|
||||
|
||||
int32_t mStartOffset;
|
||||
nsString mFontName;
|
||||
gfxFloat mFontSize; // in device pixels
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_FontRange_h_
|
||||
314
widget/GfxDriverInfo.cpp
Normal file
314
widget/GfxDriverInfo.cpp
Normal file
|
|
@ -0,0 +1,314 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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 "GfxDriverInfo.h"
|
||||
|
||||
#include "nsIGfxInfo.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
using namespace mozilla::widget;
|
||||
|
||||
int32_t GfxDriverInfo::allFeatures = 0;
|
||||
uint64_t GfxDriverInfo::allDriverVersions = ~(uint64_t(0));
|
||||
GfxDeviceFamily* const GfxDriverInfo::allDevices = nullptr;
|
||||
|
||||
GfxDeviceFamily* GfxDriverInfo::mDeviceFamilies[DeviceFamilyMax];
|
||||
nsAString* GfxDriverInfo::mDeviceVendors[DeviceVendorMax];
|
||||
|
||||
GfxDriverInfo::GfxDriverInfo()
|
||||
: mOperatingSystem(OperatingSystem::Unknown),
|
||||
mOperatingSystemVersion(0),
|
||||
mAdapterVendor(GfxDriverInfo::GetDeviceVendor(VendorAll)),
|
||||
mDevices(allDevices),
|
||||
mDeleteDevices(false),
|
||||
mFeature(allFeatures),
|
||||
mFeatureStatus(nsIGfxInfo::FEATURE_STATUS_OK),
|
||||
mComparisonOp(DRIVER_COMPARISON_IGNORED),
|
||||
mDriverVersion(0),
|
||||
mDriverVersionMax(0),
|
||||
mSuggestedVersion(nullptr),
|
||||
mRuleId(nullptr),
|
||||
mGpu2(false)
|
||||
{}
|
||||
|
||||
GfxDriverInfo::GfxDriverInfo(OperatingSystem os, nsAString& vendor,
|
||||
GfxDeviceFamily* devices,
|
||||
int32_t feature, int32_t featureStatus,
|
||||
VersionComparisonOp op,
|
||||
uint64_t driverVersion,
|
||||
const char *ruleId,
|
||||
const char *suggestedVersion /* = nullptr */,
|
||||
bool ownDevices /* = false */,
|
||||
bool gpu2 /* = false */)
|
||||
: mOperatingSystem(os),
|
||||
mOperatingSystemVersion(0),
|
||||
mAdapterVendor(vendor),
|
||||
mDevices(devices),
|
||||
mDeleteDevices(ownDevices),
|
||||
mFeature(feature),
|
||||
mFeatureStatus(featureStatus),
|
||||
mComparisonOp(op),
|
||||
mDriverVersion(driverVersion),
|
||||
mDriverVersionMax(0),
|
||||
mSuggestedVersion(suggestedVersion),
|
||||
mRuleId(ruleId),
|
||||
mGpu2(gpu2)
|
||||
{}
|
||||
|
||||
GfxDriverInfo::GfxDriverInfo(const GfxDriverInfo& aOrig)
|
||||
: mOperatingSystem(aOrig.mOperatingSystem),
|
||||
mOperatingSystemVersion(aOrig.mOperatingSystemVersion),
|
||||
mAdapterVendor(aOrig.mAdapterVendor),
|
||||
mFeature(aOrig.mFeature),
|
||||
mFeatureStatus(aOrig.mFeatureStatus),
|
||||
mComparisonOp(aOrig.mComparisonOp),
|
||||
mDriverVersion(aOrig.mDriverVersion),
|
||||
mDriverVersionMax(aOrig.mDriverVersionMax),
|
||||
mSuggestedVersion(aOrig.mSuggestedVersion),
|
||||
mRuleId(aOrig.mRuleId),
|
||||
mGpu2(aOrig.mGpu2)
|
||||
{
|
||||
// If we're managing the lifetime of the device family, we have to make a
|
||||
// copy of the original's device family.
|
||||
if (aOrig.mDeleteDevices && aOrig.mDevices) {
|
||||
mDevices = new GfxDeviceFamily;
|
||||
*mDevices = *aOrig.mDevices;
|
||||
} else {
|
||||
mDevices = aOrig.mDevices;
|
||||
}
|
||||
|
||||
mDeleteDevices = aOrig.mDeleteDevices;
|
||||
}
|
||||
|
||||
GfxDriverInfo::~GfxDriverInfo()
|
||||
{
|
||||
if (mDeleteDevices)
|
||||
delete mDevices;
|
||||
}
|
||||
|
||||
// Macros for appending a device to the DeviceFamily.
|
||||
#define APPEND_DEVICE(device) APPEND_DEVICE2(#device)
|
||||
#define APPEND_DEVICE2(device) deviceFamily->AppendElement(NS_LITERAL_STRING(device))
|
||||
|
||||
const GfxDeviceFamily* GfxDriverInfo::GetDeviceFamily(DeviceFamily id)
|
||||
{
|
||||
// The code here is too sensitive to fall through to the default case if the
|
||||
// code is invalid.
|
||||
NS_ASSERTION(id >= 0 && id < DeviceFamilyMax, "DeviceFamily id is out of range");
|
||||
|
||||
// If it already exists, we must have processed it once, so return it now.
|
||||
if (mDeviceFamilies[id])
|
||||
return mDeviceFamilies[id];
|
||||
|
||||
mDeviceFamilies[id] = new GfxDeviceFamily;
|
||||
GfxDeviceFamily* deviceFamily = mDeviceFamilies[id];
|
||||
|
||||
switch (id) {
|
||||
case IntelGMA500:
|
||||
APPEND_DEVICE(0x8108); /* IntelGMA500_1 */
|
||||
APPEND_DEVICE(0x8109); /* IntelGMA500_2 */
|
||||
break;
|
||||
case IntelGMA900:
|
||||
APPEND_DEVICE(0x2582); /* IntelGMA900_1 */
|
||||
APPEND_DEVICE(0x2782); /* IntelGMA900_2 */
|
||||
APPEND_DEVICE(0x2592); /* IntelGMA900_3 */
|
||||
APPEND_DEVICE(0x2792); /* IntelGMA900_4 */
|
||||
break;
|
||||
case IntelGMA950:
|
||||
APPEND_DEVICE(0x2772); /* Intel945G_1 */
|
||||
APPEND_DEVICE(0x2776); /* Intel945G_2 */
|
||||
APPEND_DEVICE(0x27a2); /* Intel945_1 */
|
||||
APPEND_DEVICE(0x27a6); /* Intel945_2 */
|
||||
APPEND_DEVICE(0x27ae); /* Intel945_3 */
|
||||
break;
|
||||
case IntelGMA3150:
|
||||
APPEND_DEVICE(0xa001); /* IntelGMA3150_Nettop_1 */
|
||||
APPEND_DEVICE(0xa002); /* IntelGMA3150_Nettop_2 */
|
||||
APPEND_DEVICE(0xa011); /* IntelGMA3150_Netbook_1 */
|
||||
APPEND_DEVICE(0xa012); /* IntelGMA3150_Netbook_2 */
|
||||
break;
|
||||
case IntelGMAX3000:
|
||||
APPEND_DEVICE(0x2972); /* Intel946GZ_1 */
|
||||
APPEND_DEVICE(0x2973); /* Intel946GZ_2 */
|
||||
APPEND_DEVICE(0x2982); /* IntelG35_1 */
|
||||
APPEND_DEVICE(0x2983); /* IntelG35_2 */
|
||||
APPEND_DEVICE(0x2992); /* IntelQ965_1 */
|
||||
APPEND_DEVICE(0x2993); /* IntelQ965_2 */
|
||||
APPEND_DEVICE(0x29a2); /* IntelG965_1 */
|
||||
APPEND_DEVICE(0x29a3); /* IntelG965_2 */
|
||||
APPEND_DEVICE(0x29b2); /* IntelQ35_1 */
|
||||
APPEND_DEVICE(0x29b3); /* IntelQ35_2 */
|
||||
APPEND_DEVICE(0x29c2); /* IntelG33_1 */
|
||||
APPEND_DEVICE(0x29c3); /* IntelG33_2 */
|
||||
APPEND_DEVICE(0x29d2); /* IntelQ33_1 */
|
||||
APPEND_DEVICE(0x29d3); /* IntelQ33_2 */
|
||||
APPEND_DEVICE(0x2a02); /* IntelGL960_1 */
|
||||
APPEND_DEVICE(0x2a03); /* IntelGL960_2 */
|
||||
APPEND_DEVICE(0x2a12); /* IntelGM965_1 */
|
||||
APPEND_DEVICE(0x2a13); /* IntelGM965_2 */
|
||||
break;
|
||||
case IntelGMAX4500HD:
|
||||
APPEND_DEVICE(0x2a42); /* IntelGMA4500MHD_1 */
|
||||
APPEND_DEVICE(0x2a43); /* IntelGMA4500MHD_2 */
|
||||
APPEND_DEVICE(0x2e42); /* IntelB43_1 */
|
||||
APPEND_DEVICE(0x2e43); /* IntelB43_2 */
|
||||
APPEND_DEVICE(0x2e92); /* IntelB43_3 */
|
||||
APPEND_DEVICE(0x2e93); /* IntelB43_4 */
|
||||
APPEND_DEVICE(0x2e32); /* IntelG41_1 */
|
||||
APPEND_DEVICE(0x2e33); /* IntelG41_2 */
|
||||
APPEND_DEVICE(0x2e22); /* IntelG45_1 */
|
||||
APPEND_DEVICE(0x2e23); /* IntelG45_2 */
|
||||
APPEND_DEVICE(0x2e12); /* IntelQ45_1 */
|
||||
APPEND_DEVICE(0x2e13); /* IntelQ45_2 */
|
||||
break;
|
||||
case IntelHDGraphicsToSandyBridge:
|
||||
APPEND_DEVICE(0x0042); /* IntelHDGraphics */
|
||||
APPEND_DEVICE(0x0046); /* IntelMobileHDGraphics */
|
||||
APPEND_DEVICE(0x0102); /* IntelSandyBridge_1 */
|
||||
APPEND_DEVICE(0x0106); /* IntelSandyBridge_2 */
|
||||
APPEND_DEVICE(0x0112); /* IntelSandyBridge_3 */
|
||||
APPEND_DEVICE(0x0116); /* IntelSandyBridge_4 */
|
||||
APPEND_DEVICE(0x0122); /* IntelSandyBridge_5 */
|
||||
APPEND_DEVICE(0x0126); /* IntelSandyBridge_6 */
|
||||
APPEND_DEVICE(0x010a); /* IntelSandyBridge_7 */
|
||||
break;
|
||||
case IntelHD3000:
|
||||
APPEND_DEVICE(0x0126);
|
||||
break;
|
||||
case IntelMobileHDGraphics:
|
||||
APPEND_DEVICE(0x0046); /* IntelMobileHDGraphics */
|
||||
break;
|
||||
case NvidiaBlockD3D9Layers:
|
||||
// Glitches whilst scrolling (see bugs 612007, 644787, 645872)
|
||||
APPEND_DEVICE(0x00f3); /* NV43 [GeForce 6200 (TM)] */
|
||||
APPEND_DEVICE(0x0146); /* NV43 [Geforce Go 6600TE/6200TE (TM)] */
|
||||
APPEND_DEVICE(0x014f); /* NV43 [GeForce 6200 (TM)] */
|
||||
APPEND_DEVICE(0x0161); /* NV44 [GeForce 6200 TurboCache (TM)] */
|
||||
APPEND_DEVICE(0x0162); /* NV44 [GeForce 6200SE TurboCache (TM)] */
|
||||
APPEND_DEVICE(0x0163); /* NV44 [GeForce 6200 LE (TM)] */
|
||||
APPEND_DEVICE(0x0164); /* NV44 [GeForce Go 6200 (TM)] */
|
||||
APPEND_DEVICE(0x0167); /* NV43 [GeForce Go 6200/6400 (TM)] */
|
||||
APPEND_DEVICE(0x0168); /* NV43 [GeForce Go 6200/6400 (TM)] */
|
||||
APPEND_DEVICE(0x0169); /* NV44 [GeForce 6250 (TM)] */
|
||||
APPEND_DEVICE(0x0222); /* NV44 [GeForce 6200 A-LE (TM)] */
|
||||
APPEND_DEVICE(0x0240); /* C51PV [GeForce 6150 (TM)] */
|
||||
APPEND_DEVICE(0x0241); /* C51 [GeForce 6150 LE (TM)] */
|
||||
APPEND_DEVICE(0x0244); /* C51 [Geforce Go 6150 (TM)] */
|
||||
APPEND_DEVICE(0x0245); /* C51 [Quadro NVS 210S/GeForce 6150LE (TM)] */
|
||||
APPEND_DEVICE(0x0247); /* C51 [GeForce Go 6100 (TM)] */
|
||||
APPEND_DEVICE(0x03d0); /* C61 [GeForce 6150SE nForce 430 (TM)] */
|
||||
APPEND_DEVICE(0x03d1); /* C61 [GeForce 6100 nForce 405 (TM)] */
|
||||
APPEND_DEVICE(0x03d2); /* C61 [GeForce 6100 nForce 400 (TM)] */
|
||||
APPEND_DEVICE(0x03d5); /* C61 [GeForce 6100 nForce 420 (TM)] */
|
||||
break;
|
||||
case RadeonX1000:
|
||||
// This list is from the ATIRadeonX1000.kext Info.plist
|
||||
APPEND_DEVICE(0x7187);
|
||||
APPEND_DEVICE(0x7210);
|
||||
APPEND_DEVICE(0x71de);
|
||||
APPEND_DEVICE(0x7146);
|
||||
APPEND_DEVICE(0x7142);
|
||||
APPEND_DEVICE(0x7109);
|
||||
APPEND_DEVICE(0x71c5);
|
||||
APPEND_DEVICE(0x71c0);
|
||||
APPEND_DEVICE(0x7240);
|
||||
APPEND_DEVICE(0x7249);
|
||||
APPEND_DEVICE(0x7291);
|
||||
break;
|
||||
case Geforce7300GT:
|
||||
APPEND_DEVICE(0x0393);
|
||||
break;
|
||||
case Nvidia310M:
|
||||
APPEND_DEVICE(0x0A70);
|
||||
break;
|
||||
case Nvidia8800GTS:
|
||||
APPEND_DEVICE(0x0193);
|
||||
break;
|
||||
case Bug1137716:
|
||||
APPEND_DEVICE(0x0a29);
|
||||
APPEND_DEVICE(0x0a2b);
|
||||
APPEND_DEVICE(0x0a2d);
|
||||
APPEND_DEVICE(0x0a35);
|
||||
APPEND_DEVICE(0x0a6c);
|
||||
APPEND_DEVICE(0x0a70);
|
||||
APPEND_DEVICE(0x0a72);
|
||||
APPEND_DEVICE(0x0a7a);
|
||||
APPEND_DEVICE(0x0caf);
|
||||
APPEND_DEVICE(0x0dd2);
|
||||
APPEND_DEVICE(0x0dd3);
|
||||
// GF180M ids
|
||||
APPEND_DEVICE(0x0de3);
|
||||
APPEND_DEVICE(0x0de8);
|
||||
APPEND_DEVICE(0x0de9);
|
||||
APPEND_DEVICE(0x0dea);
|
||||
APPEND_DEVICE(0x0deb);
|
||||
APPEND_DEVICE(0x0dec);
|
||||
APPEND_DEVICE(0x0ded);
|
||||
APPEND_DEVICE(0x0dee);
|
||||
APPEND_DEVICE(0x0def);
|
||||
APPEND_DEVICE(0x0df0);
|
||||
APPEND_DEVICE(0x0df1);
|
||||
APPEND_DEVICE(0x0df2);
|
||||
APPEND_DEVICE(0x0df3);
|
||||
APPEND_DEVICE(0x0df4);
|
||||
APPEND_DEVICE(0x0df5);
|
||||
APPEND_DEVICE(0x0df6);
|
||||
APPEND_DEVICE(0x0df7);
|
||||
APPEND_DEVICE(0x1050);
|
||||
APPEND_DEVICE(0x1051);
|
||||
APPEND_DEVICE(0x1052);
|
||||
APPEND_DEVICE(0x1054);
|
||||
APPEND_DEVICE(0x1055);
|
||||
break;
|
||||
case Bug1116812:
|
||||
APPEND_DEVICE(0x2e32);
|
||||
APPEND_DEVICE(0x2a02);
|
||||
break;
|
||||
case Bug1155608:
|
||||
APPEND_DEVICE(0x2e22); /* IntelG45_1 */
|
||||
break;
|
||||
case Bug1207665:
|
||||
APPEND_DEVICE(0xa001); /* Intel Media Accelerator 3150 */
|
||||
APPEND_DEVICE(0xa002);
|
||||
APPEND_DEVICE(0xa011);
|
||||
APPEND_DEVICE(0xa012);
|
||||
break;
|
||||
// This should never happen, but we get a warning if we don't handle this.
|
||||
case DeviceFamilyMax:
|
||||
NS_WARNING("Invalid DeviceFamily id");
|
||||
break;
|
||||
}
|
||||
|
||||
return deviceFamily;
|
||||
}
|
||||
|
||||
// Macro for assigning a device vendor id to a string.
|
||||
#define DECLARE_VENDOR_ID(name, deviceId) \
|
||||
case name: \
|
||||
mDeviceVendors[id]->AssignLiteral(deviceId); \
|
||||
break;
|
||||
|
||||
const nsAString& GfxDriverInfo::GetDeviceVendor(DeviceVendor id)
|
||||
{
|
||||
NS_ASSERTION(id >= 0 && id < DeviceVendorMax, "DeviceVendor id is out of range");
|
||||
|
||||
if (mDeviceVendors[id])
|
||||
return *mDeviceVendors[id];
|
||||
|
||||
mDeviceVendors[id] = new nsString();
|
||||
|
||||
switch (id) {
|
||||
DECLARE_VENDOR_ID(VendorAll, "");
|
||||
DECLARE_VENDOR_ID(VendorIntel, "0x8086");
|
||||
DECLARE_VENDOR_ID(VendorNVIDIA, "0x10de");
|
||||
DECLARE_VENDOR_ID(VendorAMD, "0x1022");
|
||||
DECLARE_VENDOR_ID(VendorATI, "0x1002");
|
||||
DECLARE_VENDOR_ID(VendorMicrosoft, "0x1414");
|
||||
// Suppress a warning.
|
||||
DECLARE_VENDOR_ID(DeviceVendorMax, "");
|
||||
}
|
||||
|
||||
return *mDeviceVendors[id];
|
||||
}
|
||||
300
widget/GfxDriverInfo.h
Normal file
300
widget/GfxDriverInfo.h
Normal file
|
|
@ -0,0 +1,300 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef __mozilla_widget_GfxDriverInfo_h__
|
||||
#define __mozilla_widget_GfxDriverInfo_h__
|
||||
|
||||
#include "nsString.h"
|
||||
|
||||
// Macros for adding a blocklist item to the static list.
|
||||
#define APPEND_TO_DRIVER_BLOCKLIST(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion, ruleId, suggestedVersion) \
|
||||
mDriverInfo->AppendElement(GfxDriverInfo(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion, ruleId, suggestedVersion))
|
||||
#define APPEND_TO_DRIVER_BLOCKLIST2(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion, ruleId) \
|
||||
mDriverInfo->AppendElement(GfxDriverInfo(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion, ruleId))
|
||||
|
||||
#define APPEND_TO_DRIVER_BLOCKLIST_RANGE(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion, driverVersionMax, ruleId, suggestedVersion) \
|
||||
do { \
|
||||
MOZ_ASSERT(driverComparator == DRIVER_BETWEEN_EXCLUSIVE || \
|
||||
driverComparator == DRIVER_BETWEEN_INCLUSIVE || \
|
||||
driverComparator == DRIVER_BETWEEN_INCLUSIVE_START); \
|
||||
GfxDriverInfo info(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion, ruleId, suggestedVersion); \
|
||||
info.mDriverVersionMax = driverVersionMax; \
|
||||
mDriverInfo->AppendElement(info); \
|
||||
} while (false)
|
||||
|
||||
#define APPEND_TO_DRIVER_BLOCKLIST_RANGE_GPU2(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion, driverVersionMax, ruleId, suggestedVersion) \
|
||||
do { \
|
||||
MOZ_ASSERT(driverComparator == DRIVER_BETWEEN_EXCLUSIVE || \
|
||||
driverComparator == DRIVER_BETWEEN_INCLUSIVE || \
|
||||
driverComparator == DRIVER_BETWEEN_INCLUSIVE_START); \
|
||||
GfxDriverInfo info(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion, ruleId, suggestedVersion, false, true); \
|
||||
info.mDriverVersionMax = driverVersionMax; \
|
||||
mDriverInfo->AppendElement(info); \
|
||||
} while (false)
|
||||
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
enum class OperatingSystem {
|
||||
Unknown,
|
||||
Windows,
|
||||
WindowsXP,
|
||||
WindowsServer2003,
|
||||
WindowsVista,
|
||||
Windows7,
|
||||
Windows8,
|
||||
Windows8_1,
|
||||
Windows10,
|
||||
Linux,
|
||||
OSX,
|
||||
OSX10_5,
|
||||
OSX10_6,
|
||||
OSX10_7,
|
||||
OSX10_8,
|
||||
OSX10_9,
|
||||
OSX10_10,
|
||||
OSX10_11,
|
||||
OSX10_12,
|
||||
Android,
|
||||
Ios
|
||||
};
|
||||
|
||||
enum VersionComparisonOp {
|
||||
DRIVER_LESS_THAN, // driver < version
|
||||
DRIVER_BUILD_ID_LESS_THAN, // driver build id < version
|
||||
DRIVER_LESS_THAN_OR_EQUAL, // driver <= version
|
||||
DRIVER_BUILD_ID_LESS_THAN_OR_EQUAL, // driver build id <= version
|
||||
DRIVER_GREATER_THAN, // driver > version
|
||||
DRIVER_GREATER_THAN_OR_EQUAL, // driver >= version
|
||||
DRIVER_EQUAL, // driver == version
|
||||
DRIVER_NOT_EQUAL, // driver != version
|
||||
DRIVER_BETWEEN_EXCLUSIVE, // driver > version && driver < versionMax
|
||||
DRIVER_BETWEEN_INCLUSIVE, // driver >= version && driver <= versionMax
|
||||
DRIVER_BETWEEN_INCLUSIVE_START, // driver >= version && driver < versionMax
|
||||
DRIVER_COMPARISON_IGNORED
|
||||
};
|
||||
|
||||
enum DeviceFamily {
|
||||
IntelGMA500,
|
||||
IntelGMA900,
|
||||
IntelGMA950,
|
||||
IntelGMA3150,
|
||||
IntelGMAX3000,
|
||||
IntelGMAX4500HD,
|
||||
IntelHDGraphicsToSandyBridge,
|
||||
IntelHD3000,
|
||||
IntelMobileHDGraphics,
|
||||
NvidiaBlockD3D9Layers,
|
||||
RadeonX1000,
|
||||
Geforce7300GT,
|
||||
Nvidia310M,
|
||||
Nvidia8800GTS,
|
||||
Bug1137716,
|
||||
Bug1116812,
|
||||
Bug1155608,
|
||||
Bug1207665,
|
||||
DeviceFamilyMax
|
||||
};
|
||||
|
||||
enum DeviceVendor {
|
||||
VendorAll,
|
||||
VendorIntel,
|
||||
VendorNVIDIA,
|
||||
VendorAMD,
|
||||
VendorATI,
|
||||
VendorMicrosoft,
|
||||
DeviceVendorMax
|
||||
};
|
||||
|
||||
/* Array of devices to match, or an empty array for all devices */
|
||||
typedef nsTArray<nsString> GfxDeviceFamily;
|
||||
|
||||
struct GfxDriverInfo
|
||||
{
|
||||
// If |ownDevices| is true, you are transferring ownership of the devices
|
||||
// array, and it will be deleted when this GfxDriverInfo is destroyed.
|
||||
GfxDriverInfo(OperatingSystem os, nsAString& vendor, GfxDeviceFamily* devices,
|
||||
int32_t feature, int32_t featureStatus, VersionComparisonOp op,
|
||||
uint64_t driverVersion, const char *ruleId,
|
||||
const char *suggestedVersion = nullptr,
|
||||
bool ownDevices = false, bool gpu2 = false);
|
||||
|
||||
GfxDriverInfo();
|
||||
GfxDriverInfo(const GfxDriverInfo&);
|
||||
~GfxDriverInfo();
|
||||
|
||||
OperatingSystem mOperatingSystem;
|
||||
uint32_t mOperatingSystemVersion;
|
||||
|
||||
nsString mAdapterVendor;
|
||||
|
||||
static GfxDeviceFamily* const allDevices;
|
||||
GfxDeviceFamily* mDevices;
|
||||
|
||||
// Whether the mDevices array should be deleted when this structure is
|
||||
// deallocated. False by default.
|
||||
bool mDeleteDevices;
|
||||
|
||||
/* A feature from nsIGfxInfo, or all features */
|
||||
int32_t mFeature;
|
||||
static int32_t allFeatures;
|
||||
|
||||
/* A feature status from nsIGfxInfo */
|
||||
int32_t mFeatureStatus;
|
||||
|
||||
VersionComparisonOp mComparisonOp;
|
||||
|
||||
/* versions are assumed to be A.B.C.D packed as 0xAAAABBBBCCCCDDDD */
|
||||
uint64_t mDriverVersion;
|
||||
uint64_t mDriverVersionMax;
|
||||
static uint64_t allDriverVersions;
|
||||
|
||||
const char *mSuggestedVersion;
|
||||
nsCString mRuleId;
|
||||
|
||||
static const GfxDeviceFamily* GetDeviceFamily(DeviceFamily id);
|
||||
static GfxDeviceFamily* mDeviceFamilies[DeviceFamilyMax];
|
||||
|
||||
static const nsAString& GetDeviceVendor(DeviceVendor id);
|
||||
static nsAString* mDeviceVendors[DeviceVendorMax];
|
||||
|
||||
nsString mModel, mHardware, mProduct, mManufacturer;
|
||||
|
||||
bool mGpu2;
|
||||
};
|
||||
|
||||
#define GFX_DRIVER_VERSION(a,b,c,d) \
|
||||
((uint64_t(a)<<48) | (uint64_t(b)<<32) | (uint64_t(c)<<16) | uint64_t(d))
|
||||
|
||||
inline uint64_t
|
||||
V(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
|
||||
{
|
||||
// We make sure every driver number is padded by 0s, this will allow us the
|
||||
// easiest 'compare as if decimals' approach. See ParseDriverVersion for a
|
||||
// more extensive explanation of this approach.
|
||||
while (b > 0 && b < 1000) {
|
||||
b *= 10;
|
||||
}
|
||||
while (c > 0 && c < 1000) {
|
||||
c *= 10;
|
||||
}
|
||||
while (d > 0 && d < 1000) {
|
||||
d *= 10;
|
||||
}
|
||||
return GFX_DRIVER_VERSION(a, b, c, d);
|
||||
}
|
||||
|
||||
// All destination string storage needs to have at least 5 bytes available.
|
||||
inline bool SplitDriverVersion(const char *aSource, char *aAStr, char *aBStr, char *aCStr, char *aDStr)
|
||||
{
|
||||
// sscanf doesn't do what we want here to we parse this manually.
|
||||
int len = strlen(aSource);
|
||||
|
||||
// This "4" is hardcoded in a few places, including once as a 3.
|
||||
char *dest[4] = { aAStr, aBStr, aCStr, aDStr };
|
||||
unsigned destIdx = 0;
|
||||
unsigned destPos = 0;
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (destIdx >= 4) {
|
||||
// Invalid format found. Ensure we don't access dest beyond bounds.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aSource[i] == '.') {
|
||||
MOZ_ASSERT (destIdx < 4 && destPos <= 4);
|
||||
dest[destIdx++][destPos] = 0;
|
||||
destPos = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (destPos > 3) {
|
||||
// Ignore more than 4 chars. Ensure we never access dest[destIdx]
|
||||
// beyond its bounds.
|
||||
continue;
|
||||
}
|
||||
|
||||
MOZ_ASSERT (destIdx < 4 && destPos < 4);
|
||||
dest[destIdx][destPos++] = aSource[i];
|
||||
}
|
||||
|
||||
// Take care of the trailing period
|
||||
if (destIdx >= 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add last terminator.
|
||||
MOZ_ASSERT (destIdx < 4 && destPos <= 4);
|
||||
dest[destIdx][destPos] = 0;
|
||||
|
||||
if (destIdx != 3) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// This allows us to pad driver version 'substrings' with 0s, this
|
||||
// effectively allows us to treat the version numbers as 'decimals'. This is
|
||||
// a little strange but this method seems to do the right thing for all
|
||||
// different vendor's driver strings. i.e. .98 will become 9800, which is
|
||||
// larger than .978 which would become 9780.
|
||||
inline void PadDriverDecimal(char *aString)
|
||||
{
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!aString[i]) {
|
||||
for (int c = i; c < 4; c++) {
|
||||
aString[c] = '0';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
aString[4] = 0;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ParseDriverVersion(const nsAString& aVersion, uint64_t *aNumericVersion)
|
||||
{
|
||||
*aNumericVersion = 0;
|
||||
|
||||
#if defined(XP_WIN)
|
||||
int a, b, c, d;
|
||||
char aStr[8], bStr[8], cStr[8], dStr[8];
|
||||
/* honestly, why do I even bother */
|
||||
if (!SplitDriverVersion(NS_LossyConvertUTF16toASCII(aVersion).get(), aStr, bStr, cStr, dStr))
|
||||
return false;
|
||||
|
||||
PadDriverDecimal(bStr);
|
||||
PadDriverDecimal(cStr);
|
||||
PadDriverDecimal(dStr);
|
||||
|
||||
a = atoi(aStr);
|
||||
b = atoi(bStr);
|
||||
c = atoi(cStr);
|
||||
d = atoi(dStr);
|
||||
|
||||
if (a < 0 || a > 0xffff) return false;
|
||||
if (b < 0 || b > 0xffff) return false;
|
||||
if (c < 0 || c > 0xffff) return false;
|
||||
if (d < 0 || d > 0xffff) return false;
|
||||
|
||||
*aNumericVersion = GFX_DRIVER_VERSION(a, b, c, d);
|
||||
MOZ_ASSERT(*aNumericVersion != GfxDriverInfo::allDriverVersions);
|
||||
return true;
|
||||
#elif defined(ANDROID)
|
||||
// Can't use aVersion.ToInteger() because that's not compiled into our code
|
||||
// unless we have XPCOM_GLUE_AVOID_NSPR disabled.
|
||||
*aNumericVersion = atoi(NS_LossyConvertUTF16toASCII(aVersion).get());
|
||||
MOZ_ASSERT(*aNumericVersion != GfxDriverInfo::allDriverVersions);
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /*__mozilla_widget_GfxDriverInfo_h__ */
|
||||
1438
widget/GfxInfoBase.cpp
Normal file
1438
widget/GfxInfoBase.cpp
Normal file
File diff suppressed because it is too large
Load diff
136
widget/GfxInfoBase.h
Normal file
136
widget/GfxInfoBase.h
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
/* vim: se cin sw=2 ts=2 et : */
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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/. */
|
||||
|
||||
#ifndef __mozilla_widget_GfxInfoBase_h__
|
||||
#define __mozilla_widget_GfxInfoBase_h__
|
||||
|
||||
#include "GfxDriverInfo.h"
|
||||
#include "GfxInfoCollector.h"
|
||||
#include "gfxFeature.h"
|
||||
#include "gfxTelemetry.h"
|
||||
#include "js/Value.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIGfxInfo.h"
|
||||
#include "nsIGfxInfoDebug.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
class GfxInfoBase : public nsIGfxInfo,
|
||||
public nsIObserver,
|
||||
public nsSupportsWeakReference
|
||||
#ifdef DEBUG
|
||||
, public nsIGfxInfoDebug
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
GfxInfoBase();
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
// We only declare a subset of the nsIGfxInfo interface. It's up to derived
|
||||
// classes to implement the rest of the interface.
|
||||
// Derived classes need to use
|
||||
// using GfxInfoBase::GetFeatureStatus;
|
||||
// using GfxInfoBase::GetFeatureSuggestedDriverVersion;
|
||||
// using GfxInfoBase::GetWebGLParameter;
|
||||
// to import the relevant methods into their namespace.
|
||||
NS_IMETHOD GetFeatureStatus(int32_t aFeature, nsACString& aFailureId, int32_t *_retval) override;
|
||||
NS_IMETHOD GetFeatureSuggestedDriverVersion(int32_t aFeature, nsAString & _retval) override;
|
||||
NS_IMETHOD GetWebGLParameter(const nsAString & aParam, nsAString & _retval) override;
|
||||
|
||||
NS_IMETHOD GetMonitors(JSContext* cx, JS::MutableHandleValue _retval) override;
|
||||
NS_IMETHOD GetFailures(uint32_t *failureCount, int32_t** indices, char ***failures) override;
|
||||
NS_IMETHOD_(void) LogFailure(const nsACString &failure) override;
|
||||
NS_IMETHOD GetInfo(JSContext*, JS::MutableHandle<JS::Value>) override;
|
||||
NS_IMETHOD GetFeatures(JSContext*, JS::MutableHandle<JS::Value>) override;
|
||||
NS_IMETHOD GetFeatureLog(JSContext*, JS::MutableHandle<JS::Value>) override;
|
||||
NS_IMETHOD GetActiveCrashGuards(JSContext*, JS::MutableHandle<JS::Value>) override;
|
||||
NS_IMETHOD GetContentBackend(nsAString & aContentBackend) override;
|
||||
|
||||
// Initialization function. If you override this, you must call this class's
|
||||
// version of Init first.
|
||||
// We need Init to be called separately from the constructor so we can
|
||||
// register as an observer after all derived classes have been constructed
|
||||
// and we know we have a non-zero refcount.
|
||||
// Ideally, Init() would be void-return, but the rules of
|
||||
// NS_GENERIC_FACTORY_CONSTRUCTOR_INIT require it be nsresult return.
|
||||
virtual nsresult Init();
|
||||
|
||||
// only useful on X11
|
||||
NS_IMETHOD_(void) GetData() override { }
|
||||
|
||||
static void AddCollector(GfxInfoCollectorBase* collector);
|
||||
static void RemoveCollector(GfxInfoCollectorBase* collector);
|
||||
|
||||
static nsTArray<GfxDriverInfo>* mDriverInfo;
|
||||
static bool mDriverInfoObserverInitialized;
|
||||
|
||||
virtual nsString Model() { return EmptyString(); }
|
||||
virtual nsString Hardware() { return EmptyString(); }
|
||||
virtual nsString Product() { return EmptyString(); }
|
||||
virtual nsString Manufacturer() { return EmptyString(); }
|
||||
virtual uint32_t OperatingSystemVersion() { return 0; }
|
||||
|
||||
// Convenience to get the application version
|
||||
static const nsCString& GetApplicationVersion();
|
||||
|
||||
virtual nsresult FindMonitors(JSContext* cx, JS::HandleObject array) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual ~GfxInfoBase();
|
||||
|
||||
virtual nsresult GetFeatureStatusImpl(int32_t aFeature, int32_t* aStatus,
|
||||
nsAString& aSuggestedDriverVersion,
|
||||
const nsTArray<GfxDriverInfo>& aDriverInfo,
|
||||
nsACString& aFailureId,
|
||||
OperatingSystem* aOS = nullptr);
|
||||
|
||||
// Gets the driver info table. Used by GfxInfoBase to check for general cases
|
||||
// (while subclasses check for more specific ones).
|
||||
virtual const nsTArray<GfxDriverInfo>& GetGfxDriverInfo() = 0;
|
||||
|
||||
virtual void DescribeFeatures(JSContext* aCx, JS::Handle<JSObject*> obj);
|
||||
bool InitFeatureObject(
|
||||
JSContext* aCx,
|
||||
JS::Handle<JSObject*> aContainer,
|
||||
const char* aName,
|
||||
int32_t aFeature,
|
||||
Maybe<mozilla::gfx::FeatureStatus> aKnownStatus,
|
||||
JS::MutableHandle<JSObject*> aOutObj);
|
||||
|
||||
private:
|
||||
virtual int32_t FindBlocklistedDeviceInList(const nsTArray<GfxDriverInfo>& aDriverInfo,
|
||||
nsAString& aSuggestedVersion,
|
||||
int32_t aFeature,
|
||||
nsACString &aFailureId,
|
||||
OperatingSystem os);
|
||||
|
||||
void EvaluateDownloadedBlacklist(nsTArray<GfxDriverInfo>& aDriverInfo);
|
||||
|
||||
bool BuildFeatureStateLog(JSContext* aCx, const gfx::FeatureState& aFeature,
|
||||
JS::MutableHandle<JS::Value> aOut);
|
||||
|
||||
Mutex mMutex;
|
||||
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* __mozilla_widget_GfxInfoBase_h__ */
|
||||
54
widget/GfxInfoCollector.cpp
Normal file
54
widget/GfxInfoCollector.cpp
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/* vim: se cin sw=2 ts=2 et : */
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 "GfxInfoCollector.h"
|
||||
#include "jsapi.h"
|
||||
#include "nsString.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace widget;
|
||||
|
||||
void
|
||||
InfoObject::DefineProperty(const char *name, int value)
|
||||
{
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
mOk = JS_DefineProperty(mCx, mObj, name, value, JSPROP_ENUMERATE);
|
||||
}
|
||||
|
||||
void
|
||||
InfoObject::DefineProperty(const char *name, nsAString &value)
|
||||
{
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
const nsString &flat = PromiseFlatString(value);
|
||||
JS::Rooted<JSString*> string(mCx, JS_NewUCStringCopyN(mCx, static_cast<const char16_t*>(flat.get()),
|
||||
flat.Length()));
|
||||
if (!string)
|
||||
mOk = false;
|
||||
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
mOk = JS_DefineProperty(mCx, mObj, name, string, JSPROP_ENUMERATE);
|
||||
}
|
||||
|
||||
void
|
||||
InfoObject::DefineProperty(const char *name, const char *value)
|
||||
{
|
||||
nsAutoString string = NS_ConvertASCIItoUTF16(value);
|
||||
DefineProperty(name, string);
|
||||
}
|
||||
|
||||
InfoObject::InfoObject(JSContext *aCx) : mCx(aCx), mObj(aCx), mOk(true)
|
||||
{
|
||||
mObj = JS_NewPlainObject(aCx);
|
||||
if (!mObj)
|
||||
mOk = false;
|
||||
}
|
||||
94
widget/GfxInfoCollector.h
Normal file
94
widget/GfxInfoCollector.h
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
/* vim: se cin sw=2 ts=2 et : */
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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/. */
|
||||
|
||||
#ifndef __mozilla_widget_GfxInfoCollector_h__
|
||||
#define __mozilla_widget_GfxInfoCollector_h__
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsStringFwd.h"
|
||||
#include "js/RootingAPI.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
|
||||
/* this is handy wrapper around JSAPI to make it more pleasant to use.
|
||||
* We collect the JSAPI errors and so that callers don't need to */
|
||||
class MOZ_STACK_CLASS InfoObject
|
||||
{
|
||||
friend class GfxInfoBase;
|
||||
|
||||
public:
|
||||
void DefineProperty(const char *name, int value);
|
||||
void DefineProperty(const char *name, nsAString &value);
|
||||
void DefineProperty(const char *name, const char *value);
|
||||
|
||||
private:
|
||||
// We need to ensure that this object lives on the stack so that GC sees it properly
|
||||
explicit InfoObject(JSContext *aCx);
|
||||
InfoObject(InfoObject&);
|
||||
|
||||
JSContext *mCx;
|
||||
JS::Rooted<JSObject*> mObj;
|
||||
bool mOk;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
Here's an example usage:
|
||||
|
||||
class Foo {
|
||||
Foo::Foo() : mInfoCollector(this, &Foo::GetAweseomeness) {}
|
||||
|
||||
void GetAwesomeness(InfoObject &obj) {
|
||||
obj.DefineProperty("awesome", mAwesome);
|
||||
}
|
||||
|
||||
int mAwesome;
|
||||
|
||||
GfxInfoCollector<Foo> mInfoCollector;
|
||||
}
|
||||
|
||||
This will define a property on the object
|
||||
returned from calling getInfo() on a
|
||||
GfxInfo object. e.g.
|
||||
|
||||
gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo);
|
||||
info = gfxInfo.getInfo();
|
||||
if (info.awesome)
|
||||
alert(info.awesome);
|
||||
|
||||
*/
|
||||
|
||||
class GfxInfoCollectorBase
|
||||
{
|
||||
public:
|
||||
GfxInfoCollectorBase();
|
||||
virtual void GetInfo(InfoObject &obj) = 0;
|
||||
virtual ~GfxInfoCollectorBase();
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class GfxInfoCollector : public GfxInfoCollectorBase
|
||||
{
|
||||
public:
|
||||
GfxInfoCollector(T* aPointer, void (T::*aFunc)(InfoObject &obj)) : mPointer(aPointer), mFunc(aFunc) {
|
||||
}
|
||||
virtual void GetInfo(InfoObject &obj) override {
|
||||
(mPointer->*mFunc)(obj);
|
||||
}
|
||||
|
||||
protected:
|
||||
T* mPointer;
|
||||
void (T::*mFunc)(InfoObject &obj);
|
||||
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
69
widget/GfxInfoWebGL.cpp
Normal file
69
widget/GfxInfoWebGL.cpp
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/* vim: se cin sw=2 ts=2 et : */
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 "GfxInfoWebGL.h"
|
||||
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
#include "GLDefs.h"
|
||||
#include "nsIDOMWebGLRenderingContext.h"
|
||||
#include "nsICanvasRenderingContextInternal.h"
|
||||
|
||||
using namespace mozilla::widget;
|
||||
|
||||
nsresult
|
||||
GfxInfoWebGL::GetWebGLParameter(const nsAString& aParam, nsAString& aResult)
|
||||
{
|
||||
GLenum param;
|
||||
|
||||
if (aParam.EqualsLiteral("vendor")) param = LOCAL_GL_VENDOR;
|
||||
else if (aParam.EqualsLiteral("renderer")) param = LOCAL_GL_RENDERER;
|
||||
else if (aParam.EqualsLiteral("version")) param = LOCAL_GL_VERSION;
|
||||
else if (aParam.EqualsLiteral("shading_language_version")) param = LOCAL_GL_SHADING_LANGUAGE_VERSION;
|
||||
else if (aParam.EqualsLiteral("extensions")) param = LOCAL_GL_EXTENSIONS;
|
||||
else if (aParam.EqualsLiteral("full-renderer")) param = 0;
|
||||
else return NS_ERROR_INVALID_ARG;
|
||||
|
||||
nsCOMPtr<nsIDOMWebGLRenderingContext> webgl =
|
||||
do_CreateInstance("@mozilla.org/content/canvas-rendering-context;1?id=webgl");
|
||||
if (!webgl)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
nsCOMPtr<nsICanvasRenderingContextInternal> webglInternal =
|
||||
do_QueryInterface(webgl);
|
||||
if (!webglInternal)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
nsresult rv = webglInternal->SetDimensions(16, 16);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (param)
|
||||
return webgl->MozGetUnderlyingParamString(param, aResult);
|
||||
|
||||
// this is the "full renderer" string, which is vendor + renderer + version
|
||||
|
||||
nsAutoString str;
|
||||
|
||||
rv = webgl->MozGetUnderlyingParamString(LOCAL_GL_VENDOR, str);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aResult.Append(str);
|
||||
aResult.AppendLiteral(" -- ");
|
||||
|
||||
rv = webgl->MozGetUnderlyingParamString(LOCAL_GL_RENDERER, str);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aResult.Append(str);
|
||||
aResult.AppendLiteral(" -- ");
|
||||
|
||||
rv = webgl->MozGetUnderlyingParamString(LOCAL_GL_VERSION, str);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aResult.Append(str);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
27
widget/GfxInfoWebGL.h
Normal file
27
widget/GfxInfoWebGL.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/* vim: se cin sw=2 ts=2 et : */
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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/. */
|
||||
|
||||
#ifndef __mozilla_widget_GfxInfoWebGL_h__
|
||||
#define __mozilla_widget_GfxInfoWebGL_h__
|
||||
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
class GfxInfoWebGL {
|
||||
public:
|
||||
static nsresult GetWebGLParameter(const nsAString& aParam, nsAString& aResult);
|
||||
|
||||
protected:
|
||||
GfxInfoWebGL() { }
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
564
widget/GfxInfoX11.cpp
Normal file
564
widget/GfxInfoX11.cpp
Normal file
|
|
@ -0,0 +1,564 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* 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 <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <errno.h>
|
||||
#include <sys/utsname.h>
|
||||
#include "nsCRTGlue.h"
|
||||
#include "prenv.h"
|
||||
|
||||
#include "GfxInfoX11.h"
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
#include "nsExceptionHandler.h"
|
||||
#include "nsICrashReporter.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
#ifdef DEBUG
|
||||
NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, GfxInfoBase, nsIGfxInfoDebug)
|
||||
#endif
|
||||
|
||||
// these global variables will be set when firing the glxtest process
|
||||
int glxtest_pipe = 0;
|
||||
pid_t glxtest_pid = 0;
|
||||
|
||||
nsresult
|
||||
GfxInfo::Init()
|
||||
{
|
||||
mGLMajorVersion = 0;
|
||||
mMajorVersion = 0;
|
||||
mMinorVersion = 0;
|
||||
mRevisionVersion = 0;
|
||||
mIsMesa = false;
|
||||
mIsNVIDIA = false;
|
||||
mIsFGLRX = false;
|
||||
mIsNouveau = false;
|
||||
mIsIntel = false;
|
||||
mIsOldSwrast = false;
|
||||
mIsLlvmpipe = false;
|
||||
mHasTextureFromPixmap = false;
|
||||
return GfxInfoBase::Init();
|
||||
}
|
||||
|
||||
void
|
||||
GfxInfo::GetData()
|
||||
{
|
||||
// to understand this function, see bug 639842. We retrieve the OpenGL driver information in a
|
||||
// separate process to protect against bad drivers.
|
||||
|
||||
// if glxtest_pipe == 0, that means that we already read the information
|
||||
if (!glxtest_pipe)
|
||||
return;
|
||||
|
||||
enum { buf_size = 1024 };
|
||||
char buf[buf_size];
|
||||
ssize_t bytesread = read(glxtest_pipe,
|
||||
&buf,
|
||||
buf_size-1); // -1 because we'll append a zero
|
||||
close(glxtest_pipe);
|
||||
glxtest_pipe = 0;
|
||||
|
||||
// bytesread < 0 would mean that the above read() call failed.
|
||||
// This should never happen. If it did, the outcome would be to blacklist anyway.
|
||||
if (bytesread < 0)
|
||||
bytesread = 0;
|
||||
|
||||
// let buf be a zero-terminated string
|
||||
buf[bytesread] = 0;
|
||||
|
||||
// Wait for the glxtest process to finish. This serves 2 purposes:
|
||||
// * avoid having a zombie glxtest process laying around
|
||||
// * get the glxtest process status info.
|
||||
int glxtest_status = 0;
|
||||
bool wait_for_glxtest_process = true;
|
||||
bool waiting_for_glxtest_process_failed = false;
|
||||
int waitpid_errno = 0;
|
||||
while(wait_for_glxtest_process) {
|
||||
wait_for_glxtest_process = false;
|
||||
if (waitpid(glxtest_pid, &glxtest_status, 0) == -1) {
|
||||
waitpid_errno = errno;
|
||||
if (waitpid_errno == EINTR) {
|
||||
wait_for_glxtest_process = true;
|
||||
} else {
|
||||
// Bug 718629
|
||||
// ECHILD happens when the glxtest process got reaped got reaped after a PR_CreateProcess
|
||||
// as per bug 227246. This shouldn't matter, as we still seem to get the data
|
||||
// from the pipe, and if we didn't, the outcome would be to blacklist anyway.
|
||||
waiting_for_glxtest_process_failed = (waitpid_errno != ECHILD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool exited_with_error_code = !waiting_for_glxtest_process_failed &&
|
||||
WIFEXITED(glxtest_status) &&
|
||||
WEXITSTATUS(glxtest_status) != EXIT_SUCCESS;
|
||||
bool received_signal = !waiting_for_glxtest_process_failed &&
|
||||
WIFSIGNALED(glxtest_status);
|
||||
|
||||
bool error = waiting_for_glxtest_process_failed || exited_with_error_code || received_signal;
|
||||
|
||||
nsCString textureFromPixmap;
|
||||
nsCString *stringToFill = nullptr;
|
||||
char *bufptr = buf;
|
||||
if (!error) {
|
||||
while(true) {
|
||||
char *line = NS_strtok("\n", &bufptr);
|
||||
if (!line)
|
||||
break;
|
||||
if (stringToFill) {
|
||||
stringToFill->Assign(line);
|
||||
stringToFill = nullptr;
|
||||
}
|
||||
else if(!strcmp(line, "VENDOR"))
|
||||
stringToFill = &mVendor;
|
||||
else if(!strcmp(line, "RENDERER"))
|
||||
stringToFill = &mRenderer;
|
||||
else if(!strcmp(line, "VERSION"))
|
||||
stringToFill = &mVersion;
|
||||
else if(!strcmp(line, "TFP"))
|
||||
stringToFill = &textureFromPixmap;
|
||||
}
|
||||
}
|
||||
|
||||
if (!strcmp(textureFromPixmap.get(), "TRUE"))
|
||||
mHasTextureFromPixmap = true;
|
||||
|
||||
// only useful for Linux kernel version check for FGLRX driver.
|
||||
// assumes X client == X server, which is sad.
|
||||
struct utsname unameobj;
|
||||
if (uname(&unameobj) >= 0)
|
||||
{
|
||||
mOS.Assign(unameobj.sysname);
|
||||
mOSRelease.Assign(unameobj.release);
|
||||
}
|
||||
|
||||
const char *spoofedVendor = PR_GetEnv("MOZ_GFX_SPOOF_GL_VENDOR");
|
||||
if (spoofedVendor)
|
||||
mVendor.Assign(spoofedVendor);
|
||||
const char *spoofedRenderer = PR_GetEnv("MOZ_GFX_SPOOF_GL_RENDERER");
|
||||
if (spoofedRenderer)
|
||||
mRenderer.Assign(spoofedRenderer);
|
||||
const char *spoofedVersion = PR_GetEnv("MOZ_GFX_SPOOF_GL_VERSION");
|
||||
if (spoofedVersion)
|
||||
mVersion.Assign(spoofedVersion);
|
||||
const char *spoofedOS = PR_GetEnv("MOZ_GFX_SPOOF_OS");
|
||||
if (spoofedOS)
|
||||
mOS.Assign(spoofedOS);
|
||||
const char *spoofedOSRelease = PR_GetEnv("MOZ_GFX_SPOOF_OS_RELEASE");
|
||||
if (spoofedOSRelease)
|
||||
mOSRelease.Assign(spoofedOSRelease);
|
||||
|
||||
if (error ||
|
||||
mVendor.IsEmpty() ||
|
||||
mRenderer.IsEmpty() ||
|
||||
mVersion.IsEmpty() ||
|
||||
mOS.IsEmpty() ||
|
||||
mOSRelease.IsEmpty())
|
||||
{
|
||||
mAdapterDescription.AppendLiteral("GLXtest process failed");
|
||||
if (waiting_for_glxtest_process_failed)
|
||||
mAdapterDescription.AppendPrintf(" (waitpid failed with errno=%d for pid %d)", waitpid_errno, glxtest_pid);
|
||||
if (exited_with_error_code)
|
||||
mAdapterDescription.AppendPrintf(" (exited with status %d)", WEXITSTATUS(glxtest_status));
|
||||
if (received_signal)
|
||||
mAdapterDescription.AppendPrintf(" (received signal %d)", WTERMSIG(glxtest_status));
|
||||
if (bytesread) {
|
||||
mAdapterDescription.AppendLiteral(": ");
|
||||
mAdapterDescription.Append(nsDependentCString(buf));
|
||||
mAdapterDescription.Append('\n');
|
||||
}
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
CrashReporter::AppendAppNotesToCrashReport(mAdapterDescription);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
mAdapterDescription.Append(mVendor);
|
||||
mAdapterDescription.AppendLiteral(" -- ");
|
||||
mAdapterDescription.Append(mRenderer);
|
||||
|
||||
nsAutoCString note;
|
||||
note.AppendLiteral("OpenGL: ");
|
||||
note.Append(mAdapterDescription);
|
||||
note.AppendLiteral(" -- ");
|
||||
note.Append(mVersion);
|
||||
if (mHasTextureFromPixmap)
|
||||
note.AppendLiteral(" -- texture_from_pixmap");
|
||||
note.Append('\n');
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
CrashReporter::AppendAppNotesToCrashReport(note);
|
||||
#endif
|
||||
|
||||
// determine the major OpenGL version. That's the first integer in the version string.
|
||||
mGLMajorVersion = strtol(mVersion.get(), 0, 10);
|
||||
|
||||
// determine driver type (vendor) and where in the version string
|
||||
// the actual driver version numbers should be expected to be found (whereToReadVersionNumbers)
|
||||
const char *whereToReadVersionNumbers = nullptr;
|
||||
const char *Mesa_in_version_string = strstr(mVersion.get(), "Mesa");
|
||||
if (Mesa_in_version_string) {
|
||||
mIsMesa = true;
|
||||
// with Mesa, the version string contains "Mesa major.minor" and that's all the version information we get:
|
||||
// there is no actual driver version info.
|
||||
whereToReadVersionNumbers = Mesa_in_version_string + strlen("Mesa");
|
||||
if (strcasestr(mVendor.get(), "nouveau"))
|
||||
mIsNouveau = true;
|
||||
if (strcasestr(mRenderer.get(), "intel")) // yes, intel is in the renderer string
|
||||
mIsIntel = true;
|
||||
if (strcasestr(mRenderer.get(), "llvmpipe"))
|
||||
mIsLlvmpipe = true;
|
||||
if (strcasestr(mRenderer.get(), "software rasterizer"))
|
||||
mIsOldSwrast = true;
|
||||
} else if (strstr(mVendor.get(), "NVIDIA Corporation")) {
|
||||
mIsNVIDIA = true;
|
||||
// with the NVIDIA driver, the version string contains "NVIDIA major.minor"
|
||||
// note that here the vendor and version strings behave differently, that's why we don't put this above
|
||||
// alongside Mesa_in_version_string.
|
||||
const char *NVIDIA_in_version_string = strstr(mVersion.get(), "NVIDIA");
|
||||
if (NVIDIA_in_version_string)
|
||||
whereToReadVersionNumbers = NVIDIA_in_version_string + strlen("NVIDIA");
|
||||
} else if (strstr(mVendor.get(), "ATI Technologies Inc")) {
|
||||
mIsFGLRX = true;
|
||||
// with the FGLRX driver, the version string only gives a OpenGL version :/ so let's return that.
|
||||
// that can at least give a rough idea of how old the driver is.
|
||||
whereToReadVersionNumbers = mVersion.get();
|
||||
}
|
||||
|
||||
// read major.minor version numbers of the driver (not to be confused with the OpenGL version)
|
||||
if (whereToReadVersionNumbers) {
|
||||
// copy into writable buffer, for tokenization
|
||||
strncpy(buf, whereToReadVersionNumbers, buf_size);
|
||||
bufptr = buf;
|
||||
|
||||
// now try to read major.minor version numbers. In case of failure, gracefully exit: these numbers have
|
||||
// been initialized as 0 anyways
|
||||
char *token = NS_strtok(".", &bufptr);
|
||||
if (token) {
|
||||
mMajorVersion = strtol(token, 0, 10);
|
||||
token = NS_strtok(".", &bufptr);
|
||||
if (token) {
|
||||
mMinorVersion = strtol(token, 0, 10);
|
||||
token = NS_strtok(".", &bufptr);
|
||||
if (token)
|
||||
mRevisionVersion = strtol(token, 0, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint64_t version(uint32_t major, uint32_t minor, uint32_t revision = 0)
|
||||
{
|
||||
return (uint64_t(major) << 32) + (uint64_t(minor) << 16) + uint64_t(revision);
|
||||
}
|
||||
|
||||
const nsTArray<GfxDriverInfo>&
|
||||
GfxInfo::GetGfxDriverInfo()
|
||||
{
|
||||
// Nothing here yet.
|
||||
//if (!mDriverInfo->Length()) {
|
||||
//
|
||||
//}
|
||||
return *mDriverInfo;
|
||||
}
|
||||
|
||||
nsresult
|
||||
GfxInfo::GetFeatureStatusImpl(int32_t aFeature,
|
||||
int32_t *aStatus,
|
||||
nsAString & aSuggestedDriverVersion,
|
||||
const nsTArray<GfxDriverInfo>& aDriverInfo,
|
||||
nsACString& aFailureId,
|
||||
OperatingSystem* aOS /* = nullptr */)
|
||||
|
||||
{
|
||||
GetData();
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aStatus);
|
||||
*aStatus = nsIGfxInfo::FEATURE_STATUS_UNKNOWN;
|
||||
aSuggestedDriverVersion.SetIsVoid(true);
|
||||
OperatingSystem os = OperatingSystem::Linux;
|
||||
if (aOS)
|
||||
*aOS = os;
|
||||
|
||||
if (mGLMajorVersion == 1) {
|
||||
// We're on OpenGL 1. In most cases that indicates really old hardware.
|
||||
// We better block them, rather than rely on them to fail gracefully, because they don't!
|
||||
// see bug 696636
|
||||
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
|
||||
aFailureId = "FEATURE_FAILURE_OPENGL_1";
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Don't evaluate any special cases if we're checking the downloaded blocklist.
|
||||
if (!aDriverInfo.Length()) {
|
||||
// Blacklist software GL implementations from using layers acceleration.
|
||||
// On the test infrastructure, we'll force-enable layers acceleration.
|
||||
if (aFeature == nsIGfxInfo::FEATURE_OPENGL_LAYERS &&
|
||||
(mIsLlvmpipe || mIsOldSwrast) &&
|
||||
!PR_GetEnv("MOZ_LAYERS_ALLOW_SOFTWARE_GL"))
|
||||
{
|
||||
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
|
||||
aFailureId = "FEATURE_FAILURE_SOFTWARE_GL";
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Only check features relevant to Linux.
|
||||
if (aFeature == nsIGfxInfo::FEATURE_OPENGL_LAYERS ||
|
||||
aFeature == nsIGfxInfo::FEATURE_WEBGL_OPENGL ||
|
||||
aFeature == nsIGfxInfo::FEATURE_WEBGL_MSAA) {
|
||||
|
||||
// whitelist the linux test slaves' current configuration.
|
||||
// this is necessary as they're still using the slightly outdated 190.42 driver.
|
||||
// this isn't a huge risk, as at least this is the exact setting in which we do continuous testing,
|
||||
// and this only affects GeForce 9400 cards on linux on this precise driver version, which is very few users.
|
||||
// We do the same thing on Windows XP, see in widget/windows/GfxInfo.cpp
|
||||
if (mIsNVIDIA &&
|
||||
!strcmp(mRenderer.get(), "GeForce 9400/PCI/SSE2") &&
|
||||
!strcmp(mVersion.get(), "3.2.0 NVIDIA 190.42"))
|
||||
{
|
||||
*aStatus = nsIGfxInfo::FEATURE_STATUS_OK;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mIsMesa) {
|
||||
if (mIsNouveau && version(mMajorVersion, mMinorVersion) < version(8,0)) {
|
||||
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION;
|
||||
aFailureId = "FEATURE_FAILURE_MESA_1";
|
||||
aSuggestedDriverVersion.AssignLiteral("Mesa 8.0");
|
||||
}
|
||||
else if (version(mMajorVersion, mMinorVersion, mRevisionVersion) < version(7,10,3)) {
|
||||
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION;
|
||||
aFailureId = "FEATURE_FAILURE_MESA_2";
|
||||
aSuggestedDriverVersion.AssignLiteral("Mesa 7.10.3");
|
||||
}
|
||||
else if (mIsOldSwrast) {
|
||||
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION;
|
||||
aFailureId = "FEATURE_FAILURE_SW_RAST";
|
||||
}
|
||||
else if (mIsLlvmpipe && version(mMajorVersion, mMinorVersion) < version(9, 1)) {
|
||||
// bug 791905, Mesa bug 57733, fixed in Mesa 9.1 according to
|
||||
// https://bugs.freedesktop.org/show_bug.cgi?id=57733#c3
|
||||
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION;
|
||||
aFailureId = "FEATURE_FAILURE_MESA_3";
|
||||
}
|
||||
else if (aFeature == nsIGfxInfo::FEATURE_WEBGL_MSAA)
|
||||
{
|
||||
if (mIsIntel && version(mMajorVersion, mMinorVersion) < version(8,1)) {
|
||||
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION;
|
||||
aFailureId = "FEATURE_FAILURE_MESA_4";
|
||||
aSuggestedDriverVersion.AssignLiteral("Mesa 8.1");
|
||||
}
|
||||
}
|
||||
|
||||
} else if (mIsNVIDIA) {
|
||||
if (version(mMajorVersion, mMinorVersion, mRevisionVersion) < version(257,21)) {
|
||||
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION;
|
||||
aFailureId = "FEATURE_FAILURE_OLD_NV";
|
||||
aSuggestedDriverVersion.AssignLiteral("NVIDIA 257.21");
|
||||
}
|
||||
} else if (mIsFGLRX) {
|
||||
// FGLRX does not report a driver version number, so we have the OpenGL version instead.
|
||||
// by requiring OpenGL 3, we effectively require recent drivers.
|
||||
if (version(mMajorVersion, mMinorVersion, mRevisionVersion) < version(3, 0)) {
|
||||
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION;
|
||||
aFailureId = "FEATURE_FAILURE_OLD_FGLRX";
|
||||
aSuggestedDriverVersion.AssignLiteral("<Something recent>");
|
||||
}
|
||||
// Bug 724640: FGLRX + Linux 2.6.32 is a crashy combo
|
||||
bool unknownOS = mOS.IsEmpty() || mOSRelease.IsEmpty();
|
||||
bool badOS = mOS.Find("Linux", true) != -1 &&
|
||||
mOSRelease.Find("2.6.32") != -1;
|
||||
if (unknownOS || badOS) {
|
||||
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_OS_VERSION;
|
||||
aFailureId = "FEATURE_FAILURE_OLD_OS";
|
||||
}
|
||||
} else {
|
||||
// like on windows, let's block unknown vendors. Think of virtual machines.
|
||||
// Also, this case is hit whenever the GLXtest probe failed to get driver info or crashed.
|
||||
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return GfxInfoBase::GetFeatureStatusImpl(aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, aFailureId, &os);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetD2DEnabled(bool *aEnabled)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetDWriteEnabled(bool *aEnabled)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetCleartypeParameters(nsAString & aCleartypeParams)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterDescription(nsAString & aAdapterDescription)
|
||||
{
|
||||
GetData();
|
||||
AppendASCIItoUTF16(mAdapterDescription, aAdapterDescription);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterDescription2(nsAString & aAdapterDescription)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterRAM(nsAString & aAdapterRAM)
|
||||
{
|
||||
aAdapterRAM.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterRAM2(nsAString & aAdapterRAM)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterDriver(nsAString & aAdapterDriver)
|
||||
{
|
||||
aAdapterDriver.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterDriver2(nsAString & aAdapterDriver)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterDriverVersion(nsAString & aAdapterDriverVersion)
|
||||
{
|
||||
GetData();
|
||||
CopyASCIItoUTF16(mVersion, aAdapterDriverVersion);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterDriverDate(nsAString & aAdapterDriverDate)
|
||||
{
|
||||
aAdapterDriverDate.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterDriverDate2(nsAString & aAdapterDriverDate)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterVendorID(nsAString & aAdapterVendorID)
|
||||
{
|
||||
GetData();
|
||||
CopyUTF8toUTF16(mVendor, aAdapterVendorID);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterVendorID2(nsAString & aAdapterVendorID)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterDeviceID(nsAString & aAdapterDeviceID)
|
||||
{
|
||||
GetData();
|
||||
CopyUTF8toUTF16(mRenderer, aAdapterDeviceID);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterDeviceID2(nsAString & aAdapterDeviceID)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterSubsysID(nsAString & aAdapterSubsysID)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterSubsysID2(nsAString & aAdapterSubsysID)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
// Implement nsIGfxInfoDebug
|
||||
// We don't support spoofing anything on Linux
|
||||
|
||||
NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString & aVendorID)
|
||||
{
|
||||
CopyUTF16toUTF8(aVendorID, mVendor);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP GfxInfo::SpoofDeviceID(const nsAString & aDeviceID)
|
||||
{
|
||||
CopyUTF16toUTF8(aDeviceID, mRenderer);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP GfxInfo::SpoofDriverVersion(const nsAString & aDriverVersion)
|
||||
{
|
||||
CopyUTF16toUTF8(aDriverVersion, mVersion);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP GfxInfo::SpoofOSVersion(uint32_t aVersion)
|
||||
{
|
||||
// We don't support OS versioning on Linux. There's just "Linux".
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // end namespace widget
|
||||
} // end namespace mozilla
|
||||
84
widget/GfxInfoX11.h
Normal file
84
widget/GfxInfoX11.h
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/* vim: se cin sw=2 ts=2 et : */
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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/. */
|
||||
|
||||
#ifndef __GfxInfoX11_h__
|
||||
#define __GfxInfoX11_h__
|
||||
|
||||
#include "GfxInfoBase.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
class GfxInfo final : public GfxInfoBase
|
||||
{
|
||||
public:
|
||||
|
||||
// We only declare the subset of nsIGfxInfo that we actually implement. The
|
||||
// rest is brought forward from GfxInfoBase.
|
||||
NS_IMETHOD GetD2DEnabled(bool *aD2DEnabled) override;
|
||||
NS_IMETHOD GetDWriteEnabled(bool *aDWriteEnabled) override;
|
||||
NS_IMETHOD GetDWriteVersion(nsAString & aDwriteVersion) override;
|
||||
NS_IMETHOD GetCleartypeParameters(nsAString & aCleartypeParams) override;
|
||||
NS_IMETHOD GetAdapterDescription(nsAString & aAdapterDescription) override;
|
||||
NS_IMETHOD GetAdapterDriver(nsAString & aAdapterDriver) override;
|
||||
NS_IMETHOD GetAdapterVendorID(nsAString & aAdapterVendorID) override;
|
||||
NS_IMETHOD GetAdapterDeviceID(nsAString & aAdapterDeviceID) override;
|
||||
NS_IMETHOD GetAdapterSubsysID(nsAString & aAdapterSubsysID) override;
|
||||
NS_IMETHOD GetAdapterRAM(nsAString & aAdapterRAM) override;
|
||||
NS_IMETHOD GetAdapterDriverVersion(nsAString & aAdapterDriverVersion) override;
|
||||
NS_IMETHOD GetAdapterDriverDate(nsAString & aAdapterDriverDate) override;
|
||||
NS_IMETHOD GetAdapterDescription2(nsAString & aAdapterDescription) override;
|
||||
NS_IMETHOD GetAdapterDriver2(nsAString & aAdapterDriver) override;
|
||||
NS_IMETHOD GetAdapterVendorID2(nsAString & aAdapterVendorID) override;
|
||||
NS_IMETHOD GetAdapterDeviceID2(nsAString & aAdapterDeviceID) override;
|
||||
NS_IMETHOD GetAdapterSubsysID2(nsAString & aAdapterSubsysID) override;
|
||||
NS_IMETHOD GetAdapterRAM2(nsAString & aAdapterRAM) override;
|
||||
NS_IMETHOD GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion) override;
|
||||
NS_IMETHOD GetAdapterDriverDate2(nsAString & aAdapterDriverDate) override;
|
||||
NS_IMETHOD GetIsGPU2Active(bool *aIsGPU2Active) override;
|
||||
using GfxInfoBase::GetFeatureStatus;
|
||||
using GfxInfoBase::GetFeatureSuggestedDriverVersion;
|
||||
using GfxInfoBase::GetWebGLParameter;
|
||||
|
||||
virtual nsresult Init() override;
|
||||
|
||||
NS_IMETHOD_(void) GetData() override;
|
||||
|
||||
#ifdef DEBUG
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIGFXINFODEBUG
|
||||
#endif
|
||||
|
||||
protected:
|
||||
~GfxInfo() {}
|
||||
|
||||
virtual nsresult GetFeatureStatusImpl(int32_t aFeature,
|
||||
int32_t *aStatus,
|
||||
nsAString & aSuggestedDriverVersion,
|
||||
const nsTArray<GfxDriverInfo>& aDriverInfo,
|
||||
nsACString& aFailureId,
|
||||
OperatingSystem* aOS = nullptr) override;
|
||||
virtual const nsTArray<GfxDriverInfo>& GetGfxDriverInfo() override;
|
||||
|
||||
private:
|
||||
nsCString mVendor;
|
||||
nsCString mRenderer;
|
||||
nsCString mVersion;
|
||||
nsCString mAdapterDescription;
|
||||
nsCString mOS;
|
||||
nsCString mOSRelease;
|
||||
bool mIsMesa, mIsNVIDIA, mIsFGLRX, mIsNouveau, mIsIntel, mIsOldSwrast, mIsLlvmpipe;
|
||||
bool mHasTextureFromPixmap;
|
||||
int mGLMajorVersion, mMajorVersion, mMinorVersion, mRevisionVersion;
|
||||
|
||||
void AddCrashReportAnnotations();
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* __GfxInfoX11_h__ */
|
||||
882
widget/IMEData.h
Normal file
882
widget/IMEData.h
Normal file
|
|
@ -0,0 +1,882 @@
|
|||
/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_widget_IMEData_h_
|
||||
#define mozilla_widget_IMEData_h_
|
||||
|
||||
#include "nsPoint.h"
|
||||
#include "nsRect.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
class nsIWidget;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class WritingMode;
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
/**
|
||||
* Preference for receiving IME updates
|
||||
*
|
||||
* If mWantUpdates is not NOTIFY_NOTHING, nsTextStateManager will observe text
|
||||
* change and/or selection change and call nsIWidget::NotifyIME() with
|
||||
* NOTIFY_IME_OF_SELECTION_CHANGE and/or NOTIFY_IME_OF_TEXT_CHANGE.
|
||||
* Please note that the text change observing cost is very expensive especially
|
||||
* on an HTML editor has focus.
|
||||
* If the IME implementation on a particular platform doesn't care about
|
||||
* NOTIFY_IME_OF_SELECTION_CHANGE and/or NOTIFY_IME_OF_TEXT_CHANGE,
|
||||
* they should set mWantUpdates to NOTIFY_NOTHING to avoid the cost.
|
||||
* If the IME implementation needs notifications even while our process is
|
||||
* deactive, it should also set NOTIFY_DURING_DEACTIVE.
|
||||
*/
|
||||
struct nsIMEUpdatePreference final
|
||||
{
|
||||
typedef uint8_t Notifications;
|
||||
|
||||
enum : Notifications
|
||||
{
|
||||
NOTIFY_NOTHING = 0,
|
||||
NOTIFY_TEXT_CHANGE = 1 << 1,
|
||||
NOTIFY_POSITION_CHANGE = 1 << 2,
|
||||
// NOTIFY_MOUSE_BUTTON_EVENT_ON_CHAR is used when mouse button is pressed
|
||||
// or released on a character in the focused editor. The notification is
|
||||
// notified to IME as a mouse event. If it's consumed by IME, NotifyIME()
|
||||
// returns NS_SUCCESS_EVENT_CONSUMED. Otherwise, it returns NS_OK if it's
|
||||
// handled without any error.
|
||||
NOTIFY_MOUSE_BUTTON_EVENT_ON_CHAR = 1 << 3,
|
||||
// NOTE: NOTIFY_DURING_DEACTIVE isn't supported in environments where two
|
||||
// or more compositions are possible. E.g., Mac and Linux (GTK).
|
||||
NOTIFY_DURING_DEACTIVE = 1 << 7
|
||||
};
|
||||
|
||||
nsIMEUpdatePreference()
|
||||
: mWantUpdates(NOTIFY_NOTHING)
|
||||
{
|
||||
}
|
||||
|
||||
explicit nsIMEUpdatePreference(Notifications aWantUpdates)
|
||||
: mWantUpdates(aWantUpdates)
|
||||
{
|
||||
}
|
||||
|
||||
nsIMEUpdatePreference operator|(const nsIMEUpdatePreference& aOther) const
|
||||
{
|
||||
return nsIMEUpdatePreference(aOther.mWantUpdates | mWantUpdates);
|
||||
}
|
||||
|
||||
bool WantTextChange() const
|
||||
{
|
||||
return !!(mWantUpdates & NOTIFY_TEXT_CHANGE);
|
||||
}
|
||||
|
||||
bool WantPositionChanged() const
|
||||
{
|
||||
return !!(mWantUpdates & NOTIFY_POSITION_CHANGE);
|
||||
}
|
||||
|
||||
bool WantChanges() const
|
||||
{
|
||||
return WantTextChange();
|
||||
}
|
||||
|
||||
bool WantMouseButtonEventOnChar() const
|
||||
{
|
||||
return !!(mWantUpdates & NOTIFY_MOUSE_BUTTON_EVENT_ON_CHAR);
|
||||
}
|
||||
|
||||
bool WantDuringDeactive() const
|
||||
{
|
||||
return !!(mWantUpdates & NOTIFY_DURING_DEACTIVE);
|
||||
}
|
||||
|
||||
Notifications mWantUpdates;
|
||||
};
|
||||
|
||||
/**
|
||||
* Contains IMEStatus plus information about the current
|
||||
* input context that the IME can use as hints if desired.
|
||||
*/
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
struct IMEState final
|
||||
{
|
||||
/**
|
||||
* IME enabled states, the mEnabled value of
|
||||
* SetInputContext()/GetInputContext() should be one value of following
|
||||
* values.
|
||||
*
|
||||
* WARNING: If you change these values, you also need to edit:
|
||||
* nsIDOMWindowUtils.idl
|
||||
* nsContentUtils::GetWidgetStatusFromIMEStatus
|
||||
*/
|
||||
enum Enabled
|
||||
{
|
||||
/**
|
||||
* 'Disabled' means the user cannot use IME. So, the IME open state should
|
||||
* be 'closed' during 'disabled'.
|
||||
*/
|
||||
DISABLED,
|
||||
/**
|
||||
* 'Enabled' means the user can use IME.
|
||||
*/
|
||||
ENABLED,
|
||||
/**
|
||||
* 'Password' state is a special case for the password editors.
|
||||
* E.g., on mac, the password editors should disable the non-Roman
|
||||
* keyboard layouts at getting focus. Thus, the password editor may have
|
||||
* special rules on some platforms.
|
||||
*/
|
||||
PASSWORD,
|
||||
/**
|
||||
* This state is used when a plugin is focused.
|
||||
* When a plug-in is focused content, we should send native events
|
||||
* directly. Because we don't process some native events, but they may
|
||||
* be needed by the plug-in.
|
||||
*/
|
||||
PLUGIN,
|
||||
/**
|
||||
* 'Unknown' is useful when you cache this enum. So, this shouldn't be
|
||||
* used with nsIWidget::SetInputContext().
|
||||
*/
|
||||
UNKNOWN
|
||||
};
|
||||
Enabled mEnabled;
|
||||
|
||||
/**
|
||||
* IME open states the mOpen value of SetInputContext() should be one value of
|
||||
* OPEN, CLOSE or DONT_CHANGE_OPEN_STATE. GetInputContext() should return
|
||||
* OPEN, CLOSE or OPEN_STATE_NOT_SUPPORTED.
|
||||
*/
|
||||
enum Open
|
||||
{
|
||||
/**
|
||||
* 'Unsupported' means the platform cannot return actual IME open state.
|
||||
* This value is used only by GetInputContext().
|
||||
*/
|
||||
OPEN_STATE_NOT_SUPPORTED,
|
||||
/**
|
||||
* 'Don't change' means the widget shouldn't change IME open state when
|
||||
* SetInputContext() is called.
|
||||
*/
|
||||
DONT_CHANGE_OPEN_STATE = OPEN_STATE_NOT_SUPPORTED,
|
||||
/**
|
||||
* 'Open' means that IME should compose in its primary language (or latest
|
||||
* input mode except direct ASCII character input mode). Even if IME is
|
||||
* opened by this value, users should be able to close IME by theirselves.
|
||||
* Web contents can specify this value by |ime-mode: active;|.
|
||||
*/
|
||||
OPEN,
|
||||
/**
|
||||
* 'Closed' means that IME shouldn't handle key events (or should handle
|
||||
* as ASCII character inputs on mobile device). Even if IME is closed by
|
||||
* this value, users should be able to open IME by theirselves.
|
||||
* Web contents can specify this value by |ime-mode: inactive;|.
|
||||
*/
|
||||
CLOSED
|
||||
};
|
||||
Open mOpen;
|
||||
|
||||
IMEState()
|
||||
: mEnabled(ENABLED)
|
||||
, mOpen(DONT_CHANGE_OPEN_STATE)
|
||||
{
|
||||
}
|
||||
|
||||
explicit IMEState(Enabled aEnabled, Open aOpen = DONT_CHANGE_OPEN_STATE)
|
||||
: mEnabled(aEnabled)
|
||||
, mOpen(aOpen)
|
||||
{
|
||||
}
|
||||
|
||||
// Returns true if the user can input characters.
|
||||
// This means that a plain text editor, an HTML editor, a password editor or
|
||||
// a plain text editor whose ime-mode is "disabled".
|
||||
bool IsEditable() const
|
||||
{
|
||||
return mEnabled == ENABLED || mEnabled == PASSWORD;
|
||||
}
|
||||
// Returns true if the user might be able to input characters.
|
||||
// This means that a plain text editor, an HTML editor, a password editor,
|
||||
// a plain text editor whose ime-mode is "disabled" or a windowless plugin
|
||||
// has focus.
|
||||
bool MaybeEditable() const
|
||||
{
|
||||
return IsEditable() || mEnabled == PLUGIN;
|
||||
}
|
||||
};
|
||||
|
||||
// NS_ONLY_ONE_NATIVE_IME_CONTEXT is a special value of native IME context.
|
||||
// If there can be only one IME composition in a process, this can be used.
|
||||
#define NS_ONLY_ONE_NATIVE_IME_CONTEXT \
|
||||
(reinterpret_cast<void*>(static_cast<intptr_t>(-1)))
|
||||
|
||||
struct NativeIMEContext final
|
||||
{
|
||||
// Pointer to native IME context. Typically this is the result of
|
||||
// nsIWidget::GetNativeData(NS_RAW_NATIVE_IME_CONTEXT) in the parent process.
|
||||
// See also NS_ONLY_ONE_NATIVE_IME_CONTEXT.
|
||||
uintptr_t mRawNativeIMEContext;
|
||||
// Process ID of the origin of mNativeIMEContext.
|
||||
uint64_t mOriginProcessID;
|
||||
|
||||
NativeIMEContext()
|
||||
{
|
||||
Init(nullptr);
|
||||
}
|
||||
|
||||
explicit NativeIMEContext(nsIWidget* aWidget)
|
||||
{
|
||||
Init(aWidget);
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return mRawNativeIMEContext &&
|
||||
mOriginProcessID != static_cast<uintptr_t>(-1);
|
||||
}
|
||||
|
||||
void Init(nsIWidget* aWidget);
|
||||
void InitWithRawNativeIMEContext(const void* aRawNativeIMEContext)
|
||||
{
|
||||
InitWithRawNativeIMEContext(const_cast<void*>(aRawNativeIMEContext));
|
||||
}
|
||||
void InitWithRawNativeIMEContext(void* aRawNativeIMEContext);
|
||||
|
||||
bool operator==(const NativeIMEContext& aOther) const
|
||||
{
|
||||
return mRawNativeIMEContext == aOther.mRawNativeIMEContext &&
|
||||
mOriginProcessID == aOther.mOriginProcessID;
|
||||
}
|
||||
bool operator!=(const NativeIMEContext& aOther) const
|
||||
{
|
||||
return !(*this == aOther);
|
||||
}
|
||||
};
|
||||
|
||||
struct InputContext final
|
||||
{
|
||||
InputContext()
|
||||
: mOrigin(XRE_IsParentProcess() ? ORIGIN_MAIN : ORIGIN_CONTENT)
|
||||
, mMayBeIMEUnaware(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool IsPasswordEditor() const
|
||||
{
|
||||
return mHTMLInputType.LowerCaseEqualsLiteral("password");
|
||||
}
|
||||
|
||||
IMEState mIMEState;
|
||||
|
||||
/* The type of the input if the input is a html input field */
|
||||
nsString mHTMLInputType;
|
||||
|
||||
/* The type of the inputmode */
|
||||
nsString mHTMLInputInputmode;
|
||||
|
||||
/* A hint for the action that is performed when the input is submitted */
|
||||
nsString mActionHint;
|
||||
|
||||
/**
|
||||
* mOrigin indicates whether this focus event refers to main or remote
|
||||
* content.
|
||||
*/
|
||||
enum Origin
|
||||
{
|
||||
// Adjusting focus of content on the main process
|
||||
ORIGIN_MAIN,
|
||||
// Adjusting focus of content in a remote process
|
||||
ORIGIN_CONTENT
|
||||
};
|
||||
Origin mOrigin;
|
||||
|
||||
/* True if the webapp may be unaware of IME events such as input event or
|
||||
* composiion events. This enables a key-events-only mode on Android for
|
||||
* compatibility with webapps relying on key listeners. */
|
||||
bool mMayBeIMEUnaware;
|
||||
|
||||
bool IsOriginMainProcess() const
|
||||
{
|
||||
return mOrigin == ORIGIN_MAIN;
|
||||
}
|
||||
|
||||
bool IsOriginContentProcess() const
|
||||
{
|
||||
return mOrigin == ORIGIN_CONTENT;
|
||||
}
|
||||
|
||||
bool IsOriginCurrentProcess() const
|
||||
{
|
||||
if (XRE_IsParentProcess()) {
|
||||
return IsOriginMainProcess();
|
||||
}
|
||||
return IsOriginContentProcess();
|
||||
}
|
||||
};
|
||||
|
||||
struct InputContextAction final
|
||||
{
|
||||
/**
|
||||
* mCause indicates what action causes calling nsIWidget::SetInputContext().
|
||||
* It must be one of following values.
|
||||
*/
|
||||
enum Cause
|
||||
{
|
||||
// The cause is unknown but originated from content. Focus might have been
|
||||
// changed by content script.
|
||||
CAUSE_UNKNOWN,
|
||||
// The cause is unknown but originated from chrome. Focus might have been
|
||||
// changed by chrome script.
|
||||
CAUSE_UNKNOWN_CHROME,
|
||||
// The cause is user's keyboard operation.
|
||||
CAUSE_KEY,
|
||||
// The cause is user's mouse operation.
|
||||
CAUSE_MOUSE,
|
||||
// The cause is user's touch operation (implies mouse)
|
||||
CAUSE_TOUCH
|
||||
};
|
||||
Cause mCause;
|
||||
|
||||
/**
|
||||
* mFocusChange indicates what happened for focus.
|
||||
*/
|
||||
enum FocusChange
|
||||
{
|
||||
FOCUS_NOT_CHANGED,
|
||||
// A content got focus.
|
||||
GOT_FOCUS,
|
||||
// Focused content lost focus.
|
||||
LOST_FOCUS,
|
||||
// Menu got pseudo focus that means focused content isn't changed but
|
||||
// keyboard events will be handled by menu.
|
||||
MENU_GOT_PSEUDO_FOCUS,
|
||||
// Menu lost pseudo focus that means focused content will handle keyboard
|
||||
// events.
|
||||
MENU_LOST_PSEUDO_FOCUS
|
||||
};
|
||||
FocusChange mFocusChange;
|
||||
|
||||
bool ContentGotFocusByTrustedCause() const
|
||||
{
|
||||
return (mFocusChange == GOT_FOCUS &&
|
||||
mCause != CAUSE_UNKNOWN);
|
||||
}
|
||||
|
||||
bool UserMightRequestOpenVKB() const
|
||||
{
|
||||
return (mFocusChange == FOCUS_NOT_CHANGED &&
|
||||
(mCause == CAUSE_MOUSE || mCause == CAUSE_TOUCH));
|
||||
}
|
||||
|
||||
static bool IsUserAction(Cause aCause)
|
||||
{
|
||||
switch (aCause) {
|
||||
case CAUSE_KEY:
|
||||
case CAUSE_MOUSE:
|
||||
case CAUSE_TOUCH:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
InputContextAction()
|
||||
: mCause(CAUSE_UNKNOWN)
|
||||
, mFocusChange(FOCUS_NOT_CHANGED)
|
||||
{
|
||||
}
|
||||
|
||||
explicit InputContextAction(Cause aCause,
|
||||
FocusChange aFocusChange = FOCUS_NOT_CHANGED)
|
||||
: mCause(aCause)
|
||||
, mFocusChange(aFocusChange)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// IMEMessage is shared by IMEStateManager and TextComposition.
|
||||
// Update values in GeckoEditable.java if you make changes here.
|
||||
// XXX Negative values are used in Android...
|
||||
typedef int8_t IMEMessageType;
|
||||
enum IMEMessage : IMEMessageType
|
||||
{
|
||||
// This is used by IMENotification internally. This means that the instance
|
||||
// hasn't been initialized yet.
|
||||
NOTIFY_IME_OF_NOTHING,
|
||||
// An editable content is getting focus
|
||||
NOTIFY_IME_OF_FOCUS,
|
||||
// An editable content is losing focus
|
||||
NOTIFY_IME_OF_BLUR,
|
||||
// Selection in the focused editable content is changed
|
||||
NOTIFY_IME_OF_SELECTION_CHANGE,
|
||||
// Text in the focused editable content is changed
|
||||
NOTIFY_IME_OF_TEXT_CHANGE,
|
||||
// Notified when a dispatched composition event is handled by the
|
||||
// contents. This must be notified after the other notifications.
|
||||
// Note that if a remote process has focus, this is notified only once when
|
||||
// all dispatched events are handled completely. So, the receiver shouldn't
|
||||
// count number of received this notification for comparing with the number
|
||||
// of dispatched events.
|
||||
// NOTE: If a composition event causes moving focus from the focused editor,
|
||||
// this notification may not be notified as usual. Even in such case,
|
||||
// NOTIFY_IME_OF_BLUR is always sent. So, notification listeners
|
||||
// should tread the blur notification as including this if there is
|
||||
// pending composition events.
|
||||
NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED,
|
||||
// Position or size of focused element may be changed.
|
||||
NOTIFY_IME_OF_POSITION_CHANGE,
|
||||
// Mouse button event is fired on a character in focused editor
|
||||
NOTIFY_IME_OF_MOUSE_BUTTON_EVENT,
|
||||
// Request to commit current composition to IME
|
||||
// (some platforms may not support)
|
||||
REQUEST_TO_COMMIT_COMPOSITION,
|
||||
// Request to cancel current composition to IME
|
||||
// (some platforms may not support)
|
||||
REQUEST_TO_CANCEL_COMPOSITION
|
||||
};
|
||||
|
||||
// FYI: Implemented in nsBaseWidget.cpp
|
||||
const char* ToChar(IMEMessage aIMEMessage);
|
||||
|
||||
struct IMENotification final
|
||||
{
|
||||
IMENotification()
|
||||
: mMessage(NOTIFY_IME_OF_NOTHING)
|
||||
{
|
||||
}
|
||||
|
||||
IMENotification(const IMENotification& aOther)
|
||||
: mMessage(NOTIFY_IME_OF_NOTHING)
|
||||
{
|
||||
Assign(aOther);
|
||||
}
|
||||
|
||||
~IMENotification()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
MOZ_IMPLICIT IMENotification(IMEMessage aMessage)
|
||||
: mMessage(aMessage)
|
||||
{
|
||||
switch (aMessage) {
|
||||
case NOTIFY_IME_OF_SELECTION_CHANGE:
|
||||
mSelectionChangeData.mString = new nsString();
|
||||
mSelectionChangeData.Clear();
|
||||
break;
|
||||
case NOTIFY_IME_OF_TEXT_CHANGE:
|
||||
mTextChangeData.Clear();
|
||||
break;
|
||||
case NOTIFY_IME_OF_MOUSE_BUTTON_EVENT:
|
||||
mMouseButtonEventData.mEventMessage = eVoidEvent;
|
||||
mMouseButtonEventData.mOffset = UINT32_MAX;
|
||||
mMouseButtonEventData.mCursorPos.Set(nsIntPoint(0, 0));
|
||||
mMouseButtonEventData.mCharRect.Set(nsIntRect(0, 0, 0, 0));
|
||||
mMouseButtonEventData.mButton = -1;
|
||||
mMouseButtonEventData.mButtons = 0;
|
||||
mMouseButtonEventData.mModifiers = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Assign(const IMENotification& aOther)
|
||||
{
|
||||
bool changingMessage = mMessage != aOther.mMessage;
|
||||
if (changingMessage) {
|
||||
Clear();
|
||||
mMessage = aOther.mMessage;
|
||||
}
|
||||
switch (mMessage) {
|
||||
case NOTIFY_IME_OF_SELECTION_CHANGE:
|
||||
if (changingMessage) {
|
||||
mSelectionChangeData.mString = new nsString();
|
||||
}
|
||||
mSelectionChangeData.Assign(aOther.mSelectionChangeData);
|
||||
break;
|
||||
case NOTIFY_IME_OF_TEXT_CHANGE:
|
||||
mTextChangeData = aOther.mTextChangeData;
|
||||
break;
|
||||
case NOTIFY_IME_OF_MOUSE_BUTTON_EVENT:
|
||||
mMouseButtonEventData = aOther.mMouseButtonEventData;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
IMENotification& operator=(const IMENotification& aOther)
|
||||
{
|
||||
Assign(aOther);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
if (mMessage == NOTIFY_IME_OF_SELECTION_CHANGE) {
|
||||
MOZ_ASSERT(mSelectionChangeData.mString);
|
||||
delete mSelectionChangeData.mString;
|
||||
mSelectionChangeData.mString = nullptr;
|
||||
}
|
||||
mMessage = NOTIFY_IME_OF_NOTHING;
|
||||
}
|
||||
|
||||
bool HasNotification() const
|
||||
{
|
||||
return mMessage != NOTIFY_IME_OF_NOTHING;
|
||||
}
|
||||
|
||||
void MergeWith(const IMENotification& aNotification)
|
||||
{
|
||||
switch (mMessage) {
|
||||
case NOTIFY_IME_OF_NOTHING:
|
||||
MOZ_ASSERT(aNotification.mMessage != NOTIFY_IME_OF_NOTHING);
|
||||
Assign(aNotification);
|
||||
break;
|
||||
case NOTIFY_IME_OF_SELECTION_CHANGE:
|
||||
MOZ_ASSERT(aNotification.mMessage == NOTIFY_IME_OF_SELECTION_CHANGE);
|
||||
mSelectionChangeData.Assign(aNotification.mSelectionChangeData);
|
||||
break;
|
||||
case NOTIFY_IME_OF_TEXT_CHANGE:
|
||||
MOZ_ASSERT(aNotification.mMessage == NOTIFY_IME_OF_TEXT_CHANGE);
|
||||
mTextChangeData += aNotification.mTextChangeData;
|
||||
break;
|
||||
case NOTIFY_IME_OF_POSITION_CHANGE:
|
||||
case NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED:
|
||||
MOZ_ASSERT(aNotification.mMessage == mMessage);
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Merging notification isn't supported");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
IMEMessage mMessage;
|
||||
|
||||
struct Point
|
||||
{
|
||||
int32_t mX;
|
||||
int32_t mY;
|
||||
|
||||
void Set(const nsIntPoint& aPoint)
|
||||
{
|
||||
mX = aPoint.x;
|
||||
mY = aPoint.y;
|
||||
}
|
||||
nsIntPoint AsIntPoint() const
|
||||
{
|
||||
return nsIntPoint(mX, mY);
|
||||
}
|
||||
};
|
||||
|
||||
struct Rect
|
||||
{
|
||||
int32_t mX;
|
||||
int32_t mY;
|
||||
int32_t mWidth;
|
||||
int32_t mHeight;
|
||||
|
||||
void Set(const nsIntRect& aRect)
|
||||
{
|
||||
mX = aRect.x;
|
||||
mY = aRect.y;
|
||||
mWidth = aRect.width;
|
||||
mHeight = aRect.height;
|
||||
}
|
||||
nsIntRect AsIntRect() const
|
||||
{
|
||||
return nsIntRect(mX, mY, mWidth, mHeight);
|
||||
}
|
||||
};
|
||||
|
||||
// NOTIFY_IME_OF_SELECTION_CHANGE specific data
|
||||
struct SelectionChangeDataBase
|
||||
{
|
||||
// Selection range.
|
||||
uint32_t mOffset;
|
||||
|
||||
// Selected string
|
||||
nsString* mString;
|
||||
|
||||
// Writing mode at the selection.
|
||||
uint8_t mWritingMode;
|
||||
|
||||
bool mReversed;
|
||||
bool mCausedByComposition;
|
||||
bool mCausedBySelectionEvent;
|
||||
bool mOccurredDuringComposition;
|
||||
|
||||
void SetWritingMode(const WritingMode& aWritingMode);
|
||||
WritingMode GetWritingMode() const;
|
||||
|
||||
uint32_t StartOffset() const
|
||||
{
|
||||
return mOffset + (mReversed ? Length() : 0);
|
||||
}
|
||||
uint32_t EndOffset() const
|
||||
{
|
||||
return mOffset + (mReversed ? 0 : Length());
|
||||
}
|
||||
const nsString& String() const
|
||||
{
|
||||
return *mString;
|
||||
}
|
||||
uint32_t Length() const
|
||||
{
|
||||
return mString->Length();
|
||||
}
|
||||
bool IsInInt32Range() const
|
||||
{
|
||||
return mOffset + Length() <= INT32_MAX;
|
||||
}
|
||||
bool IsCollapsed() const
|
||||
{
|
||||
return mString->IsEmpty();
|
||||
}
|
||||
void ClearSelectionData()
|
||||
{
|
||||
mOffset = UINT32_MAX;
|
||||
mString->Truncate();
|
||||
mWritingMode = 0;
|
||||
mReversed = false;
|
||||
}
|
||||
void Clear()
|
||||
{
|
||||
ClearSelectionData();
|
||||
mCausedByComposition = false;
|
||||
mCausedBySelectionEvent = false;
|
||||
mOccurredDuringComposition = false;
|
||||
}
|
||||
bool IsValid() const
|
||||
{
|
||||
return mOffset != UINT32_MAX;
|
||||
}
|
||||
void Assign(const SelectionChangeDataBase& aOther)
|
||||
{
|
||||
mOffset = aOther.mOffset;
|
||||
*mString = aOther.String();
|
||||
mWritingMode = aOther.mWritingMode;
|
||||
mReversed = aOther.mReversed;
|
||||
AssignReason(aOther.mCausedByComposition,
|
||||
aOther.mCausedBySelectionEvent,
|
||||
aOther.mOccurredDuringComposition);
|
||||
}
|
||||
void AssignReason(bool aCausedByComposition,
|
||||
bool aCausedBySelectionEvent,
|
||||
bool aOccurredDuringComposition)
|
||||
{
|
||||
mCausedByComposition = aCausedByComposition;
|
||||
mCausedBySelectionEvent = aCausedBySelectionEvent;
|
||||
mOccurredDuringComposition = aOccurredDuringComposition;
|
||||
}
|
||||
};
|
||||
|
||||
// SelectionChangeDataBase cannot have constructors because it's used in
|
||||
// the union. Therefore, SelectionChangeData should only implement
|
||||
// constructors. In other words, add other members to
|
||||
// SelectionChangeDataBase.
|
||||
struct SelectionChangeData final : public SelectionChangeDataBase
|
||||
{
|
||||
SelectionChangeData()
|
||||
{
|
||||
mString = &mStringInstance;
|
||||
Clear();
|
||||
}
|
||||
explicit SelectionChangeData(const SelectionChangeDataBase& aOther)
|
||||
{
|
||||
mString = &mStringInstance;
|
||||
Assign(aOther);
|
||||
}
|
||||
SelectionChangeData(const SelectionChangeData& aOther)
|
||||
{
|
||||
mString = &mStringInstance;
|
||||
Assign(aOther);
|
||||
}
|
||||
SelectionChangeData& operator=(const SelectionChangeDataBase& aOther)
|
||||
{
|
||||
mString = &mStringInstance;
|
||||
Assign(aOther);
|
||||
return *this;
|
||||
}
|
||||
SelectionChangeData& operator=(const SelectionChangeData& aOther)
|
||||
{
|
||||
mString = &mStringInstance;
|
||||
Assign(aOther);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
// When SelectionChangeData is used outside of union, it shouldn't create
|
||||
// nsString instance in the heap as far as possible.
|
||||
nsString mStringInstance;
|
||||
};
|
||||
|
||||
struct TextChangeDataBase
|
||||
{
|
||||
// mStartOffset is the start offset of modified or removed text in
|
||||
// original content and inserted text in new content.
|
||||
uint32_t mStartOffset;
|
||||
// mRemovalEndOffset is the end offset of modified or removed text in
|
||||
// original content. If the value is same as mStartOffset, no text hasn't
|
||||
// been removed yet.
|
||||
uint32_t mRemovedEndOffset;
|
||||
// mAddedEndOffset is the end offset of inserted text or same as
|
||||
// mStartOffset if just removed. The vlaue is offset in the new content.
|
||||
uint32_t mAddedEndOffset;
|
||||
|
||||
// Note that TextChangeDataBase may be the result of merging two or more
|
||||
// changes especially in e10s mode.
|
||||
|
||||
// mCausedOnlyByComposition is true only when *all* merged changes are
|
||||
// caused by composition.
|
||||
bool mCausedOnlyByComposition;
|
||||
// mIncludingChangesDuringComposition is true if at least one change which
|
||||
// is not caused by composition occurred during the last composition.
|
||||
// Note that if after the last composition is finished and there are some
|
||||
// changes not caused by composition, this is set to false.
|
||||
bool mIncludingChangesDuringComposition;
|
||||
// mIncludingChangesWithoutComposition is true if there is at least one
|
||||
// change which did occur when there wasn't a composition ongoing.
|
||||
bool mIncludingChangesWithoutComposition;
|
||||
|
||||
uint32_t OldLength() const
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
return mRemovedEndOffset - mStartOffset;
|
||||
}
|
||||
uint32_t NewLength() const
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
return mAddedEndOffset - mStartOffset;
|
||||
}
|
||||
|
||||
// Positive if text is added. Negative if text is removed.
|
||||
int64_t Difference() const
|
||||
{
|
||||
return mAddedEndOffset - mRemovedEndOffset;
|
||||
}
|
||||
|
||||
bool IsInInt32Range() const
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
return mStartOffset <= INT32_MAX &&
|
||||
mRemovedEndOffset <= INT32_MAX &&
|
||||
mAddedEndOffset <= INT32_MAX;
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return !(mStartOffset == UINT32_MAX &&
|
||||
!mRemovedEndOffset && !mAddedEndOffset);
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
mStartOffset = UINT32_MAX;
|
||||
mRemovedEndOffset = mAddedEndOffset = 0;
|
||||
}
|
||||
|
||||
void MergeWith(const TextChangeDataBase& aOther);
|
||||
TextChangeDataBase& operator+=(const TextChangeDataBase& aOther)
|
||||
{
|
||||
MergeWith(aOther);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void Test();
|
||||
#endif // #ifdef DEBUG
|
||||
};
|
||||
|
||||
// TextChangeDataBase cannot have constructors because they are used in union.
|
||||
// Therefore, TextChangeData should only implement constructor. In other
|
||||
// words, add other members to TextChangeDataBase.
|
||||
struct TextChangeData : public TextChangeDataBase
|
||||
{
|
||||
TextChangeData() { Clear(); }
|
||||
|
||||
TextChangeData(uint32_t aStartOffset,
|
||||
uint32_t aRemovedEndOffset,
|
||||
uint32_t aAddedEndOffset,
|
||||
bool aCausedByComposition,
|
||||
bool aOccurredDuringComposition)
|
||||
{
|
||||
MOZ_ASSERT(aRemovedEndOffset >= aStartOffset,
|
||||
"removed end offset must not be smaller than start offset");
|
||||
MOZ_ASSERT(aAddedEndOffset >= aStartOffset,
|
||||
"added end offset must not be smaller than start offset");
|
||||
mStartOffset = aStartOffset;
|
||||
mRemovedEndOffset = aRemovedEndOffset;
|
||||
mAddedEndOffset = aAddedEndOffset;
|
||||
mCausedOnlyByComposition = aCausedByComposition;
|
||||
mIncludingChangesDuringComposition =
|
||||
!aCausedByComposition && aOccurredDuringComposition;
|
||||
mIncludingChangesWithoutComposition =
|
||||
!aCausedByComposition && !aOccurredDuringComposition;
|
||||
}
|
||||
};
|
||||
|
||||
struct MouseButtonEventData
|
||||
{
|
||||
// The value of WidgetEvent::mMessage
|
||||
EventMessage mEventMessage;
|
||||
// Character offset from the start of the focused editor under the cursor
|
||||
uint32_t mOffset;
|
||||
// Cursor position in pixels relative to the widget
|
||||
Point mCursorPos;
|
||||
// Character rect in pixels under the cursor relative to the widget
|
||||
Rect mCharRect;
|
||||
// The value of WidgetMouseEventBase::button and buttons
|
||||
int16_t mButton;
|
||||
int16_t mButtons;
|
||||
// The value of WidgetInputEvent::modifiers
|
||||
Modifiers mModifiers;
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
// NOTIFY_IME_OF_SELECTION_CHANGE specific data
|
||||
SelectionChangeDataBase mSelectionChangeData;
|
||||
|
||||
// NOTIFY_IME_OF_TEXT_CHANGE specific data
|
||||
TextChangeDataBase mTextChangeData;
|
||||
|
||||
// NOTIFY_IME_OF_MOUSE_BUTTON_EVENT specific data
|
||||
MouseButtonEventData mMouseButtonEventData;
|
||||
};
|
||||
|
||||
void SetData(const SelectionChangeDataBase& aSelectionChangeData)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(mMessage == NOTIFY_IME_OF_SELECTION_CHANGE);
|
||||
mSelectionChangeData.Assign(aSelectionChangeData);
|
||||
}
|
||||
|
||||
void SetData(const TextChangeDataBase& aTextChangeData)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(mMessage == NOTIFY_IME_OF_TEXT_CHANGE);
|
||||
mTextChangeData = aTextChangeData;
|
||||
}
|
||||
};
|
||||
|
||||
struct CandidateWindowPosition
|
||||
{
|
||||
// Upper left corner of the candidate window if mExcludeRect is false.
|
||||
// Otherwise, the position currently interested. E.g., caret position.
|
||||
LayoutDeviceIntPoint mPoint;
|
||||
// Rect which shouldn't be overlapped with the candidate window.
|
||||
// This is valid only when mExcludeRect is true.
|
||||
LayoutDeviceIntRect mRect;
|
||||
// See explanation of mPoint and mRect.
|
||||
bool mExcludeRect;
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // #ifndef mozilla_widget_IMEData_h_
|
||||
145
widget/InProcessCompositorWidget.cpp
Normal file
145
widget/InProcessCompositorWidget.cpp
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
/* 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 "InProcessCompositorWidget.h"
|
||||
#include "nsBaseWidget.h"
|
||||
|
||||
#if defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING)
|
||||
#include "mozilla/widget/AndroidCompositorWidget.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
// Platforms with no OOP compositor process support use
|
||||
// InProcessCompositorWidget by default.
|
||||
#if !defined(MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING)
|
||||
/* static */ RefPtr<CompositorWidget>
|
||||
CompositorWidget::CreateLocal(const CompositorWidgetInitData& aInitData, nsIWidget* aWidget)
|
||||
{
|
||||
MOZ_ASSERT(aWidget);
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
return new AndroidCompositorWidget(static_cast<nsBaseWidget*>(aWidget));
|
||||
#else
|
||||
return new InProcessCompositorWidget(static_cast<nsBaseWidget*>(aWidget));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
InProcessCompositorWidget::InProcessCompositorWidget(nsBaseWidget* aWidget)
|
||||
: mWidget(aWidget)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
InProcessCompositorWidget::PreRender(WidgetRenderingContext* aContext)
|
||||
{
|
||||
return mWidget->PreRender(aContext);
|
||||
}
|
||||
|
||||
void
|
||||
InProcessCompositorWidget::PostRender(WidgetRenderingContext* aContext)
|
||||
{
|
||||
mWidget->PostRender(aContext);
|
||||
}
|
||||
|
||||
void
|
||||
InProcessCompositorWidget::DrawWindowUnderlay(WidgetRenderingContext* aContext,
|
||||
LayoutDeviceIntRect aRect)
|
||||
{
|
||||
mWidget->DrawWindowUnderlay(aContext, aRect);
|
||||
}
|
||||
|
||||
void
|
||||
InProcessCompositorWidget::DrawWindowOverlay(WidgetRenderingContext* aContext,
|
||||
LayoutDeviceIntRect aRect)
|
||||
{
|
||||
mWidget->DrawWindowOverlay(aContext, aRect);
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::DrawTarget>
|
||||
InProcessCompositorWidget::StartRemoteDrawing()
|
||||
{
|
||||
return mWidget->StartRemoteDrawing();
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::DrawTarget>
|
||||
InProcessCompositorWidget::StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion,
|
||||
layers::BufferMode* aBufferMode)
|
||||
{
|
||||
return mWidget->StartRemoteDrawingInRegion(aInvalidRegion, aBufferMode);
|
||||
}
|
||||
|
||||
void
|
||||
InProcessCompositorWidget::EndRemoteDrawing()
|
||||
{
|
||||
mWidget->EndRemoteDrawing();
|
||||
}
|
||||
|
||||
void
|
||||
InProcessCompositorWidget::EndRemoteDrawingInRegion(gfx::DrawTarget* aDrawTarget,
|
||||
LayoutDeviceIntRegion& aInvalidRegion)
|
||||
{
|
||||
mWidget->EndRemoteDrawingInRegion(aDrawTarget, aInvalidRegion);
|
||||
}
|
||||
|
||||
void
|
||||
InProcessCompositorWidget::CleanupRemoteDrawing()
|
||||
{
|
||||
mWidget->CleanupRemoteDrawing();
|
||||
}
|
||||
|
||||
void
|
||||
InProcessCompositorWidget::CleanupWindowEffects()
|
||||
{
|
||||
mWidget->CleanupWindowEffects();
|
||||
}
|
||||
|
||||
bool
|
||||
InProcessCompositorWidget::InitCompositor(layers::Compositor* aCompositor)
|
||||
{
|
||||
return mWidget->InitCompositor(aCompositor);
|
||||
}
|
||||
|
||||
LayoutDeviceIntSize
|
||||
InProcessCompositorWidget::GetClientSize()
|
||||
{
|
||||
return mWidget->GetClientSize();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
InProcessCompositorWidget::GetGLFrameBufferFormat()
|
||||
{
|
||||
return mWidget->GetGLFrameBufferFormat();
|
||||
}
|
||||
|
||||
layers::Composer2D*
|
||||
InProcessCompositorWidget::GetComposer2D()
|
||||
{
|
||||
return mWidget->GetComposer2D();
|
||||
}
|
||||
|
||||
uintptr_t
|
||||
InProcessCompositorWidget::GetWidgetKey()
|
||||
{
|
||||
return reinterpret_cast<uintptr_t>(mWidget);
|
||||
}
|
||||
|
||||
nsIWidget*
|
||||
InProcessCompositorWidget::RealWidget()
|
||||
{
|
||||
return mWidget;
|
||||
}
|
||||
|
||||
void
|
||||
InProcessCompositorWidget::ObserveVsync(VsyncObserver* aObserver)
|
||||
{
|
||||
if (RefPtr<CompositorVsyncDispatcher> cvd = mWidget->GetCompositorVsyncDispatcher()) {
|
||||
cvd->SetCompositorVsyncObserver(aObserver);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
52
widget/InProcessCompositorWidget.h
Normal file
52
widget/InProcessCompositorWidget.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_widget_InProcessCompositorWidget_h__
|
||||
#define mozilla_widget_InProcessCompositorWidget_h__
|
||||
|
||||
#include "CompositorWidget.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
// This version of CompositorWidget implements a wrapper around
|
||||
// nsBaseWidget.
|
||||
class InProcessCompositorWidget : public CompositorWidget
|
||||
{
|
||||
public:
|
||||
explicit InProcessCompositorWidget(nsBaseWidget* aWidget);
|
||||
|
||||
virtual bool PreRender(WidgetRenderingContext* aManager) override;
|
||||
virtual void PostRender(WidgetRenderingContext* aManager) override;
|
||||
virtual void DrawWindowUnderlay(WidgetRenderingContext* aContext,
|
||||
LayoutDeviceIntRect aRect) override;
|
||||
virtual void DrawWindowOverlay(WidgetRenderingContext* aContext,
|
||||
LayoutDeviceIntRect aRect) override;
|
||||
virtual already_AddRefed<gfx::DrawTarget> StartRemoteDrawing() override;
|
||||
virtual already_AddRefed<gfx::DrawTarget>
|
||||
StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion,
|
||||
layers::BufferMode* aBufferMode) override;
|
||||
virtual void EndRemoteDrawing() override;
|
||||
virtual void EndRemoteDrawingInRegion(gfx::DrawTarget* aDrawTarget,
|
||||
LayoutDeviceIntRegion& aInvalidRegion) override;
|
||||
virtual void CleanupRemoteDrawing() override;
|
||||
virtual void CleanupWindowEffects() override;
|
||||
virtual bool InitCompositor(layers::Compositor* aCompositor) override;
|
||||
virtual LayoutDeviceIntSize GetClientSize() override;
|
||||
virtual uint32_t GetGLFrameBufferFormat() override;
|
||||
virtual layers::Composer2D* GetComposer2D() override;
|
||||
virtual void ObserveVsync(VsyncObserver* aObserver) override;
|
||||
virtual uintptr_t GetWidgetKey() override;
|
||||
|
||||
// If you can override this method, inherit from CompositorWidget instead.
|
||||
nsIWidget* RealWidget() override;
|
||||
|
||||
private:
|
||||
nsBaseWidget* mWidget;
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
777
widget/InputData.cpp
Normal file
777
widget/InputData.cpp
Normal file
|
|
@ -0,0 +1,777 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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 "InputData.h"
|
||||
|
||||
#include "mozilla/dom/Touch.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/MouseEvents.h"
|
||||
#include "mozilla/TouchEvents.h"
|
||||
#include "UnitTransforms.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace dom;
|
||||
|
||||
InputData::~InputData()
|
||||
{
|
||||
}
|
||||
|
||||
InputData::InputData(InputType aInputType)
|
||||
: mInputType(aInputType)
|
||||
, mTime(0)
|
||||
, modifiers(0)
|
||||
{
|
||||
}
|
||||
|
||||
InputData::InputData(InputType aInputType, uint32_t aTime, TimeStamp aTimeStamp,
|
||||
Modifiers aModifiers)
|
||||
: mInputType(aInputType)
|
||||
, mTime(aTime)
|
||||
, mTimeStamp(aTimeStamp)
|
||||
, modifiers(aModifiers)
|
||||
{
|
||||
}
|
||||
|
||||
SingleTouchData::SingleTouchData(int32_t aIdentifier, ScreenIntPoint aScreenPoint,
|
||||
ScreenSize aRadius, float aRotationAngle,
|
||||
float aForce)
|
||||
: mIdentifier(aIdentifier)
|
||||
, mScreenPoint(aScreenPoint)
|
||||
, mRadius(aRadius)
|
||||
, mRotationAngle(aRotationAngle)
|
||||
, mForce(aForce)
|
||||
{
|
||||
}
|
||||
|
||||
SingleTouchData::SingleTouchData(int32_t aIdentifier,
|
||||
ParentLayerPoint aLocalScreenPoint,
|
||||
ScreenSize aRadius, float aRotationAngle,
|
||||
float aForce)
|
||||
: mIdentifier(aIdentifier)
|
||||
, mLocalScreenPoint(aLocalScreenPoint)
|
||||
, mRadius(aRadius)
|
||||
, mRotationAngle(aRotationAngle)
|
||||
, mForce(aForce)
|
||||
{
|
||||
}
|
||||
|
||||
SingleTouchData::SingleTouchData()
|
||||
{
|
||||
}
|
||||
|
||||
already_AddRefed<Touch> SingleTouchData::ToNewDOMTouch() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(),
|
||||
"Can only create dom::Touch instances on main thread");
|
||||
RefPtr<Touch> touch = new Touch(mIdentifier,
|
||||
LayoutDeviceIntPoint::Truncate(mScreenPoint.x, mScreenPoint.y),
|
||||
LayoutDeviceIntPoint::Truncate(mRadius.width, mRadius.height),
|
||||
mRotationAngle,
|
||||
mForce);
|
||||
return touch.forget();
|
||||
}
|
||||
|
||||
MultiTouchInput::MultiTouchInput(MultiTouchType aType, uint32_t aTime,
|
||||
TimeStamp aTimeStamp, Modifiers aModifiers)
|
||||
: InputData(MULTITOUCH_INPUT, aTime, aTimeStamp, aModifiers)
|
||||
, mType(aType)
|
||||
, mHandledByAPZ(false)
|
||||
{
|
||||
}
|
||||
|
||||
MultiTouchInput::MultiTouchInput()
|
||||
: InputData(MULTITOUCH_INPUT)
|
||||
, mHandledByAPZ(false)
|
||||
{
|
||||
}
|
||||
|
||||
MultiTouchInput::MultiTouchInput(const MultiTouchInput& aOther)
|
||||
: InputData(MULTITOUCH_INPUT, aOther.mTime, aOther.mTimeStamp, aOther.modifiers)
|
||||
, mType(aOther.mType)
|
||||
, mHandledByAPZ(aOther.mHandledByAPZ)
|
||||
{
|
||||
mTouches.AppendElements(aOther.mTouches);
|
||||
}
|
||||
|
||||
MultiTouchInput::MultiTouchInput(const WidgetTouchEvent& aTouchEvent)
|
||||
: InputData(MULTITOUCH_INPUT, aTouchEvent.mTime, aTouchEvent.mTimeStamp,
|
||||
aTouchEvent.mModifiers)
|
||||
, mHandledByAPZ(aTouchEvent.mFlags.mHandledByAPZ)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(),
|
||||
"Can only copy from WidgetTouchEvent on main thread");
|
||||
|
||||
switch (aTouchEvent.mMessage) {
|
||||
case eTouchStart:
|
||||
mType = MULTITOUCH_START;
|
||||
break;
|
||||
case eTouchMove:
|
||||
mType = MULTITOUCH_MOVE;
|
||||
break;
|
||||
case eTouchEnd:
|
||||
mType = MULTITOUCH_END;
|
||||
break;
|
||||
case eTouchCancel:
|
||||
mType = MULTITOUCH_CANCEL;
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Did not assign a type to a MultiTouchInput");
|
||||
break;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < aTouchEvent.mTouches.Length(); i++) {
|
||||
const Touch* domTouch = aTouchEvent.mTouches[i];
|
||||
|
||||
// Extract data from weird interfaces.
|
||||
int32_t identifier = domTouch->Identifier();
|
||||
int32_t radiusX = domTouch->RadiusX();
|
||||
int32_t radiusY = domTouch->RadiusY();
|
||||
float rotationAngle = domTouch->RotationAngle();
|
||||
float force = domTouch->Force();
|
||||
|
||||
SingleTouchData data(identifier,
|
||||
ViewAs<ScreenPixel>(domTouch->mRefPoint,
|
||||
PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent),
|
||||
ScreenSize(radiusX, radiusY),
|
||||
rotationAngle,
|
||||
force);
|
||||
|
||||
mTouches.AppendElement(data);
|
||||
}
|
||||
}
|
||||
|
||||
MultiTouchInput::MultiTouchInput(const WidgetMouseEvent& aMouseEvent)
|
||||
: InputData(MULTITOUCH_INPUT, aMouseEvent.mTime, aMouseEvent.mTimeStamp,
|
||||
aMouseEvent.mModifiers)
|
||||
, mHandledByAPZ(aMouseEvent.mFlags.mHandledByAPZ)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(),
|
||||
"Can only copy from WidgetMouseEvent on main thread");
|
||||
switch (aMouseEvent.mMessage) {
|
||||
case eMouseDown:
|
||||
mType = MULTITOUCH_START;
|
||||
break;
|
||||
case eMouseMove:
|
||||
mType = MULTITOUCH_MOVE;
|
||||
break;
|
||||
case eMouseUp:
|
||||
mType = MULTITOUCH_END;
|
||||
break;
|
||||
// The mouse pointer has been interrupted in an implementation-specific
|
||||
// manner, such as a synchronous event or action cancelling the touch, or a
|
||||
// touch point leaving the document window and going into a non-document
|
||||
// area capable of handling user interactions.
|
||||
case eMouseExitFromWidget:
|
||||
mType = MULTITOUCH_CANCEL;
|
||||
break;
|
||||
default:
|
||||
NS_WARNING("Did not assign a type to a MultiTouchInput");
|
||||
break;
|
||||
}
|
||||
|
||||
mTouches.AppendElement(SingleTouchData(0,
|
||||
ViewAs<ScreenPixel>(aMouseEvent.mRefPoint,
|
||||
PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent),
|
||||
ScreenSize(1, 1),
|
||||
180.0f,
|
||||
1.0f));
|
||||
}
|
||||
|
||||
WidgetTouchEvent
|
||||
MultiTouchInput::ToWidgetTouchEvent(nsIWidget* aWidget) const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(),
|
||||
"Can only convert To WidgetTouchEvent on main thread");
|
||||
|
||||
EventMessage touchEventMessage = eVoidEvent;
|
||||
switch (mType) {
|
||||
case MULTITOUCH_START:
|
||||
touchEventMessage = eTouchStart;
|
||||
break;
|
||||
case MULTITOUCH_MOVE:
|
||||
touchEventMessage = eTouchMove;
|
||||
break;
|
||||
case MULTITOUCH_END:
|
||||
touchEventMessage = eTouchEnd;
|
||||
break;
|
||||
case MULTITOUCH_CANCEL:
|
||||
touchEventMessage = eTouchCancel;
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Did not assign a type to WidgetTouchEvent in MultiTouchInput");
|
||||
break;
|
||||
}
|
||||
|
||||
WidgetTouchEvent event(true, touchEventMessage, aWidget);
|
||||
if (touchEventMessage == eVoidEvent) {
|
||||
return event;
|
||||
}
|
||||
|
||||
event.mModifiers = this->modifiers;
|
||||
event.mTime = this->mTime;
|
||||
event.mTimeStamp = this->mTimeStamp;
|
||||
event.mFlags.mHandledByAPZ = mHandledByAPZ;
|
||||
|
||||
for (size_t i = 0; i < mTouches.Length(); i++) {
|
||||
*event.mTouches.AppendElement() = mTouches[i].ToNewDOMTouch();
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
WidgetMouseEvent
|
||||
MultiTouchInput::ToWidgetMouseEvent(nsIWidget* aWidget) const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(),
|
||||
"Can only convert To WidgetMouseEvent on main thread");
|
||||
|
||||
EventMessage mouseEventMessage = eVoidEvent;
|
||||
switch (mType) {
|
||||
case MultiTouchInput::MULTITOUCH_START:
|
||||
mouseEventMessage = eMouseDown;
|
||||
break;
|
||||
case MultiTouchInput::MULTITOUCH_MOVE:
|
||||
mouseEventMessage = eMouseMove;
|
||||
break;
|
||||
case MultiTouchInput::MULTITOUCH_CANCEL:
|
||||
case MultiTouchInput::MULTITOUCH_END:
|
||||
mouseEventMessage = eMouseUp;
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Did not assign a type to WidgetMouseEvent");
|
||||
break;
|
||||
}
|
||||
|
||||
WidgetMouseEvent event(true, mouseEventMessage, aWidget,
|
||||
WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal);
|
||||
|
||||
const SingleTouchData& firstTouch = mTouches[0];
|
||||
event.mRefPoint.x = firstTouch.mScreenPoint.x;
|
||||
event.mRefPoint.y = firstTouch.mScreenPoint.y;
|
||||
|
||||
event.mTime = mTime;
|
||||
event.button = WidgetMouseEvent::eLeftButton;
|
||||
event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
||||
event.mModifiers = modifiers;
|
||||
event.mFlags.mHandledByAPZ = mHandledByAPZ;
|
||||
|
||||
if (mouseEventMessage != eMouseMove) {
|
||||
event.mClickCount = 1;
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
int32_t
|
||||
MultiTouchInput::IndexOfTouch(int32_t aTouchIdentifier)
|
||||
{
|
||||
for (size_t i = 0; i < mTouches.Length(); i++) {
|
||||
if (mTouches[i].mIdentifier == aTouchIdentifier) {
|
||||
return (int32_t)i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool
|
||||
MultiTouchInput::TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform)
|
||||
{
|
||||
for (size_t i = 0; i < mTouches.Length(); i++) {
|
||||
Maybe<ParentLayerIntPoint> point = UntransformBy(aTransform, mTouches[i].mScreenPoint);
|
||||
if (!point) {
|
||||
return false;
|
||||
}
|
||||
mTouches[i].mLocalScreenPoint = *point;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
MouseInput::MouseInput()
|
||||
: InputData(MOUSE_INPUT)
|
||||
, mType(MOUSE_NONE)
|
||||
, mButtonType(NONE)
|
||||
, mInputSource(0)
|
||||
, mButtons(0)
|
||||
, mHandledByAPZ(false)
|
||||
{
|
||||
}
|
||||
|
||||
MouseInput::MouseInput(MouseType aType, ButtonType aButtonType,
|
||||
uint16_t aInputSource, int16_t aButtons,
|
||||
const ScreenPoint& aPoint, uint32_t aTime,
|
||||
TimeStamp aTimeStamp, Modifiers aModifiers)
|
||||
: InputData(MOUSE_INPUT, aTime, aTimeStamp, aModifiers)
|
||||
, mType(aType)
|
||||
, mButtonType(aButtonType)
|
||||
, mInputSource(aInputSource)
|
||||
, mButtons(aButtons)
|
||||
, mOrigin(aPoint)
|
||||
, mHandledByAPZ(false)
|
||||
{
|
||||
}
|
||||
|
||||
MouseInput::MouseInput(const WidgetMouseEventBase& aMouseEvent)
|
||||
: InputData(MOUSE_INPUT, aMouseEvent.mTime, aMouseEvent.mTimeStamp,
|
||||
aMouseEvent.mModifiers)
|
||||
, mType(MOUSE_NONE)
|
||||
, mButtonType(NONE)
|
||||
, mInputSource(aMouseEvent.inputSource)
|
||||
, mButtons(aMouseEvent.buttons)
|
||||
, mHandledByAPZ(aMouseEvent.mFlags.mHandledByAPZ)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(),
|
||||
"Can only copy from WidgetTouchEvent on main thread");
|
||||
|
||||
mButtonType = NONE;
|
||||
|
||||
switch (aMouseEvent.button) {
|
||||
case WidgetMouseEventBase::eLeftButton:
|
||||
mButtonType = MouseInput::LEFT_BUTTON;
|
||||
break;
|
||||
case WidgetMouseEventBase::eMiddleButton:
|
||||
mButtonType = MouseInput::MIDDLE_BUTTON;
|
||||
break;
|
||||
case WidgetMouseEventBase::eRightButton:
|
||||
mButtonType = MouseInput::RIGHT_BUTTON;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (aMouseEvent.mMessage) {
|
||||
case eMouseMove:
|
||||
mType = MOUSE_MOVE;
|
||||
break;
|
||||
case eMouseUp:
|
||||
mType = MOUSE_UP;
|
||||
break;
|
||||
case eMouseDown:
|
||||
mType = MOUSE_DOWN;
|
||||
break;
|
||||
case eDragStart:
|
||||
mType = MOUSE_DRAG_START;
|
||||
break;
|
||||
case eDragEnd:
|
||||
mType = MOUSE_DRAG_END;
|
||||
break;
|
||||
case eMouseEnterIntoWidget:
|
||||
mType = MOUSE_WIDGET_ENTER;
|
||||
break;
|
||||
case eMouseExitFromWidget:
|
||||
mType = MOUSE_WIDGET_EXIT;
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Mouse event type not supported");
|
||||
break;
|
||||
}
|
||||
|
||||
mOrigin =
|
||||
ScreenPoint(ViewAs<ScreenPixel>(aMouseEvent.mRefPoint,
|
||||
PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent));
|
||||
}
|
||||
|
||||
bool
|
||||
MouseInput::IsLeftButton() const
|
||||
{
|
||||
return mButtonType == LEFT_BUTTON;
|
||||
}
|
||||
|
||||
bool
|
||||
MouseInput::TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform)
|
||||
{
|
||||
Maybe<ParentLayerPoint> point = UntransformBy(aTransform, mOrigin);
|
||||
if (!point) {
|
||||
return false;
|
||||
}
|
||||
mLocalOrigin = *point;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
WidgetMouseEvent
|
||||
MouseInput::ToWidgetMouseEvent(nsIWidget* aWidget) const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(),
|
||||
"Can only convert To WidgetTouchEvent on main thread");
|
||||
|
||||
EventMessage msg = eVoidEvent;
|
||||
uint32_t clickCount = 0;
|
||||
switch (mType) {
|
||||
case MOUSE_MOVE:
|
||||
msg = eMouseMove;
|
||||
break;
|
||||
case MOUSE_UP:
|
||||
msg = eMouseUp;
|
||||
clickCount = 1;
|
||||
break;
|
||||
case MOUSE_DOWN:
|
||||
msg = eMouseDown;
|
||||
clickCount = 1;
|
||||
break;
|
||||
case MOUSE_DRAG_START:
|
||||
msg = eDragStart;
|
||||
break;
|
||||
case MOUSE_DRAG_END:
|
||||
msg = eDragEnd;
|
||||
break;
|
||||
case MOUSE_WIDGET_ENTER:
|
||||
msg = eMouseEnterIntoWidget;
|
||||
break;
|
||||
case MOUSE_WIDGET_EXIT:
|
||||
msg = eMouseExitFromWidget;
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Did not assign a type to WidgetMouseEvent in MouseInput");
|
||||
break;
|
||||
}
|
||||
|
||||
WidgetMouseEvent event(true, msg, aWidget, WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal);
|
||||
|
||||
if (msg == eVoidEvent) {
|
||||
return event;
|
||||
}
|
||||
|
||||
switch (mButtonType) {
|
||||
case MouseInput::LEFT_BUTTON:
|
||||
event.button = WidgetMouseEventBase::eLeftButton;
|
||||
break;
|
||||
case MouseInput::MIDDLE_BUTTON:
|
||||
event.button = WidgetMouseEventBase::eMiddleButton;
|
||||
break;
|
||||
case MouseInput::RIGHT_BUTTON:
|
||||
event.button = WidgetMouseEventBase::eRightButton;
|
||||
break;
|
||||
case MouseInput::NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
event.buttons = mButtons;
|
||||
event.mModifiers = modifiers;
|
||||
event.mTime = mTime;
|
||||
event.mTimeStamp = mTimeStamp;
|
||||
event.mFlags.mHandledByAPZ = mHandledByAPZ;
|
||||
event.mRefPoint =
|
||||
RoundedToInt(ViewAs<LayoutDevicePixel>(mOrigin,
|
||||
PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent));
|
||||
event.mClickCount = clickCount;
|
||||
event.inputSource = mInputSource;
|
||||
event.mIgnoreRootScrollFrame = true;
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
PanGestureInput::PanGestureInput()
|
||||
: InputData(PANGESTURE_INPUT)
|
||||
, mLineOrPageDeltaX(0)
|
||||
, mLineOrPageDeltaY(0)
|
||||
, mUserDeltaMultiplierX(1.0)
|
||||
, mUserDeltaMultiplierY(1.0)
|
||||
, mHandledByAPZ(false)
|
||||
, mFollowedByMomentum(false)
|
||||
, mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection(false)
|
||||
{
|
||||
}
|
||||
|
||||
PanGestureInput::PanGestureInput(PanGestureType aType, uint32_t aTime,
|
||||
TimeStamp aTimeStamp,
|
||||
const ScreenPoint& aPanStartPoint,
|
||||
const ScreenPoint& aPanDisplacement,
|
||||
Modifiers aModifiers)
|
||||
: InputData(PANGESTURE_INPUT, aTime, aTimeStamp, aModifiers)
|
||||
, mType(aType)
|
||||
, mPanStartPoint(aPanStartPoint)
|
||||
, mPanDisplacement(aPanDisplacement)
|
||||
, mLineOrPageDeltaX(0)
|
||||
, mLineOrPageDeltaY(0)
|
||||
, mUserDeltaMultiplierX(1.0)
|
||||
, mUserDeltaMultiplierY(1.0)
|
||||
, mHandledByAPZ(false)
|
||||
, mFollowedByMomentum(false)
|
||||
, mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
PanGestureInput::IsMomentum() const
|
||||
{
|
||||
switch (mType) {
|
||||
case PanGestureInput::PANGESTURE_MOMENTUMSTART:
|
||||
case PanGestureInput::PANGESTURE_MOMENTUMPAN:
|
||||
case PanGestureInput::PANGESTURE_MOMENTUMEND:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
WidgetWheelEvent
|
||||
PanGestureInput::ToWidgetWheelEvent(nsIWidget* aWidget) const
|
||||
{
|
||||
WidgetWheelEvent wheelEvent(true, eWheel, aWidget);
|
||||
wheelEvent.mModifiers = this->modifiers;
|
||||
wheelEvent.mTime = mTime;
|
||||
wheelEvent.mTimeStamp = mTimeStamp;
|
||||
wheelEvent.mRefPoint =
|
||||
RoundedToInt(ViewAs<LayoutDevicePixel>(mPanStartPoint,
|
||||
PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent));
|
||||
wheelEvent.buttons = 0;
|
||||
wheelEvent.mDeltaMode = nsIDOMWheelEvent::DOM_DELTA_PIXEL;
|
||||
wheelEvent.mMayHaveMomentum = true; // pan inputs may have momentum
|
||||
wheelEvent.mIsMomentum = IsMomentum();
|
||||
wheelEvent.mLineOrPageDeltaX = mLineOrPageDeltaX;
|
||||
wheelEvent.mLineOrPageDeltaY = mLineOrPageDeltaY;
|
||||
wheelEvent.mDeltaX = mPanDisplacement.x;
|
||||
wheelEvent.mDeltaY = mPanDisplacement.y;
|
||||
wheelEvent.mFlags.mHandledByAPZ = mHandledByAPZ;
|
||||
return wheelEvent;
|
||||
}
|
||||
|
||||
bool
|
||||
PanGestureInput::TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform)
|
||||
{
|
||||
Maybe<ParentLayerPoint> panStartPoint = UntransformBy(aTransform, mPanStartPoint);
|
||||
if (!panStartPoint) {
|
||||
return false;
|
||||
}
|
||||
mLocalPanStartPoint = *panStartPoint;
|
||||
|
||||
Maybe<ParentLayerPoint> panDisplacement = UntransformVector(aTransform, mPanDisplacement, mPanStartPoint);
|
||||
if (!panDisplacement) {
|
||||
return false;
|
||||
}
|
||||
mLocalPanDisplacement = *panDisplacement;
|
||||
return true;
|
||||
}
|
||||
|
||||
ScreenPoint
|
||||
PanGestureInput::UserMultipliedPanDisplacement() const
|
||||
{
|
||||
return ScreenPoint(mPanDisplacement.x * mUserDeltaMultiplierX,
|
||||
mPanDisplacement.y * mUserDeltaMultiplierY);
|
||||
}
|
||||
|
||||
ParentLayerPoint
|
||||
PanGestureInput::UserMultipliedLocalPanDisplacement() const
|
||||
{
|
||||
return ParentLayerPoint(mLocalPanDisplacement.x * mUserDeltaMultiplierX,
|
||||
mLocalPanDisplacement.y * mUserDeltaMultiplierY);
|
||||
}
|
||||
|
||||
PinchGestureInput::PinchGestureInput()
|
||||
: InputData(PINCHGESTURE_INPUT)
|
||||
{
|
||||
}
|
||||
|
||||
PinchGestureInput::PinchGestureInput(PinchGestureType aType, uint32_t aTime,
|
||||
TimeStamp aTimeStamp,
|
||||
const ParentLayerPoint& aLocalFocusPoint,
|
||||
ParentLayerCoord aCurrentSpan,
|
||||
ParentLayerCoord aPreviousSpan,
|
||||
Modifiers aModifiers)
|
||||
: InputData(PINCHGESTURE_INPUT, aTime, aTimeStamp, aModifiers)
|
||||
, mType(aType)
|
||||
, mLocalFocusPoint(aLocalFocusPoint)
|
||||
, mCurrentSpan(aCurrentSpan)
|
||||
, mPreviousSpan(aPreviousSpan)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
PinchGestureInput::TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform)
|
||||
{
|
||||
Maybe<ParentLayerPoint> point = UntransformBy(aTransform, mFocusPoint);
|
||||
if (!point) {
|
||||
return false;
|
||||
}
|
||||
mLocalFocusPoint = *point;
|
||||
return true;
|
||||
}
|
||||
|
||||
TapGestureInput::TapGestureInput()
|
||||
: InputData(TAPGESTURE_INPUT)
|
||||
{
|
||||
}
|
||||
|
||||
TapGestureInput::TapGestureInput(TapGestureType aType, uint32_t aTime,
|
||||
TimeStamp aTimeStamp,
|
||||
const ScreenIntPoint& aPoint,
|
||||
Modifiers aModifiers)
|
||||
: InputData(TAPGESTURE_INPUT, aTime, aTimeStamp, aModifiers)
|
||||
, mType(aType)
|
||||
, mPoint(aPoint)
|
||||
{
|
||||
}
|
||||
|
||||
TapGestureInput::TapGestureInput(TapGestureType aType, uint32_t aTime,
|
||||
TimeStamp aTimeStamp,
|
||||
const ParentLayerPoint& aLocalPoint,
|
||||
Modifiers aModifiers)
|
||||
: InputData(TAPGESTURE_INPUT, aTime, aTimeStamp, aModifiers)
|
||||
, mType(aType)
|
||||
, mLocalPoint(aLocalPoint)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
TapGestureInput::TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform)
|
||||
{
|
||||
Maybe<ParentLayerIntPoint> point = UntransformBy(aTransform, mPoint);
|
||||
if (!point) {
|
||||
return false;
|
||||
}
|
||||
mLocalPoint = *point;
|
||||
return true;
|
||||
}
|
||||
|
||||
ScrollWheelInput::ScrollWheelInput()
|
||||
: InputData(SCROLLWHEEL_INPUT)
|
||||
, mHandledByAPZ(false)
|
||||
, mLineOrPageDeltaX(0)
|
||||
, mLineOrPageDeltaY(0)
|
||||
, mScrollSeriesNumber(0)
|
||||
, mUserDeltaMultiplierX(1.0)
|
||||
, mUserDeltaMultiplierY(1.0)
|
||||
, mMayHaveMomentum(false)
|
||||
, mIsMomentum(false)
|
||||
{
|
||||
}
|
||||
|
||||
ScrollWheelInput::ScrollWheelInput(uint32_t aTime, TimeStamp aTimeStamp,
|
||||
Modifiers aModifiers, ScrollMode aScrollMode,
|
||||
ScrollDeltaType aDeltaType,
|
||||
const ScreenPoint& aOrigin, double aDeltaX,
|
||||
double aDeltaY,
|
||||
bool aAllowToOverrideSystemScrollSpeed)
|
||||
: InputData(SCROLLWHEEL_INPUT, aTime, aTimeStamp, aModifiers)
|
||||
, mDeltaType(aDeltaType)
|
||||
, mScrollMode(aScrollMode)
|
||||
, mOrigin(aOrigin)
|
||||
, mHandledByAPZ(false)
|
||||
, mDeltaX(aDeltaX)
|
||||
, mDeltaY(aDeltaY)
|
||||
, mLineOrPageDeltaX(0)
|
||||
, mLineOrPageDeltaY(0)
|
||||
, mScrollSeriesNumber(0)
|
||||
, mUserDeltaMultiplierX(1.0)
|
||||
, mUserDeltaMultiplierY(1.0)
|
||||
, mMayHaveMomentum(false)
|
||||
, mIsMomentum(false)
|
||||
, mAllowToOverrideSystemScrollSpeed(aAllowToOverrideSystemScrollSpeed)
|
||||
{
|
||||
}
|
||||
|
||||
ScrollWheelInput::ScrollWheelInput(const WidgetWheelEvent& aWheelEvent)
|
||||
: InputData(SCROLLWHEEL_INPUT, aWheelEvent.mTime, aWheelEvent.mTimeStamp,
|
||||
aWheelEvent.mModifiers)
|
||||
, mDeltaType(DeltaTypeForDeltaMode(aWheelEvent.mDeltaMode))
|
||||
, mScrollMode(SCROLLMODE_INSTANT)
|
||||
, mHandledByAPZ(aWheelEvent.mFlags.mHandledByAPZ)
|
||||
, mDeltaX(aWheelEvent.mDeltaX)
|
||||
, mDeltaY(aWheelEvent.mDeltaY)
|
||||
, mLineOrPageDeltaX(aWheelEvent.mLineOrPageDeltaX)
|
||||
, mLineOrPageDeltaY(aWheelEvent.mLineOrPageDeltaY)
|
||||
, mScrollSeriesNumber(0)
|
||||
, mUserDeltaMultiplierX(1.0)
|
||||
, mUserDeltaMultiplierY(1.0)
|
||||
, mMayHaveMomentum(aWheelEvent.mMayHaveMomentum)
|
||||
, mIsMomentum(aWheelEvent.mIsMomentum)
|
||||
, mAllowToOverrideSystemScrollSpeed(
|
||||
aWheelEvent.mAllowToOverrideSystemScrollSpeed)
|
||||
{
|
||||
mOrigin =
|
||||
ScreenPoint(ViewAs<ScreenPixel>(aWheelEvent.mRefPoint,
|
||||
PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent));
|
||||
}
|
||||
|
||||
ScrollWheelInput::ScrollDeltaType
|
||||
ScrollWheelInput::DeltaTypeForDeltaMode(uint32_t aDeltaMode)
|
||||
{
|
||||
switch (aDeltaMode) {
|
||||
case nsIDOMWheelEvent::DOM_DELTA_LINE:
|
||||
return SCROLLDELTA_LINE;
|
||||
case nsIDOMWheelEvent::DOM_DELTA_PAGE:
|
||||
return SCROLLDELTA_PAGE;
|
||||
case nsIDOMWheelEvent::DOM_DELTA_PIXEL:
|
||||
return SCROLLDELTA_PIXEL;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
}
|
||||
return SCROLLDELTA_LINE;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ScrollWheelInput::DeltaModeForDeltaType(ScrollDeltaType aDeltaType)
|
||||
{
|
||||
switch (aDeltaType) {
|
||||
case ScrollWheelInput::SCROLLDELTA_LINE:
|
||||
return nsIDOMWheelEvent::DOM_DELTA_LINE;
|
||||
case ScrollWheelInput::SCROLLDELTA_PAGE:
|
||||
return nsIDOMWheelEvent::DOM_DELTA_PAGE;
|
||||
case ScrollWheelInput::SCROLLDELTA_PIXEL:
|
||||
default:
|
||||
return nsIDOMWheelEvent::DOM_DELTA_PIXEL;
|
||||
}
|
||||
}
|
||||
|
||||
nsIScrollableFrame::ScrollUnit
|
||||
ScrollWheelInput::ScrollUnitForDeltaType(ScrollDeltaType aDeltaType)
|
||||
{
|
||||
switch (aDeltaType) {
|
||||
case SCROLLDELTA_LINE:
|
||||
return nsIScrollableFrame::LINES;
|
||||
case SCROLLDELTA_PAGE:
|
||||
return nsIScrollableFrame::PAGES;
|
||||
case SCROLLDELTA_PIXEL:
|
||||
return nsIScrollableFrame::DEVICE_PIXELS;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
}
|
||||
return nsIScrollableFrame::LINES;
|
||||
}
|
||||
|
||||
WidgetWheelEvent
|
||||
ScrollWheelInput::ToWidgetWheelEvent(nsIWidget* aWidget) const
|
||||
{
|
||||
WidgetWheelEvent wheelEvent(true, eWheel, aWidget);
|
||||
wheelEvent.mModifiers = this->modifiers;
|
||||
wheelEvent.mTime = mTime;
|
||||
wheelEvent.mTimeStamp = mTimeStamp;
|
||||
wheelEvent.mRefPoint =
|
||||
RoundedToInt(ViewAs<LayoutDevicePixel>(mOrigin,
|
||||
PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent));
|
||||
wheelEvent.buttons = 0;
|
||||
wheelEvent.mDeltaMode = DeltaModeForDeltaType(mDeltaType);
|
||||
wheelEvent.mMayHaveMomentum = mMayHaveMomentum;
|
||||
wheelEvent.mIsMomentum = mIsMomentum;
|
||||
wheelEvent.mDeltaX = mDeltaX;
|
||||
wheelEvent.mDeltaY = mDeltaY;
|
||||
wheelEvent.mLineOrPageDeltaX = mLineOrPageDeltaX;
|
||||
wheelEvent.mLineOrPageDeltaY = mLineOrPageDeltaY;
|
||||
wheelEvent.mAllowToOverrideSystemScrollSpeed =
|
||||
mAllowToOverrideSystemScrollSpeed;
|
||||
wheelEvent.mFlags.mHandledByAPZ = mHandledByAPZ;
|
||||
return wheelEvent;
|
||||
}
|
||||
|
||||
bool
|
||||
ScrollWheelInput::TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform)
|
||||
{
|
||||
Maybe<ParentLayerPoint> point = UntransformBy(aTransform, mOrigin);
|
||||
if (!point) {
|
||||
return false;
|
||||
}
|
||||
mLocalOrigin = *point;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ScrollWheelInput::IsCustomizedByUserPrefs() const
|
||||
{
|
||||
return mUserDeltaMultiplierX != 1.0 ||
|
||||
mUserDeltaMultiplierY != 1.0;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
617
widget/InputData.h
Normal file
617
widget/InputData.h
Normal file
|
|
@ -0,0 +1,617 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef InputData_h__
|
||||
#define InputData_h__
|
||||
|
||||
#include "nsDebug.h"
|
||||
#include "nsIDOMWheelEvent.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsPoint.h"
|
||||
#include "nsTArray.h"
|
||||
#include "Units.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/gfx/MatrixFwd.h"
|
||||
|
||||
template<class E> struct already_AddRefed;
|
||||
class nsIWidget;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace layers {
|
||||
class PAPZCTreeManagerParent;
|
||||
class APZCTreeManagerChild;
|
||||
}
|
||||
|
||||
namespace dom {
|
||||
class Touch;
|
||||
} // namespace dom
|
||||
|
||||
enum InputType
|
||||
{
|
||||
// Warning, this enum is serialized and sent over IPC. If you reorder, add,
|
||||
// or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
|
||||
MULTITOUCH_INPUT,
|
||||
MOUSE_INPUT,
|
||||
PANGESTURE_INPUT,
|
||||
PINCHGESTURE_INPUT,
|
||||
TAPGESTURE_INPUT,
|
||||
SCROLLWHEEL_INPUT,
|
||||
|
||||
// Used as an upper bound for ContiguousEnumSerializer
|
||||
SENTINEL_INPUT,
|
||||
};
|
||||
|
||||
class MultiTouchInput;
|
||||
class MouseInput;
|
||||
class PanGestureInput;
|
||||
class PinchGestureInput;
|
||||
class TapGestureInput;
|
||||
class ScrollWheelInput;
|
||||
|
||||
// This looks unnecessary now, but as we add more and more classes that derive
|
||||
// from InputType (eventually probably almost as many as *Events.h has), it
|
||||
// will be more and more clear what's going on with a macro that shortens the
|
||||
// definition of the RTTI functions.
|
||||
#define INPUTDATA_AS_CHILD_TYPE(type, enumID) \
|
||||
const type& As##type() const \
|
||||
{ \
|
||||
MOZ_ASSERT(mInputType == enumID, "Invalid cast of InputData."); \
|
||||
return (const type&) *this; \
|
||||
} \
|
||||
type& As##type() \
|
||||
{ \
|
||||
MOZ_ASSERT(mInputType == enumID, "Invalid cast of InputData."); \
|
||||
return (type&) *this; \
|
||||
}
|
||||
|
||||
/** Base input data class. Should never be instantiated. */
|
||||
class InputData
|
||||
{
|
||||
public:
|
||||
// Warning, this class is serialized and sent over IPC. Any change to its
|
||||
// fields must be reflected in its ParamTraits<>, in nsGUIEventIPC.h
|
||||
InputType mInputType;
|
||||
// Time in milliseconds that this data is relevant to. This only really
|
||||
// matters when this data is used as an event. We use uint32_t instead of
|
||||
// TimeStamp because it is easier to convert from WidgetInputEvent. The time
|
||||
// is platform-specific but it in the case of B2G and Fennec it is since
|
||||
// startup.
|
||||
uint32_t mTime;
|
||||
// Set in parallel to mTime until we determine it is safe to drop
|
||||
// platform-specific event times (see bug 77992).
|
||||
TimeStamp mTimeStamp;
|
||||
|
||||
Modifiers modifiers;
|
||||
|
||||
INPUTDATA_AS_CHILD_TYPE(MultiTouchInput, MULTITOUCH_INPUT)
|
||||
INPUTDATA_AS_CHILD_TYPE(MouseInput, MOUSE_INPUT)
|
||||
INPUTDATA_AS_CHILD_TYPE(PanGestureInput, PANGESTURE_INPUT)
|
||||
INPUTDATA_AS_CHILD_TYPE(PinchGestureInput, PINCHGESTURE_INPUT)
|
||||
INPUTDATA_AS_CHILD_TYPE(TapGestureInput, TAPGESTURE_INPUT)
|
||||
INPUTDATA_AS_CHILD_TYPE(ScrollWheelInput, SCROLLWHEEL_INPUT)
|
||||
|
||||
virtual ~InputData();
|
||||
explicit InputData(InputType aInputType);
|
||||
|
||||
protected:
|
||||
InputData(InputType aInputType, uint32_t aTime, TimeStamp aTimeStamp,
|
||||
Modifiers aModifiers);
|
||||
};
|
||||
|
||||
/**
|
||||
* Data container for a single touch input. Similar to dom::Touch, but used in
|
||||
* off-main-thread situations. This is more for just storing touch data, whereas
|
||||
* dom::Touch is more useful for dispatching through the DOM (which can only
|
||||
* happen on the main thread). dom::Touch also bears the problem of storing
|
||||
* pointers to nsIWidget instances which can only be used on the main thread,
|
||||
* so if instead we used dom::Touch and ever set these pointers
|
||||
* off-main-thread, Bad Things Can Happen(tm).
|
||||
*
|
||||
* Note that this doesn't inherit from InputData because this itself is not an
|
||||
* event. It is only a container/struct that should have any number of instances
|
||||
* within a MultiTouchInput.
|
||||
*
|
||||
* fixme/bug 775746: Make dom::Touch inherit from this class.
|
||||
*/
|
||||
class SingleTouchData
|
||||
{
|
||||
public:
|
||||
// Construct a SingleTouchData from a Screen point.
|
||||
// mLocalScreenPoint remains (0,0) unless it's set later.
|
||||
SingleTouchData(int32_t aIdentifier,
|
||||
ScreenIntPoint aScreenPoint,
|
||||
ScreenSize aRadius,
|
||||
float aRotationAngle,
|
||||
float aForce);
|
||||
|
||||
// Construct a SingleTouchData from a ParentLayer point.
|
||||
// mScreenPoint remains (0,0) unless it's set later.
|
||||
// Note: if APZ starts using the radius for anything, we should add a local
|
||||
// version of that too, and have this constructor take it as a ParentLayerSize.
|
||||
SingleTouchData(int32_t aIdentifier,
|
||||
ParentLayerPoint aLocalScreenPoint,
|
||||
ScreenSize aRadius,
|
||||
float aRotationAngle,
|
||||
float aForce);
|
||||
|
||||
SingleTouchData();
|
||||
|
||||
already_AddRefed<dom::Touch> ToNewDOMTouch() const;
|
||||
|
||||
// Warning, this class is serialized and sent over IPC. Any change to its
|
||||
// fields must be reflected in its ParamTraits<>, in nsGUIEventIPC.h
|
||||
|
||||
// A unique number assigned to each SingleTouchData within a MultiTouchInput so
|
||||
// that they can be easily distinguished when handling a touch start/move/end.
|
||||
int32_t mIdentifier;
|
||||
|
||||
// Point on the screen that the touch hit, in device pixels. They are
|
||||
// coordinates on the screen.
|
||||
ScreenIntPoint mScreenPoint;
|
||||
|
||||
// |mScreenPoint| transformed to the local coordinates of the APZC targeted
|
||||
// by the hit. This is set and used by APZ.
|
||||
ParentLayerPoint mLocalScreenPoint;
|
||||
|
||||
// Radius that the touch covers, i.e. if you're using your thumb it will
|
||||
// probably be larger than using your pinky, even with the same force.
|
||||
// Radius can be different along x and y. For example, if you press down with
|
||||
// your entire finger vertically, the y radius will be much larger than the x
|
||||
// radius.
|
||||
ScreenSize mRadius;
|
||||
|
||||
float mRotationAngle;
|
||||
|
||||
// How hard the screen is being pressed.
|
||||
float mForce;
|
||||
};
|
||||
|
||||
/**
|
||||
* Similar to WidgetTouchEvent, but for use off-main-thread. Also only stores a
|
||||
* screen touch point instead of the many different coordinate spaces
|
||||
* WidgetTouchEvent stores its touch point in. This includes a way to initialize
|
||||
* itself from a WidgetTouchEvent by copying all relevant data over. Note that
|
||||
* this copying from WidgetTouchEvent functionality can only be used on the main
|
||||
* thread.
|
||||
*
|
||||
* Stores an array of SingleTouchData.
|
||||
*/
|
||||
class MultiTouchInput : public InputData
|
||||
{
|
||||
public:
|
||||
enum MultiTouchType
|
||||
{
|
||||
// Warning, this enum is serialized and sent over IPC. If you reorder, add,
|
||||
// or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
|
||||
MULTITOUCH_START,
|
||||
MULTITOUCH_MOVE,
|
||||
MULTITOUCH_END,
|
||||
MULTITOUCH_CANCEL,
|
||||
|
||||
// Used as an upper bound for ContiguousEnumSerializer
|
||||
MULTITOUCH_SENTINEL,
|
||||
};
|
||||
|
||||
MultiTouchInput(MultiTouchType aType, uint32_t aTime, TimeStamp aTimeStamp,
|
||||
Modifiers aModifiers);
|
||||
MultiTouchInput();
|
||||
MultiTouchInput(const MultiTouchInput& aOther);
|
||||
explicit MultiTouchInput(const WidgetTouchEvent& aTouchEvent);
|
||||
// This conversion from WidgetMouseEvent to MultiTouchInput is needed because
|
||||
// on the B2G emulator we can only receive mouse events, but we need to be
|
||||
// able to pan correctly. To do this, we convert the events into a format that
|
||||
// the panning code can handle. This code is very limited and only supports
|
||||
// SingleTouchData. It also sends garbage for the identifier, radius, force
|
||||
// and rotation angle.
|
||||
explicit MultiTouchInput(const WidgetMouseEvent& aMouseEvent);
|
||||
|
||||
WidgetTouchEvent ToWidgetTouchEvent(nsIWidget* aWidget) const;
|
||||
WidgetMouseEvent ToWidgetMouseEvent(nsIWidget* aWidget) const;
|
||||
|
||||
// Return the index into mTouches of the SingleTouchData with the given
|
||||
// identifier, or -1 if there is no such SingleTouchData.
|
||||
int32_t IndexOfTouch(int32_t aTouchIdentifier);
|
||||
|
||||
bool TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform);
|
||||
|
||||
// Warning, this class is serialized and sent over IPC. Any change to its
|
||||
// fields must be reflected in its ParamTraits<>, in nsGUIEventIPC.h
|
||||
MultiTouchType mType;
|
||||
nsTArray<SingleTouchData> mTouches;
|
||||
bool mHandledByAPZ;
|
||||
};
|
||||
|
||||
class MouseInput : public InputData
|
||||
{
|
||||
protected:
|
||||
friend mozilla::layers::PAPZCTreeManagerParent;
|
||||
friend mozilla::layers::APZCTreeManagerChild;
|
||||
|
||||
MouseInput();
|
||||
|
||||
public:
|
||||
enum MouseType
|
||||
{
|
||||
// Warning, this enum is serialized and sent over IPC. If you reorder, add,
|
||||
// or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
|
||||
MOUSE_NONE,
|
||||
MOUSE_MOVE,
|
||||
MOUSE_DOWN,
|
||||
MOUSE_UP,
|
||||
MOUSE_DRAG_START,
|
||||
MOUSE_DRAG_END,
|
||||
MOUSE_WIDGET_ENTER,
|
||||
MOUSE_WIDGET_EXIT,
|
||||
|
||||
// Used as an upper bound for ContiguousEnumSerializer
|
||||
MOUSE_SENTINEL,
|
||||
};
|
||||
|
||||
enum ButtonType
|
||||
{
|
||||
// Warning, this enum is serialized and sent over IPC. If you reorder, add,
|
||||
// or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
|
||||
LEFT_BUTTON,
|
||||
MIDDLE_BUTTON,
|
||||
RIGHT_BUTTON,
|
||||
NONE,
|
||||
|
||||
// Used as an upper bound for ContiguousEnumSerializer
|
||||
BUTTON_SENTINEL,
|
||||
};
|
||||
|
||||
MouseInput(MouseType aType, ButtonType aButtonType, uint16_t aInputSource,
|
||||
int16_t aButtons, const ScreenPoint& aPoint, uint32_t aTime,
|
||||
TimeStamp aTimeStamp, Modifiers aModifiers);
|
||||
explicit MouseInput(const WidgetMouseEventBase& aMouseEvent);
|
||||
|
||||
bool IsLeftButton() const;
|
||||
|
||||
bool TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform);
|
||||
WidgetMouseEvent ToWidgetMouseEvent(nsIWidget* aWidget) const;
|
||||
|
||||
// Warning, this class is serialized and sent over IPC. Any change to its
|
||||
// fields must be reflected in its ParamTraits<>, in nsGUIEventIPC.h
|
||||
MouseType mType;
|
||||
ButtonType mButtonType;
|
||||
uint16_t mInputSource;
|
||||
int16_t mButtons;
|
||||
ScreenPoint mOrigin;
|
||||
ParentLayerPoint mLocalOrigin;
|
||||
bool mHandledByAPZ;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encapsulation class for pan events, can be used off-main-thread.
|
||||
* These events are currently only used for scrolling on desktop.
|
||||
*/
|
||||
class PanGestureInput : public InputData
|
||||
{
|
||||
protected:
|
||||
friend mozilla::layers::PAPZCTreeManagerParent;
|
||||
friend mozilla::layers::APZCTreeManagerChild;
|
||||
|
||||
PanGestureInput();
|
||||
|
||||
public:
|
||||
enum PanGestureType
|
||||
{
|
||||
// Warning, this enum is serialized and sent over IPC. If you reorder, add,
|
||||
// or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
|
||||
|
||||
// MayStart: Dispatched before any actual panning has occurred but when a
|
||||
// pan gesture is probably about to start, for example when the user
|
||||
// starts touching the touchpad. Should interrupt any ongoing APZ
|
||||
// animation and can be used to trigger scrollability indicators (e.g.
|
||||
// flashing overlay scrollbars).
|
||||
PANGESTURE_MAYSTART,
|
||||
|
||||
// Cancelled: Dispatched after MayStart when no pan gesture is going to
|
||||
// happen after all, for example when the user lifts their fingers from a
|
||||
// touchpad without having done any scrolling.
|
||||
PANGESTURE_CANCELLED,
|
||||
|
||||
// Start: A pan gesture is starting.
|
||||
// For devices that do not support the MayStart event type, this event can
|
||||
// be used to interrupt ongoing APZ animations.
|
||||
PANGESTURE_START,
|
||||
|
||||
// Pan: The actual pan motion by mPanDisplacement.
|
||||
PANGESTURE_PAN,
|
||||
|
||||
// End: The pan gesture has ended, for example because the user has lifted
|
||||
// their fingers from a touchpad after scrolling.
|
||||
// Any potential momentum events fire after this event.
|
||||
PANGESTURE_END,
|
||||
|
||||
// The following momentum event types are used in order to control the pan
|
||||
// momentum animation. Using these instead of our own animation ensures
|
||||
// that the animation curve is OS native and that the animation stops
|
||||
// reliably if it is cancelled by the user.
|
||||
|
||||
// MomentumStart: Dispatched between the End event of the actual
|
||||
// user-controlled pan, and the first MomentumPan event of the momentum
|
||||
// animation.
|
||||
PANGESTURE_MOMENTUMSTART,
|
||||
|
||||
// MomentumPan: The actual momentum motion by mPanDisplacement.
|
||||
PANGESTURE_MOMENTUMPAN,
|
||||
|
||||
// MomentumEnd: The momentum animation has ended, for example because the
|
||||
// momentum velocity has gone below the stopping threshold, or because the
|
||||
// user has stopped the animation by putting their fingers on a touchpad.
|
||||
PANGESTURE_MOMENTUMEND,
|
||||
|
||||
// Used as an upper bound for ContiguousEnumSerializer
|
||||
PANGESTURE_SENTINEL,
|
||||
};
|
||||
|
||||
PanGestureInput(PanGestureType aType,
|
||||
uint32_t aTime,
|
||||
TimeStamp aTimeStamp,
|
||||
const ScreenPoint& aPanStartPoint,
|
||||
const ScreenPoint& aPanDisplacement,
|
||||
Modifiers aModifiers);
|
||||
|
||||
bool IsMomentum() const;
|
||||
|
||||
WidgetWheelEvent ToWidgetWheelEvent(nsIWidget* aWidget) const;
|
||||
|
||||
bool TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform);
|
||||
|
||||
ScreenPoint UserMultipliedPanDisplacement() const;
|
||||
ParentLayerPoint UserMultipliedLocalPanDisplacement() const;
|
||||
|
||||
// Warning, this class is serialized and sent over IPC. Any change to its
|
||||
// fields must be reflected in its ParamTraits<>, in nsGUIEventIPC.h
|
||||
PanGestureType mType;
|
||||
ScreenPoint mPanStartPoint;
|
||||
|
||||
// The delta. This can be non-zero on any type of event.
|
||||
ScreenPoint mPanDisplacement;
|
||||
|
||||
// Versions of |mPanStartPoint| and |mPanDisplacement| in the local
|
||||
// coordinates of the APZC receiving the pan. These are set and used by APZ.
|
||||
ParentLayerPoint mLocalPanStartPoint;
|
||||
ParentLayerPoint mLocalPanDisplacement;
|
||||
|
||||
// See lineOrPageDeltaX/Y on WidgetWheelEvent.
|
||||
int32_t mLineOrPageDeltaX;
|
||||
int32_t mLineOrPageDeltaY;
|
||||
|
||||
// User-set delta multipliers.
|
||||
double mUserDeltaMultiplierX;
|
||||
double mUserDeltaMultiplierY;
|
||||
|
||||
bool mHandledByAPZ;
|
||||
|
||||
// true if this is a PANGESTURE_END event that will be followed by a
|
||||
// PANGESTURE_MOMENTUMSTART event.
|
||||
bool mFollowedByMomentum;
|
||||
|
||||
// If this is true, and this event started a new input block that couldn't
|
||||
// find a scrollable target which is scrollable in the horizontal component
|
||||
// of the scroll start direction, then this input block needs to be put on
|
||||
// hold until a content response has arrived, even if the block has a
|
||||
// confirmed target.
|
||||
// This is used by events that can result in a swipe instead of a scroll.
|
||||
bool mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encapsulation class for pinch events. In general, these will be generated by
|
||||
* a gesture listener by looking at SingleTouchData/MultiTouchInput instances and
|
||||
* determining whether or not the user was trying to do a gesture.
|
||||
*/
|
||||
class PinchGestureInput : public InputData
|
||||
{
|
||||
protected:
|
||||
friend mozilla::layers::PAPZCTreeManagerParent;
|
||||
friend mozilla::layers::APZCTreeManagerChild;
|
||||
|
||||
PinchGestureInput();
|
||||
|
||||
public:
|
||||
enum PinchGestureType
|
||||
{
|
||||
// Warning, this enum is serialized and sent over IPC. If you reorder, add,
|
||||
// or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
|
||||
PINCHGESTURE_START,
|
||||
PINCHGESTURE_SCALE,
|
||||
PINCHGESTURE_END,
|
||||
|
||||
// Used as an upper bound for ContiguousEnumSerializer
|
||||
PINCHGESTURE_SENTINEL,
|
||||
};
|
||||
|
||||
// Construct a pinch gesture from a ParentLayer point.
|
||||
// mFocusPoint remains (0,0) unless it's set later.
|
||||
PinchGestureInput(PinchGestureType aType, uint32_t aTime, TimeStamp aTimeStamp,
|
||||
const ParentLayerPoint& aLocalFocusPoint,
|
||||
ParentLayerCoord aCurrentSpan,
|
||||
ParentLayerCoord aPreviousSpan, Modifiers aModifiers);
|
||||
|
||||
bool TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform);
|
||||
|
||||
// Warning, this class is serialized and sent over IPC. Any change to its
|
||||
// fields must be reflected in its ParamTraits<>, in nsGUIEventIPC.h
|
||||
PinchGestureType mType;
|
||||
|
||||
// Center point of the pinch gesture. That is, if there are two fingers on the
|
||||
// screen, it is their midpoint. In the case of more than two fingers, the
|
||||
// point is implementation-specific, but can for example be the midpoint
|
||||
// between the very first and very last touch. This is in device pixels and
|
||||
// are the coordinates on the screen of this midpoint.
|
||||
// For PINCHGESTURE_END events, this instead will hold the coordinates of
|
||||
// the remaining finger, if there is one. If there isn't one then it will
|
||||
// store -1, -1.
|
||||
ScreenPoint mFocusPoint;
|
||||
|
||||
// |mFocusPoint| transformed to the local coordinates of the APZC targeted
|
||||
// by the hit. This is set and used by APZ.
|
||||
ParentLayerPoint mLocalFocusPoint;
|
||||
|
||||
// The distance between the touches responsible for the pinch gesture.
|
||||
ParentLayerCoord mCurrentSpan;
|
||||
|
||||
// The previous |mCurrentSpan| in the PinchGestureInput preceding this one.
|
||||
// This is only really relevant during a PINCHGESTURE_SCALE because when it is
|
||||
// of this type then there must have been a history of spans.
|
||||
ParentLayerCoord mPreviousSpan;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encapsulation class for tap events. In general, these will be generated by
|
||||
* a gesture listener by looking at SingleTouchData/MultiTouchInput instances and
|
||||
* determining whether or not the user was trying to do a gesture.
|
||||
*/
|
||||
class TapGestureInput : public InputData
|
||||
{
|
||||
protected:
|
||||
friend mozilla::layers::PAPZCTreeManagerParent;
|
||||
friend mozilla::layers::APZCTreeManagerChild;
|
||||
|
||||
TapGestureInput();
|
||||
|
||||
public:
|
||||
enum TapGestureType
|
||||
{
|
||||
// Warning, this enum is serialized and sent over IPC. If you reorder, add,
|
||||
// or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
|
||||
TAPGESTURE_LONG,
|
||||
TAPGESTURE_LONG_UP,
|
||||
TAPGESTURE_UP,
|
||||
TAPGESTURE_CONFIRMED,
|
||||
TAPGESTURE_DOUBLE,
|
||||
TAPGESTURE_SECOND, // See GeckoContentController::TapType::eSecondTap
|
||||
TAPGESTURE_CANCEL,
|
||||
|
||||
// Used as an upper bound for ContiguousEnumSerializer
|
||||
TAPGESTURE_SENTINEL,
|
||||
};
|
||||
|
||||
// Construct a tap gesture from a Screen point.
|
||||
// mLocalPoint remains (0,0) unless it's set later.
|
||||
TapGestureInput(TapGestureType aType, uint32_t aTime, TimeStamp aTimeStamp,
|
||||
const ScreenIntPoint& aPoint, Modifiers aModifiers);
|
||||
|
||||
// Construct a tap gesture from a ParentLayer point.
|
||||
// mPoint remains (0,0) unless it's set later.
|
||||
TapGestureInput(TapGestureType aType, uint32_t aTime, TimeStamp aTimeStamp,
|
||||
const ParentLayerPoint& aLocalPoint, Modifiers aModifiers);
|
||||
|
||||
bool TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform);
|
||||
|
||||
// Warning, this class is serialized and sent over IPC. Any change to its
|
||||
// fields must be reflected in its ParamTraits<>, in nsGUIEventIPC.h
|
||||
TapGestureType mType;
|
||||
|
||||
// The location of the tap in screen pixels.
|
||||
ScreenIntPoint mPoint;
|
||||
|
||||
// The location of the tap in the local coordinates of the APZC receiving it.
|
||||
// This is set and used by APZ.
|
||||
ParentLayerPoint mLocalPoint;
|
||||
};
|
||||
|
||||
// Encapsulation class for scroll-wheel events. These are generated by mice
|
||||
// with physical scroll wheels, and on Windows by most touchpads when using
|
||||
// scroll gestures.
|
||||
class ScrollWheelInput : public InputData
|
||||
{
|
||||
protected:
|
||||
friend mozilla::layers::PAPZCTreeManagerParent;
|
||||
friend mozilla::layers::APZCTreeManagerChild;
|
||||
|
||||
ScrollWheelInput();
|
||||
|
||||
public:
|
||||
enum ScrollDeltaType
|
||||
{
|
||||
// Warning, this enum is serialized and sent over IPC. If you reorder, add,
|
||||
// or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
|
||||
|
||||
// There are three kinds of scroll delta modes in Gecko: "page", "line" and
|
||||
// "pixel".
|
||||
SCROLLDELTA_LINE,
|
||||
SCROLLDELTA_PAGE,
|
||||
SCROLLDELTA_PIXEL,
|
||||
|
||||
// Used as an upper bound for ContiguousEnumSerializer
|
||||
SCROLLDELTA_SENTINEL,
|
||||
};
|
||||
|
||||
enum ScrollMode
|
||||
{
|
||||
// Warning, this enum is serialized and sent over IPC. If you reorder, add,
|
||||
// or remove a value, you need to update its ParamTraits<> in nsGUIEventIPC.h
|
||||
|
||||
SCROLLMODE_INSTANT,
|
||||
SCROLLMODE_SMOOTH,
|
||||
|
||||
// Used as an upper bound for ContiguousEnumSerializer
|
||||
SCROLLMODE_SENTINEL,
|
||||
};
|
||||
|
||||
ScrollWheelInput(uint32_t aTime, TimeStamp aTimeStamp, Modifiers aModifiers,
|
||||
ScrollMode aScrollMode, ScrollDeltaType aDeltaType,
|
||||
const ScreenPoint& aOrigin, double aDeltaX, double aDeltaY,
|
||||
bool aAllowToOverrideSystemScrollSpeed);
|
||||
explicit ScrollWheelInput(const WidgetWheelEvent& aEvent);
|
||||
|
||||
static ScrollDeltaType DeltaTypeForDeltaMode(uint32_t aDeltaMode);
|
||||
static uint32_t DeltaModeForDeltaType(ScrollDeltaType aDeltaType);
|
||||
static nsIScrollableFrame::ScrollUnit ScrollUnitForDeltaType(ScrollDeltaType aDeltaType);
|
||||
|
||||
WidgetWheelEvent ToWidgetWheelEvent(nsIWidget* aWidget) const;
|
||||
bool TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform);
|
||||
|
||||
bool IsCustomizedByUserPrefs() const;
|
||||
|
||||
// Warning, this class is serialized and sent over IPC. Any change to its
|
||||
// fields must be reflected in its ParamTraits<>, in nsGUIEventIPC.h
|
||||
ScrollDeltaType mDeltaType;
|
||||
ScrollMode mScrollMode;
|
||||
ScreenPoint mOrigin;
|
||||
|
||||
bool mHandledByAPZ;
|
||||
|
||||
// Deltas are in units corresponding to the delta type. For line deltas, they
|
||||
// are the number of line units to scroll. The number of device pixels for a
|
||||
// horizontal and vertical line unit are in FrameMetrics::mLineScrollAmount.
|
||||
// For pixel deltas, these values are in ScreenCoords.
|
||||
//
|
||||
// The horizontal (X) delta is > 0 for scrolling right and < 0 for scrolling
|
||||
// left. The vertical (Y) delta is < 0 for scrolling up and > 0 for
|
||||
// scrolling down.
|
||||
double mDeltaX;
|
||||
double mDeltaY;
|
||||
|
||||
// The location of the scroll in local coordinates. This is set and used by
|
||||
// APZ.
|
||||
ParentLayerPoint mLocalOrigin;
|
||||
|
||||
// See lineOrPageDeltaX/Y on WidgetWheelEvent.
|
||||
int32_t mLineOrPageDeltaX;
|
||||
int32_t mLineOrPageDeltaY;
|
||||
|
||||
// Indicates the order in which this event was added to a transaction. The
|
||||
// first event is 1; if not a member of a transaction, this is 0.
|
||||
uint32_t mScrollSeriesNumber;
|
||||
|
||||
// User-set delta multipliers.
|
||||
double mUserDeltaMultiplierX;
|
||||
double mUserDeltaMultiplierY;
|
||||
|
||||
bool mMayHaveMomentum;
|
||||
bool mIsMomentum;
|
||||
bool mAllowToOverrideSystemScrollSpeed;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // InputData_h__
|
||||
81
widget/LSBUtils.cpp
Normal file
81
widget/LSBUtils.cpp
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 "LSBUtils.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include "base/process_util.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
namespace lsb {
|
||||
|
||||
static const char* gLsbReleasePath = "/usr/bin/lsb_release";
|
||||
|
||||
bool
|
||||
GetLSBRelease(nsACString& aDistributor,
|
||||
nsACString& aDescription,
|
||||
nsACString& aRelease,
|
||||
nsACString& aCodename)
|
||||
{
|
||||
if (access(gLsbReleasePath, R_OK) != 0)
|
||||
return false;
|
||||
|
||||
int pipefd[2];
|
||||
if (pipe(pipefd) == -1) {
|
||||
NS_WARNING("pipe() failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> argv = {
|
||||
gLsbReleasePath, "-idrc"
|
||||
};
|
||||
|
||||
std::vector<std::pair<int, int>> fdMap = {
|
||||
{ pipefd[1], STDOUT_FILENO }
|
||||
};
|
||||
|
||||
base::ProcessHandle process;
|
||||
base::LaunchApp(argv, fdMap, true, &process);
|
||||
close(pipefd[1]);
|
||||
if (!process) {
|
||||
NS_WARNING("Failed to spawn lsb_release!");
|
||||
close(pipefd[0]);
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE* stream = fdopen(pipefd[0], "r");
|
||||
if (!stream) {
|
||||
NS_WARNING("Could not wrap fd!");
|
||||
close(pipefd[0]);
|
||||
return false;
|
||||
}
|
||||
|
||||
char dist[256], desc[256], release[256], codename[256];
|
||||
if (fscanf(stream, "Distributor ID:\t%255[^\n]\n"
|
||||
"Description:\t%255[^\n]\n"
|
||||
"Release:\t%255[^\n]\n"
|
||||
"Codename:\t%255[^\n]\n",
|
||||
dist, desc, release, codename) != 4)
|
||||
{
|
||||
NS_WARNING("Failed to parse lsb_release!");
|
||||
fclose(stream);
|
||||
close(pipefd[0]);
|
||||
return false;
|
||||
}
|
||||
fclose(stream);
|
||||
close(pipefd[0]);
|
||||
|
||||
aDistributor.Assign(dist);
|
||||
aDescription.Assign(desc);
|
||||
aRelease.Assign(release);
|
||||
aCodename.Assign(codename);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace lsb
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
28
widget/LSBUtils.h
Normal file
28
widget/LSBUtils.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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/. */
|
||||
|
||||
#ifndef _MOZILLA_WIDGET_LSB_UTILS_H
|
||||
#define _MOZILLA_WIDGET_LSB_UTILS_H
|
||||
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
namespace lsb {
|
||||
|
||||
// Fetches the LSB release data by parsing the lsb_release command.
|
||||
// Returns false if the lsb_release command was not found, or parsing failed.
|
||||
bool GetLSBRelease(nsACString& aDistributor,
|
||||
nsACString& aDescription,
|
||||
nsACString& aRelease,
|
||||
nsACString& aCodename);
|
||||
|
||||
|
||||
} // namespace lsb
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // _MOZILLA_WIDGET_LSB_UTILS_H
|
||||
640
widget/LookAndFeel.h
Normal file
640
widget/LookAndFeel.h
Normal file
|
|
@ -0,0 +1,640 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef __LookAndFeel
|
||||
#define __LookAndFeel
|
||||
|
||||
#ifndef MOZILLA_INTERNAL_API
|
||||
#error "This header is only usable from within libxul (MOZILLA_INTERNAL_API)."
|
||||
#endif
|
||||
|
||||
#include "nsDebug.h"
|
||||
#include "nsColor.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
struct gfxFontStyle;
|
||||
|
||||
struct LookAndFeelInt
|
||||
{
|
||||
int32_t id;
|
||||
int32_t value;
|
||||
};
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class LookAndFeel
|
||||
{
|
||||
public:
|
||||
// When modifying this list, also modify nsXPLookAndFeel::sColorPrefs
|
||||
// in widget/xpwidgts/nsXPLookAndFeel.cpp.
|
||||
enum ColorID : uint8_t {
|
||||
|
||||
// WARNING : NO NEGATIVE VALUE IN THIS ENUMERATION
|
||||
// see patch in bug 57757 for more information
|
||||
|
||||
eColorID_WindowBackground,
|
||||
eColorID_WindowForeground,
|
||||
eColorID_WidgetBackground,
|
||||
eColorID_WidgetForeground,
|
||||
eColorID_WidgetSelectBackground,
|
||||
eColorID_WidgetSelectForeground,
|
||||
eColorID_Widget3DHighlight,
|
||||
eColorID_Widget3DShadow,
|
||||
eColorID_TextBackground,
|
||||
eColorID_TextForeground,
|
||||
eColorID_TextSelectBackground,
|
||||
eColorID_TextSelectForeground,
|
||||
eColorID_TextSelectForegroundCustom,
|
||||
eColorID_TextSelectBackgroundDisabled,
|
||||
eColorID_TextSelectBackgroundAttention,
|
||||
eColorID_TextHighlightBackground,
|
||||
eColorID_TextHighlightForeground,
|
||||
|
||||
eColorID_IMERawInputBackground,
|
||||
eColorID_IMERawInputForeground,
|
||||
eColorID_IMERawInputUnderline,
|
||||
eColorID_IMESelectedRawTextBackground,
|
||||
eColorID_IMESelectedRawTextForeground,
|
||||
eColorID_IMESelectedRawTextUnderline,
|
||||
eColorID_IMEConvertedTextBackground,
|
||||
eColorID_IMEConvertedTextForeground,
|
||||
eColorID_IMEConvertedTextUnderline,
|
||||
eColorID_IMESelectedConvertedTextBackground,
|
||||
eColorID_IMESelectedConvertedTextForeground,
|
||||
eColorID_IMESelectedConvertedTextUnderline,
|
||||
|
||||
eColorID_SpellCheckerUnderline,
|
||||
|
||||
// New CSS 2 color definitions
|
||||
eColorID_activeborder,
|
||||
eColorID_activecaption,
|
||||
eColorID_appworkspace,
|
||||
eColorID_background,
|
||||
eColorID_buttonface,
|
||||
eColorID_buttonhighlight,
|
||||
eColorID_buttonshadow,
|
||||
eColorID_buttontext,
|
||||
eColorID_captiontext,
|
||||
eColorID_graytext,
|
||||
eColorID_highlight,
|
||||
eColorID_highlighttext,
|
||||
eColorID_inactiveborder,
|
||||
eColorID_inactivecaption,
|
||||
eColorID_inactivecaptiontext,
|
||||
eColorID_infobackground,
|
||||
eColorID_infotext,
|
||||
eColorID_menu,
|
||||
eColorID_menutext,
|
||||
eColorID_scrollbar,
|
||||
eColorID_threeddarkshadow,
|
||||
eColorID_threedface,
|
||||
eColorID_threedhighlight,
|
||||
eColorID_threedlightshadow,
|
||||
eColorID_threedshadow,
|
||||
eColorID_window,
|
||||
eColorID_windowframe,
|
||||
eColorID_windowtext,
|
||||
|
||||
eColorID__moz_buttondefault,
|
||||
// Colors which will hopefully become CSS3
|
||||
eColorID__moz_field,
|
||||
eColorID__moz_fieldtext,
|
||||
eColorID__moz_dialog,
|
||||
eColorID__moz_dialogtext,
|
||||
// used to highlight valid regions to drop something onto
|
||||
eColorID__moz_dragtargetzone,
|
||||
|
||||
// used to cell text background, selected but not focus
|
||||
eColorID__moz_cellhighlight,
|
||||
// used to cell text, selected but not focus
|
||||
eColorID__moz_cellhighlighttext,
|
||||
// used to html select cell text background, selected but not focus
|
||||
eColorID__moz_html_cellhighlight,
|
||||
// used to html select cell text, selected but not focus
|
||||
eColorID__moz_html_cellhighlighttext,
|
||||
// used to button text background, when mouse is over
|
||||
eColorID__moz_buttonhoverface,
|
||||
// used to button text, when mouse is over
|
||||
eColorID__moz_buttonhovertext,
|
||||
// used to menu item background, when mouse is over
|
||||
eColorID__moz_menuhover,
|
||||
// used to menu item text, when mouse is over
|
||||
eColorID__moz_menuhovertext,
|
||||
// used to menu bar item text
|
||||
eColorID__moz_menubartext,
|
||||
// used to menu bar item text, when mouse is over
|
||||
eColorID__moz_menubarhovertext,
|
||||
// On platforms where these colors are the same as
|
||||
// -moz-field, use -moz-fieldtext as foreground color
|
||||
eColorID__moz_eventreerow,
|
||||
eColorID__moz_oddtreerow,
|
||||
|
||||
// colors needed by the Mac OS X theme
|
||||
|
||||
// foreground color of :hover:active buttons
|
||||
eColorID__moz_mac_buttonactivetext,
|
||||
// background color of chrome toolbars in active windows
|
||||
eColorID__moz_mac_chrome_active,
|
||||
// background color of chrome toolbars in inactive windows
|
||||
eColorID__moz_mac_chrome_inactive,
|
||||
// foreground color of default buttons
|
||||
eColorID__moz_mac_defaultbuttontext,
|
||||
//ring around text fields and lists
|
||||
eColorID__moz_mac_focusring,
|
||||
//colour used when mouse is over a menu item
|
||||
eColorID__moz_mac_menuselect,
|
||||
//colour used to do shadows on menu items
|
||||
eColorID__moz_mac_menushadow,
|
||||
// color used to display text for disabled menu items
|
||||
eColorID__moz_mac_menutextdisable,
|
||||
//colour used to display text while mouse is over a menu item
|
||||
eColorID__moz_mac_menutextselect,
|
||||
// text color of disabled text on toolbars
|
||||
eColorID__moz_mac_disabledtoolbartext,
|
||||
//inactive light hightlight
|
||||
eColorID__moz_mac_secondaryhighlight,
|
||||
|
||||
// vista rebars
|
||||
|
||||
// media rebar text
|
||||
eColorID__moz_win_mediatext,
|
||||
// communications rebar text
|
||||
eColorID__moz_win_communicationstext,
|
||||
|
||||
// Hyperlink color extracted from the system, not affected by the
|
||||
// browser.anchor_color user pref.
|
||||
// There is no OS-specified safe background color for this text,
|
||||
// but it is used regularly within Windows and the Gnome DE on Dialog and
|
||||
// Window colors.
|
||||
eColorID__moz_nativehyperlinktext,
|
||||
|
||||
// Combo box widgets
|
||||
eColorID__moz_comboboxtext,
|
||||
eColorID__moz_combobox,
|
||||
|
||||
// GtkInfoBar
|
||||
eColorID__moz_gtk_info_bar_text,
|
||||
|
||||
// keep this one last, please
|
||||
eColorID_LAST_COLOR
|
||||
};
|
||||
|
||||
// When modifying this list, also modify nsXPLookAndFeel::sIntPrefs
|
||||
// in widget/xpwidgts/nsXPLookAndFeel.cpp.
|
||||
enum IntID {
|
||||
// default, may be overriden by OS
|
||||
eIntID_CaretBlinkTime,
|
||||
// pixel width of caret
|
||||
eIntID_CaretWidth,
|
||||
// show the caret when text is selected?
|
||||
eIntID_ShowCaretDuringSelection,
|
||||
// select textfields when focused via tab/accesskey?
|
||||
eIntID_SelectTextfieldsOnKeyFocus,
|
||||
// delay before submenus open
|
||||
eIntID_SubmenuDelay,
|
||||
// can popups overlap menu/task bar?
|
||||
eIntID_MenusCanOverlapOSBar,
|
||||
// should overlay scrollbars be used?
|
||||
eIntID_UseOverlayScrollbars,
|
||||
// allow H and V overlay scrollbars to overlap?
|
||||
eIntID_AllowOverlayScrollbarsOverlap,
|
||||
// show/hide scrollbars based on activity
|
||||
eIntID_ShowHideScrollbars,
|
||||
// skip navigating to disabled menu item?
|
||||
eIntID_SkipNavigatingDisabledMenuItem,
|
||||
// begin a drag if the mouse is moved further than the threshold while the
|
||||
// button is down
|
||||
eIntID_DragThresholdX,
|
||||
eIntID_DragThresholdY,
|
||||
// Accessibility theme being used?
|
||||
eIntID_UseAccessibilityTheme,
|
||||
|
||||
// position of scroll arrows in a scrollbar
|
||||
eIntID_ScrollArrowStyle,
|
||||
// is scroll thumb proportional or fixed?
|
||||
eIntID_ScrollSliderStyle,
|
||||
|
||||
// each button can take one of four values:
|
||||
eIntID_ScrollButtonLeftMouseButtonAction,
|
||||
// 0 - scrolls one line, 1 - scrolls one page
|
||||
eIntID_ScrollButtonMiddleMouseButtonAction,
|
||||
// 2 - scrolls to end, 3 - button ignored
|
||||
eIntID_ScrollButtonRightMouseButtonAction,
|
||||
|
||||
// delay for opening spring loaded folders
|
||||
eIntID_TreeOpenDelay,
|
||||
// delay for closing spring loaded folders
|
||||
eIntID_TreeCloseDelay,
|
||||
// delay for triggering the tree scrolling
|
||||
eIntID_TreeLazyScrollDelay,
|
||||
// delay for scrolling the tree
|
||||
eIntID_TreeScrollDelay,
|
||||
// the maximum number of lines to be scrolled at ones
|
||||
eIntID_TreeScrollLinesMax,
|
||||
// What type of tab-order to use
|
||||
eIntID_TabFocusModel,
|
||||
// Should menu items blink when they're chosen?
|
||||
eIntID_ChosenMenuItemsShouldBlink,
|
||||
|
||||
/*
|
||||
* A Boolean value to determine whether the Windows default theme is
|
||||
* being used.
|
||||
*
|
||||
* The value of this metric is not used on other platforms. These platforms
|
||||
* should return NS_ERROR_NOT_IMPLEMENTED when queried for this metric.
|
||||
*/
|
||||
eIntID_WindowsDefaultTheme,
|
||||
|
||||
/*
|
||||
* A Boolean value to determine whether the DWM compositor is being used
|
||||
*
|
||||
* This metric is not used on non-Windows platforms. These platforms
|
||||
* should return NS_ERROR_NOT_IMPLEMENTED when queried for this metric.
|
||||
*/
|
||||
eIntID_DWMCompositor,
|
||||
|
||||
/*
|
||||
* A Boolean value to determine whether Windows is themed (Classic vs.
|
||||
* uxtheme)
|
||||
*
|
||||
* This is Windows-specific and is not implemented on other platforms
|
||||
* (will return the default of NS_ERROR_FAILURE).
|
||||
*/
|
||||
eIntID_WindowsClassic,
|
||||
|
||||
/*
|
||||
* A Boolean value to determine whether the current Windows desktop theme
|
||||
* supports Aero Glass.
|
||||
*
|
||||
* This is Windows-specific and is not implemented on other platforms
|
||||
* (will return the default of NS_ERROR_FAILURE).
|
||||
*/
|
||||
eIntID_WindowsGlass,
|
||||
|
||||
/*
|
||||
* A Boolean value to determine whether the device is a touch enabled
|
||||
* device. Currently this is only supported by the Windows 7 Touch API.
|
||||
*
|
||||
* Platforms that do not support this metric should return
|
||||
* NS_ERROR_NOT_IMPLEMENTED when queried for this metric.
|
||||
*/
|
||||
eIntID_TouchEnabled,
|
||||
|
||||
/*
|
||||
* A Boolean value to determine whether the Mac graphite theme is
|
||||
* being used.
|
||||
*
|
||||
* The value of this metric is not used on other platforms. These platforms
|
||||
* should return NS_ERROR_NOT_IMPLEMENTED when queried for this metric.
|
||||
*/
|
||||
eIntID_MacGraphiteTheme,
|
||||
|
||||
/*
|
||||
* A Boolean value to determine whether the Mac OS X Yosemite-specific theming
|
||||
* should be used.
|
||||
*
|
||||
* The value of this metric is not used on non-Mac platforms. These
|
||||
* platforms should return NS_ERROR_NOT_IMPLEMENTED when queried for this
|
||||
* metric.
|
||||
*/
|
||||
eIntID_MacYosemiteTheme,
|
||||
|
||||
/*
|
||||
* eIntID_AlertNotificationOrigin indicates from which corner of the
|
||||
* screen alerts slide in, and from which direction (horizontal/vertical).
|
||||
* 0, the default, represents bottom right, sliding vertically.
|
||||
* Use any bitwise combination of the following constants:
|
||||
* NS_ALERT_HORIZONTAL (1), NS_ALERT_LEFT (2), NS_ALERT_TOP (4).
|
||||
*
|
||||
* 6 4
|
||||
* +-----------+
|
||||
* 7| |5
|
||||
* | |
|
||||
* 3| |1
|
||||
* +-----------+
|
||||
* 2 0
|
||||
*/
|
||||
eIntID_AlertNotificationOrigin,
|
||||
|
||||
/**
|
||||
* If true, clicking on a scrollbar (not as in dragging the thumb) defaults
|
||||
* to scrolling the view corresponding to the clicked point. Otherwise, we
|
||||
* only do so if the scrollbar is clicked using the middle mouse button or
|
||||
* if shift is pressed when the scrollbar is clicked.
|
||||
*/
|
||||
eIntID_ScrollToClick,
|
||||
|
||||
/**
|
||||
* IME and spell checker underline styles, the values should be
|
||||
* NS_DECORATION_LINE_STYLE_*. They are defined below.
|
||||
*/
|
||||
eIntID_IMERawInputUnderlineStyle,
|
||||
eIntID_IMESelectedRawTextUnderlineStyle,
|
||||
eIntID_IMEConvertedTextUnderlineStyle,
|
||||
eIntID_IMESelectedConvertedTextUnderline,
|
||||
eIntID_SpellCheckerUnderlineStyle,
|
||||
|
||||
/**
|
||||
* If this metric != 0, support window dragging on the menubar.
|
||||
*/
|
||||
eIntID_MenuBarDrag,
|
||||
/**
|
||||
* Return the appropriate WindowsThemeIdentifier for the current theme.
|
||||
*/
|
||||
eIntID_WindowsThemeIdentifier,
|
||||
/**
|
||||
* Return an appropriate os version identifier.
|
||||
*/
|
||||
eIntID_OperatingSystemVersionIdentifier,
|
||||
/**
|
||||
* 0: scrollbar button repeats to scroll only when cursor is on the button.
|
||||
* 1: scrollbar button repeats to scroll even if cursor is outside of it.
|
||||
*/
|
||||
eIntID_ScrollbarButtonAutoRepeatBehavior,
|
||||
/**
|
||||
* Delay before showing a tooltip.
|
||||
*/
|
||||
eIntID_TooltipDelay,
|
||||
/*
|
||||
* A Boolean value to determine whether Mac OS X Lion style swipe animations
|
||||
* should be used.
|
||||
*/
|
||||
eIntID_SwipeAnimationEnabled,
|
||||
|
||||
/*
|
||||
* A Boolean value to determine whether we have a color picker available
|
||||
* for <input type="color"> to hook into.
|
||||
*
|
||||
* This lets us selectively enable the style for <input type="color">
|
||||
* based on whether it's functional or not.
|
||||
*/
|
||||
eIntID_ColorPickerAvailable,
|
||||
|
||||
/*
|
||||
* A boolean value indicating whether or not the device has a hardware
|
||||
* home button. Used on gaia to determine whether a home button
|
||||
* is shown.
|
||||
*/
|
||||
eIntID_PhysicalHomeButton,
|
||||
|
||||
/*
|
||||
* Controls whether overlay scrollbars display when the user moves
|
||||
* the mouse in a scrollable frame.
|
||||
*/
|
||||
eIntID_ScrollbarDisplayOnMouseMove,
|
||||
|
||||
/*
|
||||
* Overlay scrollbar animation constants.
|
||||
*/
|
||||
eIntID_ScrollbarFadeBeginDelay,
|
||||
eIntID_ScrollbarFadeDuration,
|
||||
|
||||
/**
|
||||
* Distance in pixels to offset the context menu from the cursor
|
||||
* on open.
|
||||
*/
|
||||
eIntID_ContextMenuOffsetVertical,
|
||||
eIntID_ContextMenuOffsetHorizontal
|
||||
};
|
||||
|
||||
/**
|
||||
* Windows themes we currently detect.
|
||||
*/
|
||||
enum WindowsTheme {
|
||||
eWindowsTheme_Generic = 0, // unrecognized theme
|
||||
eWindowsTheme_Classic,
|
||||
eWindowsTheme_Aero,
|
||||
eWindowsTheme_LunaBlue,
|
||||
eWindowsTheme_LunaOlive,
|
||||
eWindowsTheme_LunaSilver,
|
||||
eWindowsTheme_Royale,
|
||||
eWindowsTheme_Zune,
|
||||
eWindowsTheme_AeroLite
|
||||
};
|
||||
|
||||
/**
|
||||
* Operating system versions.
|
||||
*/
|
||||
enum OperatingSystemVersion {
|
||||
eOperatingSystemVersion_WindowsXP = 0,
|
||||
eOperatingSystemVersion_WindowsVista,
|
||||
eOperatingSystemVersion_Windows7,
|
||||
eOperatingSystemVersion_Windows8,
|
||||
eOperatingSystemVersion_Windows10,
|
||||
eOperatingSystemVersion_Unknown
|
||||
};
|
||||
|
||||
enum {
|
||||
eScrollArrow_None = 0,
|
||||
eScrollArrow_StartBackward = 0x1000,
|
||||
eScrollArrow_StartForward = 0x0100,
|
||||
eScrollArrow_EndBackward = 0x0010,
|
||||
eScrollArrow_EndForward = 0x0001
|
||||
};
|
||||
|
||||
enum {
|
||||
// single arrow at each end
|
||||
eScrollArrowStyle_Single =
|
||||
eScrollArrow_StartBackward | eScrollArrow_EndForward,
|
||||
// both arrows at bottom/right, none at top/left
|
||||
eScrollArrowStyle_BothAtBottom =
|
||||
eScrollArrow_EndBackward | eScrollArrow_EndForward,
|
||||
// both arrows at both ends
|
||||
eScrollArrowStyle_BothAtEachEnd =
|
||||
eScrollArrow_EndBackward | eScrollArrow_EndForward |
|
||||
eScrollArrow_StartBackward | eScrollArrow_StartForward,
|
||||
// both arrows at top/left, none at bottom/right
|
||||
eScrollArrowStyle_BothAtTop =
|
||||
eScrollArrow_StartBackward | eScrollArrow_StartForward
|
||||
};
|
||||
|
||||
enum {
|
||||
eScrollThumbStyle_Normal,
|
||||
eScrollThumbStyle_Proportional
|
||||
};
|
||||
|
||||
// When modifying this list, also modify nsXPLookAndFeel::sFloatPrefs
|
||||
// in widget/xpwidgts/nsXPLookAndFeel.cpp.
|
||||
enum FloatID {
|
||||
eFloatID_IMEUnderlineRelativeSize,
|
||||
eFloatID_SpellCheckerUnderlineRelativeSize,
|
||||
|
||||
// The width/height ratio of the cursor. If used, the CaretWidth int metric
|
||||
// should be added to the calculated caret width.
|
||||
eFloatID_CaretAspectRatio
|
||||
};
|
||||
|
||||
// These constants must be kept in 1:1 correspondence with the
|
||||
// NS_STYLE_FONT_* system font constants.
|
||||
enum FontID {
|
||||
eFont_Caption = 1, // css2
|
||||
eFont_Icon,
|
||||
eFont_Menu,
|
||||
eFont_MessageBox,
|
||||
eFont_SmallCaption,
|
||||
eFont_StatusBar,
|
||||
|
||||
eFont_Window, // css3
|
||||
eFont_Document,
|
||||
eFont_Workspace,
|
||||
eFont_Desktop,
|
||||
eFont_Info,
|
||||
eFont_Dialog,
|
||||
eFont_Button,
|
||||
eFont_PullDownMenu,
|
||||
eFont_List,
|
||||
eFont_Field,
|
||||
|
||||
eFont_Tooltips, // moz
|
||||
eFont_Widget
|
||||
};
|
||||
|
||||
/**
|
||||
* GetColor() return a native color value (might be overwritten by prefs) for
|
||||
* aID. Some platforms don't return an error even if the index doesn't
|
||||
* match any system colors. And also some platforms may initialize the
|
||||
* return value even when it returns an error. Therefore, if you want to
|
||||
* use a color for the default value, you should use the other GetColor()
|
||||
* which returns nscolor directly.
|
||||
*
|
||||
* NOTE:
|
||||
* eColorID_TextSelectForeground might return NS_DONT_CHANGE_COLOR.
|
||||
* eColorID_IME* might return NS_TRANSPARENT, NS_SAME_AS_FOREGROUND_COLOR or
|
||||
* NS_40PERCENT_FOREGROUND_COLOR.
|
||||
* These values have particular meaning. Then, they are not an actual
|
||||
* color value.
|
||||
*/
|
||||
static nsresult GetColor(ColorID aID, nscolor* aResult);
|
||||
|
||||
/**
|
||||
* This variant of GetColor() takes an extra Boolean parameter that allows
|
||||
* the caller to ask that hard-coded color values be substituted for
|
||||
* native colors (used when it is desireable to hide system colors to
|
||||
* avoid system fingerprinting).
|
||||
*/
|
||||
static nsresult GetColor(ColorID aID, bool aUseStandinsForNativeColors,
|
||||
nscolor* aResult);
|
||||
|
||||
/**
|
||||
* GetInt() and GetFloat() return a int or float value for aID. The result
|
||||
* might be distance, time, some flags or a int value which has particular
|
||||
* meaning. See each document at definition of each ID for the detail.
|
||||
* The result is always 0 when they return error. Therefore, if you want to
|
||||
* use a value for the default value, you should use the other method which
|
||||
* returns int or float directly.
|
||||
*/
|
||||
static nsresult GetInt(IntID aID, int32_t* aResult);
|
||||
static nsresult GetFloat(FloatID aID, float* aResult);
|
||||
|
||||
static nscolor GetColor(ColorID aID, nscolor aDefault = NS_RGB(0, 0, 0))
|
||||
{
|
||||
nscolor result = NS_RGB(0, 0, 0);
|
||||
if (NS_FAILED(GetColor(aID, &result))) {
|
||||
return aDefault;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static int32_t GetInt(IntID aID, int32_t aDefault = 0)
|
||||
{
|
||||
int32_t result;
|
||||
if (NS_FAILED(GetInt(aID, &result))) {
|
||||
return aDefault;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static float GetFloat(FloatID aID, float aDefault = 0.0f)
|
||||
{
|
||||
float result;
|
||||
if (NS_FAILED(GetFloat(aID, &result))) {
|
||||
return aDefault;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the name and style of a system-theme font. Returns true
|
||||
* if the system theme specifies this font, false if a default should
|
||||
* be used. In the latter case neither aName nor aStyle is modified.
|
||||
*
|
||||
* @param aID Which system-theme font is wanted.
|
||||
* @param aName The name of the font to use.
|
||||
* @param aStyle Styling to apply to the font.
|
||||
* @param aDevPixPerCSSPixel Ratio of device pixels to CSS pixels
|
||||
*/
|
||||
static bool GetFont(FontID aID, nsString& aName, gfxFontStyle& aStyle,
|
||||
float aDevPixPerCSSPixel);
|
||||
|
||||
/**
|
||||
* GetPasswordCharacter() returns a unicode character which should be used
|
||||
* for a masked character in password editor. E.g., '*'.
|
||||
*/
|
||||
static char16_t GetPasswordCharacter();
|
||||
|
||||
/**
|
||||
* If the latest character in password field shouldn't be hidden by the
|
||||
* result of GetPasswordCharacter(), GetEchoPassword() returns TRUE.
|
||||
* Otherwise, FALSE.
|
||||
*/
|
||||
static bool GetEchoPassword();
|
||||
|
||||
/**
|
||||
* The millisecond to mask password value.
|
||||
* This value is only valid when GetEchoPassword() returns true.
|
||||
*/
|
||||
static uint32_t GetPasswordMaskDelay();
|
||||
|
||||
/**
|
||||
* When system look and feel is changed, Refresh() must be called. Then,
|
||||
* cached data would be released.
|
||||
*/
|
||||
static void Refresh();
|
||||
|
||||
/**
|
||||
* If the implementation is caching values, these accessors allow the
|
||||
* cache to be exported and imported.
|
||||
*/
|
||||
static nsTArray<LookAndFeelInt> GetIntCache();
|
||||
static void SetIntCache(const nsTArray<LookAndFeelInt>& aLookAndFeelIntCache);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
// On the Mac, GetColor(eColorID_TextSelectForeground, color) returns this
|
||||
// constant to specify that the foreground color should not be changed
|
||||
// (ie. a colored text keeps its colors when selected).
|
||||
// Of course if other plaforms work like the Mac, they can use it too.
|
||||
#define NS_DONT_CHANGE_COLOR NS_RGB(0x01, 0x01, 0x01)
|
||||
|
||||
// Similar with NS_DONT_CHANGE_COLOR, except NS_DONT_CHANGE_COLOR would returns
|
||||
// complementary color if fg color is same as bg color.
|
||||
// NS_CHANGE_COLOR_IF_SAME_AS_BG would returns eColorID_TextSelectForegroundCustom if
|
||||
// fg and bg color are the same.
|
||||
#define NS_CHANGE_COLOR_IF_SAME_AS_BG NS_RGB(0x02, 0x02, 0x02)
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Special colors for eColorID_IME* and eColorID_SpellCheckerUnderline
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
// For background color only.
|
||||
#define NS_TRANSPARENT NS_RGBA(0x01, 0x00, 0x00, 0x00)
|
||||
// For foreground color only.
|
||||
#define NS_SAME_AS_FOREGROUND_COLOR NS_RGBA(0x02, 0x00, 0x00, 0x00)
|
||||
#define NS_40PERCENT_FOREGROUND_COLOR NS_RGBA(0x03, 0x00, 0x00, 0x00)
|
||||
|
||||
#define NS_IS_SELECTION_SPECIAL_COLOR(c) ((c) == NS_TRANSPARENT || \
|
||||
(c) == NS_SAME_AS_FOREGROUND_COLOR || \
|
||||
(c) == NS_40PERCENT_FOREGROUND_COLOR)
|
||||
|
||||
// ------------------------------------------
|
||||
// Bits for eIntID_AlertNotificationOrigin
|
||||
// ------------------------------------------
|
||||
|
||||
#define NS_ALERT_HORIZONTAL 1
|
||||
#define NS_ALERT_LEFT 2
|
||||
#define NS_ALERT_TOP 4
|
||||
|
||||
#endif /* __LookAndFeel */
|
||||
196
widget/MiscEvents.h
Normal file
196
widget/MiscEvents.h
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_MiscEvents_h__
|
||||
#define mozilla_MiscEvents_h__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mozilla/BasicEvents.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsITransferable.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace dom {
|
||||
class PBrowserParent;
|
||||
class PBrowserChild;
|
||||
} // namespace dom
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::WidgetContentCommandEvent
|
||||
******************************************************************************/
|
||||
|
||||
class WidgetContentCommandEvent : public WidgetGUIEvent
|
||||
{
|
||||
public:
|
||||
virtual WidgetContentCommandEvent* AsContentCommandEvent() override
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
WidgetContentCommandEvent(bool aIsTrusted, EventMessage aMessage,
|
||||
nsIWidget* aWidget,
|
||||
bool aOnlyEnabledCheck = false)
|
||||
: WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eContentCommandEventClass)
|
||||
, mOnlyEnabledCheck(aOnlyEnabledCheck)
|
||||
, mSucceeded(false)
|
||||
, mIsEnabled(false)
|
||||
{
|
||||
}
|
||||
|
||||
virtual WidgetEvent* Duplicate() const override
|
||||
{
|
||||
// This event isn't an internal event of any DOM event.
|
||||
NS_ASSERTION(!IsAllowedToDispatchDOMEvent(),
|
||||
"WidgetQueryContentEvent needs to support Duplicate()");
|
||||
MOZ_CRASH("WidgetQueryContentEvent doesn't support Duplicate()");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// eContentCommandPasteTransferable
|
||||
nsCOMPtr<nsITransferable> mTransferable; // [in]
|
||||
|
||||
// eContentCommandScroll
|
||||
// for mScroll.mUnit
|
||||
enum
|
||||
{
|
||||
eCmdScrollUnit_Line,
|
||||
eCmdScrollUnit_Page,
|
||||
eCmdScrollUnit_Whole
|
||||
};
|
||||
|
||||
struct ScrollInfo
|
||||
{
|
||||
ScrollInfo() :
|
||||
mAmount(0), mUnit(eCmdScrollUnit_Line), mIsHorizontal(false)
|
||||
{
|
||||
}
|
||||
|
||||
int32_t mAmount; // [in]
|
||||
uint8_t mUnit; // [in]
|
||||
bool mIsHorizontal; // [in]
|
||||
} mScroll;
|
||||
|
||||
bool mOnlyEnabledCheck; // [in]
|
||||
|
||||
bool mSucceeded; // [out]
|
||||
bool mIsEnabled; // [out]
|
||||
|
||||
void AssignContentCommandEventData(const WidgetContentCommandEvent& aEvent,
|
||||
bool aCopyTargets)
|
||||
{
|
||||
AssignGUIEventData(aEvent, aCopyTargets);
|
||||
|
||||
mScroll = aEvent.mScroll;
|
||||
mOnlyEnabledCheck = aEvent.mOnlyEnabledCheck;
|
||||
mSucceeded = aEvent.mSucceeded;
|
||||
mIsEnabled = aEvent.mIsEnabled;
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::WidgetCommandEvent
|
||||
*
|
||||
* This sends a command to chrome. If you want to request what is performed
|
||||
* in focused content, you should use WidgetContentCommandEvent instead.
|
||||
*
|
||||
* XXX Should be |WidgetChromeCommandEvent|?
|
||||
******************************************************************************/
|
||||
|
||||
class WidgetCommandEvent : public WidgetGUIEvent
|
||||
{
|
||||
public:
|
||||
virtual WidgetCommandEvent* AsCommandEvent() override { return this; }
|
||||
|
||||
WidgetCommandEvent(bool aIsTrusted, nsIAtom* aEventType,
|
||||
nsIAtom* aCommand, nsIWidget* aWidget)
|
||||
: WidgetGUIEvent(aIsTrusted, eUnidentifiedEvent, aWidget,
|
||||
eCommandEventClass)
|
||||
, mCommand(aCommand)
|
||||
{
|
||||
mSpecifiedEventType = aEventType;
|
||||
}
|
||||
|
||||
virtual WidgetEvent* Duplicate() const override
|
||||
{
|
||||
MOZ_ASSERT(mClass == eCommandEventClass,
|
||||
"Duplicate() must be overridden by sub class");
|
||||
// Not copying widget, it is a weak reference.
|
||||
WidgetCommandEvent* result =
|
||||
new WidgetCommandEvent(false, mSpecifiedEventType, mCommand, nullptr);
|
||||
result->AssignCommandEventData(*this, true);
|
||||
result->mFlags = mFlags;
|
||||
return result;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAtom> mCommand;
|
||||
|
||||
// XXX Not tested by test_assign_event_data.html
|
||||
void AssignCommandEventData(const WidgetCommandEvent& aEvent,
|
||||
bool aCopyTargets)
|
||||
{
|
||||
AssignGUIEventData(aEvent, aCopyTargets);
|
||||
|
||||
// mCommand must have been initialized with the constructor.
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::WidgetPluginEvent
|
||||
*
|
||||
* This event delivers only a native event to focused plugin.
|
||||
******************************************************************************/
|
||||
|
||||
class WidgetPluginEvent : public WidgetGUIEvent
|
||||
{
|
||||
private:
|
||||
friend class dom::PBrowserParent;
|
||||
friend class dom::PBrowserChild;
|
||||
|
||||
public:
|
||||
virtual WidgetPluginEvent* AsPluginEvent() override { return this; }
|
||||
|
||||
WidgetPluginEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget)
|
||||
: WidgetGUIEvent(aIsTrusted, aMessage, aWidget, ePluginEventClass)
|
||||
, mRetargetToFocusedDocument(false)
|
||||
{
|
||||
}
|
||||
|
||||
virtual WidgetEvent* Duplicate() const override
|
||||
{
|
||||
// NOTE: PluginEvent has to be dispatched to nsIFrame::HandleEvent().
|
||||
// So, this event needs to support Duplicate().
|
||||
MOZ_ASSERT(mClass == ePluginEventClass,
|
||||
"Duplicate() must be overridden by sub class");
|
||||
// Not copying widget, it is a weak reference.
|
||||
WidgetPluginEvent* result = new WidgetPluginEvent(false, mMessage, nullptr);
|
||||
result->AssignPluginEventData(*this, true);
|
||||
result->mFlags = mFlags;
|
||||
return result;
|
||||
}
|
||||
|
||||
// If true, this event needs to be retargeted to focused document.
|
||||
// Otherwise, never retargeted. Defaults to false.
|
||||
bool mRetargetToFocusedDocument;
|
||||
|
||||
void AssignPluginEventData(const WidgetPluginEvent& aEvent,
|
||||
bool aCopyTargets)
|
||||
{
|
||||
AssignGUIEventData(aEvent, aCopyTargets);
|
||||
|
||||
mRetargetToFocusedDocument = aEvent.mRetargetToFocusedDocument;
|
||||
}
|
||||
|
||||
protected:
|
||||
WidgetPluginEvent()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_MiscEvents_h__
|
||||
724
widget/MouseEvents.h
Normal file
724
widget/MouseEvents.h
Normal file
|
|
@ -0,0 +1,724 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_MouseEvents_h__
|
||||
#define mozilla_MouseEvents_h__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mozilla/BasicEvents.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
#include "mozilla/dom/DataTransfer.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDOMMouseEvent.h"
|
||||
#include "nsIDOMWheelEvent.h"
|
||||
|
||||
/******************************************************************************
|
||||
* nsDragDropEventStatus
|
||||
******************************************************************************/
|
||||
|
||||
enum nsDragDropEventStatus
|
||||
{
|
||||
// The event is a enter
|
||||
nsDragDropEventStatus_eDragEntered,
|
||||
// The event is exit
|
||||
nsDragDropEventStatus_eDragExited,
|
||||
// The event is drop
|
||||
nsDragDropEventStatus_eDrop
|
||||
};
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace dom {
|
||||
class PBrowserParent;
|
||||
class PBrowserChild;
|
||||
} // namespace dom
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::WidgetPointerHelper
|
||||
******************************************************************************/
|
||||
|
||||
class WidgetPointerHelper
|
||||
{
|
||||
public:
|
||||
bool convertToPointer;
|
||||
uint32_t pointerId;
|
||||
uint32_t tiltX;
|
||||
uint32_t tiltY;
|
||||
bool retargetedByPointerCapture;
|
||||
|
||||
WidgetPointerHelper() : convertToPointer(true), pointerId(0), tiltX(0), tiltY(0),
|
||||
retargetedByPointerCapture(false) {}
|
||||
|
||||
void AssignPointerHelperData(const WidgetPointerHelper& aEvent)
|
||||
{
|
||||
convertToPointer = aEvent.convertToPointer;
|
||||
pointerId = aEvent.pointerId;
|
||||
tiltX = aEvent.tiltX;
|
||||
tiltY = aEvent.tiltY;
|
||||
retargetedByPointerCapture = aEvent.retargetedByPointerCapture;
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::WidgetMouseEventBase
|
||||
******************************************************************************/
|
||||
|
||||
class WidgetMouseEventBase : public WidgetInputEvent
|
||||
{
|
||||
private:
|
||||
friend class dom::PBrowserParent;
|
||||
friend class dom::PBrowserChild;
|
||||
|
||||
protected:
|
||||
WidgetMouseEventBase()
|
||||
: button(0)
|
||||
, buttons(0)
|
||||
, pressure(0)
|
||||
, hitCluster(false)
|
||||
, inputSource(nsIDOMMouseEvent::MOZ_SOURCE_MOUSE)
|
||||
{
|
||||
}
|
||||
|
||||
WidgetMouseEventBase(bool aIsTrusted, EventMessage aMessage,
|
||||
nsIWidget* aWidget, EventClassID aEventClassID)
|
||||
: WidgetInputEvent(aIsTrusted, aMessage, aWidget, aEventClassID)
|
||||
, button(0)
|
||||
, buttons(0)
|
||||
, pressure(0)
|
||||
, hitCluster(false)
|
||||
, inputSource(nsIDOMMouseEvent::MOZ_SOURCE_MOUSE)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual WidgetMouseEventBase* AsMouseEventBase() override { return this; }
|
||||
|
||||
virtual WidgetEvent* Duplicate() const override
|
||||
{
|
||||
MOZ_CRASH("WidgetMouseEventBase must not be most-subclass");
|
||||
}
|
||||
|
||||
/// The possible related target
|
||||
nsCOMPtr<nsISupports> relatedTarget;
|
||||
|
||||
enum buttonType
|
||||
{
|
||||
eLeftButton = 0,
|
||||
eMiddleButton = 1,
|
||||
eRightButton = 2
|
||||
};
|
||||
// Pressed button ID of mousedown or mouseup event.
|
||||
// This is set only when pressing a button causes the event.
|
||||
int16_t button;
|
||||
|
||||
enum buttonsFlag {
|
||||
eNoButtonFlag = 0x00,
|
||||
eLeftButtonFlag = 0x01,
|
||||
eRightButtonFlag = 0x02,
|
||||
eMiddleButtonFlag = 0x04,
|
||||
// typicall, "back" button being left side of 5-button
|
||||
// mice, see "buttons" attribute document of DOM3 Events.
|
||||
e4thButtonFlag = 0x08,
|
||||
// typicall, "forward" button being right side of 5-button
|
||||
// mice, see "buttons" attribute document of DOM3 Events.
|
||||
e5thButtonFlag = 0x10
|
||||
};
|
||||
|
||||
// Flags of all pressed buttons at the event fired.
|
||||
// This is set at any mouse event, don't be confused with |button|.
|
||||
int16_t buttons;
|
||||
|
||||
// Finger or touch pressure of event. It ranges between 0.0 and 1.0.
|
||||
float pressure;
|
||||
// Touch near a cluster of links (true)
|
||||
bool hitCluster;
|
||||
|
||||
// Possible values at nsIDOMMouseEvent
|
||||
uint16_t inputSource;
|
||||
|
||||
// ID of the canvas HitRegion
|
||||
nsString region;
|
||||
|
||||
bool IsLeftButtonPressed() const { return !!(buttons & eLeftButtonFlag); }
|
||||
bool IsRightButtonPressed() const { return !!(buttons & eRightButtonFlag); }
|
||||
bool IsMiddleButtonPressed() const { return !!(buttons & eMiddleButtonFlag); }
|
||||
bool Is4thButtonPressed() const { return !!(buttons & e4thButtonFlag); }
|
||||
bool Is5thButtonPressed() const { return !!(buttons & e5thButtonFlag); }
|
||||
|
||||
void AssignMouseEventBaseData(const WidgetMouseEventBase& aEvent,
|
||||
bool aCopyTargets)
|
||||
{
|
||||
AssignInputEventData(aEvent, aCopyTargets);
|
||||
|
||||
relatedTarget = aCopyTargets ? aEvent.relatedTarget : nullptr;
|
||||
button = aEvent.button;
|
||||
buttons = aEvent.buttons;
|
||||
pressure = aEvent.pressure;
|
||||
hitCluster = aEvent.hitCluster;
|
||||
inputSource = aEvent.inputSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if left click event.
|
||||
*/
|
||||
bool IsLeftClickEvent() const
|
||||
{
|
||||
return mMessage == eMouseClick && button == eLeftButton;
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::WidgetMouseEvent
|
||||
******************************************************************************/
|
||||
|
||||
class WidgetMouseEvent : public WidgetMouseEventBase
|
||||
, public WidgetPointerHelper
|
||||
{
|
||||
private:
|
||||
friend class dom::PBrowserParent;
|
||||
friend class dom::PBrowserChild;
|
||||
|
||||
public:
|
||||
typedef bool ReasonType;
|
||||
enum Reason : ReasonType
|
||||
{
|
||||
eReal,
|
||||
eSynthesized
|
||||
};
|
||||
|
||||
typedef bool ContextMenuTriggerType;
|
||||
enum ContextMenuTrigger : ContextMenuTriggerType
|
||||
{
|
||||
eNormal,
|
||||
eContextMenuKey
|
||||
};
|
||||
|
||||
typedef bool ExitFromType;
|
||||
enum ExitFrom : ExitFromType
|
||||
{
|
||||
eChild,
|
||||
eTopLevel
|
||||
};
|
||||
|
||||
protected:
|
||||
WidgetMouseEvent()
|
||||
: mReason(eReal)
|
||||
, mContextMenuTrigger(eNormal)
|
||||
, mExitFrom(eChild)
|
||||
, mIgnoreRootScrollFrame(false)
|
||||
, mClickCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
WidgetMouseEvent(bool aIsTrusted,
|
||||
EventMessage aMessage,
|
||||
nsIWidget* aWidget,
|
||||
EventClassID aEventClassID,
|
||||
Reason aReason)
|
||||
: WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, aEventClassID)
|
||||
, mReason(aReason)
|
||||
, mContextMenuTrigger(eNormal)
|
||||
, mExitFrom(eChild)
|
||||
, mIgnoreRootScrollFrame(false)
|
||||
, mClickCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual WidgetMouseEvent* AsMouseEvent() override { return this; }
|
||||
|
||||
WidgetMouseEvent(bool aIsTrusted,
|
||||
EventMessage aMessage,
|
||||
nsIWidget* aWidget,
|
||||
Reason aReason,
|
||||
ContextMenuTrigger aContextMenuTrigger = eNormal)
|
||||
: WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, eMouseEventClass)
|
||||
, mReason(aReason)
|
||||
, mContextMenuTrigger(aContextMenuTrigger)
|
||||
, mExitFrom(eChild)
|
||||
, mIgnoreRootScrollFrame(false)
|
||||
, mClickCount(0)
|
||||
{
|
||||
if (aMessage == eContextMenu) {
|
||||
button = (mContextMenuTrigger == eNormal) ? eRightButton : eLeftButton;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
virtual ~WidgetMouseEvent()
|
||||
{
|
||||
NS_WARNING_ASSERTION(
|
||||
mMessage != eContextMenu ||
|
||||
button == ((mContextMenuTrigger == eNormal) ? eRightButton : eLeftButton),
|
||||
"Wrong button set to eContextMenu event?");
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual WidgetEvent* Duplicate() const override
|
||||
{
|
||||
MOZ_ASSERT(mClass == eMouseEventClass,
|
||||
"Duplicate() must be overridden by sub class");
|
||||
// Not copying widget, it is a weak reference.
|
||||
WidgetMouseEvent* result =
|
||||
new WidgetMouseEvent(false, mMessage, nullptr,
|
||||
mReason, mContextMenuTrigger);
|
||||
result->AssignMouseEventData(*this, true);
|
||||
result->mFlags = mFlags;
|
||||
return result;
|
||||
}
|
||||
|
||||
// mReason indicates the reason why the event is fired:
|
||||
// - Representing mouse operation.
|
||||
// - Synthesized for emulating mousemove event when the content under the
|
||||
// mouse cursor is scrolled.
|
||||
Reason mReason;
|
||||
|
||||
// mContextMenuTrigger is valid only when mMessage is eContextMenu.
|
||||
// This indicates if the context menu event is caused by context menu key or
|
||||
// other reasons (typically, a click of right mouse button).
|
||||
ContextMenuTrigger mContextMenuTrigger;
|
||||
|
||||
// mExitFrom is valid only when mMessage is eMouseExitFromWidget.
|
||||
// This indicates if the mouse cursor exits from a top level widget or
|
||||
// a child widget.
|
||||
ExitFrom mExitFrom;
|
||||
|
||||
// Whether the event should ignore scroll frame bounds during dispatch.
|
||||
bool mIgnoreRootScrollFrame;
|
||||
|
||||
// mClickCount may be non-zero value when mMessage is eMouseDown, eMouseUp,
|
||||
// eMouseClick or eMouseDoubleClick. The number is count of mouse clicks.
|
||||
// Otherwise, this must be 0.
|
||||
uint32_t mClickCount;
|
||||
|
||||
void AssignMouseEventData(const WidgetMouseEvent& aEvent, bool aCopyTargets)
|
||||
{
|
||||
AssignMouseEventBaseData(aEvent, aCopyTargets);
|
||||
AssignPointerHelperData(aEvent);
|
||||
|
||||
mIgnoreRootScrollFrame = aEvent.mIgnoreRootScrollFrame;
|
||||
mClickCount = aEvent.mClickCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the event is a context menu event caused by key.
|
||||
*/
|
||||
bool IsContextMenuKeyEvent() const
|
||||
{
|
||||
return mMessage == eContextMenu && mContextMenuTrigger == eContextMenuKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the event is a real mouse event. Otherwise, i.e., it's
|
||||
* a synthesized event by scroll or something, returns false.
|
||||
*/
|
||||
bool IsReal() const
|
||||
{
|
||||
return mReason == eReal;
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::WidgetDragEvent
|
||||
******************************************************************************/
|
||||
|
||||
class WidgetDragEvent : public WidgetMouseEvent
|
||||
{
|
||||
private:
|
||||
friend class mozilla::dom::PBrowserParent;
|
||||
friend class mozilla::dom::PBrowserChild;
|
||||
protected:
|
||||
WidgetDragEvent()
|
||||
: mUserCancelled(false)
|
||||
, mDefaultPreventedOnContent(false)
|
||||
{
|
||||
}
|
||||
public:
|
||||
virtual WidgetDragEvent* AsDragEvent() override { return this; }
|
||||
|
||||
WidgetDragEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget)
|
||||
: WidgetMouseEvent(aIsTrusted, aMessage, aWidget, eDragEventClass, eReal)
|
||||
, mUserCancelled(false)
|
||||
, mDefaultPreventedOnContent(false)
|
||||
{
|
||||
}
|
||||
|
||||
virtual WidgetEvent* Duplicate() const override
|
||||
{
|
||||
MOZ_ASSERT(mClass == eDragEventClass,
|
||||
"Duplicate() must be overridden by sub class");
|
||||
// Not copying widget, it is a weak reference.
|
||||
WidgetDragEvent* result = new WidgetDragEvent(false, mMessage, nullptr);
|
||||
result->AssignDragEventData(*this, true);
|
||||
result->mFlags = mFlags;
|
||||
return result;
|
||||
}
|
||||
|
||||
// The dragging data.
|
||||
nsCOMPtr<dom::DataTransfer> mDataTransfer;
|
||||
|
||||
// If this is true, user has cancelled the drag operation.
|
||||
bool mUserCancelled;
|
||||
// If this is true, the drag event's preventDefault() is called on content.
|
||||
bool mDefaultPreventedOnContent;
|
||||
|
||||
// XXX Not tested by test_assign_event_data.html
|
||||
void AssignDragEventData(const WidgetDragEvent& aEvent, bool aCopyTargets)
|
||||
{
|
||||
AssignMouseEventData(aEvent, aCopyTargets);
|
||||
|
||||
mDataTransfer = aEvent.mDataTransfer;
|
||||
// XXX mUserCancelled isn't copied, is this intentionally?
|
||||
mUserCancelled = false;
|
||||
mDefaultPreventedOnContent = aEvent.mDefaultPreventedOnContent;
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::WidgetMouseScrollEvent
|
||||
*
|
||||
* This is used for legacy DOM mouse scroll events, i.e.,
|
||||
* DOMMouseScroll and MozMousePixelScroll event. These events are NOT hanbled
|
||||
* by ESM even if widget dispatches them. Use new WidgetWheelEvent instead.
|
||||
******************************************************************************/
|
||||
|
||||
class WidgetMouseScrollEvent : public WidgetMouseEventBase
|
||||
{
|
||||
private:
|
||||
WidgetMouseScrollEvent()
|
||||
: mDelta(0)
|
||||
, mIsHorizontal(false)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual WidgetMouseScrollEvent* AsMouseScrollEvent() override
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
WidgetMouseScrollEvent(bool aIsTrusted, EventMessage aMessage,
|
||||
nsIWidget* aWidget)
|
||||
: WidgetMouseEventBase(aIsTrusted, aMessage, aWidget,
|
||||
eMouseScrollEventClass)
|
||||
, mDelta(0)
|
||||
, mIsHorizontal(false)
|
||||
{
|
||||
}
|
||||
|
||||
virtual WidgetEvent* Duplicate() const override
|
||||
{
|
||||
MOZ_ASSERT(mClass == eMouseScrollEventClass,
|
||||
"Duplicate() must be overridden by sub class");
|
||||
// Not copying widget, it is a weak reference.
|
||||
WidgetMouseScrollEvent* result =
|
||||
new WidgetMouseScrollEvent(false, mMessage, nullptr);
|
||||
result->AssignMouseScrollEventData(*this, true);
|
||||
result->mFlags = mFlags;
|
||||
return result;
|
||||
}
|
||||
|
||||
// The delta value of mouse scroll event.
|
||||
// If the event message is eLegacyMouseLineOrPageScroll, the value indicates
|
||||
// scroll amount in lines. However, if the value is
|
||||
// nsIDOMUIEvent::SCROLL_PAGE_UP or nsIDOMUIEvent::SCROLL_PAGE_DOWN, the
|
||||
// value inducates one page scroll. If the event message is
|
||||
// eLegacyMousePixelScroll, the value indicates scroll amount in pixels.
|
||||
int32_t mDelta;
|
||||
|
||||
// If this is true, it may cause to scroll horizontally.
|
||||
// Otherwise, vertically.
|
||||
bool mIsHorizontal;
|
||||
|
||||
void AssignMouseScrollEventData(const WidgetMouseScrollEvent& aEvent,
|
||||
bool aCopyTargets)
|
||||
{
|
||||
AssignMouseEventBaseData(aEvent, aCopyTargets);
|
||||
|
||||
mDelta = aEvent.mDelta;
|
||||
mIsHorizontal = aEvent.mIsHorizontal;
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::WidgetWheelEvent
|
||||
******************************************************************************/
|
||||
|
||||
class WidgetWheelEvent : public WidgetMouseEventBase
|
||||
{
|
||||
private:
|
||||
friend class mozilla::dom::PBrowserParent;
|
||||
friend class mozilla::dom::PBrowserChild;
|
||||
|
||||
WidgetWheelEvent()
|
||||
: mDeltaX(0.0)
|
||||
, mDeltaY(0.0)
|
||||
, mDeltaZ(0.0)
|
||||
, mOverflowDeltaX(0.0)
|
||||
, mOverflowDeltaY(0.0)
|
||||
, mDeltaMode(nsIDOMWheelEvent::DOM_DELTA_PIXEL)
|
||||
, mLineOrPageDeltaX(0)
|
||||
, mLineOrPageDeltaY(0)
|
||||
, mScrollType(SCROLL_DEFAULT)
|
||||
, mCustomizedByUserPrefs(false)
|
||||
, mIsMomentum(false)
|
||||
, mIsNoLineOrPageDelta(false)
|
||||
, mViewPortIsOverscrolled(false)
|
||||
, mCanTriggerSwipe(false)
|
||||
, mAllowToOverrideSystemScrollSpeed(false)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual WidgetWheelEvent* AsWheelEvent() override { return this; }
|
||||
|
||||
WidgetWheelEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget)
|
||||
: WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, eWheelEventClass)
|
||||
, mDeltaX(0.0)
|
||||
, mDeltaY(0.0)
|
||||
, mDeltaZ(0.0)
|
||||
, mOverflowDeltaX(0.0)
|
||||
, mOverflowDeltaY(0.0)
|
||||
, mDeltaMode(nsIDOMWheelEvent::DOM_DELTA_PIXEL)
|
||||
, mLineOrPageDeltaX(0)
|
||||
, mLineOrPageDeltaY(0)
|
||||
, mScrollType(SCROLL_DEFAULT)
|
||||
, mCustomizedByUserPrefs(false)
|
||||
, mMayHaveMomentum(false)
|
||||
, mIsMomentum(false)
|
||||
, mIsNoLineOrPageDelta(false)
|
||||
, mViewPortIsOverscrolled(false)
|
||||
, mCanTriggerSwipe(false)
|
||||
, mAllowToOverrideSystemScrollSpeed(true)
|
||||
{
|
||||
}
|
||||
|
||||
virtual WidgetEvent* Duplicate() const override
|
||||
{
|
||||
MOZ_ASSERT(mClass == eWheelEventClass,
|
||||
"Duplicate() must be overridden by sub class");
|
||||
// Not copying widget, it is a weak reference.
|
||||
WidgetWheelEvent* result = new WidgetWheelEvent(false, mMessage, nullptr);
|
||||
result->AssignWheelEventData(*this, true);
|
||||
result->mFlags = mFlags;
|
||||
return result;
|
||||
}
|
||||
|
||||
// On OS X, scroll gestures that start at the edge of the scrollable range
|
||||
// can result in a swipe gesture. For the first wheel event of such a
|
||||
// gesture, call TriggersSwipe() after the event has been processed
|
||||
// in order to find out whether a swipe should be started.
|
||||
bool TriggersSwipe() const
|
||||
{
|
||||
return mCanTriggerSwipe && mViewPortIsOverscrolled &&
|
||||
this->mOverflowDeltaX != 0.0;
|
||||
}
|
||||
|
||||
// NOTE: mDeltaX, mDeltaY and mDeltaZ may be customized by
|
||||
// mousewheel.*.delta_multiplier_* prefs which are applied by
|
||||
// EventStateManager. So, after widget dispatches this event,
|
||||
// these delta values may have different values than before.
|
||||
double mDeltaX;
|
||||
double mDeltaY;
|
||||
double mDeltaZ;
|
||||
|
||||
// overflowed delta values for scroll, these values are set by
|
||||
// nsEventStateManger. If the default action of the wheel event isn't scroll,
|
||||
// these values always zero. Otherwise, remaning delta values which are
|
||||
// not used by scroll are set.
|
||||
// NOTE: mDeltaX, mDeltaY and mDeltaZ may be modified by EventStateManager.
|
||||
// However, mOverflowDeltaX and mOverflowDeltaY indicate unused original
|
||||
// delta values which are not applied the delta_multiplier prefs.
|
||||
// So, if widget wanted to know the actual direction to be scrolled,
|
||||
// it would need to check the mDeltaX and mDeltaY.
|
||||
double mOverflowDeltaX;
|
||||
double mOverflowDeltaY;
|
||||
|
||||
// Should be one of nsIDOMWheelEvent::DOM_DELTA_*
|
||||
uint32_t mDeltaMode;
|
||||
|
||||
// If widget sets mLineOrPageDelta, EventStateManager will dispatch
|
||||
// eLegacyMouseLineOrPageScroll event for compatibility. Note that the delta
|
||||
// value means pages if the mDeltaMode is DOM_DELTA_PAGE, otherwise, lines.
|
||||
int32_t mLineOrPageDeltaX;
|
||||
int32_t mLineOrPageDeltaY;
|
||||
|
||||
// When the default action for an wheel event is moving history or zooming,
|
||||
// need to chose a delta value for doing it.
|
||||
int32_t GetPreferredIntDelta()
|
||||
{
|
||||
if (!mLineOrPageDeltaX && !mLineOrPageDeltaY) {
|
||||
return 0;
|
||||
}
|
||||
if (mLineOrPageDeltaY && !mLineOrPageDeltaX) {
|
||||
return mLineOrPageDeltaY;
|
||||
}
|
||||
if (mLineOrPageDeltaX && !mLineOrPageDeltaY) {
|
||||
return mLineOrPageDeltaX;
|
||||
}
|
||||
if ((mLineOrPageDeltaX < 0 && mLineOrPageDeltaY > 0) ||
|
||||
(mLineOrPageDeltaX > 0 && mLineOrPageDeltaY < 0)) {
|
||||
return 0; // We cannot guess the answer in this case.
|
||||
}
|
||||
return (Abs(mLineOrPageDeltaX) > Abs(mLineOrPageDeltaY)) ?
|
||||
mLineOrPageDeltaX : mLineOrPageDeltaY;
|
||||
}
|
||||
|
||||
// Scroll type
|
||||
// The default value is SCROLL_DEFAULT, which means EventStateManager will
|
||||
// select preferred scroll type automatically.
|
||||
enum ScrollType : uint8_t
|
||||
{
|
||||
SCROLL_DEFAULT,
|
||||
SCROLL_SYNCHRONOUSLY,
|
||||
SCROLL_ASYNCHRONOUSELY,
|
||||
SCROLL_SMOOTHLY
|
||||
};
|
||||
ScrollType mScrollType;
|
||||
|
||||
// If the delta values are computed from prefs, this value is true.
|
||||
// Otherwise, i.e., they are computed from native events, false.
|
||||
bool mCustomizedByUserPrefs;
|
||||
|
||||
// true if the momentum events directly tied to this event may follow it.
|
||||
bool mMayHaveMomentum;
|
||||
// true if the event is caused by momentum.
|
||||
bool mIsMomentum;
|
||||
|
||||
// If device event handlers don't know when they should set mLineOrPageDeltaX
|
||||
// and mLineOrPageDeltaY, this is true. Otherwise, false.
|
||||
// If mIsNoLineOrPageDelta is true, ESM will generate
|
||||
// eLegacyMouseLineOrPageScroll events when accumulated delta values reach
|
||||
// a line height.
|
||||
bool mIsNoLineOrPageDelta;
|
||||
|
||||
// Whether or not the parent of the currently overscrolled frame is the
|
||||
// ViewPort. This is false in situations when an element on the page is being
|
||||
// overscrolled (such as a text field), but true when the 'page' is being
|
||||
// overscrolled.
|
||||
bool mViewPortIsOverscrolled;
|
||||
|
||||
// The wheel event can trigger a swipe to start if it's overscrolling the
|
||||
// viewport.
|
||||
bool mCanTriggerSwipe;
|
||||
|
||||
// If mAllowToOverrideSystemScrollSpeed is true, the scroll speed may be
|
||||
// overridden. Otherwise, the scroll speed won't be overridden even if
|
||||
// it's enabled by the pref.
|
||||
bool mAllowToOverrideSystemScrollSpeed;
|
||||
|
||||
void AssignWheelEventData(const WidgetWheelEvent& aEvent, bool aCopyTargets)
|
||||
{
|
||||
AssignMouseEventBaseData(aEvent, aCopyTargets);
|
||||
|
||||
mDeltaX = aEvent.mDeltaX;
|
||||
mDeltaY = aEvent.mDeltaY;
|
||||
mDeltaZ = aEvent.mDeltaZ;
|
||||
mDeltaMode = aEvent.mDeltaMode;
|
||||
mCustomizedByUserPrefs = aEvent.mCustomizedByUserPrefs;
|
||||
mMayHaveMomentum = aEvent.mMayHaveMomentum;
|
||||
mIsMomentum = aEvent.mIsMomentum;
|
||||
mIsNoLineOrPageDelta = aEvent.mIsNoLineOrPageDelta;
|
||||
mLineOrPageDeltaX = aEvent.mLineOrPageDeltaX;
|
||||
mLineOrPageDeltaY = aEvent.mLineOrPageDeltaY;
|
||||
mScrollType = aEvent.mScrollType;
|
||||
mOverflowDeltaX = aEvent.mOverflowDeltaX;
|
||||
mOverflowDeltaY = aEvent.mOverflowDeltaY;
|
||||
mViewPortIsOverscrolled = aEvent.mViewPortIsOverscrolled;
|
||||
mCanTriggerSwipe = aEvent.mCanTriggerSwipe;
|
||||
mAllowToOverrideSystemScrollSpeed =
|
||||
aEvent.mAllowToOverrideSystemScrollSpeed;
|
||||
}
|
||||
|
||||
// System scroll speed settings may be too slow at using Gecko. In such
|
||||
// case, we should override the scroll speed computed with system settings.
|
||||
// Following methods return preferred delta values which are multiplied by
|
||||
// factors specified by prefs. If system scroll speed shouldn't be
|
||||
// overridden (e.g., this feature is disabled by pref), they return raw
|
||||
// delta values.
|
||||
double OverriddenDeltaX() const;
|
||||
double OverriddenDeltaY() const;
|
||||
|
||||
// Compute the overridden delta value. This may be useful for suppressing
|
||||
// too fast scroll by system scroll speed overriding when widget sets
|
||||
// mAllowToOverrideSystemScrollSpeed.
|
||||
static double ComputeOverriddenDelta(double aDelta, bool aIsForVertical);
|
||||
|
||||
private:
|
||||
static bool sInitialized;
|
||||
static bool sIsSystemScrollSpeedOverrideEnabled;
|
||||
static int32_t sOverrideFactorX;
|
||||
static int32_t sOverrideFactorY;
|
||||
static void Initialize();
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::WidgetPointerEvent
|
||||
******************************************************************************/
|
||||
|
||||
class WidgetPointerEvent : public WidgetMouseEvent
|
||||
{
|
||||
friend class mozilla::dom::PBrowserParent;
|
||||
friend class mozilla::dom::PBrowserChild;
|
||||
|
||||
WidgetPointerEvent()
|
||||
: mWidth(1)
|
||||
, mHeight(1)
|
||||
, mIsPrimary(true)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual WidgetPointerEvent* AsPointerEvent() override { return this; }
|
||||
|
||||
WidgetPointerEvent(bool aIsTrusted, EventMessage aMsg, nsIWidget* w)
|
||||
: WidgetMouseEvent(aIsTrusted, aMsg, w, ePointerEventClass, eReal)
|
||||
, mWidth(1)
|
||||
, mHeight(1)
|
||||
, mIsPrimary(true)
|
||||
{
|
||||
}
|
||||
|
||||
explicit WidgetPointerEvent(const WidgetMouseEvent& aEvent)
|
||||
: WidgetMouseEvent(aEvent)
|
||||
, mWidth(1)
|
||||
, mHeight(1)
|
||||
, mIsPrimary(true)
|
||||
{
|
||||
mClass = ePointerEventClass;
|
||||
}
|
||||
|
||||
virtual WidgetEvent* Duplicate() const override
|
||||
{
|
||||
MOZ_ASSERT(mClass == ePointerEventClass,
|
||||
"Duplicate() must be overridden by sub class");
|
||||
// Not copying widget, it is a weak reference.
|
||||
WidgetPointerEvent* result =
|
||||
new WidgetPointerEvent(false, mMessage, nullptr);
|
||||
result->AssignPointerEventData(*this, true);
|
||||
result->mFlags = mFlags;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t mWidth;
|
||||
uint32_t mHeight;
|
||||
bool mIsPrimary;
|
||||
|
||||
// XXX Not tested by test_assign_event_data.html
|
||||
void AssignPointerEventData(const WidgetPointerEvent& aEvent,
|
||||
bool aCopyTargets)
|
||||
{
|
||||
AssignMouseEventData(aEvent, aCopyTargets);
|
||||
|
||||
mWidth = aEvent.mWidth;
|
||||
mHeight = aEvent.mHeight;
|
||||
mIsPrimary = aEvent.mIsPrimary;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_MouseEvents_h__
|
||||
821
widget/NativeKeyToDOMCodeName.h
Normal file
821
widget/NativeKeyToDOMCodeName.h
Normal file
|
|
@ -0,0 +1,821 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
/**
|
||||
* This header file defines simple code mapping between native scancode or
|
||||
* something and DOM code name index.
|
||||
* You must define NS_NATIVE_KEY_TO_DOM_CODE_NAME_INDEX macro before include
|
||||
* this.
|
||||
*
|
||||
* It must have two arguments, (aNativeKey, aCodeNameIndex).
|
||||
* aNativeKey is a scancode value or something (depends on the platform).
|
||||
* aCodeNameIndex is the widget::CodeNameIndex value.
|
||||
*/
|
||||
|
||||
// Windows
|
||||
#define CODE_MAP_WIN(aCPPCodeName, aNativeKey)
|
||||
// Mac OS X
|
||||
#define CODE_MAP_MAC(aCPPCodeName, aNativeKey)
|
||||
// GTK and Qt on Linux
|
||||
#define CODE_MAP_X11(aCPPCodeName, aNativeKey)
|
||||
// Android and Gonk
|
||||
#define CODE_MAP_ANDROID(aCPPCodeName, aNativeKey)
|
||||
|
||||
#if defined(XP_WIN)
|
||||
#undef CODE_MAP_WIN
|
||||
// aNativeKey is scan code
|
||||
#define CODE_MAP_WIN(aCPPCodeName, aNativeKey) \
|
||||
NS_NATIVE_KEY_TO_DOM_CODE_NAME_INDEX(aNativeKey, \
|
||||
CODE_NAME_INDEX_##aCPPCodeName)
|
||||
#elif defined(XP_MACOSX)
|
||||
#undef CODE_MAP_MAC
|
||||
// aNativeKey is key code starting with kVK_.
|
||||
#define CODE_MAP_MAC(aCPPCodeName, aNativeKey) \
|
||||
NS_NATIVE_KEY_TO_DOM_CODE_NAME_INDEX(aNativeKey, \
|
||||
CODE_NAME_INDEX_##aCPPCodeName)
|
||||
#elif defined(MOZ_WIDGET_GTK)
|
||||
#undef CODE_MAP_X11
|
||||
// aNativeKey is hardware_keycode of GDKEvent or nativeScanCode of QKeyEvent.
|
||||
#define CODE_MAP_X11(aCPPCodeName, aNativeKey) \
|
||||
NS_NATIVE_KEY_TO_DOM_CODE_NAME_INDEX(aNativeKey, \
|
||||
CODE_NAME_INDEX_##aCPPCodeName)
|
||||
#elif defined(ANDROID)
|
||||
#undef CODE_MAP_ANDROID
|
||||
// aNativeKey is scan code
|
||||
#define CODE_MAP_ANDROID(aCPPCodeName, aNativeKey) \
|
||||
NS_NATIVE_KEY_TO_DOM_CODE_NAME_INDEX(aNativeKey, \
|
||||
CODE_NAME_INDEX_##aCPPCodeName)
|
||||
#endif
|
||||
|
||||
// Writing system keys
|
||||
CODE_MAP_WIN(Backquote, 0x0029)
|
||||
CODE_MAP_MAC(Backquote, kVK_ANSI_Grave)
|
||||
CODE_MAP_X11(Backquote, 0x0031)
|
||||
CODE_MAP_ANDROID(Backquote, 0x0029)
|
||||
|
||||
CODE_MAP_WIN(Backslash, 0x002B)
|
||||
CODE_MAP_MAC(Backslash, kVK_ANSI_Backslash)
|
||||
CODE_MAP_X11(Backslash, 0x0033)
|
||||
CODE_MAP_ANDROID(Backslash, 0x002B)
|
||||
|
||||
CODE_MAP_WIN(Backspace, 0x000E)
|
||||
CODE_MAP_MAC(Backspace, kVK_Delete)
|
||||
CODE_MAP_X11(Backspace, 0x0016)
|
||||
CODE_MAP_ANDROID(Backspace, 0x000E)
|
||||
|
||||
CODE_MAP_WIN(BracketLeft, 0x001A)
|
||||
CODE_MAP_MAC(BracketLeft, kVK_ANSI_LeftBracket)
|
||||
CODE_MAP_X11(BracketLeft, 0x0022)
|
||||
CODE_MAP_ANDROID(BracketLeft, 0x001A)
|
||||
|
||||
CODE_MAP_WIN(BracketRight, 0x001B)
|
||||
CODE_MAP_MAC(BracketRight, kVK_ANSI_RightBracket)
|
||||
CODE_MAP_X11(BracketRight, 0x0023)
|
||||
CODE_MAP_ANDROID(BracketRight, 0x001B)
|
||||
|
||||
CODE_MAP_WIN(Comma, 0x0033)
|
||||
CODE_MAP_MAC(Comma, kVK_ANSI_Comma)
|
||||
CODE_MAP_X11(Comma, 0x003B)
|
||||
CODE_MAP_ANDROID(Comma, 0x00033)
|
||||
|
||||
CODE_MAP_WIN(Digit0, 0x000B)
|
||||
CODE_MAP_MAC(Digit0, kVK_ANSI_0)
|
||||
CODE_MAP_X11(Digit0, 0x0013)
|
||||
CODE_MAP_ANDROID(Digit0, 0x000B)
|
||||
|
||||
CODE_MAP_WIN(Digit1, 0x0002)
|
||||
CODE_MAP_MAC(Digit1, kVK_ANSI_1)
|
||||
CODE_MAP_X11(Digit1, 0x000A)
|
||||
CODE_MAP_ANDROID(Digit1, 0x0002)
|
||||
|
||||
CODE_MAP_WIN(Digit2, 0x0003)
|
||||
CODE_MAP_MAC(Digit2, kVK_ANSI_2)
|
||||
CODE_MAP_X11(Digit2, 0x000B)
|
||||
CODE_MAP_ANDROID(Digit2, 0x0003)
|
||||
|
||||
CODE_MAP_WIN(Digit3, 0x0004)
|
||||
CODE_MAP_MAC(Digit3, kVK_ANSI_3)
|
||||
CODE_MAP_X11(Digit3, 0x000C)
|
||||
CODE_MAP_ANDROID(Digit3, 0x0004)
|
||||
|
||||
CODE_MAP_WIN(Digit4, 0x0005)
|
||||
CODE_MAP_MAC(Digit4, kVK_ANSI_4)
|
||||
CODE_MAP_X11(Digit4, 0x000D)
|
||||
CODE_MAP_ANDROID(Digit4, 0x0005)
|
||||
|
||||
CODE_MAP_WIN(Digit5, 0x0006)
|
||||
CODE_MAP_MAC(Digit5, kVK_ANSI_5)
|
||||
CODE_MAP_X11(Digit5, 0x000E)
|
||||
CODE_MAP_ANDROID(Digit5, 0x0006)
|
||||
|
||||
CODE_MAP_WIN(Digit6, 0x0007)
|
||||
CODE_MAP_MAC(Digit6, kVK_ANSI_6)
|
||||
CODE_MAP_X11(Digit6, 0x000F)
|
||||
CODE_MAP_ANDROID(Digit6, 0x0007)
|
||||
|
||||
CODE_MAP_WIN(Digit7, 0x0008)
|
||||
CODE_MAP_MAC(Digit7, kVK_ANSI_7)
|
||||
CODE_MAP_X11(Digit7, 0x0010)
|
||||
CODE_MAP_ANDROID(Digit7, 0x0008)
|
||||
|
||||
CODE_MAP_WIN(Digit8, 0x0009)
|
||||
CODE_MAP_MAC(Digit8, kVK_ANSI_8)
|
||||
CODE_MAP_X11(Digit8, 0x0011)
|
||||
CODE_MAP_ANDROID(Digit8, 0x0009)
|
||||
|
||||
CODE_MAP_WIN(Digit9, 0x000A)
|
||||
CODE_MAP_MAC(Digit9, kVK_ANSI_9)
|
||||
CODE_MAP_X11(Digit9, 0x0012)
|
||||
CODE_MAP_ANDROID(Digit9, 0x000A)
|
||||
|
||||
CODE_MAP_WIN(Equal, 0x000D)
|
||||
CODE_MAP_MAC(Equal, kVK_ANSI_Equal)
|
||||
CODE_MAP_X11(Equal, 0x0015)
|
||||
CODE_MAP_ANDROID(Equal, 0x000D)
|
||||
|
||||
CODE_MAP_WIN(IntlBackslash, 0x0056)
|
||||
CODE_MAP_MAC(IntlBackslash, kVK_ISO_Section)
|
||||
CODE_MAP_X11(IntlBackslash, 0x005E)
|
||||
CODE_MAP_ANDROID(IntlBackslash, 0x0056)
|
||||
|
||||
// Win: IntlHash's scan code is shared with "Backslash" key.
|
||||
// Mac: IntlHash's virtual key code is shared with "Backslash" key.
|
||||
// X11: IntlHash's scan code is shared with "Backslash" key.
|
||||
// Android: IntlHash's scan code is shared with "Backslash" key.
|
||||
|
||||
CODE_MAP_WIN(IntlRo, 0x0073)
|
||||
CODE_MAP_MAC(IntlRo, kVK_JIS_Underscore)
|
||||
CODE_MAP_X11(IntlRo, 0x0061)
|
||||
CODE_MAP_ANDROID(IntlRo, 0x0059)
|
||||
|
||||
CODE_MAP_WIN(IntlYen, 0x007D)
|
||||
CODE_MAP_MAC(IntlYen, kVK_JIS_Yen)
|
||||
CODE_MAP_X11(IntlYen, 0x0084)
|
||||
CODE_MAP_ANDROID(IntlYen, 0x007C)
|
||||
|
||||
CODE_MAP_WIN(KeyA, 0x001E)
|
||||
CODE_MAP_MAC(KeyA, kVK_ANSI_A)
|
||||
CODE_MAP_X11(KeyA, 0x0026)
|
||||
CODE_MAP_ANDROID(KeyA, 0x001E)
|
||||
|
||||
CODE_MAP_WIN(KeyB, 0x0030)
|
||||
CODE_MAP_MAC(KeyB, kVK_ANSI_B)
|
||||
CODE_MAP_X11(KeyB, 0x0038)
|
||||
CODE_MAP_ANDROID(KeyB, 0x0030)
|
||||
|
||||
CODE_MAP_WIN(KeyC, 0x002E)
|
||||
CODE_MAP_MAC(KeyC, kVK_ANSI_C)
|
||||
CODE_MAP_X11(KeyC, 0x0036)
|
||||
CODE_MAP_ANDROID(KeyC, 0x002E)
|
||||
|
||||
CODE_MAP_WIN(KeyD, 0x0020)
|
||||
CODE_MAP_MAC(KeyD, kVK_ANSI_D)
|
||||
CODE_MAP_X11(KeyD, 0x0028)
|
||||
CODE_MAP_ANDROID(KeyD, 0x0020)
|
||||
|
||||
CODE_MAP_WIN(KeyE, 0x0012)
|
||||
CODE_MAP_MAC(KeyE, kVK_ANSI_E)
|
||||
CODE_MAP_X11(KeyE, 0x001A)
|
||||
CODE_MAP_ANDROID(KeyE, 0x0012)
|
||||
|
||||
CODE_MAP_WIN(KeyF, 0x0021)
|
||||
CODE_MAP_MAC(KeyF, kVK_ANSI_F)
|
||||
CODE_MAP_X11(KeyF, 0x0029)
|
||||
CODE_MAP_ANDROID(KeyF, 0x0021)
|
||||
|
||||
CODE_MAP_WIN(KeyG, 0x0022)
|
||||
CODE_MAP_MAC(KeyG, kVK_ANSI_G)
|
||||
CODE_MAP_X11(KeyG, 0x002A)
|
||||
CODE_MAP_ANDROID(KeyG, 0x0022)
|
||||
|
||||
CODE_MAP_WIN(KeyH, 0x0023)
|
||||
CODE_MAP_MAC(KeyH, kVK_ANSI_H)
|
||||
CODE_MAP_X11(KeyH, 0x002B)
|
||||
CODE_MAP_ANDROID(KeyH, 0x0023)
|
||||
|
||||
CODE_MAP_WIN(KeyI, 0x0017)
|
||||
CODE_MAP_MAC(KeyI, kVK_ANSI_I)
|
||||
CODE_MAP_X11(KeyI, 0x001F)
|
||||
CODE_MAP_ANDROID(KeyI, 0x0017)
|
||||
|
||||
CODE_MAP_WIN(KeyJ, 0x0024)
|
||||
CODE_MAP_MAC(KeyJ, kVK_ANSI_J)
|
||||
CODE_MAP_X11(KeyJ, 0x002C)
|
||||
CODE_MAP_ANDROID(KeyJ, 0x0024)
|
||||
|
||||
CODE_MAP_WIN(KeyK, 0x0025)
|
||||
CODE_MAP_MAC(KeyK, kVK_ANSI_K)
|
||||
CODE_MAP_X11(KeyK, 0x002D)
|
||||
CODE_MAP_ANDROID(KeyK, 0x0025)
|
||||
|
||||
CODE_MAP_WIN(KeyL, 0x0026)
|
||||
CODE_MAP_MAC(KeyL, kVK_ANSI_L)
|
||||
CODE_MAP_X11(KeyL, 0x002E)
|
||||
CODE_MAP_ANDROID(KeyL, 0x0026)
|
||||
|
||||
CODE_MAP_WIN(KeyM, 0x0032)
|
||||
CODE_MAP_MAC(KeyM, kVK_ANSI_M)
|
||||
CODE_MAP_X11(KeyM, 0x003A)
|
||||
CODE_MAP_ANDROID(KeyM, 0x0032)
|
||||
|
||||
CODE_MAP_WIN(KeyN, 0x0031)
|
||||
CODE_MAP_MAC(KeyN, kVK_ANSI_N)
|
||||
CODE_MAP_X11(KeyN, 0x0039)
|
||||
CODE_MAP_ANDROID(KeyN, 0x0031)
|
||||
|
||||
CODE_MAP_WIN(KeyO, 0x0018)
|
||||
CODE_MAP_MAC(KeyO, kVK_ANSI_O)
|
||||
CODE_MAP_X11(KeyO, 0x0020)
|
||||
CODE_MAP_ANDROID(KeyO, 0x0018)
|
||||
|
||||
CODE_MAP_WIN(KeyP, 0x0019)
|
||||
CODE_MAP_MAC(KeyP, kVK_ANSI_P)
|
||||
CODE_MAP_X11(KeyP, 0x0021)
|
||||
CODE_MAP_ANDROID(KeyP, 0x0019)
|
||||
|
||||
CODE_MAP_WIN(KeyQ, 0x0010)
|
||||
CODE_MAP_MAC(KeyQ, kVK_ANSI_Q)
|
||||
CODE_MAP_X11(KeyQ, 0x0018)
|
||||
CODE_MAP_ANDROID(KeyQ, 0x0010)
|
||||
|
||||
CODE_MAP_WIN(KeyR, 0x0013)
|
||||
CODE_MAP_MAC(KeyR, kVK_ANSI_R)
|
||||
CODE_MAP_X11(KeyR, 0x001B)
|
||||
CODE_MAP_ANDROID(KeyR, 0x0013)
|
||||
|
||||
CODE_MAP_WIN(KeyS, 0x001F)
|
||||
CODE_MAP_MAC(KeyS, kVK_ANSI_S)
|
||||
CODE_MAP_X11(KeyS, 0x0027)
|
||||
CODE_MAP_ANDROID(KeyS, 0x001F)
|
||||
|
||||
CODE_MAP_WIN(KeyT, 0x0014)
|
||||
CODE_MAP_MAC(KeyT, kVK_ANSI_T)
|
||||
CODE_MAP_X11(KeyT, 0x001C)
|
||||
CODE_MAP_ANDROID(KeyT, 0x0014)
|
||||
|
||||
CODE_MAP_WIN(KeyU, 0x0016)
|
||||
CODE_MAP_MAC(KeyU, kVK_ANSI_U)
|
||||
CODE_MAP_X11(KeyU, 0x001E)
|
||||
CODE_MAP_ANDROID(KeyU, 0x0016)
|
||||
|
||||
CODE_MAP_WIN(KeyV, 0x002F)
|
||||
CODE_MAP_MAC(KeyV, kVK_ANSI_V)
|
||||
CODE_MAP_X11(KeyV, 0x0037)
|
||||
CODE_MAP_ANDROID(KeyV, 0x002F)
|
||||
|
||||
CODE_MAP_WIN(KeyW, 0x0011)
|
||||
CODE_MAP_MAC(KeyW, kVK_ANSI_W)
|
||||
CODE_MAP_X11(KeyW, 0x0019)
|
||||
CODE_MAP_ANDROID(KeyW, 0x0011)
|
||||
|
||||
CODE_MAP_WIN(KeyX, 0x002D)
|
||||
CODE_MAP_MAC(KeyX, kVK_ANSI_X)
|
||||
CODE_MAP_X11(KeyX, 0x0035)
|
||||
CODE_MAP_ANDROID(KeyX, 0x002D)
|
||||
|
||||
CODE_MAP_WIN(KeyY, 0x0015)
|
||||
CODE_MAP_MAC(KeyY, kVK_ANSI_Y)
|
||||
CODE_MAP_X11(KeyY, 0x001D)
|
||||
CODE_MAP_ANDROID(KeyY, 0x0015)
|
||||
|
||||
CODE_MAP_WIN(KeyZ, 0x002C)
|
||||
CODE_MAP_MAC(KeyZ, kVK_ANSI_Z)
|
||||
CODE_MAP_X11(KeyZ, 0x0034)
|
||||
CODE_MAP_ANDROID(KeyZ, 0x002C)
|
||||
|
||||
CODE_MAP_WIN(Minus, 0x000C)
|
||||
CODE_MAP_MAC(Minus, kVK_ANSI_Minus)
|
||||
CODE_MAP_X11(Minus, 0x0014)
|
||||
CODE_MAP_ANDROID(Minus, 0x000C)
|
||||
|
||||
CODE_MAP_WIN(Period, 0x0034)
|
||||
CODE_MAP_MAC(Period, kVK_ANSI_Period)
|
||||
CODE_MAP_X11(Period, 0x003C)
|
||||
CODE_MAP_ANDROID(Period, 0x0034)
|
||||
|
||||
CODE_MAP_WIN(Quote, 0x0028)
|
||||
CODE_MAP_MAC(Quote, kVK_ANSI_Quote)
|
||||
CODE_MAP_X11(Quote, 0x0030)
|
||||
CODE_MAP_ANDROID(Quote, 0x0028)
|
||||
|
||||
CODE_MAP_WIN(Semicolon, 0x0027)
|
||||
CODE_MAP_MAC(Semicolon, kVK_ANSI_Semicolon)
|
||||
CODE_MAP_X11(Semicolon, 0x002F)
|
||||
CODE_MAP_ANDROID(Semicolon, 0x0027)
|
||||
|
||||
CODE_MAP_WIN(Slash, 0x0035)
|
||||
CODE_MAP_MAC(Slash, kVK_ANSI_Slash)
|
||||
CODE_MAP_X11(Slash, 0x003D)
|
||||
CODE_MAP_ANDROID(Slash, 0x0035)
|
||||
|
||||
// Functional keys
|
||||
CODE_MAP_WIN(AltLeft, 0x0038)
|
||||
CODE_MAP_MAC(AltLeft, kVK_Option)
|
||||
CODE_MAP_X11(AltLeft, 0x0040)
|
||||
CODE_MAP_ANDROID(AltLeft, 0x0038)
|
||||
|
||||
CODE_MAP_WIN(AltRight, 0xE038)
|
||||
CODE_MAP_MAC(AltRight, kVK_RightOption)
|
||||
CODE_MAP_X11(AltRight, 0x006C)
|
||||
CODE_MAP_ANDROID(AltRight, 0x0064)
|
||||
|
||||
CODE_MAP_WIN(CapsLock, 0x003A)
|
||||
CODE_MAP_MAC(CapsLock, kVK_CapsLock)
|
||||
CODE_MAP_X11(CapsLock, 0x0042)
|
||||
CODE_MAP_ANDROID(CapsLock, 0x003A)
|
||||
|
||||
CODE_MAP_WIN(ContextMenu, 0xE05D)
|
||||
CODE_MAP_MAC(ContextMenu, kVK_PC_ContextMenu)
|
||||
CODE_MAP_X11(ContextMenu, 0x0087)
|
||||
CODE_MAP_ANDROID(ContextMenu, 0x007F)
|
||||
|
||||
CODE_MAP_WIN(ControlLeft, 0x001D)
|
||||
CODE_MAP_MAC(ControlLeft, kVK_Control)
|
||||
CODE_MAP_X11(ControlLeft, 0x0025)
|
||||
CODE_MAP_ANDROID(ControlLeft, 0x001D)
|
||||
|
||||
CODE_MAP_WIN(ControlRight, 0xE01D)
|
||||
CODE_MAP_MAC(ControlRight, kVK_RightControl)
|
||||
CODE_MAP_X11(ControlRight, 0x0069)
|
||||
CODE_MAP_ANDROID(ControlRight, 0x0061)
|
||||
|
||||
CODE_MAP_WIN(Enter, 0x001C)
|
||||
CODE_MAP_MAC(Enter, kVK_Return)
|
||||
CODE_MAP_X11(Enter, 0x0024)
|
||||
CODE_MAP_ANDROID(Enter, 0x001C)
|
||||
|
||||
CODE_MAP_WIN(OSLeft, 0xE05B)
|
||||
CODE_MAP_MAC(OSLeft, kVK_Command)
|
||||
CODE_MAP_X11(OSLeft, 0x0085)
|
||||
CODE_MAP_ANDROID(OSLeft, 0x007D)
|
||||
|
||||
CODE_MAP_WIN(OSRight, 0xE05C)
|
||||
CODE_MAP_MAC(OSRight, kVK_RightCommand)
|
||||
CODE_MAP_X11(OSRight, 0x0086)
|
||||
CODE_MAP_ANDROID(OSRight, 0x007E)
|
||||
|
||||
CODE_MAP_WIN(ShiftLeft, 0x002A)
|
||||
CODE_MAP_MAC(ShiftLeft, kVK_Shift)
|
||||
CODE_MAP_X11(ShiftLeft, 0x0032)
|
||||
CODE_MAP_ANDROID(ShiftLeft, 0x002A)
|
||||
|
||||
CODE_MAP_WIN(ShiftRight, 0x0036)
|
||||
CODE_MAP_MAC(ShiftRight, kVK_RightShift)
|
||||
CODE_MAP_X11(ShiftRight, 0x003E)
|
||||
CODE_MAP_ANDROID(ShiftRight, 0x0036)
|
||||
|
||||
CODE_MAP_WIN(Space, 0x0039)
|
||||
CODE_MAP_MAC(Space, kVK_Space)
|
||||
CODE_MAP_X11(Space, 0x0041)
|
||||
CODE_MAP_ANDROID(Space, 0x0039)
|
||||
|
||||
CODE_MAP_WIN(Tab, 0x000F)
|
||||
CODE_MAP_MAC(Tab, kVK_Tab)
|
||||
CODE_MAP_X11(Tab, 0x0017)
|
||||
CODE_MAP_ANDROID(Tab, 0x000F)
|
||||
|
||||
// IME keys
|
||||
CODE_MAP_WIN(Convert, 0x0079)
|
||||
CODE_MAP_X11(Convert, 0x0064)
|
||||
CODE_MAP_ANDROID(Convert, 0x005C)
|
||||
|
||||
CODE_MAP_WIN(Lang1, 0x0072) // for non-Korean layout
|
||||
CODE_MAP_WIN(Lang1, 0xE0F2) // for Korean layout
|
||||
CODE_MAP_MAC(Lang1, kVK_JIS_Kana)
|
||||
CODE_MAP_X11(Lang1, 0x0082)
|
||||
CODE_MAP_ANDROID(Lang1, 0x007A)
|
||||
|
||||
CODE_MAP_WIN(Lang2, 0x0071) // for non-Korean layout
|
||||
CODE_MAP_WIN(Lang2, 0xE0F1) // for Korean layout
|
||||
CODE_MAP_MAC(Lang2, kVK_JIS_Eisu)
|
||||
CODE_MAP_X11(Lang2, 0x0083)
|
||||
CODE_MAP_ANDROID(Lang2, 0x007B)
|
||||
|
||||
CODE_MAP_WIN(KanaMode, 0x0070)
|
||||
CODE_MAP_X11(KanaMode, 0x0065)
|
||||
CODE_MAP_ANDROID(KanaMode, 0x005D)
|
||||
|
||||
CODE_MAP_WIN(NonConvert, 0x007B)
|
||||
CODE_MAP_X11(NonConvert, 0x0066)
|
||||
CODE_MAP_ANDROID(NonConvert, 0x005E)
|
||||
|
||||
// Control pad section
|
||||
CODE_MAP_WIN(Delete, 0xE053)
|
||||
CODE_MAP_MAC(Delete, kVK_ForwardDelete)
|
||||
CODE_MAP_X11(Delete, 0x0077)
|
||||
CODE_MAP_ANDROID(Delete, 0x006F)
|
||||
|
||||
CODE_MAP_WIN(End, 0xE04F)
|
||||
CODE_MAP_MAC(End, kVK_End)
|
||||
CODE_MAP_X11(End, 0x0073)
|
||||
CODE_MAP_ANDROID(End, 0x006B)
|
||||
|
||||
CODE_MAP_MAC(Help, kVK_Help) // Insert key on PC keyboard
|
||||
CODE_MAP_X11(Help, 0x0092) // Help key on Sun keyboard
|
||||
CODE_MAP_ANDROID(Help, 0x008A) // Help key on Sun keyboard
|
||||
|
||||
CODE_MAP_WIN(Home, 0xE047)
|
||||
CODE_MAP_MAC(Home, kVK_Home)
|
||||
CODE_MAP_X11(Home, 0x006E)
|
||||
CODE_MAP_ANDROID(Home, 0x0066)
|
||||
|
||||
CODE_MAP_WIN(Insert, 0xE052)
|
||||
CODE_MAP_X11(Insert, 0x0076)
|
||||
CODE_MAP_ANDROID(Insert, 0x006E)
|
||||
|
||||
CODE_MAP_WIN(PageDown, 0xE051)
|
||||
CODE_MAP_MAC(PageDown, kVK_PageDown)
|
||||
CODE_MAP_X11(PageDown, 0x0075)
|
||||
CODE_MAP_ANDROID(PageDown, 0x006D)
|
||||
|
||||
CODE_MAP_WIN(PageUp, 0xE049)
|
||||
CODE_MAP_MAC(PageUp, kVK_PageUp)
|
||||
CODE_MAP_X11(PageUp, 0x0070)
|
||||
CODE_MAP_ANDROID(PageUp, 0x0068)
|
||||
|
||||
// Arrow pad section
|
||||
CODE_MAP_WIN(ArrowDown, 0xE050)
|
||||
CODE_MAP_MAC(ArrowDown, kVK_DownArrow)
|
||||
CODE_MAP_X11(ArrowDown, 0x0074)
|
||||
CODE_MAP_ANDROID(ArrowDown, 0x006C)
|
||||
|
||||
CODE_MAP_WIN(ArrowLeft, 0xE04B)
|
||||
CODE_MAP_MAC(ArrowLeft, kVK_LeftArrow)
|
||||
CODE_MAP_X11(ArrowLeft, 0x0071)
|
||||
CODE_MAP_ANDROID(ArrowLeft, 0x0069)
|
||||
|
||||
CODE_MAP_WIN(ArrowRight, 0xE04D)
|
||||
CODE_MAP_MAC(ArrowRight, kVK_RightArrow)
|
||||
CODE_MAP_X11(ArrowRight, 0x0072)
|
||||
CODE_MAP_ANDROID(ArrowRight, 0x006A)
|
||||
|
||||
CODE_MAP_WIN(ArrowUp, 0xE048)
|
||||
CODE_MAP_MAC(ArrowUp, kVK_UpArrow)
|
||||
CODE_MAP_X11(ArrowUp, 0x006F)
|
||||
CODE_MAP_ANDROID(ArrowUp, 0x0067)
|
||||
|
||||
// Numpad section
|
||||
CODE_MAP_WIN(NumLock, 0xE045) // MSDN says 0x0045, though...
|
||||
CODE_MAP_MAC(NumLock, kVK_ANSI_KeypadClear)
|
||||
CODE_MAP_X11(NumLock, 0x004D)
|
||||
CODE_MAP_ANDROID(NumLock, 0x0045)
|
||||
|
||||
CODE_MAP_WIN(Numpad0, 0x0052)
|
||||
CODE_MAP_MAC(Numpad0, kVK_ANSI_Keypad0)
|
||||
CODE_MAP_X11(Numpad0, 0x005A)
|
||||
CODE_MAP_ANDROID(Numpad0, 0x0052)
|
||||
|
||||
CODE_MAP_WIN(Numpad1, 0x004F)
|
||||
CODE_MAP_MAC(Numpad1, kVK_ANSI_Keypad1)
|
||||
CODE_MAP_X11(Numpad1, 0x0057)
|
||||
CODE_MAP_ANDROID(Numpad1, 0x004F)
|
||||
|
||||
CODE_MAP_WIN(Numpad2, 0x0050)
|
||||
CODE_MAP_MAC(Numpad2, kVK_ANSI_Keypad2)
|
||||
CODE_MAP_X11(Numpad2, 0x0058)
|
||||
CODE_MAP_ANDROID(Numpad2, 0x0050)
|
||||
|
||||
CODE_MAP_WIN(Numpad3, 0x0051)
|
||||
CODE_MAP_MAC(Numpad3, kVK_ANSI_Keypad3)
|
||||
CODE_MAP_X11(Numpad3, 0x0059)
|
||||
CODE_MAP_ANDROID(Numpad3, 0x0051)
|
||||
|
||||
CODE_MAP_WIN(Numpad4, 0x004B)
|
||||
CODE_MAP_MAC(Numpad4, kVK_ANSI_Keypad4)
|
||||
CODE_MAP_X11(Numpad4, 0x0053)
|
||||
CODE_MAP_ANDROID(Numpad4, 0x004B)
|
||||
|
||||
CODE_MAP_WIN(Numpad5, 0x004C)
|
||||
CODE_MAP_MAC(Numpad5, kVK_ANSI_Keypad5)
|
||||
CODE_MAP_X11(Numpad5, 0x0054)
|
||||
CODE_MAP_ANDROID(Numpad5, 0x004C)
|
||||
|
||||
CODE_MAP_WIN(Numpad6, 0x004D)
|
||||
CODE_MAP_MAC(Numpad6, kVK_ANSI_Keypad6)
|
||||
CODE_MAP_X11(Numpad6, 0x0055)
|
||||
CODE_MAP_ANDROID(Numpad6, 0x004D)
|
||||
|
||||
CODE_MAP_WIN(Numpad7, 0x0047)
|
||||
CODE_MAP_MAC(Numpad7, kVK_ANSI_Keypad7)
|
||||
CODE_MAP_X11(Numpad7, 0x004F)
|
||||
CODE_MAP_ANDROID(Numpad7, 0x0047)
|
||||
|
||||
CODE_MAP_WIN(Numpad8, 0x0048)
|
||||
CODE_MAP_MAC(Numpad8, kVK_ANSI_Keypad8)
|
||||
CODE_MAP_X11(Numpad8, 0x0050)
|
||||
CODE_MAP_ANDROID(Numpad8, 0x0048)
|
||||
|
||||
CODE_MAP_WIN(Numpad9, 0x0049)
|
||||
CODE_MAP_MAC(Numpad9, kVK_ANSI_Keypad9)
|
||||
CODE_MAP_X11(Numpad9, 0x0051)
|
||||
CODE_MAP_ANDROID(Numpad9, 0x0049)
|
||||
|
||||
CODE_MAP_WIN(NumpadAdd, 0x004E)
|
||||
CODE_MAP_MAC(NumpadAdd, kVK_ANSI_KeypadPlus)
|
||||
CODE_MAP_X11(NumpadAdd, 0x0056)
|
||||
CODE_MAP_ANDROID(NumpadAdd, 0x004E)
|
||||
|
||||
CODE_MAP_WIN(NumpadComma, 0x007E)
|
||||
CODE_MAP_MAC(NumpadComma, kVK_JIS_KeypadComma)
|
||||
CODE_MAP_X11(NumpadComma, 0x0081)
|
||||
CODE_MAP_ANDROID(NumpadComma, 0x0079)
|
||||
|
||||
CODE_MAP_WIN(NumpadDecimal, 0x0053)
|
||||
CODE_MAP_MAC(NumpadDecimal, kVK_ANSI_KeypadDecimal)
|
||||
CODE_MAP_X11(NumpadDecimal, 0x005B)
|
||||
CODE_MAP_ANDROID(NumpadDecimal, 0x0053)
|
||||
|
||||
CODE_MAP_WIN(NumpadDivide, 0xE035)
|
||||
CODE_MAP_MAC(NumpadDivide, kVK_ANSI_KeypadDivide)
|
||||
CODE_MAP_X11(NumpadDivide, 0x006A)
|
||||
CODE_MAP_ANDROID(NumpadDivide, 0x0062)
|
||||
|
||||
CODE_MAP_WIN(NumpadEnter, 0xE01C)
|
||||
CODE_MAP_MAC(NumpadEnter, kVK_ANSI_KeypadEnter)
|
||||
CODE_MAP_MAC(NumpadEnter, kVK_Powerbook_KeypadEnter)
|
||||
CODE_MAP_X11(NumpadEnter, 0x0068)
|
||||
CODE_MAP_ANDROID(NumpadEnter, 0x0060)
|
||||
|
||||
CODE_MAP_WIN(NumpadEqual, 0x0059)
|
||||
CODE_MAP_MAC(NumpadEqual, kVK_ANSI_KeypadEquals)
|
||||
CODE_MAP_X11(NumpadEqual, 0x007D)
|
||||
CODE_MAP_ANDROID(NumpadEqual, 0x0075)
|
||||
|
||||
CODE_MAP_WIN(NumpadMultiply, 0x0037)
|
||||
CODE_MAP_MAC(NumpadMultiply, kVK_ANSI_KeypadMultiply)
|
||||
CODE_MAP_X11(NumpadMultiply, 0x003F)
|
||||
CODE_MAP_ANDROID(NumpadMultiply, 0x0037)
|
||||
|
||||
CODE_MAP_WIN(NumpadSubtract, 0x004A)
|
||||
CODE_MAP_MAC(NumpadSubtract, kVK_ANSI_KeypadMinus)
|
||||
CODE_MAP_X11(NumpadSubtract, 0x0052)
|
||||
CODE_MAP_ANDROID(NumpadSubtract, 0x004A)
|
||||
|
||||
// Function section
|
||||
CODE_MAP_WIN(Escape, 0x0001)
|
||||
CODE_MAP_MAC(Escape, kVK_Escape)
|
||||
CODE_MAP_X11(Escape, 0x0009)
|
||||
CODE_MAP_ANDROID(Escape, 0x0001)
|
||||
|
||||
CODE_MAP_WIN(F1, 0x003B)
|
||||
CODE_MAP_MAC(F1, kVK_F1)
|
||||
CODE_MAP_X11(F1, 0x0043)
|
||||
CODE_MAP_ANDROID(F1, 0x003B)
|
||||
|
||||
CODE_MAP_WIN(F2, 0x003C)
|
||||
CODE_MAP_MAC(F2, kVK_F2)
|
||||
CODE_MAP_X11(F2, 0x0044)
|
||||
CODE_MAP_ANDROID(F2, 0x003C)
|
||||
|
||||
CODE_MAP_WIN(F3, 0x003D)
|
||||
CODE_MAP_MAC(F3, kVK_F3)
|
||||
CODE_MAP_X11(F3, 0x0045)
|
||||
CODE_MAP_ANDROID(F3, 0x003D)
|
||||
|
||||
CODE_MAP_WIN(F4, 0x003E)
|
||||
CODE_MAP_MAC(F4, kVK_F4)
|
||||
CODE_MAP_X11(F4, 0x0046)
|
||||
CODE_MAP_ANDROID(F4, 0x003E)
|
||||
|
||||
CODE_MAP_WIN(F5, 0x003F)
|
||||
CODE_MAP_MAC(F5, kVK_F5)
|
||||
CODE_MAP_X11(F5, 0x0047)
|
||||
CODE_MAP_ANDROID(F5, 0x003F)
|
||||
|
||||
CODE_MAP_WIN(F6, 0x0040)
|
||||
CODE_MAP_MAC(F6, kVK_F6)
|
||||
CODE_MAP_X11(F6, 0x0048)
|
||||
CODE_MAP_ANDROID(F6, 0x0040)
|
||||
|
||||
CODE_MAP_WIN(F7, 0x0041)
|
||||
CODE_MAP_MAC(F7, kVK_F7)
|
||||
CODE_MAP_X11(F7, 0x0049)
|
||||
CODE_MAP_ANDROID(F7, 0x0041)
|
||||
|
||||
CODE_MAP_WIN(F8, 0x0042)
|
||||
CODE_MAP_MAC(F8, kVK_F8)
|
||||
CODE_MAP_X11(F8, 0x004A)
|
||||
CODE_MAP_ANDROID(F8, 0x0042)
|
||||
|
||||
CODE_MAP_WIN(F9, 0x0043)
|
||||
CODE_MAP_MAC(F9, kVK_F9)
|
||||
CODE_MAP_X11(F9, 0x004B)
|
||||
CODE_MAP_ANDROID(F9, 0x0043)
|
||||
|
||||
CODE_MAP_WIN(F10, 0x0044)
|
||||
CODE_MAP_MAC(F10, kVK_F10)
|
||||
CODE_MAP_X11(F10, 0x004C)
|
||||
CODE_MAP_ANDROID(F10, 0x0044)
|
||||
|
||||
CODE_MAP_WIN(F11, 0x0057)
|
||||
CODE_MAP_MAC(F11, kVK_F11)
|
||||
CODE_MAP_X11(F11, 0x005F)
|
||||
CODE_MAP_ANDROID(F11, 0x0057)
|
||||
|
||||
CODE_MAP_WIN(F12, 0x0058)
|
||||
CODE_MAP_MAC(F12, kVK_F12)
|
||||
CODE_MAP_X11(F12, 0x0060)
|
||||
CODE_MAP_ANDROID(F12, 0x0058)
|
||||
|
||||
CODE_MAP_WIN(F13, 0x0064)
|
||||
CODE_MAP_MAC(F13, kVK_F13) // PrintScreen on PC keyboard
|
||||
CODE_MAP_X11(F13, 0x00BF)
|
||||
CODE_MAP_ANDROID(F13, 0x00B7)
|
||||
|
||||
CODE_MAP_WIN(F14, 0x0065)
|
||||
CODE_MAP_MAC(F14, kVK_F14) // ScrollLock on PC keyboard
|
||||
CODE_MAP_X11(F14, 0x00C0)
|
||||
CODE_MAP_ANDROID(F14, 0x00B8)
|
||||
|
||||
CODE_MAP_WIN(F15, 0x0066)
|
||||
CODE_MAP_MAC(F15, kVK_F15) // Pause on PC keyboard
|
||||
CODE_MAP_X11(F15, 0x00C1)
|
||||
CODE_MAP_ANDROID(F15, 0x00B9)
|
||||
|
||||
CODE_MAP_WIN(F16, 0x0067)
|
||||
CODE_MAP_MAC(F16, kVK_F16)
|
||||
CODE_MAP_X11(F16, 0x00C2)
|
||||
CODE_MAP_ANDROID(F16, 0x00BA)
|
||||
|
||||
CODE_MAP_WIN(F17, 0x0068)
|
||||
CODE_MAP_MAC(F17, kVK_F17)
|
||||
CODE_MAP_X11(F17, 0x00C3)
|
||||
CODE_MAP_ANDROID(F17, 0x00BB)
|
||||
|
||||
CODE_MAP_WIN(F18, 0x0069)
|
||||
CODE_MAP_MAC(F18, kVK_F18)
|
||||
CODE_MAP_X11(F18, 0x00C4)
|
||||
CODE_MAP_ANDROID(F18, 0x00BC)
|
||||
|
||||
CODE_MAP_WIN(F19, 0x006A)
|
||||
CODE_MAP_MAC(F19, kVK_F19)
|
||||
CODE_MAP_X11(F19, 0x00C5)
|
||||
CODE_MAP_ANDROID(F19, 0x00BD)
|
||||
|
||||
CODE_MAP_WIN(F20, 0x006B)
|
||||
CODE_MAP_MAC(F20, kVK_F20)
|
||||
CODE_MAP_X11(F20, 0x00C6)
|
||||
CODE_MAP_ANDROID(F20, 0x00BE)
|
||||
|
||||
CODE_MAP_WIN(F21, 0x006C)
|
||||
CODE_MAP_X11(F21, 0x00C7)
|
||||
CODE_MAP_ANDROID(F21, 0x00BF)
|
||||
|
||||
CODE_MAP_WIN(F22, 0x006D)
|
||||
CODE_MAP_X11(F22, 0x00C8)
|
||||
CODE_MAP_ANDROID(F22, 0x00C0)
|
||||
|
||||
CODE_MAP_WIN(F23, 0x006E)
|
||||
CODE_MAP_X11(F23, 0x00C9)
|
||||
CODE_MAP_ANDROID(F23, 0x00C1)
|
||||
|
||||
CODE_MAP_WIN(F24, 0x0076)
|
||||
CODE_MAP_X11(F24, 0x00CA)
|
||||
CODE_MAP_ANDROID(F24, 0x00C2)
|
||||
|
||||
CODE_MAP_MAC(Fn, kVK_Function) // not available?
|
||||
CODE_MAP_ANDROID(Fn, 0x01D0)
|
||||
|
||||
CODE_MAP_WIN(PrintScreen, 0xE037)
|
||||
CODE_MAP_WIN(PrintScreen, 0x0054) // Alt + PrintScreen
|
||||
CODE_MAP_X11(PrintScreen, 0x006B)
|
||||
CODE_MAP_ANDROID(PrintScreen, 0x0063)
|
||||
|
||||
CODE_MAP_WIN(ScrollLock, 0x0046)
|
||||
CODE_MAP_X11(ScrollLock, 0x004E)
|
||||
CODE_MAP_ANDROID(ScrollLock, 0x0046)
|
||||
|
||||
CODE_MAP_WIN(Pause, 0x0045)
|
||||
CODE_MAP_WIN(Pause, 0xE046) // Ctrl + Pause
|
||||
CODE_MAP_X11(Pause, 0x007F)
|
||||
CODE_MAP_ANDROID(Pause, 0x0077)
|
||||
|
||||
// Media keys
|
||||
CODE_MAP_WIN(BrowserBack, 0xE06A)
|
||||
CODE_MAP_X11(BrowserBack, 0x00A6)
|
||||
CODE_MAP_ANDROID(BrowserBack, 0x009E)
|
||||
|
||||
CODE_MAP_WIN(BrowserFavorites, 0xE066)
|
||||
CODE_MAP_X11(BrowserFavorites, 0x00A4)
|
||||
CODE_MAP_ANDROID(BrowserFavorites, 0x009C)
|
||||
|
||||
CODE_MAP_WIN(BrowserForward, 0xE069)
|
||||
CODE_MAP_X11(BrowserForward, 0x00A7)
|
||||
CODE_MAP_ANDROID(BrowserForward, 0x009F)
|
||||
|
||||
CODE_MAP_WIN(BrowserHome, 0xE032)
|
||||
CODE_MAP_X11(BrowserHome, 0x00B4)
|
||||
// CODE_MAP_ANDROID(BrowserHome) // not available? works as Home key.
|
||||
|
||||
CODE_MAP_WIN(BrowserRefresh, 0xE067)
|
||||
CODE_MAP_X11(BrowserRefresh, 0x00B5)
|
||||
CODE_MAP_ANDROID(BrowserRefresh, 0x00AD)
|
||||
|
||||
CODE_MAP_WIN(BrowserSearch, 0xE065)
|
||||
CODE_MAP_X11(BrowserSearch, 0x00E1)
|
||||
CODE_MAP_ANDROID(BrowserSearch, 0x00D9)
|
||||
|
||||
CODE_MAP_WIN(BrowserStop, 0xE068)
|
||||
CODE_MAP_X11(BrowserStop, 0x0088)
|
||||
CODE_MAP_ANDROID(BrowserStop, 0x0080)
|
||||
|
||||
// CODE_MAP_WIN(Eject) // not available?
|
||||
// CODE_MAP_MAC(Eject) // not available?
|
||||
CODE_MAP_X11(Eject, 0x00A9)
|
||||
CODE_MAP_ANDROID(Eject, 0x00A1)
|
||||
|
||||
CODE_MAP_WIN(LaunchApp1, 0xE06B)
|
||||
CODE_MAP_X11(LaunchApp1, 0x0098)
|
||||
CODE_MAP_ANDROID(LaunchApp1, 0x0090)
|
||||
|
||||
CODE_MAP_WIN(LaunchApp2, 0xE021)
|
||||
CODE_MAP_X11(LaunchApp2, 0x0094)
|
||||
// CODE_MAP_ANDROID(LaunchApp2) // not available?
|
||||
|
||||
CODE_MAP_WIN(LaunchMail, 0xE06C)
|
||||
CODE_MAP_X11(LaunchMail, 0x00A3)
|
||||
// CODE_MAP_ANDROID(LaunchMail) // not available?
|
||||
|
||||
CODE_MAP_WIN(MediaPlayPause, 0xE022)
|
||||
CODE_MAP_X11(MediaPlayPause, 0x00AC)
|
||||
CODE_MAP_ANDROID(MediaPlayPause, 0x00A4)
|
||||
|
||||
CODE_MAP_WIN(MediaSelect, 0xE06D)
|
||||
CODE_MAP_X11(MediaSelect, 0x00B3)
|
||||
// CODE_MAP_ANDROID(MediaSelect) // not available?
|
||||
|
||||
CODE_MAP_WIN(MediaStop, 0xE024)
|
||||
CODE_MAP_X11(MediaStop, 0x00AE)
|
||||
CODE_MAP_ANDROID(MediaStop, 0x00A6)
|
||||
|
||||
CODE_MAP_WIN(MediaTrackNext, 0xE019)
|
||||
CODE_MAP_X11(MediaTrackNext, 0x00AB)
|
||||
CODE_MAP_ANDROID(MediaTrackNext, 0x00A3)
|
||||
|
||||
CODE_MAP_WIN(MediaTrackPrevious, 0xE010)
|
||||
CODE_MAP_X11(MediaTrackPrevious, 0x00AD)
|
||||
CODE_MAP_ANDROID(MediaTrackPrevious, 0x00A5)
|
||||
|
||||
CODE_MAP_WIN(Power, 0xE05E)
|
||||
CODE_MAP_MAC(Power, 0x007F) // On 10.7 and 10.8 only
|
||||
// CODE_MAP_X11(Power) // not available?
|
||||
CODE_MAP_ANDROID(Power, 0x0074)
|
||||
|
||||
// CODE_MAP_WIN(Sleep) // not available?
|
||||
// CODE_MAP_X11(Sleep) // not available?
|
||||
CODE_MAP_ANDROID(Sleep, 0x008E)
|
||||
|
||||
CODE_MAP_WIN(VolumeDown, 0xE02E)
|
||||
CODE_MAP_MAC(VolumeDown, kVK_VolumeDown) // not available?
|
||||
CODE_MAP_X11(VolumeDown, 0x007A)
|
||||
CODE_MAP_ANDROID(VolumeDown, 0x0072)
|
||||
|
||||
CODE_MAP_WIN(VolumeMute, 0xE020)
|
||||
CODE_MAP_MAC(VolumeMute, kVK_Mute) // not available?
|
||||
CODE_MAP_X11(VolumeMute, 0x0079)
|
||||
CODE_MAP_ANDROID(VolumeMute, 0x0071)
|
||||
|
||||
CODE_MAP_WIN(VolumeUp, 0xE030)
|
||||
CODE_MAP_MAC(VolumeUp, kVK_VolumeUp) // not available?
|
||||
CODE_MAP_X11(VolumeUp, 0x007B)
|
||||
CODE_MAP_ANDROID(VolumeUp, 0x0073) // side of body, not on keyboard
|
||||
|
||||
// CODE_MAP_WIN(WakeUp) // not available?
|
||||
CODE_MAP_X11(WakeUp, 0x0097)
|
||||
CODE_MAP_ANDROID(WakeUp, 0x008F)
|
||||
|
||||
// Legacy editing keys
|
||||
CODE_MAP_X11(Again, 0x0089) // Again key on Sun keyboard
|
||||
CODE_MAP_ANDROID(Again, 0x0081) // Again key on Sun keyboard
|
||||
|
||||
CODE_MAP_X11(Copy, 0x008D) // Copy key on Sun keyboard
|
||||
CODE_MAP_ANDROID(Copy, 0x0085) // Copy key on Sun keyboard
|
||||
|
||||
CODE_MAP_X11(Cut, 0x0091) // Cut key on Sun keyboard
|
||||
CODE_MAP_ANDROID(Cut, 0x0089) // Cut key on Sun keyboard
|
||||
|
||||
CODE_MAP_X11(Find, 0x0090) // Find key on Sun keyboard
|
||||
CODE_MAP_ANDROID(Find, 0x0088) // Find key on Sun keyboard
|
||||
|
||||
CODE_MAP_X11(Open, 0x008E) // Open key on Sun keyboard
|
||||
CODE_MAP_ANDROID(Open, 0x0086) // Open key on Sun keyboard
|
||||
|
||||
CODE_MAP_X11(Paste, 0x008F) // Paste key on Sun keyboard
|
||||
CODE_MAP_ANDROID(Paste, 0x0087) // Paste key on Sun keyboard
|
||||
|
||||
CODE_MAP_X11(Props, 0x008A) // Props key on Sun keyboard
|
||||
CODE_MAP_ANDROID(Props, 0x0082) // Props key on Sun keyboard
|
||||
|
||||
CODE_MAP_X11(Select, 0x008C) // Front key on Sun keyboard
|
||||
CODE_MAP_ANDROID(Select, 0x0084) // Front key on Sun keyboard
|
||||
|
||||
CODE_MAP_X11(Undo, 0x008B) // Undo key on Sun keyboard
|
||||
CODE_MAP_ANDROID(Undo, 0x0083) // Undo key on Sun keyboard
|
||||
|
||||
#undef CODE_MAP_WIN
|
||||
#undef CODE_MAP_MAC
|
||||
#undef CODE_MAP_X11
|
||||
#undef CODE_MAP_ANDROID
|
||||
1144
widget/NativeKeyToDOMKeyName.h
Normal file
1144
widget/NativeKeyToDOMKeyName.h
Normal file
File diff suppressed because it is too large
Load diff
28
widget/PCompositorWidget.ipdl
Normal file
28
widget/PCompositorWidget.ipdl
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=99: */
|
||||
/* 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 protocol PCompositorBridge;
|
||||
|
||||
// This file is a stub, for platforms that do not yet support out-of-process
|
||||
// compositing or do not need specialized types to do so.
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
sync protocol PCompositorWidget
|
||||
{
|
||||
manager PCompositorBridge;
|
||||
|
||||
parent:
|
||||
async __delete__();
|
||||
|
||||
child:
|
||||
async ObserveVsync();
|
||||
async UnobserveVsync();
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
18
widget/PlatformWidgetTypes.ipdlh
Normal file
18
widget/PlatformWidgetTypes.ipdlh
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=99: */
|
||||
/* 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/. */
|
||||
|
||||
// This file is a stub, for platforms that do not yet support out-of-process
|
||||
// compositing or do not need specialized types to do so.
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
struct CompositorWidgetInitData
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
195
widget/PluginWidgetProxy.cpp
Normal file
195
widget/PluginWidgetProxy.cpp
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
/* 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 "PluginWidgetProxy.h"
|
||||
#include "mozilla/dom/TabChild.h"
|
||||
#include "mozilla/plugins/PluginWidgetChild.h"
|
||||
#include "mozilla/plugins/PluginInstanceParent.h"
|
||||
#include "nsDebug.h"
|
||||
|
||||
#define PWLOG(...)
|
||||
// #define PWLOG(...) printf_stderr(__VA_ARGS__)
|
||||
|
||||
/* static */
|
||||
already_AddRefed<nsIWidget>
|
||||
nsIWidget::CreatePluginProxyWidget(TabChild* aTabChild,
|
||||
mozilla::plugins::PluginWidgetChild* aActor)
|
||||
{
|
||||
nsCOMPtr<nsIWidget> widget =
|
||||
new mozilla::widget::PluginWidgetProxy(aTabChild, aActor);
|
||||
return widget.forget();
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
using mozilla::plugins::PluginInstanceParent;
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED(PluginWidgetProxy, PuppetWidget, nsIWidget)
|
||||
|
||||
#define ENSURE_CHANNEL do { \
|
||||
if (!mActor) { \
|
||||
NS_WARNING("called on an invalid channel."); \
|
||||
return NS_ERROR_FAILURE; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
PluginWidgetProxy::PluginWidgetProxy(dom::TabChild* aTabChild,
|
||||
mozilla::plugins::PluginWidgetChild* aActor) :
|
||||
PuppetWidget(aTabChild),
|
||||
mActor(aActor),
|
||||
mCachedPluginPort(0)
|
||||
{
|
||||
// See ChannelDestroyed() in the header
|
||||
mActor->SetWidget(this);
|
||||
}
|
||||
|
||||
PluginWidgetProxy::~PluginWidgetProxy()
|
||||
{
|
||||
PWLOG("PluginWidgetProxy::~PluginWidgetProxy()\n");
|
||||
}
|
||||
|
||||
nsresult
|
||||
PluginWidgetProxy::Create(nsIWidget* aParent,
|
||||
nsNativeWidget aNativeParent,
|
||||
const LayoutDeviceIntRect& aRect,
|
||||
nsWidgetInitData* aInitData)
|
||||
{
|
||||
ENSURE_CHANNEL;
|
||||
PWLOG("PluginWidgetProxy::Create()\n");
|
||||
|
||||
nsresult rv = NS_ERROR_UNEXPECTED;
|
||||
uint64_t scrollCaptureId;
|
||||
uintptr_t pluginInstanceId;
|
||||
mActor->SendCreate(&rv, &scrollCaptureId, &pluginInstanceId);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("failed to create chrome widget, plugins won't paint.");
|
||||
return rv;
|
||||
}
|
||||
|
||||
BaseCreate(aParent, aInitData);
|
||||
mParent = aParent;
|
||||
|
||||
mBounds = aRect;
|
||||
mEnabled = true;
|
||||
mVisible = true;
|
||||
|
||||
#if defined(XP_WIN)
|
||||
PluginInstanceParent* instance =
|
||||
PluginInstanceParent::LookupPluginInstanceByID(pluginInstanceId);
|
||||
if (instance) {
|
||||
Unused << NS_WARN_IF(NS_FAILED(instance->SetScrollCaptureId(scrollCaptureId)));
|
||||
}
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginWidgetProxy::SetParent(nsIWidget* aNewParent)
|
||||
{
|
||||
nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
|
||||
nsIWidget* parent = GetParent();
|
||||
if (parent) {
|
||||
parent->RemoveChild(this);
|
||||
}
|
||||
if (aNewParent) {
|
||||
aNewParent->AddChild(this);
|
||||
}
|
||||
mParent = aNewParent;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIWidget*
|
||||
PluginWidgetProxy::GetParent(void)
|
||||
{
|
||||
return mParent.get();
|
||||
}
|
||||
|
||||
void
|
||||
PluginWidgetProxy::Destroy()
|
||||
{
|
||||
PWLOG("PluginWidgetProxy::Destroy()\n");
|
||||
|
||||
if (mActor) {
|
||||
// Communicate that the layout widget has been torn down before the sub
|
||||
// protocol.
|
||||
mActor->ProxyShutdown();
|
||||
mActor = nullptr;
|
||||
}
|
||||
|
||||
PuppetWidget::Destroy();
|
||||
}
|
||||
|
||||
void
|
||||
PluginWidgetProxy::GetWindowClipRegion(nsTArray<LayoutDeviceIntRect>* aRects)
|
||||
{
|
||||
if (mClipRects && mClipRectCount) {
|
||||
aRects->AppendElements(mClipRects.get(), mClipRectCount);
|
||||
}
|
||||
}
|
||||
|
||||
void*
|
||||
PluginWidgetProxy::GetNativeData(uint32_t aDataType)
|
||||
{
|
||||
if (!mActor) {
|
||||
return nullptr;
|
||||
}
|
||||
auto tab = static_cast<mozilla::dom::TabChild*>(mActor->Manager());
|
||||
if (tab && tab->IsDestroyed()) {
|
||||
return nullptr;
|
||||
}
|
||||
switch (aDataType) {
|
||||
case NS_NATIVE_PLUGIN_PORT:
|
||||
case NS_NATIVE_WINDOW:
|
||||
case NS_NATIVE_SHAREABLE_WINDOW:
|
||||
break;
|
||||
default:
|
||||
NS_WARNING("PluginWidgetProxy::GetNativeData received request for unsupported data type.");
|
||||
return nullptr;
|
||||
}
|
||||
// The parent side window handle or xid never changes so we can
|
||||
// cache this for our lifetime.
|
||||
if (mCachedPluginPort) {
|
||||
return (void*)mCachedPluginPort;
|
||||
}
|
||||
mActor->SendGetNativePluginPort(&mCachedPluginPort);
|
||||
PWLOG("PluginWidgetProxy::GetNativeData %p\n", (void*)mCachedPluginPort);
|
||||
return (void*)mCachedPluginPort;
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
void
|
||||
PluginWidgetProxy::SetNativeData(uint32_t aDataType, uintptr_t aVal)
|
||||
{
|
||||
if (!mActor) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto tab = static_cast<mozilla::dom::TabChild*>(mActor->Manager());
|
||||
if (tab && tab->IsDestroyed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (aDataType) {
|
||||
case NS_NATIVE_CHILD_WINDOW:
|
||||
mActor->SendSetNativeChildWindow(aVal);
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("SetNativeData called with unsupported data type.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginWidgetProxy::SetFocus(bool aRaise)
|
||||
{
|
||||
ENSURE_CHANNEL;
|
||||
PWLOG("PluginWidgetProxy::SetFocus(%d)\n", aRaise);
|
||||
mActor->SendSetFocus(aRaise);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
78
widget/PluginWidgetProxy.h
Normal file
78
widget/PluginWidgetProxy.h
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_widget_RemotePlugin_h__
|
||||
#define mozilla_widget_RemotePlugin_h__
|
||||
|
||||
#include "PuppetWidget.h"
|
||||
#include "mozilla/dom/TabChild.h"
|
||||
|
||||
/*
|
||||
* PluginWidgetProxy is a nsIWidget wrapper we hand around in plugin and layout
|
||||
* code. It wraps a native widget it creates in the chrome process. Since this
|
||||
* is for plugins, only a limited set of the widget apis need to be overridden,
|
||||
* the rest of the implementation is in PuppetWidget or nsBaseWidget.
|
||||
*/
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
class PluginWidgetChild;
|
||||
} // namespace plugins
|
||||
namespace widget {
|
||||
|
||||
class PluginWidgetProxy final : public PuppetWidget
|
||||
{
|
||||
public:
|
||||
explicit PluginWidgetProxy(dom::TabChild* aTabChild,
|
||||
mozilla::plugins::PluginWidgetChild* aChannel);
|
||||
|
||||
protected:
|
||||
virtual ~PluginWidgetProxy();
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIWidget
|
||||
using PuppetWidget::Create; // for Create signature not overridden here
|
||||
virtual MOZ_MUST_USE nsresult Create(nsIWidget* aParent,
|
||||
nsNativeWidget aNativeParent,
|
||||
const LayoutDeviceIntRect& aRect,
|
||||
nsWidgetInitData* aInitData = nullptr)
|
||||
override;
|
||||
virtual void Destroy() override;
|
||||
NS_IMETHOD SetFocus(bool aRaise = false) override;
|
||||
NS_IMETHOD SetParent(nsIWidget* aNewParent) override;
|
||||
|
||||
virtual nsIWidget* GetParent(void) override;
|
||||
virtual void* GetNativeData(uint32_t aDataType) override;
|
||||
#if defined(XP_WIN)
|
||||
void SetNativeData(uint32_t aDataType, uintptr_t aVal) override;
|
||||
#endif
|
||||
virtual nsTransparencyMode GetTransparencyMode() override
|
||||
{ return eTransparencyOpaque; }
|
||||
virtual void GetWindowClipRegion(nsTArray<LayoutDeviceIntRect>* aRects) override;
|
||||
|
||||
public:
|
||||
/**
|
||||
* When tabs are closed PPluginWidget can terminate before plugin code is
|
||||
* finished tearing us down. When this happens plugin calls over mActor
|
||||
* fail triggering an abort in the content process. To protect against this
|
||||
* the connection tells us when it is torn down here so we can avoid making
|
||||
* calls while content finishes tearing us down.
|
||||
*/
|
||||
void ChannelDestroyed() { mActor = nullptr; }
|
||||
|
||||
private:
|
||||
// Our connection with the chrome widget, created on PBrowser.
|
||||
mozilla::plugins::PluginWidgetChild* mActor;
|
||||
// PuppetWidget does not implement parent apis, but we need
|
||||
// them for plugin widgets.
|
||||
nsCOMPtr<nsIWidget> mParent;
|
||||
uintptr_t mCachedPluginPort;
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
48
widget/PuppetBidiKeyboard.cpp
Normal file
48
widget/PuppetBidiKeyboard.cpp
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* 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 "PuppetBidiKeyboard.h"
|
||||
|
||||
using namespace mozilla::widget;
|
||||
|
||||
NS_IMPL_ISUPPORTS(PuppetBidiKeyboard, nsIBidiKeyboard)
|
||||
|
||||
PuppetBidiKeyboard::PuppetBidiKeyboard() : nsIBidiKeyboard()
|
||||
{
|
||||
}
|
||||
|
||||
PuppetBidiKeyboard::~PuppetBidiKeyboard()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PuppetBidiKeyboard::Reset()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PuppetBidiKeyboard::IsLangRTL(bool* aIsRTL)
|
||||
{
|
||||
*aIsRTL = mIsLangRTL;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
PuppetBidiKeyboard::SetBidiKeyboardInfo(bool aIsLangRTL,
|
||||
bool aHaveBidiKeyboards)
|
||||
{
|
||||
mIsLangRTL = aIsLangRTL;
|
||||
mHaveBidiKeyboards = aHaveBidiKeyboards;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PuppetBidiKeyboard::GetHaveBidiKeyboards(bool* aResult)
|
||||
{
|
||||
*aResult = mHaveBidiKeyboards;
|
||||
return NS_OK;
|
||||
}
|
||||
36
widget/PuppetBidiKeyboard.h
Normal file
36
widget/PuppetBidiKeyboard.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_widget_PuppetBidiKeyboard_h_
|
||||
#define mozilla_widget_PuppetBidiKeyboard_h_
|
||||
|
||||
#include "nsIBidiKeyboard.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
class PuppetBidiKeyboard final : public nsIBidiKeyboard
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIBIDIKEYBOARD
|
||||
|
||||
PuppetBidiKeyboard();
|
||||
|
||||
void SetBidiKeyboardInfo(bool aIsLangRTL, bool aHaveBidiKeyboards);
|
||||
|
||||
private:
|
||||
~PuppetBidiKeyboard();
|
||||
|
||||
bool mIsLangRTL;
|
||||
bool mHaveBidiKeyboards;
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_widget_PuppetBidiKeyboard_h_
|
||||
1580
widget/PuppetWidget.cpp
Normal file
1580
widget/PuppetWidget.cpp
Normal file
File diff suppressed because it is too large
Load diff
463
widget/PuppetWidget.h
Normal file
463
widget/PuppetWidget.h
Normal file
|
|
@ -0,0 +1,463 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* 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/. */
|
||||
|
||||
/**
|
||||
* This "puppet widget" isn't really a platform widget. It's intended
|
||||
* to be used in widgetless rendering contexts, such as sandboxed
|
||||
* content processes. If any "real" widgetry is needed, the request
|
||||
* is forwarded to and/or data received from elsewhere.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_widget_PuppetWidget_h__
|
||||
#define mozilla_widget_PuppetWidget_h__
|
||||
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsBaseScreen.h"
|
||||
#include "nsBaseWidget.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsIKeyEventInPluginCallback.h"
|
||||
#include "nsIScreenManager.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ContentCache.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace dom {
|
||||
class TabChild;
|
||||
} // namespace dom
|
||||
|
||||
namespace widget {
|
||||
|
||||
struct AutoCacheNativeKeyCommands;
|
||||
|
||||
class PuppetWidget : public nsBaseWidget
|
||||
{
|
||||
typedef mozilla::dom::TabChild TabChild;
|
||||
typedef mozilla::gfx::DrawTarget DrawTarget;
|
||||
typedef nsBaseWidget Base;
|
||||
typedef mozilla::CSSRect CSSRect;
|
||||
|
||||
// The width and height of the "widget" are clamped to this.
|
||||
static const size_t kMaxDimension;
|
||||
|
||||
public:
|
||||
explicit PuppetWidget(TabChild* aTabChild);
|
||||
|
||||
protected:
|
||||
virtual ~PuppetWidget();
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// PuppetWidget creation is infallible, hence InfallibleCreate(), which
|
||||
// Create() calls.
|
||||
using nsBaseWidget::Create; // for Create signature not overridden here
|
||||
virtual nsresult Create(nsIWidget* aParent,
|
||||
nsNativeWidget aNativeParent,
|
||||
const LayoutDeviceIntRect& aRect,
|
||||
nsWidgetInitData* aInitData = nullptr)
|
||||
override;
|
||||
void InfallibleCreate(nsIWidget* aParent,
|
||||
nsNativeWidget aNativeParent,
|
||||
const LayoutDeviceIntRect& aRect,
|
||||
nsWidgetInitData* aInitData = nullptr);
|
||||
|
||||
void InitIMEState();
|
||||
|
||||
virtual already_AddRefed<nsIWidget>
|
||||
CreateChild(const LayoutDeviceIntRect& aRect,
|
||||
nsWidgetInitData* aInitData = nullptr,
|
||||
bool aForceUseIWidgetParent = false) override;
|
||||
|
||||
virtual void Destroy() override;
|
||||
|
||||
NS_IMETHOD Show(bool aState) override;
|
||||
|
||||
virtual bool IsVisible() const override
|
||||
{ return mVisible; }
|
||||
|
||||
virtual void ConstrainPosition(bool /*ignored aAllowSlop*/,
|
||||
int32_t* aX,
|
||||
int32_t* aY) override
|
||||
{ *aX = kMaxDimension; *aY = kMaxDimension; }
|
||||
|
||||
// Widget position is controlled by the parent process via TabChild.
|
||||
NS_IMETHOD Move(double aX, double aY) override
|
||||
{ return NS_OK; }
|
||||
|
||||
NS_IMETHOD Resize(double aWidth,
|
||||
double aHeight,
|
||||
bool aRepaint) override;
|
||||
NS_IMETHOD Resize(double aX,
|
||||
double aY,
|
||||
double aWidth,
|
||||
double aHeight,
|
||||
bool aRepaint) override
|
||||
{
|
||||
if (mBounds.x != aX || mBounds.y != aY) {
|
||||
NotifyWindowMoved(aX, aY);
|
||||
}
|
||||
mBounds.x = aX;
|
||||
mBounds.y = aY;
|
||||
return Resize(aWidth, aHeight, aRepaint);
|
||||
}
|
||||
|
||||
// XXX/cjones: copying gtk behavior here; unclear what disabling a
|
||||
// widget is supposed to entail
|
||||
NS_IMETHOD Enable(bool aState) override
|
||||
{ mEnabled = aState; return NS_OK; }
|
||||
virtual bool IsEnabled() const override
|
||||
{ return mEnabled; }
|
||||
|
||||
NS_IMETHOD SetFocus(bool aRaise = false) override;
|
||||
|
||||
virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations) override;
|
||||
|
||||
NS_IMETHOD Invalidate(const LayoutDeviceIntRect& aRect) override;
|
||||
|
||||
// PuppetWidgets don't have native data, as they're purely nonnative.
|
||||
virtual void* GetNativeData(uint32_t aDataType) override;
|
||||
#if defined(XP_WIN)
|
||||
void SetNativeData(uint32_t aDataType, uintptr_t aVal) override;
|
||||
#endif
|
||||
|
||||
// PuppetWidgets don't have any concept of titles.
|
||||
NS_IMETHOD SetTitle(const nsAString& aTitle) override
|
||||
{ return NS_ERROR_UNEXPECTED; }
|
||||
|
||||
virtual LayoutDeviceIntPoint WidgetToScreenOffset() override
|
||||
{ return LayoutDeviceIntPoint::FromUnknownPoint(GetWindowPosition() + GetChromeDimensions()); }
|
||||
|
||||
int32_t RoundsWidgetCoordinatesTo() override;
|
||||
|
||||
void InitEvent(WidgetGUIEvent& aEvent,
|
||||
LayoutDeviceIntPoint* aPoint = nullptr);
|
||||
|
||||
NS_IMETHOD DispatchEvent(WidgetGUIEvent* aEvent, nsEventStatus& aStatus) override;
|
||||
nsEventStatus DispatchInputEvent(WidgetInputEvent* aEvent) override;
|
||||
void SetConfirmedTargetAPZC(uint64_t aInputBlockId,
|
||||
const nsTArray<ScrollableLayerGuid>& aTargets) const override;
|
||||
void UpdateZoomConstraints(const uint32_t& aPresShellId,
|
||||
const FrameMetrics::ViewID& aViewId,
|
||||
const mozilla::Maybe<ZoomConstraints>& aConstraints) override;
|
||||
bool AsyncPanZoomEnabled() const override;
|
||||
|
||||
NS_IMETHOD_(bool)
|
||||
ExecuteNativeKeyBinding(NativeKeyBindingsType aType,
|
||||
const mozilla::WidgetKeyboardEvent& aEvent,
|
||||
DoCommandCallback aCallback,
|
||||
void* aCallbackData) override;
|
||||
|
||||
friend struct AutoCacheNativeKeyCommands;
|
||||
|
||||
//
|
||||
// nsBaseWidget methods we override
|
||||
//
|
||||
|
||||
// Documents loaded in child processes are always subdocuments of
|
||||
// other docs in an ancestor process. To ensure that the
|
||||
// backgrounds of those documents are painted like those of
|
||||
// same-process subdocuments, we force the widget here to be
|
||||
// transparent, which in turn will cause layout to use a transparent
|
||||
// backstop background color.
|
||||
virtual nsTransparencyMode GetTransparencyMode() override
|
||||
{ return eTransparencyTransparent; }
|
||||
|
||||
virtual LayerManager*
|
||||
GetLayerManager(PLayerTransactionChild* aShadowManager = nullptr,
|
||||
LayersBackend aBackendHint = mozilla::layers::LayersBackend::LAYERS_NONE,
|
||||
LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT) override;
|
||||
|
||||
// This is used after a compositor reset.
|
||||
LayerManager* RecreateLayerManager(PLayerTransactionChild* aShadowManager);
|
||||
|
||||
NS_IMETHOD_(void) SetInputContext(const InputContext& aContext,
|
||||
const InputContextAction& aAction) override;
|
||||
NS_IMETHOD_(InputContext) GetInputContext() override;
|
||||
NS_IMETHOD_(NativeIMEContext) GetNativeIMEContext() override;
|
||||
virtual nsIMEUpdatePreference GetIMEUpdatePreference() override;
|
||||
|
||||
NS_IMETHOD SetCursor(nsCursor aCursor) override;
|
||||
NS_IMETHOD SetCursor(imgIContainer* aCursor,
|
||||
uint32_t aHotspotX, uint32_t aHotspotY) override;
|
||||
|
||||
virtual void ClearCachedCursor() override;
|
||||
|
||||
// Gets the DPI of the screen corresponding to this widget.
|
||||
// Contacts the parent process which gets the DPI from the
|
||||
// proper widget there. TODO: Handle DPI changes that happen
|
||||
// later on.
|
||||
virtual float GetDPI() override;
|
||||
virtual double GetDefaultScaleInternal() override;
|
||||
|
||||
virtual bool NeedsPaint() override;
|
||||
|
||||
// Paint the widget immediately if any paints are queued up.
|
||||
void PaintNowIfNeeded();
|
||||
|
||||
virtual TabChild* GetOwningTabChild() override { return mTabChild; }
|
||||
|
||||
void UpdateBackingScaleCache(float aDpi, int32_t aRounding, double aScale)
|
||||
{
|
||||
mDPI = aDpi;
|
||||
mRounding = aRounding;
|
||||
mDefaultScale = aScale;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
virtual LayoutDeviceIntRect GetScreenBounds() override;
|
||||
|
||||
NS_IMETHOD StartPluginIME(const mozilla::WidgetKeyboardEvent& aKeyboardEvent,
|
||||
int32_t aPanelX, int32_t aPanelY,
|
||||
nsString& aCommitted) override;
|
||||
|
||||
virtual void SetPluginFocused(bool& aFocused) override;
|
||||
virtual void DefaultProcOfPluginEvent(
|
||||
const mozilla::WidgetPluginEvent& aEvent) override;
|
||||
|
||||
virtual nsresult SynthesizeNativeKeyEvent(int32_t aNativeKeyboardLayout,
|
||||
int32_t aNativeKeyCode,
|
||||
uint32_t aModifierFlags,
|
||||
const nsAString& aCharacters,
|
||||
const nsAString& aUnmodifiedCharacters,
|
||||
nsIObserver* aObserver) override;
|
||||
virtual nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint,
|
||||
uint32_t aNativeMessage,
|
||||
uint32_t aModifierFlags,
|
||||
nsIObserver* aObserver) override;
|
||||
virtual nsresult SynthesizeNativeMouseMove(LayoutDeviceIntPoint aPoint,
|
||||
nsIObserver* aObserver) override;
|
||||
virtual nsresult SynthesizeNativeMouseScrollEvent(LayoutDeviceIntPoint aPoint,
|
||||
uint32_t aNativeMessage,
|
||||
double aDeltaX,
|
||||
double aDeltaY,
|
||||
double aDeltaZ,
|
||||
uint32_t aModifierFlags,
|
||||
uint32_t aAdditionalFlags,
|
||||
nsIObserver* aObserver) override;
|
||||
virtual nsresult SynthesizeNativeTouchPoint(uint32_t aPointerId,
|
||||
TouchPointerState aPointerState,
|
||||
LayoutDeviceIntPoint aPoint,
|
||||
double aPointerPressure,
|
||||
uint32_t aPointerOrientation,
|
||||
nsIObserver* aObserver) override;
|
||||
virtual nsresult SynthesizeNativeTouchTap(LayoutDeviceIntPoint aPoint,
|
||||
bool aLongTap,
|
||||
nsIObserver* aObserver) override;
|
||||
virtual nsresult ClearNativeTouchSequence(nsIObserver* aObserver) override;
|
||||
virtual uint32_t GetMaxTouchPoints() const override;
|
||||
|
||||
virtual void StartAsyncScrollbarDrag(const AsyncDragMetrics& aDragMetrics) override;
|
||||
|
||||
virtual void SetCandidateWindowForPlugin(
|
||||
const CandidateWindowPosition& aPosition) override;
|
||||
|
||||
virtual void ZoomToRect(const uint32_t& aPresShellId,
|
||||
const FrameMetrics::ViewID& aViewId,
|
||||
const CSSRect& aRect,
|
||||
const uint32_t& aFlags) override;
|
||||
|
||||
virtual bool HasPendingInputEvent() override;
|
||||
|
||||
void HandledWindowedPluginKeyEvent(const NativeEventData& aKeyEventData,
|
||||
bool aIsConsumed);
|
||||
virtual nsresult OnWindowedPluginKeyEvent(
|
||||
const NativeEventData& aKeyEventData,
|
||||
nsIKeyEventInPluginCallback* aCallback) override;
|
||||
|
||||
virtual void LookUpDictionary(
|
||||
const nsAString& aText,
|
||||
const nsTArray<mozilla::FontRange>& aFontRangeArray,
|
||||
const bool aIsVertical,
|
||||
const LayoutDeviceIntPoint& aPoint) override;
|
||||
|
||||
protected:
|
||||
virtual nsresult NotifyIMEInternal(
|
||||
const IMENotification& aIMENotification) override;
|
||||
|
||||
private:
|
||||
nsresult Paint();
|
||||
|
||||
void SetChild(PuppetWidget* aChild);
|
||||
|
||||
nsresult RequestIMEToCommitComposition(bool aCancel);
|
||||
nsresult NotifyIMEOfFocusChange(const IMENotification& aIMENotification);
|
||||
nsresult NotifyIMEOfSelectionChange(const IMENotification& aIMENotification);
|
||||
nsresult NotifyIMEOfCompositionUpdate(const IMENotification& aIMENotification);
|
||||
nsresult NotifyIMEOfTextChange(const IMENotification& aIMENotification);
|
||||
nsresult NotifyIMEOfMouseButtonEvent(const IMENotification& aIMENotification);
|
||||
nsresult NotifyIMEOfPositionChange(const IMENotification& aIMENotification);
|
||||
|
||||
bool CacheEditorRect();
|
||||
bool CacheCompositionRects(uint32_t& aStartOffset,
|
||||
nsTArray<LayoutDeviceIntRect>& aRectArray,
|
||||
uint32_t& aTargetCauseOffset);
|
||||
bool GetCaretRect(LayoutDeviceIntRect& aCaretRect, uint32_t aCaretOffset);
|
||||
uint32_t GetCaretOffset();
|
||||
|
||||
nsIWidgetListener* GetCurrentWidgetListener();
|
||||
|
||||
class PaintTask : public Runnable {
|
||||
public:
|
||||
NS_DECL_NSIRUNNABLE
|
||||
explicit PaintTask(PuppetWidget* widget) : mWidget(widget) {}
|
||||
void Revoke() { mWidget = nullptr; }
|
||||
private:
|
||||
PuppetWidget* mWidget;
|
||||
};
|
||||
|
||||
class MemoryPressureObserver : public nsIObserver {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
explicit MemoryPressureObserver(PuppetWidget* aWidget) : mWidget(aWidget) {}
|
||||
void Remove();
|
||||
private:
|
||||
virtual ~MemoryPressureObserver() {}
|
||||
PuppetWidget* mWidget;
|
||||
};
|
||||
friend class MemoryPressureObserver;
|
||||
|
||||
// TabChild normally holds a strong reference to this PuppetWidget
|
||||
// or its root ancestor, but each PuppetWidget also needs a
|
||||
// reference back to TabChild (e.g. to delegate nsIWidget IME calls
|
||||
// to chrome) So we hold a weak reference to TabChild here. Since
|
||||
// it's possible for TabChild to outlive the PuppetWidget, we clear
|
||||
// this weak reference in Destroy()
|
||||
TabChild* mTabChild;
|
||||
// The "widget" to which we delegate events if we don't have an
|
||||
// event handler.
|
||||
RefPtr<PuppetWidget> mChild;
|
||||
LayoutDeviceIntRegion mDirtyRegion;
|
||||
nsRevocableEventPtr<PaintTask> mPaintTask;
|
||||
RefPtr<MemoryPressureObserver> mMemoryPressureObserver;
|
||||
// XXX/cjones: keeping this around until we teach LayerManager to do
|
||||
// retained-content-only transactions
|
||||
RefPtr<DrawTarget> mDrawTarget;
|
||||
// IME
|
||||
nsIMEUpdatePreference mIMEPreferenceOfParent;
|
||||
InputContext mInputContext;
|
||||
// mNativeIMEContext is initialized when this dispatches every composition
|
||||
// event both from parent process's widget and TextEventDispatcher in same
|
||||
// process. If it hasn't been started composition yet, this isn't necessary
|
||||
// for XP code since there is no TextComposition instance which is caused by
|
||||
// the PuppetWidget instance.
|
||||
NativeIMEContext mNativeIMEContext;
|
||||
ContentCacheInChild mContentCache;
|
||||
|
||||
// The DPI of the screen corresponding to this widget
|
||||
float mDPI;
|
||||
int32_t mRounding;
|
||||
double mDefaultScale;
|
||||
|
||||
// Precomputed answers for ExecuteNativeKeyBinding
|
||||
InfallibleTArray<mozilla::CommandInt> mSingleLineCommands;
|
||||
InfallibleTArray<mozilla::CommandInt> mMultiLineCommands;
|
||||
InfallibleTArray<mozilla::CommandInt> mRichTextCommands;
|
||||
|
||||
nsCOMPtr<imgIContainer> mCustomCursor;
|
||||
uint32_t mCursorHotspotX, mCursorHotspotY;
|
||||
|
||||
nsCOMArray<nsIKeyEventInPluginCallback> mKeyEventInPluginCallbacks;
|
||||
|
||||
protected:
|
||||
bool mEnabled;
|
||||
bool mVisible;
|
||||
|
||||
private:
|
||||
bool mNeedIMEStateInit;
|
||||
bool mNativeKeyCommandsValid;
|
||||
};
|
||||
|
||||
struct AutoCacheNativeKeyCommands
|
||||
{
|
||||
explicit AutoCacheNativeKeyCommands(PuppetWidget* aWidget)
|
||||
: mWidget(aWidget)
|
||||
{
|
||||
mSavedValid = mWidget->mNativeKeyCommandsValid;
|
||||
mSavedSingleLine = mWidget->mSingleLineCommands;
|
||||
mSavedMultiLine = mWidget->mMultiLineCommands;
|
||||
mSavedRichText = mWidget->mRichTextCommands;
|
||||
}
|
||||
|
||||
void Cache(const InfallibleTArray<mozilla::CommandInt>& aSingleLineCommands,
|
||||
const InfallibleTArray<mozilla::CommandInt>& aMultiLineCommands,
|
||||
const InfallibleTArray<mozilla::CommandInt>& aRichTextCommands)
|
||||
{
|
||||
mWidget->mNativeKeyCommandsValid = true;
|
||||
mWidget->mSingleLineCommands = aSingleLineCommands;
|
||||
mWidget->mMultiLineCommands = aMultiLineCommands;
|
||||
mWidget->mRichTextCommands = aRichTextCommands;
|
||||
}
|
||||
|
||||
void CacheNoCommands()
|
||||
{
|
||||
mWidget->mNativeKeyCommandsValid = true;
|
||||
mWidget->mSingleLineCommands.Clear();
|
||||
mWidget->mMultiLineCommands.Clear();
|
||||
mWidget->mRichTextCommands.Clear();
|
||||
}
|
||||
|
||||
~AutoCacheNativeKeyCommands()
|
||||
{
|
||||
mWidget->mNativeKeyCommandsValid = mSavedValid;
|
||||
mWidget->mSingleLineCommands = mSavedSingleLine;
|
||||
mWidget->mMultiLineCommands = mSavedMultiLine;
|
||||
mWidget->mRichTextCommands = mSavedRichText;
|
||||
}
|
||||
|
||||
private:
|
||||
PuppetWidget* mWidget;
|
||||
bool mSavedValid;
|
||||
InfallibleTArray<mozilla::CommandInt> mSavedSingleLine;
|
||||
InfallibleTArray<mozilla::CommandInt> mSavedMultiLine;
|
||||
InfallibleTArray<mozilla::CommandInt> mSavedRichText;
|
||||
};
|
||||
|
||||
class PuppetScreen : public nsBaseScreen
|
||||
{
|
||||
public:
|
||||
explicit PuppetScreen(void* nativeScreen);
|
||||
~PuppetScreen();
|
||||
|
||||
NS_IMETHOD GetId(uint32_t* aId) override;
|
||||
NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight) override;
|
||||
NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight) override;
|
||||
NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth) override;
|
||||
NS_IMETHOD GetColorDepth(int32_t* aColorDepth) override;
|
||||
NS_IMETHOD GetRotation(uint32_t* aRotation) override;
|
||||
NS_IMETHOD SetRotation(uint32_t aRotation) override;
|
||||
};
|
||||
|
||||
class PuppetScreenManager final : public nsIScreenManager
|
||||
{
|
||||
~PuppetScreenManager();
|
||||
|
||||
public:
|
||||
PuppetScreenManager();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISCREENMANAGER
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIScreen> mOneScreen;
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_widget_PuppetWidget_h__
|
||||
189
widget/ScreenProxy.cpp
Normal file
189
widget/ScreenProxy.cpp
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 2; -*- */
|
||||
/* vim: set sw=4 ts=8 et tw=80 : */
|
||||
/* 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 "mozilla/Unused.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIAppShell.h"
|
||||
#include "nsScreenManagerProxy.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
#include "ScreenProxy.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
|
||||
|
||||
ScreenProxy::ScreenProxy(nsScreenManagerProxy* aScreenManager, ScreenDetails aDetails)
|
||||
: mContentsScaleFactor(0)
|
||||
, mScreenManager(aScreenManager)
|
||||
, mId(0)
|
||||
, mPixelDepth(0)
|
||||
, mColorDepth(0)
|
||||
, mCacheValid(false)
|
||||
, mCacheWillInvalidate(false)
|
||||
{
|
||||
PopulateByDetails(aDetails);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ScreenProxy::GetId(uint32_t *outId)
|
||||
{
|
||||
*outId = mId;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ScreenProxy::GetRect(int32_t *outLeft,
|
||||
int32_t *outTop,
|
||||
int32_t *outWidth,
|
||||
int32_t *outHeight)
|
||||
{
|
||||
if (!EnsureCacheIsValid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*outLeft = mRect.x;
|
||||
*outTop = mRect.y;
|
||||
*outWidth = mRect.width;
|
||||
*outHeight = mRect.height;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ScreenProxy::GetRectDisplayPix(int32_t *outLeft,
|
||||
int32_t *outTop,
|
||||
int32_t *outWidth,
|
||||
int32_t *outHeight)
|
||||
{
|
||||
if (!EnsureCacheIsValid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*outLeft = mRectDisplayPix.x;
|
||||
*outTop = mRectDisplayPix.y;
|
||||
*outWidth = mRectDisplayPix.width;
|
||||
*outHeight = mRectDisplayPix.height;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ScreenProxy::GetAvailRect(int32_t *outLeft,
|
||||
int32_t *outTop,
|
||||
int32_t *outWidth,
|
||||
int32_t *outHeight)
|
||||
{
|
||||
if (!EnsureCacheIsValid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*outLeft = mAvailRect.x;
|
||||
*outTop = mAvailRect.y;
|
||||
*outWidth = mAvailRect.width;
|
||||
*outHeight = mAvailRect.height;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ScreenProxy::GetAvailRectDisplayPix(int32_t *outLeft,
|
||||
int32_t *outTop,
|
||||
int32_t *outWidth,
|
||||
int32_t *outHeight)
|
||||
{
|
||||
if (!EnsureCacheIsValid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*outLeft = mAvailRectDisplayPix.x;
|
||||
*outTop = mAvailRectDisplayPix.y;
|
||||
*outWidth = mAvailRectDisplayPix.width;
|
||||
*outHeight = mAvailRectDisplayPix.height;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ScreenProxy::GetPixelDepth(int32_t *aPixelDepth)
|
||||
{
|
||||
if (!EnsureCacheIsValid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*aPixelDepth = mPixelDepth;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ScreenProxy::GetColorDepth(int32_t *aColorDepth)
|
||||
{
|
||||
if (!EnsureCacheIsValid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*aColorDepth = mColorDepth;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
ScreenProxy::PopulateByDetails(ScreenDetails aDetails)
|
||||
{
|
||||
mId = aDetails.id();
|
||||
mRect = nsIntRect(aDetails.rect());
|
||||
mRectDisplayPix = nsIntRect(aDetails.rectDisplayPix());
|
||||
mAvailRect = nsIntRect(aDetails.availRect());
|
||||
mAvailRectDisplayPix = nsIntRect(aDetails.availRectDisplayPix());
|
||||
mPixelDepth = aDetails.pixelDepth();
|
||||
mColorDepth = aDetails.colorDepth();
|
||||
mContentsScaleFactor = aDetails.contentsScaleFactor();
|
||||
}
|
||||
|
||||
bool
|
||||
ScreenProxy::EnsureCacheIsValid()
|
||||
{
|
||||
if (mCacheValid) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
// Kick off a synchronous IPC call to the parent to get the
|
||||
// most up-to-date information.
|
||||
ScreenDetails details;
|
||||
Unused << mScreenManager->SendScreenRefresh(mId, &details, &success);
|
||||
if (!success) {
|
||||
NS_WARNING("Updating a ScreenProxy in the child process failed on parent side.");
|
||||
return false;
|
||||
}
|
||||
|
||||
PopulateByDetails(details);
|
||||
mCacheValid = true;
|
||||
|
||||
InvalidateCacheOnNextTick();
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ScreenProxy::InvalidateCacheOnNextTick()
|
||||
{
|
||||
if (mCacheWillInvalidate) {
|
||||
return;
|
||||
}
|
||||
|
||||
mCacheWillInvalidate = true;
|
||||
|
||||
nsContentUtils::RunInStableState(NewRunnableMethod(this, &ScreenProxy::InvalidateCache));
|
||||
}
|
||||
|
||||
void
|
||||
ScreenProxy::InvalidateCache()
|
||||
{
|
||||
mCacheValid = false;
|
||||
mCacheWillInvalidate = false;
|
||||
}
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
71
widget/ScreenProxy.h
Normal file
71
widget/ScreenProxy.h
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 2; -*- */
|
||||
/* vim: set sw=4 ts=8 et tw=80 : */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_widget_ScreenProxy_h
|
||||
#define mozilla_widget_ScreenProxy_h
|
||||
|
||||
#include "nsBaseScreen.h"
|
||||
#include "mozilla/dom/PScreenManagerChild.h"
|
||||
#include "mozilla/dom/TabChild.h"
|
||||
|
||||
class nsScreenManagerProxy;
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
class ScreenProxy : public nsBaseScreen
|
||||
{
|
||||
public:
|
||||
ScreenProxy(nsScreenManagerProxy* aScreenManager,
|
||||
mozilla::dom::ScreenDetails aDetails);
|
||||
~ScreenProxy() {};
|
||||
|
||||
NS_IMETHOD GetId(uint32_t* aId) override;
|
||||
|
||||
NS_IMETHOD GetRect(int32_t* aLeft,
|
||||
int32_t* aTop,
|
||||
int32_t* aWidth,
|
||||
int32_t* aHeight) override;
|
||||
NS_IMETHOD GetRectDisplayPix(int32_t* aLeft,
|
||||
int32_t* aTop,
|
||||
int32_t* aWidth,
|
||||
int32_t* aHeight) override;
|
||||
NS_IMETHOD GetAvailRect(int32_t* aLeft,
|
||||
int32_t* aTop,
|
||||
int32_t* aWidth,
|
||||
int32_t* aHeight) override;
|
||||
NS_IMETHOD GetAvailRectDisplayPix(int32_t* aLeft,
|
||||
int32_t* aTop,
|
||||
int32_t* aWidth,
|
||||
int32_t* aHeight) override;
|
||||
NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth) override;
|
||||
NS_IMETHOD GetColorDepth(int32_t* aColorDepth) override;
|
||||
|
||||
private:
|
||||
|
||||
void PopulateByDetails(mozilla::dom::ScreenDetails aDetails);
|
||||
bool EnsureCacheIsValid();
|
||||
void InvalidateCacheOnNextTick();
|
||||
void InvalidateCache();
|
||||
|
||||
double mContentsScaleFactor;
|
||||
RefPtr<nsScreenManagerProxy> mScreenManager;
|
||||
uint32_t mId;
|
||||
int32_t mPixelDepth;
|
||||
int32_t mColorDepth;
|
||||
nsIntRect mRect;
|
||||
nsIntRect mRectDisplayPix;
|
||||
nsIntRect mAvailRect;
|
||||
nsIntRect mAvailRectDisplayPix;
|
||||
bool mCacheValid;
|
||||
bool mCacheWillInvalidate;
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
||||
178
widget/SharedWidgetUtils.cpp
Normal file
178
widget/SharedWidgetUtils.cpp
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 "WidgetUtils.h"
|
||||
|
||||
#include "mozilla/TextEvents.h"
|
||||
|
||||
#include "nsIBaseWindow.h"
|
||||
#include "nsIDocShellTreeItem.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
// static
|
||||
void
|
||||
WidgetUtils::Shutdown()
|
||||
{
|
||||
WidgetKeyboardEvent::Shutdown();
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<nsIWidget>
|
||||
WidgetUtils::DOMWindowToWidget(nsPIDOMWindowOuter* aDOMWindow)
|
||||
{
|
||||
nsCOMPtr<nsIWidget> widget;
|
||||
nsCOMPtr<nsPIDOMWindowOuter> window = aDOMWindow;
|
||||
|
||||
if (window) {
|
||||
nsCOMPtr<nsIBaseWindow> baseWin(do_QueryInterface(window->GetDocShell()));
|
||||
|
||||
while (!widget && baseWin) {
|
||||
baseWin->GetParentWidget(getter_AddRefs(widget));
|
||||
if (!widget) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(baseWin));
|
||||
if (!docShellAsItem)
|
||||
return nullptr;
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> parent;
|
||||
docShellAsItem->GetParent(getter_AddRefs(parent));
|
||||
|
||||
window = do_GetInterface(parent);
|
||||
if (!window)
|
||||
return nullptr;
|
||||
|
||||
baseWin = do_QueryInterface(window->GetDocShell());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return widget.forget();
|
||||
}
|
||||
|
||||
// static
|
||||
uint32_t
|
||||
WidgetUtils::ComputeKeyCodeFromChar(uint32_t aCharCode)
|
||||
{
|
||||
if (aCharCode >= 'A' && aCharCode <= 'Z') {
|
||||
return aCharCode - 'A' + NS_VK_A;
|
||||
}
|
||||
if (aCharCode >= 'a' && aCharCode <= 'z') {
|
||||
return aCharCode - 'a' + NS_VK_A;
|
||||
}
|
||||
if (aCharCode >= '0' && aCharCode <= '9') {
|
||||
return aCharCode - '0' + NS_VK_0;
|
||||
}
|
||||
switch (aCharCode) {
|
||||
case ' ': return NS_VK_SPACE;
|
||||
case '\t': return NS_VK_TAB;
|
||||
case ':': return NS_VK_COLON;
|
||||
case ';': return NS_VK_SEMICOLON;
|
||||
case '<': return NS_VK_LESS_THAN;
|
||||
case '=': return NS_VK_EQUALS;
|
||||
case '>': return NS_VK_GREATER_THAN;
|
||||
case '?': return NS_VK_QUESTION_MARK;
|
||||
case '@': return NS_VK_AT;
|
||||
case '^': return NS_VK_CIRCUMFLEX;
|
||||
case '!': return NS_VK_EXCLAMATION;
|
||||
case '"': return NS_VK_DOUBLE_QUOTE;
|
||||
case '#': return NS_VK_HASH;
|
||||
case '$': return NS_VK_DOLLAR;
|
||||
case '%': return NS_VK_PERCENT;
|
||||
case '&': return NS_VK_AMPERSAND;
|
||||
case '_': return NS_VK_UNDERSCORE;
|
||||
case '(': return NS_VK_OPEN_PAREN;
|
||||
case ')': return NS_VK_CLOSE_PAREN;
|
||||
case '*': return NS_VK_ASTERISK;
|
||||
case '+': return NS_VK_PLUS;
|
||||
case '|': return NS_VK_PIPE;
|
||||
case '-': return NS_VK_HYPHEN_MINUS;
|
||||
case '{': return NS_VK_OPEN_CURLY_BRACKET;
|
||||
case '}': return NS_VK_CLOSE_CURLY_BRACKET;
|
||||
case '~': return NS_VK_TILDE;
|
||||
case ',': return NS_VK_COMMA;
|
||||
case '.': return NS_VK_PERIOD;
|
||||
case '/': return NS_VK_SLASH;
|
||||
case '`': return NS_VK_BACK_QUOTE;
|
||||
case '[': return NS_VK_OPEN_BRACKET;
|
||||
case '\\': return NS_VK_BACK_SLASH;
|
||||
case ']': return NS_VK_CLOSE_BRACKET;
|
||||
case '\'': return NS_VK_QUOTE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
WidgetUtils::GetLatinCharCodeForKeyCode(uint32_t aKeyCode,
|
||||
bool aIsCapsLock,
|
||||
uint32_t* aUnshiftedCharCode,
|
||||
uint32_t* aShiftedCharCode)
|
||||
{
|
||||
MOZ_ASSERT(aUnshiftedCharCode && aShiftedCharCode,
|
||||
"aUnshiftedCharCode and aShiftedCharCode must not be NULL");
|
||||
|
||||
if (aKeyCode >= NS_VK_A && aKeyCode <= NS_VK_Z) {
|
||||
*aUnshiftedCharCode = *aShiftedCharCode = aKeyCode;
|
||||
if (aIsCapsLock) {
|
||||
*aShiftedCharCode += 0x20;
|
||||
} else {
|
||||
*aUnshiftedCharCode += 0x20;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// aShiftedCharCode must be zero for non-alphabet keys.
|
||||
*aShiftedCharCode = 0;
|
||||
|
||||
if (aKeyCode >= NS_VK_0 && aKeyCode <= NS_VK_9) {
|
||||
*aUnshiftedCharCode = aKeyCode;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (aKeyCode) {
|
||||
case NS_VK_SPACE: *aUnshiftedCharCode = ' '; break;
|
||||
case NS_VK_COLON: *aUnshiftedCharCode = ':'; break;
|
||||
case NS_VK_SEMICOLON: *aUnshiftedCharCode = ';'; break;
|
||||
case NS_VK_LESS_THAN: *aUnshiftedCharCode = '<'; break;
|
||||
case NS_VK_EQUALS: *aUnshiftedCharCode = '='; break;
|
||||
case NS_VK_GREATER_THAN: *aUnshiftedCharCode = '>'; break;
|
||||
case NS_VK_QUESTION_MARK: *aUnshiftedCharCode = '?'; break;
|
||||
case NS_VK_AT: *aUnshiftedCharCode = '@'; break;
|
||||
case NS_VK_CIRCUMFLEX: *aUnshiftedCharCode = '^'; break;
|
||||
case NS_VK_EXCLAMATION: *aUnshiftedCharCode = '!'; break;
|
||||
case NS_VK_DOUBLE_QUOTE: *aUnshiftedCharCode = '"'; break;
|
||||
case NS_VK_HASH: *aUnshiftedCharCode = '#'; break;
|
||||
case NS_VK_DOLLAR: *aUnshiftedCharCode = '$'; break;
|
||||
case NS_VK_PERCENT: *aUnshiftedCharCode = '%'; break;
|
||||
case NS_VK_AMPERSAND: *aUnshiftedCharCode = '&'; break;
|
||||
case NS_VK_UNDERSCORE: *aUnshiftedCharCode = '_'; break;
|
||||
case NS_VK_OPEN_PAREN: *aUnshiftedCharCode = '('; break;
|
||||
case NS_VK_CLOSE_PAREN: *aUnshiftedCharCode = ')'; break;
|
||||
case NS_VK_ASTERISK: *aUnshiftedCharCode = '*'; break;
|
||||
case NS_VK_PLUS: *aUnshiftedCharCode = '+'; break;
|
||||
case NS_VK_PIPE: *aUnshiftedCharCode = '|'; break;
|
||||
case NS_VK_HYPHEN_MINUS: *aUnshiftedCharCode = '-'; break;
|
||||
case NS_VK_OPEN_CURLY_BRACKET: *aUnshiftedCharCode = '{'; break;
|
||||
case NS_VK_CLOSE_CURLY_BRACKET: *aUnshiftedCharCode = '}'; break;
|
||||
case NS_VK_TILDE: *aUnshiftedCharCode = '~'; break;
|
||||
case NS_VK_COMMA: *aUnshiftedCharCode = ','; break;
|
||||
case NS_VK_PERIOD: *aUnshiftedCharCode = '.'; break;
|
||||
case NS_VK_SLASH: *aUnshiftedCharCode = '/'; break;
|
||||
case NS_VK_BACK_QUOTE: *aUnshiftedCharCode = '`'; break;
|
||||
case NS_VK_OPEN_BRACKET: *aUnshiftedCharCode = '['; break;
|
||||
case NS_VK_BACK_SLASH: *aUnshiftedCharCode = '\\'; break;
|
||||
case NS_VK_CLOSE_BRACKET: *aUnshiftedCharCode = ']'; break;
|
||||
case NS_VK_QUOTE: *aUnshiftedCharCode = '\''; break;
|
||||
default: *aUnshiftedCharCode = 0; break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
231
widget/SystemTimeConverter.h
Normal file
231
widget/SystemTimeConverter.h
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef SystemTimeConverter_h
|
||||
#define SystemTimeConverter_h
|
||||
|
||||
#include <limits>
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Utility class that converts time values represented as an unsigned integral
|
||||
// number of milliseconds from one time source (e.g. a native event time) to
|
||||
// corresponding mozilla::TimeStamp objects.
|
||||
//
|
||||
// This class handles wrapping of integer values and skew between the time
|
||||
// source and mozilla::TimeStamp values.
|
||||
//
|
||||
// It does this by using an historical reference time recorded in both time
|
||||
// scales (i.e. both as a numerical time value and as a TimeStamp).
|
||||
//
|
||||
// For performance reasons, this class is careful to minimize calls to the
|
||||
// native "current time" function (e.g. gdk_x11_server_get_time) since this can
|
||||
// be slow.
|
||||
template <typename Time>
|
||||
class SystemTimeConverter {
|
||||
public:
|
||||
SystemTimeConverter()
|
||||
: mReferenceTime(Time(0))
|
||||
, mReferenceTimeStamp() // Initializes to the null timestamp
|
||||
, mLastBackwardsSkewCheck(Time(0))
|
||||
, kTimeRange(std::numeric_limits<Time>::max())
|
||||
, kTimeHalfRange(kTimeRange / 2)
|
||||
, kBackwardsSkewCheckInterval(Time(2000))
|
||||
{
|
||||
static_assert(!IsSigned<Time>::value, "Expected Time to be unsigned");
|
||||
}
|
||||
|
||||
template <typename CurrentTimeGetter>
|
||||
mozilla::TimeStamp
|
||||
GetTimeStampFromSystemTime(Time aTime,
|
||||
CurrentTimeGetter& aCurrentTimeGetter) {
|
||||
// If the reference time is not set, use the current time value to fill
|
||||
// it in.
|
||||
if (mReferenceTimeStamp.IsNull()) {
|
||||
UpdateReferenceTime(aTime, aCurrentTimeGetter);
|
||||
}
|
||||
TimeStamp roughlyNow = TimeStamp::Now();
|
||||
|
||||
// Check for skew between the source of Time values and TimeStamp values.
|
||||
// We do this by comparing two durations (both in ms):
|
||||
//
|
||||
// i. The duration from the reference time to the passed-in time.
|
||||
// (timeDelta in the diagram below)
|
||||
// ii. The duration from the reference timestamp to the current time
|
||||
// based on TimeStamp::Now.
|
||||
// (timeStampDelta in the diagram below)
|
||||
//
|
||||
// Normally, we'd expect (ii) to be slightly larger than (i) to account
|
||||
// for the time taken between generating the event and processing it.
|
||||
//
|
||||
// If (ii) - (i) is negative then the source of Time values is getting
|
||||
// "ahead" of TimeStamp. We call this "forwards" skew below.
|
||||
//
|
||||
// For the reverse case, if (ii) - (i) is positive (and greater than some
|
||||
// tolerance factor), then we may have "backwards" skew. This is often
|
||||
// the case when we have a backlog of events and by the time we process
|
||||
// them, the time given by the system is comparatively "old".
|
||||
//
|
||||
// We call the absolute difference between (i) and (ii), "deltaFromNow".
|
||||
//
|
||||
// Graphically:
|
||||
//
|
||||
// mReferenceTime aTime
|
||||
// Time scale: ........+.......................*........
|
||||
// |--------timeDelta------|
|
||||
//
|
||||
// mReferenceTimeStamp roughlyNow
|
||||
// TimeStamp scale: ........+...........................*....
|
||||
// |------timeStampDelta-------|
|
||||
//
|
||||
// |---|
|
||||
// deltaFromNow
|
||||
//
|
||||
Time deltaFromNow;
|
||||
bool newer = IsTimeNewerThanTimestamp(aTime, roughlyNow, &deltaFromNow);
|
||||
|
||||
// Tolerance when detecting clock skew.
|
||||
static const Time kTolerance = 30;
|
||||
|
||||
// Check for forwards skew
|
||||
if (newer) {
|
||||
// Make aTime correspond to roughlyNow
|
||||
UpdateReferenceTime(aTime, roughlyNow);
|
||||
|
||||
// We didn't have backwards skew so don't bother checking for
|
||||
// backwards skew again for a little while.
|
||||
mLastBackwardsSkewCheck = aTime;
|
||||
|
||||
return roughlyNow;
|
||||
}
|
||||
|
||||
if (deltaFromNow <= kTolerance) {
|
||||
// If the time between event times and TimeStamp values is within
|
||||
// the tolerance then assume we don't have clock skew so we can
|
||||
// avoid checking for backwards skew for a while.
|
||||
mLastBackwardsSkewCheck = aTime;
|
||||
} else if (aTime - mLastBackwardsSkewCheck > kBackwardsSkewCheckInterval) {
|
||||
aCurrentTimeGetter.GetTimeAsyncForPossibleBackwardsSkew(roughlyNow);
|
||||
mLastBackwardsSkewCheck = aTime;
|
||||
}
|
||||
|
||||
// Finally, calculate the timestamp
|
||||
return roughlyNow - TimeDuration::FromMilliseconds(deltaFromNow);
|
||||
}
|
||||
|
||||
void
|
||||
CompensateForBackwardsSkew(Time aReferenceTime,
|
||||
const TimeStamp &aLowerBound) {
|
||||
// Check if we actually have backwards skew. Backwards skew looks like
|
||||
// the following:
|
||||
//
|
||||
// mReferenceTime
|
||||
// Time: ..+...a...b...c..........................
|
||||
//
|
||||
// mReferenceTimeStamp
|
||||
// TimeStamp: ..+.....a.....b.....c....................
|
||||
//
|
||||
// Converted
|
||||
// time: ......a'..b'..c'.........................
|
||||
//
|
||||
// What we need to do is bring mReferenceTime "forwards".
|
||||
//
|
||||
// Suppose when we get (c), we detect possible backwards skew and trigger
|
||||
// an async request for the current time (which is passed in here as
|
||||
// aReferenceTime).
|
||||
//
|
||||
// We end up with something like the following:
|
||||
//
|
||||
// mReferenceTime aReferenceTime
|
||||
// Time: ..+...a...b...c...v......................
|
||||
//
|
||||
// mReferenceTimeStamp
|
||||
// TimeStamp: ..+.....a.....b.....c..........x.........
|
||||
// ^ ^
|
||||
// aLowerBound TimeStamp::Now()
|
||||
//
|
||||
// If the duration (aLowerBound - mReferenceTimeStamp) is greater than
|
||||
// (aReferenceTime - mReferenceTime) then we know we have backwards skew.
|
||||
//
|
||||
// If that's not the case, then we probably just got caught behind
|
||||
// temporarily.
|
||||
Time delta;
|
||||
if (IsTimeNewerThanTimestamp(aReferenceTime, aLowerBound, &delta)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We have backwards skew; the equivalent TimeStamp for aReferenceTime lies
|
||||
// somewhere between aLowerBound (which was the TimeStamp when we triggered
|
||||
// the async request for the current time) and TimeStamp::Now().
|
||||
//
|
||||
// If aReferenceTime was waiting in the event queue for a long time, the
|
||||
// equivalent TimeStamp might be much closer to aLowerBound than
|
||||
// TimeStamp::Now() so for now we just set it to aLowerBound. That's
|
||||
// guaranteed to be at least somewhat of an improvement.
|
||||
UpdateReferenceTime(aReferenceTime, aLowerBound);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename CurrentTimeGetter>
|
||||
void
|
||||
UpdateReferenceTime(Time aReferenceTime,
|
||||
const CurrentTimeGetter& aCurrentTimeGetter) {
|
||||
Time currentTime = aCurrentTimeGetter.GetCurrentTime();
|
||||
TimeStamp currentTimeStamp = TimeStamp::Now();
|
||||
Time timeSinceReference = currentTime - aReferenceTime;
|
||||
TimeStamp referenceTimeStamp =
|
||||
currentTimeStamp - TimeDuration::FromMilliseconds(timeSinceReference);
|
||||
UpdateReferenceTime(aReferenceTime, referenceTimeStamp);
|
||||
}
|
||||
|
||||
void
|
||||
UpdateReferenceTime(Time aReferenceTime,
|
||||
const TimeStamp& aReferenceTimeStamp) {
|
||||
mReferenceTime = aReferenceTime;
|
||||
mReferenceTimeStamp = aReferenceTimeStamp;
|
||||
}
|
||||
|
||||
bool
|
||||
IsTimeNewerThanTimestamp(Time aTime, TimeStamp aTimeStamp, Time* aDelta)
|
||||
{
|
||||
Time timeDelta = aTime - mReferenceTime;
|
||||
|
||||
// Cast the result to signed 64-bit integer first since that should be
|
||||
// enough to hold the range of values returned by ToMilliseconds() and
|
||||
// the result of converting from double to an integer-type when the value
|
||||
// is outside the integer range is undefined.
|
||||
// Then we do an implicit cast to Time (typically an unsigned 32-bit
|
||||
// integer) which wraps times outside that range.
|
||||
Time timeStampDelta =
|
||||
static_cast<int64_t>((aTimeStamp - mReferenceTimeStamp).ToMilliseconds());
|
||||
|
||||
Time timeToTimeStamp = timeStampDelta - timeDelta;
|
||||
bool isNewer = false;
|
||||
if (timeToTimeStamp == 0) {
|
||||
*aDelta = 0;
|
||||
} else if (timeToTimeStamp < kTimeHalfRange) {
|
||||
*aDelta = timeToTimeStamp;
|
||||
} else {
|
||||
isNewer = true;
|
||||
*aDelta = timeDelta - timeStampDelta;
|
||||
}
|
||||
|
||||
return isNewer;
|
||||
}
|
||||
|
||||
Time mReferenceTime;
|
||||
TimeStamp mReferenceTimeStamp;
|
||||
Time mLastBackwardsSkewCheck;
|
||||
|
||||
const Time kTimeRange;
|
||||
const Time kTimeHalfRange;
|
||||
const Time kBackwardsSkewCheckInterval;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* SystemTimeConverter_h */
|
||||
780
widget/TextEventDispatcher.cpp
Normal file
780
widget/TextEventDispatcher.cpp
Normal file
|
|
@ -0,0 +1,780 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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 "mozilla/Preferences.h"
|
||||
#include "mozilla/TextEvents.h"
|
||||
#include "mozilla/TextEventDispatcher.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsView.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
/******************************************************************************
|
||||
* TextEventDispatcher
|
||||
*****************************************************************************/
|
||||
|
||||
bool TextEventDispatcher::sDispatchKeyEventsDuringComposition = false;
|
||||
|
||||
TextEventDispatcher::TextEventDispatcher(nsIWidget* aWidget)
|
||||
: mWidget(aWidget)
|
||||
, mDispatchingEvent(0)
|
||||
, mInputTransactionType(eNoInputTransaction)
|
||||
, mIsComposing(false)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(mWidget, "aWidget must not be nullptr");
|
||||
|
||||
static bool sInitialized = false;
|
||||
if (!sInitialized) {
|
||||
Preferences::AddBoolVarCache(
|
||||
&sDispatchKeyEventsDuringComposition,
|
||||
"dom.keyboardevent.dispatch_during_composition",
|
||||
false);
|
||||
sInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
TextEventDispatcher::BeginInputTransaction(
|
||||
TextEventDispatcherListener* aListener)
|
||||
{
|
||||
return BeginInputTransactionInternal(aListener,
|
||||
eSameProcessSyncInputTransaction);
|
||||
}
|
||||
|
||||
nsresult
|
||||
TextEventDispatcher::BeginTestInputTransaction(
|
||||
TextEventDispatcherListener* aListener,
|
||||
bool aIsAPZAware)
|
||||
{
|
||||
return BeginInputTransactionInternal(aListener,
|
||||
aIsAPZAware ? eAsyncTestInputTransaction :
|
||||
eSameProcessSyncTestInputTransaction);
|
||||
}
|
||||
|
||||
nsresult
|
||||
TextEventDispatcher::BeginNativeInputTransaction()
|
||||
{
|
||||
if (NS_WARN_IF(!mWidget)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
RefPtr<TextEventDispatcherListener> listener =
|
||||
mWidget->GetNativeTextEventDispatcherListener();
|
||||
if (NS_WARN_IF(!listener)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return BeginInputTransactionInternal(listener, eNativeInputTransaction);
|
||||
}
|
||||
|
||||
nsresult
|
||||
TextEventDispatcher::BeginInputTransactionInternal(
|
||||
TextEventDispatcherListener* aListener,
|
||||
InputTransactionType aType)
|
||||
{
|
||||
if (NS_WARN_IF(!aListener)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
nsCOMPtr<TextEventDispatcherListener> listener = do_QueryReferent(mListener);
|
||||
if (listener) {
|
||||
if (listener == aListener && mInputTransactionType == aType) {
|
||||
return NS_OK;
|
||||
}
|
||||
// If this has composition or is dispatching an event, any other listener
|
||||
// can steal ownership. Especially, if the latter case is allowed,
|
||||
// nobody cannot begin input transaction with this if a modal dialog is
|
||||
// opened during dispatching an event.
|
||||
if (IsComposing() || IsDispatchingEvent()) {
|
||||
return NS_ERROR_ALREADY_INITIALIZED;
|
||||
}
|
||||
}
|
||||
mListener = do_GetWeakReference(aListener);
|
||||
mInputTransactionType = aType;
|
||||
if (listener && listener != aListener) {
|
||||
listener->OnRemovedFrom(this);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
TextEventDispatcher::EndInputTransaction(TextEventDispatcherListener* aListener)
|
||||
{
|
||||
if (NS_WARN_IF(IsComposing()) || NS_WARN_IF(IsDispatchingEvent())) {
|
||||
return;
|
||||
}
|
||||
|
||||
mInputTransactionType = eNoInputTransaction;
|
||||
|
||||
nsCOMPtr<TextEventDispatcherListener> listener = do_QueryReferent(mListener);
|
||||
if (NS_WARN_IF(!listener)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(listener != aListener)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mListener = nullptr;
|
||||
listener->OnRemovedFrom(this);
|
||||
}
|
||||
|
||||
void
|
||||
TextEventDispatcher::OnDestroyWidget()
|
||||
{
|
||||
mWidget = nullptr;
|
||||
mPendingComposition.Clear();
|
||||
nsCOMPtr<TextEventDispatcherListener> listener = do_QueryReferent(mListener);
|
||||
mListener = nullptr;
|
||||
mInputTransactionType = eNoInputTransaction;
|
||||
if (listener) {
|
||||
listener->OnRemovedFrom(this);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
TextEventDispatcher::GetState() const
|
||||
{
|
||||
nsCOMPtr<TextEventDispatcherListener> listener = do_QueryReferent(mListener);
|
||||
if (!listener) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
if (!mWidget || mWidget->Destroyed()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
TextEventDispatcher::InitEvent(WidgetGUIEvent& aEvent) const
|
||||
{
|
||||
aEvent.mTime = PR_IntervalNow();
|
||||
aEvent.mRefPoint = LayoutDeviceIntPoint(0, 0);
|
||||
aEvent.mFlags.mIsSynthesizedForTests = IsForTests();
|
||||
if (aEvent.mClass != eCompositionEventClass) {
|
||||
return;
|
||||
}
|
||||
void* pseudoIMEContext = GetPseudoIMEContext();
|
||||
if (pseudoIMEContext) {
|
||||
aEvent.AsCompositionEvent()->mNativeIMEContext.
|
||||
InitWithRawNativeIMEContext(pseudoIMEContext);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
MOZ_ASSERT(!XRE_IsContentProcess(),
|
||||
"Why did the content process start native event transaction?");
|
||||
MOZ_ASSERT(aEvent.AsCompositionEvent()->mNativeIMEContext.IsValid(),
|
||||
"Native IME context shouldn't be invalid");
|
||||
}
|
||||
#endif // #ifdef DEBUG
|
||||
}
|
||||
|
||||
nsresult
|
||||
TextEventDispatcher::DispatchEvent(nsIWidget* aWidget,
|
||||
WidgetGUIEvent& aEvent,
|
||||
nsEventStatus& aStatus)
|
||||
{
|
||||
MOZ_ASSERT(!aEvent.AsInputEvent(), "Use DispatchInputEvent()");
|
||||
|
||||
RefPtr<TextEventDispatcher> kungFuDeathGrip(this);
|
||||
nsCOMPtr<nsIWidget> widget(aWidget);
|
||||
mDispatchingEvent++;
|
||||
nsresult rv = widget->DispatchEvent(&aEvent, aStatus);
|
||||
mDispatchingEvent--;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TextEventDispatcher::DispatchInputEvent(nsIWidget* aWidget,
|
||||
WidgetInputEvent& aEvent,
|
||||
nsEventStatus& aStatus)
|
||||
{
|
||||
RefPtr<TextEventDispatcher> kungFuDeathGrip(this);
|
||||
nsCOMPtr<nsIWidget> widget(aWidget);
|
||||
mDispatchingEvent++;
|
||||
|
||||
// If the event is dispatched via nsIWidget::DispatchInputEvent(), it
|
||||
// sends the event to the parent process first since APZ needs to handle it
|
||||
// first. However, some callers (e.g., keyboard apps on B2G and tests
|
||||
// expecting synchronous dispatch) don't want this to do that.
|
||||
nsresult rv = NS_OK;
|
||||
if (ShouldSendInputEventToAPZ()) {
|
||||
aStatus = widget->DispatchInputEvent(&aEvent);
|
||||
} else {
|
||||
rv = widget->DispatchEvent(&aEvent, aStatus);
|
||||
}
|
||||
|
||||
mDispatchingEvent--;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TextEventDispatcher::StartComposition(nsEventStatus& aStatus,
|
||||
const WidgetEventTime* aEventTime)
|
||||
{
|
||||
aStatus = nsEventStatus_eIgnore;
|
||||
|
||||
nsresult rv = GetState();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(mIsComposing)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mIsComposing = true;
|
||||
WidgetCompositionEvent compositionStartEvent(true, eCompositionStart,
|
||||
mWidget);
|
||||
InitEvent(compositionStartEvent);
|
||||
if (aEventTime) {
|
||||
compositionStartEvent.AssignEventTime(*aEventTime);
|
||||
}
|
||||
rv = DispatchEvent(mWidget, compositionStartEvent, aStatus);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TextEventDispatcher::StartCompositionAutomaticallyIfNecessary(
|
||||
nsEventStatus& aStatus,
|
||||
const WidgetEventTime* aEventTime)
|
||||
{
|
||||
if (IsComposing()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = StartComposition(aStatus, aEventTime);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// If started composition has already been committed, we shouldn't dispatch
|
||||
// the compositionchange event.
|
||||
if (!IsComposing()) {
|
||||
aStatus = nsEventStatus_eConsumeNoDefault;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Note that the widget might be destroyed during a call of
|
||||
// StartComposition(). In such case, we shouldn't keep dispatching next
|
||||
// event.
|
||||
rv = GetState();
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_ASSERT(rv != NS_ERROR_NOT_INITIALIZED,
|
||||
"aDispatcher must still be initialized in this case");
|
||||
aStatus = nsEventStatus_eConsumeNoDefault;
|
||||
return NS_OK; // Don't throw exception in this case
|
||||
}
|
||||
|
||||
aStatus = nsEventStatus_eIgnore;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TextEventDispatcher::CommitComposition(nsEventStatus& aStatus,
|
||||
const nsAString* aCommitString,
|
||||
const WidgetEventTime* aEventTime)
|
||||
{
|
||||
aStatus = nsEventStatus_eIgnore;
|
||||
|
||||
nsresult rv = GetState();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// When there is no composition, caller shouldn't try to commit composition
|
||||
// with non-existing composition string nor commit composition with empty
|
||||
// string.
|
||||
if (NS_WARN_IF(!IsComposing() &&
|
||||
(!aCommitString || aCommitString->IsEmpty()))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWidget> widget(mWidget);
|
||||
rv = StartCompositionAutomaticallyIfNecessary(aStatus, aEventTime);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
if (aStatus == nsEventStatus_eConsumeNoDefault) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// End current composition and make this free for other IMEs.
|
||||
mIsComposing = false;
|
||||
|
||||
EventMessage message = aCommitString ? eCompositionCommit :
|
||||
eCompositionCommitAsIs;
|
||||
WidgetCompositionEvent compositionCommitEvent(true, message, widget);
|
||||
InitEvent(compositionCommitEvent);
|
||||
if (aEventTime) {
|
||||
compositionCommitEvent.AssignEventTime(*aEventTime);
|
||||
}
|
||||
if (message == eCompositionCommit) {
|
||||
compositionCommitEvent.mData = *aCommitString;
|
||||
// Don't send CRLF, replace it with LF here.
|
||||
compositionCommitEvent.mData.ReplaceSubstring(NS_LITERAL_STRING("\r\n"),
|
||||
NS_LITERAL_STRING("\n"));
|
||||
}
|
||||
rv = DispatchEvent(widget, compositionCommitEvent, aStatus);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TextEventDispatcher::NotifyIME(const IMENotification& aIMENotification)
|
||||
{
|
||||
nsresult rv = NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
// First, send the notification to current input transaction's listener.
|
||||
nsCOMPtr<TextEventDispatcherListener> listener = do_QueryReferent(mListener);
|
||||
if (listener) {
|
||||
rv = listener->NotifyIME(this, aIMENotification);
|
||||
}
|
||||
|
||||
if (mInputTransactionType == eNativeInputTransaction || !mWidget) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// If current input transaction isn't for native event handler, we should
|
||||
// send the notification to the native text event dispatcher listener
|
||||
// since native event handler may need to do something from
|
||||
// TextEventDispatcherListener::NotifyIME() even before there is no
|
||||
// input transaction yet. For example, native IME handler may need to
|
||||
// create new context at receiving NOTIFY_IME_OF_FOCUS. In this case,
|
||||
// mListener may not be initialized since input transaction should be
|
||||
// initialized immediately before dispatching every WidgetKeyboardEvent
|
||||
// and WidgetCompositionEvent (dispatching events always occurs after
|
||||
// focus move).
|
||||
nsCOMPtr<TextEventDispatcherListener> nativeListener =
|
||||
mWidget->GetNativeTextEventDispatcherListener();
|
||||
if (!nativeListener) {
|
||||
return rv;
|
||||
}
|
||||
switch (aIMENotification.mMessage) {
|
||||
case REQUEST_TO_COMMIT_COMPOSITION:
|
||||
case REQUEST_TO_CANCEL_COMPOSITION:
|
||||
// It's not necessary to notify native IME of requests.
|
||||
return rv;
|
||||
default: {
|
||||
// Even if current input transaction's listener returns NS_OK or
|
||||
// something, we need to notify native IME of notifications because
|
||||
// when user typing after TIP does something, the changed information
|
||||
// is necessary for them.
|
||||
nsresult rv2 =
|
||||
nativeListener->NotifyIME(this, aIMENotification);
|
||||
// But return the result from current listener except when the
|
||||
// notification isn't handled.
|
||||
return rv == NS_ERROR_NOT_IMPLEMENTED ? rv2 : rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
TextEventDispatcher::DispatchKeyboardEvent(
|
||||
EventMessage aMessage,
|
||||
const WidgetKeyboardEvent& aKeyboardEvent,
|
||||
nsEventStatus& aStatus,
|
||||
void* aData)
|
||||
{
|
||||
return DispatchKeyboardEventInternal(aMessage, aKeyboardEvent, aStatus,
|
||||
aData);
|
||||
}
|
||||
|
||||
bool
|
||||
TextEventDispatcher::DispatchKeyboardEventInternal(
|
||||
EventMessage aMessage,
|
||||
const WidgetKeyboardEvent& aKeyboardEvent,
|
||||
nsEventStatus& aStatus,
|
||||
void* aData,
|
||||
uint32_t aIndexOfKeypress,
|
||||
bool aNeedsCallback)
|
||||
{
|
||||
// Note that this method is also used for dispatching key events on a plugin
|
||||
// because key events on a plugin should be dispatched same as normal key
|
||||
// events. Then, only some handlers which need to intercept key events
|
||||
// before the focused plugin (e.g., reserved shortcut key handlers) can
|
||||
// consume the events.
|
||||
MOZ_ASSERT(WidgetKeyboardEvent::IsKeyDownOrKeyDownOnPlugin(aMessage) ||
|
||||
WidgetKeyboardEvent::IsKeyUpOrKeyUpOnPlugin(aMessage) ||
|
||||
aMessage == eKeyPress, "Invalid aMessage value");
|
||||
nsresult rv = GetState();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the key shouldn't cause keypress events, don't this patch them.
|
||||
if (aMessage == eKeyPress && !aKeyboardEvent.ShouldCauseKeypressEvents()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Basically, key events shouldn't be dispatched during composition.
|
||||
// Note that plugin process has different IME context. Therefore, we don't
|
||||
// need to check our composition state when the key event is fired on a
|
||||
// plugin.
|
||||
if (IsComposing() && !WidgetKeyboardEvent::IsKeyEventOnPlugin(aMessage)) {
|
||||
// However, if we need to behave like other browsers, we need the keydown
|
||||
// and keyup events. Note that this behavior is also allowed by D3E spec.
|
||||
// FYI: keypress events must not be fired during composition.
|
||||
if (!sDispatchKeyEventsDuringComposition || aMessage == eKeyPress) {
|
||||
return false;
|
||||
}
|
||||
// XXX If there was mOnlyContentDispatch for this case, it might be useful
|
||||
// because our chrome doesn't assume that key events are fired during
|
||||
// composition.
|
||||
}
|
||||
|
||||
WidgetKeyboardEvent keyEvent(true, aMessage, mWidget);
|
||||
InitEvent(keyEvent);
|
||||
keyEvent.AssignKeyEventData(aKeyboardEvent, false);
|
||||
|
||||
if (aStatus == nsEventStatus_eConsumeNoDefault) {
|
||||
// If the key event should be dispatched as consumed event, marking it here.
|
||||
// This is useful to prevent double action. E.g., when the key was already
|
||||
// handled by system, our chrome shouldn't handle it.
|
||||
keyEvent.PreventDefaultBeforeDispatch();
|
||||
}
|
||||
|
||||
// Corrects each member for the specific key event type.
|
||||
if (keyEvent.mKeyNameIndex != KEY_NAME_INDEX_USE_STRING) {
|
||||
MOZ_ASSERT(!aIndexOfKeypress,
|
||||
"aIndexOfKeypress must be 0 for non-printable key");
|
||||
// If the keyboard event isn't caused by printable key, its charCode should
|
||||
// be 0.
|
||||
keyEvent.SetCharCode(0);
|
||||
} else {
|
||||
if (WidgetKeyboardEvent::IsKeyDownOrKeyDownOnPlugin(aMessage) ||
|
||||
WidgetKeyboardEvent::IsKeyUpOrKeyUpOnPlugin(aMessage)) {
|
||||
MOZ_RELEASE_ASSERT(!aIndexOfKeypress,
|
||||
"aIndexOfKeypress must be 0 for either eKeyDown or eKeyUp");
|
||||
} else {
|
||||
MOZ_RELEASE_ASSERT(
|
||||
!aIndexOfKeypress || aIndexOfKeypress < keyEvent.mKeyValue.Length(),
|
||||
"aIndexOfKeypress must be 0 - mKeyValue.Length() - 1");
|
||||
}
|
||||
wchar_t ch =
|
||||
keyEvent.mKeyValue.IsEmpty() ? 0 : keyEvent.mKeyValue[aIndexOfKeypress];
|
||||
keyEvent.SetCharCode(static_cast<uint32_t>(ch));
|
||||
if (aMessage == eKeyPress) {
|
||||
// keyCode of eKeyPress events of printable keys should be always 0.
|
||||
keyEvent.mKeyCode = 0;
|
||||
// eKeyPress events are dispatched for every character.
|
||||
// So, each key value of eKeyPress events should be a character.
|
||||
if (ch) {
|
||||
keyEvent.mKeyValue.Assign(ch);
|
||||
} else {
|
||||
keyEvent.mKeyValue.Truncate();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (WidgetKeyboardEvent::IsKeyUpOrKeyUpOnPlugin(aMessage)) {
|
||||
// mIsRepeat of keyup event must be false.
|
||||
keyEvent.mIsRepeat = false;
|
||||
}
|
||||
// mIsComposing should be initialized later.
|
||||
keyEvent.mIsComposing = false;
|
||||
if (mInputTransactionType == eNativeInputTransaction) {
|
||||
// Copy mNativeKeyEvent here because for safety for other users of
|
||||
// AssignKeyEventData(), it doesn't copy this.
|
||||
keyEvent.mNativeKeyEvent = aKeyboardEvent.mNativeKeyEvent;
|
||||
} else {
|
||||
// If it's not a keyboard event for native key event, we should ensure that
|
||||
// mNativeKeyEvent and mPluginEvent are null/empty.
|
||||
keyEvent.mNativeKeyEvent = nullptr;
|
||||
keyEvent.mPluginEvent.Clear();
|
||||
}
|
||||
// TODO: Manage mUniqueId here.
|
||||
|
||||
// Request the alternative char codes for the key event.
|
||||
// eKeyDown also needs alternative char codes because nsXBLWindowKeyHandler
|
||||
// needs to check if a following keypress event is reserved by chrome for
|
||||
// stopping propagation of its preceding keydown event.
|
||||
keyEvent.mAlternativeCharCodes.Clear();
|
||||
if ((WidgetKeyboardEvent::IsKeyDownOrKeyDownOnPlugin(aMessage) ||
|
||||
aMessage == eKeyPress) &&
|
||||
(aNeedsCallback || keyEvent.IsControl() || keyEvent.IsAlt() ||
|
||||
keyEvent.IsMeta() || keyEvent.IsOS())) {
|
||||
nsCOMPtr<TextEventDispatcherListener> listener =
|
||||
do_QueryReferent(mListener);
|
||||
if (listener) {
|
||||
DebugOnly<WidgetKeyboardEvent> original(keyEvent);
|
||||
listener->WillDispatchKeyboardEvent(this, keyEvent, aIndexOfKeypress,
|
||||
aData);
|
||||
MOZ_ASSERT(keyEvent.mMessage ==
|
||||
static_cast<WidgetKeyboardEvent&>(original).mMessage);
|
||||
MOZ_ASSERT(keyEvent.mKeyCode ==
|
||||
static_cast<WidgetKeyboardEvent&>(original).mKeyCode);
|
||||
MOZ_ASSERT(keyEvent.mLocation ==
|
||||
static_cast<WidgetKeyboardEvent&>(original).mLocation);
|
||||
MOZ_ASSERT(keyEvent.mIsRepeat ==
|
||||
static_cast<WidgetKeyboardEvent&>(original).mIsRepeat);
|
||||
MOZ_ASSERT(keyEvent.mIsComposing ==
|
||||
static_cast<WidgetKeyboardEvent&>(original).mIsComposing);
|
||||
MOZ_ASSERT(keyEvent.mKeyNameIndex ==
|
||||
static_cast<WidgetKeyboardEvent&>(original).mKeyNameIndex);
|
||||
MOZ_ASSERT(keyEvent.mCodeNameIndex ==
|
||||
static_cast<WidgetKeyboardEvent&>(original).mCodeNameIndex);
|
||||
MOZ_ASSERT(keyEvent.mKeyValue ==
|
||||
static_cast<WidgetKeyboardEvent&>(original).mKeyValue);
|
||||
MOZ_ASSERT(keyEvent.mCodeValue ==
|
||||
static_cast<WidgetKeyboardEvent&>(original).mCodeValue);
|
||||
}
|
||||
}
|
||||
|
||||
DispatchInputEvent(mWidget, keyEvent, aStatus);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TextEventDispatcher::MaybeDispatchKeypressEvents(
|
||||
const WidgetKeyboardEvent& aKeyboardEvent,
|
||||
nsEventStatus& aStatus,
|
||||
void* aData,
|
||||
bool aNeedsCallback)
|
||||
{
|
||||
// If the key event was consumed, keypress event shouldn't be fired.
|
||||
if (aStatus == nsEventStatus_eConsumeNoDefault) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the key shouldn't cause keypress events, don't fire them.
|
||||
if (!aKeyboardEvent.ShouldCauseKeypressEvents()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the key isn't a printable key or just inputting one character or
|
||||
// no character, we should dispatch only one keypress. Otherwise, i.e.,
|
||||
// if the key is a printable key and inputs multiple characters, keypress
|
||||
// event should be dispatched the count of inputting characters times.
|
||||
size_t keypressCount =
|
||||
aKeyboardEvent.mKeyNameIndex != KEY_NAME_INDEX_USE_STRING ?
|
||||
1 : std::max(static_cast<nsAString::size_type>(1),
|
||||
aKeyboardEvent.mKeyValue.Length());
|
||||
bool isDispatched = false;
|
||||
bool consumed = false;
|
||||
for (size_t i = 0; i < keypressCount; i++) {
|
||||
aStatus = nsEventStatus_eIgnore;
|
||||
if (!DispatchKeyboardEventInternal(eKeyPress, aKeyboardEvent,
|
||||
aStatus, aData, i, aNeedsCallback)) {
|
||||
// The widget must have been gone.
|
||||
break;
|
||||
}
|
||||
isDispatched = true;
|
||||
if (!consumed) {
|
||||
consumed = (aStatus == nsEventStatus_eConsumeNoDefault);
|
||||
}
|
||||
}
|
||||
|
||||
// If one of the keypress event was consumed, return ConsumeNoDefault.
|
||||
if (consumed) {
|
||||
aStatus = nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
return isDispatched;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* TextEventDispatcher::PendingComposition
|
||||
*****************************************************************************/
|
||||
|
||||
TextEventDispatcher::PendingComposition::PendingComposition()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void
|
||||
TextEventDispatcher::PendingComposition::Clear()
|
||||
{
|
||||
mString.Truncate();
|
||||
mClauses = nullptr;
|
||||
mCaret.mRangeType = TextRangeType::eUninitialized;
|
||||
}
|
||||
|
||||
void
|
||||
TextEventDispatcher::PendingComposition::EnsureClauseArray()
|
||||
{
|
||||
if (mClauses) {
|
||||
return;
|
||||
}
|
||||
mClauses = new TextRangeArray();
|
||||
}
|
||||
|
||||
nsresult
|
||||
TextEventDispatcher::PendingComposition::SetString(const nsAString& aString)
|
||||
{
|
||||
mString = aString;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TextEventDispatcher::PendingComposition::AppendClause(
|
||||
uint32_t aLength,
|
||||
TextRangeType aTextRangeType)
|
||||
{
|
||||
if (NS_WARN_IF(!aLength)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
switch (aTextRangeType) {
|
||||
case TextRangeType::eRawClause:
|
||||
case TextRangeType::eSelectedRawClause:
|
||||
case TextRangeType::eConvertedClause:
|
||||
case TextRangeType::eSelectedClause: {
|
||||
EnsureClauseArray();
|
||||
TextRange textRange;
|
||||
textRange.mStartOffset =
|
||||
mClauses->IsEmpty() ? 0 : mClauses->LastElement().mEndOffset;
|
||||
textRange.mEndOffset = textRange.mStartOffset + aLength;
|
||||
textRange.mRangeType = aTextRangeType;
|
||||
mClauses->AppendElement(textRange);
|
||||
return NS_OK;
|
||||
}
|
||||
default:
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
TextEventDispatcher::PendingComposition::SetCaret(uint32_t aOffset,
|
||||
uint32_t aLength)
|
||||
{
|
||||
mCaret.mStartOffset = aOffset;
|
||||
mCaret.mEndOffset = mCaret.mStartOffset + aLength;
|
||||
mCaret.mRangeType = TextRangeType::eCaret;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TextEventDispatcher::PendingComposition::Set(const nsAString& aString,
|
||||
const TextRangeArray* aRanges)
|
||||
{
|
||||
Clear();
|
||||
|
||||
nsAutoString str(aString);
|
||||
// Don't expose CRLF to web contents, instead, use LF.
|
||||
str.ReplaceSubstring(NS_LITERAL_STRING("\r\n"), NS_LITERAL_STRING("\n"));
|
||||
nsresult rv = SetString(str);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!aRanges || aRanges->IsEmpty()) {
|
||||
// Create dummy range if aString isn't empty.
|
||||
if (!aString.IsEmpty()) {
|
||||
rv = AppendClause(str.Length(), TextRangeType::eRawClause);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Adjust offsets in the ranges for XP linefeed character (only \n).
|
||||
// XXX Following code is the safest approach. However, it wastes performance.
|
||||
// For ensuring the clauses do not overlap each other, we should redesign
|
||||
// TextRange later.
|
||||
for (uint32_t i = 0; i < aRanges->Length(); ++i) {
|
||||
TextRange range = aRanges->ElementAt(i);
|
||||
TextRange nativeRange = range;
|
||||
if (nativeRange.mStartOffset > 0) {
|
||||
nsAutoString preText(Substring(aString, 0, nativeRange.mStartOffset));
|
||||
preText.ReplaceSubstring(NS_LITERAL_STRING("\r\n"),
|
||||
NS_LITERAL_STRING("\n"));
|
||||
range.mStartOffset = preText.Length();
|
||||
}
|
||||
if (nativeRange.Length() == 0) {
|
||||
range.mEndOffset = range.mStartOffset;
|
||||
} else {
|
||||
nsAutoString clause(
|
||||
Substring(aString, nativeRange.mStartOffset, nativeRange.Length()));
|
||||
clause.ReplaceSubstring(NS_LITERAL_STRING("\r\n"),
|
||||
NS_LITERAL_STRING("\n"));
|
||||
range.mEndOffset = range.mStartOffset + clause.Length();
|
||||
}
|
||||
if (range.mRangeType == TextRangeType::eCaret) {
|
||||
mCaret = range;
|
||||
} else {
|
||||
EnsureClauseArray();
|
||||
mClauses->AppendElement(range);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TextEventDispatcher::PendingComposition::Flush(
|
||||
TextEventDispatcher* aDispatcher,
|
||||
nsEventStatus& aStatus,
|
||||
const WidgetEventTime* aEventTime)
|
||||
{
|
||||
aStatus = nsEventStatus_eIgnore;
|
||||
|
||||
nsresult rv = aDispatcher->GetState();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (mClauses && !mClauses->IsEmpty() &&
|
||||
mClauses->LastElement().mEndOffset != mString.Length()) {
|
||||
NS_WARNING("Sum of length of the all clauses must be same as the string "
|
||||
"length");
|
||||
Clear();
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
if (mCaret.mRangeType == TextRangeType::eCaret) {
|
||||
if (mCaret.mEndOffset > mString.Length()) {
|
||||
NS_WARNING("Caret position is out of the composition string");
|
||||
Clear();
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
EnsureClauseArray();
|
||||
mClauses->AppendElement(mCaret);
|
||||
}
|
||||
|
||||
RefPtr<TextEventDispatcher> kungFuDeathGrip(aDispatcher);
|
||||
nsCOMPtr<nsIWidget> widget(aDispatcher->mWidget);
|
||||
WidgetCompositionEvent compChangeEvent(true, eCompositionChange, widget);
|
||||
aDispatcher->InitEvent(compChangeEvent);
|
||||
if (aEventTime) {
|
||||
compChangeEvent.AssignEventTime(*aEventTime);
|
||||
}
|
||||
compChangeEvent.mData = mString;
|
||||
if (mClauses) {
|
||||
MOZ_ASSERT(!mClauses->IsEmpty(),
|
||||
"mClauses must be non-empty array when it's not nullptr");
|
||||
compChangeEvent.mRanges = mClauses;
|
||||
}
|
||||
|
||||
// While this method dispatches a composition event, some other event handler
|
||||
// cause more clauses to be added. So, we should clear pending composition
|
||||
// before dispatching the event.
|
||||
Clear();
|
||||
|
||||
rv = aDispatcher->StartCompositionAutomaticallyIfNecessary(aStatus,
|
||||
aEventTime);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
if (aStatus == nsEventStatus_eConsumeNoDefault) {
|
||||
return NS_OK;
|
||||
}
|
||||
rv = aDispatcher->DispatchEvent(widget, compChangeEvent, aStatus);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
486
widget/TextEventDispatcher.h
Normal file
486
widget/TextEventDispatcher.h
Normal file
|
|
@ -0,0 +1,486 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_textcompositionsynthesizer_h_
|
||||
#define mozilla_textcompositionsynthesizer_h_
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "mozilla/TextEventDispatcherListener.h"
|
||||
#include "mozilla/TextRange.h"
|
||||
|
||||
class nsIWidget;
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
struct IMENotification;
|
||||
|
||||
/**
|
||||
* TextEventDispatcher is a helper class for dispatching widget events defined
|
||||
* in TextEvents.h. Currently, this is a helper for dispatching
|
||||
* WidgetCompositionEvent and WidgetKeyboardEvent. This manages the behavior
|
||||
* of them for conforming to DOM Level 3 Events.
|
||||
* An instance of this class is created by nsIWidget instance and owned by it.
|
||||
* This is typically created only by the top level widgets because only they
|
||||
* handle IME.
|
||||
*/
|
||||
|
||||
class TextEventDispatcher final
|
||||
{
|
||||
~TextEventDispatcher()
|
||||
{
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(TextEventDispatcher)
|
||||
|
||||
public:
|
||||
explicit TextEventDispatcher(nsIWidget* aWidget);
|
||||
|
||||
/**
|
||||
* Initializes the instance for IME or automated test. Either IME or tests
|
||||
* need to call one of them before starting composition. If they return
|
||||
* NS_ERROR_ALREADY_INITIALIZED, it means that the listener already listens
|
||||
* notifications from TextEventDispatcher for same purpose (for IME or tests).
|
||||
* If this returns another error, the caller shouldn't keep starting
|
||||
* composition.
|
||||
*
|
||||
* @param aListener Specify the listener to listen notifications and
|
||||
* requests. This must not be null.
|
||||
* NOTE: aListener is stored as weak reference in
|
||||
* TextEventDispatcher. See mListener
|
||||
* definition below.
|
||||
*/
|
||||
nsresult BeginInputTransaction(TextEventDispatcherListener* aListener);
|
||||
nsresult BeginTestInputTransaction(TextEventDispatcherListener* aListener,
|
||||
bool aIsAPZAware);
|
||||
nsresult BeginNativeInputTransaction();
|
||||
|
||||
/**
|
||||
* EndInputTransaction() should be called when the listener stops using
|
||||
* the TextEventDispatcher.
|
||||
*
|
||||
* @param aListener The listener using the TextEventDispatcher instance.
|
||||
*/
|
||||
void EndInputTransaction(TextEventDispatcherListener* aListener);
|
||||
|
||||
/**
|
||||
* OnDestroyWidget() is called when mWidget is being destroyed.
|
||||
*/
|
||||
void OnDestroyWidget();
|
||||
|
||||
nsIWidget* GetWidget() const { return mWidget; }
|
||||
|
||||
/**
|
||||
* GetState() returns current state of this class.
|
||||
*
|
||||
* @return NS_OK: Fine to compose text.
|
||||
* NS_ERROR_NOT_INITIALIZED: BeginInputTransaction() or
|
||||
* BeginInputTransactionForTests()
|
||||
* should be called.
|
||||
* NS_ERROR_NOT_AVAILABLE: The widget isn't available for
|
||||
* composition.
|
||||
*/
|
||||
nsresult GetState() const;
|
||||
|
||||
/**
|
||||
* IsComposing() returns true after calling StartComposition() and before
|
||||
* calling CommitComposition().
|
||||
*/
|
||||
bool IsComposing() const { return mIsComposing; }
|
||||
|
||||
/**
|
||||
* IsInNativeInputTransaction() returns true if native IME handler began a
|
||||
* transaction and it's not finished yet.
|
||||
*/
|
||||
bool IsInNativeInputTransaction() const
|
||||
{
|
||||
return mInputTransactionType == eNativeInputTransaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* IsDispatchingEvent() returns true while this instance dispatching an event.
|
||||
*/
|
||||
bool IsDispatchingEvent() const { return mDispatchingEvent > 0; }
|
||||
|
||||
/**
|
||||
* GetPseudoIMEContext() returns pseudo native IME context if there is an
|
||||
* input transaction whose type is not for native event handler.
|
||||
* Otherwise, returns nullptr.
|
||||
*/
|
||||
void* GetPseudoIMEContext() const
|
||||
{
|
||||
if (mInputTransactionType == eNoInputTransaction ||
|
||||
mInputTransactionType == eNativeInputTransaction) {
|
||||
return nullptr;
|
||||
}
|
||||
return const_cast<TextEventDispatcher*>(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* StartComposition() starts composition explicitly.
|
||||
*
|
||||
* @param aEventTime If this is not nullptr, WidgetCompositionEvent will
|
||||
* be initialized with this. Otherwise, initialized
|
||||
* with the time at initializing.
|
||||
*/
|
||||
nsresult StartComposition(nsEventStatus& aStatus,
|
||||
const WidgetEventTime* aEventTime = nullptr);
|
||||
|
||||
/**
|
||||
* CommitComposition() commits composition.
|
||||
*
|
||||
* @param aCommitString If this is null, commits with the last composition
|
||||
* string. Otherwise, commits the composition with
|
||||
* this value.
|
||||
* @param aEventTime If this is not nullptr, WidgetCompositionEvent will
|
||||
* be initialized with this. Otherwise, initialized
|
||||
* with the time at initializing.
|
||||
*/
|
||||
nsresult CommitComposition(nsEventStatus& aStatus,
|
||||
const nsAString* aCommitString = nullptr,
|
||||
const WidgetEventTime* aEventTime = nullptr);
|
||||
|
||||
/**
|
||||
* SetPendingCompositionString() sets new composition string which will be
|
||||
* dispatched with eCompositionChange event by calling Flush().
|
||||
*
|
||||
* @param aString New composition string.
|
||||
*/
|
||||
nsresult SetPendingCompositionString(const nsAString& aString)
|
||||
{
|
||||
return mPendingComposition.SetString(aString);
|
||||
}
|
||||
|
||||
/**
|
||||
* AppendClauseToPendingComposition() appends a clause information to
|
||||
* the pending composition string.
|
||||
*
|
||||
* @param aLength Length of the clause.
|
||||
* @param aTextRangeType One of TextRangeType::eRawClause,
|
||||
* TextRangeType::eSelectedRawClause,
|
||||
* TextRangeType::eConvertedClause or
|
||||
* TextRangeType::eSelectedClause.
|
||||
*/
|
||||
nsresult AppendClauseToPendingComposition(uint32_t aLength,
|
||||
TextRangeType aTextRangeType)
|
||||
{
|
||||
return mPendingComposition.AppendClause(aLength, aTextRangeType);
|
||||
}
|
||||
|
||||
/**
|
||||
* SetCaretInPendingComposition() sets caret position in the pending
|
||||
* composition string and its length. This is optional. If IME doesn't
|
||||
* want to show caret, it shouldn't need to call this.
|
||||
*
|
||||
* @param aOffset Offset of the caret in the pending composition
|
||||
* string. This should not be larger than the length
|
||||
* of the pending composition string.
|
||||
* @param aLength Caret width. If this is 0, caret will be collapsed.
|
||||
* Note that Gecko doesn't supported wide caret yet,
|
||||
* therefore, this is ignored for now.
|
||||
*/
|
||||
nsresult SetCaretInPendingComposition(uint32_t aOffset,
|
||||
uint32_t aLength)
|
||||
{
|
||||
return mPendingComposition.SetCaret(aOffset, aLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* SetPendingComposition() is useful if native IME handler already creates
|
||||
* array of clauses and/or caret information.
|
||||
*
|
||||
* @param aString Composition string. This may include native line
|
||||
* breakers since they will be replaced with XP line
|
||||
* breakers automatically.
|
||||
* @param aRanges This should include the ranges of clauses and/or
|
||||
* a range of caret. Note that this method allows
|
||||
* some ranges overlap each other and the range order
|
||||
* is not from start to end.
|
||||
*/
|
||||
nsresult SetPendingComposition(const nsAString& aString,
|
||||
const TextRangeArray* aRanges)
|
||||
{
|
||||
return mPendingComposition.Set(aString, aRanges);
|
||||
}
|
||||
|
||||
/**
|
||||
* FlushPendingComposition() sends the pending composition string
|
||||
* to the widget of the store DOM window. Before calling this, IME needs to
|
||||
* set pending composition string with SetPendingCompositionString(),
|
||||
* AppendClauseToPendingComposition() and/or
|
||||
* SetCaretInPendingComposition().
|
||||
*
|
||||
* @param aEventTime If this is not nullptr, WidgetCompositionEvent will
|
||||
* be initialized with this. Otherwise, initialized
|
||||
* with the time at initializing.
|
||||
*/
|
||||
nsresult FlushPendingComposition(nsEventStatus& aStatus,
|
||||
const WidgetEventTime* aEventTime = nullptr)
|
||||
{
|
||||
return mPendingComposition.Flush(this, aStatus, aEventTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* ClearPendingComposition() makes this instance forget pending composition.
|
||||
*/
|
||||
void ClearPendingComposition()
|
||||
{
|
||||
mPendingComposition.Clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* GetPendingCompositionClauses() returns text ranges which was appended by
|
||||
* AppendClauseToPendingComposition() or SetPendingComposition().
|
||||
*/
|
||||
const TextRangeArray* GetPendingCompositionClauses() const
|
||||
{
|
||||
return mPendingComposition.GetClauses();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see nsIWidget::NotifyIME()
|
||||
*/
|
||||
nsresult NotifyIME(const IMENotification& aIMENotification);
|
||||
|
||||
/**
|
||||
* DispatchKeyboardEvent() maybe dispatches aKeyboardEvent.
|
||||
*
|
||||
* @param aMessage Must be eKeyDown or eKeyUp.
|
||||
* Use MaybeDispatchKeypressEvents() for dispatching
|
||||
* eKeyPress.
|
||||
* @param aKeyboardEvent A keyboard event.
|
||||
* @param aStatus If dispatching event should be marked as consumed,
|
||||
* set nsEventStatus_eConsumeNoDefault. Otherwise,
|
||||
* set nsEventStatus_eIgnore. After dispatching
|
||||
* a event and it's consumed this returns
|
||||
* nsEventStatus_eConsumeNoDefault.
|
||||
* @param aData Calling this method may cause calling
|
||||
* WillDispatchKeyboardEvent() of the listener.
|
||||
* aData will be set to its argument.
|
||||
* @return true if an event is dispatched. Otherwise, false.
|
||||
*/
|
||||
bool DispatchKeyboardEvent(EventMessage aMessage,
|
||||
const WidgetKeyboardEvent& aKeyboardEvent,
|
||||
nsEventStatus& aStatus,
|
||||
void* aData = nullptr);
|
||||
|
||||
/**
|
||||
* MaybeDispatchKeypressEvents() maybe dispatches a keypress event which is
|
||||
* generated from aKeydownEvent.
|
||||
*
|
||||
* @param aKeyboardEvent A keyboard event.
|
||||
* @param aStatus Sets the result when the caller dispatches
|
||||
* aKeyboardEvent. Note that if the value is
|
||||
* nsEventStatus_eConsumeNoDefault, this does NOT
|
||||
* dispatch keypress events.
|
||||
* When this method dispatches one or more keypress
|
||||
* events and one of them is consumed, this returns
|
||||
* nsEventStatus_eConsumeNoDefault.
|
||||
* @param aData Calling this method may cause calling
|
||||
* WillDispatchKeyboardEvent() of the listener.
|
||||
* aData will be set to its argument.
|
||||
* @param aNeedsCallback Set true when caller needs to initialize each
|
||||
* eKeyPress event immediately before dispatch.
|
||||
* Then, WillDispatchKeyboardEvent() is always called.
|
||||
* @return true if one or more events are dispatched.
|
||||
* Otherwise, false.
|
||||
*/
|
||||
bool MaybeDispatchKeypressEvents(const WidgetKeyboardEvent& aKeyboardEvent,
|
||||
nsEventStatus& aStatus,
|
||||
void* aData = nullptr,
|
||||
bool aNeedsCallback = false);
|
||||
|
||||
private:
|
||||
// mWidget is owner of the instance. When this is created, this is set.
|
||||
// And when mWidget is released, this is cleared by OnDestroyWidget().
|
||||
// Note that mWidget may be destroyed already (i.e., mWidget->Destroyed() may
|
||||
// return true).
|
||||
nsIWidget* mWidget;
|
||||
// mListener is a weak reference to TextEventDispatcherListener. That might
|
||||
// be referred by JS. Therefore, the listener might be difficult to release
|
||||
// itself if this is a strong reference. Additionally, it's difficult to
|
||||
// check if a method to uninstall the listener is called by valid instance.
|
||||
// So, using weak reference is the best way in this case.
|
||||
nsWeakPtr mListener;
|
||||
|
||||
// mPendingComposition stores new composition string temporarily.
|
||||
// These values will be used for dispatching eCompositionChange event
|
||||
// in Flush(). When Flush() is called, the members will be cleared
|
||||
// automatically.
|
||||
class PendingComposition
|
||||
{
|
||||
public:
|
||||
PendingComposition();
|
||||
nsresult SetString(const nsAString& aString);
|
||||
nsresult AppendClause(uint32_t aLength, TextRangeType aTextRangeType);
|
||||
nsresult SetCaret(uint32_t aOffset, uint32_t aLength);
|
||||
nsresult Set(const nsAString& aString, const TextRangeArray* aRanges);
|
||||
nsresult Flush(TextEventDispatcher* aDispatcher,
|
||||
nsEventStatus& aStatus,
|
||||
const WidgetEventTime* aEventTime);
|
||||
const TextRangeArray* GetClauses() const { return mClauses; }
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
nsString mString;
|
||||
RefPtr<TextRangeArray> mClauses;
|
||||
TextRange mCaret;
|
||||
|
||||
void EnsureClauseArray();
|
||||
};
|
||||
PendingComposition mPendingComposition;
|
||||
|
||||
// While dispatching an event, this is incremented.
|
||||
uint16_t mDispatchingEvent;
|
||||
|
||||
enum InputTransactionType : uint8_t
|
||||
{
|
||||
// No input transaction has been started.
|
||||
eNoInputTransaction,
|
||||
// Input transaction for native IME or keyboard event handler. Note that
|
||||
// keyboard events may be dispatched via parent process if there is.
|
||||
eNativeInputTransaction,
|
||||
// Input transaction for automated tests which are APZ-aware. Note that
|
||||
// keyboard events may be dispatched via parent process if there is.
|
||||
eAsyncTestInputTransaction,
|
||||
// Input transaction for automated tests which assume events are fired
|
||||
// synchronously. I.e., keyboard events are always dispatched in the
|
||||
// current process.
|
||||
eSameProcessSyncTestInputTransaction,
|
||||
// Input transaction for Others (must be IME on B2G). Events are fired
|
||||
// synchronously because TextInputProcessor which is the only user of
|
||||
// this input transaction type supports only keyboard apps on B2G.
|
||||
// Keyboard apps on B2G doesn't want to dispatch keyboard events to
|
||||
// chrome process. Therefore, this should dispatch key events only in
|
||||
// the current process.
|
||||
eSameProcessSyncInputTransaction
|
||||
};
|
||||
|
||||
InputTransactionType mInputTransactionType;
|
||||
|
||||
bool IsForTests() const
|
||||
{
|
||||
return mInputTransactionType == eAsyncTestInputTransaction ||
|
||||
mInputTransactionType == eSameProcessSyncTestInputTransaction;
|
||||
}
|
||||
|
||||
// ShouldSendInputEventToAPZ() returns true when WidgetInputEvent should
|
||||
// be dispatched via its parent process (if there is) for APZ. Otherwise,
|
||||
// when the input transaction is for IME of B2G or automated tests which
|
||||
// isn't APZ-aware, WidgetInputEvent should be dispatched form current
|
||||
// process directly.
|
||||
bool ShouldSendInputEventToAPZ() const
|
||||
{
|
||||
switch (mInputTransactionType) {
|
||||
case eNativeInputTransaction:
|
||||
case eAsyncTestInputTransaction:
|
||||
return true;
|
||||
case eSameProcessSyncTestInputTransaction:
|
||||
case eSameProcessSyncInputTransaction:
|
||||
return false;
|
||||
case eNoInputTransaction:
|
||||
NS_WARNING("Why does the caller need to dispatch an event when "
|
||||
"there is no input transaction?");
|
||||
return true;
|
||||
default:
|
||||
MOZ_CRASH("Define the behavior of new InputTransactionType");
|
||||
}
|
||||
}
|
||||
|
||||
// See IsComposing().
|
||||
bool mIsComposing;
|
||||
|
||||
// If this is true, keydown and keyup events are dispatched even when there
|
||||
// is a composition.
|
||||
static bool sDispatchKeyEventsDuringComposition;
|
||||
|
||||
nsresult BeginInputTransactionInternal(
|
||||
TextEventDispatcherListener* aListener,
|
||||
InputTransactionType aType);
|
||||
|
||||
/**
|
||||
* InitEvent() initializes aEvent. This must be called before dispatching
|
||||
* the event.
|
||||
*/
|
||||
void InitEvent(WidgetGUIEvent& aEvent) const;
|
||||
|
||||
|
||||
/**
|
||||
* DispatchEvent() dispatches aEvent on aWidget.
|
||||
*/
|
||||
nsresult DispatchEvent(nsIWidget* aWidget,
|
||||
WidgetGUIEvent& aEvent,
|
||||
nsEventStatus& aStatus);
|
||||
|
||||
/**
|
||||
* DispatchInputEvent() dispatches aEvent on aWidget.
|
||||
*/
|
||||
nsresult DispatchInputEvent(nsIWidget* aWidget,
|
||||
WidgetInputEvent& aEvent,
|
||||
nsEventStatus& aStatus);
|
||||
|
||||
/**
|
||||
* StartCompositionAutomaticallyIfNecessary() starts composition if it hasn't
|
||||
* been started it yet.
|
||||
*
|
||||
* @param aStatus If it succeeded to start composition normally, this
|
||||
* returns nsEventStatus_eIgnore. Otherwise, e.g.,
|
||||
* the composition is canceled during dispatching
|
||||
* compositionstart event, this returns
|
||||
* nsEventStatus_eConsumeNoDefault. In this case,
|
||||
* the caller shouldn't keep doing its job.
|
||||
* @param aEventTime If this is not nullptr, WidgetCompositionEvent will
|
||||
* be initialized with this. Otherwise, initialized
|
||||
* with the time at initializing.
|
||||
* @return Only when something unexpected occurs, this returns
|
||||
* an error. Otherwise, returns NS_OK even if aStatus
|
||||
* is nsEventStatus_eConsumeNoDefault.
|
||||
*/
|
||||
nsresult StartCompositionAutomaticallyIfNecessary(
|
||||
nsEventStatus& aStatus,
|
||||
const WidgetEventTime* aEventTime);
|
||||
|
||||
/**
|
||||
* DispatchKeyboardEventInternal() maybe dispatches aKeyboardEvent.
|
||||
*
|
||||
* @param aMessage Must be eKeyDown, eKeyUp or eKeyPress.
|
||||
* @param aKeyboardEvent A keyboard event. If aMessage is eKeyPress and
|
||||
* the event is for second or later character, its
|
||||
* mKeyValue should be empty string.
|
||||
* @param aStatus If dispatching event should be marked as consumed,
|
||||
* set nsEventStatus_eConsumeNoDefault. Otherwise,
|
||||
* set nsEventStatus_eIgnore. After dispatching
|
||||
* a event and it's consumed this returns
|
||||
* nsEventStatus_eConsumeNoDefault.
|
||||
* @param aData Calling this method may cause calling
|
||||
* WillDispatchKeyboardEvent() of the listener.
|
||||
* aData will be set to its argument.
|
||||
* @param aIndexOfKeypress This must be 0 if aMessage isn't eKeyPress or
|
||||
* aKeyboard.mKeyNameIndex isn't
|
||||
* KEY_NAME_INDEX_USE_STRING. Otherwise, i.e.,
|
||||
* when an eKeyPress event causes inputting
|
||||
* text, this must be between 0 and
|
||||
* mKeyValue.Length() - 1 since keypress events
|
||||
* sending only one character per event.
|
||||
* @param aNeedsCallback Set true when caller needs to initialize each
|
||||
* eKeyPress event immediately before dispatch.
|
||||
* Then, WillDispatchKeyboardEvent() is always called.
|
||||
* @return true if an event is dispatched. Otherwise, false.
|
||||
*/
|
||||
bool DispatchKeyboardEventInternal(EventMessage aMessage,
|
||||
const WidgetKeyboardEvent& aKeyboardEvent,
|
||||
nsEventStatus& aStatus,
|
||||
void* aData,
|
||||
uint32_t aIndexOfKeypress = 0,
|
||||
bool aNeedsCallback = false);
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // #ifndef mozilla_widget_textcompositionsynthesizer_h_
|
||||
89
widget/TextEventDispatcherListener.h
Normal file
89
widget/TextEventDispatcherListener.h
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_textinputdispatcherlistener_h_
|
||||
#define mozilla_textinputdispatcherlistener_h_
|
||||
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
class TextEventDispatcher;
|
||||
struct IMENotification;
|
||||
|
||||
#define NS_TEXT_INPUT_PROXY_LISTENER_IID \
|
||||
{ 0xf2226f55, 0x6ddb, 0x40d5, \
|
||||
{ 0x8a, 0x24, 0xce, 0x4d, 0x5b, 0x38, 0x15, 0xf0 } };
|
||||
|
||||
class TextEventDispatcherListener : public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_TEXT_INPUT_PROXY_LISTENER_IID)
|
||||
|
||||
/**
|
||||
* NotifyIME() is called by TextEventDispatcher::NotifyIME(). This is a
|
||||
* notification or request to IME. See document of nsIWidget::NotifyIME()
|
||||
* for the detail.
|
||||
*/
|
||||
NS_IMETHOD NotifyIME(TextEventDispatcher* aTextEventDispatcher,
|
||||
const IMENotification& aNotification) = 0;
|
||||
|
||||
/**
|
||||
* OnRemovedFrom() is called when the TextEventDispatcher stops working and
|
||||
* is releasing the listener.
|
||||
*/
|
||||
NS_IMETHOD_(void) OnRemovedFrom(
|
||||
TextEventDispatcher* aTextEventDispatcher) = 0;
|
||||
|
||||
/**
|
||||
* WillDispatchKeyboardEvent() may be called immediately before
|
||||
* TextEventDispatcher dispatching a keyboard event. This is called only
|
||||
* during calling TextEventDispatcher::DispatchKeyboardEvent() or
|
||||
* TextEventDispatcher::MaybeDispatchKeypressEvents(). But this may not
|
||||
* be called if TextEventDispatcher thinks that the keyboard event doesn't
|
||||
* need alternative char codes.
|
||||
*
|
||||
* This method can overwrite any members of aKeyboardEvent which is already
|
||||
* initialized by TextEventDispatcher. If it's necessary, this method should
|
||||
* overwrite the charCode when Control key is pressed. TextEventDispatcher
|
||||
* computes charCode from mKeyValue. However, when Control key is pressed,
|
||||
* charCode should be an ASCII char. In such case, this method needs to
|
||||
* overwrite it properly.
|
||||
*
|
||||
* @param aTextEventDispatcher Pointer to the caller.
|
||||
* @param aKeyboardEvent The event trying to dispatch.
|
||||
* This is already initialized, but if it's
|
||||
* necessary, this method should overwrite the
|
||||
* members and set alternative char codes.
|
||||
* @param aIndexOfKeypress When aKeyboardEvent is eKeyPress event,
|
||||
* it may be a sequence of keypress events
|
||||
* if the key causes multiple characters.
|
||||
* In such case, this indicates the index from
|
||||
* first keypress event.
|
||||
* If aKeyboardEvent is the first eKeyPress or
|
||||
* other events, this value is 0.
|
||||
* @param aData The pointer which was specified at calling
|
||||
* the method of TextEventDispatcher.
|
||||
* For example, if you do:
|
||||
* |TextEventDispatcher->DispatchKeyboardEvent(
|
||||
* eKeyDown, event, status, this);|
|
||||
* Then, aData of this method becomes |this|.
|
||||
* Finally, you can use it like:
|
||||
* |static_cast<NativeEventHandler*>(aData)|
|
||||
*/
|
||||
NS_IMETHOD_(void) WillDispatchKeyboardEvent(
|
||||
TextEventDispatcher* aTextEventDispatcher,
|
||||
WidgetKeyboardEvent& aKeyboardEvent,
|
||||
uint32_t aIndexOfKeypress,
|
||||
void* aData) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(TextEventDispatcherListener,
|
||||
NS_TEXT_INPUT_PROXY_LISTENER_IID)
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // #ifndef mozilla_textinputdispatcherlistener_h_
|
||||
1014
widget/TextEvents.h
Normal file
1014
widget/TextEvents.h
Normal file
File diff suppressed because it is too large
Load diff
314
widget/TextRange.h
Normal file
314
widget/TextRange.h
Normal file
|
|
@ -0,0 +1,314 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_TextRage_h_
|
||||
#define mozilla_TextRage_h_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mozilla/EventForwards.h"
|
||||
|
||||
#include "nsColor.h"
|
||||
#include "nsISelectionController.h"
|
||||
#include "nsITextInputProcessor.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::TextRangeStyle
|
||||
******************************************************************************/
|
||||
|
||||
struct TextRangeStyle
|
||||
{
|
||||
enum
|
||||
{
|
||||
LINESTYLE_NONE = NS_STYLE_TEXT_DECORATION_STYLE_NONE,
|
||||
LINESTYLE_SOLID = NS_STYLE_TEXT_DECORATION_STYLE_SOLID,
|
||||
LINESTYLE_DOTTED = NS_STYLE_TEXT_DECORATION_STYLE_DOTTED,
|
||||
LINESTYLE_DASHED = NS_STYLE_TEXT_DECORATION_STYLE_DASHED,
|
||||
LINESTYLE_DOUBLE = NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE,
|
||||
LINESTYLE_WAVY = NS_STYLE_TEXT_DECORATION_STYLE_WAVY
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
DEFINED_NONE = 0x00,
|
||||
DEFINED_LINESTYLE = 0x01,
|
||||
DEFINED_FOREGROUND_COLOR = 0x02,
|
||||
DEFINED_BACKGROUND_COLOR = 0x04,
|
||||
DEFINED_UNDERLINE_COLOR = 0x08
|
||||
};
|
||||
|
||||
// Initialize all members, because TextRange instances may be compared by
|
||||
// memcomp.
|
||||
TextRangeStyle()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
mDefinedStyles = DEFINED_NONE;
|
||||
mLineStyle = LINESTYLE_NONE;
|
||||
mIsBoldLine = false;
|
||||
mForegroundColor = mBackgroundColor = mUnderlineColor = NS_RGBA(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
bool IsDefined() const { return mDefinedStyles != DEFINED_NONE; }
|
||||
|
||||
bool IsLineStyleDefined() const
|
||||
{
|
||||
return (mDefinedStyles & DEFINED_LINESTYLE) != 0;
|
||||
}
|
||||
|
||||
bool IsForegroundColorDefined() const
|
||||
{
|
||||
return (mDefinedStyles & DEFINED_FOREGROUND_COLOR) != 0;
|
||||
}
|
||||
|
||||
bool IsBackgroundColorDefined() const
|
||||
{
|
||||
return (mDefinedStyles & DEFINED_BACKGROUND_COLOR) != 0;
|
||||
}
|
||||
|
||||
bool IsUnderlineColorDefined() const
|
||||
{
|
||||
return (mDefinedStyles & DEFINED_UNDERLINE_COLOR) != 0;
|
||||
}
|
||||
|
||||
bool IsNoChangeStyle() const
|
||||
{
|
||||
return !IsForegroundColorDefined() && !IsBackgroundColorDefined() &&
|
||||
IsLineStyleDefined() && mLineStyle == LINESTYLE_NONE;
|
||||
}
|
||||
|
||||
bool Equals(const TextRangeStyle& aOther) const
|
||||
{
|
||||
if (mDefinedStyles != aOther.mDefinedStyles)
|
||||
return false;
|
||||
if (IsLineStyleDefined() && (mLineStyle != aOther.mLineStyle ||
|
||||
!mIsBoldLine != !aOther.mIsBoldLine))
|
||||
return false;
|
||||
if (IsForegroundColorDefined() &&
|
||||
(mForegroundColor != aOther.mForegroundColor))
|
||||
return false;
|
||||
if (IsBackgroundColorDefined() &&
|
||||
(mBackgroundColor != aOther.mBackgroundColor))
|
||||
return false;
|
||||
if (IsUnderlineColorDefined() &&
|
||||
(mUnderlineColor != aOther.mUnderlineColor))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator !=(const TextRangeStyle &aOther) const
|
||||
{
|
||||
return !Equals(aOther);
|
||||
}
|
||||
|
||||
bool operator ==(const TextRangeStyle &aOther) const
|
||||
{
|
||||
return Equals(aOther);
|
||||
}
|
||||
|
||||
uint8_t mDefinedStyles;
|
||||
uint8_t mLineStyle; // DEFINED_LINESTYLE
|
||||
|
||||
bool mIsBoldLine; // DEFINED_LINESTYLE
|
||||
|
||||
nscolor mForegroundColor; // DEFINED_FOREGROUND_COLOR
|
||||
nscolor mBackgroundColor; // DEFINED_BACKGROUND_COLOR
|
||||
nscolor mUnderlineColor; // DEFINED_UNDERLINE_COLOR
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::TextRange
|
||||
******************************************************************************/
|
||||
|
||||
enum class TextRangeType : RawTextRangeType
|
||||
{
|
||||
eUninitialized = 0x00,
|
||||
eCaret = 0x01,
|
||||
eRawClause = nsITextInputProcessor::ATTR_RAW_CLAUSE,
|
||||
eSelectedRawClause = nsITextInputProcessor::ATTR_SELECTED_RAW_CLAUSE,
|
||||
eConvertedClause = nsITextInputProcessor::ATTR_CONVERTED_CLAUSE,
|
||||
eSelectedClause = nsITextInputProcessor::ATTR_SELECTED_CLAUSE
|
||||
};
|
||||
|
||||
bool IsValidRawTextRangeValue(RawTextRangeType aRawTextRangeValue);
|
||||
RawTextRangeType ToRawTextRangeType(TextRangeType aTextRangeType);
|
||||
TextRangeType ToTextRangeType(RawTextRangeType aRawTextRangeType);
|
||||
const char* ToChar(TextRangeType aTextRangeType);
|
||||
SelectionType ToSelectionType(TextRangeType aTextRangeType);
|
||||
|
||||
inline RawSelectionType ToRawSelectionType(TextRangeType aTextRangeType)
|
||||
{
|
||||
return ToRawSelectionType(ToSelectionType(aTextRangeType));
|
||||
}
|
||||
|
||||
struct TextRange
|
||||
{
|
||||
TextRange()
|
||||
: mStartOffset(0)
|
||||
, mEndOffset(0)
|
||||
, mRangeType(TextRangeType::eUninitialized)
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t mStartOffset;
|
||||
// XXX Storing end offset makes the initializing code very complicated.
|
||||
// We should replace it with mLength.
|
||||
uint32_t mEndOffset;
|
||||
|
||||
TextRangeStyle mRangeStyle;
|
||||
|
||||
TextRangeType mRangeType;
|
||||
|
||||
uint32_t Length() const { return mEndOffset - mStartOffset; }
|
||||
|
||||
bool IsClause() const
|
||||
{
|
||||
return mRangeType != TextRangeType::eCaret;
|
||||
}
|
||||
|
||||
bool Equals(const TextRange& aOther) const
|
||||
{
|
||||
return mStartOffset == aOther.mStartOffset &&
|
||||
mEndOffset == aOther.mEndOffset &&
|
||||
mRangeType == aOther.mRangeType &&
|
||||
mRangeStyle == aOther.mRangeStyle;
|
||||
}
|
||||
|
||||
void RemoveCharacter(uint32_t aOffset)
|
||||
{
|
||||
if (mStartOffset > aOffset) {
|
||||
--mStartOffset;
|
||||
--mEndOffset;
|
||||
} else if (mEndOffset > aOffset) {
|
||||
--mEndOffset;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::TextRangeArray
|
||||
******************************************************************************/
|
||||
class TextRangeArray final : public AutoTArray<TextRange, 10>
|
||||
{
|
||||
friend class WidgetCompositionEvent;
|
||||
|
||||
~TextRangeArray() {}
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(TextRangeArray)
|
||||
|
||||
const TextRange* GetTargetClause() const
|
||||
{
|
||||
for (uint32_t i = 0; i < Length(); ++i) {
|
||||
const TextRange& range = ElementAt(i);
|
||||
if (range.mRangeType == TextRangeType::eSelectedRawClause ||
|
||||
range.mRangeType == TextRangeType::eSelectedClause) {
|
||||
return ⦥
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Returns target clause offset. If there are selected clauses, this returns
|
||||
// the first selected clause offset. Otherwise, 0.
|
||||
uint32_t TargetClauseOffset() const
|
||||
{
|
||||
const TextRange* range = GetTargetClause();
|
||||
return range ? range->mStartOffset : 0;
|
||||
}
|
||||
|
||||
// Returns target clause length. If there are selected clauses, this returns
|
||||
// the first selected clause length. Otherwise, UINT32_MAX.
|
||||
uint32_t TargetClauseLength() const
|
||||
{
|
||||
const TextRange* range = GetTargetClause();
|
||||
return range ? range->Length() : UINT32_MAX;
|
||||
}
|
||||
|
||||
public:
|
||||
bool IsComposing() const
|
||||
{
|
||||
for (uint32_t i = 0; i < Length(); ++i) {
|
||||
if (ElementAt(i).IsClause()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Equals(const TextRangeArray& aOther) const
|
||||
{
|
||||
size_t len = Length();
|
||||
if (len != aOther.Length()) {
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (!ElementAt(i).Equals(aOther.ElementAt(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void RemoveCharacter(uint32_t aOffset)
|
||||
{
|
||||
for (size_t i = 0, len = Length(); i < len; i++) {
|
||||
ElementAt(i).RemoveCharacter(aOffset);
|
||||
}
|
||||
}
|
||||
|
||||
bool HasCaret() const
|
||||
{
|
||||
for (const TextRange& range : *this) {
|
||||
if (range.mRangeType == TextRangeType::eCaret) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HasClauses() const
|
||||
{
|
||||
for (const TextRange& range : *this) {
|
||||
if (range.IsClause()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t GetCaretPosition() const
|
||||
{
|
||||
for (const TextRange& range : *this) {
|
||||
if (range.mRangeType == TextRangeType::eCaret) {
|
||||
return range.mStartOffset;
|
||||
}
|
||||
}
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
const TextRange* GetFirstClause() const
|
||||
{
|
||||
for (const TextRange& range : *this) {
|
||||
// Look for the range of a clause whose start offset is 0 because the
|
||||
// first clause's start offset is always 0.
|
||||
if (range.IsClause() && !range.mStartOffset) {
|
||||
return ⦥
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(!HasClauses());
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_TextRage_h_
|
||||
220
widget/TouchEvents.h
Normal file
220
widget/TouchEvents.h
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_TouchEvents_h__
|
||||
#define mozilla_TouchEvents_h__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mozilla/dom/Touch.h"
|
||||
#include "mozilla/MouseEvents.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsIDOMSimpleGestureEvent.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::WidgetGestureNotifyEvent
|
||||
*
|
||||
* This event is the first event generated when the user touches
|
||||
* the screen with a finger, and it's meant to decide what kind
|
||||
* of action we'll use for that touch interaction.
|
||||
*
|
||||
* The event is dispatched to the layout and based on what is underneath
|
||||
* the initial contact point it's then decided if we should pan
|
||||
* (finger scrolling) or drag the target element.
|
||||
******************************************************************************/
|
||||
|
||||
class WidgetGestureNotifyEvent : public WidgetGUIEvent
|
||||
{
|
||||
public:
|
||||
virtual WidgetGestureNotifyEvent* AsGestureNotifyEvent() override
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
WidgetGestureNotifyEvent(bool aIsTrusted, EventMessage aMessage,
|
||||
nsIWidget *aWidget)
|
||||
: WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eGestureNotifyEventClass)
|
||||
, mPanDirection(ePanNone)
|
||||
, mDisplayPanFeedback(false)
|
||||
{
|
||||
}
|
||||
|
||||
virtual WidgetEvent* Duplicate() const override
|
||||
{
|
||||
// XXX Looks like this event is handled only in PostHandleEvent() of
|
||||
// EventStateManager. Therefore, it might be possible to handle this
|
||||
// in PreHandleEvent() and not to dispatch as a DOM event into the DOM
|
||||
// tree like ContentQueryEvent. Then, this event doesn't need to
|
||||
// support Duplicate().
|
||||
MOZ_ASSERT(mClass == eGestureNotifyEventClass,
|
||||
"Duplicate() must be overridden by sub class");
|
||||
// Not copying widget, it is a weak reference.
|
||||
WidgetGestureNotifyEvent* result =
|
||||
new WidgetGestureNotifyEvent(false, mMessage, nullptr);
|
||||
result->AssignGestureNotifyEventData(*this, true);
|
||||
result->mFlags = mFlags;
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef int8_t PanDirectionType;
|
||||
enum PanDirection : PanDirectionType
|
||||
{
|
||||
ePanNone,
|
||||
ePanVertical,
|
||||
ePanHorizontal,
|
||||
ePanBoth
|
||||
};
|
||||
|
||||
PanDirection mPanDirection;
|
||||
bool mDisplayPanFeedback;
|
||||
|
||||
void AssignGestureNotifyEventData(const WidgetGestureNotifyEvent& aEvent,
|
||||
bool aCopyTargets)
|
||||
{
|
||||
AssignGUIEventData(aEvent, aCopyTargets);
|
||||
|
||||
mPanDirection = aEvent.mPanDirection;
|
||||
mDisplayPanFeedback = aEvent.mDisplayPanFeedback;
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::WidgetSimpleGestureEvent
|
||||
******************************************************************************/
|
||||
|
||||
class WidgetSimpleGestureEvent : public WidgetMouseEventBase
|
||||
{
|
||||
public:
|
||||
virtual WidgetSimpleGestureEvent* AsSimpleGestureEvent() override
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
WidgetSimpleGestureEvent(bool aIsTrusted, EventMessage aMessage,
|
||||
nsIWidget* aWidget)
|
||||
: WidgetMouseEventBase(aIsTrusted, aMessage, aWidget,
|
||||
eSimpleGestureEventClass)
|
||||
, mAllowedDirections(0)
|
||||
, mDirection(0)
|
||||
, mClickCount(0)
|
||||
, mDelta(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
WidgetSimpleGestureEvent(const WidgetSimpleGestureEvent& aOther)
|
||||
: WidgetMouseEventBase(aOther.IsTrusted(), aOther.mMessage,
|
||||
aOther.mWidget, eSimpleGestureEventClass)
|
||||
, mAllowedDirections(aOther.mAllowedDirections)
|
||||
, mDirection(aOther.mDirection)
|
||||
, mClickCount(0)
|
||||
, mDelta(aOther.mDelta)
|
||||
{
|
||||
}
|
||||
|
||||
virtual WidgetEvent* Duplicate() const override
|
||||
{
|
||||
MOZ_ASSERT(mClass == eSimpleGestureEventClass,
|
||||
"Duplicate() must be overridden by sub class");
|
||||
// Not copying widget, it is a weak reference.
|
||||
WidgetSimpleGestureEvent* result =
|
||||
new WidgetSimpleGestureEvent(false, mMessage, nullptr);
|
||||
result->AssignSimpleGestureEventData(*this, true);
|
||||
result->mFlags = mFlags;
|
||||
return result;
|
||||
}
|
||||
|
||||
// See nsIDOMSimpleGestureEvent for values
|
||||
uint32_t mAllowedDirections;
|
||||
// See nsIDOMSimpleGestureEvent for values
|
||||
uint32_t mDirection;
|
||||
// The number of taps for tap events
|
||||
uint32_t mClickCount;
|
||||
// Delta for magnify and rotate events
|
||||
double mDelta;
|
||||
|
||||
// XXX Not tested by test_assign_event_data.html
|
||||
void AssignSimpleGestureEventData(const WidgetSimpleGestureEvent& aEvent,
|
||||
bool aCopyTargets)
|
||||
{
|
||||
AssignMouseEventBaseData(aEvent, aCopyTargets);
|
||||
|
||||
// mAllowedDirections isn't copied
|
||||
mDirection = aEvent.mDirection;
|
||||
mDelta = aEvent.mDelta;
|
||||
mClickCount = aEvent.mClickCount;
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::WidgetTouchEvent
|
||||
******************************************************************************/
|
||||
|
||||
class WidgetTouchEvent : public WidgetInputEvent
|
||||
{
|
||||
public:
|
||||
typedef nsTArray<RefPtr<mozilla::dom::Touch>> TouchArray;
|
||||
typedef AutoTArray<RefPtr<mozilla::dom::Touch>, 10> AutoTouchArray;
|
||||
|
||||
virtual WidgetTouchEvent* AsTouchEvent() override { return this; }
|
||||
|
||||
WidgetTouchEvent()
|
||||
{
|
||||
MOZ_COUNT_CTOR(WidgetTouchEvent);
|
||||
}
|
||||
|
||||
WidgetTouchEvent(const WidgetTouchEvent& aOther)
|
||||
: WidgetInputEvent(aOther.IsTrusted(), aOther.mMessage, aOther.mWidget,
|
||||
eTouchEventClass)
|
||||
{
|
||||
MOZ_COUNT_CTOR(WidgetTouchEvent);
|
||||
mModifiers = aOther.mModifiers;
|
||||
mTime = aOther.mTime;
|
||||
mTimeStamp = aOther.mTimeStamp;
|
||||
mTouches.AppendElements(aOther.mTouches);
|
||||
mFlags.mCancelable = mMessage != eTouchCancel;
|
||||
mFlags.mHandledByAPZ = aOther.mFlags.mHandledByAPZ;
|
||||
}
|
||||
|
||||
WidgetTouchEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget)
|
||||
: WidgetInputEvent(aIsTrusted, aMessage, aWidget, eTouchEventClass)
|
||||
{
|
||||
MOZ_COUNT_CTOR(WidgetTouchEvent);
|
||||
mFlags.mCancelable = mMessage != eTouchCancel;
|
||||
}
|
||||
|
||||
virtual ~WidgetTouchEvent()
|
||||
{
|
||||
MOZ_COUNT_DTOR(WidgetTouchEvent);
|
||||
}
|
||||
|
||||
virtual WidgetEvent* Duplicate() const override
|
||||
{
|
||||
MOZ_ASSERT(mClass == eTouchEventClass,
|
||||
"Duplicate() must be overridden by sub class");
|
||||
// Not copying widget, it is a weak reference.
|
||||
WidgetTouchEvent* result = new WidgetTouchEvent(false, mMessage, nullptr);
|
||||
result->AssignTouchEventData(*this, true);
|
||||
result->mFlags = mFlags;
|
||||
return result;
|
||||
}
|
||||
|
||||
TouchArray mTouches;
|
||||
|
||||
void AssignTouchEventData(const WidgetTouchEvent& aEvent, bool aCopyTargets)
|
||||
{
|
||||
AssignInputEventData(aEvent, aCopyTargets);
|
||||
|
||||
// Assign*EventData() assume that they're called only new instance.
|
||||
MOZ_ASSERT(mTouches.IsEmpty());
|
||||
mTouches.AppendElements(aEvent.mTouches);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_TouchEvents_h__
|
||||
187
widget/VsyncDispatcher.cpp
Normal file
187
widget/VsyncDispatcher.cpp
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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 "MainThreadUtils.h"
|
||||
#include "VsyncDispatcher.h"
|
||||
#include "VsyncSource.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "mozilla/layers/Compositor.h"
|
||||
#include "mozilla/layers/CompositorBridgeParent.h"
|
||||
#include "mozilla/layers/CompositorThread.h"
|
||||
|
||||
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||
#include "GeckoProfiler.h"
|
||||
#include "ProfilerMarkers.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
CompositorVsyncDispatcher::CompositorVsyncDispatcher()
|
||||
: mCompositorObserverLock("CompositorObserverLock")
|
||||
, mDidShutdown(false)
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
CompositorVsyncDispatcher::~CompositorVsyncDispatcher()
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
// We auto remove this vsync dispatcher from the vsync source in the nsBaseWidget
|
||||
}
|
||||
|
||||
void
|
||||
CompositorVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp)
|
||||
{
|
||||
// In vsync thread
|
||||
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||
layers::CompositorBridgeParent::PostInsertVsyncProfilerMarker(aVsyncTimestamp);
|
||||
#endif
|
||||
|
||||
MutexAutoLock lock(mCompositorObserverLock);
|
||||
if (mCompositorVsyncObserver) {
|
||||
mCompositorVsyncObserver->NotifyVsync(aVsyncTimestamp);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CompositorVsyncDispatcher::ObserveVsync(bool aEnable)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
if (mDidShutdown) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aEnable) {
|
||||
gfxPlatform::GetPlatform()->GetHardwareVsync()->AddCompositorVsyncDispatcher(this);
|
||||
} else {
|
||||
gfxPlatform::GetPlatform()->GetHardwareVsync()->RemoveCompositorVsyncDispatcher(this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CompositorVsyncDispatcher::SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver)
|
||||
{
|
||||
// When remote compositing or running gtests, vsync observation is
|
||||
// initiated on the main thread. Otherwise, it is initiated from the compositor
|
||||
// thread.
|
||||
MOZ_ASSERT(NS_IsMainThread() || CompositorThreadHolder::IsInCompositorThread());
|
||||
|
||||
{ // scope lock
|
||||
MutexAutoLock lock(mCompositorObserverLock);
|
||||
mCompositorVsyncObserver = aVsyncObserver;
|
||||
}
|
||||
|
||||
bool observeVsync = aVsyncObserver != nullptr;
|
||||
nsCOMPtr<nsIRunnable> vsyncControl = NewRunnableMethod<bool>(this,
|
||||
&CompositorVsyncDispatcher::ObserveVsync,
|
||||
observeVsync);
|
||||
NS_DispatchToMainThread(vsyncControl);
|
||||
}
|
||||
|
||||
void
|
||||
CompositorVsyncDispatcher::Shutdown()
|
||||
{
|
||||
// Need to explicitly remove CompositorVsyncDispatcher when the nsBaseWidget shuts down.
|
||||
// Otherwise, we would get dead vsync notifications between when the nsBaseWidget
|
||||
// shuts down and the CompositorBridgeParent shuts down.
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ObserveVsync(false);
|
||||
mDidShutdown = true;
|
||||
{ // scope lock
|
||||
MutexAutoLock lock(mCompositorObserverLock);
|
||||
mCompositorVsyncObserver = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
RefreshTimerVsyncDispatcher::RefreshTimerVsyncDispatcher()
|
||||
: mRefreshTimersLock("RefreshTimers lock")
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
RefreshTimerVsyncDispatcher::~RefreshTimerVsyncDispatcher()
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
void
|
||||
RefreshTimerVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp)
|
||||
{
|
||||
MutexAutoLock lock(mRefreshTimersLock);
|
||||
|
||||
for (size_t i = 0; i < mChildRefreshTimers.Length(); i++) {
|
||||
mChildRefreshTimers[i]->NotifyVsync(aVsyncTimestamp);
|
||||
}
|
||||
|
||||
if (mParentRefreshTimer) {
|
||||
mParentRefreshTimer->NotifyVsync(aVsyncTimestamp);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RefreshTimerVsyncDispatcher::SetParentRefreshTimer(VsyncObserver* aVsyncObserver)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
{ // lock scope because UpdateVsyncStatus runs on main thread and will deadlock
|
||||
MutexAutoLock lock(mRefreshTimersLock);
|
||||
mParentRefreshTimer = aVsyncObserver;
|
||||
}
|
||||
|
||||
UpdateVsyncStatus();
|
||||
}
|
||||
|
||||
void
|
||||
RefreshTimerVsyncDispatcher::AddChildRefreshTimer(VsyncObserver* aVsyncObserver)
|
||||
{
|
||||
{ // scope lock - called on pbackground thread
|
||||
MutexAutoLock lock(mRefreshTimersLock);
|
||||
MOZ_ASSERT(aVsyncObserver);
|
||||
if (!mChildRefreshTimers.Contains(aVsyncObserver)) {
|
||||
mChildRefreshTimers.AppendElement(aVsyncObserver);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateVsyncStatus();
|
||||
}
|
||||
|
||||
void
|
||||
RefreshTimerVsyncDispatcher::RemoveChildRefreshTimer(VsyncObserver* aVsyncObserver)
|
||||
{
|
||||
{ // scope lock - called on pbackground thread
|
||||
MutexAutoLock lock(mRefreshTimersLock);
|
||||
MOZ_ASSERT(aVsyncObserver);
|
||||
mChildRefreshTimers.RemoveElement(aVsyncObserver);
|
||||
}
|
||||
|
||||
UpdateVsyncStatus();
|
||||
}
|
||||
|
||||
void
|
||||
RefreshTimerVsyncDispatcher::UpdateVsyncStatus()
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
NS_DispatchToMainThread(NewRunnableMethod(this,
|
||||
&RefreshTimerVsyncDispatcher::UpdateVsyncStatus));
|
||||
return;
|
||||
}
|
||||
|
||||
gfx::VsyncSource::Display& display = gfxPlatform::GetPlatform()->GetHardwareVsync()->GetGlobalDisplay();
|
||||
display.NotifyRefreshTimerVsyncStatus(NeedsVsync());
|
||||
}
|
||||
|
||||
bool
|
||||
RefreshTimerVsyncDispatcher::NeedsVsync()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MutexAutoLock lock(mRefreshTimersLock);
|
||||
return (mParentRefreshTimer != nullptr) || !mChildRefreshTimers.IsEmpty();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
103
widget/VsyncDispatcher.h
Normal file
103
widget/VsyncDispatcher.h
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_widget_VsyncDispatcher_h
|
||||
#define mozilla_widget_VsyncDispatcher_h
|
||||
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsTArray.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class VsyncObserver
|
||||
{
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VsyncObserver)
|
||||
|
||||
public:
|
||||
// The method called when a vsync occurs. Return true if some work was done.
|
||||
// In general, this vsync notification will occur on the hardware vsync
|
||||
// thread from VsyncSource. But it might also be called on PVsync ipc thread
|
||||
// if this notification is cross process. Thus all observer should check the
|
||||
// thread model before handling the real task.
|
||||
virtual bool NotifyVsync(TimeStamp aVsyncTimestamp) = 0;
|
||||
|
||||
protected:
|
||||
VsyncObserver() {}
|
||||
virtual ~VsyncObserver() {}
|
||||
}; // VsyncObserver
|
||||
|
||||
// Used to dispatch vsync events in the parent process to compositors.
|
||||
//
|
||||
// When the compositor is in-process, CompositorWidgets own a
|
||||
// CompositorVsyncDispatcher, and directly attach the compositor's observer
|
||||
// to it.
|
||||
//
|
||||
// When the compositor is out-of-process, the CompositorWidgetDelegate owns
|
||||
// the vsync dispatcher instead. The widget receives vsync observer/unobserve
|
||||
// commands via IPDL, and uses this to attach a CompositorWidgetVsyncObserver.
|
||||
// This observer forwards vsync notifications (on the vsync thread) to a
|
||||
// dedicated vsync I/O thread, which then forwards the notification to the
|
||||
// compositor thread in the compositor process.
|
||||
class CompositorVsyncDispatcher final
|
||||
{
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorVsyncDispatcher)
|
||||
|
||||
public:
|
||||
CompositorVsyncDispatcher();
|
||||
|
||||
// Called on the vsync thread when a hardware vsync occurs
|
||||
void NotifyVsync(TimeStamp aVsyncTimestamp);
|
||||
|
||||
// Compositor vsync observers must be added/removed on the compositor thread
|
||||
void SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver);
|
||||
void Shutdown();
|
||||
|
||||
private:
|
||||
virtual ~CompositorVsyncDispatcher();
|
||||
void ObserveVsync(bool aEnable);
|
||||
|
||||
Mutex mCompositorObserverLock;
|
||||
RefPtr<VsyncObserver> mCompositorVsyncObserver;
|
||||
bool mDidShutdown;
|
||||
};
|
||||
|
||||
// Dispatch vsync event to ipc actor parent and chrome RefreshTimer.
|
||||
class RefreshTimerVsyncDispatcher final
|
||||
{
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RefreshTimerVsyncDispatcher)
|
||||
|
||||
public:
|
||||
RefreshTimerVsyncDispatcher();
|
||||
|
||||
// Please check CompositorVsyncDispatcher::NotifyVsync().
|
||||
void NotifyVsync(TimeStamp aVsyncTimestamp);
|
||||
|
||||
// Set chrome process's RefreshTimer to this dispatcher.
|
||||
// This function can be called from any thread.
|
||||
void SetParentRefreshTimer(VsyncObserver* aVsyncObserver);
|
||||
|
||||
// Add or remove the content process' RefreshTimer to this dispatcher. This
|
||||
// will be a no-op for AddChildRefreshTimer() if the observer is already
|
||||
// registered.
|
||||
// These functions can be called from any thread.
|
||||
void AddChildRefreshTimer(VsyncObserver* aVsyncObserver);
|
||||
void RemoveChildRefreshTimer(VsyncObserver* aVsyncObserver);
|
||||
|
||||
private:
|
||||
virtual ~RefreshTimerVsyncDispatcher();
|
||||
void UpdateVsyncStatus();
|
||||
bool NeedsVsync();
|
||||
|
||||
Mutex mRefreshTimersLock;
|
||||
RefPtr<VsyncObserver> mParentRefreshTimer;
|
||||
nsTArray<RefPtr<VsyncObserver>> mChildRefreshTimers;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_widget_VsyncDispatcher_h
|
||||
1075
widget/WidgetEventImpl.cpp
Normal file
1075
widget/WidgetEventImpl.cpp
Normal file
File diff suppressed because it is too large
Load diff
39
widget/WidgetMessageUtils.h
Normal file
39
widget/WidgetMessageUtils.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_WidgetMessageUtils_h
|
||||
#define mozilla_WidgetMessageUtils_h
|
||||
|
||||
#include "ipc/IPCMessageUtils.h"
|
||||
#include "mozilla/LookAndFeel.h"
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template<>
|
||||
struct ParamTraits<LookAndFeelInt>
|
||||
{
|
||||
typedef LookAndFeelInt paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.id);
|
||||
WriteParam(aMsg, aParam.value);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
|
||||
{
|
||||
int32_t id, value;
|
||||
if (ReadParam(aMsg, aIter, &id) &&
|
||||
ReadParam(aMsg, aIter, &value)) {
|
||||
aResult->id = id;
|
||||
aResult->value = value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
#endif // WidgetMessageUtils_h
|
||||
27
widget/WidgetTraceEvent.h
Normal file
27
widget/WidgetTraceEvent.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/* 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/. */
|
||||
|
||||
#ifndef WIDGET_PUBLIC_WIDGETTRACEEVENT_H_
|
||||
#define WIDGET_PUBLIC_WIDGETTRACEEVENT_H_
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Perform any required initialization in the widget backend for
|
||||
// event tracing. Return true if initialization was successful.
|
||||
bool InitWidgetTracing();
|
||||
|
||||
// Perform any required cleanup in the widget backend for event tracing.
|
||||
void CleanUpWidgetTracing();
|
||||
|
||||
// Fire a tracer event at the UI-thread event loop, and block until
|
||||
// the event is processed. This should only be called by
|
||||
// a thread that's not the UI thread.
|
||||
bool FireAndWaitForTracerEvent();
|
||||
|
||||
// Signal that the event has been received by the event loop.
|
||||
void SignalTracerThread();
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // WIDGET_PUBLIC_WIDGETTRACEEVENT_H_
|
||||
141
widget/WidgetUtils.cpp
Normal file
141
widget/WidgetUtils.cpp
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* 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 "mozilla/WidgetUtils.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIBidiKeyboard.h"
|
||||
#include "nsTArray.h"
|
||||
#ifdef XP_WIN
|
||||
#include "WinUtils.h"
|
||||
#endif
|
||||
#if MOZ_WIDGET_GTK == 3
|
||||
#include "mozilla/WidgetUtilsGtk.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
gfx::Matrix
|
||||
ComputeTransformForRotation(const nsIntRect& aBounds,
|
||||
ScreenRotation aRotation)
|
||||
{
|
||||
gfx::Matrix transform;
|
||||
static const gfx::Float floatPi = static_cast<gfx::Float>(M_PI);
|
||||
|
||||
switch (aRotation) {
|
||||
case ROTATION_0:
|
||||
break;
|
||||
case ROTATION_90:
|
||||
transform.PreTranslate(aBounds.width, 0);
|
||||
transform.PreRotate(floatPi / 2);
|
||||
break;
|
||||
case ROTATION_180:
|
||||
transform.PreTranslate(aBounds.width, aBounds.height);
|
||||
transform.PreRotate(floatPi);
|
||||
break;
|
||||
case ROTATION_270:
|
||||
transform.PreTranslate(0, aBounds.height);
|
||||
transform.PreRotate(floatPi * 3 / 2);
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Unknown rotation");
|
||||
}
|
||||
return transform;
|
||||
}
|
||||
|
||||
gfx::Matrix
|
||||
ComputeTransformForUnRotation(const nsIntRect& aBounds,
|
||||
ScreenRotation aRotation)
|
||||
{
|
||||
gfx::Matrix transform;
|
||||
static const gfx::Float floatPi = static_cast<gfx::Float>(M_PI);
|
||||
|
||||
switch (aRotation) {
|
||||
case ROTATION_0:
|
||||
break;
|
||||
case ROTATION_90:
|
||||
transform.PreTranslate(0, aBounds.height);
|
||||
transform.PreRotate(floatPi * 3 / 2);
|
||||
break;
|
||||
case ROTATION_180:
|
||||
transform.PreTranslate(aBounds.width, aBounds.height);
|
||||
transform.PreRotate(floatPi);
|
||||
break;
|
||||
case ROTATION_270:
|
||||
transform.PreTranslate(aBounds.width, 0);
|
||||
transform.PreRotate(floatPi / 2);
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Unknown rotation");
|
||||
}
|
||||
return transform;
|
||||
}
|
||||
|
||||
nsIntRect RotateRect(nsIntRect aRect,
|
||||
const nsIntRect& aBounds,
|
||||
ScreenRotation aRotation)
|
||||
{
|
||||
switch (aRotation) {
|
||||
case ROTATION_0:
|
||||
return aRect;
|
||||
case ROTATION_90:
|
||||
return nsIntRect(aRect.y,
|
||||
aBounds.width - aRect.x - aRect.width,
|
||||
aRect.height, aRect.width);
|
||||
case ROTATION_180:
|
||||
return nsIntRect(aBounds.width - aRect.x - aRect.width,
|
||||
aBounds.height - aRect.y - aRect.height,
|
||||
aRect.width, aRect.height);
|
||||
case ROTATION_270:
|
||||
return nsIntRect(aBounds.height - aRect.y - aRect.height,
|
||||
aRect.x,
|
||||
aRect.height, aRect.width);
|
||||
default:
|
||||
MOZ_CRASH("Unknown rotation");
|
||||
}
|
||||
}
|
||||
|
||||
namespace widget {
|
||||
|
||||
uint32_t
|
||||
WidgetUtils::IsTouchDeviceSupportPresent()
|
||||
{
|
||||
#ifdef XP_WIN
|
||||
return WinUtils::IsTouchDeviceSupportPresent();
|
||||
#elif MOZ_WIDGET_GTK == 3
|
||||
return WidgetUtilsGTK::IsTouchDeviceSupportPresent();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
WidgetUtils::SendBidiKeyboardInfoToContent()
|
||||
{
|
||||
nsCOMPtr<nsIBidiKeyboard> bidiKeyboard = nsContentUtils::GetBidiKeyboard();
|
||||
if (!bidiKeyboard) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool rtl;
|
||||
if (NS_FAILED(bidiKeyboard->IsLangRTL(&rtl))) {
|
||||
return;
|
||||
}
|
||||
bool bidiKeyboards = false;
|
||||
bidiKeyboard->GetHaveBidiKeyboards(&bidiKeyboards);
|
||||
|
||||
nsTArray<dom::ContentParent*> children;
|
||||
dom::ContentParent::GetAll(children);
|
||||
for (uint32_t i = 0; i < children.Length(); i++) {
|
||||
Unused << children[i]->SendBidiKeyboardNotify(rtl, bidiKeyboards);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
99
widget/WidgetUtils.h
Normal file
99
widget/WidgetUtils.h
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_WidgetUtils_h
|
||||
#define mozilla_WidgetUtils_h
|
||||
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "mozilla/gfx/Matrix.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "nsRect.h"
|
||||
|
||||
class nsPIDOMWindowOuter;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// NB: these must match up with pseudo-enum in nsIScreen.idl.
|
||||
enum ScreenRotation {
|
||||
ROTATION_0 = 0,
|
||||
ROTATION_90,
|
||||
ROTATION_180,
|
||||
ROTATION_270,
|
||||
|
||||
ROTATION_COUNT
|
||||
};
|
||||
|
||||
gfx::Matrix ComputeTransformForRotation(const nsIntRect& aBounds,
|
||||
ScreenRotation aRotation);
|
||||
|
||||
gfx::Matrix ComputeTransformForUnRotation(const nsIntRect& aBounds,
|
||||
ScreenRotation aRotation);
|
||||
|
||||
nsIntRect RotateRect(nsIntRect aRect,
|
||||
const nsIntRect& aBounds,
|
||||
ScreenRotation aRotation);
|
||||
|
||||
namespace widget {
|
||||
|
||||
class WidgetUtils
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Shutdown() is called when "xpcom-will-shutdown" is notified. This is
|
||||
* useful when you need to observe the notification in XP level code under
|
||||
* widget.
|
||||
*/
|
||||
static void Shutdown();
|
||||
|
||||
/**
|
||||
* Starting at the docshell item for the passed in DOM window this looks up
|
||||
* the docshell tree until it finds a docshell item that has a widget.
|
||||
*/
|
||||
static already_AddRefed<nsIWidget> DOMWindowToWidget(nsPIDOMWindowOuter* aDOMWindow);
|
||||
|
||||
/**
|
||||
* Compute our keyCode value (NS_VK_*) from an ASCII character.
|
||||
*/
|
||||
static uint32_t ComputeKeyCodeFromChar(uint32_t aCharCode);
|
||||
|
||||
/**
|
||||
* Get unshifted charCode and shifted charCode for aKeyCode if the keyboad
|
||||
* layout is a Latin keyboard layout.
|
||||
*
|
||||
* @param aKeyCode Our keyCode (NS_VK_*).
|
||||
* @param aIsCapsLock TRUE if CapsLock is Locked. Otherwise, FALSE.
|
||||
* This is used only when aKeyCode is NS_VK_[0-9].
|
||||
* @param aUnshiftedCharCode CharCode for aKeyCode without Shift key.
|
||||
* This may be zero if aKeyCode key doesn't input
|
||||
* a Latin character.
|
||||
* Note that must not be nullptr.
|
||||
* @param aShiftedCharCode CharCode for aKeyCOde with Shift key.
|
||||
* This is always 0 when aKeyCode isn't
|
||||
* NS_VK_[A-Z].
|
||||
* Note that must not be nullptr.
|
||||
*/
|
||||
static void GetLatinCharCodeForKeyCode(uint32_t aKeyCode,
|
||||
bool aIsCapsLock,
|
||||
uint32_t* aUnshiftedCharCode,
|
||||
uint32_t* aShiftedCharCode);
|
||||
|
||||
/**
|
||||
* Does device have touch support
|
||||
*/
|
||||
static uint32_t IsTouchDeviceSupportPresent();
|
||||
|
||||
/**
|
||||
* Send bidi keyboard information to content process
|
||||
*/
|
||||
static void SendBidiKeyboardInfoToContent();
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_WidgetUtils_h
|
||||
37
widget/WindowSurface.h
Normal file
37
widget/WindowSurface.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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/. */
|
||||
|
||||
#ifndef _MOZILLA_WIDGET_WINDOW_SURFACE_H
|
||||
#define _MOZILLA_WIDGET_WINDOW_SURFACE_H
|
||||
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "Units.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
// A class for drawing to double-buffered windows.
|
||||
class WindowSurface {
|
||||
public:
|
||||
virtual ~WindowSurface() {}
|
||||
|
||||
// Locks a region of the window for drawing, returning a draw target
|
||||
// capturing the bounds of the provided region.
|
||||
// Implementations must permit invocation from any thread.
|
||||
virtual already_AddRefed<gfx::DrawTarget> Lock(const LayoutDeviceIntRegion& aRegion) = 0;
|
||||
|
||||
// Swaps the provided invalid region from the back buffer to the window.
|
||||
// Implementations must permit invocation from any thread.
|
||||
virtual void Commit(const LayoutDeviceIntRegion& aInvalidRegion) = 0;
|
||||
|
||||
// Whether the window surface represents a fallback method.
|
||||
virtual bool IsFallback() const { return false; }
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // _MOZILLA_WIDGET_WINDOW_SURFACE_H
|
||||
33
widget/WindowSurfaceX11SHM.cpp
Normal file
33
widget/WindowSurfaceX11SHM.cpp
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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 "WindowSurfaceX11SHM.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
WindowSurfaceX11SHM::WindowSurfaceX11SHM(Display* aDisplay, Drawable aWindow,
|
||||
Visual* aVisual, unsigned int aDepth)
|
||||
{
|
||||
mFrontImage = new nsShmImage(aDisplay, aWindow, aVisual, aDepth);
|
||||
mBackImage = new nsShmImage(aDisplay, aWindow, aVisual, aDepth);
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::DrawTarget>
|
||||
WindowSurfaceX11SHM::Lock(const LayoutDeviceIntRegion& aRegion)
|
||||
{
|
||||
mBackImage.swap(mFrontImage);
|
||||
return mBackImage->CreateDrawTarget(aRegion);
|
||||
}
|
||||
|
||||
void
|
||||
WindowSurfaceX11SHM::Commit(const LayoutDeviceIntRegion& aInvalidRegion)
|
||||
{
|
||||
mBackImage->Put(aInvalidRegion);
|
||||
}
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
35
widget/WindowSurfaceX11SHM.h
Normal file
35
widget/WindowSurfaceX11SHM.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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/. */
|
||||
|
||||
#ifndef _MOZILLA_WIDGET_WINDOW_SURFACE_X11_SHM_H
|
||||
#define _MOZILLA_WIDGET_WINDOW_SURFACE_X11_SHM_H
|
||||
|
||||
#ifdef MOZ_X11
|
||||
|
||||
#include "mozilla/widget/WindowSurface.h"
|
||||
#include "nsShmImage.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
class WindowSurfaceX11SHM : public WindowSurface {
|
||||
public:
|
||||
WindowSurfaceX11SHM(Display* aDisplay, Drawable aWindow, Visual* aVisual,
|
||||
unsigned int aDepth);
|
||||
|
||||
already_AddRefed<gfx::DrawTarget> Lock(const LayoutDeviceIntRegion& aRegion) override;
|
||||
void Commit(const LayoutDeviceIntRegion& aInvalidRegion) override;
|
||||
|
||||
private:
|
||||
RefPtr<nsShmImage> mFrontImage;
|
||||
RefPtr<nsShmImage> mBackImage;
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // MOZ_X11
|
||||
#endif // _MOZILLA_WIDGET_WINDOW_SURFACE_X11_SHM_H
|
||||
89
widget/android/ANRReporter.cpp
Normal file
89
widget/android/ANRReporter.cpp
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* 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 "ANRReporter.h"
|
||||
#include "GeckoProfiler.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
bool
|
||||
ANRReporter::RequestNativeStack(bool aUnwind)
|
||||
{
|
||||
if (profiler_is_active()) {
|
||||
// Don't proceed if profiler is already running
|
||||
return false;
|
||||
}
|
||||
// WARNING: we are on the ANR reporter thread at this point and it is
|
||||
// generally unsafe to use the profiler from off the main thread. However,
|
||||
// the risk here is limited because for most users, the profiler is not run
|
||||
// elsewhere. See the discussion in Bug 863777, comment 13
|
||||
const char *NATIVE_STACK_FEATURES[] =
|
||||
{"leaf", "threads", "privacy"};
|
||||
const char *NATIVE_STACK_UNWIND_FEATURES[] =
|
||||
{"leaf", "threads", "privacy", "stackwalk"};
|
||||
|
||||
const char **features = NATIVE_STACK_FEATURES;
|
||||
size_t features_size = sizeof(NATIVE_STACK_FEATURES);
|
||||
if (aUnwind) {
|
||||
features = NATIVE_STACK_UNWIND_FEATURES;
|
||||
features_size = sizeof(NATIVE_STACK_UNWIND_FEATURES);
|
||||
// We want the new unwinder if the unwind mode has not been set yet
|
||||
putenv("MOZ_PROFILER_NEW=1");
|
||||
}
|
||||
|
||||
const char *NATIVE_STACK_THREADS[] =
|
||||
{"GeckoMain", "Compositor"};
|
||||
// Buffer one sample and let the profiler wait a long time
|
||||
profiler_start(100, 10000, features, features_size / sizeof(char*),
|
||||
NATIVE_STACK_THREADS, sizeof(NATIVE_STACK_THREADS) / sizeof(char*));
|
||||
return true;
|
||||
}
|
||||
|
||||
jni::String::LocalRef
|
||||
ANRReporter::GetNativeStack()
|
||||
{
|
||||
if (!profiler_is_active()) {
|
||||
// Maybe profiler support is disabled?
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Timeout if we don't get a profiler sample after 5 seconds.
|
||||
const PRIntervalTime timeout = PR_SecondsToInterval(5);
|
||||
const PRIntervalTime startTime = PR_IntervalNow();
|
||||
|
||||
// Pointer to a profile JSON string
|
||||
typedef mozilla::UniquePtr<char[]> ProfilePtr;
|
||||
|
||||
ProfilePtr profile(profiler_get_profile());
|
||||
|
||||
while (profile && !strstr(profile.get(), "\"samples\":[{")) {
|
||||
// no sample yet?
|
||||
if (PR_IntervalNow() - startTime >= timeout) {
|
||||
return nullptr;
|
||||
}
|
||||
usleep(100000ul); // Sleep for 100ms
|
||||
profile = ProfilePtr(profiler_get_profile());
|
||||
}
|
||||
|
||||
if (profile) {
|
||||
return jni::String::Param(profile.get());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
ANRReporter::ReleaseNativeStack()
|
||||
{
|
||||
if (!profiler_is_active()) {
|
||||
// Maybe profiler support is disabled?
|
||||
return;
|
||||
}
|
||||
profiler_stop();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
26
widget/android/ANRReporter.h
Normal file
26
widget/android/ANRReporter.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* 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/. */
|
||||
|
||||
#ifndef ANRReporter_h__
|
||||
#define ANRReporter_h__
|
||||
|
||||
#include "FennecJNINatives.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ANRReporter : public java::ANRReporter::Natives<ANRReporter>
|
||||
{
|
||||
private:
|
||||
ANRReporter();
|
||||
|
||||
public:
|
||||
static bool RequestNativeStack(bool aUnwind);
|
||||
static jni::String::LocalRef GetNativeStack();
|
||||
static void ReleaseNativeStack();
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // ANRReporter_h__
|
||||
126
widget/android/AndroidAlerts.cpp
Normal file
126
widget/android/AndroidAlerts.cpp
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
/* -*- Mode: c++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4; -*- */
|
||||
/* 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 "AndroidAlerts.h"
|
||||
#include "GeneratedJNIWrappers.h"
|
||||
#include "nsAlertsUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
NS_IMPL_ISUPPORTS(AndroidAlerts, nsIAlertsService)
|
||||
|
||||
StaticAutoPtr<AndroidAlerts::ListenerMap> AndroidAlerts::sListenerMap;
|
||||
|
||||
NS_IMETHODIMP
|
||||
AndroidAlerts::ShowAlertNotification(const nsAString & aImageUrl,
|
||||
const nsAString & aAlertTitle,
|
||||
const nsAString & aAlertText,
|
||||
bool aAlertTextClickable,
|
||||
const nsAString & aAlertCookie,
|
||||
nsIObserver * aAlertListener,
|
||||
const nsAString & aAlertName,
|
||||
const nsAString & aBidi,
|
||||
const nsAString & aLang,
|
||||
const nsAString & aData,
|
||||
nsIPrincipal * aPrincipal,
|
||||
bool aInPrivateBrowsing,
|
||||
bool aRequireInteraction)
|
||||
{
|
||||
MOZ_ASSERT_UNREACHABLE("Should be implemented by nsAlertsService.");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AndroidAlerts::ShowAlert(nsIAlertNotification* aAlert,
|
||||
nsIObserver* aAlertListener)
|
||||
{
|
||||
return ShowPersistentNotification(EmptyString(), aAlert, aAlertListener);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AndroidAlerts::ShowPersistentNotification(const nsAString& aPersistentData,
|
||||
nsIAlertNotification* aAlert,
|
||||
nsIObserver* aAlertListener)
|
||||
{
|
||||
// nsAlertsService disables our alerts backend if we ever return failure
|
||||
// here. To keep the backend enabled, we always return NS_OK even if we
|
||||
// encounter an error here.
|
||||
nsresult rv;
|
||||
|
||||
nsAutoString imageUrl;
|
||||
rv = aAlert->GetImageURL(imageUrl);
|
||||
NS_ENSURE_SUCCESS(rv, NS_OK);
|
||||
|
||||
nsAutoString title;
|
||||
rv = aAlert->GetTitle(title);
|
||||
NS_ENSURE_SUCCESS(rv, NS_OK);
|
||||
|
||||
nsAutoString text;
|
||||
rv = aAlert->GetText(text);
|
||||
NS_ENSURE_SUCCESS(rv, NS_OK);
|
||||
|
||||
nsAutoString cookie;
|
||||
rv = aAlert->GetCookie(cookie);
|
||||
NS_ENSURE_SUCCESS(rv, NS_OK);
|
||||
|
||||
nsAutoString name;
|
||||
rv = aAlert->GetName(name);
|
||||
NS_ENSURE_SUCCESS(rv, NS_OK);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
rv = aAlert->GetPrincipal(getter_AddRefs(principal));
|
||||
NS_ENSURE_SUCCESS(rv, NS_OK);
|
||||
|
||||
nsAutoString host;
|
||||
nsAlertsUtils::GetSourceHostPort(principal, host);
|
||||
|
||||
if (aPersistentData.IsEmpty() && aAlertListener) {
|
||||
if (!sListenerMap) {
|
||||
sListenerMap = new ListenerMap();
|
||||
}
|
||||
// This will remove any observers already registered for this name.
|
||||
sListenerMap->Put(name, aAlertListener);
|
||||
}
|
||||
|
||||
java::GeckoAppShell::ShowNotification(
|
||||
name, cookie, title, text, host, imageUrl,
|
||||
!aPersistentData.IsEmpty() ? jni::StringParam(aPersistentData)
|
||||
: jni::StringParam(nullptr));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AndroidAlerts::CloseAlert(const nsAString& aAlertName,
|
||||
nsIPrincipal* aPrincipal)
|
||||
{
|
||||
// We delete the entry in sListenerMap later, when CloseNotification calls
|
||||
// NotifyListener.
|
||||
java::GeckoAppShell::CloseNotification(aAlertName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
AndroidAlerts::NotifyListener(const nsAString& aName, const char* aTopic,
|
||||
const char16_t* aCookie)
|
||||
{
|
||||
if (!sListenerMap) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserver> listener = sListenerMap->Get(aName);
|
||||
if (!listener) {
|
||||
return;
|
||||
}
|
||||
|
||||
listener->Observe(nullptr, aTopic, aCookie);
|
||||
|
||||
if (NS_LITERAL_CSTRING("alertfinished").Equals(aTopic)) {
|
||||
sListenerMap->Remove(aName);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
44
widget/android/AndroidAlerts.h
Normal file
44
widget/android/AndroidAlerts.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/* -*- Mode: c++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4; -*- */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_widget_AndroidAlerts_h__
|
||||
#define mozilla_widget_AndroidAlerts_h__
|
||||
|
||||
#include "nsInterfaceHashtable.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsIAlertsService.h"
|
||||
#include "nsIObserver.h"
|
||||
|
||||
#include "mozilla/StaticPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
class AndroidAlerts : public nsIAlertsService
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIALERTSSERVICE
|
||||
|
||||
AndroidAlerts() {}
|
||||
|
||||
static void NotifyListener(const nsAString& aName, const char* aTopic,
|
||||
const char16_t* aCookie);
|
||||
|
||||
protected:
|
||||
virtual ~AndroidAlerts()
|
||||
{
|
||||
sListenerMap = nullptr;
|
||||
}
|
||||
|
||||
using ListenerMap = nsInterfaceHashtable<nsStringHashKey, nsIObserver>;
|
||||
static StaticAutoPtr<ListenerMap> sListenerMap;
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // nsAndroidAlerts_h__
|
||||
1126
widget/android/AndroidBridge.cpp
Normal file
1126
widget/android/AndroidBridge.cpp
Normal file
File diff suppressed because it is too large
Load diff
419
widget/android/AndroidBridge.h
Normal file
419
widget/android/AndroidBridge.h
Normal file
|
|
@ -0,0 +1,419 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* 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/. */
|
||||
|
||||
#ifndef AndroidBridge_h__
|
||||
#define AndroidBridge_h__
|
||||
|
||||
#include <jni.h>
|
||||
#include <android/log.h>
|
||||
#include <cstdlib>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "APKOpen.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCOMArray.h"
|
||||
|
||||
#include "GeneratedJNIWrappers.h"
|
||||
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsIMIMEInfo.h"
|
||||
#include "nsColor.h"
|
||||
#include "gfxRect.h"
|
||||
|
||||
#include "nsIAndroidBridge.h"
|
||||
#include "nsIDOMDOMCursor.h"
|
||||
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/Types.h"
|
||||
#include "mozilla/gfx/Point.h"
|
||||
#include "mozilla/jni/Utils.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsDataHashtable.h"
|
||||
|
||||
#include "Units.h"
|
||||
|
||||
// Some debug #defines
|
||||
// #define DEBUG_ANDROID_EVENTS
|
||||
// #define DEBUG_ANDROID_WIDGET
|
||||
|
||||
class nsPIDOMWindowOuter;
|
||||
|
||||
namespace base {
|
||||
class Thread;
|
||||
} // end namespace base
|
||||
|
||||
typedef void* EGLSurface;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class AutoLocalJNIFrame;
|
||||
class Runnable;
|
||||
|
||||
namespace hal {
|
||||
class BatteryInformation;
|
||||
class NetworkInformation;
|
||||
} // namespace hal
|
||||
|
||||
// The order and number of the members in this structure must correspond
|
||||
// to the attrsAppearance array in GeckoAppShell.getSystemColors()
|
||||
typedef struct AndroidSystemColors {
|
||||
nscolor textColorPrimary;
|
||||
nscolor textColorPrimaryInverse;
|
||||
nscolor textColorSecondary;
|
||||
nscolor textColorSecondaryInverse;
|
||||
nscolor textColorTertiary;
|
||||
nscolor textColorTertiaryInverse;
|
||||
nscolor textColorHighlight;
|
||||
nscolor colorForeground;
|
||||
nscolor colorBackground;
|
||||
nscolor panelColorForeground;
|
||||
nscolor panelColorBackground;
|
||||
} AndroidSystemColors;
|
||||
|
||||
class MessageCursorContinueCallback : public nsICursorContinueCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICURSORCONTINUECALLBACK
|
||||
|
||||
MessageCursorContinueCallback(int aRequestId)
|
||||
: mRequestId(aRequestId)
|
||||
{
|
||||
}
|
||||
private:
|
||||
virtual ~MessageCursorContinueCallback()
|
||||
{
|
||||
}
|
||||
|
||||
int mRequestId;
|
||||
};
|
||||
|
||||
class AndroidBridge final
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
// Values for NotifyIME, in addition to values from the Gecko
|
||||
// IMEMessage enum; use negative values here to prevent conflict
|
||||
NOTIFY_IME_OPEN_VKB = -2,
|
||||
NOTIFY_IME_REPLY_EVENT = -1,
|
||||
};
|
||||
|
||||
enum {
|
||||
LAYER_CLIENT_TYPE_NONE = 0,
|
||||
LAYER_CLIENT_TYPE_GL = 2 // AndroidGeckoGLLayerClient
|
||||
};
|
||||
|
||||
static bool IsJavaUiThread() {
|
||||
return pthread_equal(pthread_self(), ::getJavaUiThread());
|
||||
}
|
||||
|
||||
static void ConstructBridge();
|
||||
static void DeconstructBridge();
|
||||
|
||||
static AndroidBridge *Bridge() {
|
||||
return sBridge;
|
||||
}
|
||||
|
||||
void ContentDocumentChanged(mozIDOMWindowProxy* aDOMWindow);
|
||||
bool IsContentDocumentDisplayed(mozIDOMWindowProxy* aDOMWindow);
|
||||
|
||||
bool GetHandlersForURL(const nsAString& aURL,
|
||||
nsIMutableArray* handlersArray = nullptr,
|
||||
nsIHandlerApp **aDefaultApp = nullptr,
|
||||
const nsAString& aAction = EmptyString());
|
||||
|
||||
bool GetHandlersForMimeType(const nsAString& aMimeType,
|
||||
nsIMutableArray* handlersArray = nullptr,
|
||||
nsIHandlerApp **aDefaultApp = nullptr,
|
||||
const nsAString& aAction = EmptyString());
|
||||
|
||||
bool GetHWEncoderCapability();
|
||||
bool GetHWDecoderCapability();
|
||||
|
||||
void GetMimeTypeFromExtensions(const nsACString& aFileExt, nsCString& aMimeType);
|
||||
void GetExtensionFromMimeType(const nsACString& aMimeType, nsACString& aFileExt);
|
||||
|
||||
bool GetClipboardText(nsAString& aText);
|
||||
|
||||
int GetDPI();
|
||||
int GetScreenDepth();
|
||||
|
||||
void Vibrate(const nsTArray<uint32_t>& aPattern);
|
||||
|
||||
void GetSystemColors(AndroidSystemColors *aColors);
|
||||
|
||||
void GetIconForExtension(const nsACString& aFileExt, uint32_t aIconSize, uint8_t * const aBuf);
|
||||
|
||||
bool GetStaticStringField(const char *classID, const char *field, nsAString &result, JNIEnv* env = nullptr);
|
||||
|
||||
bool GetStaticIntField(const char *className, const char *fieldName, int32_t* aInt, JNIEnv* env = nullptr);
|
||||
|
||||
// Returns a global reference to the Context for Fennec's Activity. The
|
||||
// caller is responsible for ensuring this doesn't leak by calling
|
||||
// DeleteGlobalRef() when the context is no longer needed.
|
||||
jobject GetGlobalContextRef(void);
|
||||
|
||||
void HandleGeckoMessage(JSContext* cx, JS::HandleObject message);
|
||||
|
||||
void GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo);
|
||||
|
||||
void GetCurrentNetworkInformation(hal::NetworkInformation* aNetworkInfo);
|
||||
|
||||
// These methods don't use a ScreenOrientation because it's an
|
||||
// enum and that would require including the header which requires
|
||||
// include IPC headers which requires including basictypes.h which
|
||||
// requires a lot of changes...
|
||||
uint32_t GetScreenOrientation();
|
||||
uint16_t GetScreenAngle();
|
||||
|
||||
int GetAPIVersion() { return mAPIVersion; }
|
||||
|
||||
nsresult GetProxyForURI(const nsACString & aSpec,
|
||||
const nsACString & aScheme,
|
||||
const nsACString & aHost,
|
||||
const int32_t aPort,
|
||||
nsACString & aResult);
|
||||
|
||||
bool PumpMessageLoop();
|
||||
|
||||
// Utility methods.
|
||||
static jstring NewJavaString(JNIEnv* env, const char16_t* string, uint32_t len);
|
||||
static jstring NewJavaString(JNIEnv* env, const nsAString& string);
|
||||
static jstring NewJavaString(JNIEnv* env, const char* string);
|
||||
static jstring NewJavaString(JNIEnv* env, const nsACString& string);
|
||||
|
||||
static jstring NewJavaString(AutoLocalJNIFrame* frame, const char16_t* string, uint32_t len);
|
||||
static jstring NewJavaString(AutoLocalJNIFrame* frame, const nsAString& string);
|
||||
static jstring NewJavaString(AutoLocalJNIFrame* frame, const char* string);
|
||||
static jstring NewJavaString(AutoLocalJNIFrame* frame, const nsACString& string);
|
||||
|
||||
static jfieldID GetFieldID(JNIEnv* env, jclass jClass, const char* fieldName, const char* fieldType);
|
||||
static jfieldID GetStaticFieldID(JNIEnv* env, jclass jClass, const char* fieldName, const char* fieldType);
|
||||
static jmethodID GetMethodID(JNIEnv* env, jclass jClass, const char* methodName, const char* methodType);
|
||||
static jmethodID GetStaticMethodID(JNIEnv* env, jclass jClass, const char* methodName, const char* methodType);
|
||||
|
||||
static jni::Object::LocalRef ChannelCreate(jni::Object::Param);
|
||||
|
||||
static void InputStreamClose(jni::Object::Param obj);
|
||||
static uint32_t InputStreamAvailable(jni::Object::Param obj);
|
||||
static nsresult InputStreamRead(jni::Object::Param obj, char *aBuf, uint32_t aCount, uint32_t *aRead);
|
||||
|
||||
protected:
|
||||
static nsDataHashtable<nsStringHashKey, nsString> sStoragePaths;
|
||||
|
||||
static AndroidBridge* sBridge;
|
||||
|
||||
AndroidBridge();
|
||||
~AndroidBridge();
|
||||
|
||||
int mAPIVersion;
|
||||
|
||||
// intput stream
|
||||
jclass jReadableByteChannel;
|
||||
jclass jChannels;
|
||||
jmethodID jChannelCreate;
|
||||
jmethodID jByteBufferRead;
|
||||
|
||||
jclass jInputStream;
|
||||
jmethodID jClose;
|
||||
jmethodID jAvailable;
|
||||
|
||||
jmethodID jCalculateLength;
|
||||
|
||||
// some convinient types to have around
|
||||
jclass jStringClass;
|
||||
|
||||
jni::Object::GlobalRef mMessageQueue;
|
||||
jfieldID mMessageQueueMessages;
|
||||
jmethodID mMessageQueueNext;
|
||||
|
||||
private:
|
||||
class DelayedTask;
|
||||
nsTArray<DelayedTask> mUiTaskQueue;
|
||||
mozilla::Mutex mUiTaskQueueLock;
|
||||
|
||||
public:
|
||||
void PostTaskToUiThread(already_AddRefed<Runnable> aTask, int aDelayMs);
|
||||
int64_t RunDelayedUiThreadTasks();
|
||||
};
|
||||
|
||||
class AutoJNIClass {
|
||||
private:
|
||||
JNIEnv* const mEnv;
|
||||
const jclass mClass;
|
||||
|
||||
public:
|
||||
AutoJNIClass(JNIEnv* jEnv, const char* name)
|
||||
: mEnv(jEnv)
|
||||
, mClass(jni::GetClassRef(jEnv, name))
|
||||
{}
|
||||
|
||||
~AutoJNIClass() {
|
||||
mEnv->DeleteLocalRef(mClass);
|
||||
}
|
||||
|
||||
jclass getRawRef() const {
|
||||
return mClass;
|
||||
}
|
||||
|
||||
jclass getGlobalRef() const {
|
||||
return static_cast<jclass>(mEnv->NewGlobalRef(mClass));
|
||||
}
|
||||
|
||||
jfieldID getField(const char* name, const char* type) const {
|
||||
return AndroidBridge::GetFieldID(mEnv, mClass, name, type);
|
||||
}
|
||||
|
||||
jfieldID getStaticField(const char* name, const char* type) const {
|
||||
return AndroidBridge::GetStaticFieldID(mEnv, mClass, name, type);
|
||||
}
|
||||
|
||||
jmethodID getMethod(const char* name, const char* type) const {
|
||||
return AndroidBridge::GetMethodID(mEnv, mClass, name, type);
|
||||
}
|
||||
|
||||
jmethodID getStaticMethod(const char* name, const char* type) const {
|
||||
return AndroidBridge::GetStaticMethodID(mEnv, mClass, name, type);
|
||||
}
|
||||
};
|
||||
|
||||
class AutoJObject {
|
||||
public:
|
||||
AutoJObject(JNIEnv* aJNIEnv = nullptr) : mObject(nullptr)
|
||||
{
|
||||
mJNIEnv = aJNIEnv ? aJNIEnv : jni::GetGeckoThreadEnv();
|
||||
}
|
||||
|
||||
AutoJObject(JNIEnv* aJNIEnv, jobject aObject)
|
||||
{
|
||||
mJNIEnv = aJNIEnv ? aJNIEnv : jni::GetGeckoThreadEnv();
|
||||
mObject = aObject;
|
||||
}
|
||||
|
||||
~AutoJObject() {
|
||||
if (mObject)
|
||||
mJNIEnv->DeleteLocalRef(mObject);
|
||||
}
|
||||
|
||||
jobject operator=(jobject aObject)
|
||||
{
|
||||
if (mObject) {
|
||||
mJNIEnv->DeleteLocalRef(mObject);
|
||||
}
|
||||
return mObject = aObject;
|
||||
}
|
||||
|
||||
operator jobject() {
|
||||
return mObject;
|
||||
}
|
||||
private:
|
||||
JNIEnv* mJNIEnv;
|
||||
jobject mObject;
|
||||
};
|
||||
|
||||
class AutoLocalJNIFrame {
|
||||
public:
|
||||
AutoLocalJNIFrame(int nEntries = 15)
|
||||
: mEntries(nEntries)
|
||||
, mJNIEnv(jni::GetGeckoThreadEnv())
|
||||
, mHasFrameBeenPushed(false)
|
||||
{
|
||||
MOZ_ASSERT(mJNIEnv);
|
||||
Push();
|
||||
}
|
||||
|
||||
AutoLocalJNIFrame(JNIEnv* aJNIEnv, int nEntries = 15)
|
||||
: mEntries(nEntries)
|
||||
, mJNIEnv(aJNIEnv ? aJNIEnv : jni::GetGeckoThreadEnv())
|
||||
, mHasFrameBeenPushed(false)
|
||||
{
|
||||
MOZ_ASSERT(mJNIEnv);
|
||||
Push();
|
||||
}
|
||||
|
||||
~AutoLocalJNIFrame() {
|
||||
if (mHasFrameBeenPushed) {
|
||||
Pop();
|
||||
}
|
||||
}
|
||||
|
||||
JNIEnv* GetEnv() {
|
||||
return mJNIEnv;
|
||||
}
|
||||
|
||||
bool CheckForException() {
|
||||
if (mJNIEnv->ExceptionCheck()) {
|
||||
MOZ_CATCH_JNI_EXCEPTION(mJNIEnv);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Note! Calling Purge makes all previous local refs created in
|
||||
// the AutoLocalJNIFrame's scope INVALID; be sure that you locked down
|
||||
// any local refs that you need to keep around in global refs!
|
||||
void Purge() {
|
||||
Pop();
|
||||
Push();
|
||||
}
|
||||
|
||||
template <typename ReturnType = jobject>
|
||||
ReturnType Pop(ReturnType aResult = nullptr) {
|
||||
MOZ_ASSERT(mHasFrameBeenPushed);
|
||||
mHasFrameBeenPushed = false;
|
||||
return static_cast<ReturnType>(
|
||||
mJNIEnv->PopLocalFrame(static_cast<jobject>(aResult)));
|
||||
}
|
||||
|
||||
private:
|
||||
void Push() {
|
||||
MOZ_ASSERT(!mHasFrameBeenPushed);
|
||||
// Make sure there is enough space to store a local ref to the
|
||||
// exception. I am not completely sure this is needed, but does
|
||||
// not hurt.
|
||||
if (mJNIEnv->PushLocalFrame(mEntries + 1) != 0) {
|
||||
CheckForException();
|
||||
return;
|
||||
}
|
||||
mHasFrameBeenPushed = true;
|
||||
}
|
||||
|
||||
const int mEntries;
|
||||
JNIEnv* const mJNIEnv;
|
||||
bool mHasFrameBeenPushed;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#define NS_ANDROIDBRIDGE_CID \
|
||||
{ 0x0FE2321D, 0xEBD9, 0x467D, \
|
||||
{ 0xA7, 0x43, 0x03, 0xA6, 0x8D, 0x40, 0x59, 0x9E } }
|
||||
|
||||
class nsAndroidBridge final : public nsIAndroidBridge,
|
||||
public nsIObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIANDROIDBRIDGE
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
nsAndroidBridge();
|
||||
|
||||
private:
|
||||
~nsAndroidBridge();
|
||||
|
||||
void AddObservers();
|
||||
void RemoveObservers();
|
||||
|
||||
void UpdateAudioPlayingWindows(uint64_t aWindowId, bool aPlaying);
|
||||
|
||||
nsTArray<uint64_t> mAudioPlayingWindows;
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
#endif /* AndroidBridge_h__ */
|
||||
13
widget/android/AndroidBridgeUtilities.h
Normal file
13
widget/android/AndroidBridgeUtilities.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef ALOG
|
||||
#if defined(DEBUG) || defined(FORCE_ALOG)
|
||||
#define ALOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gecko" , ## args)
|
||||
#else
|
||||
#define ALOG(args...) ((void)0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#define ALOG_BRIDGE(args...) ALOG(args)
|
||||
#else
|
||||
#define ALOG_BRIDGE(args...) ((void)0)
|
||||
#endif
|
||||
63
widget/android/AndroidCompositorWidget.cpp
Normal file
63
widget/android/AndroidCompositorWidget.cpp
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=2 et tw=80 : */
|
||||
/* 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 "AndroidCompositorWidget.h"
|
||||
#include "nsWindow.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
void
|
||||
AndroidCompositorWidget::SetFirstPaintViewport(const LayerIntPoint& aOffset,
|
||||
const CSSToLayerScale& aZoom,
|
||||
const CSSRect& aCssPageRect)
|
||||
{
|
||||
auto layerClient = static_cast<nsWindow*>(RealWidget())->GetLayerClient();
|
||||
if (!layerClient) {
|
||||
return;
|
||||
}
|
||||
|
||||
layerClient->SetFirstPaintViewport(
|
||||
float(aOffset.x), float(aOffset.y), aZoom.scale, aCssPageRect.x,
|
||||
aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost());
|
||||
}
|
||||
|
||||
void
|
||||
AndroidCompositorWidget::SyncFrameMetrics(const ParentLayerPoint& aScrollOffset,
|
||||
const CSSToParentLayerScale& aZoom,
|
||||
const CSSRect& aCssPageRect,
|
||||
const CSSRect& aDisplayPort,
|
||||
const CSSToLayerScale& aPaintedResolution,
|
||||
bool aLayersUpdated,
|
||||
int32_t aPaintSyncId,
|
||||
ScreenMargin& aFixedLayerMargins)
|
||||
{
|
||||
auto layerClient = static_cast<nsWindow*>(RealWidget())->GetLayerClient();
|
||||
if (!layerClient) {
|
||||
return;
|
||||
}
|
||||
|
||||
// convert the displayport rect from document-relative CSS pixels to
|
||||
// document-relative device pixels
|
||||
LayerIntRect dp = gfx::RoundedToInt(aDisplayPort * aPaintedResolution);
|
||||
|
||||
java::ViewTransform::LocalRef viewTransform = layerClient->SyncFrameMetrics(
|
||||
aScrollOffset.x, aScrollOffset.y, aZoom.scale,
|
||||
aCssPageRect.x, aCssPageRect.y,
|
||||
aCssPageRect.XMost(), aCssPageRect.YMost(),
|
||||
dp.x, dp.y, dp.width, dp.height,
|
||||
aPaintedResolution.scale, aLayersUpdated, aPaintSyncId);
|
||||
|
||||
MOZ_ASSERT(viewTransform, "No view transform object!");
|
||||
|
||||
aFixedLayerMargins.top = viewTransform->FixedLayerMarginTop();
|
||||
aFixedLayerMargins.right = viewTransform->FixedLayerMarginRight();
|
||||
aFixedLayerMargins.bottom = viewTransform->FixedLayerMarginBottom();
|
||||
aFixedLayerMargins.left = viewTransform->FixedLayerMarginLeft();
|
||||
}
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
44
widget/android/AndroidCompositorWidget.h
Normal file
44
widget/android/AndroidCompositorWidget.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* 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/. */
|
||||
|
||||
#ifndef mozilla_widget_AndroidCompositorWidget_h
|
||||
#define mozilla_widget_AndroidCompositorWidget_h
|
||||
|
||||
#include "mozilla/widget/InProcessCompositorWidget.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
/**
|
||||
* AndroidCompositorWidget inherits from InProcessCompositorWidget because
|
||||
* Android does not support OOP compositing yet. Once it does,
|
||||
* AndroidCompositorWidget will be made to inherit from CompositorWidget
|
||||
* instead.
|
||||
*/
|
||||
class AndroidCompositorWidget final : public InProcessCompositorWidget
|
||||
{
|
||||
public:
|
||||
using InProcessCompositorWidget::InProcessCompositorWidget;
|
||||
|
||||
AndroidCompositorWidget* AsAndroid() override { return this; }
|
||||
|
||||
void SetFirstPaintViewport(const LayerIntPoint& aOffset,
|
||||
const CSSToLayerScale& aZoom,
|
||||
const CSSRect& aCssPageRect);
|
||||
|
||||
void SyncFrameMetrics(const ParentLayerPoint& aScrollOffset,
|
||||
const CSSToParentLayerScale& aZoom,
|
||||
const CSSRect& aCssPageRect,
|
||||
const CSSRect& aDisplayPort,
|
||||
const CSSToLayerScale& aPaintedResolution,
|
||||
bool aLayersUpdated,
|
||||
int32_t aPaintSyncId,
|
||||
ScreenMargin& aFixedLayerMargins);
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_widget_AndroidCompositorWidget_h
|
||||
157
widget/android/AndroidContentController.cpp
Normal file
157
widget/android/AndroidContentController.cpp
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* 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 "AndroidContentController.h"
|
||||
|
||||
#include "AndroidBridge.h"
|
||||
#include "base/message_loop.h"
|
||||
#include "mozilla/layers/APZCCallbackHelper.h"
|
||||
#include "mozilla/layers/IAPZCTreeManager.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsWindow.h"
|
||||
|
||||
using mozilla::layers::IAPZCTreeManager;
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
void
|
||||
AndroidContentController::Destroy()
|
||||
{
|
||||
mAndroidWindow = nullptr;
|
||||
ChromeProcessController::Destroy();
|
||||
}
|
||||
|
||||
void
|
||||
AndroidContentController::NotifyDefaultPrevented(IAPZCTreeManager* aManager,
|
||||
uint64_t aInputBlockId,
|
||||
bool aDefaultPrevented)
|
||||
{
|
||||
if (!AndroidBridge::IsJavaUiThread()) {
|
||||
// The notification must reach the APZ on the Java UI thread (aka the
|
||||
// APZ "controller" thread) but we get it from the Gecko thread, so we
|
||||
// have to throw it onto the other thread.
|
||||
AndroidBridge::Bridge()->PostTaskToUiThread(NewRunnableMethod<uint64_t, bool>(
|
||||
aManager, &IAPZCTreeManager::ContentReceivedInputBlock,
|
||||
aInputBlockId, aDefaultPrevented), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
aManager->ContentReceivedInputBlock(aInputBlockId, aDefaultPrevented);
|
||||
}
|
||||
|
||||
void
|
||||
AndroidContentController::DispatchSingleTapToObservers(const LayoutDevicePoint& aPoint,
|
||||
const ScrollableLayerGuid& aGuid) const
|
||||
{
|
||||
nsIContent* content = nsLayoutUtils::FindContentFor(aGuid.mScrollId);
|
||||
nsPresContext* context = content
|
||||
? mozilla::layers::APZCCallbackHelper::GetPresContextForContent(content)
|
||||
: nullptr;
|
||||
|
||||
if (!context) {
|
||||
return;
|
||||
}
|
||||
|
||||
CSSPoint point = mozilla::layers::APZCCallbackHelper::ApplyCallbackTransform(
|
||||
aPoint / context->CSSToDevPixelScale(), aGuid);
|
||||
|
||||
nsPresContext* rcdContext = context->GetToplevelContentDocumentPresContext();
|
||||
if (rcdContext && rcdContext->PresShell()->ScaleToResolution()) {
|
||||
// We need to convert from the root document to the root content document,
|
||||
// by unapplying the resolution that's on the content document.
|
||||
const float resolution = rcdContext->PresShell()->GetResolution();
|
||||
point.x /= resolution;
|
||||
point.y /= resolution;
|
||||
}
|
||||
|
||||
CSSIntPoint rounded = RoundedToInt(point);
|
||||
nsAppShell::PostEvent([rounded] {
|
||||
nsCOMPtr<nsIObserverService> obsServ =
|
||||
mozilla::services::GetObserverService();
|
||||
if (!obsServ) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsPrintfCString data("{\"x\":%d,\"y\":%d}", rounded.x, rounded.y);
|
||||
obsServ->NotifyObservers(nullptr, "Gesture:SingleTap",
|
||||
NS_ConvertASCIItoUTF16(data).get());
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
AndroidContentController::HandleTap(TapType aType, const LayoutDevicePoint& aPoint,
|
||||
Modifiers aModifiers,
|
||||
const ScrollableLayerGuid& aGuid,
|
||||
uint64_t aInputBlockId)
|
||||
{
|
||||
// This function will get invoked first on the Java UI thread, and then
|
||||
// again on the main thread (because of the code in ChromeProcessController::
|
||||
// HandleTap). We want to post the SingleTap message once; it can be
|
||||
// done from either thread but we need access to the callback transform
|
||||
// so we do it from the main thread.
|
||||
if (NS_IsMainThread() &&
|
||||
(aType == TapType::eSingleTap || aType == TapType::eSecondTap)) {
|
||||
DispatchSingleTapToObservers(aPoint, aGuid);
|
||||
}
|
||||
|
||||
ChromeProcessController::HandleTap(aType, aPoint, aModifiers, aGuid, aInputBlockId);
|
||||
}
|
||||
|
||||
void
|
||||
AndroidContentController::PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs)
|
||||
{
|
||||
AndroidBridge::Bridge()->PostTaskToUiThread(Move(aTask), aDelayMs);
|
||||
}
|
||||
void
|
||||
AndroidContentController::UpdateOverscrollVelocity(const float aX, const float aY, const bool aIsRootContent)
|
||||
{
|
||||
if (aIsRootContent && mAndroidWindow) {
|
||||
mAndroidWindow->UpdateOverscrollVelocity(aX, aY);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AndroidContentController::UpdateOverscrollOffset(const float aX, const float aY, const bool aIsRootContent)
|
||||
{
|
||||
if (aIsRootContent && mAndroidWindow) {
|
||||
mAndroidWindow->UpdateOverscrollOffset(aX, aY);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AndroidContentController::SetScrollingRootContent(const bool isRootContent)
|
||||
{
|
||||
if (mAndroidWindow) {
|
||||
mAndroidWindow->SetScrollingRootContent(isRootContent);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AndroidContentController::NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
|
||||
APZStateChange aChange,
|
||||
int aArg)
|
||||
{
|
||||
// This function may get invoked twice, if the first invocation is not on
|
||||
// the main thread then the ChromeProcessController version of this function
|
||||
// will redispatch to the main thread. We want to make sure that our handling
|
||||
// only happens on the main thread.
|
||||
ChromeProcessController::NotifyAPZStateChange(aGuid, aChange, aArg);
|
||||
if (NS_IsMainThread()) {
|
||||
nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
|
||||
if (aChange == layers::GeckoContentController::APZStateChange::eTransformEnd) {
|
||||
// This is used by tests to determine when the APZ is done doing whatever
|
||||
// it's doing. XXX generify this as needed when writing additional tests.
|
||||
observerService->NotifyObservers(nullptr, "APZ:TransformEnd", nullptr);
|
||||
observerService->NotifyObservers(nullptr, "PanZoom:StateChange", u"NOTHING");
|
||||
} else if (aChange == layers::GeckoContentController::APZStateChange::eTransformBegin) {
|
||||
observerService->NotifyObservers(nullptr, "PanZoom:StateChange", u"PANNING");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
59
widget/android/AndroidContentController.h
Normal file
59
widget/android/AndroidContentController.h
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* 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/. */
|
||||
|
||||
#ifndef AndroidContentController_h__
|
||||
#define AndroidContentController_h__
|
||||
|
||||
#include "mozilla/layers/ChromeProcessController.h"
|
||||
#include "mozilla/EventForwards.h" // for Modifiers
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsIDOMWindowUtils.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsWindow.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
class APZEventState;
|
||||
class IAPZCTreeManager;
|
||||
}
|
||||
namespace widget {
|
||||
|
||||
class AndroidContentController final
|
||||
: public mozilla::layers::ChromeProcessController
|
||||
{
|
||||
public:
|
||||
AndroidContentController(nsWindow* aWindow,
|
||||
mozilla::layers::APZEventState* aAPZEventState,
|
||||
mozilla::layers::IAPZCTreeManager* aAPZCTreeManager)
|
||||
: mozilla::layers::ChromeProcessController(aWindow, aAPZEventState, aAPZCTreeManager)
|
||||
, mAndroidWindow(aWindow)
|
||||
{}
|
||||
|
||||
// ChromeProcessController methods
|
||||
virtual void Destroy() override;
|
||||
void HandleTap(TapType aType, const LayoutDevicePoint& aPoint, Modifiers aModifiers,
|
||||
const ScrollableLayerGuid& aGuid, uint64_t aInputBlockId) override;
|
||||
void PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) override;
|
||||
void UpdateOverscrollVelocity(const float aX, const float aY, const bool aIsRootContent) override;
|
||||
void UpdateOverscrollOffset(const float aX, const float aY, const bool aIsRootContent) override;
|
||||
void SetScrollingRootContent(const bool isRootContent) override;
|
||||
void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
|
||||
APZStateChange aChange,
|
||||
int aArg) override;
|
||||
|
||||
static void NotifyDefaultPrevented(mozilla::layers::IAPZCTreeManager* aManager,
|
||||
uint64_t aInputBlockId, bool aDefaultPrevented);
|
||||
private:
|
||||
nsWindow* mAndroidWindow;
|
||||
|
||||
void DispatchSingleTapToObservers(const LayoutDevicePoint& aPoint,
|
||||
const ScrollableLayerGuid& aGuid) const;
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
58
widget/android/AndroidDirectTexture.h
Normal file
58
widget/android/AndroidDirectTexture.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* 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/. */
|
||||
|
||||
#ifndef AndroidDirectTexture_h_
|
||||
#define AndroidDirectTexture_h_
|
||||
|
||||
#include "gfxTypes.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "AndroidGraphicBuffer.h"
|
||||
#include "nsRect.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* This is a thread safe wrapper around AndroidGraphicBuffer that handles
|
||||
* double buffering. Each call to Bind() flips the buffer when necessary.
|
||||
*
|
||||
* You need to be careful when destroying an instance of this class. If either
|
||||
* buffer is locked by the application of the driver/hardware, bad things will
|
||||
* happen. Be sure that the OpenGL texture is no longer on the screen.
|
||||
*/
|
||||
class AndroidDirectTexture
|
||||
{
|
||||
public:
|
||||
AndroidDirectTexture(uint32_t width, uint32_t height, uint32_t usage, gfxImageFormat format);
|
||||
virtual ~AndroidDirectTexture();
|
||||
|
||||
bool Lock(uint32_t usage, unsigned char **bits);
|
||||
bool Lock(uint32_t usage, const nsIntRect& rect, unsigned char **bits);
|
||||
bool Unlock(bool aFlip = true);
|
||||
|
||||
bool Reallocate(uint32_t aWidth, uint32_t aHeight);
|
||||
bool Reallocate(uint32_t aWidth, uint32_t aHeight, gfxImageFormat aFormat);
|
||||
|
||||
uint32_t Width() { return mWidth; }
|
||||
uint32_t Height() { return mHeight; }
|
||||
|
||||
bool Bind();
|
||||
|
||||
private:
|
||||
mozilla::Mutex mLock;
|
||||
bool mNeedFlip;
|
||||
|
||||
uint32_t mWidth;
|
||||
uint32_t mHeight;
|
||||
gfxImageFormat mFormat;
|
||||
|
||||
AndroidGraphicBuffer* mFrontBuffer;
|
||||
AndroidGraphicBuffer* mBackBuffer;
|
||||
|
||||
AndroidGraphicBuffer* mPendingReallocBuffer;
|
||||
void ReallocPendingBuffer();
|
||||
};
|
||||
|
||||
} /* mozilla */
|
||||
#endif /* AndroidDirectTexture_h_ */
|
||||
72
widget/android/AndroidGraphicBuffer.h
Normal file
72
widget/android/AndroidGraphicBuffer.h
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* 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/. */
|
||||
|
||||
#ifndef AndroidGraphicBuffer_h_
|
||||
#define AndroidGraphicBuffer_h_
|
||||
|
||||
#include "gfxTypes.h"
|
||||
#include "nsRect.h"
|
||||
|
||||
typedef void* EGLImageKHR;
|
||||
typedef void* EGLClientBuffer;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* This class allows access to Android's direct texturing mechanism. Locking
|
||||
* the buffer gives you a pointer you can read/write to directly. It is fully
|
||||
* threadsafe, but you probably really want to use the AndroidDirectTexture
|
||||
* class which will handle double buffering.
|
||||
*
|
||||
* In order to use the buffer in OpenGL, just call Bind() and it will attach
|
||||
* to whatever texture is bound to GL_TEXTURE_2D.
|
||||
*/
|
||||
class AndroidGraphicBuffer
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
UsageSoftwareRead = 1,
|
||||
UsageSoftwareWrite = 1 << 1,
|
||||
UsageTexture = 1 << 2,
|
||||
UsageTarget = 1 << 3,
|
||||
Usage2D = 1 << 4
|
||||
};
|
||||
|
||||
AndroidGraphicBuffer(uint32_t width, uint32_t height, uint32_t usage, gfxImageFormat format);
|
||||
virtual ~AndroidGraphicBuffer();
|
||||
|
||||
int Lock(uint32_t usage, unsigned char **bits);
|
||||
int Lock(uint32_t usage, const nsIntRect& rect, unsigned char **bits);
|
||||
int Unlock();
|
||||
bool Reallocate(uint32_t aWidth, uint32_t aHeight, gfxImageFormat aFormat);
|
||||
|
||||
uint32_t Width() { return mWidth; }
|
||||
uint32_t Height() { return mHeight; }
|
||||
|
||||
bool Bind();
|
||||
|
||||
static bool IsBlacklisted();
|
||||
|
||||
private:
|
||||
uint32_t mWidth;
|
||||
uint32_t mHeight;
|
||||
uint32_t mUsage;
|
||||
gfxImageFormat mFormat;
|
||||
|
||||
bool EnsureInitialized();
|
||||
bool EnsureEGLImage();
|
||||
|
||||
void DestroyBuffer();
|
||||
bool EnsureBufferCreated();
|
||||
|
||||
uint32_t GetAndroidUsage(uint32_t aUsage);
|
||||
uint32_t GetAndroidFormat(gfxImageFormat aFormat);
|
||||
|
||||
void *mHandle;
|
||||
void *mEGLImage;
|
||||
};
|
||||
|
||||
} /* mozilla */
|
||||
#endif /* AndroidGraphicBuffer_h_ */
|
||||
47
widget/android/AndroidJNI.cpp
Normal file
47
widget/android/AndroidJNI.cpp
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* 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 "mozilla/Hal.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#include "AndroidBridge.h"
|
||||
#include "AndroidContentController.h"
|
||||
#include "AndroidGraphicBuffer.h"
|
||||
|
||||
#include <jni.h>
|
||||
#include <pthread.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "nsAppShell.h"
|
||||
#include "nsWindow.h"
|
||||
#include <android/log.h>
|
||||
#include "nsIObserverService.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "mozilla/Unused.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
#include "mozilla/layers/APZCTreeManager.h"
|
||||
#include "nsPluginInstanceOwner.h"
|
||||
#include "AndroidSurfaceTexture.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::layers;
|
||||
using namespace mozilla::widget;
|
||||
|
||||
/* Forward declare all the JNI methods as extern "C" */
|
||||
|
||||
extern "C" {
|
||||
/*
|
||||
* Incoming JNI methods
|
||||
*/
|
||||
|
||||
}
|
||||
140
widget/android/AndroidJNIWrapper.cpp
Normal file
140
widget/android/AndroidJNIWrapper.cpp
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* 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 <android/log.h>
|
||||
#include <dlfcn.h>
|
||||
#include <prthread.h>
|
||||
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/SyncRunnable.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "AndroidBridge.h"
|
||||
|
||||
extern "C" {
|
||||
jclass __jsjni_GetGlobalClassRef(const char *className);
|
||||
}
|
||||
|
||||
class GetGlobalClassRefRunnable : public mozilla::Runnable {
|
||||
public:
|
||||
GetGlobalClassRefRunnable(const char *className, jclass *foundClass) :
|
||||
mClassName(className), mResult(foundClass) {}
|
||||
NS_IMETHOD Run() override {
|
||||
*mResult = __jsjni_GetGlobalClassRef(mClassName);
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
const char *mClassName;
|
||||
jclass *mResult;
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
__attribute__ ((visibility("default")))
|
||||
jclass
|
||||
jsjni_FindClass(const char *className) {
|
||||
// FindClass outside the main thread will run into problems due
|
||||
// to missing the classpath
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
JNIEnv *env = mozilla::jni::GetGeckoThreadEnv();
|
||||
return env->FindClass(className);
|
||||
}
|
||||
|
||||
jclass
|
||||
__jsjni_GetGlobalClassRef(const char *className) {
|
||||
// root class globally
|
||||
JNIEnv *env = mozilla::jni::GetGeckoThreadEnv();
|
||||
jclass globalRef = static_cast<jclass>(env->NewGlobalRef(env->FindClass(className)));
|
||||
if (!globalRef)
|
||||
return nullptr;
|
||||
|
||||
// return the newly create global reference
|
||||
return globalRef;
|
||||
}
|
||||
|
||||
__attribute__ ((visibility("default")))
|
||||
jclass
|
||||
jsjni_GetGlobalClassRef(const char *className) {
|
||||
if (NS_IsMainThread()) {
|
||||
return __jsjni_GetGlobalClassRef(className);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIThread> mainThread;
|
||||
mozilla::DebugOnly<nsresult> rv = NS_GetMainThread(getter_AddRefs(mainThread));
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
jclass foundClass;
|
||||
nsCOMPtr<nsIRunnable> runnable_ref(new GetGlobalClassRefRunnable(className,
|
||||
&foundClass));
|
||||
RefPtr<mozilla::SyncRunnable> sr = new mozilla::SyncRunnable(runnable_ref);
|
||||
sr->DispatchToThread(mainThread);
|
||||
if (!foundClass)
|
||||
return nullptr;
|
||||
|
||||
return foundClass;
|
||||
}
|
||||
|
||||
__attribute__ ((visibility("default")))
|
||||
jmethodID
|
||||
jsjni_GetStaticMethodID(jclass methodClass,
|
||||
const char *methodName,
|
||||
const char *signature) {
|
||||
JNIEnv *env = mozilla::jni::GetGeckoThreadEnv();
|
||||
return env->GetStaticMethodID(methodClass, methodName, signature);
|
||||
}
|
||||
|
||||
__attribute__ ((visibility("default")))
|
||||
bool
|
||||
jsjni_ExceptionCheck() {
|
||||
JNIEnv *env = mozilla::jni::GetGeckoThreadEnv();
|
||||
return env->ExceptionCheck();
|
||||
}
|
||||
|
||||
__attribute__ ((visibility("default")))
|
||||
void
|
||||
jsjni_CallStaticVoidMethodA(jclass cls,
|
||||
jmethodID method,
|
||||
jvalue *values) {
|
||||
JNIEnv *env = mozilla::jni::GetGeckoThreadEnv();
|
||||
|
||||
mozilla::AutoLocalJNIFrame jniFrame(env);
|
||||
env->CallStaticVoidMethodA(cls, method, values);
|
||||
}
|
||||
|
||||
__attribute__ ((visibility("default")))
|
||||
int
|
||||
jsjni_CallStaticIntMethodA(jclass cls,
|
||||
jmethodID method,
|
||||
jvalue *values) {
|
||||
JNIEnv *env = mozilla::jni::GetGeckoThreadEnv();
|
||||
|
||||
mozilla::AutoLocalJNIFrame jniFrame(env);
|
||||
return env->CallStaticIntMethodA(cls, method, values);
|
||||
}
|
||||
|
||||
__attribute__ ((visibility("default")))
|
||||
jobject jsjni_GetGlobalContextRef() {
|
||||
return mozilla::AndroidBridge::Bridge()->GetGlobalContextRef();
|
||||
}
|
||||
|
||||
__attribute__ ((visibility("default")))
|
||||
JavaVM* jsjni_GetVM() {
|
||||
JavaVM* jvm;
|
||||
JNIEnv* const env = mozilla::jni::GetGeckoThreadEnv();
|
||||
MOZ_ALWAYS_TRUE(!env->GetJavaVM(&jvm));
|
||||
return jvm;
|
||||
}
|
||||
|
||||
__attribute__ ((visibility("default")))
|
||||
JNIEnv* jsjni_GetJNIForThread() {
|
||||
return mozilla::jni::GetEnvForThread();
|
||||
}
|
||||
|
||||
// For compatibility with JNI.jsm; some addons bundle their own JNI.jsm,
|
||||
// so we cannot just change the function name used in JNI.jsm.
|
||||
__attribute__ ((visibility("default")))
|
||||
JNIEnv* GetJNIForThread() {
|
||||
return mozilla::jni::GetEnvForThread();
|
||||
}
|
||||
}
|
||||
34
widget/android/AndroidJNIWrapper.h
Normal file
34
widget/android/AndroidJNIWrapper.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* 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/. */
|
||||
|
||||
#ifndef AndroidJNIWrapper_h__
|
||||
#define AndroidJNIWrapper_h__
|
||||
|
||||
#include "mozilla/Types.h"
|
||||
#include <jni.h>
|
||||
#include <android/log.h>
|
||||
|
||||
extern "C" MOZ_EXPORT jclass jsjni_FindClass(const char *className);
|
||||
|
||||
/**
|
||||
* JNIEnv::FindClass alternative.
|
||||
* Callable from any thread, including code
|
||||
* invoked via the JNI that doesn't have MOZILLA_INTERNAL_API defined.
|
||||
* The caller is responsible for ensuring that the class is not leaked by
|
||||
* calling DeleteGlobalRef at an appropriate time.
|
||||
*/
|
||||
extern "C" MOZ_EXPORT jclass jsjni_GetGlobalClassRef(const char *className);
|
||||
|
||||
extern "C" MOZ_EXPORT jmethodID jsjni_GetStaticMethodID(jclass methodClass,
|
||||
const char *methodName,
|
||||
const char *signature);
|
||||
extern "C" MOZ_EXPORT bool jsjni_ExceptionCheck();
|
||||
extern "C" MOZ_EXPORT void jsjni_CallStaticVoidMethodA(jclass cls, jmethodID method, jvalue *values);
|
||||
extern "C" MOZ_EXPORT int jsjni_CallStaticIntMethodA(jclass cls, jmethodID method, jvalue *values);
|
||||
extern "C" MOZ_EXPORT jobject jsjni_GetGlobalContextRef();
|
||||
extern "C" MOZ_EXPORT JavaVM* jsjni_GetVM();
|
||||
extern "C" MOZ_EXPORT JNIEnv* jsjni_GetJNIForThread();
|
||||
|
||||
#endif /* AndroidJNIWrapper_h__ */
|
||||
62
widget/android/AndroidJavaWrappers.cpp
Normal file
62
widget/android/AndroidJavaWrappers.cpp
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* 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 "AndroidJavaWrappers.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
nsJNIString::nsJNIString(jstring jstr, JNIEnv *jenv)
|
||||
{
|
||||
if (!jstr) {
|
||||
SetIsVoid(true);
|
||||
return;
|
||||
}
|
||||
JNIEnv *jni = jenv;
|
||||
if (!jni) {
|
||||
jni = jni::GetGeckoThreadEnv();
|
||||
}
|
||||
const jchar* jCharPtr = jni->GetStringChars(jstr, nullptr);
|
||||
|
||||
if (!jCharPtr) {
|
||||
SetIsVoid(true);
|
||||
return;
|
||||
}
|
||||
|
||||
jsize len = jni->GetStringLength(jstr);
|
||||
|
||||
if (len <= 0) {
|
||||
SetIsVoid(true);
|
||||
} else {
|
||||
Assign(reinterpret_cast<const char16_t*>(jCharPtr), len);
|
||||
}
|
||||
jni->ReleaseStringChars(jstr, jCharPtr);
|
||||
}
|
||||
|
||||
nsJNICString::nsJNICString(jstring jstr, JNIEnv *jenv)
|
||||
{
|
||||
if (!jstr) {
|
||||
SetIsVoid(true);
|
||||
return;
|
||||
}
|
||||
JNIEnv *jni = jenv;
|
||||
if (!jni) {
|
||||
jni = jni::GetGeckoThreadEnv();
|
||||
}
|
||||
const char* jCharPtr = jni->GetStringUTFChars(jstr, nullptr);
|
||||
|
||||
if (!jCharPtr) {
|
||||
SetIsVoid(true);
|
||||
return;
|
||||
}
|
||||
|
||||
jsize len = jni->GetStringUTFLength(jstr);
|
||||
|
||||
if (len <= 0) {
|
||||
SetIsVoid(true);
|
||||
} else {
|
||||
Assign(jCharPtr, len);
|
||||
}
|
||||
jni->ReleaseStringUTFChars(jstr, jCharPtr);
|
||||
}
|
||||
218
widget/android/AndroidJavaWrappers.h
Normal file
218
widget/android/AndroidJavaWrappers.h
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* 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/. */
|
||||
|
||||
#ifndef AndroidJavaWrappers_h__
|
||||
#define AndroidJavaWrappers_h__
|
||||
|
||||
#include <jni.h>
|
||||
#include <android/input.h>
|
||||
#include <android/log.h>
|
||||
#include <android/api-level.h>
|
||||
|
||||
#include "nsRect.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIAndroidBridge.h"
|
||||
#include "mozilla/gfx/Rect.h"
|
||||
#include "mozilla/dom/Touch.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "InputData.h"
|
||||
#include "Units.h"
|
||||
#include "FrameMetrics.h"
|
||||
|
||||
//#define FORCE_ALOG 1
|
||||
|
||||
class nsIAndroidDisplayport;
|
||||
class nsIWidget;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
enum {
|
||||
// These keycode masks are not defined in android/keycodes.h:
|
||||
#if __ANDROID_API__ < 13
|
||||
AKEYCODE_ESCAPE = 111,
|
||||
AKEYCODE_FORWARD_DEL = 112,
|
||||
AKEYCODE_CTRL_LEFT = 113,
|
||||
AKEYCODE_CTRL_RIGHT = 114,
|
||||
AKEYCODE_CAPS_LOCK = 115,
|
||||
AKEYCODE_SCROLL_LOCK = 116,
|
||||
AKEYCODE_META_LEFT = 117,
|
||||
AKEYCODE_META_RIGHT = 118,
|
||||
AKEYCODE_FUNCTION = 119,
|
||||
AKEYCODE_SYSRQ = 120,
|
||||
AKEYCODE_BREAK = 121,
|
||||
AKEYCODE_MOVE_HOME = 122,
|
||||
AKEYCODE_MOVE_END = 123,
|
||||
AKEYCODE_INSERT = 124,
|
||||
AKEYCODE_FORWARD = 125,
|
||||
AKEYCODE_MEDIA_PLAY = 126,
|
||||
AKEYCODE_MEDIA_PAUSE = 127,
|
||||
AKEYCODE_MEDIA_CLOSE = 128,
|
||||
AKEYCODE_MEDIA_EJECT = 129,
|
||||
AKEYCODE_MEDIA_RECORD = 130,
|
||||
AKEYCODE_F1 = 131,
|
||||
AKEYCODE_F2 = 132,
|
||||
AKEYCODE_F3 = 133,
|
||||
AKEYCODE_F4 = 134,
|
||||
AKEYCODE_F5 = 135,
|
||||
AKEYCODE_F6 = 136,
|
||||
AKEYCODE_F7 = 137,
|
||||
AKEYCODE_F8 = 138,
|
||||
AKEYCODE_F9 = 139,
|
||||
AKEYCODE_F10 = 140,
|
||||
AKEYCODE_F11 = 141,
|
||||
AKEYCODE_F12 = 142,
|
||||
AKEYCODE_NUM_LOCK = 143,
|
||||
AKEYCODE_NUMPAD_0 = 144,
|
||||
AKEYCODE_NUMPAD_1 = 145,
|
||||
AKEYCODE_NUMPAD_2 = 146,
|
||||
AKEYCODE_NUMPAD_3 = 147,
|
||||
AKEYCODE_NUMPAD_4 = 148,
|
||||
AKEYCODE_NUMPAD_5 = 149,
|
||||
AKEYCODE_NUMPAD_6 = 150,
|
||||
AKEYCODE_NUMPAD_7 = 151,
|
||||
AKEYCODE_NUMPAD_8 = 152,
|
||||
AKEYCODE_NUMPAD_9 = 153,
|
||||
AKEYCODE_NUMPAD_DIVIDE = 154,
|
||||
AKEYCODE_NUMPAD_MULTIPLY = 155,
|
||||
AKEYCODE_NUMPAD_SUBTRACT = 156,
|
||||
AKEYCODE_NUMPAD_ADD = 157,
|
||||
AKEYCODE_NUMPAD_DOT = 158,
|
||||
AKEYCODE_NUMPAD_COMMA = 159,
|
||||
AKEYCODE_NUMPAD_ENTER = 160,
|
||||
AKEYCODE_NUMPAD_EQUALS = 161,
|
||||
AKEYCODE_NUMPAD_LEFT_PAREN = 162,
|
||||
AKEYCODE_NUMPAD_RIGHT_PAREN = 163,
|
||||
AKEYCODE_VOLUME_MUTE = 164,
|
||||
AKEYCODE_INFO = 165,
|
||||
AKEYCODE_CHANNEL_UP = 166,
|
||||
AKEYCODE_CHANNEL_DOWN = 167,
|
||||
AKEYCODE_ZOOM_IN = 168,
|
||||
AKEYCODE_ZOOM_OUT = 169,
|
||||
AKEYCODE_TV = 170,
|
||||
AKEYCODE_WINDOW = 171,
|
||||
AKEYCODE_GUIDE = 172,
|
||||
AKEYCODE_DVR = 173,
|
||||
AKEYCODE_BOOKMARK = 174,
|
||||
AKEYCODE_CAPTIONS = 175,
|
||||
AKEYCODE_SETTINGS = 176,
|
||||
AKEYCODE_TV_POWER = 177,
|
||||
AKEYCODE_TV_INPUT = 178,
|
||||
AKEYCODE_STB_POWER = 179,
|
||||
AKEYCODE_STB_INPUT = 180,
|
||||
AKEYCODE_AVR_POWER = 181,
|
||||
AKEYCODE_AVR_INPUT = 182,
|
||||
AKEYCODE_PROG_RED = 183,
|
||||
AKEYCODE_PROG_GREEN = 184,
|
||||
AKEYCODE_PROG_YELLOW = 185,
|
||||
AKEYCODE_PROG_BLUE = 186,
|
||||
AKEYCODE_APP_SWITCH = 187,
|
||||
AKEYCODE_BUTTON_1 = 188,
|
||||
AKEYCODE_BUTTON_2 = 189,
|
||||
AKEYCODE_BUTTON_3 = 190,
|
||||
AKEYCODE_BUTTON_4 = 191,
|
||||
AKEYCODE_BUTTON_5 = 192,
|
||||
AKEYCODE_BUTTON_6 = 193,
|
||||
AKEYCODE_BUTTON_7 = 194,
|
||||
AKEYCODE_BUTTON_8 = 195,
|
||||
AKEYCODE_BUTTON_9 = 196,
|
||||
AKEYCODE_BUTTON_10 = 197,
|
||||
AKEYCODE_BUTTON_11 = 198,
|
||||
AKEYCODE_BUTTON_12 = 199,
|
||||
AKEYCODE_BUTTON_13 = 200,
|
||||
AKEYCODE_BUTTON_14 = 201,
|
||||
AKEYCODE_BUTTON_15 = 202,
|
||||
AKEYCODE_BUTTON_16 = 203,
|
||||
#endif
|
||||
#if __ANDROID_API__ < 14
|
||||
AKEYCODE_LANGUAGE_SWITCH = 204,
|
||||
AKEYCODE_MANNER_MODE = 205,
|
||||
AKEYCODE_3D_MODE = 206,
|
||||
#endif
|
||||
#if __ANDROID_API__ < 15
|
||||
AKEYCODE_CONTACTS = 207,
|
||||
AKEYCODE_CALENDAR = 208,
|
||||
AKEYCODE_MUSIC = 209,
|
||||
AKEYCODE_CALCULATOR = 210,
|
||||
#endif
|
||||
#if __ANDROID_API__ < 16
|
||||
AKEYCODE_ZENKAKU_HANKAKU = 211,
|
||||
AKEYCODE_EISU = 212,
|
||||
AKEYCODE_MUHENKAN = 213,
|
||||
AKEYCODE_HENKAN = 214,
|
||||
AKEYCODE_KATAKANA_HIRAGANA = 215,
|
||||
AKEYCODE_YEN = 216,
|
||||
AKEYCODE_RO = 217,
|
||||
AKEYCODE_KANA = 218,
|
||||
AKEYCODE_ASSIST = 219,
|
||||
#endif
|
||||
|
||||
AMETA_FUNCTION_ON = 0x00000008,
|
||||
AMETA_CTRL_ON = 0x00001000,
|
||||
AMETA_CTRL_LEFT_ON = 0x00002000,
|
||||
AMETA_CTRL_RIGHT_ON = 0x00004000,
|
||||
AMETA_META_ON = 0x00010000,
|
||||
AMETA_META_LEFT_ON = 0x00020000,
|
||||
AMETA_META_RIGHT_ON = 0x00040000,
|
||||
AMETA_CAPS_LOCK_ON = 0x00100000,
|
||||
AMETA_NUM_LOCK_ON = 0x00200000,
|
||||
AMETA_SCROLL_LOCK_ON = 0x00400000,
|
||||
|
||||
AMETA_ALT_MASK = AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON | AMETA_ALT_ON,
|
||||
AMETA_CTRL_MASK = AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON | AMETA_CTRL_ON,
|
||||
AMETA_META_MASK = AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON | AMETA_META_ON,
|
||||
AMETA_SHIFT_MASK = AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON | AMETA_SHIFT_ON,
|
||||
};
|
||||
|
||||
class AndroidMotionEvent
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
ACTION_DOWN = 0,
|
||||
ACTION_UP = 1,
|
||||
ACTION_MOVE = 2,
|
||||
ACTION_CANCEL = 3,
|
||||
ACTION_OUTSIDE = 4,
|
||||
ACTION_POINTER_DOWN = 5,
|
||||
ACTION_POINTER_UP = 6,
|
||||
ACTION_HOVER_MOVE = 7,
|
||||
ACTION_HOVER_ENTER = 9,
|
||||
ACTION_HOVER_EXIT = 10,
|
||||
ACTION_MAGNIFY_START = 11,
|
||||
ACTION_MAGNIFY = 12,
|
||||
ACTION_MAGNIFY_END = 13,
|
||||
EDGE_TOP = 0x00000001,
|
||||
EDGE_BOTTOM = 0x00000002,
|
||||
EDGE_LEFT = 0x00000004,
|
||||
EDGE_RIGHT = 0x00000008,
|
||||
SAMPLE_X = 0,
|
||||
SAMPLE_Y = 1,
|
||||
SAMPLE_PRESSURE = 2,
|
||||
SAMPLE_SIZE = 3,
|
||||
NUM_SAMPLE_DATA = 4,
|
||||
TOOL_TYPE_UNKNOWN = 0,
|
||||
TOOL_TYPE_FINGER = 1,
|
||||
TOOL_TYPE_STYLUS = 2,
|
||||
TOOL_TYPE_MOUSE = 3,
|
||||
TOOL_TYPE_ERASER = 4,
|
||||
dummy_java_enum_list_end
|
||||
};
|
||||
};
|
||||
|
||||
class nsJNIString : public nsString
|
||||
{
|
||||
public:
|
||||
nsJNIString(jstring jstr, JNIEnv *jenv);
|
||||
};
|
||||
|
||||
class nsJNICString : public nsCString
|
||||
{
|
||||
public:
|
||||
nsJNICString(jstring jstr, JNIEnv *jenv);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
30
widget/android/GeckoBatteryManager.h
Normal file
30
widget/android/GeckoBatteryManager.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* 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/. */
|
||||
|
||||
#ifndef GeckoBatteryManager_h
|
||||
#define GeckoBatteryManager_h
|
||||
|
||||
#include "GeneratedJNINatives.h"
|
||||
#include "nsAppShell.h"
|
||||
|
||||
#include "mozilla/Hal.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class GeckoBatteryManager final
|
||||
: public java::GeckoBatteryManager::Natives<GeckoBatteryManager>
|
||||
{
|
||||
public:
|
||||
static void
|
||||
OnBatteryChange(double aLevel, bool aCharging, double aRemainingTime)
|
||||
{
|
||||
hal::NotifyBatteryChange(
|
||||
hal::BatteryInformation(aLevel, aCharging, aRemainingTime));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // GeckoBatteryManager_h
|
||||
53
widget/android/GeckoNetworkManager.h
Normal file
53
widget/android/GeckoNetworkManager.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* 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/. */
|
||||
|
||||
#ifndef GeckoNetworkManager_h
|
||||
#define GeckoNetworkManager_h
|
||||
|
||||
#include "GeneratedJNINatives.h"
|
||||
#include "nsAppShell.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsINetworkLinkService.h"
|
||||
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class GeckoNetworkManager final
|
||||
: public java::GeckoNetworkManager::Natives<GeckoNetworkManager>
|
||||
{
|
||||
GeckoNetworkManager() = delete;
|
||||
|
||||
public:
|
||||
static void
|
||||
OnConnectionChanged(int32_t aType, jni::String::Param aSubType,
|
||||
bool aIsWifi, int32_t aGateway)
|
||||
{
|
||||
hal::NotifyNetworkChange(hal::NetworkInformation(
|
||||
aType, aIsWifi, aGateway));
|
||||
|
||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||
if (os) {
|
||||
os->NotifyObservers(nullptr,
|
||||
NS_NETWORK_LINK_TYPE_TOPIC,
|
||||
aSubType->ToString().get());
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
OnStatusChanged(jni::String::Param aStatus)
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
|
||||
if (os) {
|
||||
os->NotifyObservers(nullptr,
|
||||
NS_NETWORK_LINK_TOPIC,
|
||||
aStatus->ToString().get());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // GeckoNetworkManager_h
|
||||
55
widget/android/GeckoScreenOrientation.h
Normal file
55
widget/android/GeckoScreenOrientation.h
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* 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/. */
|
||||
|
||||
#ifndef GeckoScreenOrientation_h
|
||||
#define GeckoScreenOrientation_h
|
||||
|
||||
#include "GeneratedJNINatives.h"
|
||||
#include "nsAppShell.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIScreenManager.h"
|
||||
|
||||
#include "mozilla/Hal.h"
|
||||
#include "mozilla/dom/ScreenOrientation.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class GeckoScreenOrientation final
|
||||
: public java::GeckoScreenOrientation::Natives<GeckoScreenOrientation>
|
||||
{
|
||||
GeckoScreenOrientation() = delete;
|
||||
|
||||
public:
|
||||
static void
|
||||
OnOrientationChange(int16_t aOrientation, int16_t aAngle)
|
||||
{
|
||||
nsCOMPtr<nsIScreenManager> screenMgr =
|
||||
do_GetService("@mozilla.org/gfx/screenmanager;1");
|
||||
nsCOMPtr<nsIScreen> screen;
|
||||
|
||||
if (!screenMgr || NS_FAILED(screenMgr->GetPrimaryScreen(
|
||||
getter_AddRefs(screen))) || !screen) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsIntRect rect;
|
||||
int32_t colorDepth, pixelDepth;
|
||||
|
||||
if (NS_FAILED(screen->GetRect(&rect.x, &rect.y,
|
||||
&rect.width, &rect.height)) ||
|
||||
NS_FAILED(screen->GetColorDepth(&colorDepth)) ||
|
||||
NS_FAILED(screen->GetPixelDepth(&pixelDepth))) {
|
||||
return;
|
||||
}
|
||||
|
||||
hal::NotifyScreenConfigurationChange(hal::ScreenConfiguration(
|
||||
rect, static_cast<dom::ScreenOrientationInternal>(aOrientation),
|
||||
aAngle, colorDepth, pixelDepth));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // GeckoScreenOrientation_h
|
||||
526
widget/android/GeneratedJNINatives.h
Normal file
526
widget/android/GeneratedJNINatives.h
Normal file
|
|
@ -0,0 +1,526 @@
|
|||
// GENERATED CODE
|
||||
// Generated by the Java program at /build/annotationProcessors at compile time
|
||||
// from annotations on Java methods. To update, change the annotations on the
|
||||
// corresponding Java methods and rerun the build. Manually updating this file
|
||||
// will cause your build to fail.
|
||||
|
||||
#ifndef GeneratedJNINatives_h
|
||||
#define GeneratedJNINatives_h
|
||||
|
||||
#include "GeneratedJNIWrappers.h"
|
||||
#include "mozilla/jni/Natives.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace java {
|
||||
|
||||
template<class Impl>
|
||||
class AlarmReceiver::Natives : public mozilla::jni::NativeImpl<AlarmReceiver, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[1];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod AlarmReceiver::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<AlarmReceiver::NotifyAlarmFired_t>(
|
||||
mozilla::jni::NativeStub<AlarmReceiver::NotifyAlarmFired_t, Impl>
|
||||
::template Wrap<&Impl::NotifyAlarmFired>)
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
class AndroidGamepadManager::Natives : public mozilla::jni::NativeImpl<AndroidGamepadManager, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[3];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod AndroidGamepadManager::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<AndroidGamepadManager::OnAxisChange_t>(
|
||||
mozilla::jni::NativeStub<AndroidGamepadManager::OnAxisChange_t, Impl>
|
||||
::template Wrap<&Impl::OnAxisChange>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<AndroidGamepadManager::OnButtonChange_t>(
|
||||
mozilla::jni::NativeStub<AndroidGamepadManager::OnButtonChange_t, Impl>
|
||||
::template Wrap<&Impl::OnButtonChange>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<AndroidGamepadManager::OnGamepadChange_t>(
|
||||
mozilla::jni::NativeStub<AndroidGamepadManager::OnGamepadChange_t, Impl>
|
||||
::template Wrap<&Impl::OnGamepadChange>)
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
class GeckoAppShell::Natives : public mozilla::jni::NativeImpl<GeckoAppShell, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[8];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod GeckoAppShell::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoAppShell::NotifyObservers_t>(
|
||||
mozilla::jni::NativeStub<GeckoAppShell::NotifyObservers_t, Impl>
|
||||
::template Wrap<&Impl::NotifyObservers>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoAppShell::NotifyAlertListener_t>(
|
||||
mozilla::jni::NativeStub<GeckoAppShell::NotifyAlertListener_t, Impl>
|
||||
::template Wrap<&Impl::NotifyAlertListener>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoAppShell::NotifyUriVisited_t>(
|
||||
mozilla::jni::NativeStub<GeckoAppShell::NotifyUriVisited_t, Impl>
|
||||
::template Wrap<&Impl::NotifyUriVisited>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoAppShell::OnFullScreenPluginHidden_t>(
|
||||
mozilla::jni::NativeStub<GeckoAppShell::OnFullScreenPluginHidden_t, Impl>
|
||||
::template Wrap<&Impl::OnFullScreenPluginHidden>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoAppShell::OnLocationChanged_t>(
|
||||
mozilla::jni::NativeStub<GeckoAppShell::OnLocationChanged_t, Impl>
|
||||
::template Wrap<&Impl::OnLocationChanged>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoAppShell::OnSensorChanged_t>(
|
||||
mozilla::jni::NativeStub<GeckoAppShell::OnSensorChanged_t, Impl>
|
||||
::template Wrap<&Impl::OnSensorChanged>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoAppShell::ReportJavaCrash_t>(
|
||||
mozilla::jni::NativeStub<GeckoAppShell::ReportJavaCrash_t, Impl>
|
||||
::template Wrap<&Impl::ReportJavaCrash>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoAppShell::SyncNotifyObservers_t>(
|
||||
mozilla::jni::NativeStub<GeckoAppShell::SyncNotifyObservers_t, Impl>
|
||||
::template Wrap<&Impl::SyncNotifyObservers>)
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
class GeckoAppShell::CameraCallback::Natives : public mozilla::jni::NativeImpl<CameraCallback, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[1];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod GeckoAppShell::CameraCallback::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoAppShell::CameraCallback::OnFrameData_t>(
|
||||
mozilla::jni::NativeStub<GeckoAppShell::CameraCallback::OnFrameData_t, Impl>
|
||||
::template Wrap<&Impl::OnFrameData>)
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
class GeckoBatteryManager::Natives : public mozilla::jni::NativeImpl<GeckoBatteryManager, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[1];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod GeckoBatteryManager::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoBatteryManager::OnBatteryChange_t>(
|
||||
mozilla::jni::NativeStub<GeckoBatteryManager::OnBatteryChange_t, Impl>
|
||||
::template Wrap<&Impl::OnBatteryChange>)
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
class GeckoEditable::Natives : public mozilla::jni::NativeImpl<GeckoEditable, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[7];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod GeckoEditable::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoEditable::DisposeNative_t>(
|
||||
mozilla::jni::NativeStub<GeckoEditable::DisposeNative_t, Impl>
|
||||
::template Wrap<&Impl::DisposeNative>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoEditable::OnImeAddCompositionRange_t>(
|
||||
mozilla::jni::NativeStub<GeckoEditable::OnImeAddCompositionRange_t, Impl>
|
||||
::template Wrap<&Impl::OnImeAddCompositionRange>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoEditable::OnImeReplaceText_t>(
|
||||
mozilla::jni::NativeStub<GeckoEditable::OnImeReplaceText_t, Impl>
|
||||
::template Wrap<&Impl::OnImeReplaceText>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoEditable::OnImeRequestCursorUpdates_t>(
|
||||
mozilla::jni::NativeStub<GeckoEditable::OnImeRequestCursorUpdates_t, Impl>
|
||||
::template Wrap<&Impl::OnImeRequestCursorUpdates>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoEditable::OnImeSynchronize_t>(
|
||||
mozilla::jni::NativeStub<GeckoEditable::OnImeSynchronize_t, Impl>
|
||||
::template Wrap<&Impl::OnImeSynchronize>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoEditable::OnImeUpdateComposition_t>(
|
||||
mozilla::jni::NativeStub<GeckoEditable::OnImeUpdateComposition_t, Impl>
|
||||
::template Wrap<&Impl::OnImeUpdateComposition>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoEditable::OnKeyEvent_t>(
|
||||
mozilla::jni::NativeStub<GeckoEditable::OnKeyEvent_t, Impl>
|
||||
::template Wrap<&Impl::OnKeyEvent>)
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
class GeckoNetworkManager::Natives : public mozilla::jni::NativeImpl<GeckoNetworkManager, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[2];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod GeckoNetworkManager::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoNetworkManager::OnConnectionChanged_t>(
|
||||
mozilla::jni::NativeStub<GeckoNetworkManager::OnConnectionChanged_t, Impl>
|
||||
::template Wrap<&Impl::OnConnectionChanged>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoNetworkManager::OnStatusChanged_t>(
|
||||
mozilla::jni::NativeStub<GeckoNetworkManager::OnStatusChanged_t, Impl>
|
||||
::template Wrap<&Impl::OnStatusChanged>)
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
class GeckoScreenOrientation::Natives : public mozilla::jni::NativeImpl<GeckoScreenOrientation, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[1];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod GeckoScreenOrientation::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoScreenOrientation::OnOrientationChange_t>(
|
||||
mozilla::jni::NativeStub<GeckoScreenOrientation::OnOrientationChange_t, Impl>
|
||||
::template Wrap<&Impl::OnOrientationChange>)
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
class GeckoThread::Natives : public mozilla::jni::NativeImpl<GeckoThread, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[6];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod GeckoThread::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoThread::CreateServices_t>(
|
||||
mozilla::jni::NativeStub<GeckoThread::CreateServices_t, Impl>
|
||||
::template Wrap<&Impl::CreateServices>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoThread::OnPause_t>(
|
||||
mozilla::jni::NativeStub<GeckoThread::OnPause_t, Impl>
|
||||
::template Wrap<&Impl::OnPause>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoThread::OnResume_t>(
|
||||
mozilla::jni::NativeStub<GeckoThread::OnResume_t, Impl>
|
||||
::template Wrap<&Impl::OnResume>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoThread::RunUiThreadCallback_t>(
|
||||
mozilla::jni::NativeStub<GeckoThread::RunUiThreadCallback_t, Impl>
|
||||
::template Wrap<&Impl::RunUiThreadCallback>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoThread::SpeculativeConnect_t>(
|
||||
mozilla::jni::NativeStub<GeckoThread::SpeculativeConnect_t, Impl>
|
||||
::template Wrap<&Impl::SpeculativeConnect>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoThread::WaitOnGecko_t>(
|
||||
mozilla::jni::NativeStub<GeckoThread::WaitOnGecko_t, Impl>
|
||||
::template Wrap<&Impl::WaitOnGecko>)
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
class GeckoView::Window::Natives : public mozilla::jni::NativeImpl<Window, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[5];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod GeckoView::Window::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoView::Window::Close_t>(
|
||||
mozilla::jni::NativeStub<GeckoView::Window::Close_t, Impl>
|
||||
::template Wrap<&Impl::Close>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoView::Window::DisposeNative_t>(
|
||||
mozilla::jni::NativeStub<GeckoView::Window::DisposeNative_t, Impl>
|
||||
::template Wrap<&Impl::DisposeNative>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoView::Window::LoadUri_t>(
|
||||
mozilla::jni::NativeStub<GeckoView::Window::LoadUri_t, Impl>
|
||||
::template Wrap<&Impl::LoadUri>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoView::Window::Open_t>(
|
||||
mozilla::jni::NativeStub<GeckoView::Window::Open_t, Impl>
|
||||
::template Wrap<&Impl::Open>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoView::Window::Reattach_t>(
|
||||
mozilla::jni::NativeStub<GeckoView::Window::Reattach_t, Impl>
|
||||
::template Wrap<&Impl::Reattach>)
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
class PrefsHelper::Natives : public mozilla::jni::NativeImpl<PrefsHelper, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[4];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod PrefsHelper::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<PrefsHelper::AddObserver_t>(
|
||||
mozilla::jni::NativeStub<PrefsHelper::AddObserver_t, Impl>
|
||||
::template Wrap<&Impl::AddObserver>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<PrefsHelper::GetPrefs_t>(
|
||||
mozilla::jni::NativeStub<PrefsHelper::GetPrefs_t, Impl>
|
||||
::template Wrap<&Impl::GetPrefs>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<PrefsHelper::RemoveObserver_t>(
|
||||
mozilla::jni::NativeStub<PrefsHelper::RemoveObserver_t, Impl>
|
||||
::template Wrap<&Impl::RemoveObserver>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<PrefsHelper::SetPref_t>(
|
||||
mozilla::jni::NativeStub<PrefsHelper::SetPref_t, Impl>
|
||||
::template Wrap<&Impl::SetPref>)
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
class SurfaceTextureListener::Natives : public mozilla::jni::NativeImpl<SurfaceTextureListener, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[1];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod SurfaceTextureListener::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<SurfaceTextureListener::OnFrameAvailable_t>(
|
||||
mozilla::jni::NativeStub<SurfaceTextureListener::OnFrameAvailable_t, Impl>
|
||||
::template Wrap<&Impl::OnFrameAvailable>)
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
class LayerView::Compositor::Natives : public mozilla::jni::NativeImpl<Compositor, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[7];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod LayerView::Compositor::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<LayerView::Compositor::AttachToJava_t>(
|
||||
mozilla::jni::NativeStub<LayerView::Compositor::AttachToJava_t, Impl>
|
||||
::template Wrap<&Impl::AttachToJava>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<LayerView::Compositor::CreateCompositor_t>(
|
||||
mozilla::jni::NativeStub<LayerView::Compositor::CreateCompositor_t, Impl>
|
||||
::template Wrap<&Impl::CreateCompositor>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<LayerView::Compositor::DisposeNative_t>(
|
||||
mozilla::jni::NativeStub<LayerView::Compositor::DisposeNative_t, Impl>
|
||||
::template Wrap<&Impl::DisposeNative>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<LayerView::Compositor::OnSizeChanged_t>(
|
||||
mozilla::jni::NativeStub<LayerView::Compositor::OnSizeChanged_t, Impl>
|
||||
::template Wrap<&Impl::OnSizeChanged>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<LayerView::Compositor::SyncInvalidateAndScheduleComposite_t>(
|
||||
mozilla::jni::NativeStub<LayerView::Compositor::SyncInvalidateAndScheduleComposite_t, Impl>
|
||||
::template Wrap<&Impl::SyncInvalidateAndScheduleComposite>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<LayerView::Compositor::SyncPauseCompositor_t>(
|
||||
mozilla::jni::NativeStub<LayerView::Compositor::SyncPauseCompositor_t, Impl>
|
||||
::template Wrap<&Impl::SyncPauseCompositor>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<LayerView::Compositor::SyncResumeResizeCompositor_t>(
|
||||
mozilla::jni::NativeStub<LayerView::Compositor::SyncResumeResizeCompositor_t, Impl>
|
||||
::template Wrap<&Impl::SyncResumeResizeCompositor>)
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
class NativePanZoomController::Natives : public mozilla::jni::NativeImpl<NativePanZoomController, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[7];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod NativePanZoomController::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativePanZoomController::AdjustScrollForSurfaceShift_t>(
|
||||
mozilla::jni::NativeStub<NativePanZoomController::AdjustScrollForSurfaceShift_t, Impl>
|
||||
::template Wrap<&Impl::AdjustScrollForSurfaceShift>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativePanZoomController::DisposeNative_t>(
|
||||
mozilla::jni::NativeStub<NativePanZoomController::DisposeNative_t, Impl>
|
||||
::template Wrap<&Impl::DisposeNative>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativePanZoomController::HandleMotionEvent_t>(
|
||||
mozilla::jni::NativeStub<NativePanZoomController::HandleMotionEvent_t, Impl>
|
||||
::template Wrap<&Impl::HandleMotionEvent>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativePanZoomController::HandleMotionEventVelocity_t>(
|
||||
mozilla::jni::NativeStub<NativePanZoomController::HandleMotionEventVelocity_t, Impl>
|
||||
::template Wrap<&Impl::HandleMotionEventVelocity>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativePanZoomController::HandleMouseEvent_t>(
|
||||
mozilla::jni::NativeStub<NativePanZoomController::HandleMouseEvent_t, Impl>
|
||||
::template Wrap<&Impl::HandleMouseEvent>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativePanZoomController::HandleScrollEvent_t>(
|
||||
mozilla::jni::NativeStub<NativePanZoomController::HandleScrollEvent_t, Impl>
|
||||
::template Wrap<&Impl::HandleScrollEvent>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativePanZoomController::SetIsLongpressEnabled_t>(
|
||||
mozilla::jni::NativeStub<NativePanZoomController::SetIsLongpressEnabled_t, Impl>
|
||||
::template Wrap<&Impl::SetIsLongpressEnabled>)
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
class NativeJSContainer::Natives : public mozilla::jni::NativeImpl<NativeJSContainer, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[2];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod NativeJSContainer::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSContainer::Clone2_t>(
|
||||
mozilla::jni::NativeStub<NativeJSContainer::Clone2_t, Impl>
|
||||
::template Wrap<&Impl::Clone>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSContainer::DisposeNative_t>(
|
||||
mozilla::jni::NativeStub<NativeJSContainer::DisposeNative_t, Impl>
|
||||
::template Wrap<&Impl::DisposeNative>)
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
class NativeJSObject::Natives : public mozilla::jni::NativeImpl<NativeJSObject, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[27];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod NativeJSObject::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::GetBoolean_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::GetBoolean_t, Impl>
|
||||
::template Wrap<&Impl::GetBoolean>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::GetBooleanArray_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::GetBooleanArray_t, Impl>
|
||||
::template Wrap<&Impl::GetBooleanArray>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::GetBundle_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::GetBundle_t, Impl>
|
||||
::template Wrap<&Impl::GetBundle>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::GetBundleArray_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::GetBundleArray_t, Impl>
|
||||
::template Wrap<&Impl::GetBundleArray>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::GetDouble_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::GetDouble_t, Impl>
|
||||
::template Wrap<&Impl::GetDouble>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::GetDoubleArray_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::GetDoubleArray_t, Impl>
|
||||
::template Wrap<&Impl::GetDoubleArray>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::GetInt_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::GetInt_t, Impl>
|
||||
::template Wrap<&Impl::GetInt>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::GetIntArray_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::GetIntArray_t, Impl>
|
||||
::template Wrap<&Impl::GetIntArray>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::GetObject_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::GetObject_t, Impl>
|
||||
::template Wrap<&Impl::GetObject>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::GetObjectArray_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::GetObjectArray_t, Impl>
|
||||
::template Wrap<&Impl::GetObjectArray>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::GetString_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::GetString_t, Impl>
|
||||
::template Wrap<&Impl::GetString>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::GetStringArray_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::GetStringArray_t, Impl>
|
||||
::template Wrap<&Impl::GetStringArray>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::Has_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::Has_t, Impl>
|
||||
::template Wrap<&Impl::Has>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::OptBoolean_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::OptBoolean_t, Impl>
|
||||
::template Wrap<&Impl::OptBoolean>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::OptBooleanArray_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::OptBooleanArray_t, Impl>
|
||||
::template Wrap<&Impl::OptBooleanArray>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::OptBundle_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::OptBundle_t, Impl>
|
||||
::template Wrap<&Impl::OptBundle>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::OptBundleArray_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::OptBundleArray_t, Impl>
|
||||
::template Wrap<&Impl::OptBundleArray>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::OptDouble_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::OptDouble_t, Impl>
|
||||
::template Wrap<&Impl::OptDouble>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::OptDoubleArray_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::OptDoubleArray_t, Impl>
|
||||
::template Wrap<&Impl::OptDoubleArray>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::OptInt_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::OptInt_t, Impl>
|
||||
::template Wrap<&Impl::OptInt>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::OptIntArray_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::OptIntArray_t, Impl>
|
||||
::template Wrap<&Impl::OptIntArray>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::OptObject_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::OptObject_t, Impl>
|
||||
::template Wrap<&Impl::OptObject>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::OptObjectArray_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::OptObjectArray_t, Impl>
|
||||
::template Wrap<&Impl::OptObjectArray>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::OptString_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::OptString_t, Impl>
|
||||
::template Wrap<&Impl::OptString>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::OptStringArray_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::OptStringArray_t, Impl>
|
||||
::template Wrap<&Impl::OptStringArray>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::ToBundle_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::ToBundle_t, Impl>
|
||||
::template Wrap<&Impl::ToBundle>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<NativeJSObject::ToString_t>(
|
||||
mozilla::jni::NativeStub<NativeJSObject::ToString_t, Impl>
|
||||
::template Wrap<&Impl::ToString>)
|
||||
};
|
||||
|
||||
} /* java */
|
||||
} /* mozilla */
|
||||
#endif // GeneratedJNINatives_h
|
||||
1874
widget/android/GeneratedJNIWrappers.cpp
Normal file
1874
widget/android/GeneratedJNIWrappers.cpp
Normal file
File diff suppressed because it is too large
Load diff
5456
widget/android/GeneratedJNIWrappers.h
Normal file
5456
widget/android/GeneratedJNIWrappers.h
Normal file
File diff suppressed because it is too large
Load diff
621
widget/android/GfxInfo.cpp
Normal file
621
widget/android/GfxInfo.cpp
Normal file
|
|
@ -0,0 +1,621 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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 "GfxInfo.h"
|
||||
#include "GLContext.h"
|
||||
#include "GLContextProvider.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "prenv.h"
|
||||
#include "prprf.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsVersionComparator.h"
|
||||
#include "AndroidBridge.h"
|
||||
#include "nsIWindowWatcher.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
#include "nsExceptionHandler.h"
|
||||
#include "nsICrashReporter.h"
|
||||
#define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
class GfxInfo::GLStrings
|
||||
{
|
||||
nsCString mVendor;
|
||||
nsCString mRenderer;
|
||||
nsCString mVersion;
|
||||
bool mReady;
|
||||
|
||||
public:
|
||||
GLStrings()
|
||||
: mReady(false)
|
||||
{}
|
||||
|
||||
const nsCString& Vendor() {
|
||||
EnsureInitialized();
|
||||
return mVendor;
|
||||
}
|
||||
|
||||
// This spoofed value wins, even if the environment variable
|
||||
// MOZ_GFX_SPOOF_GL_VENDOR was set.
|
||||
void SpoofVendor(const nsCString& s) {
|
||||
mVendor = s;
|
||||
}
|
||||
|
||||
const nsCString& Renderer() {
|
||||
EnsureInitialized();
|
||||
return mRenderer;
|
||||
}
|
||||
|
||||
// This spoofed value wins, even if the environment variable
|
||||
// MOZ_GFX_SPOOF_GL_RENDERER was set.
|
||||
void SpoofRenderer(const nsCString& s) {
|
||||
mRenderer = s;
|
||||
}
|
||||
|
||||
const nsCString& Version() {
|
||||
EnsureInitialized();
|
||||
return mVersion;
|
||||
}
|
||||
|
||||
// This spoofed value wins, even if the environment variable
|
||||
// MOZ_GFX_SPOOF_GL_VERSION was set.
|
||||
void SpoofVersion(const nsCString& s) {
|
||||
mVersion = s;
|
||||
}
|
||||
|
||||
void EnsureInitialized() {
|
||||
if (mReady) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<gl::GLContext> gl;
|
||||
nsCString discardFailureId;
|
||||
gl = gl::GLContextProvider::CreateHeadless(gl::CreateContextFlags::REQUIRE_COMPAT_PROFILE,
|
||||
&discardFailureId);
|
||||
|
||||
if (!gl) {
|
||||
// Setting mReady to true here means that we won't retry. Everything will
|
||||
// remain blacklisted forever. Ideally, we would like to update that once
|
||||
// any GLContext is successfully created, like the compositor's GLContext.
|
||||
mReady = true;
|
||||
return;
|
||||
}
|
||||
|
||||
gl->MakeCurrent();
|
||||
|
||||
if (mVendor.IsEmpty()) {
|
||||
const char *spoofedVendor = PR_GetEnv("MOZ_GFX_SPOOF_GL_VENDOR");
|
||||
if (spoofedVendor) {
|
||||
mVendor.Assign(spoofedVendor);
|
||||
} else {
|
||||
mVendor.Assign((const char*)gl->fGetString(LOCAL_GL_VENDOR));
|
||||
}
|
||||
}
|
||||
|
||||
if (mRenderer.IsEmpty()) {
|
||||
const char *spoofedRenderer = PR_GetEnv("MOZ_GFX_SPOOF_GL_RENDERER");
|
||||
if (spoofedRenderer) {
|
||||
mRenderer.Assign(spoofedRenderer);
|
||||
} else {
|
||||
mRenderer.Assign((const char*)gl->fGetString(LOCAL_GL_RENDERER));
|
||||
}
|
||||
}
|
||||
|
||||
if (mVersion.IsEmpty()) {
|
||||
const char *spoofedVersion = PR_GetEnv("MOZ_GFX_SPOOF_GL_VERSION");
|
||||
if (spoofedVersion) {
|
||||
mVersion.Assign(spoofedVersion);
|
||||
} else {
|
||||
mVersion.Assign((const char*)gl->fGetString(LOCAL_GL_VERSION));
|
||||
}
|
||||
}
|
||||
|
||||
mReady = true;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, GfxInfoBase, nsIGfxInfoDebug)
|
||||
#endif
|
||||
|
||||
GfxInfo::GfxInfo()
|
||||
: mInitialized(false)
|
||||
, mGLStrings(new GLStrings)
|
||||
, mOSVersionInteger(0)
|
||||
, mSDKVersion(0)
|
||||
{
|
||||
}
|
||||
|
||||
GfxInfo::~GfxInfo()
|
||||
{
|
||||
}
|
||||
|
||||
/* GetD2DEnabled and GetDwriteEnabled shouldn't be called until after gfxPlatform initialization
|
||||
* has occurred because they depend on it for information. (See bug 591561) */
|
||||
nsresult
|
||||
GfxInfo::GetD2DEnabled(bool *aEnabled)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
GfxInfo::GetDWriteEnabled(bool *aEnabled)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetCleartypeParameters(nsAString & aCleartypeParams)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
void
|
||||
GfxInfo::EnsureInitialized()
|
||||
{
|
||||
if (mInitialized)
|
||||
return;
|
||||
|
||||
if (!mozilla::AndroidBridge::Bridge()) {
|
||||
gfxWarning() << "AndroidBridge missing during initialization";
|
||||
return;
|
||||
}
|
||||
|
||||
if (mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build", "MODEL", mModel)) {
|
||||
mAdapterDescription.AppendPrintf("Model: %s", NS_LossyConvertUTF16toASCII(mModel).get());
|
||||
}
|
||||
|
||||
if (mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build", "PRODUCT", mProduct)) {
|
||||
mAdapterDescription.AppendPrintf(", Product: %s", NS_LossyConvertUTF16toASCII(mProduct).get());
|
||||
}
|
||||
|
||||
if (mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build", "MANUFACTURER", mManufacturer)) {
|
||||
mAdapterDescription.AppendPrintf(", Manufacturer: %s", NS_LossyConvertUTF16toASCII(mManufacturer).get());
|
||||
}
|
||||
|
||||
if (mozilla::AndroidBridge::Bridge()->GetStaticIntField("android/os/Build$VERSION", "SDK_INT", &mSDKVersion)) {
|
||||
// the HARDWARE field isn't available on Android SDK < 8, but we require 9+ anyway.
|
||||
MOZ_ASSERT(mSDKVersion >= 8);
|
||||
if (mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build", "HARDWARE", mHardware)) {
|
||||
mAdapterDescription.AppendPrintf(", Hardware: %s", NS_LossyConvertUTF16toASCII(mHardware).get());
|
||||
}
|
||||
} else {
|
||||
mSDKVersion = 0;
|
||||
}
|
||||
|
||||
nsString release;
|
||||
mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build$VERSION", "RELEASE", release);
|
||||
mOSVersion = NS_LossyConvertUTF16toASCII(release);
|
||||
|
||||
mOSVersionInteger = 0;
|
||||
char a[5], b[5], c[5], d[5];
|
||||
SplitDriverVersion(mOSVersion.get(), a, b, c, d);
|
||||
uint8_t na = atoi(a);
|
||||
uint8_t nb = atoi(b);
|
||||
uint8_t nc = atoi(c);
|
||||
uint8_t nd = atoi(d);
|
||||
|
||||
mOSVersionInteger = (uint32_t(na) << 24) |
|
||||
(uint32_t(nb) << 16) |
|
||||
(uint32_t(nc) << 8) |
|
||||
uint32_t(nd);
|
||||
|
||||
mAdapterDescription.AppendPrintf(", OpenGL: %s -- %s -- %s",
|
||||
mGLStrings->Vendor().get(),
|
||||
mGLStrings->Renderer().get(),
|
||||
mGLStrings->Version().get());
|
||||
|
||||
AddCrashReportAnnotations();
|
||||
|
||||
mInitialized = true;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterDescription(nsAString & aAdapterDescription)
|
||||
{
|
||||
EnsureInitialized();
|
||||
aAdapterDescription = NS_ConvertASCIItoUTF16(mAdapterDescription);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterDescription2(nsAString & aAdapterDescription)
|
||||
{
|
||||
EnsureInitialized();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterRAM(nsAString & aAdapterRAM)
|
||||
{
|
||||
EnsureInitialized();
|
||||
aAdapterRAM.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterRAM2(nsAString & aAdapterRAM)
|
||||
{
|
||||
EnsureInitialized();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterDriver(nsAString & aAdapterDriver)
|
||||
{
|
||||
EnsureInitialized();
|
||||
aAdapterDriver.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterDriver2(nsAString & aAdapterDriver)
|
||||
{
|
||||
EnsureInitialized();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterDriverVersion(nsAString & aAdapterDriverVersion)
|
||||
{
|
||||
EnsureInitialized();
|
||||
aAdapterDriverVersion = NS_ConvertASCIItoUTF16(mGLStrings->Version());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion)
|
||||
{
|
||||
EnsureInitialized();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterDriverDate(nsAString & aAdapterDriverDate)
|
||||
{
|
||||
EnsureInitialized();
|
||||
aAdapterDriverDate.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterDriverDate2(nsAString & aAdapterDriverDate)
|
||||
{
|
||||
EnsureInitialized();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterVendorID(nsAString & aAdapterVendorID)
|
||||
{
|
||||
EnsureInitialized();
|
||||
aAdapterVendorID = NS_ConvertASCIItoUTF16(mGLStrings->Vendor());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterVendorID2(nsAString & aAdapterVendorID)
|
||||
{
|
||||
EnsureInitialized();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterDeviceID(nsAString & aAdapterDeviceID)
|
||||
{
|
||||
EnsureInitialized();
|
||||
aAdapterDeviceID = NS_ConvertASCIItoUTF16(mGLStrings->Renderer());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterDeviceID2(nsAString & aAdapterDeviceID)
|
||||
{
|
||||
EnsureInitialized();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterSubsysID(nsAString & aAdapterSubsysID)
|
||||
{
|
||||
EnsureInitialized();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAdapterSubsysID2(nsAString & aAdapterSubsysID)
|
||||
{
|
||||
EnsureInitialized();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active)
|
||||
{
|
||||
EnsureInitialized();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
void
|
||||
GfxInfo::AddCrashReportAnnotations()
|
||||
{
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AdapterVendorID"),
|
||||
mGLStrings->Vendor());
|
||||
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AdapterDeviceID"),
|
||||
mGLStrings->Renderer());
|
||||
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AdapterDriverVersion"),
|
||||
mGLStrings->Version());
|
||||
|
||||
/* Add an App Note for now so that we get the data immediately. These
|
||||
* can go away after we store the above in the socorro db */
|
||||
nsAutoCString note;
|
||||
note.AppendPrintf("AdapterDescription: '%s'\n", mAdapterDescription.get());
|
||||
|
||||
CrashReporter::AppendAppNotesToCrashReport(note);
|
||||
#endif
|
||||
}
|
||||
|
||||
const nsTArray<GfxDriverInfo>&
|
||||
GfxInfo::GetGfxDriverInfo()
|
||||
{
|
||||
if (mDriverInfo->IsEmpty()) {
|
||||
APPEND_TO_DRIVER_BLOCKLIST2(OperatingSystem::Android,
|
||||
(nsAString&) GfxDriverInfo::GetDeviceVendor(VendorAll), GfxDriverInfo::allDevices,
|
||||
nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_STATUS_OK,
|
||||
DRIVER_COMPARISON_IGNORED, GfxDriverInfo::allDriverVersions,
|
||||
"FEATURE_OK_FORCE_OPENGL" );
|
||||
}
|
||||
|
||||
return *mDriverInfo;
|
||||
}
|
||||
|
||||
nsresult
|
||||
GfxInfo::GetFeatureStatusImpl(int32_t aFeature,
|
||||
int32_t *aStatus,
|
||||
nsAString &aSuggestedDriverVersion,
|
||||
const nsTArray<GfxDriverInfo>& aDriverInfo,
|
||||
nsACString &aFailureId,
|
||||
OperatingSystem* aOS /* = nullptr */)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aStatus);
|
||||
aSuggestedDriverVersion.SetIsVoid(true);
|
||||
*aStatus = nsIGfxInfo::FEATURE_STATUS_UNKNOWN;
|
||||
OperatingSystem os = mOS;
|
||||
if (aOS)
|
||||
*aOS = os;
|
||||
|
||||
// OpenGL layers are never blacklisted on Android.
|
||||
// This early return is so we avoid potentially slow
|
||||
// GLStrings initialization on startup when we initialize GL layers.
|
||||
if (aFeature == nsIGfxInfo::FEATURE_OPENGL_LAYERS) {
|
||||
*aStatus = nsIGfxInfo::FEATURE_STATUS_OK;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
EnsureInitialized();
|
||||
|
||||
if (mGLStrings->Vendor().IsEmpty() || mGLStrings->Renderer().IsEmpty()) {
|
||||
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Don't evaluate special cases when evaluating the downloaded blocklist.
|
||||
if (aDriverInfo.IsEmpty()) {
|
||||
if (aFeature == nsIGfxInfo::FEATURE_CANVAS2D_ACCELERATION) {
|
||||
if (mSDKVersion < 11) {
|
||||
// It's slower than software due to not having a compositing fast path
|
||||
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_OS_VERSION;
|
||||
aFailureId = "FEATURE_FAILURE_CANVAS_2D_SDK";
|
||||
} else if (mGLStrings->Renderer().Find("Vivante GC1000") != -1) {
|
||||
// Blocklist Vivante GC1000. See bug 1248183.
|
||||
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
|
||||
aFailureId = "FEATURE_FAILED_CANVAS_2D_HW";
|
||||
} else {
|
||||
*aStatus = nsIGfxInfo::FEATURE_STATUS_OK;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aFeature == FEATURE_WEBGL_OPENGL) {
|
||||
if (mGLStrings->Renderer().Find("Adreno 200") != -1 ||
|
||||
mGLStrings->Renderer().Find("Adreno 205") != -1)
|
||||
{
|
||||
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
|
||||
aFailureId = "FEATURE_FAILURE_ADRENO_20x";
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mHardware.EqualsLiteral("ville")) {
|
||||
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
|
||||
aFailureId = "FEATURE_FAILURE_VILLE";
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (aFeature == FEATURE_STAGEFRIGHT) {
|
||||
NS_LossyConvertUTF16toASCII cManufacturer(mManufacturer);
|
||||
NS_LossyConvertUTF16toASCII cModel(mModel);
|
||||
NS_LossyConvertUTF16toASCII cHardware(mHardware);
|
||||
|
||||
if (cHardware.EqualsLiteral("antares") ||
|
||||
cHardware.EqualsLiteral("harmony") ||
|
||||
cHardware.EqualsLiteral("picasso") ||
|
||||
cHardware.EqualsLiteral("picasso_e") ||
|
||||
cHardware.EqualsLiteral("ventana") ||
|
||||
cHardware.EqualsLiteral("rk30board"))
|
||||
{
|
||||
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
|
||||
aFailureId = "FEATURE_FAILURE_STAGE_HW";
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (CompareVersions(mOSVersion.get(), "4.1.0") < 0)
|
||||
{
|
||||
// Whitelist:
|
||||
// All Samsung ICS devices, except for:
|
||||
// Samsung SGH-I717 (Bug 845729)
|
||||
// Samsung SGH-I727 (Bug 845729)
|
||||
// Samsung SGH-I757 (Bug 845729)
|
||||
// All Galaxy nexus ICS devices
|
||||
// Sony Xperia Ion (LT28) ICS devices
|
||||
bool isWhitelisted =
|
||||
cModel.Equals("LT28h", nsCaseInsensitiveCStringComparator()) ||
|
||||
cManufacturer.Equals("samsung", nsCaseInsensitiveCStringComparator()) ||
|
||||
cModel.Equals("galaxy nexus", nsCaseInsensitiveCStringComparator()); // some Galaxy Nexus have manufacturer=amazon
|
||||
|
||||
if (cModel.Find("SGH-I717", true) != -1 ||
|
||||
cModel.Find("SGH-I727", true) != -1 ||
|
||||
cModel.Find("SGH-I757", true) != -1)
|
||||
{
|
||||
isWhitelisted = false;
|
||||
}
|
||||
|
||||
if (!isWhitelisted) {
|
||||
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
|
||||
aFailureId = "FEATURE_FAILURE_4_1_HW";
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
else if (CompareVersions(mOSVersion.get(), "4.2.0") < 0)
|
||||
{
|
||||
// Whitelist:
|
||||
// All JB phones except for those in blocklist below
|
||||
// Blocklist:
|
||||
// Samsung devices from bug 812881 and 853522.
|
||||
// Motorola XT890 from bug 882342.
|
||||
bool isBlocklisted =
|
||||
cModel.Find("GT-P3100", true) != -1 ||
|
||||
cModel.Find("GT-P3110", true) != -1 ||
|
||||
cModel.Find("GT-P3113", true) != -1 ||
|
||||
cModel.Find("GT-P5100", true) != -1 ||
|
||||
cModel.Find("GT-P5110", true) != -1 ||
|
||||
cModel.Find("GT-P5113", true) != -1 ||
|
||||
cModel.Find("XT890", true) != -1;
|
||||
|
||||
if (isBlocklisted) {
|
||||
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
|
||||
aFailureId = "FEATURE_FAILURE_4_2_HW";
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
else if (CompareVersions(mOSVersion.get(), "4.3.0") < 0)
|
||||
{
|
||||
// Blocklist all Sony devices
|
||||
if (cManufacturer.Find("Sony", true) != -1) {
|
||||
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
|
||||
aFailureId = "FEATURE_FAILURE_4_3_SONY";
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aFeature == FEATURE_WEBRTC_HW_ACCELERATION_ENCODE) {
|
||||
if (mozilla::AndroidBridge::Bridge()) {
|
||||
*aStatus = mozilla::AndroidBridge::Bridge()->GetHWEncoderCapability() ? nsIGfxInfo::FEATURE_STATUS_OK : nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
|
||||
aFailureId = "FEATURE_FAILURE_WEBRTC_ENCODE";
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
if (aFeature == FEATURE_WEBRTC_HW_ACCELERATION_DECODE) {
|
||||
if (mozilla::AndroidBridge::Bridge()) {
|
||||
*aStatus = mozilla::AndroidBridge::Bridge()->GetHWDecoderCapability() ? nsIGfxInfo::FEATURE_STATUS_OK : nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
|
||||
aFailureId = "FEATURE_FAILURE_WEBRTC_DECODE";
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (aFeature == FEATURE_VP8_HW_DECODE || aFeature == FEATURE_VP9_HW_DECODE) {
|
||||
NS_LossyConvertUTF16toASCII model(mModel);
|
||||
bool isBlocked =
|
||||
// GIFV crash, see bug 1232911.
|
||||
model.Equals("GT-N8013", nsCaseInsensitiveCStringComparator());
|
||||
|
||||
if (isBlocked) {
|
||||
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
|
||||
aFailureId = "FEATURE_FAILURE_VPx";
|
||||
} else {
|
||||
*aStatus = nsIGfxInfo::FEATURE_STATUS_OK;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return GfxInfoBase::GetFeatureStatusImpl(aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, aFailureId, &os);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
// Implement nsIGfxInfoDebug
|
||||
|
||||
NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString & aVendorID)
|
||||
{
|
||||
mGLStrings->SpoofVendor(NS_LossyConvertUTF16toASCII(aVendorID));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP GfxInfo::SpoofDeviceID(const nsAString & aDeviceID)
|
||||
{
|
||||
mGLStrings->SpoofRenderer(NS_LossyConvertUTF16toASCII(aDeviceID));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP GfxInfo::SpoofDriverVersion(const nsAString & aDriverVersion)
|
||||
{
|
||||
mGLStrings->SpoofVersion(NS_LossyConvertUTF16toASCII(aDriverVersion));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP GfxInfo::SpoofOSVersion(uint32_t aVersion)
|
||||
{
|
||||
EnsureInitialized();
|
||||
mOSVersion = aVersion;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
nsString GfxInfo::Model()
|
||||
{
|
||||
EnsureInitialized();
|
||||
return mModel;
|
||||
}
|
||||
|
||||
nsString GfxInfo::Hardware()
|
||||
{
|
||||
EnsureInitialized();
|
||||
return mHardware;
|
||||
}
|
||||
|
||||
nsString GfxInfo::Product()
|
||||
{
|
||||
EnsureInitialized();
|
||||
return mProduct;
|
||||
}
|
||||
|
||||
nsString GfxInfo::Manufacturer()
|
||||
{
|
||||
EnsureInitialized();
|
||||
return mManufacturer;
|
||||
}
|
||||
|
||||
uint32_t GfxInfo::OperatingSystemVersion()
|
||||
{
|
||||
EnsureInitialized();
|
||||
return mOSVersionInteger;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
102
widget/android/GfxInfo.h
Normal file
102
widget/android/GfxInfo.h
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/* vim: se cin sw=2 ts=2 et : */
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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/. */
|
||||
|
||||
#ifndef __mozilla_widget_GfxInfo_h__
|
||||
#define __mozilla_widget_GfxInfo_h__
|
||||
|
||||
#include "GfxInfoBase.h"
|
||||
#include "GfxDriverInfo.h"
|
||||
|
||||
#include "nsString.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace widget {
|
||||
|
||||
class GfxInfo : public GfxInfoBase
|
||||
{
|
||||
private:
|
||||
~GfxInfo();
|
||||
|
||||
public:
|
||||
GfxInfo();
|
||||
|
||||
// We only declare the subset of nsIGfxInfo that we actually implement. The
|
||||
// rest is brought forward from GfxInfoBase.
|
||||
NS_IMETHOD GetD2DEnabled(bool *aD2DEnabled) override;
|
||||
NS_IMETHOD GetDWriteEnabled(bool *aDWriteEnabled) override;
|
||||
NS_IMETHOD GetDWriteVersion(nsAString & aDwriteVersion) override;
|
||||
NS_IMETHOD GetCleartypeParameters(nsAString & aCleartypeParams) override;
|
||||
NS_IMETHOD GetAdapterDescription(nsAString & aAdapterDescription) override;
|
||||
NS_IMETHOD GetAdapterDriver(nsAString & aAdapterDriver) override;
|
||||
NS_IMETHOD GetAdapterVendorID(nsAString & aAdapterVendorID) override;
|
||||
NS_IMETHOD GetAdapterDeviceID(nsAString & aAdapterDeviceID) override;
|
||||
NS_IMETHOD GetAdapterSubsysID(nsAString & aAdapterSubsysID) override;
|
||||
NS_IMETHOD GetAdapterRAM(nsAString & aAdapterRAM) override;
|
||||
NS_IMETHOD GetAdapterDriverVersion(nsAString & aAdapterDriverVersion) override;
|
||||
NS_IMETHOD GetAdapterDriverDate(nsAString & aAdapterDriverDate) override;
|
||||
NS_IMETHOD GetAdapterDescription2(nsAString & aAdapterDescription) override;
|
||||
NS_IMETHOD GetAdapterDriver2(nsAString & aAdapterDriver) override;
|
||||
NS_IMETHOD GetAdapterVendorID2(nsAString & aAdapterVendorID) override;
|
||||
NS_IMETHOD GetAdapterDeviceID2(nsAString & aAdapterDeviceID) override;
|
||||
NS_IMETHOD GetAdapterSubsysID2(nsAString & aAdapterSubsysID) override;
|
||||
NS_IMETHOD GetAdapterRAM2(nsAString & aAdapterRAM) override;
|
||||
NS_IMETHOD GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion) override;
|
||||
NS_IMETHOD GetAdapterDriverDate2(nsAString & aAdapterDriverDate) override;
|
||||
NS_IMETHOD GetIsGPU2Active(bool *aIsGPU2Active) override;
|
||||
using GfxInfoBase::GetFeatureStatus;
|
||||
using GfxInfoBase::GetFeatureSuggestedDriverVersion;
|
||||
using GfxInfoBase::GetWebGLParameter;
|
||||
|
||||
void EnsureInitialized();
|
||||
|
||||
virtual nsString Model() override;
|
||||
virtual nsString Hardware() override;
|
||||
virtual nsString Product() override;
|
||||
virtual nsString Manufacturer() override;
|
||||
|
||||
#ifdef DEBUG
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIGFXINFODEBUG
|
||||
#endif
|
||||
|
||||
virtual uint32_t OperatingSystemVersion() override;
|
||||
|
||||
protected:
|
||||
|
||||
virtual nsresult GetFeatureStatusImpl(int32_t aFeature,
|
||||
int32_t *aStatus,
|
||||
nsAString & aSuggestedDriverVersion,
|
||||
const nsTArray<GfxDriverInfo>& aDriverInfo,
|
||||
nsACString &aFailureId,
|
||||
OperatingSystem* aOS = nullptr) override;
|
||||
virtual const nsTArray<GfxDriverInfo>& GetGfxDriverInfo() override;
|
||||
|
||||
private:
|
||||
|
||||
void AddCrashReportAnnotations();
|
||||
|
||||
bool mInitialized;
|
||||
|
||||
class GLStrings;
|
||||
UniquePtr<GLStrings> mGLStrings;
|
||||
|
||||
nsCString mAdapterDescription;
|
||||
|
||||
OperatingSystem mOS;
|
||||
|
||||
nsString mModel, mHardware, mManufacturer, mProduct;
|
||||
nsCString mOSVersion;
|
||||
uint32_t mOSVersionInteger;
|
||||
int32_t mSDKVersion;
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* __mozilla_widget_GfxInfo_h__ */
|
||||
881
widget/android/NativeJSContainer.cpp
Normal file
881
widget/android/NativeJSContainer.cpp
Normal file
|
|
@ -0,0 +1,881 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* 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 "NativeJSContainer.h"
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include "Bundle.h"
|
||||
#include "GeneratedJNINatives.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "jsapi.h"
|
||||
#include "nsJSUtils.h"
|
||||
|
||||
#include <mozilla/Vector.h>
|
||||
#include <mozilla/jni/Accessors.h>
|
||||
#include <mozilla/jni/Refs.h>
|
||||
#include <mozilla/jni/Utils.h>
|
||||
|
||||
/**
|
||||
* NativeJSContainer.cpp implements the native methods in both
|
||||
* NativeJSContainer and NativeJSObject, using JSAPI to retrieve values from a
|
||||
* JSObject and using JNI to return those values to Java code.
|
||||
*/
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
namespace {
|
||||
|
||||
bool CheckThread()
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
jni::ThrowException("java/lang/IllegalThreadStateException",
|
||||
"Not on Gecko thread");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class C, typename T> bool
|
||||
CheckJNIArgument(const jni::Ref<C, T>& arg)
|
||||
{
|
||||
if (!arg) {
|
||||
jni::ThrowException("java/lang/IllegalArgumentException",
|
||||
"Null argument");
|
||||
}
|
||||
return !!arg;
|
||||
}
|
||||
|
||||
nsresult
|
||||
CheckSDKCall(nsresult rv)
|
||||
{
|
||||
if (NS_FAILED(rv)) {
|
||||
jni::ThrowException("java/lang/UnsupportedOperationException",
|
||||
"SDK JNI call failed");
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Convert a JNI string to a char16_t string that JSAPI expects.
|
||||
class JSJNIString final
|
||||
{
|
||||
JNIEnv* const mEnv;
|
||||
jni::String::Param mJNIString;
|
||||
const char16_t* const mJSString;
|
||||
|
||||
public:
|
||||
JSJNIString(JNIEnv* env, jni::String::Param str)
|
||||
: mEnv(env)
|
||||
, mJNIString(str)
|
||||
, mJSString(!str ? nullptr : reinterpret_cast<const char16_t*>(
|
||||
mEnv->GetStringChars(str.Get(), nullptr)))
|
||||
{}
|
||||
|
||||
~JSJNIString() {
|
||||
if (mJNIString) {
|
||||
mEnv->ReleaseStringChars(mJNIString.Get(),
|
||||
reinterpret_cast<const jchar*>(mJSString));
|
||||
}
|
||||
}
|
||||
|
||||
operator const char16_t*() const {
|
||||
return mJSString;
|
||||
}
|
||||
|
||||
size_t Length() const {
|
||||
return static_cast<size_t>(mEnv->GetStringLength(mJNIString.Get()));
|
||||
}
|
||||
};
|
||||
|
||||
} // namepsace
|
||||
|
||||
class NativeJSContainerImpl final
|
||||
: public NativeJSObject::Natives<NativeJSContainerImpl>
|
||||
, public NativeJSContainer::Natives<NativeJSContainerImpl>
|
||||
{
|
||||
typedef NativeJSContainerImpl Self;
|
||||
typedef NativeJSContainer::Natives<NativeJSContainerImpl> ContainerBase;
|
||||
typedef NativeJSObject::Natives<NativeJSContainerImpl> ObjectBase;
|
||||
|
||||
typedef JS::PersistentRooted<JSObject*> PersistentObject;
|
||||
|
||||
JNIEnv* const mEnv;
|
||||
// Context that the object is valid in
|
||||
JSContext* const mJSContext;
|
||||
// Root JS object
|
||||
PersistentObject mJSObject;
|
||||
// Children objects
|
||||
Vector<NativeJSObject::GlobalRef, 0> mChildren;
|
||||
|
||||
bool CheckObject() const
|
||||
{
|
||||
if (!mJSObject) {
|
||||
jni::ThrowException("java/lang/NullPointerException",
|
||||
"Null JSObject");
|
||||
}
|
||||
return !!mJSObject;
|
||||
}
|
||||
|
||||
bool CheckJSCall(bool result) const
|
||||
{
|
||||
if (!result) {
|
||||
JS_ClearPendingException(mJSContext);
|
||||
jni::ThrowException("java/lang/UnsupportedOperationException",
|
||||
"JSAPI call failed");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check that a JS Value contains a particular property type as indicaed by
|
||||
// the property's InValue method (e.g. StringProperty::InValue).
|
||||
bool CheckProperty(bool (Self::*InValue)(JS::HandleValue) const,
|
||||
JS::HandleValue val) const
|
||||
{
|
||||
if (!(this->*InValue)(val)) {
|
||||
// XXX this can happen when converting a double array inside a
|
||||
// Bundle, because double arrays can be misidentified as an int
|
||||
// array. The workaround is to add a dummy first element to the
|
||||
// array that is a floating point value, i.e. [0.5, ...].
|
||||
jni::ThrowException(
|
||||
"org/mozilla/gecko/util/NativeJSObject$InvalidPropertyException",
|
||||
"Property type mismatch");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Primitive properties
|
||||
|
||||
template<bool (JS::Value::*IsType)() const> bool
|
||||
PrimitiveInValue(JS::HandleValue val) const
|
||||
{
|
||||
return (static_cast<const JS::Value&>(val).*IsType)();
|
||||
}
|
||||
|
||||
template<typename U, U (JS::Value::*ToType)() const> U
|
||||
PrimitiveFromValue(JS::HandleValue val) const
|
||||
{
|
||||
return (static_cast<const JS::Value&>(val).*ToType)();
|
||||
}
|
||||
|
||||
template<class Prop> typename Prop::NativeArray
|
||||
PrimitiveNewArray(JS::HandleObject array, size_t length) const
|
||||
{
|
||||
typedef typename Prop::JNIType JNIType;
|
||||
|
||||
// Fill up a temporary buffer for our array, then use
|
||||
// JNIEnv::Set*ArrayRegion to fill out array in one go.
|
||||
|
||||
UniquePtr<JNIType[]> buffer = MakeUnique<JNIType[]>(length);
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
JS::RootedValue elem(mJSContext);
|
||||
if (!CheckJSCall(JS_GetElement(mJSContext, array, i, &elem)) ||
|
||||
!CheckProperty(Prop::InValue, elem)) {
|
||||
return nullptr;
|
||||
}
|
||||
buffer[i] = JNIType((this->*Prop::FromValue)(elem));
|
||||
}
|
||||
auto jarray = Prop::NativeArray::Adopt(
|
||||
mEnv, (mEnv->*Prop::NewJNIArray)(length));
|
||||
if (!jarray) {
|
||||
return nullptr;
|
||||
}
|
||||
(mEnv->*Prop::SetJNIArrayRegion)(
|
||||
jarray.Get(), 0, length, buffer.get());
|
||||
if (mEnv->ExceptionCheck()) {
|
||||
return nullptr;
|
||||
}
|
||||
return jarray;
|
||||
}
|
||||
|
||||
template<typename U, typename UA, typename V, typename VA,
|
||||
bool (JS::Value::*IsType)() const,
|
||||
U (JS::Value::*ToType)() const,
|
||||
VA (JNIEnv::*NewArray_)(jsize),
|
||||
void (JNIEnv::*SetArrayRegion_)(VA, jsize, jsize, const V*)>
|
||||
struct PrimitiveProperty
|
||||
{
|
||||
// C++ type for a primitive property (e.g. bool)
|
||||
typedef U NativeType;
|
||||
// C++ type for the fallback value used in opt* methods
|
||||
typedef U NativeFallback;
|
||||
// Type for an array of the primitive type (e.g. BooleanArray::LocalRef)
|
||||
typedef typename UA::LocalRef NativeArray;
|
||||
// Type for the fallback value used in opt*Array methods
|
||||
typedef const typename UA::Ref ArrayFallback;
|
||||
// JNI type (e.g. jboolean)
|
||||
typedef V JNIType;
|
||||
|
||||
// JNIEnv function to create a new JNI array of the primiive type
|
||||
typedef decltype(NewArray_) NewJNIArray_t;
|
||||
static constexpr NewJNIArray_t NewJNIArray = NewArray_;
|
||||
|
||||
// JNIEnv function to fill a JNI array of the primiive type
|
||||
typedef decltype(SetArrayRegion_) SetJNIArrayRegion_t;
|
||||
static constexpr SetJNIArrayRegion_t SetJNIArrayRegion = SetArrayRegion_;
|
||||
|
||||
// Function to determine if a JS Value contains the primitive type
|
||||
typedef decltype(&Self::PrimitiveInValue<IsType>) InValue_t;
|
||||
static constexpr InValue_t InValue = &Self::PrimitiveInValue<IsType>;
|
||||
|
||||
// Function to convert a JS Value to the primitive type
|
||||
typedef decltype(&Self::PrimitiveFromValue<U, ToType>) FromValue_t;
|
||||
static constexpr FromValue_t FromValue
|
||||
= &Self::PrimitiveFromValue<U, ToType>;
|
||||
|
||||
// Function to convert a JS array to a JNI array
|
||||
typedef decltype(&Self::PrimitiveNewArray<PrimitiveProperty>) NewArray_t;
|
||||
static constexpr NewArray_t NewArray
|
||||
= &Self::PrimitiveNewArray<PrimitiveProperty>;
|
||||
};
|
||||
|
||||
// String properties
|
||||
|
||||
bool StringInValue(JS::HandleValue val) const
|
||||
{
|
||||
return val.isString();
|
||||
}
|
||||
|
||||
jni::String::LocalRef
|
||||
StringFromValue(const JS::HandleString str) const
|
||||
{
|
||||
nsAutoJSString autoStr;
|
||||
if (!CheckJSCall(autoStr.init(mJSContext, str))) {
|
||||
return nullptr;
|
||||
}
|
||||
// StringParam can automatically convert a nsString to jstring.
|
||||
return jni::StringParam(autoStr, mEnv);
|
||||
}
|
||||
|
||||
jni::String::LocalRef
|
||||
StringFromValue(JS::HandleValue val)
|
||||
{
|
||||
const JS::RootedString str(mJSContext, val.toString());
|
||||
return StringFromValue(str);
|
||||
}
|
||||
|
||||
// Bundle properties
|
||||
|
||||
sdk::Bundle::LocalRef
|
||||
BundleFromValue(const JS::HandleObject obj)
|
||||
{
|
||||
JS::Rooted<JS::IdVector> ids(mJSContext, JS::IdVector(mJSContext));
|
||||
if (!CheckJSCall(JS_Enumerate(mJSContext, obj, &ids))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const size_t length = ids.length();
|
||||
sdk::Bundle::LocalRef newBundle(mEnv);
|
||||
NS_ENSURE_SUCCESS(CheckSDKCall(
|
||||
sdk::Bundle::New(length, &newBundle)), nullptr);
|
||||
|
||||
// Iterate through each property of the JS object. For each property,
|
||||
// determine its type from a list of supported types, and convert that
|
||||
// proeprty to the supported type.
|
||||
|
||||
for (size_t i = 0; i < ids.length(); i++) {
|
||||
const JS::RootedId id(mJSContext, ids[i]);
|
||||
JS::RootedValue idVal(mJSContext);
|
||||
if (!CheckJSCall(JS_IdToValue(mJSContext, id, &idVal))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const JS::RootedString idStr(mJSContext,
|
||||
JS::ToString(mJSContext, idVal));
|
||||
if (!CheckJSCall(!!idStr)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
jni::String::LocalRef name = StringFromValue(idStr);
|
||||
JS::RootedValue val(mJSContext);
|
||||
if (!name ||
|
||||
!CheckJSCall(JS_GetPropertyById(mJSContext, obj, id, &val))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#define PUT_IN_BUNDLE_IF_TYPE_IS(TYPE) \
|
||||
if ((this->*TYPE##Property::InValue)(val)) { \
|
||||
auto jval = (this->*TYPE##Property::FromValue)(val); \
|
||||
if (mEnv->ExceptionCheck()) { \
|
||||
return nullptr; \
|
||||
} \
|
||||
NS_ENSURE_SUCCESS(CheckSDKCall( \
|
||||
newBundle->Put##TYPE(name, jval)), nullptr); \
|
||||
continue; \
|
||||
} \
|
||||
((void) 0) // Accommodate trailing semicolon.
|
||||
|
||||
// Scalar values are faster to check, so check them first.
|
||||
PUT_IN_BUNDLE_IF_TYPE_IS(Boolean);
|
||||
// Int can be casted to double, so check int first.
|
||||
PUT_IN_BUNDLE_IF_TYPE_IS(Int);
|
||||
PUT_IN_BUNDLE_IF_TYPE_IS(Double);
|
||||
PUT_IN_BUNDLE_IF_TYPE_IS(String);
|
||||
// There's no "putObject", so don't check ObjectProperty
|
||||
|
||||
// Check for array types if scalar checks all failed.
|
||||
// XXX empty arrays are treated as boolean arrays. Workaround is
|
||||
// to always have a dummy element to create a non-empty array.
|
||||
PUT_IN_BUNDLE_IF_TYPE_IS(BooleanArray);
|
||||
// XXX because we only check the first element of an array,
|
||||
// a double array can potentially be seen as an int array.
|
||||
// When that happens, the Bundle conversion will fail.
|
||||
PUT_IN_BUNDLE_IF_TYPE_IS(IntArray);
|
||||
PUT_IN_BUNDLE_IF_TYPE_IS(DoubleArray);
|
||||
PUT_IN_BUNDLE_IF_TYPE_IS(StringArray);
|
||||
// There's no "putObjectArray", so don't check ObjectArrayProperty
|
||||
// There's no "putBundleArray", so don't check BundleArrayProperty
|
||||
|
||||
// Use Bundle as the default catch-all for objects
|
||||
PUT_IN_BUNDLE_IF_TYPE_IS(Bundle);
|
||||
|
||||
#undef PUT_IN_BUNDLE_IF_TYPE_IS
|
||||
|
||||
// We tried all supported types; just bail.
|
||||
jni::ThrowException("java/lang/UnsupportedOperationException",
|
||||
"Unsupported property type");
|
||||
return nullptr;
|
||||
}
|
||||
return jni::Object::LocalRef::Adopt(newBundle.Env(),
|
||||
newBundle.Forget());
|
||||
}
|
||||
|
||||
sdk::Bundle::LocalRef
|
||||
BundleFromValue(JS::HandleValue val)
|
||||
{
|
||||
if (val.isNull()) {
|
||||
return nullptr;
|
||||
}
|
||||
JS::RootedObject object(mJSContext, &val.toObject());
|
||||
return BundleFromValue(object);
|
||||
}
|
||||
|
||||
// Object properties
|
||||
|
||||
bool ObjectInValue(JS::HandleValue val) const
|
||||
{
|
||||
return val.isObjectOrNull();
|
||||
}
|
||||
|
||||
NativeJSObject::LocalRef
|
||||
ObjectFromValue(JS::HandleValue val)
|
||||
{
|
||||
if (val.isNull()) {
|
||||
return nullptr;
|
||||
}
|
||||
JS::RootedObject object(mJSContext, &val.toObject());
|
||||
return CreateChild(object);
|
||||
}
|
||||
|
||||
template<class Prop> typename Prop::NativeArray
|
||||
ObjectNewArray(JS::HandleObject array, size_t length)
|
||||
{
|
||||
auto jarray = Prop::NativeArray::Adopt(mEnv, mEnv->NewObjectArray(
|
||||
length, typename Prop::ClassType::Context().ClassRef(),
|
||||
nullptr));
|
||||
if (!jarray) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// For object arrays, we have to set each element separately.
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
JS::RootedValue elem(mJSContext);
|
||||
if (!CheckJSCall(JS_GetElement(mJSContext, array, i, &elem)) ||
|
||||
!CheckProperty(Prop::InValue, elem)) {
|
||||
return nullptr;
|
||||
}
|
||||
mEnv->SetObjectArrayElement(
|
||||
jarray.Get(), i, (this->*Prop::FromValue)(elem).Get());
|
||||
if (mEnv->ExceptionCheck()) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return jarray;
|
||||
}
|
||||
|
||||
template<class Class,
|
||||
bool (Self::*InValue_)(JS::HandleValue) const,
|
||||
typename Class::LocalRef (Self::*FromValue_)(JS::HandleValue)>
|
||||
struct BaseObjectProperty
|
||||
{
|
||||
// JNI class for the object type (e.g. jni::String)
|
||||
typedef Class ClassType;
|
||||
|
||||
// See comments in PrimitiveProperty.
|
||||
typedef typename ClassType::LocalRef NativeType;
|
||||
typedef const typename ClassType::Ref NativeFallback;
|
||||
typedef typename jni::ObjectArray::LocalRef NativeArray;
|
||||
typedef const jni::ObjectArray::Ref ArrayFallback;
|
||||
|
||||
typedef decltype(InValue_) InValue_t;
|
||||
static constexpr InValue_t InValue = InValue_;
|
||||
|
||||
typedef decltype(FromValue_) FromValue_t;
|
||||
static constexpr FromValue_t FromValue = FromValue_;
|
||||
|
||||
typedef decltype(&Self::ObjectNewArray<BaseObjectProperty>) NewArray_t;
|
||||
static constexpr NewArray_t NewArray
|
||||
= &Self::ObjectNewArray<BaseObjectProperty>;
|
||||
};
|
||||
|
||||
// Array properties
|
||||
|
||||
template<class Prop> bool
|
||||
ArrayInValue(JS::HandleValue val) const
|
||||
{
|
||||
if (!val.isObject()) {
|
||||
return false;
|
||||
}
|
||||
JS::RootedObject obj(mJSContext, &val.toObject());
|
||||
bool isArray;
|
||||
uint32_t length = 0;
|
||||
if (!JS_IsArrayObject(mJSContext, obj, &isArray) ||
|
||||
!isArray ||
|
||||
!JS_GetArrayLength(mJSContext, obj, &length)) {
|
||||
JS_ClearPendingException(mJSContext);
|
||||
return false;
|
||||
}
|
||||
if (!length) {
|
||||
// Empty arrays are always okay.
|
||||
return true;
|
||||
}
|
||||
// We only check to see the first element is the target type. If the
|
||||
// array has mixed types, we'll throw an error during actual conversion.
|
||||
JS::RootedValue element(mJSContext);
|
||||
if (!JS_GetElement(mJSContext, obj, 0, &element)) {
|
||||
JS_ClearPendingException(mJSContext);
|
||||
return false;
|
||||
}
|
||||
return (this->*Prop::InValue)(element);
|
||||
}
|
||||
|
||||
template<class Prop> typename Prop::NativeArray
|
||||
ArrayFromValue(JS::HandleValue val)
|
||||
{
|
||||
JS::RootedObject obj(mJSContext, &val.toObject());
|
||||
uint32_t length = 0;
|
||||
if (!CheckJSCall(JS_GetArrayLength(mJSContext, obj, &length))) {
|
||||
return nullptr;
|
||||
}
|
||||
return (this->*Prop::NewArray)(obj, length);
|
||||
}
|
||||
|
||||
template<class Prop>
|
||||
struct ArrayProperty
|
||||
{
|
||||
// See comments in PrimitiveProperty.
|
||||
typedef typename Prop::NativeArray NativeType;
|
||||
typedef typename Prop::ArrayFallback NativeFallback;
|
||||
|
||||
typedef decltype(&Self::ArrayInValue<Prop>) InValue_t;
|
||||
static constexpr InValue_t InValue
|
||||
= &Self::ArrayInValue<Prop>;
|
||||
|
||||
typedef decltype(&Self::ArrayFromValue<Prop>) FromValue_t;
|
||||
static constexpr FromValue_t FromValue
|
||||
= &Self::ArrayFromValue<Prop>;
|
||||
};
|
||||
|
||||
// "Has" property is a special property type that is used to implement
|
||||
// NativeJSObject.has, by returning true from InValue and FromValue for
|
||||
// every existing property, and having false as the fallback value for
|
||||
// when a property doesn't exist.
|
||||
|
||||
bool HasValue(JS::HandleValue val) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
struct HasProperty
|
||||
{
|
||||
// See comments in PrimitiveProperty.
|
||||
typedef bool NativeType;
|
||||
typedef bool NativeFallback;
|
||||
|
||||
typedef decltype(&Self::HasValue) HasValue_t;
|
||||
static constexpr HasValue_t InValue = &Self::HasValue;
|
||||
static constexpr HasValue_t FromValue = &Self::HasValue;
|
||||
};
|
||||
|
||||
// Statically cast from bool to jboolean (unsigned char); it works
|
||||
// since false and JNI_FALSE have the same value (0), and true and
|
||||
// JNI_TRUE have the same value (1).
|
||||
typedef PrimitiveProperty<
|
||||
bool, jni::BooleanArray, jboolean, jbooleanArray,
|
||||
&JS::Value::isBoolean, &JS::Value::toBoolean,
|
||||
&JNIEnv::NewBooleanArray, &JNIEnv::SetBooleanArrayRegion>
|
||||
BooleanProperty;
|
||||
|
||||
typedef PrimitiveProperty<
|
||||
double, jni::DoubleArray, jdouble, jdoubleArray,
|
||||
&JS::Value::isNumber, &JS::Value::toNumber,
|
||||
&JNIEnv::NewDoubleArray, &JNIEnv::SetDoubleArrayRegion>
|
||||
DoubleProperty;
|
||||
|
||||
typedef PrimitiveProperty<
|
||||
int32_t, jni::IntArray, jint, jintArray,
|
||||
&JS::Value::isInt32, &JS::Value::toInt32,
|
||||
&JNIEnv::NewIntArray, &JNIEnv::SetIntArrayRegion>
|
||||
IntProperty;
|
||||
|
||||
typedef BaseObjectProperty<
|
||||
jni::String, &Self::StringInValue, &Self::StringFromValue>
|
||||
StringProperty;
|
||||
|
||||
typedef BaseObjectProperty<
|
||||
sdk::Bundle, &Self::ObjectInValue, &Self::BundleFromValue>
|
||||
BundleProperty;
|
||||
|
||||
typedef BaseObjectProperty<
|
||||
NativeJSObject, &Self::ObjectInValue, &Self::ObjectFromValue>
|
||||
ObjectProperty;
|
||||
|
||||
typedef ArrayProperty<BooleanProperty> BooleanArrayProperty;
|
||||
typedef ArrayProperty<DoubleProperty> DoubleArrayProperty;
|
||||
typedef ArrayProperty<IntProperty> IntArrayProperty;
|
||||
typedef ArrayProperty<StringProperty> StringArrayProperty;
|
||||
typedef ArrayProperty<BundleProperty> BundleArrayProperty;
|
||||
typedef ArrayProperty<ObjectProperty> ObjectArrayProperty;
|
||||
|
||||
template<class Prop>
|
||||
typename Prop::NativeType
|
||||
GetProperty(jni::String::Param name,
|
||||
typename Prop::NativeFallback* fallback = nullptr)
|
||||
{
|
||||
if (!CheckThread() || !CheckObject()) {
|
||||
return typename Prop::NativeType();
|
||||
}
|
||||
|
||||
const JSJNIString nameStr(mEnv, name);
|
||||
JS::RootedValue val(mJSContext);
|
||||
|
||||
if (!CheckJNIArgument(name) ||
|
||||
!CheckJSCall(JS_GetUCProperty(
|
||||
mJSContext, mJSObject, nameStr, nameStr.Length(), &val))) {
|
||||
return typename Prop::NativeType();
|
||||
}
|
||||
|
||||
// Strictly, null is different from undefined in JS. However, in
|
||||
// practice, null is often used to indicate a property doesn't exist in
|
||||
// the same manner as undefined. Therefore, we treat null in the same
|
||||
// way as undefined when checking property existence (bug 1014965).
|
||||
if (val.isUndefined() || val.isNull()) {
|
||||
if (fallback) {
|
||||
return mozilla::Move(*fallback);
|
||||
}
|
||||
jni::ThrowException(
|
||||
"org/mozilla/gecko/util/NativeJSObject$InvalidPropertyException",
|
||||
"Property does not exist");
|
||||
return typename Prop::NativeType();
|
||||
}
|
||||
|
||||
if (!CheckProperty(Prop::InValue, val)) {
|
||||
return typename Prop::NativeType();
|
||||
}
|
||||
return (this->*Prop::FromValue)(val);
|
||||
}
|
||||
|
||||
NativeJSObject::LocalRef CreateChild(JS::HandleObject object)
|
||||
{
|
||||
auto instance = NativeJSObject::New();
|
||||
mozilla::UniquePtr<NativeJSContainerImpl> impl(
|
||||
new NativeJSContainerImpl(instance.Env(), mJSContext, object));
|
||||
|
||||
ObjectBase::AttachNative(instance, mozilla::Move(impl));
|
||||
if (!mChildren.append(NativeJSObject::GlobalRef(instance))) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
NativeJSContainerImpl(JNIEnv* env, JSContext* cx, JS::HandleObject object)
|
||||
: mEnv(env)
|
||||
, mJSContext(cx)
|
||||
, mJSObject(cx, object)
|
||||
{}
|
||||
|
||||
public:
|
||||
~NativeJSContainerImpl()
|
||||
{
|
||||
// Dispose of all children on destruction. The children will in turn
|
||||
// dispose any of their children (i.e. our grandchildren) and so on.
|
||||
NativeJSObject::LocalRef child(mEnv);
|
||||
for (size_t i = 0; i < mChildren.length(); i++) {
|
||||
child = mChildren[i];
|
||||
ObjectBase::GetNative(child)->ObjectBase::DisposeNative(child);
|
||||
}
|
||||
}
|
||||
|
||||
static NativeJSContainer::LocalRef
|
||||
CreateInstance(JSContext* cx, JS::HandleObject object)
|
||||
{
|
||||
auto instance = NativeJSContainer::New();
|
||||
mozilla::UniquePtr<NativeJSContainerImpl> impl(
|
||||
new NativeJSContainerImpl(instance.Env(), cx, object));
|
||||
|
||||
ContainerBase::AttachNative(instance, mozilla::Move(impl));
|
||||
return instance;
|
||||
}
|
||||
|
||||
// NativeJSContainer methods
|
||||
|
||||
void DisposeNative(const NativeJSContainer::LocalRef& instance)
|
||||
{
|
||||
if (!CheckThread()) {
|
||||
return;
|
||||
}
|
||||
ContainerBase::DisposeNative(instance);
|
||||
}
|
||||
|
||||
NativeJSContainer::LocalRef Clone()
|
||||
{
|
||||
if (!CheckThread()) {
|
||||
return nullptr;
|
||||
}
|
||||
return CreateInstance(mJSContext, mJSObject);
|
||||
}
|
||||
|
||||
// NativeJSObject methods
|
||||
|
||||
bool GetBoolean(jni::String::Param name)
|
||||
{
|
||||
return GetProperty<BooleanProperty>(name);
|
||||
}
|
||||
|
||||
bool OptBoolean(jni::String::Param name, bool fallback)
|
||||
{
|
||||
return GetProperty<BooleanProperty>(name, &fallback);
|
||||
}
|
||||
|
||||
jni::BooleanArray::LocalRef
|
||||
GetBooleanArray(jni::String::Param name)
|
||||
{
|
||||
return GetProperty<BooleanArrayProperty>(name);
|
||||
}
|
||||
|
||||
jni::BooleanArray::LocalRef
|
||||
OptBooleanArray(jni::String::Param name, jni::BooleanArray::Param fallback)
|
||||
{
|
||||
return GetProperty<BooleanArrayProperty>(name, &fallback);
|
||||
}
|
||||
|
||||
jni::Object::LocalRef
|
||||
GetBundle(jni::String::Param name)
|
||||
{
|
||||
return GetProperty<BundleProperty>(name);
|
||||
}
|
||||
|
||||
jni::Object::LocalRef
|
||||
OptBundle(jni::String::Param name, jni::Object::Param fallback)
|
||||
{
|
||||
// Because the GetProperty expects a sdk::Bundle::Param,
|
||||
// we have to do conversions here from jni::Object::Param.
|
||||
const auto& fb = sdk::Bundle::Ref::From(fallback.Get());
|
||||
return GetProperty<BundleProperty>(name, &fb);
|
||||
}
|
||||
|
||||
jni::ObjectArray::LocalRef
|
||||
GetBundleArray(jni::String::Param name)
|
||||
{
|
||||
return GetProperty<BundleArrayProperty>(name);
|
||||
}
|
||||
|
||||
jni::ObjectArray::LocalRef
|
||||
OptBundleArray(jni::String::Param name, jni::ObjectArray::Param fallback)
|
||||
{
|
||||
return GetProperty<BundleArrayProperty>(name, &fallback);
|
||||
}
|
||||
|
||||
double GetDouble(jni::String::Param name)
|
||||
{
|
||||
return GetProperty<DoubleProperty>(name);
|
||||
}
|
||||
|
||||
double OptDouble(jni::String::Param name, double fallback)
|
||||
{
|
||||
return GetProperty<DoubleProperty>(name, &fallback);
|
||||
}
|
||||
|
||||
jni::DoubleArray::LocalRef
|
||||
GetDoubleArray(jni::String::Param name)
|
||||
{
|
||||
return GetProperty<DoubleArrayProperty>(name);
|
||||
}
|
||||
|
||||
jni::DoubleArray::LocalRef
|
||||
OptDoubleArray(jni::String::Param name, jni::DoubleArray::Param fallback)
|
||||
{
|
||||
jni::DoubleArray::LocalRef fb(fallback);
|
||||
return GetProperty<DoubleArrayProperty>(name, &fb);
|
||||
}
|
||||
|
||||
int GetInt(jni::String::Param name)
|
||||
{
|
||||
return GetProperty<IntProperty>(name);
|
||||
}
|
||||
|
||||
int OptInt(jni::String::Param name, int fallback)
|
||||
{
|
||||
return GetProperty<IntProperty>(name, &fallback);
|
||||
}
|
||||
|
||||
jni::IntArray::LocalRef
|
||||
GetIntArray(jni::String::Param name)
|
||||
{
|
||||
return GetProperty<IntArrayProperty>(name);
|
||||
}
|
||||
|
||||
jni::IntArray::LocalRef
|
||||
OptIntArray(jni::String::Param name, jni::IntArray::Param fallback)
|
||||
{
|
||||
jni::IntArray::LocalRef fb(fallback);
|
||||
return GetProperty<IntArrayProperty>(name, &fb);
|
||||
}
|
||||
|
||||
NativeJSObject::LocalRef
|
||||
GetObject(jni::String::Param name)
|
||||
{
|
||||
return GetProperty<ObjectProperty>(name);
|
||||
}
|
||||
|
||||
NativeJSObject::LocalRef
|
||||
OptObject(jni::String::Param name, NativeJSObject::Param fallback)
|
||||
{
|
||||
return GetProperty<ObjectProperty>(name, &fallback);
|
||||
}
|
||||
|
||||
jni::ObjectArray::LocalRef
|
||||
GetObjectArray(jni::String::Param name)
|
||||
{
|
||||
return GetProperty<ObjectArrayProperty>(name);
|
||||
}
|
||||
|
||||
jni::ObjectArray::LocalRef
|
||||
OptObjectArray(jni::String::Param name, jni::ObjectArray::Param fallback)
|
||||
{
|
||||
return GetProperty<ObjectArrayProperty>(name, &fallback);
|
||||
}
|
||||
|
||||
jni::String::LocalRef
|
||||
GetString(jni::String::Param name)
|
||||
{
|
||||
return GetProperty<StringProperty>(name);
|
||||
}
|
||||
|
||||
jni::String::LocalRef
|
||||
OptString(jni::String::Param name, jni::String::Param fallback)
|
||||
{
|
||||
return GetProperty<StringProperty>(name, &fallback);
|
||||
}
|
||||
|
||||
jni::ObjectArray::LocalRef
|
||||
GetStringArray(jni::String::Param name)
|
||||
{
|
||||
return GetProperty<StringArrayProperty>(name);
|
||||
}
|
||||
|
||||
jni::ObjectArray::LocalRef
|
||||
OptStringArray(jni::String::Param name, jni::ObjectArray::Param fallback)
|
||||
{
|
||||
return GetProperty<StringArrayProperty>(name, &fallback);
|
||||
}
|
||||
|
||||
bool Has(jni::String::Param name)
|
||||
{
|
||||
bool no = false;
|
||||
// Fallback to false indicating no such property.
|
||||
return GetProperty<HasProperty>(name, &no);
|
||||
}
|
||||
|
||||
jni::Object::LocalRef ToBundle()
|
||||
{
|
||||
if (!CheckThread() || !CheckObject()) {
|
||||
return nullptr;
|
||||
}
|
||||
return BundleFromValue(mJSObject);
|
||||
}
|
||||
|
||||
private:
|
||||
static bool AppendJSON(const char16_t* buf, uint32_t len, void* data)
|
||||
{
|
||||
static_cast<nsAutoString*>(data)->Append(buf, len);
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
jni::String::LocalRef ToString()
|
||||
{
|
||||
if (!CheckThread() || !CheckObject()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JS::RootedValue value(mJSContext, JS::ObjectValue(*mJSObject));
|
||||
nsAutoString json;
|
||||
if (!CheckJSCall(JS_Stringify(mJSContext, &value, nullptr,
|
||||
JS::NullHandleValue, AppendJSON, &json))) {
|
||||
return nullptr;
|
||||
}
|
||||
return jni::StringParam(json, mEnv);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Define the "static constexpr" members of our property types (e.g.
|
||||
// PrimitiveProperty<>::InValue). This is tricky because there are a lot of
|
||||
// template parameters, so we use macros to make it simpler.
|
||||
|
||||
#define DEFINE_PRIMITIVE_PROPERTY_MEMBER(Name) \
|
||||
template<typename U, typename UA, typename V, typename VA, \
|
||||
bool (JS::Value::*I)() const, \
|
||||
U (JS::Value::*T)() const, \
|
||||
VA (JNIEnv::*N)(jsize), \
|
||||
void (JNIEnv::*S)(VA, jsize, jsize, const V*)> \
|
||||
constexpr typename NativeJSContainerImpl \
|
||||
::PrimitiveProperty<U, UA, V, VA, I, T, N, S>::Name##_t \
|
||||
NativeJSContainerImpl::PrimitiveProperty<U, UA, V, VA, I, T, N, S>::Name
|
||||
|
||||
DEFINE_PRIMITIVE_PROPERTY_MEMBER(NewJNIArray);
|
||||
DEFINE_PRIMITIVE_PROPERTY_MEMBER(SetJNIArrayRegion);
|
||||
DEFINE_PRIMITIVE_PROPERTY_MEMBER(InValue);
|
||||
DEFINE_PRIMITIVE_PROPERTY_MEMBER(FromValue);
|
||||
DEFINE_PRIMITIVE_PROPERTY_MEMBER(NewArray);
|
||||
|
||||
#undef DEFINE_PRIMITIVE_PROPERTY_MEMBER
|
||||
|
||||
#define DEFINE_OBJECT_PROPERTY_MEMBER(Name) \
|
||||
template<class C, \
|
||||
bool (NativeJSContainerImpl::*I)(JS::HandleValue) const, \
|
||||
typename C::LocalRef (NativeJSContainerImpl::*F)(JS::HandleValue)> \
|
||||
constexpr typename NativeJSContainerImpl \
|
||||
::BaseObjectProperty<C, I, F>::Name##_t \
|
||||
NativeJSContainerImpl::BaseObjectProperty<C, I, F>::Name
|
||||
|
||||
DEFINE_OBJECT_PROPERTY_MEMBER(InValue);
|
||||
DEFINE_OBJECT_PROPERTY_MEMBER(FromValue);
|
||||
DEFINE_OBJECT_PROPERTY_MEMBER(NewArray);
|
||||
|
||||
#undef DEFINE_OBJECT_PROPERTY_MEMBER
|
||||
|
||||
template<class P> constexpr typename NativeJSContainerImpl::ArrayProperty<P>
|
||||
::InValue_t NativeJSContainerImpl::ArrayProperty<P>::InValue;
|
||||
template<class P> constexpr typename NativeJSContainerImpl::ArrayProperty<P>
|
||||
::FromValue_t NativeJSContainerImpl::ArrayProperty<P>::FromValue;
|
||||
|
||||
constexpr NativeJSContainerImpl::HasProperty::HasValue_t
|
||||
NativeJSContainerImpl::HasProperty::InValue;
|
||||
constexpr NativeJSContainerImpl::HasProperty::HasValue_t
|
||||
NativeJSContainerImpl::HasProperty::FromValue;
|
||||
|
||||
|
||||
NativeJSContainer::LocalRef
|
||||
CreateNativeJSContainer(JSContext* cx, JS::HandleObject object)
|
||||
{
|
||||
return NativeJSContainerImpl::CreateInstance(cx, object);
|
||||
}
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
22
widget/android/NativeJSContainer.h
Normal file
22
widget/android/NativeJSContainer.h
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/* -*- Mode: c++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4; -*- */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef NativeJSObject_h__
|
||||
#define NativeJSObject_h__
|
||||
|
||||
#include "GeneratedJNIWrappers.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
java::NativeJSContainer::LocalRef
|
||||
CreateNativeJSContainer(JSContext* cx, JS::HandleObject object);
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // NativeJSObject_h__
|
||||
|
||||
324
widget/android/PrefsHelper.h
Normal file
324
widget/android/PrefsHelper.h
Normal file
|
|
@ -0,0 +1,324 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* 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/. */
|
||||
|
||||
#ifndef PrefsHelper_h
|
||||
#define PrefsHelper_h
|
||||
|
||||
#include "GeneratedJNINatives.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "nsAppShell.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsVariant.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class PrefsHelper
|
||||
: public java::PrefsHelper::Natives<PrefsHelper>
|
||||
{
|
||||
PrefsHelper() = delete;
|
||||
|
||||
static bool GetVariantPref(nsIObserverService* aObsServ,
|
||||
nsIWritableVariant* aVariant,
|
||||
jni::Object::Param aPrefHandler,
|
||||
const jni::String::LocalRef& aPrefName)
|
||||
{
|
||||
if (NS_FAILED(aObsServ->NotifyObservers(aVariant, "android-get-pref",
|
||||
aPrefName->ToString().get()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t varType = nsIDataType::VTYPE_EMPTY;
|
||||
if (NS_FAILED(aVariant->GetDataType(&varType))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t type = java::PrefsHelper::PREF_INVALID;
|
||||
bool boolVal = false;
|
||||
int32_t intVal = 0;
|
||||
nsAutoString strVal;
|
||||
|
||||
switch (varType) {
|
||||
case nsIDataType::VTYPE_BOOL:
|
||||
type = java::PrefsHelper::PREF_BOOL;
|
||||
if (NS_FAILED(aVariant->GetAsBool(&boolVal))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case nsIDataType::VTYPE_INT32:
|
||||
type = java::PrefsHelper::PREF_INT;
|
||||
if (NS_FAILED(aVariant->GetAsInt32(&intVal))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case nsIDataType::VTYPE_ASTRING:
|
||||
type = java::PrefsHelper::PREF_STRING;
|
||||
if (NS_FAILED(aVariant->GetAsAString(strVal))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
jni::StringParam jstrVal(type == java::PrefsHelper::PREF_STRING ?
|
||||
jni::StringParam(strVal, aPrefName.Env()) :
|
||||
jni::StringParam(nullptr));
|
||||
|
||||
if (aPrefHandler) {
|
||||
java::PrefsHelper::CallPrefHandler(
|
||||
aPrefHandler, type, aPrefName,
|
||||
boolVal, intVal, jstrVal);
|
||||
} else {
|
||||
java::PrefsHelper::OnPrefChange(
|
||||
aPrefName, type, boolVal, intVal, jstrVal);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool SetVariantPref(nsIObserverService* aObsServ,
|
||||
nsIWritableVariant* aVariant,
|
||||
jni::String::Param aPrefName,
|
||||
bool aFlush,
|
||||
int32_t aType,
|
||||
bool aBoolVal,
|
||||
int32_t aIntVal,
|
||||
jni::String::Param aStrVal)
|
||||
{
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
switch (aType) {
|
||||
case java::PrefsHelper::PREF_BOOL:
|
||||
rv = aVariant->SetAsBool(aBoolVal);
|
||||
break;
|
||||
case java::PrefsHelper::PREF_INT:
|
||||
rv = aVariant->SetAsInt32(aIntVal);
|
||||
break;
|
||||
case java::PrefsHelper::PREF_STRING:
|
||||
rv = aVariant->SetAsAString(aStrVal->ToString());
|
||||
break;
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = aObsServ->NotifyObservers(aVariant, "android-set-pref",
|
||||
aPrefName->ToString().get());
|
||||
}
|
||||
|
||||
uint16_t varType = nsIDataType::VTYPE_EMPTY;
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = aVariant->GetDataType(&varType);
|
||||
}
|
||||
|
||||
// We use set-to-empty to signal the pref was handled.
|
||||
const bool handled = varType == nsIDataType::VTYPE_EMPTY;
|
||||
|
||||
if (NS_SUCCEEDED(rv) && handled && aFlush) {
|
||||
rv = Preferences::GetService()->SavePrefFile(nullptr);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return handled;
|
||||
}
|
||||
|
||||
NS_WARNING(nsPrintfCString("Failed to set pref %s",
|
||||
aPrefName->ToCString().get()).get());
|
||||
// Pretend we handled the pref.
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
static void GetPrefs(const jni::Class::LocalRef& aCls,
|
||||
jni::ObjectArray::Param aPrefNames,
|
||||
jni::Object::Param aPrefHandler)
|
||||
{
|
||||
nsTArray<jni::Object::LocalRef> nameRefArray(aPrefNames->GetElements());
|
||||
nsCOMPtr<nsIObserverService> obsServ;
|
||||
nsCOMPtr<nsIWritableVariant> value;
|
||||
nsAdoptingString strVal;
|
||||
|
||||
for (jni::Object::LocalRef& nameRef : nameRefArray) {
|
||||
jni::String::LocalRef nameStr(mozilla::Move(nameRef));
|
||||
const nsCString& name = nameStr->ToCString();
|
||||
|
||||
int32_t type = java::PrefsHelper::PREF_INVALID;
|
||||
bool boolVal = false;
|
||||
int32_t intVal = 0;
|
||||
|
||||
switch (Preferences::GetType(name.get())) {
|
||||
case nsIPrefBranch::PREF_BOOL:
|
||||
type = java::PrefsHelper::PREF_BOOL;
|
||||
boolVal = Preferences::GetBool(name.get());
|
||||
break;
|
||||
|
||||
case nsIPrefBranch::PREF_INT:
|
||||
type = java::PrefsHelper::PREF_INT;
|
||||
intVal = Preferences::GetInt(name.get());
|
||||
break;
|
||||
|
||||
case nsIPrefBranch::PREF_STRING:
|
||||
type = java::PrefsHelper::PREF_STRING;
|
||||
strVal = Preferences::GetLocalizedString(name.get());
|
||||
if (!strVal) {
|
||||
strVal = Preferences::GetString(name.get());
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// Pref not found; try to find it.
|
||||
if (!obsServ) {
|
||||
obsServ = services::GetObserverService();
|
||||
if (!obsServ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (value) {
|
||||
value->SetAsEmpty();
|
||||
} else {
|
||||
value = new nsVariant();
|
||||
}
|
||||
if (!GetVariantPref(obsServ, value,
|
||||
aPrefHandler, nameStr)) {
|
||||
NS_WARNING(nsPrintfCString("Failed to get pref %s",
|
||||
name.get()).get());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
java::PrefsHelper::CallPrefHandler(
|
||||
aPrefHandler, type, nameStr, boolVal, intVal,
|
||||
jni::StringParam(type == java::PrefsHelper::PREF_STRING ?
|
||||
jni::StringParam(strVal, aCls.Env()) :
|
||||
jni::StringParam(nullptr)));
|
||||
}
|
||||
|
||||
java::PrefsHelper::CallPrefHandler(
|
||||
aPrefHandler, java::PrefsHelper::PREF_FINISH,
|
||||
nullptr, false, 0, nullptr);
|
||||
}
|
||||
|
||||
static void SetPref(jni::String::Param aPrefName,
|
||||
bool aFlush,
|
||||
int32_t aType,
|
||||
bool aBoolVal,
|
||||
int32_t aIntVal,
|
||||
jni::String::Param aStrVal)
|
||||
{
|
||||
const nsCString& name = aPrefName->ToCString();
|
||||
|
||||
if (Preferences::GetType(name.get()) == nsIPrefBranch::PREF_INVALID) {
|
||||
// No pref; try asking first.
|
||||
nsCOMPtr<nsIObserverService> obsServ =
|
||||
services::GetObserverService();
|
||||
nsCOMPtr<nsIWritableVariant> value = new nsVariant();
|
||||
if (obsServ && SetVariantPref(obsServ, value, aPrefName, aFlush,
|
||||
aType, aBoolVal, aIntVal, aStrVal)) {
|
||||
// The "pref" has changed; send a notification.
|
||||
GetVariantPref(obsServ, value, nullptr,
|
||||
jni::String::LocalRef(aPrefName));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (aType) {
|
||||
case java::PrefsHelper::PREF_BOOL:
|
||||
Preferences::SetBool(name.get(), aBoolVal);
|
||||
break;
|
||||
case java::PrefsHelper::PREF_INT:
|
||||
Preferences::SetInt(name.get(), aIntVal);
|
||||
break;
|
||||
case java::PrefsHelper::PREF_STRING:
|
||||
Preferences::SetString(name.get(), aStrVal->ToString());
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(false, "Invalid pref type");
|
||||
}
|
||||
|
||||
if (aFlush) {
|
||||
Preferences::GetService()->SavePrefFile(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
static void AddObserver(const jni::Class::LocalRef& aCls,
|
||||
jni::ObjectArray::Param aPrefNames,
|
||||
jni::Object::Param aPrefHandler,
|
||||
jni::ObjectArray::Param aPrefsToObserve)
|
||||
{
|
||||
// Call observer immediately with existing pref values.
|
||||
GetPrefs(aCls, aPrefNames, aPrefHandler);
|
||||
|
||||
if (!aPrefsToObserve) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsTArray<jni::Object::LocalRef> nameRefArray(
|
||||
aPrefsToObserve->GetElements());
|
||||
nsAppShell* const appShell = nsAppShell::Get();
|
||||
MOZ_ASSERT(appShell);
|
||||
|
||||
for (jni::Object::LocalRef& nameRef : nameRefArray) {
|
||||
jni::String::LocalRef nameStr(mozilla::Move(nameRef));
|
||||
MOZ_ALWAYS_SUCCEEDS(Preferences::AddStrongObserver(
|
||||
appShell, nameStr->ToCString().get()));
|
||||
}
|
||||
}
|
||||
|
||||
static void RemoveObserver(const jni::Class::LocalRef& aCls,
|
||||
jni::ObjectArray::Param aPrefsToUnobserve)
|
||||
{
|
||||
nsTArray<jni::Object::LocalRef> nameRefArray(
|
||||
aPrefsToUnobserve->GetElements());
|
||||
nsAppShell* const appShell = nsAppShell::Get();
|
||||
MOZ_ASSERT(appShell);
|
||||
|
||||
for (jni::Object::LocalRef& nameRef : nameRefArray) {
|
||||
jni::String::LocalRef nameStr(mozilla::Move(nameRef));
|
||||
MOZ_ALWAYS_SUCCEEDS(Preferences::RemoveObserver(
|
||||
appShell, nameStr->ToCString().get()));
|
||||
}
|
||||
}
|
||||
|
||||
static void OnPrefChange(const char16_t* aData)
|
||||
{
|
||||
const nsCString& name = NS_LossyConvertUTF16toASCII(aData);
|
||||
|
||||
int32_t type = -1;
|
||||
bool boolVal = false;
|
||||
int32_t intVal = false;
|
||||
nsAdoptingString strVal;
|
||||
|
||||
switch (Preferences::GetType(name.get())) {
|
||||
case nsIPrefBranch::PREF_BOOL:
|
||||
type = java::PrefsHelper::PREF_BOOL;
|
||||
boolVal = Preferences::GetBool(name.get());
|
||||
break;
|
||||
case nsIPrefBranch::PREF_INT:
|
||||
type = java::PrefsHelper::PREF_INT;
|
||||
intVal = Preferences::GetInt(name.get());
|
||||
break;
|
||||
case nsIPrefBranch::PREF_STRING:
|
||||
type = java::PrefsHelper::PREF_STRING;
|
||||
strVal = Preferences::GetLocalizedString(name.get());
|
||||
if (!strVal) {
|
||||
strVal = Preferences::GetString(name.get());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NS_WARNING(nsPrintfCString("Invalid pref %s",
|
||||
name.get()).get());
|
||||
return;
|
||||
}
|
||||
|
||||
java::PrefsHelper::OnPrefChange(
|
||||
name, type, boolVal, intVal,
|
||||
jni::StringParam(type == java::PrefsHelper::PREF_STRING ?
|
||||
jni::StringParam(strVal) : jni::StringParam(nullptr)));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // PrefsHelper_h
|
||||
2
widget/android/bindings/AndroidRect-classes.txt
Normal file
2
widget/android/bindings/AndroidRect-classes.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
android.graphics.Rect
|
||||
android.graphics.RectF
|
||||
1
widget/android/bindings/Bundle-classes.txt
Normal file
1
widget/android/bindings/Bundle-classes.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
android.os.Bundle
|
||||
1
widget/android/bindings/KeyEvent-classes.txt
Normal file
1
widget/android/bindings/KeyEvent-classes.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
android.view.KeyEvent
|
||||
27
widget/android/bindings/Makefile.in
Normal file
27
widget/android/bindings/Makefile.in
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# 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/.
|
||||
|
||||
# Bug 1099345 - The SDK's lint code (used by the code generator) does not enjoy
|
||||
# concurrent access to a cache that it generates.
|
||||
.NOTPARALLEL:
|
||||
|
||||
annotation_processor_jar_files := \
|
||||
$(DEPTH)/build/annotationProcessors/annotationProcessors.jar \
|
||||
$(ANDROID_TOOLS)/lib/lint.jar \
|
||||
$(ANDROID_TOOLS)/lib/lint-checks.jar \
|
||||
$(NULL)
|
||||
|
||||
sdk_processor := \
|
||||
$(JAVA) \
|
||||
-Dcom.android.tools.lint.bindir='$(ANDROID_TOOLS)' \
|
||||
-classpath $(subst $(NULL) ,:,$(strip $(annotation_processor_jar_files))) \
|
||||
org.mozilla.gecko.annotationProcessors.SDKProcessor
|
||||
|
||||
# For the benefit of readers: the following pattern rule says that,
|
||||
# for example, MediaCodec.cpp and MediaCodec.h can be produced from
|
||||
# MediaCodec-classes.txt. This formulation invokes the SDK processor
|
||||
# at most once.
|
||||
|
||||
%.cpp %.h: $(ANDROID_SDK)/android.jar %-classes.txt $(annotation_processor_jar_files)
|
||||
$(sdk_processor) $(ANDROID_SDK)/android.jar $(srcdir)/$*-classes.txt $(CURDIR) $* 16
|
||||
5
widget/android/bindings/MediaCodec-classes.txt
Normal file
5
widget/android/bindings/MediaCodec-classes.txt
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
android.media.MediaCodec
|
||||
android.media.MediaCodec$BufferInfo
|
||||
android.media.MediaCodec$CryptoInfo
|
||||
android.media.MediaDrm$KeyStatus
|
||||
android.media.MediaFormat
|
||||
1
widget/android/bindings/MotionEvent-classes.txt
Normal file
1
widget/android/bindings/MotionEvent-classes.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
android.view.MotionEvent
|
||||
2
widget/android/bindings/SurfaceTexture-classes.txt
Normal file
2
widget/android/bindings/SurfaceTexture-classes.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
android.graphics.SurfaceTexture
|
||||
android.view.Surface
|
||||
1
widget/android/bindings/ViewConfiguration-classes.txt
Normal file
1
widget/android/bindings/ViewConfiguration-classes.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
android.view.ViewConfiguration
|
||||
41
widget/android/bindings/moz.build
Normal file
41
widget/android/bindings/moz.build
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
# List of stems to generate .cpp and .h files for. To add a stem, add it to
|
||||
# this list and ensure that $(stem)-classes.txt exists in this directory.
|
||||
generated = [
|
||||
'AndroidRect',
|
||||
'Bundle',
|
||||
'KeyEvent',
|
||||
'MediaCodec',
|
||||
'MotionEvent',
|
||||
'SurfaceTexture',
|
||||
'ViewConfiguration'
|
||||
]
|
||||
|
||||
SOURCES += ['!%s.cpp' % stem for stem in generated]
|
||||
|
||||
EXPORTS += ['!%s.h' % stem for stem in generated]
|
||||
|
||||
# We'd like to add these to a future GENERATED_EXPORTS list, but for now we mark
|
||||
# them as generated here and manually install them in Makefile.in.
|
||||
GENERATED_FILES += [stem + '.h' for stem in generated]
|
||||
|
||||
# There is an unfortunate race condition when using generated SOURCES and
|
||||
# pattern rules (see Makefile.in) that manifests itself as a VPATH resolution
|
||||
# conflict: MediaCodec.o looks for MediaCodec.cpp and $(CURDIR)/MediaCodec.cpp,
|
||||
# and the pattern rule is matched but doesn't resolve both sources, causing a
|
||||
# failure. Adding the SOURCES to GENERATED_FILES causes the sources
|
||||
# to be built at export time, which is before MediaCodec.o needs them; and by
|
||||
# the time MediaCodec.o is built, the source is in place and the VPATH
|
||||
# resolution works as expected.
|
||||
GENERATED_FILES += [f[1:] for f in SOURCES]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/widget/android',
|
||||
]
|
||||
244
widget/android/fennec/FennecJNINatives.h
Normal file
244
widget/android/fennec/FennecJNINatives.h
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
// GENERATED CODE
|
||||
// Generated by the Java program at /build/annotationProcessors at compile time
|
||||
// from annotations on Java methods. To update, change the annotations on the
|
||||
// corresponding Java methods and rerun the build. Manually updating this file
|
||||
// will cause your build to fail.
|
||||
|
||||
#ifndef FennecJNINatives_h
|
||||
#define FennecJNINatives_h
|
||||
|
||||
#include "FennecJNIWrappers.h"
|
||||
#include "mozilla/jni/Natives.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace java {
|
||||
|
||||
template<class Impl>
|
||||
class ANRReporter::Natives : public mozilla::jni::NativeImpl<ANRReporter, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[3];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod ANRReporter::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<ANRReporter::GetNativeStack_t>(
|
||||
mozilla::jni::NativeStub<ANRReporter::GetNativeStack_t, Impl>
|
||||
::template Wrap<&Impl::GetNativeStack>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<ANRReporter::ReleaseNativeStack_t>(
|
||||
mozilla::jni::NativeStub<ANRReporter::ReleaseNativeStack_t, Impl>
|
||||
::template Wrap<&Impl::ReleaseNativeStack>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<ANRReporter::RequestNativeStack_t>(
|
||||
mozilla::jni::NativeStub<ANRReporter::RequestNativeStack_t, Impl>
|
||||
::template Wrap<&Impl::RequestNativeStack>)
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
class GeckoJavaSampler::Natives : public mozilla::jni::NativeImpl<GeckoJavaSampler, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[1];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod GeckoJavaSampler::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<GeckoJavaSampler::GetProfilerTime_t>(
|
||||
mozilla::jni::NativeStub<GeckoJavaSampler::GetProfilerTime_t, Impl>
|
||||
::template Wrap<&Impl::GetProfilerTime>)
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
class MemoryMonitor::Natives : public mozilla::jni::NativeImpl<MemoryMonitor, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[1];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod MemoryMonitor::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<MemoryMonitor::DispatchMemoryPressure_t>(
|
||||
mozilla::jni::NativeStub<MemoryMonitor::DispatchMemoryPressure_t, Impl>
|
||||
::template Wrap<&Impl::DispatchMemoryPressure>)
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
class PresentationMediaPlayerManager::Natives : public mozilla::jni::NativeImpl<PresentationMediaPlayerManager, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[3];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod PresentationMediaPlayerManager::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<PresentationMediaPlayerManager::AddPresentationSurface_t>(
|
||||
mozilla::jni::NativeStub<PresentationMediaPlayerManager::AddPresentationSurface_t, Impl>
|
||||
::template Wrap<&Impl::AddPresentationSurface>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<PresentationMediaPlayerManager::InvalidateAndScheduleComposite_t>(
|
||||
mozilla::jni::NativeStub<PresentationMediaPlayerManager::InvalidateAndScheduleComposite_t, Impl>
|
||||
::template Wrap<&Impl::InvalidateAndScheduleComposite>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<PresentationMediaPlayerManager::RemovePresentationSurface_t>(
|
||||
mozilla::jni::NativeStub<PresentationMediaPlayerManager::RemovePresentationSurface_t, Impl>
|
||||
::template Wrap<&Impl::RemovePresentationSurface>)
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
class ScreenManagerHelper::Natives : public mozilla::jni::NativeImpl<ScreenManagerHelper, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[2];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod ScreenManagerHelper::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<ScreenManagerHelper::AddDisplay_t>(
|
||||
mozilla::jni::NativeStub<ScreenManagerHelper::AddDisplay_t, Impl>
|
||||
::template Wrap<&Impl::AddDisplay>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<ScreenManagerHelper::RemoveDisplay_t>(
|
||||
mozilla::jni::NativeStub<ScreenManagerHelper::RemoveDisplay_t, Impl>
|
||||
::template Wrap<&Impl::RemoveDisplay>)
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
class Telemetry::Natives : public mozilla::jni::NativeImpl<Telemetry, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[5];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod Telemetry::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<Telemetry::AddHistogram_t>(
|
||||
mozilla::jni::NativeStub<Telemetry::AddHistogram_t, Impl>
|
||||
::template Wrap<&Impl::AddHistogram>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<Telemetry::AddKeyedHistogram_t>(
|
||||
mozilla::jni::NativeStub<Telemetry::AddKeyedHistogram_t, Impl>
|
||||
::template Wrap<&Impl::AddKeyedHistogram>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<Telemetry::AddUIEvent_t>(
|
||||
mozilla::jni::NativeStub<Telemetry::AddUIEvent_t, Impl>
|
||||
::template Wrap<&Impl::AddUIEvent>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<Telemetry::StartUISession_t>(
|
||||
mozilla::jni::NativeStub<Telemetry::StartUISession_t, Impl>
|
||||
::template Wrap<&Impl::StartUISession>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<Telemetry::StopUISession_t>(
|
||||
mozilla::jni::NativeStub<Telemetry::StopUISession_t, Impl>
|
||||
::template Wrap<&Impl::StopUISession>)
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
class ThumbnailHelper::Natives : public mozilla::jni::NativeImpl<ThumbnailHelper, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[1];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod ThumbnailHelper::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<ThumbnailHelper::RequestThumbnail_t>(
|
||||
mozilla::jni::NativeStub<ThumbnailHelper::RequestThumbnail_t, Impl>
|
||||
::template Wrap<&Impl::RequestThumbnail>)
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
class ZoomedView::Natives : public mozilla::jni::NativeImpl<ZoomedView, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[1];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod ZoomedView::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<ZoomedView::RequestZoomedViewData_t>(
|
||||
mozilla::jni::NativeStub<ZoomedView::RequestZoomedViewData_t, Impl>
|
||||
::template Wrap<&Impl::RequestZoomedViewData>)
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
class CodecProxy::NativeCallbacks::Natives : public mozilla::jni::NativeImpl<NativeCallbacks, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[5];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod CodecProxy::NativeCallbacks::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<CodecProxy::NativeCallbacks::DisposeNative_t>(
|
||||
mozilla::jni::NativeStub<CodecProxy::NativeCallbacks::DisposeNative_t, Impl>
|
||||
::template Wrap<&Impl::DisposeNative>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<CodecProxy::NativeCallbacks::OnError_t>(
|
||||
mozilla::jni::NativeStub<CodecProxy::NativeCallbacks::OnError_t, Impl>
|
||||
::template Wrap<&Impl::OnError>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<CodecProxy::NativeCallbacks::OnInputExhausted_t>(
|
||||
mozilla::jni::NativeStub<CodecProxy::NativeCallbacks::OnInputExhausted_t, Impl>
|
||||
::template Wrap<&Impl::OnInputExhausted>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<CodecProxy::NativeCallbacks::OnOutput_t>(
|
||||
mozilla::jni::NativeStub<CodecProxy::NativeCallbacks::OnOutput_t, Impl>
|
||||
::template Wrap<&Impl::OnOutput>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<CodecProxy::NativeCallbacks::OnOutputFormatChanged_t>(
|
||||
mozilla::jni::NativeStub<CodecProxy::NativeCallbacks::OnOutputFormatChanged_t, Impl>
|
||||
::template Wrap<&Impl::OnOutputFormatChanged>)
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
class MediaDrmProxy::NativeMediaDrmProxyCallbacks::Natives : public mozilla::jni::NativeImpl<NativeMediaDrmProxyCallbacks, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[7];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod MediaDrmProxy::NativeMediaDrmProxyCallbacks::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnRejectPromise_t>(
|
||||
mozilla::jni::NativeStub<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnRejectPromise_t, Impl>
|
||||
::template Wrap<&Impl::OnRejectPromise>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionBatchedKeyChanged_t>(
|
||||
mozilla::jni::NativeStub<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionBatchedKeyChanged_t, Impl>
|
||||
::template Wrap<&Impl::OnSessionBatchedKeyChanged>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionClosed_t>(
|
||||
mozilla::jni::NativeStub<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionClosed_t, Impl>
|
||||
::template Wrap<&Impl::OnSessionClosed>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionCreated_t>(
|
||||
mozilla::jni::NativeStub<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionCreated_t, Impl>
|
||||
::template Wrap<&Impl::OnSessionCreated>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionError_t>(
|
||||
mozilla::jni::NativeStub<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionError_t, Impl>
|
||||
::template Wrap<&Impl::OnSessionError>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionMessage_t>(
|
||||
mozilla::jni::NativeStub<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionMessage_t, Impl>
|
||||
::template Wrap<&Impl::OnSessionMessage>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionUpdated_t>(
|
||||
mozilla::jni::NativeStub<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionUpdated_t, Impl>
|
||||
::template Wrap<&Impl::OnSessionUpdated>)
|
||||
};
|
||||
|
||||
} /* java */
|
||||
} /* mozilla */
|
||||
#endif // FennecJNINatives_h
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue