mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 07:13:20 +00:00
Merge mozilla-central to autoland
This commit is contained in:
commit
2ecf173b14
@ -20,20 +20,12 @@
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
AccessibleWrap::
|
||||
AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc) :
|
||||
Accessible(aContent, aDoc), mNativeObject(nil),
|
||||
mNativeInited(false)
|
||||
{
|
||||
}
|
||||
AccessibleWrap::AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc)
|
||||
: Accessible(aContent, aDoc), mNativeObject(nil), mNativeInited(false) {}
|
||||
|
||||
AccessibleWrap::~AccessibleWrap()
|
||||
{
|
||||
}
|
||||
AccessibleWrap::~AccessibleWrap() {}
|
||||
|
||||
mozAccessible*
|
||||
AccessibleWrap::GetNativeObject()
|
||||
{
|
||||
mozAccessible* AccessibleWrap::GetNativeObject() {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
if (!mNativeInited && !mNativeObject && !IsDefunct() && !AncestorIsFlat()) {
|
||||
@ -48,30 +40,22 @@ AccessibleWrap::GetNativeObject()
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
void
|
||||
AccessibleWrap::GetNativeInterface(void** aOutInterface)
|
||||
{
|
||||
void AccessibleWrap::GetNativeInterface(void** aOutInterface) {
|
||||
*aOutInterface = static_cast<void*>(GetNativeObject());
|
||||
}
|
||||
|
||||
// overridden in subclasses to create the right kind of object. by default we create a generic
|
||||
// 'mozAccessible' node.
|
||||
Class
|
||||
AccessibleWrap::GetNativeType ()
|
||||
{
|
||||
Class AccessibleWrap::GetNativeType() {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
if (IsXULTabpanels())
|
||||
return [mozPaneAccessible class];
|
||||
if (IsXULTabpanels()) return [mozPaneAccessible class];
|
||||
|
||||
if (IsTable())
|
||||
return [mozTableAccessible class];
|
||||
if (IsTable()) return [mozTableAccessible class];
|
||||
|
||||
if (IsTableRow())
|
||||
return [mozTableRowAccessible class];
|
||||
if (IsTableRow()) return [mozTableRowAccessible class];
|
||||
|
||||
if (IsTableCell())
|
||||
return [mozTableCellAccessible class];
|
||||
if (IsTableCell()) return [mozTableCellAccessible class];
|
||||
|
||||
return GetTypeFromRole(Role());
|
||||
|
||||
@ -81,9 +65,7 @@ AccessibleWrap::GetNativeType ()
|
||||
// this method is very important. it is fired when an accessible object "dies". after this point
|
||||
// the object might still be around (because some 3rd party still has a ref to it), but it is
|
||||
// in fact 'dead'.
|
||||
void
|
||||
AccessibleWrap::Shutdown ()
|
||||
{
|
||||
void AccessibleWrap::Shutdown() {
|
||||
// this ensure we will not try to re-create the native object.
|
||||
mNativeInited = true;
|
||||
|
||||
@ -97,9 +79,7 @@ AccessibleWrap::Shutdown ()
|
||||
Accessible::Shutdown();
|
||||
}
|
||||
|
||||
nsresult
|
||||
AccessibleWrap::HandleAccEvent(AccEvent* aEvent)
|
||||
{
|
||||
nsresult AccessibleWrap::HandleAccEvent(AccEvent* aEvent) {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
nsresult rv = Accessible::HandleAccEvent(aEvent);
|
||||
@ -124,10 +104,9 @@ AccessibleWrap::HandleAccEvent(AccEvent* aEvent)
|
||||
Accessible* accessible = aEvent->GetAccessible();
|
||||
NS_ENSURE_STATE(accessible);
|
||||
|
||||
mozAccessible *nativeAcc = nil;
|
||||
mozAccessible* nativeAcc = nil;
|
||||
accessible->GetNativeInterface((void**)&nativeAcc);
|
||||
if (!nativeAcc)
|
||||
return NS_ERROR_FAILURE;
|
||||
if (!nativeAcc) return NS_ERROR_FAILURE;
|
||||
|
||||
FireNativeEvent(nativeAcc, eventType);
|
||||
|
||||
@ -136,23 +115,17 @@ AccessibleWrap::HandleAccEvent(AccEvent* aEvent)
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
||||
}
|
||||
|
||||
bool
|
||||
AccessibleWrap::InsertChildAt(uint32_t aIdx, Accessible* aAccessible)
|
||||
{
|
||||
bool AccessibleWrap::InsertChildAt(uint32_t aIdx, Accessible* aAccessible) {
|
||||
bool inserted = Accessible::InsertChildAt(aIdx, aAccessible);
|
||||
if (inserted && mNativeObject)
|
||||
[mNativeObject appendChild:aAccessible];
|
||||
if (inserted && mNativeObject) [mNativeObject appendChild:aAccessible];
|
||||
|
||||
return inserted;
|
||||
}
|
||||
|
||||
bool
|
||||
AccessibleWrap::RemoveChild(Accessible* aAccessible)
|
||||
{
|
||||
bool AccessibleWrap::RemoveChild(Accessible* aAccessible) {
|
||||
bool removed = Accessible::RemoveChild(aAccessible);
|
||||
|
||||
if (removed && mNativeObject)
|
||||
[mNativeObject invalidateChildren];
|
||||
if (removed && mNativeObject) [mNativeObject invalidateChildren];
|
||||
|
||||
return removed;
|
||||
}
|
||||
@ -160,9 +133,7 @@ AccessibleWrap::RemoveChild(Accessible* aAccessible)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AccessibleWrap protected
|
||||
|
||||
bool
|
||||
AccessibleWrap::AncestorIsFlat()
|
||||
{
|
||||
bool AccessibleWrap::AncestorIsFlat() {
|
||||
// We don't create a native object if we're child of a "flat" accessible;
|
||||
// for example, on OS X buttons shouldn't have any children, because that
|
||||
// makes the OS confused.
|
||||
@ -173,8 +144,7 @@ AccessibleWrap::AncestorIsFlat()
|
||||
|
||||
Accessible* parent = Parent();
|
||||
while (parent) {
|
||||
if (nsAccUtils::MustPrune(parent))
|
||||
return true;
|
||||
if (nsAccUtils::MustPrune(parent)) return true;
|
||||
|
||||
parent = parent->Parent();
|
||||
}
|
||||
@ -182,9 +152,7 @@ AccessibleWrap::AncestorIsFlat()
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
a11y::FireNativeEvent(mozAccessible* aNativeAcc, uint32_t aEventType)
|
||||
{
|
||||
void a11y::FireNativeEvent(mozAccessible* aNativeAcc, uint32_t aEventType) {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
// Under headless mode we don't have access to a native window, so we skip
|
||||
@ -213,18 +181,15 @@ a11y::FireNativeEvent(mozAccessible* aNativeAcc, uint32_t aEventType)
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
Class
|
||||
a11y::GetTypeFromRole(roles::Role aRole)
|
||||
{
|
||||
Class a11y::GetTypeFromRole(roles::Role aRole) {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
switch (aRole) {
|
||||
case roles::COMBOBOX:
|
||||
case roles::PUSHBUTTON:
|
||||
case roles::SPLITBUTTON:
|
||||
case roles::TOGGLE_BUTTON:
|
||||
{
|
||||
return [mozButtonAccessible class];
|
||||
case roles::TOGGLE_BUTTON: {
|
||||
return [mozButtonAccessible class];
|
||||
}
|
||||
|
||||
case roles::PAGETAB:
|
||||
|
@ -9,13 +9,7 @@
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
DocAccessibleWrap::
|
||||
DocAccessibleWrap(mozilla::dom::Document* aDocument, nsIPresShell* aPresShell) :
|
||||
DocAccessible(aDocument, aPresShell)
|
||||
{
|
||||
}
|
||||
|
||||
DocAccessibleWrap::~DocAccessibleWrap()
|
||||
{
|
||||
}
|
||||
DocAccessibleWrap::DocAccessibleWrap(mozilla::dom::Document* aDocument, nsIPresShell* aPresShell)
|
||||
: DocAccessible(aDocument, aPresShell) {}
|
||||
|
||||
DocAccessibleWrap::~DocAccessibleWrap() {}
|
||||
|
@ -18,9 +18,7 @@ namespace utils {
|
||||
* Get a localized string from the a11y string bundle.
|
||||
* Return nil if not found.
|
||||
*/
|
||||
NSString*
|
||||
LocalizedString(const nsString& aString)
|
||||
{
|
||||
NSString* LocalizedString(const nsString& aString) {
|
||||
nsString text;
|
||||
|
||||
Accessible::TranslateString(aString, text);
|
||||
|
@ -19,26 +19,17 @@ namespace a11y {
|
||||
// Mac a11y whitelisting
|
||||
static bool sA11yShouldBeEnabled = false;
|
||||
|
||||
bool
|
||||
ShouldA11yBeEnabled()
|
||||
{
|
||||
bool ShouldA11yBeEnabled() {
|
||||
EPlatformDisabledState disabledState = PlatformDisabledState();
|
||||
return (disabledState == ePlatformIsForceEnabled) || ((disabledState == ePlatformIsEnabled) && sA11yShouldBeEnabled);
|
||||
return (disabledState == ePlatformIsForceEnabled) ||
|
||||
((disabledState == ePlatformIsEnabled) && sA11yShouldBeEnabled);
|
||||
}
|
||||
|
||||
void
|
||||
PlatformInit()
|
||||
{
|
||||
}
|
||||
void PlatformInit() {}
|
||||
|
||||
void
|
||||
PlatformShutdown()
|
||||
{
|
||||
}
|
||||
void PlatformShutdown() {}
|
||||
|
||||
void
|
||||
ProxyCreated(ProxyAccessible* aProxy, uint32_t)
|
||||
{
|
||||
void ProxyCreated(ProxyAccessible* aProxy, uint32_t) {
|
||||
// Pass in dummy state for now as retrieving proxy state requires IPC.
|
||||
// Note that we can use ProxyAccessible::IsTable* functions here because they
|
||||
// do not use IPC calls but that might change after bug 1210477.
|
||||
@ -76,9 +67,7 @@ ProxyCreated(ProxyAccessible* aProxy, uint32_t)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ProxyDestroyed(ProxyAccessible* aProxy)
|
||||
{
|
||||
void ProxyDestroyed(ProxyAccessible* aProxy) {
|
||||
mozAccessible* nativeParent = nil;
|
||||
if (aProxy->IsDoc() && aProxy->AsDoc()->IsTopLevel()) {
|
||||
// Invalidate native parent in parent process's children on proxy destruction
|
||||
@ -108,9 +97,7 @@ ProxyDestroyed(ProxyAccessible* aProxy)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ProxyEvent(ProxyAccessible* aProxy, uint32_t aEventType)
|
||||
{
|
||||
void ProxyEvent(ProxyAccessible* aProxy, uint32_t aEventType) {
|
||||
// ignore everything but focus-changed, value-changed, caret and selection
|
||||
// events for now.
|
||||
if (aEventType != nsIAccessibleEvent::EVENT_FOCUS &&
|
||||
@ -121,50 +108,33 @@ ProxyEvent(ProxyAccessible* aProxy, uint32_t aEventType)
|
||||
return;
|
||||
|
||||
mozAccessible* wrapper = GetNativeFromProxy(aProxy);
|
||||
if (wrapper)
|
||||
FireNativeEvent(wrapper, aEventType);
|
||||
if (wrapper) FireNativeEvent(wrapper, aEventType);
|
||||
}
|
||||
|
||||
void
|
||||
ProxyStateChangeEvent(ProxyAccessible* aProxy, uint64_t, bool)
|
||||
{
|
||||
void ProxyStateChangeEvent(ProxyAccessible* aProxy, uint64_t, bool) {
|
||||
// mac doesn't care about state change events
|
||||
}
|
||||
|
||||
void
|
||||
ProxyCaretMoveEvent(ProxyAccessible* aTarget, int32_t aOffset)
|
||||
{
|
||||
void ProxyCaretMoveEvent(ProxyAccessible* aTarget, int32_t aOffset) {
|
||||
mozAccessible* wrapper = GetNativeFromProxy(aTarget);
|
||||
if (wrapper)
|
||||
[wrapper selectedTextDidChange];
|
||||
if (wrapper) [wrapper selectedTextDidChange];
|
||||
}
|
||||
|
||||
void
|
||||
ProxyTextChangeEvent(ProxyAccessible*, const nsString&, int32_t, uint32_t,
|
||||
bool, bool)
|
||||
{
|
||||
}
|
||||
void ProxyTextChangeEvent(ProxyAccessible*, const nsString&, int32_t, uint32_t, bool, bool) {}
|
||||
|
||||
void
|
||||
ProxyShowHideEvent(ProxyAccessible*, ProxyAccessible*, bool, bool)
|
||||
{
|
||||
}
|
||||
void ProxyShowHideEvent(ProxyAccessible*, ProxyAccessible*, bool, bool) {}
|
||||
|
||||
void
|
||||
ProxySelectionEvent(ProxyAccessible*, ProxyAccessible*, uint32_t)
|
||||
{
|
||||
}
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
void ProxySelectionEvent(ProxyAccessible*, ProxyAccessible*, uint32_t) {}
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
@interface GeckoNSApplication(a11y)
|
||||
-(void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute;
|
||||
@interface GeckoNSApplication (a11y)
|
||||
- (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute;
|
||||
@end
|
||||
|
||||
@implementation GeckoNSApplication(a11y)
|
||||
@implementation GeckoNSApplication (a11y)
|
||||
|
||||
-(void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute
|
||||
{
|
||||
- (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute {
|
||||
if ([attribute isEqualToString:@"AXEnhancedUserInterface"])
|
||||
mozilla::a11y::sA11yShouldBeEnabled = ([value intValue] == 1);
|
||||
|
||||
@ -172,4 +142,3 @@ ProxySelectionEvent(ProxyAccessible*, ProxyAccessible*, uint32_t)
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
@ -15,19 +15,12 @@
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
RootAccessibleWrap::
|
||||
RootAccessibleWrap(mozilla::dom::Document* aDocument, nsIPresShell* aPresShell) :
|
||||
RootAccessible(aDocument, aPresShell)
|
||||
{
|
||||
}
|
||||
RootAccessibleWrap::RootAccessibleWrap(mozilla::dom::Document* aDocument, nsIPresShell* aPresShell)
|
||||
: RootAccessible(aDocument, aPresShell) {}
|
||||
|
||||
RootAccessibleWrap::~RootAccessibleWrap()
|
||||
{
|
||||
}
|
||||
RootAccessibleWrap::~RootAccessibleWrap() {}
|
||||
|
||||
Class
|
||||
RootAccessibleWrap::GetNativeType()
|
||||
{
|
||||
Class RootAccessibleWrap::GetNativeType() {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
return [mozRootAccessible class];
|
||||
@ -35,18 +28,16 @@ RootAccessibleWrap::GetNativeType()
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
void
|
||||
RootAccessibleWrap::GetNativeWidget(void** aOutView)
|
||||
{
|
||||
nsIFrame *frame = GetFrame();
|
||||
void RootAccessibleWrap::GetNativeWidget(void** aOutView) {
|
||||
nsIFrame* frame = GetFrame();
|
||||
if (frame) {
|
||||
nsView *view = frame->GetView();
|
||||
nsView* view = frame->GetView();
|
||||
if (view) {
|
||||
nsIWidget *widget = view->GetWidget();
|
||||
nsIWidget* widget = view->GetWidget();
|
||||
if (widget) {
|
||||
*aOutView = (void**)widget->GetNativeData (NS_NATIVE_WIDGET);
|
||||
NS_ASSERTION (*aOutView,
|
||||
"Couldn't get the native NSView parent we need to connect the accessibility hierarchy!");
|
||||
*aOutView = (void**)widget->GetNativeData(NS_NATIVE_WIDGET);
|
||||
NS_ASSERTION(*aOutView, "Couldn't get the native NSView parent we need to connect the "
|
||||
"accessibility hierarchy!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -24,49 +24,45 @@ enum CheckboxValue {
|
||||
|
||||
@implementation mozButtonAccessible
|
||||
|
||||
- (NSArray*)accessibilityAttributeNames
|
||||
{
|
||||
- (NSArray*)accessibilityAttributeNames {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
static NSArray *attributes = nil;
|
||||
static NSArray* attributes = nil;
|
||||
if (!attributes) {
|
||||
attributes = [[NSArray alloc] initWithObjects:NSAccessibilityParentAttribute, // required
|
||||
NSAccessibilityRoleAttribute, // required
|
||||
NSAccessibilityRoleDescriptionAttribute,
|
||||
NSAccessibilityPositionAttribute, // required
|
||||
NSAccessibilitySizeAttribute, // required
|
||||
NSAccessibilityWindowAttribute, // required
|
||||
NSAccessibilityPositionAttribute, // required
|
||||
NSAccessibilityTopLevelUIElementAttribute, // required
|
||||
NSAccessibilityHelpAttribute,
|
||||
NSAccessibilityEnabledAttribute, // required
|
||||
NSAccessibilityFocusedAttribute, // required
|
||||
NSAccessibilityTitleAttribute, // required
|
||||
NSAccessibilityChildrenAttribute,
|
||||
NSAccessibilityDescriptionAttribute,
|
||||
attributes = [[NSArray alloc]
|
||||
initWithObjects:NSAccessibilityParentAttribute, // required
|
||||
NSAccessibilityRoleAttribute, // required
|
||||
NSAccessibilityRoleDescriptionAttribute,
|
||||
NSAccessibilityPositionAttribute, // required
|
||||
NSAccessibilitySizeAttribute, // required
|
||||
NSAccessibilityWindowAttribute, // required
|
||||
NSAccessibilityPositionAttribute, // required
|
||||
NSAccessibilityTopLevelUIElementAttribute, // required
|
||||
NSAccessibilityHelpAttribute,
|
||||
NSAccessibilityEnabledAttribute, // required
|
||||
NSAccessibilityFocusedAttribute, // required
|
||||
NSAccessibilityTitleAttribute, // required
|
||||
NSAccessibilityChildrenAttribute, NSAccessibilityDescriptionAttribute,
|
||||
#if DEBUG
|
||||
@"AXMozDescription",
|
||||
@"AXMozDescription",
|
||||
#endif
|
||||
nil];
|
||||
nil];
|
||||
}
|
||||
return attributes;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (id)accessibilityAttributeValue:(NSString *)attribute
|
||||
{
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
|
||||
if ([self hasPopup])
|
||||
return [self children];
|
||||
if ([self hasPopup]) return [self children];
|
||||
return nil;
|
||||
}
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute]) {
|
||||
if ([self isTab])
|
||||
return utils::LocalizedString(NS_LITERAL_STRING("tab"));
|
||||
if ([self isTab]) return utils::LocalizedString(NS_LITERAL_STRING("tab"));
|
||||
|
||||
return NSAccessibilityRoleDescription([self role], nil);
|
||||
}
|
||||
@ -76,20 +72,17 @@ enum CheckboxValue {
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (BOOL)accessibilityIsIgnored
|
||||
{
|
||||
- (BOOL)accessibilityIsIgnored {
|
||||
return ![self getGeckoAccessible] && ![self getProxyAccessible];
|
||||
}
|
||||
|
||||
- (NSArray*)accessibilityActionNames
|
||||
{
|
||||
- (NSArray*)accessibilityActionNames {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
if ([self isEnabled]) {
|
||||
if ([self hasPopup])
|
||||
return [NSArray arrayWithObjects:NSAccessibilityPressAction,
|
||||
NSAccessibilityShowMenuAction,
|
||||
nil];
|
||||
return
|
||||
[NSArray arrayWithObjects:NSAccessibilityPressAction, NSAccessibilityShowMenuAction, nil];
|
||||
return [NSArray arrayWithObject:NSAccessibilityPressAction];
|
||||
}
|
||||
return nil;
|
||||
@ -97,20 +90,17 @@ enum CheckboxValue {
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (NSString*)accessibilityActionDescription:(NSString*)action
|
||||
{
|
||||
- (NSString*)accessibilityActionDescription:(NSString*)action {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
if ([action isEqualToString:NSAccessibilityPressAction]) {
|
||||
if ([self isTab])
|
||||
return utils::LocalizedString(NS_LITERAL_STRING("switch"));
|
||||
if ([self isTab]) return utils::LocalizedString(NS_LITERAL_STRING("switch"));
|
||||
|
||||
return @"press button"; // XXX: localize this later?
|
||||
return @"press button"; // XXX: localize this later?
|
||||
}
|
||||
|
||||
if ([self hasPopup]) {
|
||||
if ([action isEqualToString:NSAccessibilityShowMenuAction])
|
||||
return @"show menu";
|
||||
if ([action isEqualToString:NSAccessibilityShowMenuAction]) return @"show menu";
|
||||
}
|
||||
|
||||
return nil;
|
||||
@ -118,8 +108,7 @@ enum CheckboxValue {
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (void)accessibilityPerformAction:(NSString*)action
|
||||
{
|
||||
- (void)accessibilityPerformAction:(NSString*)action {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
if ([self isEnabled] && [action isEqualToString:NSAccessibilityPressAction]) {
|
||||
@ -132,8 +121,7 @@ enum CheckboxValue {
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
- (void)click
|
||||
{
|
||||
- (void)click {
|
||||
// both buttons and checkboxes have only one action. we should really stop using arbitrary
|
||||
// arrays with actions, and define constants for these actions.
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible])
|
||||
@ -142,19 +130,15 @@ enum CheckboxValue {
|
||||
proxy->DoAction(0);
|
||||
}
|
||||
|
||||
- (BOOL)isTab
|
||||
{
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible])
|
||||
return accWrap->Role() == roles::PAGETAB;
|
||||
- (BOOL)isTab {
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) return accWrap->Role() == roles::PAGETAB;
|
||||
|
||||
if (ProxyAccessible* proxy = [self getProxyAccessible])
|
||||
return proxy->Role() == roles::PAGETAB;
|
||||
if (ProxyAccessible* proxy = [self getProxyAccessible]) return proxy->Role() == roles::PAGETAB;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
- (BOOL)hasPopup
|
||||
{
|
||||
- (BOOL)hasPopup {
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible])
|
||||
return accWrap->NativeState() & states::HASPOPUP;
|
||||
|
||||
@ -168,15 +152,13 @@ enum CheckboxValue {
|
||||
|
||||
@implementation mozCheckboxAccessible
|
||||
|
||||
- (NSString*)accessibilityActionDescription:(NSString*)action
|
||||
{
|
||||
- (NSString*)accessibilityActionDescription:(NSString*)action {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
if ([action isEqualToString:NSAccessibilityPressAction]) {
|
||||
if ([self isChecked] != kUnchecked)
|
||||
return @"uncheck checkbox"; // XXX: localize this later?
|
||||
if ([self isChecked] != kUnchecked) return @"uncheck checkbox"; // XXX: localize this later?
|
||||
|
||||
return @"check checkbox"; // XXX: localize this later?
|
||||
return @"check checkbox"; // XXX: localize this later?
|
||||
}
|
||||
|
||||
return nil;
|
||||
@ -184,8 +166,7 @@ enum CheckboxValue {
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (int)isChecked
|
||||
{
|
||||
- (int)isChecked {
|
||||
uint64_t state = 0;
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible])
|
||||
state = accWrap->NativeState();
|
||||
@ -200,8 +181,7 @@ enum CheckboxValue {
|
||||
return kUnchecked;
|
||||
}
|
||||
|
||||
- (id)value
|
||||
{
|
||||
- (id)value {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
return [NSNumber numberWithInt:[self isChecked]];
|
||||
@ -213,15 +193,13 @@ enum CheckboxValue {
|
||||
|
||||
@implementation mozTabsAccessible
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
- (void)dealloc {
|
||||
[mTabs release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSArray*)accessibilityAttributeNames
|
||||
{
|
||||
- (NSArray*)accessibilityAttributeNames {
|
||||
// standard attributes that are shared and supported by root accessible (AXMain) elements.
|
||||
static NSMutableArray* attributes = nil;
|
||||
|
||||
@ -234,12 +212,9 @@ enum CheckboxValue {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
- (id)accessibilityAttributeValue:(NSString *)attribute
|
||||
{
|
||||
if ([attribute isEqualToString:NSAccessibilityContentsAttribute])
|
||||
return [super children];
|
||||
if ([attribute isEqualToString:NSAccessibilityTabsAttribute])
|
||||
return [self tabs];
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute {
|
||||
if ([attribute isEqualToString:NSAccessibilityContentsAttribute]) return [super children];
|
||||
if ([attribute isEqualToString:NSAccessibilityTabsAttribute]) return [self tabs];
|
||||
|
||||
return [super accessibilityAttributeValue:attribute];
|
||||
}
|
||||
@ -247,8 +222,7 @@ enum CheckboxValue {
|
||||
/**
|
||||
* Returns the selected tab (the mozAccessible)
|
||||
*/
|
||||
- (id)value
|
||||
{
|
||||
- (id)value {
|
||||
mozAccessible* nativeAcc = nil;
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
|
||||
if (Accessible* accTab = accWrap->GetSelectedItem(0)) {
|
||||
@ -266,10 +240,8 @@ enum CheckboxValue {
|
||||
/**
|
||||
* Return the mozAccessibles that are the tabs.
|
||||
*/
|
||||
- (id)tabs
|
||||
{
|
||||
if (mTabs)
|
||||
return mTabs;
|
||||
- (id)tabs {
|
||||
if (mTabs) return mTabs;
|
||||
|
||||
NSArray* children = [self children];
|
||||
NSEnumerator* enumerator = [children objectEnumerator];
|
||||
@ -277,14 +249,12 @@ enum CheckboxValue {
|
||||
|
||||
id obj;
|
||||
while ((obj = [enumerator nextObject]))
|
||||
if ([obj isTab])
|
||||
[mTabs addObject:obj];
|
||||
if ([obj isTab]) [mTabs addObject:obj];
|
||||
|
||||
return mTabs;
|
||||
}
|
||||
|
||||
- (void)invalidateChildren
|
||||
{
|
||||
- (void)invalidateChildren {
|
||||
[super invalidateChildren];
|
||||
|
||||
[mTabs release];
|
||||
@ -295,18 +265,15 @@ enum CheckboxValue {
|
||||
|
||||
@implementation mozPaneAccessible
|
||||
|
||||
- (NSUInteger)accessibilityArrayAttributeCount:(NSString*)attribute
|
||||
{
|
||||
- (NSUInteger)accessibilityArrayAttributeCount:(NSString*)attribute {
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
ProxyAccessible* proxy = [self getProxyAccessible];
|
||||
if (!accWrap && !proxy)
|
||||
return 0;
|
||||
if (!accWrap && !proxy) return 0;
|
||||
|
||||
// By default this calls -[[mozAccessible children] count].
|
||||
// Since we don't cache mChildren. This is faster.
|
||||
if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
|
||||
if (accWrap)
|
||||
return accWrap->ChildCount() ? 1 : 0;
|
||||
if (accWrap) return accWrap->ChildCount() ? 1 : 0;
|
||||
|
||||
return proxy->ChildrenCount() ? 1 : 0;
|
||||
}
|
||||
@ -314,24 +281,21 @@ enum CheckboxValue {
|
||||
return [super accessibilityArrayAttributeCount:attribute];
|
||||
}
|
||||
|
||||
- (NSArray*)children
|
||||
{
|
||||
if (![self getGeckoAccessible])
|
||||
return nil;
|
||||
- (NSArray*)children {
|
||||
if (![self getGeckoAccessible]) return nil;
|
||||
|
||||
nsDeckFrame* deckFrame = do_QueryFrame([self getGeckoAccessible]->GetFrame());
|
||||
nsDeckFrame* deckFrame = do_QueryFrame([self getGeckoAccessible] -> GetFrame());
|
||||
nsIFrame* selectedFrame = deckFrame ? deckFrame->GetSelectedBox() : nullptr;
|
||||
|
||||
Accessible* selectedAcc = nullptr;
|
||||
if (selectedFrame) {
|
||||
nsINode* node = selectedFrame->GetContent();
|
||||
selectedAcc = [self getGeckoAccessible]->Document()->GetAccessible(node);
|
||||
selectedAcc = [self getGeckoAccessible] -> Document() -> GetAccessible(node);
|
||||
}
|
||||
|
||||
if (selectedAcc) {
|
||||
mozAccessible *curNative = GetNativeFromGeckoAccessible(selectedAcc);
|
||||
if (curNative)
|
||||
return [NSArray arrayWithObjects:GetObjectOrRepresentedView(curNative), nil];
|
||||
mozAccessible* curNative = GetNativeFromGeckoAccessible(selectedAcc);
|
||||
if (curNative) return [NSArray arrayWithObjects:GetObjectOrRepresentedView(curNative), nil];
|
||||
}
|
||||
|
||||
return nil;
|
||||
|
@ -14,13 +14,10 @@
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
static id <mozAccessible, mozView>
|
||||
getNativeViewFromRootAccessible(Accessible* aAccessible)
|
||||
{
|
||||
RootAccessibleWrap* root =
|
||||
static_cast<RootAccessibleWrap*>(aAccessible->AsRoot());
|
||||
id <mozAccessible, mozView> nativeView = nil;
|
||||
root->GetNativeWidget ((void**)&nativeView);
|
||||
static id<mozAccessible, mozView> getNativeViewFromRootAccessible(Accessible* aAccessible) {
|
||||
RootAccessibleWrap* root = static_cast<RootAccessibleWrap*>(aAccessible->AsRoot());
|
||||
id<mozAccessible, mozView> nativeView = nil;
|
||||
root->GetNativeWidget((void**)&nativeView);
|
||||
return nativeView;
|
||||
}
|
||||
|
||||
@ -28,13 +25,11 @@ getNativeViewFromRootAccessible(Accessible* aAccessible)
|
||||
|
||||
@implementation mozRootAccessible
|
||||
|
||||
- (NSArray*)accessibilityAttributeNames
|
||||
{
|
||||
- (NSArray*)accessibilityAttributeNames {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
// if we're expired, we don't support any attributes.
|
||||
if (![self getGeckoAccessible])
|
||||
return [NSArray array];
|
||||
if (![self getGeckoAccessible]) return [NSArray array];
|
||||
|
||||
// standard attributes that are shared and supported by root accessible (AXMain) elements.
|
||||
static NSMutableArray* attributes = nil;
|
||||
@ -50,8 +45,7 @@ getNativeViewFromRootAccessible(Accessible* aAccessible)
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (id)accessibilityAttributeValue:(NSString *)attribute
|
||||
{
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityMainAttribute])
|
||||
@ -64,14 +58,11 @@ getNativeViewFromRootAccessible(Accessible* aAccessible)
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
|
||||
// return the AXParent that our parallell NSView tells us about.
|
||||
- (id)parent
|
||||
{
|
||||
- (id)parent {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
if (!mParallelView)
|
||||
mParallelView = (id<mozView, mozAccessible>)[self representedView];
|
||||
if (!mParallelView) mParallelView = (id<mozView, mozAccessible>)[self representedView];
|
||||
|
||||
if (mParallelView)
|
||||
return [mParallelView accessibilityAttributeValue:NSAccessibilityParentAttribute];
|
||||
@ -82,20 +73,17 @@ getNativeViewFromRootAccessible(Accessible* aAccessible)
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (BOOL)hasRepresentedView
|
||||
{
|
||||
- (BOOL)hasRepresentedView {
|
||||
return YES;
|
||||
}
|
||||
|
||||
// this will return our parallell NSView. see mozDocAccessible.h
|
||||
- (id)representedView
|
||||
{
|
||||
- (id)representedView {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
if (mParallelView)
|
||||
return (id)mParallelView;
|
||||
if (mParallelView) return (id)mParallelView;
|
||||
|
||||
mParallelView = getNativeViewFromRootAccessible ([self getGeckoAccessible]);
|
||||
mParallelView = getNativeViewFromRootAccessible([self getGeckoAccessible]);
|
||||
|
||||
NSAssert(mParallelView, @"can't return root accessible's native parallel view.");
|
||||
return mParallelView;
|
||||
@ -103,8 +91,7 @@ getNativeViewFromRootAccessible(Accessible* aAccessible)
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (BOOL)isRoot
|
||||
{
|
||||
- (BOOL)isRoot {
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
@ -14,8 +14,7 @@
|
||||
|
||||
@implementation mozHeadingAccessible
|
||||
|
||||
- (NSString*)title
|
||||
{
|
||||
- (NSString*)title {
|
||||
nsAutoString title;
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
|
||||
mozilla::ErrorResult rv;
|
||||
@ -29,8 +28,7 @@
|
||||
return nsCocoaUtils::ToNSString(title);
|
||||
}
|
||||
|
||||
- (id)value
|
||||
{
|
||||
- (id)value {
|
||||
uint32_t level = 0;
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
|
||||
level = accWrap->GetLevelInternal();
|
||||
@ -44,16 +42,14 @@
|
||||
@end
|
||||
|
||||
@interface mozLinkAccessible ()
|
||||
-(NSURL*)url;
|
||||
- (NSURL*)url;
|
||||
@end
|
||||
|
||||
@implementation mozLinkAccessible
|
||||
|
||||
- (NSArray*)accessibilityAttributeNames
|
||||
{
|
||||
- (NSArray*)accessibilityAttributeNames {
|
||||
// if we're expired, we don't support any attributes.
|
||||
if (![self getGeckoAccessible] && ![self getProxyAccessible])
|
||||
return [NSArray array];
|
||||
if (![self getGeckoAccessible] && ![self getProxyAccessible]) return [NSArray array];
|
||||
|
||||
static NSMutableArray* attributes = nil;
|
||||
|
||||
@ -65,32 +61,26 @@
|
||||
return attributes;
|
||||
}
|
||||
|
||||
- (id)accessibilityAttributeValue:(NSString *)attribute
|
||||
{
|
||||
if ([attribute isEqualToString:NSAccessibilityURLAttribute])
|
||||
return [self url];
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute {
|
||||
if ([attribute isEqualToString:NSAccessibilityURLAttribute]) return [self url];
|
||||
|
||||
return [super accessibilityAttributeValue:attribute];
|
||||
}
|
||||
|
||||
- (NSArray*)accessibilityActionNames
|
||||
{
|
||||
// if we're expired, we don't support any attributes.
|
||||
if (![self getGeckoAccessible] && ![self getProxyAccessible])
|
||||
return [NSArray array];
|
||||
- (NSArray*)accessibilityActionNames {
|
||||
// if we're expired, we don't support any attributes.
|
||||
if (![self getGeckoAccessible] && ![self getProxyAccessible]) return [NSArray array];
|
||||
|
||||
static NSArray* actionNames = nil;
|
||||
|
||||
if (!actionNames) {
|
||||
actionNames = [[NSArray alloc] initWithObjects:NSAccessibilityPressAction,
|
||||
nil];
|
||||
actionNames = [[NSArray alloc] initWithObjects:NSAccessibilityPressAction, nil];
|
||||
}
|
||||
|
||||
return actionNames;
|
||||
}
|
||||
|
||||
- (void)accessibilityPerformAction:(NSString*)action
|
||||
{
|
||||
- (void)accessibilityPerformAction:(NSString*)action {
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
ProxyAccessible* proxy = [self getProxyAccessible];
|
||||
if (!accWrap && !proxy) {
|
||||
@ -107,21 +97,17 @@
|
||||
}
|
||||
|
||||
[super accessibilityPerformAction:action];
|
||||
|
||||
}
|
||||
|
||||
- (NSString*)customDescription
|
||||
{
|
||||
- (NSString*)customDescription {
|
||||
return @"";
|
||||
}
|
||||
|
||||
- (NSString*)value
|
||||
{
|
||||
- (NSString*)value {
|
||||
return @"";
|
||||
}
|
||||
|
||||
- (NSURL*)url
|
||||
{
|
||||
- (NSURL*)url {
|
||||
nsAutoString value;
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
|
||||
accWrap->Value(value);
|
||||
@ -130,8 +116,7 @@
|
||||
}
|
||||
|
||||
NSString* urlString = value.IsEmpty() ? nil : nsCocoaUtils::ToNSString(value);
|
||||
if (!urlString)
|
||||
return nil;
|
||||
if (!urlString) return nil;
|
||||
|
||||
return [NSURL URLWithString:urlString];
|
||||
}
|
||||
|
@ -33,15 +33,13 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
- (NSString*)role
|
||||
{
|
||||
- (NSString*)role {
|
||||
return [self isLayoutTablePart] ? NSAccessibilityGroupRole : [super role];
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation mozTableAccessible
|
||||
- (NSArray*)additionalAccessibilityAttributeNames
|
||||
{
|
||||
- (NSArray*)additionalAccessibilityAttributeNames {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
NSArray* additionalAttributes = [super additionalAccessibilityAttributeNames];
|
||||
@ -64,12 +62,10 @@
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute
|
||||
{
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute {
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
|
||||
TableAccessible* table = accWrap->AsTable();
|
||||
if ([attribute isEqualToString:NSAccessibilityRowCountAttribute])
|
||||
return @(table->RowCount());
|
||||
if ([attribute isEqualToString:NSAccessibilityRowCountAttribute]) return @(table->RowCount());
|
||||
if ([attribute isEqualToString:NSAccessibilityColumnCountAttribute])
|
||||
return @(table->ColCount());
|
||||
if ([attribute isEqualToString:NSAccessibilityRowsAttribute]) {
|
||||
@ -78,10 +74,8 @@
|
||||
uint32_t totalCount = accWrap->ChildCount();
|
||||
for (uint32_t i = 0; i < totalCount; i++) {
|
||||
if (accWrap->GetChildAt(i)->IsTableRow()) {
|
||||
mozAccessible* curNative =
|
||||
GetNativeFromGeckoAccessible(accWrap->GetChildAt(i));
|
||||
if (curNative)
|
||||
[nativeArray addObject:GetObjectOrRepresentedView(curNative)];
|
||||
mozAccessible* curNative = GetNativeFromGeckoAccessible(accWrap->GetChildAt(i));
|
||||
if (curNative) [nativeArray addObject:GetObjectOrRepresentedView(curNative)];
|
||||
}
|
||||
}
|
||||
return nativeArray;
|
||||
@ -97,10 +91,8 @@
|
||||
uint32_t totalCount = proxy->ChildrenCount();
|
||||
for (uint32_t i = 0; i < totalCount; i++) {
|
||||
if (proxy->ChildAt(i)->IsTableRow()) {
|
||||
mozAccessible* curNative =
|
||||
GetNativeFromProxy(proxy->ChildAt(i));
|
||||
if (curNative)
|
||||
[nativeArray addObject:GetObjectOrRepresentedView(curNative)];
|
||||
mozAccessible* curNative = GetNativeFromProxy(proxy->ChildAt(i));
|
||||
if (curNative) [nativeArray addObject:GetObjectOrRepresentedView(curNative)];
|
||||
}
|
||||
}
|
||||
return nativeArray;
|
||||
@ -112,8 +104,7 @@
|
||||
@end
|
||||
|
||||
@implementation mozTableRowAccessible
|
||||
- (NSArray*)additionalAccessibilityAttributeNames
|
||||
{
|
||||
- (NSArray*)additionalAccessibilityAttributeNames {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
NSArray* additionalAttributes = [super additionalAccessibilityAttributeNames];
|
||||
@ -134,8 +125,7 @@
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute
|
||||
{
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute {
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
|
||||
if ([attribute isEqualToString:NSAccessibilityIndexAttribute]) {
|
||||
// Count the number of rows before that one to obtain the row index.
|
||||
@ -171,8 +161,7 @@
|
||||
@end
|
||||
|
||||
@implementation mozTableCellAccessible
|
||||
- (NSArray*)additionalAccessibilityAttributeNames
|
||||
{
|
||||
- (NSArray*)additionalAccessibilityAttributeNames {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
NSArray* additionalAttributes = [super additionalAccessibilityAttributeNames];
|
||||
@ -196,16 +185,13 @@
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute
|
||||
{
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute {
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
|
||||
TableCellAccessible* cell = accWrap->AsTableCell();
|
||||
if ([attribute isEqualToString:NSAccessibilityRowIndexRangeAttribute])
|
||||
return [NSValue valueWithRange:NSMakeRange(cell->RowIdx(),
|
||||
cell->RowExtent())];
|
||||
return [NSValue valueWithRange:NSMakeRange(cell->RowIdx(), cell->RowExtent())];
|
||||
if ([attribute isEqualToString:NSAccessibilityColumnIndexRangeAttribute])
|
||||
return [NSValue valueWithRange:NSMakeRange(cell->ColIdx(),
|
||||
cell->ColExtent())];
|
||||
return [NSValue valueWithRange:NSMakeRange(cell->ColIdx(), cell->ColExtent())];
|
||||
if ([attribute isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute]) {
|
||||
AutoTArray<Accessible*, 10> headerCells;
|
||||
cell->RowHeaderCells(&headerCells);
|
||||
@ -218,11 +204,9 @@
|
||||
}
|
||||
} else if (ProxyAccessible* proxy = [self getProxyAccessible]) {
|
||||
if ([attribute isEqualToString:NSAccessibilityRowIndexRangeAttribute])
|
||||
return [NSValue valueWithRange:NSMakeRange(proxy->RowIdx(),
|
||||
proxy->RowExtent())];
|
||||
return [NSValue valueWithRange:NSMakeRange(proxy->RowIdx(), proxy->RowExtent())];
|
||||
if ([attribute isEqualToString:NSAccessibilityColumnIndexRangeAttribute])
|
||||
return [NSValue valueWithRange:NSMakeRange(proxy->ColIdx(),
|
||||
proxy->ColExtent())];
|
||||
return [NSValue valueWithRange:NSMakeRange(proxy->ColIdx(), proxy->ColExtent())];
|
||||
if ([attribute isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute]) {
|
||||
nsTArray<ProxyAccessible*> headerCells;
|
||||
proxy->RowHeaderCells(&headerCells);
|
||||
|
@ -14,9 +14,7 @@
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
inline bool
|
||||
ToNSRange(id aValue, NSRange* aRange)
|
||||
{
|
||||
inline bool ToNSRange(id aValue, NSRange* aRange) {
|
||||
MOZ_ASSERT(aRange, "aRange is nil");
|
||||
|
||||
if ([aValue isKindOfClass:[NSValue class]] &&
|
||||
@ -28,9 +26,7 @@ ToNSRange(id aValue, NSRange* aRange)
|
||||
return false;
|
||||
}
|
||||
|
||||
inline NSString*
|
||||
ToNSString(id aValue)
|
||||
{
|
||||
inline NSString* ToNSString(id aValue) {
|
||||
if ([aValue isKindOfClass:[NSString class]]) {
|
||||
return aValue;
|
||||
}
|
||||
@ -53,28 +49,23 @@ ToNSString(id aValue)
|
||||
|
||||
@implementation mozTextAccessible
|
||||
|
||||
- (BOOL)accessibilityIsIgnored
|
||||
{
|
||||
- (BOOL)accessibilityIsIgnored {
|
||||
return ![self getGeckoAccessible] && ![self getProxyAccessible];
|
||||
}
|
||||
|
||||
- (NSArray*)accessibilityAttributeNames
|
||||
{
|
||||
- (NSArray*)accessibilityAttributeNames {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
static NSMutableArray* supportedAttributes = nil;
|
||||
if (!supportedAttributes) {
|
||||
// text-specific attributes to supplement the standard one
|
||||
supportedAttributes = [[NSMutableArray alloc] initWithObjects:
|
||||
NSAccessibilitySelectedTextAttribute, // required
|
||||
NSAccessibilitySelectedTextRangeAttribute, // required
|
||||
NSAccessibilityNumberOfCharactersAttribute, // required
|
||||
NSAccessibilityVisibleCharacterRangeAttribute, // required
|
||||
NSAccessibilityInsertionPointLineNumberAttribute,
|
||||
@"AXRequired",
|
||||
@"AXInvalid",
|
||||
nil
|
||||
];
|
||||
supportedAttributes = [[NSMutableArray alloc]
|
||||
initWithObjects:NSAccessibilitySelectedTextAttribute, // required
|
||||
NSAccessibilitySelectedTextRangeAttribute, // required
|
||||
NSAccessibilityNumberOfCharactersAttribute, // required
|
||||
NSAccessibilityVisibleCharacterRangeAttribute, // required
|
||||
NSAccessibilityInsertionPointLineNumberAttribute, @"AXRequired",
|
||||
@"AXInvalid", nil];
|
||||
[supportedAttributes addObjectsFromArray:[super accessibilityAttributeNames]];
|
||||
}
|
||||
return supportedAttributes;
|
||||
@ -82,8 +73,7 @@ ToNSString(id aValue)
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute
|
||||
{
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityNumberOfCharactersAttribute])
|
||||
@ -95,11 +85,9 @@ ToNSString(id aValue)
|
||||
if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute])
|
||||
return [self selectedTextRange];
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute])
|
||||
return [self selectedText];
|
||||
if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute]) return [self selectedText];
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityTitleAttribute])
|
||||
return @"";
|
||||
if ([attribute isEqualToString:NSAccessibilityTitleAttribute]) return @"";
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityValueAttribute]) {
|
||||
// Apple's SpeechSynthesisServer expects AXValue to return an AXStaticText
|
||||
@ -141,37 +129,33 @@ ToNSString(id aValue)
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (NSArray*)accessibilityParameterizedAttributeNames
|
||||
{
|
||||
- (NSArray*)accessibilityParameterizedAttributeNames {
|
||||
static NSArray* supportedParametrizedAttributes = nil;
|
||||
// text specific parametrized attributes
|
||||
if (!supportedParametrizedAttributes) {
|
||||
supportedParametrizedAttributes = [[NSArray alloc] initWithObjects:
|
||||
NSAccessibilityStringForRangeParameterizedAttribute,
|
||||
NSAccessibilityLineForIndexParameterizedAttribute,
|
||||
NSAccessibilityRangeForLineParameterizedAttribute,
|
||||
NSAccessibilityAttributedStringForRangeParameterizedAttribute,
|
||||
NSAccessibilityBoundsForRangeParameterizedAttribute,
|
||||
supportedParametrizedAttributes = [[NSArray alloc]
|
||||
initWithObjects:NSAccessibilityStringForRangeParameterizedAttribute,
|
||||
NSAccessibilityLineForIndexParameterizedAttribute,
|
||||
NSAccessibilityRangeForLineParameterizedAttribute,
|
||||
NSAccessibilityAttributedStringForRangeParameterizedAttribute,
|
||||
NSAccessibilityBoundsForRangeParameterizedAttribute,
|
||||
#if DEBUG
|
||||
NSAccessibilityRangeForPositionParameterizedAttribute,
|
||||
NSAccessibilityRangeForIndexParameterizedAttribute,
|
||||
NSAccessibilityRTFForRangeParameterizedAttribute,
|
||||
NSAccessibilityStyleRangeForIndexParameterizedAttribute,
|
||||
NSAccessibilityRangeForPositionParameterizedAttribute,
|
||||
NSAccessibilityRangeForIndexParameterizedAttribute,
|
||||
NSAccessibilityRTFForRangeParameterizedAttribute,
|
||||
NSAccessibilityStyleRangeForIndexParameterizedAttribute,
|
||||
#endif
|
||||
nil
|
||||
];
|
||||
nil];
|
||||
}
|
||||
return supportedParametrizedAttributes;
|
||||
}
|
||||
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute forParameter:(id)parameter
|
||||
{
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute forParameter:(id)parameter {
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
ProxyAccessible* proxy = [self getProxyAccessible];
|
||||
|
||||
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
|
||||
if (!textAcc && !proxy)
|
||||
return nil;
|
||||
HyperTextAccessible* textAcc = accWrap ? accWrap->AsHyperText() : nullptr;
|
||||
if (!textAcc && !proxy) return nil;
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityStringForRangeParameterizedAttribute]) {
|
||||
NSRange range;
|
||||
@ -220,11 +204,9 @@ ToNSString(id aValue)
|
||||
int32_t end = start + range.length;
|
||||
DesktopIntRect bounds;
|
||||
if (textAcc) {
|
||||
bounds =
|
||||
DesktopIntRect::FromUnknownRect(textAcc->TextBounds(start, end));
|
||||
bounds = DesktopIntRect::FromUnknownRect(textAcc->TextBounds(start, end));
|
||||
} else if (proxy) {
|
||||
bounds =
|
||||
DesktopIntRect::FromUnknownRect(proxy->TextBounds(start, end));
|
||||
bounds = DesktopIntRect::FromUnknownRect(proxy->TextBounds(start, end));
|
||||
}
|
||||
|
||||
return [NSValue valueWithRect:nsCocoaUtils::GeckoRectToCocoaRect(bounds)];
|
||||
@ -237,12 +219,10 @@ ToNSString(id aValue)
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (BOOL)accessibilityIsAttributeSettable:(NSString*)attribute
|
||||
{
|
||||
- (BOOL)accessibilityIsAttributeSettable:(NSString*)attribute {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityValueAttribute])
|
||||
return ![self isReadOnly];
|
||||
if ([attribute isEqualToString:NSAccessibilityValueAttribute]) return ![self isReadOnly];
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute] ||
|
||||
[attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute] ||
|
||||
@ -254,16 +234,14 @@ ToNSString(id aValue)
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO);
|
||||
}
|
||||
|
||||
- (void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute
|
||||
{
|
||||
- (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
ProxyAccessible* proxy = [self getProxyAccessible];
|
||||
|
||||
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
|
||||
if (!textAcc && !proxy)
|
||||
return;
|
||||
HyperTextAccessible* textAcc = accWrap ? accWrap->AsHyperText() : nullptr;
|
||||
if (!textAcc && !proxy) return;
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityValueAttribute]) {
|
||||
[self setText:ToNSString(value)];
|
||||
@ -273,8 +251,7 @@ ToNSString(id aValue)
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute]) {
|
||||
NSString* stringValue = ToNSString(value);
|
||||
if (!stringValue)
|
||||
return;
|
||||
if (!stringValue) return;
|
||||
|
||||
int32_t start = 0, end = 0;
|
||||
nsString text;
|
||||
@ -294,23 +271,19 @@ ToNSString(id aValue)
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) {
|
||||
NSRange range;
|
||||
if (!ToNSRange(value, &range))
|
||||
return;
|
||||
if (!ToNSRange(value, &range)) return;
|
||||
|
||||
if (textAcc) {
|
||||
textAcc->SetSelectionBoundsAt(0, range.location,
|
||||
range.location + range.length);
|
||||
textAcc->SetSelectionBoundsAt(0, range.location, range.location + range.length);
|
||||
} else if (proxy) {
|
||||
proxy->SetSelectionBoundsAt(0, range.location,
|
||||
range.location + range.length);
|
||||
proxy->SetSelectionBoundsAt(0, range.location, range.location + range.length);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityVisibleCharacterRangeAttribute]) {
|
||||
NSRange range;
|
||||
if (!ToNSRange(value, &range))
|
||||
return;
|
||||
if (!ToNSRange(value, &range)) return;
|
||||
|
||||
if (textAcc) {
|
||||
textAcc->ScrollSubstringTo(range.location, range.location + range.length,
|
||||
@ -327,27 +300,22 @@ ToNSString(id aValue)
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
- (NSString*)subrole
|
||||
{
|
||||
if(mRole == roles::PASSWORD_TEXT)
|
||||
return NSAccessibilitySecureTextFieldSubrole;
|
||||
- (NSString*)subrole {
|
||||
if (mRole == roles::PASSWORD_TEXT) return NSAccessibilitySecureTextFieldSubrole;
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (BOOL)isReadOnly
|
||||
{
|
||||
- (BOOL)isReadOnly {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
||||
|
||||
if ([[self role] isEqualToString:NSAccessibilityStaticTextRole])
|
||||
return YES;
|
||||
if ([[self role] isEqualToString:NSAccessibilityStaticTextRole]) return YES;
|
||||
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
|
||||
if (textAcc)
|
||||
return (accWrap->State() & states::READONLY) == 0;
|
||||
HyperTextAccessible* textAcc = accWrap ? accWrap->AsHyperText() : nullptr;
|
||||
if (textAcc) return (accWrap->State() & states::READONLY) == 0;
|
||||
|
||||
if (ProxyAccessible* proxy = [self getProxyAccessible])
|
||||
return (proxy->State() & states::READONLY) == 0;
|
||||
@ -357,10 +325,9 @@ ToNSString(id aValue)
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO);
|
||||
}
|
||||
|
||||
- (NSNumber*)caretLineNumber
|
||||
{
|
||||
- (NSNumber*)caretLineNumber {
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
|
||||
HyperTextAccessible* textAcc = accWrap ? accWrap->AsHyperText() : nullptr;
|
||||
|
||||
int32_t lineNumber = -1;
|
||||
if (textAcc) {
|
||||
@ -372,12 +339,11 @@ ToNSString(id aValue)
|
||||
return (lineNumber >= 0) ? [NSNumber numberWithInt:lineNumber] : nil;
|
||||
}
|
||||
|
||||
- (void)setText:(NSString*)aNewString
|
||||
{
|
||||
- (void)setText:(NSString*)aNewString {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
|
||||
HyperTextAccessible* textAcc = accWrap ? accWrap->AsHyperText() : nullptr;
|
||||
|
||||
nsString text;
|
||||
nsCocoaUtils::GetStringForNSString(aNewString, text);
|
||||
@ -390,17 +356,14 @@ ToNSString(id aValue)
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
- (NSString*)text
|
||||
{
|
||||
- (NSString*)text {
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
ProxyAccessible* proxy = [self getProxyAccessible];
|
||||
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
|
||||
if (!textAcc && !proxy)
|
||||
return nil;
|
||||
HyperTextAccessible* textAcc = accWrap ? accWrap->AsHyperText() : nullptr;
|
||||
if (!textAcc && !proxy) return nil;
|
||||
|
||||
// A password text field returns an empty value
|
||||
if (mRole == roles::PASSWORD_TEXT)
|
||||
return @"";
|
||||
if (mRole == roles::PASSWORD_TEXT) return @"";
|
||||
|
||||
nsAutoString text;
|
||||
if (textAcc) {
|
||||
@ -412,30 +375,26 @@ ToNSString(id aValue)
|
||||
return nsCocoaUtils::ToNSString(text);
|
||||
}
|
||||
|
||||
- (long)textLength
|
||||
{
|
||||
- (long)textLength {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
||||
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
ProxyAccessible* proxy = [self getProxyAccessible];
|
||||
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
|
||||
if (!textAcc && !proxy)
|
||||
return 0;
|
||||
HyperTextAccessible* textAcc = accWrap ? accWrap->AsHyperText() : nullptr;
|
||||
if (!textAcc && !proxy) return 0;
|
||||
|
||||
return textAcc ? textAcc->CharacterCount() : proxy->CharacterCount();
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0);
|
||||
}
|
||||
|
||||
- (long)selectedTextLength
|
||||
{
|
||||
- (long)selectedTextLength {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
||||
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
ProxyAccessible* proxy = [self getProxyAccessible];
|
||||
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
|
||||
if (!textAcc && !proxy)
|
||||
return 0;
|
||||
HyperTextAccessible* textAcc = accWrap ? accWrap->AsHyperText() : nullptr;
|
||||
if (!textAcc && !proxy) return 0;
|
||||
|
||||
int32_t start = 0, end = 0;
|
||||
if (textAcc) {
|
||||
@ -449,15 +408,13 @@ ToNSString(id aValue)
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0);
|
||||
}
|
||||
|
||||
- (NSString*)selectedText
|
||||
{
|
||||
- (NSString*)selectedText {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
ProxyAccessible* proxy = [self getProxyAccessible];
|
||||
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
|
||||
if (!textAcc && !proxy)
|
||||
return nil;
|
||||
HyperTextAccessible* textAcc = accWrap ? accWrap->AsHyperText() : nullptr;
|
||||
if (!textAcc && !proxy) return nil;
|
||||
|
||||
int32_t start = 0, end = 0;
|
||||
nsAutoString selText;
|
||||
@ -475,13 +432,12 @@ ToNSString(id aValue)
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (NSValue*)selectedTextRange
|
||||
{
|
||||
- (NSValue*)selectedTextRange {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
ProxyAccessible* proxy = [self getProxyAccessible];
|
||||
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
|
||||
HyperTextAccessible* textAcc = accWrap ? accWrap->AsHyperText() : nullptr;
|
||||
|
||||
int32_t start = 0;
|
||||
int32_t end = 0;
|
||||
@ -514,23 +470,19 @@ ToNSString(id aValue)
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (NSValue*)visibleCharacterRange
|
||||
{
|
||||
- (NSValue*)visibleCharacterRange {
|
||||
// XXX this won't work with Textarea and such as we actually don't give
|
||||
// the visible character range.
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
ProxyAccessible* proxy = [self getProxyAccessible];
|
||||
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
|
||||
if (!textAcc && !proxy)
|
||||
return 0;
|
||||
HyperTextAccessible* textAcc = accWrap ? accWrap->AsHyperText() : nullptr;
|
||||
if (!textAcc && !proxy) return 0;
|
||||
|
||||
return [NSValue valueWithRange:
|
||||
NSMakeRange(0, textAcc ?
|
||||
textAcc->CharacterCount() : proxy->CharacterCount())];
|
||||
return [NSValue
|
||||
valueWithRange:NSMakeRange(0, textAcc ? textAcc->CharacterCount() : proxy->CharacterCount())];
|
||||
}
|
||||
|
||||
- (void)valueDidChange
|
||||
{
|
||||
- (void)valueDidChange {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
NSAccessibilityPostNotification(GetObjectOrRepresentedView(self),
|
||||
@ -539,29 +491,24 @@ ToNSString(id aValue)
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
- (void)selectedTextDidChange
|
||||
{
|
||||
- (void)selectedTextDidChange {
|
||||
NSAccessibilityPostNotification(GetObjectOrRepresentedView(self),
|
||||
NSAccessibilitySelectedTextChangedNotification);
|
||||
}
|
||||
|
||||
- (NSString*)stringFromRange:(NSRange*)range
|
||||
{
|
||||
- (NSString*)stringFromRange:(NSRange*)range {
|
||||
MOZ_ASSERT(range, "no range");
|
||||
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
ProxyAccessible* proxy = [self getProxyAccessible];
|
||||
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
|
||||
if (!textAcc && !proxy)
|
||||
return nil;
|
||||
HyperTextAccessible* textAcc = accWrap ? accWrap->AsHyperText() : nullptr;
|
||||
if (!textAcc && !proxy) return nil;
|
||||
|
||||
nsAutoString text;
|
||||
if (textAcc) {
|
||||
textAcc->TextSubstring(range->location,
|
||||
range->location + range->length, text);
|
||||
textAcc->TextSubstring(range->location, range->location + range->length, text);
|
||||
} else if (proxy) {
|
||||
proxy->TextSubstring(range->location,
|
||||
range->location + range->length, text);
|
||||
proxy->TextSubstring(range->location, range->location + range->length, text);
|
||||
}
|
||||
|
||||
return nsCocoaUtils::ToNSString(text);
|
||||
@ -571,8 +518,7 @@ ToNSString(id aValue)
|
||||
|
||||
@implementation mozTextLeafAccessible
|
||||
|
||||
- (NSArray*)accessibilityAttributeNames
|
||||
{
|
||||
- (NSArray*)accessibilityAttributeNames {
|
||||
static NSMutableArray* supportedAttributes = nil;
|
||||
if (!supportedAttributes) {
|
||||
supportedAttributes = [[super accessibilityAttributeNames] mutableCopy];
|
||||
@ -582,19 +528,15 @@ ToNSString(id aValue)
|
||||
return supportedAttributes;
|
||||
}
|
||||
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute
|
||||
{
|
||||
if ([attribute isEqualToString:NSAccessibilityTitleAttribute])
|
||||
return @"";
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute {
|
||||
if ([attribute isEqualToString:NSAccessibilityTitleAttribute]) return @"";
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityValueAttribute])
|
||||
return [self text];
|
||||
if ([attribute isEqualToString:NSAccessibilityValueAttribute]) return [self text];
|
||||
|
||||
return [super accessibilityAttributeValue:attribute];
|
||||
}
|
||||
|
||||
- (NSString*)text
|
||||
{
|
||||
- (NSString*)text {
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
|
||||
return nsCocoaUtils::ToNSString(accWrap->AsTextLeaf()->Text());
|
||||
}
|
||||
@ -608,8 +550,7 @@ ToNSString(id aValue)
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (long)textLength
|
||||
{
|
||||
- (long)textLength {
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
|
||||
return accWrap->AsTextLeaf()->Text().Length();
|
||||
}
|
||||
|
@ -5196,7 +5196,7 @@ class TabProgressListener {
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.mBlank) {
|
||||
if (!this.mBlank || this.mBrowser.hasContentOpener) {
|
||||
this._callProgressListeners("onLocationChange",
|
||||
[aWebProgress, aRequest, aLocation, aFlags]);
|
||||
if (topLevel && !isSameDocument) {
|
||||
|
@ -40,6 +40,8 @@ skip-if = os != "win" # Windows only feature
|
||||
[browser_urlbar_blanking.js]
|
||||
support-files =
|
||||
file_blank_but_not_blank.html
|
||||
[browser_urlbar_content_opener.js]
|
||||
skip-if = debug # Bug 1521835 - shutdown leaks
|
||||
[browser_urlbar_locationchange_urlbar_edit_dos.js]
|
||||
support-files =
|
||||
file_urlbar_edit_dos.html
|
||||
|
@ -0,0 +1,18 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_PATH = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "https://example.com");
|
||||
|
||||
add_task(async function() {
|
||||
await BrowserTestUtils.withNewTab(TEST_PATH + "dummy_page.html", async function(browser) {
|
||||
let windowOpenedPromise = BrowserTestUtils.waitForNewWindow();
|
||||
await ContentTask.spawn(browser, null, function() {
|
||||
content.window.open("", "_BLANK", "toolbar=no,height=300,width=500");
|
||||
});
|
||||
let newWin = await windowOpenedPromise;
|
||||
is(newWin.gURLBar.value, "about:blank", "Should be displaying about:blank for the opened window.");
|
||||
await BrowserTestUtils.closeWindow(newWin);
|
||||
});
|
||||
});
|
@ -10,6 +10,7 @@
|
||||
exports.animations = require("devtools/client/inspector/animation/reducers/animations");
|
||||
exports.boxModel = require("devtools/client/inspector/boxmodel/reducers/box-model");
|
||||
exports.changes = require("devtools/client/inspector/changes/reducers/changes");
|
||||
exports.classList = require("devtools/client/inspector/rules/reducers/class-list");
|
||||
exports.extensionsSidebar = require("devtools/client/inspector/extensions/reducers/sidebar");
|
||||
exports.flexbox = require("devtools/client/inspector/flexbox/reducers/flexbox");
|
||||
exports.fontOptions = require("devtools/client/inspector/fonts/reducers/font-options");
|
||||
|
40
devtools/client/inspector/rules/actions/class-list.js
Normal file
40
devtools/client/inspector/rules/actions/class-list.js
Normal file
@ -0,0 +1,40 @@
|
||||
/* 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 {
|
||||
UPDATE_CLASSES,
|
||||
UPDATE_CLASS_PANEL_EXPANDED,
|
||||
} = require("./index");
|
||||
|
||||
module.exports = {
|
||||
|
||||
/**
|
||||
* Updates the entire class list state with the new list of classes.
|
||||
*
|
||||
* @param {Array<Object>} classes
|
||||
* Array of CSS classes object applied to the element.
|
||||
*/
|
||||
updateClasses(classes) {
|
||||
return {
|
||||
type: UPDATE_CLASSES,
|
||||
classes,
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates whether or not the class list panel is expanded.
|
||||
*
|
||||
* @param {Boolean} isClassPanelExpanded
|
||||
* Whether or not the class list panel is expanded.
|
||||
*/
|
||||
updateClassPanelExpanded(isClassPanelExpanded) {
|
||||
return {
|
||||
type: UPDATE_CLASS_PANEL_EXPANDED,
|
||||
isClassPanelExpanded,
|
||||
};
|
||||
},
|
||||
|
||||
};
|
@ -19,6 +19,12 @@ createEnum([
|
||||
// Toggles on or off the given pseudo class value for the current selected element.
|
||||
"TOGGLE_PSEUDO_CLASS",
|
||||
|
||||
// Updates the entire class list state with the new list of classes.
|
||||
"UPDATE_CLASSES",
|
||||
|
||||
// Updates whether or not the class list panel is expanded.
|
||||
"UPDATE_CLASS_PANEL_EXPANDED",
|
||||
|
||||
// Updates the highlighted selector.
|
||||
"UPDATE_HIGHLIGHTED_SELECTOR",
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DevToolsModules(
|
||||
'class-list.js',
|
||||
'index.js',
|
||||
'pseudo-classes.js',
|
||||
'rules.js',
|
||||
|
@ -4,14 +4,57 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const { PureComponent } = require("devtools/client/shared/vendor/react");
|
||||
const { createRef, PureComponent } = require("devtools/client/shared/vendor/react");
|
||||
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
const { connect } = require("devtools/client/shared/vendor/react-redux");
|
||||
const { KeyCodes } = require("devtools/client/shared/keycodes");
|
||||
|
||||
const { getStr } = require("../utils/l10n");
|
||||
const Types = require("../types");
|
||||
|
||||
class ClassListPanel extends PureComponent {
|
||||
static get propTypes() {
|
||||
return {};
|
||||
return {
|
||||
classes: PropTypes.arrayOf(PropTypes.shape(Types.class)).isRequired,
|
||||
onAddClass: PropTypes.func.isRequired,
|
||||
onSetClassState: PropTypes.func.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
// Class list panel input value.
|
||||
value: "",
|
||||
};
|
||||
|
||||
this.inputRef = createRef();
|
||||
|
||||
this.onInputChange = this.onInputChange.bind(this);
|
||||
this.onInputKeyUp = this.onInputKeyUp.bind(this);
|
||||
this.onToggleChange = this.onToggleChange.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.inputRef.current.focus();
|
||||
}
|
||||
|
||||
onInputChange({ target }) {
|
||||
this.setState({ value: target.value });
|
||||
}
|
||||
|
||||
onInputKeyUp({ target, keyCode }) {
|
||||
// On Enter, submit the input.
|
||||
if (keyCode === KeyCodes.DOM_VK_RETURN) {
|
||||
this.props.onAddClass(target.value);
|
||||
this.setState({ value: "" });
|
||||
}
|
||||
}
|
||||
|
||||
onToggleChange({ target }) {
|
||||
this.props.onSetClassState(target.value, target.checked);
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -24,13 +67,42 @@ class ClassListPanel extends PureComponent {
|
||||
dom.input({
|
||||
className: "devtools-textinput add-class",
|
||||
placeholder: getStr("rule.classPanel.newClass.placeholder"),
|
||||
onChange: this.onInputChange,
|
||||
onKeyUp: this.onInputKeyUp,
|
||||
ref: this.inputRef,
|
||||
value: this.state.value,
|
||||
}),
|
||||
dom.div({ className: "classes" },
|
||||
dom.p({ className: "no-classes" }, getStr("rule.classPanel.noClasses"))
|
||||
this.props.classes.length ?
|
||||
this.props.classes.map(({ name, isApplied }) => {
|
||||
return (
|
||||
dom.label(
|
||||
{
|
||||
key: name,
|
||||
title: name,
|
||||
},
|
||||
dom.input({
|
||||
checked: isApplied,
|
||||
onChange: this.onToggleChange,
|
||||
type: "checkbox",
|
||||
value: name,
|
||||
}),
|
||||
dom.span({}, name)
|
||||
)
|
||||
);
|
||||
})
|
||||
:
|
||||
dom.p({ className: "no-classes" }, getStr("rule.classPanel.noClasses"))
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ClassListPanel;
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
classes: state.classList.classes,
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = connect(mapStateToProps)(ClassListPanel);
|
||||
|
@ -21,6 +21,7 @@ class Rule extends PureComponent {
|
||||
onToggleDeclaration: PropTypes.func.isRequired,
|
||||
onToggleSelectorHighlighter: PropTypes.func.isRequired,
|
||||
rule: PropTypes.shape(Types.rule).isRequired,
|
||||
showSelectorEditor: PropTypes.func.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
@ -29,9 +30,11 @@ class Rule extends PureComponent {
|
||||
onToggleDeclaration,
|
||||
onToggleSelectorHighlighter,
|
||||
rule,
|
||||
showSelectorEditor,
|
||||
} = this.props;
|
||||
const {
|
||||
declarations,
|
||||
id,
|
||||
isUnmatched,
|
||||
isUserAgentStyle,
|
||||
selector,
|
||||
@ -50,7 +53,10 @@ class Rule extends PureComponent {
|
||||
dom.div({ className: "ruleview-code" },
|
||||
dom.div({},
|
||||
Selector({
|
||||
id,
|
||||
isUserAgentStyle,
|
||||
selector,
|
||||
showSelectorEditor,
|
||||
type,
|
||||
}),
|
||||
type !== CSSRule.KEYFRAME_RULE ?
|
||||
|
@ -17,6 +17,7 @@ class Rules extends PureComponent {
|
||||
onToggleDeclaration: PropTypes.func.isRequired,
|
||||
onToggleSelectorHighlighter: PropTypes.func.isRequired,
|
||||
rules: PropTypes.arrayOf(PropTypes.shape(Types.rule)).isRequired,
|
||||
showSelectorEditor: PropTypes.func.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
@ -25,6 +26,7 @@ class Rules extends PureComponent {
|
||||
onToggleDeclaration,
|
||||
onToggleSelectorHighlighter,
|
||||
rules,
|
||||
showSelectorEditor,
|
||||
} = this.props;
|
||||
|
||||
return rules.map(rule => {
|
||||
@ -33,6 +35,7 @@ class Rules extends PureComponent {
|
||||
onToggleDeclaration,
|
||||
onToggleSelectorHighlighter,
|
||||
rule,
|
||||
showSelectorEditor,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -28,10 +28,22 @@ const SHOW_PSEUDO_ELEMENTS_PREF = "devtools.inspector.show_pseudo_elements";
|
||||
class RulesApp extends PureComponent {
|
||||
static get propTypes() {
|
||||
return {
|
||||
onAddClass: PropTypes.func.isRequired,
|
||||
onSetClassState: PropTypes.func.isRequired,
|
||||
onToggleClassPanelExpanded: PropTypes.func.isRequired,
|
||||
onToggleDeclaration: PropTypes.func.isRequired,
|
||||
onTogglePseudoClass: PropTypes.func.isRequired,
|
||||
onToggleSelectorHighlighter: PropTypes.func.isRequired,
|
||||
rules: PropTypes.arrayOf(PropTypes.shape(Types.rule)).isRequired,
|
||||
showSelectorEditor: PropTypes.func.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
getRuleProps() {
|
||||
return {
|
||||
onToggleDeclaration: this.props.onToggleDeclaration,
|
||||
onToggleSelectorHighlighter: this.props.onToggleSelectorHighlighter,
|
||||
showSelectorEditor: this.props.showSelectorEditor,
|
||||
};
|
||||
}
|
||||
|
||||
@ -53,8 +65,7 @@ class RulesApp extends PureComponent {
|
||||
}
|
||||
|
||||
output.push(Rule({
|
||||
onToggleDeclaration: this.props.onToggleDeclaration,
|
||||
onToggleSelectorHighlighter: this.props.onToggleSelectorHighlighter,
|
||||
...this.getRuleProps(),
|
||||
rule,
|
||||
}));
|
||||
}
|
||||
@ -81,8 +92,7 @@ class RulesApp extends PureComponent {
|
||||
{
|
||||
component: Rules,
|
||||
componentProps: {
|
||||
onToggleDeclaration: this.props.onToggleDeclaration,
|
||||
onToggleSelectorHighlighter: this.props.onToggleSelectorHighlighter,
|
||||
...this.getRuleProps(),
|
||||
rules: rules.filter(r => r.keyframesRule.id === lastKeyframes),
|
||||
},
|
||||
header: rule.keyframesRule.keyframesName,
|
||||
@ -102,8 +112,7 @@ class RulesApp extends PureComponent {
|
||||
}
|
||||
|
||||
return Rules({
|
||||
onToggleDeclaration: this.props.onToggleDeclaration,
|
||||
onToggleSelectorHighlighter: this.props.onToggleSelectorHighlighter,
|
||||
...this.getRuleProps(),
|
||||
rules,
|
||||
});
|
||||
}
|
||||
@ -117,8 +126,7 @@ class RulesApp extends PureComponent {
|
||||
{
|
||||
component: Rules,
|
||||
componentProps: {
|
||||
onToggleDeclaration: this.props.onToggleDeclaration,
|
||||
onToggleSelectorHighlighter: this.props.onToggleSelectorHighlighter,
|
||||
...this.getRuleProps(),
|
||||
rules,
|
||||
},
|
||||
header: getStr("rule.pseudoElement"),
|
||||
@ -162,6 +170,9 @@ class RulesApp extends PureComponent {
|
||||
className: "theme-sidebar inspector-tabpanel",
|
||||
},
|
||||
Toolbar({
|
||||
onAddClass: this.props.onAddClass,
|
||||
onSetClassState: this.props.onSetClassState,
|
||||
onToggleClassPanelExpanded: this.props.onToggleClassPanelExpanded,
|
||||
onTogglePseudoClass: this.props.onTogglePseudoClass,
|
||||
}),
|
||||
dom.div(
|
||||
|
@ -4,10 +4,10 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const { PureComponent } = require("devtools/client/shared/vendor/react");
|
||||
const { createRef, PureComponent } = require("devtools/client/shared/vendor/react");
|
||||
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
|
||||
const { editableItem } = require("devtools/client/shared/inplace-editor");
|
||||
const {
|
||||
parsePseudoClassesAndAttributes,
|
||||
SELECTOR_ATTRIBUTE,
|
||||
@ -24,11 +24,34 @@ const Types = require("../types");
|
||||
class Selector extends PureComponent {
|
||||
static get propTypes() {
|
||||
return {
|
||||
id: PropTypes.string.isRequired,
|
||||
isUserAgentStyle: PropTypes.bool.isRequired,
|
||||
selector: PropTypes.shape(Types.selector).isRequired,
|
||||
showSelectorEditor: PropTypes.func.isRequired,
|
||||
type: PropTypes.number.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.selectorRef = createRef();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.isUserAgentStyle ||
|
||||
this.props.type === ELEMENT_STYLE ||
|
||||
this.props.type === CSSRule.KEYFRAME_RULE) {
|
||||
// Selector is not editable.
|
||||
return;
|
||||
}
|
||||
|
||||
editableItem({
|
||||
element: this.selectorRef.current,
|
||||
}, element => {
|
||||
this.props.showSelectorEditor(element, this.props.id);
|
||||
});
|
||||
}
|
||||
|
||||
renderSelector() {
|
||||
// Show the text directly for custom selector text (such as the inline "element"
|
||||
// style and Keyframes rules).
|
||||
@ -87,6 +110,7 @@ class Selector extends PureComponent {
|
||||
dom.span(
|
||||
{
|
||||
className: "ruleview-selectorcontainer",
|
||||
ref: this.selectorRef,
|
||||
tabIndex: 0,
|
||||
},
|
||||
this.renderSelector()
|
||||
|
@ -7,6 +7,7 @@
|
||||
const { createFactory, PureComponent } = require("devtools/client/shared/vendor/react");
|
||||
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
const { connect } = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
const SearchBox = createFactory(require("./SearchBox"));
|
||||
|
||||
@ -22,6 +23,10 @@ const { getStr } = require("../utils/l10n");
|
||||
class Toolbar extends PureComponent {
|
||||
static get propTypes() {
|
||||
return {
|
||||
isClassPanelExpanded: PropTypes.bool.isRequired,
|
||||
onAddClass: PropTypes.func.isRequired,
|
||||
onSetClassState: PropTypes.func.isRequired,
|
||||
onToggleClassPanelExpanded: PropTypes.func.isRequired,
|
||||
onTogglePseudoClass: PropTypes.func.isRequired,
|
||||
};
|
||||
}
|
||||
@ -30,8 +35,6 @@ class Toolbar extends PureComponent {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
// Whether or not the class panel is expanded.
|
||||
isClassPanelExpanded: false,
|
||||
// Whether or not the pseudo class panel is expanded.
|
||||
isPseudoClassPanelExpanded: false,
|
||||
};
|
||||
@ -43,14 +46,13 @@ class Toolbar extends PureComponent {
|
||||
onClassPanelToggle(event) {
|
||||
event.stopPropagation();
|
||||
|
||||
const isClassPanelExpanded = !this.props.isClassPanelExpanded;
|
||||
this.props.onToggleClassPanelExpanded(isClassPanelExpanded);
|
||||
this.setState(prevState => {
|
||||
const isClassPanelExpanded = !prevState.isClassPanelExpanded;
|
||||
const isPseudoClassPanelExpanded = isClassPanelExpanded ?
|
||||
false : prevState.isPseudoClassPanelExpanded;
|
||||
|
||||
return {
|
||||
isClassPanelExpanded,
|
||||
isPseudoClassPanelExpanded,
|
||||
isPseudoClassPanelExpanded: isClassPanelExpanded ?
|
||||
false :
|
||||
prevState.isPseudoClassPanelExpanded,
|
||||
};
|
||||
});
|
||||
}
|
||||
@ -58,23 +60,18 @@ class Toolbar extends PureComponent {
|
||||
onPseudoClassPanelToggle(event) {
|
||||
event.stopPropagation();
|
||||
|
||||
this.setState(prevState => {
|
||||
const isPseudoClassPanelExpanded = !prevState.isPseudoClassPanelExpanded;
|
||||
const isClassPanelExpanded = isPseudoClassPanelExpanded ?
|
||||
false : prevState.isClassPanelExpanded;
|
||||
const isPseudoClassPanelExpanded = !this.state.isPseudoClassPanelExpanded;
|
||||
|
||||
return {
|
||||
isClassPanelExpanded,
|
||||
isPseudoClassPanelExpanded,
|
||||
};
|
||||
});
|
||||
if (isPseudoClassPanelExpanded) {
|
||||
this.props.onToggleClassPanelExpanded(false);
|
||||
}
|
||||
|
||||
this.setState({ isPseudoClassPanelExpanded });
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
isClassPanelExpanded,
|
||||
isPseudoClassPanelExpanded,
|
||||
} = this.state;
|
||||
const { isClassPanelExpanded } = this.props;
|
||||
const { isPseudoClassPanelExpanded } = this.state;
|
||||
|
||||
return (
|
||||
dom.div(
|
||||
@ -107,7 +104,10 @@ class Toolbar extends PureComponent {
|
||||
)
|
||||
),
|
||||
isClassPanelExpanded ?
|
||||
ClassListPanel({})
|
||||
ClassListPanel({
|
||||
onAddClass: this.props.onAddClass,
|
||||
onSetClassState: this.props.onSetClassState,
|
||||
})
|
||||
:
|
||||
null,
|
||||
isPseudoClassPanelExpanded ?
|
||||
@ -121,4 +121,10 @@ class Toolbar extends PureComponent {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Toolbar;
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
isClassPanelExpanded: state.classList.isClassPanelExpanded,
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = connect(mapStateToProps)(Toolbar);
|
||||
|
191
devtools/client/inspector/rules/models/class-list.js
Normal file
191
devtools/client/inspector/rules/models/class-list.js
Normal file
@ -0,0 +1,191 @@
|
||||
/* 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 EventEmitter = require("devtools/shared/event-emitter");
|
||||
|
||||
// This serves as a local cache for the classes applied to each of the node we care about
|
||||
// here.
|
||||
// The map is indexed by NodeFront. Any time a new node is selected in the inspector, an
|
||||
// entry is added here, indexed by the corresponding NodeFront.
|
||||
// The value for each entry is an array of each of the class this node has. Items of this
|
||||
// array are objects like: { name, isApplied } where the name is the class itself, and
|
||||
// isApplied is a Boolean indicating if the class is applied on the node or not.
|
||||
const CLASSES = new WeakMap();
|
||||
|
||||
/**
|
||||
* Manages the list classes per DOM elements we care about.
|
||||
* The actual list is stored in the CLASSES const, indexed by NodeFront objects.
|
||||
* The responsibility of this class is to be the source of truth for anyone who wants to
|
||||
* know which classes a given NodeFront has, and which of these are enabled and which are
|
||||
* disabled.
|
||||
* It also reacts to DOM mutations so the list of classes is up to date with what is in
|
||||
* the DOM.
|
||||
* It can also be used to enable/disable a given class, or add classes.
|
||||
*
|
||||
* @param {Inspector} inspector
|
||||
* The current inspector instance.
|
||||
*/
|
||||
function ClassList(inspector) {
|
||||
EventEmitter.decorate(this);
|
||||
|
||||
this.inspector = inspector;
|
||||
|
||||
this.onMutations = this.onMutations.bind(this);
|
||||
this.inspector.on("markupmutation", this.onMutations);
|
||||
|
||||
this.classListProxyNode = this.inspector.panelDoc.createElement("div");
|
||||
}
|
||||
|
||||
ClassList.prototype = {
|
||||
destroy() {
|
||||
this.inspector.off("markupmutation", this.onMutations);
|
||||
this.inspector = null;
|
||||
this.classListProxyNode = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* The current node selection (which only returns if the node is an ELEMENT_NODE type
|
||||
* since that's the only type this model can work with.)
|
||||
*/
|
||||
get currentNode() {
|
||||
if (this.inspector.selection.isElementNode() &&
|
||||
!this.inspector.selection.isPseudoElementNode()) {
|
||||
return this.inspector.selection.nodeFront;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* The class states for the current node selection. See the documentation of the CLASSES
|
||||
* constant.
|
||||
*/
|
||||
get currentClasses() {
|
||||
if (!this.currentNode) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!CLASSES.has(this.currentNode)) {
|
||||
// Use the proxy node to get a clean list of classes.
|
||||
this.classListProxyNode.className = this.currentNode.className;
|
||||
const nodeClasses = [...new Set([...this.classListProxyNode.classList])]
|
||||
.map(name => {
|
||||
return { name, isApplied: true };
|
||||
});
|
||||
|
||||
CLASSES.set(this.currentNode, nodeClasses);
|
||||
}
|
||||
|
||||
return CLASSES.get(this.currentNode);
|
||||
},
|
||||
|
||||
/**
|
||||
* Same as currentClasses, but returns it in the form of a className string, where only
|
||||
* enabled classes are added.
|
||||
*/
|
||||
get currentClassesPreview() {
|
||||
return this.currentClasses.filter(({ isApplied }) => isApplied)
|
||||
.map(({ name }) => name)
|
||||
.join(" ");
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the state for a given class on the current node.
|
||||
*
|
||||
* @param {String} name
|
||||
* The class which state should be changed.
|
||||
* @param {Boolean} isApplied
|
||||
* True if the class should be enabled, false otherwise.
|
||||
* @return {Promise} Resolves when the change has been made in the DOM.
|
||||
*/
|
||||
setClassState(name, isApplied) {
|
||||
// Do the change in our local model.
|
||||
const nodeClasses = this.currentClasses;
|
||||
nodeClasses.find(({ name: cName }) => cName === name).isApplied = isApplied;
|
||||
|
||||
return this.applyClassState();
|
||||
},
|
||||
|
||||
/**
|
||||
* Add several classes to the current node at once.
|
||||
*
|
||||
* @param {String} classNameString
|
||||
* The string that contains all classes.
|
||||
* @return {Promise} Resolves when the change has been made in the DOM.
|
||||
*/
|
||||
addClassName(classNameString) {
|
||||
this.classListProxyNode.className = classNameString;
|
||||
return Promise.all([...new Set([...this.classListProxyNode.classList])].map(name => {
|
||||
return this.addClass(name);
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a class to the current node at once.
|
||||
*
|
||||
* @param {String} name
|
||||
* The class to be added.
|
||||
* @return {Promise} Resolves when the change has been made in the DOM.
|
||||
*/
|
||||
addClass(name) {
|
||||
// Avoid adding the same class again.
|
||||
if (this.currentClasses.some(({ name: cName }) => cName === name)) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
// Change the local model, so we retain the state of the existing classes.
|
||||
this.currentClasses.push({ name, isApplied: true });
|
||||
|
||||
return this.applyClassState();
|
||||
},
|
||||
|
||||
/**
|
||||
* Used internally by other functions like addClass or setClassState. Actually applies
|
||||
* the class change to the DOM.
|
||||
*
|
||||
* @return {Promise} Resolves when the change has been made in the DOM.
|
||||
*/
|
||||
applyClassState() {
|
||||
// If there is no valid inspector selection, bail out silently. No need to report an
|
||||
// error here.
|
||||
if (!this.currentNode) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
// Remember which node we changed and the className we applied, so we can filter out
|
||||
// dom mutations that are caused by us in onMutations.
|
||||
this.lastStateChange = {
|
||||
node: this.currentNode,
|
||||
className: this.currentClassesPreview,
|
||||
};
|
||||
|
||||
// Apply the change to the node.
|
||||
const mod = this.currentNode.startModifyingAttributes();
|
||||
mod.setAttribute("class", this.currentClassesPreview);
|
||||
return mod.apply();
|
||||
},
|
||||
|
||||
onMutations(mutations) {
|
||||
for (const {type, target, attributeName} of mutations) {
|
||||
// Only care if this mutation is for the class attribute.
|
||||
if (type !== "attributes" || attributeName !== "class") {
|
||||
continue;
|
||||
}
|
||||
|
||||
const isMutationForOurChange = this.lastStateChange &&
|
||||
target === this.lastStateChange.node &&
|
||||
target.className === this.lastStateChange.className;
|
||||
|
||||
if (!isMutationForOurChange) {
|
||||
CLASSES.delete(target);
|
||||
if (target === this.currentNode) {
|
||||
this.emit("current-node-class-changed");
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = ClassList;
|
@ -332,6 +332,73 @@ ElementStyle.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Modifies the existing rule's selector to the new given value.
|
||||
*
|
||||
* @param {String} ruleId
|
||||
* The id of the Rule to be modified.
|
||||
* @param {String} selector
|
||||
* The new selector value.
|
||||
*/
|
||||
modifySelector: async function(ruleId, selector) {
|
||||
try {
|
||||
const rule = this.getRule(ruleId);
|
||||
if (!rule) {
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await rule.domRule.modifySelector(this.element, selector);
|
||||
const { ruleProps, isMatching } = response;
|
||||
|
||||
if (!ruleProps) {
|
||||
// Notify for changes, even when nothing changes, just to allow tests
|
||||
// being able to track end of this request.
|
||||
this.ruleView.emit("ruleview-invalid-selector");
|
||||
return;
|
||||
}
|
||||
|
||||
const newRule = new Rule(this, {
|
||||
...ruleProps,
|
||||
isUnmatched: !isMatching,
|
||||
});
|
||||
|
||||
// Recompute the list of applied styles because editing a
|
||||
// selector might cause this rule's position to change.
|
||||
const appliedStyles = await this.pageStyle.getApplied(this.element, {
|
||||
inherited: true,
|
||||
matchedSelectors: true,
|
||||
filter: this.showUserAgentStyles ? "ua" : undefined,
|
||||
});
|
||||
const newIndex = appliedStyles.findIndex(r => r.rule == ruleProps.rule);
|
||||
const oldIndex = this.rules.indexOf(rule);
|
||||
|
||||
// Remove the old rule and insert the new rule according to where it appears
|
||||
// in the list of applied styles.
|
||||
this.rules.splice(oldIndex, 1);
|
||||
// If the selector no longer matches, then we leave the rule in
|
||||
// the same relative position.
|
||||
this.rules.splice(newIndex === -1 ? oldIndex : newIndex, 0, newRule);
|
||||
|
||||
// Mark any properties that are overridden according to the new list of rules.
|
||||
this.markOverriddenAll();
|
||||
|
||||
// In order to keep the new rule in place of the old in the rules view, we need
|
||||
// to remove the rule again if the rule was inserted to its new index according
|
||||
// to the list of applied styles.
|
||||
// Note: you might think we would replicate the list-modification logic above,
|
||||
// but that is complicated due to the way the UI installs pseudo-element rules
|
||||
// and the like.
|
||||
if (newIndex !== -1) {
|
||||
this.rules.splice(newIndex, 1);
|
||||
this.rules.splice(oldIndex, 0, newRule);
|
||||
}
|
||||
|
||||
this._changed();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggles the enabled state of the given CSS declaration.
|
||||
*
|
||||
|
@ -5,6 +5,7 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DevToolsModules(
|
||||
'class-list.js',
|
||||
'element-style.js',
|
||||
'rule.js',
|
||||
'text-property.js',
|
||||
|
@ -10,6 +10,10 @@ const { createFactory, createElement } = require("devtools/client/shared/vendor/
|
||||
const { Provider } = require("devtools/client/shared/vendor/react-redux");
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
|
||||
const {
|
||||
updateClasses,
|
||||
updateClassPanelExpanded,
|
||||
} = require("./actions/class-list");
|
||||
const {
|
||||
disableAllPseudoClasses,
|
||||
setPseudoClassLocks,
|
||||
@ -26,6 +30,9 @@ const { LocalizationHelper } = require("devtools/shared/l10n");
|
||||
const INSPECTOR_L10N =
|
||||
new LocalizationHelper("devtools/client/locales/inspector.properties");
|
||||
|
||||
loader.lazyRequireGetter(this, "ClassList", "devtools/client/inspector/rules/models/class-list");
|
||||
loader.lazyRequireGetter(this, "InplaceEditor", "devtools/client/shared/inplace-editor", true);
|
||||
|
||||
const PREF_UA_STYLES = "devtools.inspector.showUserAgentStyles";
|
||||
|
||||
class RulesView {
|
||||
@ -41,10 +48,15 @@ class RulesView {
|
||||
|
||||
this.showUserAgentStyles = Services.prefs.getBoolPref(PREF_UA_STYLES);
|
||||
|
||||
this.onAddClass = this.onAddClass.bind(this);
|
||||
this.onSelection = this.onSelection.bind(this);
|
||||
this.onSetClassState = this.onSetClassState.bind(this);
|
||||
this.onToggleClassPanelExpanded = this.onToggleClassPanelExpanded.bind(this);
|
||||
this.onToggleDeclaration = this.onToggleDeclaration.bind(this);
|
||||
this.onTogglePseudoClass = this.onTogglePseudoClass.bind(this);
|
||||
this.onToggleSelectorHighlighter = this.onToggleSelectorHighlighter.bind(this);
|
||||
this.showSelectorEditor = this.showSelectorEditor.bind(this);
|
||||
this.updateClassList = this.updateClassList.bind(this);
|
||||
this.updateRules = this.updateRules.bind(this);
|
||||
|
||||
this.inspector.sidebar.on("select", this.onSelection);
|
||||
@ -62,9 +74,13 @@ class RulesView {
|
||||
}
|
||||
|
||||
const rulesApp = RulesApp({
|
||||
onAddClass: this.onAddClass,
|
||||
onSetClassState: this.onSetClassState,
|
||||
onToggleClassPanelExpanded: this.onToggleClassPanelExpanded,
|
||||
onToggleDeclaration: this.onToggleDeclaration,
|
||||
onTogglePseudoClass: this.onTogglePseudoClass,
|
||||
onToggleSelectorHighlighter: this.onToggleSelectorHighlighter,
|
||||
showSelectorEditor: this.showSelectorEditor,
|
||||
});
|
||||
|
||||
const provider = createElement(Provider, {
|
||||
@ -83,6 +99,12 @@ class RulesView {
|
||||
this.selection.off("detached-front", this.onSelection);
|
||||
this.selection.off("new-node-front", this.onSelection);
|
||||
|
||||
if (this._classList) {
|
||||
this._classList.off("current-node-class-changed", this.refreshClassList);
|
||||
this._classList.destroy();
|
||||
this._classList = null;
|
||||
}
|
||||
|
||||
if (this._selectHighlighter) {
|
||||
this._selectorHighlighter.finalize();
|
||||
this._selectorHighlighter = null;
|
||||
@ -105,6 +127,19 @@ class RulesView {
|
||||
this.toolbox = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an instance of the ClassList model used to manage the list of CSS classes
|
||||
* applied to the element.
|
||||
*
|
||||
* @return {ClassList} used to manage the list of CSS classes applied to the element.
|
||||
*/
|
||||
get classList() {
|
||||
if (!this._classList) {
|
||||
this._classList = new ClassList(this.inspector);
|
||||
}
|
||||
|
||||
return this._classList;
|
||||
}
|
||||
/**
|
||||
* Creates a dummy element in the document that helps get the computed style in
|
||||
* TextProperty.
|
||||
@ -166,6 +201,17 @@ class RulesView {
|
||||
this.inspector.sidebar.getCurrentTabID() === "newruleview";
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for adding the given CSS class value to the current element's class list.
|
||||
*
|
||||
* @param {String} value
|
||||
* The string that contains all classes.
|
||||
*/
|
||||
async onAddClass(value) {
|
||||
await this.classList.addClassName(value);
|
||||
this.updateClassList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for selection events "detached-front" and "new-node-front" and inspector
|
||||
* sidbar "select" event. Updates the rules view with the selected node if the panel
|
||||
@ -185,6 +231,36 @@ class RulesView {
|
||||
this.update(this.selection.nodeFront);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for toggling a CSS class from the current element's class list. Sets the
|
||||
* state of given CSS class name to the given checked value.
|
||||
*
|
||||
* @param {String} name
|
||||
* The CSS class name.
|
||||
* @param {Boolean} checked
|
||||
* Whether or not the given CSS class is checked.
|
||||
*/
|
||||
async onSetClassState(name, checked) {
|
||||
await this.classList.setClassState(name, checked);
|
||||
this.updateClassList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for toggling the expanded property of the class list panel.
|
||||
*
|
||||
* @param {Boolean} isClassPanelExpanded
|
||||
* Whether or not the class list panel is expanded.
|
||||
*/
|
||||
onToggleClassPanelExpanded(isClassPanelExpanded) {
|
||||
if (isClassPanelExpanded) {
|
||||
this.classList.on("current-node-class-changed", this.updateClassList);
|
||||
} else {
|
||||
this.classList.off("current-node-class-changed", this.updateClassList);
|
||||
}
|
||||
|
||||
this.store.dispatch(updateClassPanelExpanded(isClassPanelExpanded));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for toggling the enabled property for a given CSS declaration.
|
||||
*
|
||||
@ -251,6 +327,35 @@ class RulesView {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the inplace editor for the a selector.
|
||||
*
|
||||
* @param {DOMNode} element
|
||||
* The selector's span element to show the inplace editor.
|
||||
* @param {String} ruleId
|
||||
* The id of the Rule to be modified.
|
||||
*/
|
||||
showSelectorEditor(element, ruleId) {
|
||||
new InplaceEditor({
|
||||
element,
|
||||
done: async (value, commit) => {
|
||||
if (!value || !commit) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Hide the selector highlighter if it matches the selector being edited.
|
||||
if (this.highlighters.selectorHighlighterShown) {
|
||||
const selector = await this.elementStyle.getRule(ruleId).getUniqueSelector();
|
||||
if (this.highlighters.selectorHighlighterShown === selector) {
|
||||
this.onToggleSelectorHighlighter(this.highlighters.selectorHighlighterShown);
|
||||
}
|
||||
}
|
||||
|
||||
await this.elementStyle.modifySelector(ruleId, value);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the rules view by dispatching the new rules data of the newly selected
|
||||
* element. This is called when the rules view becomes visible or upon new node
|
||||
@ -262,6 +367,7 @@ class RulesView {
|
||||
async update(element) {
|
||||
if (!element) {
|
||||
this.store.dispatch(disableAllPseudoClasses());
|
||||
this.store.dispatch(updateClasses([]));
|
||||
this.store.dispatch(updateRules([]));
|
||||
return;
|
||||
}
|
||||
@ -272,9 +378,17 @@ class RulesView {
|
||||
await this.elementStyle.populate();
|
||||
|
||||
this.store.dispatch(setPseudoClassLocks(this.elementStyle.element.pseudoClassLocks));
|
||||
this.updateClassList();
|
||||
this.updateRules();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the class list panel with the current list of CSS classes.
|
||||
*/
|
||||
updateClassList() {
|
||||
this.store.dispatch(updateClasses(this.classList.currentClasses));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the rules view by dispatching the current rules state. This is called from
|
||||
* the update() function, and from the ElementStyle's onChange() handler.
|
||||
|
44
devtools/client/inspector/rules/reducers/class-list.js
Normal file
44
devtools/client/inspector/rules/reducers/class-list.js
Normal file
@ -0,0 +1,44 @@
|
||||
/* 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 {
|
||||
UPDATE_CLASSES,
|
||||
UPDATE_CLASS_PANEL_EXPANDED,
|
||||
} = require("../actions/index");
|
||||
|
||||
const INITIAL_CLASS_LIST = {
|
||||
// An array of objects containing the CSS class state that is applied to the current
|
||||
// element.
|
||||
classes: [],
|
||||
// Whether or not the class list panel is expanded.
|
||||
isClassPanelExpanded: false,
|
||||
};
|
||||
|
||||
const reducers = {
|
||||
|
||||
[UPDATE_CLASSES](classList, { classes }) {
|
||||
return {
|
||||
...classList,
|
||||
classes: [...classes],
|
||||
};
|
||||
},
|
||||
|
||||
[UPDATE_CLASS_PANEL_EXPANDED](classList, { isClassPanelExpanded }) {
|
||||
return {
|
||||
...classList,
|
||||
isClassPanelExpanded,
|
||||
};
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
module.exports = function(classList = INITIAL_CLASS_LIST, action) {
|
||||
const reducer = reducers[action.type];
|
||||
if (!reducer) {
|
||||
return classList;
|
||||
}
|
||||
return reducer(classList, action);
|
||||
};
|
@ -3,6 +3,7 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DevToolsModules(
|
||||
'class-list.js',
|
||||
'pseudo-classes.js',
|
||||
'rules.js',
|
||||
)
|
||||
|
@ -6,6 +6,17 @@
|
||||
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
|
||||
/**
|
||||
* A CSS class.
|
||||
*/
|
||||
exports.classes = {
|
||||
// The CSS class name.
|
||||
name: PropTypes.string,
|
||||
|
||||
// Whether or not the CSS class is applied.
|
||||
isApplied: PropTypes.bool,
|
||||
};
|
||||
|
||||
/**
|
||||
* A CSS declaration.
|
||||
*/
|
||||
|
@ -4,193 +4,11 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const ClassList = require("devtools/client/inspector/rules/models/class-list");
|
||||
const {LocalizationHelper} = require("devtools/shared/l10n");
|
||||
|
||||
const L10N = new LocalizationHelper("devtools/client/locales/inspector.properties");
|
||||
|
||||
// This serves as a local cache for the classes applied to each of the node we care about
|
||||
// here.
|
||||
// The map is indexed by NodeFront. Any time a new node is selected in the inspector, an
|
||||
// entry is added here, indexed by the corresponding NodeFront.
|
||||
// The value for each entry is an array of each of the class this node has. Items of this
|
||||
// array are objects like: { name, isApplied } where the name is the class itself, and
|
||||
// isApplied is a Boolean indicating if the class is applied on the node or not.
|
||||
const CLASSES = new WeakMap();
|
||||
|
||||
/**
|
||||
* Manages the list classes per DOM elements we care about.
|
||||
* The actual list is stored in the CLASSES const, indexed by NodeFront objects.
|
||||
* The responsibility of this class is to be the source of truth for anyone who wants to
|
||||
* know which classes a given NodeFront has, and which of these are enabled and which are
|
||||
* disabled.
|
||||
* It also reacts to DOM mutations so the list of classes is up to date with what is in
|
||||
* the DOM.
|
||||
* It can also be used to enable/disable a given class, or add classes.
|
||||
*
|
||||
* @param {Inspector} inspector
|
||||
* The current inspector instance.
|
||||
*/
|
||||
function ClassListPreviewerModel(inspector) {
|
||||
EventEmitter.decorate(this);
|
||||
|
||||
this.inspector = inspector;
|
||||
|
||||
this.onMutations = this.onMutations.bind(this);
|
||||
this.inspector.on("markupmutation", this.onMutations);
|
||||
|
||||
this.classListProxyNode = this.inspector.panelDoc.createElement("div");
|
||||
}
|
||||
|
||||
ClassListPreviewerModel.prototype = {
|
||||
destroy() {
|
||||
this.inspector.off("markupmutation", this.onMutations);
|
||||
this.inspector = null;
|
||||
this.classListProxyNode = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* The current node selection (which only returns if the node is an ELEMENT_NODE type
|
||||
* since that's the only type this model can work with.)
|
||||
*/
|
||||
get currentNode() {
|
||||
if (this.inspector.selection.isElementNode() &&
|
||||
!this.inspector.selection.isPseudoElementNode()) {
|
||||
return this.inspector.selection.nodeFront;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* The class states for the current node selection. See the documentation of the CLASSES
|
||||
* constant.
|
||||
*/
|
||||
get currentClasses() {
|
||||
if (!this.currentNode) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!CLASSES.has(this.currentNode)) {
|
||||
// Use the proxy node to get a clean list of classes.
|
||||
this.classListProxyNode.className = this.currentNode.className;
|
||||
const nodeClasses = [...new Set([...this.classListProxyNode.classList])]
|
||||
.map(name => {
|
||||
return { name, isApplied: true };
|
||||
});
|
||||
|
||||
CLASSES.set(this.currentNode, nodeClasses);
|
||||
}
|
||||
|
||||
return CLASSES.get(this.currentNode);
|
||||
},
|
||||
|
||||
/**
|
||||
* Same as currentClasses, but returns it in the form of a className string, where only
|
||||
* enabled classes are added.
|
||||
*/
|
||||
get currentClassesPreview() {
|
||||
return this.currentClasses.filter(({ isApplied }) => isApplied)
|
||||
.map(({ name }) => name)
|
||||
.join(" ");
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the state for a given class on the current node.
|
||||
*
|
||||
* @param {String} name
|
||||
* The class which state should be changed.
|
||||
* @param {Boolean} isApplied
|
||||
* True if the class should be enabled, false otherwise.
|
||||
* @return {Promise} Resolves when the change has been made in the DOM.
|
||||
*/
|
||||
setClassState(name, isApplied) {
|
||||
// Do the change in our local model.
|
||||
const nodeClasses = this.currentClasses;
|
||||
nodeClasses.find(({ name: cName }) => cName === name).isApplied = isApplied;
|
||||
|
||||
return this.applyClassState();
|
||||
},
|
||||
|
||||
/**
|
||||
* Add several classes to the current node at once.
|
||||
*
|
||||
* @param {String} classNameString
|
||||
* The string that contains all classes.
|
||||
* @return {Promise} Resolves when the change has been made in the DOM.
|
||||
*/
|
||||
addClassName(classNameString) {
|
||||
this.classListProxyNode.className = classNameString;
|
||||
return Promise.all([...new Set([...this.classListProxyNode.classList])].map(name => {
|
||||
return this.addClass(name);
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a class to the current node at once.
|
||||
*
|
||||
* @param {String} name
|
||||
* The class to be added.
|
||||
* @return {Promise} Resolves when the change has been made in the DOM.
|
||||
*/
|
||||
addClass(name) {
|
||||
// Avoid adding the same class again.
|
||||
if (this.currentClasses.some(({ name: cName }) => cName === name)) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
// Change the local model, so we retain the state of the existing classes.
|
||||
this.currentClasses.push({ name, isApplied: true });
|
||||
|
||||
return this.applyClassState();
|
||||
},
|
||||
|
||||
/**
|
||||
* Used internally by other functions like addClass or setClassState. Actually applies
|
||||
* the class change to the DOM.
|
||||
*
|
||||
* @return {Promise} Resolves when the change has been made in the DOM.
|
||||
*/
|
||||
applyClassState() {
|
||||
// If there is no valid inspector selection, bail out silently. No need to report an
|
||||
// error here.
|
||||
if (!this.currentNode) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
// Remember which node we changed and the className we applied, so we can filter out
|
||||
// dom mutations that are caused by us in onMutations.
|
||||
this.lastStateChange = {
|
||||
node: this.currentNode,
|
||||
className: this.currentClassesPreview,
|
||||
};
|
||||
|
||||
// Apply the change to the node.
|
||||
const mod = this.currentNode.startModifyingAttributes();
|
||||
mod.setAttribute("class", this.currentClassesPreview);
|
||||
return mod.apply();
|
||||
},
|
||||
|
||||
onMutations(mutations) {
|
||||
for (const {type, target, attributeName} of mutations) {
|
||||
// Only care if this mutation is for the class attribute.
|
||||
if (type !== "attributes" || attributeName !== "class") {
|
||||
continue;
|
||||
}
|
||||
|
||||
const isMutationForOurChange = this.lastStateChange &&
|
||||
target === this.lastStateChange.node &&
|
||||
target.className === this.lastStateChange.className;
|
||||
|
||||
if (!isMutationForOurChange) {
|
||||
CLASSES.delete(target);
|
||||
if (target === this.currentNode) {
|
||||
this.emit("current-node-class-changed");
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* This UI widget shows a textfield and a series of checkboxes in the rule-view. It is
|
||||
* used to toggle classes on the current node selection, and add new classes.
|
||||
@ -203,7 +21,7 @@ ClassListPreviewerModel.prototype = {
|
||||
function ClassListPreviewer(inspector, containerEl) {
|
||||
this.inspector = inspector;
|
||||
this.containerEl = containerEl;
|
||||
this.model = new ClassListPreviewerModel(inspector);
|
||||
this.model = new ClassList(inspector);
|
||||
|
||||
this.onNewSelection = this.onNewSelection.bind(this);
|
||||
this.onCheckBoxChanged = this.onCheckBoxChanged.bind(this);
|
||||
|
@ -45,8 +45,6 @@ function setupServer(mm) {
|
||||
mm.addMessageListener("debug:content-process-destroy", function onDestroy() {
|
||||
mm.removeMessageListener("debug:content-process-destroy", onDestroy);
|
||||
|
||||
Cu.unblockThreadedExecution();
|
||||
|
||||
DebuggerServer.destroy();
|
||||
gLoader.destroy();
|
||||
gLoader = null;
|
||||
@ -59,32 +57,23 @@ function init(msg) {
|
||||
const mm = msg.target;
|
||||
const prefix = msg.data.prefix;
|
||||
|
||||
// Using the JS debugger causes problems when we're trying to
|
||||
// schedule those zone groups across different threads. Calling
|
||||
// blockThreadedExecution causes Gecko to switch to a simpler
|
||||
// single-threaded model until unblockThreadedExecution is called
|
||||
// later. We cannot start the debugger until the callback passed to
|
||||
// blockThreadedExecution has run, signaling that we're running
|
||||
// single-threaded.
|
||||
Cu.blockThreadedExecution(() => {
|
||||
// Setup a server if none started yet
|
||||
const loader = setupServer(mm);
|
||||
// Setup a server if none started yet
|
||||
const loader = setupServer(mm);
|
||||
|
||||
// Connect both parent/child processes debugger servers RDP via message
|
||||
// managers
|
||||
const { DebuggerServer } = loader.require("devtools/server/main");
|
||||
const conn = DebuggerServer.connectToParent(prefix, mm);
|
||||
conn.parentMessageManager = mm;
|
||||
// Connect both parent/child processes debugger servers RDP via message
|
||||
// managers
|
||||
const { DebuggerServer } = loader.require("devtools/server/main");
|
||||
const conn = DebuggerServer.connectToParent(prefix, mm);
|
||||
conn.parentMessageManager = mm;
|
||||
|
||||
const { ContentProcessTargetActor } =
|
||||
loader.require("devtools/server/actors/targets/content-process");
|
||||
const { ActorPool } = loader.require("devtools/server/actors/common");
|
||||
const actor = new ContentProcessTargetActor(conn);
|
||||
const actorPool = new ActorPool(conn);
|
||||
actorPool.addActor(actor);
|
||||
conn.addActorPool(actorPool);
|
||||
const { ContentProcessTargetActor } =
|
||||
loader.require("devtools/server/actors/targets/content-process");
|
||||
const { ActorPool } = loader.require("devtools/server/actors/common");
|
||||
const actor = new ContentProcessTargetActor(conn);
|
||||
const actorPool = new ActorPool(conn);
|
||||
actorPool.addActor(actor);
|
||||
conn.addActorPool(actorPool);
|
||||
|
||||
const response = { actor: actor.form() };
|
||||
mm.sendAsyncMessage("debug:content-process-actor", response);
|
||||
});
|
||||
const response = { actor: actor.form() };
|
||||
mm.sendAsyncMessage("debug:content-process-actor", response);
|
||||
}
|
||||
|
@ -39,34 +39,25 @@ try {
|
||||
const prefix = msg.data.prefix;
|
||||
const addonId = msg.data.addonId;
|
||||
|
||||
// Using the JS debugger causes problems when we're trying to
|
||||
// schedule those zone groups across different threads. Calling
|
||||
// blockThreadedExecution causes Gecko to switch to a simpler
|
||||
// single-threaded model until unblockThreadedExecution is
|
||||
// called later. We cannot start the debugger until the callback
|
||||
// passed to blockThreadedExecution has run, signaling that
|
||||
// we're running single-threaded.
|
||||
Cu.blockThreadedExecution(() => {
|
||||
const conn = DebuggerServer.connectToParent(prefix, mm);
|
||||
conn.parentMessageManager = mm;
|
||||
connections.set(prefix, conn);
|
||||
const conn = DebuggerServer.connectToParent(prefix, mm);
|
||||
conn.parentMessageManager = mm;
|
||||
connections.set(prefix, conn);
|
||||
|
||||
let actor;
|
||||
let actor;
|
||||
|
||||
if (addonId) {
|
||||
const { WebExtensionTargetActor } = require("devtools/server/actors/targets/webextension");
|
||||
actor = new WebExtensionTargetActor(conn, chromeGlobal, prefix, addonId);
|
||||
} else {
|
||||
const { FrameTargetActor } = require("devtools/server/actors/targets/frame");
|
||||
actor = new FrameTargetActor(conn, chromeGlobal);
|
||||
}
|
||||
if (addonId) {
|
||||
const { WebExtensionTargetActor } = require("devtools/server/actors/targets/webextension");
|
||||
actor = new WebExtensionTargetActor(conn, chromeGlobal, prefix, addonId);
|
||||
} else {
|
||||
const { FrameTargetActor } = require("devtools/server/actors/targets/frame");
|
||||
actor = new FrameTargetActor(conn, chromeGlobal);
|
||||
}
|
||||
|
||||
const actorPool = new ActorPool(conn);
|
||||
actorPool.addActor(actor);
|
||||
conn.addActorPool(actorPool);
|
||||
const actorPool = new ActorPool(conn);
|
||||
actorPool.addActor(actor);
|
||||
conn.addActorPool(actorPool);
|
||||
|
||||
sendAsyncMessage("debug:actor", {actor: actor.form(), prefix: prefix});
|
||||
});
|
||||
sendAsyncMessage("debug:actor", {actor: actor.form(), prefix: prefix});
|
||||
});
|
||||
|
||||
addMessageListener("debug:connect", onConnect);
|
||||
@ -113,8 +104,6 @@ try {
|
||||
return;
|
||||
}
|
||||
|
||||
Cu.unblockThreadedExecution();
|
||||
|
||||
removeMessageListener("debug:disconnect", onDisconnect);
|
||||
// Call DebuggerServerConnection.close to destroy all child actors. It should end up
|
||||
// calling DebuggerServerConnection.onClosed that would actually cleanup all actor
|
||||
|
@ -99,7 +99,6 @@
|
||||
#include "mozilla/ProcessHangMonitorIPC.h"
|
||||
#include "mozilla/RDDProcessManager.h"
|
||||
#include "mozilla/recordreplay/ParentIPC.h"
|
||||
#include "mozilla/Scheduler.h"
|
||||
#include "mozilla/ScopeExit.h"
|
||||
#include "mozilla/ScriptPreloader.h"
|
||||
#include "mozilla/Services.h"
|
||||
@ -2187,12 +2186,6 @@ void ContentParent::LaunchSubprocessInternal(
|
||||
extraArgs.push_back("-prefMapSize");
|
||||
extraArgs.push_back(formatPtrArg(prefSerializer.GetPrefMapSize()).get());
|
||||
|
||||
// Scheduler prefs need to be handled differently because the scheduler needs
|
||||
// to start up in the content process before the normal preferences service.
|
||||
nsPrintfCString schedulerPrefs = Scheduler::GetPrefs();
|
||||
extraArgs.push_back("-schedulerPrefs");
|
||||
extraArgs.push_back(schedulerPrefs.get());
|
||||
|
||||
if (gSafeMode) {
|
||||
extraArgs.push_back("-safeMode");
|
||||
}
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "ContentProcess.h"
|
||||
#include "base/shared_memory.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Scheduler.h"
|
||||
#include "mozilla/recordreplay/ParentIPC.h"
|
||||
|
||||
#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
|
||||
@ -81,7 +80,6 @@ static void SetUpSandboxEnvironment() {
|
||||
bool ContentProcess::Init(int aArgc, char* aArgv[]) {
|
||||
Maybe<uint64_t> childID;
|
||||
Maybe<bool> isForBrowser;
|
||||
Maybe<const char*> schedulerPrefs;
|
||||
Maybe<const char*> parentBuildID;
|
||||
char* prefsHandle = nullptr;
|
||||
char* prefMapHandle = nullptr;
|
||||
@ -142,12 +140,6 @@ bool ContentProcess::Init(int aArgc, char* aArgv[]) {
|
||||
return false;
|
||||
}
|
||||
prefMapSize = aArgv[i];
|
||||
} else if (strcmp(aArgv[i], "-schedulerPrefs") == 0) {
|
||||
if (++i == aArgc) {
|
||||
return false;
|
||||
}
|
||||
schedulerPrefs = Some(aArgv[i]);
|
||||
|
||||
} else if (strcmp(aArgv[i], "-safeMode") == 0) {
|
||||
gSafeMode = true;
|
||||
|
||||
@ -174,7 +166,7 @@ bool ContentProcess::Init(int aArgc, char* aArgv[]) {
|
||||
|
||||
// Did we find all the mandatory flags?
|
||||
if (childID.isNothing() || isForBrowser.isNothing() ||
|
||||
schedulerPrefs.isNothing() || parentBuildID.isNothing()) {
|
||||
parentBuildID.isNothing()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -184,8 +176,6 @@ bool ContentProcess::Init(int aArgc, char* aArgv[]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Scheduler::SetPrefs(*schedulerPrefs);
|
||||
|
||||
if (recordreplay::IsMiddleman()) {
|
||||
recordreplay::parent::InitializeMiddleman(aArgc, aArgv, ParentPid(),
|
||||
deserializer.GetPrefsHandle(),
|
||||
|
@ -27,11 +27,9 @@
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
class SpeechTaskCallback final : public nsISpeechTaskCallback
|
||||
{
|
||||
public:
|
||||
SpeechTaskCallback(nsISpeechTask* aTask,
|
||||
NSSpeechSynthesizer* aSynth,
|
||||
class SpeechTaskCallback final : public nsISpeechTaskCallback {
|
||||
public:
|
||||
SpeechTaskCallback(nsISpeechTask* aTask, NSSpeechSynthesizer* aSynth,
|
||||
const nsTArray<size_t>& aOffsets);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
@ -43,7 +41,7 @@ public:
|
||||
void OnError(uint32_t aIndex);
|
||||
void OnDidFinishSpeaking();
|
||||
|
||||
private:
|
||||
private:
|
||||
virtual ~SpeechTaskCallback();
|
||||
|
||||
float GetTimeDurationFromStart();
|
||||
@ -56,40 +54,35 @@ private:
|
||||
nsTArray<size_t> mOffsets;
|
||||
};
|
||||
|
||||
@interface SpeechDelegate : NSObject<NSSpeechSynthesizerDelegate>
|
||||
{
|
||||
@private
|
||||
@interface SpeechDelegate : NSObject <NSSpeechSynthesizerDelegate> {
|
||||
@private
|
||||
SpeechTaskCallback* mCallback;
|
||||
}
|
||||
|
||||
- (id)initWithCallback:(SpeechTaskCallback*)aCallback;
|
||||
- (id)initWithCallback:(SpeechTaskCallback*)aCallback;
|
||||
@end
|
||||
|
||||
@implementation SpeechDelegate
|
||||
- (id)initWithCallback:(SpeechTaskCallback*)aCallback
|
||||
{
|
||||
- (id)initWithCallback:(SpeechTaskCallback*)aCallback {
|
||||
[super init];
|
||||
mCallback = aCallback;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)speechSynthesizer:(NSSpeechSynthesizer *)aSender
|
||||
willSpeakWord:(NSRange)aRange ofString:(NSString*)aString
|
||||
{
|
||||
- (void)speechSynthesizer:(NSSpeechSynthesizer*)aSender
|
||||
willSpeakWord:(NSRange)aRange
|
||||
ofString:(NSString*)aString {
|
||||
mCallback->OnWillSpeakWord(aRange.location, aRange.length);
|
||||
}
|
||||
|
||||
- (void)speechSynthesizer:(NSSpeechSynthesizer *)aSender
|
||||
didFinishSpeaking:(BOOL)aFinishedSpeaking
|
||||
{
|
||||
- (void)speechSynthesizer:(NSSpeechSynthesizer*)aSender didFinishSpeaking:(BOOL)aFinishedSpeaking {
|
||||
mCallback->OnDidFinishSpeaking();
|
||||
}
|
||||
|
||||
- (void)speechSynthesizer:(NSSpeechSynthesizer*)aSender
|
||||
didEncounterErrorAtIndex:(NSUInteger)aCharacterIndex
|
||||
ofString:(NSString*)aString
|
||||
message:(NSString*)aMessage
|
||||
{
|
||||
didEncounterErrorAtIndex:(NSUInteger)aCharacterIndex
|
||||
ofString:(NSString*)aString
|
||||
message:(NSString*)aMessage {
|
||||
mCallback->OnError(aCharacterIndex);
|
||||
}
|
||||
@end
|
||||
@ -104,29 +97,22 @@ NS_INTERFACE_MAP_END
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(SpeechTaskCallback)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(SpeechTaskCallback)
|
||||
|
||||
SpeechTaskCallback::SpeechTaskCallback(nsISpeechTask* aTask,
|
||||
NSSpeechSynthesizer* aSynth,
|
||||
SpeechTaskCallback::SpeechTaskCallback(nsISpeechTask* aTask, NSSpeechSynthesizer* aSynth,
|
||||
const nsTArray<size_t>& aOffsets)
|
||||
: mTask(aTask)
|
||||
, mSpeechSynthesizer(aSynth)
|
||||
, mCurrentIndex(0)
|
||||
, mOffsets(aOffsets)
|
||||
{
|
||||
: mTask(aTask), mSpeechSynthesizer(aSynth), mCurrentIndex(0), mOffsets(aOffsets) {
|
||||
mDelegate = [[SpeechDelegate alloc] initWithCallback:this];
|
||||
[mSpeechSynthesizer setDelegate:mDelegate];
|
||||
mStartingTime = TimeStamp::Now();
|
||||
}
|
||||
|
||||
SpeechTaskCallback::~SpeechTaskCallback()
|
||||
{
|
||||
SpeechTaskCallback::~SpeechTaskCallback() {
|
||||
[mSpeechSynthesizer setDelegate:nil];
|
||||
[mDelegate release];
|
||||
[mSpeechSynthesizer release];
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SpeechTaskCallback::OnCancel()
|
||||
{
|
||||
SpeechTaskCallback::OnCancel() {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
[mSpeechSynthesizer stopSpeaking];
|
||||
@ -136,8 +122,7 @@ SpeechTaskCallback::OnCancel()
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SpeechTaskCallback::OnPause()
|
||||
{
|
||||
SpeechTaskCallback::OnPause() {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
[mSpeechSynthesizer pauseSpeakingAtBoundary:NSSpeechImmediateBoundary];
|
||||
@ -153,8 +138,7 @@ SpeechTaskCallback::OnPause()
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SpeechTaskCallback::OnResume()
|
||||
{
|
||||
SpeechTaskCallback::OnResume() {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
[mSpeechSynthesizer continueSpeaking];
|
||||
@ -170,48 +154,39 @@ SpeechTaskCallback::OnResume()
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SpeechTaskCallback::OnVolumeChanged(float aVolume)
|
||||
{
|
||||
SpeechTaskCallback::OnVolumeChanged(float aVolume) {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
[mSpeechSynthesizer setObject:[NSNumber numberWithFloat:aVolume]
|
||||
forProperty:NSSpeechVolumeProperty error:nil];
|
||||
forProperty:NSSpeechVolumeProperty
|
||||
error:nil];
|
||||
return NS_OK;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
||||
}
|
||||
|
||||
float
|
||||
SpeechTaskCallback::GetTimeDurationFromStart()
|
||||
{
|
||||
float SpeechTaskCallback::GetTimeDurationFromStart() {
|
||||
TimeDuration duration = TimeStamp::Now() - mStartingTime;
|
||||
return duration.ToMilliseconds();
|
||||
}
|
||||
|
||||
void
|
||||
SpeechTaskCallback::OnWillSpeakWord(uint32_t aIndex, uint32_t aLength)
|
||||
{
|
||||
void SpeechTaskCallback::OnWillSpeakWord(uint32_t aIndex, uint32_t aLength) {
|
||||
mCurrentIndex = aIndex < mOffsets.Length() ? mOffsets[aIndex] : mCurrentIndex;
|
||||
if (!mTask) {
|
||||
return;
|
||||
}
|
||||
mTask->DispatchBoundary(NS_LITERAL_STRING("word"),
|
||||
GetTimeDurationFromStart(),
|
||||
mCurrentIndex, aLength, 1);
|
||||
mTask->DispatchBoundary(NS_LITERAL_STRING("word"), GetTimeDurationFromStart(), mCurrentIndex,
|
||||
aLength, 1);
|
||||
}
|
||||
|
||||
void
|
||||
SpeechTaskCallback::OnError(uint32_t aIndex)
|
||||
{
|
||||
void SpeechTaskCallback::OnError(uint32_t aIndex) {
|
||||
if (!mTask) {
|
||||
return;
|
||||
}
|
||||
mTask->DispatchError(GetTimeDurationFromStart(), aIndex);
|
||||
}
|
||||
|
||||
void
|
||||
SpeechTaskCallback::OnDidFinishSpeaking()
|
||||
{
|
||||
void SpeechTaskCallback::OnDidFinishSpeaking() {
|
||||
mTask->DispatchEnd(GetTimeDurationFromStart(), mCurrentIndex);
|
||||
// no longer needed
|
||||
[mSpeechSynthesizer setDelegate:nil];
|
||||
@ -221,11 +196,8 @@ SpeechTaskCallback::OnDidFinishSpeaking()
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
struct OSXVoice
|
||||
{
|
||||
OSXVoice() : mIsDefault(false)
|
||||
{
|
||||
}
|
||||
struct OSXVoice {
|
||||
OSXVoice() : mIsDefault(false) {}
|
||||
|
||||
nsString mUri;
|
||||
nsString mName;
|
||||
@ -233,20 +205,14 @@ struct OSXVoice
|
||||
bool mIsDefault;
|
||||
};
|
||||
|
||||
class RegisterVoicesRunnable final : public Runnable
|
||||
{
|
||||
public:
|
||||
RegisterVoicesRunnable(OSXSpeechSynthesizerService* aSpeechService,
|
||||
nsTArray<OSXVoice>& aList)
|
||||
: Runnable("RegisterVoicesRunnable")
|
||||
, mSpeechService(aSpeechService)
|
||||
, mVoices(aList)
|
||||
{
|
||||
}
|
||||
class RegisterVoicesRunnable final : public Runnable {
|
||||
public:
|
||||
RegisterVoicesRunnable(OSXSpeechSynthesizerService* aSpeechService, nsTArray<OSXVoice>& aList)
|
||||
: Runnable("RegisterVoicesRunnable"), mSpeechService(aSpeechService), mVoices(aList) {}
|
||||
|
||||
NS_IMETHOD Run() override;
|
||||
|
||||
private:
|
||||
private:
|
||||
~RegisterVoicesRunnable() override = default;
|
||||
|
||||
// This runnable always use sync mode. It is unnecesarry to reference object
|
||||
@ -255,11 +221,9 @@ private:
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
RegisterVoicesRunnable::Run()
|
||||
{
|
||||
RegisterVoicesRunnable::Run() {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISynthVoiceRegistry> registry =
|
||||
do_GetService(NS_SYNTHVOICEREGISTRY_CONTRACTID, &rv);
|
||||
nsCOMPtr<nsISynthVoiceRegistry> registry = do_GetService(NS_SYNTHVOICEREGISTRY_CONTRACTID, &rv);
|
||||
if (!registry) {
|
||||
return rv;
|
||||
}
|
||||
@ -280,26 +244,21 @@ RegisterVoicesRunnable::Run()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class EnumVoicesRunnable final : public Runnable
|
||||
{
|
||||
public:
|
||||
class EnumVoicesRunnable final : public Runnable {
|
||||
public:
|
||||
explicit EnumVoicesRunnable(OSXSpeechSynthesizerService* aSpeechService)
|
||||
: Runnable("EnumVoicesRunnable")
|
||||
, mSpeechService(aSpeechService)
|
||||
{
|
||||
}
|
||||
: Runnable("EnumVoicesRunnable"), mSpeechService(aSpeechService) {}
|
||||
|
||||
NS_IMETHOD Run() override;
|
||||
|
||||
private:
|
||||
private:
|
||||
~EnumVoicesRunnable() override = default;
|
||||
|
||||
RefPtr<OSXSpeechSynthesizerService> mSpeechService;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
EnumVoicesRunnable::Run()
|
||||
{
|
||||
EnumVoicesRunnable::Run() {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
AutoTArray<OSXVoice, 64> list;
|
||||
@ -313,13 +272,11 @@ EnumVoicesRunnable::Run()
|
||||
NSDictionary* attr = [NSSpeechSynthesizer attributesForVoice:voice];
|
||||
|
||||
nsAutoString identifier;
|
||||
nsCocoaUtils::GetStringForNSString([attr objectForKey:NSVoiceIdentifier],
|
||||
identifier);
|
||||
nsCocoaUtils::GetStringForNSString([attr objectForKey:NSVoiceIdentifier], identifier);
|
||||
|
||||
nsCocoaUtils::GetStringForNSString([attr objectForKey:NSVoiceName], item.mName);
|
||||
|
||||
nsCocoaUtils::GetStringForNSString(
|
||||
[attr objectForKey:NSVoiceLocaleIdentifier], item.mLocale);
|
||||
nsCocoaUtils::GetStringForNSString([attr objectForKey:NSVoiceLocaleIdentifier], item.mLocale);
|
||||
item.mLocale.ReplaceChar('_', '-');
|
||||
|
||||
item.mUri.AssignLiteral("urn:moz-tts:osx:");
|
||||
@ -351,15 +308,9 @@ NS_INTERFACE_MAP_END
|
||||
NS_IMPL_ADDREF(OSXSpeechSynthesizerService)
|
||||
NS_IMPL_RELEASE(OSXSpeechSynthesizerService)
|
||||
|
||||
OSXSpeechSynthesizerService::OSXSpeechSynthesizerService()
|
||||
: mInitialized(false)
|
||||
{
|
||||
}
|
||||
OSXSpeechSynthesizerService::OSXSpeechSynthesizerService() : mInitialized(false) {}
|
||||
|
||||
|
||||
bool
|
||||
OSXSpeechSynthesizerService::Init()
|
||||
{
|
||||
bool OSXSpeechSynthesizerService::Init() {
|
||||
if (Preferences::GetBool("media.webspeech.synth.test") ||
|
||||
!Preferences::GetBool("media.webspeech.synth.enabled")) {
|
||||
// When test is enabled, we shouldn't add OS backend (Bug 1160844)
|
||||
@ -368,7 +319,7 @@ OSXSpeechSynthesizerService::Init()
|
||||
|
||||
nsCOMPtr<nsIThread> thread;
|
||||
if (NS_FAILED(NS_NewNamedThread("SpeechWorker", getter_AddRefs(thread)))) {
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get all the voices and register in the SynthVoiceRegistry
|
||||
@ -380,13 +331,8 @@ OSXSpeechSynthesizerService::Init()
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
OSXSpeechSynthesizerService::Speak(const nsAString& aText,
|
||||
const nsAString& aUri,
|
||||
float aVolume,
|
||||
float aRate,
|
||||
float aPitch,
|
||||
nsISpeechTask* aTask)
|
||||
{
|
||||
OSXSpeechSynthesizerService::Speak(const nsAString& aText, const nsAString& aUri, float aVolume,
|
||||
float aRate, float aPitch, nsISpeechTask* aTask) {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
MOZ_ASSERT(StringBeginsWith(aUri, NS_LITERAL_STRING("urn:moz-tts:osx:")),
|
||||
@ -398,18 +344,16 @@ OSXSpeechSynthesizerService::Speak(const nsAString& aText,
|
||||
[synth setVoice:identifier];
|
||||
|
||||
// default rate is 180-220
|
||||
[synth setObject:[NSNumber numberWithInt:aRate * 200]
|
||||
forProperty:NSSpeechRateProperty error:nil];
|
||||
[synth setObject:[NSNumber numberWithInt:aRate * 200] forProperty:NSSpeechRateProperty error:nil];
|
||||
// volume allows 0.0-1.0
|
||||
[synth setObject:[NSNumber numberWithFloat:aVolume]
|
||||
forProperty:NSSpeechVolumeProperty error:nil];
|
||||
[synth setObject:[NSNumber numberWithFloat:aVolume] forProperty:NSSpeechVolumeProperty error:nil];
|
||||
// Use default pitch value to calculate this
|
||||
NSNumber* defaultPitch =
|
||||
[synth objectForProperty:NSSpeechPitchBaseProperty error:nil];
|
||||
NSNumber* defaultPitch = [synth objectForProperty:NSSpeechPitchBaseProperty error:nil];
|
||||
if (defaultPitch) {
|
||||
int newPitch = [defaultPitch intValue] * (aPitch / 2 + 0.5);
|
||||
[synth setObject:[NSNumber numberWithInt:newPitch]
|
||||
forProperty:NSSpeechPitchBaseProperty error:nil];
|
||||
forProperty:NSSpeechPitchBaseProperty
|
||||
error:nil];
|
||||
}
|
||||
|
||||
nsAutoString escapedText;
|
||||
@ -423,8 +367,7 @@ OSXSpeechSynthesizerService::Speak(const nsAString& aText,
|
||||
// populates the offsets array to supply a map to the original offsets.
|
||||
for (size_t i = 0; i < aText.Length(); i++) {
|
||||
if (aText.Length() > i + 1 &&
|
||||
((aText[i] == ']' && aText[i+1] == ']') ||
|
||||
(aText[i] == '[' && aText[i+1] == '['))) {
|
||||
((aText[i] == ']' && aText[i + 1] == ']') || (aText[i] == '[' && aText[i + 1] == '['))) {
|
||||
escapedText.AppendLiteral(DLIM_ESCAPE_START);
|
||||
offsets.AppendElements(strlen(DLIM_ESCAPE_START));
|
||||
escapedText.Append(aText[i]);
|
||||
@ -455,22 +398,18 @@ OSXSpeechSynthesizerService::Speak(const nsAString& aText,
|
||||
|
||||
NS_IMETHODIMP
|
||||
OSXSpeechSynthesizerService::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
const char16_t* aData)
|
||||
{
|
||||
const char16_t* aData) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
OSXSpeechSynthesizerService*
|
||||
OSXSpeechSynthesizerService::GetInstance()
|
||||
{
|
||||
OSXSpeechSynthesizerService* OSXSpeechSynthesizerService::GetInstance() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (XRE_GetProcessType() != GeckoProcessType_Default) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!sSingleton) {
|
||||
RefPtr<OSXSpeechSynthesizerService> speechService =
|
||||
new OSXSpeechSynthesizerService();
|
||||
RefPtr<OSXSpeechSynthesizerService> speechService = new OSXSpeechSynthesizerService();
|
||||
if (speechService->Init()) {
|
||||
sSingleton = speechService;
|
||||
}
|
||||
@ -478,21 +417,17 @@ OSXSpeechSynthesizerService::GetInstance()
|
||||
return sSingleton;
|
||||
}
|
||||
|
||||
already_AddRefed<OSXSpeechSynthesizerService>
|
||||
OSXSpeechSynthesizerService::GetInstanceForService()
|
||||
{
|
||||
already_AddRefed<OSXSpeechSynthesizerService> OSXSpeechSynthesizerService::GetInstanceForService() {
|
||||
RefPtr<OSXSpeechSynthesizerService> speechService = GetInstance();
|
||||
return speechService.forget();
|
||||
}
|
||||
|
||||
void
|
||||
OSXSpeechSynthesizerService::Shutdown()
|
||||
{
|
||||
void OSXSpeechSynthesizerService::Shutdown() {
|
||||
if (!sSingleton) {
|
||||
return;
|
||||
}
|
||||
sSingleton = nullptr;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -47,19 +47,13 @@ int32_t NSCursorInfo::mNativeCursorsSupported = -1;
|
||||
// This constructor may be called from the browser process or the plugin
|
||||
// process.
|
||||
NSCursorInfo::NSCursorInfo()
|
||||
: mType(TypeArrow)
|
||||
, mHotSpot(nsPoint(0, 0))
|
||||
, mCustomImageData(NULL)
|
||||
, mCustomImageDataLength(0)
|
||||
{
|
||||
}
|
||||
: mType(TypeArrow),
|
||||
mHotSpot(nsPoint(0, 0)),
|
||||
mCustomImageData(NULL),
|
||||
mCustomImageDataLength(0) {}
|
||||
|
||||
NSCursorInfo::NSCursorInfo(NSCursor* aCursor)
|
||||
: mType(TypeArrow)
|
||||
, mHotSpot(nsPoint(0, 0))
|
||||
, mCustomImageData(NULL)
|
||||
, mCustomImageDataLength(0)
|
||||
{
|
||||
: mType(TypeArrow), mHotSpot(nsPoint(0, 0)), mCustomImageData(NULL), mCustomImageDataLength(0) {
|
||||
// This constructor is only ever called from the plugin process, so the
|
||||
// following is safe.
|
||||
if (!GetNativeCursorsSupported()) {
|
||||
@ -96,7 +90,7 @@ NSCursorInfo::NSCursorInfo(NSCursor* aCursor)
|
||||
mType = TypeResizeUp;
|
||||
} else if ([aCursor isEqual:[NSCursor resizeUpDownCursor]]) {
|
||||
mType = TypeResizeUpDown;
|
||||
// The following cursor types are only supported on OS X 10.6 and up.
|
||||
// The following cursor types are only supported on OS X 10.6 and up.
|
||||
} else if ([nsCursorClass respondsToSelector:@selector(contextualMenuCursor)] &&
|
||||
[aCursor isEqual:[nsCursorClass performSelector:@selector(contextualMenuCursor)]]) {
|
||||
mType = TypeContextualMenu;
|
||||
@ -107,7 +101,8 @@ NSCursorInfo::NSCursorInfo(NSCursor* aCursor)
|
||||
[aCursor isEqual:[nsCursorClass performSelector:@selector(dragLinkCursor)]]) {
|
||||
mType = TypeDragLink;
|
||||
} else if ([nsCursorClass respondsToSelector:@selector(operationNotAllowedCursor)] &&
|
||||
[aCursor isEqual:[nsCursorClass performSelector:@selector(operationNotAllowedCursor)]]) {
|
||||
[aCursor
|
||||
isEqual:[nsCursorClass performSelector:@selector(operationNotAllowedCursor)]]) {
|
||||
mType = TypeNotAllowed;
|
||||
} else {
|
||||
NSImage* image = [aCursor image];
|
||||
@ -132,15 +127,13 @@ NSCursorInfo::NSCursorInfo(NSCursor* aCursor)
|
||||
if (cgImage) {
|
||||
CFMutableDataRef data = ::CFDataCreateMutable(kCFAllocatorDefault, 0);
|
||||
if (data) {
|
||||
CGImageDestinationRef dest = ::CGImageDestinationCreateWithData(data,
|
||||
kUTTypePNG,
|
||||
1,
|
||||
NULL);
|
||||
CGImageDestinationRef dest =
|
||||
::CGImageDestinationCreateWithData(data, kUTTypePNG, 1, NULL);
|
||||
if (dest) {
|
||||
::CGImageDestinationAddImage(dest, cgImage, NULL);
|
||||
if (::CGImageDestinationFinalize(dest)) {
|
||||
uint32_t dataLength = (uint32_t) ::CFDataGetLength(data);
|
||||
mCustomImageData = (uint8_t*) moz_xmalloc(dataLength);
|
||||
uint32_t dataLength = (uint32_t)::CFDataGetLength(data);
|
||||
mCustomImageData = (uint8_t*)moz_xmalloc(dataLength);
|
||||
::CFDataGetBytes(data, ::CFRangeMake(0, dataLength), mCustomImageData);
|
||||
mCustomImageDataLength = dataLength;
|
||||
mType = TypeCustom;
|
||||
@ -158,11 +151,7 @@ NSCursorInfo::NSCursorInfo(NSCursor* aCursor)
|
||||
}
|
||||
|
||||
NSCursorInfo::NSCursorInfo(const Cursor* aCursor)
|
||||
: mType(TypeArrow)
|
||||
, mHotSpot(nsPoint(0, 0))
|
||||
, mCustomImageData(NULL)
|
||||
, mCustomImageDataLength(0)
|
||||
{
|
||||
: mType(TypeArrow), mHotSpot(nsPoint(0, 0)), mCustomImageData(NULL), mCustomImageDataLength(0) {
|
||||
// This constructor is only ever called from the plugin process, so the
|
||||
// following is safe.
|
||||
if (!GetNativeCursorsSupported()) {
|
||||
@ -178,7 +167,7 @@ NSCursorInfo::NSCursorInfo(const Cursor* aCursor)
|
||||
|
||||
bool isTransparent = true;
|
||||
|
||||
uint8_t* bitmap = (uint8_t*) moz_xmalloc(bitmapSize);
|
||||
uint8_t* bitmap = (uint8_t*)moz_xmalloc(bitmapSize);
|
||||
// The way we create 'bitmap' is largely "borrowed" from Chrome's
|
||||
// WebCursor::InitFromCursor().
|
||||
for (int y = 0; y < height; ++y) {
|
||||
@ -195,11 +184,11 @@ NSCursorInfo::NSCursorInfo(const Cursor* aCursor)
|
||||
int offset = (y * rowBytes) + (x * bytesPerPixel);
|
||||
// Color value
|
||||
if (data & 0x8000) {
|
||||
bitmap[offset] = 0x0;
|
||||
bitmap[offset] = 0x0;
|
||||
bitmap[offset + 1] = 0x0;
|
||||
bitmap[offset + 2] = 0x0;
|
||||
} else {
|
||||
bitmap[offset] = 0xFF;
|
||||
bitmap[offset] = 0xFF;
|
||||
bitmap[offset + 1] = 0xFF;
|
||||
bitmap[offset + 2] = 0xFF;
|
||||
}
|
||||
@ -223,32 +212,21 @@ NSCursorInfo::NSCursorInfo(const Cursor* aCursor)
|
||||
CGColorSpaceRef color = ::CGColorSpaceCreateDeviceRGB();
|
||||
if (color) {
|
||||
CGContextRef context =
|
||||
::CGBitmapContextCreate(bitmap,
|
||||
width,
|
||||
height,
|
||||
8,
|
||||
rowBytes,
|
||||
color,
|
||||
kCGImageAlphaPremultipliedLast |
|
||||
kCGBitmapByteOrder32Big);
|
||||
::CGBitmapContextCreate(bitmap, width, height, 8, rowBytes, color,
|
||||
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
|
||||
if (context) {
|
||||
CGImageRef image = ::CGBitmapContextCreateImage(context);
|
||||
if (image) {
|
||||
::CFMutableDataRef data = ::CFDataCreateMutable(kCFAllocatorDefault, 0);
|
||||
if (data) {
|
||||
CGImageDestinationRef dest =
|
||||
::CGImageDestinationCreateWithData(data,
|
||||
kUTTypePNG,
|
||||
1,
|
||||
NULL);
|
||||
::CGImageDestinationCreateWithData(data, kUTTypePNG, 1, NULL);
|
||||
if (dest) {
|
||||
::CGImageDestinationAddImage(dest, image, NULL);
|
||||
if (::CGImageDestinationFinalize(dest)) {
|
||||
uint32_t dataLength = (uint32_t) ::CFDataGetLength(data);
|
||||
mCustomImageData = (uint8_t*) moz_xmalloc(dataLength);
|
||||
::CFDataGetBytes(data,
|
||||
::CFRangeMake(0, dataLength),
|
||||
mCustomImageData);
|
||||
uint32_t dataLength = (uint32_t)::CFDataGetLength(data);
|
||||
mCustomImageData = (uint8_t*)moz_xmalloc(dataLength);
|
||||
::CFDataGetBytes(data, ::CFRangeMake(0, dataLength), mCustomImageData);
|
||||
mCustomImageDataLength = dataLength;
|
||||
mType = TypeCustom;
|
||||
}
|
||||
@ -267,19 +245,17 @@ NSCursorInfo::NSCursorInfo(const Cursor* aCursor)
|
||||
free(bitmap);
|
||||
}
|
||||
|
||||
NSCursorInfo::~NSCursorInfo()
|
||||
{
|
||||
NSCursorInfo::~NSCursorInfo() {
|
||||
if (mCustomImageData) {
|
||||
free(mCustomImageData);
|
||||
}
|
||||
}
|
||||
|
||||
NSCursor* NSCursorInfo::GetNSCursor() const
|
||||
{
|
||||
NSCursor* NSCursorInfo::GetNSCursor() const {
|
||||
NSCursor* retval = nil;
|
||||
|
||||
Class nsCursorClass = [NSCursor class];
|
||||
switch(mType) {
|
||||
switch (mType) {
|
||||
case TypeArrow:
|
||||
retval = [NSCursor arrowCursor];
|
||||
break;
|
||||
@ -352,24 +328,20 @@ NSCursor* NSCursorInfo::GetNSCursor() const
|
||||
}
|
||||
|
||||
if (!retval && mCustomImageData && mCustomImageDataLength) {
|
||||
CGDataProviderRef provider = ::CGDataProviderCreateWithData(NULL,
|
||||
(const void*)mCustomImageData,
|
||||
mCustomImageDataLength,
|
||||
NULL);
|
||||
CGDataProviderRef provider = ::CGDataProviderCreateWithData(NULL, (const void*)mCustomImageData,
|
||||
mCustomImageDataLength, NULL);
|
||||
if (provider) {
|
||||
CGImageRef cgImage = ::CGImageCreateWithPNGDataProvider(provider,
|
||||
NULL,
|
||||
false,
|
||||
kCGRenderingIntentDefault);
|
||||
CGImageRef cgImage =
|
||||
::CGImageCreateWithPNGDataProvider(provider, NULL, false, kCGRenderingIntentDefault);
|
||||
if (cgImage) {
|
||||
NSBitmapImageRep* rep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage];
|
||||
if (rep) {
|
||||
NSImage* image = [[NSImage alloc] init];
|
||||
if (image) {
|
||||
[image addRepresentation:rep];
|
||||
retval = [[[NSCursor alloc] initWithImage:image
|
||||
hotSpot:NSMakePoint(mHotSpot.x, mHotSpot.y)]
|
||||
autorelease];
|
||||
retval =
|
||||
[[[NSCursor alloc] initWithImage:image
|
||||
hotSpot:NSMakePoint(mHotSpot.x, mHotSpot.y)] autorelease];
|
||||
[image release];
|
||||
}
|
||||
[rep release];
|
||||
@ -390,8 +362,7 @@ NSCursor* NSCursorInfo::GetNSCursor() const
|
||||
|
||||
// Get a transparent cursor with the appropriate hot spot. We need one if
|
||||
// (for example) we have a custom cursor with no image data.
|
||||
NSCursor* NSCursorInfo::GetTransparentCursor() const
|
||||
{
|
||||
NSCursor* NSCursorInfo::GetTransparentCursor() const {
|
||||
NSCursor* retval = nil;
|
||||
|
||||
int width = 16, height = 16;
|
||||
@ -399,40 +370,35 @@ NSCursor* NSCursorInfo::GetTransparentCursor() const
|
||||
int rowBytes = width * bytesPerPixel;
|
||||
int dataSize = height * rowBytes;
|
||||
|
||||
uint8_t* data = (uint8_t*) moz_xmalloc(dataSize);
|
||||
uint8_t* data = (uint8_t*)moz_xmalloc(dataSize);
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int x = 0; x < width; ++x) {
|
||||
int offset = (y * rowBytes) + (x * bytesPerPixel);
|
||||
data[offset] = 0x7E; // Arbitrary gray-scale value
|
||||
data[offset + 1] = 0; // Alpha value to make us transparent
|
||||
data[offset] = 0x7E; // Arbitrary gray-scale value
|
||||
data[offset + 1] = 0; // Alpha value to make us transparent
|
||||
}
|
||||
}
|
||||
|
||||
NSBitmapImageRep* imageRep =
|
||||
[[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
|
||||
pixelsWide:width
|
||||
pixelsHigh:height
|
||||
bitsPerSample:8
|
||||
samplesPerPixel:2
|
||||
hasAlpha:YES
|
||||
isPlanar:NO
|
||||
colorSpaceName:NSCalibratedWhiteColorSpace
|
||||
bytesPerRow:rowBytes
|
||||
bitsPerPixel:16]
|
||||
autorelease];
|
||||
[[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
|
||||
pixelsWide:width
|
||||
pixelsHigh:height
|
||||
bitsPerSample:8
|
||||
samplesPerPixel:2
|
||||
hasAlpha:YES
|
||||
isPlanar:NO
|
||||
colorSpaceName:NSCalibratedWhiteColorSpace
|
||||
bytesPerRow:rowBytes
|
||||
bitsPerPixel:16] autorelease];
|
||||
if (imageRep) {
|
||||
uint8_t* repDataPtr = [imageRep bitmapData];
|
||||
if (repDataPtr) {
|
||||
memcpy(repDataPtr, data, dataSize);
|
||||
NSImage *image =
|
||||
[[[NSImage alloc] initWithSize:NSMakeSize(width, height)]
|
||||
autorelease];
|
||||
NSImage* image = [[[NSImage alloc] initWithSize:NSMakeSize(width, height)] autorelease];
|
||||
if (image) {
|
||||
[image addRepresentation:imageRep];
|
||||
retval =
|
||||
[[[NSCursor alloc] initWithImage:image
|
||||
hotSpot:NSMakePoint(mHotSpot.x, mHotSpot.y)]
|
||||
autorelease];
|
||||
retval = [[[NSCursor alloc] initWithImage:image
|
||||
hotSpot:NSMakePoint(mHotSpot.x, mHotSpot.y)] autorelease];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -447,14 +413,10 @@ NSCursor* NSCursorInfo::GetTransparentCursor() const
|
||||
return retval;
|
||||
}
|
||||
|
||||
NSCursorInfo::Type NSCursorInfo::GetType() const
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
NSCursorInfo::Type NSCursorInfo::GetType() const { return mType; }
|
||||
|
||||
const char* NSCursorInfo::GetTypeName() const
|
||||
{
|
||||
switch(mType) {
|
||||
const char* NSCursorInfo::GetTypeName() const {
|
||||
switch (mType) {
|
||||
case TypeCustom:
|
||||
return "TypeCustom";
|
||||
case TypeArrow:
|
||||
@ -499,38 +461,22 @@ const char* NSCursorInfo::GetTypeName() const
|
||||
return "TypeUnknown";
|
||||
}
|
||||
|
||||
nsPoint NSCursorInfo::GetHotSpot() const
|
||||
{
|
||||
return mHotSpot;
|
||||
}
|
||||
nsPoint NSCursorInfo::GetHotSpot() const { return mHotSpot; }
|
||||
|
||||
uint8_t* NSCursorInfo::GetCustomImageData() const
|
||||
{
|
||||
return mCustomImageData;
|
||||
}
|
||||
uint8_t* NSCursorInfo::GetCustomImageData() const { return mCustomImageData; }
|
||||
|
||||
uint32_t NSCursorInfo::GetCustomImageDataLength() const
|
||||
{
|
||||
return mCustomImageDataLength;
|
||||
}
|
||||
uint32_t NSCursorInfo::GetCustomImageDataLength() const { return mCustomImageDataLength; }
|
||||
|
||||
void NSCursorInfo::SetType(Type aType)
|
||||
{
|
||||
mType = aType;
|
||||
}
|
||||
void NSCursorInfo::SetType(Type aType) { mType = aType; }
|
||||
|
||||
void NSCursorInfo::SetHotSpot(nsPoint aHotSpot)
|
||||
{
|
||||
mHotSpot = aHotSpot;
|
||||
}
|
||||
void NSCursorInfo::SetHotSpot(nsPoint aHotSpot) { mHotSpot = aHotSpot; }
|
||||
|
||||
void NSCursorInfo::SetCustomImageData(uint8_t* aData, uint32_t aDataLength)
|
||||
{
|
||||
void NSCursorInfo::SetCustomImageData(uint8_t* aData, uint32_t aDataLength) {
|
||||
if (mCustomImageData) {
|
||||
free(mCustomImageData);
|
||||
}
|
||||
if (aDataLength) {
|
||||
mCustomImageData = (uint8_t*) moz_xmalloc(aDataLength);
|
||||
mCustomImageData = (uint8_t*)moz_xmalloc(aDataLength);
|
||||
memcpy(mCustomImageData, aData, aDataLength);
|
||||
} else {
|
||||
mCustomImageData = NULL;
|
||||
@ -540,11 +486,10 @@ void NSCursorInfo::SetCustomImageData(uint8_t* aData, uint32_t aDataLength)
|
||||
|
||||
// This should never be called from the browser process -- only from the
|
||||
// plugin process.
|
||||
bool NSCursorInfo::GetNativeCursorsSupported()
|
||||
{
|
||||
bool NSCursorInfo::GetNativeCursorsSupported() {
|
||||
if (mNativeCursorsSupported == -1) {
|
||||
ENSURE_PLUGIN_THREAD(false);
|
||||
PluginModuleChild *pmc = PluginModuleChild::GetChrome();
|
||||
PluginModuleChild* pmc = PluginModuleChild::GetChrome();
|
||||
if (pmc) {
|
||||
bool result = pmc->GetNativeCursorsSupported();
|
||||
if (result) {
|
||||
@ -557,7 +502,7 @@ bool NSCursorInfo::GetNativeCursorsSupported()
|
||||
return (mNativeCursorsSupported == 1);
|
||||
}
|
||||
|
||||
} // namespace mac_plugin_interposing
|
||||
} // namespace mac_plugin_interposing
|
||||
|
||||
namespace mac_plugin_interposing {
|
||||
namespace parent {
|
||||
@ -569,19 +514,15 @@ std::set<uint32_t> plugin_fullscreen_windows_set_;
|
||||
// Tracks modal windows currently visible.
|
||||
std::set<uint32_t> plugin_modal_windows_set_;
|
||||
|
||||
void OnPluginShowWindow(uint32_t window_id,
|
||||
CGRect window_bounds,
|
||||
bool modal) {
|
||||
void OnPluginShowWindow(uint32_t window_id, CGRect window_bounds, bool modal) {
|
||||
plugin_visible_windows_set_.insert(window_id);
|
||||
|
||||
if (modal)
|
||||
plugin_modal_windows_set_.insert(window_id);
|
||||
if (modal) plugin_modal_windows_set_.insert(window_id);
|
||||
|
||||
CGRect main_display_bounds = ::CGDisplayBounds(CGMainDisplayID());
|
||||
|
||||
if (CGRectEqualToRect(window_bounds, main_display_bounds) &&
|
||||
(plugin_fullscreen_windows_set_.find(window_id) ==
|
||||
plugin_fullscreen_windows_set_.end())) {
|
||||
(plugin_fullscreen_windows_set_.find(window_id) == plugin_fullscreen_windows_set_.end())) {
|
||||
plugin_fullscreen_windows_set_.insert(window_id);
|
||||
|
||||
nsCocoaUtils::HideOSChromeOnScreen(true);
|
||||
@ -617,12 +558,10 @@ static void ReleasePluginFullScreen(pid_t plugin_pid) {
|
||||
void OnPluginHideWindow(uint32_t window_id, pid_t aPluginPid) {
|
||||
bool had_windows = !plugin_visible_windows_set_.empty();
|
||||
plugin_visible_windows_set_.erase(window_id);
|
||||
bool browser_needs_activation = had_windows &&
|
||||
plugin_visible_windows_set_.empty();
|
||||
bool browser_needs_activation = had_windows && plugin_visible_windows_set_.empty();
|
||||
|
||||
plugin_modal_windows_set_.erase(window_id);
|
||||
if (plugin_fullscreen_windows_set_.find(window_id) !=
|
||||
plugin_fullscreen_windows_set_.end()) {
|
||||
if (plugin_fullscreen_windows_set_.find(window_id) != plugin_fullscreen_windows_set_.end()) {
|
||||
plugin_fullscreen_windows_set_.erase(window_id);
|
||||
pid_t plugin_pid = browser_needs_activation ? -1 : aPluginPid;
|
||||
browser_needs_activation = false;
|
||||
@ -634,16 +573,14 @@ void OnPluginHideWindow(uint32_t window_id, pid_t aPluginPid) {
|
||||
}
|
||||
}
|
||||
|
||||
void OnSetCursor(const NSCursorInfo& cursorInfo)
|
||||
{
|
||||
void OnSetCursor(const NSCursorInfo& cursorInfo) {
|
||||
NSCursor* aCursor = cursorInfo.GetNSCursor();
|
||||
if (aCursor) {
|
||||
[aCursor set];
|
||||
}
|
||||
}
|
||||
|
||||
void OnShowCursor(bool show)
|
||||
{
|
||||
void OnShowCursor(bool show) {
|
||||
if (show) {
|
||||
[NSCursor unhide];
|
||||
} else {
|
||||
@ -651,21 +588,17 @@ void OnShowCursor(bool show)
|
||||
}
|
||||
}
|
||||
|
||||
void OnPushCursor(const NSCursorInfo& cursorInfo)
|
||||
{
|
||||
void OnPushCursor(const NSCursorInfo& cursorInfo) {
|
||||
NSCursor* aCursor = cursorInfo.GetNSCursor();
|
||||
if (aCursor) {
|
||||
[aCursor push];
|
||||
}
|
||||
}
|
||||
|
||||
void OnPopCursor()
|
||||
{
|
||||
[NSCursor pop];
|
||||
}
|
||||
void OnPopCursor() { [NSCursor pop]; }
|
||||
|
||||
} // namespace parent
|
||||
} // namespace mac_plugin_interposing
|
||||
} // namespace parent
|
||||
} // namespace mac_plugin_interposing
|
||||
|
||||
namespace mac_plugin_interposing {
|
||||
namespace child {
|
||||
@ -674,66 +607,57 @@ namespace child {
|
||||
// browser process only if the browser is current frontmost.
|
||||
void FocusPluginProcess() {
|
||||
ProcessSerialNumber this_process, front_process;
|
||||
if ((GetCurrentProcess(&this_process) != noErr) ||
|
||||
(GetFrontProcess(&front_process) != noErr)) {
|
||||
if ((GetCurrentProcess(&this_process) != noErr) || (GetFrontProcess(&front_process) != noErr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Boolean matched = false;
|
||||
if ((SameProcess(&this_process, &front_process, &matched) == noErr) &&
|
||||
!matched) {
|
||||
if ((SameProcess(&this_process, &front_process, &matched) == noErr) && !matched) {
|
||||
SetFrontProcess(&this_process);
|
||||
}
|
||||
}
|
||||
|
||||
void NotifyBrowserOfPluginShowWindow(uint32_t window_id, CGRect bounds,
|
||||
bool modal) {
|
||||
void NotifyBrowserOfPluginShowWindow(uint32_t window_id, CGRect bounds, bool modal) {
|
||||
ENSURE_PLUGIN_THREAD_VOID();
|
||||
|
||||
PluginModuleChild *pmc = PluginModuleChild::GetChrome();
|
||||
if (pmc)
|
||||
pmc->PluginShowWindow(window_id, modal, bounds);
|
||||
PluginModuleChild* pmc = PluginModuleChild::GetChrome();
|
||||
if (pmc) pmc->PluginShowWindow(window_id, modal, bounds);
|
||||
}
|
||||
|
||||
void NotifyBrowserOfPluginHideWindow(uint32_t window_id, CGRect bounds) {
|
||||
ENSURE_PLUGIN_THREAD_VOID();
|
||||
|
||||
PluginModuleChild *pmc = PluginModuleChild::GetChrome();
|
||||
if (pmc)
|
||||
pmc->PluginHideWindow(window_id);
|
||||
PluginModuleChild* pmc = PluginModuleChild::GetChrome();
|
||||
if (pmc) pmc->PluginHideWindow(window_id);
|
||||
}
|
||||
|
||||
void NotifyBrowserOfSetCursor(NSCursorInfo& aCursorInfo)
|
||||
{
|
||||
void NotifyBrowserOfSetCursor(NSCursorInfo& aCursorInfo) {
|
||||
ENSURE_PLUGIN_THREAD_VOID();
|
||||
PluginModuleChild *pmc = PluginModuleChild::GetChrome();
|
||||
PluginModuleChild* pmc = PluginModuleChild::GetChrome();
|
||||
if (pmc) {
|
||||
pmc->SetCursor(aCursorInfo);
|
||||
}
|
||||
}
|
||||
|
||||
void NotifyBrowserOfShowCursor(bool show)
|
||||
{
|
||||
void NotifyBrowserOfShowCursor(bool show) {
|
||||
ENSURE_PLUGIN_THREAD_VOID();
|
||||
PluginModuleChild *pmc = PluginModuleChild::GetChrome();
|
||||
PluginModuleChild* pmc = PluginModuleChild::GetChrome();
|
||||
if (pmc) {
|
||||
pmc->ShowCursor(show);
|
||||
}
|
||||
}
|
||||
|
||||
void NotifyBrowserOfPushCursor(NSCursorInfo& aCursorInfo)
|
||||
{
|
||||
void NotifyBrowserOfPushCursor(NSCursorInfo& aCursorInfo) {
|
||||
ENSURE_PLUGIN_THREAD_VOID();
|
||||
PluginModuleChild *pmc = PluginModuleChild::GetChrome();
|
||||
PluginModuleChild* pmc = PluginModuleChild::GetChrome();
|
||||
if (pmc) {
|
||||
pmc->PushCursor(aCursorInfo);
|
||||
}
|
||||
}
|
||||
|
||||
void NotifyBrowserOfPopCursor()
|
||||
{
|
||||
void NotifyBrowserOfPopCursor() {
|
||||
ENSURE_PLUGIN_THREAD_VOID();
|
||||
PluginModuleChild *pmc = PluginModuleChild::GetChrome();
|
||||
PluginModuleChild* pmc = PluginModuleChild::GetChrome();
|
||||
if (pmc) {
|
||||
pmc->PopCursor();
|
||||
}
|
||||
@ -750,8 +674,7 @@ struct WindowInfo {
|
||||
};
|
||||
|
||||
static void OnPluginWindowClosed(const WindowInfo& window_info) {
|
||||
if (window_info.window_id == 0)
|
||||
return;
|
||||
if (window_info.window_id == 0) return;
|
||||
mac_plugin_interposing::child::NotifyBrowserOfPluginHideWindow(window_info.window_id,
|
||||
window_info.bounds);
|
||||
}
|
||||
@ -762,20 +685,18 @@ static void OnPluginWindowShown(const WindowInfo& window_info, BOOL is_modal) {
|
||||
// it in _setWindowNumber instead.
|
||||
static BOOL s_pending_display_is_modal = NO;
|
||||
if (window_info.window_id == 0) {
|
||||
if (is_modal)
|
||||
s_pending_display_is_modal = YES;
|
||||
if (is_modal) s_pending_display_is_modal = YES;
|
||||
return;
|
||||
}
|
||||
if (s_pending_display_is_modal) {
|
||||
is_modal = YES;
|
||||
s_pending_display_is_modal = NO;
|
||||
}
|
||||
mac_plugin_interposing::child::NotifyBrowserOfPluginShowWindow(
|
||||
window_info.window_id, window_info.bounds, is_modal);
|
||||
mac_plugin_interposing::child::NotifyBrowserOfPluginShowWindow(window_info.window_id,
|
||||
window_info.bounds, is_modal);
|
||||
}
|
||||
|
||||
static BOOL OnSetCursor(NSCursorInfo &aInfo)
|
||||
{
|
||||
static BOOL OnSetCursor(NSCursorInfo& aInfo) {
|
||||
if (NSCursorInfo::GetNativeCursorsSupported()) {
|
||||
NotifyBrowserOfSetCursor(aInfo);
|
||||
return YES;
|
||||
@ -783,8 +704,7 @@ static BOOL OnSetCursor(NSCursorInfo &aInfo)
|
||||
return NO;
|
||||
}
|
||||
|
||||
static BOOL OnHideCursor()
|
||||
{
|
||||
static BOOL OnHideCursor() {
|
||||
if (NSCursorInfo::GetNativeCursorsSupported()) {
|
||||
NotifyBrowserOfShowCursor(NO);
|
||||
return YES;
|
||||
@ -792,8 +712,7 @@ static BOOL OnHideCursor()
|
||||
return NO;
|
||||
}
|
||||
|
||||
static BOOL OnUnhideCursor()
|
||||
{
|
||||
static BOOL OnUnhideCursor() {
|
||||
if (NSCursorInfo::GetNativeCursorsSupported()) {
|
||||
NotifyBrowserOfShowCursor(YES);
|
||||
return YES;
|
||||
@ -801,8 +720,7 @@ static BOOL OnUnhideCursor()
|
||||
return NO;
|
||||
}
|
||||
|
||||
static BOOL OnPushCursor(NSCursorInfo &aInfo)
|
||||
{
|
||||
static BOOL OnPushCursor(NSCursorInfo& aInfo) {
|
||||
if (NSCursorInfo::GetNativeCursorsSupported()) {
|
||||
NotifyBrowserOfPushCursor(aInfo);
|
||||
return YES;
|
||||
@ -810,8 +728,7 @@ static BOOL OnPushCursor(NSCursorInfo &aInfo)
|
||||
return NO;
|
||||
}
|
||||
|
||||
static BOOL OnPopCursor()
|
||||
{
|
||||
static BOOL OnPopCursor() {
|
||||
if (NSCursorInfo::GetNativeCursorsSupported()) {
|
||||
NotifyBrowserOfPopCursor();
|
||||
return YES;
|
||||
@ -819,8 +736,8 @@ static BOOL OnPopCursor()
|
||||
return NO;
|
||||
}
|
||||
|
||||
} // namespace child
|
||||
} // namespace mac_plugin_interposing
|
||||
} // namespace child
|
||||
} // namespace mac_plugin_interposing
|
||||
|
||||
using namespace mac_plugin_interposing::child;
|
||||
|
||||
@ -852,11 +769,9 @@ using namespace mac_plugin_interposing::child;
|
||||
}
|
||||
|
||||
- (void)pluginInterpose_setWindowNumber:(NSInteger)num {
|
||||
if (num > 0)
|
||||
mac_plugin_interposing::child::FocusPluginProcess();
|
||||
if (num > 0) mac_plugin_interposing::child::FocusPluginProcess();
|
||||
[self pluginInterpose_setWindowNumber:num];
|
||||
if (num > 0)
|
||||
OnPluginWindowShown(WindowInfo(self), NO);
|
||||
if (num > 0) OnPluginWindowShown(WindowInfo(self), NO);
|
||||
}
|
||||
|
||||
@end
|
||||
@ -895,25 +810,20 @@ using namespace mac_plugin_interposing::child;
|
||||
// The last element is always the current cursor.
|
||||
static NSMutableArray* gCursorStack = nil;
|
||||
|
||||
static BOOL initCursorStack()
|
||||
{
|
||||
static BOOL initCursorStack() {
|
||||
if (!gCursorStack) {
|
||||
gCursorStack = [[NSMutableArray arrayWithCapacity:5] retain];
|
||||
}
|
||||
return (gCursorStack != NULL);
|
||||
}
|
||||
|
||||
static NSCursor* currentCursorFromCache()
|
||||
{
|
||||
if (!initCursorStack())
|
||||
return nil;
|
||||
return (NSCursor*) [gCursorStack lastObject];
|
||||
static NSCursor* currentCursorFromCache() {
|
||||
if (!initCursorStack()) return nil;
|
||||
return (NSCursor*)[gCursorStack lastObject];
|
||||
}
|
||||
|
||||
static void setCursorInCache(NSCursor* aCursor)
|
||||
{
|
||||
if (!initCursorStack() || !aCursor)
|
||||
return;
|
||||
static void setCursorInCache(NSCursor* aCursor) {
|
||||
if (!initCursorStack() || !aCursor) return;
|
||||
NSUInteger count = [gCursorStack count];
|
||||
if (count) {
|
||||
[gCursorStack replaceObjectAtIndex:count - 1 withObject:aCursor];
|
||||
@ -922,17 +832,13 @@ static void setCursorInCache(NSCursor* aCursor)
|
||||
}
|
||||
}
|
||||
|
||||
static void pushCursorInCache(NSCursor* aCursor)
|
||||
{
|
||||
if (!initCursorStack() || !aCursor)
|
||||
return;
|
||||
static void pushCursorInCache(NSCursor* aCursor) {
|
||||
if (!initCursorStack() || !aCursor) return;
|
||||
[gCursorStack addObject:aCursor];
|
||||
}
|
||||
|
||||
static void popCursorInCache()
|
||||
{
|
||||
if (!initCursorStack())
|
||||
return;
|
||||
static void popCursorInCache() {
|
||||
if (!initCursorStack()) return;
|
||||
// Apple's doc on the +[NSCursor pop] method says: "If the current cursor
|
||||
// is the only cursor on the stack, this method does nothing."
|
||||
if ([gCursorStack count] > 1) {
|
||||
@ -942,24 +848,21 @@ static void popCursorInCache()
|
||||
|
||||
@implementation NSCursor (PluginInterposing)
|
||||
|
||||
- (void)pluginInterpose_set
|
||||
{
|
||||
- (void)pluginInterpose_set {
|
||||
NSCursorInfo info(self);
|
||||
OnSetCursor(info);
|
||||
setCursorInCache(self);
|
||||
[self pluginInterpose_set];
|
||||
}
|
||||
|
||||
- (void)pluginInterpose_push
|
||||
{
|
||||
- (void)pluginInterpose_push {
|
||||
NSCursorInfo info(self);
|
||||
OnPushCursor(info);
|
||||
pushCursorInCache(self);
|
||||
[self pluginInterpose_push];
|
||||
}
|
||||
|
||||
- (void)pluginInterpose_pop
|
||||
{
|
||||
- (void)pluginInterpose_pop {
|
||||
OnPopCursor();
|
||||
popCursorInCache();
|
||||
[self pluginInterpose_pop];
|
||||
@ -972,8 +875,7 @@ static void popCursorInCache()
|
||||
// currentCursor "only returns the cursor set by your application using
|
||||
// NSCursor methods". So we don't need to worry about changes to the cursor
|
||||
// made by other methods like SetThemeCursor().
|
||||
+ (NSCursor*)pluginInterpose_currentCursor
|
||||
{
|
||||
+ (NSCursor*)pluginInterpose_currentCursor {
|
||||
NSCursor* retval = [self pluginInterpose_currentCursor];
|
||||
if (!retval) {
|
||||
retval = currentCursorFromCache();
|
||||
@ -981,20 +883,17 @@ static void popCursorInCache()
|
||||
return retval;
|
||||
}
|
||||
|
||||
+ (void)pluginInterpose_hide
|
||||
{
|
||||
+ (void)pluginInterpose_hide {
|
||||
OnHideCursor();
|
||||
[self pluginInterpose_hide];
|
||||
}
|
||||
|
||||
+ (void)pluginInterpose_unhide
|
||||
{
|
||||
+ (void)pluginInterpose_unhide {
|
||||
OnUnhideCursor();
|
||||
[self pluginInterpose_unhide];
|
||||
}
|
||||
|
||||
+ (void)pluginInterpose_pop
|
||||
{
|
||||
+ (void)pluginInterpose_pop {
|
||||
OnPopCursor();
|
||||
popCursorInCache();
|
||||
[self pluginInterpose_pop];
|
||||
@ -1002,10 +901,7 @@ static void popCursorInCache()
|
||||
|
||||
@end
|
||||
|
||||
static void ExchangeMethods(Class target_class,
|
||||
BOOL class_method,
|
||||
SEL original,
|
||||
SEL replacement) {
|
||||
static void ExchangeMethods(Class target_class, BOOL class_method, SEL original, SEL replacement) {
|
||||
Method m1;
|
||||
Method m2;
|
||||
if (class_method) {
|
||||
@ -1016,8 +912,7 @@ static void ExchangeMethods(Class target_class,
|
||||
m2 = class_getInstanceMethod(target_class, replacement);
|
||||
}
|
||||
|
||||
if (m1 == m2)
|
||||
return;
|
||||
if (m1 == m2) return;
|
||||
|
||||
if (m1 && m2)
|
||||
method_exchangeImplementations(m1, m2);
|
||||
@ -1030,8 +925,7 @@ namespace child {
|
||||
|
||||
void SetUpCocoaInterposing() {
|
||||
Class nswindow_class = [NSWindow class];
|
||||
ExchangeMethods(nswindow_class, NO, @selector(orderOut:),
|
||||
@selector(pluginInterpose_orderOut:));
|
||||
ExchangeMethods(nswindow_class, NO, @selector(orderOut:), @selector(pluginInterpose_orderOut:));
|
||||
ExchangeMethods(nswindow_class, NO, @selector(orderFront:),
|
||||
@selector(pluginInterpose_orderFront:));
|
||||
ExchangeMethods(nswindow_class, NO, @selector(makeKeyAndOrderFront:),
|
||||
@ -1043,20 +937,14 @@ void SetUpCocoaInterposing() {
|
||||
@selector(pluginInterpose_runModalForWindow:));
|
||||
|
||||
Class nscursor_class = [NSCursor class];
|
||||
ExchangeMethods(nscursor_class, NO, @selector(set),
|
||||
@selector(pluginInterpose_set));
|
||||
ExchangeMethods(nscursor_class, NO, @selector(push),
|
||||
@selector(pluginInterpose_push));
|
||||
ExchangeMethods(nscursor_class, NO, @selector(pop),
|
||||
@selector(pluginInterpose_pop));
|
||||
ExchangeMethods(nscursor_class, NO, @selector(set), @selector(pluginInterpose_set));
|
||||
ExchangeMethods(nscursor_class, NO, @selector(push), @selector(pluginInterpose_push));
|
||||
ExchangeMethods(nscursor_class, NO, @selector(pop), @selector(pluginInterpose_pop));
|
||||
ExchangeMethods(nscursor_class, YES, @selector(currentCursor),
|
||||
@selector(pluginInterpose_currentCursor));
|
||||
ExchangeMethods(nscursor_class, YES, @selector(hide),
|
||||
@selector(pluginInterpose_hide));
|
||||
ExchangeMethods(nscursor_class, YES, @selector(unhide),
|
||||
@selector(pluginInterpose_unhide));
|
||||
ExchangeMethods(nscursor_class, YES, @selector(pop),
|
||||
@selector(pluginInterpose_pop));
|
||||
ExchangeMethods(nscursor_class, YES, @selector(hide), @selector(pluginInterpose_hide));
|
||||
ExchangeMethods(nscursor_class, YES, @selector(unhide), @selector(pluginInterpose_unhide));
|
||||
ExchangeMethods(nscursor_class, YES, @selector(pop), @selector(pluginInterpose_pop));
|
||||
}
|
||||
|
||||
} // namespace child
|
||||
@ -1065,8 +953,7 @@ void SetUpCocoaInterposing() {
|
||||
// Called from plugin_child_interpose.mm, which hooks calls to
|
||||
// SetCursor() (the QuickDraw call) from the plugin child process.
|
||||
extern "C" NS_VISIBILITY_DEFAULT BOOL
|
||||
mac_plugin_interposing_child_OnSetCursor(const Cursor* cursor)
|
||||
{
|
||||
mac_plugin_interposing_child_OnSetCursor(const Cursor* cursor) {
|
||||
NSCursorInfo info(cursor);
|
||||
return OnSetCursor(info);
|
||||
}
|
||||
@ -1075,8 +962,7 @@ mac_plugin_interposing_child_OnSetCursor(const Cursor* cursor)
|
||||
// SetThemeCursor() (the Appearance Manager call) from the plugin child
|
||||
// process.
|
||||
extern "C" NS_VISIBILITY_DEFAULT BOOL
|
||||
mac_plugin_interposing_child_OnSetThemeCursor(ThemeCursor cursor)
|
||||
{
|
||||
mac_plugin_interposing_child_OnSetThemeCursor(ThemeCursor cursor) {
|
||||
NSCursorInfo info;
|
||||
switch (cursor) {
|
||||
case kThemeArrowCursor:
|
||||
@ -1145,14 +1031,10 @@ mac_plugin_interposing_child_OnSetThemeCursor(ThemeCursor cursor)
|
||||
return OnSetCursor(info);
|
||||
}
|
||||
|
||||
extern "C" NS_VISIBILITY_DEFAULT BOOL
|
||||
mac_plugin_interposing_child_OnHideCursor()
|
||||
{
|
||||
extern "C" NS_VISIBILITY_DEFAULT BOOL mac_plugin_interposing_child_OnHideCursor() {
|
||||
return OnHideCursor();
|
||||
}
|
||||
|
||||
extern "C" NS_VISIBILITY_DEFAULT BOOL
|
||||
mac_plugin_interposing_child_OnShowCursor()
|
||||
{
|
||||
extern "C" NS_VISIBILITY_DEFAULT BOOL mac_plugin_interposing_child_OnShowCursor() {
|
||||
return OnUnhideCursor();
|
||||
}
|
||||
|
@ -26,11 +26,10 @@ using namespace mozilla::plugins::PluginUtilsOSX;
|
||||
|
||||
@interface CGBridgeLayer : CALayer {
|
||||
DrawPluginFunc mDrawFunc;
|
||||
void* mPluginInstance;
|
||||
void *mPluginInstance;
|
||||
nsIntRect mUpdateRect;
|
||||
}
|
||||
- (void)setDrawFunc:(DrawPluginFunc)aFunc
|
||||
pluginInstance:(void*)aPluginInstance;
|
||||
- (void)setDrawFunc:(DrawPluginFunc)aFunc pluginInstance:(void *)aPluginInstance;
|
||||
- (void)updateRect:(nsIntRect)aRect;
|
||||
|
||||
@end
|
||||
@ -40,35 +39,25 @@ using namespace mozilla::plugins::PluginUtilsOSX;
|
||||
// it's used to replace the "data" in a bitmap context that was
|
||||
// originally specified in a call to CGBitmapContextCreate() or
|
||||
// CGBitmapContextCreateWithData().
|
||||
typedef void (*CGBitmapContextSetDataFunc) (CGContextRef c,
|
||||
size_t x,
|
||||
size_t y,
|
||||
size_t width,
|
||||
size_t height,
|
||||
void* data,
|
||||
size_t bitsPerComponent,
|
||||
size_t bitsPerPixel,
|
||||
size_t bytesPerRow);
|
||||
typedef void (*CGBitmapContextSetDataFunc)(CGContextRef c, size_t x, size_t y, size_t width,
|
||||
size_t height, void *data, size_t bitsPerComponent,
|
||||
size_t bitsPerPixel, size_t bytesPerRow);
|
||||
CGBitmapContextSetDataFunc CGBitmapContextSetDataPtr = NULL;
|
||||
|
||||
@implementation CGBridgeLayer
|
||||
- (void) updateRect:(nsIntRect)aRect
|
||||
{
|
||||
mUpdateRect.UnionRect(mUpdateRect, aRect);
|
||||
- (void)updateRect:(nsIntRect)aRect {
|
||||
mUpdateRect.UnionRect(mUpdateRect, aRect);
|
||||
}
|
||||
|
||||
- (void) setDrawFunc:(DrawPluginFunc)aFunc
|
||||
pluginInstance:(void*)aPluginInstance
|
||||
{
|
||||
- (void)setDrawFunc:(DrawPluginFunc)aFunc pluginInstance:(void *)aPluginInstance {
|
||||
mDrawFunc = aFunc;
|
||||
mPluginInstance = aPluginInstance;
|
||||
}
|
||||
|
||||
- (void)drawInContext:(CGContextRef)aCGContext
|
||||
{
|
||||
::CGContextSaveGState(aCGContext);
|
||||
- (void)drawInContext:(CGContextRef)aCGContext {
|
||||
::CGContextSaveGState(aCGContext);
|
||||
::CGContextTranslateCTM(aCGContext, 0, self.bounds.size.height);
|
||||
::CGContextScaleCTM(aCGContext, (CGFloat) 1, (CGFloat) -1);
|
||||
::CGContextScaleCTM(aCGContext, (CGFloat)1, (CGFloat)-1);
|
||||
|
||||
mUpdateRect = nsIntRect::Truncate(0, 0, self.bounds.size.width, self.bounds.size.height);
|
||||
|
||||
@ -81,8 +70,7 @@ CGBitmapContextSetDataFunc CGBitmapContextSetDataPtr = NULL;
|
||||
|
||||
@end
|
||||
|
||||
void* mozilla::plugins::PluginUtilsOSX::GetCGLayer(DrawPluginFunc aFunc,
|
||||
void* aPluginInstance,
|
||||
void *mozilla::plugins::PluginUtilsOSX::GetCGLayer(DrawPluginFunc aFunc, void *aPluginInstance,
|
||||
double aContentsScaleFactor) {
|
||||
CGBridgeLayer *bridgeLayer = [[CGBridgeLayer alloc] init];
|
||||
|
||||
@ -91,12 +79,9 @@ void* mozilla::plugins::PluginUtilsOSX::GetCGLayer(DrawPluginFunc aFunc,
|
||||
bridgeLayer.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
|
||||
bridgeLayer.needsDisplayOnBoundsChange = YES;
|
||||
NSNull *nullValue = [NSNull null];
|
||||
NSDictionary *actions = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
nullValue, @"bounds",
|
||||
nullValue, @"contents",
|
||||
nullValue, @"contentsRect",
|
||||
nullValue, @"position",
|
||||
nil];
|
||||
NSDictionary *actions = [NSDictionary
|
||||
dictionaryWithObjectsAndKeys:nullValue, @"bounds", nullValue, @"contents", nullValue,
|
||||
@"contentsRect", nullValue, @"position", nil];
|
||||
[bridgeLayer setStyle:[NSDictionary dictionaryWithObject:actions forKey:@"actions"]];
|
||||
|
||||
// For reasons that aren't clear (perhaps one or more OS bugs), we can only
|
||||
@ -105,25 +90,23 @@ void* mozilla::plugins::PluginUtilsOSX::GetCGLayer(DrawPluginFunc aFunc,
|
||||
// of bridgeLayer (even to the same value) causes it to stop working (go
|
||||
// blank). This doesn't happen with objects that are members of the CALayer
|
||||
// class (as opposed to one of its subclasses).
|
||||
#if defined(MAC_OS_X_VERSION_10_7) && \
|
||||
MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
|
||||
#if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
|
||||
if ([bridgeLayer respondsToSelector:@selector(setContentsScale:)]) {
|
||||
bridgeLayer.contentsScale = aContentsScaleFactor;
|
||||
}
|
||||
#endif
|
||||
|
||||
[bridgeLayer setDrawFunc:aFunc
|
||||
pluginInstance:aPluginInstance];
|
||||
[bridgeLayer setDrawFunc:aFunc pluginInstance:aPluginInstance];
|
||||
return bridgeLayer;
|
||||
}
|
||||
|
||||
void mozilla::plugins::PluginUtilsOSX::ReleaseCGLayer(void *cgLayer) {
|
||||
CGBridgeLayer *bridgeLayer = (CGBridgeLayer*)cgLayer;
|
||||
CGBridgeLayer *bridgeLayer = (CGBridgeLayer *)cgLayer;
|
||||
[bridgeLayer release];
|
||||
}
|
||||
|
||||
void mozilla::plugins::PluginUtilsOSX::Repaint(void *caLayer, nsIntRect aRect) {
|
||||
CGBridgeLayer *bridgeLayer = (CGBridgeLayer*)caLayer;
|
||||
CGBridgeLayer *bridgeLayer = (CGBridgeLayer *)caLayer;
|
||||
[CATransaction begin];
|
||||
[bridgeLayer updateRect:aRect];
|
||||
[bridgeLayer setNeedsDisplay];
|
||||
@ -132,30 +115,29 @@ void mozilla::plugins::PluginUtilsOSX::Repaint(void *caLayer, nsIntRect aRect) {
|
||||
}
|
||||
|
||||
@interface EventProcessor : NSObject {
|
||||
RemoteProcessEvents aRemoteEvents;
|
||||
void *aPluginModule;
|
||||
RemoteProcessEvents aRemoteEvents;
|
||||
void *aPluginModule;
|
||||
}
|
||||
- (void)setRemoteEvents:(RemoteProcessEvents) remoteEvents pluginModule:(void*) pluginModule;
|
||||
- (void)setRemoteEvents:(RemoteProcessEvents)remoteEvents pluginModule:(void *)pluginModule;
|
||||
- (void)onTick;
|
||||
@end
|
||||
|
||||
@implementation EventProcessor
|
||||
- (void) onTick
|
||||
{
|
||||
aRemoteEvents(aPluginModule);
|
||||
- (void)onTick {
|
||||
aRemoteEvents(aPluginModule);
|
||||
}
|
||||
|
||||
- (void)setRemoteEvents:(RemoteProcessEvents) remoteEvents pluginModule:(void*) pluginModule
|
||||
{
|
||||
aRemoteEvents = remoteEvents;
|
||||
aPluginModule = pluginModule;
|
||||
- (void)setRemoteEvents:(RemoteProcessEvents)remoteEvents pluginModule:(void *)pluginModule {
|
||||
aRemoteEvents = remoteEvents;
|
||||
aPluginModule = pluginModule;
|
||||
}
|
||||
@end
|
||||
|
||||
#define EVENT_PROCESS_DELAY 0.05 // 50 ms
|
||||
#define EVENT_PROCESS_DELAY 0.05 // 50 ms
|
||||
|
||||
NPError mozilla::plugins::PluginUtilsOSX::ShowCocoaContextMenu(void* aMenu, int aX, int aY, void* pluginModule, RemoteProcessEvents remoteEvent)
|
||||
{
|
||||
NPError mozilla::plugins::PluginUtilsOSX::ShowCocoaContextMenu(void *aMenu, int aX, int aY,
|
||||
void *pluginModule,
|
||||
RemoteProcessEvents remoteEvent) {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
// Set the native cursor to the OS default (an arrow) before displaying the
|
||||
@ -166,7 +148,7 @@ NPError mozilla::plugins::PluginUtilsOSX::ShowCocoaContextMenu(void* aMenu, int
|
||||
// change to an arrow cursor automatically -- as it does in Chrome.
|
||||
[[NSCursor arrowCursor] set];
|
||||
|
||||
EventProcessor* eventProcessor = nullptr;
|
||||
EventProcessor *eventProcessor = nullptr;
|
||||
NSTimer *eventTimer = nullptr;
|
||||
if (pluginModule) {
|
||||
// Create a timer to process browser events while waiting
|
||||
@ -175,15 +157,16 @@ NPError mozilla::plugins::PluginUtilsOSX::ShowCocoaContextMenu(void* aMenu, int
|
||||
eventProcessor = [[EventProcessor alloc] init];
|
||||
[eventProcessor setRemoteEvents:remoteEvent pluginModule:pluginModule];
|
||||
eventTimer = [NSTimer timerWithTimeInterval:EVENT_PROCESS_DELAY
|
||||
target:eventProcessor selector:@selector(onTick)
|
||||
userInfo:nil repeats:TRUE];
|
||||
target:eventProcessor
|
||||
selector:@selector(onTick)
|
||||
userInfo:nil
|
||||
repeats:TRUE];
|
||||
// Use NSEventTrackingRunLoopMode otherwise the timer will
|
||||
// not fire during the right click menu.
|
||||
[[NSRunLoop currentRunLoop] addTimer:eventTimer
|
||||
forMode:NSEventTrackingRunLoopMode];
|
||||
[[NSRunLoop currentRunLoop] addTimer:eventTimer forMode:NSEventTrackingRunLoopMode];
|
||||
}
|
||||
|
||||
NSMenu* nsmenu = reinterpret_cast<NSMenu*>(aMenu);
|
||||
NSMenu *nsmenu = reinterpret_cast<NSMenu *>(aMenu);
|
||||
NSPoint screen_point = ::NSMakePoint(aX, aY);
|
||||
|
||||
[nsmenu popUpMenuPositioningItem:nil atLocation:screen_point inView:nil];
|
||||
@ -198,25 +181,23 @@ NPError mozilla::plugins::PluginUtilsOSX::ShowCocoaContextMenu(void* aMenu, int
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NPERR_GENERIC_ERROR);
|
||||
}
|
||||
|
||||
void mozilla::plugins::PluginUtilsOSX::InvokeNativeEventLoop()
|
||||
{
|
||||
void mozilla::plugins::PluginUtilsOSX::InvokeNativeEventLoop() {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
::CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.0, true);
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
|
||||
#define UNDOCUMENTED_SESSION_CONSTANT ((int)-2)
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
namespace PluginUtilsOSX {
|
||||
static void *sApplicationASN = NULL;
|
||||
static void *sApplicationInfoItem = NULL;
|
||||
} // namespace PluginUtilsOSX
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
static void *sApplicationASN = NULL;
|
||||
static void *sApplicationInfoItem = NULL;
|
||||
} // namespace PluginUtilsOSX
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
bool mozilla::plugins::PluginUtilsOSX::SetProcessName(const char* aProcessName) {
|
||||
bool mozilla::plugins::PluginUtilsOSX::SetProcessName(const char *aProcessName) {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
nsAutoreleasePool localPool;
|
||||
|
||||
@ -224,8 +205,8 @@ bool mozilla::plugins::PluginUtilsOSX::SetProcessName(const char* aProcessName)
|
||||
return false;
|
||||
}
|
||||
|
||||
NSString *currentName = [[[NSBundle mainBundle] localizedInfoDictionary]
|
||||
objectForKey:(NSString *)kCFBundleNameKey];
|
||||
NSString *currentName =
|
||||
[[[NSBundle mainBundle] localizedInfoDictionary] objectForKey:(NSString *)kCFBundleNameKey];
|
||||
|
||||
char formattedName[1024];
|
||||
SprintfLiteral(formattedName, "%s %s", [currentName UTF8String], aProcessName);
|
||||
@ -234,21 +215,18 @@ bool mozilla::plugins::PluginUtilsOSX::SetProcessName(const char* aProcessName)
|
||||
|
||||
// This function is based on Chrome/Webkit's and relies on potentially dangerous SPI.
|
||||
typedef CFTypeRef (*LSGetASNType)();
|
||||
typedef OSStatus (*LSSetInformationItemType)(int, CFTypeRef,
|
||||
CFStringRef,
|
||||
CFStringRef,
|
||||
CFDictionaryRef*);
|
||||
typedef OSStatus (*LSSetInformationItemType)(int, CFTypeRef, CFStringRef, CFStringRef,
|
||||
CFDictionaryRef *);
|
||||
|
||||
CFBundleRef launchServices = ::CFBundleGetBundleWithIdentifier(
|
||||
CFSTR("com.apple.LaunchServices"));
|
||||
CFBundleRef launchServices = ::CFBundleGetBundleWithIdentifier(CFSTR("com.apple.LaunchServices"));
|
||||
if (!launchServices) {
|
||||
NS_WARNING("Failed to set process name: Could not open LaunchServices bundle");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sApplicationASN) {
|
||||
sApplicationASN = ::CFBundleGetFunctionPointerForName(launchServices,
|
||||
CFSTR("_LSGetCurrentApplicationASN"));
|
||||
sApplicationASN =
|
||||
::CFBundleGetFunctionPointerForName(launchServices, CFSTR("_LSGetCurrentApplicationASN"));
|
||||
if (!sApplicationASN) {
|
||||
NS_WARNING("Failed to set process name: Could not get function pointer "
|
||||
"for LaunchServices");
|
||||
@ -256,24 +234,22 @@ bool mozilla::plugins::PluginUtilsOSX::SetProcessName(const char* aProcessName)
|
||||
}
|
||||
}
|
||||
|
||||
LSGetASNType getASNFunc = reinterpret_cast<LSGetASNType>
|
||||
(sApplicationASN);
|
||||
LSGetASNType getASNFunc = reinterpret_cast<LSGetASNType>(sApplicationASN);
|
||||
|
||||
if (!sApplicationInfoItem) {
|
||||
sApplicationInfoItem = ::CFBundleGetFunctionPointerForName(launchServices,
|
||||
CFSTR("_LSSetApplicationInformationItem"));
|
||||
sApplicationInfoItem = ::CFBundleGetFunctionPointerForName(
|
||||
launchServices, CFSTR("_LSSetApplicationInformationItem"));
|
||||
}
|
||||
|
||||
LSSetInformationItemType setInformationItemFunc
|
||||
= reinterpret_cast<LSSetInformationItemType>
|
||||
(sApplicationInfoItem);
|
||||
LSSetInformationItemType setInformationItemFunc =
|
||||
reinterpret_cast<LSSetInformationItemType>(sApplicationInfoItem);
|
||||
|
||||
void * displayNameKeyAddr = ::CFBundleGetDataPointerForName(launchServices,
|
||||
CFSTR("_kLSDisplayNameKey"));
|
||||
void *displayNameKeyAddr =
|
||||
::CFBundleGetDataPointerForName(launchServices, CFSTR("_kLSDisplayNameKey"));
|
||||
|
||||
CFStringRef displayNameKey = nil;
|
||||
if (displayNameKeyAddr) {
|
||||
displayNameKey = reinterpret_cast<CFStringRef>(*(CFStringRef*)displayNameKeyAddr);
|
||||
displayNameKey = reinterpret_cast<CFStringRef>(*(CFStringRef *)displayNameKeyAddr);
|
||||
}
|
||||
|
||||
// Rename will fail without this
|
||||
@ -284,23 +260,20 @@ bool mozilla::plugins::PluginUtilsOSX::SetProcessName(const char* aProcessName)
|
||||
|
||||
CFTypeRef currentAsn = getASNFunc ? getASNFunc() : nullptr;
|
||||
|
||||
if (!getASNFunc || !setInformationItemFunc ||
|
||||
!displayNameKey || !currentAsn) {
|
||||
if (!getASNFunc || !setInformationItemFunc || !displayNameKey || !currentAsn) {
|
||||
NS_WARNING("Failed to set process name: Accessing launchServices failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
CFStringRef processName = ::CFStringCreateWithCString(nil,
|
||||
aProcessName,
|
||||
kCFStringEncodingASCII);
|
||||
CFStringRef processName = ::CFStringCreateWithCString(nil, aProcessName, kCFStringEncodingASCII);
|
||||
if (!processName) {
|
||||
NS_WARNING("Failed to set process name: Could not create CFStringRef");
|
||||
return false;
|
||||
}
|
||||
|
||||
OSErr err = setInformationItemFunc(UNDOCUMENTED_SESSION_CONSTANT, currentAsn,
|
||||
displayNameKey, processName,
|
||||
nil); // Optional out param
|
||||
OSErr err =
|
||||
setInformationItemFunc(UNDOCUMENTED_SESSION_CONSTANT, currentAsn, displayNameKey, processName,
|
||||
nil); // Optional out param
|
||||
::CFRelease(processName);
|
||||
if (err != noErr) {
|
||||
NS_WARNING("Failed to set process name: LSSetInformationItemType err");
|
||||
@ -371,21 +344,13 @@ IOSurfaceID nsDoubleBufferCARenderer::GetFrontSurfaceID() {
|
||||
return mFrontSurface->GetIOSurfaceID();
|
||||
}
|
||||
|
||||
bool nsDoubleBufferCARenderer::HasBackSurface() {
|
||||
return !!mBackSurface;
|
||||
}
|
||||
bool nsDoubleBufferCARenderer::HasBackSurface() { return !!mBackSurface; }
|
||||
|
||||
bool nsDoubleBufferCARenderer::HasFrontSurface() {
|
||||
return !!mFrontSurface;
|
||||
}
|
||||
bool nsDoubleBufferCARenderer::HasFrontSurface() { return !!mFrontSurface; }
|
||||
|
||||
bool nsDoubleBufferCARenderer::HasCALayer() {
|
||||
return !!mCALayer;
|
||||
}
|
||||
bool nsDoubleBufferCARenderer::HasCALayer() { return !!mCALayer; }
|
||||
|
||||
void nsDoubleBufferCARenderer::SetCALayer(void *aCALayer) {
|
||||
mCALayer = aCALayer;
|
||||
}
|
||||
void nsDoubleBufferCARenderer::SetCALayer(void *aCALayer) { mCALayer = aCALayer; }
|
||||
|
||||
bool nsDoubleBufferCARenderer::InitFrontSurface(size_t aWidth, size_t aHeight,
|
||||
double aContentsScaleFactor,
|
||||
@ -410,11 +375,9 @@ bool nsDoubleBufferCARenderer::InitFrontSurface(size_t aWidth, size_t aHeight,
|
||||
|
||||
mCARenderer->AttachIOSurface(mFrontSurface);
|
||||
|
||||
nsresult result = mCARenderer->SetupRenderer(mCALayer,
|
||||
mFrontSurface->GetWidth(),
|
||||
mFrontSurface->GetHeight(),
|
||||
mContentsScaleFactor,
|
||||
aAllowOfflineRenderer);
|
||||
nsresult result =
|
||||
mCARenderer->SetupRenderer(mCALayer, mFrontSurface->GetWidth(), mFrontSurface->GetHeight(),
|
||||
mContentsScaleFactor, aAllowOfflineRenderer);
|
||||
|
||||
if (result != NS_OK) {
|
||||
mCARenderer = nullptr;
|
||||
@ -433,8 +396,8 @@ void nsDoubleBufferCARenderer::Render() {
|
||||
return;
|
||||
}
|
||||
|
||||
mCARenderer->Render(GetFrontSurfaceWidth(), GetFrontSurfaceHeight(),
|
||||
mContentsScaleFactor, nullptr);
|
||||
mCARenderer->Render(GetFrontSurfaceWidth(), GetFrontSurfaceHeight(), mContentsScaleFactor,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
void nsDoubleBufferCARenderer::SwapSurfaces() {
|
||||
@ -461,7 +424,6 @@ void nsDoubleBufferCARenderer::ClearBackSurface() {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace PluginUtilsOSX
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
} // namespace PluginUtilsOSX
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
@ -27,63 +27,58 @@
|
||||
|
||||
#if !defined(__LP64__)
|
||||
|
||||
#include <dlfcn.h>
|
||||
#import <Carbon/Carbon.h>
|
||||
# include <dlfcn.h>
|
||||
# import <Carbon/Carbon.h>
|
||||
|
||||
// The header file QuickdrawAPI.h is missing on OS X 10.7 and up (though the
|
||||
// QuickDraw APIs defined in it are still present) -- so we need to supply the
|
||||
// relevant parts of its contents here. It's likely that Apple will eventually
|
||||
// remove the APIs themselves (probably in OS X 10.8), so we need to make them
|
||||
// weak imports, and test for their presence before using them.
|
||||
#if !defined(__QUICKDRAWAPI__)
|
||||
# if !defined(__QUICKDRAWAPI__)
|
||||
|
||||
struct Cursor;
|
||||
extern "C" void SetCursor(const Cursor * crsr) __attribute__((weak_import));
|
||||
extern "C" void SetCursor(const Cursor* crsr) __attribute__((weak_import));
|
||||
|
||||
#endif /* __QUICKDRAWAPI__ */
|
||||
# endif /* __QUICKDRAWAPI__ */
|
||||
|
||||
BOOL (*OnSetThemeCursorPtr) (ThemeCursor) = NULL;
|
||||
BOOL (*OnSetCursorPtr) (const Cursor*) = NULL;
|
||||
BOOL (*OnHideCursorPtr) () = NULL;
|
||||
BOOL (*OnShowCursorPtr) () = NULL;
|
||||
BOOL (*OnSetThemeCursorPtr)(ThemeCursor) = NULL;
|
||||
BOOL (*OnSetCursorPtr)(const Cursor*) = NULL;
|
||||
BOOL (*OnHideCursorPtr)() = NULL;
|
||||
BOOL (*OnShowCursorPtr)() = NULL;
|
||||
|
||||
static BOOL loadXULPtrs()
|
||||
{
|
||||
static BOOL loadXULPtrs() {
|
||||
if (!OnSetThemeCursorPtr) {
|
||||
// mac_plugin_interposing_child_OnSetThemeCursor(ThemeCursor cursor) is in
|
||||
// PluginInterposeOSX.mm
|
||||
OnSetThemeCursorPtr = (BOOL(*)(ThemeCursor))
|
||||
dlsym(RTLD_DEFAULT, "mac_plugin_interposing_child_OnSetThemeCursor");
|
||||
OnSetThemeCursorPtr =
|
||||
(BOOL(*)(ThemeCursor))dlsym(RTLD_DEFAULT, "mac_plugin_interposing_child_OnSetThemeCursor");
|
||||
}
|
||||
if (!OnSetCursorPtr) {
|
||||
// mac_plugin_interposing_child_OnSetCursor(const Cursor* cursor) is in
|
||||
// PluginInterposeOSX.mm
|
||||
OnSetCursorPtr = (BOOL(*)(const Cursor*))
|
||||
dlsym(RTLD_DEFAULT, "mac_plugin_interposing_child_OnSetCursor");
|
||||
OnSetCursorPtr =
|
||||
(BOOL(*)(const Cursor*))dlsym(RTLD_DEFAULT, "mac_plugin_interposing_child_OnSetCursor");
|
||||
}
|
||||
if (!OnHideCursorPtr) {
|
||||
// mac_plugin_interposing_child_OnHideCursor() is in PluginInterposeOSX.mm
|
||||
OnHideCursorPtr = (BOOL(*)())
|
||||
dlsym(RTLD_DEFAULT, "mac_plugin_interposing_child_OnHideCursor");
|
||||
OnHideCursorPtr = (BOOL(*)())dlsym(RTLD_DEFAULT, "mac_plugin_interposing_child_OnHideCursor");
|
||||
}
|
||||
if (!OnShowCursorPtr) {
|
||||
// mac_plugin_interposing_child_OnShowCursor() is in PluginInterposeOSX.mm
|
||||
OnShowCursorPtr = (BOOL(*)())
|
||||
dlsym(RTLD_DEFAULT, "mac_plugin_interposing_child_OnShowCursor");
|
||||
OnShowCursorPtr = (BOOL(*)())dlsym(RTLD_DEFAULT, "mac_plugin_interposing_child_OnShowCursor");
|
||||
}
|
||||
return (OnSetCursorPtr && OnSetThemeCursorPtr && OnHideCursorPtr && OnShowCursorPtr);
|
||||
}
|
||||
|
||||
static OSStatus MacPluginChildSetThemeCursor(ThemeCursor cursor)
|
||||
{
|
||||
static OSStatus MacPluginChildSetThemeCursor(ThemeCursor cursor) {
|
||||
if (loadXULPtrs()) {
|
||||
OnSetThemeCursorPtr(cursor);
|
||||
}
|
||||
return ::SetThemeCursor(cursor);
|
||||
}
|
||||
|
||||
static void MacPluginChildSetCursor(const Cursor* cursor)
|
||||
{
|
||||
static void MacPluginChildSetCursor(const Cursor* cursor) {
|
||||
if (::SetCursor) {
|
||||
if (loadXULPtrs()) {
|
||||
OnSetCursorPtr(cursor);
|
||||
@ -92,43 +87,43 @@ static void MacPluginChildSetCursor(const Cursor* cursor)
|
||||
}
|
||||
}
|
||||
|
||||
static CGError MacPluginChildCGDisplayHideCursor(CGDirectDisplayID display)
|
||||
{
|
||||
static CGError MacPluginChildCGDisplayHideCursor(CGDirectDisplayID display) {
|
||||
if (loadXULPtrs()) {
|
||||
OnHideCursorPtr();
|
||||
}
|
||||
return ::CGDisplayHideCursor(display);
|
||||
}
|
||||
|
||||
static CGError MacPluginChildCGDisplayShowCursor(CGDirectDisplayID display)
|
||||
{
|
||||
static CGError MacPluginChildCGDisplayShowCursor(CGDirectDisplayID display) {
|
||||
if (loadXULPtrs()) {
|
||||
OnShowCursorPtr();
|
||||
}
|
||||
return ::CGDisplayShowCursor(display);
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
# pragma mark -
|
||||
|
||||
struct interpose_substitution {
|
||||
const void* replacement;
|
||||
const void* original;
|
||||
};
|
||||
|
||||
#define INTERPOSE_FUNCTION(function) \
|
||||
{ reinterpret_cast<const void*>(MacPluginChild##function), \
|
||||
reinterpret_cast<const void*>(function) }
|
||||
# define INTERPOSE_FUNCTION(function) \
|
||||
{ \
|
||||
reinterpret_cast<const void*>(MacPluginChild##function), \
|
||||
reinterpret_cast<const void*>(function) \
|
||||
}
|
||||
|
||||
__attribute__((used)) static const interpose_substitution substitutions[]
|
||||
__attribute__((section("__DATA, __interpose"))) = {
|
||||
INTERPOSE_FUNCTION(SetThemeCursor),
|
||||
INTERPOSE_FUNCTION(CGDisplayHideCursor),
|
||||
INTERPOSE_FUNCTION(CGDisplayShowCursor),
|
||||
// SetCursor() and other QuickDraw APIs will probably be removed in OS X
|
||||
// 10.8. But this will make 'SetCursor' NULL, which will just stop the OS
|
||||
// from interposing it (tested using an INTERPOSE_FUNCTION_BROKEN macro
|
||||
// that just sets the second address of each tuple to NULL).
|
||||
INTERPOSE_FUNCTION(SetCursor),
|
||||
INTERPOSE_FUNCTION(SetThemeCursor),
|
||||
INTERPOSE_FUNCTION(CGDisplayHideCursor),
|
||||
INTERPOSE_FUNCTION(CGDisplayShowCursor),
|
||||
// SetCursor() and other QuickDraw APIs will probably be removed in OS X
|
||||
// 10.8. But this will make 'SetCursor' NULL, which will just stop the OS
|
||||
// from interposing it (tested using an INTERPOSE_FUNCTION_BROKEN macro
|
||||
// that just sets the second address of each tuple to NULL).
|
||||
INTERPOSE_FUNCTION(SetCursor),
|
||||
};
|
||||
|
||||
#endif // !__LP64__
|
||||
|
@ -1,11 +1,11 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2008, Mozilla Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
@ -14,7 +14,7 @@
|
||||
* * Neither the name of the Mozilla Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
@ -25,10 +25,10 @@
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* Contributor(s):
|
||||
* Josh Aas <josh@mozilla.com>
|
||||
*
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nptest_platform.h"
|
||||
@ -38,21 +38,11 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
bool
|
||||
pluginSupportsWindowMode()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool pluginSupportsWindowMode() { return false; }
|
||||
|
||||
bool
|
||||
pluginSupportsWindowlessMode()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool pluginSupportsWindowlessMode() { return true; }
|
||||
|
||||
NPError
|
||||
pluginInstanceInit(InstanceData* instanceData)
|
||||
{
|
||||
NPError pluginInstanceInit(InstanceData* instanceData) {
|
||||
NPP npp = instanceData->npp;
|
||||
|
||||
NPBool supportsCoreGraphics = false;
|
||||
@ -77,28 +67,19 @@ pluginInstanceInit(InstanceData* instanceData)
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
void
|
||||
pluginInstanceShutdown(InstanceData* instanceData)
|
||||
{
|
||||
void pluginInstanceShutdown(InstanceData* instanceData) {}
|
||||
|
||||
static bool RectEquals(const NPRect& r1, const NPRect& r2) {
|
||||
return r1.left == r2.left && r1.top == r2.top && r1.right == r2.right && r1.bottom == r2.bottom;
|
||||
}
|
||||
|
||||
static bool
|
||||
RectEquals(const NPRect& r1, const NPRect& r2)
|
||||
{
|
||||
return r1.left == r2.left && r1.top == r2.top &&
|
||||
r1.right == r2.right && r1.bottom == r2.bottom;
|
||||
}
|
||||
|
||||
void
|
||||
pluginDoSetWindow(InstanceData* instanceData, NPWindow* newWindow)
|
||||
{
|
||||
void pluginDoSetWindow(InstanceData* instanceData, NPWindow* newWindow) {
|
||||
// Ugh. Due to a terrible Gecko bug, we have to ignore position changes
|
||||
// when the clip rect doesn't change; the position can be wrong
|
||||
// when set by a path other than nsPluginFrame::FixUpPluginWindow.
|
||||
int32_t oldX = instanceData->window.x;
|
||||
int32_t oldY = instanceData->window.y;
|
||||
bool clipChanged =
|
||||
!RectEquals(instanceData->window.clipRect, newWindow->clipRect);
|
||||
bool clipChanged = !RectEquals(instanceData->window.clipRect, newWindow->clipRect);
|
||||
instanceData->window = *newWindow;
|
||||
if (!clipChanged) {
|
||||
instanceData->window.x = oldX;
|
||||
@ -106,36 +87,27 @@ pluginDoSetWindow(InstanceData* instanceData, NPWindow* newWindow)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pluginWidgetInit(InstanceData* instanceData, void* oldWindow)
|
||||
{
|
||||
void pluginWidgetInit(InstanceData* instanceData, void* oldWindow) {
|
||||
// Should never be called since we don't support window mode
|
||||
}
|
||||
|
||||
static void
|
||||
GetColorsFromRGBA(uint32_t rgba, float* r, float* g, float* b, float* a)
|
||||
{
|
||||
static void GetColorsFromRGBA(uint32_t rgba, float* r, float* g, float* b, float* a) {
|
||||
*b = (rgba & 0xFF) / 255.0;
|
||||
*g = ((rgba & 0xFF00) >> 8) / 255.0;
|
||||
*r = ((rgba & 0xFF0000) >> 16) / 255.0;
|
||||
*a = ((rgba & 0xFF000000) >> 24) / 255.0;
|
||||
}
|
||||
|
||||
static void
|
||||
pluginDraw(InstanceData* instanceData, NPCocoaEvent* event)
|
||||
{
|
||||
if (!instanceData)
|
||||
return;
|
||||
static void pluginDraw(InstanceData* instanceData, NPCocoaEvent* event) {
|
||||
if (!instanceData) return;
|
||||
|
||||
notifyDidPaint(instanceData);
|
||||
|
||||
NPP npp = instanceData->npp;
|
||||
if (!npp)
|
||||
return;
|
||||
|
||||
if (!npp) return;
|
||||
|
||||
const char* uaString = NPN_UserAgent(npp);
|
||||
if (!uaString)
|
||||
return;
|
||||
if (!uaString) return;
|
||||
|
||||
NPWindow window = instanceData->window;
|
||||
|
||||
@ -144,92 +116,92 @@ pluginDraw(InstanceData* instanceData, NPCocoaEvent* event)
|
||||
float windowWidth = window.width;
|
||||
float windowHeight = window.height;
|
||||
|
||||
switch(instanceData->scriptableObject->drawMode) {
|
||||
case DM_DEFAULT: {
|
||||
CFStringRef uaCFString = CFStringCreateWithCString(kCFAllocatorDefault, uaString, kCFStringEncodingASCII);
|
||||
// save the cgcontext gstate
|
||||
CGContextSaveGState(cgContext);
|
||||
switch (instanceData->scriptableObject->drawMode) {
|
||||
case DM_DEFAULT: {
|
||||
CFStringRef uaCFString =
|
||||
CFStringCreateWithCString(kCFAllocatorDefault, uaString, kCFStringEncodingASCII);
|
||||
// save the cgcontext gstate
|
||||
CGContextSaveGState(cgContext);
|
||||
|
||||
// we get a flipped context
|
||||
CGContextTranslateCTM(cgContext, 0.0, windowHeight);
|
||||
CGContextScaleCTM(cgContext, 1.0, -1.0);
|
||||
// we get a flipped context
|
||||
CGContextTranslateCTM(cgContext, 0.0, windowHeight);
|
||||
CGContextScaleCTM(cgContext, 1.0, -1.0);
|
||||
|
||||
// draw a gray background for the plugin
|
||||
CGContextAddRect(cgContext, CGRectMake(0, 0, windowWidth, windowHeight));
|
||||
CGContextSetGrayFillColor(cgContext, 0.5, 1.0);
|
||||
CGContextDrawPath(cgContext, kCGPathFill);
|
||||
// draw a gray background for the plugin
|
||||
CGContextAddRect(cgContext, CGRectMake(0, 0, windowWidth, windowHeight));
|
||||
CGContextSetGrayFillColor(cgContext, 0.5, 1.0);
|
||||
CGContextDrawPath(cgContext, kCGPathFill);
|
||||
|
||||
// draw a black frame around the plugin
|
||||
CGContextAddRect(cgContext, CGRectMake(0, 0, windowWidth, windowHeight));
|
||||
CGContextSetGrayStrokeColor(cgContext, 0.0, 1.0);
|
||||
CGContextSetLineWidth(cgContext, 6.0);
|
||||
CGContextStrokePath(cgContext);
|
||||
// draw a black frame around the plugin
|
||||
CGContextAddRect(cgContext, CGRectMake(0, 0, windowWidth, windowHeight));
|
||||
CGContextSetGrayStrokeColor(cgContext, 0.0, 1.0);
|
||||
CGContextSetLineWidth(cgContext, 6.0);
|
||||
CGContextStrokePath(cgContext);
|
||||
|
||||
// draw the UA string using Core Text
|
||||
CGContextSetTextMatrix(cgContext, CGAffineTransformIdentity);
|
||||
// draw the UA string using Core Text
|
||||
CGContextSetTextMatrix(cgContext, CGAffineTransformIdentity);
|
||||
|
||||
// Initialize a rectangular path.
|
||||
CGMutablePathRef path = CGPathCreateMutable();
|
||||
CGRect bounds = CGRectMake(10.0, 10.0, std::max(0.0, windowWidth - 20.0),
|
||||
std::max(0.0, windowHeight - 20.0));
|
||||
CGPathAddRect(path, NULL, bounds);
|
||||
// Initialize a rectangular path.
|
||||
CGMutablePathRef path = CGPathCreateMutable();
|
||||
CGRect bounds = CGRectMake(10.0, 10.0, std::max(0.0, windowWidth - 20.0),
|
||||
std::max(0.0, windowHeight - 20.0));
|
||||
CGPathAddRect(path, NULL, bounds);
|
||||
|
||||
// Initialize an attributed string.
|
||||
CFMutableAttributedStringRef attrString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
|
||||
CFAttributedStringReplaceString(attrString, CFRangeMake(0, 0), uaCFString);
|
||||
// Initialize an attributed string.
|
||||
CFMutableAttributedStringRef attrString =
|
||||
CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
|
||||
CFAttributedStringReplaceString(attrString, CFRangeMake(0, 0), uaCFString);
|
||||
|
||||
// Create a color and add it as an attribute to the string.
|
||||
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
CGFloat components[] = { 0.0, 0.0, 0.0, 1.0 };
|
||||
CGColorRef red = CGColorCreate(rgbColorSpace, components);
|
||||
CGColorSpaceRelease(rgbColorSpace);
|
||||
CFAttributedStringSetAttribute(attrString, CFRangeMake(0, 50), kCTForegroundColorAttributeName, red);
|
||||
// Create a color and add it as an attribute to the string.
|
||||
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
CGFloat components[] = {0.0, 0.0, 0.0, 1.0};
|
||||
CGColorRef red = CGColorCreate(rgbColorSpace, components);
|
||||
CGColorSpaceRelease(rgbColorSpace);
|
||||
CFAttributedStringSetAttribute(attrString, CFRangeMake(0, 50),
|
||||
kCTForegroundColorAttributeName, red);
|
||||
|
||||
// Create the framesetter with the attributed string.
|
||||
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrString);
|
||||
CFRelease(attrString);
|
||||
// Create the framesetter with the attributed string.
|
||||
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrString);
|
||||
CFRelease(attrString);
|
||||
|
||||
// Create the frame and draw it into the graphics context
|
||||
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);
|
||||
CFRelease(framesetter);
|
||||
if (frame) {
|
||||
CTFrameDraw(frame, cgContext);
|
||||
CFRelease(frame);
|
||||
// Create the frame and draw it into the graphics context
|
||||
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);
|
||||
CFRelease(framesetter);
|
||||
if (frame) {
|
||||
CTFrameDraw(frame, cgContext);
|
||||
CFRelease(frame);
|
||||
}
|
||||
|
||||
// restore the cgcontext gstate
|
||||
CGContextRestoreGState(cgContext);
|
||||
break;
|
||||
}
|
||||
case DM_SOLID_COLOR: {
|
||||
// save the cgcontext gstate
|
||||
CGContextSaveGState(cgContext);
|
||||
|
||||
// restore the cgcontext gstate
|
||||
CGContextRestoreGState(cgContext);
|
||||
break;
|
||||
}
|
||||
case DM_SOLID_COLOR: {
|
||||
// save the cgcontext gstate
|
||||
CGContextSaveGState(cgContext);
|
||||
// we get a flipped context
|
||||
CGContextTranslateCTM(cgContext, 0.0, windowHeight);
|
||||
CGContextScaleCTM(cgContext, 1.0, -1.0);
|
||||
|
||||
// we get a flipped context
|
||||
CGContextTranslateCTM(cgContext, 0.0, windowHeight);
|
||||
CGContextScaleCTM(cgContext, 1.0, -1.0);
|
||||
// draw a solid background for the plugin
|
||||
CGContextAddRect(cgContext, CGRectMake(0, 0, windowWidth, windowHeight));
|
||||
|
||||
// draw a solid background for the plugin
|
||||
CGContextAddRect(cgContext, CGRectMake(0, 0, windowWidth, windowHeight));
|
||||
float r, g, b, a;
|
||||
GetColorsFromRGBA(instanceData->scriptableObject->drawColor, &r, &g, &b, &a);
|
||||
CGContextSetRGBFillColor(cgContext, r, g, b, a);
|
||||
CGContextDrawPath(cgContext, kCGPathFill);
|
||||
|
||||
float r,g,b,a;
|
||||
GetColorsFromRGBA(instanceData->scriptableObject->drawColor, &r, &g, &b, &a);
|
||||
CGContextSetRGBFillColor(cgContext, r, g, b, a);
|
||||
CGContextDrawPath(cgContext, kCGPathFill);
|
||||
|
||||
// restore the cgcontext gstate
|
||||
CGContextRestoreGState(cgContext);
|
||||
break;
|
||||
}
|
||||
// restore the cgcontext gstate
|
||||
CGContextRestoreGState(cgContext);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int16_t
|
||||
pluginHandleEvent(InstanceData* instanceData, void* event)
|
||||
{
|
||||
int16_t pluginHandleEvent(InstanceData* instanceData, void* event) {
|
||||
NPCocoaEvent* cocoaEvent = (NPCocoaEvent*)event;
|
||||
if (!cocoaEvent)
|
||||
return kNPEventNotHandled;
|
||||
if (!cocoaEvent) return kNPEventNotHandled;
|
||||
|
||||
switch (cocoaEvent->type) {
|
||||
case NPCocoaEventDrawRect:
|
||||
@ -246,13 +218,15 @@ pluginHandleEvent(InstanceData* instanceData, void* event)
|
||||
}
|
||||
break;
|
||||
case NPCocoaEventWindowFocusChanged:
|
||||
instanceData->topLevelWindowActivationState = cocoaEvent->data.focus.hasFocus ?
|
||||
ACTIVATION_STATE_ACTIVATED : ACTIVATION_STATE_DEACTIVATED;
|
||||
instanceData->topLevelWindowActivationEventCount = instanceData->topLevelWindowActivationEventCount + 1;
|
||||
instanceData->topLevelWindowActivationState = cocoaEvent->data.focus.hasFocus
|
||||
? ACTIVATION_STATE_ACTIVATED
|
||||
: ACTIVATION_STATE_DEACTIVATED;
|
||||
instanceData->topLevelWindowActivationEventCount =
|
||||
instanceData->topLevelWindowActivationEventCount + 1;
|
||||
break;
|
||||
case NPCocoaEventFocusChanged:
|
||||
instanceData->focusState = cocoaEvent->data.focus.hasFocus ?
|
||||
ACTIVATION_STATE_ACTIVATED : ACTIVATION_STATE_DEACTIVATED;
|
||||
instanceData->focusState = cocoaEvent->data.focus.hasFocus ? ACTIVATION_STATE_ACTIVATED
|
||||
: ACTIVATION_STATE_DEACTIVATED;
|
||||
instanceData->focusEventCount = instanceData->focusEventCount + 1;
|
||||
break;
|
||||
default:
|
||||
@ -262,32 +236,25 @@ pluginHandleEvent(InstanceData* instanceData, void* event)
|
||||
return kNPEventHandled;
|
||||
}
|
||||
|
||||
int32_t pluginGetEdge(InstanceData* instanceData, RectEdge edge)
|
||||
{
|
||||
int32_t pluginGetEdge(InstanceData* instanceData, RectEdge edge) {
|
||||
NPWindow* w = &instanceData->window;
|
||||
switch (edge) {
|
||||
case EDGE_LEFT:
|
||||
return w->x;
|
||||
case EDGE_TOP:
|
||||
return w->y;
|
||||
case EDGE_RIGHT:
|
||||
return w->x + w->width;
|
||||
case EDGE_BOTTOM:
|
||||
return w->y + w->height;
|
||||
case EDGE_LEFT:
|
||||
return w->x;
|
||||
case EDGE_TOP:
|
||||
return w->y;
|
||||
case EDGE_RIGHT:
|
||||
return w->x + w->width;
|
||||
case EDGE_BOTTOM:
|
||||
return w->y + w->height;
|
||||
}
|
||||
MOZ_CRASH("Unexpected RectEdge?!");
|
||||
}
|
||||
|
||||
int32_t pluginGetClipRegionRectCount(InstanceData* instanceData)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
int32_t pluginGetClipRegionRectCount(InstanceData* instanceData) { return 1; }
|
||||
|
||||
int32_t pluginGetClipRegionRectEdge(InstanceData* instanceData,
|
||||
int32_t rectIndex, RectEdge edge)
|
||||
{
|
||||
if (rectIndex != 0)
|
||||
return NPTEST_INT32_ERROR;
|
||||
int32_t pluginGetClipRegionRectEdge(InstanceData* instanceData, int32_t rectIndex, RectEdge edge) {
|
||||
if (rectIndex != 0) return NPTEST_INT32_ERROR;
|
||||
|
||||
// We have to add the Cocoa titlebar height here since the clip rect
|
||||
// is being returned relative to that
|
||||
@ -295,18 +262,16 @@ int32_t pluginGetClipRegionRectEdge(InstanceData* instanceData,
|
||||
|
||||
NPWindow* w = &instanceData->window;
|
||||
switch (edge) {
|
||||
case EDGE_LEFT:
|
||||
return w->clipRect.left;
|
||||
case EDGE_TOP:
|
||||
return w->clipRect.top + COCOA_TITLEBAR_HEIGHT;
|
||||
case EDGE_RIGHT:
|
||||
return w->clipRect.right;
|
||||
case EDGE_BOTTOM:
|
||||
return w->clipRect.bottom + COCOA_TITLEBAR_HEIGHT;
|
||||
case EDGE_LEFT:
|
||||
return w->clipRect.left;
|
||||
case EDGE_TOP:
|
||||
return w->clipRect.top + COCOA_TITLEBAR_HEIGHT;
|
||||
case EDGE_RIGHT:
|
||||
return w->clipRect.right;
|
||||
case EDGE_BOTTOM:
|
||||
return w->clipRect.bottom + COCOA_TITLEBAR_HEIGHT;
|
||||
}
|
||||
MOZ_CRASH("Unexpected RectEdge?!");
|
||||
}
|
||||
|
||||
void pluginDoInternalConsistencyCheck(InstanceData* instanceData, string& error)
|
||||
{
|
||||
}
|
||||
void pluginDoInternalConsistencyCheck(InstanceData* instanceData, string& error) {}
|
||||
|
@ -32,21 +32,18 @@ using namespace mozilla;
|
||||
static const CLLocationAccuracy kHIGH_ACCURACY = kCLLocationAccuracyBest;
|
||||
static const CLLocationAccuracy kDEFAULT_ACCURACY = kCLLocationAccuracyNearestTenMeters;
|
||||
|
||||
@interface LocationDelegate : NSObject <CLLocationManagerDelegate>
|
||||
{
|
||||
@interface LocationDelegate : NSObject <CLLocationManagerDelegate> {
|
||||
CoreLocationLocationProvider* mProvider;
|
||||
}
|
||||
|
||||
- (id)init:(CoreLocationLocationProvider*)aProvider;
|
||||
- (void)locationManager:(CLLocationManager*)aManager
|
||||
didFailWithError:(NSError *)aError;
|
||||
- (void)locationManager:(CLLocationManager*)aManager didFailWithError:(NSError*)aError;
|
||||
- (void)locationManager:(CLLocationManager*)aManager didUpdateLocations:(NSArray*)locations;
|
||||
|
||||
@end
|
||||
|
||||
@implementation LocationDelegate
|
||||
- (id) init:(CoreLocationLocationProvider*) aProvider
|
||||
{
|
||||
- (id)init:(CoreLocationLocationProvider*)aProvider {
|
||||
if ((self = [super init])) {
|
||||
mProvider = aProvider;
|
||||
}
|
||||
@ -54,16 +51,13 @@ static const CLLocationAccuracy kDEFAULT_ACCURACY = kCLLocationAccuracyNearestTe
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)locationManager:(CLLocationManager*)aManager
|
||||
didFailWithError:(NSError *)aError
|
||||
{
|
||||
nsCOMPtr<nsIConsoleService> console =
|
||||
do_GetService(NS_CONSOLESERVICE_CONTRACTID);
|
||||
- (void)locationManager:(CLLocationManager*)aManager didFailWithError:(NSError*)aError {
|
||||
nsCOMPtr<nsIConsoleService> console = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
|
||||
|
||||
NS_ENSURE_TRUE_VOID(console);
|
||||
|
||||
NSString* message =
|
||||
[@"Failed to acquire position: " stringByAppendingString: [aError localizedDescription]];
|
||||
[@"Failed to acquire position: " stringByAppendingString:[aError localizedDescription]];
|
||||
|
||||
console->LogStringMessage(NS_ConvertUTF8toUTF16([message UTF8String]).get());
|
||||
|
||||
@ -78,8 +72,7 @@ static const CLLocationAccuracy kDEFAULT_ACCURACY = kCLLocationAccuracyNearestTe
|
||||
mProvider->CreateMLSFallbackProvider();
|
||||
}
|
||||
|
||||
- (void)locationManager:(CLLocationManager*)aManager didUpdateLocations:(NSArray*)aLocations
|
||||
{
|
||||
- (void)locationManager:(CLLocationManager*)aManager didUpdateLocations:(NSArray*)aLocations {
|
||||
if (aLocations.count < 1) {
|
||||
return;
|
||||
}
|
||||
@ -100,25 +93,15 @@ static const CLLocationAccuracy kDEFAULT_ACCURACY = kCLLocationAccuracyNearestTe
|
||||
altitudeAccuracy = UnspecifiedNaN<double>();
|
||||
}
|
||||
|
||||
double speed = location.speed >= 0
|
||||
? location.speed
|
||||
: UnspecifiedNaN<double>();
|
||||
double speed = location.speed >= 0 ? location.speed : UnspecifiedNaN<double>();
|
||||
|
||||
double heading = location.course >= 0
|
||||
? location.course
|
||||
: UnspecifiedNaN<double>();
|
||||
double heading = location.course >= 0 ? location.course : UnspecifiedNaN<double>();
|
||||
|
||||
// nsGeoPositionCoords will convert NaNs to null for optional properties of
|
||||
// the JavaScript Coordinates object.
|
||||
nsCOMPtr<nsIDOMGeoPosition> geoPosition =
|
||||
new nsGeoPosition(location.coordinate.latitude,
|
||||
location.coordinate.longitude,
|
||||
altitude,
|
||||
location.horizontalAccuracy,
|
||||
altitudeAccuracy,
|
||||
heading,
|
||||
speed,
|
||||
PR_Now() / PR_USEC_PER_MSEC);
|
||||
nsCOMPtr<nsIDOMGeoPosition> geoPosition = new nsGeoPosition(
|
||||
location.coordinate.latitude, location.coordinate.longitude, altitude,
|
||||
location.horizontalAccuracy, altitudeAccuracy, heading, speed, PR_Now() / PR_USEC_PER_MSEC);
|
||||
|
||||
mProvider->Update(geoPosition);
|
||||
Telemetry::Accumulate(Telemetry::GEOLOCATION_OSX_SOURCE_IS_MLS, false);
|
||||
@ -128,13 +111,10 @@ static const CLLocationAccuracy kDEFAULT_ACCURACY = kCLLocationAccuracyNearestTe
|
||||
NS_IMPL_ISUPPORTS(CoreLocationLocationProvider::MLSUpdate, nsIGeolocationUpdate);
|
||||
|
||||
CoreLocationLocationProvider::MLSUpdate::MLSUpdate(CoreLocationLocationProvider& parentProvider)
|
||||
: mParentLocationProvider(parentProvider)
|
||||
{
|
||||
}
|
||||
: mParentLocationProvider(parentProvider) {}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CoreLocationLocationProvider::MLSUpdate::Update(nsIDOMGeoPosition *position)
|
||||
{
|
||||
CoreLocationLocationProvider::MLSUpdate::Update(nsIDOMGeoPosition* position) {
|
||||
nsCOMPtr<nsIDOMGeoPositionCoords> coords;
|
||||
position->GetCoords(getter_AddRefs(coords));
|
||||
if (!coords) {
|
||||
@ -146,14 +126,13 @@ CoreLocationLocationProvider::MLSUpdate::Update(nsIDOMGeoPosition *position)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CoreLocationLocationProvider::MLSUpdate::NotifyError(uint16_t error)
|
||||
{
|
||||
CoreLocationLocationProvider::MLSUpdate::NotifyError(uint16_t error) {
|
||||
mParentLocationProvider.NotifyError(error);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class CoreLocationObjects {
|
||||
public:
|
||||
public:
|
||||
nsresult Init(CoreLocationLocationProvider* aProvider) {
|
||||
mLocationManager = [[CLLocationManager alloc] init];
|
||||
NS_ENSURE_TRUE(mLocationManager, NS_ERROR_NOT_AVAILABLE);
|
||||
@ -184,13 +163,10 @@ public:
|
||||
NS_IMPL_ISUPPORTS(CoreLocationLocationProvider, nsIGeolocationProvider)
|
||||
|
||||
CoreLocationLocationProvider::CoreLocationLocationProvider()
|
||||
: mCLObjects(nullptr), mMLSFallbackProvider(nullptr)
|
||||
{
|
||||
}
|
||||
: mCLObjects(nullptr), mMLSFallbackProvider(nullptr) {}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CoreLocationLocationProvider::Startup()
|
||||
{
|
||||
CoreLocationLocationProvider::Startup() {
|
||||
if (!mCLObjects) {
|
||||
nsAutoPtr<CoreLocationObjects> clObjs(new CoreLocationObjects());
|
||||
|
||||
@ -207,8 +183,7 @@ CoreLocationLocationProvider::Startup()
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CoreLocationLocationProvider::Watch(nsIGeolocationUpdate* aCallback)
|
||||
{
|
||||
CoreLocationLocationProvider::Watch(nsIGeolocationUpdate* aCallback) {
|
||||
if (mCallback) {
|
||||
return NS_OK;
|
||||
}
|
||||
@ -218,8 +193,7 @@ CoreLocationLocationProvider::Watch(nsIGeolocationUpdate* aCallback)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CoreLocationLocationProvider::Shutdown()
|
||||
{
|
||||
CoreLocationLocationProvider::Shutdown() {
|
||||
NS_ENSURE_STATE(mCLObjects);
|
||||
|
||||
[mCLObjects->mLocationManager stopUpdatingLocation];
|
||||
@ -236,31 +210,23 @@ CoreLocationLocationProvider::Shutdown()
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CoreLocationLocationProvider::SetHighAccuracy(bool aEnable)
|
||||
{
|
||||
CoreLocationLocationProvider::SetHighAccuracy(bool aEnable) {
|
||||
NS_ENSURE_STATE(mCLObjects);
|
||||
|
||||
mCLObjects->mLocationManager.desiredAccuracy =
|
||||
(aEnable ? kHIGH_ACCURACY : kDEFAULT_ACCURACY);
|
||||
mCLObjects->mLocationManager.desiredAccuracy = (aEnable ? kHIGH_ACCURACY : kDEFAULT_ACCURACY);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
CoreLocationLocationProvider::Update(nsIDOMGeoPosition* aSomewhere)
|
||||
{
|
||||
void CoreLocationLocationProvider::Update(nsIDOMGeoPosition* aSomewhere) {
|
||||
if (aSomewhere && mCallback) {
|
||||
mCallback->Update(aSomewhere);
|
||||
}
|
||||
}
|
||||
void
|
||||
CoreLocationLocationProvider::NotifyError(uint16_t aErrorCode)
|
||||
{
|
||||
void CoreLocationLocationProvider::NotifyError(uint16_t aErrorCode) {
|
||||
mCallback->NotifyError(aErrorCode);
|
||||
}
|
||||
void
|
||||
CoreLocationLocationProvider::CreateMLSFallbackProvider()
|
||||
{
|
||||
void CoreLocationLocationProvider::CreateMLSFallbackProvider() {
|
||||
if (mMLSFallbackProvider) {
|
||||
return;
|
||||
}
|
||||
@ -269,9 +235,7 @@ CoreLocationLocationProvider::CreateMLSFallbackProvider()
|
||||
mMLSFallbackProvider->Startup(new MLSUpdate(*this));
|
||||
}
|
||||
|
||||
void
|
||||
CoreLocationLocationProvider::CancelMLSFallbackProvider()
|
||||
{
|
||||
void CoreLocationLocationProvider::CancelMLSFallbackProvider() {
|
||||
if (!mMLSFallbackProvider) {
|
||||
return;
|
||||
}
|
||||
|
@ -15,8 +15,7 @@ using namespace mozilla;
|
||||
using mozilla::dom::Promise;
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsOSPermissionRequest::GetAudioCapturePermissionState(uint16_t* aAudio)
|
||||
{
|
||||
nsOSPermissionRequest::GetAudioCapturePermissionState(uint16_t* aAudio) {
|
||||
MOZ_ASSERT(aAudio);
|
||||
|
||||
if (!nsCocoaFeatures::OnMojaveOrLater()) {
|
||||
@ -27,8 +26,7 @@ nsOSPermissionRequest::GetAudioCapturePermissionState(uint16_t* aAudio)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsOSPermissionRequest::GetVideoCapturePermissionState(uint16_t* aVideo)
|
||||
{
|
||||
nsOSPermissionRequest::GetVideoCapturePermissionState(uint16_t* aVideo) {
|
||||
MOZ_ASSERT(aVideo);
|
||||
|
||||
if (!nsCocoaFeatures::OnMojaveOrLater()) {
|
||||
@ -39,9 +37,7 @@ nsOSPermissionRequest::GetVideoCapturePermissionState(uint16_t* aVideo)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsOSPermissionRequest::RequestVideoCapturePermission(JSContext* aCx,
|
||||
Promise** aPromiseOut)
|
||||
{
|
||||
nsOSPermissionRequest::RequestVideoCapturePermission(JSContext* aCx, Promise** aPromiseOut) {
|
||||
if (!nsCocoaFeatures::OnMojaveOrLater()) {
|
||||
return nsOSPermissionRequestBase::RequestVideoCapturePermission(aCx, aPromiseOut);
|
||||
}
|
||||
@ -58,9 +54,7 @@ nsOSPermissionRequest::RequestVideoCapturePermission(JSContext* aCx,
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsOSPermissionRequest::RequestAudioCapturePermission(JSContext* aCx,
|
||||
Promise** aPromiseOut)
|
||||
{
|
||||
nsOSPermissionRequest::RequestAudioCapturePermission(JSContext* aCx, Promise** aPromiseOut) {
|
||||
if (!nsCocoaFeatures::OnMojaveOrLater()) {
|
||||
return nsOSPermissionRequestBase::RequestAudioCapturePermission(aCx, aPromiseOut);
|
||||
}
|
||||
|
@ -19,24 +19,22 @@
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
static const nsXREAppData sAppData = {
|
||||
sizeof(nsXREAppData),
|
||||
nullptr, // directory
|
||||
"Mozilla",
|
||||
"Browser",
|
||||
nullptr,
|
||||
"38.0a1",
|
||||
"201502090123",
|
||||
"browser@mozilla.org",
|
||||
nullptr, // copyright
|
||||
0,
|
||||
nullptr, // xreDirectory
|
||||
"38.0a1",
|
||||
"*",
|
||||
"https://crash-reports.mozilla.com/submit",
|
||||
nullptr,
|
||||
"Firefox"
|
||||
};
|
||||
static const nsXREAppData sAppData = {sizeof(nsXREAppData),
|
||||
nullptr, // directory
|
||||
"Mozilla",
|
||||
"Browser",
|
||||
nullptr,
|
||||
"38.0a1",
|
||||
"201502090123",
|
||||
"browser@mozilla.org",
|
||||
nullptr, // copyright
|
||||
0,
|
||||
nullptr, // xreDirectory
|
||||
"38.0a1",
|
||||
"*",
|
||||
"https://crash-reports.mozilla.com/submit",
|
||||
nullptr,
|
||||
"Firefox"};
|
||||
|
||||
XRE_GetFileFromPathType XRE_GetFileFromPath;
|
||||
XRE_CreateAppDataType XRE_CreateAppData;
|
||||
@ -44,17 +42,16 @@ XRE_FreeAppDataType XRE_FreeAppData;
|
||||
XRE_mainType XRE_main;
|
||||
|
||||
static const nsDynamicFunctionLoad kXULFuncs[] = {
|
||||
{ "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath },
|
||||
{ "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData },
|
||||
{ "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData },
|
||||
{ "XRE_main", (NSFuncPtr*) &XRE_main },
|
||||
{ nullptr, nullptr }
|
||||
};
|
||||
{"XRE_GetFileFromPath", (NSFuncPtr*)&XRE_GetFileFromPath},
|
||||
{"XRE_CreateAppData", (NSFuncPtr*)&XRE_CreateAppData},
|
||||
{"XRE_FreeAppData", (NSFuncPtr*)&XRE_FreeAppData},
|
||||
{"XRE_main", (NSFuncPtr*)&XRE_main},
|
||||
{nullptr, nullptr}};
|
||||
|
||||
const int MAXPATHLEN = 1024;
|
||||
const char* XPCOM_DLL = "XUL";
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
int main(int argc, char* argv[]) {
|
||||
char exeDir[MAXPATHLEN];
|
||||
NSString* bundlePath = [[NSBundle mainBundle] bundlePath];
|
||||
strncpy(exeDir, [bundlePath UTF8String], MAXPATHLEN);
|
||||
@ -82,7 +79,7 @@ int main(int argc, char * argv[]) {
|
||||
printf("Couldn't find the application directory.\n");
|
||||
return 255;
|
||||
}
|
||||
|
||||
|
||||
nsCOMPtr<nsIFile> appSubdir;
|
||||
greDir->Clone(getter_AddRefs(appSubdir));
|
||||
greDir->Append(NS_LITERAL_STRING("Frameworks"));
|
||||
|
@ -14,19 +14,17 @@
|
||||
#include <dlfcn.h>
|
||||
#include "GLDefs.h"
|
||||
|
||||
#define IOSURFACE_FRAMEWORK_PATH \
|
||||
"/System/Library/Frameworks/IOSurface.framework/IOSurface"
|
||||
#define OPENGL_FRAMEWORK_PATH \
|
||||
"/System/Library/Frameworks/OpenGL.framework/OpenGL"
|
||||
#define COREGRAPHICS_FRAMEWORK_PATH \
|
||||
"/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/CoreGraphics"
|
||||
#define IOSURFACE_FRAMEWORK_PATH "/System/Library/Frameworks/IOSurface.framework/IOSurface"
|
||||
#define OPENGL_FRAMEWORK_PATH "/System/Library/Frameworks/OpenGL.framework/OpenGL"
|
||||
#define COREGRAPHICS_FRAMEWORK_PATH \
|
||||
"/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/" \
|
||||
"CoreGraphics"
|
||||
|
||||
@interface CALayer (ContentsScale)
|
||||
- (double)contentsScale;
|
||||
- (void)setContentsScale:(double)scale;
|
||||
@end
|
||||
|
||||
|
||||
CGColorSpaceRef CreateSystemColorSpace() {
|
||||
CGColorSpaceRef cspace = ::CGDisplayCopyColorSpace(::CGMainDisplayID());
|
||||
if (!cspace) {
|
||||
@ -35,11 +33,9 @@ CGColorSpaceRef CreateSystemColorSpace() {
|
||||
return cspace;
|
||||
}
|
||||
|
||||
nsCARenderer::~nsCARenderer() {
|
||||
Destroy();
|
||||
}
|
||||
nsCARenderer::~nsCARenderer() { Destroy(); }
|
||||
|
||||
void cgdata_release_callback(void *aCGData, const void *data, size_t size) {
|
||||
void cgdata_release_callback(void* aCGData, const void* data, size_t size) {
|
||||
if (aCGData) {
|
||||
free(aCGData);
|
||||
}
|
||||
@ -75,8 +71,7 @@ void nsCARenderer::Destroy() {
|
||||
::glDeleteFramebuffersEXT(1, &mFBO);
|
||||
}
|
||||
|
||||
if (oldContext)
|
||||
::CGLSetCurrentContext(oldContext);
|
||||
if (oldContext) ::CGLSetCurrentContext(oldContext);
|
||||
}
|
||||
::CGLDestroyContext((CGLContextObj)mOpenGLContext);
|
||||
}
|
||||
@ -95,25 +90,20 @@ void nsCARenderer::Destroy() {
|
||||
mIOTexture = 0;
|
||||
}
|
||||
|
||||
nsresult nsCARenderer::SetupRenderer(void *aCALayer, int aWidth, int aHeight,
|
||||
nsresult nsCARenderer::SetupRenderer(void* aCALayer, int aWidth, int aHeight,
|
||||
double aContentsScaleFactor,
|
||||
AllowOfflineRendererEnum aAllowOfflineRenderer) {
|
||||
mAllowOfflineRenderer = aAllowOfflineRenderer;
|
||||
|
||||
if (aWidth == 0 || aHeight == 0 || aContentsScaleFactor <= 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
if (aWidth == 0 || aHeight == 0 || aContentsScaleFactor <= 0) return NS_ERROR_FAILURE;
|
||||
|
||||
if (aWidth == mUnsupportedWidth &&
|
||||
aHeight == mUnsupportedHeight) {
|
||||
if (aWidth == mUnsupportedWidth && aHeight == mUnsupportedHeight) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
CGLPixelFormatAttribute attributes[] = {
|
||||
kCGLPFAAccelerated,
|
||||
kCGLPFADepthSize, (CGLPixelFormatAttribute)24,
|
||||
kCGLPFAAllowOfflineRenderers,
|
||||
(CGLPixelFormatAttribute)0
|
||||
};
|
||||
CGLPixelFormatAttribute attributes[] = {kCGLPFAAccelerated, kCGLPFADepthSize,
|
||||
(CGLPixelFormatAttribute)24, kCGLPFAAllowOfflineRenderers,
|
||||
(CGLPixelFormatAttribute)0};
|
||||
|
||||
if (mAllowOfflineRenderer == DISALLOW_OFFLINE_RENDERER) {
|
||||
attributes[3] = (CGLPixelFormatAttribute)0;
|
||||
@ -136,8 +126,7 @@ nsresult nsCARenderer::SetupRenderer(void *aCALayer, int aWidth, int aHeight,
|
||||
}
|
||||
::CGLDestroyPixelFormat(format);
|
||||
|
||||
CARenderer* caRenderer = [[CARenderer rendererWithCGLContext:mOpenGLContext
|
||||
options:nil] retain];
|
||||
CARenderer* caRenderer = [[CARenderer rendererWithCGLContext:mOpenGLContext options:nil] retain];
|
||||
if (caRenderer == nil) {
|
||||
mUnsupportedWidth = aWidth;
|
||||
mUnsupportedHeight = aHeight;
|
||||
@ -163,22 +152,22 @@ nsresult nsCARenderer::SetupRenderer(void *aCALayer, int aWidth, int aHeight,
|
||||
|
||||
// We target rendering to a CGImage if no shared IOSurface are given.
|
||||
if (!mIOSurface) {
|
||||
mCGData = malloc(aWidth*intScaleFactor*aHeight*4*intScaleFactor);
|
||||
mCGData = malloc(aWidth * intScaleFactor * aHeight * 4 * intScaleFactor);
|
||||
if (!mCGData) {
|
||||
mUnsupportedWidth = aWidth;
|
||||
mUnsupportedHeight = aHeight;
|
||||
Destroy();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
memset(mCGData, 0, aWidth*intScaleFactor*aHeight*4*intScaleFactor);
|
||||
memset(mCGData, 0, aWidth * intScaleFactor * aHeight * 4 * intScaleFactor);
|
||||
|
||||
CGDataProviderRef dataProvider = nullptr;
|
||||
dataProvider = ::CGDataProviderCreateWithData(mCGData,
|
||||
mCGData, aHeight*intScaleFactor*aWidth*4*intScaleFactor,
|
||||
cgdata_release_callback);
|
||||
dataProvider = ::CGDataProviderCreateWithData(
|
||||
mCGData, mCGData, aHeight * intScaleFactor * aWidth * 4 * intScaleFactor,
|
||||
cgdata_release_callback);
|
||||
if (!dataProvider) {
|
||||
cgdata_release_callback(mCGData, mCGData,
|
||||
aHeight*intScaleFactor*aWidth*4*intScaleFactor);
|
||||
aHeight * intScaleFactor * aWidth * 4 * intScaleFactor);
|
||||
mUnsupportedWidth = aWidth;
|
||||
mUnsupportedHeight = aHeight;
|
||||
Destroy();
|
||||
@ -187,10 +176,10 @@ nsresult nsCARenderer::SetupRenderer(void *aCALayer, int aWidth, int aHeight,
|
||||
|
||||
CGColorSpaceRef colorSpace = CreateSystemColorSpace();
|
||||
|
||||
mCGImage = ::CGImageCreate(aWidth * intScaleFactor, aHeight * intScaleFactor,
|
||||
8, 32, aWidth * intScaleFactor * 4, colorSpace,
|
||||
kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
|
||||
dataProvider, nullptr, true, kCGRenderingIntentDefault);
|
||||
mCGImage = ::CGImageCreate(aWidth * intScaleFactor, aHeight * intScaleFactor, 8, 32,
|
||||
aWidth * intScaleFactor * 4, colorSpace,
|
||||
kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
|
||||
dataProvider, nullptr, true, kCGRenderingIntentDefault);
|
||||
|
||||
::CGDataProviderRelease(dataProvider);
|
||||
::CGColorSpaceRelease(colorSpace);
|
||||
@ -211,11 +200,10 @@ nsresult nsCARenderer::SetupRenderer(void *aCALayer, int aWidth, int aHeight,
|
||||
::glBindTexture(GL_TEXTURE_RECTANGLE_ARB, mIOTexture);
|
||||
::glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
::glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
MacIOSurfaceLib::CGLTexImageIOSurface2D(mOpenGLContext, GL_TEXTURE_RECTANGLE_ARB,
|
||||
GL_RGBA, aWidth * intScaleFactor,
|
||||
aHeight * intScaleFactor,
|
||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
mIOSurface->mIOSurfacePtr, 0);
|
||||
MacIOSurfaceLib::CGLTexImageIOSurface2D(mOpenGLContext, GL_TEXTURE_RECTANGLE_ARB, GL_RGBA,
|
||||
aWidth * intScaleFactor, aHeight * intScaleFactor,
|
||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
mIOSurface->mIOSurfacePtr, 0);
|
||||
::glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
} else {
|
||||
::glGenTextures(1, &mFBOTexture);
|
||||
@ -229,21 +217,19 @@ nsresult nsCARenderer::SetupRenderer(void *aCALayer, int aWidth, int aHeight,
|
||||
::glGenFramebuffersEXT(1, &mFBO);
|
||||
::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO);
|
||||
if (mIOSurface) {
|
||||
::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
||||
::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
||||
GL_TEXTURE_RECTANGLE_ARB, mIOTexture, 0);
|
||||
} else {
|
||||
::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
||||
GL_TEXTURE_RECTANGLE_ARB, mFBOTexture, 0);
|
||||
}
|
||||
|
||||
|
||||
// Make sure that the Framebuffer configuration is supported on the client machine
|
||||
GLenum fboStatus;
|
||||
fboStatus = ::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||
if (fboStatus != GL_FRAMEBUFFER_COMPLETE_EXT) {
|
||||
NS_ERROR("FBO not supported");
|
||||
if (oldContext)
|
||||
::CGLSetCurrentContext(oldContext);
|
||||
if (oldContext) ::CGLSetCurrentContext(oldContext);
|
||||
mUnsupportedWidth = aWidth;
|
||||
mUnsupportedHeight = aHeight;
|
||||
Destroy();
|
||||
@ -258,13 +244,11 @@ nsresult nsCARenderer::SetupRenderer(void *aCALayer, int aWidth, int aHeight,
|
||||
mUnsupportedWidth = aWidth;
|
||||
mUnsupportedHeight = aHeight;
|
||||
Destroy();
|
||||
if (oldContext)
|
||||
::CGLSetCurrentContext(oldContext);
|
||||
if (oldContext) ::CGLSetCurrentContext(oldContext);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (oldContext)
|
||||
::CGLSetCurrentContext(oldContext);
|
||||
if (oldContext) ::CGLSetCurrentContext(oldContext);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -273,20 +257,15 @@ void nsCARenderer::SetBounds(int aWidth, int aHeight) {
|
||||
CARenderer* caRenderer = (CARenderer*)mCARenderer;
|
||||
CALayer* wrapperLayer = (CALayer*)mWrapperCALayer;
|
||||
NSArray* sublayers = [wrapperLayer sublayers];
|
||||
CALayer* pluginLayer = (CALayer*) [sublayers objectAtIndex:0];
|
||||
CALayer* pluginLayer = (CALayer*)[sublayers objectAtIndex:0];
|
||||
|
||||
// Create a transaction and disable animations
|
||||
// to make the position update instant.
|
||||
[CATransaction begin];
|
||||
NSMutableDictionary *newActions =
|
||||
[[NSMutableDictionary alloc] initWithObjectsAndKeys:
|
||||
[NSNull null], @"onOrderIn",
|
||||
[NSNull null], @"onOrderOut",
|
||||
[NSNull null], @"sublayers",
|
||||
[NSNull null], @"contents",
|
||||
[NSNull null], @"position",
|
||||
[NSNull null], @"bounds",
|
||||
nil];
|
||||
NSMutableDictionary* newActions = [[NSMutableDictionary alloc]
|
||||
initWithObjectsAndKeys:[NSNull null], @"onOrderIn", [NSNull null], @"onOrderOut",
|
||||
[NSNull null], @"sublayers", [NSNull null], @"contents", [NSNull null],
|
||||
@"position", [NSNull null], @"bounds", nil];
|
||||
wrapperLayer.actions = newActions;
|
||||
[newActions release];
|
||||
|
||||
@ -298,10 +277,10 @@ void nsCARenderer::SetBounds(int aWidth, int aHeight) {
|
||||
// making pluginLayer (usually the CALayer* provided by the plugin) a
|
||||
// sublayer of our own wrapperLayer (see bug 829284).
|
||||
size_t intScaleFactor = ceil(mContentsScaleFactor);
|
||||
[CATransaction setValue: [NSNumber numberWithFloat:0.0f] forKey: kCATransactionAnimationDuration];
|
||||
[CATransaction setValue: (id) kCFBooleanTrue forKey: kCATransactionDisableActions];
|
||||
[CATransaction setValue:[NSNumber numberWithFloat:0.0f] forKey:kCATransactionAnimationDuration];
|
||||
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
|
||||
[wrapperLayer setBounds:CGRectMake(0, 0, aWidth, aHeight)];
|
||||
[wrapperLayer setPosition:CGPointMake(aWidth/2.0, aHeight/2.0)];
|
||||
[wrapperLayer setPosition:CGPointMake(aWidth / 2.0, aHeight / 2.0)];
|
||||
[pluginLayer setBounds:CGRectMake(0, 0, aWidth, aHeight)];
|
||||
[pluginLayer setFrame:CGRectMake(0, 0, aWidth, aHeight)];
|
||||
caRenderer.bounds = CGRectMake(0, 0, aWidth * intScaleFactor, aHeight * intScaleFactor);
|
||||
@ -309,8 +288,8 @@ void nsCARenderer::SetBounds(int aWidth, int aHeight) {
|
||||
CGAffineTransform affineTransform = [wrapperLayer affineTransform];
|
||||
affineTransform.a = mContentsScaleFactor;
|
||||
affineTransform.d = mContentsScaleFactor;
|
||||
affineTransform.tx = ((double)aWidth)/mContentsScaleFactor;
|
||||
affineTransform.ty = ((double)aHeight)/mContentsScaleFactor;
|
||||
affineTransform.tx = ((double)aWidth) / mContentsScaleFactor;
|
||||
affineTransform.ty = ((double)aHeight) / mContentsScaleFactor;
|
||||
[wrapperLayer setAffineTransform:affineTransform];
|
||||
} else {
|
||||
// These settings are the default values. But they might have been
|
||||
@ -329,16 +308,15 @@ void nsCARenderer::SetViewport(int aWidth, int aHeight) {
|
||||
::glViewport(0.0, 0.0, aWidth, aHeight);
|
||||
::glMatrixMode(GL_PROJECTION);
|
||||
::glLoadIdentity();
|
||||
::glOrtho (0.0, aWidth, 0.0, aHeight, -1, 1);
|
||||
::glOrtho(0.0, aWidth, 0.0, aHeight, -1, 1);
|
||||
|
||||
// Render upside down to speed up CGContextDrawImage
|
||||
::glTranslatef(0.0f, aHeight, 0.0);
|
||||
::glScalef(1.0, -1.0, 1.0);
|
||||
}
|
||||
|
||||
void nsCARenderer::AttachIOSurface(MacIOSurface *aSurface) {
|
||||
if (mIOSurface &&
|
||||
aSurface->GetIOSurfaceID() == mIOSurface->GetIOSurfaceID()) {
|
||||
void nsCARenderer::AttachIOSurface(MacIOSurface* aSurface) {
|
||||
if (mIOSurface && aSurface->GetIOSurfaceID() == mIOSurface->GetIOSurfaceID()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -354,11 +332,10 @@ void nsCARenderer::AttachIOSurface(MacIOSurface *aSurface) {
|
||||
CGLContextObj oldContext = ::CGLGetCurrentContext();
|
||||
::CGLSetCurrentContext(mOpenGLContext);
|
||||
::glBindTexture(GL_TEXTURE_RECTANGLE_ARB, mIOTexture);
|
||||
MacIOSurfaceLib::CGLTexImageIOSurface2D(mOpenGLContext, GL_TEXTURE_RECTANGLE_ARB,
|
||||
GL_RGBA, mIOSurface->GetDevicePixelWidth(),
|
||||
mIOSurface->GetDevicePixelHeight(),
|
||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
mIOSurface->mIOSurfacePtr, 0);
|
||||
MacIOSurfaceLib::CGLTexImageIOSurface2D(
|
||||
mOpenGLContext, GL_TEXTURE_RECTANGLE_ARB, GL_RGBA, mIOSurface->GetDevicePixelWidth(),
|
||||
mIOSurface->GetDevicePixelHeight(), GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
mIOSurface->mIOSurfacePtr, 0);
|
||||
::glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
|
||||
// Rebind the FBO to make it live
|
||||
@ -386,9 +363,8 @@ IOSurfaceID nsCARenderer::GetIOSurfaceID() {
|
||||
return mIOSurface->GetIOSurfaceID();
|
||||
}
|
||||
|
||||
nsresult nsCARenderer::Render(int aWidth, int aHeight,
|
||||
double aContentsScaleFactor,
|
||||
CGImageRef *aOutCGImage) {
|
||||
nsresult nsCARenderer::Render(int aWidth, int aHeight, double aContentsScaleFactor,
|
||||
CGImageRef* aOutCGImage) {
|
||||
if (!aOutCGImage && !mIOSurface) {
|
||||
NS_ERROR("No target destination for rendering");
|
||||
} else if (aOutCGImage) {
|
||||
@ -397,8 +373,7 @@ nsresult nsCARenderer::Render(int aWidth, int aHeight,
|
||||
*aOutCGImage = nullptr;
|
||||
}
|
||||
|
||||
if (aWidth == 0 || aHeight == 0 || aContentsScaleFactor <= 0)
|
||||
return NS_OK;
|
||||
if (aWidth == 0 || aHeight == 0 || aContentsScaleFactor <= 0) return NS_OK;
|
||||
|
||||
if (!mCARenderer || !mWrapperCALayer) {
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -417,15 +392,15 @@ nsresult nsCARenderer::Render(int aWidth, int aHeight,
|
||||
// caLayer may be the CALayer* provided by the plugin, so we need to
|
||||
// preserve it across the call to Destroy().
|
||||
NSArray* sublayers = [wrapperLayer sublayers];
|
||||
CALayer* caLayer = (CALayer*) [sublayers objectAtIndex:0];
|
||||
CALayer* caLayer = (CALayer*)[sublayers objectAtIndex:0];
|
||||
// mIOSurface is set by AttachIOSurface(), not by SetupRenderer(). So
|
||||
// since it may have been set by a prior call to AttachIOSurface(), we
|
||||
// need to preserve it across the call to Destroy().
|
||||
RefPtr<MacIOSurface> ioSurface = mIOSurface;
|
||||
Destroy();
|
||||
mIOSurface = ioSurface;
|
||||
if (SetupRenderer(caLayer, aWidth, aHeight, aContentsScaleFactor,
|
||||
mAllowOfflineRenderer) != NS_OK) {
|
||||
if (SetupRenderer(caLayer, aWidth, aHeight, aContentsScaleFactor, mAllowOfflineRenderer) !=
|
||||
NS_OK) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -444,8 +419,7 @@ nsresult nsCARenderer::Render(int aWidth, int aHeight,
|
||||
if (result != GL_NO_ERROR) {
|
||||
NS_ERROR("Unexpected OpenGL Error");
|
||||
Destroy();
|
||||
if (oldContext)
|
||||
::CGLSetCurrentContext(oldContext);
|
||||
if (oldContext) ::CGLSetCurrentContext(oldContext);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -455,8 +429,7 @@ nsresult nsCARenderer::Render(int aWidth, int aHeight,
|
||||
[CATransaction commit];
|
||||
double caTime = ::CACurrentMediaTime();
|
||||
[caRenderer beginFrameAtTime:caTime timeStamp:nullptr];
|
||||
[caRenderer addUpdateRect:CGRectMake(0,0, aWidth * intScaleFactor,
|
||||
aHeight * intScaleFactor)];
|
||||
[caRenderer addUpdateRect:CGRectMake(0, 0, aWidth * intScaleFactor, aHeight * intScaleFactor)];
|
||||
[caRenderer render];
|
||||
[caRenderer endFrame];
|
||||
|
||||
@ -469,10 +442,8 @@ nsresult nsCARenderer::Render(int aWidth, int aHeight,
|
||||
::glPixelStorei(GL_PACK_SKIP_ROWS, 0);
|
||||
::glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
|
||||
|
||||
::glReadPixels(0.0f, 0.0f, aWidth * intScaleFactor,
|
||||
aHeight * intScaleFactor,
|
||||
GL_BGRA, GL_UNSIGNED_BYTE,
|
||||
mCGData);
|
||||
::glReadPixels(0.0f, 0.0f, aWidth * intScaleFactor, aHeight * intScaleFactor, GL_BGRA,
|
||||
GL_UNSIGNED_BYTE, mCGData);
|
||||
|
||||
*aOutCGImage = mCGImage;
|
||||
}
|
||||
@ -484,10 +455,8 @@ nsresult nsCARenderer::Render(int aWidth, int aHeight,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsCARenderer::DrawSurfaceToCGContext(CGContextRef aContext,
|
||||
MacIOSurface *surf,
|
||||
CGColorSpaceRef aColorSpace,
|
||||
int aX, int aY,
|
||||
nsresult nsCARenderer::DrawSurfaceToCGContext(CGContextRef aContext, MacIOSurface* surf,
|
||||
CGColorSpaceRef aColorSpace, int aX, int aY,
|
||||
size_t aWidth, size_t aHeight) {
|
||||
surf->Lock();
|
||||
size_t bytesPerRow = surf->GetBytesPerRow();
|
||||
@ -496,13 +465,11 @@ nsresult nsCARenderer::DrawSurfaceToCGContext(CGContextRef aContext,
|
||||
|
||||
// We get rendering glitches if we use a width/height that falls
|
||||
// outside of the IOSurface.
|
||||
if (aWidth + aX > ioWidth)
|
||||
aWidth = ioWidth - aX;
|
||||
if (aHeight + aY > ioHeight)
|
||||
aHeight = ioHeight - aY;
|
||||
if (aWidth + aX > ioWidth) aWidth = ioWidth - aX;
|
||||
if (aHeight + aY > ioHeight) aHeight = ioHeight - aY;
|
||||
|
||||
if (aX < 0 || static_cast<size_t>(aX) >= ioWidth ||
|
||||
aY < 0 || static_cast<size_t>(aY) >= ioHeight) {
|
||||
if (aX < 0 || static_cast<size_t>(aX) >= ioWidth || aY < 0 ||
|
||||
static_cast<size_t>(aY) >= ioHeight) {
|
||||
surf->Unlock();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -510,28 +477,26 @@ nsresult nsCARenderer::DrawSurfaceToCGContext(CGContextRef aContext,
|
||||
void* ioData = surf->GetBaseAddress();
|
||||
double scaleFactor = surf->GetContentsScaleFactor();
|
||||
size_t intScaleFactor = ceil(surf->GetContentsScaleFactor());
|
||||
CGDataProviderRef dataProvider = ::CGDataProviderCreateWithData(ioData,
|
||||
ioData, ioHeight*intScaleFactor*(bytesPerRow)*4,
|
||||
nullptr); //No release callback
|
||||
CGDataProviderRef dataProvider =
|
||||
::CGDataProviderCreateWithData(ioData, ioData, ioHeight * intScaleFactor * (bytesPerRow)*4,
|
||||
nullptr); // No release callback
|
||||
if (!dataProvider) {
|
||||
surf->Unlock();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
CGImageRef cgImage = ::CGImageCreate(ioWidth * intScaleFactor,
|
||||
ioHeight * intScaleFactor, 8, 32, bytesPerRow, aColorSpace,
|
||||
kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
|
||||
dataProvider, nullptr, true, kCGRenderingIntentDefault);
|
||||
CGImageRef cgImage =
|
||||
::CGImageCreate(ioWidth * intScaleFactor, ioHeight * intScaleFactor, 8, 32, bytesPerRow,
|
||||
aColorSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
|
||||
dataProvider, nullptr, true, kCGRenderingIntentDefault);
|
||||
::CGDataProviderRelease(dataProvider);
|
||||
if (!cgImage) {
|
||||
surf->Unlock();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
CGImageRef subImage = ::CGImageCreateWithImageInRect(cgImage,
|
||||
::CGRectMake(aX * scaleFactor,
|
||||
aY * scaleFactor,
|
||||
aWidth * scaleFactor,
|
||||
aHeight * scaleFactor));
|
||||
CGImageRef subImage = ::CGImageCreateWithImageInRect(
|
||||
cgImage, ::CGRectMake(aX * scaleFactor, aY * scaleFactor, aWidth * scaleFactor,
|
||||
aHeight * scaleFactor));
|
||||
if (!subImage) {
|
||||
::CGImageRelease(cgImage);
|
||||
surf->Unlock();
|
||||
@ -539,11 +504,9 @@ nsresult nsCARenderer::DrawSurfaceToCGContext(CGContextRef aContext,
|
||||
}
|
||||
|
||||
::CGContextScaleCTM(aContext, 1.0f, -1.0f);
|
||||
::CGContextDrawImage(aContext,
|
||||
CGRectMake(aX * scaleFactor,
|
||||
(-(CGFloat)aY - (CGFloat)aHeight) * scaleFactor,
|
||||
aWidth * scaleFactor,
|
||||
aHeight * scaleFactor),
|
||||
::CGContextDrawImage(aContext,
|
||||
CGRectMake(aX * scaleFactor, (-(CGFloat)aY - (CGFloat)aHeight) * scaleFactor,
|
||||
aWidth * scaleFactor, aHeight * scaleFactor),
|
||||
subImage);
|
||||
|
||||
::CGImageRelease(subImage);
|
||||
@ -555,14 +518,14 @@ nsresult nsCARenderer::DrawSurfaceToCGContext(CGContextRef aContext,
|
||||
void nsCARenderer::DetachCALayer() {
|
||||
CALayer* wrapperLayer = (CALayer*)mWrapperCALayer;
|
||||
NSArray* sublayers = [wrapperLayer sublayers];
|
||||
CALayer* oldLayer = (CALayer*) [sublayers objectAtIndex:0];
|
||||
CALayer* oldLayer = (CALayer*)[sublayers objectAtIndex:0];
|
||||
[oldLayer removeFromSuperlayer];
|
||||
}
|
||||
|
||||
void nsCARenderer::AttachCALayer(void *aCALayer) {
|
||||
void nsCARenderer::AttachCALayer(void* aCALayer) {
|
||||
CALayer* wrapperLayer = (CALayer*)mWrapperCALayer;
|
||||
NSArray* sublayers = [wrapperLayer sublayers];
|
||||
CALayer* oldLayer = (CALayer*) [sublayers objectAtIndex:0];
|
||||
CALayer* oldLayer = (CALayer*)[sublayers objectAtIndex:0];
|
||||
[oldLayer removeFromSuperlayer];
|
||||
[wrapperLayer addSublayer:(CALayer*)aCALayer];
|
||||
}
|
||||
@ -570,24 +533,24 @@ void nsCARenderer::AttachCALayer(void *aCALayer) {
|
||||
#ifdef DEBUG
|
||||
|
||||
int sSaveToDiskSequence = 0;
|
||||
void nsCARenderer::SaveToDisk(MacIOSurface *surf) {
|
||||
void nsCARenderer::SaveToDisk(MacIOSurface* surf) {
|
||||
surf->Lock();
|
||||
size_t bytesPerRow = surf->GetBytesPerRow();
|
||||
size_t ioWidth = surf->GetWidth();
|
||||
size_t ioHeight = surf->GetHeight();
|
||||
void* ioData = surf->GetBaseAddress();
|
||||
CGDataProviderRef dataProvider = ::CGDataProviderCreateWithData(ioData,
|
||||
ioData, ioHeight*(bytesPerRow)*4,
|
||||
nullptr); //No release callback
|
||||
CGDataProviderRef dataProvider =
|
||||
::CGDataProviderCreateWithData(ioData, ioData, ioHeight * (bytesPerRow)*4,
|
||||
nullptr); // No release callback
|
||||
if (!dataProvider) {
|
||||
surf->Unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
CGColorSpaceRef colorSpace = CreateSystemColorSpace();
|
||||
CGImageRef cgImage = ::CGImageCreate(ioWidth, ioHeight, 8, 32, bytesPerRow,
|
||||
colorSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
|
||||
dataProvider, nullptr, true, kCGRenderingIntentDefault);
|
||||
CGImageRef cgImage = ::CGImageCreate(ioWidth, ioHeight, 8, 32, bytesPerRow, colorSpace,
|
||||
kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
|
||||
dataProvider, nullptr, true, kCGRenderingIntentDefault);
|
||||
::CGDataProviderRelease(dataProvider);
|
||||
::CGColorSpaceRelease(colorSpace);
|
||||
if (!cgImage) {
|
||||
@ -598,10 +561,11 @@ void nsCARenderer::SaveToDisk(MacIOSurface *surf) {
|
||||
char cstr[1000];
|
||||
SprintfLiteral(cstr, "file:///Users/benoitgirard/debug/iosurface_%i.png", ++sSaveToDiskSequence);
|
||||
|
||||
CFStringRef cfStr = ::CFStringCreateWithCString(kCFAllocatorDefault, cstr, kCFStringEncodingMacRoman);
|
||||
CFStringRef cfStr =
|
||||
::CFStringCreateWithCString(kCFAllocatorDefault, cstr, kCFStringEncodingMacRoman);
|
||||
|
||||
printf("Exporting: %s\n", cstr);
|
||||
CFURLRef url = ::CFURLCreateWithString( nullptr, cfStr, nullptr);
|
||||
CFURLRef url = ::CFURLCreateWithString(nullptr, cfStr, nullptr);
|
||||
::CFRelease(cfStr);
|
||||
|
||||
CFStringRef type = kUTTypePNG;
|
||||
@ -619,7 +583,6 @@ void nsCARenderer::SaveToDisk(MacIOSurface *surf) {
|
||||
surf->Unlock();
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -28,167 +28,118 @@ namespace gl {
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::widget;
|
||||
|
||||
class CGLLibrary
|
||||
{
|
||||
public:
|
||||
bool EnsureInitialized()
|
||||
{
|
||||
if (mInitialized) {
|
||||
return true;
|
||||
}
|
||||
if (!mOGLLibrary) {
|
||||
mOGLLibrary = PR_LoadLibrary("/System/Library/Frameworks/OpenGL.framework/OpenGL");
|
||||
if (!mOGLLibrary) {
|
||||
NS_WARNING("Couldn't load OpenGL Framework.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const char* db = PR_GetEnv("MOZ_CGL_DB");
|
||||
if (db) {
|
||||
mUseDoubleBufferedWindows = *db != '0';
|
||||
}
|
||||
|
||||
mInitialized = true;
|
||||
return true;
|
||||
class CGLLibrary {
|
||||
public:
|
||||
bool EnsureInitialized() {
|
||||
if (mInitialized) {
|
||||
return true;
|
||||
}
|
||||
if (!mOGLLibrary) {
|
||||
mOGLLibrary = PR_LoadLibrary("/System/Library/Frameworks/OpenGL.framework/OpenGL");
|
||||
if (!mOGLLibrary) {
|
||||
NS_WARNING("Couldn't load OpenGL Framework.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool UseDoubleBufferedWindows() const {
|
||||
MOZ_ASSERT(mInitialized);
|
||||
return mUseDoubleBufferedWindows;
|
||||
const char* db = PR_GetEnv("MOZ_CGL_DB");
|
||||
if (db) {
|
||||
mUseDoubleBufferedWindows = *db != '0';
|
||||
}
|
||||
|
||||
private:
|
||||
bool mInitialized = false;
|
||||
bool mUseDoubleBufferedWindows = true;
|
||||
PRLibrary* mOGLLibrary = nullptr;
|
||||
mInitialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UseDoubleBufferedWindows() const {
|
||||
MOZ_ASSERT(mInitialized);
|
||||
return mUseDoubleBufferedWindows;
|
||||
}
|
||||
|
||||
private:
|
||||
bool mInitialized = false;
|
||||
bool mUseDoubleBufferedWindows = true;
|
||||
PRLibrary* mOGLLibrary = nullptr;
|
||||
};
|
||||
|
||||
CGLLibrary sCGLLibrary;
|
||||
|
||||
GLContextCGL::GLContextCGL(CreateContextFlags flags, const SurfaceCaps& caps,
|
||||
NSOpenGLContext* context, bool isOffscreen)
|
||||
: GLContext(flags, caps, nullptr, isOffscreen)
|
||||
, mContext(context)
|
||||
{
|
||||
}
|
||||
: GLContext(flags, caps, nullptr, isOffscreen), mContext(context) {}
|
||||
|
||||
GLContextCGL::~GLContextCGL()
|
||||
{
|
||||
MarkDestroyed();
|
||||
GLContextCGL::~GLContextCGL() {
|
||||
MarkDestroyed();
|
||||
|
||||
if (mContext) {
|
||||
if ([NSOpenGLContext currentContext] == mContext) {
|
||||
// Clear the current context before releasing. If we don't do
|
||||
// this, the next time we call [NSOpenGLContext currentContext],
|
||||
// "invalid context" will be printed to the console.
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
}
|
||||
[mContext release];
|
||||
if (mContext) {
|
||||
if ([NSOpenGLContext currentContext] == mContext) {
|
||||
// Clear the current context before releasing. If we don't do
|
||||
// this, the next time we call [NSOpenGLContext currentContext],
|
||||
// "invalid context" will be printed to the console.
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
}
|
||||
[mContext release];
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
GLContextCGL::Init()
|
||||
{
|
||||
if (!InitWithPrefix("gl", true))
|
||||
return false;
|
||||
bool GLContextCGL::Init() {
|
||||
if (!InitWithPrefix("gl", true)) return false;
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
CGLContextObj
|
||||
GLContextCGL::GetCGLContext() const
|
||||
{
|
||||
return static_cast<CGLContextObj>([mContext CGLContextObj]);
|
||||
CGLContextObj GLContextCGL::GetCGLContext() const {
|
||||
return static_cast<CGLContextObj>([mContext CGLContextObj]);
|
||||
}
|
||||
|
||||
bool
|
||||
GLContextCGL::MakeCurrentImpl() const
|
||||
{
|
||||
if (mContext) {
|
||||
[mContext makeCurrentContext];
|
||||
MOZ_ASSERT(IsCurrentImpl());
|
||||
// Use non-blocking swap in "ASAP mode".
|
||||
// ASAP mode means that rendering is iterated as fast as possible.
|
||||
// ASAP mode is entered when layout.frame_rate=0 (requires restart).
|
||||
// If swapInt is 1, then glSwapBuffers will block and wait for a vblank signal.
|
||||
// When we're iterating as fast as possible, however, we want a non-blocking
|
||||
// glSwapBuffers, which will happen when swapInt==0.
|
||||
GLint swapInt = gfxPrefs::LayoutFrameRate() == 0 ? 0 : 1;
|
||||
[mContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
|
||||
}
|
||||
return true;
|
||||
bool GLContextCGL::MakeCurrentImpl() const {
|
||||
if (mContext) {
|
||||
[mContext makeCurrentContext];
|
||||
MOZ_ASSERT(IsCurrentImpl());
|
||||
// Use non-blocking swap in "ASAP mode".
|
||||
// ASAP mode means that rendering is iterated as fast as possible.
|
||||
// ASAP mode is entered when layout.frame_rate=0 (requires restart).
|
||||
// If swapInt is 1, then glSwapBuffers will block and wait for a vblank signal.
|
||||
// When we're iterating as fast as possible, however, we want a non-blocking
|
||||
// glSwapBuffers, which will happen when swapInt==0.
|
||||
GLint swapInt = gfxPrefs::LayoutFrameRate() == 0 ? 0 : 1;
|
||||
[mContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GLContextCGL::IsCurrentImpl() const
|
||||
{
|
||||
return [NSOpenGLContext currentContext] == mContext;
|
||||
}
|
||||
bool GLContextCGL::IsCurrentImpl() const { return [NSOpenGLContext currentContext] == mContext; }
|
||||
|
||||
GLenum
|
||||
GLContextCGL::GetPreferredARGB32Format() const
|
||||
{
|
||||
return LOCAL_GL_BGRA;
|
||||
}
|
||||
GLenum GLContextCGL::GetPreferredARGB32Format() const { return LOCAL_GL_BGRA; }
|
||||
|
||||
bool
|
||||
GLContextCGL::SetupLookupFunction()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool GLContextCGL::SetupLookupFunction() { return false; }
|
||||
|
||||
bool
|
||||
GLContextCGL::IsDoubleBuffered() const
|
||||
{
|
||||
return sCGLLibrary.UseDoubleBufferedWindows();
|
||||
}
|
||||
bool GLContextCGL::IsDoubleBuffered() const { return sCGLLibrary.UseDoubleBufferedWindows(); }
|
||||
|
||||
bool
|
||||
GLContextCGL::SwapBuffers()
|
||||
{
|
||||
bool GLContextCGL::SwapBuffers() {
|
||||
AUTO_PROFILER_LABEL("GLContextCGL::SwapBuffers", GRAPHICS);
|
||||
|
||||
[mContext flushBuffer];
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
GLContextCGL::GetWSIInfo(nsCString* const out) const
|
||||
{
|
||||
out->AppendLiteral("CGL");
|
||||
}
|
||||
void GLContextCGL::GetWSIInfo(nsCString* const out) const { out->AppendLiteral("CGL"); }
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderCGL::CreateWrappingExisting(void*, void*)
|
||||
{
|
||||
return nullptr;
|
||||
already_AddRefed<GLContext> GLContextProviderCGL::CreateWrappingExisting(void*, void*) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static const NSOpenGLPixelFormatAttribute kAttribs_singleBuffered[] = {
|
||||
NSOpenGLPFAAllowOfflineRenderers,
|
||||
0
|
||||
};
|
||||
NSOpenGLPFAAllowOfflineRenderers, 0};
|
||||
|
||||
static const NSOpenGLPixelFormatAttribute kAttribs_singleBuffered_accel[] = {
|
||||
NSOpenGLPFAAccelerated,
|
||||
NSOpenGLPFAAllowOfflineRenderers,
|
||||
0
|
||||
};
|
||||
NSOpenGLPFAAccelerated, NSOpenGLPFAAllowOfflineRenderers, 0};
|
||||
|
||||
static const NSOpenGLPixelFormatAttribute kAttribs_doubleBuffered[] = {
|
||||
NSOpenGLPFAAllowOfflineRenderers,
|
||||
NSOpenGLPFADoubleBuffer,
|
||||
0
|
||||
};
|
||||
NSOpenGLPFAAllowOfflineRenderers, NSOpenGLPFADoubleBuffer, 0};
|
||||
|
||||
static const NSOpenGLPixelFormatAttribute kAttribs_doubleBuffered_accel[] = {
|
||||
NSOpenGLPFAAccelerated,
|
||||
NSOpenGLPFAAllowOfflineRenderers,
|
||||
NSOpenGLPFADoubleBuffer,
|
||||
0
|
||||
};
|
||||
NSOpenGLPFAAccelerated, NSOpenGLPFAAllowOfflineRenderers, NSOpenGLPFADoubleBuffer, 0};
|
||||
|
||||
static const NSOpenGLPixelFormatAttribute kAttribs_doubleBuffered_accel_webrender[] = {
|
||||
NSOpenGLPFAAccelerated,
|
||||
@ -196,199 +147,177 @@ static const NSOpenGLPixelFormatAttribute kAttribs_doubleBuffered_accel_webrende
|
||||
NSOpenGLPFADoubleBuffer,
|
||||
NSOpenGLPFAOpenGLProfile,
|
||||
NSOpenGLProfileVersion3_2Core,
|
||||
NSOpenGLPFADepthSize, 24,
|
||||
0
|
||||
};
|
||||
NSOpenGLPFADepthSize,
|
||||
24,
|
||||
0};
|
||||
|
||||
static NSOpenGLContext*
|
||||
CreateWithFormat(const NSOpenGLPixelFormatAttribute* attribs)
|
||||
{
|
||||
NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc]
|
||||
initWithAttributes:attribs];
|
||||
if (!format) {
|
||||
NS_WARNING("Failed to create NSOpenGLPixelFormat.");
|
||||
return nullptr;
|
||||
}
|
||||
static NSOpenGLContext* CreateWithFormat(const NSOpenGLPixelFormatAttribute* attribs) {
|
||||
NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
|
||||
if (!format) {
|
||||
NS_WARNING("Failed to create NSOpenGLPixelFormat.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NSOpenGLContext* context = [[NSOpenGLContext alloc] initWithFormat:format
|
||||
shareContext:nullptr];
|
||||
NSOpenGLContext* context = [[NSOpenGLContext alloc] initWithFormat:format shareContext:nullptr];
|
||||
|
||||
[format release];
|
||||
[format release];
|
||||
|
||||
return context;
|
||||
return context;
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderCGL::CreateForCompositorWidget(CompositorWidget* aCompositorWidget, bool aForceAccelerated)
|
||||
{
|
||||
return CreateForWindow(aCompositorWidget->RealWidget(),
|
||||
aCompositorWidget->GetCompositorOptions().UseWebRender(),
|
||||
aForceAccelerated);
|
||||
already_AddRefed<GLContext> GLContextProviderCGL::CreateForCompositorWidget(
|
||||
CompositorWidget* aCompositorWidget, bool aForceAccelerated) {
|
||||
return CreateForWindow(aCompositorWidget->RealWidget(),
|
||||
aCompositorWidget->GetCompositorOptions().UseWebRender(),
|
||||
aForceAccelerated);
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderCGL::CreateForWindow(nsIWidget* aWidget,
|
||||
bool aWebRender,
|
||||
bool aForceAccelerated)
|
||||
{
|
||||
if (!sCGLLibrary.EnsureInitialized()) {
|
||||
return nullptr;
|
||||
}
|
||||
already_AddRefed<GLContext> GLContextProviderCGL::CreateForWindow(nsIWidget* aWidget,
|
||||
bool aWebRender,
|
||||
bool aForceAccelerated) {
|
||||
if (!sCGLLibrary.EnsureInitialized()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifdef EMULATE_VM
|
||||
if (aForceAccelerated) {
|
||||
return nullptr;
|
||||
}
|
||||
if (aForceAccelerated) {
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
const NSOpenGLPixelFormatAttribute* attribs;
|
||||
if (sCGLLibrary.UseDoubleBufferedWindows()) {
|
||||
if (aWebRender) {
|
||||
attribs = aForceAccelerated ? kAttribs_doubleBuffered_accel_webrender : kAttribs_doubleBuffered;
|
||||
} else {
|
||||
attribs = aForceAccelerated ? kAttribs_doubleBuffered_accel : kAttribs_doubleBuffered;
|
||||
}
|
||||
const NSOpenGLPixelFormatAttribute* attribs;
|
||||
if (sCGLLibrary.UseDoubleBufferedWindows()) {
|
||||
if (aWebRender) {
|
||||
attribs =
|
||||
aForceAccelerated ? kAttribs_doubleBuffered_accel_webrender : kAttribs_doubleBuffered;
|
||||
} else {
|
||||
attribs = aForceAccelerated ? kAttribs_singleBuffered_accel : kAttribs_singleBuffered;
|
||||
}
|
||||
NSOpenGLContext* context = CreateWithFormat(attribs);
|
||||
if (!context) {
|
||||
return nullptr;
|
||||
attribs = aForceAccelerated ? kAttribs_doubleBuffered_accel : kAttribs_doubleBuffered;
|
||||
}
|
||||
} else {
|
||||
attribs = aForceAccelerated ? kAttribs_singleBuffered_accel : kAttribs_singleBuffered;
|
||||
}
|
||||
NSOpenGLContext* context = CreateWithFormat(attribs);
|
||||
if (!context) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GLint opaque = gfxPrefs::CompositorGLContextOpaque();
|
||||
[context setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];
|
||||
GLint opaque = gfxPrefs::CompositorGLContextOpaque();
|
||||
[context setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];
|
||||
|
||||
RefPtr<GLContextCGL> glContext = new GLContextCGL(CreateContextFlags::NONE,
|
||||
SurfaceCaps::ForRGBA(), context,
|
||||
false);
|
||||
RefPtr<GLContextCGL> glContext =
|
||||
new GLContextCGL(CreateContextFlags::NONE, SurfaceCaps::ForRGBA(), context, false);
|
||||
|
||||
if (!glContext->Init()) {
|
||||
glContext = nullptr;
|
||||
[context release];
|
||||
return nullptr;
|
||||
}
|
||||
if (!glContext->Init()) {
|
||||
glContext = nullptr;
|
||||
[context release];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return glContext.forget();
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
static already_AddRefed<GLContextCGL>
|
||||
CreateOffscreenFBOContext(CreateContextFlags flags)
|
||||
{
|
||||
if (!sCGLLibrary.EnsureInitialized()) {
|
||||
return nullptr;
|
||||
}
|
||||
static already_AddRefed<GLContextCGL> CreateOffscreenFBOContext(CreateContextFlags flags) {
|
||||
if (!sCGLLibrary.EnsureInitialized()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NSOpenGLContext* context = nullptr;
|
||||
NSOpenGLContext* context = nullptr;
|
||||
|
||||
std::vector<NSOpenGLPixelFormatAttribute> attribs;
|
||||
std::vector<NSOpenGLPixelFormatAttribute> attribs;
|
||||
|
||||
if (flags & CreateContextFlags::ALLOW_OFFLINE_RENDERER ||
|
||||
!(flags & CreateContextFlags::HIGH_POWER))
|
||||
{
|
||||
// This is really poorly named on Apple's part, but "AllowOfflineRenderers" means
|
||||
// that we want to allow running on the iGPU instead of requiring the dGPU.
|
||||
attribs.push_back(NSOpenGLPFAAllowOfflineRenderers);
|
||||
}
|
||||
if (flags & CreateContextFlags::ALLOW_OFFLINE_RENDERER ||
|
||||
!(flags & CreateContextFlags::HIGH_POWER)) {
|
||||
// This is really poorly named on Apple's part, but "AllowOfflineRenderers" means
|
||||
// that we want to allow running on the iGPU instead of requiring the dGPU.
|
||||
attribs.push_back(NSOpenGLPFAAllowOfflineRenderers);
|
||||
}
|
||||
|
||||
if (gfxPrefs::RequireHardwareGL()) {
|
||||
attribs.push_back(NSOpenGLPFAAccelerated);
|
||||
}
|
||||
if (gfxPrefs::RequireHardwareGL()) {
|
||||
attribs.push_back(NSOpenGLPFAAccelerated);
|
||||
}
|
||||
|
||||
if (!(flags & CreateContextFlags::REQUIRE_COMPAT_PROFILE)) {
|
||||
auto coreAttribs = attribs;
|
||||
coreAttribs.push_back(NSOpenGLPFAOpenGLProfile);
|
||||
coreAttribs.push_back(NSOpenGLProfileVersion3_2Core);
|
||||
coreAttribs.push_back(0);
|
||||
context = CreateWithFormat(coreAttribs.data());
|
||||
}
|
||||
if (!(flags & CreateContextFlags::REQUIRE_COMPAT_PROFILE)) {
|
||||
auto coreAttribs = attribs;
|
||||
coreAttribs.push_back(NSOpenGLPFAOpenGLProfile);
|
||||
coreAttribs.push_back(NSOpenGLProfileVersion3_2Core);
|
||||
coreAttribs.push_back(0);
|
||||
context = CreateWithFormat(coreAttribs.data());
|
||||
}
|
||||
|
||||
if (!context) {
|
||||
attribs.push_back(0);
|
||||
context = CreateWithFormat(attribs.data());
|
||||
}
|
||||
if (!context) {
|
||||
attribs.push_back(0);
|
||||
context = CreateWithFormat(attribs.data());
|
||||
}
|
||||
|
||||
if (!context) {
|
||||
NS_WARNING("Failed to create NSOpenGLContext.");
|
||||
return nullptr;
|
||||
}
|
||||
if (!context) {
|
||||
NS_WARNING("Failed to create NSOpenGLContext.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<GLContextCGL> glContext = new GLContextCGL(flags, SurfaceCaps::Any(), context,
|
||||
true);
|
||||
RefPtr<GLContextCGL> glContext = new GLContextCGL(flags, SurfaceCaps::Any(), context, true);
|
||||
|
||||
if (gfxPrefs::GLMultithreaded()) {
|
||||
CGLEnable(glContext->GetCGLContext(), kCGLCEMPEngine);
|
||||
}
|
||||
return glContext.forget();
|
||||
if (gfxPrefs::GLMultithreaded()) {
|
||||
CGLEnable(glContext->GetCGLContext(), kCGLCEMPEngine);
|
||||
}
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderCGL::CreateHeadless(CreateContextFlags flags,
|
||||
nsACString* const out_failureId)
|
||||
{
|
||||
RefPtr<GLContextCGL> gl;
|
||||
gl = CreateOffscreenFBOContext(flags);
|
||||
if (!gl) {
|
||||
*out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_CGL_FBO");
|
||||
return nullptr;
|
||||
}
|
||||
already_AddRefed<GLContext> GLContextProviderCGL::CreateHeadless(CreateContextFlags flags,
|
||||
nsACString* const out_failureId) {
|
||||
RefPtr<GLContextCGL> gl;
|
||||
gl = CreateOffscreenFBOContext(flags);
|
||||
if (!gl) {
|
||||
*out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_CGL_FBO");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!gl->Init()) {
|
||||
*out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_CGL_INIT");
|
||||
NS_WARNING("Failed during Init.");
|
||||
return nullptr;
|
||||
}
|
||||
if (!gl->Init()) {
|
||||
*out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_CGL_INIT");
|
||||
NS_WARNING("Failed during Init.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return gl.forget();
|
||||
return gl.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderCGL::CreateOffscreen(const IntSize& size,
|
||||
const SurfaceCaps& minCaps,
|
||||
CreateContextFlags flags,
|
||||
nsACString* const out_failureId)
|
||||
{
|
||||
RefPtr<GLContext> gl = CreateHeadless(flags, out_failureId);
|
||||
if (!gl) {
|
||||
return nullptr;
|
||||
}
|
||||
already_AddRefed<GLContext> GLContextProviderCGL::CreateOffscreen(const IntSize& size,
|
||||
const SurfaceCaps& minCaps,
|
||||
CreateContextFlags flags,
|
||||
nsACString* const out_failureId) {
|
||||
RefPtr<GLContext> gl = CreateHeadless(flags, out_failureId);
|
||||
if (!gl) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!gl->InitOffscreen(size, minCaps)) {
|
||||
*out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_CGL_INIT");
|
||||
return nullptr;
|
||||
}
|
||||
if (!gl->InitOffscreen(size, minCaps)) {
|
||||
*out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_CGL_INIT");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return gl.forget();
|
||||
return gl.forget();
|
||||
}
|
||||
|
||||
static RefPtr<GLContext> gGlobalContext;
|
||||
|
||||
GLContext*
|
||||
GLContextProviderCGL::GetGlobalContext()
|
||||
{
|
||||
static bool triedToCreateContext = false;
|
||||
if (!triedToCreateContext) {
|
||||
triedToCreateContext = true;
|
||||
GLContext* GLContextProviderCGL::GetGlobalContext() {
|
||||
static bool triedToCreateContext = false;
|
||||
if (!triedToCreateContext) {
|
||||
triedToCreateContext = true;
|
||||
|
||||
MOZ_RELEASE_ASSERT(!gGlobalContext);
|
||||
nsCString discardFailureId;
|
||||
RefPtr<GLContext> temp = CreateHeadless(CreateContextFlags::NONE,
|
||||
&discardFailureId);
|
||||
gGlobalContext = temp;
|
||||
MOZ_RELEASE_ASSERT(!gGlobalContext);
|
||||
nsCString discardFailureId;
|
||||
RefPtr<GLContext> temp = CreateHeadless(CreateContextFlags::NONE, &discardFailureId);
|
||||
gGlobalContext = temp;
|
||||
|
||||
if (!gGlobalContext) {
|
||||
NS_WARNING("Couldn't init gGlobalContext.");
|
||||
}
|
||||
if (!gGlobalContext) {
|
||||
NS_WARNING("Couldn't init gGlobalContext.");
|
||||
}
|
||||
}
|
||||
|
||||
return gGlobalContext;
|
||||
return gGlobalContext;
|
||||
}
|
||||
|
||||
void
|
||||
GLContextProviderCGL::Shutdown()
|
||||
{
|
||||
gGlobalContext = nullptr;
|
||||
}
|
||||
void GLContextProviderCGL::Shutdown() { gGlobalContext = nullptr; }
|
||||
|
||||
} /* namespace gl */
|
||||
} /* namespace mozilla */
|
||||
|
@ -23,256 +23,202 @@ namespace gl {
|
||||
using namespace mozilla::widget;
|
||||
|
||||
GLContextEAGL::GLContextEAGL(CreateContextFlags flags, const SurfaceCaps& caps,
|
||||
EAGLContext* context, GLContext* sharedContext,
|
||||
bool isOffscreen)
|
||||
: GLContext(flags, caps, sharedContext, isOffscreen)
|
||||
, mContext(context)
|
||||
{
|
||||
EAGLContext* context, GLContext* sharedContext, bool isOffscreen)
|
||||
: GLContext(flags, caps, sharedContext, isOffscreen), mContext(context) {}
|
||||
|
||||
GLContextEAGL::~GLContextEAGL() {
|
||||
MakeCurrent();
|
||||
|
||||
if (mBackbufferFB) {
|
||||
fDeleteFramebuffers(1, &mBackbufferFB);
|
||||
}
|
||||
|
||||
if (mBackbufferRB) {
|
||||
fDeleteRenderbuffers(1, &mBackbufferRB);
|
||||
}
|
||||
|
||||
MarkDestroyed();
|
||||
|
||||
if (mLayer) {
|
||||
mLayer = nil;
|
||||
}
|
||||
|
||||
if (mContext) {
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
[mContext release];
|
||||
}
|
||||
}
|
||||
|
||||
GLContextEAGL::~GLContextEAGL()
|
||||
{
|
||||
MakeCurrent();
|
||||
bool GLContextEAGL::Init() {
|
||||
if (!InitWithPrefix("gl", true)) return false;
|
||||
|
||||
if (mBackbufferFB) {
|
||||
fDeleteFramebuffers(1, &mBackbufferFB);
|
||||
}
|
||||
|
||||
if (mBackbufferRB) {
|
||||
fDeleteRenderbuffers(1, &mBackbufferRB);
|
||||
}
|
||||
|
||||
MarkDestroyed();
|
||||
|
||||
if (mLayer) {
|
||||
mLayer = nil;
|
||||
}
|
||||
|
||||
if (mContext) {
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
[mContext release];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GLContextEAGL::AttachToWindow(nsIWidget* aWidget) {
|
||||
// This should only be called once
|
||||
MOZ_ASSERT(!mBackbufferFB && !mBackbufferRB);
|
||||
|
||||
UIView* view = reinterpret_cast<UIView*>(aWidget->GetNativeData(NS_NATIVE_WIDGET));
|
||||
|
||||
if (!view) {
|
||||
MOZ_CRASH("no view!");
|
||||
}
|
||||
|
||||
mLayer = [view layer];
|
||||
|
||||
fGenFramebuffers(1, &mBackbufferFB);
|
||||
return RecreateRB();
|
||||
}
|
||||
|
||||
bool GLContextEAGL::RecreateRB() {
|
||||
MakeCurrent();
|
||||
|
||||
CAEAGLLayer* layer = (CAEAGLLayer*)mLayer;
|
||||
|
||||
if (mBackbufferRB) {
|
||||
// It doesn't seem to be enough to just call renderbufferStorage: below,
|
||||
// we apparently have to recreate the RB.
|
||||
fDeleteRenderbuffers(1, &mBackbufferRB);
|
||||
mBackbufferRB = 0;
|
||||
}
|
||||
|
||||
fGenRenderbuffers(1, &mBackbufferRB);
|
||||
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mBackbufferRB);
|
||||
|
||||
[mContext renderbufferStorage:LOCAL_GL_RENDERBUFFER fromDrawable:layer];
|
||||
|
||||
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mBackbufferFB);
|
||||
fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, LOCAL_GL_RENDERBUFFER,
|
||||
mBackbufferRB);
|
||||
|
||||
return LOCAL_GL_FRAMEBUFFER_COMPLETE == fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
|
||||
}
|
||||
|
||||
bool GLContextEAGL::MakeCurrentImpl() const {
|
||||
if (mContext) {
|
||||
if (![EAGLContext setCurrentContext:mContext]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GLContextEAGL::Init()
|
||||
{
|
||||
if (!InitWithPrefix("gl", true))
|
||||
return false;
|
||||
bool GLContextEAGL::IsCurrentImpl() const { return [EAGLContext currentContext] == mContext; }
|
||||
|
||||
return true;
|
||||
}
|
||||
bool GLContextEAGL::SetupLookupFunction() { return false; }
|
||||
|
||||
bool
|
||||
GLContextEAGL::AttachToWindow(nsIWidget* aWidget)
|
||||
{
|
||||
// This should only be called once
|
||||
MOZ_ASSERT(!mBackbufferFB && !mBackbufferRB);
|
||||
bool GLContextEAGL::IsDoubleBuffered() const { return true; }
|
||||
|
||||
UIView* view =
|
||||
reinterpret_cast<UIView*>(aWidget->GetNativeData(NS_NATIVE_WIDGET));
|
||||
|
||||
if (!view) {
|
||||
MOZ_CRASH("no view!");
|
||||
}
|
||||
|
||||
mLayer = [view layer];
|
||||
|
||||
fGenFramebuffers(1, &mBackbufferFB);
|
||||
return RecreateRB();
|
||||
}
|
||||
|
||||
bool
|
||||
GLContextEAGL::RecreateRB()
|
||||
{
|
||||
MakeCurrent();
|
||||
|
||||
CAEAGLLayer* layer = (CAEAGLLayer*)mLayer;
|
||||
|
||||
if (mBackbufferRB) {
|
||||
// It doesn't seem to be enough to just call renderbufferStorage: below,
|
||||
// we apparently have to recreate the RB.
|
||||
fDeleteRenderbuffers(1, &mBackbufferRB);
|
||||
mBackbufferRB = 0;
|
||||
}
|
||||
|
||||
fGenRenderbuffers(1, &mBackbufferRB);
|
||||
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mBackbufferRB);
|
||||
|
||||
[mContext renderbufferStorage:LOCAL_GL_RENDERBUFFER
|
||||
fromDrawable:layer];
|
||||
|
||||
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mBackbufferFB);
|
||||
fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
|
||||
LOCAL_GL_RENDERBUFFER, mBackbufferRB);
|
||||
|
||||
return LOCAL_GL_FRAMEBUFFER_COMPLETE == fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
|
||||
}
|
||||
|
||||
bool
|
||||
GLContextEAGL::MakeCurrentImpl() const
|
||||
{
|
||||
if (mContext) {
|
||||
if(![EAGLContext setCurrentContext:mContext]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GLContextEAGL::IsCurrentImpl() const
|
||||
{
|
||||
return [EAGLContext currentContext] == mContext;
|
||||
}
|
||||
|
||||
bool
|
||||
GLContextEAGL::SetupLookupFunction()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
GLContextEAGL::IsDoubleBuffered() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GLContextEAGL::SwapBuffers()
|
||||
{
|
||||
bool GLContextEAGL::SwapBuffers() {
|
||||
AUTO_PROFILER_LABEL("GLContextEAGL::SwapBuffers", GRAPHICS);
|
||||
|
||||
[mContext presentRenderbuffer:LOCAL_GL_RENDERBUFFER];
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
GLContextEAGL::GetWSIInfo(nsCString* const out) const
|
||||
{
|
||||
out->AppendLiteral("EAGL");
|
||||
void GLContextEAGL::GetWSIInfo(nsCString* const out) const { out->AppendLiteral("EAGL"); }
|
||||
|
||||
already_AddRefed<GLContext> GLContextProviderEAGL::CreateWrappingExisting(void*, void*) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderEAGL::CreateWrappingExisting(void*, void*)
|
||||
{
|
||||
static GLContextEAGL* GetGlobalContextEAGL() {
|
||||
return static_cast<GLContextEAGL*>(GLContextProviderEAGL::GetGlobalContext());
|
||||
}
|
||||
|
||||
static already_AddRefed<GLContext> CreateEAGLContext(CreateContextFlags flags, bool aOffscreen,
|
||||
GLContextEAGL* sharedContext) {
|
||||
EAGLRenderingAPI apis[] = {kEAGLRenderingAPIOpenGLES3, kEAGLRenderingAPIOpenGLES2};
|
||||
|
||||
// Try to create a GLES3 context if we can, otherwise fall back to GLES2
|
||||
EAGLContext* context = nullptr;
|
||||
for (EAGLRenderingAPI api : apis) {
|
||||
if (sharedContext) {
|
||||
context = [[EAGLContext alloc] initWithAPI:api
|
||||
sharegroup:sharedContext->GetEAGLContext().sharegroup];
|
||||
} else {
|
||||
context = [[EAGLContext alloc] initWithAPI:api];
|
||||
}
|
||||
|
||||
if (context) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!context) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<GLContextEAGL> glContext =
|
||||
new GLContextEAGL(flags, SurfaceCaps::ForRGBA(), context, sharedContext, aOffscreen);
|
||||
if (!glContext->Init()) {
|
||||
glContext = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
static GLContextEAGL*
|
||||
GetGlobalContextEAGL()
|
||||
{
|
||||
return static_cast<GLContextEAGL*>(GLContextProviderEAGL::GetGlobalContext());
|
||||
already_AddRefed<GLContext> GLContextProviderEAGL::CreateForCompositorWidget(
|
||||
CompositorWidget* aCompositorWidget, bool aForceAccelerated) {
|
||||
return CreateForWindow(aCompositorWidget->RealWidget(),
|
||||
aCompositorWidget->GetCompositorOptions().UseWebRender(),
|
||||
aForceAccelerated);
|
||||
}
|
||||
|
||||
static already_AddRefed<GLContext>
|
||||
CreateEAGLContext(CreateContextFlags flags, bool aOffscreen, GLContextEAGL* sharedContext)
|
||||
{
|
||||
EAGLRenderingAPI apis[] = { kEAGLRenderingAPIOpenGLES3, kEAGLRenderingAPIOpenGLES2 };
|
||||
already_AddRefed<GLContext> GLContextProviderEAGL::CreateForWindow(nsIWidget* aWidget,
|
||||
bool aWebRender,
|
||||
bool aForceAccelerated) {
|
||||
RefPtr<GLContext> glContext =
|
||||
CreateEAGLContext(CreateContextFlags::NONE, false, GetGlobalContextEAGL());
|
||||
if (!glContext) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Try to create a GLES3 context if we can, otherwise fall back to GLES2
|
||||
EAGLContext* context = nullptr;
|
||||
for (EAGLRenderingAPI api : apis) {
|
||||
if (sharedContext) {
|
||||
context = [[EAGLContext alloc] initWithAPI:api
|
||||
sharegroup:sharedContext->GetEAGLContext().sharegroup];
|
||||
} else {
|
||||
context = [[EAGLContext alloc] initWithAPI:api];
|
||||
}
|
||||
if (!GLContextEAGL::Cast(glContext)->AttachToWindow(aWidget)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (context) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!context) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<GLContextEAGL> glContext = new GLContextEAGL(flags, SurfaceCaps::ForRGBA(),
|
||||
context, sharedContext,
|
||||
aOffscreen);
|
||||
if (!glContext->Init()) {
|
||||
glContext = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return glContext.forget();
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderEAGL::CreateForCompositorWidget(CompositorWidget* aCompositorWidget, bool aForceAccelerated)
|
||||
{
|
||||
return CreateForWindow(aCompositorWidget->RealWidget(),
|
||||
aCompositorWidget->GetCompositorOptions().UseWebRender(),
|
||||
aForceAccelerated);
|
||||
already_AddRefed<GLContext> GLContextProviderEAGL::CreateHeadless(CreateContextFlags flags,
|
||||
nsACString* const out_failureId) {
|
||||
return CreateEAGLContext(flags, true, GetGlobalContextEAGL());
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderEAGL::CreateForWindow(nsIWidget* aWidget,
|
||||
bool aWebRender,
|
||||
bool aForceAccelerated)
|
||||
{
|
||||
RefPtr<GLContext> glContext = CreateEAGLContext(CreateContextFlags::NONE, false,
|
||||
GetGlobalContextEAGL());
|
||||
if (!glContext) {
|
||||
return nullptr;
|
||||
}
|
||||
already_AddRefed<GLContext> GLContextProviderEAGL::CreateOffscreen(
|
||||
const mozilla::gfx::IntSize& size, const SurfaceCaps& caps, CreateContextFlags flags,
|
||||
nsACString* const out_failureId) {
|
||||
RefPtr<GLContext> glContext = CreateHeadless(flags, out_failureId);
|
||||
if (!glContext->InitOffscreen(size, caps)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!GLContextEAGL::Cast(glContext)->AttachToWindow(aWidget)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderEAGL::CreateHeadless(CreateContextFlags flags,
|
||||
nsACString* const out_failureId)
|
||||
{
|
||||
return CreateEAGLContext(flags, true, GetGlobalContextEAGL());
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderEAGL::CreateOffscreen(const mozilla::gfx::IntSize& size,
|
||||
const SurfaceCaps& caps,
|
||||
CreateContextFlags flags,
|
||||
nsACString* const out_failureId)
|
||||
{
|
||||
RefPtr<GLContext> glContext = CreateHeadless(flags, out_failureId);
|
||||
if (!glContext->InitOffscreen(size, caps)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return glContext.forget();
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
static RefPtr<GLContext> gGlobalContext;
|
||||
|
||||
GLContext*
|
||||
GLContextProviderEAGL::GetGlobalContext()
|
||||
{
|
||||
static bool triedToCreateContext = false;
|
||||
if (!triedToCreateContext) {
|
||||
triedToCreateContext = true;
|
||||
GLContext* GLContextProviderEAGL::GetGlobalContext() {
|
||||
static bool triedToCreateContext = false;
|
||||
if (!triedToCreateContext) {
|
||||
triedToCreateContext = true;
|
||||
|
||||
MOZ_RELEASE_ASSERT(!gGlobalContext, "GFX: Global GL context already initialized.");
|
||||
RefPtr<GLContext> temp = CreateHeadless(CreateContextFlags::NONE);
|
||||
gGlobalContext = temp;
|
||||
MOZ_RELEASE_ASSERT(!gGlobalContext, "GFX: Global GL context already initialized.");
|
||||
RefPtr<GLContext> temp = CreateHeadless(CreateContextFlags::NONE);
|
||||
gGlobalContext = temp;
|
||||
|
||||
if (!gGlobalContext) {
|
||||
MOZ_CRASH("Failed to create global context");
|
||||
}
|
||||
if (!gGlobalContext) {
|
||||
MOZ_CRASH("Failed to create global context");
|
||||
}
|
||||
}
|
||||
|
||||
return gGlobalContext;
|
||||
return gGlobalContext;
|
||||
}
|
||||
|
||||
void
|
||||
GLContextProviderEAGL::Shutdown()
|
||||
{
|
||||
gGlobalContext = nullptr;
|
||||
}
|
||||
void GLContextProviderEAGL::Shutdown() { gGlobalContext = nullptr; }
|
||||
|
||||
} /* namespace gl */
|
||||
} /* namespace mozilla */
|
||||
|
@ -13,60 +13,46 @@
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
PrintTargetCG::PrintTargetCG(PMPrintSession aPrintSession,
|
||||
PMPageFormat aPageFormat,
|
||||
PMPrintSettings aPrintSettings,
|
||||
const IntSize& aSize)
|
||||
: PrintTarget(/* aCairoSurface */ nullptr, aSize)
|
||||
, mPrintSession(aPrintSession)
|
||||
, mPageFormat(aPageFormat)
|
||||
, mPrintSettings(aPrintSettings)
|
||||
{
|
||||
PrintTargetCG::PrintTargetCG(PMPrintSession aPrintSession, PMPageFormat aPageFormat,
|
||||
PMPrintSettings aPrintSettings, const IntSize& aSize)
|
||||
: PrintTarget(/* aCairoSurface */ nullptr, aSize),
|
||||
mPrintSession(aPrintSession),
|
||||
mPageFormat(aPageFormat),
|
||||
mPrintSettings(aPrintSettings) {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
::PMRetain(mPrintSession);
|
||||
|
||||
// TODO: Add memory reporting like gfxQuartzSurface.
|
||||
//RecordMemoryUsed(mSize.height * 4 + sizeof(gfxQuartzSurface));
|
||||
// RecordMemoryUsed(mSize.height * 4 + sizeof(gfxQuartzSurface));
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
PrintTargetCG::~PrintTargetCG()
|
||||
{
|
||||
PrintTargetCG::~PrintTargetCG() {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
if (mPrintSession)
|
||||
::PMRelease(mPrintSession);
|
||||
if (mPrintSession) ::PMRelease(mPrintSession);
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<PrintTargetCG>
|
||||
PrintTargetCG::CreateOrNull(PMPrintSession aPrintSession,
|
||||
PMPageFormat aPageFormat,
|
||||
PMPrintSettings aPrintSettings,
|
||||
const IntSize& aSize)
|
||||
{
|
||||
/* static */ already_AddRefed<PrintTargetCG> PrintTargetCG::CreateOrNull(
|
||||
PMPrintSession aPrintSession, PMPageFormat aPageFormat, PMPrintSettings aPrintSettings,
|
||||
const IntSize& aSize) {
|
||||
if (!Factory::CheckSurfaceSize(aSize)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<PrintTargetCG> target = new PrintTargetCG(aPrintSession, aPageFormat,
|
||||
aPrintSettings, aSize);
|
||||
RefPtr<PrintTargetCG> target =
|
||||
new PrintTargetCG(aPrintSession, aPageFormat, aPrintSettings, aSize);
|
||||
|
||||
return target.forget();
|
||||
}
|
||||
|
||||
static size_t
|
||||
PutBytesNull(void* info, const void* buffer, size_t count)
|
||||
{
|
||||
return count;
|
||||
}
|
||||
static size_t PutBytesNull(void* info, const void* buffer, size_t count) { return count; }
|
||||
|
||||
already_AddRefed<DrawTarget>
|
||||
PrintTargetCG::GetReferenceDrawTarget()
|
||||
{
|
||||
already_AddRefed<DrawTarget> PrintTargetCG::GetReferenceDrawTarget() {
|
||||
if (!mRefDT) {
|
||||
const IntSize size(1, 1);
|
||||
|
||||
@ -76,8 +62,7 @@ PrintTargetCG::GetReferenceDrawTarget()
|
||||
CGDataConsumerRelease(consumer);
|
||||
|
||||
cairo_surface_t* similar =
|
||||
cairo_quartz_surface_create_for_cg_context(
|
||||
pdfContext, size.width, size.height);
|
||||
cairo_quartz_surface_create_for_cg_context(pdfContext, size.width, size.height);
|
||||
|
||||
CGContextRelease(pdfContext);
|
||||
|
||||
@ -85,8 +70,7 @@ PrintTargetCG::GetReferenceDrawTarget()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<DrawTarget> dt =
|
||||
Factory::CreateDrawTargetForCairoSurface(similar, size);
|
||||
RefPtr<DrawTarget> dt = Factory::CreateDrawTargetForCairoSurface(similar, size);
|
||||
|
||||
// The DT addrefs the surface, so we need drop our own reference to it:
|
||||
cairo_surface_destroy(similar);
|
||||
@ -100,12 +84,8 @@ PrintTargetCG::GetReferenceDrawTarget()
|
||||
return do_AddRef(mRefDT);
|
||||
}
|
||||
|
||||
nsresult
|
||||
PrintTargetCG::BeginPrinting(const nsAString& aTitle,
|
||||
const nsAString& aPrintToFileName,
|
||||
int32_t aStartPage,
|
||||
int32_t aEndPage)
|
||||
{
|
||||
nsresult PrintTargetCG::BeginPrinting(const nsAString& aTitle, const nsAString& aPrintToFileName,
|
||||
int32_t aStartPage, int32_t aEndPage) {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
OSStatus status;
|
||||
@ -121,9 +101,7 @@ PrintTargetCG::BeginPrinting(const nsAString& aTitle,
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PrintTargetCG::EndPrinting()
|
||||
{
|
||||
nsresult PrintTargetCG::EndPrinting() {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
::PMSessionEndDocumentNoDialog(mPrintSession);
|
||||
@ -132,18 +110,14 @@ PrintTargetCG::EndPrinting()
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PrintTargetCG::AbortPrinting()
|
||||
{
|
||||
nsresult PrintTargetCG::AbortPrinting() {
|
||||
#ifdef DEBUG
|
||||
mHasActivePage = false;
|
||||
#endif
|
||||
return EndPrinting();
|
||||
}
|
||||
|
||||
nsresult
|
||||
PrintTargetCG::BeginPage()
|
||||
{
|
||||
nsresult PrintTargetCG::BeginPage() {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
PMSessionError(mPrintSession);
|
||||
@ -169,8 +143,7 @@ PrintTargetCG::BeginPage()
|
||||
CGContextTranslateCTM(context, 0, height);
|
||||
CGContextScaleCTM(context, 1.0, -1.0);
|
||||
|
||||
cairo_surface_t* surface =
|
||||
cairo_quartz_surface_create_for_cg_context(context, width, height);
|
||||
cairo_surface_t* surface = cairo_quartz_surface_create_for_cg_context(context, width, height);
|
||||
|
||||
if (cairo_surface_status(surface)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -183,9 +156,7 @@ PrintTargetCG::BeginPage()
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PrintTargetCG::EndPage()
|
||||
{
|
||||
nsresult PrintTargetCG::EndPage() {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
cairo_surface_finish(mCairoSurface);
|
||||
@ -201,5 +172,5 @@ PrintTargetCG::EndPage()
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -15,31 +15,27 @@
|
||||
using namespace mozilla::hal;
|
||||
namespace mozilla {
|
||||
namespace hal_impl {
|
||||
static nsITimer* sUpdateTimer = nullptr;
|
||||
static nsITimer *sUpdateTimer = nullptr;
|
||||
static bool sActiveSensors[NUM_SENSOR_TYPE];
|
||||
static io_connect_t sDataPort = IO_OBJECT_NULL;
|
||||
static uint64_t sLastMean = -1;
|
||||
static float
|
||||
LMUvalueToLux(uint64_t aValue)
|
||||
{
|
||||
//Conversion formula from regression. See Bug 793728.
|
||||
static float LMUvalueToLux(uint64_t aValue) {
|
||||
// Conversion formula from regression. See Bug 793728.
|
||||
// -3*(10^-27)*x^4 + 2.6*(10^-19)*x^3 + -3.4*(10^-12)*x^2 + 3.9*(10^-5)*x - 0.19
|
||||
long double powerC4 = 1/pow((long double)10,27);
|
||||
long double powerC3 = 1/pow((long double)10,19);
|
||||
long double powerC2 = 1/pow((long double)10,12);
|
||||
long double powerC1 = 1/pow((long double)10,5);
|
||||
long double powerC4 = 1 / pow((long double)10, 27);
|
||||
long double powerC3 = 1 / pow((long double)10, 19);
|
||||
long double powerC2 = 1 / pow((long double)10, 12);
|
||||
long double powerC1 = 1 / pow((long double)10, 5);
|
||||
|
||||
long double term4 = -3.0 * powerC4 * pow(aValue,4);
|
||||
long double term3 = 2.6 * powerC3 * pow(aValue,3);
|
||||
long double term2 = -3.4 * powerC2 * pow(aValue,2);
|
||||
long double term1 = 3.9 * powerC1 * aValue;
|
||||
long double term4 = -3.0 * powerC4 * pow(aValue, 4);
|
||||
long double term3 = 2.6 * powerC3 * pow(aValue, 3);
|
||||
long double term2 = -3.4 * powerC2 * pow(aValue, 2);
|
||||
long double term1 = 3.9 * powerC1 * aValue;
|
||||
|
||||
float lux = ceil(static_cast<float>(term4 + term3 + term2 + term1 - 0.19));
|
||||
return lux > 0 ? lux : 0;
|
||||
}
|
||||
void
|
||||
UpdateHandler(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
void UpdateHandler(nsITimer *aTimer, void *aClosure) {
|
||||
for (int i = 0; i < NUM_SENSOR_TYPE; i++) {
|
||||
if (!sActiveSensors[i]) {
|
||||
continue;
|
||||
@ -71,15 +67,11 @@ UpdateHandler(nsITimer *aTimer, void *aClosure)
|
||||
}
|
||||
}
|
||||
|
||||
hal::SensorData sdata(sensor,
|
||||
PR_Now(),
|
||||
values);
|
||||
hal::SensorData sdata(sensor, PR_Now(), values);
|
||||
hal::NotifySensorChange(sdata);
|
||||
}
|
||||
}
|
||||
void
|
||||
EnableSensorNotifications(SensorType aSensor)
|
||||
{
|
||||
void EnableSensorNotifications(SensorType aSensor) {
|
||||
if (aSensor == SENSOR_ACCELERATION) {
|
||||
int result = smsStartup(nil, nil);
|
||||
|
||||
@ -92,8 +84,8 @@ EnableSensorNotifications(SensorType aSensor)
|
||||
}
|
||||
} else if (aSensor == SENSOR_LIGHT) {
|
||||
io_service_t serviceObject;
|
||||
serviceObject = IOServiceGetMatchingService(kIOMasterPortDefault,
|
||||
IOServiceMatching("AppleLMUController"));
|
||||
serviceObject =
|
||||
IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleLMUController"));
|
||||
if (!serviceObject) {
|
||||
return;
|
||||
}
|
||||
@ -112,17 +104,13 @@ EnableSensorNotifications(SensorType aSensor)
|
||||
if (!sUpdateTimer) {
|
||||
CallCreateInstance("@mozilla.org/timer;1", &sUpdateTimer);
|
||||
if (sUpdateTimer) {
|
||||
sUpdateTimer->InitWithNamedFuncCallback(UpdateHandler,
|
||||
nullptr,
|
||||
DEFAULT_SENSOR_POLL,
|
||||
nsITimer::TYPE_REPEATING_SLACK,
|
||||
"hal_impl::UpdateHandler");
|
||||
sUpdateTimer->InitWithNamedFuncCallback(UpdateHandler, nullptr, DEFAULT_SENSOR_POLL,
|
||||
nsITimer::TYPE_REPEATING_SLACK,
|
||||
"hal_impl::UpdateHandler");
|
||||
}
|
||||
}
|
||||
}
|
||||
void
|
||||
DisableSensorNotifications(SensorType aSensor)
|
||||
{
|
||||
void DisableSensorNotifications(SensorType aSensor) {
|
||||
if (!sActiveSensors[aSensor] || (aSensor != SENSOR_ACCELERATION && aSensor != SENSOR_LIGHT)) {
|
||||
return;
|
||||
}
|
||||
@ -145,5 +133,5 @@ DisableSensorNotifications(SensorType aSensor)
|
||||
NS_RELEASE(sUpdateTimer);
|
||||
}
|
||||
}
|
||||
} // namespace hal_impl
|
||||
} // namespace mozilla
|
||||
} // namespace hal_impl
|
||||
} // namespace mozilla
|
||||
|
1262
hal/cocoa/smslib.mm
1262
hal/cocoa/smslib.mm
File diff suppressed because it is too large
Load Diff
@ -32,27 +32,17 @@
|
||||
#include <Cocoa/Cocoa.h>
|
||||
|
||||
// nsIconChannel methods
|
||||
nsIconChannel::nsIconChannel()
|
||||
{
|
||||
}
|
||||
nsIconChannel::nsIconChannel() {}
|
||||
|
||||
nsIconChannel::~nsIconChannel()
|
||||
{
|
||||
nsIconChannel::~nsIconChannel() {
|
||||
if (mLoadInfo) {
|
||||
NS_ReleaseOnMainThreadSystemGroup(
|
||||
"nsIconChannel::mLoadInfo", mLoadInfo.forget());
|
||||
NS_ReleaseOnMainThreadSystemGroup("nsIconChannel::mLoadInfo", mLoadInfo.forget());
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsIconChannel,
|
||||
nsIChannel,
|
||||
nsIRequest,
|
||||
nsIRequestObserver,
|
||||
nsIStreamListener)
|
||||
NS_IMPL_ISUPPORTS(nsIconChannel, nsIChannel, nsIRequest, nsIRequestObserver, nsIStreamListener)
|
||||
|
||||
nsresult
|
||||
nsIconChannel::Init(nsIURI* uri)
|
||||
{
|
||||
nsresult nsIconChannel::Init(nsIURI* uri) {
|
||||
NS_ASSERTION(uri, "no uri");
|
||||
mUrl = uri;
|
||||
mOriginalURI = uri;
|
||||
@ -65,46 +55,26 @@ nsIconChannel::Init(nsIURI* uri)
|
||||
// nsIRequest methods:
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::GetName(nsACString& result)
|
||||
{
|
||||
return mUrl->GetSpec(result);
|
||||
}
|
||||
nsIconChannel::GetName(nsACString& result) { return mUrl->GetSpec(result); }
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::IsPending(bool* result)
|
||||
{
|
||||
return mPump->IsPending(result);
|
||||
}
|
||||
nsIconChannel::IsPending(bool* result) { return mPump->IsPending(result); }
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::GetStatus(nsresult* status)
|
||||
{
|
||||
return mPump->GetStatus(status);
|
||||
}
|
||||
nsIconChannel::GetStatus(nsresult* status) { return mPump->GetStatus(status); }
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::Cancel(nsresult status)
|
||||
{
|
||||
return mPump->Cancel(status);
|
||||
}
|
||||
nsIconChannel::Cancel(nsresult status) { return mPump->Cancel(status); }
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::Suspend(void)
|
||||
{
|
||||
return mPump->Suspend();
|
||||
}
|
||||
nsIconChannel::Suspend(void) { return mPump->Suspend(); }
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::Resume(void)
|
||||
{
|
||||
return mPump->Resume();
|
||||
}
|
||||
nsIconChannel::Resume(void) { return mPump->Resume(); }
|
||||
|
||||
// nsIRequestObserver methods
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::OnStartRequest(nsIRequest* aRequest,
|
||||
nsISupports* aContext)
|
||||
{
|
||||
nsIconChannel::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext) {
|
||||
if (mListener) {
|
||||
return mListener->OnStartRequest(this, aContext);
|
||||
}
|
||||
@ -112,10 +82,7 @@ nsIconChannel::OnStartRequest(nsIRequest* aRequest,
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::OnStopRequest(nsIRequest* aRequest,
|
||||
nsISupports* aContext,
|
||||
nsresult aStatus)
|
||||
{
|
||||
nsIconChannel::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext, nsresult aStatus) {
|
||||
if (mListener) {
|
||||
mListener->OnStopRequest(this, aContext, aStatus);
|
||||
mListener = nullptr;
|
||||
@ -131,12 +98,8 @@ nsIconChannel::OnStopRequest(nsIRequest* aRequest,
|
||||
|
||||
// nsIStreamListener methods
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::OnDataAvailable(nsIRequest* aRequest,
|
||||
nsISupports* aContext,
|
||||
nsIInputStream* aStream,
|
||||
uint64_t aOffset,
|
||||
uint32_t aCount)
|
||||
{
|
||||
nsIconChannel::OnDataAvailable(nsIRequest* aRequest, nsISupports* aContext, nsIInputStream* aStream,
|
||||
uint64_t aOffset, uint32_t aCount) {
|
||||
if (mListener) {
|
||||
return mListener->OnDataAvailable(this, aContext, aStream, aOffset, aCount);
|
||||
}
|
||||
@ -147,52 +110,42 @@ nsIconChannel::OnDataAvailable(nsIRequest* aRequest,
|
||||
// nsIChannel methods:
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::GetOriginalURI(nsIURI** aURI)
|
||||
{
|
||||
nsIconChannel::GetOriginalURI(nsIURI** aURI) {
|
||||
*aURI = mOriginalURI;
|
||||
NS_ADDREF(*aURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::SetOriginalURI(nsIURI* aURI)
|
||||
{
|
||||
nsIconChannel::SetOriginalURI(nsIURI* aURI) {
|
||||
NS_ENSURE_ARG_POINTER(aURI);
|
||||
mOriginalURI = aURI;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::GetURI(nsIURI** aURI)
|
||||
{
|
||||
nsIconChannel::GetURI(nsIURI** aURI) {
|
||||
*aURI = mUrl;
|
||||
NS_IF_ADDREF(*aURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::Open(nsIInputStream** _retval)
|
||||
{
|
||||
return MakeInputStream(_retval, false);
|
||||
}
|
||||
nsIconChannel::Open(nsIInputStream** _retval) { return MakeInputStream(_retval, false); }
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::Open2(nsIInputStream** aStream)
|
||||
{
|
||||
nsIconChannel::Open2(nsIInputStream** aStream) {
|
||||
nsCOMPtr<nsIStreamListener> listener;
|
||||
nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return Open(aStream);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsIconChannel::ExtractIconInfoFromUrl(nsIFile** aLocalFile,
|
||||
uint32_t* aDesiredImageSize,
|
||||
nsresult nsIconChannel::ExtractIconInfoFromUrl(nsIFile** aLocalFile, uint32_t* aDesiredImageSize,
|
||||
nsACString& aContentType,
|
||||
nsACString& aFileExtension)
|
||||
{
|
||||
nsACString& aFileExtension) {
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIMozIconURI> iconURI (do_QueryInterface(mUrl, &rv));
|
||||
nsCOMPtr<nsIMozIconURI> iconURI(do_QueryInterface(mUrl, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
iconURI->GetImageSize(aDesiredImageSize);
|
||||
@ -210,7 +163,7 @@ nsIconChannel::ExtractIconInfoFromUrl(nsIFile** aLocalFile,
|
||||
rv = fileURL->GetFile(getter_AddRefs(file));
|
||||
if (NS_FAILED(rv) || !file) return NS_OK;
|
||||
|
||||
nsCOMPtr<nsILocalFileMac> localFileMac (do_QueryInterface(file, &rv));
|
||||
nsCOMPtr<nsILocalFileMac> localFileMac(do_QueryInterface(file, &rv));
|
||||
if (NS_FAILED(rv) || !localFileMac) return NS_OK;
|
||||
|
||||
*aLocalFile = file;
|
||||
@ -220,31 +173,27 @@ nsIconChannel::ExtractIconInfoFromUrl(nsIFile** aLocalFile,
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::AsyncOpen(nsIStreamListener* aListener,
|
||||
nsISupports* ctxt)
|
||||
{
|
||||
MOZ_ASSERT(!mLoadInfo ||
|
||||
mLoadInfo->GetSecurityMode() == 0 ||
|
||||
mLoadInfo->GetInitialSecurityCheckDone() ||
|
||||
(mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL &&
|
||||
nsContentUtils::IsSystemPrincipal(mLoadInfo->LoadingPrincipal())),
|
||||
"security flags in loadInfo but asyncOpen2() not called");
|
||||
nsIconChannel::AsyncOpen(nsIStreamListener* aListener, nsISupports* ctxt) {
|
||||
MOZ_ASSERT(
|
||||
!mLoadInfo || mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->GetInitialSecurityCheckDone() ||
|
||||
(mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL &&
|
||||
nsContentUtils::IsSystemPrincipal(mLoadInfo->LoadingPrincipal())),
|
||||
"security flags in loadInfo but asyncOpen2() not called");
|
||||
|
||||
nsCOMPtr<nsIInputStream> inStream;
|
||||
nsresult rv = MakeInputStream(getter_AddRefs(inStream), true);
|
||||
if (NS_FAILED(rv)) {
|
||||
mCallbacks = nullptr;
|
||||
return rv;
|
||||
mCallbacks = nullptr;
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Init our stream pump
|
||||
nsCOMPtr<nsIEventTarget> target =
|
||||
nsContentUtils::GetEventTargetByLoadInfo(mLoadInfo,
|
||||
mozilla::TaskCategory::Other);
|
||||
nsContentUtils::GetEventTargetByLoadInfo(mLoadInfo, mozilla::TaskCategory::Other);
|
||||
rv = mPump->Init(inStream, 0, 0, false, target);
|
||||
if (NS_FAILED(rv)) {
|
||||
mCallbacks = nullptr;
|
||||
return rv;
|
||||
mCallbacks = nullptr;
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mPump->AsyncRead(this, ctxt);
|
||||
@ -256,36 +205,32 @@ nsIconChannel::AsyncOpen(nsIStreamListener* aListener,
|
||||
mLoadGroup->AddRequest(this, nullptr);
|
||||
}
|
||||
} else {
|
||||
mCallbacks = nullptr;
|
||||
mCallbacks = nullptr;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::AsyncOpen2(nsIStreamListener* aListener)
|
||||
{
|
||||
nsIconChannel::AsyncOpen2(nsIStreamListener* aListener) {
|
||||
nsCOMPtr<nsIStreamListener> listener = aListener;
|
||||
nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
|
||||
if (NS_FAILED(rv)) {
|
||||
mCallbacks = nullptr;
|
||||
return rv;
|
||||
mCallbacks = nullptr;
|
||||
return rv;
|
||||
}
|
||||
return AsyncOpen(listener, nullptr);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsIconChannel::MakeInputStream(nsIInputStream** _retval,
|
||||
bool aNonBlocking)
|
||||
{
|
||||
nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval, bool aNonBlocking) {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
nsCString contentType;
|
||||
nsAutoCString fileExt;
|
||||
nsCOMPtr<nsIFile> fileloc; // file we want an icon for
|
||||
nsCOMPtr<nsIFile> fileloc; // file we want an icon for
|
||||
uint32_t desiredImageSize;
|
||||
nsresult rv = ExtractIconInfoFromUrl(getter_AddRefs(fileloc),
|
||||
&desiredImageSize, contentType, fileExt);
|
||||
nsresult rv =
|
||||
ExtractIconInfoFromUrl(getter_AddRefs(fileloc), &desiredImageSize, contentType, fileExt);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool fileExists = false;
|
||||
@ -304,8 +249,7 @@ nsIconChannel::MakeInputStream(nsIInputStream** _retval,
|
||||
|
||||
CFURLRef macURL;
|
||||
if (NS_SUCCEEDED(localFileMac->GetCFURL(&macURL))) {
|
||||
iconImage = [[NSWorkspace sharedWorkspace]
|
||||
iconForFile:[(NSURL*)macURL path]];
|
||||
iconImage = [[NSWorkspace sharedWorkspace] iconForFile:[(NSURL*)macURL path]];
|
||||
::CFRelease(macURL);
|
||||
}
|
||||
}
|
||||
@ -318,8 +262,7 @@ nsIconChannel::MakeInputStream(nsIInputStream** _retval,
|
||||
|
||||
// If we still don't have an icon, get the generic document icon.
|
||||
if (!iconImage) {
|
||||
iconImage = [[NSWorkspace sharedWorkspace]
|
||||
iconForFileType:NSFileTypeUnknown];
|
||||
iconImage = [[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeUnknown];
|
||||
}
|
||||
|
||||
if (!iconImage) {
|
||||
@ -331,20 +274,18 @@ nsIconChannel::MakeInputStream(nsIInputStream** _retval,
|
||||
[iconImage setSize:desiredSizeRect.size];
|
||||
|
||||
[iconImage lockFocus];
|
||||
NSBitmapImageRep* bitmapRep = [[[NSBitmapImageRep alloc]
|
||||
initWithFocusedViewRect:desiredSizeRect]
|
||||
autorelease];
|
||||
NSBitmapImageRep* bitmapRep =
|
||||
[[[NSBitmapImageRep alloc] initWithFocusedViewRect:desiredSizeRect] autorelease];
|
||||
[iconImage unlockFocus];
|
||||
|
||||
// we expect the following things to be true about our bitmapRep
|
||||
NS_ENSURE_TRUE(![bitmapRep isPlanar] &&
|
||||
// Not necessarily: on a HiDPI-capable system, we'll get
|
||||
// a 2x bitmap
|
||||
// (unsigned int)[bitmapRep bytesPerPlane] ==
|
||||
// desiredImageSize * desiredImageSize * 4 &&
|
||||
[bitmapRep bitsPerPixel] == 32 &&
|
||||
[bitmapRep samplesPerPixel] == 4 &&
|
||||
[bitmapRep hasAlpha] == YES,
|
||||
// Not necessarily: on a HiDPI-capable system, we'll get
|
||||
// a 2x bitmap
|
||||
// (unsigned int)[bitmapRep bytesPerPlane] ==
|
||||
// desiredImageSize * desiredImageSize * 4 &&
|
||||
[bitmapRep bitsPerPixel] == 32 && [bitmapRep samplesPerPixel] == 4 &&
|
||||
[bitmapRep hasAlpha] == YES,
|
||||
NS_ERROR_UNEXPECTED);
|
||||
|
||||
// check what size we actually got, and ensure it isn't too big to return
|
||||
@ -352,8 +293,7 @@ nsIconChannel::MakeInputStream(nsIInputStream** _retval,
|
||||
NS_ENSURE_TRUE(actualImageSize < 256, NS_ERROR_UNEXPECTED);
|
||||
|
||||
// now we can validate the amount of data
|
||||
NS_ENSURE_TRUE((unsigned int)[bitmapRep bytesPerPlane] ==
|
||||
actualImageSize * actualImageSize * 4,
|
||||
NS_ENSURE_TRUE((unsigned int)[bitmapRep bytesPerPlane] == actualImageSize * actualImageSize * 4,
|
||||
NS_ERROR_UNEXPECTED);
|
||||
|
||||
// rgba, pre-multiplied data
|
||||
@ -361,8 +301,8 @@ nsIconChannel::MakeInputStream(nsIInputStream** _retval,
|
||||
|
||||
// create our buffer
|
||||
int32_t bufferCapacity = 2 + [bitmapRep bytesPerPlane];
|
||||
AutoTArray<uint8_t, 3 + 16 * 16 * 5> iconBuffer; // initial size is for
|
||||
// 16x16
|
||||
AutoTArray<uint8_t, 3 + 16 * 16 * 5> iconBuffer; // initial size is for
|
||||
// 16x16
|
||||
iconBuffer.SetLength(bufferCapacity);
|
||||
|
||||
uint8_t* iconBufferPtr = iconBuffer.Elements();
|
||||
@ -402,13 +342,12 @@ nsIconChannel::MakeInputStream(nsIInputStream** _retval,
|
||||
// Now, create a pipe and stuff our data into it
|
||||
nsCOMPtr<nsIInputStream> inStream;
|
||||
nsCOMPtr<nsIOutputStream> outStream;
|
||||
rv = NS_NewPipe(getter_AddRefs(inStream), getter_AddRefs(outStream),
|
||||
bufferCapacity, bufferCapacity, aNonBlocking);
|
||||
rv = NS_NewPipe(getter_AddRefs(inStream), getter_AddRefs(outStream), bufferCapacity,
|
||||
bufferCapacity, aNonBlocking);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
uint32_t written;
|
||||
rv = outStream->Write((char*)iconBuffer.Elements(), bufferCapacity,
|
||||
&written);
|
||||
rv = outStream->Write((char*)iconBuffer.Elements(), bufferCapacity, &written);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
NS_IF_ADDREF(*_retval = inStream);
|
||||
}
|
||||
@ -423,165 +362,136 @@ nsIconChannel::MakeInputStream(nsIInputStream** _retval,
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::GetLoadFlags(uint32_t* aLoadAttributes)
|
||||
{
|
||||
nsIconChannel::GetLoadFlags(uint32_t* aLoadAttributes) {
|
||||
return mPump->GetLoadFlags(aLoadAttributes);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::SetLoadFlags(uint32_t aLoadAttributes)
|
||||
{
|
||||
nsIconChannel::SetLoadFlags(uint32_t aLoadAttributes) {
|
||||
return mPump->SetLoadFlags(aLoadAttributes);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::GetIsDocument(bool *aIsDocument)
|
||||
{
|
||||
nsIconChannel::GetIsDocument(bool* aIsDocument) {
|
||||
return NS_GetIsDocumentChannel(this, aIsDocument);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::GetContentType(nsACString& aContentType)
|
||||
{
|
||||
nsIconChannel::GetContentType(nsACString& aContentType) {
|
||||
aContentType.AssignLiteral(IMAGE_ICON_MS);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::SetContentType(const nsACString& aContentType)
|
||||
{
|
||||
//It doesn't make sense to set the content-type on this type
|
||||
nsIconChannel::SetContentType(const nsACString& aContentType) {
|
||||
// It doesn't make sense to set the content-type on this type
|
||||
// of channel...
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::GetContentCharset(nsACString& aContentCharset)
|
||||
{
|
||||
nsIconChannel::GetContentCharset(nsACString& aContentCharset) {
|
||||
aContentCharset.AssignLiteral(IMAGE_ICON_MS);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::SetContentCharset(const nsACString& aContentCharset)
|
||||
{
|
||||
//It doesn't make sense to set the content-type on this type
|
||||
nsIconChannel::SetContentCharset(const nsACString& aContentCharset) {
|
||||
// It doesn't make sense to set the content-type on this type
|
||||
// of channel...
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::GetContentDisposition(uint32_t* aContentDisposition)
|
||||
{
|
||||
nsIconChannel::GetContentDisposition(uint32_t* aContentDisposition) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::SetContentDisposition(uint32_t aContentDisposition)
|
||||
{
|
||||
nsIconChannel::SetContentDisposition(uint32_t aContentDisposition) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::
|
||||
GetContentDispositionFilename(nsAString& aContentDispositionFilename)
|
||||
{
|
||||
nsIconChannel::GetContentDispositionFilename(nsAString& aContentDispositionFilename) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::
|
||||
SetContentDispositionFilename(const nsAString& aContentDispositionFilename)
|
||||
{
|
||||
nsIconChannel::SetContentDispositionFilename(const nsAString& aContentDispositionFilename) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::
|
||||
GetContentDispositionHeader(nsACString& aContentDispositionHeader)
|
||||
{
|
||||
nsIconChannel::GetContentDispositionHeader(nsACString& aContentDispositionHeader) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::GetContentLength(int64_t* aContentLength)
|
||||
{
|
||||
nsIconChannel::GetContentLength(int64_t* aContentLength) {
|
||||
*aContentLength = 0;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::SetContentLength(int64_t aContentLength)
|
||||
{
|
||||
nsIconChannel::SetContentLength(int64_t aContentLength) {
|
||||
MOZ_ASSERT_UNREACHABLE("nsIconChannel::SetContentLength");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::GetLoadGroup(nsILoadGroup** aLoadGroup)
|
||||
{
|
||||
nsIconChannel::GetLoadGroup(nsILoadGroup** aLoadGroup) {
|
||||
*aLoadGroup = mLoadGroup;
|
||||
NS_IF_ADDREF(*aLoadGroup);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
|
||||
{
|
||||
nsIconChannel::SetLoadGroup(nsILoadGroup* aLoadGroup) {
|
||||
mLoadGroup = aLoadGroup;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::GetOwner(nsISupports** aOwner)
|
||||
{
|
||||
nsIconChannel::GetOwner(nsISupports** aOwner) {
|
||||
*aOwner = mOwner.get();
|
||||
NS_IF_ADDREF(*aOwner);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::SetOwner(nsISupports* aOwner)
|
||||
{
|
||||
nsIconChannel::SetOwner(nsISupports* aOwner) {
|
||||
mOwner = aOwner;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::GetLoadInfo(nsILoadInfo** aLoadInfo)
|
||||
{
|
||||
nsIconChannel::GetLoadInfo(nsILoadInfo** aLoadInfo) {
|
||||
NS_IF_ADDREF(*aLoadInfo = mLoadInfo);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::SetLoadInfo(nsILoadInfo* aLoadInfo)
|
||||
{
|
||||
nsIconChannel::SetLoadInfo(nsILoadInfo* aLoadInfo) {
|
||||
mLoadInfo = aLoadInfo;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::
|
||||
GetNotificationCallbacks(nsIInterfaceRequestor** aNotificationCallbacks)
|
||||
{
|
||||
nsIconChannel::GetNotificationCallbacks(nsIInterfaceRequestor** aNotificationCallbacks) {
|
||||
*aNotificationCallbacks = mCallbacks.get();
|
||||
NS_IF_ADDREF(*aNotificationCallbacks);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::
|
||||
SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
|
||||
{
|
||||
nsIconChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks) {
|
||||
mCallbacks = aNotificationCallbacks;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::GetSecurityInfo(nsISupports** aSecurityInfo)
|
||||
{
|
||||
nsIconChannel::GetSecurityInfo(nsISupports** aSecurityInfo) {
|
||||
*aSecurityInfo = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -7,9 +7,7 @@
|
||||
#include "base/logging.h"
|
||||
|
||||
@interface CrApplication ()
|
||||
@property(readwrite,
|
||||
getter=isHandlingSendEvent,
|
||||
nonatomic) BOOL handlingSendEvent;
|
||||
@property(readwrite, getter=isHandlingSendEvent, nonatomic) BOOL handlingSendEvent;
|
||||
@end
|
||||
|
||||
@implementation CrApplication
|
||||
@ -21,8 +19,8 @@
|
||||
+ (NSApplication*)sharedApplication {
|
||||
NSApplication* app = [super sharedApplication];
|
||||
if (![NSApp isKindOfClass:self]) {
|
||||
CHROMIUM_LOG(ERROR) << "NSApp should be of type " << [[self className] UTF8String]
|
||||
<< ", not " << [[NSApp className] UTF8String];
|
||||
CHROMIUM_LOG(ERROR) << "NSApp should be of type " << [[self className] UTF8String] << ", not "
|
||||
<< [[NSApp className] UTF8String];
|
||||
DCHECK(false) << "NSApp is of wrong type";
|
||||
}
|
||||
return app;
|
||||
@ -61,8 +59,6 @@ ScopedSendingEvent::ScopedSendingEvent()
|
||||
[app_ setHandlingSendEvent:YES];
|
||||
}
|
||||
|
||||
ScopedSendingEvent::~ScopedSendingEvent() {
|
||||
[app_ setHandlingSendEvent:handling_];
|
||||
}
|
||||
ScopedSendingEvent::~ScopedSendingEvent() { [app_ setHandlingSendEvent:handling_]; }
|
||||
|
||||
} // namespace chrome_application_mac
|
||||
|
@ -17,19 +17,15 @@ namespace file_util {
|
||||
bool GetTempDir(FilePath* path) {
|
||||
base::ScopedNSAutoreleasePool autorelease_pool;
|
||||
NSString* tmp = NSTemporaryDirectory();
|
||||
if (tmp == nil)
|
||||
return false;
|
||||
if (tmp == nil) return false;
|
||||
*path = FilePath([tmp fileSystemRepresentation]);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetShmemTempDir(FilePath* path) {
|
||||
return GetTempDir(path);
|
||||
}
|
||||
bool GetShmemTempDir(FilePath* path) { return GetTempDir(path); }
|
||||
|
||||
bool CopyFile(const FilePath& from_path, const FilePath& to_path) {
|
||||
return (copyfile(from_path.value().c_str(),
|
||||
to_path.value().c_str(), NULL, COPYFILE_ALL) == 0);
|
||||
return (copyfile(from_path.value().c_str(), to_path.value().c_str(), NULL, COPYFILE_ALL) == 0);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -19,12 +19,10 @@ bool AmIBundled() {
|
||||
ProcessSerialNumber psn = {0, kCurrentProcess};
|
||||
|
||||
FSRef fsref;
|
||||
if (GetProcessBundleLocation(&psn, &fsref) != noErr)
|
||||
return false;
|
||||
if (GetProcessBundleLocation(&psn, &fsref) != noErr) return false;
|
||||
|
||||
FSCatalogInfo info;
|
||||
if (FSGetCatalogInfo(&fsref, kFSCatInfoNodeFlags, &info,
|
||||
NULL, NULL, NULL) != noErr) {
|
||||
if (FSGetCatalogInfo(&fsref, kFSCatInfoNodeFlags, &info, NULL, NULL, NULL) != noErr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -17,11 +17,9 @@
|
||||
|
||||
namespace {
|
||||
|
||||
void NoOp(void* info) {
|
||||
}
|
||||
void NoOp(void* info) {}
|
||||
|
||||
const CFTimeInterval kCFTimeIntervalMax =
|
||||
std::numeric_limits<CFTimeInterval>::max();
|
||||
const CFTimeInterval kCFTimeIntervalMax = std::numeric_limits<CFTimeInterval>::max();
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -32,12 +30,9 @@ namespace base {
|
||||
// case where an autorelease pool needs to be passed in.
|
||||
class MessagePumpScopedAutoreleasePool {
|
||||
public:
|
||||
explicit MessagePumpScopedAutoreleasePool(MessagePumpCFRunLoopBase* pump) :
|
||||
pool_(pump->CreateAutoreleasePool()) {
|
||||
}
|
||||
~MessagePumpScopedAutoreleasePool() {
|
||||
[pool_ drain];
|
||||
}
|
||||
explicit MessagePumpScopedAutoreleasePool(MessagePumpCFRunLoopBase* pump)
|
||||
: pool_(pump->CreateAutoreleasePool()) {}
|
||||
~MessagePumpScopedAutoreleasePool() { [pool_ drain]; }
|
||||
|
||||
private:
|
||||
NSAutoreleasePool* pool_;
|
||||
@ -67,8 +62,7 @@ MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase()
|
||||
kCFTimeIntervalMax, // interval
|
||||
0, // flags
|
||||
0, // priority
|
||||
RunDelayedWorkTimer,
|
||||
&timer_context);
|
||||
RunDelayedWorkTimer, &timer_context);
|
||||
CFRunLoopAddTimer(run_loop_, delayed_work_timer_, kCFRunLoopCommonModes);
|
||||
|
||||
CFRunLoopSourceContext source_context = CFRunLoopSourceContext();
|
||||
@ -95,8 +89,7 @@ MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase()
|
||||
nesting_deferred_work_source_ = CFRunLoopSourceCreate(NULL, // allocator
|
||||
0, // priority
|
||||
&source_context);
|
||||
CFRunLoopAddSource(run_loop_, nesting_deferred_work_source_,
|
||||
kCFRunLoopCommonModes);
|
||||
CFRunLoopAddSource(run_loop_, nesting_deferred_work_source_, kCFRunLoopCommonModes);
|
||||
|
||||
CFRunLoopObserverContext observer_context = CFRunLoopObserverContext();
|
||||
observer_context.info = this;
|
||||
@ -104,36 +97,28 @@ MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase()
|
||||
kCFRunLoopBeforeWaiting,
|
||||
true, // repeat
|
||||
0, // priority
|
||||
PreWaitObserver,
|
||||
&observer_context);
|
||||
PreWaitObserver, &observer_context);
|
||||
CFRunLoopAddObserver(run_loop_, pre_wait_observer_, kCFRunLoopCommonModes);
|
||||
|
||||
pre_source_observer_ = CFRunLoopObserverCreate(NULL, // allocator
|
||||
kCFRunLoopBeforeSources,
|
||||
true, // repeat
|
||||
0, // priority
|
||||
PreSourceObserver,
|
||||
&observer_context);
|
||||
PreSourceObserver, &observer_context);
|
||||
CFRunLoopAddObserver(run_loop_, pre_source_observer_, kCFRunLoopCommonModes);
|
||||
|
||||
enter_exit_observer_ = CFRunLoopObserverCreate(NULL, // allocator
|
||||
kCFRunLoopEntry |
|
||||
kCFRunLoopExit,
|
||||
kCFRunLoopEntry | kCFRunLoopExit,
|
||||
true, // repeat
|
||||
0, // priority
|
||||
EnterExitObserver,
|
||||
&observer_context);
|
||||
EnterExitObserver, &observer_context);
|
||||
CFRunLoopAddObserver(run_loop_, enter_exit_observer_, kCFRunLoopCommonModes);
|
||||
|
||||
root_power_domain_ = IORegisterForSystemPower(this,
|
||||
&power_notification_port_,
|
||||
PowerStateNotification,
|
||||
&power_notification_object_);
|
||||
root_power_domain_ = IORegisterForSystemPower(
|
||||
this, &power_notification_port_, PowerStateNotification, &power_notification_object_);
|
||||
if (root_power_domain_ != MACH_PORT_NULL) {
|
||||
CFRunLoopAddSource(
|
||||
run_loop_,
|
||||
IONotificationPortGetRunLoopSource(power_notification_port_),
|
||||
kCFRunLoopCommonModes);
|
||||
CFRunLoopAddSource(run_loop_, IONotificationPortGetRunLoopSource(power_notification_port_),
|
||||
kCFRunLoopCommonModes);
|
||||
}
|
||||
}
|
||||
|
||||
@ -142,29 +127,23 @@ MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase()
|
||||
// same number of run loops must be running when this object is destroyed.
|
||||
MessagePumpCFRunLoopBase::~MessagePumpCFRunLoopBase() {
|
||||
if (root_power_domain_ != MACH_PORT_NULL) {
|
||||
CFRunLoopRemoveSource(
|
||||
run_loop_,
|
||||
IONotificationPortGetRunLoopSource(power_notification_port_),
|
||||
kCFRunLoopCommonModes);
|
||||
CFRunLoopRemoveSource(run_loop_, IONotificationPortGetRunLoopSource(power_notification_port_),
|
||||
kCFRunLoopCommonModes);
|
||||
IODeregisterForSystemPower(&power_notification_object_);
|
||||
IOServiceClose(root_power_domain_);
|
||||
IONotificationPortDestroy(power_notification_port_);
|
||||
}
|
||||
|
||||
CFRunLoopRemoveObserver(run_loop_, enter_exit_observer_,
|
||||
kCFRunLoopCommonModes);
|
||||
CFRunLoopRemoveObserver(run_loop_, enter_exit_observer_, kCFRunLoopCommonModes);
|
||||
CFRelease(enter_exit_observer_);
|
||||
|
||||
CFRunLoopRemoveObserver(run_loop_, pre_source_observer_,
|
||||
kCFRunLoopCommonModes);
|
||||
CFRunLoopRemoveObserver(run_loop_, pre_source_observer_, kCFRunLoopCommonModes);
|
||||
CFRelease(pre_source_observer_);
|
||||
|
||||
CFRunLoopRemoveObserver(run_loop_, pre_wait_observer_,
|
||||
kCFRunLoopCommonModes);
|
||||
CFRunLoopRemoveObserver(run_loop_, pre_wait_observer_, kCFRunLoopCommonModes);
|
||||
CFRelease(pre_wait_observer_);
|
||||
|
||||
CFRunLoopRemoveSource(run_loop_, nesting_deferred_work_source_,
|
||||
kCFRunLoopCommonModes);
|
||||
CFRunLoopRemoveSource(run_loop_, nesting_deferred_work_source_, kCFRunLoopCommonModes);
|
||||
CFRelease(nesting_deferred_work_source_);
|
||||
|
||||
CFRunLoopRemoveSource(run_loop_, idle_work_source_, kCFRunLoopCommonModes);
|
||||
@ -224,8 +203,7 @@ void MessagePumpCFRunLoopBase::ScheduleWork() {
|
||||
}
|
||||
|
||||
// Must be called on the run loop thread.
|
||||
void MessagePumpCFRunLoopBase::ScheduleDelayedWork(
|
||||
const TimeTicks& delayed_work_time) {
|
||||
void MessagePumpCFRunLoopBase::ScheduleDelayedWork(const TimeTicks& delayed_work_time) {
|
||||
TimeDelta delta = delayed_work_time - TimeTicks::Now();
|
||||
delayed_work_fire_time_ = CFAbsoluteTimeGetCurrent() + delta.InSecondsF();
|
||||
CFRunLoopTimerSetNextFireDate(delayed_work_timer_, delayed_work_fire_time_);
|
||||
@ -233,8 +211,7 @@ void MessagePumpCFRunLoopBase::ScheduleDelayedWork(
|
||||
|
||||
// Called from the run loop.
|
||||
// static
|
||||
void MessagePumpCFRunLoopBase::RunDelayedWorkTimer(CFRunLoopTimerRef timer,
|
||||
void* info) {
|
||||
void MessagePumpCFRunLoopBase::RunDelayedWorkTimer(CFRunLoopTimerRef timer, void* info) {
|
||||
MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info);
|
||||
|
||||
// The timer won't fire again until it's reset.
|
||||
@ -415,8 +392,7 @@ void MessagePumpCFRunLoopBase::MaybeScheduleNestingDeferredWork() {
|
||||
// Called from the run loop.
|
||||
// static
|
||||
void MessagePumpCFRunLoopBase::PreWaitObserver(CFRunLoopObserverRef observer,
|
||||
CFRunLoopActivity activity,
|
||||
void* info) {
|
||||
CFRunLoopActivity activity, void* info) {
|
||||
MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info);
|
||||
|
||||
// Attempt to do some idle work before going to sleep.
|
||||
@ -432,8 +408,7 @@ void MessagePumpCFRunLoopBase::PreWaitObserver(CFRunLoopObserverRef observer,
|
||||
// Called from the run loop.
|
||||
// static
|
||||
void MessagePumpCFRunLoopBase::PreSourceObserver(CFRunLoopObserverRef observer,
|
||||
CFRunLoopActivity activity,
|
||||
void* info) {
|
||||
CFRunLoopActivity activity, void* info) {
|
||||
MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info);
|
||||
|
||||
// The run loop has reached the top of the loop and is about to begin
|
||||
@ -447,8 +422,7 @@ void MessagePumpCFRunLoopBase::PreSourceObserver(CFRunLoopObserverRef observer,
|
||||
// Called from the run loop.
|
||||
// static
|
||||
void MessagePumpCFRunLoopBase::EnterExitObserver(CFRunLoopObserverRef observer,
|
||||
CFRunLoopActivity activity,
|
||||
void* info) {
|
||||
CFRunLoopActivity activity, void* info) {
|
||||
MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info);
|
||||
|
||||
switch (activity) {
|
||||
@ -489,8 +463,7 @@ void MessagePumpCFRunLoopBase::EnterExitObserver(CFRunLoopObserverRef observer,
|
||||
|
||||
// Called from the run loop.
|
||||
// static
|
||||
void MessagePumpCFRunLoopBase::PowerStateNotification(void* info,
|
||||
io_service_t service,
|
||||
void MessagePumpCFRunLoopBase::PowerStateNotification(void* info, io_service_t service,
|
||||
uint32_t message_type,
|
||||
void* message_argument) {
|
||||
// CFRunLoopTimer (NSTimer) is scheduled in terms of CFAbsoluteTime, which
|
||||
@ -535,8 +508,7 @@ void MessagePumpCFRunLoopBase::PowerStateNotification(void* info,
|
||||
switch (message_type) {
|
||||
case kIOMessageSystemWillPowerOn:
|
||||
if (self->delayed_work_fire_time_ != kCFTimeIntervalMax) {
|
||||
CFRunLoopTimerSetNextFireDate(self->delayed_work_timer_,
|
||||
self->delayed_work_fire_time_);
|
||||
CFRunLoopTimerSetNextFireDate(self->delayed_work_timer_, self->delayed_work_fire_time_);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -545,8 +517,7 @@ void MessagePumpCFRunLoopBase::PowerStateNotification(void* info,
|
||||
// The system will wait for 30 seconds before entering sleep if neither
|
||||
// IOAllowPowerChange nor IOCancelPowerChange are called. That would be
|
||||
// pretty antisocial.
|
||||
IOAllowPowerChange(self->root_power_domain_,
|
||||
reinterpret_cast<long>(message_argument));
|
||||
IOAllowPowerChange(self->root_power_domain_, reinterpret_cast<long>(message_argument));
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -556,17 +527,14 @@ void MessagePumpCFRunLoopBase::PowerStateNotification(void* info,
|
||||
|
||||
// Called by MessagePumpCFRunLoopBase::EnterExitRunLoop. The default
|
||||
// implementation is a no-op.
|
||||
void MessagePumpCFRunLoopBase::EnterExitRunLoop(CFRunLoopActivity activity) {
|
||||
}
|
||||
void MessagePumpCFRunLoopBase::EnterExitRunLoop(CFRunLoopActivity activity) {}
|
||||
|
||||
// Base version returns a standard NSAutoreleasePool.
|
||||
NSAutoreleasePool* MessagePumpCFRunLoopBase::CreateAutoreleasePool() {
|
||||
return [[NSAutoreleasePool alloc] init];
|
||||
}
|
||||
|
||||
MessagePumpCFRunLoop::MessagePumpCFRunLoop()
|
||||
: quit_pending_(false) {
|
||||
}
|
||||
MessagePumpCFRunLoop::MessagePumpCFRunLoop() : quit_pending_(false) {}
|
||||
|
||||
// Called by MessagePumpCFRunLoopBase::DoRun. If other CFRunLoopRun loops were
|
||||
// running lower on the run loop thread's stack when this object was created,
|
||||
@ -578,9 +546,7 @@ void MessagePumpCFRunLoop::DoRun(Delegate* delegate) {
|
||||
int result;
|
||||
do {
|
||||
MessagePumpScopedAutoreleasePool autorelease_pool(this);
|
||||
result = CFRunLoopRunInMode(kCFRunLoopDefaultMode,
|
||||
kCFTimeIntervalMax,
|
||||
false);
|
||||
result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, kCFTimeIntervalMax, false);
|
||||
} while (result != kCFRunLoopRunStopped && result != kCFRunLoopRunFinished);
|
||||
}
|
||||
|
||||
@ -602,9 +568,7 @@ void MessagePumpCFRunLoop::Quit() {
|
||||
|
||||
// Called by MessagePumpCFRunLoopBase::EnterExitObserver.
|
||||
void MessagePumpCFRunLoop::EnterExitRunLoop(CFRunLoopActivity activity) {
|
||||
if (activity == kCFRunLoopExit &&
|
||||
nesting_level() == run_nesting_level() &&
|
||||
quit_pending_) {
|
||||
if (activity == kCFRunLoopExit && nesting_level() == run_nesting_level() && quit_pending_) {
|
||||
// Quit was called while loops other than those managed by this object
|
||||
// were running further inside a run loop managed by this object. Now
|
||||
// that all unmanaged inner run loops are gone, stop the loop running
|
||||
@ -614,8 +578,7 @@ void MessagePumpCFRunLoop::EnterExitRunLoop(CFRunLoopActivity activity) {
|
||||
}
|
||||
}
|
||||
|
||||
MessagePumpNSRunLoop::MessagePumpNSRunLoop()
|
||||
: keep_running_(true) {
|
||||
MessagePumpNSRunLoop::MessagePumpNSRunLoop() : keep_running_(true) {
|
||||
CFRunLoopSourceContext source_context = CFRunLoopSourceContext();
|
||||
source_context.perform = NoOp;
|
||||
quit_source_ = CFRunLoopSourceCreate(NULL, // allocator
|
||||
@ -632,8 +595,7 @@ MessagePumpNSRunLoop::~MessagePumpNSRunLoop() {
|
||||
void MessagePumpNSRunLoop::DoRun(Delegate* delegate) {
|
||||
while (keep_running_) {
|
||||
// NSRunLoop manages autorelease pools itself.
|
||||
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
|
||||
beforeDate:[NSDate distantFuture]];
|
||||
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
|
||||
}
|
||||
|
||||
keep_running_ = true;
|
||||
@ -646,9 +608,7 @@ void MessagePumpNSRunLoop::Quit() {
|
||||
}
|
||||
|
||||
MessagePumpNSApplication::MessagePumpNSApplication()
|
||||
: keep_running_(true),
|
||||
running_own_loop_(false) {
|
||||
}
|
||||
: keep_running_(true), running_own_loop_(false) {}
|
||||
|
||||
void MessagePumpNSApplication::DoRun(Delegate* delegate) {
|
||||
bool last_running_own_loop_ = running_own_loop_;
|
||||
|
@ -42,9 +42,7 @@ void InitThreading() {
|
||||
|
||||
static BOOL multithreaded = [NSThread isMultiThreaded];
|
||||
if (!multithreaded) {
|
||||
[NSThread detachNewThreadSelector:@selector(noOp)
|
||||
toTarget:[NoOp class]
|
||||
withObject:nil];
|
||||
[NSThread detachNewThreadSelector:@selector(noOp) toTarget:[NoOp class] withObject:nil];
|
||||
multithreaded = YES;
|
||||
|
||||
DCHECK([NSThread isMultiThreaded]);
|
||||
@ -60,8 +58,7 @@ void PlatformThread::SetName(const char* name) {
|
||||
int (*dynamic_pthread_setname_np)(const char*);
|
||||
*reinterpret_cast<void**>(&dynamic_pthread_setname_np) =
|
||||
dlsym(RTLD_DEFAULT, "pthread_setname_np");
|
||||
if (!dynamic_pthread_setname_np)
|
||||
return;
|
||||
if (!dynamic_pthread_setname_np) return;
|
||||
|
||||
// Mac OS X does not expose the length limit of the name, so
|
||||
// hardcode it.
|
||||
@ -74,4 +71,3 @@ void PlatformThread::SetName(const char* name) {
|
||||
// Checked against the bionic implementation in bionic/libc/bionic/pthread.c
|
||||
dynamic_pthread_setname_np(shortened_name.c_str());
|
||||
}
|
||||
|
||||
|
@ -25,10 +25,8 @@ static mozilla::EnvironmentLog gProcessLog("MOZ_PROCESS_LOG");
|
||||
|
||||
namespace base {
|
||||
|
||||
bool LaunchApp(const std::vector<std::string>& argv,
|
||||
const LaunchOptions& options,
|
||||
ProcessHandle* process_handle)
|
||||
{
|
||||
bool LaunchApp(const std::vector<std::string>& argv, const LaunchOptions& options,
|
||||
ProcessHandle* process_handle) {
|
||||
bool retval = true;
|
||||
|
||||
char* argv_copy[argv.size() + 1];
|
||||
@ -43,9 +41,8 @@ bool LaunchApp(const std::vector<std::string>& argv,
|
||||
if (posix_spawn_file_actions_init(&file_actions) != 0) {
|
||||
return false;
|
||||
}
|
||||
auto file_actions_guard = mozilla::MakeScopeExit([&file_actions] {
|
||||
posix_spawn_file_actions_destroy(&file_actions);
|
||||
});
|
||||
auto file_actions_guard =
|
||||
mozilla::MakeScopeExit([&file_actions] { posix_spawn_file_actions_destroy(&file_actions); });
|
||||
|
||||
// Turn fds_to_remap array into a set of dup2 calls.
|
||||
mozilla::ipc::FileDescriptorShuffle shuffle;
|
||||
@ -66,9 +63,8 @@ bool LaunchApp(const std::vector<std::string>& argv,
|
||||
if (posix_spawnattr_init(&spawnattr) != 0) {
|
||||
return false;
|
||||
}
|
||||
auto spawnattr_guard = mozilla::MakeScopeExit([&spawnattr] {
|
||||
posix_spawnattr_destroy(&spawnattr);
|
||||
});
|
||||
auto spawnattr_guard =
|
||||
mozilla::MakeScopeExit([&spawnattr] { posix_spawnattr_destroy(&spawnattr); });
|
||||
|
||||
// Prevent the child process from inheriting any file descriptors
|
||||
// that aren't named in `file_actions`. (This is an Apple-specific
|
||||
@ -85,32 +81,23 @@ bool LaunchApp(const std::vector<std::string>& argv,
|
||||
}
|
||||
|
||||
int pid = 0;
|
||||
int spawn_succeeded = (posix_spawnp(&pid,
|
||||
argv_copy[0],
|
||||
&file_actions,
|
||||
&spawnattr,
|
||||
argv_copy,
|
||||
vars.get()) == 0);
|
||||
int spawn_succeeded =
|
||||
(posix_spawnp(&pid, argv_copy[0], &file_actions, &spawnattr, argv_copy, vars.get()) == 0);
|
||||
|
||||
bool process_handle_valid = pid > 0;
|
||||
if (!spawn_succeeded || !process_handle_valid) {
|
||||
retval = false;
|
||||
} else {
|
||||
gProcessLog.print("==> process %d launched child process %d\n",
|
||||
GetCurrentProcId(), pid);
|
||||
if (options.wait)
|
||||
HANDLE_EINTR(waitpid(pid, 0, 0));
|
||||
gProcessLog.print("==> process %d launched child process %d\n", GetCurrentProcId(), pid);
|
||||
if (options.wait) HANDLE_EINTR(waitpid(pid, 0, 0));
|
||||
|
||||
if (process_handle)
|
||||
*process_handle = pid;
|
||||
if (process_handle) *process_handle = pid;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool LaunchApp(const CommandLine& cl,
|
||||
const LaunchOptions& options,
|
||||
ProcessHandle* process_handle) {
|
||||
bool LaunchApp(const CommandLine& cl, const LaunchOptions& options, ProcessHandle* process_handle) {
|
||||
return LaunchApp(cl.argv(), options, process_handle);
|
||||
}
|
||||
|
||||
|
@ -15,9 +15,7 @@ ScopedNSAutoreleasePool::ScopedNSAutoreleasePool()
|
||||
DCHECK(autorelease_pool_);
|
||||
}
|
||||
|
||||
ScopedNSAutoreleasePool::~ScopedNSAutoreleasePool() {
|
||||
[autorelease_pool_ drain];
|
||||
}
|
||||
ScopedNSAutoreleasePool::~ScopedNSAutoreleasePool() { [autorelease_pool_ drain]; }
|
||||
|
||||
// Cycle the internal pool, allowing everything there to get cleaned up and
|
||||
// start anew.
|
||||
|
@ -19,25 +19,21 @@ namespace {
|
||||
// an STL string of the template type. Returns an empty string on failure.
|
||||
//
|
||||
// Do not assert in this function since it is used by the asssertion code!
|
||||
template<typename StringType>
|
||||
template <typename StringType>
|
||||
static StringType CFStringToSTLStringWithEncodingT(CFStringRef cfstring,
|
||||
CFStringEncoding encoding) {
|
||||
CFIndex length = CFStringGetLength(cfstring);
|
||||
if (length == 0)
|
||||
return StringType();
|
||||
if (length == 0) return StringType();
|
||||
|
||||
CFRange whole_string = CFRangeMake(0, length);
|
||||
CFIndex out_size;
|
||||
CFIndex converted = CFStringGetBytes(cfstring,
|
||||
whole_string,
|
||||
encoding,
|
||||
CFIndex converted = CFStringGetBytes(cfstring, whole_string, encoding,
|
||||
0, // lossByte
|
||||
false, // isExternalRepresentation
|
||||
NULL, // buffer
|
||||
0, // maxBufLen
|
||||
&out_size);
|
||||
if (converted == 0 || out_size == 0)
|
||||
return StringType();
|
||||
if (converted == 0 || out_size == 0) return StringType();
|
||||
|
||||
// out_size is the number of UInt8-sized units needed in the destination.
|
||||
// A buffer allocated as UInt8 units might not be properly aligned to
|
||||
@ -48,16 +44,12 @@ static StringType CFStringToSTLStringWithEncodingT(CFStringRef cfstring,
|
||||
out_size * sizeof(UInt8) / sizeof(typename StringType::value_type) + 1;
|
||||
|
||||
std::vector<typename StringType::value_type> out_buffer(elements);
|
||||
converted = CFStringGetBytes(cfstring,
|
||||
whole_string,
|
||||
encoding,
|
||||
converted = CFStringGetBytes(cfstring, whole_string, encoding,
|
||||
0, // lossByte
|
||||
false, // isExternalRepresentation
|
||||
reinterpret_cast<UInt8*>(&out_buffer[0]),
|
||||
out_size,
|
||||
reinterpret_cast<UInt8*>(&out_buffer[0]), out_size,
|
||||
NULL); // usedBufLen
|
||||
if (converted == 0)
|
||||
return StringType();
|
||||
if (converted == 0) return StringType();
|
||||
|
||||
out_buffer[elements - 1] = '\0';
|
||||
return StringType(&out_buffer[0], elements - 1);
|
||||
@ -68,45 +60,31 @@ static StringType CFStringToSTLStringWithEncodingT(CFStringRef cfstring,
|
||||
// |OutStringType| template type. Returns an empty string on failure.
|
||||
//
|
||||
// Do not assert in this function since it is used by the asssertion code!
|
||||
template<typename InStringType, typename OutStringType>
|
||||
static OutStringType STLStringToSTLStringWithEncodingsT(
|
||||
const InStringType& in,
|
||||
CFStringEncoding in_encoding,
|
||||
CFStringEncoding out_encoding) {
|
||||
template <typename InStringType, typename OutStringType>
|
||||
static OutStringType STLStringToSTLStringWithEncodingsT(const InStringType& in,
|
||||
CFStringEncoding in_encoding,
|
||||
CFStringEncoding out_encoding) {
|
||||
typename InStringType::size_type in_length = in.length();
|
||||
if (in_length == 0)
|
||||
return OutStringType();
|
||||
if (in_length == 0) return OutStringType();
|
||||
|
||||
scoped_cftyperef<CFStringRef> cfstring(
|
||||
CFStringCreateWithBytesNoCopy(NULL,
|
||||
reinterpret_cast<const UInt8*>(in.data()),
|
||||
in_length *
|
||||
sizeof(typename InStringType::value_type),
|
||||
in_encoding,
|
||||
false,
|
||||
kCFAllocatorNull));
|
||||
if (!cfstring)
|
||||
return OutStringType();
|
||||
scoped_cftyperef<CFStringRef> cfstring(CFStringCreateWithBytesNoCopy(
|
||||
NULL, reinterpret_cast<const UInt8*>(in.data()),
|
||||
in_length * sizeof(typename InStringType::value_type), in_encoding, false, kCFAllocatorNull));
|
||||
if (!cfstring) return OutStringType();
|
||||
|
||||
return CFStringToSTLStringWithEncodingT<OutStringType>(cfstring,
|
||||
out_encoding);
|
||||
return CFStringToSTLStringWithEncodingT<OutStringType>(cfstring, out_encoding);
|
||||
}
|
||||
|
||||
// Given an STL string |in| with an encoding specified by |in_encoding|,
|
||||
// return it as a CFStringRef. Returns NULL on failure.
|
||||
template<typename StringType>
|
||||
static CFStringRef STLStringToCFStringWithEncodingsT(
|
||||
const StringType& in,
|
||||
CFStringEncoding in_encoding) {
|
||||
template <typename StringType>
|
||||
static CFStringRef STLStringToCFStringWithEncodingsT(const StringType& in,
|
||||
CFStringEncoding in_encoding) {
|
||||
typename StringType::size_type in_length = in.length();
|
||||
if (in_length == 0)
|
||||
return CFSTR("");
|
||||
if (in_length == 0) return CFSTR("");
|
||||
|
||||
return CFStringCreateWithBytes(kCFAllocatorDefault,
|
||||
reinterpret_cast<const UInt8*>(in.data()),
|
||||
in_length *
|
||||
sizeof(typename StringType::value_type),
|
||||
in_encoding,
|
||||
return CFStringCreateWithBytes(kCFAllocatorDefault, reinterpret_cast<const UInt8*>(in.data()),
|
||||
in_length * sizeof(typename StringType::value_type), in_encoding,
|
||||
false);
|
||||
}
|
||||
|
||||
@ -124,22 +102,18 @@ static const CFStringEncoding kWideStringEncoding = kCFStringEncodingUTF32LE;
|
||||
|
||||
// Do not assert in this function since it is used by the asssertion code!
|
||||
std::string SysWideToUTF8(const std::wstring& wide) {
|
||||
return STLStringToSTLStringWithEncodingsT<std::wstring, std::string>(
|
||||
wide, kWideStringEncoding, kNarrowStringEncoding);
|
||||
return STLStringToSTLStringWithEncodingsT<std::wstring, std::string>(wide, kWideStringEncoding,
|
||||
kNarrowStringEncoding);
|
||||
}
|
||||
|
||||
// Do not assert in this function since it is used by the asssertion code!
|
||||
std::wstring SysUTF8ToWide(const StringPiece& utf8) {
|
||||
return STLStringToSTLStringWithEncodingsT<StringPiece, std::wstring>(
|
||||
utf8, kNarrowStringEncoding, kWideStringEncoding);
|
||||
return STLStringToSTLStringWithEncodingsT<StringPiece, std::wstring>(utf8, kNarrowStringEncoding,
|
||||
kWideStringEncoding);
|
||||
}
|
||||
|
||||
std::string SysWideToNativeMB(const std::wstring& wide) {
|
||||
return SysWideToUTF8(wide);
|
||||
}
|
||||
std::string SysWideToNativeMB(const std::wstring& wide) { return SysWideToUTF8(wide); }
|
||||
|
||||
std::wstring SysNativeMBToWide(const StringPiece& native_mb) {
|
||||
return SysUTF8ToWide(native_mb);
|
||||
}
|
||||
std::wstring SysNativeMBToWide(const StringPiece& native_mb) { return SysUTF8ToWide(native_mb); }
|
||||
|
||||
} // namespace base
|
||||
|
@ -10,12 +10,9 @@
|
||||
#include "base/logging.h"
|
||||
|
||||
//==============================================================================
|
||||
MachSendMessage::MachSendMessage(int32_t message_id) : MachMessage() {
|
||||
Initialize(message_id);
|
||||
}
|
||||
MachSendMessage::MachSendMessage(int32_t message_id) : MachMessage() { Initialize(message_id); }
|
||||
|
||||
MachSendMessage::MachSendMessage(void *storage, size_t storage_length,
|
||||
int32_t message_id)
|
||||
MachSendMessage::MachSendMessage(void *storage, size_t storage_length, int32_t message_id)
|
||||
: MachMessage(storage, storage_length) {
|
||||
Initialize(message_id);
|
||||
}
|
||||
@ -31,7 +28,7 @@ void MachSendMessage::Initialize(int32_t message_id) {
|
||||
SetDescriptorCount(0); // start out with no descriptors
|
||||
|
||||
SetMessageID(message_id);
|
||||
SetData(NULL, 0); // client may add data later
|
||||
SetData(NULL, 0); // client may add data later
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
@ -44,7 +41,7 @@ MachMessage::MachMessage()
|
||||
|
||||
//==============================================================================
|
||||
MachMessage::MachMessage(void *storage, size_t storage_length)
|
||||
: storage_(static_cast<MachMessageData*>(storage)),
|
||||
: storage_(static_cast<MachMessageData *>(storage)),
|
||||
storage_length_bytes_(storage_length),
|
||||
own_storage_(false) {
|
||||
DCHECK(storage);
|
||||
@ -59,25 +56,18 @@ MachMessage::~MachMessage() {
|
||||
}
|
||||
}
|
||||
|
||||
u_int32_t MachMessage::GetDataLength() { return EndianU32_LtoN(GetDataPacket()->data_length); }
|
||||
|
||||
u_int32_t MachMessage::GetDataLength() {
|
||||
return EndianU32_LtoN(GetDataPacket()->data_length);
|
||||
}
|
||||
|
||||
// The message ID may be used as a code identifying the type of message
|
||||
// The message ID may be used as a code identifying the type of message
|
||||
void MachMessage::SetMessageID(int32_t message_id) {
|
||||
GetDataPacket()->id = EndianU32_NtoL(message_id);
|
||||
}
|
||||
|
||||
int32_t MachMessage::GetMessageID() {
|
||||
return EndianU32_LtoN(GetDataPacket()->id);
|
||||
}
|
||||
|
||||
int32_t MachMessage::GetMessageID() { return EndianU32_LtoN(GetDataPacket()->id); }
|
||||
|
||||
//==============================================================================
|
||||
// returns true if successful
|
||||
bool MachMessage::SetData(const void* data,
|
||||
int32_t data_length) {
|
||||
bool MachMessage::SetData(const void *data, int32_t data_length) {
|
||||
// Enforce the fact that it's only safe to call this method once on a
|
||||
// message.
|
||||
DCHECK(GetDataPacket()->data_length == 0);
|
||||
@ -108,7 +98,7 @@ int MachMessage::CalculateSize() {
|
||||
|
||||
// add space for MessageDataPacket
|
||||
int32_t alignedDataLength = (GetDataLength() + 3) & ~0x3;
|
||||
size += 2*sizeof(int32_t) + alignedDataLength;
|
||||
size += 2 * sizeof(int32_t) + alignedDataLength;
|
||||
|
||||
// add space for descriptors
|
||||
size += GetDescriptorCount() * sizeof(MachMsgPortDescriptor);
|
||||
@ -120,18 +110,15 @@ int MachMessage::CalculateSize() {
|
||||
|
||||
//==============================================================================
|
||||
MachMessage::MessageDataPacket *MachMessage::GetDataPacket() {
|
||||
int desc_size = sizeof(MachMsgPortDescriptor)*GetDescriptorCount();
|
||||
MessageDataPacket *packet =
|
||||
reinterpret_cast<MessageDataPacket*>(storage_->padding + desc_size);
|
||||
int desc_size = sizeof(MachMsgPortDescriptor) * GetDescriptorCount();
|
||||
MessageDataPacket *packet = reinterpret_cast<MessageDataPacket *>(storage_->padding + desc_size);
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void MachMessage::SetDescriptor(int n,
|
||||
const MachMsgPortDescriptor &desc) {
|
||||
MachMsgPortDescriptor *desc_array =
|
||||
reinterpret_cast<MachMsgPortDescriptor*>(storage_->padding);
|
||||
void MachMessage::SetDescriptor(int n, const MachMsgPortDescriptor &desc) {
|
||||
MachMsgPortDescriptor *desc_array = reinterpret_cast<MachMsgPortDescriptor *>(storage_->padding);
|
||||
desc_array[n] = desc;
|
||||
}
|
||||
|
||||
@ -148,8 +135,8 @@ bool MachMessage::AddDescriptor(const MachMsgPortDescriptor &desc) {
|
||||
|
||||
// unfortunately, we need to move the data to allow space for the
|
||||
// new descriptor
|
||||
u_int8_t *p = reinterpret_cast<u_int8_t*>(GetDataPacket());
|
||||
bcopy(p, p+sizeof(MachMsgPortDescriptor), GetDataLength()+2*sizeof(int32_t));
|
||||
u_int8_t *p = reinterpret_cast<u_int8_t *>(GetDataPacket());
|
||||
bcopy(p, p + sizeof(MachMsgPortDescriptor), GetDataLength() + 2 * sizeof(int32_t));
|
||||
|
||||
SetDescriptor(GetDescriptorCount(), desc);
|
||||
SetDescriptorCount(GetDescriptorCount() + 1);
|
||||
@ -173,8 +160,7 @@ void MachMessage::SetDescriptorCount(int n) {
|
||||
//==============================================================================
|
||||
MachMsgPortDescriptor *MachMessage::GetDescriptor(int n) {
|
||||
if (n < GetDescriptorCount()) {
|
||||
MachMsgPortDescriptor *desc =
|
||||
reinterpret_cast<MachMsgPortDescriptor*>(storage_->padding);
|
||||
MachMsgPortDescriptor *desc = reinterpret_cast<MachMsgPortDescriptor *>(storage_->padding);
|
||||
return desc + n;
|
||||
}
|
||||
|
||||
@ -196,20 +182,13 @@ mach_port_t MachMessage::GetTranslatedPort(int n) {
|
||||
ReceivePort::ReceivePort(const char *receive_port_name) {
|
||||
mach_port_t current_task = mach_task_self();
|
||||
|
||||
init_result_ = mach_port_allocate(current_task,
|
||||
MACH_PORT_RIGHT_RECEIVE,
|
||||
&port_);
|
||||
init_result_ = mach_port_allocate(current_task, MACH_PORT_RIGHT_RECEIVE, &port_);
|
||||
|
||||
if (init_result_ != KERN_SUCCESS)
|
||||
return;
|
||||
if (init_result_ != KERN_SUCCESS) return;
|
||||
|
||||
init_result_ = mach_port_insert_right(current_task,
|
||||
port_,
|
||||
port_,
|
||||
MACH_MSG_TYPE_MAKE_SEND);
|
||||
init_result_ = mach_port_insert_right(current_task, port_, port_, MACH_MSG_TYPE_MAKE_SEND);
|
||||
|
||||
if (init_result_ != KERN_SUCCESS)
|
||||
return;
|
||||
if (init_result_ != KERN_SUCCESS) return;
|
||||
|
||||
NSPort *ns_port = [NSMachPort portWithMachPort:port_];
|
||||
NSString *port_name = [NSString stringWithUTF8String:receive_port_name];
|
||||
@ -221,31 +200,22 @@ ReceivePort::ReceivePort(const char *receive_port_name) {
|
||||
ReceivePort::ReceivePort() {
|
||||
mach_port_t current_task = mach_task_self();
|
||||
|
||||
init_result_ = mach_port_allocate(current_task,
|
||||
MACH_PORT_RIGHT_RECEIVE,
|
||||
&port_);
|
||||
init_result_ = mach_port_allocate(current_task, MACH_PORT_RIGHT_RECEIVE, &port_);
|
||||
|
||||
if (init_result_ != KERN_SUCCESS)
|
||||
return;
|
||||
if (init_result_ != KERN_SUCCESS) return;
|
||||
|
||||
init_result_ = mach_port_insert_right(current_task,
|
||||
port_,
|
||||
port_,
|
||||
MACH_MSG_TYPE_MAKE_SEND);
|
||||
init_result_ = mach_port_insert_right(current_task, port_, port_, MACH_MSG_TYPE_MAKE_SEND);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// Given an already existing mach port, use it. We take ownership of the
|
||||
// port and deallocate it in our destructor.
|
||||
ReceivePort::ReceivePort(mach_port_t receive_port)
|
||||
: port_(receive_port),
|
||||
init_result_(KERN_SUCCESS) {
|
||||
}
|
||||
: port_(receive_port), init_result_(KERN_SUCCESS) {}
|
||||
|
||||
//==============================================================================
|
||||
ReceivePort::~ReceivePort() {
|
||||
if (init_result_ == KERN_SUCCESS)
|
||||
mach_port_deallocate(mach_task_self(), port_);
|
||||
if (init_result_ == KERN_SUCCESS) mach_port_deallocate(mach_task_self(), port_);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
@ -256,8 +226,7 @@ kern_return_t ReceivePort::WaitForMessage(MachReceiveMessage *out_message,
|
||||
}
|
||||
|
||||
// return any error condition encountered in constructor
|
||||
if (init_result_ != KERN_SUCCESS)
|
||||
return init_result_;
|
||||
if (init_result_ != KERN_SUCCESS) return init_result_;
|
||||
|
||||
out_message->Head()->msgh_bits = 0;
|
||||
out_message->Head()->msgh_local_port = port_;
|
||||
@ -265,45 +234,36 @@ kern_return_t ReceivePort::WaitForMessage(MachReceiveMessage *out_message,
|
||||
out_message->Head()->msgh_reserved = 0;
|
||||
out_message->Head()->msgh_id = 0;
|
||||
|
||||
kern_return_t result = mach_msg(out_message->Head(),
|
||||
MACH_RCV_MSG | (timeout == MACH_MSG_TIMEOUT_NONE ? 0 : MACH_RCV_TIMEOUT),
|
||||
0,
|
||||
out_message->MaxSize(),
|
||||
port_,
|
||||
timeout, // timeout in ms
|
||||
MACH_PORT_NULL);
|
||||
kern_return_t result = mach_msg(
|
||||
out_message->Head(), MACH_RCV_MSG | (timeout == MACH_MSG_TIMEOUT_NONE ? 0 : MACH_RCV_TIMEOUT),
|
||||
0, out_message->MaxSize(), port_,
|
||||
timeout, // timeout in ms
|
||||
MACH_PORT_NULL);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// send a message to this port
|
||||
kern_return_t ReceivePort::SendMessageToSelf(MachSendMessage& message, mach_msg_timeout_t timeout) {
|
||||
kern_return_t ReceivePort::SendMessageToSelf(MachSendMessage &message, mach_msg_timeout_t timeout) {
|
||||
if (message.Head()->msgh_size == 0) {
|
||||
NOTREACHED();
|
||||
return KERN_INVALID_VALUE; // just for safety -- never should occur
|
||||
return KERN_INVALID_VALUE; // just for safety -- never should occur
|
||||
};
|
||||
|
||||
if (init_result_ != KERN_SUCCESS)
|
||||
return init_result_;
|
||||
if (init_result_ != KERN_SUCCESS) return init_result_;
|
||||
|
||||
message.Head()->msgh_remote_port = port_;
|
||||
message.Head()->msgh_bits
|
||||
= MACH_MSGH_BITS (MACH_MSG_TYPE_MAKE_SEND,
|
||||
MACH_MSG_TYPE_MAKE_SEND_ONCE);
|
||||
kern_return_t result = mach_msg(message.Head(),
|
||||
MACH_SEND_MSG | (timeout == MACH_MSG_TIMEOUT_NONE ? 0 : MACH_SEND_TIMEOUT),
|
||||
message.Head()->msgh_size,
|
||||
0,
|
||||
MACH_PORT_NULL,
|
||||
timeout, // timeout in ms
|
||||
MACH_PORT_NULL);
|
||||
message.Head()->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE);
|
||||
kern_return_t result = mach_msg(
|
||||
message.Head(), MACH_SEND_MSG | (timeout == MACH_MSG_TIMEOUT_NONE ? 0 : MACH_SEND_TIMEOUT),
|
||||
message.Head()->msgh_size, 0, MACH_PORT_NULL,
|
||||
timeout, // timeout in ms
|
||||
MACH_PORT_NULL);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
//==============================================================================
|
||||
@ -312,40 +272,32 @@ MachPortSender::MachPortSender(const char *receive_port_name) {
|
||||
mach_port_t bootstrap_port = 0;
|
||||
init_result_ = task_get_bootstrap_port(mach_task_self(), &bootstrap_port);
|
||||
|
||||
if (init_result_ != KERN_SUCCESS)
|
||||
return;
|
||||
if (init_result_ != KERN_SUCCESS) return;
|
||||
|
||||
init_result_ = bootstrap_look_up(bootstrap_port,
|
||||
const_cast<char*>(receive_port_name),
|
||||
&send_port_);
|
||||
init_result_ =
|
||||
bootstrap_look_up(bootstrap_port, const_cast<char *>(receive_port_name), &send_port_);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
MachPortSender::MachPortSender(mach_port_t send_port)
|
||||
: send_port_(send_port),
|
||||
init_result_(KERN_SUCCESS) {
|
||||
}
|
||||
: send_port_(send_port), init_result_(KERN_SUCCESS) {}
|
||||
|
||||
//==============================================================================
|
||||
kern_return_t MachPortSender::SendMessage(MachSendMessage &message,
|
||||
mach_msg_timeout_t timeout) {
|
||||
kern_return_t MachPortSender::SendMessage(MachSendMessage &message, mach_msg_timeout_t timeout) {
|
||||
if (message.Head()->msgh_size == 0) {
|
||||
NOTREACHED();
|
||||
return KERN_INVALID_VALUE; // just for safety -- never should occur
|
||||
return KERN_INVALID_VALUE; // just for safety -- never should occur
|
||||
};
|
||||
|
||||
if (init_result_ != KERN_SUCCESS)
|
||||
return init_result_;
|
||||
if (init_result_ != KERN_SUCCESS) return init_result_;
|
||||
|
||||
message.Head()->msgh_remote_port = send_port_;
|
||||
|
||||
kern_return_t result = mach_msg(message.Head(),
|
||||
MACH_SEND_MSG | (timeout == MACH_MSG_TIMEOUT_NONE ? 0 : MACH_SEND_TIMEOUT),
|
||||
message.Head()->msgh_size,
|
||||
0,
|
||||
MACH_PORT_NULL,
|
||||
timeout, // timeout in ms
|
||||
MACH_PORT_NULL);
|
||||
kern_return_t result = mach_msg(
|
||||
message.Head(), MACH_SEND_MSG | (timeout == MACH_MSG_TIMEOUT_NONE ? 0 : MACH_SEND_TIMEOUT),
|
||||
message.Head()->msgh_size, 0, MACH_PORT_NULL,
|
||||
timeout, // timeout in ms
|
||||
MACH_PORT_NULL);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -11,10 +11,9 @@
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
void SetThisProcessName(const char *aName)
|
||||
{
|
||||
void SetThisProcessName(const char *aName) {
|
||||
mozilla::plugins::PluginUtilsOSX::SetProcessName(aName);
|
||||
}
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
@ -10,14 +10,14 @@
|
||||
#include <mach/vm_map.h>
|
||||
#include <mach/mach_port.h>
|
||||
#if defined(XP_IOS)
|
||||
#include <mach/vm_map.h>
|
||||
#define mach_vm_address_t vm_address_t
|
||||
#define mach_vm_map vm_map
|
||||
#define mach_vm_read vm_read
|
||||
#define mach_vm_region_recurse vm_region_recurse_64
|
||||
#define mach_vm_size_t vm_size_t
|
||||
# include <mach/vm_map.h>
|
||||
# define mach_vm_address_t vm_address_t
|
||||
# define mach_vm_map vm_map
|
||||
# define mach_vm_read vm_read
|
||||
# define mach_vm_region_recurse vm_region_recurse_64
|
||||
# define mach_vm_size_t vm_size_t
|
||||
#else
|
||||
#include <mach/mach_vm.h>
|
||||
# include <mach/mach_vm.h>
|
||||
#endif
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
@ -29,21 +29,23 @@
|
||||
#include "mozilla/layers/TextureSync.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define LOG_ERROR(str, args...) \
|
||||
PR_BEGIN_MACRO \
|
||||
mozilla::SmprintfPointer msg = mozilla::Smprintf(str, ## args); \
|
||||
NS_WARNING(msg.get()); \
|
||||
PR_END_MACRO
|
||||
# define LOG_ERROR(str, args...) \
|
||||
PR_BEGIN_MACRO \
|
||||
mozilla::SmprintfPointer msg = mozilla::Smprintf(str, ##args); \
|
||||
NS_WARNING(msg.get()); \
|
||||
PR_END_MACRO
|
||||
#else
|
||||
#define LOG_ERROR(str, args...) do { /* nothing */ } while(0)
|
||||
# define LOG_ERROR(str, args...) \
|
||||
do { /* nothing */ \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define CHECK_MACH_ERROR(kr, msg) \
|
||||
PR_BEGIN_MACRO \
|
||||
if (kr != KERN_SUCCESS) { \
|
||||
LOG_ERROR("%s %s (%x)\n", msg, mach_error_string(kr), kr); \
|
||||
return false; \
|
||||
} \
|
||||
#define CHECK_MACH_ERROR(kr, msg) \
|
||||
PR_BEGIN_MACRO \
|
||||
if (kr != KERN_SUCCESS) { \
|
||||
LOG_ERROR("%s %s (%x)\n", msg, mach_error_string(kr), kr); \
|
||||
return false; \
|
||||
} \
|
||||
PR_END_MACRO
|
||||
|
||||
/*
|
||||
@ -95,8 +97,7 @@ struct PIDPair {
|
||||
pid_t mRequester;
|
||||
pid_t mRequested;
|
||||
|
||||
PIDPair(pid_t requester, pid_t requested)
|
||||
: mRequester(requester), mRequested(requested) {}
|
||||
PIDPair(pid_t requester, pid_t requested) : mRequester(requester), mRequested(requested) {}
|
||||
};
|
||||
|
||||
struct ListeningThread {
|
||||
@ -104,8 +105,7 @@ struct ListeningThread {
|
||||
MemoryPorts* mPorts;
|
||||
|
||||
ListeningThread() = default;
|
||||
ListeningThread(pthread_t thread, MemoryPorts* ports)
|
||||
: mThread(thread), mPorts(ports) {}
|
||||
ListeningThread(pthread_t thread, MemoryPorts* ports) : mThread(thread), mPorts(ports) {}
|
||||
};
|
||||
|
||||
struct SharePortsReply {
|
||||
@ -115,18 +115,11 @@ struct SharePortsReply {
|
||||
|
||||
std::map<pid_t, ListeningThread> gThreads;
|
||||
|
||||
static void *
|
||||
PortServerThread(void *argument);
|
||||
static void* PortServerThread(void* argument);
|
||||
|
||||
|
||||
static void
|
||||
SetupMachMemory(pid_t pid,
|
||||
ReceivePort* listen_port,
|
||||
MachPortSender* listen_port_ack,
|
||||
MachPortSender* send_port,
|
||||
ReceivePort* send_port_ack,
|
||||
bool pidIsParent)
|
||||
{
|
||||
static void SetupMachMemory(pid_t pid, ReceivePort* listen_port, MachPortSender* listen_port_ack,
|
||||
MachPortSender* send_port, ReceivePort* send_port_ack,
|
||||
bool pidIsParent) {
|
||||
if (pidIsParent) {
|
||||
gParentPid = pid;
|
||||
}
|
||||
@ -149,12 +142,8 @@ SetupMachMemory(pid_t pid,
|
||||
|
||||
// Send two communication ports to another process along with the pid of the process that is
|
||||
// listening on them.
|
||||
bool
|
||||
SendPortsMessage(MachPortSender* sender,
|
||||
mach_port_t ports_in_receiver,
|
||||
mach_port_t ports_out_receiver,
|
||||
PIDPair pid_pair)
|
||||
{
|
||||
bool SendPortsMessage(MachPortSender* sender, mach_port_t ports_in_receiver,
|
||||
mach_port_t ports_out_receiver, PIDPair pid_pair) {
|
||||
MachSendMessage getPortsMsg(kGetPortsMsg);
|
||||
if (!getPortsMsg.AddDescriptor(MachMsgPortDescriptor(ports_in_receiver))) {
|
||||
LOG_ERROR("Adding descriptor to message failed");
|
||||
@ -168,20 +157,19 @@ SendPortsMessage(MachPortSender* sender,
|
||||
getPortsMsg.SetData(&pid_pair, sizeof(PIDPair));
|
||||
kern_return_t err = sender->SendMessage(getPortsMsg, kTimeout);
|
||||
if (KERN_SUCCESS != err) {
|
||||
LOG_ERROR("Error sending get ports message %s (%x)\n", mach_error_string(err), err);
|
||||
LOG_ERROR("Error sending get ports message %s (%x)\n", mach_error_string(err), err);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Receive two communication ports from another process
|
||||
bool
|
||||
RecvPortsMessage(ReceivePort* receiver, mach_port_t* ports_in_sender, mach_port_t* ports_out_sender)
|
||||
{
|
||||
bool RecvPortsMessage(ReceivePort* receiver, mach_port_t* ports_in_sender,
|
||||
mach_port_t* ports_out_sender) {
|
||||
MachReceiveMessage rcvPortsMsg;
|
||||
kern_return_t err = receiver->WaitForMessage(&rcvPortsMsg, kTimeout);
|
||||
if (KERN_SUCCESS != err) {
|
||||
LOG_ERROR("Error receiving get ports message %s (%x)\n", mach_error_string(err), err);
|
||||
LOG_ERROR("Error receiving get ports message %s (%x)\n", mach_error_string(err), err);
|
||||
}
|
||||
if (rcvPortsMsg.GetTranslatedPort(0) == MACH_PORT_NULL) {
|
||||
LOG_ERROR("GetTranslatedPort(0) failed");
|
||||
@ -198,23 +186,16 @@ RecvPortsMessage(ReceivePort* receiver, mach_port_t* ports_in_sender, mach_port_
|
||||
}
|
||||
|
||||
// Send two communication ports to another process and receive two back
|
||||
bool
|
||||
RequestPorts(const MemoryPorts& request_ports,
|
||||
mach_port_t ports_in_receiver,
|
||||
mach_port_t* ports_in_sender,
|
||||
mach_port_t* ports_out_sender,
|
||||
mach_port_t ports_out_receiver,
|
||||
PIDPair pid_pair)
|
||||
{
|
||||
bool RequestPorts(const MemoryPorts& request_ports, mach_port_t ports_in_receiver,
|
||||
mach_port_t* ports_in_sender, mach_port_t* ports_out_sender,
|
||||
mach_port_t ports_out_receiver, PIDPair pid_pair) {
|
||||
if (!SendPortsMessage(request_ports.mSender, ports_in_receiver, ports_out_receiver, pid_pair)) {
|
||||
return false;
|
||||
}
|
||||
return RecvPortsMessage(request_ports.mReceiver, ports_in_sender, ports_out_sender);
|
||||
}
|
||||
|
||||
MemoryPorts*
|
||||
GetMemoryPortsForPid(pid_t pid)
|
||||
{
|
||||
MemoryPorts* GetMemoryPortsForPid(pid_t pid) {
|
||||
gMutex.AssertCurrentThreadOwns();
|
||||
|
||||
if (gMemoryCommPorts.find(pid) == gMemoryCommPorts.end()) {
|
||||
@ -233,11 +214,8 @@ GetMemoryPortsForPid(pid_t pid)
|
||||
auto* ports_in_receiver = new ReceivePort();
|
||||
auto* ports_out_receiver = new ReceivePort();
|
||||
mach_port_t raw_ports_in_sender, raw_ports_out_sender;
|
||||
if (!RequestPorts(parent,
|
||||
ports_in_receiver->GetPort(),
|
||||
&raw_ports_in_sender,
|
||||
&raw_ports_out_sender,
|
||||
ports_out_receiver->GetPort(),
|
||||
if (!RequestPorts(parent, ports_in_receiver->GetPort(), &raw_ports_in_sender,
|
||||
&raw_ports_out_sender, ports_out_receiver->GetPort(),
|
||||
PIDPair(getpid(), pid))) {
|
||||
LOG_ERROR("failed to request ports\n");
|
||||
return nullptr;
|
||||
@ -246,11 +224,7 @@ GetMemoryPortsForPid(pid_t pid)
|
||||
// is for replying with the Handle when we receive new memory.
|
||||
auto* ports_in_sender = new MachPortSender(raw_ports_in_sender);
|
||||
auto* ports_out_sender = new MachPortSender(raw_ports_out_sender);
|
||||
SetupMachMemory(pid,
|
||||
ports_in_receiver,
|
||||
ports_in_sender,
|
||||
ports_out_sender,
|
||||
ports_out_receiver,
|
||||
SetupMachMemory(pid, ports_in_receiver, ports_in_sender, ports_out_sender, ports_out_receiver,
|
||||
false);
|
||||
MOZ_ASSERT(gMemoryCommPorts.find(pid) != gMemoryCommPorts.end());
|
||||
}
|
||||
@ -260,9 +234,7 @@ GetMemoryPortsForPid(pid_t pid)
|
||||
// We just received a port representing a region of shared memory, reply to
|
||||
// the process that set it with the mach_port_t that represents it in this process.
|
||||
// That will be the Handle to be shared over normal IPC
|
||||
void
|
||||
HandleSharePortsMessage(MachReceiveMessage* rmsg, MemoryPorts* ports)
|
||||
{
|
||||
void HandleSharePortsMessage(MachReceiveMessage* rmsg, MemoryPorts* ports) {
|
||||
mach_port_t port = rmsg->GetTranslatedPort(0);
|
||||
uint64_t* serial = reinterpret_cast<uint64_t*>(rmsg->GetData());
|
||||
MachSendMessage msg(kReturnIdMsg);
|
||||
@ -279,11 +251,8 @@ HandleSharePortsMessage(MachReceiveMessage* rmsg, MemoryPorts* ports)
|
||||
|
||||
// We were asked by another process to get communications ports to some process. Return
|
||||
// those ports via an IPC message.
|
||||
bool
|
||||
SendReturnPortsMsg(MachPortSender* sender,
|
||||
mach_port_t raw_ports_in_sender,
|
||||
mach_port_t raw_ports_out_sender)
|
||||
{
|
||||
bool SendReturnPortsMsg(MachPortSender* sender, mach_port_t raw_ports_in_sender,
|
||||
mach_port_t raw_ports_out_sender) {
|
||||
MachSendMessage getPortsMsg(kReturnPortsMsg);
|
||||
if (!getPortsMsg.AddDescriptor(MachMsgPortDescriptor(raw_ports_in_sender))) {
|
||||
LOG_ERROR("Adding descriptor to message failed");
|
||||
@ -296,7 +265,7 @@ SendReturnPortsMsg(MachPortSender* sender,
|
||||
}
|
||||
kern_return_t err = sender->SendMessage(getPortsMsg, kTimeout);
|
||||
if (KERN_SUCCESS != err) {
|
||||
LOG_ERROR("Error sending get ports message %s (%x)\n", mach_error_string(err), err);
|
||||
LOG_ERROR("Error sending get ports message %s (%x)\n", mach_error_string(err), err);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -304,9 +273,7 @@ SendReturnPortsMsg(MachPortSender* sender,
|
||||
|
||||
// We were asked for communcations ports to a process that isn't us. Assuming that process
|
||||
// is one of our children, forward that request on.
|
||||
void
|
||||
ForwardGetPortsMessage(MachReceiveMessage* rmsg, MemoryPorts* ports, PIDPair* pid_pair)
|
||||
{
|
||||
void ForwardGetPortsMessage(MachReceiveMessage* rmsg, MemoryPorts* ports, PIDPair* pid_pair) {
|
||||
if (rmsg->GetTranslatedPort(0) == MACH_PORT_NULL) {
|
||||
LOG_ERROR("GetTranslatedPort(0) failed");
|
||||
return;
|
||||
@ -330,9 +297,7 @@ ForwardGetPortsMessage(MachReceiveMessage* rmsg, MemoryPorts* ports, PIDPair* pi
|
||||
}
|
||||
|
||||
// We receieved a message asking us to get communications ports for another process
|
||||
void
|
||||
HandleGetPortsMessage(MachReceiveMessage* rmsg, MemoryPorts* ports)
|
||||
{
|
||||
void HandleGetPortsMessage(MachReceiveMessage* rmsg, MemoryPorts* ports) {
|
||||
PIDPair* pid_pair;
|
||||
if (rmsg->GetDataLength() != sizeof(PIDPair)) {
|
||||
LOG_ERROR("Improperly formatted message\n");
|
||||
@ -358,20 +323,15 @@ HandleGetPortsMessage(MachReceiveMessage* rmsg, MemoryPorts* ports)
|
||||
|
||||
auto* ports_in_receiver = new ReceivePort();
|
||||
auto* ports_out_receiver = new ReceivePort();
|
||||
if (SendReturnPortsMsg(ports->mSender, ports_in_receiver->GetPort(), ports_out_receiver->GetPort())) {
|
||||
SetupMachMemory(pid_pair->mRequester,
|
||||
ports_out_receiver,
|
||||
ports_out_sender,
|
||||
ports_in_sender,
|
||||
ports_in_receiver,
|
||||
false);
|
||||
if (SendReturnPortsMsg(ports->mSender, ports_in_receiver->GetPort(),
|
||||
ports_out_receiver->GetPort())) {
|
||||
SetupMachMemory(pid_pair->mRequester, ports_out_receiver, ports_out_sender, ports_in_sender,
|
||||
ports_in_receiver, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void *
|
||||
PortServerThread(void *argument)
|
||||
{
|
||||
static void* PortServerThread(void* argument) {
|
||||
MemoryPorts* ports = static_cast<MemoryPorts*>(argument);
|
||||
MachReceiveMessage child_message;
|
||||
while (true) {
|
||||
@ -394,48 +354,42 @@ PortServerThread(void *argument)
|
||||
} else {
|
||||
StaticMutexAutoLock smal(gMutex);
|
||||
switch (rmsg.GetMessageID()) {
|
||||
case kSharePortsMsg:
|
||||
HandleSharePortsMessage(&rmsg, ports);
|
||||
break;
|
||||
case kGetPortsMsg:
|
||||
HandleGetPortsMessage(&rmsg, ports);
|
||||
break;
|
||||
case kCleanupMsg:
|
||||
if (gParentPid == 0) {
|
||||
LOG_ERROR("Cleanup message not valid for parent process");
|
||||
continue;
|
||||
}
|
||||
case kSharePortsMsg:
|
||||
HandleSharePortsMessage(&rmsg, ports);
|
||||
break;
|
||||
case kGetPortsMsg:
|
||||
HandleGetPortsMessage(&rmsg, ports);
|
||||
break;
|
||||
case kCleanupMsg:
|
||||
if (gParentPid == 0) {
|
||||
LOG_ERROR("Cleanup message not valid for parent process");
|
||||
continue;
|
||||
}
|
||||
|
||||
pid_t* pid;
|
||||
if (rmsg.GetDataLength() != sizeof(pid_t)) {
|
||||
LOG_ERROR("Improperly formatted message\n");
|
||||
continue;
|
||||
}
|
||||
pid = reinterpret_cast<pid_t*>(rmsg.GetData());
|
||||
SharedMemoryBasic::CleanupForPid(*pid);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unknown message\n");
|
||||
pid_t* pid;
|
||||
if (rmsg.GetDataLength() != sizeof(pid_t)) {
|
||||
LOG_ERROR("Improperly formatted message\n");
|
||||
continue;
|
||||
}
|
||||
pid = reinterpret_cast<pid_t*>(rmsg.GetData());
|
||||
SharedMemoryBasic::CleanupForPid(*pid);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unknown message\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SharedMemoryBasic::SetupMachMemory(pid_t pid,
|
||||
ReceivePort* listen_port,
|
||||
MachPortSender* listen_port_ack,
|
||||
MachPortSender* send_port,
|
||||
ReceivePort* send_port_ack,
|
||||
bool pidIsParent)
|
||||
{
|
||||
void SharedMemoryBasic::SetupMachMemory(pid_t pid, ReceivePort* listen_port,
|
||||
MachPortSender* listen_port_ack, MachPortSender* send_port,
|
||||
ReceivePort* send_port_ack, bool pidIsParent) {
|
||||
StaticMutexAutoLock smal(gMutex);
|
||||
mozilla::ipc::SetupMachMemory(pid, listen_port, listen_port_ack, send_port, send_port_ack, pidIsParent);
|
||||
mozilla::ipc::SetupMachMemory(pid, listen_port, listen_port_ack, send_port, send_port_ack,
|
||||
pidIsParent);
|
||||
}
|
||||
|
||||
void
|
||||
SharedMemoryBasic::Shutdown()
|
||||
{
|
||||
void SharedMemoryBasic::Shutdown() {
|
||||
StaticMutexAutoLock smal(gMutex);
|
||||
|
||||
layers::TextureSync::Shutdown();
|
||||
@ -453,9 +407,7 @@ SharedMemoryBasic::Shutdown()
|
||||
gMemoryCommPorts.clear();
|
||||
}
|
||||
|
||||
void
|
||||
SharedMemoryBasic::CleanupForPid(pid_t pid)
|
||||
{
|
||||
void SharedMemoryBasic::CleanupForPid(pid_t pid) {
|
||||
if (gThreads.find(pid) == gThreads.end()) {
|
||||
return;
|
||||
}
|
||||
@ -486,11 +438,8 @@ SharedMemoryBasic::CleanupForPid(pid_t pid)
|
||||
gMemoryCommPorts.erase(pid);
|
||||
}
|
||||
|
||||
bool
|
||||
SharedMemoryBasic::SendMachMessage(pid_t pid,
|
||||
MachSendMessage& message,
|
||||
MachReceiveMessage* response)
|
||||
{
|
||||
bool SharedMemoryBasic::SendMachMessage(pid_t pid, MachSendMessage& message,
|
||||
MachReceiveMessage* response) {
|
||||
StaticMutexAutoLock smal(gMutex);
|
||||
ipc::MemoryPorts* ports = GetMemoryPortsForPid(pid);
|
||||
if (!ports) {
|
||||
@ -521,21 +470,14 @@ SharedMemoryBasic::SendMachMessage(pid_t pid,
|
||||
}
|
||||
|
||||
SharedMemoryBasic::SharedMemoryBasic()
|
||||
: mPort(MACH_PORT_NULL)
|
||||
, mMemory(nullptr)
|
||||
, mOpenRights(RightsReadWrite)
|
||||
{
|
||||
}
|
||||
: mPort(MACH_PORT_NULL), mMemory(nullptr), mOpenRights(RightsReadWrite) {}
|
||||
|
||||
SharedMemoryBasic::~SharedMemoryBasic()
|
||||
{
|
||||
SharedMemoryBasic::~SharedMemoryBasic() {
|
||||
Unmap();
|
||||
CloseHandle();
|
||||
}
|
||||
|
||||
bool
|
||||
SharedMemoryBasic::SetHandle(const Handle& aHandle, OpenRights aRights)
|
||||
{
|
||||
bool SharedMemoryBasic::SetHandle(const Handle& aHandle, OpenRights aRights) {
|
||||
MOZ_ASSERT(mPort == MACH_PORT_NULL, "already initialized");
|
||||
|
||||
mPort = aHandle;
|
||||
@ -543,34 +485,25 @@ SharedMemoryBasic::SetHandle(const Handle& aHandle, OpenRights aRights)
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void*
|
||||
toPointer(mach_vm_address_t address)
|
||||
{
|
||||
static inline void* toPointer(mach_vm_address_t address) {
|
||||
return reinterpret_cast<void*>(static_cast<uintptr_t>(address));
|
||||
}
|
||||
|
||||
static inline mach_vm_address_t
|
||||
toVMAddress(void* pointer)
|
||||
{
|
||||
static inline mach_vm_address_t toVMAddress(void* pointer) {
|
||||
return static_cast<mach_vm_address_t>(reinterpret_cast<uintptr_t>(pointer));
|
||||
}
|
||||
|
||||
bool
|
||||
SharedMemoryBasic::Create(size_t size)
|
||||
{
|
||||
bool SharedMemoryBasic::Create(size_t size) {
|
||||
MOZ_ASSERT(mPort == MACH_PORT_NULL, "already initialized");
|
||||
|
||||
memory_object_size_t memoryObjectSize = round_page(size);
|
||||
|
||||
kern_return_t kr = mach_make_memory_entry_64(mach_task_self(),
|
||||
&memoryObjectSize,
|
||||
0,
|
||||
MAP_MEM_NAMED_CREATE | VM_PROT_DEFAULT,
|
||||
&mPort,
|
||||
MACH_PORT_NULL);
|
||||
kern_return_t kr =
|
||||
mach_make_memory_entry_64(mach_task_self(), &memoryObjectSize, 0,
|
||||
MAP_MEM_NAMED_CREATE | VM_PROT_DEFAULT, &mPort, MACH_PORT_NULL);
|
||||
if (kr != KERN_SUCCESS || memoryObjectSize < round_page(size)) {
|
||||
LOG_ERROR("Failed to make memory entry (%zu bytes). %s (%x)\n",
|
||||
size, mach_error_string(kr), kr);
|
||||
LOG_ERROR("Failed to make memory entry (%zu bytes). %s (%x)\n", size, mach_error_string(kr),
|
||||
kr);
|
||||
CloseHandle();
|
||||
return false;
|
||||
}
|
||||
@ -579,9 +512,7 @@ SharedMemoryBasic::Create(size_t size)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SharedMemoryBasic::Map(size_t size)
|
||||
{
|
||||
bool SharedMemoryBasic::Map(size_t size) {
|
||||
MOZ_ASSERT(mMemory == nullptr);
|
||||
|
||||
if (MACH_PORT_NULL == mPort) {
|
||||
@ -596,11 +527,11 @@ SharedMemoryBasic::Map(size_t size)
|
||||
vmProtection |= VM_PROT_WRITE;
|
||||
}
|
||||
|
||||
kr = mach_vm_map(mach_task_self(), &address, round_page(size), 0, VM_FLAGS_ANYWHERE,
|
||||
mPort, 0, false, vmProtection, vmProtection, VM_INHERIT_NONE);
|
||||
kr = mach_vm_map(mach_task_self(), &address, round_page(size), 0, VM_FLAGS_ANYWHERE, mPort, 0,
|
||||
false, vmProtection, vmProtection, VM_INHERIT_NONE);
|
||||
if (kr != KERN_SUCCESS) {
|
||||
LOG_ERROR("Failed to map shared memory (%zu bytes) into %x, port %x. %s (%x)\n",
|
||||
size, mach_task_self(), mPort, mach_error_string(kr), kr);
|
||||
LOG_ERROR("Failed to map shared memory (%zu bytes) into %x, port %x. %s (%x)\n", size,
|
||||
mach_task_self(), mPort, mach_error_string(kr), kr);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -609,17 +540,15 @@ SharedMemoryBasic::Map(size_t size)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SharedMemoryBasic::ShareToProcess(base::ProcessId pid,
|
||||
Handle* aNewHandle)
|
||||
{
|
||||
bool SharedMemoryBasic::ShareToProcess(base::ProcessId pid, Handle* aNewHandle) {
|
||||
if (pid == getpid()) {
|
||||
*aNewHandle = mPort;
|
||||
return mach_port_mod_refs(mach_task_self(), *aNewHandle, MACH_PORT_RIGHT_SEND, 1) == KERN_SUCCESS;
|
||||
return mach_port_mod_refs(mach_task_self(), *aNewHandle, MACH_PORT_RIGHT_SEND, 1) ==
|
||||
KERN_SUCCESS;
|
||||
}
|
||||
StaticMutexAutoLock smal(gMutex);
|
||||
|
||||
// Serially number the messages, to check whether
|
||||
// Serially number the messages, to check whether
|
||||
// the reply we get was meant for us.
|
||||
static uint64_t serial = 0;
|
||||
uint64_t my_serial = serial;
|
||||
@ -664,24 +593,20 @@ SharedMemoryBasic::ShareToProcess(base::ProcessId pid,
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
SharedMemoryBasic::Unmap()
|
||||
{
|
||||
void SharedMemoryBasic::Unmap() {
|
||||
if (!mMemory) {
|
||||
return;
|
||||
}
|
||||
vm_address_t address = toVMAddress(mMemory);
|
||||
kern_return_t kr = vm_deallocate(mach_task_self(), address, round_page(mMappedSize));
|
||||
if (kr != KERN_SUCCESS) {
|
||||
LOG_ERROR("Failed to deallocate shared memory. %s (%x)\n", mach_error_string(kr), kr);
|
||||
LOG_ERROR("Failed to deallocate shared memory. %s (%x)\n", mach_error_string(kr), kr);
|
||||
return;
|
||||
}
|
||||
mMemory = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
SharedMemoryBasic::CloseHandle()
|
||||
{
|
||||
void SharedMemoryBasic::CloseHandle() {
|
||||
if (mPort != MACH_PORT_NULL) {
|
||||
mach_port_deallocate(mach_task_self(), mPort);
|
||||
mPort = MACH_PORT_NULL;
|
||||
@ -689,11 +614,7 @@ SharedMemoryBasic::CloseHandle()
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
SharedMemoryBasic::IsHandleValid(const Handle& aHandle) const
|
||||
{
|
||||
return aHandle > 0;
|
||||
}
|
||||
bool SharedMemoryBasic::IsHandleValid(const Handle& aHandle) const { return aHandle > 0; }
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
@ -342,15 +342,18 @@ def run_command(command, check=False, **kwargs):
|
||||
return stdout, stderr, status
|
||||
|
||||
|
||||
# Replacement strings in environment variables.
|
||||
REPLACEMENTS = {
|
||||
'DIR': DIR.scripts,
|
||||
'TOOLTOOL_CHECKOUT': DIR.tooltool,
|
||||
'MOZ_UPLOAD_DIR': env['MOZ_UPLOAD_DIR'],
|
||||
'OUTDIR': OUTDIR,
|
||||
}
|
||||
|
||||
# Add in environment variable settings for this variant. Normally used to
|
||||
# modify the flags passed to the shell or to set the GC zeal mode.
|
||||
for k, v in variant.get('env', {}).items():
|
||||
env[k.encode('ascii')] = v.encode('ascii').format(
|
||||
DIR=DIR.scripts,
|
||||
TOOLTOOL_CHECKOUT=DIR.tooltool,
|
||||
MOZ_UPLOAD_DIR=env['MOZ_UPLOAD_DIR'],
|
||||
OUTDIR=OUTDIR,
|
||||
)
|
||||
env[k.encode('ascii')] = v.encode('ascii').format(**REPLACEMENTS)
|
||||
|
||||
if AUTOMATION:
|
||||
# Currently only supported on linux64.
|
||||
@ -460,6 +463,10 @@ elif platform.system() == 'Darwin':
|
||||
else:
|
||||
variant_platform = 'other'
|
||||
|
||||
# Override environment variant settings conditionally.
|
||||
for k, v in variant.get('conditional-env', {}).get(variant_platform, {}).items():
|
||||
env[k.encode('ascii')] = v.encode('ascii').format(**REPLACEMENTS)
|
||||
|
||||
# Skip any tests that are not run on this platform (or the 'all' platform).
|
||||
test_suites -= set(normalize_tests(variant.get('skip-tests', {}).get(variant_platform, [])))
|
||||
test_suites -= set(normalize_tests(variant.get('skip-tests', {}).get('all', [])))
|
||||
|
@ -7,6 +7,11 @@
|
||||
"JITTEST_EXTRA_ARGS": "--jitflags=debug --ignore-timeouts={DIR}/cgc-jittest-timeouts.txt",
|
||||
"JSTESTS_EXTRA_ARGS": "--exclude-file={DIR}/cgc-jstests-slow.txt"
|
||||
},
|
||||
"conditional-env": {
|
||||
"linux64": {
|
||||
"JITTEST_EXTRA_ARGS": "--jitflags=debug --ignore-timeouts={DIR}/cgc-jittest-timeouts.txt --run-binast"
|
||||
}
|
||||
},
|
||||
"skip-tests": {
|
||||
"win32": ["jstests"],
|
||||
"win64": ["jstests"]
|
||||
|
@ -3,5 +3,10 @@
|
||||
"optimize": true,
|
||||
"env": {
|
||||
"JSTESTS_EXTRA_ARGS": "--jitflags=all"
|
||||
},
|
||||
"conditional-env": {
|
||||
"linux64": {
|
||||
"JITTEST_EXTRA_ARGS": "--run-binast"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,5 +3,10 @@
|
||||
"debug": true,
|
||||
"env": {
|
||||
"JSTESTS_EXTRA_ARGS": "--jitflags=debug"
|
||||
},
|
||||
"conditional-env": {
|
||||
"linux64": {
|
||||
"JITTEST_EXTRA_ARGS": "--run-binast"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ void LifoAlloc::reset(size_t defaultChunkSize) {
|
||||
chunks_.popFirst();
|
||||
}
|
||||
while (!oversize_.empty()) {
|
||||
chunks_.popFirst();
|
||||
oversize_.popFirst();
|
||||
}
|
||||
while (!unused_.empty()) {
|
||||
unused_.popFirst();
|
||||
@ -113,10 +113,15 @@ void LifoAlloc::reset(size_t defaultChunkSize) {
|
||||
oversizeThreshold_ = defaultChunkSize;
|
||||
markCount = 0;
|
||||
curSize_ = 0;
|
||||
oversizeSize_ = 0;
|
||||
smallAllocsSize_ = 0;
|
||||
}
|
||||
|
||||
void LifoAlloc::freeAll() {
|
||||
// When free-ing all chunks, we can no longer determine which chunks were
|
||||
// transferred and which were not, so simply clear the heuristic to zero
|
||||
// right away.
|
||||
smallAllocsSize_ = 0;
|
||||
|
||||
while (!chunks_.empty()) {
|
||||
UniqueBumpChunk bc = chunks_.popFirst();
|
||||
decrementCurSize(bc->computedSizeOfIncludingThis());
|
||||
@ -124,7 +129,6 @@ void LifoAlloc::freeAll() {
|
||||
while (!oversize_.empty()) {
|
||||
UniqueBumpChunk bc = oversize_.popFirst();
|
||||
decrementCurSize(bc->computedSizeOfIncludingThis());
|
||||
oversizeSize_ -= bc->computedSizeOfIncludingThis();
|
||||
}
|
||||
while (!unused_.empty()) {
|
||||
UniqueBumpChunk bc = unused_.popFirst();
|
||||
@ -134,7 +138,6 @@ void LifoAlloc::freeAll() {
|
||||
// Nb: maintaining curSize_ correctly isn't easy. Fortunately, this is an
|
||||
// excellent sanity check.
|
||||
MOZ_ASSERT(curSize_ == 0);
|
||||
MOZ_ASSERT(oversizeSize_ == 0);
|
||||
}
|
||||
|
||||
// Round at the same page granularity used by malloc.
|
||||
@ -176,11 +179,14 @@ LifoAlloc::UniqueBumpChunk LifoAlloc::newChunkWithCapacity(size_t n,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(curSize_ >= oversizeSize_);
|
||||
// Note: When computing chunkSize growth, we only are interested in chunks
|
||||
// used for small allocations. This excludes unused chunks, oversized chunks,
|
||||
// and chunks transferred in from another LifoAlloc.
|
||||
MOZ_ASSERT(curSize_ >= smallAllocsSize_);
|
||||
const size_t chunkSize =
|
||||
(oversize || minSize > defaultChunkSize_)
|
||||
? MallocGoodSize(minSize)
|
||||
: NextSize(defaultChunkSize_, curSize_ - oversizeSize_);
|
||||
: NextSize(defaultChunkSize_, smallAllocsSize_);
|
||||
|
||||
// Create a new BumpChunk, and allocate space for it.
|
||||
UniqueBumpChunk result = detail::BumpChunk::newWithCapacity(chunkSize);
|
||||
@ -219,8 +225,7 @@ LifoAlloc::UniqueBumpChunk LifoAlloc::getOrCreateChunk(size_t n) {
|
||||
if (!newChunk) {
|
||||
return newChunk;
|
||||
}
|
||||
size_t size = newChunk->computedSizeOfIncludingThis();
|
||||
incrementCurSize(size);
|
||||
incrementCurSize(newChunk->computedSizeOfIncludingThis());
|
||||
return newChunk;
|
||||
}
|
||||
|
||||
@ -231,6 +236,9 @@ void* LifoAlloc::allocImplColdPath(size_t n) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// This new chunk is about to be used for small allocations.
|
||||
smallAllocsSize_ += newChunk->computedSizeOfIncludingThis();
|
||||
|
||||
// Since we just created a large enough chunk, this can't fail.
|
||||
chunks_.append(std::move(newChunk));
|
||||
result = chunks_.last()->tryAlloc(n);
|
||||
@ -245,7 +253,6 @@ void* LifoAlloc::allocImplOversize(size_t n) {
|
||||
return nullptr;
|
||||
}
|
||||
incrementCurSize(newChunk->computedSizeOfIncludingThis());
|
||||
oversizeSize_ += newChunk->computedSizeOfIncludingThis();
|
||||
|
||||
// Since we just created a large enough chunk, this can't fail.
|
||||
oversize_.append(std::move(newChunk));
|
||||
@ -266,9 +273,8 @@ bool LifoAlloc::ensureUnusedApproximateColdPath(size_t n, size_t total) {
|
||||
if (!newChunk) {
|
||||
return false;
|
||||
}
|
||||
size_t size = newChunk->computedSizeOfIncludingThis();
|
||||
incrementCurSize(newChunk->computedSizeOfIncludingThis());
|
||||
unused_.pushFront(std::move(newChunk));
|
||||
incrementCurSize(size);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -325,6 +331,10 @@ void LifoAlloc::release(Mark mark) {
|
||||
cutAtMark(mark.chunk, chunks_);
|
||||
for (detail::BumpChunk& bc : released) {
|
||||
bc.release();
|
||||
|
||||
// Chunks moved from (after a mark) in chunks_ to unused_ are no longer
|
||||
// considered small allocations.
|
||||
smallAllocsSize_ -= bc.computedSizeOfIncludingThis();
|
||||
}
|
||||
unused_.appendAll(std::move(released));
|
||||
|
||||
@ -333,7 +343,6 @@ void LifoAlloc::release(Mark mark) {
|
||||
while (!released.empty()) {
|
||||
UniqueBumpChunk bc = released.popFirst();
|
||||
decrementCurSize(bc->computedSizeOfIncludingThis());
|
||||
oversizeSize_ -= bc->computedSizeOfIncludingThis();
|
||||
}
|
||||
}
|
||||
|
||||
@ -353,7 +362,7 @@ void LifoAlloc::steal(LifoAlloc* other) {
|
||||
oversizeThreshold_ = other->oversizeThreshold_;
|
||||
curSize_ = other->curSize_;
|
||||
peakSize_ = Max(peakSize_, other->peakSize_);
|
||||
oversizeSize_ = other->oversizeSize_;
|
||||
smallAllocsSize_ = other->smallAllocsSize_;
|
||||
#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
|
||||
fallibleScope_ = other->fallibleScope_;
|
||||
#endif
|
||||
@ -365,13 +374,19 @@ void LifoAlloc::transferFrom(LifoAlloc* other) {
|
||||
MOZ_ASSERT(!markCount);
|
||||
MOZ_ASSERT(!other->markCount);
|
||||
|
||||
// Transferred chunks are not counted as part of |smallAllocsSize| as this
|
||||
// could introduce bias in the |NextSize| heuristics, leading to
|
||||
// over-allocations in *this* LifoAlloc. As well, to avoid interference with
|
||||
// small allocations made with |this|, the last chunk of the |chunks_| list
|
||||
// should remain the last chunk. Therefore, the transferred chunks are
|
||||
// prepended to the |chunks_| list.
|
||||
incrementCurSize(other->curSize_);
|
||||
oversizeSize_ += other->oversizeSize_;
|
||||
|
||||
appendUnused(std::move(other->unused_));
|
||||
appendUsed(std::move(other->chunks_));
|
||||
oversize_.appendAll(std::move(other->oversize_));
|
||||
chunks_.prependAll(std::move(other->chunks_));
|
||||
oversize_.prependAll(std::move(other->oversize_));
|
||||
other->curSize_ = 0;
|
||||
other->oversizeSize_ = 0;
|
||||
other->smallAllocsSize_ = 0;
|
||||
}
|
||||
|
||||
void LifoAlloc::transferUnusedFrom(LifoAlloc* other) {
|
||||
|
@ -174,6 +174,17 @@ class SingleLinkedList {
|
||||
assertInvariants();
|
||||
list.assertInvariants();
|
||||
}
|
||||
void steal(SingleLinkedList&& list) {
|
||||
head_ = std::move(list.head_);
|
||||
last_ = list.last_;
|
||||
list.last_ = nullptr;
|
||||
assertInvariants();
|
||||
list.assertInvariants();
|
||||
}
|
||||
void prependAll(SingleLinkedList&& list) {
|
||||
list.appendAll(std::move(*this));
|
||||
steal(std::move(list));
|
||||
}
|
||||
UniquePtr<T, D> popFirst() {
|
||||
MOZ_ASSERT(head_);
|
||||
UniquePtr<T, D> result = std::move(head_);
|
||||
@ -505,7 +516,7 @@ class LifoAlloc {
|
||||
|
||||
// List of chunks containing allocated data where each allocation is larger
|
||||
// than the oversize threshold. Each chunk contains exactly on allocation.
|
||||
// This reduces wasted space in the normal chunk list.
|
||||
// This reduces wasted space in the chunk list.
|
||||
//
|
||||
// Oversize chunks are allocated on demand and freed as soon as they are
|
||||
// released, instead of being pushed to the unused list.
|
||||
@ -517,9 +528,16 @@ class LifoAlloc {
|
||||
size_t markCount;
|
||||
size_t defaultChunkSize_;
|
||||
size_t oversizeThreshold_;
|
||||
|
||||
// Size of all chunks in chunks_, oversize_, unused_ lists.
|
||||
size_t curSize_;
|
||||
size_t peakSize_;
|
||||
size_t oversizeSize_;
|
||||
|
||||
// Size of all chunks containing small bump allocations. This heuristic is
|
||||
// used to compute growth rate while ignoring chunks such as oversized,
|
||||
// now-unused, or transferred (which followed their own growth patterns).
|
||||
size_t smallAllocsSize_;
|
||||
|
||||
#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
|
||||
bool fallibleScope_;
|
||||
#endif
|
||||
@ -562,6 +580,7 @@ class LifoAlloc {
|
||||
void decrementCurSize(size_t size) {
|
||||
MOZ_ASSERT(curSize_ >= size);
|
||||
curSize_ -= size;
|
||||
MOZ_ASSERT(curSize_ >= smallAllocsSize_);
|
||||
}
|
||||
|
||||
void* allocImplColdPath(size_t n);
|
||||
@ -760,16 +779,22 @@ class LifoAlloc {
|
||||
public:
|
||||
void releaseAll() {
|
||||
MOZ_ASSERT(!markCount);
|
||||
|
||||
// When releasing all chunks, we can no longer determine which chunks were
|
||||
// transferred and which were not, so simply clear the heuristic to zero
|
||||
// right away.
|
||||
smallAllocsSize_ = 0;
|
||||
|
||||
for (detail::BumpChunk& bc : chunks_) {
|
||||
bc.release();
|
||||
}
|
||||
unused_.appendAll(std::move(chunks_));
|
||||
|
||||
// On release, we free any oversize allocations instead of keeping them
|
||||
// in unused chunks.
|
||||
while (!oversize_.empty()) {
|
||||
UniqueBumpChunk bc = oversize_.popFirst();
|
||||
decrementCurSize(bc->computedSizeOfIncludingThis());
|
||||
oversizeSize_ -= bc->computedSizeOfIncludingThis();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,6 +178,11 @@ def main(argv):
|
||||
op.add_option('--test-reflect-stringify', dest="test_reflect_stringify",
|
||||
help="instead of running tests, use them to test the "
|
||||
"Reflect.stringify code in specified file")
|
||||
op.add_option('--run-binast', action='store_true',
|
||||
dest="run_binast",
|
||||
help="By default BinAST testcases encoded from JS "
|
||||
"testcases are skipped. If specified, BinAST testcases "
|
||||
"are also executed.")
|
||||
|
||||
options, args = op.parse_args(argv)
|
||||
if len(args) < 1:
|
||||
@ -227,7 +232,7 @@ def main(argv):
|
||||
if test_args:
|
||||
read_all = False
|
||||
for arg in test_args:
|
||||
test_list += jittests.find_tests(arg)
|
||||
test_list += jittests.find_tests(arg, run_binast=options.run_binast)
|
||||
|
||||
if options.read_tests:
|
||||
read_all = False
|
||||
@ -247,7 +252,7 @@ def main(argv):
|
||||
sys.stderr.write('---\n')
|
||||
|
||||
if read_all:
|
||||
test_list = jittests.find_tests()
|
||||
test_list = jittests.find_tests(run_binast=options.run_binast)
|
||||
|
||||
# Exclude tests when code coverage is enabled.
|
||||
# This part is equivalent to:
|
||||
@ -281,7 +286,7 @@ def main(argv):
|
||||
if options.exclude:
|
||||
exclude_list = []
|
||||
for exclude in options.exclude:
|
||||
exclude_list += jittests.find_tests(exclude)
|
||||
exclude_list += jittests.find_tests(exclude, run_binast=options.run_binast)
|
||||
test_list = [test for test in test_list
|
||||
if test not in set(exclude_list)]
|
||||
|
||||
@ -327,8 +332,16 @@ def main(argv):
|
||||
read_all = False
|
||||
try:
|
||||
with open(options.ignore_timeouts) as f:
|
||||
options.ignore_timeouts = set(
|
||||
[line.strip('\n') for line in f.readlines()])
|
||||
ignore = set()
|
||||
for line in f.readlines():
|
||||
path = line.strip('\n')
|
||||
ignore.add(path)
|
||||
|
||||
binjs_path = path.replace('.js', '.binjs')
|
||||
# Do not use os.path.join to always use '/'.
|
||||
ignore.add('binast/nonlazy/{}'.format(binjs_path))
|
||||
ignore.add('binast/lazy/{}'.format(binjs_path))
|
||||
options.ignore_timeouts = ignore
|
||||
except IOError:
|
||||
sys.exit("Error reading file: " + options.ignore_timeouts)
|
||||
else:
|
||||
|
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/Bug981650.binjs
Normal file
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/Bug981650.binjs
Normal file
Binary file not shown.
Binary file not shown.
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug1096016.binjs
Normal file
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug1096016.binjs
Normal file
Binary file not shown.
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug1096023.binjs
Normal file
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug1096023.binjs
Normal file
Binary file not shown.
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug1103273-1.binjs
Normal file
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug1103273-1.binjs
Normal file
Binary file not shown.
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug1103273-2.binjs
Normal file
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug1103273-2.binjs
Normal file
Binary file not shown.
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug1232159.binjs
Normal file
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug1232159.binjs
Normal file
Binary file not shown.
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug1369774.binjs
Normal file
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug1369774.binjs
Normal file
Binary file not shown.
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug1510588.binjs
Normal file
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug1510588.binjs
Normal file
Binary file not shown.
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug920463.binjs
Normal file
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug920463.binjs
Normal file
Binary file not shown.
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug950458.binjs
Normal file
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug950458.binjs
Normal file
Binary file not shown.
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug953111.binjs
Normal file
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug953111.binjs
Normal file
Binary file not shown.
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug969159.binjs
Normal file
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug969159.binjs
Normal file
Binary file not shown.
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug970285.binjs
Normal file
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug970285.binjs
Normal file
Binary file not shown.
@ -0,0 +1 @@
|
||||
// |jit-test| error:TypeError
|
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug973563.binjs
Normal file
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug973563.binjs
Normal file
Binary file not shown.
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug976530.binjs
Normal file
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/bug976530.binjs
Normal file
Binary file not shown.
@ -0,0 +1 @@
|
||||
// |jit-test| error:Error
|
Binary file not shown.
@ -0,0 +1 @@
|
||||
|jit-test| skip-if: !this.hasOwnProperty("TypedObject")
|
Binary file not shown.
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/fuzz10.binjs
Normal file
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/fuzz10.binjs
Normal file
Binary file not shown.
1
js/src/jit-test/tests/binast/lazy/TypedObject/fuzz10.dir
Normal file
1
js/src/jit-test/tests/binast/lazy/TypedObject/fuzz10.dir
Normal file
@ -0,0 +1 @@
|
||||
// |jit-test| error:Error
|
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/fuzz11.binjs
Normal file
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/fuzz11.binjs
Normal file
Binary file not shown.
1
js/src/jit-test/tests/binast/lazy/TypedObject/fuzz11.dir
Normal file
1
js/src/jit-test/tests/binast/lazy/TypedObject/fuzz11.dir
Normal file
@ -0,0 +1 @@
|
||||
// |jit-test| error:Error
|
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/fuzz2.binjs
Normal file
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/fuzz2.binjs
Normal file
Binary file not shown.
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/fuzz4.binjs
Normal file
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/fuzz4.binjs
Normal file
Binary file not shown.
1
js/src/jit-test/tests/binast/lazy/TypedObject/fuzz4.dir
Normal file
1
js/src/jit-test/tests/binast/lazy/TypedObject/fuzz4.dir
Normal file
@ -0,0 +1 @@
|
||||
// |jit-test| error:Error;
|
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/fuzz5.binjs
Normal file
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/fuzz5.binjs
Normal file
Binary file not shown.
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/fuzz6.binjs
Normal file
BIN
js/src/jit-test/tests/binast/lazy/TypedObject/fuzz6.binjs
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user