зеркало из 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,
|
||||
bool aIsSelectionCollapsed) {
|
||||
bool aIsSelectionCollapsed,
|
||||
int32_t aGranularity) {
|
||||
RefPtr<SessionAccessibility> sessionAcc =
|
||||
SessionAccessibility::GetInstanceFor(aTarget);
|
||||
|
||||
|
|
|
@ -1372,7 +1372,8 @@ void a11y::ProxyStateChangeEvent(RemoteAccessible* aTarget, uint64_t aState,
|
|||
}
|
||||
|
||||
void a11y::ProxyCaretMoveEvent(RemoteAccessible* aTarget, int32_t aOffset,
|
||||
bool aIsSelectionCollapsed) {
|
||||
bool aIsSelectionCollapsed,
|
||||
int32_t aGranularity) {
|
||||
AtkObject* wrapper = GetWrapperFor(aTarget);
|
||||
g_signal_emit_by_name(wrapper, "text_caret_moved", aOffset);
|
||||
}
|
||||
|
|
|
@ -127,11 +127,13 @@ AccShowEvent::AccShowEvent(LocalAccessible* aTarget)
|
|||
|
||||
AccTextSelChangeEvent::AccTextSelChangeEvent(HyperTextAccessible* aTarget,
|
||||
dom::Selection* aSelection,
|
||||
int32_t aReason)
|
||||
int32_t aReason,
|
||||
int32_t aGranularity)
|
||||
: AccEvent(nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED, aTarget,
|
||||
eAutoDetect, eCoalesceTextSelChange),
|
||||
mSel(aSelection),
|
||||
mReason(aReason) {}
|
||||
mReason(aReason),
|
||||
mGranularity(aGranularity) {}
|
||||
|
||||
AccTextSelChangeEvent::~AccTextSelChangeEvent() {}
|
||||
|
||||
|
@ -246,7 +248,8 @@ already_AddRefed<nsIAccessibleEvent> a11y::MakeXPCEvent(AccEvent* aEvent) {
|
|||
AccCaretMoveEvent* cm = downcast_accEvent(aEvent);
|
||||
xpEvent = new xpcAccCaretMoveEvent(
|
||||
type, ToXPC(acc), ToXPCDocument(doc), node, fromUser,
|
||||
cm->GetCaretOffset(), cm->IsSelectionCollapsed(), cm->IsAtEndOfLine());
|
||||
cm->GetCaretOffset(), cm->IsSelectionCollapsed(), cm->IsAtEndOfLine(),
|
||||
cm->GetGranularity());
|
||||
return xpEvent.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -348,12 +348,14 @@ class AccCaretMoveEvent : public AccEvent {
|
|||
public:
|
||||
AccCaretMoveEvent(LocalAccessible* aAccessible, int32_t aCaretOffset,
|
||||
bool aIsSelectionCollapsed, bool aIsAtEndOfLine,
|
||||
int32_t aGranularity,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect)
|
||||
: AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aAccessible,
|
||||
aIsFromUserInput),
|
||||
mCaretOffset(aCaretOffset),
|
||||
mIsSelectionCollapsed(aIsSelectionCollapsed),
|
||||
mIsAtEndOfLine(aIsAtEndOfLine) {}
|
||||
mIsAtEndOfLine(aIsAtEndOfLine),
|
||||
mGranularity(aGranularity) {}
|
||||
virtual ~AccCaretMoveEvent() {}
|
||||
|
||||
// AccEvent
|
||||
|
@ -368,11 +370,14 @@ class AccCaretMoveEvent : public AccEvent {
|
|||
bool IsSelectionCollapsed() const { return mIsSelectionCollapsed; }
|
||||
bool IsAtEndOfLine() { return mIsAtEndOfLine; }
|
||||
|
||||
int32_t GetGranularity() const { return mGranularity; }
|
||||
|
||||
private:
|
||||
int32_t mCaretOffset;
|
||||
|
||||
bool mIsSelectionCollapsed;
|
||||
bool mIsAtEndOfLine;
|
||||
int32_t mGranularity;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -381,7 +386,8 @@ class AccCaretMoveEvent : public AccEvent {
|
|||
class AccTextSelChangeEvent : public AccEvent {
|
||||
public:
|
||||
AccTextSelChangeEvent(HyperTextAccessible* aTarget,
|
||||
dom::Selection* aSelection, int32_t aReason);
|
||||
dom::Selection* aSelection, int32_t aReason,
|
||||
int32_t aGranularity);
|
||||
virtual ~AccTextSelChangeEvent();
|
||||
|
||||
// AccEvent
|
||||
|
@ -397,6 +403,8 @@ class AccTextSelChangeEvent : public AccEvent {
|
|||
*/
|
||||
bool IsCaretMoveOnly() const;
|
||||
|
||||
int32_t GetGranularity() const { return mGranularity; }
|
||||
|
||||
/**
|
||||
* Return selection ranges in document/control.
|
||||
*/
|
||||
|
@ -405,6 +413,7 @@ class AccTextSelChangeEvent : public AccEvent {
|
|||
private:
|
||||
RefPtr<dom::Selection> mSel;
|
||||
int32_t mReason;
|
||||
int32_t mGranularity;
|
||||
|
||||
friend class EventQueue;
|
||||
friend class SelectionManager;
|
||||
|
|
|
@ -104,10 +104,11 @@ void ProxyStateChangeEvent(RemoteAccessible* aTarget, uint64_t aState,
|
|||
void ProxyFocusEvent(RemoteAccessible* aTarget,
|
||||
const LayoutDeviceIntRect& aCaretRect);
|
||||
void ProxyCaretMoveEvent(RemoteAccessible* aTarget,
|
||||
const LayoutDeviceIntRect& aCaretRect);
|
||||
const LayoutDeviceIntRect& aCaretRect,
|
||||
int32_t aGranularity);
|
||||
#else
|
||||
void ProxyCaretMoveEvent(RemoteAccessible* aTarget, int32_t aOffset,
|
||||
bool aIsSelectionCollapsed);
|
||||
bool aIsSelectionCollapsed, int32_t aGranularity);
|
||||
#endif
|
||||
void ProxyTextChangeEvent(RemoteAccessible* aTarget, const nsString& aStr,
|
||||
int32_t aStart, uint32_t aLen, bool aIsInsert,
|
||||
|
|
|
@ -24,10 +24,12 @@ using namespace mozilla::a11y;
|
|||
using mozilla::dom::Selection;
|
||||
|
||||
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;
|
||||
int16_t mReason;
|
||||
int32_t mGranularity;
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(SelData)
|
||||
|
||||
|
@ -148,17 +150,18 @@ void SelectionManager::ProcessTextSelChangeEvent(AccEvent* aEvent) {
|
|||
selection->FocusOffset());
|
||||
mAccWithCaret = caretCntr;
|
||||
if (mCaretOffset != -1) {
|
||||
RefPtr<AccCaretMoveEvent> caretMoveEvent = new AccCaretMoveEvent(
|
||||
caretCntr, mCaretOffset, selection->IsCollapsed(),
|
||||
caretCntr->IsCaretAtEndOfLine(), aEvent->FromUserInput());
|
||||
RefPtr<AccCaretMoveEvent> caretMoveEvent =
|
||||
new AccCaretMoveEvent(caretCntr, mCaretOffset, selection->IsCollapsed(),
|
||||
caretCntr->IsCaretAtEndOfLine(),
|
||||
event->GetGranularity(), aEvent->FromUserInput());
|
||||
nsEventShell::FireEvent(caretMoveEvent);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SelectionManager::NotifySelectionChanged(dom::Document* aDocument,
|
||||
Selection* aSelection,
|
||||
int16_t aReason) {
|
||||
Selection* aSelection, int16_t aReason,
|
||||
int32_t aAmount) {
|
||||
if (NS_WARN_IF(!aDocument) || NS_WARN_IF(!aSelection)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
@ -175,7 +178,7 @@ SelectionManager::NotifySelectionChanged(dom::Document* aDocument,
|
|||
// Selection manager has longer lifetime than any document accessible,
|
||||
// so that we are guaranteed that the notification is processed before
|
||||
// the selection manager is destroyed.
|
||||
RefPtr<SelData> selData = new SelData(aSelection, aReason);
|
||||
RefPtr<SelData> selData = new SelData(aSelection, aReason, aAmount);
|
||||
document->HandleNotification<SelectionManager, SelData>(
|
||||
this, &SelectionManager::ProcessSelectionChanged, selData);
|
||||
}
|
||||
|
@ -211,8 +214,8 @@ void SelectionManager::ProcessSelectionChanged(SelData* aSelData) {
|
|||
}
|
||||
|
||||
if (selection->GetType() == SelectionType::eNormal) {
|
||||
RefPtr<AccEvent> event =
|
||||
new AccTextSelChangeEvent(text, selection, aSelData->mReason);
|
||||
RefPtr<AccEvent> event = new AccTextSelChangeEvent(
|
||||
text, selection, aSelData->mReason, aSelData->mGranularity);
|
||||
text->Document()->FireDelayedEvent(event);
|
||||
|
||||
} else if (selection->GetType() == SelectionType::eSpellCheck) {
|
||||
|
|
|
@ -934,9 +934,9 @@ nsresult LocalAccessible::HandleAccEvent(AccEvent* aEvent) {
|
|||
}
|
||||
case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED: {
|
||||
AccCaretMoveEvent* event = downcast_accEvent(aEvent);
|
||||
ipcDoc->SendCaretMoveEvent(id, event->GetCaretOffset(),
|
||||
event->IsSelectionCollapsed(),
|
||||
event->IsAtEndOfLine());
|
||||
ipcDoc->SendCaretMoveEvent(
|
||||
id, event->GetCaretOffset(), event->IsSelectionCollapsed(),
|
||||
event->IsAtEndOfLine(), event->GetGranularity());
|
||||
break;
|
||||
}
|
||||
case nsIAccessibleEvent::EVENT_TEXT_INSERTED:
|
||||
|
|
|
@ -25,4 +25,9 @@ interface nsIAccessibleCaretMoveEvent: nsIAccessibleEvent
|
|||
* Return true if the caret is at the end of a line.
|
||||
*/
|
||||
readonly attribute bool isAtEndOfLine;
|
||||
|
||||
/**
|
||||
* Return caret move granularity.
|
||||
*/
|
||||
readonly attribute long granularity;
|
||||
};
|
||||
|
|
|
@ -341,7 +341,7 @@ mozilla::ipc::IPCResult DocAccessibleParent::RecvCaretMoveEvent(
|
|||
const LayoutDeviceIntRect& aCaretRect,
|
||||
#endif // defined (XP_WIN)
|
||||
const int32_t& aOffset, const bool& aIsSelectionCollapsed,
|
||||
const bool& aIsAtEndOfLine) {
|
||||
const bool& aIsAtEndOfLine, const int32_t& aGranularity) {
|
||||
if (mShutdown) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
@ -364,9 +364,9 @@ mozilla::ipc::IPCResult DocAccessibleParent::RecvCaretMoveEvent(
|
|||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
ProxyCaretMoveEvent(proxy, aCaretRect);
|
||||
ProxyCaretMoveEvent(proxy, aCaretRect, aGranularity);
|
||||
#else
|
||||
ProxyCaretMoveEvent(proxy, aOffset, aIsSelectionCollapsed);
|
||||
ProxyCaretMoveEvent(proxy, aOffset, aIsSelectionCollapsed, aGranularity);
|
||||
#endif
|
||||
|
||||
if (!nsCoreUtils::AccEventObserversExist()) {
|
||||
|
@ -378,9 +378,9 @@ mozilla::ipc::IPCResult DocAccessibleParent::RecvCaretMoveEvent(
|
|||
nsINode* node = nullptr;
|
||||
bool fromUser = true; // XXX fix me
|
||||
uint32_t type = nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED;
|
||||
RefPtr<xpcAccCaretMoveEvent> event =
|
||||
new xpcAccCaretMoveEvent(type, xpcAcc, doc, node, fromUser, aOffset,
|
||||
aIsSelectionCollapsed, aIsAtEndOfLine);
|
||||
RefPtr<xpcAccCaretMoveEvent> event = new xpcAccCaretMoveEvent(
|
||||
type, xpcAcc, doc, node, fromUser, aOffset, aIsSelectionCollapsed,
|
||||
aIsAtEndOfLine, aGranularity);
|
||||
nsCoreUtils::DispatchAccEvent(std::move(event));
|
||||
|
||||
return IPC_OK();
|
||||
|
|
|
@ -108,7 +108,7 @@ class DocAccessibleParent : public RemoteAccessible,
|
|||
const LayoutDeviceIntRect& aCaretRect,
|
||||
#endif
|
||||
const int32_t& aOffset, const bool& aIsSelectionCollapsed,
|
||||
const bool& aIsAtEndOfLine) final;
|
||||
const bool& aIsAtEndOfLine, const int32_t& aGranularity) final;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvTextChangeEvent(
|
||||
const uint64_t& aID, const nsString& aStr, const int32_t& aStart,
|
||||
|
|
|
@ -99,7 +99,8 @@ parent:
|
|||
async HideEvent(uint64_t aRootID, bool aFromUser);
|
||||
async StateChangeEvent(uint64_t aID, uint64_t aState, bool aEnabled);
|
||||
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,
|
||||
bool aIsInsert, bool aFromUser);
|
||||
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,
|
||||
const int32_t& aOffset,
|
||||
const bool& aIsSelectionCollapsed,
|
||||
const bool& aIsAtEndOfLine) {
|
||||
const bool& aIsAtEndOfLine,
|
||||
const int32_t& aGranularity) {
|
||||
return SendCaretMoveEvent(aID, GetCaretRectFor(aID), aOffset,
|
||||
aIsSelectionCollapsed, aIsAtEndOfLine);
|
||||
aIsSelectionCollapsed, aIsAtEndOfLine,
|
||||
aGranularity);
|
||||
}
|
||||
|
||||
bool DocAccessibleChild::SendCaretMoveEvent(
|
||||
const uint64_t& aID, const LayoutDeviceIntRect& aCaretRect,
|
||||
const int32_t& aOffset, const bool& aIsSelectionCollapsed,
|
||||
const bool& aIsAtEndOfLine) {
|
||||
const bool& aIsAtEndOfLine, const int32_t& aGranularity) {
|
||||
if (IsConstructedInParentProcess()) {
|
||||
return PDocAccessibleChild::SendCaretMoveEvent(
|
||||
aID, aCaretRect, aOffset, aIsSelectionCollapsed, aIsAtEndOfLine);
|
||||
aID, aCaretRect, aOffset, aIsSelectionCollapsed, aIsAtEndOfLine,
|
||||
aGranularity);
|
||||
}
|
||||
|
||||
PushDeferredEvent(MakeUnique<SerializedCaretMove>(
|
||||
this, aID, aCaretRect, aOffset, aIsSelectionCollapsed, aIsAtEndOfLine));
|
||||
this, aID, aCaretRect, aOffset, aIsSelectionCollapsed, aIsAtEndOfLine,
|
||||
aGranularity));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -52,12 +52,14 @@ class DocAccessibleChild : public DocAccessibleChildBase {
|
|||
const bool& aEnabled);
|
||||
bool SendCaretMoveEvent(const uint64_t& aID, const int32_t& aOffset,
|
||||
const bool& aIsSelectionCollapsed,
|
||||
const bool& aIsAtEndOfLine);
|
||||
const bool& aIsAtEndOfLine,
|
||||
const int32_t& aGranularity);
|
||||
bool SendCaretMoveEvent(const uint64_t& aID,
|
||||
const LayoutDeviceIntRect& aCaretRect,
|
||||
const int32_t& aOffset,
|
||||
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,
|
||||
const LayoutDeviceIntRect& aCaretRect);
|
||||
|
@ -175,17 +177,20 @@ class DocAccessibleChild : public DocAccessibleChildBase {
|
|||
struct SerializedCaretMove final : public DeferredEvent {
|
||||
SerializedCaretMove(DocAccessibleChild* aTarget, uint64_t aID,
|
||||
const LayoutDeviceIntRect& aCaretRect, int32_t aOffset,
|
||||
bool aIsSelectionCollapsed, bool aIsAtEndOfLine)
|
||||
bool aIsSelectionCollapsed, bool aIsAtEndOfLine,
|
||||
int32_t aGranularity)
|
||||
: DeferredEvent(aTarget),
|
||||
mID(aID),
|
||||
mCaretRect(aCaretRect),
|
||||
mOffset(aOffset),
|
||||
mIsSelectionCollapsed(aIsSelectionCollapsed),
|
||||
mIsAtEndOfLine(aIsAtEndOfLine) {}
|
||||
mIsAtEndOfLine(aIsAtEndOfLine),
|
||||
mGranularity(aGranularity) {}
|
||||
|
||||
void Dispatch(DocAccessibleChild* aIPCDoc) override {
|
||||
Unused << aIPCDoc->SendCaretMoveEvent(
|
||||
mID, mCaretRect, mOffset, mIsSelectionCollapsed, mIsAtEndOfLine);
|
||||
Unused << aIPCDoc->SendCaretMoveEvent(mID, mCaretRect, mOffset,
|
||||
mIsSelectionCollapsed,
|
||||
mIsAtEndOfLine, mGranularity);
|
||||
}
|
||||
|
||||
uint64_t mID;
|
||||
|
@ -193,6 +198,7 @@ class DocAccessibleChild : public DocAccessibleChildBase {
|
|||
int32_t mOffset;
|
||||
bool mIsSelectionCollapsed;
|
||||
bool mIsAtEndOfLine;
|
||||
int32_t mGranularity;
|
||||
};
|
||||
|
||||
struct SerializedFocus final : public DeferredEvent {
|
||||
|
|
|
@ -70,7 +70,7 @@ parent:
|
|||
async StateChangeEvent(uint64_t aID, uint64_t aState, bool aEnabled);
|
||||
async CaretMoveEvent(uint64_t aID, LayoutDeviceIntRect aCaretRect,
|
||||
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,
|
||||
bool aIsInsert, bool aFromUser);
|
||||
sync SyncTextChangeEvent(uint64_t aID, nsString aStr, int32_t aStart,
|
||||
|
|
|
@ -226,7 +226,9 @@ nsresult AccessibleWrap::HandleAccEvent(AccEvent* aEvent) {
|
|||
int32_t caretOffset = event->GetCaretOffset();
|
||||
MOXTextMarkerDelegate* delegate =
|
||||
[MOXTextMarkerDelegate getOrCreateForDoc:aEvent->Document()];
|
||||
[delegate setCaretOffset:eventTarget at:caretOffset];
|
||||
[delegate setCaretOffset:eventTarget
|
||||
at:caretOffset
|
||||
moveGranularity:event->GetGranularity()];
|
||||
if (event->IsSelectionCollapsed()) {
|
||||
// If the selection is collapsed, invalidate our text selection cache.
|
||||
[delegate setSelectionFrom:eventTarget
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
AXTextMarkerRangeRef mSelection;
|
||||
AXTextMarkerRef mCaret;
|
||||
AXTextMarkerRef mPrevCaret;
|
||||
int32_t mCaretMoveGranularity;
|
||||
}
|
||||
|
||||
+ (id)getOrCreateForDoc:(mozilla::a11y::Accessible*)aDoc;
|
||||
|
@ -30,7 +31,9 @@
|
|||
to:(mozilla::a11y::Accessible*)endContainer
|
||||
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;
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "mozAccessible.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsISelectionListener.h"
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
|
@ -52,6 +53,8 @@ static nsTHashMap<nsPtrHashKey<mozilla::a11y::Accessible>,
|
|||
mGeckoDocAccessible = aDoc;
|
||||
}
|
||||
|
||||
mCaretMoveGranularity = nsISelectionListener::NO_AMOUNT;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -76,11 +79,14 @@ static nsTHashMap<nsPtrHashKey<mozilla::a11y::Accessible>,
|
|||
}
|
||||
|
||||
- (void)setCaretOffset:(mozilla::a11y::Accessible*)container
|
||||
at:(int32_t)offset {
|
||||
at:(int32_t)offset
|
||||
moveGranularity:(int32_t)granularity {
|
||||
GeckoTextMarker caretMarker(container, offset);
|
||||
|
||||
mPrevCaret = mCaret;
|
||||
mCaret = caretMarker.CreateAXTextMarker();
|
||||
mCaretMoveGranularity = granularity;
|
||||
|
||||
CFRetain(mCaret);
|
||||
}
|
||||
|
||||
|
@ -146,21 +152,43 @@ static nsTHashMap<nsPtrHashKey<mozilla::a11y::Accessible>,
|
|||
}
|
||||
|
||||
bool isForward = prevCaretMarker < caretMarker;
|
||||
uint32_t deltaLength =
|
||||
GeckoTextMarkerRange(isForward ? prevCaretMarker : caretMarker,
|
||||
isForward ? caretMarker : prevCaretMarker)
|
||||
.Length();
|
||||
int direction = isForward ? AXTextSelectionDirectionNext
|
||||
: AXTextSelectionDirectionPrevious;
|
||||
|
||||
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.
|
||||
// If the delta between the two markers is more than one, consider it
|
||||
// a word. Not accurate, but good enough for VO.
|
||||
[info addEntriesFromDictionary:@{
|
||||
@"AXTextSelectionDirection" : isForward
|
||||
? @(AXTextSelectionDirectionNext)
|
||||
: @(AXTextSelectionDirectionPrevious),
|
||||
@"AXTextSelectionGranularity" : deltaLength == 1
|
||||
? @(AXTextSelectionGranularityCharacter)
|
||||
: @(AXTextSelectionGranularityWord)
|
||||
@"AXTextSelectionDirection" : @(direction),
|
||||
@"AXTextSelectionGranularity" : @(granularity)
|
||||
}];
|
||||
|
||||
return info;
|
||||
|
|
|
@ -111,11 +111,11 @@ void ProxyStateChangeEvent(RemoteAccessible* aProxy, uint64_t aState,
|
|||
}
|
||||
|
||||
void ProxyCaretMoveEvent(RemoteAccessible* aTarget, int32_t aOffset,
|
||||
bool aIsSelectionCollapsed) {
|
||||
bool aIsSelectionCollapsed, int32_t aGranularity) {
|
||||
mozAccessible* wrapper = GetNativeFromGeckoAccessible(aTarget);
|
||||
MOXTextMarkerDelegate* delegate =
|
||||
[MOXTextMarkerDelegate getOrCreateForDoc:aTarget->Document()];
|
||||
[delegate setCaretOffset:aTarget at:aOffset];
|
||||
[delegate setCaretOffset:aTarget at:aOffset moveGranularity:aGranularity];
|
||||
if (aIsSelectionCollapsed) {
|
||||
// If selection is collapsed, invalidate selection.
|
||||
[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::ProxyCaretMoveEvent(RemoteAccessible* aTarget, int32_t aOffset,
|
||||
bool aIsSelectionCollapsed) {}
|
||||
bool aIsSelectionCollapsed,
|
||||
int32_t aGranularity) {}
|
||||
|
||||
void a11y::ProxyTextChangeEvent(RemoteAccessible*, const nsString&, int32_t,
|
||||
uint32_t, bool, bool) {}
|
||||
|
|
|
@ -8,6 +8,7 @@ support-files =
|
|||
environment =
|
||||
A11YLOG=doclifecycle,events,notifications
|
||||
|
||||
[browser_test_caret_move_granularity.js]
|
||||
[browser_test_docload.js]
|
||||
skip-if = e10s
|
||||
[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 input = getNativeInterface(accDoc, inputId);
|
||||
ok(!input.getAttributeValue("AXFocused"), "input is not focused");
|
||||
|
@ -249,6 +249,11 @@ async function focusIntoInputAndType(accDoc, inputId, innerContainerId) {
|
|||
]);
|
||||
input.setAttributeValue("AXFocused", true);
|
||||
await events;
|
||||
}
|
||||
|
||||
async function focusIntoInputAndType(accDoc, inputId, innerContainerId) {
|
||||
let selectionId = innerContainerId ? innerContainerId : inputId;
|
||||
await focusIntoInput(accDoc, inputId, innerContainerId);
|
||||
|
||||
async function testTextInput(
|
||||
synthKey,
|
||||
|
@ -337,14 +342,14 @@ async function focusIntoInputAndType(accDoc, inputId, innerContainerId) {
|
|||
{ AXTextStateChangeType: AXTextStateChangeTypeSelectionMove }
|
||||
);
|
||||
await synthKeyAndTestSelectionChanged(
|
||||
"KEY_Home",
|
||||
{ shiftKey: true },
|
||||
"KEY_ArrowLeft",
|
||||
{ shiftKey: true, metaKey: true },
|
||||
selectionId,
|
||||
"hello ",
|
||||
{
|
||||
AXTextStateChangeType: AXTextStateChangeTypeSelectionExtend,
|
||||
AXTextSelectionDirection: AXTextSelectionDirectionPrevious,
|
||||
AXTextSelectionGranularity: AXTextSelectionGranularityWord,
|
||||
AXTextSelectionDirection: AXTextSelectionDirectionBeginning,
|
||||
AXTextSelectionGranularity: AXTextSelectionGranularityLine,
|
||||
}
|
||||
);
|
||||
await synthKeyAndTestSelectionChanged(
|
||||
|
@ -372,7 +377,8 @@ addAccessibleTask(
|
|||
`<a href="#">link</a> <input id="input">`,
|
||||
async (browser, accDoc) => {
|
||||
await focusIntoInputAndType(accDoc, "input");
|
||||
}
|
||||
},
|
||||
{ topLevel: true, iframe: true, remoteIframe: true }
|
||||
);
|
||||
|
||||
// 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
|
||||
addAccessibleTask(`<input type="text" id="box">`, async (browser, accDoc) => {
|
||||
const box = getNativeInterface(accDoc, "box");
|
||||
|
@ -410,3 +407,48 @@ addAccessibleTask(`<input type="text" id="box">`, async (browser, accDoc) => {
|
|||
);
|
||||
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,
|
||||
AXTextSelectionDirectionPrevious, AXTextSelectionDirectionNext,
|
||||
AXTextSelectionDirectionDiscontiguous, AXTextSelectionGranularityUnknown,
|
||||
AXTextSelectionGranularityCharacter, AXTextSelectionGranularityWord */
|
||||
AXTextSelectionDirectionBeginning, AXTextSelectionDirectionEnd,
|
||||
AXTextSelectionGranularityCharacter, AXTextSelectionGranularityWord,
|
||||
AXTextSelectionGranularityLine */
|
||||
|
||||
// Load the shared-head file first.
|
||||
/* import-globals-from ../shared-head.js */
|
||||
|
@ -37,6 +39,8 @@ const AXTextEditTypeTyping = 3;
|
|||
|
||||
// AXTextSelectionDirection enum values
|
||||
const AXTextSelectionDirectionUnknown = 0;
|
||||
const AXTextSelectionDirectionBeginning = 1;
|
||||
const AXTextSelectionDirectionEnd = 2;
|
||||
const AXTextSelectionDirectionPrevious = 3;
|
||||
const AXTextSelectionDirectionNext = 4;
|
||||
const AXTextSelectionDirectionDiscontiguous = 5;
|
||||
|
@ -45,6 +49,7 @@ const AXTextSelectionDirectionDiscontiguous = 5;
|
|||
const AXTextSelectionGranularityUnknown = 0;
|
||||
const AXTextSelectionGranularityCharacter = 1;
|
||||
const AXTextSelectionGranularityWord = 2;
|
||||
const AXTextSelectionGranularityLine = 3;
|
||||
|
||||
function getNativeInterface(accDoc, id) {
|
||||
return findAccessibleChildByID(accDoc, id).nativeInterface.QueryInterface(
|
||||
|
|
|
@ -172,7 +172,8 @@ void a11y::ProxyFocusEvent(RemoteAccessible* aTarget,
|
|||
}
|
||||
|
||||
void a11y::ProxyCaretMoveEvent(RemoteAccessible* aTarget,
|
||||
const LayoutDeviceIntRect& aCaretRect) {
|
||||
const LayoutDeviceIntRect& aCaretRect,
|
||||
int32_t aGranularity) {
|
||||
AccessibleWrap::UpdateSystemCaretFor(aTarget, aCaretRect);
|
||||
MsaaAccessible::FireWinEvent(aTarget,
|
||||
nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED);
|
||||
|
|
|
@ -3198,6 +3198,8 @@ void Selection::NotifySelectionListeners() {
|
|||
reason |= nsISelectionListener::JS_REASON;
|
||||
}
|
||||
|
||||
int32_t amount = static_cast<int32_t>(frameSelection->GetCaretMoveAmount());
|
||||
|
||||
if (mNotifyAutoCopy) {
|
||||
AutoCopyListener::OnSelectionChange(doc, *this, reason);
|
||||
}
|
||||
|
@ -3218,7 +3220,7 @@ void Selection::NotifySelectionListeners() {
|
|||
//
|
||||
// This can go away once
|
||||
// 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.
|
||||
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]
|
||||
void notifySelectionChanged(in Document doc, in Selection sel,
|
||||
in short reason);
|
||||
in short reason, in long amount);
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
|
|
@ -195,18 +195,12 @@ nsresult CamerasParent::DispatchToVideoCaptureThread(RefPtr<Runnable> event) {
|
|||
// There's a potential deadlock because the sThreadMonitor is likely
|
||||
// to be taken already.
|
||||
MonitorAutoLock lock(*sThreadMonitor);
|
||||
MOZ_ASSERT(!sVideoCaptureThread ||
|
||||
sVideoCaptureThread->thread_id() != PlatformThread::CurrentId());
|
||||
|
||||
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");
|
||||
if (!sVideoCaptureThread) {
|
||||
LOG("Can't dispatch to video capture thread: thread not present");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
MOZ_ASSERT(sVideoCaptureThread->thread_id() != PlatformThread::CurrentId());
|
||||
|
||||
sVideoCaptureThread->message_loop()->PostTask(event.forget());
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -230,9 +224,7 @@ void CamerasParent::StopVideoCapture() {
|
|||
}
|
||||
nsresult rv = NS_DispatchToMainThread(NewRunnableFrom([self, thread]() {
|
||||
if (thread) {
|
||||
if (thread->IsRunning()) {
|
||||
thread->Stop();
|
||||
}
|
||||
thread->Stop();
|
||||
delete thread;
|
||||
}
|
||||
nsresult rv = MustGetShutdownBarrier()->RemoveBlocker(self);
|
||||
|
@ -1088,47 +1080,50 @@ NS_IMETHODIMP CamerasParent::BlockShutdown(nsIAsyncShutdownClient*) {
|
|||
CamerasParent::CamerasParent()
|
||||
: mName(GetNewName()),
|
||||
mShmemPool(CaptureEngine::MaxEngine),
|
||||
mPBackgroundEventTarget(GetCurrentSerialEventTarget()),
|
||||
mChildIsAlive(true),
|
||||
mDestroyed(false),
|
||||
mWebRTCAlive(true) {
|
||||
MOZ_ASSERT(mPBackgroundEventTarget != nullptr,
|
||||
"GetCurrentThreadEventTarget failed");
|
||||
LOG("CamerasParent: %p", this);
|
||||
StaticMutexAutoLock slock(sMutex);
|
||||
|
||||
if (sNumOfCamerasParents++ == 0) {
|
||||
sThreadMonitor = new Monitor("CamerasParent::sThreadMonitor");
|
||||
}
|
||||
}
|
||||
|
||||
mPBackgroundEventTarget = GetCurrentSerialEventTarget();
|
||||
MOZ_ASSERT(mPBackgroundEventTarget != nullptr,
|
||||
"GetCurrentThreadEventTarget failed");
|
||||
ipc::IPCResult CamerasParent::RecvPCamerasConstructor() {
|
||||
ipc::AssertIsOnBackgroundThread();
|
||||
|
||||
// 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");
|
||||
|
||||
RefPtr<CamerasParent> self(this);
|
||||
NS_DispatchToMainThread(NewRunnableFrom([self]() {
|
||||
nsresult rv = MustGetShutdownBarrier()->AddBlocker(
|
||||
self, NS_LITERAL_STRING_FROM_CSTRING(__FILE__), __LINE__, u""_ns);
|
||||
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;
|
||||
MonitorAutoLock lock(*sThreadMonitor);
|
||||
if (sVideoCaptureThread == nullptr) {
|
||||
MOZ_ASSERT(sNumOfOpenCamerasParentEngines == 0);
|
||||
sVideoCaptureThread = new base::Thread("VideoCapture");
|
||||
base::Thread::Options options;
|
||||
#if defined(_WIN32)
|
||||
options.message_loop_type = MessageLoop::TYPE_MOZILLA_NONMAINUITHREAD;
|
||||
options.message_loop_type = MessageLoop::TYPE_MOZILLA_NONMAINUITHREAD;
|
||||
#else
|
||||
options.message_loop_type = MessageLoop::TYPE_MOZILLA_NONMAINTHREAD;
|
||||
options.message_loop_type = MessageLoop::TYPE_MOZILLA_NONMAINTHREAD;
|
||||
#endif
|
||||
if (!self->sVideoCaptureThread->StartWithOptions(options)) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
if (!sVideoCaptureThread->StartWithOptions(options)) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
sNumOfOpenCamerasParentEngines++;
|
||||
self->sThreadMonitor->NotifyAll();
|
||||
return NS_OK;
|
||||
}));
|
||||
}
|
||||
sNumOfOpenCamerasParentEngines++;
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
CamerasParent::~CamerasParent() {
|
||||
|
|
|
@ -72,7 +72,8 @@ class CamerasParent final : public PCamerasParent,
|
|||
|
||||
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(
|
||||
const CaptureEngine& aEngine, const nsCString& aUnique_idUTF8,
|
||||
const uint64_t& aWindowID) override;
|
||||
|
@ -137,30 +138,29 @@ class CamerasParent final : public PCamerasParent,
|
|||
static nsString GetNewName();
|
||||
|
||||
// sEngines will be accessed by VideoCapture thread only
|
||||
// sNumOfCamerasParent, sNumOfOpenCamerasParentEngines, and
|
||||
// sNumOfCamerasParents, sNumOfOpenCamerasParentEngines, and
|
||||
// sVideoCaptureThread will be accessed by main thread / PBackground thread /
|
||||
// VideoCapture thread
|
||||
// sNumOfCamerasParent and sThreadMonitor create & delete are protected by
|
||||
// sNumOfCamerasParents and sThreadMonitor create & delete are protected by
|
||||
// sMutex
|
||||
// sNumOfOpenCamerasParentEngines and sVideoCaptureThread are protected by
|
||||
// sThreadMonitor
|
||||
static StaticRefPtr<VideoEngine> sEngines[CaptureEngine::MaxEngine];
|
||||
static int32_t sNumOfOpenCamerasParentEngines;
|
||||
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;
|
||||
nsString mName;
|
||||
|
||||
// image buffers
|
||||
ShmemPool mShmemPool;
|
||||
|
||||
// PBackground parent thread
|
||||
nsCOMPtr<nsISerialEventTarget> mPBackgroundEventTarget;
|
||||
|
||||
static StaticMutex sMutex;
|
||||
static Monitor* sThreadMonitor;
|
||||
|
||||
// video processing thread - where webrtc.org capturer code runs
|
||||
static base::Thread* sVideoCaptureThread;
|
||||
// PBackgroundParent thread
|
||||
const nsCOMPtr<nsISerialEventTarget> mPBackgroundEventTarget;
|
||||
|
||||
// Shutdown handling
|
||||
bool mChildIsAlive;
|
||||
|
|
|
@ -2178,7 +2178,8 @@ nsresult EditorBase::DeleteNodeWithTransaction(nsIContent& aContent) {
|
|||
|
||||
NS_IMETHODIMP EditorBase::NotifySelectionChanged(Document* aDocument,
|
||||
Selection* aSelection,
|
||||
int16_t aReason) {
|
||||
int16_t aReason,
|
||||
int32_t aAmount) {
|
||||
if (NS_WARN_IF(!aDocument) || NS_WARN_IF(!aSelection)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
|
|
@ -554,7 +554,8 @@ bool HTMLEditor::UpdateMetaCharsetWithTransaction(
|
|||
|
||||
NS_IMETHODIMP HTMLEditor::NotifySelectionChanged(Document* aDocument,
|
||||
Selection* aSelection,
|
||||
int16_t aReason) {
|
||||
int16_t aReason,
|
||||
int32_t aAmount) {
|
||||
if (NS_WARN_IF(!aDocument) || NS_WARN_IF(!aSelection)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
@ -593,8 +594,8 @@ NS_IMETHODIMP HTMLEditor::NotifySelectionChanged(Document* aDocument,
|
|||
updater->OnSelectionChange();
|
||||
}
|
||||
|
||||
nsresult rv =
|
||||
EditorBase::NotifySelectionChanged(aDocument, aSelection, aReason);
|
||||
nsresult rv = EditorBase::NotifySelectionChanged(aDocument, aSelection,
|
||||
aReason, aAmount);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"EditorBase::NotifySelectionChanged() failed");
|
||||
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
|
||||
// notification actually comes here.
|
||||
let selectionListener = {
|
||||
notifySelectionChanged(aDocument, aSelection, aReason) {
|
||||
notifySelectionChanged(aDocument, aSelection, aReason, aAmount) {
|
||||
ok(true, "selectionStart: " + textarea.selectionStart);
|
||||
ok(true, "selectionEnd: " + textarea.selectionEnd);
|
||||
},
|
||||
|
|
|
@ -1713,8 +1713,9 @@ struct NewLayerData {
|
|||
ScrollableLayerGuid::ViewID mDeferredId = ScrollableLayerGuid::NULL_SCROLL_ID;
|
||||
bool mTransformShouldGetOwnLayer = false;
|
||||
|
||||
void ComputeDeferredTransformInfo(const StackingContextHelper& aSc,
|
||||
nsDisplayItem* aItem) {
|
||||
void ComputeDeferredTransformInfo(
|
||||
const StackingContextHelper& aSc, nsDisplayItem* aItem,
|
||||
nsDisplayTransform* aLastDeferredTransform) {
|
||||
// See the comments on StackingContextHelper::mDeferredTransformItem
|
||||
// for an overview of what deferred transforms are.
|
||||
// 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
|
||||
// holds the scroll metadata for the child's ASR.
|
||||
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) {
|
||||
// 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,
|
||||
|
@ -1890,7 +1899,10 @@ void WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList(
|
|||
newLayerData->mLayerCountBeforeRecursing = mLayerScrollData.size();
|
||||
newLayerData->mStopAtAsr =
|
||||
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
|
||||
// |stopAtAsr|, otherwise we could get cyclic scroll metadata
|
||||
|
@ -1910,6 +1922,13 @@ void WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList(
|
|||
newLayerData->mDeferredItem->GetActiveScrolledRoot());
|
||||
}
|
||||
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)
|
||||
mAsrStack.pop_back();
|
||||
|
||||
if (newLayerData->mDeferredItem) {
|
||||
MOZ_ASSERT(!mDeferredTransformStack.empty());
|
||||
mDeferredTransformStack.pop_back();
|
||||
}
|
||||
|
||||
const ActiveScrolledRoot* stopAtAsr = newLayerData->mStopAtAsr;
|
||||
|
||||
int32_t descendants =
|
||||
|
|
|
@ -215,6 +215,9 @@ class WebRenderCommandBuilder final {
|
|||
// need this so that WebRenderLayerScrollData items that deeper in the
|
||||
// tree don't duplicate scroll metadata that their ancestors already have.
|
||||
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;
|
||||
|
||||
WebRenderUserDataRefTable mWebRenderUserDatas;
|
||||
|
|
|
@ -726,6 +726,16 @@ camera::PCamerasParent* BackgroundParentImpl::AllocPCamerasParent() {
|
|||
#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(
|
||||
camera::PCamerasParent* aActor) {
|
||||
AssertIsInMainOrSocketProcess();
|
||||
|
|
|
@ -254,7 +254,10 @@ class BackgroundParentImpl : public PBackgroundParent,
|
|||
PServiceWorkerManagerParent* aActor) override;
|
||||
|
||||
PCamerasParent* AllocPCamerasParent() override;
|
||||
|
||||
#ifdef MOZ_WEBRTC
|
||||
mozilla::ipc::IPCResult RecvPCamerasConstructor(
|
||||
PCamerasParent* aActor) override;
|
||||
#endif
|
||||
bool DeallocPCamerasParent(PCamerasParent* aActor) 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 1729581.html
|
||||
load 1734007.html
|
||||
asserts-if(Android,0-1000) load 1749190.html
|
||||
load 1745860.html
|
||||
pref(layout.accessiblecaret.enabled,true) load 1746989.html
|
||||
load 1752649.html
|
||||
load 1753779.html
|
||||
pref(layout.css.backdrop-filter.enabled,true) load 1755790.html
|
||||
|
|
|
@ -569,8 +569,8 @@ void nsCaret::PaintCaret(DrawTarget& aDrawTarget, nsIFrame* aForFrame,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCaret::NotifySelectionChanged(Document*, Selection* aDomSel,
|
||||
int16_t aReason) {
|
||||
nsCaret::NotifySelectionChanged(Document*, Selection* aDomSel, int16_t aReason,
|
||||
int32_t aAmount) {
|
||||
// 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
|
||||
// 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(
|
||||
Document*, Selection*, int16_t aReason) {
|
||||
Document*, Selection*, int16_t aReason, int32_t aAmount) {
|
||||
if (!mDocViewer) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -729,6 +729,8 @@ nsresult nsFrameSelection::MoveCaret(nsDirection aDirection,
|
|||
SetChangeReasons(nsISelectionListener::KEYPRESS_REASON);
|
||||
}
|
||||
|
||||
mCaretMoveAmount = aAmount;
|
||||
|
||||
AutoPrepareFocusRange prep(sel, false);
|
||||
|
||||
// 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) {
|
||||
AddChangeReasons(aReasons);
|
||||
mCaretMoveAmount = eSelectNoAmount;
|
||||
mBatching.mChangesDuringBatching = false;
|
||||
// Be aware, the Selection instance may be destroyed after this call.
|
||||
NotifySelectionListeners(SelectionType::eNormal);
|
||||
|
@ -2182,6 +2185,7 @@ nsresult nsFrameSelection::NotifySelectionListeners(
|
|||
if (index >= 0 && mDomSelections[index]) {
|
||||
RefPtr<Selection> selection = mDomSelections[index];
|
||||
selection->NotifySelectionListeners();
|
||||
mCaretMoveAmount = eSelectNoAmount;
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
|
|
|
@ -829,6 +829,8 @@ class nsFrameSelection final {
|
|||
return retval;
|
||||
}
|
||||
|
||||
nsSelectionAmount GetCaretMoveAmount() { return mCaretMoveAmount; }
|
||||
|
||||
bool IsUserSelectionReason() const {
|
||||
return (mSelectionChangeReasons &
|
||||
(nsISelectionListener::DRAG_REASON |
|
||||
|
@ -1047,6 +1049,7 @@ class nsFrameSelection final {
|
|||
int16_t mSelectionChangeReasons = nsISelectionListener::NO_REASON;
|
||||
// For visual display purposes.
|
||||
int16_t mDisplaySelection = nsISelectionController::SELECTION_OFF;
|
||||
nsSelectionAmount mCaretMoveAmount = eSelectNoAmount;
|
||||
|
||||
struct Caret {
|
||||
// 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 {
|
||||
-moz-user-input: none !important;
|
||||
}
|
||||
|
||||
input[type=file] {
|
||||
height: 2em;
|
||||
}
|
||||
}
|
||||
|
||||
progress {
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
#include "SandboxTestingChild.h"
|
||||
|
||||
#include "mozilla/StaticPrefs_security.h"
|
||||
#ifdef XP_MACOSX
|
||||
# include "nsCocoaFeatures.h"
|
||||
#endif
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
#ifdef XP_UNIX
|
||||
|
@ -36,7 +39,12 @@
|
|||
#endif
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
# include <spawn.h>
|
||||
# include <CoreFoundation/CoreFoundation.h>
|
||||
# include <CoreGraphics/CoreGraphics.h>
|
||||
namespace ApplicationServices {
|
||||
# include <ApplicationServices/ApplicationServices.h>
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
|
@ -146,6 +154,86 @@ static void FileTest(const nsCString& aName, const char* aSpecialDirName,
|
|||
}
|
||||
#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) {
|
||||
MOZ_ASSERT(child, "No SandboxTestingChild*?");
|
||||
|
||||
|
@ -296,18 +384,8 @@ void RunTestsContent(SandboxTestingChild* child) {
|
|||
# endif // XP_LINUX
|
||||
|
||||
# ifdef XP_MACOSX
|
||||
// Test that content processes can not connect to the macOS window server.
|
||||
// CGSessionCopyCurrentDictionary() returns NULL when a connection to the
|
||||
// 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);
|
||||
}
|
||||
RunMacTestLaunchProcess(child, EPERM);
|
||||
RunMacTestWindowServer(child);
|
||||
# endif
|
||||
|
||||
#elif XP_WIN
|
||||
|
@ -385,9 +463,11 @@ void RunTestsSocket(SandboxTestingChild* child) {
|
|||
child->ErrnoTest("getcpu"_ns, true,
|
||||
[&] { return syscall(SYS_getcpu, &c, NULL, NULL); });
|
||||
# endif // XP_LINUX
|
||||
|
||||
#elif XP_MACOSX
|
||||
RunMacTestLaunchProcess(child);
|
||||
RunMacTestWindowServer(child);
|
||||
#else // XP_UNIX
|
||||
child->ReportNoTests();
|
||||
child->ReportNoTests();
|
||||
#endif // XP_UNIX
|
||||
}
|
||||
|
||||
|
@ -440,8 +520,11 @@ void RunTestsRDD(SandboxTestingChild* child) {
|
|||
int c;
|
||||
child->ErrnoTest("getcpu"_ns, true,
|
||||
[&] { return syscall(SYS_getcpu, &c, NULL, NULL); });
|
||||
# endif // XP_LINUX
|
||||
#else // XP_UNIX
|
||||
# elif XP_MACOSX
|
||||
RunMacTestLaunchProcess(child);
|
||||
RunMacTestWindowServer(child);
|
||||
# endif
|
||||
#else // XP_UNIX
|
||||
child->ReportNoTests();
|
||||
#endif
|
||||
}
|
||||
|
@ -487,8 +570,12 @@ void RunTestsGMPlugin(SandboxTestingChild* child) {
|
|||
return fd;
|
||||
});
|
||||
}
|
||||
# endif // XP_LINUX
|
||||
#else // XP_UNIX
|
||||
# elif XP_MACOSX // XP_LINUX
|
||||
RunMacTestLaunchProcess(child);
|
||||
/* The Mac GMP process requires access to the window server */
|
||||
RunMacTestWindowServer(child, true /* aShouldHaveAccess */);
|
||||
# endif // XP_MACOSX
|
||||
#else // XP_UNIX
|
||||
child->ReportNoTests();
|
||||
#endif
|
||||
}
|
||||
|
@ -508,9 +595,11 @@ void RunTestsUtility(SandboxTestingChild* child) {
|
|||
int rv = getrusage(RUSAGE_SELF, &res);
|
||||
return rv;
|
||||
});
|
||||
# endif // XP_LINUX
|
||||
#else // XP_UNIX
|
||||
# ifdef XP_WIN
|
||||
# elif XP_MACOSX // XP_LINUX
|
||||
RunMacTestLaunchProcess(child);
|
||||
RunMacTestWindowServer(child);
|
||||
# endif // XP_MACOSX
|
||||
#elif XP_WIN // XP_UNIX
|
||||
child->ErrnoValueTest("write_only"_ns, EACCES, [&] {
|
||||
FILE* rv = fopen("test_sandbox.txt", "w");
|
||||
if (rv != nullptr) {
|
||||
|
@ -519,10 +608,9 @@ void RunTestsUtility(SandboxTestingChild* child) {
|
|||
}
|
||||
return -1;
|
||||
});
|
||||
# else // XP_WIN
|
||||
child->ReportNoTests();
|
||||
# endif // XP_WIN
|
||||
#endif
|
||||
#else // XP_UNIX
|
||||
child->ReportNoTests();
|
||||
#endif // XP_MACOSX
|
||||
}
|
||||
|
||||
} // 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>
|
Загрузка…
Ссылка в новой задаче