зеркало из https://github.com/mozilla/gecko-dev.git
Merge autoland to mozilla-central. a=merge
This commit is contained in:
Коммит
b61bbd064d
|
@ -111,7 +111,8 @@ void a11y::ProxyStateChangeEvent(RemoteAccessible* aTarget, uint64_t aState,
|
||||||
}
|
}
|
||||||
|
|
||||||
void a11y::ProxyCaretMoveEvent(RemoteAccessible* aTarget, int32_t aOffset,
|
void a11y::ProxyCaretMoveEvent(RemoteAccessible* aTarget, int32_t aOffset,
|
||||||
bool aIsSelectionCollapsed) {
|
bool aIsSelectionCollapsed,
|
||||||
|
int32_t aGranularity) {
|
||||||
RefPtr<SessionAccessibility> sessionAcc =
|
RefPtr<SessionAccessibility> sessionAcc =
|
||||||
SessionAccessibility::GetInstanceFor(aTarget);
|
SessionAccessibility::GetInstanceFor(aTarget);
|
||||||
|
|
||||||
|
|
|
@ -1372,7 +1372,8 @@ void a11y::ProxyStateChangeEvent(RemoteAccessible* aTarget, uint64_t aState,
|
||||||
}
|
}
|
||||||
|
|
||||||
void a11y::ProxyCaretMoveEvent(RemoteAccessible* aTarget, int32_t aOffset,
|
void a11y::ProxyCaretMoveEvent(RemoteAccessible* aTarget, int32_t aOffset,
|
||||||
bool aIsSelectionCollapsed) {
|
bool aIsSelectionCollapsed,
|
||||||
|
int32_t aGranularity) {
|
||||||
AtkObject* wrapper = GetWrapperFor(aTarget);
|
AtkObject* wrapper = GetWrapperFor(aTarget);
|
||||||
g_signal_emit_by_name(wrapper, "text_caret_moved", aOffset);
|
g_signal_emit_by_name(wrapper, "text_caret_moved", aOffset);
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,11 +127,13 @@ AccShowEvent::AccShowEvent(LocalAccessible* aTarget)
|
||||||
|
|
||||||
AccTextSelChangeEvent::AccTextSelChangeEvent(HyperTextAccessible* aTarget,
|
AccTextSelChangeEvent::AccTextSelChangeEvent(HyperTextAccessible* aTarget,
|
||||||
dom::Selection* aSelection,
|
dom::Selection* aSelection,
|
||||||
int32_t aReason)
|
int32_t aReason,
|
||||||
|
int32_t aGranularity)
|
||||||
: AccEvent(nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED, aTarget,
|
: AccEvent(nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED, aTarget,
|
||||||
eAutoDetect, eCoalesceTextSelChange),
|
eAutoDetect, eCoalesceTextSelChange),
|
||||||
mSel(aSelection),
|
mSel(aSelection),
|
||||||
mReason(aReason) {}
|
mReason(aReason),
|
||||||
|
mGranularity(aGranularity) {}
|
||||||
|
|
||||||
AccTextSelChangeEvent::~AccTextSelChangeEvent() {}
|
AccTextSelChangeEvent::~AccTextSelChangeEvent() {}
|
||||||
|
|
||||||
|
@ -246,7 +248,8 @@ already_AddRefed<nsIAccessibleEvent> a11y::MakeXPCEvent(AccEvent* aEvent) {
|
||||||
AccCaretMoveEvent* cm = downcast_accEvent(aEvent);
|
AccCaretMoveEvent* cm = downcast_accEvent(aEvent);
|
||||||
xpEvent = new xpcAccCaretMoveEvent(
|
xpEvent = new xpcAccCaretMoveEvent(
|
||||||
type, ToXPC(acc), ToXPCDocument(doc), node, fromUser,
|
type, ToXPC(acc), ToXPCDocument(doc), node, fromUser,
|
||||||
cm->GetCaretOffset(), cm->IsSelectionCollapsed(), cm->IsAtEndOfLine());
|
cm->GetCaretOffset(), cm->IsSelectionCollapsed(), cm->IsAtEndOfLine(),
|
||||||
|
cm->GetGranularity());
|
||||||
return xpEvent.forget();
|
return xpEvent.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -348,12 +348,14 @@ class AccCaretMoveEvent : public AccEvent {
|
||||||
public:
|
public:
|
||||||
AccCaretMoveEvent(LocalAccessible* aAccessible, int32_t aCaretOffset,
|
AccCaretMoveEvent(LocalAccessible* aAccessible, int32_t aCaretOffset,
|
||||||
bool aIsSelectionCollapsed, bool aIsAtEndOfLine,
|
bool aIsSelectionCollapsed, bool aIsAtEndOfLine,
|
||||||
|
int32_t aGranularity,
|
||||||
EIsFromUserInput aIsFromUserInput = eAutoDetect)
|
EIsFromUserInput aIsFromUserInput = eAutoDetect)
|
||||||
: AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aAccessible,
|
: AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aAccessible,
|
||||||
aIsFromUserInput),
|
aIsFromUserInput),
|
||||||
mCaretOffset(aCaretOffset),
|
mCaretOffset(aCaretOffset),
|
||||||
mIsSelectionCollapsed(aIsSelectionCollapsed),
|
mIsSelectionCollapsed(aIsSelectionCollapsed),
|
||||||
mIsAtEndOfLine(aIsAtEndOfLine) {}
|
mIsAtEndOfLine(aIsAtEndOfLine),
|
||||||
|
mGranularity(aGranularity) {}
|
||||||
virtual ~AccCaretMoveEvent() {}
|
virtual ~AccCaretMoveEvent() {}
|
||||||
|
|
||||||
// AccEvent
|
// AccEvent
|
||||||
|
@ -368,11 +370,14 @@ class AccCaretMoveEvent : public AccEvent {
|
||||||
bool IsSelectionCollapsed() const { return mIsSelectionCollapsed; }
|
bool IsSelectionCollapsed() const { return mIsSelectionCollapsed; }
|
||||||
bool IsAtEndOfLine() { return mIsAtEndOfLine; }
|
bool IsAtEndOfLine() { return mIsAtEndOfLine; }
|
||||||
|
|
||||||
|
int32_t GetGranularity() const { return mGranularity; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int32_t mCaretOffset;
|
int32_t mCaretOffset;
|
||||||
|
|
||||||
bool mIsSelectionCollapsed;
|
bool mIsSelectionCollapsed;
|
||||||
bool mIsAtEndOfLine;
|
bool mIsAtEndOfLine;
|
||||||
|
int32_t mGranularity;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -381,7 +386,8 @@ class AccCaretMoveEvent : public AccEvent {
|
||||||
class AccTextSelChangeEvent : public AccEvent {
|
class AccTextSelChangeEvent : public AccEvent {
|
||||||
public:
|
public:
|
||||||
AccTextSelChangeEvent(HyperTextAccessible* aTarget,
|
AccTextSelChangeEvent(HyperTextAccessible* aTarget,
|
||||||
dom::Selection* aSelection, int32_t aReason);
|
dom::Selection* aSelection, int32_t aReason,
|
||||||
|
int32_t aGranularity);
|
||||||
virtual ~AccTextSelChangeEvent();
|
virtual ~AccTextSelChangeEvent();
|
||||||
|
|
||||||
// AccEvent
|
// AccEvent
|
||||||
|
@ -397,6 +403,8 @@ class AccTextSelChangeEvent : public AccEvent {
|
||||||
*/
|
*/
|
||||||
bool IsCaretMoveOnly() const;
|
bool IsCaretMoveOnly() const;
|
||||||
|
|
||||||
|
int32_t GetGranularity() const { return mGranularity; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return selection ranges in document/control.
|
* Return selection ranges in document/control.
|
||||||
*/
|
*/
|
||||||
|
@ -405,6 +413,7 @@ class AccTextSelChangeEvent : public AccEvent {
|
||||||
private:
|
private:
|
||||||
RefPtr<dom::Selection> mSel;
|
RefPtr<dom::Selection> mSel;
|
||||||
int32_t mReason;
|
int32_t mReason;
|
||||||
|
int32_t mGranularity;
|
||||||
|
|
||||||
friend class EventQueue;
|
friend class EventQueue;
|
||||||
friend class SelectionManager;
|
friend class SelectionManager;
|
||||||
|
|
|
@ -104,10 +104,11 @@ void ProxyStateChangeEvent(RemoteAccessible* aTarget, uint64_t aState,
|
||||||
void ProxyFocusEvent(RemoteAccessible* aTarget,
|
void ProxyFocusEvent(RemoteAccessible* aTarget,
|
||||||
const LayoutDeviceIntRect& aCaretRect);
|
const LayoutDeviceIntRect& aCaretRect);
|
||||||
void ProxyCaretMoveEvent(RemoteAccessible* aTarget,
|
void ProxyCaretMoveEvent(RemoteAccessible* aTarget,
|
||||||
const LayoutDeviceIntRect& aCaretRect);
|
const LayoutDeviceIntRect& aCaretRect,
|
||||||
|
int32_t aGranularity);
|
||||||
#else
|
#else
|
||||||
void ProxyCaretMoveEvent(RemoteAccessible* aTarget, int32_t aOffset,
|
void ProxyCaretMoveEvent(RemoteAccessible* aTarget, int32_t aOffset,
|
||||||
bool aIsSelectionCollapsed);
|
bool aIsSelectionCollapsed, int32_t aGranularity);
|
||||||
#endif
|
#endif
|
||||||
void ProxyTextChangeEvent(RemoteAccessible* aTarget, const nsString& aStr,
|
void ProxyTextChangeEvent(RemoteAccessible* aTarget, const nsString& aStr,
|
||||||
int32_t aStart, uint32_t aLen, bool aIsInsert,
|
int32_t aStart, uint32_t aLen, bool aIsInsert,
|
||||||
|
|
|
@ -24,10 +24,12 @@ using namespace mozilla::a11y;
|
||||||
using mozilla::dom::Selection;
|
using mozilla::dom::Selection;
|
||||||
|
|
||||||
struct mozilla::a11y::SelData final {
|
struct mozilla::a11y::SelData final {
|
||||||
SelData(Selection* aSel, int32_t aReason) : mSel(aSel), mReason(aReason) {}
|
SelData(Selection* aSel, int32_t aReason, int32_t aGranularity)
|
||||||
|
: mSel(aSel), mReason(aReason), mGranularity(aGranularity) {}
|
||||||
|
|
||||||
RefPtr<Selection> mSel;
|
RefPtr<Selection> mSel;
|
||||||
int16_t mReason;
|
int16_t mReason;
|
||||||
|
int32_t mGranularity;
|
||||||
|
|
||||||
NS_INLINE_DECL_REFCOUNTING(SelData)
|
NS_INLINE_DECL_REFCOUNTING(SelData)
|
||||||
|
|
||||||
|
@ -148,17 +150,18 @@ void SelectionManager::ProcessTextSelChangeEvent(AccEvent* aEvent) {
|
||||||
selection->FocusOffset());
|
selection->FocusOffset());
|
||||||
mAccWithCaret = caretCntr;
|
mAccWithCaret = caretCntr;
|
||||||
if (mCaretOffset != -1) {
|
if (mCaretOffset != -1) {
|
||||||
RefPtr<AccCaretMoveEvent> caretMoveEvent = new AccCaretMoveEvent(
|
RefPtr<AccCaretMoveEvent> caretMoveEvent =
|
||||||
caretCntr, mCaretOffset, selection->IsCollapsed(),
|
new AccCaretMoveEvent(caretCntr, mCaretOffset, selection->IsCollapsed(),
|
||||||
caretCntr->IsCaretAtEndOfLine(), aEvent->FromUserInput());
|
caretCntr->IsCaretAtEndOfLine(),
|
||||||
|
event->GetGranularity(), aEvent->FromUserInput());
|
||||||
nsEventShell::FireEvent(caretMoveEvent);
|
nsEventShell::FireEvent(caretMoveEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
SelectionManager::NotifySelectionChanged(dom::Document* aDocument,
|
SelectionManager::NotifySelectionChanged(dom::Document* aDocument,
|
||||||
Selection* aSelection,
|
Selection* aSelection, int16_t aReason,
|
||||||
int16_t aReason) {
|
int32_t aAmount) {
|
||||||
if (NS_WARN_IF(!aDocument) || NS_WARN_IF(!aSelection)) {
|
if (NS_WARN_IF(!aDocument) || NS_WARN_IF(!aSelection)) {
|
||||||
return NS_ERROR_INVALID_ARG;
|
return NS_ERROR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
@ -175,7 +178,7 @@ SelectionManager::NotifySelectionChanged(dom::Document* aDocument,
|
||||||
// Selection manager has longer lifetime than any document accessible,
|
// Selection manager has longer lifetime than any document accessible,
|
||||||
// so that we are guaranteed that the notification is processed before
|
// so that we are guaranteed that the notification is processed before
|
||||||
// the selection manager is destroyed.
|
// the selection manager is destroyed.
|
||||||
RefPtr<SelData> selData = new SelData(aSelection, aReason);
|
RefPtr<SelData> selData = new SelData(aSelection, aReason, aAmount);
|
||||||
document->HandleNotification<SelectionManager, SelData>(
|
document->HandleNotification<SelectionManager, SelData>(
|
||||||
this, &SelectionManager::ProcessSelectionChanged, selData);
|
this, &SelectionManager::ProcessSelectionChanged, selData);
|
||||||
}
|
}
|
||||||
|
@ -211,8 +214,8 @@ void SelectionManager::ProcessSelectionChanged(SelData* aSelData) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selection->GetType() == SelectionType::eNormal) {
|
if (selection->GetType() == SelectionType::eNormal) {
|
||||||
RefPtr<AccEvent> event =
|
RefPtr<AccEvent> event = new AccTextSelChangeEvent(
|
||||||
new AccTextSelChangeEvent(text, selection, aSelData->mReason);
|
text, selection, aSelData->mReason, aSelData->mGranularity);
|
||||||
text->Document()->FireDelayedEvent(event);
|
text->Document()->FireDelayedEvent(event);
|
||||||
|
|
||||||
} else if (selection->GetType() == SelectionType::eSpellCheck) {
|
} else if (selection->GetType() == SelectionType::eSpellCheck) {
|
||||||
|
|
|
@ -934,9 +934,9 @@ nsresult LocalAccessible::HandleAccEvent(AccEvent* aEvent) {
|
||||||
}
|
}
|
||||||
case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED: {
|
case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED: {
|
||||||
AccCaretMoveEvent* event = downcast_accEvent(aEvent);
|
AccCaretMoveEvent* event = downcast_accEvent(aEvent);
|
||||||
ipcDoc->SendCaretMoveEvent(id, event->GetCaretOffset(),
|
ipcDoc->SendCaretMoveEvent(
|
||||||
event->IsSelectionCollapsed(),
|
id, event->GetCaretOffset(), event->IsSelectionCollapsed(),
|
||||||
event->IsAtEndOfLine());
|
event->IsAtEndOfLine(), event->GetGranularity());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case nsIAccessibleEvent::EVENT_TEXT_INSERTED:
|
case nsIAccessibleEvent::EVENT_TEXT_INSERTED:
|
||||||
|
|
|
@ -25,4 +25,9 @@ interface nsIAccessibleCaretMoveEvent: nsIAccessibleEvent
|
||||||
* Return true if the caret is at the end of a line.
|
* Return true if the caret is at the end of a line.
|
||||||
*/
|
*/
|
||||||
readonly attribute bool isAtEndOfLine;
|
readonly attribute bool isAtEndOfLine;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return caret move granularity.
|
||||||
|
*/
|
||||||
|
readonly attribute long granularity;
|
||||||
};
|
};
|
||||||
|
|
|
@ -341,7 +341,7 @@ mozilla::ipc::IPCResult DocAccessibleParent::RecvCaretMoveEvent(
|
||||||
const LayoutDeviceIntRect& aCaretRect,
|
const LayoutDeviceIntRect& aCaretRect,
|
||||||
#endif // defined (XP_WIN)
|
#endif // defined (XP_WIN)
|
||||||
const int32_t& aOffset, const bool& aIsSelectionCollapsed,
|
const int32_t& aOffset, const bool& aIsSelectionCollapsed,
|
||||||
const bool& aIsAtEndOfLine) {
|
const bool& aIsAtEndOfLine, const int32_t& aGranularity) {
|
||||||
if (mShutdown) {
|
if (mShutdown) {
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
|
@ -364,9 +364,9 @@ mozilla::ipc::IPCResult DocAccessibleParent::RecvCaretMoveEvent(
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(XP_WIN)
|
#if defined(XP_WIN)
|
||||||
ProxyCaretMoveEvent(proxy, aCaretRect);
|
ProxyCaretMoveEvent(proxy, aCaretRect, aGranularity);
|
||||||
#else
|
#else
|
||||||
ProxyCaretMoveEvent(proxy, aOffset, aIsSelectionCollapsed);
|
ProxyCaretMoveEvent(proxy, aOffset, aIsSelectionCollapsed, aGranularity);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!nsCoreUtils::AccEventObserversExist()) {
|
if (!nsCoreUtils::AccEventObserversExist()) {
|
||||||
|
@ -378,9 +378,9 @@ mozilla::ipc::IPCResult DocAccessibleParent::RecvCaretMoveEvent(
|
||||||
nsINode* node = nullptr;
|
nsINode* node = nullptr;
|
||||||
bool fromUser = true; // XXX fix me
|
bool fromUser = true; // XXX fix me
|
||||||
uint32_t type = nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED;
|
uint32_t type = nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED;
|
||||||
RefPtr<xpcAccCaretMoveEvent> event =
|
RefPtr<xpcAccCaretMoveEvent> event = new xpcAccCaretMoveEvent(
|
||||||
new xpcAccCaretMoveEvent(type, xpcAcc, doc, node, fromUser, aOffset,
|
type, xpcAcc, doc, node, fromUser, aOffset, aIsSelectionCollapsed,
|
||||||
aIsSelectionCollapsed, aIsAtEndOfLine);
|
aIsAtEndOfLine, aGranularity);
|
||||||
nsCoreUtils::DispatchAccEvent(std::move(event));
|
nsCoreUtils::DispatchAccEvent(std::move(event));
|
||||||
|
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
|
|
|
@ -108,7 +108,7 @@ class DocAccessibleParent : public RemoteAccessible,
|
||||||
const LayoutDeviceIntRect& aCaretRect,
|
const LayoutDeviceIntRect& aCaretRect,
|
||||||
#endif
|
#endif
|
||||||
const int32_t& aOffset, const bool& aIsSelectionCollapsed,
|
const int32_t& aOffset, const bool& aIsSelectionCollapsed,
|
||||||
const bool& aIsAtEndOfLine) final;
|
const bool& aIsAtEndOfLine, const int32_t& aGranularity) final;
|
||||||
|
|
||||||
virtual mozilla::ipc::IPCResult RecvTextChangeEvent(
|
virtual mozilla::ipc::IPCResult RecvTextChangeEvent(
|
||||||
const uint64_t& aID, const nsString& aStr, const int32_t& aStart,
|
const uint64_t& aID, const nsString& aStr, const int32_t& aStart,
|
||||||
|
|
|
@ -99,7 +99,8 @@ parent:
|
||||||
async HideEvent(uint64_t aRootID, bool aFromUser);
|
async HideEvent(uint64_t aRootID, bool aFromUser);
|
||||||
async StateChangeEvent(uint64_t aID, uint64_t aState, bool aEnabled);
|
async StateChangeEvent(uint64_t aID, uint64_t aState, bool aEnabled);
|
||||||
async CaretMoveEvent(uint64_t aID, int32_t aOffset,
|
async CaretMoveEvent(uint64_t aID, int32_t aOffset,
|
||||||
bool aIsSelectionCollapsed, bool aIsAtEndOfLine);
|
bool aIsSelectionCollapsed, bool aIsAtEndOfLine,
|
||||||
|
int32_t aGranularity);
|
||||||
async TextChangeEvent(uint64_t aID, nsString aStr, int32_t aStart, uint32_t aLen,
|
async TextChangeEvent(uint64_t aID, nsString aStr, int32_t aStart, uint32_t aLen,
|
||||||
bool aIsInsert, bool aFromUser);
|
bool aIsInsert, bool aFromUser);
|
||||||
async SelectionEvent(uint64_t aID, uint64_t aWidgetID, uint32_t aType);
|
async SelectionEvent(uint64_t aID, uint64_t aWidgetID, uint32_t aType);
|
||||||
|
|
|
@ -200,22 +200,26 @@ bool DocAccessibleChild::SendFocusEvent(const uint64_t& aID,
|
||||||
bool DocAccessibleChild::SendCaretMoveEvent(const uint64_t& aID,
|
bool DocAccessibleChild::SendCaretMoveEvent(const uint64_t& aID,
|
||||||
const int32_t& aOffset,
|
const int32_t& aOffset,
|
||||||
const bool& aIsSelectionCollapsed,
|
const bool& aIsSelectionCollapsed,
|
||||||
const bool& aIsAtEndOfLine) {
|
const bool& aIsAtEndOfLine,
|
||||||
|
const int32_t& aGranularity) {
|
||||||
return SendCaretMoveEvent(aID, GetCaretRectFor(aID), aOffset,
|
return SendCaretMoveEvent(aID, GetCaretRectFor(aID), aOffset,
|
||||||
aIsSelectionCollapsed, aIsAtEndOfLine);
|
aIsSelectionCollapsed, aIsAtEndOfLine,
|
||||||
|
aGranularity);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DocAccessibleChild::SendCaretMoveEvent(
|
bool DocAccessibleChild::SendCaretMoveEvent(
|
||||||
const uint64_t& aID, const LayoutDeviceIntRect& aCaretRect,
|
const uint64_t& aID, const LayoutDeviceIntRect& aCaretRect,
|
||||||
const int32_t& aOffset, const bool& aIsSelectionCollapsed,
|
const int32_t& aOffset, const bool& aIsSelectionCollapsed,
|
||||||
const bool& aIsAtEndOfLine) {
|
const bool& aIsAtEndOfLine, const int32_t& aGranularity) {
|
||||||
if (IsConstructedInParentProcess()) {
|
if (IsConstructedInParentProcess()) {
|
||||||
return PDocAccessibleChild::SendCaretMoveEvent(
|
return PDocAccessibleChild::SendCaretMoveEvent(
|
||||||
aID, aCaretRect, aOffset, aIsSelectionCollapsed, aIsAtEndOfLine);
|
aID, aCaretRect, aOffset, aIsSelectionCollapsed, aIsAtEndOfLine,
|
||||||
|
aGranularity);
|
||||||
}
|
}
|
||||||
|
|
||||||
PushDeferredEvent(MakeUnique<SerializedCaretMove>(
|
PushDeferredEvent(MakeUnique<SerializedCaretMove>(
|
||||||
this, aID, aCaretRect, aOffset, aIsSelectionCollapsed, aIsAtEndOfLine));
|
this, aID, aCaretRect, aOffset, aIsSelectionCollapsed, aIsAtEndOfLine,
|
||||||
|
aGranularity));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,12 +52,14 @@ class DocAccessibleChild : public DocAccessibleChildBase {
|
||||||
const bool& aEnabled);
|
const bool& aEnabled);
|
||||||
bool SendCaretMoveEvent(const uint64_t& aID, const int32_t& aOffset,
|
bool SendCaretMoveEvent(const uint64_t& aID, const int32_t& aOffset,
|
||||||
const bool& aIsSelectionCollapsed,
|
const bool& aIsSelectionCollapsed,
|
||||||
const bool& aIsAtEndOfLine);
|
const bool& aIsAtEndOfLine,
|
||||||
|
const int32_t& aGranularity);
|
||||||
bool SendCaretMoveEvent(const uint64_t& aID,
|
bool SendCaretMoveEvent(const uint64_t& aID,
|
||||||
const LayoutDeviceIntRect& aCaretRect,
|
const LayoutDeviceIntRect& aCaretRect,
|
||||||
const int32_t& aOffset,
|
const int32_t& aOffset,
|
||||||
const bool& aIsSelectionCollapsed,
|
const bool& aIsSelectionCollapsed,
|
||||||
const bool& aIsAtEndOfLine);
|
const bool& aIsAtEndOfLine,
|
||||||
|
const int32_t& aGranularity);
|
||||||
bool SendFocusEvent(const uint64_t& aID);
|
bool SendFocusEvent(const uint64_t& aID);
|
||||||
bool SendFocusEvent(const uint64_t& aID,
|
bool SendFocusEvent(const uint64_t& aID,
|
||||||
const LayoutDeviceIntRect& aCaretRect);
|
const LayoutDeviceIntRect& aCaretRect);
|
||||||
|
@ -175,17 +177,20 @@ class DocAccessibleChild : public DocAccessibleChildBase {
|
||||||
struct SerializedCaretMove final : public DeferredEvent {
|
struct SerializedCaretMove final : public DeferredEvent {
|
||||||
SerializedCaretMove(DocAccessibleChild* aTarget, uint64_t aID,
|
SerializedCaretMove(DocAccessibleChild* aTarget, uint64_t aID,
|
||||||
const LayoutDeviceIntRect& aCaretRect, int32_t aOffset,
|
const LayoutDeviceIntRect& aCaretRect, int32_t aOffset,
|
||||||
bool aIsSelectionCollapsed, bool aIsAtEndOfLine)
|
bool aIsSelectionCollapsed, bool aIsAtEndOfLine,
|
||||||
|
int32_t aGranularity)
|
||||||
: DeferredEvent(aTarget),
|
: DeferredEvent(aTarget),
|
||||||
mID(aID),
|
mID(aID),
|
||||||
mCaretRect(aCaretRect),
|
mCaretRect(aCaretRect),
|
||||||
mOffset(aOffset),
|
mOffset(aOffset),
|
||||||
mIsSelectionCollapsed(aIsSelectionCollapsed),
|
mIsSelectionCollapsed(aIsSelectionCollapsed),
|
||||||
mIsAtEndOfLine(aIsAtEndOfLine) {}
|
mIsAtEndOfLine(aIsAtEndOfLine),
|
||||||
|
mGranularity(aGranularity) {}
|
||||||
|
|
||||||
void Dispatch(DocAccessibleChild* aIPCDoc) override {
|
void Dispatch(DocAccessibleChild* aIPCDoc) override {
|
||||||
Unused << aIPCDoc->SendCaretMoveEvent(
|
Unused << aIPCDoc->SendCaretMoveEvent(mID, mCaretRect, mOffset,
|
||||||
mID, mCaretRect, mOffset, mIsSelectionCollapsed, mIsAtEndOfLine);
|
mIsSelectionCollapsed,
|
||||||
|
mIsAtEndOfLine, mGranularity);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t mID;
|
uint64_t mID;
|
||||||
|
@ -193,6 +198,7 @@ class DocAccessibleChild : public DocAccessibleChildBase {
|
||||||
int32_t mOffset;
|
int32_t mOffset;
|
||||||
bool mIsSelectionCollapsed;
|
bool mIsSelectionCollapsed;
|
||||||
bool mIsAtEndOfLine;
|
bool mIsAtEndOfLine;
|
||||||
|
int32_t mGranularity;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SerializedFocus final : public DeferredEvent {
|
struct SerializedFocus final : public DeferredEvent {
|
||||||
|
|
|
@ -70,7 +70,7 @@ parent:
|
||||||
async StateChangeEvent(uint64_t aID, uint64_t aState, bool aEnabled);
|
async StateChangeEvent(uint64_t aID, uint64_t aState, bool aEnabled);
|
||||||
async CaretMoveEvent(uint64_t aID, LayoutDeviceIntRect aCaretRect,
|
async CaretMoveEvent(uint64_t aID, LayoutDeviceIntRect aCaretRect,
|
||||||
int32_t aOffset, bool aIsAtEndOfLine,
|
int32_t aOffset, bool aIsAtEndOfLine,
|
||||||
bool aIsSelectionCollapsed);
|
bool aIsSelectionCollapsed, int32_t aGranularity);
|
||||||
async TextChangeEvent(uint64_t aID, nsString aStr, int32_t aStart, uint32_t aLen,
|
async TextChangeEvent(uint64_t aID, nsString aStr, int32_t aStart, uint32_t aLen,
|
||||||
bool aIsInsert, bool aFromUser);
|
bool aIsInsert, bool aFromUser);
|
||||||
sync SyncTextChangeEvent(uint64_t aID, nsString aStr, int32_t aStart,
|
sync SyncTextChangeEvent(uint64_t aID, nsString aStr, int32_t aStart,
|
||||||
|
|
|
@ -226,7 +226,9 @@ nsresult AccessibleWrap::HandleAccEvent(AccEvent* aEvent) {
|
||||||
int32_t caretOffset = event->GetCaretOffset();
|
int32_t caretOffset = event->GetCaretOffset();
|
||||||
MOXTextMarkerDelegate* delegate =
|
MOXTextMarkerDelegate* delegate =
|
||||||
[MOXTextMarkerDelegate getOrCreateForDoc:aEvent->Document()];
|
[MOXTextMarkerDelegate getOrCreateForDoc:aEvent->Document()];
|
||||||
[delegate setCaretOffset:eventTarget at:caretOffset];
|
[delegate setCaretOffset:eventTarget
|
||||||
|
at:caretOffset
|
||||||
|
moveGranularity:event->GetGranularity()];
|
||||||
if (event->IsSelectionCollapsed()) {
|
if (event->IsSelectionCollapsed()) {
|
||||||
// If the selection is collapsed, invalidate our text selection cache.
|
// If the selection is collapsed, invalidate our text selection cache.
|
||||||
[delegate setSelectionFrom:eventTarget
|
[delegate setSelectionFrom:eventTarget
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
AXTextMarkerRangeRef mSelection;
|
AXTextMarkerRangeRef mSelection;
|
||||||
AXTextMarkerRef mCaret;
|
AXTextMarkerRef mCaret;
|
||||||
AXTextMarkerRef mPrevCaret;
|
AXTextMarkerRef mPrevCaret;
|
||||||
|
int32_t mCaretMoveGranularity;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (id)getOrCreateForDoc:(mozilla::a11y::Accessible*)aDoc;
|
+ (id)getOrCreateForDoc:(mozilla::a11y::Accessible*)aDoc;
|
||||||
|
@ -30,7 +31,9 @@
|
||||||
to:(mozilla::a11y::Accessible*)endContainer
|
to:(mozilla::a11y::Accessible*)endContainer
|
||||||
at:(int32_t)endOffset;
|
at:(int32_t)endOffset;
|
||||||
|
|
||||||
- (void)setCaretOffset:(mozilla::a11y::Accessible*)container at:(int32_t)offset;
|
- (void)setCaretOffset:(mozilla::a11y::Accessible*)container
|
||||||
|
at:(int32_t)offset
|
||||||
|
moveGranularity:(int32_t)granularity;
|
||||||
|
|
||||||
- (NSDictionary*)selectionChangeInfo;
|
- (NSDictionary*)selectionChangeInfo;
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include "mozAccessible.h"
|
#include "mozAccessible.h"
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
|
#include "nsISelectionListener.h"
|
||||||
|
|
||||||
using namespace mozilla::a11y;
|
using namespace mozilla::a11y;
|
||||||
|
|
||||||
|
@ -52,6 +53,8 @@ static nsTHashMap<nsPtrHashKey<mozilla::a11y::Accessible>,
|
||||||
mGeckoDocAccessible = aDoc;
|
mGeckoDocAccessible = aDoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mCaretMoveGranularity = nsISelectionListener::NO_AMOUNT;
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,11 +79,14 @@ static nsTHashMap<nsPtrHashKey<mozilla::a11y::Accessible>,
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setCaretOffset:(mozilla::a11y::Accessible*)container
|
- (void)setCaretOffset:(mozilla::a11y::Accessible*)container
|
||||||
at:(int32_t)offset {
|
at:(int32_t)offset
|
||||||
|
moveGranularity:(int32_t)granularity {
|
||||||
GeckoTextMarker caretMarker(container, offset);
|
GeckoTextMarker caretMarker(container, offset);
|
||||||
|
|
||||||
mPrevCaret = mCaret;
|
mPrevCaret = mCaret;
|
||||||
mCaret = caretMarker.CreateAXTextMarker();
|
mCaret = caretMarker.CreateAXTextMarker();
|
||||||
|
mCaretMoveGranularity = granularity;
|
||||||
|
|
||||||
CFRetain(mCaret);
|
CFRetain(mCaret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,21 +152,43 @@ static nsTHashMap<nsPtrHashKey<mozilla::a11y::Accessible>,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isForward = prevCaretMarker < caretMarker;
|
bool isForward = prevCaretMarker < caretMarker;
|
||||||
uint32_t deltaLength =
|
int direction = isForward ? AXTextSelectionDirectionNext
|
||||||
GeckoTextMarkerRange(isForward ? prevCaretMarker : caretMarker,
|
: AXTextSelectionDirectionPrevious;
|
||||||
isForward ? caretMarker : prevCaretMarker)
|
|
||||||
.Length();
|
int32_t granularity = AXTextSelectionGranularityUnknown;
|
||||||
|
switch (mCaretMoveGranularity) {
|
||||||
|
case nsISelectionListener::CHARACTER_AMOUNT:
|
||||||
|
case nsISelectionListener::CLUSTER_AMOUNT:
|
||||||
|
granularity = AXTextSelectionGranularityCharacter;
|
||||||
|
break;
|
||||||
|
case nsISelectionListener::WORD_AMOUNT:
|
||||||
|
case nsISelectionListener::WORDNOSPACE_AMOUNT:
|
||||||
|
granularity = AXTextSelectionGranularityWord;
|
||||||
|
break;
|
||||||
|
case nsISelectionListener::LINE_AMOUNT:
|
||||||
|
granularity = AXTextSelectionGranularityLine;
|
||||||
|
break;
|
||||||
|
case nsISelectionListener::BEGINLINE_AMOUNT:
|
||||||
|
direction = AXTextSelectionDirectionBeginning;
|
||||||
|
granularity = AXTextSelectionGranularityLine;
|
||||||
|
break;
|
||||||
|
case nsISelectionListener::ENDLINE_AMOUNT:
|
||||||
|
direction = AXTextSelectionDirectionEnd;
|
||||||
|
granularity = AXTextSelectionGranularityLine;
|
||||||
|
break;
|
||||||
|
case nsISelectionListener::PARAGRAPH_AMOUNT:
|
||||||
|
granularity = AXTextSelectionGranularityParagraph;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Determine selection direction with marker comparison.
|
// Determine selection direction with marker comparison.
|
||||||
// If the delta between the two markers is more than one, consider it
|
// If the delta between the two markers is more than one, consider it
|
||||||
// a word. Not accurate, but good enough for VO.
|
// a word. Not accurate, but good enough for VO.
|
||||||
[info addEntriesFromDictionary:@{
|
[info addEntriesFromDictionary:@{
|
||||||
@"AXTextSelectionDirection" : isForward
|
@"AXTextSelectionDirection" : @(direction),
|
||||||
? @(AXTextSelectionDirectionNext)
|
@"AXTextSelectionGranularity" : @(granularity)
|
||||||
: @(AXTextSelectionDirectionPrevious),
|
|
||||||
@"AXTextSelectionGranularity" : deltaLength == 1
|
|
||||||
? @(AXTextSelectionGranularityCharacter)
|
|
||||||
: @(AXTextSelectionGranularityWord)
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
|
|
|
@ -111,11 +111,11 @@ void ProxyStateChangeEvent(RemoteAccessible* aProxy, uint64_t aState,
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProxyCaretMoveEvent(RemoteAccessible* aTarget, int32_t aOffset,
|
void ProxyCaretMoveEvent(RemoteAccessible* aTarget, int32_t aOffset,
|
||||||
bool aIsSelectionCollapsed) {
|
bool aIsSelectionCollapsed, int32_t aGranularity) {
|
||||||
mozAccessible* wrapper = GetNativeFromGeckoAccessible(aTarget);
|
mozAccessible* wrapper = GetNativeFromGeckoAccessible(aTarget);
|
||||||
MOXTextMarkerDelegate* delegate =
|
MOXTextMarkerDelegate* delegate =
|
||||||
[MOXTextMarkerDelegate getOrCreateForDoc:aTarget->Document()];
|
[MOXTextMarkerDelegate getOrCreateForDoc:aTarget->Document()];
|
||||||
[delegate setCaretOffset:aTarget at:aOffset];
|
[delegate setCaretOffset:aTarget at:aOffset moveGranularity:aGranularity];
|
||||||
if (aIsSelectionCollapsed) {
|
if (aIsSelectionCollapsed) {
|
||||||
// If selection is collapsed, invalidate selection.
|
// If selection is collapsed, invalidate selection.
|
||||||
[delegate setSelectionFrom:aTarget at:aOffset to:aTarget at:aOffset];
|
[delegate setSelectionFrom:aTarget at:aOffset to:aTarget at:aOffset];
|
||||||
|
|
|
@ -22,7 +22,8 @@ void a11y::ProxyEvent(RemoteAccessible*, uint32_t) {}
|
||||||
void a11y::ProxyStateChangeEvent(RemoteAccessible*, uint64_t, bool) {}
|
void a11y::ProxyStateChangeEvent(RemoteAccessible*, uint64_t, bool) {}
|
||||||
|
|
||||||
void a11y::ProxyCaretMoveEvent(RemoteAccessible* aTarget, int32_t aOffset,
|
void a11y::ProxyCaretMoveEvent(RemoteAccessible* aTarget, int32_t aOffset,
|
||||||
bool aIsSelectionCollapsed) {}
|
bool aIsSelectionCollapsed,
|
||||||
|
int32_t aGranularity) {}
|
||||||
|
|
||||||
void a11y::ProxyTextChangeEvent(RemoteAccessible*, const nsString&, int32_t,
|
void a11y::ProxyTextChangeEvent(RemoteAccessible*, const nsString&, int32_t,
|
||||||
uint32_t, bool, bool) {}
|
uint32_t, bool, bool) {}
|
||||||
|
|
|
@ -8,6 +8,7 @@ support-files =
|
||||||
environment =
|
environment =
|
||||||
A11YLOG=doclifecycle,events,notifications
|
A11YLOG=doclifecycle,events,notifications
|
||||||
|
|
||||||
|
[browser_test_caret_move_granularity.js]
|
||||||
[browser_test_docload.js]
|
[browser_test_docload.js]
|
||||||
skip-if = e10s
|
skip-if = e10s
|
||||||
[browser_test_scrolling.js]
|
[browser_test_scrolling.js]
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const CLUSTER_AMOUNT = Ci.nsISelectionListener.CLUSTER_AMOUNT;
|
||||||
|
const WORD_AMOUNT = Ci.nsISelectionListener.WORD_AMOUNT;
|
||||||
|
const LINE_AMOUNT = Ci.nsISelectionListener.LINE_AMOUNT;
|
||||||
|
const BEGINLINE_AMOUNT = Ci.nsISelectionListener.BEGINLINE_AMOUNT;
|
||||||
|
const ENDLINE_AMOUNT = Ci.nsISelectionListener.ENDLINE_AMOUNT;
|
||||||
|
|
||||||
|
const isMac = AppConstants.platform == "macosx";
|
||||||
|
|
||||||
|
function matchCaretMoveEvent(id, caretOffset) {
|
||||||
|
return evt => {
|
||||||
|
evt.QueryInterface(nsIAccessibleCaretMoveEvent);
|
||||||
|
return (
|
||||||
|
getAccessibleDOMNodeID(evt.accessible) == id &&
|
||||||
|
evt.caretOffset == caretOffset
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
addAccessibleTask(
|
||||||
|
`<textarea id="textarea" style="scrollbar-width: none;" cols="15">` +
|
||||||
|
`one two three four five six seven eight` +
|
||||||
|
`</textarea>`,
|
||||||
|
async function(browser, accDoc) {
|
||||||
|
const textarea = findAccessibleChildByID(accDoc, "textarea");
|
||||||
|
let caretMoved = waitForEvent(
|
||||||
|
EVENT_TEXT_CARET_MOVED,
|
||||||
|
matchCaretMoveEvent("textarea", 0)
|
||||||
|
);
|
||||||
|
textarea.takeFocus();
|
||||||
|
let evt = await caretMoved;
|
||||||
|
evt.QueryInterface(nsIAccessibleCaretMoveEvent);
|
||||||
|
ok(!evt.isAtEndOfLine, "Caret is not at end of line");
|
||||||
|
|
||||||
|
caretMoved = waitForEvent(
|
||||||
|
EVENT_TEXT_CARET_MOVED,
|
||||||
|
matchCaretMoveEvent("textarea", 1)
|
||||||
|
);
|
||||||
|
EventUtils.synthesizeKey("KEY_ArrowRight");
|
||||||
|
evt = await caretMoved;
|
||||||
|
evt.QueryInterface(nsIAccessibleCaretMoveEvent);
|
||||||
|
ok(!evt.isAtEndOfLine, "Caret is not at end of line");
|
||||||
|
is(evt.granularity, CLUSTER_AMOUNT, "Caret moved by cluster");
|
||||||
|
|
||||||
|
caretMoved = waitForEvent(
|
||||||
|
EVENT_TEXT_CARET_MOVED,
|
||||||
|
matchCaretMoveEvent("textarea", 15)
|
||||||
|
);
|
||||||
|
EventUtils.synthesizeKey("KEY_ArrowDown");
|
||||||
|
evt = await caretMoved;
|
||||||
|
evt.QueryInterface(nsIAccessibleCaretMoveEvent);
|
||||||
|
todo(!evt.isAtEndOfLine, "Caret is not at end of line");
|
||||||
|
is(evt.granularity, LINE_AMOUNT, "Caret moved by line");
|
||||||
|
|
||||||
|
caretMoved = waitForEvent(
|
||||||
|
EVENT_TEXT_CARET_MOVED,
|
||||||
|
matchCaretMoveEvent("textarea", 14)
|
||||||
|
);
|
||||||
|
if (isMac) {
|
||||||
|
EventUtils.synthesizeKey("KEY_ArrowLeft", { metaKey: true });
|
||||||
|
} else {
|
||||||
|
EventUtils.synthesizeKey("KEY_Home");
|
||||||
|
}
|
||||||
|
evt = await caretMoved;
|
||||||
|
evt.QueryInterface(nsIAccessibleCaretMoveEvent);
|
||||||
|
ok(!evt.isAtEndOfLine, "Caret is not at end of line");
|
||||||
|
is(evt.granularity, BEGINLINE_AMOUNT, "Caret moved to line start");
|
||||||
|
|
||||||
|
caretMoved = waitForEvent(
|
||||||
|
EVENT_TEXT_CARET_MOVED,
|
||||||
|
matchCaretMoveEvent("textarea", 28)
|
||||||
|
);
|
||||||
|
if (isMac) {
|
||||||
|
EventUtils.synthesizeKey("KEY_ArrowRight", { metaKey: true });
|
||||||
|
} else {
|
||||||
|
EventUtils.synthesizeKey("KEY_End");
|
||||||
|
}
|
||||||
|
evt = await caretMoved;
|
||||||
|
evt.QueryInterface(nsIAccessibleCaretMoveEvent);
|
||||||
|
ok(evt.isAtEndOfLine, "Caret is at end of line");
|
||||||
|
is(evt.granularity, ENDLINE_AMOUNT, "Caret moved to line end");
|
||||||
|
|
||||||
|
caretMoved = waitForEvent(
|
||||||
|
EVENT_TEXT_CARET_MOVED,
|
||||||
|
matchCaretMoveEvent("textarea", 24)
|
||||||
|
);
|
||||||
|
if (isMac) {
|
||||||
|
EventUtils.synthesizeKey("KEY_ArrowLeft", { altKey: true });
|
||||||
|
} else {
|
||||||
|
EventUtils.synthesizeKey("KEY_ArrowLeft", { ctrlKey: true });
|
||||||
|
}
|
||||||
|
evt = await caretMoved;
|
||||||
|
evt.QueryInterface(nsIAccessibleCaretMoveEvent);
|
||||||
|
ok(!evt.isAtEndOfLine, "Caret is not at end of line");
|
||||||
|
is(evt.granularity, WORD_AMOUNT, "Caret moved by word");
|
||||||
|
}
|
||||||
|
);
|
|
@ -224,7 +224,7 @@ async function synthKeyAndTestValueChanged(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function focusIntoInputAndType(accDoc, inputId, innerContainerId) {
|
async function focusIntoInput(accDoc, inputId, innerContainerId) {
|
||||||
let selectionId = innerContainerId ? innerContainerId : inputId;
|
let selectionId = innerContainerId ? innerContainerId : inputId;
|
||||||
let input = getNativeInterface(accDoc, inputId);
|
let input = getNativeInterface(accDoc, inputId);
|
||||||
ok(!input.getAttributeValue("AXFocused"), "input is not focused");
|
ok(!input.getAttributeValue("AXFocused"), "input is not focused");
|
||||||
|
@ -249,6 +249,11 @@ async function focusIntoInputAndType(accDoc, inputId, innerContainerId) {
|
||||||
]);
|
]);
|
||||||
input.setAttributeValue("AXFocused", true);
|
input.setAttributeValue("AXFocused", true);
|
||||||
await events;
|
await events;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function focusIntoInputAndType(accDoc, inputId, innerContainerId) {
|
||||||
|
let selectionId = innerContainerId ? innerContainerId : inputId;
|
||||||
|
await focusIntoInput(accDoc, inputId, innerContainerId);
|
||||||
|
|
||||||
async function testTextInput(
|
async function testTextInput(
|
||||||
synthKey,
|
synthKey,
|
||||||
|
@ -337,14 +342,14 @@ async function focusIntoInputAndType(accDoc, inputId, innerContainerId) {
|
||||||
{ AXTextStateChangeType: AXTextStateChangeTypeSelectionMove }
|
{ AXTextStateChangeType: AXTextStateChangeTypeSelectionMove }
|
||||||
);
|
);
|
||||||
await synthKeyAndTestSelectionChanged(
|
await synthKeyAndTestSelectionChanged(
|
||||||
"KEY_Home",
|
"KEY_ArrowLeft",
|
||||||
{ shiftKey: true },
|
{ shiftKey: true, metaKey: true },
|
||||||
selectionId,
|
selectionId,
|
||||||
"hello ",
|
"hello ",
|
||||||
{
|
{
|
||||||
AXTextStateChangeType: AXTextStateChangeTypeSelectionExtend,
|
AXTextStateChangeType: AXTextStateChangeTypeSelectionExtend,
|
||||||
AXTextSelectionDirection: AXTextSelectionDirectionPrevious,
|
AXTextSelectionDirection: AXTextSelectionDirectionBeginning,
|
||||||
AXTextSelectionGranularity: AXTextSelectionGranularityWord,
|
AXTextSelectionGranularity: AXTextSelectionGranularityLine,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
await synthKeyAndTestSelectionChanged(
|
await synthKeyAndTestSelectionChanged(
|
||||||
|
@ -372,7 +377,8 @@ addAccessibleTask(
|
||||||
`<a href="#">link</a> <input id="input">`,
|
`<a href="#">link</a> <input id="input">`,
|
||||||
async (browser, accDoc) => {
|
async (browser, accDoc) => {
|
||||||
await focusIntoInputAndType(accDoc, "input");
|
await focusIntoInputAndType(accDoc, "input");
|
||||||
}
|
},
|
||||||
|
{ topLevel: true, iframe: true, remoteIframe: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
// Test content editable
|
// Test content editable
|
||||||
|
@ -390,15 +396,6 @@ addAccessibleTask(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// Test text input in iframe
|
|
||||||
addAccessibleTask(
|
|
||||||
`<a href="#">link</a> <input id="input">`,
|
|
||||||
async (browser, accDoc) => {
|
|
||||||
await focusIntoInputAndType(accDoc, "input");
|
|
||||||
},
|
|
||||||
{ iframe: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
// Test input that gets role::EDITCOMBOBOX
|
// Test input that gets role::EDITCOMBOBOX
|
||||||
addAccessibleTask(`<input type="text" id="box">`, async (browser, accDoc) => {
|
addAccessibleTask(`<input type="text" id="box">`, async (browser, accDoc) => {
|
||||||
const box = getNativeInterface(accDoc, "box");
|
const box = getNativeInterface(accDoc, "box");
|
||||||
|
@ -410,3 +407,48 @@ addAccessibleTask(`<input type="text" id="box">`, async (browser, accDoc) => {
|
||||||
);
|
);
|
||||||
await focusIntoInputAndType(accDoc, "box");
|
await focusIntoInputAndType(accDoc, "box");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Test multiline caret control in a text area
|
||||||
|
addAccessibleTask(
|
||||||
|
`<textarea id="input" cols="15">one two three four five six seven eight</textarea>`,
|
||||||
|
async (browser, accDoc) => {
|
||||||
|
await focusIntoInput(accDoc, "input");
|
||||||
|
|
||||||
|
await synthKeyAndTestSelectionChanged("KEY_ArrowRight", null, "input", "", {
|
||||||
|
AXTextStateChangeType: AXTextStateChangeTypeSelectionMove,
|
||||||
|
AXTextSelectionDirection: AXTextSelectionDirectionNext,
|
||||||
|
AXTextSelectionGranularity: AXTextSelectionGranularityCharacter,
|
||||||
|
});
|
||||||
|
|
||||||
|
await synthKeyAndTestSelectionChanged("KEY_ArrowDown", null, "input", "", {
|
||||||
|
AXTextStateChangeType: AXTextStateChangeTypeSelectionMove,
|
||||||
|
AXTextSelectionDirection: AXTextSelectionDirectionNext,
|
||||||
|
AXTextSelectionGranularity: AXTextSelectionGranularityLine,
|
||||||
|
});
|
||||||
|
|
||||||
|
await synthKeyAndTestSelectionChanged(
|
||||||
|
"KEY_ArrowLeft",
|
||||||
|
{ metaKey: true },
|
||||||
|
"input",
|
||||||
|
"",
|
||||||
|
{
|
||||||
|
AXTextStateChangeType: AXTextStateChangeTypeSelectionMove,
|
||||||
|
AXTextSelectionDirection: AXTextSelectionDirectionBeginning,
|
||||||
|
AXTextSelectionGranularity: AXTextSelectionGranularityLine,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await synthKeyAndTestSelectionChanged(
|
||||||
|
"KEY_ArrowRight",
|
||||||
|
{ metaKey: true },
|
||||||
|
"input",
|
||||||
|
"",
|
||||||
|
{
|
||||||
|
AXTextStateChangeType: AXTextStateChangeTypeSelectionMove,
|
||||||
|
AXTextSelectionDirection: AXTextSelectionDirectionEnd,
|
||||||
|
AXTextSelectionGranularity: AXTextSelectionGranularityLine,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
{ topLevel: true, iframe: true, remoteIframe: true }
|
||||||
|
);
|
||||||
|
|
|
@ -10,7 +10,9 @@
|
||||||
AXTextStateChangeTypeSelectionExtend, AXTextSelectionDirectionUnknown,
|
AXTextStateChangeTypeSelectionExtend, AXTextSelectionDirectionUnknown,
|
||||||
AXTextSelectionDirectionPrevious, AXTextSelectionDirectionNext,
|
AXTextSelectionDirectionPrevious, AXTextSelectionDirectionNext,
|
||||||
AXTextSelectionDirectionDiscontiguous, AXTextSelectionGranularityUnknown,
|
AXTextSelectionDirectionDiscontiguous, AXTextSelectionGranularityUnknown,
|
||||||
AXTextSelectionGranularityCharacter, AXTextSelectionGranularityWord */
|
AXTextSelectionDirectionBeginning, AXTextSelectionDirectionEnd,
|
||||||
|
AXTextSelectionGranularityCharacter, AXTextSelectionGranularityWord,
|
||||||
|
AXTextSelectionGranularityLine */
|
||||||
|
|
||||||
// Load the shared-head file first.
|
// Load the shared-head file first.
|
||||||
/* import-globals-from ../shared-head.js */
|
/* import-globals-from ../shared-head.js */
|
||||||
|
@ -37,6 +39,8 @@ const AXTextEditTypeTyping = 3;
|
||||||
|
|
||||||
// AXTextSelectionDirection enum values
|
// AXTextSelectionDirection enum values
|
||||||
const AXTextSelectionDirectionUnknown = 0;
|
const AXTextSelectionDirectionUnknown = 0;
|
||||||
|
const AXTextSelectionDirectionBeginning = 1;
|
||||||
|
const AXTextSelectionDirectionEnd = 2;
|
||||||
const AXTextSelectionDirectionPrevious = 3;
|
const AXTextSelectionDirectionPrevious = 3;
|
||||||
const AXTextSelectionDirectionNext = 4;
|
const AXTextSelectionDirectionNext = 4;
|
||||||
const AXTextSelectionDirectionDiscontiguous = 5;
|
const AXTextSelectionDirectionDiscontiguous = 5;
|
||||||
|
@ -45,6 +49,7 @@ const AXTextSelectionDirectionDiscontiguous = 5;
|
||||||
const AXTextSelectionGranularityUnknown = 0;
|
const AXTextSelectionGranularityUnknown = 0;
|
||||||
const AXTextSelectionGranularityCharacter = 1;
|
const AXTextSelectionGranularityCharacter = 1;
|
||||||
const AXTextSelectionGranularityWord = 2;
|
const AXTextSelectionGranularityWord = 2;
|
||||||
|
const AXTextSelectionGranularityLine = 3;
|
||||||
|
|
||||||
function getNativeInterface(accDoc, id) {
|
function getNativeInterface(accDoc, id) {
|
||||||
return findAccessibleChildByID(accDoc, id).nativeInterface.QueryInterface(
|
return findAccessibleChildByID(accDoc, id).nativeInterface.QueryInterface(
|
||||||
|
|
|
@ -172,7 +172,8 @@ void a11y::ProxyFocusEvent(RemoteAccessible* aTarget,
|
||||||
}
|
}
|
||||||
|
|
||||||
void a11y::ProxyCaretMoveEvent(RemoteAccessible* aTarget,
|
void a11y::ProxyCaretMoveEvent(RemoteAccessible* aTarget,
|
||||||
const LayoutDeviceIntRect& aCaretRect) {
|
const LayoutDeviceIntRect& aCaretRect,
|
||||||
|
int32_t aGranularity) {
|
||||||
AccessibleWrap::UpdateSystemCaretFor(aTarget, aCaretRect);
|
AccessibleWrap::UpdateSystemCaretFor(aTarget, aCaretRect);
|
||||||
MsaaAccessible::FireWinEvent(aTarget,
|
MsaaAccessible::FireWinEvent(aTarget,
|
||||||
nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED);
|
nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED);
|
||||||
|
|
|
@ -3198,6 +3198,8 @@ void Selection::NotifySelectionListeners() {
|
||||||
reason |= nsISelectionListener::JS_REASON;
|
reason |= nsISelectionListener::JS_REASON;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t amount = static_cast<int32_t>(frameSelection->GetCaretMoveAmount());
|
||||||
|
|
||||||
if (mNotifyAutoCopy) {
|
if (mNotifyAutoCopy) {
|
||||||
AutoCopyListener::OnSelectionChange(doc, *this, reason);
|
AutoCopyListener::OnSelectionChange(doc, *this, reason);
|
||||||
}
|
}
|
||||||
|
@ -3218,7 +3220,7 @@ void Selection::NotifySelectionListeners() {
|
||||||
//
|
//
|
||||||
// This can go away once
|
// This can go away once
|
||||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1620312 is fixed.
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=1620312 is fixed.
|
||||||
MOZ_KnownLive(listener)->NotifySelectionChanged(doc, this, reason);
|
MOZ_KnownLive(listener)->NotifySelectionChanged(doc, this, reason, amount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,21 @@ interface nsISelectionListener : nsISupports
|
||||||
// of Selection API or Range API.
|
// of Selection API or Range API.
|
||||||
const short JS_REASON=256;
|
const short JS_REASON=256;
|
||||||
|
|
||||||
|
// Values of nsSelectionAmount.
|
||||||
|
// Reflects the granularity in which the selection caret has moved.
|
||||||
|
const long CHARACTER_AMOUNT = 0;
|
||||||
|
const long CLUSTER_AMOUNT = 1;
|
||||||
|
const long WORD_AMOUNT = 2;
|
||||||
|
const long WORDNOSPACE_AMOUNT = 3;
|
||||||
|
const long LINE_AMOUNT = 4;
|
||||||
|
const long BEGINLINE_AMOUNT = 5;
|
||||||
|
const long ENDLINE_AMOUNT = 6;
|
||||||
|
const long NO_AMOUNT = 7;
|
||||||
|
const long PARAGRAPH_AMOUNT = 8;
|
||||||
|
|
||||||
[can_run_script]
|
[can_run_script]
|
||||||
void notifySelectionChanged(in Document doc, in Selection sel,
|
void notifySelectionChanged(in Document doc, in Selection sel,
|
||||||
in short reason);
|
in short reason, in long amount);
|
||||||
};
|
};
|
||||||
|
|
||||||
%{C++
|
%{C++
|
||||||
|
|
|
@ -195,18 +195,12 @@ nsresult CamerasParent::DispatchToVideoCaptureThread(RefPtr<Runnable> event) {
|
||||||
// There's a potential deadlock because the sThreadMonitor is likely
|
// There's a potential deadlock because the sThreadMonitor is likely
|
||||||
// to be taken already.
|
// to be taken already.
|
||||||
MonitorAutoLock lock(*sThreadMonitor);
|
MonitorAutoLock lock(*sThreadMonitor);
|
||||||
MOZ_ASSERT(!sVideoCaptureThread ||
|
if (!sVideoCaptureThread) {
|
||||||
sVideoCaptureThread->thread_id() != PlatformThread::CurrentId());
|
LOG("Can't dispatch to video capture thread: thread not present");
|
||||||
|
|
||||||
while (mChildIsAlive && mWebRTCAlive &&
|
|
||||||
(!sVideoCaptureThread || !sVideoCaptureThread->IsRunning())) {
|
|
||||||
sThreadMonitor->Wait();
|
|
||||||
}
|
|
||||||
if (!sVideoCaptureThread || !sVideoCaptureThread->IsRunning()) {
|
|
||||||
LOG("Can't dispatch to video capture thread: thread not present or not "
|
|
||||||
"running");
|
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
MOZ_ASSERT(sVideoCaptureThread->thread_id() != PlatformThread::CurrentId());
|
||||||
|
|
||||||
sVideoCaptureThread->message_loop()->PostTask(event.forget());
|
sVideoCaptureThread->message_loop()->PostTask(event.forget());
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -230,9 +224,7 @@ void CamerasParent::StopVideoCapture() {
|
||||||
}
|
}
|
||||||
nsresult rv = NS_DispatchToMainThread(NewRunnableFrom([self, thread]() {
|
nsresult rv = NS_DispatchToMainThread(NewRunnableFrom([self, thread]() {
|
||||||
if (thread) {
|
if (thread) {
|
||||||
if (thread->IsRunning()) {
|
thread->Stop();
|
||||||
thread->Stop();
|
|
||||||
}
|
|
||||||
delete thread;
|
delete thread;
|
||||||
}
|
}
|
||||||
nsresult rv = MustGetShutdownBarrier()->RemoveBlocker(self);
|
nsresult rv = MustGetShutdownBarrier()->RemoveBlocker(self);
|
||||||
|
@ -1088,47 +1080,50 @@ NS_IMETHODIMP CamerasParent::BlockShutdown(nsIAsyncShutdownClient*) {
|
||||||
CamerasParent::CamerasParent()
|
CamerasParent::CamerasParent()
|
||||||
: mName(GetNewName()),
|
: mName(GetNewName()),
|
||||||
mShmemPool(CaptureEngine::MaxEngine),
|
mShmemPool(CaptureEngine::MaxEngine),
|
||||||
|
mPBackgroundEventTarget(GetCurrentSerialEventTarget()),
|
||||||
mChildIsAlive(true),
|
mChildIsAlive(true),
|
||||||
mDestroyed(false),
|
mDestroyed(false),
|
||||||
mWebRTCAlive(true) {
|
mWebRTCAlive(true) {
|
||||||
|
MOZ_ASSERT(mPBackgroundEventTarget != nullptr,
|
||||||
|
"GetCurrentThreadEventTarget failed");
|
||||||
LOG("CamerasParent: %p", this);
|
LOG("CamerasParent: %p", this);
|
||||||
StaticMutexAutoLock slock(sMutex);
|
StaticMutexAutoLock slock(sMutex);
|
||||||
|
|
||||||
if (sNumOfCamerasParents++ == 0) {
|
if (sNumOfCamerasParents++ == 0) {
|
||||||
sThreadMonitor = new Monitor("CamerasParent::sThreadMonitor");
|
sThreadMonitor = new Monitor("CamerasParent::sThreadMonitor");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mPBackgroundEventTarget = GetCurrentSerialEventTarget();
|
ipc::IPCResult CamerasParent::RecvPCamerasConstructor() {
|
||||||
MOZ_ASSERT(mPBackgroundEventTarget != nullptr,
|
ipc::AssertIsOnBackgroundThread();
|
||||||
"GetCurrentThreadEventTarget failed");
|
|
||||||
|
// Don't dispatch from the constructor a runnable that may toggle the
|
||||||
|
// reference count, because the IPC thread does not get a reference until
|
||||||
|
// after the constructor returns.
|
||||||
|
NS_DispatchToMainThread(
|
||||||
|
NS_NewRunnableFunction(__func__, [self = RefPtr(this)]() {
|
||||||
|
nsresult rv = MustGetShutdownBarrier()->AddBlocker(
|
||||||
|
self, NS_LITERAL_STRING_FROM_CSTRING(__FILE__), __LINE__, u""_ns);
|
||||||
|
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
|
||||||
|
}));
|
||||||
|
|
||||||
LOG("Spinning up WebRTC Cameras Thread");
|
LOG("Spinning up WebRTC Cameras Thread");
|
||||||
|
MonitorAutoLock lock(*sThreadMonitor);
|
||||||
RefPtr<CamerasParent> self(this);
|
if (sVideoCaptureThread == nullptr) {
|
||||||
NS_DispatchToMainThread(NewRunnableFrom([self]() {
|
MOZ_ASSERT(sNumOfOpenCamerasParentEngines == 0);
|
||||||
nsresult rv = MustGetShutdownBarrier()->AddBlocker(
|
sVideoCaptureThread = new base::Thread("VideoCapture");
|
||||||
self, NS_LITERAL_STRING_FROM_CSTRING(__FILE__), __LINE__, u""_ns);
|
base::Thread::Options options;
|
||||||
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
|
|
||||||
|
|
||||||
// Start the thread
|
|
||||||
MonitorAutoLock lock(*(self->sThreadMonitor));
|
|
||||||
if (self->sVideoCaptureThread == nullptr) {
|
|
||||||
MOZ_ASSERT(sNumOfOpenCamerasParentEngines == 0);
|
|
||||||
self->sVideoCaptureThread = new base::Thread("VideoCapture");
|
|
||||||
base::Thread::Options options;
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
options.message_loop_type = MessageLoop::TYPE_MOZILLA_NONMAINUITHREAD;
|
options.message_loop_type = MessageLoop::TYPE_MOZILLA_NONMAINUITHREAD;
|
||||||
#else
|
#else
|
||||||
options.message_loop_type = MessageLoop::TYPE_MOZILLA_NONMAINTHREAD;
|
options.message_loop_type = MessageLoop::TYPE_MOZILLA_NONMAINTHREAD;
|
||||||
#endif
|
#endif
|
||||||
if (!self->sVideoCaptureThread->StartWithOptions(options)) {
|
if (!sVideoCaptureThread->StartWithOptions(options)) {
|
||||||
MOZ_CRASH();
|
MOZ_CRASH();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
sNumOfOpenCamerasParentEngines++;
|
}
|
||||||
self->sThreadMonitor->NotifyAll();
|
sNumOfOpenCamerasParentEngines++;
|
||||||
return NS_OK;
|
return IPC_OK();
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CamerasParent::~CamerasParent() {
|
CamerasParent::~CamerasParent() {
|
||||||
|
|
|
@ -72,7 +72,8 @@ class CamerasParent final : public PCamerasParent,
|
||||||
|
|
||||||
static already_AddRefed<CamerasParent> Create();
|
static already_AddRefed<CamerasParent> Create();
|
||||||
|
|
||||||
// Messages received form the child. These run on the IPC/PBackground thread.
|
// Messages received from the child. These run on the IPC/PBackground thread.
|
||||||
|
mozilla::ipc::IPCResult RecvPCamerasConstructor();
|
||||||
mozilla::ipc::IPCResult RecvAllocateCapture(
|
mozilla::ipc::IPCResult RecvAllocateCapture(
|
||||||
const CaptureEngine& aEngine, const nsCString& aUnique_idUTF8,
|
const CaptureEngine& aEngine, const nsCString& aUnique_idUTF8,
|
||||||
const uint64_t& aWindowID) override;
|
const uint64_t& aWindowID) override;
|
||||||
|
@ -137,30 +138,29 @@ class CamerasParent final : public PCamerasParent,
|
||||||
static nsString GetNewName();
|
static nsString GetNewName();
|
||||||
|
|
||||||
// sEngines will be accessed by VideoCapture thread only
|
// sEngines will be accessed by VideoCapture thread only
|
||||||
// sNumOfCamerasParent, sNumOfOpenCamerasParentEngines, and
|
// sNumOfCamerasParents, sNumOfOpenCamerasParentEngines, and
|
||||||
// sVideoCaptureThread will be accessed by main thread / PBackground thread /
|
// sVideoCaptureThread will be accessed by main thread / PBackground thread /
|
||||||
// VideoCapture thread
|
// VideoCapture thread
|
||||||
// sNumOfCamerasParent and sThreadMonitor create & delete are protected by
|
// sNumOfCamerasParents and sThreadMonitor create & delete are protected by
|
||||||
// sMutex
|
// sMutex
|
||||||
// sNumOfOpenCamerasParentEngines and sVideoCaptureThread are protected by
|
// sNumOfOpenCamerasParentEngines and sVideoCaptureThread are protected by
|
||||||
// sThreadMonitor
|
// sThreadMonitor
|
||||||
static StaticRefPtr<VideoEngine> sEngines[CaptureEngine::MaxEngine];
|
static StaticRefPtr<VideoEngine> sEngines[CaptureEngine::MaxEngine];
|
||||||
static int32_t sNumOfOpenCamerasParentEngines;
|
static int32_t sNumOfOpenCamerasParentEngines;
|
||||||
static int32_t sNumOfCamerasParents;
|
static int32_t sNumOfCamerasParents;
|
||||||
|
static StaticMutex sMutex;
|
||||||
|
static Monitor* sThreadMonitor;
|
||||||
|
// video processing thread - where webrtc.org capturer code runs
|
||||||
|
static base::Thread* sVideoCaptureThread;
|
||||||
|
|
||||||
nsTArray<CallbackHelper*> mCallbacks;
|
nsTArray<CallbackHelper*> mCallbacks;
|
||||||
nsString mName;
|
nsString mName;
|
||||||
|
|
||||||
// image buffers
|
// image buffers
|
||||||
ShmemPool mShmemPool;
|
ShmemPool mShmemPool;
|
||||||
|
|
||||||
// PBackground parent thread
|
// PBackgroundParent thread
|
||||||
nsCOMPtr<nsISerialEventTarget> mPBackgroundEventTarget;
|
const nsCOMPtr<nsISerialEventTarget> mPBackgroundEventTarget;
|
||||||
|
|
||||||
static StaticMutex sMutex;
|
|
||||||
static Monitor* sThreadMonitor;
|
|
||||||
|
|
||||||
// video processing thread - where webrtc.org capturer code runs
|
|
||||||
static base::Thread* sVideoCaptureThread;
|
|
||||||
|
|
||||||
// Shutdown handling
|
// Shutdown handling
|
||||||
bool mChildIsAlive;
|
bool mChildIsAlive;
|
||||||
|
|
|
@ -2178,7 +2178,8 @@ nsresult EditorBase::DeleteNodeWithTransaction(nsIContent& aContent) {
|
||||||
|
|
||||||
NS_IMETHODIMP EditorBase::NotifySelectionChanged(Document* aDocument,
|
NS_IMETHODIMP EditorBase::NotifySelectionChanged(Document* aDocument,
|
||||||
Selection* aSelection,
|
Selection* aSelection,
|
||||||
int16_t aReason) {
|
int16_t aReason,
|
||||||
|
int32_t aAmount) {
|
||||||
if (NS_WARN_IF(!aDocument) || NS_WARN_IF(!aSelection)) {
|
if (NS_WARN_IF(!aDocument) || NS_WARN_IF(!aSelection)) {
|
||||||
return NS_ERROR_INVALID_ARG;
|
return NS_ERROR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
|
@ -554,7 +554,8 @@ bool HTMLEditor::UpdateMetaCharsetWithTransaction(
|
||||||
|
|
||||||
NS_IMETHODIMP HTMLEditor::NotifySelectionChanged(Document* aDocument,
|
NS_IMETHODIMP HTMLEditor::NotifySelectionChanged(Document* aDocument,
|
||||||
Selection* aSelection,
|
Selection* aSelection,
|
||||||
int16_t aReason) {
|
int16_t aReason,
|
||||||
|
int32_t aAmount) {
|
||||||
if (NS_WARN_IF(!aDocument) || NS_WARN_IF(!aSelection)) {
|
if (NS_WARN_IF(!aDocument) || NS_WARN_IF(!aSelection)) {
|
||||||
return NS_ERROR_INVALID_ARG;
|
return NS_ERROR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
@ -593,8 +594,8 @@ NS_IMETHODIMP HTMLEditor::NotifySelectionChanged(Document* aDocument,
|
||||||
updater->OnSelectionChange();
|
updater->OnSelectionChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult rv =
|
nsresult rv = EditorBase::NotifySelectionChanged(aDocument, aSelection,
|
||||||
EditorBase::NotifySelectionChanged(aDocument, aSelection, aReason);
|
aReason, aAmount);
|
||||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||||
"EditorBase::NotifySelectionChanged() failed");
|
"EditorBase::NotifySelectionChanged() failed");
|
||||||
return rv;
|
return rv;
|
||||||
|
|
|
@ -37,7 +37,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1053048
|
||||||
// synthesizing the key press. So, we don't need to check whether a
|
// synthesizing the key press. So, we don't need to check whether a
|
||||||
// notification actually comes here.
|
// notification actually comes here.
|
||||||
let selectionListener = {
|
let selectionListener = {
|
||||||
notifySelectionChanged(aDocument, aSelection, aReason) {
|
notifySelectionChanged(aDocument, aSelection, aReason, aAmount) {
|
||||||
ok(true, "selectionStart: " + textarea.selectionStart);
|
ok(true, "selectionStart: " + textarea.selectionStart);
|
||||||
ok(true, "selectionEnd: " + textarea.selectionEnd);
|
ok(true, "selectionEnd: " + textarea.selectionEnd);
|
||||||
},
|
},
|
||||||
|
|
|
@ -1713,8 +1713,9 @@ struct NewLayerData {
|
||||||
ScrollableLayerGuid::ViewID mDeferredId = ScrollableLayerGuid::NULL_SCROLL_ID;
|
ScrollableLayerGuid::ViewID mDeferredId = ScrollableLayerGuid::NULL_SCROLL_ID;
|
||||||
bool mTransformShouldGetOwnLayer = false;
|
bool mTransformShouldGetOwnLayer = false;
|
||||||
|
|
||||||
void ComputeDeferredTransformInfo(const StackingContextHelper& aSc,
|
void ComputeDeferredTransformInfo(
|
||||||
nsDisplayItem* aItem) {
|
const StackingContextHelper& aSc, nsDisplayItem* aItem,
|
||||||
|
nsDisplayTransform* aLastDeferredTransform) {
|
||||||
// See the comments on StackingContextHelper::mDeferredTransformItem
|
// See the comments on StackingContextHelper::mDeferredTransformItem
|
||||||
// for an overview of what deferred transforms are.
|
// for an overview of what deferred transforms are.
|
||||||
// In the case where we deferred a transform, but have a child display
|
// In the case where we deferred a transform, but have a child display
|
||||||
|
@ -1730,6 +1731,14 @@ struct NewLayerData {
|
||||||
// that we deferred, and a child WebRenderLayerScrollData item that
|
// that we deferred, and a child WebRenderLayerScrollData item that
|
||||||
// holds the scroll metadata for the child's ASR.
|
// holds the scroll metadata for the child's ASR.
|
||||||
mDeferredItem = aSc.GetDeferredTransformItem();
|
mDeferredItem = aSc.GetDeferredTransformItem();
|
||||||
|
// If this deferred transform is already slated to be emitted onto an
|
||||||
|
// ancestor layer, do not emit it on this layer as well. Note that it's
|
||||||
|
// sufficient to check the most recently deferred item here, because
|
||||||
|
// there's only one per stacking context, and we emit it when changing
|
||||||
|
// stacking contexts.
|
||||||
|
if (mDeferredItem == aLastDeferredTransform) {
|
||||||
|
mDeferredItem = nullptr;
|
||||||
|
}
|
||||||
if (mDeferredItem) {
|
if (mDeferredItem) {
|
||||||
// It's possible the transform's ASR is not only an ancestor of
|
// It's possible the transform's ASR is not only an ancestor of
|
||||||
// the item's ASR, but an ancestor of stopAtAsr. In such cases,
|
// the item's ASR, but an ancestor of stopAtAsr. In such cases,
|
||||||
|
@ -1890,7 +1899,10 @@ void WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList(
|
||||||
newLayerData->mLayerCountBeforeRecursing = mLayerScrollData.size();
|
newLayerData->mLayerCountBeforeRecursing = mLayerScrollData.size();
|
||||||
newLayerData->mStopAtAsr =
|
newLayerData->mStopAtAsr =
|
||||||
mAsrStack.empty() ? nullptr : mAsrStack.back();
|
mAsrStack.empty() ? nullptr : mAsrStack.back();
|
||||||
newLayerData->ComputeDeferredTransformInfo(aSc, item);
|
newLayerData->ComputeDeferredTransformInfo(
|
||||||
|
aSc, item,
|
||||||
|
mDeferredTransformStack.empty() ? nullptr
|
||||||
|
: mDeferredTransformStack.back());
|
||||||
|
|
||||||
// Ensure our children's |stopAtAsr| is not be an ancestor of our
|
// Ensure our children's |stopAtAsr| is not be an ancestor of our
|
||||||
// |stopAtAsr|, otherwise we could get cyclic scroll metadata
|
// |stopAtAsr|, otherwise we could get cyclic scroll metadata
|
||||||
|
@ -1910,6 +1922,13 @@ void WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList(
|
||||||
newLayerData->mDeferredItem->GetActiveScrolledRoot());
|
newLayerData->mDeferredItem->GetActiveScrolledRoot());
|
||||||
}
|
}
|
||||||
mAsrStack.push_back(stopAtAsrForChildren);
|
mAsrStack.push_back(stopAtAsrForChildren);
|
||||||
|
|
||||||
|
// If we're going to emit a deferred transform onto this layer,
|
||||||
|
// keep track of that so descendant layers know not to emit the
|
||||||
|
// same deferred transform.
|
||||||
|
if (newLayerData->mDeferredItem) {
|
||||||
|
mDeferredTransformStack.push_back(newLayerData->mDeferredItem);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1951,6 +1970,11 @@ void WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList(
|
||||||
// the stack is enclosing display item's ASR (or the stack is empty)
|
// the stack is enclosing display item's ASR (or the stack is empty)
|
||||||
mAsrStack.pop_back();
|
mAsrStack.pop_back();
|
||||||
|
|
||||||
|
if (newLayerData->mDeferredItem) {
|
||||||
|
MOZ_ASSERT(!mDeferredTransformStack.empty());
|
||||||
|
mDeferredTransformStack.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
const ActiveScrolledRoot* stopAtAsr = newLayerData->mStopAtAsr;
|
const ActiveScrolledRoot* stopAtAsr = newLayerData->mStopAtAsr;
|
||||||
|
|
||||||
int32_t descendants =
|
int32_t descendants =
|
||||||
|
|
|
@ -215,6 +215,9 @@ class WebRenderCommandBuilder final {
|
||||||
// need this so that WebRenderLayerScrollData items that deeper in the
|
// need this so that WebRenderLayerScrollData items that deeper in the
|
||||||
// tree don't duplicate scroll metadata that their ancestors already have.
|
// tree don't duplicate scroll metadata that their ancestors already have.
|
||||||
std::vector<const ActiveScrolledRoot*> mAsrStack;
|
std::vector<const ActiveScrolledRoot*> mAsrStack;
|
||||||
|
// A similar stack to track the deferred transform that we decided to emit
|
||||||
|
// most recently.
|
||||||
|
std::vector<nsDisplayTransform*> mDeferredTransformStack;
|
||||||
const ActiveScrolledRoot* mLastAsr;
|
const ActiveScrolledRoot* mLastAsr;
|
||||||
|
|
||||||
WebRenderUserDataRefTable mWebRenderUserDatas;
|
WebRenderUserDataRefTable mWebRenderUserDatas;
|
||||||
|
|
|
@ -726,6 +726,16 @@ camera::PCamerasParent* BackgroundParentImpl::AllocPCamerasParent() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MOZ_WEBRTC
|
||||||
|
mozilla::ipc::IPCResult BackgroundParentImpl::RecvPCamerasConstructor(
|
||||||
|
camera::PCamerasParent* aActor) {
|
||||||
|
AssertIsInMainOrSocketProcess();
|
||||||
|
AssertIsOnBackgroundThread();
|
||||||
|
MOZ_ASSERT(aActor);
|
||||||
|
return static_cast<camera::CamerasParent*>(aActor)->RecvPCamerasConstructor();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool BackgroundParentImpl::DeallocPCamerasParent(
|
bool BackgroundParentImpl::DeallocPCamerasParent(
|
||||||
camera::PCamerasParent* aActor) {
|
camera::PCamerasParent* aActor) {
|
||||||
AssertIsInMainOrSocketProcess();
|
AssertIsInMainOrSocketProcess();
|
||||||
|
|
|
@ -254,7 +254,10 @@ class BackgroundParentImpl : public PBackgroundParent,
|
||||||
PServiceWorkerManagerParent* aActor) override;
|
PServiceWorkerManagerParent* aActor) override;
|
||||||
|
|
||||||
PCamerasParent* AllocPCamerasParent() override;
|
PCamerasParent* AllocPCamerasParent() override;
|
||||||
|
#ifdef MOZ_WEBRTC
|
||||||
|
mozilla::ipc::IPCResult RecvPCamerasConstructor(
|
||||||
|
PCamerasParent* aActor) override;
|
||||||
|
#endif
|
||||||
bool DeallocPCamerasParent(PCamerasParent* aActor) override;
|
bool DeallocPCamerasParent(PCamerasParent* aActor) override;
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvShutdownServiceWorkerRegistrar() override;
|
mozilla::ipc::IPCResult RecvShutdownServiceWorkerRegistrar() override;
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,16 @@
|
||||||
|
<style>
|
||||||
|
#a {
|
||||||
|
line-height: 41%;
|
||||||
|
flex: -1; transform: translatex(0)
|
||||||
|
}
|
||||||
|
.b {
|
||||||
|
overflow-y: scroll;
|
||||||
|
opacity: -1;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<h1 id="a">
|
||||||
|
<ol class="b">
|
||||||
|
<li>
|
||||||
|
<label class="b">
|
||||||
|
<menu style="position: fixed">x</menu>
|
||||||
|
|
|
@ -563,8 +563,8 @@ load 1723200.html
|
||||||
load 1729578.html
|
load 1729578.html
|
||||||
load 1729581.html
|
load 1729581.html
|
||||||
load 1734007.html
|
load 1734007.html
|
||||||
asserts-if(Android,0-1000) load 1749190.html
|
|
||||||
load 1745860.html
|
load 1745860.html
|
||||||
pref(layout.accessiblecaret.enabled,true) load 1746989.html
|
pref(layout.accessiblecaret.enabled,true) load 1746989.html
|
||||||
load 1752649.html
|
load 1752649.html
|
||||||
|
load 1753779.html
|
||||||
pref(layout.css.backdrop-filter.enabled,true) load 1755790.html
|
pref(layout.css.backdrop-filter.enabled,true) load 1755790.html
|
||||||
|
|
|
@ -569,8 +569,8 @@ void nsCaret::PaintCaret(DrawTarget& aDrawTarget, nsIFrame* aForFrame,
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsCaret::NotifySelectionChanged(Document*, Selection* aDomSel,
|
nsCaret::NotifySelectionChanged(Document*, Selection* aDomSel, int16_t aReason,
|
||||||
int16_t aReason) {
|
int32_t aAmount) {
|
||||||
// Note that aDomSel, per the comment below may not be the same as our
|
// Note that aDomSel, per the comment below may not be the same as our
|
||||||
// selection, but that's OK since if that is the case, it wouldn't have
|
// selection, but that's OK since if that is the case, it wouldn't have
|
||||||
// mattered what IsVisible() returns here, so we just opt for checking
|
// mattered what IsVisible() returns here, so we just opt for checking
|
||||||
|
|
|
@ -2824,7 +2824,7 @@ NS_IMETHODIMP nsDocumentViewer::GetInImage(bool* aInImage) {
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP nsDocViewerSelectionListener::NotifySelectionChanged(
|
NS_IMETHODIMP nsDocViewerSelectionListener::NotifySelectionChanged(
|
||||||
Document*, Selection*, int16_t aReason) {
|
Document*, Selection*, int16_t aReason, int32_t aAmount) {
|
||||||
if (!mDocViewer) {
|
if (!mDocViewer) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -729,6 +729,8 @@ nsresult nsFrameSelection::MoveCaret(nsDirection aDirection,
|
||||||
SetChangeReasons(nsISelectionListener::KEYPRESS_REASON);
|
SetChangeReasons(nsISelectionListener::KEYPRESS_REASON);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mCaretMoveAmount = aAmount;
|
||||||
|
|
||||||
AutoPrepareFocusRange prep(sel, false);
|
AutoPrepareFocusRange prep(sel, false);
|
||||||
|
|
||||||
// we must keep this around and revalidate it when its just UP/DOWN
|
// we must keep this around and revalidate it when its just UP/DOWN
|
||||||
|
@ -2170,6 +2172,7 @@ void nsFrameSelection::EndBatchChanges(const char* aRequesterFuncName,
|
||||||
|
|
||||||
if (mBatching.mCounter == 0 && mBatching.mChangesDuringBatching) {
|
if (mBatching.mCounter == 0 && mBatching.mChangesDuringBatching) {
|
||||||
AddChangeReasons(aReasons);
|
AddChangeReasons(aReasons);
|
||||||
|
mCaretMoveAmount = eSelectNoAmount;
|
||||||
mBatching.mChangesDuringBatching = false;
|
mBatching.mChangesDuringBatching = false;
|
||||||
// Be aware, the Selection instance may be destroyed after this call.
|
// Be aware, the Selection instance may be destroyed after this call.
|
||||||
NotifySelectionListeners(SelectionType::eNormal);
|
NotifySelectionListeners(SelectionType::eNormal);
|
||||||
|
@ -2182,6 +2185,7 @@ nsresult nsFrameSelection::NotifySelectionListeners(
|
||||||
if (index >= 0 && mDomSelections[index]) {
|
if (index >= 0 && mDomSelections[index]) {
|
||||||
RefPtr<Selection> selection = mDomSelections[index];
|
RefPtr<Selection> selection = mDomSelections[index];
|
||||||
selection->NotifySelectionListeners();
|
selection->NotifySelectionListeners();
|
||||||
|
mCaretMoveAmount = eSelectNoAmount;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
|
@ -829,6 +829,8 @@ class nsFrameSelection final {
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsSelectionAmount GetCaretMoveAmount() { return mCaretMoveAmount; }
|
||||||
|
|
||||||
bool IsUserSelectionReason() const {
|
bool IsUserSelectionReason() const {
|
||||||
return (mSelectionChangeReasons &
|
return (mSelectionChangeReasons &
|
||||||
(nsISelectionListener::DRAG_REASON |
|
(nsISelectionListener::DRAG_REASON |
|
||||||
|
@ -1047,6 +1049,7 @@ class nsFrameSelection final {
|
||||||
int16_t mSelectionChangeReasons = nsISelectionListener::NO_REASON;
|
int16_t mSelectionChangeReasons = nsISelectionListener::NO_REASON;
|
||||||
// For visual display purposes.
|
// For visual display purposes.
|
||||||
int16_t mDisplaySelection = nsISelectionController::SELECTION_OFF;
|
int16_t mDisplaySelection = nsISelectionController::SELECTION_OFF;
|
||||||
|
nsSelectionAmount mCaretMoveAmount = eSelectNoAmount;
|
||||||
|
|
||||||
struct Caret {
|
struct Caret {
|
||||||
// Hint to tell if the selection is at the end of this line or beginning of
|
// Hint to tell if the selection is at the end of this line or beginning of
|
||||||
|
|
|
@ -737,10 +737,6 @@ optgroup:before {
|
||||||
input, textarea, select, button {
|
input, textarea, select, button {
|
||||||
-moz-user-input: none !important;
|
-moz-user-input: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=file] {
|
|
||||||
height: 2em;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
progress {
|
progress {
|
||||||
|
|
|
@ -7,6 +7,9 @@
|
||||||
#include "SandboxTestingChild.h"
|
#include "SandboxTestingChild.h"
|
||||||
|
|
||||||
#include "mozilla/StaticPrefs_security.h"
|
#include "mozilla/StaticPrefs_security.h"
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
# include "nsCocoaFeatures.h"
|
||||||
|
#endif
|
||||||
#include "nsXULAppAPI.h"
|
#include "nsXULAppAPI.h"
|
||||||
|
|
||||||
#ifdef XP_UNIX
|
#ifdef XP_UNIX
|
||||||
|
@ -36,7 +39,12 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef XP_MACOSX
|
#ifdef XP_MACOSX
|
||||||
|
# include <spawn.h>
|
||||||
|
# include <CoreFoundation/CoreFoundation.h>
|
||||||
# include <CoreGraphics/CoreGraphics.h>
|
# include <CoreGraphics/CoreGraphics.h>
|
||||||
|
namespace ApplicationServices {
|
||||||
|
# include <ApplicationServices/ApplicationServices.h>
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
|
@ -146,6 +154,86 @@ static void FileTest(const nsCString& aName, const char* aSpecialDirName,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
/*
|
||||||
|
* Test if this process can launch another process with posix_spawnp,
|
||||||
|
* exec, and LSOpenCFURLRef. All launches are expected to fail. In processes
|
||||||
|
* where the sandbox permits reading of file metadata (content processes at
|
||||||
|
* this time), we expect the posix_spawnp error to be EPERM. In processes
|
||||||
|
* without that permission, we expect ENOENT. Changing the sandbox policy
|
||||||
|
* may break this assumption, but the important aspect to test for is that the
|
||||||
|
* launch is not permitted.
|
||||||
|
*/
|
||||||
|
void RunMacTestLaunchProcess(SandboxTestingChild* child,
|
||||||
|
int aPosixSpawnExpectedError = ENOENT) {
|
||||||
|
// Test that posix_spawnp fails
|
||||||
|
char* argv[2];
|
||||||
|
argv[0] = const_cast<char*>("bash");
|
||||||
|
argv[1] = NULL;
|
||||||
|
int rv = posix_spawnp(NULL, "/bin/bash", NULL, NULL, argv, NULL);
|
||||||
|
nsPrintfCString posixSpawnMessage("posix_spawnp returned %d, expected %d", rv,
|
||||||
|
aPosixSpawnExpectedError);
|
||||||
|
child->SendReportTestResults("posix_spawnp test"_ns,
|
||||||
|
rv == aPosixSpawnExpectedError,
|
||||||
|
posixSpawnMessage);
|
||||||
|
|
||||||
|
// Test that exec fails
|
||||||
|
child->ErrnoTest("execv /bin/bash test"_ns, false, [&] {
|
||||||
|
char* argvp = NULL;
|
||||||
|
return execv("/bin/bash", &argvp);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test that launching an application using LSOpenCFURLRef fails
|
||||||
|
char* uri;
|
||||||
|
if (nsCocoaFeatures::OnCatalinaOrLater()) {
|
||||||
|
uri = const_cast<char*>("/System/Applications/Utilities/Console.app");
|
||||||
|
} else {
|
||||||
|
uri = const_cast<char*>("/Applications/Utilities/Console.app");
|
||||||
|
}
|
||||||
|
CFStringRef filePath = ::CFStringCreateWithCString(kCFAllocatorDefault, uri,
|
||||||
|
kCFStringEncodingUTF8);
|
||||||
|
CFURLRef urlRef = ::CFURLCreateWithFileSystemPath(
|
||||||
|
kCFAllocatorDefault, filePath, kCFURLPOSIXPathStyle, false);
|
||||||
|
if (!urlRef) {
|
||||||
|
child->SendReportTestResults("LSOpenCFURLRef"_ns, false,
|
||||||
|
"CFURLCreateWithFileSystemPath failed"_ns);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSStatus status = ApplicationServices::LSOpenCFURLRef(urlRef, NULL);
|
||||||
|
::CFRelease(urlRef);
|
||||||
|
nsPrintfCString lsMessage(
|
||||||
|
"LSOpenCFURLRef returned %d, "
|
||||||
|
"expected kLSServerCommunicationErr (%d)",
|
||||||
|
status, ApplicationServices::kLSServerCommunicationErr);
|
||||||
|
child->SendReportTestResults(
|
||||||
|
"LSOpenCFURLRef"_ns,
|
||||||
|
status == ApplicationServices::kLSServerCommunicationErr, lsMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test if this process can connect to the macOS window server.
|
||||||
|
* When |aShouldHaveAccess| is true, the test passes if access is __permitted__.
|
||||||
|
* When |aShouldHaveAccess| is false, the test passes if access is __blocked__.
|
||||||
|
*/
|
||||||
|
void RunMacTestWindowServer(SandboxTestingChild* child,
|
||||||
|
bool aShouldHaveAccess = false) {
|
||||||
|
// CGSessionCopyCurrentDictionary() returns NULL when a
|
||||||
|
// connection to the window server is not available.
|
||||||
|
CFDictionaryRef windowServerDict = CGSessionCopyCurrentDictionary();
|
||||||
|
bool gotWindowServerDetails = (windowServerDict != nullptr);
|
||||||
|
bool testPassed = (gotWindowServerDetails == aShouldHaveAccess);
|
||||||
|
child->SendReportTestResults(
|
||||||
|
"CGSessionCopyCurrentDictionary"_ns, testPassed,
|
||||||
|
gotWindowServerDetails
|
||||||
|
? "dictionary returned, access is permitted"_ns
|
||||||
|
: "no dictionary returned, access appears blocked"_ns);
|
||||||
|
if (windowServerDict != nullptr) {
|
||||||
|
CFRelease(windowServerDict);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* XP_MACOSX */
|
||||||
|
|
||||||
void RunTestsContent(SandboxTestingChild* child) {
|
void RunTestsContent(SandboxTestingChild* child) {
|
||||||
MOZ_ASSERT(child, "No SandboxTestingChild*?");
|
MOZ_ASSERT(child, "No SandboxTestingChild*?");
|
||||||
|
|
||||||
|
@ -296,18 +384,8 @@ void RunTestsContent(SandboxTestingChild* child) {
|
||||||
# endif // XP_LINUX
|
# endif // XP_LINUX
|
||||||
|
|
||||||
# ifdef XP_MACOSX
|
# ifdef XP_MACOSX
|
||||||
// Test that content processes can not connect to the macOS window server.
|
RunMacTestLaunchProcess(child, EPERM);
|
||||||
// CGSessionCopyCurrentDictionary() returns NULL when a connection to the
|
RunMacTestWindowServer(child);
|
||||||
// window server is not available.
|
|
||||||
CFDictionaryRef windowServerDict = CGSessionCopyCurrentDictionary();
|
|
||||||
bool gotWindowServerDetails = (windowServerDict != nullptr);
|
|
||||||
child->SendReportTestResults(
|
|
||||||
"CGSessionCopyCurrentDictionary"_ns, !gotWindowServerDetails,
|
|
||||||
gotWindowServerDetails ? "Failed: dictionary unexpectedly returned"_ns
|
|
||||||
: "Succeeded: no dictionary returned"_ns);
|
|
||||||
if (windowServerDict != nullptr) {
|
|
||||||
CFRelease(windowServerDict);
|
|
||||||
}
|
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
#elif XP_WIN
|
#elif XP_WIN
|
||||||
|
@ -385,9 +463,11 @@ void RunTestsSocket(SandboxTestingChild* child) {
|
||||||
child->ErrnoTest("getcpu"_ns, true,
|
child->ErrnoTest("getcpu"_ns, true,
|
||||||
[&] { return syscall(SYS_getcpu, &c, NULL, NULL); });
|
[&] { return syscall(SYS_getcpu, &c, NULL, NULL); });
|
||||||
# endif // XP_LINUX
|
# endif // XP_LINUX
|
||||||
|
#elif XP_MACOSX
|
||||||
|
RunMacTestLaunchProcess(child);
|
||||||
|
RunMacTestWindowServer(child);
|
||||||
#else // XP_UNIX
|
#else // XP_UNIX
|
||||||
child->ReportNoTests();
|
child->ReportNoTests();
|
||||||
#endif // XP_UNIX
|
#endif // XP_UNIX
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,8 +520,11 @@ void RunTestsRDD(SandboxTestingChild* child) {
|
||||||
int c;
|
int c;
|
||||||
child->ErrnoTest("getcpu"_ns, true,
|
child->ErrnoTest("getcpu"_ns, true,
|
||||||
[&] { return syscall(SYS_getcpu, &c, NULL, NULL); });
|
[&] { return syscall(SYS_getcpu, &c, NULL, NULL); });
|
||||||
# endif // XP_LINUX
|
# elif XP_MACOSX
|
||||||
#else // XP_UNIX
|
RunMacTestLaunchProcess(child);
|
||||||
|
RunMacTestWindowServer(child);
|
||||||
|
# endif
|
||||||
|
#else // XP_UNIX
|
||||||
child->ReportNoTests();
|
child->ReportNoTests();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -487,8 +570,12 @@ void RunTestsGMPlugin(SandboxTestingChild* child) {
|
||||||
return fd;
|
return fd;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
# endif // XP_LINUX
|
# elif XP_MACOSX // XP_LINUX
|
||||||
#else // XP_UNIX
|
RunMacTestLaunchProcess(child);
|
||||||
|
/* The Mac GMP process requires access to the window server */
|
||||||
|
RunMacTestWindowServer(child, true /* aShouldHaveAccess */);
|
||||||
|
# endif // XP_MACOSX
|
||||||
|
#else // XP_UNIX
|
||||||
child->ReportNoTests();
|
child->ReportNoTests();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -508,9 +595,11 @@ void RunTestsUtility(SandboxTestingChild* child) {
|
||||||
int rv = getrusage(RUSAGE_SELF, &res);
|
int rv = getrusage(RUSAGE_SELF, &res);
|
||||||
return rv;
|
return rv;
|
||||||
});
|
});
|
||||||
# endif // XP_LINUX
|
# elif XP_MACOSX // XP_LINUX
|
||||||
#else // XP_UNIX
|
RunMacTestLaunchProcess(child);
|
||||||
# ifdef XP_WIN
|
RunMacTestWindowServer(child);
|
||||||
|
# endif // XP_MACOSX
|
||||||
|
#elif XP_WIN // XP_UNIX
|
||||||
child->ErrnoValueTest("write_only"_ns, EACCES, [&] {
|
child->ErrnoValueTest("write_only"_ns, EACCES, [&] {
|
||||||
FILE* rv = fopen("test_sandbox.txt", "w");
|
FILE* rv = fopen("test_sandbox.txt", "w");
|
||||||
if (rv != nullptr) {
|
if (rv != nullptr) {
|
||||||
|
@ -519,10 +608,9 @@ void RunTestsUtility(SandboxTestingChild* child) {
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
});
|
});
|
||||||
# else // XP_WIN
|
#else // XP_UNIX
|
||||||
child->ReportNoTests();
|
child->ReportNoTests();
|
||||||
# endif // XP_WIN
|
#endif // XP_MACOSX
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Reference case</title>
|
||||||
|
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=133984">
|
||||||
|
<style>
|
||||||
|
input[type="file"] { height: auto; }
|
||||||
|
.with-outline {
|
||||||
|
outline: 2px solid teal;
|
||||||
|
}
|
||||||
|
.wrapper {
|
||||||
|
border: 2px solid fuchsia;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<input type="file">
|
||||||
|
<br><br>
|
||||||
|
<input type="file" class="with-outline">
|
||||||
|
<br><br>
|
||||||
|
<div class="wrapper"><input type="file"></div>
|
||||||
|
</body>
|
|
@ -0,0 +1,23 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Test that file-input widgets have 'auto' height (not some other arbitrary value) when printed</title>
|
||||||
|
<meta name="assert" content="file-input widgets should have 'auto' height (not some other arbitrary value) when printed">
|
||||||
|
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=133984">
|
||||||
|
<link rel="match" href="input-file-print-ref.html">
|
||||||
|
<style>
|
||||||
|
.with-outline {
|
||||||
|
outline: 2px solid teal;
|
||||||
|
}
|
||||||
|
.wrapper {
|
||||||
|
border: 2px solid fuchsia;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<input type="file">
|
||||||
|
<br><br>
|
||||||
|
<input type="file" class="with-outline">
|
||||||
|
<br><br>
|
||||||
|
<div class="wrapper"><input type="file"></div>
|
||||||
|
</body>
|
Загрузка…
Ссылка в новой задаче