Issue #1751 -- Remove cocoa and uikit widget support code

This commit is contained in:
Moonchild
2021-05-08 21:00:49 +00:00
parent ca35efb84e
commit 08da125d9c
165 changed files with 4 additions and 42109 deletions
-48
View File
@@ -1,48 +0,0 @@
/*
* Copyright (C) 2009 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 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.
*
* Modified by Josh Aas of Mozilla Corporation.
*/
#ifndef ComplexTextInputPanel_h_
#define ComplexTextInputPanel_h_
#include "nsString.h"
#include "npapi.h"
class ComplexTextInputPanel
{
public:
static ComplexTextInputPanel* GetSharedComplexTextInputPanel();
virtual void PlacePanel(int32_t x, int32_t y) = 0; // Bottom left coordinate of plugin in screen coords
virtual void InterpretKeyEvent(void* aEvent, nsAString& aOutText) = 0;
virtual bool IsInComposition() = 0;
virtual void* GetInputContext() = 0;
virtual void CancelComposition() = 0;
protected:
virtual ~ComplexTextInputPanel() {};
};
#endif // ComplexTextInputPanel_h_
-261
View File
@@ -1,261 +0,0 @@
/*
* Copyright (C) 2009 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 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.
*
* Modified by Josh Aas of Mozilla Corporation.
*/
#import "ComplexTextInputPanel.h"
#import <Cocoa/Cocoa.h>
#include <algorithm>
#include "mozilla/Preferences.h"
#include "nsChildView.h"
using namespace mozilla;
extern "C" OSStatus TSMProcessRawKeyEvent(EventRef anEvent);
#define kInputWindowHeight 20
@interface ComplexTextInputPanelImpl : NSPanel {
NSTextView *mInputTextView;
}
+ (ComplexTextInputPanelImpl*)sharedComplexTextInputPanelImpl;
- (NSTextInputContext*)inputContext;
- (void)interpretKeyEvent:(NSEvent*)event string:(NSString**)string;
- (void)cancelComposition;
- (BOOL)inComposition;
// This places the text input panel fully onscreen and below the lower left
// corner of the focused plugin.
- (void)adjustTo:(NSPoint)point;
@end
@implementation ComplexTextInputPanelImpl
+ (ComplexTextInputPanelImpl*)sharedComplexTextInputPanelImpl
{
static ComplexTextInputPanelImpl *sComplexTextInputPanelImpl;
if (!sComplexTextInputPanelImpl)
sComplexTextInputPanelImpl = [[ComplexTextInputPanelImpl alloc] init];
return sComplexTextInputPanelImpl;
}
- (id)init
{
// In the original Apple code the style mask is given by a function which is not open source.
// What could possibly be worth hiding in that function, I do not know.
// Courtesy of gdb: stylemask: 011000011111, 0x61f
self = [super initWithContentRect:NSZeroRect styleMask:0x61f backing:NSBackingStoreBuffered defer:YES];
if (!self)
return nil;
// Set the frame size.
NSRect visibleFrame = [[NSScreen mainScreen] visibleFrame];
NSRect frame = NSMakeRect(visibleFrame.origin.x, visibleFrame.origin.y, visibleFrame.size.width, kInputWindowHeight);
[self setFrame:frame display:NO];
mInputTextView = [[NSTextView alloc] initWithFrame:[self.contentView frame]];
mInputTextView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable | NSViewMaxXMargin | NSViewMinXMargin | NSViewMaxYMargin | NSViewMinYMargin;
NSScrollView* scrollView = [[NSScrollView alloc] initWithFrame:[self.contentView frame]];
scrollView.documentView = mInputTextView;
self.contentView = scrollView;
[scrollView release];
[self setFloatingPanel:YES];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardInputSourceChanged:)
name:NSTextInputContextKeyboardSelectionDidChangeNotification
object:nil];
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[mInputTextView release];
[super dealloc];
}
- (void)keyboardInputSourceChanged:(NSNotification *)notification
{
static int8_t sDoCancel = -1;
if (!sDoCancel || ![self inComposition]) {
return;
}
if (sDoCancel < 0) {
bool cancelComposition = false;
static const char* kPrefName =
"ui.plugin.cancel_composition_at_input_source_changed";
nsresult rv = Preferences::GetBool(kPrefName, &cancelComposition);
NS_ENSURE_SUCCESS(rv, );
sDoCancel = cancelComposition ? 1 : 0;
}
if (sDoCancel) {
[self cancelComposition];
}
}
- (void)interpretKeyEvent:(NSEvent*)event string:(NSString**)string
{
*string = nil;
if (![[mInputTextView inputContext] handleEvent:event]) {
return;
}
if ([mInputTextView hasMarkedText]) {
// Don't show the input method window for dead keys
if ([[event characters] length] > 0) {
[self orderFront:nil];
}
return;
} else {
[self orderOut:nil];
NSString *text = [[mInputTextView textStorage] string];
if ([text length] > 0) {
*string = [[text copy] autorelease];
}
}
[mInputTextView setString:@""];
}
- (NSTextInputContext*)inputContext
{
return [mInputTextView inputContext];
}
- (void)cancelComposition
{
[mInputTextView setString:@""];
[self orderOut:nil];
}
- (BOOL)inComposition
{
return [mInputTextView hasMarkedText];
}
- (void)adjustTo:(NSPoint)point
{
NSRect selfRect = [self frame];
NSRect rect = NSMakeRect(point.x,
point.y - selfRect.size.height,
500,
selfRect.size.height);
// Adjust to screen.
NSRect screenRect = [[NSScreen mainScreen] visibleFrame];
if (rect.origin.x < screenRect.origin.x) {
rect.origin.x = screenRect.origin.x;
}
if (rect.origin.y < screenRect.origin.y) {
rect.origin.y = screenRect.origin.y;
}
CGFloat xMostOfScreen = screenRect.origin.x + screenRect.size.width;
CGFloat yMostOfScreen = screenRect.origin.y + screenRect.size.height;
CGFloat xMost = rect.origin.x + rect.size.width;
CGFloat yMost = rect.origin.y + rect.size.height;
if (xMostOfScreen < xMost) {
rect.origin.x -= xMost - xMostOfScreen;
}
if (yMostOfScreen < yMost) {
rect.origin.y -= yMost - yMostOfScreen;
}
[self setFrame:rect display:[self isVisible]];
}
@end
class ComplexTextInputPanelPrivate : public ComplexTextInputPanel
{
public:
ComplexTextInputPanelPrivate();
virtual void InterpretKeyEvent(void* aEvent, nsAString& aOutText);
virtual bool IsInComposition();
virtual void PlacePanel(int32_t x, int32_t y);
virtual void* GetInputContext() { return [mPanel inputContext]; }
virtual void CancelComposition() { [mPanel cancelComposition]; }
private:
~ComplexTextInputPanelPrivate();
ComplexTextInputPanelImpl* mPanel;
};
ComplexTextInputPanelPrivate::ComplexTextInputPanelPrivate()
{
mPanel = [[ComplexTextInputPanelImpl alloc] init];
}
ComplexTextInputPanelPrivate::~ComplexTextInputPanelPrivate()
{
[mPanel release];
}
ComplexTextInputPanel*
ComplexTextInputPanel::GetSharedComplexTextInputPanel()
{
static ComplexTextInputPanelPrivate *sComplexTextInputPanelPrivate;
if (!sComplexTextInputPanelPrivate) {
sComplexTextInputPanelPrivate = new ComplexTextInputPanelPrivate();
}
return sComplexTextInputPanelPrivate;
}
void
ComplexTextInputPanelPrivate::InterpretKeyEvent(void* aEvent, nsAString& aOutText)
{
NSString* textString = nil;
[mPanel interpretKeyEvent:(NSEvent*)aEvent string:&textString];
if (textString) {
nsCocoaUtils::GetStringForNSString(textString, aOutText);
}
}
bool
ComplexTextInputPanelPrivate::IsInComposition()
{
return !![mPanel inComposition];
}
void
ComplexTextInputPanelPrivate::PlacePanel(int32_t x, int32_t y)
{
[mPanel adjustTo:NSMakePoint(x, y)];
}
-18
View File
@@ -1,18 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* This file defines constants to be used in the "subtype" field of
* NSApplicationDefined type NSEvents.
*/
#ifndef WIDGET_COCOA_CUSTOMCOCOAEVENTS_H_
#define WIDGET_COCOA_CUSTOMCOCOAEVENTS_H_
// Empty event, just used for prodding the event loop into responding.
const short kEventSubtypeNone = 0;
// Tracer event, used for timing the event loop responsiveness.
const short kEventSubtypeTrace = 1;
#endif /* WIDGET_COCOA_CUSTOMCOCOAEVENTS_H_ */
-95
View File
@@ -1,95 +0,0 @@
/* vim: se cin sw=2 ts=2 et : */
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef __mozilla_widget_GfxInfo_h__
#define __mozilla_widget_GfxInfo_h__
#include "GfxInfoBase.h"
#include "nsString.h"
namespace mozilla {
namespace widget {
class GfxInfo : public GfxInfoBase
{
public:
GfxInfo();
// We only declare the subset of nsIGfxInfo that we actually implement. The
// rest is brought forward from GfxInfoBase.
NS_IMETHOD GetD2DEnabled(bool *aD2DEnabled) override;
NS_IMETHOD GetDWriteEnabled(bool *aDWriteEnabled) override;
NS_IMETHOD GetDWriteVersion(nsAString & aDwriteVersion) override;
NS_IMETHOD GetCleartypeParameters(nsAString & aCleartypeParams) override;
NS_IMETHOD GetAdapterDescription(nsAString & aAdapterDescription) override;
NS_IMETHOD GetAdapterDriver(nsAString & aAdapterDriver) override;
NS_IMETHOD GetAdapterVendorID(nsAString & aAdapterVendorID) override;
NS_IMETHOD GetAdapterDeviceID(nsAString & aAdapterDeviceID) override;
NS_IMETHOD GetAdapterSubsysID(nsAString & aAdapterSubsysID) override;
NS_IMETHOD GetAdapterRAM(nsAString & aAdapterRAM) override;
NS_IMETHOD GetAdapterDriverVersion(nsAString & aAdapterDriverVersion) override;
NS_IMETHOD GetAdapterDriverDate(nsAString & aAdapterDriverDate) override;
NS_IMETHOD GetAdapterDescription2(nsAString & aAdapterDescription) override;
NS_IMETHOD GetAdapterDriver2(nsAString & aAdapterDriver) override;
NS_IMETHOD GetAdapterVendorID2(nsAString & aAdapterVendorID) override;
NS_IMETHOD GetAdapterDeviceID2(nsAString & aAdapterDeviceID) override;
NS_IMETHOD GetAdapterSubsysID2(nsAString & aAdapterSubsysID) override;
NS_IMETHOD GetAdapterRAM2(nsAString & aAdapterRAM) override;
NS_IMETHOD GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion) override;
NS_IMETHOD GetAdapterDriverDate2(nsAString & aAdapterDriverDate) override;
NS_IMETHOD GetIsGPU2Active(bool *aIsGPU2Active) override;
using GfxInfoBase::GetFeatureStatus;
using GfxInfoBase::GetFeatureSuggestedDriverVersion;
using GfxInfoBase::GetWebGLParameter;
virtual nsresult Init() override;
#ifdef DEBUG
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIGFXINFODEBUG
#endif
virtual uint32_t OperatingSystemVersion() override { return mOSXVersion; }
nsresult FindMonitors(JSContext* cx, JS::HandleObject array) override;
protected:
virtual ~GfxInfo() {}
virtual nsresult GetFeatureStatusImpl(int32_t aFeature,
int32_t *aStatus,
nsAString & aSuggestedDriverVersion,
const nsTArray<GfxDriverInfo>& aDriverInfo,
nsACString &aFailureId,
OperatingSystem* aOS = nullptr) override;
virtual const nsTArray<GfxDriverInfo>& GetGfxDriverInfo() override;
private:
void GetDeviceInfo();
void GetSelectedCityInfo();
void AddCrashReportAnnotations();
nsString mAdapterRAMString;
nsString mDeviceID;
nsString mDriverVersion;
nsString mDriverDate;
nsString mDeviceKey;
nsString mAdapterVendorID;
nsString mAdapterDeviceID;
uint32_t mOSXVersion;
};
} // namespace widget
} // namespace mozilla
#endif /* __mozilla_widget_GfxInfo_h__ */
-426
View File
@@ -1,426 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <OpenGL/OpenGL.h>
#include <OpenGL/CGLRenderers.h>
#include "mozilla/ArrayUtils.h"
#include "GfxInfo.h"
#include "nsUnicharUtils.h"
#include "nsCocoaFeatures.h"
#include "mozilla/Preferences.h"
#include <algorithm>
#import <Foundation/Foundation.h>
#import <IOKit/IOKitLib.h>
#import <Cocoa/Cocoa.h>
using namespace mozilla;
using namespace mozilla::widget;
#ifdef DEBUG
NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, GfxInfoBase, nsIGfxInfoDebug)
#endif
GfxInfo::GfxInfo()
{
}
static OperatingSystem
OSXVersionToOperatingSystem(uint32_t aOSXVersion) {
switch (nsCocoaFeatures::ExtractMajorVersion(aOSXVersion)) {
case 10:
switch (nsCocoaFeatures::ExtractMinorVersion(aOSXVersion)) {
case 6:
return OperatingSystem::OSX10_6;
case 7:
return OperatingSystem::OSX10_7;
case 8:
return OperatingSystem::OSX10_8;
case 9:
return OperatingSystem::OSX10_9;
case 10:
return OperatingSystem::OSX10_10;
case 11:
return OperatingSystem::OSX10_11;
case 12:
return OperatingSystem::OSX10_12;
case 13:
return OperatingSystem::OSX10_13;
case 14:
return OperatingSystem::OSX10_14;
case 15:
return OperatingSystem::OSX10_15;
case 16:
// Depending on the SDK version, we either get 10.16 or 11.0.
// Normalize this to 11.0.
return OperatingSystem::OSX11_0;
default:
break;
}
break;
case 11:
switch (nsCocoaFeatures::ExtractMinorVersion(aOSXVersion)) {
case 0:
return OperatingSystem::OSX11_0;
default:
break;
}
break;
}
return OperatingSystem::Unknown;
}
// The following three functions are derived from Chromium code
static CFTypeRef SearchPortForProperty(io_registry_entry_t dspPort,
CFStringRef propertyName)
{
return IORegistryEntrySearchCFProperty(dspPort,
kIOServicePlane,
propertyName,
kCFAllocatorDefault,
kIORegistryIterateRecursively |
kIORegistryIterateParents);
}
static uint32_t IntValueOfCFData(CFDataRef d)
{
uint32_t value = 0;
if (d) {
const uint32_t *vp = reinterpret_cast<const uint32_t*>(CFDataGetBytePtr(d));
if (vp != NULL)
value = *vp;
}
return value;
}
void
GfxInfo::GetDeviceInfo()
{
io_registry_entry_t dsp_port = CGDisplayIOServicePort(kCGDirectMainDisplay);
CFTypeRef vendor_id_ref = SearchPortForProperty(dsp_port, CFSTR("vendor-id"));
if (vendor_id_ref) {
mAdapterVendorID.AppendPrintf("0x%04x", IntValueOfCFData((CFDataRef)vendor_id_ref));
CFRelease(vendor_id_ref);
}
CFTypeRef device_id_ref = SearchPortForProperty(dsp_port, CFSTR("device-id"));
if (device_id_ref) {
mAdapterDeviceID.AppendPrintf("0x%04x", IntValueOfCFData((CFDataRef)device_id_ref));
CFRelease(device_id_ref);
}
}
nsresult
GfxInfo::Init()
{
nsresult rv = GfxInfoBase::Init();
// Calling CGLQueryRendererInfo causes us to switch to the discrete GPU
// even when we don't want to. We'll avoid doing so for now and just
// use the device ids.
GetDeviceInfo();
AddCrashReportAnnotations();
mOSXVersion = nsCocoaFeatures::macOSVersion();
return rv;
}
NS_IMETHODIMP
GfxInfo::GetD2DEnabled(bool *aEnabled)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
GfxInfo::GetDWriteEnabled(bool *aEnabled)
{
return NS_ERROR_FAILURE;
}
/* readonly attribute DOMString DWriteVersion; */
NS_IMETHODIMP
GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)
{
return NS_ERROR_FAILURE;
}
/* readonly attribute DOMString cleartypeParameters; */
NS_IMETHODIMP
GfxInfo::GetCleartypeParameters(nsAString & aCleartypeParams)
{
return NS_ERROR_FAILURE;
}
/* readonly attribute DOMString adapterDescription; */
NS_IMETHODIMP
GfxInfo::GetAdapterDescription(nsAString & aAdapterDescription)
{
aAdapterDescription.AssignLiteral("");
return NS_OK;
}
/* readonly attribute DOMString adapterDescription2; */
NS_IMETHODIMP
GfxInfo::GetAdapterDescription2(nsAString & aAdapterDescription)
{
return NS_ERROR_FAILURE;
}
/* readonly attribute DOMString adapterRAM; */
NS_IMETHODIMP
GfxInfo::GetAdapterRAM(nsAString & aAdapterRAM)
{
aAdapterRAM = mAdapterRAMString;
return NS_OK;
}
/* readonly attribute DOMString adapterRAM2; */
NS_IMETHODIMP
GfxInfo::GetAdapterRAM2(nsAString & aAdapterRAM)
{
return NS_ERROR_FAILURE;
}
/* readonly attribute DOMString adapterDriver; */
NS_IMETHODIMP
GfxInfo::GetAdapterDriver(nsAString & aAdapterDriver)
{
aAdapterDriver.AssignLiteral("");
return NS_OK;
}
/* readonly attribute DOMString adapterDriver2; */
NS_IMETHODIMP
GfxInfo::GetAdapterDriver2(nsAString & aAdapterDriver)
{
return NS_ERROR_FAILURE;
}
/* readonly attribute DOMString adapterDriverVersion; */
NS_IMETHODIMP
GfxInfo::GetAdapterDriverVersion(nsAString & aAdapterDriverVersion)
{
aAdapterDriverVersion.AssignLiteral("");
return NS_OK;
}
/* readonly attribute DOMString adapterDriverVersion2; */
NS_IMETHODIMP
GfxInfo::GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion)
{
return NS_ERROR_FAILURE;
}
/* readonly attribute DOMString adapterDriverDate; */
NS_IMETHODIMP
GfxInfo::GetAdapterDriverDate(nsAString & aAdapterDriverDate)
{
aAdapterDriverDate.AssignLiteral("");
return NS_OK;
}
/* readonly attribute DOMString adapterDriverDate2; */
NS_IMETHODIMP
GfxInfo::GetAdapterDriverDate2(nsAString & aAdapterDriverDate)
{
return NS_ERROR_FAILURE;
}
/* readonly attribute DOMString adapterVendorID; */
NS_IMETHODIMP
GfxInfo::GetAdapterVendorID(nsAString & aAdapterVendorID)
{
aAdapterVendorID = mAdapterVendorID;
return NS_OK;
}
/* readonly attribute DOMString adapterVendorID2; */
NS_IMETHODIMP
GfxInfo::GetAdapterVendorID2(nsAString & aAdapterVendorID)
{
return NS_ERROR_FAILURE;
}
/* readonly attribute DOMString adapterDeviceID; */
NS_IMETHODIMP
GfxInfo::GetAdapterDeviceID(nsAString & aAdapterDeviceID)
{
aAdapterDeviceID = mAdapterDeviceID;
return NS_OK;
}
/* readonly attribute DOMString adapterDeviceID2; */
NS_IMETHODIMP
GfxInfo::GetAdapterDeviceID2(nsAString & aAdapterDeviceID)
{
return NS_ERROR_FAILURE;
}
/* readonly attribute DOMString adapterSubsysID; */
NS_IMETHODIMP
GfxInfo::GetAdapterSubsysID(nsAString & aAdapterSubsysID)
{
return NS_ERROR_FAILURE;
}
/* readonly attribute DOMString adapterSubsysID2; */
NS_IMETHODIMP
GfxInfo::GetAdapterSubsysID2(nsAString & aAdapterSubsysID)
{
return NS_ERROR_FAILURE;
}
/* readonly attribute boolean isGPU2Active; */
NS_IMETHODIMP
GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active)
{
return NS_ERROR_FAILURE;
}
void
GfxInfo::AddCrashReportAnnotations()
{
/*** STUB ***/
}
// We don't support checking driver versions on Mac.
#define IMPLEMENT_MAC_DRIVER_BLOCKLIST(os, vendor, device, features, blockOn, ruleId) \
APPEND_TO_DRIVER_BLOCKLIST(os, vendor, device, features, blockOn, \
DRIVER_COMPARISON_IGNORED, V(0,0,0,0), ruleId, "")
const nsTArray<GfxDriverInfo>&
GfxInfo::GetGfxDriverInfo()
{
if (!mDriverInfo->Length()) {
IMPLEMENT_MAC_DRIVER_BLOCKLIST(OperatingSystem::OSX,
(nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices,
nsIGfxInfo::FEATURE_WEBGL_MSAA, nsIGfxInfo::FEATURE_BLOCKED_OS_VERSION, "FEATURE_FAILURE_MAC_ATI_NO_MSAA");
IMPLEMENT_MAC_DRIVER_BLOCKLIST(OperatingSystem::OSX,
(nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(RadeonX1000),
nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_BLOCKED_DEVICE, "FEATURE_FAILURE_MAC_RADEONX1000_NO_TEXTURE2D");
IMPLEMENT_MAC_DRIVER_BLOCKLIST(OperatingSystem::OSX,
(nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(Geforce7300GT),
nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_BLOCKED_DEVICE, "FEATURE_FAILURE_MAC_7300_NO_WEBGL");
}
return *mDriverInfo;
}
nsresult
GfxInfo::GetFeatureStatusImpl(int32_t aFeature,
int32_t* aStatus,
nsAString& aSuggestedDriverVersion,
const nsTArray<GfxDriverInfo>& aDriverInfo,
nsACString& aFailureId,
OperatingSystem* aOS /* = nullptr */)
{
NS_ENSURE_ARG_POINTER(aStatus);
aSuggestedDriverVersion.SetIsVoid(true);
*aStatus = nsIGfxInfo::FEATURE_STATUS_UNKNOWN;
OperatingSystem os = OSXVersionToOperatingSystem(mOSXVersion);
if (aOS)
*aOS = os;
if (mShutdownOccurred) {
return NS_OK;
}
// Don't evaluate special cases when we're evaluating the downloaded blocklist.
if (!aDriverInfo.Length()) {
if (aFeature == nsIGfxInfo::FEATURE_WEBGL_MSAA) {
// Blacklist all ATI cards on OSX, except for
// 0x6760 and 0x9488
if (mAdapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorATI), nsCaseInsensitiveStringComparator()) &&
(mAdapterDeviceID.LowerCaseEqualsLiteral("0x6760") ||
mAdapterDeviceID.LowerCaseEqualsLiteral("0x9488"))) {
*aStatus = nsIGfxInfo::FEATURE_STATUS_OK;
return NS_OK;
}
} else if (aFeature == nsIGfxInfo::FEATURE_CANVAS2D_ACCELERATION) {
// See bug 1249659
switch(os) {
case OperatingSystem::OSX10_5:
case OperatingSystem::OSX10_6:
case OperatingSystem::OSX10_7:
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_OS_VERSION;
aFailureId = "FEATURE_FAILURE_CANVAS_OSX_VERSION";
break;
default:
*aStatus = nsIGfxInfo::FEATURE_STATUS_OK;
break;
}
return NS_OK;
}
}
return GfxInfoBase::GetFeatureStatusImpl(aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, aFailureId, &os);
}
nsresult
GfxInfo::FindMonitors(JSContext* aCx, JS::HandleObject aOutArray)
{
// Getting the refresh rate is a little hard on OS X. We could use
// CVDisplayLinkGetNominalOutputVideoRefreshPeriod, but that's a little
// involved. Ideally we could query it from vsync. For now, we leave it out.
int32_t deviceCount = 0;
for (NSScreen* screen in [NSScreen screens]) {
NSRect rect = [screen frame];
JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
JS::Rooted<JS::Value> screenWidth(aCx, JS::Int32Value((int)rect.size.width));
JS_SetProperty(aCx, obj, "screenWidth", screenWidth);
JS::Rooted<JS::Value> screenHeight(aCx, JS::Int32Value((int)rect.size.height));
JS_SetProperty(aCx, obj, "screenHeight", screenHeight);
JS::Rooted<JS::Value> scale(aCx, JS::NumberValue(nsCocoaUtils::GetBackingScaleFactor(screen)));
JS_SetProperty(aCx, obj, "scale", scale);
JS::Rooted<JS::Value> element(aCx, JS::ObjectValue(*obj));
JS_SetElement(aCx, aOutArray, deviceCount++, element);
}
return NS_OK;
}
#ifdef DEBUG
// Implement nsIGfxInfoDebug
/* void spoofVendorID (in DOMString aVendorID); */
NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString & aVendorID)
{
mAdapterVendorID = aVendorID;
return NS_OK;
}
/* void spoofDeviceID (in unsigned long aDeviceID); */
NS_IMETHODIMP GfxInfo::SpoofDeviceID(const nsAString & aDeviceID)
{
mAdapterDeviceID = aDeviceID;
return NS_OK;
}
/* void spoofDriverVersion (in DOMString aDriverVersion); */
NS_IMETHODIMP GfxInfo::SpoofDriverVersion(const nsAString & aDriverVersion)
{
mDriverVersion = aDriverVersion;
return NS_OK;
}
/* void spoofOSVersion (in unsigned long aVersion); */
NS_IMETHODIMP GfxInfo::SpoofOSVersion(uint32_t aVersion)
{
mOSXVersion = aVersion;
return NS_OK;
}
#endif
-48
View File
@@ -1,48 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_widget_NativeKeyBindings_h_
#define mozilla_widget_NativeKeyBindings_h_
#import <Cocoa/Cocoa.h>
#include "mozilla/Attributes.h"
#include "mozilla/EventForwards.h"
#include "nsDataHashtable.h"
#include "nsIWidget.h"
namespace mozilla {
namespace widget {
typedef nsDataHashtable<nsPtrHashKey<struct objc_selector>, CommandInt>
SelectorCommandHashtable;
class NativeKeyBindings final
{
typedef nsIWidget::NativeKeyBindingsType NativeKeyBindingsType;
typedef nsIWidget::DoCommandCallback DoCommandCallback;
public:
static NativeKeyBindings* GetInstance(NativeKeyBindingsType aType);
static void Shutdown();
void Init(NativeKeyBindingsType aType);
bool Execute(const WidgetKeyboardEvent& aEvent,
DoCommandCallback aCallback,
void* aCallbackData);
private:
NativeKeyBindings();
SelectorCommandHashtable mSelectorToCommand;
static NativeKeyBindings* sInstanceForSingleLineEditor;
static NativeKeyBindings* sInstanceForMultiLineEditor;
}; // NativeKeyBindings
} // namespace widget
} // namespace mozilla
#endif // mozilla_widget_NativeKeyBindings_h_
-292
View File
@@ -1,292 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "NativeKeyBindings.h"
#include "nsTArray.h"
#include "nsCocoaUtils.h"
#include "mozilla/Logging.h"
#include "mozilla/TextEvents.h"
namespace mozilla {
namespace widget {
PRLogModuleInfo* gNativeKeyBindingsLog = nullptr;
NativeKeyBindings* NativeKeyBindings::sInstanceForSingleLineEditor = nullptr;
NativeKeyBindings* NativeKeyBindings::sInstanceForMultiLineEditor = nullptr;
// static
NativeKeyBindings*
NativeKeyBindings::GetInstance(NativeKeyBindingsType aType)
{
switch (aType) {
case nsIWidget::NativeKeyBindingsForSingleLineEditor:
if (!sInstanceForSingleLineEditor) {
sInstanceForSingleLineEditor = new NativeKeyBindings();
sInstanceForSingleLineEditor->Init(aType);
}
return sInstanceForSingleLineEditor;
case nsIWidget::NativeKeyBindingsForMultiLineEditor:
case nsIWidget::NativeKeyBindingsForRichTextEditor:
if (!sInstanceForMultiLineEditor) {
sInstanceForMultiLineEditor = new NativeKeyBindings();
sInstanceForMultiLineEditor->Init(aType);
}
return sInstanceForMultiLineEditor;
default:
MOZ_CRASH("Not implemented");
return nullptr;
}
}
// static
void
NativeKeyBindings::Shutdown()
{
delete sInstanceForSingleLineEditor;
sInstanceForSingleLineEditor = nullptr;
delete sInstanceForMultiLineEditor;
sInstanceForMultiLineEditor = nullptr;
}
NativeKeyBindings::NativeKeyBindings()
{
}
#define SEL_TO_COMMAND(aSel, aCommand) \
mSelectorToCommand.Put( \
reinterpret_cast<struct objc_selector *>(@selector(aSel)), aCommand)
void
NativeKeyBindings::Init(NativeKeyBindingsType aType)
{
if (!gNativeKeyBindingsLog) {
gNativeKeyBindingsLog = PR_NewLogModule("NativeKeyBindings");
}
MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info,
("%p NativeKeyBindings::Init", this));
// Many selectors have a one-to-one mapping to a Gecko command. Those mappings
// are registered in mSelectorToCommand.
// Selectors from NSResponder's "Responding to Action Messages" section and
// from NSText's "Action Methods for Editing" section
// TODO: Improves correctness of left / right meaning
// TODO: Add real paragraph motions
// SEL_TO_COMMAND(cancelOperation:, );
// SEL_TO_COMMAND(capitalizeWord:, );
// SEL_TO_COMMAND(centerSelectionInVisibleArea:, );
// SEL_TO_COMMAND(changeCaseOfLetter:, );
// SEL_TO_COMMAND(complete:, );
SEL_TO_COMMAND(copy:, CommandCopy);
// SEL_TO_COMMAND(copyFont:, );
// SEL_TO_COMMAND(copyRuler:, );
SEL_TO_COMMAND(cut:, CommandCut);
SEL_TO_COMMAND(delete:, CommandDelete);
SEL_TO_COMMAND(deleteBackward:, CommandDeleteCharBackward);
// SEL_TO_COMMAND(deleteBackwardByDecomposingPreviousCharacter:, );
SEL_TO_COMMAND(deleteForward:, CommandDeleteCharForward);
// TODO: deleteTo* selectors are also supposed to add text to a kill buffer
SEL_TO_COMMAND(deleteToBeginningOfLine:, CommandDeleteToBeginningOfLine);
SEL_TO_COMMAND(deleteToBeginningOfParagraph:, CommandDeleteToBeginningOfLine);
SEL_TO_COMMAND(deleteToEndOfLine:, CommandDeleteToEndOfLine);
SEL_TO_COMMAND(deleteToEndOfParagraph:, CommandDeleteToEndOfLine);
// SEL_TO_COMMAND(deleteToMark:, );
SEL_TO_COMMAND(deleteWordBackward:, CommandDeleteWordBackward);
SEL_TO_COMMAND(deleteWordForward:, CommandDeleteWordForward);
// SEL_TO_COMMAND(indent:, );
// SEL_TO_COMMAND(insertBacktab:, );
// SEL_TO_COMMAND(insertContainerBreak:, );
// SEL_TO_COMMAND(insertLineBreak:, );
// SEL_TO_COMMAND(insertNewline:, );
// SEL_TO_COMMAND(insertNewlineIgnoringFieldEditor:, );
// SEL_TO_COMMAND(insertParagraphSeparator:, );
// SEL_TO_COMMAND(insertTab:, );
// SEL_TO_COMMAND(insertTabIgnoringFieldEditor:, );
// SEL_TO_COMMAND(insertDoubleQuoteIgnoringSubstitution:, );
// SEL_TO_COMMAND(insertSingleQuoteIgnoringSubstitution:, );
// SEL_TO_COMMAND(lowercaseWord:, );
SEL_TO_COMMAND(moveBackward:, CommandCharPrevious);
SEL_TO_COMMAND(moveBackwardAndModifySelection:, CommandSelectCharPrevious);
if (aType == nsIWidget::NativeKeyBindingsForSingleLineEditor) {
SEL_TO_COMMAND(moveDown:, CommandEndLine);
} else {
SEL_TO_COMMAND(moveDown:, CommandLineNext);
}
SEL_TO_COMMAND(moveDownAndModifySelection:, CommandSelectLineNext);
SEL_TO_COMMAND(moveForward:, CommandCharNext);
SEL_TO_COMMAND(moveForwardAndModifySelection:, CommandSelectCharNext);
SEL_TO_COMMAND(moveLeft:, CommandCharPrevious);
SEL_TO_COMMAND(moveLeftAndModifySelection:, CommandSelectCharPrevious);
SEL_TO_COMMAND(moveParagraphBackwardAndModifySelection:,
CommandSelectBeginLine);
SEL_TO_COMMAND(moveParagraphForwardAndModifySelection:, CommandSelectEndLine);
SEL_TO_COMMAND(moveRight:, CommandCharNext);
SEL_TO_COMMAND(moveRightAndModifySelection:, CommandSelectCharNext);
SEL_TO_COMMAND(moveToBeginningOfDocument:, CommandMoveTop);
SEL_TO_COMMAND(moveToBeginningOfDocumentAndModifySelection:,
CommandSelectTop);
SEL_TO_COMMAND(moveToBeginningOfLine:, CommandBeginLine);
SEL_TO_COMMAND(moveToBeginningOfLineAndModifySelection:,
CommandSelectBeginLine);
SEL_TO_COMMAND(moveToBeginningOfParagraph:, CommandBeginLine);
SEL_TO_COMMAND(moveToBeginningOfParagraphAndModifySelection:,
CommandSelectBeginLine);
SEL_TO_COMMAND(moveToEndOfDocument:, CommandMoveBottom);
SEL_TO_COMMAND(moveToEndOfDocumentAndModifySelection:, CommandSelectBottom);
SEL_TO_COMMAND(moveToEndOfLine:, CommandEndLine);
SEL_TO_COMMAND(moveToEndOfLineAndModifySelection:, CommandSelectEndLine);
SEL_TO_COMMAND(moveToEndOfParagraph:, CommandEndLine);
SEL_TO_COMMAND(moveToEndOfParagraphAndModifySelection:, CommandSelectEndLine);
SEL_TO_COMMAND(moveToLeftEndOfLine:, CommandBeginLine);
SEL_TO_COMMAND(moveToLeftEndOfLineAndModifySelection:,
CommandSelectBeginLine);
SEL_TO_COMMAND(moveToRightEndOfLine:, CommandEndLine);
SEL_TO_COMMAND(moveToRightEndOfLineAndModifySelection:, CommandSelectEndLine);
if (aType == nsIWidget::NativeKeyBindingsForSingleLineEditor) {
SEL_TO_COMMAND(moveUp:, CommandBeginLine);
} else {
SEL_TO_COMMAND(moveUp:, CommandLinePrevious);
}
SEL_TO_COMMAND(moveUpAndModifySelection:, CommandSelectLinePrevious);
SEL_TO_COMMAND(moveWordBackward:, CommandWordPrevious);
SEL_TO_COMMAND(moveWordBackwardAndModifySelection:,
CommandSelectWordPrevious);
SEL_TO_COMMAND(moveWordForward:, CommandWordNext);
SEL_TO_COMMAND(moveWordForwardAndModifySelection:, CommandSelectWordNext);
SEL_TO_COMMAND(moveWordLeft:, CommandWordPrevious);
SEL_TO_COMMAND(moveWordLeftAndModifySelection:, CommandSelectWordPrevious);
SEL_TO_COMMAND(moveWordRight:, CommandWordNext);
SEL_TO_COMMAND(moveWordRightAndModifySelection:, CommandSelectWordNext);
SEL_TO_COMMAND(pageDown:, CommandMovePageDown);
SEL_TO_COMMAND(pageDownAndModifySelection:, CommandSelectPageDown);
SEL_TO_COMMAND(pageUp:, CommandMovePageUp);
SEL_TO_COMMAND(pageUpAndModifySelection:, CommandSelectPageUp);
SEL_TO_COMMAND(paste:, CommandPaste);
// SEL_TO_COMMAND(pasteFont:, );
// SEL_TO_COMMAND(pasteRuler:, );
SEL_TO_COMMAND(scrollLineDown:, CommandScrollLineDown);
SEL_TO_COMMAND(scrollLineUp:, CommandScrollLineUp);
SEL_TO_COMMAND(scrollPageDown:, CommandScrollPageDown);
SEL_TO_COMMAND(scrollPageUp:, CommandScrollPageUp);
SEL_TO_COMMAND(scrollToBeginningOfDocument:, CommandScrollTop);
SEL_TO_COMMAND(scrollToEndOfDocument:, CommandScrollBottom);
SEL_TO_COMMAND(selectAll:, CommandSelectAll);
// selectLine: is complex, see KeyDown
if (aType == nsIWidget::NativeKeyBindingsForSingleLineEditor) {
SEL_TO_COMMAND(selectParagraph:, CommandSelectAll);
}
// SEL_TO_COMMAND(selectToMark:, );
// selectWord: is complex, see KeyDown
// SEL_TO_COMMAND(setMark:, );
// SEL_TO_COMMAND(showContextHelp:, );
// SEL_TO_COMMAND(supplementalTargetForAction:sender:, );
// SEL_TO_COMMAND(swapWithMark:, );
// SEL_TO_COMMAND(transpose:, );
// SEL_TO_COMMAND(transposeWords:, );
// SEL_TO_COMMAND(uppercaseWord:, );
// SEL_TO_COMMAND(yank:, );
}
#undef SEL_TO_COMMAND
bool
NativeKeyBindings::Execute(const WidgetKeyboardEvent& aEvent,
DoCommandCallback aCallback,
void* aCallbackData)
{
MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info,
("%p NativeKeyBindings::KeyPress", this));
// Recover the current event, which should always be the key down we are
// responding to.
NSEvent* cocoaEvent = reinterpret_cast<NSEvent*>(aEvent.mNativeKeyEvent);
if (!cocoaEvent || [cocoaEvent type] != NSKeyDown) {
MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info,
("%p NativeKeyBindings::KeyPress, no Cocoa key down event", this));
return false;
}
MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info,
("%p NativeKeyBindings::KeyPress, interpreting", this));
AutoTArray<KeyBindingsCommand, 2> bindingCommands;
nsCocoaUtils::GetCommandsFromKeyEvent(cocoaEvent, bindingCommands);
MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info,
("%p NativeKeyBindings::KeyPress, bindingCommands=%u",
this, bindingCommands.Length()));
AutoTArray<Command, 4> geckoCommands;
for (uint32_t i = 0; i < bindingCommands.Length(); i++) {
SEL selector = bindingCommands[i].selector;
if (MOZ_LOG_TEST(gNativeKeyBindingsLog, LogLevel::Info)) {
NSString* selectorString = NSStringFromSelector(selector);
nsAutoString nsSelectorString;
nsCocoaUtils::GetStringForNSString(selectorString, nsSelectorString);
MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info,
("%p NativeKeyBindings::KeyPress, selector=%s",
this, NS_LossyConvertUTF16toASCII(nsSelectorString).get()));
}
// Try to find a simple mapping in the hashtable
Command geckoCommand = static_cast<Command>(mSelectorToCommand.Get(
reinterpret_cast<struct objc_selector*>(selector)));
if (geckoCommand) {
geckoCommands.AppendElement(geckoCommand);
} else if (selector == @selector(selectLine:)) {
// This is functional, but Cocoa's version is direction-less in that
// selection direction is not determined until some future directed action
// is taken. See bug 282097, comment 79 for more details.
geckoCommands.AppendElement(CommandBeginLine);
geckoCommands.AppendElement(CommandSelectEndLine);
} else if (selector == @selector(selectWord:)) {
// This is functional, but Cocoa's version is direction-less in that
// selection direction is not determined until some future directed action
// is taken. See bug 282097, comment 79 for more details.
geckoCommands.AppendElement(CommandWordPrevious);
geckoCommands.AppendElement(CommandSelectWordNext);
}
}
if (geckoCommands.IsEmpty()) {
MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info,
("%p NativeKeyBindings::KeyPress, handled=false", this));
return false;
}
for (uint32_t i = 0; i < geckoCommands.Length(); i++) {
Command geckoCommand = geckoCommands[i];
MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info,
("%p NativeKeyBindings::KeyPress, command=%s",
this, WidgetKeyboardEvent::GetCommandStr(geckoCommand)));
// Execute the Gecko command
aCallback(geckoCommand, aCallbackData);
}
MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info,
("%p NativeKeyBindings::KeyPress, handled=true", this));
return true;
}
} // namespace widget
} // namespace mozilla
-55
View File
@@ -1,55 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef OSXNotificationCenter_h
#define OSXNotificationCenter_h
#import <Foundation/Foundation.h>
#include "nsIAlertsService.h"
#include "imgINotificationObserver.h"
#include "nsITimer.h"
#include "nsTArray.h"
#include "mozilla/RefPtr.h"
@class mozNotificationCenterDelegate;
#if !defined(MAC_OS_X_VERSION_10_8) || (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8)
typedef NSInteger NSUserNotificationActivationType;
#endif
namespace mozilla {
class OSXNotificationInfo;
class OSXNotificationCenter : public nsIAlertsService,
public nsIAlertsIconData,
public nsIAlertNotificationImageListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIALERTSSERVICE
NS_DECL_NSIALERTSICONDATA
NS_DECL_NSIALERTNOTIFICATIONIMAGELISTENER
OSXNotificationCenter();
nsresult Init();
void CloseAlertCocoaString(NSString *aAlertName);
void OnActivate(NSString *aAlertName, NSUserNotificationActivationType aActivationType,
unsigned long long aAdditionalActionIndex);
void ShowPendingNotification(OSXNotificationInfo *osxni);
protected:
virtual ~OSXNotificationCenter();
private:
mozNotificationCenterDelegate *mDelegate;
nsTArray<RefPtr<OSXNotificationInfo> > mActiveAlerts;
nsTArray<RefPtr<OSXNotificationInfo> > mPendingAlerts;
};
} // namespace mozilla
#endif // OSXNotificationCenter_h
-589
View File
@@ -1,589 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "OSXNotificationCenter.h"
#import <AppKit/AppKit.h>
#include "imgIRequest.h"
#include "imgIContainer.h"
#include "nsICancelable.h"
#include "nsIStringBundle.h"
#include "nsNetUtil.h"
#import "nsCocoaUtils.h"
#include "nsComponentManagerUtils.h"
#include "nsContentUtils.h"
#include "nsObjCExceptions.h"
#include "nsString.h"
#include "nsCOMPtr.h"
#include "nsIObserver.h"
using namespace mozilla;
#define MAX_NOTIFICATION_NAME_LEN 5000
#if !defined(MAC_OS_X_VERSION_10_8) || (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8)
@protocol NSUserNotificationCenterDelegate
@end
static NSString * const NSUserNotificationDefaultSoundName = @"DefaultSoundName";
enum {
NSUserNotificationActivationTypeNone = 0,
NSUserNotificationActivationTypeContentsClicked = 1,
NSUserNotificationActivationTypeActionButtonClicked = 2,
};
#endif
#if !defined(MAC_OS_X_VERSION_10_9) || (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_9)
enum {
NSUserNotificationActivationTypeReplied = 3,
};
#endif
#if !defined(MAC_OS_X_VERSION_10_10) || (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_10)
enum {
NSUserNotificationActivationTypeAdditionalActionClicked = 4
};
#endif
@protocol FakeNSUserNotification <NSObject>
@property (copy) NSString* title;
@property (copy) NSString* subtitle;
@property (copy) NSString* informativeText;
@property (copy) NSString* actionButtonTitle;
@property (copy) NSDictionary* userInfo;
@property (copy) NSDate* deliveryDate;
@property (copy) NSTimeZone* deliveryTimeZone;
@property (copy) NSDateComponents* deliveryRepeatInterval;
@property (readonly) NSDate* actualDeliveryDate;
@property (readonly, getter=isPresented) BOOL presented;
@property (readonly, getter=isRemote) BOOL remote;
@property (copy) NSString* soundName;
@property BOOL hasActionButton;
@property (readonly) NSUserNotificationActivationType activationType;
@property (copy) NSString *otherButtonTitle;
@property (copy) NSImage *contentImage;
@end
@protocol FakeNSUserNotificationCenter <NSObject>
+ (id<FakeNSUserNotificationCenter>)defaultUserNotificationCenter;
@property (assign) id <NSUserNotificationCenterDelegate> delegate;
@property (copy) NSArray *scheduledNotifications;
- (void)scheduleNotification:(id<FakeNSUserNotification>)notification;
- (void)removeScheduledNotification:(id<FakeNSUserNotification>)notification;
@property (readonly) NSArray *deliveredNotifications;
- (void)deliverNotification:(id<FakeNSUserNotification>)notification;
- (void)removeDeliveredNotification:(id<FakeNSUserNotification>)notification;
- (void)removeAllDeliveredNotifications;
- (void)_removeAllDisplayedNotifications;
- (void)_removeDisplayedNotification:(id<FakeNSUserNotification>)notification;
@end
@interface mozNotificationCenterDelegate : NSObject <NSUserNotificationCenterDelegate>
{
OSXNotificationCenter *mOSXNC;
}
- (id)initWithOSXNC:(OSXNotificationCenter*)osxnc;
@end
@implementation mozNotificationCenterDelegate
- (id)initWithOSXNC:(OSXNotificationCenter*)osxnc
{
[super init];
// We should *never* outlive this OSXNotificationCenter.
mOSXNC = osxnc;
return self;
}
- (void)userNotificationCenter:(id<FakeNSUserNotificationCenter>)center
didDeliverNotification:(id<FakeNSUserNotification>)notification
{
}
- (void)userNotificationCenter:(id<FakeNSUserNotificationCenter>)center
didActivateNotification:(id<FakeNSUserNotification>)notification
{
unsigned long long additionalActionIndex = ULLONG_MAX;
if ([notification respondsToSelector:@selector(_alternateActionIndex)]) {
NSNumber *alternateActionIndex = [(NSObject*)notification valueForKey:@"_alternateActionIndex"];
additionalActionIndex = [alternateActionIndex unsignedLongLongValue];
}
mOSXNC->OnActivate([[notification userInfo] valueForKey:@"name"],
notification.activationType,
additionalActionIndex);
}
- (BOOL)userNotificationCenter:(id<FakeNSUserNotificationCenter>)center
shouldPresentNotification:(id<FakeNSUserNotification>)notification
{
return YES;
}
// This is an undocumented method that we need for parity with Safari.
// Apple bug #15440664.
- (void)userNotificationCenter:(id<FakeNSUserNotificationCenter>)center
didRemoveDeliveredNotifications:(NSArray *)notifications
{
for (id<FakeNSUserNotification> notification in notifications) {
NSString *name = [[notification userInfo] valueForKey:@"name"];
mOSXNC->CloseAlertCocoaString(name);
}
}
// This is an undocumented method that we need to be notified if a user clicks the close button.
- (void)userNotificationCenter:(id<FakeNSUserNotificationCenter>)center
didDismissAlert:(id<FakeNSUserNotification>)notification
{
NSString *name = [[notification userInfo] valueForKey:@"name"];
mOSXNC->CloseAlertCocoaString(name);
}
@end
namespace mozilla {
enum {
OSXNotificationActionDisable = 0,
OSXNotificationActionSettings = 1,
};
class OSXNotificationInfo final : public nsISupports {
private:
virtual ~OSXNotificationInfo();
public:
NS_DECL_ISUPPORTS
OSXNotificationInfo(NSString *name, nsIObserver *observer,
const nsAString & alertCookie);
NSString *mName;
nsCOMPtr<nsIObserver> mObserver;
nsString mCookie;
RefPtr<nsICancelable> mIconRequest;
id<FakeNSUserNotification> mPendingNotifiction;
};
NS_IMPL_ISUPPORTS0(OSXNotificationInfo)
OSXNotificationInfo::OSXNotificationInfo(NSString *name, nsIObserver *observer,
const nsAString & alertCookie)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
NS_ASSERTION(name, "Cannot create OSXNotificationInfo without a name!");
mName = [name retain];
mObserver = observer;
mCookie = alertCookie;
mPendingNotifiction = nil;
NS_OBJC_END_TRY_ABORT_BLOCK;
}
OSXNotificationInfo::~OSXNotificationInfo()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
[mName release];
[mPendingNotifiction release];
NS_OBJC_END_TRY_ABORT_BLOCK;
}
static id<FakeNSUserNotificationCenter> GetNotificationCenter() {
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
Class c = NSClassFromString(@"NSUserNotificationCenter");
return [c performSelector:@selector(defaultUserNotificationCenter)];
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
OSXNotificationCenter::OSXNotificationCenter()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
mDelegate = [[mozNotificationCenterDelegate alloc] initWithOSXNC:this];
GetNotificationCenter().delegate = mDelegate;
NS_OBJC_END_TRY_ABORT_BLOCK;
}
OSXNotificationCenter::~OSXNotificationCenter()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
[GetNotificationCenter() removeAllDeliveredNotifications];
[mDelegate release];
NS_OBJC_END_TRY_ABORT_BLOCK;
}
NS_IMPL_ISUPPORTS(OSXNotificationCenter, nsIAlertsService, nsIAlertsIconData,
nsIAlertNotificationImageListener)
nsresult OSXNotificationCenter::Init()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
return (!!NSClassFromString(@"NSUserNotification")) ? NS_OK : NS_ERROR_FAILURE;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_IMETHODIMP
OSXNotificationCenter::ShowAlertNotification(const nsAString & aImageUrl, const nsAString & aAlertTitle,
const nsAString & aAlertText, bool aAlertTextClickable,
const nsAString & aAlertCookie,
nsIObserver * aAlertListener,
const nsAString & aAlertName,
const nsAString & aBidi,
const nsAString & aLang,
const nsAString & aData,
nsIPrincipal * aPrincipal,
bool aInPrivateBrowsing,
bool aRequireInteraction)
{
nsCOMPtr<nsIAlertNotification> alert =
do_CreateInstance(ALERT_NOTIFICATION_CONTRACTID);
NS_ENSURE_TRUE(alert, NS_ERROR_FAILURE);
nsresult rv = alert->Init(aAlertName, aImageUrl, aAlertTitle,
aAlertText, aAlertTextClickable,
aAlertCookie, aBidi, aLang, aData,
aPrincipal, aInPrivateBrowsing,
aRequireInteraction);
NS_ENSURE_SUCCESS(rv, rv);
return ShowAlert(alert, aAlertListener);
}
NS_IMETHODIMP
OSXNotificationCenter::ShowPersistentNotification(const nsAString& aPersistentData,
nsIAlertNotification* aAlert,
nsIObserver* aAlertListener)
{
return ShowAlert(aAlert, aAlertListener);
}
NS_IMETHODIMP
OSXNotificationCenter::ShowAlert(nsIAlertNotification* aAlert,
nsIObserver* aAlertListener)
{
return ShowAlertWithIconData(aAlert, aAlertListener, 0, nullptr);
}
NS_IMETHODIMP
OSXNotificationCenter::ShowAlertWithIconData(nsIAlertNotification* aAlert,
nsIObserver* aAlertListener,
uint32_t aIconSize,
const uint8_t* aIconData)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
NS_ENSURE_ARG(aAlert);
Class unClass = NSClassFromString(@"NSUserNotification");
id<FakeNSUserNotification> notification = [[unClass alloc] init];
nsAutoString title;
nsresult rv = aAlert->GetTitle(title);
NS_ENSURE_SUCCESS(rv, rv);
notification.title = nsCocoaUtils::ToNSString(title);
nsAutoString hostPort;
rv = aAlert->GetSource(hostPort);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIStringBundle> bundle;
nsCOMPtr<nsIStringBundleService> sbs = do_GetService(NS_STRINGBUNDLE_CONTRACTID);
sbs->CreateBundle("chrome://alerts/locale/alert.properties", getter_AddRefs(bundle));
if (!hostPort.IsEmpty() && bundle) {
const char16_t* formatStrings[] = { hostPort.get() };
nsXPIDLString notificationSource;
bundle->FormatStringFromName(u"source.label",
formatStrings,
ArrayLength(formatStrings),
getter_Copies(notificationSource));
notification.subtitle = nsCocoaUtils::ToNSString(notificationSource);
}
nsAutoString text;
rv = aAlert->GetText(text);
NS_ENSURE_SUCCESS(rv, rv);
notification.informativeText = nsCocoaUtils::ToNSString(text);
notification.soundName = NSUserNotificationDefaultSoundName;
notification.hasActionButton = NO;
// If this is not an application/extension alert, show additional actions dealing with permissions.
bool isActionable;
if (bundle && NS_SUCCEEDED(aAlert->GetActionable(&isActionable)) && isActionable) {
nsXPIDLString closeButtonTitle, actionButtonTitle, disableButtonTitle, settingsButtonTitle;
bundle->GetStringFromName(u"closeButton.title",
getter_Copies(closeButtonTitle));
bundle->GetStringFromName(u"actionButton.label",
getter_Copies(actionButtonTitle));
if (!hostPort.IsEmpty()) {
const char16_t* formatStrings[] = { hostPort.get() };
bundle->FormatStringFromName(u"webActions.disableForOrigin.label",
formatStrings,
ArrayLength(formatStrings),
getter_Copies(disableButtonTitle));
}
bundle->GetStringFromName(u"webActions.settings.label",
getter_Copies(settingsButtonTitle));
notification.otherButtonTitle = nsCocoaUtils::ToNSString(closeButtonTitle);
// OS X 10.8 only shows action buttons if the "Alerts" style is set in
// Notification Center preferences, and doesn't support the alternate
// action menu.
if ([notification respondsToSelector:@selector(set_showsButtons:)] &&
[notification respondsToSelector:@selector(set_alwaysShowAlternateActionMenu:)] &&
[notification respondsToSelector:@selector(set_alternateActionButtonTitles:)]) {
notification.hasActionButton = YES;
notification.actionButtonTitle = nsCocoaUtils::ToNSString(actionButtonTitle);
[(NSObject*)notification setValue:@(YES) forKey:@"_showsButtons"];
[(NSObject*)notification setValue:@(YES) forKey:@"_alwaysShowAlternateActionMenu"];
[(NSObject*)notification setValue:@[
nsCocoaUtils::ToNSString(disableButtonTitle),
nsCocoaUtils::ToNSString(settingsButtonTitle)
]
forKey:@"_alternateActionButtonTitles"];
}
}
nsAutoString name;
rv = aAlert->GetName(name);
// Don't let an alert name be more than MAX_NOTIFICATION_NAME_LEN characters.
// More than that shouldn't be necessary and userInfo (assigned to below) has
// a length limit of 16k on OS X 10.11. Exception thrown if limit exceeded.
if (name.Length() > MAX_NOTIFICATION_NAME_LEN) {
return NS_ERROR_FAILURE;
}
NS_ENSURE_SUCCESS(rv, rv);
NSString *alertName = nsCocoaUtils::ToNSString(name);
if (!alertName) {
return NS_ERROR_FAILURE;
}
notification.userInfo = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:alertName, nil]
forKeys:[NSArray arrayWithObjects:@"name", nil]];
nsAutoString cookie;
rv = aAlert->GetCookie(cookie);
NS_ENSURE_SUCCESS(rv, rv);
OSXNotificationInfo *osxni = new OSXNotificationInfo(alertName, aAlertListener, cookie);
// Show the favicon if supported on this version of OS X.
if (aIconSize > 0 &&
[notification respondsToSelector:@selector(set_identityImage:)] &&
[notification respondsToSelector:@selector(set_identityImageHasBorder:)]) {
NSData *iconData = [NSData dataWithBytes:aIconData length:aIconSize];
NSImage *icon = [[[NSImage alloc] initWithData:iconData] autorelease];
[(NSObject*)notification setValue:icon forKey:@"_identityImage"];
[(NSObject*)notification setValue:@(NO) forKey:@"_identityImageHasBorder"];
}
bool inPrivateBrowsing;
rv = aAlert->GetInPrivateBrowsing(&inPrivateBrowsing);
NS_ENSURE_SUCCESS(rv, rv);
// Show the notification without waiting for an image if there is no icon URL or
// notification icons are not supported on this version of OS X.
if (![unClass instancesRespondToSelector:@selector(setContentImage:)]) {
CloseAlertCocoaString(alertName);
mActiveAlerts.AppendElement(osxni);
[GetNotificationCenter() deliverNotification:notification];
[notification release];
if (aAlertListener) {
aAlertListener->Observe(nullptr, "alertshow", cookie.get());
}
} else {
mPendingAlerts.AppendElement(osxni);
osxni->mPendingNotifiction = notification;
// Wait six seconds for the image to load.
rv = aAlert->LoadImage(6000, this, osxni,
getter_AddRefs(osxni->mIconRequest));
if (NS_WARN_IF(NS_FAILED(rv))) {
ShowPendingNotification(osxni);
}
}
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_IMETHODIMP
OSXNotificationCenter::CloseAlert(const nsAString& aAlertName,
nsIPrincipal* aPrincipal)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
NSString *alertName = nsCocoaUtils::ToNSString(aAlertName);
CloseAlertCocoaString(alertName);
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
void
OSXNotificationCenter::CloseAlertCocoaString(NSString *aAlertName)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
if (!aAlertName) {
return; // Can't do anything without a name
}
NSArray *notifications = [GetNotificationCenter() deliveredNotifications];
for (id<FakeNSUserNotification> notification in notifications) {
NSString *name = [[notification userInfo] valueForKey:@"name"];
if ([name isEqualToString:aAlertName]) {
[GetNotificationCenter() removeDeliveredNotification:notification];
[GetNotificationCenter() _removeDisplayedNotification:notification];
break;
}
}
for (unsigned int i = 0; i < mActiveAlerts.Length(); i++) {
OSXNotificationInfo *osxni = mActiveAlerts[i];
if ([aAlertName isEqualToString:osxni->mName]) {
if (osxni->mObserver) {
osxni->mObserver->Observe(nullptr, "alertfinished", osxni->mCookie.get());
}
if (osxni->mIconRequest) {
osxni->mIconRequest->Cancel(NS_BINDING_ABORTED);
osxni->mIconRequest = nullptr;
}
mActiveAlerts.RemoveElementAt(i);
break;
}
}
NS_OBJC_END_TRY_ABORT_BLOCK;
}
void
OSXNotificationCenter::OnActivate(NSString *aAlertName,
NSUserNotificationActivationType aActivationType,
unsigned long long aAdditionalActionIndex)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
if (!aAlertName) {
return; // Can't do anything without a name
}
for (unsigned int i = 0; i < mActiveAlerts.Length(); i++) {
OSXNotificationInfo *osxni = mActiveAlerts[i];
if ([aAlertName isEqualToString:osxni->mName]) {
if (osxni->mObserver) {
switch ((int)aActivationType) {
case NSUserNotificationActivationTypeAdditionalActionClicked:
case NSUserNotificationActivationTypeActionButtonClicked:
switch (aAdditionalActionIndex) {
case OSXNotificationActionDisable:
osxni->mObserver->Observe(nullptr, "alertdisablecallback", osxni->mCookie.get());
break;
case OSXNotificationActionSettings:
osxni->mObserver->Observe(nullptr, "alertsettingscallback", osxni->mCookie.get());
break;
default:
NS_WARNING("Unknown NSUserNotification additional action clicked");
break;
}
break;
default:
osxni->mObserver->Observe(nullptr, "alertclickcallback", osxni->mCookie.get());
break;
}
}
return;
}
}
NS_OBJC_END_TRY_ABORT_BLOCK;
}
void
OSXNotificationCenter::ShowPendingNotification(OSXNotificationInfo *osxni)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
if (osxni->mIconRequest) {
osxni->mIconRequest->Cancel(NS_BINDING_ABORTED);
osxni->mIconRequest = nullptr;
}
CloseAlertCocoaString(osxni->mName);
for (unsigned int i = 0; i < mPendingAlerts.Length(); i++) {
if (mPendingAlerts[i] == osxni) {
mActiveAlerts.AppendElement(osxni);
mPendingAlerts.RemoveElementAt(i);
break;
}
}
[GetNotificationCenter() deliverNotification:osxni->mPendingNotifiction];
if (osxni->mObserver) {
osxni->mObserver->Observe(nullptr, "alertshow", osxni->mCookie.get());
}
[osxni->mPendingNotifiction release];
osxni->mPendingNotifiction = nil;
NS_OBJC_END_TRY_ABORT_BLOCK;
}
NS_IMETHODIMP
OSXNotificationCenter::OnImageMissing(nsISupports* aUserData)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
OSXNotificationInfo *osxni = static_cast<OSXNotificationInfo*>(aUserData);
if (osxni->mPendingNotifiction) {
// If there was an error getting the image, or the request timed out, show
// the notification without a content image.
ShowPendingNotification(osxni);
}
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_IMETHODIMP
OSXNotificationCenter::OnImageReady(nsISupports* aUserData,
imgIRequest* aRequest)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
nsCOMPtr<imgIContainer> image;
nsresult rv = aRequest->GetImage(getter_AddRefs(image));
if (NS_WARN_IF(NS_FAILED(rv) || !image)) {
return rv;
}
OSXNotificationInfo *osxni = static_cast<OSXNotificationInfo*>(aUserData);
if (!osxni->mPendingNotifiction) {
return NS_ERROR_FAILURE;
}
NSImage *cocoaImage = nil;
nsCocoaUtils::CreateNSImageFromImageContainer(image, imgIContainer::FRAME_FIRST, &cocoaImage, 1.0f);
(osxni->mPendingNotifiction).contentImage = cocoaImage;
[cocoaImage release];
ShowPendingNotification(osxni);
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
} // namespace mozilla
-80
View File
@@ -1,80 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef RectTextureImage_h_
#define RectTextureImage_h_
#include "mozilla/RefPtr.h"
class MacIOSurface;
namespace mozilla {
namespace gl {
class GLContext;
} // namespace gl
namespace widget {
// Manages a texture which can resize dynamically, binds to the
// LOCAL_GL_TEXTURE_RECTANGLE_ARB texture target and is automatically backed
// by a power-of-two size GL texture. The latter two features are used for
// compatibility with older Mac hardware which we block GL layers on.
// RectTextureImages are used both for accelerated GL layers drawing and for
// OMTC BasicLayers drawing.
class RectTextureImage {
public:
RectTextureImage();
virtual ~RectTextureImage();
already_AddRefed<gfx::DrawTarget>
BeginUpdate(const LayoutDeviceIntSize& aNewSize,
const LayoutDeviceIntRegion& aDirtyRegion =
LayoutDeviceIntRegion());
void EndUpdate();
void UpdateIfNeeded(const LayoutDeviceIntSize& aNewSize,
const LayoutDeviceIntRegion& aDirtyRegion,
void (^aCallback)(gfx::DrawTarget*,
const LayoutDeviceIntRegion&))
{
RefPtr<gfx::DrawTarget> drawTarget = BeginUpdate(aNewSize, aDirtyRegion);
if (drawTarget) {
aCallback(drawTarget, GetUpdateRegion());
EndUpdate();
}
}
void UpdateFromCGContext(const LayoutDeviceIntSize& aNewSize,
const LayoutDeviceIntRegion& aDirtyRegion,
CGContextRef aCGContext);
LayoutDeviceIntRegion GetUpdateRegion() {
MOZ_ASSERT(mInUpdate, "update region only valid during update");
return mUpdateRegion;
}
void Draw(mozilla::layers::GLManager* aManager,
const LayoutDeviceIntPoint& aLocation,
const gfx::Matrix4x4& aTransform = gfx::Matrix4x4());
protected:
void DeleteTexture();
void BindIOSurfaceToTexture(gl::GLContext* aGL);
RefPtr<MacIOSurface> mIOSurface;
gl::GLContext* mGLContext;
LayoutDeviceIntRegion mUpdateRegion;
LayoutDeviceIntSize mBufferSize;
GLuint mTexture;
bool mInUpdate;
};
} // namespace widget
} // namespace mozilla
#endif // RectTextureImage_h_
-171
View File
@@ -1,171 +0,0 @@
/* -*- Mode: objc; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "RectTextureImage.h"
#include "gfxUtils.h"
#include "GLContextCGL.h"
#include "mozilla/layers/GLManager.h"
#include "mozilla/gfx/MacIOSurface.h"
#include "OGLShaderProgram.h"
#include "ScopedGLHelpers.h"
namespace mozilla {
namespace widget {
RectTextureImage::RectTextureImage()
: mGLContext(nullptr)
, mTexture(0)
, mInUpdate(false)
{
}
RectTextureImage::~RectTextureImage()
{
DeleteTexture();
}
already_AddRefed<gfx::DrawTarget>
RectTextureImage::BeginUpdate(const LayoutDeviceIntSize& aNewSize,
const LayoutDeviceIntRegion& aDirtyRegion)
{
MOZ_ASSERT(!mInUpdate, "Beginning update during update!");
mUpdateRegion = aDirtyRegion;
bool needRecreate = false;
if (aNewSize != mBufferSize) {
mBufferSize = aNewSize;
mUpdateRegion =
LayoutDeviceIntRect(LayoutDeviceIntPoint(0, 0), aNewSize);
needRecreate = true;
}
if (mUpdateRegion.IsEmpty()) {
return nullptr;
}
if (!mIOSurface || needRecreate) {
DeleteTexture();
mIOSurface = MacIOSurface::CreateIOSurface(mBufferSize.width,
mBufferSize.height);
if (!mIOSurface) {
return nullptr;
}
}
mInUpdate = true;
mIOSurface->Lock(false);
unsigned char* ioData = (unsigned char*)mIOSurface->GetBaseAddress();
gfx::IntSize size(mBufferSize.width, mBufferSize.height);
int32_t stride = mIOSurface->GetBytesPerRow();
gfx::SurfaceFormat format = gfx::SurfaceFormat::B8G8R8A8;
RefPtr<gfx::DrawTarget> drawTarget =
gfx::Factory::CreateDrawTargetForData(gfx::BackendType::SKIA,
ioData, size,
stride, format);
return drawTarget.forget();
}
void
RectTextureImage::EndUpdate()
{
MOZ_ASSERT(mInUpdate, "Ending update while not in update");
mIOSurface->Unlock(false);
mInUpdate = false;
}
void
RectTextureImage::UpdateFromCGContext(const LayoutDeviceIntSize& aNewSize,
const LayoutDeviceIntRegion& aDirtyRegion,
CGContextRef aCGContext)
{
gfx::IntSize size = gfx::IntSize(CGBitmapContextGetWidth(aCGContext),
CGBitmapContextGetHeight(aCGContext));
RefPtr<gfx::DrawTarget> dt = BeginUpdate(aNewSize, aDirtyRegion);
if (dt) {
gfx::Rect rect(0, 0, size.width, size.height);
gfxUtils::ClipToRegion(dt, GetUpdateRegion().ToUnknownRegion());
RefPtr<gfx::SourceSurface> sourceSurface =
dt->CreateSourceSurfaceFromData(static_cast<uint8_t *>(CGBitmapContextGetData(aCGContext)),
size,
CGBitmapContextGetBytesPerRow(aCGContext),
gfx::SurfaceFormat::B8G8R8A8);
dt->DrawSurface(sourceSurface, rect, rect,
gfx::DrawSurfaceOptions(),
gfx::DrawOptions(1.0, gfx::CompositionOp::OP_SOURCE));
dt->PopClip();
EndUpdate();
}
}
void
RectTextureImage::Draw(layers::GLManager* aManager,
const LayoutDeviceIntPoint& aLocation,
const gfx::Matrix4x4& aTransform)
{
gl::GLContext* gl = aManager->gl();
BindIOSurfaceToTexture(gl);
layers::ShaderProgramOGL* program =
aManager->GetProgram(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
gfx::SurfaceFormat::R8G8B8A8);
gl->fActiveTexture(LOCAL_GL_TEXTURE0);
gl::ScopedBindTexture texture(gl, mTexture, LOCAL_GL_TEXTURE_RECTANGLE_ARB);
aManager->ActivateProgram(program);
program->SetProjectionMatrix(aManager->GetProjMatrix());
program->SetLayerTransform(gfx::Matrix4x4(aTransform).PostTranslate(aLocation.x, aLocation.y, 0));
program->SetTextureTransform(gfx::Matrix4x4());
program->SetRenderOffset(nsIntPoint(0, 0));
program->SetTexCoordMultiplier(mBufferSize.width, mBufferSize.height);
program->SetTextureUnit(0);
aManager->BindAndDrawQuad(program,
gfx::Rect(0.0, 0.0, mBufferSize.width, mBufferSize.height),
gfx::Rect(0.0, 0.0, 1.0f, 1.0f));
}
void
RectTextureImage::DeleteTexture()
{
if (mTexture) {
MOZ_ASSERT(mGLContext);
mGLContext->MakeCurrent();
mGLContext->fDeleteTextures(1, &mTexture);
mTexture = 0;
}
}
void
RectTextureImage::BindIOSurfaceToTexture(gl::GLContext* aGL)
{
if (!mTexture) {
MOZ_ASSERT(aGL);
aGL->fGenTextures(1, &mTexture);
aGL->fActiveTexture(LOCAL_GL_TEXTURE0);
gl::ScopedBindTexture texture(aGL, mTexture, LOCAL_GL_TEXTURE_RECTANGLE_ARB);
aGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
LOCAL_GL_TEXTURE_MIN_FILTER,
LOCAL_GL_LINEAR);
aGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
LOCAL_GL_TEXTURE_MAG_FILTER,
LOCAL_GL_LINEAR);
aGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
LOCAL_GL_TEXTURE_WRAP_T,
LOCAL_GL_CLAMP_TO_EDGE);
aGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
LOCAL_GL_TEXTURE_WRAP_S,
LOCAL_GL_CLAMP_TO_EDGE);
mIOSurface->CGLTexImageIOSurface2D(gl::GLContextCGL::Cast(aGL)->GetCGLContext());
mGLContext = aGL;
}
}
} // namespace widget
} // namespace mozilla
-95
View File
@@ -1,95 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef SwipeTracker_h
#define SwipeTracker_h
#include "EventForwards.h"
#include "mozilla/layers/AxisPhysicsMSDModel.h"
#include "mozilla/RefPtr.h"
#include "mozilla/TimeStamp.h"
#include "nsRefreshDriver.h"
#include "Units.h"
class nsIPresShell;
namespace mozilla {
class PanGestureInput;
/**
* SwipeTracker turns PanGestureInput events into swipe events
* (WidgetSimpleGestureEvent) and dispatches them into Gecko.
* The swiping behavior mirrors the behavior of the Cocoa API
* -[NSEvent trackSwipeEventWithOptions:dampenAmountThresholdMin:max:usingHandler:].
* The advantage of using this class over the Cocoa API is that this class
* properly supports submitting queued up events to it, and that it hopefully
* doesn't intermittently break scrolling the way the Cocoa API does (bug 927702).
*
* The swipe direction is either left or right. It is determined before the
* SwipeTracker is created and stays fixed during the swipe.
* During the swipe, the swipe has a current "value" which is between 0 and the
* target value. The target value is either 1 (swiping left) or -1 (swiping
* right) - see SwipeSuccessTargetValue().
* A swipe can either succeed or fail. If it succeeds, the swipe animation
* animates towards the success target value; if it fails, it animates back to
* a value of 0. A swipe can only succeed if the user is swiping in an allowed
* direction. (Since both the allowed directions and the swipe direction are
* known at swipe start time, it's clear from the beginning whether a swipe is
* doomed to fail. In that case, the purpose of the SwipeTracker is to simulate
* a bounce-back animation.)
*/
class SwipeTracker final : public nsARefreshObserver {
public:
NS_INLINE_DECL_REFCOUNTING(SwipeTracker, override)
SwipeTracker(nsChildView& aWidget,
const PanGestureInput& aSwipeStartEvent,
uint32_t aAllowedDirections,
uint32_t aSwipeDirection);
void Destroy();
nsEventStatus ProcessEvent(const PanGestureInput& aEvent);
void CancelSwipe();
static WidgetSimpleGestureEvent
CreateSwipeGestureEvent(EventMessage aMsg, nsIWidget* aWidget,
const LayoutDeviceIntPoint& aPosition);
// nsARefreshObserver
void WillRefresh(mozilla::TimeStamp aTime) override;
protected:
~SwipeTracker();
bool SwipingInAllowedDirection() const { return mAllowedDirections & mSwipeDirection; }
double SwipeSuccessTargetValue() const;
double ClampToAllowedRange(double aGestureAmount) const;
bool ComputeSwipeSuccess() const;
void StartAnimating(double aTargetValue);
void SwipeFinished();
void UnregisterFromRefreshDriver();
bool SendSwipeEvent(EventMessage aMsg, uint32_t aDirection, double aDelta);
nsChildView& mWidget;
RefPtr<nsRefreshDriver> mRefreshDriver;
layers::AxisPhysicsMSDModel mAxis;
const LayoutDeviceIntPoint mEventPosition;
TimeStamp mLastEventTimeStamp;
TimeStamp mLastAnimationFrameTime;
const uint32_t mAllowedDirections;
const uint32_t mSwipeDirection;
double mGestureAmount;
double mCurrentVelocity;
bool mEventsAreControllingSwipe;
bool mEventsHaveStartedNewGesture;
bool mRegisteredWithRefreshDriver;
};
} // namespace mozilla
#endif // SwipeTracker_h
-219
View File
@@ -1,219 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SwipeTracker.h"
#include "InputData.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/TouchEvents.h"
#include "nsAlgorithm.h"
#include "nsChildView.h"
#include "UnitTransforms.h"
// These values were tweaked to make the physics feel similar to the native swipe.
static const double kSpringForce = 250.0;
static const double kVelocityTwitchTolerance = 0.0000001;
static const double kWholePagePixelSize = 1000.0;
static const double kRubberBandResistanceFactor = 4.0;
static const double kSwipeSuccessThreshold = 0.25;
static const double kSwipeSuccessVelocityContribution = 0.3;
namespace mozilla {
static already_AddRefed<nsRefreshDriver>
GetRefreshDriver(nsIWidget& aWidget)
{
nsIWidgetListener* widgetListener = aWidget.GetWidgetListener();
nsIPresShell* presShell = widgetListener ? widgetListener->GetPresShell() : nullptr;
nsPresContext* presContext = presShell ? presShell->GetPresContext() : nullptr;
RefPtr<nsRefreshDriver> refreshDriver = presContext ? presContext->RefreshDriver() : nullptr;
return refreshDriver.forget();
}
SwipeTracker::SwipeTracker(nsChildView& aWidget,
const PanGestureInput& aSwipeStartEvent,
uint32_t aAllowedDirections,
uint32_t aSwipeDirection)
: mWidget(aWidget)
, mRefreshDriver(GetRefreshDriver(mWidget))
, mAxis(0.0, 0.0, 0.0, kSpringForce, 1.0)
, mEventPosition(RoundedToInt(ViewAs<LayoutDevicePixel>(aSwipeStartEvent.mPanStartPoint,
PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent)))
, mLastEventTimeStamp(aSwipeStartEvent.mTimeStamp)
, mAllowedDirections(aAllowedDirections)
, mSwipeDirection(aSwipeDirection)
, mGestureAmount(0.0)
, mCurrentVelocity(0.0)
, mEventsAreControllingSwipe(true)
, mEventsHaveStartedNewGesture(false)
, mRegisteredWithRefreshDriver(false)
{
SendSwipeEvent(eSwipeGestureStart, 0, 0.0);
ProcessEvent(aSwipeStartEvent);
}
void
SwipeTracker::Destroy()
{
UnregisterFromRefreshDriver();
}
SwipeTracker::~SwipeTracker()
{
MOZ_ASSERT(!mRegisteredWithRefreshDriver, "Destroy needs to be called before deallocating");
}
double
SwipeTracker::SwipeSuccessTargetValue() const
{
return (mSwipeDirection == nsIDOMSimpleGestureEvent::DIRECTION_RIGHT) ? -1.0 : 1.0;
}
double
SwipeTracker::ClampToAllowedRange(double aGestureAmount) const
{
// gestureAmount needs to stay between -1 and 0 when swiping right and
// between 0 and 1 when swiping left.
double min = (mSwipeDirection == nsIDOMSimpleGestureEvent::DIRECTION_RIGHT) ? -1.0 : 0.0;
double max = (mSwipeDirection == nsIDOMSimpleGestureEvent::DIRECTION_LEFT) ? 1.0 : 0.0;
return clamped(aGestureAmount, min, max);
}
bool
SwipeTracker::ComputeSwipeSuccess() const
{
double targetValue = SwipeSuccessTargetValue();
// If the fingers were moving away from the target direction when they were
// lifted from the touchpad, abort the swipe.
if (mCurrentVelocity * targetValue < -kVelocityTwitchTolerance) {
return false;
}
return (mGestureAmount * targetValue +
mCurrentVelocity * targetValue * kSwipeSuccessVelocityContribution) >= kSwipeSuccessThreshold;
}
nsEventStatus
SwipeTracker::ProcessEvent(const PanGestureInput& aEvent)
{
// If the fingers have already been lifted, don't process this event for swiping.
if (!mEventsAreControllingSwipe) {
// Return nsEventStatus_eConsumeNoDefault for events from the swipe gesture
// and nsEventStatus_eIgnore for events of subsequent scroll gestures.
if (aEvent.mType == PanGestureInput::PANGESTURE_MAYSTART ||
aEvent.mType == PanGestureInput::PANGESTURE_START) {
mEventsHaveStartedNewGesture = true;
}
return mEventsHaveStartedNewGesture ? nsEventStatus_eIgnore : nsEventStatus_eConsumeNoDefault;
}
double delta = -aEvent.mPanDisplacement.x / mWidget.BackingScaleFactor() / kWholePagePixelSize;
if (!SwipingInAllowedDirection()) {
delta /= kRubberBandResistanceFactor;
}
mGestureAmount = ClampToAllowedRange(mGestureAmount + delta);
SendSwipeEvent(eSwipeGestureUpdate, 0, mGestureAmount);
if (aEvent.mType != PanGestureInput::PANGESTURE_END) {
double elapsedSeconds = std::max(0.008, (aEvent.mTimeStamp - mLastEventTimeStamp).ToSeconds());
mCurrentVelocity = delta / elapsedSeconds;
mLastEventTimeStamp = aEvent.mTimeStamp;
} else {
mEventsAreControllingSwipe = false;
bool didSwipeSucceed = SwipingInAllowedDirection() && ComputeSwipeSuccess();
double targetValue = 0.0;
if (didSwipeSucceed) {
SendSwipeEvent(eSwipeGesture, mSwipeDirection, 0.0);
targetValue = SwipeSuccessTargetValue();
}
StartAnimating(targetValue);
}
return nsEventStatus_eConsumeNoDefault;
}
void
SwipeTracker::StartAnimating(double aTargetValue)
{
mAxis.SetPosition(mGestureAmount);
mAxis.SetDestination(aTargetValue);
mAxis.SetVelocity(mCurrentVelocity);
mLastAnimationFrameTime = TimeStamp::Now();
// Add ourselves as a refresh driver observer. The refresh driver
// will call WillRefresh for each animation frame until we
// unregister ourselves.
MOZ_ASSERT(!mRegisteredWithRefreshDriver);
if (mRefreshDriver) {
mRefreshDriver->AddRefreshObserver(this, Flush_Style);
mRegisteredWithRefreshDriver = true;
}
}
void
SwipeTracker::WillRefresh(mozilla::TimeStamp aTime)
{
TimeStamp now = TimeStamp::Now();
mAxis.Simulate(now - mLastAnimationFrameTime);
mLastAnimationFrameTime = now;
bool isFinished = mAxis.IsFinished(1.0 / kWholePagePixelSize);
mGestureAmount = (isFinished ? mAxis.GetDestination() : mAxis.GetPosition());
SendSwipeEvent(eSwipeGestureUpdate, 0, mGestureAmount);
if (isFinished) {
UnregisterFromRefreshDriver();
SwipeFinished();
}
}
void
SwipeTracker::CancelSwipe()
{
SendSwipeEvent(eSwipeGestureEnd, 0, 0.0);
}
void SwipeTracker::SwipeFinished()
{
SendSwipeEvent(eSwipeGestureEnd, 0, 0.0);
mWidget.SwipeFinished();
}
void
SwipeTracker::UnregisterFromRefreshDriver()
{
if (mRegisteredWithRefreshDriver) {
MOZ_ASSERT(mRefreshDriver, "How were we able to register, then?");
mRefreshDriver->RemoveRefreshObserver(this, Flush_Style);
}
mRegisteredWithRefreshDriver = false;
}
/* static */ WidgetSimpleGestureEvent
SwipeTracker::CreateSwipeGestureEvent(EventMessage aMsg, nsIWidget* aWidget,
const LayoutDeviceIntPoint& aPosition)
{
WidgetSimpleGestureEvent geckoEvent(true, aMsg, aWidget);
geckoEvent.mModifiers = 0;
geckoEvent.mTimeStamp = TimeStamp::Now();
geckoEvent.mRefPoint = aPosition;
geckoEvent.buttons = 0;
return geckoEvent;
}
bool
SwipeTracker::SendSwipeEvent(EventMessage aMsg, uint32_t aDirection, double aDelta)
{
WidgetSimpleGestureEvent geckoEvent =
CreateSwipeGestureEvent(aMsg, &mWidget, mEventPosition);
geckoEvent.mDirection = aDirection;
geckoEvent.mDelta = aDelta;
geckoEvent.mAllowedDirections = mAllowedDirections;
return mWidget.DispatchWindowEvent(geckoEvent);
}
} // namespace mozilla
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-120
View File
@@ -1,120 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef VibrancyManager_h
#define VibrancyManager_h
#include "mozilla/Assertions.h"
#include "nsClassHashtable.h"
#include "nsRegion.h"
#include "nsTArray.h"
#include "ViewRegion.h"
#import <Foundation/NSGeometry.h>
@class NSColor;
@class NSView;
class nsChildView;
namespace mozilla {
enum class VibrancyType {
LIGHT,
DARK,
TOOLTIP,
MENU,
HIGHLIGHTED_MENUITEM,
SHEET,
SOURCE_LIST,
SOURCE_LIST_SELECTION,
ACTIVE_SOURCE_LIST_SELECTION
};
/**
* VibrancyManager takes care of updating the vibrant regions of a window.
* Vibrancy is a visual look that was introduced on OS X starting with 10.10.
* An app declares vibrant window regions to the window server, and the window
* server will display a blurred rendering of the screen contents from behind
* the window in these areas, behind the actual window contents. Consequently,
* the effect is only visible in areas where the window contents are not
* completely opaque. Usually this is achieved by clearing the background of
* the window prior to drawing in the vibrant areas. This is possible even if
* the window is declared as opaque.
*/
class VibrancyManager {
public:
/**
* Create a new VibrancyManager instance and provide it with an NSView
* to attach NSVisualEffectViews to.
*
* @param aCoordinateConverter The nsChildView to use for converting
* nsIntRect device pixel coordinates into Cocoa NSRect coordinates. Must
* outlive this VibrancyManager instance.
* @param aContainerView The view that's going to be the superview of the
* NSVisualEffectViews which will be created for vibrant regions.
*/
VibrancyManager(const nsChildView& aCoordinateConverter,
NSView* aContainerView)
: mCoordinateConverter(aCoordinateConverter)
, mContainerView(aContainerView)
{
MOZ_ASSERT(SystemSupportsVibrancy(),
"Don't instantiate this if !SystemSupportsVibrancy()");
}
/**
* Update the placement of the NSVisualEffectViews inside the container
* NSView so that they cover aRegion, and create new NSVisualEffectViews
* or remove existing ones as needed.
* @param aType The vibrancy type to use in the region.
* @param aRegion The vibrant area, in device pixels.
*/
void UpdateVibrantRegion(VibrancyType aType,
const LayoutDeviceIntRegion& aRegion);
bool HasVibrantRegions() { return !mVibrantRegions.IsEmpty(); }
/**
* Return the fill color that should be drawn on top of the cleared window
* parts. Usually this would be drawn by -[NSVisualEffectView drawRect:].
* The returned color is opaque if the system-wide "Reduce transparency"
* preference is set.
*/
NSColor* VibrancyFillColorForType(VibrancyType aType);
/**
* Return the font smoothing background color that should be used for text
* drawn on top of the vibrant window parts.
*/
NSColor* VibrancyFontSmoothingBackgroundColorForType(VibrancyType aType);
/**
* Check whether the operating system supports vibrancy at all.
* You may only create a VibrancyManager instance if this returns true.
* @return Whether VibrancyManager can be used on this OS.
*/
static bool SystemSupportsVibrancy();
/**
* Create an NSVisualEffectView for the specified vibrancy type. The return
* value is not autoreleased. We return an object of type NSView* because we
* compile with an SDK that does not contain a definition for
* NSVisualEffectView.
* @param aIsContainer Whether this NSView will have child views. This value
* affects hit testing: Container views will pass through
* hit testing requests to their children, and leaf views
* will be transparent to hit testing.
*/
static NSView* CreateEffectView(VibrancyType aType, BOOL aIsContainer = NO);
protected:
const nsChildView& mCoordinateConverter;
NSView* mContainerView;
nsClassHashtable<nsUint32HashKey, ViewRegion> mVibrantRegions;
};
} // namespace mozilla
#endif // VibrancyManager_h
-244
View File
@@ -1,244 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "VibrancyManager.h"
#include "nsChildView.h"
#import <objc/message.h>
using namespace mozilla;
void
VibrancyManager::UpdateVibrantRegion(VibrancyType aType,
const LayoutDeviceIntRegion& aRegion)
{
if (aRegion.IsEmpty()) {
mVibrantRegions.Remove(uint32_t(aType));
return;
}
auto& vr = *mVibrantRegions.LookupOrAdd(uint32_t(aType));
vr.UpdateRegion(aRegion, mCoordinateConverter, mContainerView, ^() {
return this->CreateEffectView(aType);
});
}
@interface NSView(CurrentFillColor)
- (NSColor*)_currentFillColor;
@end
static NSColor*
AdjustedColor(NSColor* aFillColor, VibrancyType aType)
{
if (aType == VibrancyType::MENU && [aFillColor alphaComponent] == 1.0) {
// The opaque fill color that's used for the menu background when "Reduce
// vibrancy" is checked in the system accessibility prefs is too dark.
// This is probably because we're not using the right material for menus,
// see VibrancyManager::CreateEffectView.
return [NSColor colorWithDeviceWhite:0.96 alpha:1.0];
}
return aFillColor;
}
NSColor*
VibrancyManager::VibrancyFillColorForType(VibrancyType aType)
{
NSView* view = mVibrantRegions.LookupOrAdd(uint32_t(aType))->GetAnyView();
if (view && [view respondsToSelector:@selector(_currentFillColor)]) {
// -[NSVisualEffectView _currentFillColor] is the color that the view
// draws in its drawRect implementation.
return AdjustedColor([view _currentFillColor], aType);
}
return [NSColor whiteColor];
}
@interface NSView(FontSmoothingBackgroundColor)
- (NSColor*)fontSmoothingBackgroundColor;
@end
NSColor*
VibrancyManager::VibrancyFontSmoothingBackgroundColorForType(VibrancyType aType)
{
NSView* view = mVibrantRegions.LookupOrAdd(uint32_t(aType))->GetAnyView();
if (view && [view respondsToSelector:@selector(fontSmoothingBackgroundColor)]) {
return [view fontSmoothingBackgroundColor];
}
return [NSColor clearColor];
}
static NSView*
HitTestNil(id self, SEL _cmd, NSPoint aPoint)
{
// This view must be transparent to mouse events.
return nil;
}
static BOOL
AllowsVibrancyYes(id self, SEL _cmd)
{
// Means that the foreground is blended using a vibrant blend mode.
return YES;
}
static Class
CreateEffectViewClass(BOOL aForegroundVibrancy, BOOL aIsContainer)
{
// Create a class that inherits from NSVisualEffectView and overrides the
// methods -[NSView hitTest:] and -[NSVisualEffectView allowsVibrancy].
Class NSVisualEffectViewClass = NSClassFromString(@"NSVisualEffectView");
const char* className = aForegroundVibrancy
? "EffectViewWithForegroundVibrancy" : "EffectViewWithoutForegroundVibrancy";
Class EffectViewClass = objc_allocateClassPair(NSVisualEffectViewClass, className, 0);
if (!aIsContainer) {
class_addMethod(EffectViewClass, @selector(hitTest:), (IMP)HitTestNil,
"@@:{CGPoint=dd}");
}
if (aForegroundVibrancy) {
// Override the -[NSView allowsVibrancy] method to return YES.
class_addMethod(EffectViewClass, @selector(allowsVibrancy), (IMP)AllowsVibrancyYes, "I@:");
}
return EffectViewClass;
}
static id
AppearanceForVibrancyType(VibrancyType aType)
{
Class NSAppearanceClass = NSClassFromString(@"NSAppearance");
switch (aType) {
case VibrancyType::LIGHT:
case VibrancyType::TOOLTIP:
case VibrancyType::MENU:
case VibrancyType::HIGHLIGHTED_MENUITEM:
case VibrancyType::SHEET:
case VibrancyType::SOURCE_LIST:
case VibrancyType::SOURCE_LIST_SELECTION:
case VibrancyType::ACTIVE_SOURCE_LIST_SELECTION:
return [NSAppearanceClass performSelector:@selector(appearanceNamed:)
withObject:@"NSAppearanceNameVibrantLight"];
case VibrancyType::DARK:
return [NSAppearanceClass performSelector:@selector(appearanceNamed:)
withObject:@"NSAppearanceNameVibrantDark"];
}
}
#if !defined(MAC_OS_X_VERSION_10_10) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_10
enum {
NSVisualEffectStateFollowsWindowActiveState,
NSVisualEffectStateActive,
NSVisualEffectStateInactive
};
enum {
NSVisualEffectMaterialTitlebar = 3
};
#endif
#if !defined(MAC_OS_X_VERSION_10_11) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_11
enum {
NSVisualEffectMaterialMenu = 5,
NSVisualEffectMaterialSidebar = 7
};
#endif
static NSUInteger
VisualEffectStateForVibrancyType(VibrancyType aType)
{
switch (aType) {
case VibrancyType::TOOLTIP:
case VibrancyType::MENU:
case VibrancyType::HIGHLIGHTED_MENUITEM:
case VibrancyType::SHEET:
// Tooltip and menu windows are never "key" and sheets always looks
// active, so we need to tell the vibrancy effect to look active
// regardless of window state.
return NSVisualEffectStateActive;
default:
return NSVisualEffectStateFollowsWindowActiveState;
}
}
static BOOL
HasVibrantForeground(VibrancyType aType)
{
switch (aType) {
case VibrancyType::MENU:
return YES;
default:
return NO;
}
}
#if !defined(MAC_OS_X_VERSION_10_12) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12
enum {
NSVisualEffectMaterialSelection = 4
};
#endif
@interface NSView(NSVisualEffectViewMethods)
- (void)setState:(NSUInteger)state;
- (void)setMaterial:(NSUInteger)material;
- (void)setEmphasized:(BOOL)emphasized;
@end
NSView*
VibrancyManager::CreateEffectView(VibrancyType aType, BOOL aIsContainer)
{
static Class EffectViewWithoutForegroundVibrancy = CreateEffectViewClass(NO, NO);
static Class EffectViewWithForegroundVibrancy = CreateEffectViewClass(YES, NO);
static Class EffectViewContainer = CreateEffectViewClass(NO, YES);
// Pick the right NSVisualEffectView subclass for the desired vibrancy mode.
// For "container" views, never use foreground vibrancy, because returning
// YES from allowsVibrancy forces on foreground vibrancy for all descendant
// views which can have unintended effects.
Class EffectViewClass = aIsContainer
? EffectViewContainer
: (HasVibrantForeground(aType) ? EffectViewWithForegroundVibrancy
: EffectViewWithoutForegroundVibrancy);
NSView* effectView = [[EffectViewClass alloc] initWithFrame:NSZeroRect];
[effectView performSelector:@selector(setAppearance:)
withObject:AppearanceForVibrancyType(aType)];
[effectView setState:VisualEffectStateForVibrancyType(aType)];
BOOL canUseElCapitanMaterials = nsCocoaFeatures::OnElCapitanOrLater();
if (aType == VibrancyType::MENU) {
// Before 10.11 there is no material that perfectly matches the menu
// look. Of all available material types, NSVisualEffectMaterialTitlebar
// is the one that comes closest.
[effectView setMaterial:canUseElCapitanMaterials ? NSVisualEffectMaterialMenu
: NSVisualEffectMaterialTitlebar];
} else if (aType == VibrancyType::SOURCE_LIST && canUseElCapitanMaterials) {
[effectView setMaterial:NSVisualEffectMaterialSidebar];
} else if (aType == VibrancyType::HIGHLIGHTED_MENUITEM ||
aType == VibrancyType::SOURCE_LIST_SELECTION ||
aType == VibrancyType::ACTIVE_SOURCE_LIST_SELECTION) {
[effectView setMaterial:NSVisualEffectMaterialSelection];
if ([effectView respondsToSelector:@selector(setEmphasized:)] &&
aType != VibrancyType::SOURCE_LIST_SELECTION) {
[effectView setEmphasized:YES];
}
}
return effectView;
}
static bool
ComputeSystemSupportsVibrancy()
{
#ifdef __x86_64__
return NSClassFromString(@"NSAppearance") &&
NSClassFromString(@"NSVisualEffectView");
#else
// objc_allocateClassPair doesn't work in 32 bit mode, so turn off vibrancy.
return false;
#endif
}
/* static */ bool
VibrancyManager::SystemSupportsVibrancy()
{
static bool supportsVibrancy = ComputeSystemSupportsVibrancy();
return supportsVibrancy;
}
-52
View File
@@ -1,52 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef ViewRegion_h
#define ViewRegion_h
#include "Units.h"
#include "nsTArray.h"
@class NSView;
namespace mozilla {
/**
* Manages a set of NSViews to cover a LayoutDeviceIntRegion.
*/
class ViewRegion {
public:
~ViewRegion();
mozilla::LayoutDeviceIntRegion Region() { return mRegion; }
/**
* Update the region.
* @param aRegion The new region.
* @param aCoordinateConverter The nsChildView to use for converting
* LayoutDeviceIntRect device pixel coordinates into Cocoa NSRect coordinates.
* @param aContainerView The view that's going to be the superview of the
* NSViews which will be created for this region.
* @param aViewCreationCallback A block that instantiates new NSViews.
* @return Whether or not the region changed.
*/
bool UpdateRegion(const mozilla::LayoutDeviceIntRegion& aRegion,
const nsChildView& aCoordinateConverter,
NSView* aContainerView,
NSView* (^aViewCreationCallback)());
/**
* Return an NSView from the region, if there is any.
*/
NSView* GetAnyView() { return mViews.Length() > 0 ? mViews[0] : nil; }
private:
mozilla::LayoutDeviceIntRegion mRegion;
nsTArray<NSView*> mViews;
};
} // namespace mozilla
#endif // ViewRegion_h
-70
View File
@@ -1,70 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ViewRegion.h"
#import <Cocoa/Cocoa.h>
using namespace mozilla;
ViewRegion::~ViewRegion()
{
for (size_t i = 0; i < mViews.Length(); i++) {
[mViews[i] removeFromSuperview];
}
}
bool
ViewRegion::UpdateRegion(const LayoutDeviceIntRegion& aRegion,
const nsChildView& aCoordinateConverter,
NSView* aContainerView,
NSView* (^aViewCreationCallback)())
{
if (mRegion == aRegion) {
return false;
}
// We need to construct the required region using as many EffectViews
// as necessary. We try to update the geometry of existing views if
// possible, or create new ones or remove old ones if the number of
// rects in the region has changed.
nsTArray<NSView*> viewsToRecycle;
mViews.SwapElements(viewsToRecycle);
// The mViews array is now empty.
size_t i = 0;
for (auto iter = aRegion.RectIter();
!iter.Done() || i < viewsToRecycle.Length();
i++) {
if (!iter.Done()) {
NSView* view = nil;
NSRect rect = aCoordinateConverter.DevPixelsToCocoaPoints(iter.Get());
if (i < viewsToRecycle.Length()) {
view = viewsToRecycle[i];
} else {
view = aViewCreationCallback();
[aContainerView addSubview:view];
// Now that the view is in the view hierarchy, it'll be kept alive by
// its superview, so we can drop our reference.
[view release];
}
if (!NSEqualRects(rect, [view frame])) {
[view setFrame:rect];
}
[view setNeedsDisplay:YES];
mViews.AppendElement(view);
iter.Next();
} else {
// Our new region is made of fewer rects than the old region, so we can
// remove this view. We only have a weak reference to it, so removing it
// from the view hierarchy will release it.
[viewsToRecycle[i] removeFromSuperview];
}
}
mRegion = aRegion;
return true;
}
-85
View File
@@ -1,85 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <Cocoa/Cocoa.h>
#include "CustomCocoaEvents.h"
#include <Foundation/NSAutoreleasePool.h>
#include <mozilla/CondVar.h>
#include <mozilla/Mutex.h>
#include "mozilla/WidgetTraceEvent.h"
using mozilla::CondVar;
using mozilla::Mutex;
using mozilla::MutexAutoLock;
namespace {
Mutex* sMutex = NULL;
CondVar* sCondVar = NULL;
bool sTracerProcessed = false;
} // namespace
namespace mozilla {
bool InitWidgetTracing()
{
sMutex = new Mutex("Event tracer thread mutex");
sCondVar = new CondVar(*sMutex, "Event tracer thread condvar");
return sMutex && sCondVar;
}
void CleanUpWidgetTracing()
{
delete sMutex;
delete sCondVar;
sMutex = NULL;
sCondVar = NULL;
}
// This function is called from the main (UI) thread.
void SignalTracerThread()
{
if (!sMutex || !sCondVar)
return;
MutexAutoLock lock(*sMutex);
if (!sTracerProcessed) {
sTracerProcessed = true;
sCondVar->Notify();
}
}
// This function is called from the background tracer thread.
bool FireAndWaitForTracerEvent()
{
MOZ_ASSERT(sMutex && sCondVar, "Tracing not initialized!");
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
MutexAutoLock lock(*sMutex);
if (sTracerProcessed) {
// Things are out of sync. This is likely because we're in
// the middle of shutting down. Just return false and hope the
// tracer thread is quitting anyway.
return false;
}
// Post an application-defined event to the main thread's event queue
// and wait for it to get processed.
[NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined
location:NSMakePoint(0,0)
modifierFlags:0
timestamp:0
windowNumber:0
context:NULL
subtype:kEventSubtypeTrace
data1:0
data2:0]
atStart:NO];
while (!sTracerProcessed)
sCondVar->Wait();
sTracerProcessed = false;
[pool release];
return true;
}
} // namespace mozilla
@@ -1,39 +0,0 @@
<html>
<head>
<script>
function boom()
{
document.body.style.position = "fixed"
setTimeout(boom2, 1);
}
function boom2()
{
lappy = document.getElementById("lappy");
lappy.style.display = "none"
setTimeout(boom3, 200);
}
function boom3()
{
dump("Reloading\n");
location.reload();
}
</script>
</head>
<body bgcolor="black" onload="boom()">
<span style="overflow: scroll; display: -moz-box;"></span>
<embed id="lappy" src="" width=550 height=400 TYPE="application/x-shockwave-flash" ></embed>
</body>
</html>
-9
View File
@@ -1,9 +0,0 @@
<html class="reftest-wait">
<head>
<script>
setTimeout('document.documentElement.className = ""', 1000);
</script>
<body>
<iframe src="373122-1-inner.html"></iframe>
</body>
</html>
-7
View File
@@ -1,7 +0,0 @@
<html>
<head>
</head>
<body>
<button style="width: 8205em;"></button>
</body>
</html>
-10
View File
@@ -1,10 +0,0 @@
<html xmlns="http://www.w3.org/1999/xhtml"
class="reftest-wait"
style="margin: 12em; padding: 20px 10em; opacity: 0.2; font-size: 11.2px; -moz-appearance: toolbar; white-space: nowrap;"><body
style="position: absolute;"
onload="setTimeout(function() { document.body.removeChild(document.getElementById('tr')); document.documentElement.removeAttribute('class'); }, 30);">
xxx
yyy
<tr id="tr">300</tr></body></html>
-8
View File
@@ -1,8 +0,0 @@
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div><span style="-moz-appearance: radio; padding: 15000px;"></span></div>
</body>
</html>
-8
View File
@@ -1,8 +0,0 @@
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div style="min-width: -moz-max-content;"><div style="-moz-appearance: button;"><div style="margin: 0 100%;"></div></div></div>
</body>
</html>
-3
View File
@@ -1,3 +0,0 @@
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<hbox><button width="7788025414616">S</button></hbox>
</window>
-6
View File
@@ -1,6 +0,0 @@
<!DOCTYPE html>
<html>
<body>
<div style="padding: 10px;"><input type="button" value="Go" style="letter-spacing: 331989pt;"></div>
</body>
</html>
-4
View File
@@ -1,4 +0,0 @@
<html>
<head></head>
<body><div style="display: -moz-box; word-spacing: 549755813889px;"><button>T </button></div></body>
</html>
-4
View File
@@ -1,4 +0,0 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head></head>
<body><div><mstyle xmlns="http://www.w3.org/1998/Math/MathML" style="-moz-appearance: button;"/></div></body>
</html>
-2
View File
@@ -1,2 +0,0 @@
<!DOCTYPE html>
<html><head></head><body><div style="display: table; padding: 625203mm; -moz-appearance: menulist;"></div></body></html>
-20
View File
@@ -1,20 +0,0 @@
<html>
<head>
<script type="text/javascript">
function boom()
{
var o2 = document.createElement("option");
document.getElementById("o1").appendChild(o2);
o2.style.padding = "131072cm";
}
</script>
</head>
<body onload="boom();">
<select><option id="o1" style="height: 0cm;"></option></select>
</body>
</html>
-11
View File
@@ -1,11 +0,0 @@
skip-if(!cocoaWidget) load 373122-1.html # bug 1300017
load 397209-1.html
load 403296-1.xhtml
load 419737-1.html
load 435223-1.html
load 444260-1.xul
load 444864-1.html
load 449111-1.html
load 460349-1.xhtml
load 460387-1.html
load 464589-1.html
Binary file not shown.

Before

Width:  |  Height:  |  Size: 256 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 655 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 256 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 649 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 268 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 647 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 836 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 723 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 284 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 621 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 331 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 852 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 794 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 975 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 660 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 278 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 790 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 976 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 270 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 802 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 806 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 655 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 650 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

-140
View File
@@ -1,140 +0,0 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 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/.
XPIDL_SOURCES += [
'nsPIWidgetCocoa.idl',
]
XPIDL_MODULE = 'widget_cocoa'
EXPORTS += [
'mozView.h',
'nsBidiKeyboard.h',
'nsChangeObserver.h',
'nsCocoaDebugUtils.h',
'nsCocoaFeatures.h',
'nsCocoaUtils.h',
]
UNIFIED_SOURCES += [
'ComplexTextInputPanel.mm',
'GfxInfo.mm',
'NativeKeyBindings.mm',
'nsAppShell.mm',
'nsBidiKeyboard.mm',
'nsCocoaFeatures.mm',
'nsCocoaUtils.mm',
'nsCocoaWindow.mm',
'nsColorPicker.mm',
'nsCursorManager.mm',
'nsDeviceContextSpecX.mm',
'nsFilePicker.mm',
'nsIdleServiceX.mm',
'nsLookAndFeel.mm',
'nsMacCursor.mm',
'nsMacDockSupport.mm',
'nsMacWebAppUtils.mm',
'nsMenuBarX.mm',
'nsMenuGroupOwnerX.mm',
'nsMenuItemIconX.mm',
'nsMenuItemX.mm',
'nsMenuUtilsX.mm',
'nsMenuX.mm',
'nsPrintDialogX.mm',
'nsPrintOptionsX.mm',
'nsPrintSettingsX.mm',
'nsScreenCocoa.mm',
'nsScreenManagerCocoa.mm',
'nsSound.mm',
'nsStandaloneNativeMenu.mm',
'nsSystemStatusBarCocoa.mm',
'nsToolkit.mm',
'nsWidgetFactory.mm',
'nsWindowMap.mm',
'OSXNotificationCenter.mm',
'RectTextureImage.mm',
'SwipeTracker.mm',
'TextInputHandler.mm',
'VibrancyManager.mm',
'ViewRegion.mm',
'WidgetTraceEvent.mm',
]
# These files cannot be built in unified mode because they cause symbol conflicts
SOURCES += [
'nsChildView.mm',
'nsClipboard.mm',
'nsCocoaDebugUtils.mm',
'nsDragService.mm',
'nsNativeThemeCocoa.mm',
]
if not CONFIG['RELEASE_OR_BETA'] or CONFIG['MOZ_DEBUG']:
SOURCES += [
'nsSandboxViolationSink.mm',
]
include('/ipc/chromium/chromium-config.mozbuild')
# XXX: We should fix these warnings.
ALLOW_COMPILER_WARNINGS = True
FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [
'/layout/forms',
'/layout/generic',
'/layout/style',
'/layout/xul',
'/widget',
]
RESOURCE_FILES.cursors += [
'cursors/arrowN.png',
'cursors/arrowN@2x.png',
'cursors/arrowS.png',
'cursors/arrowS@2x.png',
'cursors/cell.png',
'cursors/cell@2x.png',
'cursors/colResize.png',
'cursors/colResize@2x.png',
'cursors/help.png',
'cursors/help@2x.png',
'cursors/move.png',
'cursors/move@2x.png',
'cursors/rowResize.png',
'cursors/rowResize@2x.png',
'cursors/sizeNE.png',
'cursors/sizeNE@2x.png',
'cursors/sizeNESW.png',
'cursors/sizeNESW@2x.png',
'cursors/sizeNS.png',
'cursors/sizeNS@2x.png',
'cursors/sizeNW.png',
'cursors/sizeNW@2x.png',
'cursors/sizeNWSE.png',
'cursors/sizeNWSE@2x.png',
'cursors/sizeSE.png',
'cursors/sizeSE@2x.png',
'cursors/sizeSW.png',
'cursors/sizeSW@2x.png',
'cursors/vtIBeam.png',
'cursors/vtIBeam@2x.png',
'cursors/zoomIn.png',
'cursors/zoomIn@2x.png',
'cursors/zoomOut.png',
'cursors/zoomOut@2x.png',
]
# These resources go in $(DIST)/bin/res/MainMenu.nib, but we can't use a magic
# RESOURCE_FILES.MainMenu.nib attribute, since that would put the files in
# $(DIST)/bin/res/MainMenu/nib. Instead, we call __setattr__ directly to create
# an attribute with the correct name.
RESOURCE_FILES.__setattr__('MainMenu.nib', [
'resources/MainMenu.nib/classes.nib',
'resources/MainMenu.nib/info.nib',
'resources/MainMenu.nib/keyedobjects.nib',
])
CXXFLAGS += CONFIG['TK_CFLAGS']
-62
View File
@@ -1,62 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozView_h_
#define mozView_h_
#undef DARWIN
#import <Cocoa/Cocoa.h>
class nsIWidget;
namespace mozilla {
namespace widget{
class TextInputHandler;
} // namespace widget
} // namespace mozilla
// A protocol listing all the methods that an object which wants
// to live in gecko's widget hierarchy must implement. |nsChildView|
// makes assumptions that any NSView with which it comes in contact will
// implement this protocol.
@protocol mozView
// aHandler is Gecko's default text input handler: It implements the
// NSTextInput protocol to handle key events. Don't make aHandler a
// strong reference -- that causes a memory leak.
- (void)installTextInputHandler:(mozilla::widget::TextInputHandler*)aHandler;
- (void)uninstallTextInputHandler;
// access the nsIWidget associated with this view. DOES NOT ADDREF.
- (nsIWidget*)widget;
// return a context menu for this view
- (NSMenu*)contextMenu;
// called when our corresponding Gecko view goes away
- (void)widgetDestroyed;
- (BOOL)isDragInProgress;
// Checks whether the view is first responder or not
- (BOOL)isFirstResponder;
// Call when you dispatch an event which may cause to open context menu.
- (void)maybeInitContextMenuTracking;
@end
// An informal protocol implemented by the NSWindow of the host application.
//
// It's used to prevent re-entrant calls to -makeKeyAndOrderFront: when gecko
// focus/activate events propagate out to the embedder's
// nsIEmbeddingSiteWindow::SetFocus implementation.
@interface NSObject(mozWindow)
- (BOOL)suppressMakeKeyFront;
- (void)setSuppressMakeKeyFront:(BOOL)inSuppress;
@end
#endif // mozView_h_
-71
View File
@@ -1,71 +0,0 @@
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* Runs the main native Cocoa run loop, interrupting it as needed to process
* Gecko events.
*/
#ifndef nsAppShell_h_
#define nsAppShell_h_
#include "nsBaseAppShell.h"
#include "nsTArray.h"
// GeckoNSApplication
//
// Subclass of NSApplication for filtering out certain events.
@interface GeckoNSApplication : NSApplication
{
}
@end
@class AppShellDelegate;
class nsAppShell : public nsBaseAppShell
{
public:
NS_IMETHOD ResumeNative(void);
nsAppShell();
nsresult Init();
NS_IMETHOD Run(void);
NS_IMETHOD Exit(void);
NS_IMETHOD OnProcessNextEvent(nsIThreadInternal *aThread, bool aMayWait);
NS_IMETHOD AfterProcessNextEvent(nsIThreadInternal *aThread,
bool aEventWasProcessed);
// public only to be visible to Objective-C code that must call it
void WillTerminate();
protected:
virtual ~nsAppShell();
virtual void ScheduleNativeEventCallback();
virtual bool ProcessNextNativeEvent(bool aMayWait);
static void ProcessGeckoEvents(void* aInfo);
protected:
CFMutableArrayRef mAutoreleasePools;
AppShellDelegate* mDelegate;
CFRunLoopRef mCFRunLoop;
CFRunLoopSourceRef mCFRunLoopSource;
bool mRunningEventLoop;
bool mStarted;
bool mTerminated;
bool mSkippedNativeCallback;
bool mRunningCocoaEmbedded;
int32_t mNativeEventCallbackDepth;
// Can be set from different threads, so must be modified atomically
int32_t mNativeEventScheduledDepth;
};
#endif // nsAppShell_h_
-907
View File
@@ -1,907 +0,0 @@
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* Runs the main native Cocoa run loop, interrupting it as needed to process
* Gecko events.
*/
#import <Cocoa/Cocoa.h>
#include "CustomCocoaEvents.h"
#include "mozilla/WidgetTraceEvent.h"
#include "nsAppShell.h"
#include "nsCOMPtr.h"
#include "nsIFile.h"
#include "nsDirectoryServiceDefs.h"
#include "nsString.h"
#include "nsIRollupListener.h"
#include "nsIWidget.h"
#include "nsThreadUtils.h"
#include "nsIWindowMediator.h"
#include "nsServiceManagerUtils.h"
#include "nsIInterfaceRequestor.h"
#include "nsIWebBrowserChrome.h"
#include "nsObjCExceptions.h"
#include "nsCocoaFeatures.h"
#include "nsCocoaUtils.h"
#include "nsChildView.h"
#include "nsToolkit.h"
#include "TextInputHandler.h"
#include "mozilla/HangMonitor.h"
#include "GeckoProfiler.h"
#include "pratom.h"
#if !defined(RELEASE_OR_BETA) || defined(DEBUG)
#include "nsSandboxViolationSink.h"
#endif
#include <IOKit/pwr_mgt/IOPMLib.h>
#include "nsIDOMWakeLockListener.h"
#include "nsIPowerManagerService.h"
using namespace mozilla::widget;
// A wake lock listener that disables screen saver when requested by
// Gecko. For example when we're playing video in a foreground tab we
// don't want the screen saver to turn on.
class MacWakeLockListener final : public nsIDOMMozWakeLockListener {
public:
NS_DECL_ISUPPORTS;
private:
~MacWakeLockListener() {}
IOPMAssertionID mAssertionID = kIOPMNullAssertionID;
NS_IMETHOD Callback(const nsAString& aTopic, const nsAString& aState) override {
if (!aTopic.EqualsASCII("screen")) {
return NS_OK;
}
// Note the wake lock code ensures that we're not sent duplicate
// "locked-foreground" notifications when multiple wake locks are held.
if (aState.EqualsASCII("locked-foreground")) {
// Prevent screen saver.
CFStringRef cf_topic =
::CFStringCreateWithCharacters(kCFAllocatorDefault,
reinterpret_cast<const UniChar*>
(aTopic.Data()),
aTopic.Length());
IOReturn success =
::IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep,
kIOPMAssertionLevelOn,
cf_topic,
&mAssertionID);
CFRelease(cf_topic);
if (success != kIOReturnSuccess) {
NS_WARNING("failed to disable screensaver");
}
} else {
// Re-enable screen saver.
NS_WARNING("Releasing screensaver");
if (mAssertionID != kIOPMNullAssertionID) {
IOReturn result = ::IOPMAssertionRelease(mAssertionID);
if (result != kIOReturnSuccess) {
NS_WARNING("failed to release screensaver");
}
}
}
return NS_OK;
}
}; // MacWakeLockListener
// defined in nsCocoaWindow.mm
extern int32_t gXULModalLevel;
static bool gAppShellMethodsSwizzled = false;
@implementation GeckoNSApplication
- (void)sendEvent:(NSEvent *)anEvent
{
mozilla::HangMonitor::NotifyActivity();
if ([anEvent type] == NSApplicationDefined &&
[anEvent subtype] == kEventSubtypeTrace) {
mozilla::SignalTracerThread();
return;
}
[super sendEvent:anEvent];
}
#if defined(MAC_OS_X_VERSION_10_12) && \
MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12 && \
__LP64__
// 10.12 changed `mask` to NSEventMask (unsigned long long) for x86_64 builds.
- (NSEvent*)nextEventMatchingMask:(NSEventMask)mask
#else
- (NSEvent*)nextEventMatchingMask:(NSUInteger)mask
#endif
untilDate:(NSDate*)expiration
inMode:(NSString*)mode
dequeue:(BOOL)flag
{
if (expiration) {
mozilla::HangMonitor::Suspend();
}
NSEvent* nextEvent = [super nextEventMatchingMask:mask
untilDate:expiration inMode:mode dequeue:flag];
if (expiration) {
mozilla::HangMonitor::NotifyActivity();
}
return nextEvent;
}
@end
// AppShellDelegate
//
// Cocoa bridge class. An object of this class is registered to receive
// notifications.
//
@interface AppShellDelegate : NSObject
{
@private
nsAppShell* mAppShell;
}
- (id)initWithAppShell:(nsAppShell*)aAppShell;
- (void)applicationWillTerminate:(NSNotification*)aNotification;
- (void)beginMenuTracking:(NSNotification*)aNotification;
@end
// nsAppShell implementation
NS_IMETHODIMP
nsAppShell::ResumeNative(void)
{
nsresult retval = nsBaseAppShell::ResumeNative();
if (NS_SUCCEEDED(retval) && (mSuspendNativeCount == 0) &&
mSkippedNativeCallback)
{
mSkippedNativeCallback = false;
ScheduleNativeEventCallback();
}
return retval;
}
nsAppShell::nsAppShell()
: mAutoreleasePools(nullptr)
, mDelegate(nullptr)
, mCFRunLoop(NULL)
, mCFRunLoopSource(NULL)
, mRunningEventLoop(false)
, mStarted(false)
, mTerminated(false)
, mSkippedNativeCallback(false)
, mNativeEventCallbackDepth(0)
, mNativeEventScheduledDepth(0)
{
// A Cocoa event loop is running here if (and only if) we've been embedded
// by a Cocoa app.
mRunningCocoaEmbedded = [NSApp isRunning] ? true : false;
}
nsAppShell::~nsAppShell()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
if (mCFRunLoop) {
if (mCFRunLoopSource) {
::CFRunLoopRemoveSource(mCFRunLoop, mCFRunLoopSource,
kCFRunLoopCommonModes);
::CFRelease(mCFRunLoopSource);
}
::CFRelease(mCFRunLoop);
}
if (mAutoreleasePools) {
NS_ASSERTION(::CFArrayGetCount(mAutoreleasePools) == 0,
"nsAppShell destroyed without popping all autorelease pools");
::CFRelease(mAutoreleasePools);
}
[mDelegate release];
NS_OBJC_END_TRY_ABORT_BLOCK
}
NS_IMPL_ISUPPORTS(MacWakeLockListener, nsIDOMMozWakeLockListener)
mozilla::StaticRefPtr<MacWakeLockListener> sWakeLockListener;
static void
AddScreenWakeLockListener()
{
nsCOMPtr<nsIPowerManagerService> sPowerManagerService = do_GetService(
POWERMANAGERSERVICE_CONTRACTID);
if (sPowerManagerService) {
sWakeLockListener = new MacWakeLockListener();
sPowerManagerService->AddWakeLockListener(sWakeLockListener);
} else {
NS_WARNING("Failed to retrieve PowerManagerService, wakelocks will be broken!");
}
}
static void
RemoveScreenWakeLockListener()
{
nsCOMPtr<nsIPowerManagerService> sPowerManagerService = do_GetService(
POWERMANAGERSERVICE_CONTRACTID);
if (sPowerManagerService) {
sPowerManagerService->RemoveWakeLockListener(sWakeLockListener);
sPowerManagerService = nullptr;
sWakeLockListener = nullptr;
}
}
// An undocumented CoreGraphics framework method, present in the same form
// since at least OS X 10.5.
extern "C" CGError CGSSetDebugOptions(int options);
// Init
//
// Loads the nib (see bug 316076c21) and sets up the CFRunLoopSource used to
// interrupt the main native run loop.
//
// public
nsresult
nsAppShell::Init()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
// No event loop is running yet (unless an embedding app that uses
// NSApplicationMain() is running).
NSAutoreleasePool* localPool = [[NSAutoreleasePool alloc] init];
// mAutoreleasePools is used as a stack of NSAutoreleasePool objects created
// by |this|. CFArray is used instead of NSArray because NSArray wants to
// retain each object you add to it, and you can't retain an
// NSAutoreleasePool.
mAutoreleasePools = ::CFArrayCreateMutable(nullptr, 0, nullptr);
NS_ENSURE_STATE(mAutoreleasePools);
// Get the path of the nib file, which lives in the GRE location
nsCOMPtr<nsIFile> nibFile;
nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(nibFile));
NS_ENSURE_SUCCESS(rv, rv);
nibFile->AppendNative(NS_LITERAL_CSTRING("res"));
nibFile->AppendNative(NS_LITERAL_CSTRING("MainMenu.nib"));
nsAutoCString nibPath;
rv = nibFile->GetNativePath(nibPath);
NS_ENSURE_SUCCESS(rv, rv);
// This call initializes NSApplication unless:
// 1) we're using xre -- NSApp's already been initialized by
// MacApplicationDelegate.mm's EnsureUseCocoaDockAPI().
// 2) an embedding app that uses NSApplicationMain() is running -- NSApp's
// already been initialized and its main run loop is already running.
[NSBundle loadNibFile:
[NSString stringWithUTF8String:(const char*)nibPath.get()]
externalNameTable:
[NSDictionary dictionaryWithObject:[GeckoNSApplication sharedApplication]
forKey:@"NSOwner"]
withZone:NSDefaultMallocZone()];
mDelegate = [[AppShellDelegate alloc] initWithAppShell:this];
NS_ENSURE_STATE(mDelegate);
// Add a CFRunLoopSource to the main native run loop. The source is
// responsible for interrupting the run loop when Gecko events are ready.
mCFRunLoop = [[NSRunLoop currentRunLoop] getCFRunLoop];
NS_ENSURE_STATE(mCFRunLoop);
::CFRetain(mCFRunLoop);
CFRunLoopSourceContext context;
bzero(&context, sizeof(context));
// context.version = 0;
context.info = this;
context.perform = ProcessGeckoEvents;
mCFRunLoopSource = ::CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
NS_ENSURE_STATE(mCFRunLoopSource);
::CFRunLoopAddSource(mCFRunLoop, mCFRunLoopSource, kCFRunLoopCommonModes);
rv = nsBaseAppShell::Init();
if (!gAppShellMethodsSwizzled) {
// We should only replace the original terminate: method if we're not
// running in a Cocoa embedder. See bug 604901.
if (!mRunningCocoaEmbedded) {
nsToolkit::SwizzleMethods([NSApplication class], @selector(terminate:),
@selector(nsAppShell_NSApplication_terminate:));
}
gAppShellMethodsSwizzled = true;
}
if (nsCocoaFeatures::OnYosemiteOrLater()) {
// Explicitly turn off CGEvent logging. This works around bug 1092855.
// If there are already CGEvents in the log, turning off logging also
// causes those events to be written to disk. But at this point no
// CGEvents have yet been processed. CGEvents are events (usually
// input events) pulled from the WindowServer. An option of 0x80000008
// turns on CGEvent logging.
CGSSetDebugOptions(0x80000007);
}
#if !defined(RELEASE_OR_BETA) || defined(DEBUG)
if (Preferences::GetBool("security.sandbox.mac.track.violations", false)) {
nsSandboxViolationSink::Start();
}
#endif
[localPool release];
return rv;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
// ProcessGeckoEvents
//
// The "perform" target of mCFRunLoop, called when mCFRunLoopSource is
// signalled from ScheduleNativeEventCallback.
//
// Arrange for Gecko events to be processed on demand (in response to a call
// to ScheduleNativeEventCallback(), if processing of Gecko events via "native
// methods" hasn't been suspended). This happens in NativeEventCallback().
//
// protected static
void
nsAppShell::ProcessGeckoEvents(void* aInfo)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
PROFILER_LABEL("Events", "ProcessGeckoEvents",
js::ProfileEntry::Category::EVENTS);
nsAppShell* self = static_cast<nsAppShell*> (aInfo);
if (self->mRunningEventLoop) {
self->mRunningEventLoop = false;
// The run loop may be sleeping -- [NSRunLoop runMode:...]
// won't return until it's given a reason to wake up. Awaken it by
// posting a bogus event. There's no need to make the event
// presentable.
//
// But _don't_ set windowNumber to '-1' -- that can lead to nasty
// weirdness like bmo bug 397039 (a crash in [NSApp sendEvent:] on one of
// these fake events, because the -1 has gotten changed into the number
// of an actual NSWindow object, and that NSWindow object has just been
// destroyed). Setting windowNumber to '0' seems to work fine -- this
// seems to prevent the OS from ever trying to associate our bogus event
// with a particular NSWindow object.
[NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined
location:NSMakePoint(0,0)
modifierFlags:0
timestamp:0
windowNumber:0
context:NULL
subtype:kEventSubtypeNone
data1:0
data2:0]
atStart:NO];
}
if (self->mSuspendNativeCount <= 0) {
++self->mNativeEventCallbackDepth;
self->NativeEventCallback();
--self->mNativeEventCallbackDepth;
} else {
self->mSkippedNativeCallback = true;
}
// Still needed to avoid crashes on quit in most Mochitests.
[NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined
location:NSMakePoint(0,0)
modifierFlags:0
timestamp:0
windowNumber:0
context:NULL
subtype:kEventSubtypeNone
data1:0
data2:0]
atStart:NO];
// Normally every call to ScheduleNativeEventCallback() results in
// exactly one call to ProcessGeckoEvents(). So each Release() here
// normally balances exactly one AddRef() in ScheduleNativeEventCallback().
// But if Exit() is called just after ScheduleNativeEventCallback(), the
// corresponding call to ProcessGeckoEvents() will never happen. We check
// for this possibility in two different places -- here and in Exit()
// itself. If we find here that Exit() has been called (that mTerminated
// is true), it's because we've been called recursively, that Exit() was
// called from self->NativeEventCallback() above, and that we're unwinding
// the recursion. In this case we'll never be called again, and we balance
// here any extra calls to ScheduleNativeEventCallback().
//
// When ProcessGeckoEvents() is called recursively, it's because of a
// call to ScheduleNativeEventCallback() from NativeEventCallback(). We
// balance the "extra" AddRefs here (rather than always in Exit()) in order
// to ensure that 'self' stays alive until the end of this method. We also
// make sure not to finish the balancing until all the recursion has been
// unwound.
if (self->mTerminated) {
int32_t releaseCount = 0;
if (self->mNativeEventScheduledDepth > self->mNativeEventCallbackDepth) {
releaseCount = PR_ATOMIC_SET(&self->mNativeEventScheduledDepth,
self->mNativeEventCallbackDepth);
}
while (releaseCount-- > self->mNativeEventCallbackDepth)
self->Release();
} else {
// As best we can tell, every call to ProcessGeckoEvents() is triggered
// by a call to ScheduleNativeEventCallback(). But we've seen a few
// (non-reproducible) cases of double-frees that *might* have been caused
// by spontaneous calls (from the OS) to ProcessGeckoEvents(). So we
// deal with that possibility here.
if (PR_ATOMIC_DECREMENT(&self->mNativeEventScheduledDepth) < 0) {
PR_ATOMIC_SET(&self->mNativeEventScheduledDepth, 0);
NS_WARNING("Spontaneous call to ProcessGeckoEvents()!");
} else {
self->Release();
}
}
NS_OBJC_END_TRY_ABORT_BLOCK;
}
// WillTerminate
//
// Called by the AppShellDelegate when an NSApplicationWillTerminate
// notification is posted. After this method is called, native events should
// no longer be processed. The NSApplicationWillTerminate notification is
// only posted when [NSApp terminate:] is called, which doesn't happen on a
// "normal" application quit.
//
// public
void
nsAppShell::WillTerminate()
{
if (mTerminated)
return;
// Make sure that the nsAppExitEvent posted by nsAppStartup::Quit() (called
// from [MacApplicationDelegate applicationShouldTerminate:]) gets run.
NS_ProcessPendingEvents(NS_GetCurrentThread());
mTerminated = true;
}
// ScheduleNativeEventCallback
//
// Called (possibly on a non-main thread) when Gecko has an event that
// needs to be processed. The Gecko event needs to be processed on the
// main thread, so the native run loop must be interrupted.
//
// In nsBaseAppShell.cpp, the mNativeEventPending variable is used to
// ensure that ScheduleNativeEventCallback() is called no more than once
// per call to NativeEventCallback(). ProcessGeckoEvents() can skip its
// call to NativeEventCallback() if processing of Gecko events by native
// means is suspended (using nsIAppShell::SuspendNative()), which will
// suspend calls from nsBaseAppShell::OnDispatchedEvent() to
// ScheduleNativeEventCallback(). But when Gecko event processing by
// native means is resumed (in ResumeNative()), an extra call is made to
// ScheduleNativeEventCallback() (from ResumeNative()). This triggers
// another call to ProcessGeckoEvents(), which calls NativeEventCallback(),
// and nsBaseAppShell::OnDispatchedEvent() resumes calling
// ScheduleNativeEventCallback().
//
// protected virtual
void
nsAppShell::ScheduleNativeEventCallback()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
if (mTerminated)
return;
// Each AddRef() here is normally balanced by exactly one Release() in
// ProcessGeckoEvents(). But there are exceptions, for which see
// ProcessGeckoEvents() and Exit().
NS_ADDREF_THIS();
PR_ATOMIC_INCREMENT(&mNativeEventScheduledDepth);
// This will invoke ProcessGeckoEvents on the main thread.
::CFRunLoopSourceSignal(mCFRunLoopSource);
::CFRunLoopWakeUp(mCFRunLoop);
NS_OBJC_END_TRY_ABORT_BLOCK;
}
// Undocumented Cocoa Event Manager function, present in the same form since
// at least OS X 10.6.
extern "C" EventAttributes GetEventAttributes(EventRef inEvent);
// ProcessNextNativeEvent
//
// If aMayWait is false, process a single native event. If it is true, run
// the native run loop until stopped by ProcessGeckoEvents.
//
// Returns true if more events are waiting in the native event queue.
//
// protected virtual
bool
nsAppShell::ProcessNextNativeEvent(bool aMayWait)
{
bool moreEvents = false;
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
bool eventProcessed = false;
NSString* currentMode = nil;
if (mTerminated)
return false;
bool wasRunningEventLoop = mRunningEventLoop;
mRunningEventLoop = aMayWait;
NSDate* waitUntil = nil;
if (aMayWait)
waitUntil = [NSDate distantFuture];
NSRunLoop* currentRunLoop = [NSRunLoop currentRunLoop];
EventQueueRef currentEventQueue = GetCurrentEventQueue();
EventTargetRef eventDispatcherTarget = GetEventDispatcherTarget();
if (aMayWait) {
mozilla::HangMonitor::Suspend();
}
// Only call -[NSApp sendEvent:] (and indirectly send user-input events to
// Gecko) if aMayWait is true. Tbis ensures most calls to -[NSApp
// sendEvent:] happen under nsAppShell::Run(), at the lowest level of
// recursion -- thereby making it less likely Gecko will process user-input
// events in the wrong order or skip some of them. It also avoids eating
// too much CPU in nsBaseAppShell::OnProcessNextEvent() (which calls
// us) -- thereby avoiding the starvation of nsIRunnable events in
// nsThread::ProcessNextEvent(). For more information see bug 996848.
do {
// No autorelease pool is provided here, because OnProcessNextEvent
// and AfterProcessNextEvent are responsible for maintaining it.
NS_ASSERTION(mAutoreleasePools && ::CFArrayGetCount(mAutoreleasePools),
"No autorelease pool for native event");
if (aMayWait) {
currentMode = [currentRunLoop currentMode];
if (!currentMode)
currentMode = NSDefaultRunLoopMode;
NSEvent *nextEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:waitUntil
inMode:currentMode
dequeue:YES];
if (nextEvent) {
mozilla::HangMonitor::NotifyActivity();
[NSApp sendEvent:nextEvent];
eventProcessed = true;
}
} else {
// AcquireFirstMatchingEventInQueue() doesn't spin the (native) event
// loop, though it does queue up any newly available events from the
// window server.
EventRef currentEvent = AcquireFirstMatchingEventInQueue(currentEventQueue, 0, NULL,
kEventQueueOptionsNone);
if (!currentEvent) {
continue;
}
EventAttributes attrs = GetEventAttributes(currentEvent);
UInt32 eventKind = GetEventKind(currentEvent);
UInt32 eventClass = GetEventClass(currentEvent);
bool osCocoaEvent =
((eventClass == 'appl') || (eventClass == kEventClassAppleEvent) ||
((eventClass == 'cgs ') && (eventKind != NSApplicationDefined)));
// If attrs is kEventAttributeUserEvent or kEventAttributeMonitored
// (i.e. a user input event), we shouldn't process it here while
// aMayWait is false. Likewise if currentEvent will eventually be
// turned into an OS-defined Cocoa event, or otherwise needs AppKit
// processing. Doing otherwise risks doing too much work here, and
// preventing the event from being properly processed by the AppKit
// framework.
if ((attrs != kEventAttributeNone) || osCocoaEvent) {
// Since we can't process the next event here (while aMayWait is false),
// we want moreEvents to be false on return.
eventProcessed = false;
// This call to ReleaseEvent() matches a call to RetainEvent() in
// AcquireFirstMatchingEventInQueue() above.
ReleaseEvent(currentEvent);
break;
}
// This call to RetainEvent() matches a call to ReleaseEvent() in
// RemoveEventFromQueue() below.
RetainEvent(currentEvent);
RemoveEventFromQueue(currentEventQueue, currentEvent);
SendEventToEventTarget(currentEvent, eventDispatcherTarget);
// This call to ReleaseEvent() matches a call to RetainEvent() in
// AcquireFirstMatchingEventInQueue() above.
ReleaseEvent(currentEvent);
eventProcessed = true;
}
} while (mRunningEventLoop);
if (eventProcessed) {
moreEvents =
(AcquireFirstMatchingEventInQueue(currentEventQueue, 0, NULL,
kEventQueueOptionsNone) != NULL);
}
mRunningEventLoop = wasRunningEventLoop;
NS_OBJC_END_TRY_ABORT_BLOCK;
if (!moreEvents) {
nsChildView::UpdateCurrentInputEventCount();
}
return moreEvents;
}
// Run
//
// Overrides the base class's Run() method to call [NSApp run] (which spins
// the native run loop until the application quits). Since (unlike the base
// class's Run() method) we don't process any Gecko events here, they need
// to be processed elsewhere (in NativeEventCallback(), called from
// ProcessGeckoEvents()).
//
// Camino called [NSApp run] on its own (via NSApplicationMain()), and so
// didn't call nsAppShell::Run().
//
// public
NS_IMETHODIMP
nsAppShell::Run(void)
{
NS_ASSERTION(!mStarted, "nsAppShell::Run() called multiple times");
if (mStarted || mTerminated)
return NS_OK;
mStarted = true;
AddScreenWakeLockListener();
NS_OBJC_TRY_ABORT([NSApp run]);
RemoveScreenWakeLockListener();
return NS_OK;
}
NS_IMETHODIMP
nsAppShell::Exit(void)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
// This method is currently called more than once -- from (according to
// mento) an nsAppExitEvent dispatched by nsAppStartup::Quit() and from an
// XPCOM shutdown notification that nsBaseAppShell has registered to
// receive. So we need to ensure that multiple calls won't break anything.
// But we should also complain about it (since it isn't quite kosher).
if (mTerminated) {
NS_WARNING("nsAppShell::Exit() called redundantly");
return NS_OK;
}
mTerminated = true;
#if !defined(RELEASE_OR_BETA) || defined(DEBUG)
nsSandboxViolationSink::Stop();
#endif
// Quoting from Apple's doc on the [NSApplication stop:] method (from their
// doc on the NSApplication class): "If this method is invoked during a
// modal event loop, it will break that loop but not the main event loop."
// nsAppShell::Exit() shouldn't be called from a modal event loop. So if
// it is we complain about it (to users of debug builds) and call [NSApp
// stop:] one extra time. (I'm not sure if modal event loops can be nested
// -- Apple's docs don't say one way or the other. But the return value
// of [NSApp _isRunningModal] doesn't change immediately after a call to
// [NSApp stop:], so we have to assume that one extra call to [NSApp stop:]
// will do the job.)
BOOL cocoaModal = [NSApp _isRunningModal];
NS_ASSERTION(!cocoaModal,
"Don't call nsAppShell::Exit() from a modal event loop!");
if (cocoaModal)
[NSApp stop:nullptr];
[NSApp stop:nullptr];
// A call to Exit() just after a call to ScheduleNativeEventCallback()
// prevents the (normally) matching call to ProcessGeckoEvents() from
// happening. If we've been called from ProcessGeckoEvents() (as usually
// happens), we take care of it there. But if we have an unbalanced call
// to ScheduleNativeEventCallback() and ProcessGeckoEvents() isn't on the
// stack, we need to take care of the problem here.
if (!mNativeEventCallbackDepth && mNativeEventScheduledDepth) {
int32_t releaseCount = PR_ATOMIC_SET(&mNativeEventScheduledDepth, 0);
while (releaseCount-- > 0)
NS_RELEASE_THIS();
}
return nsBaseAppShell::Exit();
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
// OnProcessNextEvent
//
// This nsIThreadObserver method is called prior to processing an event.
// Set up an autorelease pool that will service any autoreleased Cocoa
// objects during this event. This includes native events processed by
// ProcessNextNativeEvent. The autorelease pool will be popped by
// AfterProcessNextEvent, it is important for these two methods to be
// tightly coupled.
//
// public
NS_IMETHODIMP
nsAppShell::OnProcessNextEvent(nsIThreadInternal *aThread, bool aMayWait)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
NS_ASSERTION(mAutoreleasePools,
"No stack on which to store autorelease pool");
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
::CFArrayAppendValue(mAutoreleasePools, pool);
return nsBaseAppShell::OnProcessNextEvent(aThread, aMayWait);
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
// AfterProcessNextEvent
//
// This nsIThreadObserver method is called after event processing is complete.
// The Cocoa implementation cleans up the autorelease pool create by the
// previous OnProcessNextEvent call.
//
// public
NS_IMETHODIMP
nsAppShell::AfterProcessNextEvent(nsIThreadInternal *aThread,
bool aEventWasProcessed)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
CFIndex count = ::CFArrayGetCount(mAutoreleasePools);
NS_ASSERTION(mAutoreleasePools && count,
"Processed an event, but there's no autorelease pool?");
const NSAutoreleasePool* pool = static_cast<const NSAutoreleasePool*>
(::CFArrayGetValueAtIndex(mAutoreleasePools, count - 1));
::CFArrayRemoveValueAtIndex(mAutoreleasePools, count - 1);
[pool release];
return nsBaseAppShell::AfterProcessNextEvent(aThread, aEventWasProcessed);
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
// AppShellDelegate implementation
@implementation AppShellDelegate
// initWithAppShell:
//
// Constructs the AppShellDelegate object
- (id)initWithAppShell:(nsAppShell*)aAppShell
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if ((self = [self init])) {
mAppShell = aAppShell;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillTerminate:)
name:NSApplicationWillTerminateNotification
object:NSApp];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationDidBecomeActive:)
name:NSApplicationDidBecomeActiveNotification
object:NSApp];
[[NSDistributedNotificationCenter defaultCenter] addObserver:self
selector:@selector(beginMenuTracking:)
name:@"com.apple.HIToolbox.beginMenuTrackingNotification"
object:nil];
}
return self;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
- (void)dealloc
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
NS_OBJC_END_TRY_ABORT_BLOCK;
}
// applicationWillTerminate:
//
// Notify the nsAppShell that native event processing should be discontinued.
- (void)applicationWillTerminate:(NSNotification*)aNotification
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
mAppShell->WillTerminate();
NS_OBJC_END_TRY_ABORT_BLOCK;
}
// applicationDidBecomeActive
//
// Make sure TextInputHandler::sLastModifierState is updated when we become
// active (since we won't have received [ChildView flagsChanged:] messages
// while inactive).
- (void)applicationDidBecomeActive:(NSNotification*)aNotification
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
// [NSEvent modifierFlags] is valid on every kind of event, so we don't need
// to worry about getting an NSInternalInconsistencyException here.
NSEvent* currentEvent = [NSApp currentEvent];
if (currentEvent) {
TextInputHandler::sLastModifierState =
[currentEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask;
}
NS_OBJC_END_TRY_ABORT_BLOCK;
}
// beginMenuTracking
//
// Roll up our context menu (if any) when some other app (or the OS) opens
// any sort of menu. But make sure we don't do this for notifications we
// send ourselves (whose 'sender' will be @"org.mozilla.gecko.PopupWindow").
- (void)beginMenuTracking:(NSNotification*)aNotification
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
NSString *sender = [aNotification object];
if (!sender || ![sender isEqualToString:@"org.mozilla.gecko.PopupWindow"]) {
nsIRollupListener* rollupListener = nsBaseWidget::GetActiveRollupListener();
nsCOMPtr<nsIWidget> rollupWidget = rollupListener->GetRollupWidget();
if (rollupWidget)
rollupListener->Rollup(0, true, nullptr, nullptr);
}
NS_OBJC_END_TRY_ABORT_BLOCK;
}
@end
// We hook terminate: in order to make OS-initiated termination work nicely
// with Gecko's shutdown sequence. (Two ways to trigger OS-initiated
// termination: 1) Quit from the Dock menu; 2) Log out from (or shut down)
// your computer while the browser is active.)
@interface NSApplication (MethodSwizzling)
- (void)nsAppShell_NSApplication_terminate:(id)sender;
@end
@implementation NSApplication (MethodSwizzling)
// Called by the OS after [MacApplicationDelegate applicationShouldTerminate:]
// has returned NSTerminateNow. This method "subclasses" and replaces the
// OS's original implementation. The only thing the orginal method does which
// we need is that it posts NSApplicationWillTerminateNotification. Everything
// else is unneeded (because it's handled elsewhere), or actively interferes
// with Gecko's shutdown sequence. For example the original terminate: method
// causes the app to exit() inside [NSApp run] (called from nsAppShell::Run()
// above), which means that nothing runs after the call to nsAppStartup::Run()
// in XRE_Main(), which in particular means that ScopedXPCOMStartup's destructor
// and NS_ShutdownXPCOM() never get called.
- (void)nsAppShell_NSApplication_terminate:(id)sender
{
[[NSNotificationCenter defaultCenter] postNotificationName:NSApplicationWillTerminateNotification
object:NSApp];
}
@end
-24
View File
@@ -1,24 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsBidiKeyboard_h_
#define nsBidiKeyboard_h_
#include "nsIBidiKeyboard.h"
class nsBidiKeyboard : public nsIBidiKeyboard
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIBIDIKEYBOARD
nsBidiKeyboard();
protected:
virtual ~nsBidiKeyboard();
};
#endif // nsBidiKeyboard_h_
-42
View File
@@ -1,42 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsBidiKeyboard.h"
#include "nsCocoaUtils.h"
#include "TextInputHandler.h"
// This must be the last include:
#include "nsObjCExceptions.h"
using namespace mozilla::widget;
NS_IMPL_ISUPPORTS(nsBidiKeyboard, nsIBidiKeyboard)
nsBidiKeyboard::nsBidiKeyboard() : nsIBidiKeyboard()
{
Reset();
}
nsBidiKeyboard::~nsBidiKeyboard()
{
}
NS_IMETHODIMP nsBidiKeyboard::Reset()
{
return NS_OK;
}
NS_IMETHODIMP nsBidiKeyboard::IsLangRTL(bool *aIsRTL)
{
*aIsRTL = TISInputSourceWrapper::CurrentInputSource().IsForRTLLanguage();
return NS_OK;
}
NS_IMETHODIMP nsBidiKeyboard::GetHaveBidiKeyboards(bool* aResult)
{
// not implemented yet
return NS_ERROR_NOT_IMPLEMENTED;
}
-44
View File
@@ -1,44 +0,0 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsChangeObserver_h_
#define nsChangeObserver_h_
class nsIContent;
class nsIDocument;
class nsIAtom;
#define NS_DECL_CHANGEOBSERVER \
void ObserveAttributeChanged(nsIDocument *aDocument, nsIContent *aContent, nsIAtom *aAttribute) override; \
void ObserveContentRemoved(nsIDocument *aDocument, nsIContent *aChild, int32_t aIndexInContainer) override; \
void ObserveContentInserted(nsIDocument *aDocument, nsIContent* aContainer, nsIContent *aChild) override;
// Something that wants to be alerted to changes in attributes or changes in
// its corresponding content object.
//
// This interface is used by our menu code so we only have to have one
// nsIDocumentObserver.
//
// Any class that implements this interface must take care to unregister itself
// on deletion.
class nsChangeObserver
{
public:
// XXX use dom::Element
virtual void ObserveAttributeChanged(nsIDocument* aDocument,
nsIContent* aContent,
nsIAtom* aAttribute)=0;
virtual void ObserveContentRemoved(nsIDocument* aDocument,
nsIContent* aChild,
int32_t aIndexInContainer)=0;
virtual void ObserveContentInserted(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild)=0;
};
#endif // nsChangeObserver_h_
-666
View File
@@ -1,666 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsChildView_h_
#define nsChildView_h_
// formal protocols
#include "mozView.h"
#ifdef ACCESSIBILITY
#include "mozilla/a11y/Accessible.h"
#include "mozAccessibleProtocol.h"
#endif
#include "nsISupports.h"
#include "nsBaseWidget.h"
#include "nsWeakPtr.h"
#include "TextInputHandler.h"
#include "nsCocoaUtils.h"
#include "gfxQuartzSurface.h"
#include "GLContextTypes.h"
#include "mozilla/Mutex.h"
#include "nsRegion.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/UniquePtr.h"
#include "nsString.h"
#include "nsIDragService.h"
#include "ViewRegion.h"
#import <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
#import <AppKit/NSOpenGL.h>
class nsChildView;
class nsCocoaWindow;
namespace {
class GLPresenter;
} // namespace
namespace mozilla {
class InputData;
class PanGestureInput;
class SwipeTracker;
struct SwipeEventQueue;
class VibrancyManager;
namespace layers {
class GLManager;
class IAPZCTreeManager;
} // namespace layers
namespace widget {
class RectTextureImage;
class WidgetRenderingContext;
} // namespace widget
} // namespace mozilla
@class PixelHostingView;
@interface NSEvent (Undocumented)
// Return Cocoa event's corresponding Carbon event. Not initialized (on
// synthetic events) until the OS actually "sends" the event. This method
// has been present in the same form since at least OS X 10.2.8.
- (EventRef)_eventRef;
@end
@interface NSView (Undocumented)
// Draws the title string of a window.
// Present on NSThemeFrame since at least 10.6.
// _drawTitleBar is somewhat complex, and has changed over the years
// since OS X 10.6. But in that time it's never done anything that
// would break when called outside of -[NSView drawRect:] (which we
// sometimes do), or whose output can't be redirected to a
// CGContextRef object (which we also sometimes do). This is likely
// to remain true for the indefinite future. However we should
// check _drawTitleBar in each new major version of OS X. For more
// information see bug 877767.
- (void)_drawTitleBar:(NSRect)aRect;
// Returns an NSRect that is the bounding box for all an NSView's dirty
// rectangles (ones that need to be redrawn). The full list of dirty
// rectangles can be obtained by calling -[NSView _dirtyRegion] and then
// calling -[NSRegion getRects:count:] on what it returns. Both these
// methods have been present in the same form since at least OS X 10.5.
// Unlike -[NSView getRectsBeingDrawn:count:], these methods can be called
// outside a call to -[NSView drawRect:].
- (NSRect)_dirtyRect;
// Undocumented method of one or more of NSFrameView's subclasses. Called
// when one or more of the titlebar buttons needs to be repositioned, to
// disappear, or to reappear (say if the window's style changes). If
// 'redisplay' is true, the entire titlebar (the window's top 22 pixels) is
// marked as needing redisplay. This method has been present in the same
// format since at least OS X 10.5.
- (void)_tileTitlebarAndRedisplay:(BOOL)redisplay;
// The following undocumented methods are used to work around bug 1069658,
// which is an Apple bug or design flaw that effects Yosemite. None of them
// were present prior to Yosemite (OS X 10.10).
- (NSView *)titlebarView; // Method of NSThemeFrame
- (NSView *)titlebarContainerView; // Method of NSThemeFrame
- (BOOL)transparent; // Method of NSTitlebarView and NSTitlebarContainerView
- (void)setTransparent:(BOOL)transparent; // Method of NSTitlebarView and
// NSTitlebarContainerView
@end
@interface ChildView : NSView<
#ifdef ACCESSIBILITY
mozAccessible,
#endif
mozView, NSTextInputClient>
{
@private
// the nsChildView that created the view. It retains this NSView, so
// the link back to it must be weak.
nsChildView* mGeckoChild;
// Text input handler for mGeckoChild and us. Note that this is a weak
// reference. Ideally, this should be a strong reference but a ChildView
// object can live longer than the mGeckoChild that owns it. And if
// mTextInputHandler were a strong reference, this would make it difficult
// for Gecko's leak detector to detect leaked TextInputHandler objects.
// This is initialized by [mozView installTextInputHandler:aHandler] and
// cleared by [mozView uninstallTextInputHandler].
mozilla::widget::TextInputHandler* mTextInputHandler; // [WEAK]
// when mouseDown: is called, we store its event here (strong)
NSEvent* mLastMouseDownEvent;
// Needed for IME support in e10s mode. Strong.
NSEvent* mLastKeyDownEvent;
// Whether the last mouse down event was blocked from Gecko.
BOOL mBlockedLastMouseDown;
// when acceptsFirstMouse: is called, we store the event here (strong)
NSEvent* mClickThroughMouseDownEvent;
// WheelStart/Stop events should always come in pairs. This BOOL records the
// last received event so that, when we receive one of the events, we make sure
// to send its pair event first, in case we didn't yet for any reason.
BOOL mExpectingWheelStop;
// Set to YES when our GL surface has been updated and we need to call
// updateGLContext before we composite.
BOOL mNeedsGLUpdate;
// Holds our drag service across multiple drag calls. The reference to the
// service is obtained when the mouse enters the view and is released when
// the mouse exits or there is a drop. This prevents us from having to
// re-establish the connection to the service manager many times per second
// when handling |draggingUpdated:| messages.
nsIDragService* mDragService;
NSOpenGLContext *mGLContext;
// Simple gestures support
//
// mGestureState is used to detect when Cocoa has called both
// magnifyWithEvent and rotateWithEvent within the same
// beginGestureWithEvent and endGestureWithEvent sequence. We
// discard the spurious gesture event so as not to confuse Gecko.
//
// mCumulativeMagnification keeps track of the total amount of
// magnification peformed during a magnify gesture so that we can
// send that value with the final MozMagnifyGesture event.
//
// mCumulativeRotation keeps track of the total amount of rotation
// performed during a rotate gesture so we can send that value with
// the final MozRotateGesture event.
enum {
eGestureState_None,
eGestureState_StartGesture,
eGestureState_MagnifyGesture,
eGestureState_RotateGesture
} mGestureState;
float mCumulativeMagnification;
float mCumulativeRotation;
#ifdef __LP64__
// Support for fluid swipe tracking.
BOOL* mCancelSwipeAnimation;
#endif
// Whether this uses off-main-thread compositing.
BOOL mUsingOMTCompositor;
// The mask image that's used when painting into the titlebar using basic
// CGContext painting (i.e. non-accelerated).
CGImageRef mTopLeftCornerMask;
// Subviews of self, which act as container views for vibrancy views and
// non-draggable views.
NSView* mVibrancyViewsContainer; // [STRONG]
NSView* mNonDraggableViewsContainer; // [STRONG]
// The view that does our drawing. This is a subview of self so that it can
// be ordered on top of mVibrancyViewsContainer.
PixelHostingView* mPixelHostingView;
}
// class initialization
+ (void)initialize;
+ (void)registerViewForDraggedTypes:(NSView*)aView;
// these are sent to the first responder when the window key status changes
- (void)viewsWindowDidBecomeKey;
- (void)viewsWindowDidResignKey;
// Stop NSView hierarchy being changed during [ChildView drawRect:]
- (void)delayedTearDown;
- (void)sendFocusEvent:(mozilla::EventMessage)eventMessage;
- (void)handleMouseMoved:(NSEvent*)aEvent;
- (void)sendMouseEnterOrExitEvent:(NSEvent*)aEvent
enter:(BOOL)aEnter
exitFrom:(mozilla::WidgetMouseEvent::ExitFrom)aExitFrom;
- (void)updateGLContext;
- (void)_surfaceNeedsUpdate:(NSNotification*)notification;
- (bool)preRender:(NSOpenGLContext *)aGLContext;
- (void)postRender:(NSOpenGLContext *)aGLContext;
- (NSView*)vibrancyViewsContainer;
- (NSView*)nonDraggableViewsContainer;
- (NSView*)pixelHostingView;
- (BOOL)isCoveringTitlebar;
- (void)viewWillStartLiveResize;
- (void)viewDidEndLiveResize;
- (NSColor*)vibrancyFillColorForThemeGeometryType:(nsITheme::ThemeGeometryType)aThemeGeometryType;
- (NSColor*)vibrancyFontSmoothingBackgroundColorForThemeGeometryType:(nsITheme::ThemeGeometryType)aThemeGeometryType;
// Simple gestures support
//
// XXX - The swipeWithEvent, beginGestureWithEvent, magnifyWithEvent,
// rotateWithEvent, and endGestureWithEvent methods are part of a
// PRIVATE interface exported by nsResponder and reverse-engineering
// was necessary to obtain the methods' prototypes. Thus, Apple may
// change the interface in the future without notice.
//
// The prototypes were obtained from the following link:
// http://cocoadex.com/2008/02/nsevent-modifications-swipe-ro.html
- (void)swipeWithEvent:(NSEvent *)anEvent;
- (void)beginGestureWithEvent:(NSEvent *)anEvent;
- (void)magnifyWithEvent:(NSEvent *)anEvent;
- (void)smartMagnifyWithEvent:(NSEvent *)anEvent;
- (void)rotateWithEvent:(NSEvent *)anEvent;
- (void)endGestureWithEvent:(NSEvent *)anEvent;
- (void)scrollWheel:(NSEvent *)anEvent;
- (void)setUsingOMTCompositor:(BOOL)aUseOMTC;
- (NSEvent*)lastKeyDownEvent;
@end
class ChildViewMouseTracker {
public:
static void MouseMoved(NSEvent* aEvent);
static void MouseScrolled(NSEvent* aEvent);
static void OnDestroyView(ChildView* aView);
static void OnDestroyWindow(NSWindow* aWindow);
static BOOL WindowAcceptsEvent(NSWindow* aWindow, NSEvent* aEvent,
ChildView* aView, BOOL isClickThrough = NO);
static void MouseExitedWindow(NSEvent* aEvent);
static void MouseEnteredWindow(NSEvent* aEvent);
static void ReEvaluateMouseEnterState(NSEvent* aEvent = nil, ChildView* aOldView = nil);
static void ResendLastMouseMoveEvent();
static ChildView* ViewForEvent(NSEvent* aEvent);
static ChildView* sLastMouseEventView;
static NSEvent* sLastMouseMoveEvent;
static NSWindow* sWindowUnderMouse;
static NSPoint sLastScrollEventScreenLocation;
};
//-------------------------------------------------------------------------
//
// nsChildView
//
//-------------------------------------------------------------------------
class nsChildView : public nsBaseWidget
{
private:
typedef nsBaseWidget Inherited;
typedef mozilla::layers::IAPZCTreeManager IAPZCTreeManager;
public:
nsChildView();
// nsIWidget interface
virtual MOZ_MUST_USE nsresult Create(nsIWidget* aParent,
nsNativeWidget aNativeParent,
const LayoutDeviceIntRect& aRect,
nsWidgetInitData* aInitData = nullptr)
override;
virtual void Destroy() override;
NS_IMETHOD Show(bool aState) override;
virtual bool IsVisible() const override;
NS_IMETHOD SetParent(nsIWidget* aNewParent) override;
virtual nsIWidget* GetParent(void) override;
virtual float GetDPI() override;
NS_IMETHOD Move(double aX, double aY) override;
NS_IMETHOD Resize(double aWidth, double aHeight, bool aRepaint) override;
NS_IMETHOD Resize(double aX, double aY,
double aWidth, double aHeight, bool aRepaint) override;
NS_IMETHOD Enable(bool aState) override;
virtual bool IsEnabled() const override;
NS_IMETHOD SetFocus(bool aRaise) override;
virtual LayoutDeviceIntRect GetBounds() override;
virtual LayoutDeviceIntRect GetClientBounds() override;
virtual LayoutDeviceIntRect GetScreenBounds() override;
// Returns the "backing scale factor" of the view's window, which is the
// ratio of pixels in the window's backing store to Cocoa points. Prior to
// HiDPI support in OS X 10.7, this was always 1.0, but in HiDPI mode it
// will be 2.0 (and might potentially other values as screen resolutions
// evolve). This gives the relationship between what Gecko calls "device
// pixels" and the Cocoa "points" coordinate system.
CGFloat BackingScaleFactor() const;
mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale() final {
return mozilla::DesktopToLayoutDeviceScale(BackingScaleFactor());
}
// Call if the window's backing scale factor changes - i.e., it is moved
// between HiDPI and non-HiDPI screens
void BackingScaleFactorChanged();
virtual double GetDefaultScaleInternal() override;
virtual int32_t RoundsWidgetCoordinatesTo() override;
NS_IMETHOD Invalidate(const LayoutDeviceIntRect &aRect) override;
virtual void* GetNativeData(uint32_t aDataType) override;
virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations) override;
virtual LayoutDeviceIntPoint WidgetToScreenOffset() override;
virtual bool ShowsResizeIndicator(LayoutDeviceIntRect* aResizerRect) override;
static bool ConvertStatus(nsEventStatus aStatus)
{ return aStatus == nsEventStatus_eConsumeNoDefault; }
NS_IMETHOD DispatchEvent(mozilla::WidgetGUIEvent* aEvent,
nsEventStatus& aStatus) override;
virtual bool WidgetTypeSupportsAcceleration() override;
virtual bool ShouldUseOffMainThreadCompositing() override;
NS_IMETHOD SetCursor(nsCursor aCursor) override;
NS_IMETHOD SetCursor(imgIContainer* aCursor, uint32_t aHotspotX, uint32_t aHotspotY) override;
NS_IMETHOD SetTitle(const nsAString& title) override;
NS_IMETHOD GetAttention(int32_t aCycleCount) override;
virtual bool HasPendingInputEvent() override;
NS_IMETHOD ActivateNativeMenuItemAt(const nsAString& indexString) override;
NS_IMETHOD ForceUpdateNativeMenuAt(const nsAString& indexString) override;
NS_IMETHOD GetSelectionAsPlaintext(nsAString& aResult) override;
NS_IMETHOD_(void) SetInputContext(const InputContext& aContext,
const InputContextAction& aAction) override;
NS_IMETHOD_(InputContext) GetInputContext() override;
NS_IMETHOD_(TextEventDispatcherListener*)
GetNativeTextEventDispatcherListener() override;
NS_IMETHOD AttachNativeKeyEvent(mozilla::WidgetKeyboardEvent& aEvent) override;
NS_IMETHOD_(bool) ExecuteNativeKeyBinding(
NativeKeyBindingsType aType,
const mozilla::WidgetKeyboardEvent& aEvent,
DoCommandCallback aCallback,
void* aCallbackData) override;
bool ExecuteNativeKeyBindingRemapped(
NativeKeyBindingsType aType,
const mozilla::WidgetKeyboardEvent& aEvent,
DoCommandCallback aCallback,
void* aCallbackData,
uint32_t aGeckoKeyCode,
uint32_t aCocoaKeyCode);
virtual nsIMEUpdatePreference GetIMEUpdatePreference() override;
virtual nsTransparencyMode GetTransparencyMode() override;
virtual void SetTransparencyMode(nsTransparencyMode aMode) override;
virtual nsresult SynthesizeNativeKeyEvent(int32_t aNativeKeyboardLayout,
int32_t aNativeKeyCode,
uint32_t aModifierFlags,
const nsAString& aCharacters,
const nsAString& aUnmodifiedCharacters,
nsIObserver* aObserver) override;
virtual nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint,
uint32_t aNativeMessage,
uint32_t aModifierFlags,
nsIObserver* aObserver) override;
virtual nsresult SynthesizeNativeMouseMove(LayoutDeviceIntPoint aPoint,
nsIObserver* aObserver) override
{ return SynthesizeNativeMouseEvent(aPoint, NSMouseMoved, 0, aObserver); }
virtual nsresult SynthesizeNativeMouseScrollEvent(LayoutDeviceIntPoint aPoint,
uint32_t aNativeMessage,
double aDeltaX,
double aDeltaY,
double aDeltaZ,
uint32_t aModifierFlags,
uint32_t aAdditionalFlags,
nsIObserver* aObserver) override;
virtual nsresult SynthesizeNativeTouchPoint(uint32_t aPointerId,
TouchPointerState aPointerState,
LayoutDeviceIntPoint aPoint,
double aPointerPressure,
uint32_t aPointerOrientation,
nsIObserver* aObserver) override;
// Mac specific methods
virtual bool DispatchWindowEvent(mozilla::WidgetGUIEvent& event);
void WillPaintWindow();
bool PaintWindow(LayoutDeviceIntRegion aRegion);
bool PaintWindowInContext(CGContextRef aContext, const LayoutDeviceIntRegion& aRegion,
mozilla::gfx::IntSize aSurfaceSize);
#ifdef ACCESSIBILITY
already_AddRefed<mozilla::a11y::Accessible> GetDocumentAccessible();
#endif
virtual void CreateCompositor() override;
virtual void PrepareWindowEffects() override;
virtual void CleanupWindowEffects() override;
virtual bool PreRender(mozilla::widget::WidgetRenderingContext* aContext) override;
virtual void PostRender(mozilla::widget::WidgetRenderingContext* aContext) override;
virtual void DrawWindowOverlay(mozilla::widget::WidgetRenderingContext* aManager,
LayoutDeviceIntRect aRect) override;
virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) override;
virtual void UpdateWindowDraggingRegion(const LayoutDeviceIntRegion& aRegion) override;
LayoutDeviceIntRegion GetNonDraggableRegion() { return mNonDraggableRegion.Region(); }
virtual void ReportSwipeStarted(uint64_t aInputBlockId, bool aStartSwipe) override;
virtual void LookUpDictionary(
const nsAString& aText,
const nsTArray<mozilla::FontRange>& aFontRangeArray,
const bool aIsVertical,
const LayoutDeviceIntPoint& aPoint) override;
void ResetParent();
static bool DoHasPendingInputEvent();
static uint32_t GetCurrentInputEventCount();
static void UpdateCurrentInputEventCount();
NSView<mozView>* GetEditorView();
nsCocoaWindow* GetXULWindowWidget();
virtual void ReparentNativeWidget(nsIWidget* aNewParent) override;
mozilla::widget::TextInputHandler* GetTextInputHandler()
{
return mTextInputHandler;
}
void ClearVibrantAreas();
NSColor* VibrancyFillColorForThemeGeometryType(nsITheme::ThemeGeometryType aThemeGeometryType);
NSColor* VibrancyFontSmoothingBackgroundColorForThemeGeometryType(nsITheme::ThemeGeometryType aThemeGeometryType);
// unit conversion convenience functions
int32_t CocoaPointsToDevPixels(CGFloat aPts) const {
return nsCocoaUtils::CocoaPointsToDevPixels(aPts, BackingScaleFactor());
}
LayoutDeviceIntPoint CocoaPointsToDevPixels(const NSPoint& aPt) const {
return nsCocoaUtils::CocoaPointsToDevPixels(aPt, BackingScaleFactor());
}
LayoutDeviceIntPoint CocoaPointsToDevPixelsRoundDown(const NSPoint& aPt) const {
return nsCocoaUtils::CocoaPointsToDevPixelsRoundDown(aPt, BackingScaleFactor());
}
LayoutDeviceIntRect CocoaPointsToDevPixels(const NSRect& aRect) const {
return nsCocoaUtils::CocoaPointsToDevPixels(aRect, BackingScaleFactor());
}
CGFloat DevPixelsToCocoaPoints(int32_t aPixels) const {
return nsCocoaUtils::DevPixelsToCocoaPoints(aPixels, BackingScaleFactor());
}
NSRect DevPixelsToCocoaPoints(const LayoutDeviceIntRect& aRect) const {
return nsCocoaUtils::DevPixelsToCocoaPoints(aRect, BackingScaleFactor());
}
already_AddRefed<mozilla::gfx::DrawTarget>
StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion,
mozilla::layers::BufferMode* aBufferMode) override;
void EndRemoteDrawing() override;
void CleanupRemoteDrawing() override;
bool InitCompositor(mozilla::layers::Compositor* aCompositor) override;
NS_IMETHOD StartPluginIME(const mozilla::WidgetKeyboardEvent& aKeyboardEvent,
int32_t aPanelX, int32_t aPanelY,
nsString& aCommitted) override;
virtual void SetPluginFocused(bool& aFocused) override;
bool IsPluginFocused() { return mPluginFocused; }
virtual LayoutDeviceIntPoint GetClientOffset() override;
void DispatchAPZWheelInputEvent(mozilla::InputData& aEvent, bool aCanTriggerSwipe);
void SwipeFinished();
protected:
virtual ~nsChildView();
void ReportMoveEvent();
void ReportSizeEvent();
void TearDownView();
virtual already_AddRefed<nsIWidget>
AllocateChildPopupWidget() override
{
static NS_DEFINE_IID(kCPopUpCID, NS_POPUP_CID);
nsCOMPtr<nsIWidget> widget = do_CreateInstance(kCPopUpCID);
return widget.forget();
}
void ConfigureAPZCTreeManager() override;
void ConfigureAPZControllerThread() override;
void DoRemoteComposition(const LayoutDeviceIntRect& aRenderRect);
// Overlay drawing functions for OpenGL drawing
void DrawWindowOverlay(mozilla::layers::GLManager* aManager, LayoutDeviceIntRect aRect);
void MaybeDrawResizeIndicator(mozilla::layers::GLManager* aManager);
void MaybeDrawRoundedCorners(mozilla::layers::GLManager* aManager, const LayoutDeviceIntRect& aRect);
void MaybeDrawTitlebar(mozilla::layers::GLManager* aManager);
// Redraw the contents of mTitlebarCGContext on the main thread, as
// determined by mDirtyTitlebarRegion.
void UpdateTitlebarCGContext();
LayoutDeviceIntRect RectContainingTitlebarControls();
void UpdateVibrancy(const nsTArray<ThemeGeometry>& aThemeGeometries);
mozilla::VibrancyManager& EnsureVibrancyManager();
nsIWidget* GetWidgetForListenerEvents();
struct SwipeInfo {
bool wantsSwipe;
uint32_t allowedDirections;
};
SwipeInfo SendMayStartSwipe(const mozilla::PanGestureInput& aSwipeStartEvent);
void TrackScrollEventAsSwipe(const mozilla::PanGestureInput& aSwipeStartEvent,
uint32_t aAllowedDirections);
protected:
ChildView<mozView>* mView; // my parallel cocoa view, [STRONG]
RefPtr<mozilla::widget::TextInputHandler> mTextInputHandler;
InputContext mInputContext;
NSView<mozView>* mParentView;
nsIWidget* mParentWidget;
#ifdef ACCESSIBILITY
// weak ref to this childview's associated mozAccessible for speed reasons
// (we get queried for it *a lot* but don't want to own it)
nsWeakPtr mAccessible;
#endif
// Protects the view from being teared down while a composition is in
// progress on the compositor thread.
mozilla::Mutex mViewTearDownLock;
mozilla::Mutex mEffectsLock;
// May be accessed from any thread, protected
// by mEffectsLock.
bool mShowsResizeIndicator;
LayoutDeviceIntRect mResizeIndicatorRect;
bool mHasRoundedBottomCorners;
int mDevPixelCornerRadius;
bool mIsCoveringTitlebar;
bool mIsFullscreen;
bool mIsOpaque;
LayoutDeviceIntRect mTitlebarRect;
// The area of mTitlebarCGContext that needs to be redrawn during the next
// transaction. Accessed from any thread, protected by mEffectsLock.
LayoutDeviceIntRegion mUpdatedTitlebarRegion;
CGContextRef mTitlebarCGContext;
// Compositor thread only
mozilla::UniquePtr<mozilla::widget::RectTextureImage> mResizerImage;
mozilla::UniquePtr<mozilla::widget::RectTextureImage> mCornerMaskImage;
mozilla::UniquePtr<mozilla::widget::RectTextureImage> mTitlebarImage;
mozilla::UniquePtr<mozilla::widget::RectTextureImage> mBasicCompositorImage;
// The area of mTitlebarCGContext that has changed and needs to be
// uploaded to to mTitlebarImage. Main thread only.
nsIntRegion mDirtyTitlebarRegion;
mozilla::ViewRegion mNonDraggableRegion;
// Cached value of [mView backingScaleFactor], to avoid sending two obj-c
// messages (respondsToSelector, backingScaleFactor) every time we need to
// use it.
// ** We'll need to reinitialize this if the backing resolution changes. **
mutable CGFloat mBackingScaleFactor;
bool mVisible;
bool mDrawing;
bool mIsDispatchPaint; // Is a paint event being dispatched
bool mPluginFocused;
// Used in OMTC BasicLayers mode. Presents the BasicCompositor result
// surface to the screen using an OpenGL context.
mozilla::UniquePtr<GLPresenter> mGLPresenter;
mozilla::UniquePtr<mozilla::VibrancyManager> mVibrancyManager;
RefPtr<mozilla::SwipeTracker> mSwipeTracker;
mozilla::UniquePtr<mozilla::SwipeEventQueue> mSwipeEventQueue;
// Only used for drawRect-based painting in popups.
RefPtr<mozilla::gfx::DrawTarget> mBackingSurface;
// This flag is only used when APZ is off. It indicates that the current pan
// gesture was processed as a swipe. Sometimes the swipe animation can finish
// before momentum events of the pan gesture have stopped firing, so this
// flag tells us that we shouldn't allow the remaining events to cause
// scrolling. It is reset to false once a new gesture starts (as indicated by
// a PANGESTURE_(MAY)START event).
bool mCurrentPanGestureBelongsToSwipe;
static uint32_t sLastInputEventCount;
void ReleaseTitlebarCGContext();
// This is used by SynthesizeNativeTouchPoint to maintain state between
// multiple synthesized points
mozilla::UniquePtr<mozilla::MultiTouchInput> mSynthesizedTouchInput;
};
#endif // nsChildView_h_
File diff suppressed because it is too large Load Diff
-55
View File
@@ -1,55 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsClipboard_h_
#define nsClipboard_h_
#include "nsIClipboard.h"
#include "nsXPIDLString.h"
#include "mozilla/StaticPtr.h"
#import <Cocoa/Cocoa.h>
class nsITransferable;
class nsClipboard : public nsIClipboard
{
public:
nsClipboard();
NS_DECL_ISUPPORTS
NS_DECL_NSICLIPBOARD
// On macOS, cache the transferable of the current selection (chrome/content)
// in the parent process. This is needed for the services menu which
// requires synchronous access to the current selection.
static mozilla::StaticRefPtr<nsITransferable> sSelectionCache;
// Helper methods, used also by nsDragService
static NSDictionary* PasteboardDictFromTransferable(nsITransferable *aTransferable);
static bool IsStringType(const nsCString& aMIMEType, NSString** aPasteboardType);
static NSString* WrapHtmlForSystemPasteboard(NSString* aString);
static nsresult TransferableFromPasteboard(nsITransferable *aTransferable, NSPasteboard *pboard);
protected:
// impelement the native clipboard behavior
NS_IMETHOD SetNativeClipboardData(int32_t aWhichClipboard);
NS_IMETHOD GetNativeClipboardData(nsITransferable * aTransferable, int32_t aWhichClipboard);
void ClearSelectionCache();
void SetSelectionCache(nsITransferable* aTransferable);
private:
virtual ~nsClipboard();
int32_t mCachedClipboard;
int32_t mChangeCount; // Set to the native change count after any modification of the clipboard.
bool mIgnoreEmptyNotification;
nsCOMPtr<nsIClipboardOwner> mClipboardOwner;
nsCOMPtr<nsITransferable> mTransferable;
};
#endif // nsClipboard_h_
-775
View File
@@ -1,775 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/Logging.h"
#include "mozilla/Unused.h"
#include "gfxPlatform.h"
#include "nsArrayUtils.h"
#include "nsCOMPtr.h"
#include "nsClipboard.h"
#include "nsString.h"
#include "nsISupportsPrimitives.h"
#include "nsXPIDLString.h"
#include "nsPrimitiveHelpers.h"
#include "nsMemory.h"
#include "nsIFile.h"
#include "nsStringStream.h"
#include "nsDragService.h"
#include "nsEscape.h"
#include "nsPrintfCString.h"
#include "nsObjCExceptions.h"
#include "imgIContainer.h"
#include "nsCocoaUtils.h"
using mozilla::gfx::DataSourceSurface;
using mozilla::gfx::SourceSurface;
using mozilla::LogLevel;
// Screenshots use the (undocumented) png pasteboard type.
#define IMAGE_PASTEBOARD_TYPES NSTIFFPboardType, @"Apple PNG pasteboard type", nil
extern PRLogModuleInfo* sCocoaLog;
extern void EnsureLogInitialized();
mozilla::StaticRefPtr<nsITransferable> nsClipboard::sSelectionCache;
nsClipboard::nsClipboard()
: mCachedClipboard(-1)
, mChangeCount(0)
, mIgnoreEmptyNotification(false)
{
EnsureLogInitialized();
}
nsClipboard::~nsClipboard()
{
EmptyClipboard(kGlobalClipboard);
EmptyClipboard(kFindClipboard);
ClearSelectionCache();
}
NS_IMPL_ISUPPORTS(nsClipboard, nsIClipboard)
// We separate this into its own function because after an @try, all local
// variables within that function get marked as volatile, and our C++ type
// system doesn't like volatile things.
static NSData*
GetDataFromPasteboard(NSPasteboard* aPasteboard, NSString* aType)
{
NSData *data = nil;
@try {
data = [aPasteboard dataForType:aType];
} @catch (NSException* e) {
NS_WARNING(nsPrintfCString("Exception raised while getting data from the pasteboard: \"%s - %s\"",
[[e name] UTF8String], [[e reason] UTF8String]).get());
mozilla::Unused << e;
}
return data;
}
void
nsClipboard::SetSelectionCache(nsITransferable *aTransferable)
{
sSelectionCache = aTransferable;
}
void
nsClipboard::ClearSelectionCache()
{
sSelectionCache = nullptr;
}
NS_IMETHODIMP
nsClipboard::SetNativeClipboardData(int32_t aWhichClipboard)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
if ((aWhichClipboard != kGlobalClipboard && aWhichClipboard != kFindClipboard) || !mTransferable)
return NS_ERROR_FAILURE;
mIgnoreEmptyNotification = true;
NSDictionary* pasteboardOutputDict = PasteboardDictFromTransferable(mTransferable);
if (!pasteboardOutputDict)
return NS_ERROR_FAILURE;
unsigned int outputCount = [pasteboardOutputDict count];
NSArray* outputKeys = [pasteboardOutputDict allKeys];
NSPasteboard* cocoaPasteboard;
if (aWhichClipboard == kFindClipboard) {
cocoaPasteboard = [NSPasteboard pasteboardWithName:NSFindPboard];
[cocoaPasteboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
} else {
// Write everything else out to the general pasteboard.
cocoaPasteboard = [NSPasteboard generalPasteboard];
[cocoaPasteboard declareTypes:outputKeys owner:nil];
}
for (unsigned int i = 0; i < outputCount; i++) {
NSString* currentKey = [outputKeys objectAtIndex:i];
id currentValue = [pasteboardOutputDict valueForKey:currentKey];
if (aWhichClipboard == kFindClipboard) {
if (currentKey == NSStringPboardType)
[cocoaPasteboard setString:currentValue forType:currentKey];
} else {
if (currentKey == NSStringPboardType ||
currentKey == kCorePboardType_url ||
currentKey == kCorePboardType_urld ||
currentKey == kCorePboardType_urln) {
[cocoaPasteboard setString:currentValue forType:currentKey];
} else if (currentKey == NSHTMLPboardType) {
[cocoaPasteboard setString:(nsClipboard::WrapHtmlForSystemPasteboard(currentValue))
forType:currentKey];
} else {
[cocoaPasteboard setData:currentValue forType:currentKey];
}
}
}
mCachedClipboard = aWhichClipboard;
mChangeCount = [cocoaPasteboard changeCount];
mIgnoreEmptyNotification = false;
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
nsresult
nsClipboard::TransferableFromPasteboard(nsITransferable *aTransferable, NSPasteboard *cocoaPasteboard)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
// get flavor list that includes all acceptable flavors (including ones obtained through conversion)
nsCOMPtr<nsIArray> flavorList;
nsresult rv = aTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList));
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
uint32_t flavorCount;
flavorList->GetLength(&flavorCount);
for (uint32_t i = 0; i < flavorCount; i++) {
nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryElementAt(flavorList, i);
if (!currentFlavor)
continue;
nsXPIDLCString flavorStr;
currentFlavor->ToString(getter_Copies(flavorStr)); // i has a flavr
// printf("looking for clipboard data of type %s\n", flavorStr.get());
NSString *pboardType = nil;
if (nsClipboard::IsStringType(flavorStr, &pboardType)) {
NSString* pString = [cocoaPasteboard stringForType:pboardType];
if (!pString)
continue;
NSData* stringData;
if ([pboardType isEqualToString:NSRTFPboardType]) {
stringData = [pString dataUsingEncoding:NSASCIIStringEncoding];
} else {
stringData = [pString dataUsingEncoding:NSUnicodeStringEncoding];
}
unsigned int dataLength = [stringData length];
void* clipboardDataPtr = malloc(dataLength);
if (!clipboardDataPtr)
return NS_ERROR_OUT_OF_MEMORY;
[stringData getBytes:clipboardDataPtr];
// The DOM only wants LF, so convert from MacOS line endings to DOM line endings.
int32_t signedDataLength = dataLength;
nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks(flavorStr, &clipboardDataPtr, &signedDataLength);
dataLength = signedDataLength;
// skip BOM (Byte Order Mark to distinguish little or big endian)
char16_t* clipboardDataPtrNoBOM = (char16_t*)clipboardDataPtr;
if ((dataLength > 2) &&
((clipboardDataPtrNoBOM[0] == 0xFEFF) ||
(clipboardDataPtrNoBOM[0] == 0xFFFE))) {
dataLength -= sizeof(char16_t);
clipboardDataPtrNoBOM += 1;
}
nsCOMPtr<nsISupports> genericDataWrapper;
nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr, clipboardDataPtrNoBOM, dataLength,
getter_AddRefs(genericDataWrapper));
aTransferable->SetTransferData(flavorStr, genericDataWrapper, dataLength);
free(clipboardDataPtr);
break;
}
else if (flavorStr.EqualsLiteral(kCustomTypesMime)) {
NSString* type = [cocoaPasteboard availableTypeFromArray:[NSArray arrayWithObject:kCustomTypesPboardType]];
if (!type) {
continue;
}
NSData* pasteboardData = GetDataFromPasteboard(cocoaPasteboard, type);
if (!pasteboardData) {
continue;
}
unsigned int dataLength = [pasteboardData length];
void* clipboardDataPtr = malloc(dataLength);
if (!clipboardDataPtr) {
return NS_ERROR_OUT_OF_MEMORY;
}
[pasteboardData getBytes:clipboardDataPtr];
nsCOMPtr<nsISupports> genericDataWrapper;
nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr, clipboardDataPtr, dataLength,
getter_AddRefs(genericDataWrapper));
aTransferable->SetTransferData(flavorStr, genericDataWrapper, dataLength);
free(clipboardDataPtr);
}
else if (flavorStr.EqualsLiteral(kJPEGImageMime) ||
flavorStr.EqualsLiteral(kJPGImageMime) ||
flavorStr.EqualsLiteral(kPNGImageMime) ||
flavorStr.EqualsLiteral(kGIFImageMime)) {
// Figure out if there's data on the pasteboard we can grab (sanity check)
NSString *type = [cocoaPasteboard availableTypeFromArray:[NSArray arrayWithObjects:IMAGE_PASTEBOARD_TYPES]];
if (!type)
continue;
// Read data off the clipboard
NSData *pasteboardData = GetDataFromPasteboard(cocoaPasteboard, type);
if (!pasteboardData)
continue;
// Figure out what type we're converting to
CFStringRef outputType = NULL;
if (flavorStr.EqualsLiteral(kJPEGImageMime) ||
flavorStr.EqualsLiteral(kJPGImageMime))
outputType = CFSTR("public.jpeg");
else if (flavorStr.EqualsLiteral(kPNGImageMime))
outputType = CFSTR("public.png");
else if (flavorStr.EqualsLiteral(kGIFImageMime))
outputType = CFSTR("com.compuserve.gif");
else
continue;
// Use ImageIO to interpret the data on the clipboard and transcode.
// Note that ImageIO, like all CF APIs, allows NULLs to propagate freely
// and safely in most cases (like ObjC). A notable exception is CFRelease.
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
(NSNumber*)kCFBooleanTrue, kCGImageSourceShouldAllowFloat,
(type == NSTIFFPboardType ? @"public.tiff" : @"public.png"),
kCGImageSourceTypeIdentifierHint, nil];
CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)pasteboardData,
(CFDictionaryRef)options);
NSMutableData *encodedData = [NSMutableData data];
CGImageDestinationRef dest = CGImageDestinationCreateWithData((CFMutableDataRef)encodedData,
outputType,
1, NULL);
CGImageDestinationAddImageFromSource(dest, source, 0, NULL);
bool successfullyConverted = CGImageDestinationFinalize(dest);
if (successfullyConverted) {
// Put the converted data in a form Gecko can understand
nsCOMPtr<nsIInputStream> byteStream;
NS_NewByteInputStream(getter_AddRefs(byteStream), (const char*)[encodedData bytes],
[encodedData length], NS_ASSIGNMENT_COPY);
aTransferable->SetTransferData(flavorStr, byteStream, sizeof(nsIInputStream*));
}
if (dest)
CFRelease(dest);
if (source)
CFRelease(source);
if (successfullyConverted)
break;
else
continue;
}
}
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_IMETHODIMP
nsClipboard::GetNativeClipboardData(nsITransferable* aTransferable, int32_t aWhichClipboard)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
if ((aWhichClipboard != kGlobalClipboard && aWhichClipboard != kFindClipboard) || !aTransferable)
return NS_ERROR_FAILURE;
NSPasteboard* cocoaPasteboard;
if (aWhichClipboard == kFindClipboard) {
cocoaPasteboard = [NSPasteboard pasteboardWithName:NSFindPboard];
} else {
cocoaPasteboard = [NSPasteboard generalPasteboard];
}
if (!cocoaPasteboard)
return NS_ERROR_FAILURE;
// get flavor list that includes all acceptable flavors (including ones obtained through conversion)
nsCOMPtr<nsIArray> flavorList;
nsresult rv = aTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList));
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
uint32_t flavorCount;
flavorList->GetLength(&flavorCount);
// If we were the last ones to put something on the pasteboard, then just use the cached
// transferable. Otherwise clear it because it isn't relevant any more.
if (mCachedClipboard == aWhichClipboard &&
mChangeCount == [cocoaPasteboard changeCount]) {
if (mTransferable) {
for (uint32_t i = 0; i < flavorCount; i++) {
nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryElementAt(flavorList, i);
if (!currentFlavor)
continue;
nsXPIDLCString flavorStr;
currentFlavor->ToString(getter_Copies(flavorStr));
nsCOMPtr<nsISupports> dataSupports;
uint32_t dataSize = 0;
rv = mTransferable->GetTransferData(flavorStr, getter_AddRefs(dataSupports), &dataSize);
if (NS_SUCCEEDED(rv)) {
aTransferable->SetTransferData(flavorStr, dataSupports, dataSize);
return NS_OK; // maybe try to fill in more types? Is there a point?
}
}
}
} else {
EmptyClipboard(aWhichClipboard);
}
// at this point we can't satisfy the request from cache data so let's look
// for things other people put on the system clipboard
return nsClipboard::TransferableFromPasteboard(aTransferable, cocoaPasteboard);
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
// returns true if we have *any* of the passed in flavors available for pasting
NS_IMETHODIMP
nsClipboard::HasDataMatchingFlavors(const char** aFlavorList, uint32_t aLength,
int32_t aWhichClipboard, bool* outResult)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
*outResult = false;
if ((aWhichClipboard != kGlobalClipboard) || !aFlavorList)
return NS_OK;
// first see if we have data for this in our cached transferable
if (mTransferable) {
nsCOMPtr<nsIArray> transferableFlavorList;
nsresult rv = mTransferable->FlavorsTransferableCanImport(getter_AddRefs(transferableFlavorList));
if (NS_SUCCEEDED(rv)) {
uint32_t transferableFlavorCount;
transferableFlavorList->GetLength(&transferableFlavorCount);
for (uint32_t j = 0; j < transferableFlavorCount; j++) {
nsCOMPtr<nsISupportsCString> currentTransferableFlavor =
do_QueryElementAt(transferableFlavorList, j);
if (!currentTransferableFlavor)
continue;
nsXPIDLCString transferableFlavorStr;
currentTransferableFlavor->ToString(getter_Copies(transferableFlavorStr));
for (uint32_t k = 0; k < aLength; k++) {
if (transferableFlavorStr.Equals(aFlavorList[k])) {
*outResult = true;
return NS_OK;
}
}
}
}
}
NSPasteboard* generalPBoard = [NSPasteboard generalPasteboard];
for (uint32_t i = 0; i < aLength; i++) {
nsDependentCString mimeType(aFlavorList[i]);
NSString *pboardType = nil;
if (nsClipboard::IsStringType(mimeType, &pboardType)) {
NSString* availableType = [generalPBoard availableTypeFromArray:[NSArray arrayWithObject:pboardType]];
if (availableType && [availableType isEqualToString:pboardType]) {
*outResult = true;
break;
}
} else if (!strcmp(aFlavorList[i], kCustomTypesMime)) {
NSString* availableType = [generalPBoard availableTypeFromArray:[NSArray arrayWithObject:kCustomTypesPboardType]];
if (availableType) {
*outResult = true;
break;
}
} else if (!strcmp(aFlavorList[i], kJPEGImageMime) ||
!strcmp(aFlavorList[i], kJPGImageMime) ||
!strcmp(aFlavorList[i], kPNGImageMime) ||
!strcmp(aFlavorList[i], kGIFImageMime)) {
NSString* availableType = [generalPBoard availableTypeFromArray:
[NSArray arrayWithObjects:IMAGE_PASTEBOARD_TYPES]];
if (availableType) {
*outResult = true;
break;
}
}
}
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_IMETHODIMP
nsClipboard::SupportsFindClipboard(bool *_retval)
{
NS_ENSURE_ARG_POINTER(_retval);
*_retval = true;
return NS_OK;
}
// This function converts anything that other applications might understand into the system format
// and puts it into a dictionary which it returns.
// static
NSDictionary*
nsClipboard::PasteboardDictFromTransferable(nsITransferable* aTransferable)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if (!aTransferable)
return nil;
NSMutableDictionary* pasteboardOutputDict = [NSMutableDictionary dictionary];
nsCOMPtr<nsIArray> flavorList;
nsresult rv = aTransferable->FlavorsTransferableCanExport(getter_AddRefs(flavorList));
if (NS_FAILED(rv))
return nil;
uint32_t flavorCount;
flavorList->GetLength(&flavorCount);
for (uint32_t i = 0; i < flavorCount; i++) {
nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryElementAt(flavorList, i);
if (!currentFlavor)
continue;
nsXPIDLCString flavorStr;
currentFlavor->ToString(getter_Copies(flavorStr));
MOZ_LOG(sCocoaLog, LogLevel::Info, ("writing out clipboard data of type %s (%d)\n", flavorStr.get(), i));
NSString *pboardType = nil;
if (nsClipboard::IsStringType(flavorStr, &pboardType)) {
void* data = nullptr;
uint32_t dataSize = 0;
nsCOMPtr<nsISupports> genericDataWrapper;
rv = aTransferable->GetTransferData(flavorStr, getter_AddRefs(genericDataWrapper), &dataSize);
nsPrimitiveHelpers::CreateDataFromPrimitive(flavorStr, genericDataWrapper, &data, dataSize);
NSString* nativeString;
if (data)
nativeString = [NSString stringWithCharacters:(const unichar*)data length:(dataSize / sizeof(char16_t))];
else
nativeString = [NSString string];
// be nice to Carbon apps, normalize the receiver's contents using Form C.
nativeString = [nativeString precomposedStringWithCanonicalMapping];
[pasteboardOutputDict setObject:nativeString forKey:pboardType];
free(data);
}
else if (flavorStr.EqualsLiteral(kCustomTypesMime)) {
void* data = nullptr;
uint32_t dataSize = 0;
nsCOMPtr<nsISupports> genericDataWrapper;
rv = aTransferable->GetTransferData(flavorStr, getter_AddRefs(genericDataWrapper), &dataSize);
nsPrimitiveHelpers::CreateDataFromPrimitive(flavorStr, genericDataWrapper, &data, dataSize);
if (data) {
NSData* nativeData = [NSData dataWithBytes:data length:dataSize];
[pasteboardOutputDict setObject:nativeData forKey:kCustomTypesPboardType];
free(data);
}
}
else if (flavorStr.EqualsLiteral(kPNGImageMime) || flavorStr.EqualsLiteral(kJPEGImageMime) ||
flavorStr.EqualsLiteral(kJPGImageMime) || flavorStr.EqualsLiteral(kGIFImageMime) ||
flavorStr.EqualsLiteral(kNativeImageMime)) {
uint32_t dataSize = 0;
nsCOMPtr<nsISupports> transferSupports;
aTransferable->GetTransferData(flavorStr, getter_AddRefs(transferSupports), &dataSize);
nsCOMPtr<nsISupportsInterfacePointer> ptrPrimitive(do_QueryInterface(transferSupports));
if (!ptrPrimitive)
continue;
nsCOMPtr<nsISupports> primitiveData;
ptrPrimitive->GetData(getter_AddRefs(primitiveData));
nsCOMPtr<imgIContainer> image(do_QueryInterface(primitiveData));
if (!image) {
NS_WARNING("Image isn't an imgIContainer in transferable");
continue;
}
RefPtr<SourceSurface> surface =
image->GetFrame(imgIContainer::FRAME_CURRENT,
imgIContainer::FLAG_SYNC_DECODE);
if (!surface) {
continue;
}
CGImageRef imageRef = NULL;
rv = nsCocoaUtils::CreateCGImageFromSurface(surface, &imageRef);
if (NS_FAILED(rv) || !imageRef) {
continue;
}
// Convert the CGImageRef to TIFF data.
CFMutableDataRef tiffData = CFDataCreateMutable(kCFAllocatorDefault, 0);
CGImageDestinationRef destRef = CGImageDestinationCreateWithData(tiffData,
CFSTR("public.tiff"),
1,
NULL);
CGImageDestinationAddImage(destRef, imageRef, NULL);
bool successfullyConverted = CGImageDestinationFinalize(destRef);
CGImageRelease(imageRef);
if (destRef)
CFRelease(destRef);
if (!successfullyConverted) {
if (tiffData)
CFRelease(tiffData);
continue;
}
[pasteboardOutputDict setObject:(NSMutableData*)tiffData forKey:NSTIFFPboardType];
if (tiffData)
CFRelease(tiffData);
}
else if (flavorStr.EqualsLiteral(kFileMime)) {
uint32_t len = 0;
nsCOMPtr<nsISupports> genericFile;
rv = aTransferable->GetTransferData(flavorStr, getter_AddRefs(genericFile), &len);
if (NS_FAILED(rv)) {
continue;
}
nsCOMPtr<nsIFile> file(do_QueryInterface(genericFile));
if (!file) {
nsCOMPtr<nsISupportsInterfacePointer> ptr(do_QueryInterface(genericFile));
if (ptr) {
ptr->GetData(getter_AddRefs(genericFile));
file = do_QueryInterface(genericFile);
}
}
if (!file) {
continue;
}
nsAutoString fileURI;
rv = file->GetPath(fileURI);
if (NS_FAILED(rv)) {
continue;
}
NSString* str = nsCocoaUtils::ToNSString(fileURI);
NSArray* fileList = [NSArray arrayWithObjects:str, nil];
[pasteboardOutputDict setObject:fileList forKey:NSFilenamesPboardType];
}
else if (flavorStr.EqualsLiteral(kFilePromiseMime)) {
[pasteboardOutputDict setObject:[NSArray arrayWithObject:@""] forKey:NSFilesPromisePboardType];
}
else if (flavorStr.EqualsLiteral(kURLMime)) {
uint32_t len = 0;
nsCOMPtr<nsISupports> genericURL;
rv = aTransferable->GetTransferData(flavorStr, getter_AddRefs(genericURL), &len);
nsCOMPtr<nsISupportsString> urlObject(do_QueryInterface(genericURL));
nsAutoString url;
urlObject->GetData(url);
// A newline embedded in the URL means that the form is actually URL + title.
int32_t newlinePos = url.FindChar(char16_t('\n'));
if (newlinePos >= 0) {
url.Truncate(newlinePos);
nsAutoString urlTitle;
urlObject->GetData(urlTitle);
urlTitle.Mid(urlTitle, newlinePos + 1, len - (newlinePos + 1));
NSString *nativeTitle = [[NSString alloc] initWithCharacters:reinterpret_cast<const unichar*>(urlTitle.get())
length:urlTitle.Length()];
// be nice to Carbon apps, normalize the receiver's contents using Form C.
[pasteboardOutputDict setObject:[nativeTitle precomposedStringWithCanonicalMapping] forKey:kCorePboardType_urln];
// Also put the title out as 'urld', since some recipients will look for that.
[pasteboardOutputDict setObject:[nativeTitle precomposedStringWithCanonicalMapping] forKey:kCorePboardType_urld];
[nativeTitle release];
}
// The Finder doesn't like getting random binary data aka
// Unicode, so change it into an escaped URL containing only
// ASCII.
nsAutoCString utf8Data = NS_ConvertUTF16toUTF8(url.get(), url.Length());
nsAutoCString escData;
NS_EscapeURL(utf8Data.get(), utf8Data.Length(), esc_OnlyNonASCII|esc_AlwaysCopy, escData);
// printf("Escaped url is %s, length %d\n", escData.get(), escData.Length());
NSString *nativeURL = [NSString stringWithUTF8String:escData.get()];
[pasteboardOutputDict setObject:nativeURL forKey:kCorePboardType_url];
}
// If it wasn't a type that we recognize as exportable we don't put it on the system
// clipboard. We'll just access it from our cached transferable when we need it.
}
return pasteboardOutputDict;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
bool nsClipboard::IsStringType(const nsCString& aMIMEType, NSString** aPasteboardType)
{
if (aMIMEType.EqualsLiteral(kUnicodeMime)) {
*aPasteboardType = NSStringPboardType;
return true;
} else if (aMIMEType.EqualsLiteral(kRTFMime)) {
*aPasteboardType = NSRTFPboardType;
return true;
} else if (aMIMEType.EqualsLiteral(kHTMLMime)) {
*aPasteboardType = NSHTMLPboardType;
return true;
} else {
return false;
}
}
NSString* nsClipboard::WrapHtmlForSystemPasteboard(NSString* aString)
{
NSString* wrapped =
[NSString stringWithFormat:
@"<html>"
"<head>"
"<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">"
"</head>"
"<body>"
"%@"
"</body>"
"</html>", aString];
return wrapped;
}
/**
* Sets the transferable object
*
*/
NS_IMETHODIMP
nsClipboard::SetData(nsITransferable* aTransferable, nsIClipboardOwner* anOwner,
int32_t aWhichClipboard)
{
NS_ASSERTION (aTransferable, "clipboard given a null transferable");
if (aWhichClipboard == kSelectionCache) {
if (aTransferable) {
SetSelectionCache(aTransferable);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
if (aTransferable == mTransferable && anOwner == mClipboardOwner) {
return NS_OK;
}
bool selectClipPresent;
SupportsSelectionClipboard(&selectClipPresent);
bool findClipPresent;
SupportsFindClipboard(&findClipPresent);
if (!selectClipPresent && !findClipPresent && aWhichClipboard != kGlobalClipboard) {
return NS_ERROR_FAILURE;
}
EmptyClipboard(aWhichClipboard);
mClipboardOwner = anOwner;
mTransferable = aTransferable;
nsresult rv = NS_ERROR_FAILURE;
if (mTransferable) {
rv = SetNativeClipboardData(aWhichClipboard);
}
return rv;
}
/**
* Gets the transferable object
*
*/
NS_IMETHODIMP
nsClipboard::GetData(nsITransferable* aTransferable, int32_t aWhichClipboard)
{
NS_ASSERTION (aTransferable, "clipboard given a null transferable");
bool selectClipPresent;
SupportsSelectionClipboard(&selectClipPresent);
bool findClipPresent;
SupportsFindClipboard(&findClipPresent);
if (!selectClipPresent && !findClipPresent && aWhichClipboard != kGlobalClipboard)
return NS_ERROR_FAILURE;
if (aTransferable) {
return GetNativeClipboardData(aTransferable, aWhichClipboard);
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsClipboard::EmptyClipboard(int32_t aWhichClipboard)
{
if (aWhichClipboard == kSelectionCache) {
ClearSelectionCache();
return NS_OK;
}
bool selectClipPresent;
SupportsSelectionClipboard(&selectClipPresent);
bool findClipPresent;
SupportsFindClipboard(&findClipPresent);
if (!selectClipPresent && !findClipPresent && aWhichClipboard != kGlobalClipboard) {
return NS_ERROR_FAILURE;
}
if (mIgnoreEmptyNotification) {
return NS_OK;
}
if (mClipboardOwner) {
mClipboardOwner->LosingOwnership(mTransferable);
mClipboardOwner = nullptr;
}
mTransferable = nullptr;
return NS_OK;
}
NS_IMETHODIMP
nsClipboard::SupportsSelectionClipboard(bool* _retval)
{
*_retval = false; // we don't support the selection clipboard by default.
return NS_OK;
}
-136
View File
@@ -1,136 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsCocoaDebugUtils_h_
#define nsCocoaDebugUtils_h_
#include <CoreServices/CoreServices.h>
// Definitions and declarations of stuff used by us from the CoreSymbolication
// framework. This is an undocumented, private framework available on OS X
// 10.6 and up. It's used by Apple utilities like dtrace, atos, ReportCrash
// and crashreporterd.
typedef struct _CSTypeRef {
unsigned long type;
void* contents;
} CSTypeRef;
typedef CSTypeRef CSSymbolicatorRef;
typedef CSTypeRef CSSymbolOwnerRef;
typedef CSTypeRef CSSymbolRef;
typedef CSTypeRef CSSourceInfoRef;
typedef struct _CSRange {
unsigned long long location;
unsigned long long length;
} CSRange;
typedef unsigned long long CSArchitecture;
#define kCSNow LONG_MAX
extern "C" {
CSSymbolicatorRef
CSSymbolicatorCreateWithPid(pid_t pid);
CSSymbolicatorRef
CSSymbolicatorCreateWithPidFlagsAndNotification(pid_t pid,
uint32_t flags,
uint32_t notification);
CSArchitecture
CSSymbolicatorGetArchitecture(CSSymbolicatorRef symbolicator);
CSSymbolOwnerRef
CSSymbolicatorGetSymbolOwnerWithAddressAtTime(CSSymbolicatorRef symbolicator,
unsigned long long address,
long time);
const char*
CSSymbolOwnerGetName(CSSymbolOwnerRef owner);
unsigned long long
CSSymbolOwnerGetBaseAddress(CSSymbolOwnerRef owner);
CSSymbolRef
CSSymbolOwnerGetSymbolWithAddress(CSSymbolOwnerRef owner,
unsigned long long address);
CSSourceInfoRef
CSSymbolOwnerGetSourceInfoWithAddress(CSSymbolOwnerRef owner,
unsigned long long address);
const char*
CSSymbolGetName(CSSymbolRef symbol);
CSRange
CSSymbolGetRange(CSSymbolRef symbol);
const char*
CSSourceInfoGetFilename(CSSourceInfoRef info);
uint32_t
CSSourceInfoGetLineNumber(CSSourceInfoRef info);
CSTypeRef
CSRetain(CSTypeRef);
void
CSRelease(CSTypeRef);
bool
CSIsNull(CSTypeRef);
void
CSShow(CSTypeRef);
const char*
CSArchitectureGetFamilyName(CSArchitecture);
} // extern "C"
class nsCocoaDebugUtils
{
public:
// Like NSLog() but records more information (for example the full path to
// the executable and the "thread name"). Like NSLog(), writes to both
// stdout and the system log.
static void DebugLog(const char* aFormat, ...);
// Logs a stack trace of the current point of execution, to both stdout and
// the system log.
static void PrintStackTrace();
// Returns the name of the module that "owns" aAddress. This must be
// free()ed by the caller.
static char* GetOwnerName(void* aAddress);
// Returns a symbolicated representation of aAddress. This must be
// free()ed by the caller.
static char* GetAddressString(void* aAddress);
private:
static void DebugLogInt(bool aDecorate, const char* aFormat, ...);
static void DebugLogV(bool aDecorate, CFStringRef aFormat, va_list aArgs);
static void PrintAddress(void* aAddress);
// The values returned by GetOwnerNameInt() and GetAddressStringInt() must
// be free()ed by the caller.
static char* GetOwnerNameInt(void* aAddress,
CSTypeRef aOwner = sInitializer);
static char* GetAddressStringInt(void* aAddress,
CSTypeRef aOwner = sInitializer);
static CSSymbolicatorRef GetSymbolicatorRef();
static void ReleaseSymbolicator();
static CSTypeRef sInitializer;
static CSSymbolicatorRef sSymbolicator;
};
#endif // nsCocoaDebugUtils_h_
-284
View File
@@ -1,284 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsCocoaDebugUtils.h"
#include <pthread.h>
#include <libproc.h>
#include <stdarg.h>
#include <time.h>
#include <execinfo.h>
#include <asl.h>
static char gProcPath[PROC_PIDPATHINFO_MAXSIZE] = {0};
static char gBundleID[MAXPATHLEN] = {0};
static void MaybeGetPathAndID()
{
if (!gProcPath[0]) {
proc_pidpath(getpid(), gProcPath, sizeof(gProcPath));
}
if (!gBundleID[0]) {
// Apple's CFLog() uses "com.apple.console" (in its call to asl_open()) if
// it can't find the bundle id.
CFStringRef bundleID = NULL;
CFBundleRef mainBundle = CFBundleGetMainBundle();
if (mainBundle) {
bundleID = CFBundleGetIdentifier(mainBundle);
}
if (!bundleID) {
strcpy(gBundleID, "com.apple.console");
} else {
CFStringGetCString(bundleID, gBundleID, sizeof(gBundleID),
kCFStringEncodingUTF8);
}
}
}
static void GetThreadName(char* aName, size_t aSize)
{
pthread_getname_np(pthread_self(), aName, aSize);
}
void
nsCocoaDebugUtils::DebugLog(const char* aFormat, ...)
{
va_list args;
va_start(args, aFormat);
CFStringRef formatCFSTR =
CFStringCreateWithCString(kCFAllocatorDefault, aFormat,
kCFStringEncodingUTF8);
DebugLogV(true, formatCFSTR, args);
CFRelease(formatCFSTR);
va_end(args);
}
void
nsCocoaDebugUtils::DebugLogInt(bool aDecorate, const char* aFormat, ...)
{
va_list args;
va_start(args, aFormat);
CFStringRef formatCFSTR =
CFStringCreateWithCString(kCFAllocatorDefault, aFormat,
kCFStringEncodingUTF8);
DebugLogV(aDecorate, formatCFSTR, args);
CFRelease(formatCFSTR);
va_end(args);
}
void
nsCocoaDebugUtils::DebugLogV(bool aDecorate, CFStringRef aFormat,
va_list aArgs)
{
MaybeGetPathAndID();
CFStringRef message =
CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, NULL,
aFormat, aArgs);
int msgLength =
CFStringGetMaximumSizeForEncoding(CFStringGetLength(message),
kCFStringEncodingUTF8);
char* msgUTF8 = (char*) calloc(msgLength, 1);
CFStringGetCString(message, msgUTF8, msgLength, kCFStringEncodingUTF8);
CFRelease(message);
int finishedLength = msgLength + PROC_PIDPATHINFO_MAXSIZE;
char* finished = (char*) calloc(finishedLength, 1);
const time_t currentTime = time(NULL);
char timestamp[30] = {0};
ctime_r(&currentTime, timestamp);
if (aDecorate) {
char threadName[MAXPATHLEN] = {0};
GetThreadName(threadName, sizeof(threadName));
snprintf(finished, finishedLength, "(%s) %s[%u] %s[%p] %s\n",
timestamp, gProcPath, getpid(), threadName, pthread_self(), msgUTF8);
} else {
snprintf(finished, finishedLength, "%s\n", msgUTF8);
}
free(msgUTF8);
fputs(finished, stdout);
// Use the Apple System Log facility, as NSLog and CFLog do.
aslclient asl = asl_open(NULL, gBundleID, ASL_OPT_NO_DELAY);
aslmsg msg = asl_new(ASL_TYPE_MSG);
asl_set(msg, ASL_KEY_LEVEL, "4"); // kCFLogLevelWarning, used by NSLog()
asl_set(msg, ASL_KEY_MSG, finished);
asl_send(asl, msg);
asl_free(msg);
asl_close(asl);
free(finished);
}
CSTypeRef
nsCocoaDebugUtils::sInitializer = {0};
CSSymbolicatorRef
nsCocoaDebugUtils::sSymbolicator = {0};
#define STACK_MAX 256
void
nsCocoaDebugUtils::PrintStackTrace()
{
void** addresses = (void**) calloc(STACK_MAX, sizeof(void*));
if (!addresses) {
return;
}
CSSymbolicatorRef symbolicator = GetSymbolicatorRef();
if (CSIsNull(symbolicator)) {
free(addresses);
return;
}
uint32_t count = backtrace(addresses, STACK_MAX);
for (uint32_t i = 0; i < count; ++i) {
PrintAddress(addresses[i]);
}
ReleaseSymbolicator();
free(addresses);
}
void
nsCocoaDebugUtils::PrintAddress(void* aAddress)
{
const char* ownerName = "unknown";
const char* addressString = "unknown + 0";
char* allocatedOwnerName = nullptr;
char* allocatedAddressString = nullptr;
CSSymbolOwnerRef owner = {0};
CSSymbolicatorRef symbolicator = GetSymbolicatorRef();
if (!CSIsNull(symbolicator)) {
owner =
CSSymbolicatorGetSymbolOwnerWithAddressAtTime(symbolicator,
(unsigned long long) aAddress,
kCSNow);
}
if (!CSIsNull(owner)) {
ownerName = allocatedOwnerName = GetOwnerNameInt(aAddress, owner);
addressString = allocatedAddressString = GetAddressStringInt(aAddress, owner);
}
DebugLogInt(false, " (%s) %s", ownerName, addressString);
free(allocatedOwnerName);
free(allocatedAddressString);
ReleaseSymbolicator();
}
char*
nsCocoaDebugUtils::GetOwnerName(void* aAddress)
{
return GetOwnerNameInt(aAddress);
}
char*
nsCocoaDebugUtils::GetOwnerNameInt(void* aAddress, CSTypeRef aOwner)
{
char* retval = (char*) calloc(MAXPATHLEN, 1);
const char* ownerName = "unknown";
CSSymbolicatorRef symbolicator = GetSymbolicatorRef();
CSTypeRef owner = aOwner;
if (CSIsNull(owner) && !CSIsNull(symbolicator)) {
owner =
CSSymbolicatorGetSymbolOwnerWithAddressAtTime(symbolicator,
(unsigned long long) aAddress,
kCSNow);
}
if (!CSIsNull(owner)) {
ownerName = CSSymbolOwnerGetName(owner);
}
snprintf(retval, MAXPATHLEN, "%s", ownerName);
ReleaseSymbolicator();
return retval;
}
char*
nsCocoaDebugUtils::GetAddressString(void* aAddress)
{
return GetAddressStringInt(aAddress);
}
char*
nsCocoaDebugUtils::GetAddressStringInt(void* aAddress, CSTypeRef aOwner)
{
char* retval = (char*) calloc(MAXPATHLEN, 1);
const char* addressName = "unknown";
unsigned long long addressOffset = 0;
CSSymbolicatorRef symbolicator = GetSymbolicatorRef();
CSTypeRef owner = aOwner;
if (CSIsNull(owner) && !CSIsNull(symbolicator)) {
owner =
CSSymbolicatorGetSymbolOwnerWithAddressAtTime(symbolicator,
(unsigned long long) aAddress,
kCSNow);
}
if (!CSIsNull(owner)) {
CSSymbolRef symbol =
CSSymbolOwnerGetSymbolWithAddress(owner,
(unsigned long long) aAddress);
if (!CSIsNull(symbol)) {
addressName = CSSymbolGetName(symbol);
CSRange range = CSSymbolGetRange(symbol);
addressOffset = (unsigned long long) aAddress - range.location;
} else {
addressOffset = (unsigned long long)
aAddress - CSSymbolOwnerGetBaseAddress(owner);
}
}
snprintf(retval, MAXPATHLEN, "%s + 0x%llx",
addressName, addressOffset);
ReleaseSymbolicator();
return retval;
}
CSSymbolicatorRef
nsCocoaDebugUtils::GetSymbolicatorRef()
{
if (CSIsNull(sSymbolicator)) {
// 0x40e0000 is the value returned by
// uint32_t CSSymbolicatorGetFlagsForNListOnlyData(void). We don't use
// this method directly because it doesn't exist on OS X 10.6. Unless
// we limit ourselves to NList data, it will take too long to get a
// stack trace where Dwarf debugging info is available (about 15 seconds
// with Firefox). This means we won't be able to get a CSSourceInfoRef,
// or line number information. Oh well.
sSymbolicator =
CSSymbolicatorCreateWithPidFlagsAndNotification(getpid(),
0x40e0000, 0);
}
// Retaining just after creation prevents crashes when calling symbolicator
// code (for example from PrintStackTrace()) as Firefox is quitting. Not
// sure why. Doing this may mean that we leak sSymbolicator on quitting
// (if we ever created it). No particular harm in that, though.
return CSRetain(sSymbolicator);
}
void
nsCocoaDebugUtils::ReleaseSymbolicator()
{
if (!CSIsNull(sSymbolicator)) {
CSRelease(sSymbolicator);
}
}
-46
View File
@@ -1,46 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsCocoaFeatures_h_
#define nsCocoaFeatures_h_
#include <stdint.h>
/// Note that this class assumes we support the platform we are running on.
/// For better or worse, if the version is unknown or less than what we
/// support, we set it to the minimum supported version. GetSystemVersion
/// is the only call that returns the unadjusted values.
class nsCocoaFeatures {
public:
static int32_t macOSVersion();
static int32_t macOSVersionMajor();
static int32_t macOSVersionMinor();
static int32_t macOSVersionBugFix();
static bool OnYosemiteOrLater();
static bool OnElCapitanOrLater();
static bool OnSierraOrLater();
static bool OnHighSierraOrLater();
static bool OnMojaveOrLater();
static bool OnCatalinaOrLater();
static bool OnBigSurOrLater();
static bool IsAtLeastVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFix=0);
// These are utilities that do not change or depend on the value of mOSXVersion
// and instead just encapsulate the encoding algorithm. Note that GetVersion
// actually adjusts to the lowest supported OS, so it will always return
// a "supported" version. GetSystemVersion does not make any modifications.
static void GetSystemVersion(int &aMajor, int &aMinor, int &aBugFix);
static int32_t GetVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFix);
static int32_t ExtractMajorVersion(int32_t aVersion);
static int32_t ExtractMinorVersion(int32_t aVersion);
static int32_t ExtractBugFixVersion(int32_t aVersion);
private:
static void InitializeVersionNumbers();
static int32_t mOSVersion;
};
#endif // nsCocoaFeatures_h_
-209
View File
@@ -1,209 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This file makes some assumptions about the versions of macOS.
// We are assuming that the major, minor and bugfix versions are each less than
// 256.
// There are MOZ_ASSERTs for that.
// The formula for the version integer is (major << 16) + (minor << 8) + bugfix.
#define MACOS_VERSION_MASK 0x00FFFFFF
#define MACOS_MAJOR_VERSION_MASK 0x00FFFFFF
#define MACOS_MINOR_VERSION_MASK 0x00FFFFFF
#define MACOS_BUGFIX_VERSION_MASK 0x00FFFFFF
#define MACOS_VERSION_10_0_HEX 0x000A0000
#define MACOS_VERSION_10_7_HEX 0x000A0700
#define MACOS_VERSION_10_8_HEX 0x000A0800
#define MACOS_VERSION_10_9_HEX 0x000A0900
#define MACOS_VERSION_10_10_HEX 0x000A0A00
#define MACOS_VERSION_10_11_HEX 0x000A0B00
#define MACOS_VERSION_10_12_HEX 0x000A0C00
#define MACOS_VERSION_10_13_HEX 0x000A0D00
#define MACOS_VERSION_10_14_HEX 0x000A0E00
#define MACOS_VERSION_10_15_HEX 0x000A0F00
#define MACOS_VERSION_10_16_HEX 0x000A1000
#define MACOS_VERSION_11_0_HEX 0x000B0000
#include "nsCocoaFeatures.h"
#include "nsCocoaUtils.h"
#include "nsDebug.h"
#include "nsObjCExceptions.h"
#import <Cocoa/Cocoa.h>
int32_t nsCocoaFeatures::mOSVersion = 0;
// This should not be called with unchecked aMajor, which should be >= 10.
inline int32_t AssembleVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFix)
{
MOZ_ASSERT(aMajor >= 10);
return (aMajor << 16) + (aMinor << 8) + aBugFix;
}
int32_t nsCocoaFeatures::ExtractMajorVersion(int32_t aVersion)
{
MOZ_ASSERT((aVersion & MACOS_VERSION_MASK) == aVersion);
return (aVersion & 0xFF0000) >> 16;
}
int32_t nsCocoaFeatures::ExtractMinorVersion(int32_t aVersion)
{
MOZ_ASSERT((aVersion & MACOS_VERSION_MASK) == aVersion);
return (aVersion & 0xFF00) >> 8;
}
int32_t nsCocoaFeatures::ExtractBugFixVersion(int32_t aVersion)
{
MOZ_ASSERT((aVersion & MACOS_VERSION_MASK) == aVersion);
return aVersion & 0xFF;
}
static int intAtStringIndex(NSArray *array, int index)
{
return [(NSString*)[array objectAtIndex:index] integerValue];
}
void nsCocoaFeatures::GetSystemVersion(int &major, int &minor, int &bugfix)
{
major = minor = bugfix = 0;
NSString* versionString = [[NSDictionary dictionaryWithContentsOfFile:
@"/System/Library/CoreServices/SystemVersion.plist"] objectForKey:@"ProductVersion"];
NSArray* versions = [versionString componentsSeparatedByString:@"."];
NSUInteger count = [versions count];
if (count > 0) {
major = intAtStringIndex(versions, 0);
if (count > 1) {
minor = intAtStringIndex(versions, 1);
if (count > 2) {
bugfix = intAtStringIndex(versions, 2);
}
}
}
}
int32_t nsCocoaFeatures::GetVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFix)
{
int32_t macOSVersion;
if (aMajor < 10) {
aMajor = 10;
NS_ERROR("Couldn't determine macOS version, assuming 10.7");
macOSVersion = MACOS_VERSION_10_7_HEX;
} else if (aMajor == 10 && aMinor < 7) {
aMinor = 7;
NS_ERROR("macOS version too old, assuming 10.7");
macOSVersion = MACOS_VERSION_10_7_HEX;
} else {
MOZ_ASSERT(aMajor >= 10);
MOZ_ASSERT(aMajor < 256);
MOZ_ASSERT(aMinor >= 0);
MOZ_ASSERT(aMinor < 256);
MOZ_ASSERT(aBugFix >= 0);
MOZ_ASSERT(aBugFix < 256);
macOSVersion = AssembleVersion(aMajor, aMinor, aBugFix);
}
MOZ_ASSERT(aMajor == ExtractMajorVersion(macOSVersion));
MOZ_ASSERT(aMinor == ExtractMinorVersion(macOSVersion));
MOZ_ASSERT(aBugFix == ExtractBugFixVersion(macOSVersion));
return macOSVersion;
}
/*static*/ void
nsCocoaFeatures::InitializeVersionNumbers()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
// Provide an autorelease pool to avoid leaking Cocoa objects,
// as this gets called before the main autorelease pool is in place.
nsAutoreleasePool localPool;
int major, minor, bugfix;
GetSystemVersion(major, minor, bugfix);
mOSVersion = GetVersion(major, minor, bugfix);
NS_OBJC_END_TRY_ABORT_BLOCK;
}
/* static */ int32_t
nsCocoaFeatures::macOSVersion()
{
// Don't let this be called while we're first setting the value...
MOZ_ASSERT((mOSVersion & MACOS_VERSION_MASK) >= 0);
if (!mOSVersion) {
mOSVersion = -1;
InitializeVersionNumbers();
}
return mOSVersion;
}
/* static */ int32_t
nsCocoaFeatures::macOSVersionMajor()
{
return ExtractMajorVersion(macOSVersion());
}
/* static */ int32_t
nsCocoaFeatures::macOSVersionMinor()
{
return ExtractMinorVersion(macOSVersion());
}
/* static */ int32_t
nsCocoaFeatures::macOSVersionBugFix()
{
return ExtractBugFixVersion(macOSVersion());
}
/* static */ bool
nsCocoaFeatures::OnYosemiteOrLater()
{
return (macOSVersion() >= MACOS_VERSION_10_10_HEX);
}
/* static */ bool
nsCocoaFeatures::OnElCapitanOrLater()
{
return (macOSVersion() >= MACOS_VERSION_10_11_HEX);
}
/* static */ bool
nsCocoaFeatures::OnSierraOrLater()
{
return (macOSVersion() >= MACOS_VERSION_10_12_HEX);
}
/* static */ bool
nsCocoaFeatures::OnHighSierraOrLater()
{
return (macOSVersion() >= MACOS_VERSION_10_13_HEX);
}
/* static */ bool
nsCocoaFeatures::OnMojaveOrLater()
{
return (macOSVersion() >= MACOS_VERSION_10_14_HEX);
}
/* static */ bool
nsCocoaFeatures::OnCatalinaOrLater()
{
return (macOSVersion() >= MACOS_VERSION_10_15_HEX);
}
/* static */ bool
nsCocoaFeatures::OnBigSurOrLater()
{
// Account for the version being 10.16 (which occurs when the
// application is linked with an older SDK) or 11.0 on Big Sur.
return ((macOSVersion() >= MACOS_VERSION_10_16_HEX) ||
(macOSVersion() >= MACOS_VERSION_11_0_HEX));
}
/* static */ bool
nsCocoaFeatures::IsAtLeastVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFix)
{
return macOSVersion() >= GetVersion(aMajor, aMinor, aBugFix);
}
-389
View File
@@ -1,389 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsCocoaUtils_h_
#define nsCocoaUtils_h_
#import <Cocoa/Cocoa.h>
#include "nsRect.h"
#include "imgIContainer.h"
#include "npapi.h"
#include "nsTArray.h"
#include "Units.h"
// This must be the last include:
#include "nsObjCExceptions.h"
#include "mozilla/EventForwards.h"
// Declare the backingScaleFactor method that we want to call
// on NSView/Window/Screen objects, if they recognize it.
@interface NSObject (BackingScaleFactorCategory)
- (CGFloat)backingScaleFactor;
@end
#if !defined(MAC_OS_X_VERSION_10_8) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8
enum {
NSEventPhaseMayBegin = 0x1 << 5
};
#endif
class nsIWidget;
namespace mozilla {
namespace gfx {
class SourceSurface;
} // namespace gfx
} // namespace mozilla
// Used to retain a Cocoa object for the remainder of a method's execution.
class nsAutoRetainCocoaObject {
public:
explicit nsAutoRetainCocoaObject(id anObject)
{
mObject = NS_OBJC_TRY_EXPR_ABORT([anObject retain]);
}
~nsAutoRetainCocoaObject()
{
NS_OBJC_TRY_ABORT([mObject release]);
}
private:
id mObject; // [STRONG]
};
// Provide a local autorelease pool for the remainder of a method's execution.
class nsAutoreleasePool {
public:
nsAutoreleasePool()
{
mLocalPool = [[NSAutoreleasePool alloc] init];
}
~nsAutoreleasePool()
{
[mLocalPool release];
}
private:
NSAutoreleasePool *mLocalPool;
};
@interface NSApplication (Undocumented)
// Present in all versions of OS X from (at least) 10.2.8 through 10.5.
- (BOOL)_isRunningModal;
- (BOOL)_isRunningAppModal;
// It's sometimes necessary to explicitly remove a window from the "window
// cache" in order to deactivate it. The "window cache" is an undocumented
// subsystem, all of whose methods are included in the NSWindowCache category
// of the NSApplication class (in header files generated using class-dump).
// Present in all versions of OS X from (at least) 10.2.8 through 10.5.
- (void)_removeWindowFromCache:(NSWindow *)aWindow;
// Send an event to the current Cocoa app-modal session. Present in all
// versions of OS X from (at least) 10.2.8 through 10.5.
- (void)_modalSession:(NSModalSession)aSession sendEvent:(NSEvent *)theEvent;
@end
struct KeyBindingsCommand
{
SEL selector;
id data;
};
@interface NativeKeyBindingsRecorder : NSResponder
{
@private
nsTArray<KeyBindingsCommand>* mCommands;
}
- (void)startRecording:(nsTArray<KeyBindingsCommand>&)aCommands;
- (void)doCommandBySelector:(SEL)aSelector;
- (void)insertText:(id)aString;
@end // NativeKeyBindingsRecorder
class nsCocoaUtils
{
typedef mozilla::gfx::SourceSurface SourceSurface;
typedef mozilla::LayoutDeviceIntPoint LayoutDeviceIntPoint;
typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect;
public:
// Get the backing scale factor from an object that supports this selector
// (NSView/Window/Screen, on 10.7 or later), returning 1.0 if not supported
static CGFloat
GetBackingScaleFactor(id aObject)
{
if (HiDPIEnabled() &&
[aObject respondsToSelector:@selector(backingScaleFactor)]) {
return [aObject backingScaleFactor];
}
return 1.0;
}
// Conversions between Cocoa points and device pixels, given the backing
// scale factor from a view/window/screen.
static int32_t
CocoaPointsToDevPixels(CGFloat aPts, CGFloat aBackingScale)
{
return NSToIntRound(aPts * aBackingScale);
}
static LayoutDeviceIntPoint
CocoaPointsToDevPixels(const NSPoint& aPt, CGFloat aBackingScale)
{
return LayoutDeviceIntPoint(NSToIntRound(aPt.x * aBackingScale),
NSToIntRound(aPt.y * aBackingScale));
}
static LayoutDeviceIntPoint
CocoaPointsToDevPixelsRoundDown(const NSPoint& aPt, CGFloat aBackingScale)
{
return LayoutDeviceIntPoint(NSToIntFloor(aPt.x * aBackingScale),
NSToIntFloor(aPt.y * aBackingScale));
}
static LayoutDeviceIntRect
CocoaPointsToDevPixels(const NSRect& aRect, CGFloat aBackingScale)
{
return LayoutDeviceIntRect(NSToIntRound(aRect.origin.x * aBackingScale),
NSToIntRound(aRect.origin.y * aBackingScale),
NSToIntRound(aRect.size.width * aBackingScale),
NSToIntRound(aRect.size.height * aBackingScale));
}
static CGFloat
DevPixelsToCocoaPoints(int32_t aPixels, CGFloat aBackingScale)
{
return (CGFloat)aPixels / aBackingScale;
}
static NSPoint
DevPixelsToCocoaPoints(const mozilla::LayoutDeviceIntPoint& aPt,
CGFloat aBackingScale)
{
return NSMakePoint((CGFloat)aPt.x / aBackingScale,
(CGFloat)aPt.y / aBackingScale);
}
// Implements an NSPoint equivalent of -[NSWindow convertRectFromScreen:].
static NSPoint
ConvertPointFromScreen(NSWindow* aWindow, const NSPoint& aPt)
{
return [aWindow convertRectFromScreen:NSMakeRect(aPt.x, aPt.y, 0, 0)].origin;
}
// Implements an NSPoint equivalent of -[NSWindow convertRectToScreen:].
static NSPoint
ConvertPointToScreen(NSWindow* aWindow, const NSPoint& aPt)
{
return [aWindow convertRectToScreen:NSMakeRect(aPt.x, aPt.y, 0, 0)].origin;
}
static NSRect
DevPixelsToCocoaPoints(const LayoutDeviceIntRect& aRect,
CGFloat aBackingScale)
{
return NSMakeRect((CGFloat)aRect.x / aBackingScale,
(CGFloat)aRect.y / aBackingScale,
(CGFloat)aRect.width / aBackingScale,
(CGFloat)aRect.height / aBackingScale);
}
// Returns the given y coordinate, which must be in screen coordinates,
// flipped from Gecko to Cocoa or Cocoa to Gecko.
static float FlippedScreenY(float y);
// The following functions come in "DevPix" variants that work with
// backing-store (device pixel) coordinates, as well as the original
// versions that expect coordinates in Cocoa points/CSS pixels.
// The difference becomes important in HiDPI display modes, where Cocoa
// points and backing-store pixels are no longer 1:1.
// Gecko rects (nsRect) contain an origin (x,y) in a coordinate
// system with (0,0) in the top-left of the primary screen. Cocoa rects
// (NSRect) contain an origin (x,y) in a coordinate system with (0,0)
// in the bottom-left of the primary screen. Both nsRect and NSRect
// contain width/height info, with no difference in their use.
// This function does no scaling, so the Gecko coordinates are
// expected to be desktop pixels, which are equal to Cocoa points
// (by definition).
static NSRect GeckoRectToCocoaRect(const mozilla::DesktopIntRect &geckoRect);
// Converts aGeckoRect in dev pixels to points in Cocoa coordinates
static NSRect
GeckoRectToCocoaRectDevPix(const mozilla::LayoutDeviceIntRect &aGeckoRect,
CGFloat aBackingScale);
// See explanation for geckoRectToCocoaRect, guess what this does...
static mozilla::DesktopIntRect CocoaRectToGeckoRect(const NSRect &cocoaRect);
static mozilla::LayoutDeviceIntRect CocoaRectToGeckoRectDevPix(
const NSRect& aCocoaRect, CGFloat aBackingScale);
// Gives the location for the event in screen coordinates. Do not call this
// unless the window the event was originally targeted at is still alive!
// anEvent may be nil -- in that case the current mouse location is returned.
static NSPoint ScreenLocationForEvent(NSEvent* anEvent);
// Determines if an event happened over a window, whether or not the event
// is for the window. Does not take window z-order into account.
static BOOL IsEventOverWindow(NSEvent* anEvent, NSWindow* aWindow);
// Events are set up so that their coordinates refer to the window to which they
// were originally sent. If we reroute the event somewhere else, we'll have
// to get the window coordinates this way. Do not call this unless the window
// the event was originally targeted at is still alive!
static NSPoint EventLocationForWindow(NSEvent* anEvent, NSWindow* aWindow);
// Compatibility wrappers for the -[NSEvent phase], -[NSEvent momentumPhase],
// -[NSEvent hasPreciseScrollingDeltas] and -[NSEvent scrollingDeltaX/Y] APIs
// that became availaible starting with the 10.7 SDK.
// All of these can be removed once we drop support for 10.6.
static NSEventPhase EventPhase(NSEvent* aEvent);
static NSEventPhase EventMomentumPhase(NSEvent* aEvent);
static BOOL IsMomentumScrollEvent(NSEvent* aEvent);
static BOOL HasPreciseScrollingDeltas(NSEvent* aEvent);
static void GetScrollingDeltas(NSEvent* aEvent, CGFloat* aOutDeltaX, CGFloat* aOutDeltaY);
static BOOL EventHasPhaseInformation(NSEvent* aEvent);
// Hides the Menu bar and the Dock. Multiple hide/show requests can be nested.
static void HideOSChromeOnScreen(bool aShouldHide);
static nsIWidget* GetHiddenWindowWidget();
static void PrepareForNativeAppModalDialog();
static void CleanUpAfterNativeAppModalDialog();
// 3 utility functions to go from a frame of imgIContainer to CGImage and then to NSImage
// Convert imgIContainer -> CGImageRef, caller owns result
/** Creates a <code>CGImageRef</code> from a frame contained in an <code>imgIContainer</code>.
Copies the pixel data from the indicated frame of the <code>imgIContainer</code> into a new <code>CGImageRef</code>.
The caller owns the <code>CGImageRef</code>.
@param aFrame the frame to convert
@param aResult the resulting CGImageRef
@return NS_OK if the conversion worked, NS_ERROR_FAILURE otherwise
*/
static nsresult CreateCGImageFromSurface(SourceSurface* aSurface,
CGImageRef* aResult);
/** Creates a Cocoa <code>NSImage</code> from a <code>CGImageRef</code>.
Copies the pixel data from the <code>CGImageRef</code> into a new <code>NSImage</code>.
The caller owns the <code>NSImage</code>.
@param aInputImage the image to convert
@param aResult the resulting NSImage
@return NS_OK if the conversion worked, NS_ERROR_FAILURE otherwise
*/
static nsresult CreateNSImageFromCGImage(CGImageRef aInputImage, NSImage **aResult);
/** Creates a Cocoa <code>NSImage</code> from a frame of an <code>imgIContainer</code>.
Combines the two methods above. The caller owns the <code>NSImage</code>.
@param aImage the image to extract a frame from
@param aWhichFrame the frame to extract (see imgIContainer FRAME_*)
@param aResult the resulting NSImage
@param scaleFactor the desired scale factor of the NSImage (2 for a retina display)
@return NS_OK if the conversion worked, NS_ERROR_FAILURE otherwise
*/
static nsresult CreateNSImageFromImageContainer(imgIContainer *aImage, uint32_t aWhichFrame, NSImage **aResult, CGFloat scaleFactor);
/**
* Returns nsAString for aSrc.
*/
static void GetStringForNSString(const NSString *aSrc, nsAString& aDist);
/**
* Makes NSString instance for aString.
*/
static NSString* ToNSString(const nsAString& aString);
/**
* Returns NSRect for aGeckoRect.
* Just copies values between the two types; it does no coordinate-system
* conversion, so both rects must have the same coordinate origin/direction.
*/
static void GeckoRectToNSRect(const nsIntRect& aGeckoRect,
NSRect& aOutCocoaRect);
/**
* Returns Gecko rect for aCocoaRect.
* Just copies values between the two types; it does no coordinate-system
* conversion, so both rects must have the same coordinate origin/direction.
*/
static void NSRectToGeckoRect(const NSRect& aCocoaRect,
nsIntRect& aOutGeckoRect);
/**
* Makes NSEvent instance for aEventTytpe and aEvent.
*/
static NSEvent* MakeNewCocoaEventWithType(NSEventType aEventType,
NSEvent *aEvent);
/**
* Initializes aNPCocoaEvent.
*/
static void InitNPCocoaEvent(NPCocoaEvent* aNPCocoaEvent);
/**
* Initializes WidgetInputEvent for aNativeEvent or aModifiers.
*/
static void InitInputEvent(mozilla::WidgetInputEvent &aInputEvent,
NSEvent* aNativeEvent);
/**
* Converts the native modifiers from aNativeEvent into WidgetMouseEvent
* Modifiers. aNativeEvent can be null.
*/
static mozilla::Modifiers ModifiersForEvent(NSEvent* aNativeEvent);
/**
* ConvertToCarbonModifier() returns carbon modifier flags for the cocoa
* modifier flags.
* NOTE: The result never includes right*Key.
*/
static UInt32 ConvertToCarbonModifier(NSUInteger aCocoaModifier);
/**
* Whether to support HiDPI rendering. For testing purposes, to be removed
* once we're comfortable with the HiDPI behavior.
*/
static bool HiDPIEnabled();
/**
* Keys can optionally be bound by system or user key bindings to one or more
* commands based on selectors. This collects any such commands in the
* provided array.
*/
static void GetCommandsFromKeyEvent(NSEvent* aEvent,
nsTArray<KeyBindingsCommand>& aCommands);
/**
* Converts the string name of a Gecko key (like "VK_HOME") to the
* corresponding Cocoa Unicode character.
*/
static uint32_t ConvertGeckoNameToMacCharCode(const nsAString& aKeyCodeName);
/**
* Converts a Gecko key code (like NS_VK_HOME) to the corresponding Cocoa
* Unicode character.
*/
static uint32_t ConvertGeckoKeyCodeToMacCharCode(uint32_t aKeyCode);
/**
* Convert string with font attribute to NSMutableAttributedString
*/
static NSMutableAttributedString* GetNSMutableAttributedString(
const nsAString& aText,
const nsTArray<mozilla::FontRange>& aFontRanges,
const bool aIsVertical,
const CGFloat aBackingScaleFactor);
};
#endif // nsCocoaUtils_h_
File diff suppressed because it is too large Load Diff
-426
View File
@@ -1,426 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsCocoaWindow_h_
#define nsCocoaWindow_h_
#undef DARWIN
#import <Cocoa/Cocoa.h>
#include "mozilla/RefPtr.h"
#include "nsBaseWidget.h"
#include "nsPIWidgetCocoa.h"
#include "nsCocoaUtils.h"
class nsCocoaWindow;
class nsChildView;
class nsMenuBarX;
@class ChildView;
typedef struct _nsCocoaWindowList {
_nsCocoaWindowList() : prev(nullptr), window(nullptr) {}
struct _nsCocoaWindowList *prev;
nsCocoaWindow *window; // Weak
} nsCocoaWindowList;
// NSWindow subclass that is the base class for all of our own window classes.
// Among other things, this class handles the storage of those settings that
// need to be persisted across window destruction and reconstruction, i.e. when
// switching to and from fullscreen mode.
// We don't save shadow, transparency mode or background color because it's not
// worth the hassle - Gecko will reset them anyway as soon as the window is
// resized.
@interface BaseWindow : NSWindow
{
// Data Storage
NSMutableDictionary* mState;
BOOL mDrawsIntoWindowFrame;
NSColor* mActiveTitlebarColor;
NSColor* mInactiveTitlebarColor;
// Shadow
BOOL mScheduledShadowInvalidation;
// Invalidation disabling
BOOL mDisabledNeedsDisplay;
// DPI cache. Getting the physical screen size (CGDisplayScreenSize)
// is ridiculously slow, so we cache it in the toplevel window for all
// descendants to use.
float mDPI;
NSTrackingArea* mTrackingArea;
NSRect mDirtyRect;
BOOL mBeingShown;
BOOL mDrawTitle;
BOOL mBrightTitlebarForeground;
BOOL mUseMenuStyle;
}
- (void)importState:(NSDictionary*)aState;
- (NSMutableDictionary*)exportState;
- (void)setDrawsContentsIntoWindowFrame:(BOOL)aState;
- (BOOL)drawsContentsIntoWindowFrame;
- (void)setTitlebarColor:(NSColor*)aColor forActiveWindow:(BOOL)aActive;
- (NSColor*)titlebarColorForActiveWindow:(BOOL)aActive;
- (void)deferredInvalidateShadow;
- (void)invalidateShadow;
- (float)getDPI;
- (void)mouseEntered:(NSEvent*)aEvent;
- (void)mouseExited:(NSEvent*)aEvent;
- (void)mouseMoved:(NSEvent*)aEvent;
- (void)updateTrackingArea;
- (NSView*)trackingAreaView;
- (void)setBeingShown:(BOOL)aValue;
- (BOOL)isBeingShown;
- (BOOL)isVisibleOrBeingShown;
- (ChildView*)mainChildView;
- (NSArray*)titlebarControls;
- (void)setWantsTitleDrawn:(BOOL)aDrawTitle;
- (BOOL)wantsTitleDrawn;
- (void)setUseBrightTitlebarForeground:(BOOL)aBrightForeground;
- (BOOL)useBrightTitlebarForeground;
- (void)disableSetNeedsDisplay;
- (void)enableSetNeedsDisplay;
- (NSRect)getAndResetNativeDirtyRect;
- (void)setUseMenuStyle:(BOOL)aValue;
@end
@interface NSWindow (Undocumented)
// If a window has been explicitly removed from the "window cache" (to
// deactivate it), it's sometimes necessary to "reset" it to reactivate it
// (and put it back in the "window cache"). One way to do this, which Apple
// often uses, is to set the "window number" to '-1' and then back to its
// original value.
- (void)_setWindowNumber:(NSInteger)aNumber;
// If we set the window's stylemask to be textured, the corners on the bottom of
// the window are rounded by default. We use this private method to make
// the corners square again, a la Safari. Starting with 10.7, all windows have
// rounded bottom corners, so this call doesn't have any effect there.
- (void)setBottomCornerRounded:(BOOL)rounded;
- (BOOL)bottomCornerRounded;
// Present in the same form on OS X since at least OS X 10.5.
- (NSRect)contentRectForFrameRect:(NSRect)windowFrame styleMask:(NSUInteger)windowStyle;
- (NSRect)frameRectForContentRect:(NSRect)windowContentRect styleMask:(NSUInteger)windowStyle;
// Present since at least OS X 10.5. The OS calls this method on NSWindow
// (and its subclasses) to find out which NSFrameView subclass to instantiate
// to create its "frame view".
+ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask;
@end
@interface PopupWindow : BaseWindow
{
@private
BOOL mIsContextMenu;
}
- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask
backing:(NSBackingStoreType)bufferingType defer:(BOOL)deferCreation;
- (BOOL)isContextMenu;
- (void)setIsContextMenu:(BOOL)flag;
- (BOOL)canBecomeMainWindow;
@end
@interface BorderlessWindow : BaseWindow
{
}
- (BOOL)canBecomeKeyWindow;
- (BOOL)canBecomeMainWindow;
@end
@interface WindowDelegate : NSObject <NSWindowDelegate>
{
nsCocoaWindow* mGeckoWindow; // [WEAK] (we are owned by the window)
// Used to avoid duplication when we send NS_ACTIVATE and
// NS_DEACTIVATE to Gecko for toplevel widgets. Starts out
// false.
bool mToplevelActiveState;
BOOL mHasEverBeenZoomed;
}
+ (void)paintMenubarForWindow:(NSWindow*)aWindow;
- (id)initWithGeckoWindow:(nsCocoaWindow*)geckoWind;
- (void)windowDidResize:(NSNotification*)aNotification;
- (nsCocoaWindow*)geckoWidget;
- (bool)toplevelActiveState;
- (void)sendToplevelActivateEvents;
- (void)sendToplevelDeactivateEvents;
@end
@class ToolbarWindow;
// NSColor subclass that allows us to draw separate colors both in the titlebar
// and for background of the window.
@interface TitlebarAndBackgroundColor : NSColor
{
ToolbarWindow *mWindow; // [WEAK] (we are owned by the window)
}
- (id)initWithWindow:(ToolbarWindow*)aWindow;
@end
// NSWindow subclass for handling windows with toolbars.
@interface ToolbarWindow : BaseWindow
{
TitlebarAndBackgroundColor *mColor; // strong
CGFloat mUnifiedToolbarHeight;
NSColor *mBackgroundColor; // strong
NSView *mTitlebarView; // strong
NSRect mWindowButtonsRect;
NSRect mFullScreenButtonRect;
}
// Pass nil here to get the default appearance.
- (void)setTitlebarColor:(NSColor*)aColor forActiveWindow:(BOOL)aActive;
- (void)setUnifiedToolbarHeight:(CGFloat)aHeight;
- (CGFloat)unifiedToolbarHeight;
- (CGFloat)titlebarHeight;
- (NSRect)titlebarRect;
- (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect sync:(BOOL)aSync;
- (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect;
- (void)setDrawsContentsIntoWindowFrame:(BOOL)aState;
- (void)setSheetAttachmentPosition:(CGFloat)aY;
- (void)placeWindowButtons:(NSRect)aRect;
- (void)placeFullScreenButton:(NSRect)aRect;
- (NSPoint)windowButtonsPositionWithDefaultPosition:(NSPoint)aDefaultPosition;
- (NSPoint)fullScreenButtonPositionWithDefaultPosition:(NSPoint)aDefaultPosition;
- (void)setTemporaryBackgroundColor;
- (void)restoreBackgroundColor;
@end
class nsCocoaWindow : public nsBaseWidget, public nsPIWidgetCocoa
{
private:
typedef nsBaseWidget Inherited;
public:
nsCocoaWindow();
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSPIWIDGETCOCOA
virtual MOZ_MUST_USE nsresult Create(nsIWidget* aParent,
nsNativeWidget aNativeParent,
const DesktopIntRect& aRect,
nsWidgetInitData* aInitData = nullptr)
override;
virtual MOZ_MUST_USE nsresult Create(nsIWidget* aParent,
nsNativeWidget aNativeParent,
const LayoutDeviceIntRect& aRect,
nsWidgetInitData* aInitData = nullptr)
override;
virtual void Destroy() override;
NS_IMETHOD Show(bool aState) override;
virtual nsIWidget* GetSheetWindowParent(void) override;
NS_IMETHOD Enable(bool aState) override;
virtual bool IsEnabled() const override;
virtual void SetModal(bool aState) override;
virtual void SetFakeModal(bool aState) override;
virtual bool IsRunningAppModal() override;
virtual bool IsVisible() const override;
NS_IMETHOD SetFocus(bool aState=false) override;
virtual LayoutDeviceIntPoint WidgetToScreenOffset() override;
virtual LayoutDeviceIntPoint GetClientOffset() override;
virtual LayoutDeviceIntSize
ClientToWindowSize(const LayoutDeviceIntSize& aClientSize) override;
virtual void* GetNativeData(uint32_t aDataType) override;
virtual void ConstrainPosition(bool aAllowSlop,
int32_t *aX, int32_t *aY) override;
virtual void SetSizeConstraints(const SizeConstraints& aConstraints) override;
NS_IMETHOD Move(double aX, double aY) override;
virtual void SetSizeMode(nsSizeMode aMode) override;
NS_IMETHOD HideWindowChrome(bool aShouldHide) override;
void EnteredFullScreen(bool aFullScreen, bool aNativeMode = true);
virtual bool PrepareForFullscreenTransition(nsISupports** aData) override;
virtual void PerformFullscreenTransition(FullscreenTransitionStage aStage,
uint16_t aDuration,
nsISupports* aData,
nsIRunnable* aCallback) override;
virtual nsresult MakeFullScreen(
bool aFullScreen, nsIScreen* aTargetScreen = nullptr) override final;
NS_IMETHOD MakeFullScreenWithNativeTransition(
bool aFullScreen, nsIScreen* aTargetScreen = nullptr) override final;
NSAnimation* FullscreenTransitionAnimation() const { return mFullscreenTransitionAnimation; }
void ReleaseFullscreenTransitionAnimation()
{
MOZ_ASSERT(mFullscreenTransitionAnimation,
"Should only be called when there is animation");
[mFullscreenTransitionAnimation release];
mFullscreenTransitionAnimation = nil;
}
NS_IMETHOD Resize(double aWidth, double aHeight, bool aRepaint) override;
NS_IMETHOD Resize(double aX, double aY, double aWidth, double aHeight, bool aRepaint) override;
virtual LayoutDeviceIntRect GetClientBounds() override;
virtual LayoutDeviceIntRect GetScreenBounds() override;
void ReportMoveEvent();
void ReportSizeEvent();
NS_IMETHOD SetCursor(nsCursor aCursor) override;
NS_IMETHOD SetCursor(imgIContainer* aCursor, uint32_t aHotspotX, uint32_t aHotspotY) override;
CGFloat BackingScaleFactor();
void BackingScaleFactorChanged();
virtual double GetDefaultScaleInternal() override;
virtual int32_t RoundsWidgetCoordinatesTo() override;
mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale() final {
return mozilla::DesktopToLayoutDeviceScale(BackingScaleFactor());
}
NS_IMETHOD SetTitle(const nsAString& aTitle) override;
NS_IMETHOD Invalidate(const LayoutDeviceIntRect& aRect) override;
virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations) override;
virtual LayerManager* GetLayerManager(PLayerTransactionChild* aShadowManager = nullptr,
LayersBackend aBackendHint = mozilla::layers::LayersBackend::LAYERS_NONE,
LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT) override;
NS_IMETHOD DispatchEvent(mozilla::WidgetGUIEvent* aEvent,
nsEventStatus& aStatus) override;
virtual void CaptureRollupEvents(nsIRollupListener * aListener,
bool aDoCapture) override;
NS_IMETHOD GetAttention(int32_t aCycleCount) override;
virtual bool HasPendingInputEvent() override;
virtual nsTransparencyMode GetTransparencyMode() override;
virtual void SetTransparencyMode(nsTransparencyMode aMode) override;
virtual void SetWindowShadowStyle(int32_t aStyle) override;
virtual void SetShowsToolbarButton(bool aShow) override;
virtual void SetShowsFullScreenButton(bool aShow) override;
virtual void SetWindowAnimationType(WindowAnimationType aType) override;
virtual void SetDrawsTitle(bool aDrawTitle) override;
virtual void SetUseBrightTitlebarForeground(bool aBrightForeground) override;
NS_IMETHOD SetNonClientMargins(LayoutDeviceIntMargin& aMargins) override;
virtual void SetWindowTitlebarColor(nscolor aColor, bool aActive) override;
virtual void SetDrawsInTitlebar(bool aState) override;
virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) override;
virtual nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint,
uint32_t aNativeMessage,
uint32_t aModifierFlags,
nsIObserver* aObserver) override;
void DispatchSizeModeEvent();
// be notified that a some form of drag event needs to go into Gecko
virtual bool DragEvent(unsigned int aMessage, mozilla::gfx::Point aMouseGlobal, UInt16 aKeyModifiers);
bool HasModalDescendents() { return mNumModalDescendents > 0; }
NSWindow *GetCocoaWindow() { return mWindow; }
void SetMenuBar(nsMenuBarX* aMenuBar);
nsMenuBarX *GetMenuBar();
NS_IMETHOD_(void) SetInputContext(
const InputContext& aContext,
const InputContextAction& aAction) override;
NS_IMETHOD_(InputContext) GetInputContext() override
{
return mInputContext;
}
NS_IMETHOD_(bool) ExecuteNativeKeyBinding(
NativeKeyBindingsType aType,
const mozilla::WidgetKeyboardEvent& aEvent,
DoCommandCallback aCallback,
void* aCallbackData) override;
void SetPopupWindowLevel();
protected:
virtual ~nsCocoaWindow();
nsresult CreateNativeWindow(const NSRect &aRect,
nsBorderStyle aBorderStyle,
bool aRectIsFrameRect);
nsresult CreatePopupContentView(const LayoutDeviceIntRect &aRect,
nsWidgetInitData* aInitData);
void DestroyNativeWindow();
void AdjustWindowShadow();
void SetWindowBackgroundBlur();
void UpdateBounds();
nsresult DoResize(double aX, double aY, double aWidth, double aHeight,
bool aRepaint, bool aConstrainToCurrentScreen);
inline bool ShouldToggleNativeFullscreen(bool aFullScreen,
bool aUseSystemTransition);
nsresult DoMakeFullScreen(bool aFullScreen, bool aUseSystemTransition);
virtual already_AddRefed<nsIWidget>
AllocateChildPopupWidget() override
{
static NS_DEFINE_IID(kCPopUpCID, NS_POPUP_CID);
nsCOMPtr<nsIWidget> widget = do_CreateInstance(kCPopUpCID);
return widget.forget();
}
nsIWidget* mParent; // if we're a popup, this is our parent [WEAK]
nsIWidget* mAncestorLink; // link to traverse ancestors [WEAK]
BaseWindow* mWindow; // our cocoa window [STRONG]
WindowDelegate* mDelegate; // our delegate for processing window msgs [STRONG]
RefPtr<nsMenuBarX> mMenuBar;
NSWindow* mSheetWindowParent; // if this is a sheet, this is the NSWindow it's attached to
nsChildView* mPopupContentView; // if this is a popup, this is its content widget
// if this is a toplevel window, and there is any ongoing fullscreen
// transition, it is the animation object.
NSAnimation* mFullscreenTransitionAnimation;
int32_t mShadowStyle;
CGFloat mBackingScaleFactor;
WindowAnimationType mAnimationType;
bool mWindowMadeHere; // true if we created the window, false for embedding
bool mSheetNeedsShow; // if this is a sheet, are we waiting to be shown?
// this is used for sibling sheet contention only
bool mInFullScreenMode;
bool mInFullScreenTransition; // true from the request to enter/exit fullscreen
// (MakeFullScreen() call) to EnteredFullScreen()
bool mModal;
bool mFakeModal;
// Only true on 10.7+ if SetShowsFullScreenButton(true) is called.
bool mSupportsNativeFullScreen;
// Whether we are currently using native fullscreen. It could be false because
// we are in the DOM fullscreen where we do not use the native fullscreen.
bool mInNativeFullScreenMode;
bool mIsAnimationSuppressed;
bool mInReportMoveEvent; // true if in a call to ReportMoveEvent().
bool mInResize; // true if in a call to DoResize().
bool mAlwaysOnTop;
int32_t mNumModalDescendents;
InputContext mInputContext;
};
#endif // nsCocoaWindow_h_
File diff suppressed because it is too large Load Diff
-50
View File
@@ -1,50 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsColorPicker_h_
#define nsColorPicker_h_
#include "nsIColorPicker.h"
#include "nsString.h"
#include "nsCOMPtr.h"
class nsIColorPickerShownCallback;
class mozIDOMWindowProxy;
@class NSColorPanelWrapper;
@class NSColor;
class nsColorPicker final : public nsIColorPicker
{
public:
NS_DECL_ISUPPORTS
NS_IMETHOD Init(mozIDOMWindowProxy* aParent, const nsAString& aTitle,
const nsAString& aInitialColor) override;
NS_IMETHOD Open(nsIColorPickerShownCallback* aCallback) override;
// For NSColorPanelWrapper.
void Update(NSColor* aColor);
// Call this method if you are done with this input, but the color picker needs to
// stay open as it will be associated to another input
void DoneWithRetarget();
// Same as DoneWithRetarget + clean the static instance of sColorPanelWrapper,
// as it is not needed anymore for now
void Done();
private:
~nsColorPicker();
static NSColor* GetNSColorFromHexString(const nsAString& aColor);
static void GetHexStringFromNSColor(NSColor* aColor, nsAString& aResult);
static NSColorPanelWrapper* sColorPanelWrapper;
nsString mTitle;
nsString mColor;
nsCOMPtr<nsIColorPickerShownCallback> mCallback;
};
#endif // nsColorPicker_h_
-188
View File
@@ -1,188 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#import <Cocoa/Cocoa.h>
#include "nsColorPicker.h"
#include "nsCocoaUtils.h"
#include "nsThreadUtils.h"
using namespace mozilla;
static unsigned int
HexStrToInt(NSString* str)
{
unsigned int result = 0;
for (unsigned int i = 0; i < [str length]; ++i) {
char c = [str characterAtIndex:i];
result *= 16;
if (c >= '0' && c <= '9') {
result += c - '0';
} else if (c >= 'A' && c <= 'F') {
result += 10 + (c - 'A');
} else {
result += 10 + (c - 'a');
}
}
return result;
}
@interface NSColorPanelWrapper : NSObject <NSWindowDelegate>
{
NSColorPanel* mColorPanel;
nsColorPicker* mColorPicker;
}
- (id)initWithPicker:(nsColorPicker*)aPicker;
- (void)open:(NSColor*)aInitialColor title:(NSString*)aTitle;
- (void)retarget:(nsColorPicker*)aPicker;
- (void)colorChanged:(NSColorPanel*)aPanel;
@end
@implementation NSColorPanelWrapper
- (id)initWithPicker:(nsColorPicker*)aPicker
{
mColorPicker = aPicker;
mColorPanel = [NSColorPanel sharedColorPanel];
self = [super init];
return self;
}
- (void)open:(NSColor*)aInitialColor title:(NSString*)aTitle
{
[mColorPanel setTarget:self];
[mColorPanel setAction:@selector(colorChanged:)];
[mColorPanel setDelegate:self];
[mColorPanel setTitle:aTitle];
[mColorPanel setColor:aInitialColor];
[mColorPanel makeKeyAndOrderFront:nil];
}
- (void)colorChanged:(NSColorPanel*)aPanel
{
mColorPicker->Update([mColorPanel color]);
}
- (void)windowWillClose:(NSNotification*)aNotification
{
mColorPicker->Done();
}
- (void)retarget:(nsColorPicker*)aPicker
{
mColorPicker->DoneWithRetarget();
mColorPicker = aPicker;
}
- (void)dealloc
{
[mColorPanel setTarget:nil];
[mColorPanel setAction:nil];
[mColorPanel setDelegate:nil];
mColorPanel = nil;
mColorPicker = nullptr;
[super dealloc];
}
@end
NS_IMPL_ISUPPORTS(nsColorPicker, nsIColorPicker)
NSColorPanelWrapper* nsColorPicker::sColorPanelWrapper = nullptr;
nsColorPicker::~nsColorPicker()
{
}
NS_IMETHODIMP
nsColorPicker::Init(mozIDOMWindowProxy* aParent, const nsAString& aTitle,
const nsAString& aInitialColor)
{
MOZ_ASSERT(NS_IsMainThread(),
"Color pickers can only be opened from main thread currently");
mTitle = aTitle;
mColor = aInitialColor;
if (sColorPanelWrapper) {
// Update current wrapper to target the new input instead
[sColorPanelWrapper retarget:this];
} else {
// Create a brand new color panel wrapper
sColorPanelWrapper = [[NSColorPanelWrapper alloc] initWithPicker:this];
}
return NS_OK;
}
/* static */ NSColor*
nsColorPicker::GetNSColorFromHexString(const nsAString& aColor)
{
NSString* str = nsCocoaUtils::ToNSString(aColor);
double red = HexStrToInt([str substringWithRange:NSMakeRange(1, 2)]) / 255.0;
double green = HexStrToInt([str substringWithRange:NSMakeRange(3, 2)]) / 255.0;
double blue = HexStrToInt([str substringWithRange:NSMakeRange(5, 2)]) / 255.0;
return [NSColor colorWithDeviceRed: red green: green blue: blue alpha: 1.0];
}
/* static */ void
nsColorPicker::GetHexStringFromNSColor(NSColor* aColor, nsAString& aResult)
{
CGFloat redFloat, greenFloat, blueFloat;
NSColor* color = aColor;
@try {
[color getRed:&redFloat green:&greenFloat blue:&blueFloat alpha: nil];
} @catch (NSException* e) {
color = [color colorUsingColorSpace:[NSColorSpace genericRGBColorSpace]];
[color getRed:&redFloat green:&greenFloat blue:&blueFloat alpha: nil];
}
nsCocoaUtils::GetStringForNSString([NSString stringWithFormat:@"#%02x%02x%02x",
(int)(redFloat * 255),
(int)(greenFloat * 255),
(int)(blueFloat * 255)],
aResult);
}
NS_IMETHODIMP
nsColorPicker::Open(nsIColorPickerShownCallback* aCallback)
{
MOZ_ASSERT(aCallback);
mCallback = aCallback;
[sColorPanelWrapper open:GetNSColorFromHexString(mColor)
title:nsCocoaUtils::ToNSString(mTitle)];
NS_ADDREF_THIS();
return NS_OK;
}
void
nsColorPicker::Update(NSColor* aColor)
{
GetHexStringFromNSColor(aColor, mColor);
mCallback->Update(mColor);
}
void
nsColorPicker::DoneWithRetarget()
{
mCallback->Done(EmptyString());
mCallback = nullptr;
NS_RELEASE_THIS();
}
void
nsColorPicker::Done()
{
[sColorPanelWrapper release];
sColorPanelWrapper = nullptr;
DoneWithRetarget();
}
-65
View File
@@ -1,65 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsCursorManager_h_
#define nsCursorManager_h_
#import <Foundation/Foundation.h>
#include "nsIWidget.h"
#include "nsMacCursor.h"
/*! @class nsCursorManager
@abstract Singleton service provides access to all cursors available in the application.
@discussion Use <code>nsCusorManager</code> to set the current cursor using an XP <code>nsCusor</code> enum value.
<code>nsCursorManager</code> encapsulates the details of setting different types of cursors, animating
cursors and cleaning up cursors when they are no longer in use.
*/
@interface nsCursorManager : NSObject
{
@private
NSMutableDictionary *mCursors;
nsMacCursor *mCurrentMacCursor;
}
/*! @method setCursor:
@abstract Sets the current cursor.
@discussion Sets the current cursor to the cursor indicated by the XP cursor constant given as an argument.
Resources associated with the previous cursor are cleaned up.
@param aCursor the cursor to use
*/
- (nsresult) setCursor: (nsCursor) aCursor;
/*! @method setCursorWithImage:hotSpotX:hotSpotY:
@abstract Sets the current cursor to a custom image
@discussion Sets the current cursor to the cursor given by the aCursorImage argument.
Resources associated with the previous cursor are cleaned up.
@param aCursorImage the cursor image to use
@param aHotSpotX the x coordinate of the cursor's hotspot
@param aHotSpotY the y coordinate of the cursor's hotspot
@param scaleFactor the scale factor of the target display (2 for a retina display)
*/
- (nsresult) setCursorWithImage: (imgIContainer*) aCursorImage hotSpotX: (uint32_t) aHotspotX hotSpotY: (uint32_t) aHotspotY scaleFactor: (CGFloat) scaleFactor;
/*! @method sharedInstance
@abstract Get the Singleton instance of the cursor manager.
@discussion Use this method to obtain a reference to the cursor manager.
@result a reference to the cursor manager
*/
+ (nsCursorManager *) sharedInstance;
/*! @method dispose
@abstract Releases the shared instance of the cursor manager.
@discussion Use dispose to clean up the cursor manager and associated cursors.
*/
+ (void) dispose;
@end
@interface NSCursor (Undocumented)
// busyButClickableCursor is an undocumented NSCursor API, but has been in use since
// at least OS X 10.4 and through 10.9.
+ (NSCursor*)busyButClickableCursor;
@end
#endif // nsCursorManager_h_
-308
View File
@@ -1,308 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "imgIContainer.h"
#include "nsCocoaUtils.h"
#include "nsCursorManager.h"
#include "nsObjCExceptions.h"
#include <math.h>
static nsCursorManager *gInstance;
static CGFloat sCursorScaleFactor = 0.0f;
static imgIContainer *sCursorImgContainer = nullptr;
static const nsCursor sCustomCursor = eCursorCount;
/*! @category nsCursorManager(PrivateMethods)
Private methods for the cursor manager class.
*/
@interface nsCursorManager(PrivateMethods)
/*! @method getCursor:
@abstract Get a reference to the native Mac representation of a cursor.
@discussion Gets a reference to the Mac native implementation of a cursor.
If the cursor has been requested before, it is retreived from the cursor cache,
otherwise it is created and cached.
@param aCursor the cursor to get
@result the Mac native implementation of the cursor
*/
- (nsMacCursor *) getCursor: (nsCursor) aCursor;
/*! @method setMacCursor:
@abstract Set the current Mac native cursor
@discussion Sets the current cursor - this routine is what actually causes the cursor to change.
The argument is retained and the old cursor is released.
@param aMacCursor the cursor to set
@result NS_OK
*/
- (nsresult) setMacCursor: (nsMacCursor*) aMacCursor;
/*! @method createCursor:
@abstract Create a Mac native representation of a cursor.
@discussion Creates a version of the Mac native representation of this cursor
@param aCursor the cursor to create
@result the Mac native implementation of the cursor
*/
+ (nsMacCursor *) createCursor: (enum nsCursor) aCursor;
@end
@implementation nsCursorManager
+ (nsCursorManager *) sharedInstance
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if (!gInstance) {
gInstance = [[nsCursorManager alloc] init];
}
return gInstance;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
+ (void) dispose
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
[gInstance release];
gInstance = nil;
NS_OBJC_END_TRY_ABORT_BLOCK;
}
+ (nsMacCursor *) createCursor: (enum nsCursor) aCursor
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
switch(aCursor)
{
SEL cursorSelector;
case eCursor_standard:
return [nsMacCursor cursorWithCursor:[NSCursor arrowCursor] type:aCursor];
case eCursor_wait:
case eCursor_spinning:
{
return [nsMacCursor cursorWithCursor:[NSCursor busyButClickableCursor] type:aCursor];
}
case eCursor_select:
return [nsMacCursor cursorWithCursor:[NSCursor IBeamCursor] type:aCursor];
case eCursor_hyperlink:
return [nsMacCursor cursorWithCursor:[NSCursor pointingHandCursor] type:aCursor];
case eCursor_crosshair:
return [nsMacCursor cursorWithCursor:[NSCursor crosshairCursor] type:aCursor];
case eCursor_move:
return [nsMacCursor cursorWithImageNamed:@"move" hotSpot:NSMakePoint(12,12) type:aCursor];
case eCursor_help:
return [nsMacCursor cursorWithImageNamed:@"help" hotSpot:NSMakePoint(12,12) type:aCursor];
case eCursor_copy:
cursorSelector = @selector(dragCopyCursor);
return [nsMacCursor cursorWithCursor:[NSCursor respondsToSelector:cursorSelector] ?
[NSCursor performSelector:cursorSelector] :
[NSCursor arrowCursor] type:aCursor];
case eCursor_alias:
cursorSelector = @selector(dragLinkCursor);
return [nsMacCursor cursorWithCursor:[NSCursor respondsToSelector:cursorSelector] ?
[NSCursor performSelector:cursorSelector] :
[NSCursor arrowCursor] type:aCursor];
case eCursor_context_menu:
cursorSelector = @selector(contextualMenuCursor);
return [nsMacCursor cursorWithCursor:[NSCursor respondsToSelector:cursorSelector] ?
[NSCursor performSelector:cursorSelector] :
[NSCursor arrowCursor] type:aCursor];
case eCursor_cell:
return [nsMacCursor cursorWithImageNamed:@"cell" hotSpot:NSMakePoint(12,12) type:aCursor];
case eCursor_grab:
return [nsMacCursor cursorWithCursor:[NSCursor openHandCursor] type:aCursor];
case eCursor_grabbing:
return [nsMacCursor cursorWithCursor:[NSCursor closedHandCursor] type:aCursor];
case eCursor_zoom_in:
return [nsMacCursor cursorWithImageNamed:@"zoomIn" hotSpot:NSMakePoint(10,10) type:aCursor];
case eCursor_zoom_out:
return [nsMacCursor cursorWithImageNamed:@"zoomOut" hotSpot:NSMakePoint(10,10) type:aCursor];
case eCursor_vertical_text:
return [nsMacCursor cursorWithImageNamed:@"vtIBeam" hotSpot:NSMakePoint(12,11) type:aCursor];
case eCursor_all_scroll:
return [nsMacCursor cursorWithCursor:[NSCursor openHandCursor] type:aCursor];
case eCursor_not_allowed:
case eCursor_no_drop:
cursorSelector = @selector(operationNotAllowedCursor);
return [nsMacCursor cursorWithCursor:[NSCursor respondsToSelector:cursorSelector] ?
[NSCursor performSelector:cursorSelector] :
[NSCursor arrowCursor] type:aCursor];
// Resize Cursors:
// North
case eCursor_n_resize:
return [nsMacCursor cursorWithCursor:[NSCursor resizeUpCursor] type:aCursor];
// North East
case eCursor_ne_resize:
return [nsMacCursor cursorWithImageNamed:@"sizeNE" hotSpot:NSMakePoint(12,11) type:aCursor];
// East
case eCursor_e_resize:
return [nsMacCursor cursorWithCursor:[NSCursor resizeRightCursor] type:aCursor];
// South East
case eCursor_se_resize:
return [nsMacCursor cursorWithImageNamed:@"sizeSE" hotSpot:NSMakePoint(12,12) type:aCursor];
// South
case eCursor_s_resize:
return [nsMacCursor cursorWithCursor:[NSCursor resizeDownCursor] type:aCursor];
// South West
case eCursor_sw_resize:
return [nsMacCursor cursorWithImageNamed:@"sizeSW" hotSpot:NSMakePoint(10,12) type:aCursor];
// West
case eCursor_w_resize:
return [nsMacCursor cursorWithCursor:[NSCursor resizeLeftCursor] type:aCursor];
// North West
case eCursor_nw_resize:
return [nsMacCursor cursorWithImageNamed:@"sizeNW" hotSpot:NSMakePoint(11,11) type:aCursor];
// North & South
case eCursor_ns_resize:
return [nsMacCursor cursorWithCursor:[NSCursor resizeUpDownCursor] type:aCursor];
// East & West
case eCursor_ew_resize:
return [nsMacCursor cursorWithCursor:[NSCursor resizeLeftRightCursor] type:aCursor];
// North East & South West
case eCursor_nesw_resize:
return [nsMacCursor cursorWithImageNamed:@"sizeNESW" hotSpot:NSMakePoint(12,12) type:aCursor];
// North West & South East
case eCursor_nwse_resize:
return [nsMacCursor cursorWithImageNamed:@"sizeNWSE" hotSpot:NSMakePoint(12,12) type:aCursor];
// Column Resize
case eCursor_col_resize:
return [nsMacCursor cursorWithImageNamed:@"colResize" hotSpot:NSMakePoint(12,12) type:aCursor];
// Row Resize
case eCursor_row_resize:
return [nsMacCursor cursorWithImageNamed:@"rowResize" hotSpot:NSMakePoint(12,12) type:aCursor];
default:
return [nsMacCursor cursorWithCursor:[NSCursor arrowCursor] type:aCursor];
}
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
- (id) init
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if ((self = [super init])) {
mCursors = [[NSMutableDictionary alloc] initWithCapacity:25];
}
return self;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
- (nsresult) setCursor: (enum nsCursor) aCursor
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
// Some plugins mess with our cursors and set a cursor that even
// [NSCursor currentCursor] doesn't know about. In case that happens, just
// reset the state.
[[NSCursor currentCursor] set];
nsCursor oldType = [mCurrentMacCursor type];
if (oldType != aCursor) {
if (aCursor == eCursor_none) {
[NSCursor hide];
} else if (oldType == eCursor_none) {
[NSCursor unhide];
}
}
[self setMacCursor:[self getCursor:aCursor]];
// if a custom cursor was previously set, release sCursorImgContainer
if (oldType == sCustomCursor) {
NS_IF_RELEASE(sCursorImgContainer);
}
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
- (nsresult) setMacCursor: (nsMacCursor*) aMacCursor
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
if (mCurrentMacCursor != aMacCursor || ![mCurrentMacCursor isSet]) {
[aMacCursor retain];
[mCurrentMacCursor unset];
[aMacCursor set];
[mCurrentMacCursor release];
mCurrentMacCursor = aMacCursor;
}
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
- (nsresult) setCursorWithImage: (imgIContainer*) aCursorImage hotSpotX: (uint32_t) aHotspotX hotSpotY: (uint32_t) aHotspotY scaleFactor: (CGFloat) scaleFactor
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
// As the user moves the mouse, this gets called repeatedly with the same aCursorImage
if (sCursorImgContainer == aCursorImage && sCursorScaleFactor == scaleFactor && mCurrentMacCursor) {
[self setMacCursor:mCurrentMacCursor];
return NS_OK;
}
[[NSCursor currentCursor] set];
int32_t width = 0, height = 0;
aCursorImage->GetWidth(&width);
aCursorImage->GetHeight(&height);
// prevent DoS attacks
if (width > 128 || height > 128) {
return NS_OK;
}
NSImage *cursorImage;
nsresult rv = nsCocoaUtils::CreateNSImageFromImageContainer(aCursorImage, imgIContainer::FRAME_FIRST, &cursorImage, scaleFactor);
if (NS_FAILED(rv) || !cursorImage) {
return NS_ERROR_FAILURE;
}
// if the hotspot is nonsensical, make it 0,0
aHotspotX = (aHotspotX > (uint32_t)width - 1) ? 0 : aHotspotX;
aHotspotY = (aHotspotY > (uint32_t)height - 1) ? 0 : aHotspotY;
NSPoint hotSpot = ::NSMakePoint(aHotspotX, aHotspotY);
[self setMacCursor:[nsMacCursor cursorWithCursor:[[NSCursor alloc] initWithImage:cursorImage hotSpot:hotSpot] type:sCustomCursor]];
[cursorImage release];
NS_IF_RELEASE(sCursorImgContainer);
sCursorImgContainer = aCursorImage;
sCursorScaleFactor = scaleFactor;
NS_ADDREF(sCursorImgContainer);
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
- (nsMacCursor *) getCursor: (enum nsCursor) aCursor
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
nsMacCursor * result = [mCursors objectForKey:[NSNumber numberWithInt:aCursor]];
if (!result) {
result = [nsCursorManager createCursor:aCursor];
[mCursors setObject:result forKey:[NSNumber numberWithInt:aCursor]];
}
return result;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
- (void) dealloc
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
[mCurrentMacCursor unset];
[mCurrentMacCursor release];
[mCursors release];
NS_IF_RELEASE(sCursorImgContainer);
[super dealloc];
NS_OBJC_END_TRY_ABORT_BLOCK;
}
@end
-41
View File
@@ -1,41 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsDeviceContextSpecX_h_
#define nsDeviceContextSpecX_h_
#include "nsIDeviceContextSpec.h"
#include <ApplicationServices/ApplicationServices.h>
class nsDeviceContextSpecX : public nsIDeviceContextSpec
{
public:
NS_DECL_ISUPPORTS
nsDeviceContextSpecX();
NS_IMETHOD Init(nsIWidget *aWidget, nsIPrintSettings* aPS, bool aIsPrintPreview) override;
virtual already_AddRefed<PrintTarget> MakePrintTarget() final;
NS_IMETHOD BeginDocument(const nsAString& aTitle,
const nsAString& aPrintToFileName,
int32_t aStartPage,
int32_t aEndPage) override;
NS_IMETHOD EndDocument() override;
NS_IMETHOD BeginPage() override;
NS_IMETHOD EndPage() override;
void GetPaperRect(double* aTop, double* aLeft, double* aBottom, double* aRight);
protected:
virtual ~nsDeviceContextSpecX();
protected:
PMPrintSession mPrintSession; // printing context.
PMPageFormat mPageFormat; // page format.
PMPrintSettings mPrintSettings; // print settings.
};
#endif //nsDeviceContextSpecX_h_
-165
View File
@@ -1,165 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsDeviceContextSpecX.h"
#include "mozilla/gfx/PrintTargetCG.h"
#include "mozilla/RefPtr.h"
#include "nsCRT.h"
#include <unistd.h>
#include "nsQueryObject.h"
#include "nsIServiceManager.h"
#include "nsPrintSettingsX.h"
// This must be the last include:
#include "nsObjCExceptions.h"
using namespace mozilla;
using namespace mozilla::gfx;
nsDeviceContextSpecX::nsDeviceContextSpecX()
: mPrintSession(NULL)
, mPageFormat(kPMNoPageFormat)
, mPrintSettings(kPMNoPrintSettings)
{
}
nsDeviceContextSpecX::~nsDeviceContextSpecX()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
if (mPrintSession)
::PMRelease(mPrintSession);
NS_OBJC_END_TRY_ABORT_BLOCK;
}
NS_IMPL_ISUPPORTS(nsDeviceContextSpecX, nsIDeviceContextSpec)
NS_IMETHODIMP nsDeviceContextSpecX::Init(nsIWidget *aWidget,
nsIPrintSettings* aPS,
bool aIsPrintPreview)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
RefPtr<nsPrintSettingsX> settings(do_QueryObject(aPS));
if (!settings)
return NS_ERROR_NO_INTERFACE;
mPrintSession = settings->GetPMPrintSession();
::PMRetain(mPrintSession);
mPageFormat = settings->GetPMPageFormat();
mPrintSettings = settings->GetPMPrintSettings();
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_IMETHODIMP nsDeviceContextSpecX::BeginDocument(const nsAString& aTitle,
const nsAString& aPrintToFileName,
int32_t aStartPage,
int32_t aEndPage)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
if (!aTitle.IsEmpty()) {
CFStringRef cfString =
::CFStringCreateWithCharacters(NULL, reinterpret_cast<const UniChar*>(aTitle.BeginReading()),
aTitle.Length());
if (cfString) {
::PMPrintSettingsSetJobName(mPrintSettings, cfString);
::CFRelease(cfString);
}
}
OSStatus status;
status = ::PMSetFirstPage(mPrintSettings, aStartPage, false);
NS_ASSERTION(status == noErr, "PMSetFirstPage failed");
status = ::PMSetLastPage(mPrintSettings, aEndPage, false);
NS_ASSERTION(status == noErr, "PMSetLastPage failed");
status = ::PMSessionBeginCGDocumentNoDialog(mPrintSession, mPrintSettings, mPageFormat);
if (status != noErr)
return NS_ERROR_ABORT;
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_IMETHODIMP nsDeviceContextSpecX::EndDocument()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
::PMSessionEndDocumentNoDialog(mPrintSession);
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_IMETHODIMP nsDeviceContextSpecX::BeginPage()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
PMSessionError(mPrintSession);
OSStatus status = ::PMSessionBeginPageNoDialog(mPrintSession, mPageFormat, NULL);
if (status != noErr) return NS_ERROR_ABORT;
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_IMETHODIMP nsDeviceContextSpecX::EndPage()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
OSStatus status = ::PMSessionEndPageNoDialog(mPrintSession);
if (status != noErr) return NS_ERROR_ABORT;
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
void nsDeviceContextSpecX::GetPaperRect(double* aTop, double* aLeft, double* aBottom, double* aRight)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
PMRect paperRect;
::PMGetAdjustedPaperRect(mPageFormat, &paperRect);
*aTop = paperRect.top, *aLeft = paperRect.left;
*aBottom = paperRect.bottom, *aRight = paperRect.right;
NS_OBJC_END_TRY_ABORT_BLOCK;
}
already_AddRefed<PrintTarget> nsDeviceContextSpecX::MakePrintTarget()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
double top, left, bottom, right;
GetPaperRect(&top, &left, &bottom, &right);
const double width = right - left;
const double height = bottom - top;
IntSize size = IntSize::Floor(width, height);
CGContextRef context;
::PMSessionGetCGGraphicsContext(mPrintSession, &context);
if (context) {
// Initially, origin is at bottom-left corner of the paper.
// Here, we translate it to top-left corner of the paper.
CGContextTranslateCTM(context, 0, height);
CGContextScaleCTM(context, 1.0, -1.0);
return PrintTargetCG::CreateOrNull(context, size);
}
// Apparently we do need this branch - bug 368933.
return PrintTargetCG::CreateOrNull(size, SurfaceFormat::A8R8G8B8_UINT32);
NS_OBJC_END_TRY_ABORT_BLOCK_NSNULL;
}
-55
View File
@@ -1,55 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsDragService_h_
#define nsDragService_h_
#include "nsBaseDragService.h"
#include <Cocoa/Cocoa.h>
extern NSString* const kWildcardPboardType;
extern NSString* const kCorePboardType_url;
extern NSString* const kCorePboardType_urld;
extern NSString* const kCorePboardType_urln;
extern NSString* const kCustomTypesPboardType;
class nsDragService : public nsBaseDragService
{
public:
nsDragService();
// nsBaseDragService
virtual nsresult InvokeDragSessionImpl(nsIArray* anArrayTransferables,
nsIScriptableRegion* aRegion,
uint32_t aActionType);
// nsIDragService
NS_IMETHOD EndDragSession(bool aDoneDrag);
// nsIDragSession
NS_IMETHOD GetData(nsITransferable * aTransferable, uint32_t aItemIndex);
NS_IMETHOD IsDataFlavorSupported(const char *aDataFlavor, bool *_retval);
NS_IMETHOD GetNumDropItems(uint32_t * aNumItems);
protected:
virtual ~nsDragService();
private:
NSImage* ConstructDragImage(nsIDOMNode* aDOMNode,
mozilla::LayoutDeviceIntRect* aDragRect,
nsIScriptableRegion* aRegion);
bool IsValidType(NSString* availableType, bool allowFileURL);
NSString* GetStringForType(NSPasteboardItem* item, const NSString* type,
bool allowFileURL = false);
NSString* GetTitleForURL(NSPasteboardItem* item);
NSString* GetFilePath(NSPasteboardItem* item);
nsCOMPtr<nsIArray> mDataItems; // only valid for a drag started within gecko
NSView* mNativeDragView;
NSEvent* mNativeDragEvent;
};
#endif // nsDragService_h_
-669
View File
@@ -1,669 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/Logging.h"
#include "nsArrayUtils.h"
#include "nsDragService.h"
#include "nsArrayUtils.h"
#include "nsObjCExceptions.h"
#include "nsITransferable.h"
#include "nsString.h"
#include "nsClipboard.h"
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
#include "nsCOMPtr.h"
#include "nsPrimitiveHelpers.h"
#include "nsLinebreakConverter.h"
#include "nsIMacUtils.h"
#include "nsIDOMNode.h"
#include "nsRect.h"
#include "nsPoint.h"
#include "nsIIOService.h"
#include "nsIDocument.h"
#include "nsIContent.h"
#include "nsView.h"
#include "gfxContext.h"
#include "nsCocoaUtils.h"
#include "mozilla/gfx/2D.h"
#include "gfxPlatform.h"
using namespace mozilla;
using namespace mozilla::gfx;
extern PRLogModuleInfo* sCocoaLog;
extern void EnsureLogInitialized();
extern NSPasteboard* globalDragPboard;
extern NSView* gLastDragView;
extern NSEvent* gLastDragMouseDownEvent;
extern bool gUserCancelledDrag;
// This global makes the transferable array available to Cocoa's promised
// file destination callback.
nsIArray *gDraggedTransferables = nullptr;
NSString* const kWildcardPboardType = @"MozillaWildcard";
NSString* const kCorePboardType_url = @"CorePasteboardFlavorType 0x75726C20"; // 'url ' url
NSString* const kCorePboardType_urld = @"CorePasteboardFlavorType 0x75726C64"; // 'urld' desc
NSString* const kCorePboardType_urln = @"CorePasteboardFlavorType 0x75726C6E"; // 'urln' title
NSString* const kUTTypeURLName = @"public.url-name";
NSString* const kCustomTypesPboardType = @"org.mozilla.custom-clipdata";
nsDragService::nsDragService()
{
mNativeDragView = nil;
mNativeDragEvent = nil;
EnsureLogInitialized();
}
nsDragService::~nsDragService()
{
}
static nsresult SetUpDragClipboard(nsIArray* aTransferableArray)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
if (!aTransferableArray)
return NS_ERROR_FAILURE;
uint32_t count = 0;
aTransferableArray->GetLength(&count);
NSPasteboard* dragPBoard = [NSPasteboard pasteboardWithName:NSDragPboard];
for (uint32_t j = 0; j < count; j++) {
nsCOMPtr<nsITransferable> currentTransferable = do_QueryElementAt(aTransferableArray, j);
if (!currentTransferable)
return NS_ERROR_FAILURE;
// Transform the transferable to an NSDictionary
NSDictionary* pasteboardOutputDict = nsClipboard::PasteboardDictFromTransferable(currentTransferable);
if (!pasteboardOutputDict)
return NS_ERROR_FAILURE;
// write everything out to the general pasteboard
unsigned int typeCount = [pasteboardOutputDict count];
NSMutableArray* types = [NSMutableArray arrayWithCapacity:typeCount + 1];
[types addObjectsFromArray:[pasteboardOutputDict allKeys]];
// Gecko is initiating this drag so we always want its own views to consider
// it. Add our wildcard type to the pasteboard to accomplish this.
[types addObject:kWildcardPboardType]; // we don't increase the count for the loop below on purpose
[dragPBoard declareTypes:types owner:nil];
for (unsigned int k = 0; k < typeCount; k++) {
NSString* currentKey = [types objectAtIndex:k];
id currentValue = [pasteboardOutputDict valueForKey:currentKey];
if (currentKey == NSStringPboardType ||
currentKey == kCorePboardType_url ||
currentKey == kCorePboardType_urld ||
currentKey == kCorePboardType_urln) {
[dragPBoard setString:currentValue forType:currentKey];
}
else if (currentKey == NSHTMLPboardType) {
[dragPBoard setString:(nsClipboard::WrapHtmlForSystemPasteboard(currentValue))
forType:currentKey];
}
else if (currentKey == NSTIFFPboardType ||
currentKey == kCustomTypesPboardType) {
[dragPBoard setData:currentValue forType:currentKey];
}
else if (currentKey == NSFilesPromisePboardType ||
currentKey == NSFilenamesPboardType) {
[dragPBoard setPropertyList:currentValue forType:currentKey];
}
}
}
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NSImage*
nsDragService::ConstructDragImage(nsIDOMNode* aDOMNode,
LayoutDeviceIntRect* aDragRect,
nsIScriptableRegion* aRegion)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
CGFloat scaleFactor = nsCocoaUtils::GetBackingScaleFactor(gLastDragView);
RefPtr<SourceSurface> surface;
nsPresContext* pc;
nsresult rv = DrawDrag(aDOMNode, aRegion, mScreenPosition,
aDragRect, &surface, &pc);
if (pc && (!aDragRect->width || !aDragRect->height)) {
// just use some suitable defaults
int32_t size = nsCocoaUtils::CocoaPointsToDevPixels(20, scaleFactor);
aDragRect->SetRect(pc->CSSPixelsToDevPixels(mScreenPosition.x),
pc->CSSPixelsToDevPixels(mScreenPosition.y), size, size);
}
if (NS_FAILED(rv) || !surface)
return nil;
uint32_t width = aDragRect->width;
uint32_t height = aDragRect->height;
RefPtr<DataSourceSurface> dataSurface =
Factory::CreateDataSourceSurface(IntSize(width, height),
SurfaceFormat::B8G8R8A8);
DataSourceSurface::MappedSurface map;
if (!dataSurface->Map(DataSourceSurface::MapType::READ_WRITE, &map)) {
return nil;
}
RefPtr<DrawTarget> dt =
Factory::CreateDrawTargetForData(BackendType::CAIRO,
map.mData,
dataSurface->GetSize(),
map.mStride,
dataSurface->GetFormat());
if (!dt) {
dataSurface->Unmap();
return nil;
}
dt->FillRect(gfx::Rect(0, 0, width, height),
SurfacePattern(surface, ExtendMode::CLAMP),
DrawOptions(1.0f, CompositionOp::OP_SOURCE));
NSBitmapImageRep* imageRep =
[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
pixelsWide:width
pixelsHigh:height
bitsPerSample:8
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSDeviceRGBColorSpace
bytesPerRow:width * 4
bitsPerPixel:32];
uint8_t* dest = [imageRep bitmapData];
for (uint32_t i = 0; i < height; ++i) {
uint8_t* src = map.mData + i * map.mStride;
for (uint32_t j = 0; j < width; ++j) {
// Reduce transparency overall by multipying by a factor. Remember, Alpha
// is premultipled here. Also, Quartz likes RGBA, so do that translation as well.
#ifdef IS_BIG_ENDIAN
dest[0] = uint8_t(src[1] * DRAG_TRANSLUCENCY);
dest[1] = uint8_t(src[2] * DRAG_TRANSLUCENCY);
dest[2] = uint8_t(src[3] * DRAG_TRANSLUCENCY);
dest[3] = uint8_t(src[0] * DRAG_TRANSLUCENCY);
#else
dest[0] = uint8_t(src[2] * DRAG_TRANSLUCENCY);
dest[1] = uint8_t(src[1] * DRAG_TRANSLUCENCY);
dest[2] = uint8_t(src[0] * DRAG_TRANSLUCENCY);
dest[3] = uint8_t(src[3] * DRAG_TRANSLUCENCY);
#endif
src += 4;
dest += 4;
}
}
dataSurface->Unmap();
NSImage* image =
[[NSImage alloc] initWithSize:NSMakeSize(width / scaleFactor,
height / scaleFactor)];
[image addRepresentation:imageRep];
[imageRep release];
return [image autorelease];
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
bool
nsDragService::IsValidType(NSString* availableType, bool allowFileURL)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
// Prevent exposing fileURL for non-fileURL type.
// We need URL provided by dropped webloc file, but don't need file's URL.
// kUTTypeFileURL is returned by [NSPasteboard availableTypeFromArray:] for
// kUTTypeURL, since it conforms to kUTTypeURL.
if (!allowFileURL && [availableType isEqualToString:(id)kUTTypeFileURL]) {
return false;
}
return true;
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
}
NSString*
nsDragService::GetStringForType(NSPasteboardItem* item, const NSString* type,
bool allowFileURL)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
NSString* availableType = [item availableTypeFromArray:[NSArray arrayWithObjects:(id)type, nil]];
if (availableType && IsValidType(availableType, allowFileURL)) {
return [item stringForType:(id)availableType];
}
return nil;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
NSString*
nsDragService::GetTitleForURL(NSPasteboardItem* item)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
NSString* name = GetStringForType(item, (const NSString*)kUTTypeURLName);
if (name) {
return name;
}
NSString* filePath = GetFilePath(item);
if (filePath) {
return [filePath lastPathComponent];
}
return nil;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
NSString*
nsDragService::GetFilePath(NSPasteboardItem* item)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
NSString* urlString = GetStringForType(item, (const NSString*)kUTTypeFileURL, true);
if (urlString) {
NSURL* url = [NSURL URLWithString:urlString];
if (url) {
return [url path];
}
}
return nil;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
// We can only invoke NSView's 'dragImage:at:offset:event:pasteboard:source:slideBack:' from
// within NSView's 'mouseDown:' or 'mouseDragged:'. Luckily 'mouseDragged' is always on the
// stack when InvokeDragSession gets called.
nsresult
nsDragService::InvokeDragSessionImpl(nsIArray* aTransferableArray,
nsIScriptableRegion* aDragRgn,
uint32_t aActionType)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
mDataItems = aTransferableArray;
// put data on the clipboard
if (NS_FAILED(SetUpDragClipboard(aTransferableArray)))
return NS_ERROR_FAILURE;
CGFloat scaleFactor = nsCocoaUtils::GetBackingScaleFactor(gLastDragView);
LayoutDeviceIntRect dragRect(0, 0, 20, 20);
NSImage* image = ConstructDragImage(mSourceNode, &dragRect, aDragRgn);
if (!image) {
// if no image was returned, just draw a rectangle
NSSize size;
size.width = nsCocoaUtils::DevPixelsToCocoaPoints(dragRect.width, scaleFactor);
size.height = nsCocoaUtils::DevPixelsToCocoaPoints(dragRect.height, scaleFactor);
image = [[NSImage alloc] initWithSize:size];
[image lockFocus];
[[NSColor grayColor] set];
NSBezierPath* path = [NSBezierPath bezierPath];
[path setLineWidth:2.0];
[path moveToPoint:NSMakePoint(0, 0)];
[path lineToPoint:NSMakePoint(0, size.height)];
[path lineToPoint:NSMakePoint(size.width, size.height)];
[path lineToPoint:NSMakePoint(size.width, 0)];
[path lineToPoint:NSMakePoint(0, 0)];
[path stroke];
[image unlockFocus];
}
LayoutDeviceIntPoint pt(dragRect.x, dragRect.YMost());
NSPoint point = nsCocoaUtils::DevPixelsToCocoaPoints(pt, scaleFactor);
point.y = nsCocoaUtils::FlippedScreenY(point.y);
point = nsCocoaUtils::ConvertPointFromScreen([gLastDragView window], point);
NSPoint localPoint = [gLastDragView convertPoint:point fromView:nil];
// Save the transferables away in case a promised file callback is invoked.
gDraggedTransferables = aTransferableArray;
nsBaseDragService::StartDragSession();
nsBaseDragService::OpenDragPopup();
// We need to retain the view and the event during the drag in case either gets destroyed.
mNativeDragView = [gLastDragView retain];
mNativeDragEvent = [gLastDragMouseDownEvent retain];
gUserCancelledDrag = false;
[mNativeDragView dragImage:image
at:localPoint
offset:NSZeroSize
event:mNativeDragEvent
pasteboard:[NSPasteboard pasteboardWithName:NSDragPboard]
source:mNativeDragView
slideBack:YES];
gUserCancelledDrag = false;
if (mDoingDrag)
nsBaseDragService::EndDragSession(false);
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_IMETHODIMP
nsDragService::GetData(nsITransferable* aTransferable, uint32_t aItemIndex)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
if (!aTransferable)
return NS_ERROR_FAILURE;
// get flavor list that includes all acceptable flavors (including ones obtained through conversion)
nsCOMPtr<nsIArray> flavorList;
nsresult rv = aTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList));
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
uint32_t acceptableFlavorCount;
flavorList->GetLength(&acceptableFlavorCount);
// if this drag originated within Mozilla we should just use the cached data from
// when the drag started if possible
if (mDataItems) {
nsCOMPtr<nsITransferable> currentTransferable = do_QueryElementAt(mDataItems, aItemIndex);
if (currentTransferable) {
for (uint32_t i = 0; i < acceptableFlavorCount; i++) {
nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryElementAt(flavorList, i);
if (!currentFlavor)
continue;
nsXPIDLCString flavorStr;
currentFlavor->ToString(getter_Copies(flavorStr));
nsCOMPtr<nsISupports> dataSupports;
uint32_t dataSize = 0;
rv = currentTransferable->GetTransferData(flavorStr, getter_AddRefs(dataSupports), &dataSize);
if (NS_SUCCEEDED(rv)) {
aTransferable->SetTransferData(flavorStr, dataSupports, dataSize);
return NS_OK; // maybe try to fill in more types? Is there a point?
}
}
}
}
// now check the actual clipboard for data
for (uint32_t i = 0; i < acceptableFlavorCount; i++) {
nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryElementAt(flavorList, i);
if (!currentFlavor)
continue;
nsXPIDLCString flavorStr;
currentFlavor->ToString(getter_Copies(flavorStr));
MOZ_LOG(sCocoaLog, LogLevel::Info, ("nsDragService::GetData: looking for clipboard data of type %s\n", flavorStr.get()));
NSArray* droppedItems = [globalDragPboard pasteboardItems];
if (!droppedItems) {
continue;
}
uint32_t itemCount = [droppedItems count];
if (aItemIndex >= itemCount) {
continue;
}
NSPasteboardItem* item = [droppedItems objectAtIndex:aItemIndex];
if (!item) {
continue;
}
if (flavorStr.EqualsLiteral(kFileMime)) {
NSString* filePath = GetFilePath(item);
if (!filePath)
continue;
unsigned int stringLength = [filePath length];
unsigned int dataLength = (stringLength + 1) * sizeof(char16_t); // in bytes
char16_t* clipboardDataPtr = (char16_t*)malloc(dataLength);
if (!clipboardDataPtr)
return NS_ERROR_OUT_OF_MEMORY;
[filePath getCharacters:reinterpret_cast<unichar*>(clipboardDataPtr)];
clipboardDataPtr[stringLength] = 0; // null terminate
nsCOMPtr<nsIFile> file;
rv = NS_NewLocalFile(nsDependentString(clipboardDataPtr), true, getter_AddRefs(file));
free(clipboardDataPtr);
if (NS_FAILED(rv))
continue;
aTransferable->SetTransferData(flavorStr, file, dataLength);
break;
}
else if (flavorStr.EqualsLiteral(kCustomTypesMime)) {
NSString* availableType = [item availableTypeFromArray:[NSArray arrayWithObject:kCustomTypesPboardType]];
if (!availableType || !IsValidType(availableType, false)) {
continue;
}
NSData *pasteboardData = [item dataForType:availableType];
if (!pasteboardData) {
continue;
}
unsigned int dataLength = [pasteboardData length];
void* clipboardDataPtr = malloc(dataLength);
if (!clipboardDataPtr) {
return NS_ERROR_OUT_OF_MEMORY;
}
[pasteboardData getBytes:clipboardDataPtr];
nsCOMPtr<nsISupports> genericDataWrapper;
nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr, clipboardDataPtr, dataLength,
getter_AddRefs(genericDataWrapper));
aTransferable->SetTransferData(flavorStr, genericDataWrapper, sizeof(nsIInputStream*));
free(clipboardDataPtr);
break;
}
NSString* pString = nil;
if (flavorStr.EqualsLiteral(kUnicodeMime)) {
pString = GetStringForType(item, (const NSString*)kUTTypeUTF8PlainText);
} else if (flavorStr.EqualsLiteral(kHTMLMime)) {
pString = GetStringForType(item, (const NSString*)kUTTypeHTML);
} else if (flavorStr.EqualsLiteral(kURLMime)) {
pString = GetStringForType(item, (const NSString*)kUTTypeURL);
if (pString) {
NSString* title = GetTitleForURL(item);
if (!title) {
title = pString;
}
pString = [NSString stringWithFormat:@"%@\n%@", pString, title];
}
} else if (flavorStr.EqualsLiteral(kURLDataMime)) {
pString = GetStringForType(item, (const NSString*)kUTTypeURL);
} else if (flavorStr.EqualsLiteral(kURLDescriptionMime)) {
pString = GetTitleForURL(item);
} else if (flavorStr.EqualsLiteral(kRTFMime)) {
pString = GetStringForType(item, (const NSString*)kUTTypeRTF);
}
if (pString) {
NSData* stringData;
if (flavorStr.EqualsLiteral(kRTFMime)) {
stringData = [pString dataUsingEncoding:NSASCIIStringEncoding];
} else {
stringData = [pString dataUsingEncoding:NSUnicodeStringEncoding];
}
unsigned int dataLength = [stringData length];
void* clipboardDataPtr = malloc(dataLength);
if (!clipboardDataPtr)
return NS_ERROR_OUT_OF_MEMORY;
[stringData getBytes:clipboardDataPtr];
// The DOM only wants LF, so convert from MacOS line endings to DOM line endings.
int32_t signedDataLength = dataLength;
nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks(flavorStr, &clipboardDataPtr, &signedDataLength);
dataLength = signedDataLength;
// skip BOM (Byte Order Mark to distinguish little or big endian)
char16_t* clipboardDataPtrNoBOM = (char16_t*)clipboardDataPtr;
if ((dataLength > 2) &&
((clipboardDataPtrNoBOM[0] == 0xFEFF) ||
(clipboardDataPtrNoBOM[0] == 0xFFFE))) {
dataLength -= sizeof(char16_t);
clipboardDataPtrNoBOM += 1;
}
nsCOMPtr<nsISupports> genericDataWrapper;
nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr, clipboardDataPtrNoBOM, dataLength,
getter_AddRefs(genericDataWrapper));
aTransferable->SetTransferData(flavorStr, genericDataWrapper, dataLength);
free(clipboardDataPtr);
break;
}
// We have never supported this on Mac OS X, we should someday. Normally dragging images
// in is accomplished with a file path drag instead of the image data itself.
/*
if (flavorStr.EqualsLiteral(kPNGImageMime) || flavorStr.EqualsLiteral(kJPEGImageMime) ||
flavorStr.EqualsLiteral(kJPGImageMime) || flavorStr.EqualsLiteral(kGIFImageMime)) {
}
*/
}
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_IMETHODIMP
nsDragService::IsDataFlavorSupported(const char *aDataFlavor, bool *_retval)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
*_retval = false;
if (!globalDragPboard)
return NS_ERROR_FAILURE;
nsDependentCString dataFlavor(aDataFlavor);
// first see if we have data for this in our cached transferable
if (mDataItems) {
uint32_t dataItemsCount;
mDataItems->GetLength(&dataItemsCount);
for (unsigned int i = 0; i < dataItemsCount; i++) {
nsCOMPtr<nsITransferable> currentTransferable = do_QueryElementAt(mDataItems, i);
if (!currentTransferable)
continue;
nsCOMPtr<nsIArray> flavorList;
nsresult rv = currentTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList));
if (NS_FAILED(rv))
continue;
uint32_t flavorCount;
flavorList->GetLength(&flavorCount);
for (uint32_t j = 0; j < flavorCount; j++) {
nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryElementAt(flavorList, j);
if (!currentFlavor)
continue;
nsXPIDLCString flavorStr;
currentFlavor->ToString(getter_Copies(flavorStr));
if (dataFlavor.Equals(flavorStr)) {
*_retval = true;
return NS_OK;
}
}
}
}
const NSString* type = nil;
bool allowFileURL = false;
if (dataFlavor.EqualsLiteral(kFileMime)) {
type = (const NSString*)kUTTypeFileURL;
allowFileURL = true;
} else if (dataFlavor.EqualsLiteral(kUnicodeMime)) {
type = (const NSString*)kUTTypeUTF8PlainText;
} else if (dataFlavor.EqualsLiteral(kHTMLMime)) {
type = (const NSString*)kUTTypeHTML;
} else if (dataFlavor.EqualsLiteral(kURLMime) ||
dataFlavor.EqualsLiteral(kURLDataMime)) {
type = (const NSString*)kUTTypeURL;
} else if (dataFlavor.EqualsLiteral(kURLDescriptionMime)) {
type = (const NSString*)kUTTypeURLName;
} else if (dataFlavor.EqualsLiteral(kRTFMime)) {
type = (const NSString*)kUTTypeRTF;
} else if (dataFlavor.EqualsLiteral(kCustomTypesMime)) {
type = (const NSString*)kCustomTypesPboardType;
}
NSString* availableType = [globalDragPboard availableTypeFromArray:[NSArray arrayWithObjects:(id)type, nil]];
if (availableType && IsValidType(availableType, allowFileURL)) {
*_retval = true;
}
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_IMETHODIMP
nsDragService::GetNumDropItems(uint32_t* aNumItems)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
*aNumItems = 0;
// first check to see if we have a number of items cached
if (mDataItems) {
mDataItems->GetLength(aNumItems);
return NS_OK;
}
NSArray* droppedItems = [globalDragPboard pasteboardItems];
if (droppedItems) {
*aNumItems = [droppedItems count];
}
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_IMETHODIMP
nsDragService::EndDragSession(bool aDoneDrag)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
if (mNativeDragView) {
[mNativeDragView release];
mNativeDragView = nil;
}
if (mNativeDragEvent) {
[mNativeDragEvent release];
mNativeDragEvent = nil;
}
mUserCancelled = gUserCancelledDrag;
nsresult rv = nsBaseDragService::EndDragSession(aDoneDrag);
mDataItems = nullptr;
return rv;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
-74
View File
@@ -1,74 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsFilePicker_h_
#define nsFilePicker_h_
#include "nsBaseFilePicker.h"
#include "nsString.h"
#include "nsIFileChannel.h"
#include "nsIFile.h"
#include "nsCOMArray.h"
#include "nsTArray.h"
class nsILocalFileMac;
@class NSArray;
class nsFilePicker : public nsBaseFilePicker
{
public:
nsFilePicker();
NS_DECL_ISUPPORTS
// nsIFilePicker (less what's in nsBaseFilePicker)
NS_IMETHOD GetDefaultString(nsAString& aDefaultString) override;
NS_IMETHOD SetDefaultString(const nsAString& aDefaultString) override;
NS_IMETHOD GetDefaultExtension(nsAString& aDefaultExtension) override;
NS_IMETHOD GetFilterIndex(int32_t *aFilterIndex) override;
NS_IMETHOD SetFilterIndex(int32_t aFilterIndex) override;
NS_IMETHOD SetDefaultExtension(const nsAString& aDefaultExtension) override;
NS_IMETHOD GetFile(nsIFile * *aFile) override;
NS_IMETHOD GetFileURL(nsIURI * *aFileURL) override;
NS_IMETHOD GetFiles(nsISimpleEnumerator **aFiles) override;
NS_IMETHOD Show(int16_t *_retval) override;
NS_IMETHOD AppendFilter(const nsAString& aTitle, const nsAString& aFilter) override;
/**
* Returns the current filter list in the format used by Cocoa's NSSavePanel
* and NSOpenPanel.
* Returns nil if no filter currently apply.
*/
NSArray* GetFilterList();
protected:
virtual ~nsFilePicker();
virtual void InitNative(nsIWidget *aParent, const nsAString& aTitle) override;
// actual implementations of get/put dialogs using NSOpenPanel & NSSavePanel
// aFile is an existing but unspecified file. These functions must specify it.
//
// will return |returnCancel| or |returnOK| as result.
int16_t GetLocalFiles(const nsString& inTitle, bool inAllowMultiple, nsCOMArray<nsIFile>& outFiles);
int16_t GetLocalFolder(const nsString& inTitle, nsIFile** outFile);
int16_t PutLocalFile(const nsString& inTitle, const nsString& inDefaultName, nsIFile** outFile);
void SetDialogTitle(const nsString& inTitle, id aDialog);
NSString *PanelDefaultDirectory();
NSView* GetAccessoryView();
nsString mTitle;
nsCOMArray<nsIFile> mFiles;
nsString mDefault;
nsTArray<nsString> mFilters;
nsTArray<nsString> mTitles;
int32_t mSelectedTypeIndex;
};
#endif // nsFilePicker_h_
-676
View File
@@ -1,676 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#import <Cocoa/Cocoa.h>
#include "nsFilePicker.h"
#include "nsCOMPtr.h"
#include "nsReadableUtils.h"
#include "nsNetUtil.h"
#include "nsIComponentManager.h"
#include "nsIFile.h"
#include "nsILocalFileMac.h"
#include "nsIURL.h"
#include "nsArrayEnumerator.h"
#include "nsIStringBundle.h"
#include "nsCocoaUtils.h"
#include "mozilla/Preferences.h"
// This must be included last:
#include "nsObjCExceptions.h"
using namespace mozilla;
const float kAccessoryViewPadding = 5;
const int kSaveTypeControlTag = 1;
static bool gCallSecretHiddenFileAPI = false;
const char kShowHiddenFilesPref[] = "filepicker.showHiddenFiles";
/**
* This class is an observer of NSPopUpButton selection change.
*/
@interface NSPopUpButtonObserver : NSObject
{
NSPopUpButton* mPopUpButton;
NSOpenPanel* mOpenPanel;
nsFilePicker* mFilePicker;
}
- (void) setPopUpButton:(NSPopUpButton*)aPopUpButton;
- (void) setOpenPanel:(NSOpenPanel*)aOpenPanel;
- (void) setFilePicker:(nsFilePicker*)aFilePicker;
- (void) menuChangedItem:(NSNotification*)aSender;
@end
NS_IMPL_ISUPPORTS(nsFilePicker, nsIFilePicker)
// We never want to call the secret show hidden files API unless the pref
// has been set. Once the pref has been set we always need to call it even
// if it disappears so that we stop showing hidden files if a user deletes
// the pref. If the secret API was used once and things worked out it should
// continue working for subsequent calls so the user is at no more risk.
static void SetShowHiddenFileState(NSSavePanel* panel)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
bool show = false;
if (NS_SUCCEEDED(Preferences::GetBool(kShowHiddenFilesPref, &show))) {
gCallSecretHiddenFileAPI = true;
}
if (gCallSecretHiddenFileAPI) {
// invoke a method to get a Cocoa-internal nav view
SEL navViewSelector = @selector(_navView);
NSMethodSignature* navViewSignature = [panel methodSignatureForSelector:navViewSelector];
if (!navViewSignature)
return;
NSInvocation* navViewInvocation = [NSInvocation invocationWithMethodSignature:navViewSignature];
[navViewInvocation setSelector:navViewSelector];
[navViewInvocation setTarget:panel];
[navViewInvocation invoke];
// get the returned nav view
id navView = nil;
[navViewInvocation getReturnValue:&navView];
// invoke the secret show hidden file state method on the nav view
SEL showHiddenFilesSelector = @selector(setShowsHiddenFiles:);
NSMethodSignature* showHiddenFilesSignature = [navView methodSignatureForSelector:showHiddenFilesSelector];
if (!showHiddenFilesSignature)
return;
NSInvocation* showHiddenFilesInvocation = [NSInvocation invocationWithMethodSignature:showHiddenFilesSignature];
[showHiddenFilesInvocation setSelector:showHiddenFilesSelector];
[showHiddenFilesInvocation setTarget:navView];
[showHiddenFilesInvocation setArgument:&show atIndex:2];
[showHiddenFilesInvocation invoke];
}
NS_OBJC_END_TRY_ABORT_BLOCK;
}
nsFilePicker::nsFilePicker()
: mSelectedTypeIndex(0)
{
}
nsFilePicker::~nsFilePicker()
{
}
void
nsFilePicker::InitNative(nsIWidget *aParent, const nsAString& aTitle)
{
mTitle = aTitle;
}
NSView* nsFilePicker::GetAccessoryView()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
NSView* accessoryView = [[[NSView alloc] initWithFrame:NSMakeRect(0, 0, 0, 0)] autorelease];
// Set a label's default value.
NSString* label = @"Format:";
// Try to get the localized string.
nsCOMPtr<nsIStringBundleService> sbs = do_GetService(NS_STRINGBUNDLE_CONTRACTID);
nsCOMPtr<nsIStringBundle> bundle;
nsresult rv = sbs->CreateBundle("chrome://global/locale/filepicker.properties", getter_AddRefs(bundle));
if (NS_SUCCEEDED(rv)) {
nsXPIDLString locaLabel;
bundle->GetStringFromName(u"formatLabel", getter_Copies(locaLabel));
if (locaLabel) {
label = [NSString stringWithCharacters:reinterpret_cast<const unichar*>(locaLabel.get())
length:locaLabel.Length()];
}
}
// set up label text field
NSTextField* textField = [[[NSTextField alloc] init] autorelease];
[textField setEditable:NO];
[textField setSelectable:NO];
[textField setDrawsBackground:NO];
[textField setBezeled:NO];
[textField setBordered:NO];
[textField setFont:[NSFont labelFontOfSize:13.0]];
[textField setStringValue:label];
[textField setTag:0];
[textField sizeToFit];
// set up popup button
NSPopUpButton* popupButton = [[[NSPopUpButton alloc] initWithFrame:NSMakeRect(0, 0, 0, 0) pullsDown:NO] autorelease];
uint32_t numMenuItems = mTitles.Length();
for (uint32_t i = 0; i < numMenuItems; i++) {
const nsString& currentTitle = mTitles[i];
NSString *titleString;
if (currentTitle.IsEmpty()) {
const nsString& currentFilter = mFilters[i];
titleString = [[NSString alloc] initWithCharacters:reinterpret_cast<const unichar*>(currentFilter.get())
length:currentFilter.Length()];
}
else {
titleString = [[NSString alloc] initWithCharacters:reinterpret_cast<const unichar*>(currentTitle.get())
length:currentTitle.Length()];
}
[popupButton addItemWithTitle:titleString];
[titleString release];
}
if (mSelectedTypeIndex >= 0 && (uint32_t)mSelectedTypeIndex < numMenuItems)
[popupButton selectItemAtIndex:mSelectedTypeIndex];
[popupButton setTag:kSaveTypeControlTag];
[popupButton sizeToFit]; // we have to do sizeToFit to get the height calculated for us
// This is just a default width that works well, doesn't truncate the vast majority of
// things that might end up in the menu.
[popupButton setFrameSize:NSMakeSize(180, [popupButton frame].size.height)];
// position everything based on control sizes with kAccessoryViewPadding pix padding
// on each side kAccessoryViewPadding pix horizontal padding between controls
float greatestHeight = [textField frame].size.height;
if ([popupButton frame].size.height > greatestHeight)
greatestHeight = [popupButton frame].size.height;
float totalViewHeight = greatestHeight + kAccessoryViewPadding * 2;
float totalViewWidth = [textField frame].size.width + [popupButton frame].size.width + kAccessoryViewPadding * 3;
[accessoryView setFrameSize:NSMakeSize(totalViewWidth, totalViewHeight)];
float textFieldOriginY = ((greatestHeight - [textField frame].size.height) / 2 + 1) + kAccessoryViewPadding;
[textField setFrameOrigin:NSMakePoint(kAccessoryViewPadding, textFieldOriginY)];
float popupOriginX = [textField frame].size.width + kAccessoryViewPadding * 2;
float popupOriginY = ((greatestHeight - [popupButton frame].size.height) / 2) + kAccessoryViewPadding;
[popupButton setFrameOrigin:NSMakePoint(popupOriginX, popupOriginY)];
[accessoryView addSubview:textField];
[accessoryView addSubview:popupButton];
return accessoryView;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
// Display the file dialog
NS_IMETHODIMP nsFilePicker::Show(int16_t *retval)
{
NS_ENSURE_ARG_POINTER(retval);
*retval = returnCancel;
int16_t userClicksOK = returnCancel;
// Random questions from DHH:
//
// Why do we pass mTitle, mDefault to the functions? Can GetLocalFile. PutLocalFile,
// and GetLocalFolder get called someplace else? It generates a bunch of warnings
// as it is right now.
//
// I think we could easily combine GetLocalFile and GetLocalFolder together, just
// setting panel pick options based on mMode. I didn't do it here b/c I wanted to
// make this look as much like Carbon nsFilePicker as possible.
mFiles.Clear();
nsCOMPtr<nsIFile> theFile;
switch (mMode)
{
case modeOpen:
userClicksOK = GetLocalFiles(mTitle, false, mFiles);
break;
case modeOpenMultiple:
userClicksOK = GetLocalFiles(mTitle, true, mFiles);
break;
case modeSave:
userClicksOK = PutLocalFile(mTitle, mDefault, getter_AddRefs(theFile));
break;
case modeGetFolder:
userClicksOK = GetLocalFolder(mTitle, getter_AddRefs(theFile));
break;
default:
NS_ERROR("Unknown file picker mode");
break;
}
if (theFile)
mFiles.AppendObject(theFile);
*retval = userClicksOK;
return NS_OK;
}
static
void UpdatePanelFileTypes(NSOpenPanel* aPanel, NSArray* aFilters)
{
// If we show all file types, also "expose" bundles' contents.
[aPanel setTreatsFilePackagesAsDirectories:!aFilters];
[aPanel setAllowedFileTypes:aFilters];
}
@implementation NSPopUpButtonObserver
- (void) setPopUpButton:(NSPopUpButton*)aPopUpButton
{
mPopUpButton = aPopUpButton;
}
- (void) setOpenPanel:(NSOpenPanel*)aOpenPanel
{
mOpenPanel = aOpenPanel;
}
- (void) setFilePicker:(nsFilePicker*)aFilePicker
{
mFilePicker = aFilePicker;
}
- (void) menuChangedItem:(NSNotification *)aSender
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
int32_t selectedItem = [mPopUpButton indexOfSelectedItem];
if (selectedItem < 0) {
return;
}
mFilePicker->SetFilterIndex(selectedItem);
UpdatePanelFileTypes(mOpenPanel, mFilePicker->GetFilterList());
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN();
}
@end
// Use OpenPanel to do a GetFile. Returns |returnOK| if the user presses OK in the dialog.
int16_t
nsFilePicker::GetLocalFiles(const nsString& inTitle, bool inAllowMultiple, nsCOMArray<nsIFile>& outFiles)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
int16_t retVal = (int16_t)returnCancel;
NSOpenPanel *thePanel = [NSOpenPanel openPanel];
SetShowHiddenFileState(thePanel);
// Set the options for how the get file dialog will appear
SetDialogTitle(inTitle, thePanel);
[thePanel setAllowsMultipleSelection:inAllowMultiple];
[thePanel setCanSelectHiddenExtension:YES];
[thePanel setCanChooseDirectories:NO];
[thePanel setCanChooseFiles:YES];
[thePanel setResolvesAliases:YES]; //this is default - probably doesn't need to be set
// Get filters
// filters may be null, if we should allow all file types.
NSArray *filters = GetFilterList();
// set up default directory
NSString *theDir = PanelDefaultDirectory();
// if this is the "Choose application..." dialog, and no other start
// dir has been set, then use the Applications folder.
if (!theDir) {
if (filters && [filters count] == 1 &&
[(NSString *)[filters objectAtIndex:0] isEqualToString:@"app"])
theDir = @"/Applications/";
else
theDir = @"";
}
if (theDir) {
[thePanel setDirectoryURL:[NSURL fileURLWithPath:theDir isDirectory:YES]];
}
int result;
nsCocoaUtils::PrepareForNativeAppModalDialog();
if (mFilters.Length() > 1) {
// [NSURL initWithString:] (below) throws an exception if URLString is nil.
NSPopUpButtonObserver* observer = [[NSPopUpButtonObserver alloc] init];
NSView* accessoryView = GetAccessoryView();
[thePanel setAccessoryView:accessoryView];
[observer setPopUpButton:[accessoryView viewWithTag:kSaveTypeControlTag]];
[observer setOpenPanel:thePanel];
[observer setFilePicker:this];
[[NSNotificationCenter defaultCenter]
addObserver:observer
selector:@selector(menuChangedItem:)
name:NSMenuWillSendActionNotification object:nil];
UpdatePanelFileTypes(thePanel, filters);
result = [thePanel runModal];
[[NSNotificationCenter defaultCenter] removeObserver:observer];
[observer release];
} else {
// If we show all file types, also "expose" bundles' contents.
if (!filters) {
[thePanel setTreatsFilePackagesAsDirectories:YES];
}
[thePanel setAllowedFileTypes:filters];
result = [thePanel runModal];
}
nsCocoaUtils::CleanUpAfterNativeAppModalDialog();
if (result == NSFileHandlingPanelCancelButton)
return retVal;
// Converts data from a NSArray of NSURL to the returned format.
// We should be careful to not call [thePanel URLs] more than once given that
// it creates a new array each time.
// We are using Fast Enumeration, thus the NSURL array is created once then
// iterated.
for (NSURL* url in [thePanel URLs]) {
if (!url) {
continue;
}
nsCOMPtr<nsIFile> localFile;
NS_NewLocalFile(EmptyString(), true, getter_AddRefs(localFile));
nsCOMPtr<nsILocalFileMac> macLocalFile = do_QueryInterface(localFile);
if (macLocalFile && NS_SUCCEEDED(macLocalFile->InitWithCFURL((CFURLRef)url))) {
outFiles.AppendObject(localFile);
}
}
if (outFiles.Count() > 0)
retVal = returnOK;
return retVal;
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0);
}
// Use OpenPanel to do a GetFolder. Returns |returnOK| if the user presses OK in the dialog.
int16_t
nsFilePicker::GetLocalFolder(const nsString& inTitle, nsIFile** outFile)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
NS_ASSERTION(outFile, "this protected member function expects a null initialized out pointer");
int16_t retVal = (int16_t)returnCancel;
NSOpenPanel *thePanel = [NSOpenPanel openPanel];
SetShowHiddenFileState(thePanel);
// Set the options for how the get file dialog will appear
SetDialogTitle(inTitle, thePanel);
[thePanel setAllowsMultipleSelection:NO]; //this is default -probably doesn't need to be set
[thePanel setCanSelectHiddenExtension:YES];
[thePanel setCanChooseDirectories:YES];
[thePanel setCanChooseFiles:NO];
[thePanel setResolvesAliases:YES]; //this is default - probably doesn't need to be set
[thePanel setCanCreateDirectories:YES];
// packages != folders
[thePanel setTreatsFilePackagesAsDirectories:NO];
// set up default directory
NSString *theDir = PanelDefaultDirectory();
if (theDir) {
[thePanel setDirectoryURL:[NSURL fileURLWithPath:theDir isDirectory:YES]];
}
nsCocoaUtils::PrepareForNativeAppModalDialog();
int result = [thePanel runModal];
nsCocoaUtils::CleanUpAfterNativeAppModalDialog();
if (result == NSFileHandlingPanelCancelButton)
return retVal;
// get the path for the folder (we allow just 1, so that's all we get)
NSURL *theURL = [[thePanel URLs] objectAtIndex:0];
if (theURL) {
nsCOMPtr<nsIFile> localFile;
NS_NewLocalFile(EmptyString(), true, getter_AddRefs(localFile));
nsCOMPtr<nsILocalFileMac> macLocalFile = do_QueryInterface(localFile);
if (macLocalFile && NS_SUCCEEDED(macLocalFile->InitWithCFURL((CFURLRef)theURL))) {
*outFile = localFile;
NS_ADDREF(*outFile);
retVal = returnOK;
}
}
return retVal;
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0);
}
// Returns |returnOK| if the user presses OK in the dialog.
int16_t
nsFilePicker::PutLocalFile(const nsString& inTitle, const nsString& inDefaultName, nsIFile** outFile)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
NS_ASSERTION(outFile, "this protected member function expects a null initialized out pointer");
int16_t retVal = returnCancel;
NSSavePanel *thePanel = [NSSavePanel savePanel];
SetShowHiddenFileState(thePanel);
SetDialogTitle(inTitle, thePanel);
// set up accessory view for file format options
NSView* accessoryView = GetAccessoryView();
[thePanel setAccessoryView:accessoryView];
// set up default file name
NSString* defaultFilename = [NSString stringWithCharacters:(const unichar*)inDefaultName.get() length:inDefaultName.Length()];
// set up allowed types; this prevents the extension from being selected
// use the UTI for the file type to allow alternate extensions (e.g., jpg vs. jpeg)
NSString* extension = defaultFilename.pathExtension;
if (extension.length != 0) {
CFStringRef type = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (CFStringRef)extension, NULL);
if (type) {
thePanel.allowedFileTypes = @[(NSString*)type];
CFRelease(type);
} else {
// if there's no UTI for the file extension, use the extension itself.
thePanel.allowedFileTypes = @[extension];
}
}
// Allow users to change the extension.
thePanel.allowsOtherFileTypes = YES;
// set up default directory
NSString *theDir = PanelDefaultDirectory();
if (theDir) {
[thePanel setDirectoryURL:[NSURL fileURLWithPath:theDir isDirectory:YES]];
}
// load the panel
nsCocoaUtils::PrepareForNativeAppModalDialog();
[thePanel setNameFieldStringValue:defaultFilename];
int result = [thePanel runModal];
nsCocoaUtils::CleanUpAfterNativeAppModalDialog();
if (result == NSFileHandlingPanelCancelButton)
return retVal;
// get the save type
NSPopUpButton* popupButton = [accessoryView viewWithTag:kSaveTypeControlTag];
if (popupButton) {
mSelectedTypeIndex = [popupButton indexOfSelectedItem];
}
NSURL* fileURL = [thePanel URL];
if (fileURL) {
nsCOMPtr<nsIFile> localFile;
NS_NewLocalFile(EmptyString(), true, getter_AddRefs(localFile));
nsCOMPtr<nsILocalFileMac> macLocalFile = do_QueryInterface(localFile);
if (macLocalFile && NS_SUCCEEDED(macLocalFile->InitWithCFURL((CFURLRef)fileURL))) {
*outFile = localFile;
NS_ADDREF(*outFile);
// We tell if we are replacing or not by just looking to see if the file exists.
// The user could not have hit OK and not meant to replace the file.
if ([[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]])
retVal = returnReplace;
else
retVal = returnOK;
}
}
return retVal;
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0);
}
NSArray *
nsFilePicker::GetFilterList()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if (!mFilters.Length()) {
return nil;
}
if (mFilters.Length() <= (uint32_t)mSelectedTypeIndex) {
NS_WARNING("An out of range index has been selected. Using the first index instead.");
mSelectedTypeIndex = 0;
}
const nsString& filterWide = mFilters[mSelectedTypeIndex];
if (!filterWide.Length()) {
return nil;
}
if (filterWide.Equals(NS_LITERAL_STRING("*"))) {
return nil;
}
// The extensions in filterWide are in the format "*.ext" but are expected
// in the format "ext" by NSOpenPanel. So we need to filter some characters.
NSMutableString* filterString = [[[NSMutableString alloc] initWithString:
[NSString stringWithCharacters:reinterpret_cast<const unichar*>(filterWide.get())
length:filterWide.Length()]] autorelease];
NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:@". *"];
NSRange range = [filterString rangeOfCharacterFromSet:set];
while (range.length) {
[filterString replaceCharactersInRange:range withString:@""];
range = [filterString rangeOfCharacterFromSet:set];
}
return [[[NSArray alloc] initWithArray:
[filterString componentsSeparatedByString:@";"]] autorelease];
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
// Sets the dialog title to whatever it should be. If it fails, eh,
// the OS will provide a sensible default.
void
nsFilePicker::SetDialogTitle(const nsString& inTitle, id aPanel)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
[aPanel setTitle:[NSString stringWithCharacters:(const unichar*)inTitle.get() length:inTitle.Length()]];
if (!mOkButtonLabel.IsEmpty()) {
[aPanel setPrompt:[NSString stringWithCharacters:(const unichar*)mOkButtonLabel.get() length:mOkButtonLabel.Length()]];
}
NS_OBJC_END_TRY_ABORT_BLOCK;
}
// Converts path from an nsIFile into a NSString path
// If it fails, returns an empty string.
NSString *
nsFilePicker::PanelDefaultDirectory()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
NSString *directory = nil;
if (mDisplayDirectory) {
nsAutoString pathStr;
mDisplayDirectory->GetPath(pathStr);
directory = [[[NSString alloc] initWithCharacters:reinterpret_cast<const unichar*>(pathStr.get())
length:pathStr.Length()] autorelease];
}
return directory;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
NS_IMETHODIMP nsFilePicker::GetFile(nsIFile **aFile)
{
NS_ENSURE_ARG_POINTER(aFile);
*aFile = nullptr;
// just return the first file
if (mFiles.Count() > 0) {
*aFile = mFiles.ObjectAt(0);
NS_IF_ADDREF(*aFile);
}
return NS_OK;
}
NS_IMETHODIMP nsFilePicker::GetFileURL(nsIURI **aFileURL)
{
NS_ENSURE_ARG_POINTER(aFileURL);
*aFileURL = nullptr;
if (mFiles.Count() == 0)
return NS_OK;
return NS_NewFileURI(aFileURL, mFiles.ObjectAt(0));
}
NS_IMETHODIMP nsFilePicker::GetFiles(nsISimpleEnumerator **aFiles)
{
return NS_NewArrayEnumerator(aFiles, mFiles);
}
NS_IMETHODIMP nsFilePicker::SetDefaultString(const nsAString& aString)
{
mDefault = aString;
return NS_OK;
}
NS_IMETHODIMP nsFilePicker::GetDefaultString(nsAString& aString)
{
return NS_ERROR_FAILURE;
}
// The default extension to use for files
NS_IMETHODIMP nsFilePicker::GetDefaultExtension(nsAString& aExtension)
{
aExtension.Truncate();
return NS_OK;
}
NS_IMETHODIMP nsFilePicker::SetDefaultExtension(const nsAString& aExtension)
{
return NS_OK;
}
// Append an entry to the filters array
NS_IMETHODIMP
nsFilePicker::AppendFilter(const nsAString& aTitle, const nsAString& aFilter)
{
// "..apps" has to be translated with native executable extensions.
if (aFilter.EqualsLiteral("..apps")) {
mFilters.AppendElement(NS_LITERAL_STRING("*.app"));
} else {
mFilters.AppendElement(aFilter);
}
mTitles.AppendElement(aTitle);
return NS_OK;
}
// Get the filter index - do we still need this?
NS_IMETHODIMP nsFilePicker::GetFilterIndex(int32_t *aFilterIndex)
{
*aFilterIndex = mSelectedTypeIndex;
return NS_OK;
}
// Set the filter index - do we still need this?
NS_IMETHODIMP nsFilePicker::SetFilterIndex(int32_t aFilterIndex)
{
mSelectedTypeIndex = aFilterIndex;
return NS_OK;
}
-33
View File
@@ -1,33 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsIdleServiceX_h_
#define nsIdleServiceX_h_
#include "nsIdleService.h"
class nsIdleServiceX : public nsIdleService
{
public:
NS_DECL_ISUPPORTS_INHERITED
bool PollIdleTime(uint32_t* aIdleTime) override;
static already_AddRefed<nsIdleServiceX> GetInstance()
{
RefPtr<nsIdleService> idleService = nsIdleService::GetInstance();
if (!idleService) {
idleService = new nsIdleServiceX();
}
return idleService.forget().downcast<nsIdleServiceX>();
}
protected:
nsIdleServiceX() { }
virtual ~nsIdleServiceX() { }
bool UsePollMode() override;
};
#endif // nsIdleServiceX_h_
-77
View File
@@ -1,77 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsIdleServiceX.h"
#include "nsObjCExceptions.h"
#include "nsIServiceManager.h"
#import <Foundation/Foundation.h>
NS_IMPL_ISUPPORTS_INHERITED0(nsIdleServiceX, nsIdleService)
bool
nsIdleServiceX::PollIdleTime(uint32_t *aIdleTime)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
kern_return_t rval;
mach_port_t masterPort;
rval = IOMasterPort(kIOMasterPortDefault, &masterPort);
if (rval != KERN_SUCCESS)
return false;
io_iterator_t hidItr;
rval = IOServiceGetMatchingServices(masterPort,
IOServiceMatching("IOHIDSystem"),
&hidItr);
if (rval != KERN_SUCCESS)
return false;
NS_ASSERTION(hidItr, "Our iterator is null, but it ought not to be!");
io_registry_entry_t entry = IOIteratorNext(hidItr);
NS_ASSERTION(entry, "Our IO Registry Entry is null, but it shouldn't be!");
IOObjectRelease(hidItr);
NSMutableDictionary *hidProps;
rval = IORegistryEntryCreateCFProperties(entry,
(CFMutableDictionaryRef*)&hidProps,
kCFAllocatorDefault, 0);
if (rval != KERN_SUCCESS)
return false;
NS_ASSERTION(hidProps, "HIDProperties is null, but no error was returned.");
[hidProps autorelease];
id idleObj = [hidProps objectForKey:@"HIDIdleTime"];
NS_ASSERTION([idleObj isKindOfClass: [NSData class]] ||
[idleObj isKindOfClass: [NSNumber class]],
"What we got for the idle object is not what we expect!");
uint64_t time;
if ([idleObj isKindOfClass: [NSData class]])
[idleObj getBytes: &time];
else
time = [idleObj unsignedLongLongValue];
IOObjectRelease(entry);
// convert to ms from ns
time /= 1000000;
if (time > UINT32_MAX) // Overflow will occur
return false;
*aIdleTime = static_cast<uint32_t>(time);
return true;
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
}
bool
nsIdleServiceX::UsePollMode()
{
return true;
}
-46
View File
@@ -1,46 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsLookAndFeel_h_
#define nsLookAndFeel_h_
#include "nsXPLookAndFeel.h"
class nsLookAndFeel: public nsXPLookAndFeel {
public:
nsLookAndFeel();
virtual ~nsLookAndFeel();
virtual nsresult NativeGetColor(ColorID aID, nscolor &aResult);
virtual nsresult GetIntImpl(IntID aID, int32_t &aResult);
virtual nsresult GetFloatImpl(FloatID aID, float &aResult);
virtual bool GetFontImpl(FontID aID, nsString& aFontName,
gfxFontStyle& aFontStyle,
float aDevPixPerCSSPixel);
virtual char16_t GetPasswordCharacterImpl()
{
// unicode value for the bullet character, used for password textfields.
return 0x2022;
}
static bool UseOverlayScrollbars();
virtual nsTArray<LookAndFeelInt> GetIntCacheImpl();
virtual void SetIntCacheImpl(const nsTArray<LookAndFeelInt>& aLookAndFeelIntCache);
virtual void RefreshImpl();
protected:
static bool SystemWantsOverlayScrollbars();
static bool AllowOverlayScrollbarsOverlap();
private:
int32_t mUseOverlayScrollbars;
bool mUseOverlayScrollbarsCached;
int32_t mAllowOverlayScrollbarsOverlap;
bool mAllowOverlayScrollbarsOverlapCached;
};
#endif // nsLookAndFeel_h_
-584
View File
@@ -1,584 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsLookAndFeel.h"
#include "nsCocoaFeatures.h"
#include "nsIServiceManager.h"
#include "nsNativeThemeColors.h"
#include "nsStyleConsts.h"
#include "nsCocoaFeatures.h"
#include "nsIContent.h"
#include "gfxFont.h"
#include "gfxFontConstants.h"
#include "gfxPlatformMac.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/widget/WidgetMessageUtils.h"
#import <Cocoa/Cocoa.h>
// This must be included last:
#include "nsObjCExceptions.h"
enum {
mozNSScrollerStyleLegacy = 0,
mozNSScrollerStyleOverlay = 1
};
typedef NSInteger mozNSScrollerStyle;
@interface NSScroller(AvailableSinceLion)
+ (mozNSScrollerStyle)preferredScrollerStyle;
@end
nsLookAndFeel::nsLookAndFeel()
: nsXPLookAndFeel()
, mUseOverlayScrollbars(-1)
, mUseOverlayScrollbarsCached(false)
, mAllowOverlayScrollbarsOverlap(-1)
, mAllowOverlayScrollbarsOverlapCached(false)
{
}
nsLookAndFeel::~nsLookAndFeel()
{
}
static nscolor GetColorFromNSColor(NSColor* aColor)
{
NSColor* deviceColor = [aColor colorUsingColorSpaceName:NSDeviceRGBColorSpace];
return NS_RGB((unsigned int)([deviceColor redComponent] * 255.0),
(unsigned int)([deviceColor greenComponent] * 255.0),
(unsigned int)([deviceColor blueComponent] * 255.0));
}
static nscolor GetColorFromNSColorWithAlpha(NSColor* aColor, float alpha)
{
NSColor* deviceColor = [aColor colorUsingColorSpaceName:NSDeviceRGBColorSpace];
return NS_RGBA((unsigned int)([deviceColor redComponent] * 255.0),
(unsigned int)([deviceColor greenComponent] * 255.0),
(unsigned int)([deviceColor blueComponent] * 255.0),
(unsigned int)(alpha * 255.0));
}
nsresult
nsLookAndFeel::NativeGetColor(ColorID aID, nscolor &aColor)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
nsresult res = NS_OK;
switch (aID) {
case eColorID_WindowBackground:
aColor = NS_RGB(0xff,0xff,0xff);
break;
case eColorID_WindowForeground:
aColor = NS_RGB(0x00,0x00,0x00);
break;
case eColorID_WidgetBackground:
aColor = NS_RGB(0xdd,0xdd,0xdd);
break;
case eColorID_WidgetForeground:
aColor = NS_RGB(0x00,0x00,0x00);
break;
case eColorID_WidgetSelectBackground:
aColor = NS_RGB(0x80,0x80,0x80);
break;
case eColorID_WidgetSelectForeground:
aColor = NS_RGB(0x00,0x00,0x80);
break;
case eColorID_Widget3DHighlight:
aColor = NS_RGB(0xa0,0xa0,0xa0);
break;
case eColorID_Widget3DShadow:
aColor = NS_RGB(0x40,0x40,0x40);
break;
case eColorID_TextBackground:
aColor = NS_RGB(0xff,0xff,0xff);
break;
case eColorID_TextForeground:
aColor = NS_RGB(0x00,0x00,0x00);
break;
case eColorID_TextSelectBackground:
aColor = GetColorFromNSColor([NSColor selectedTextBackgroundColor]);
break;
case eColorID_highlight: // CSS2 color
aColor = GetColorFromNSColor([NSColor alternateSelectedControlColor]);
break;
case eColorID__moz_menuhover:
aColor = GetColorFromNSColor([NSColor alternateSelectedControlColor]);
break;
case eColorID_TextSelectForeground:
GetColor(eColorID_TextSelectBackground, aColor);
if (aColor == 0x000000)
aColor = NS_RGB(0xff,0xff,0xff);
else
aColor = NS_DONT_CHANGE_COLOR;
break;
case eColorID_highlighttext: // CSS2 color
case eColorID__moz_menuhovertext:
aColor = GetColorFromNSColor([NSColor alternateSelectedControlTextColor]);
break;
case eColorID_IMESelectedRawTextBackground:
case eColorID_IMESelectedConvertedTextBackground:
case eColorID_IMERawInputBackground:
case eColorID_IMEConvertedTextBackground:
aColor = NS_TRANSPARENT;
break;
case eColorID_IMESelectedRawTextForeground:
case eColorID_IMESelectedConvertedTextForeground:
case eColorID_IMERawInputForeground:
case eColorID_IMEConvertedTextForeground:
aColor = NS_SAME_AS_FOREGROUND_COLOR;
break;
case eColorID_IMERawInputUnderline:
case eColorID_IMEConvertedTextUnderline:
aColor = NS_40PERCENT_FOREGROUND_COLOR;
break;
case eColorID_IMESelectedRawTextUnderline:
case eColorID_IMESelectedConvertedTextUnderline:
aColor = NS_SAME_AS_FOREGROUND_COLOR;
break;
case eColorID_SpellCheckerUnderline:
aColor = NS_RGB(0xff, 0, 0);
break;
//
// css2 system colors http://www.w3.org/TR/REC-CSS2/ui.html#system-colors
//
// It's really hard to effectively map these to the Appearance Manager properly,
// since they are modeled word for word after the win32 system colors and don't have any
// real counterparts in the Mac world. I'm sure we'll be tweaking these for
// years to come.
//
// Thanks to mpt26@student.canterbury.ac.nz for the hardcoded values that form the defaults
// if querying the Appearance Manager fails ;)
//
case eColorID__moz_mac_buttonactivetext:
case eColorID__moz_mac_defaultbuttontext:
if (nsCocoaFeatures::OnYosemiteOrLater()) {
aColor = NS_RGB(0xFF,0xFF,0xFF);
break;
}
// Otherwise fall through and return the regular button text:
case eColorID_buttontext:
case eColorID__moz_buttonhovertext:
aColor = GetColorFromNSColor([NSColor controlTextColor]);
break;
case eColorID_captiontext:
case eColorID_menutext:
case eColorID_infotext:
case eColorID__moz_menubartext:
aColor = GetColorFromNSColor([NSColor textColor]);
break;
case eColorID_windowtext:
aColor = GetColorFromNSColor([NSColor windowFrameTextColor]);
break;
case eColorID_activecaption:
aColor = GetColorFromNSColor([NSColor gridColor]);
break;
case eColorID_activeborder:
aColor = GetColorFromNSColor([NSColor keyboardFocusIndicatorColor]);
break;
case eColorID_appworkspace:
aColor = NS_RGB(0xFF,0xFF,0xFF);
break;
case eColorID_background:
aColor = NS_RGB(0x63,0x63,0xCE);
break;
case eColorID_buttonface:
case eColorID__moz_buttonhoverface:
aColor = NS_RGB(0xF0,0xF0,0xF0);
break;
case eColorID_buttonhighlight:
aColor = NS_RGB(0xFF,0xFF,0xFF);
break;
case eColorID_buttonshadow:
aColor = NS_RGB(0xDC,0xDC,0xDC);
break;
case eColorID_graytext:
aColor = GetColorFromNSColor([NSColor disabledControlTextColor]);
break;
case eColorID_inactiveborder:
aColor = GetColorFromNSColor([NSColor controlBackgroundColor]);
break;
case eColorID_inactivecaption:
aColor = GetColorFromNSColor([NSColor controlBackgroundColor]);
break;
case eColorID_inactivecaptiontext:
aColor = NS_RGB(0x45,0x45,0x45);
break;
case eColorID_scrollbar:
aColor = GetColorFromNSColor([NSColor scrollBarColor]);
break;
case eColorID_threeddarkshadow:
aColor = NS_RGB(0xDC,0xDC,0xDC);
break;
case eColorID_threedshadow:
aColor = NS_RGB(0xE0,0xE0,0xE0);
break;
case eColorID_threedface:
aColor = NS_RGB(0xF0,0xF0,0xF0);
break;
case eColorID_threedhighlight:
aColor = GetColorFromNSColor([NSColor highlightColor]);
break;
case eColorID_threedlightshadow:
aColor = NS_RGB(0xDA,0xDA,0xDA);
break;
case eColorID_menu:
aColor = GetColorFromNSColor([NSColor alternateSelectedControlTextColor]);
break;
case eColorID_infobackground:
aColor = NS_RGB(0xFF,0xFF,0xC7);
break;
case eColorID_windowframe:
aColor = GetColorFromNSColor([NSColor gridColor]);
break;
case eColorID_window:
case eColorID__moz_field:
case eColorID__moz_combobox:
aColor = NS_RGB(0xff,0xff,0xff);
break;
case eColorID__moz_fieldtext:
case eColorID__moz_comboboxtext:
aColor = GetColorFromNSColor([NSColor controlTextColor]);
break;
case eColorID__moz_dialog:
aColor = GetColorFromNSColor([NSColor controlHighlightColor]);
break;
case eColorID__moz_dialogtext:
case eColorID__moz_cellhighlighttext:
case eColorID__moz_html_cellhighlighttext:
aColor = GetColorFromNSColor([NSColor controlTextColor]);
break;
case eColorID__moz_dragtargetzone:
aColor = GetColorFromNSColor([NSColor selectedControlColor]);
break;
case eColorID__moz_mac_chrome_active:
case eColorID__moz_mac_chrome_inactive: {
int grey = NativeGreyColorAsInt(toolbarFillGrey, (aID == eColorID__moz_mac_chrome_active));
aColor = NS_RGB(grey, grey, grey);
}
break;
case eColorID__moz_mac_focusring:
aColor = GetColorFromNSColorWithAlpha([NSColor keyboardFocusIndicatorColor], 0.48);
break;
case eColorID__moz_mac_menushadow:
aColor = NS_RGB(0xA3,0xA3,0xA3);
break;
case eColorID__moz_mac_menutextdisable:
aColor = NS_RGB(0x98,0x98,0x98);
break;
case eColorID__moz_mac_menutextselect:
aColor = GetColorFromNSColor([NSColor selectedMenuItemTextColor]);
break;
case eColorID__moz_mac_disabledtoolbartext:
aColor = GetColorFromNSColor([NSColor disabledControlTextColor]);
break;
case eColorID__moz_mac_menuselect:
aColor = GetColorFromNSColor([NSColor alternateSelectedControlColor]);
break;
case eColorID__moz_buttondefault:
aColor = NS_RGB(0xDC,0xDC,0xDC);
break;
case eColorID__moz_cellhighlight:
case eColorID__moz_html_cellhighlight:
case eColorID__moz_mac_secondaryhighlight:
// For inactive list selection
aColor = GetColorFromNSColor([NSColor secondarySelectedControlColor]);
break;
case eColorID__moz_eventreerow:
// Background color of even list rows.
aColor = GetColorFromNSColor([[NSColor controlAlternatingRowBackgroundColors] objectAtIndex:0]);
break;
case eColorID__moz_oddtreerow:
// Background color of odd list rows.
aColor = GetColorFromNSColor([[NSColor controlAlternatingRowBackgroundColors] objectAtIndex:1]);
break;
case eColorID__moz_nativehyperlinktext:
// There appears to be no available system defined color. HARDCODING to the appropriate color.
aColor = NS_RGB(0x14,0x4F,0xAE);
break;
default:
NS_WARNING("Someone asked nsILookAndFeel for a color I don't know about");
aColor = NS_RGB(0xff,0xff,0xff);
res = NS_ERROR_FAILURE;
break;
}
return res;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
nsresult
nsLookAndFeel::GetIntImpl(IntID aID, int32_t &aResult)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
nsresult res = nsXPLookAndFeel::GetIntImpl(aID, aResult);
if (NS_SUCCEEDED(res))
return res;
res = NS_OK;
switch (aID) {
case eIntID_CaretBlinkTime:
aResult = 567;
break;
case eIntID_CaretWidth:
aResult = 1;
break;
case eIntID_ShowCaretDuringSelection:
aResult = 0;
break;
case eIntID_SelectTextfieldsOnKeyFocus:
// Select textfield content when focused by kbd
// used by EventStateManager::sTextfieldSelectModel
aResult = 1;
break;
case eIntID_SubmenuDelay:
aResult = 200;
break;
case eIntID_TooltipDelay:
aResult = 500;
break;
case eIntID_MenusCanOverlapOSBar:
// xul popups are not allowed to overlap the menubar.
aResult = 0;
break;
case eIntID_SkipNavigatingDisabledMenuItem:
aResult = 1;
break;
case eIntID_DragThresholdX:
case eIntID_DragThresholdY:
aResult = 4;
break;
case eIntID_ScrollArrowStyle:
aResult = eScrollArrow_None;
break;
case eIntID_ScrollSliderStyle:
aResult = eScrollThumbStyle_Proportional;
break;
case eIntID_UseOverlayScrollbars:
if (!mUseOverlayScrollbarsCached) {
mUseOverlayScrollbars = SystemWantsOverlayScrollbars() ? 1 : 0;
mUseOverlayScrollbarsCached = true;
}
aResult = mUseOverlayScrollbars;
break;
case eIntID_AllowOverlayScrollbarsOverlap:
if (!mAllowOverlayScrollbarsOverlapCached) {
mAllowOverlayScrollbarsOverlap = AllowOverlayScrollbarsOverlap() ? 1 : 0;
mAllowOverlayScrollbarsOverlapCached = true;
}
aResult = mAllowOverlayScrollbarsOverlap;
break;
case eIntID_ScrollbarDisplayOnMouseMove:
aResult = 0;
break;
case eIntID_ScrollbarFadeBeginDelay:
aResult = 450;
break;
case eIntID_ScrollbarFadeDuration:
aResult = 200;
break;
case eIntID_TreeOpenDelay:
aResult = 1000;
break;
case eIntID_TreeCloseDelay:
aResult = 1000;
break;
case eIntID_TreeLazyScrollDelay:
aResult = 150;
break;
case eIntID_TreeScrollDelay:
aResult = 100;
break;
case eIntID_TreeScrollLinesMax:
aResult = 3;
break;
case eIntID_DWMCompositor:
case eIntID_WindowsClassic:
case eIntID_WindowsDefaultTheme:
case eIntID_TouchEnabled:
case eIntID_WindowsThemeIdentifier:
case eIntID_OperatingSystemVersionIdentifier:
aResult = 0;
res = NS_ERROR_NOT_IMPLEMENTED;
break;
case eIntID_MacGraphiteTheme:
aResult = [NSColor currentControlTint] == NSGraphiteControlTint;
break;
case eIntID_MacLionTheme:
aResult = 1;
break;
case eIntID_MacYosemiteTheme:
aResult = nsCocoaFeatures::OnYosemiteOrLater();
break;
case eIntID_AlertNotificationOrigin:
aResult = NS_ALERT_TOP;
break;
case eIntID_TabFocusModel:
aResult = [NSApp isFullKeyboardAccessEnabled] ?
nsIContent::eTabFocus_any : nsIContent::eTabFocus_textControlsMask;
break;
case eIntID_ScrollToClick:
{
aResult = [[NSUserDefaults standardUserDefaults] boolForKey:@"AppleScrollerPagingBehavior"];
}
break;
case eIntID_ChosenMenuItemsShouldBlink:
aResult = 1;
break;
case eIntID_IMERawInputUnderlineStyle:
case eIntID_IMEConvertedTextUnderlineStyle:
case eIntID_IMESelectedRawTextUnderlineStyle:
case eIntID_IMESelectedConvertedTextUnderline:
aResult = NS_STYLE_TEXT_DECORATION_STYLE_SOLID;
break;
case eIntID_SpellCheckerUnderlineStyle:
aResult = NS_STYLE_TEXT_DECORATION_STYLE_DOTTED;
break;
case eIntID_ScrollbarButtonAutoRepeatBehavior:
aResult = 0;
break;
case eIntID_SwipeAnimationEnabled:
aResult = 0;
if ([NSEvent respondsToSelector:@selector(
isSwipeTrackingFromScrollEventsEnabled)]) {
aResult = [NSEvent isSwipeTrackingFromScrollEventsEnabled] ? 1 : 0;
}
break;
case eIntID_ColorPickerAvailable:
aResult = 1;
break;
case eIntID_ContextMenuOffsetVertical:
aResult = -6;
break;
case eIntID_ContextMenuOffsetHorizontal:
aResult = 1;
break;
default:
aResult = 0;
res = NS_ERROR_FAILURE;
}
return res;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
nsresult
nsLookAndFeel::GetFloatImpl(FloatID aID, float &aResult)
{
nsresult res = nsXPLookAndFeel::GetFloatImpl(aID, aResult);
if (NS_SUCCEEDED(res))
return res;
res = NS_OK;
switch (aID) {
case eFloatID_IMEUnderlineRelativeSize:
aResult = 2.0f;
break;
case eFloatID_SpellCheckerUnderlineRelativeSize:
aResult = 2.0f;
break;
default:
aResult = -1.0;
res = NS_ERROR_FAILURE;
}
return res;
}
bool nsLookAndFeel::UseOverlayScrollbars()
{
return GetInt(eIntID_UseOverlayScrollbars) != 0;
}
bool nsLookAndFeel::SystemWantsOverlayScrollbars()
{
return ([NSScroller respondsToSelector:@selector(preferredScrollerStyle)] &&
[NSScroller preferredScrollerStyle] == mozNSScrollerStyleOverlay);
}
bool nsLookAndFeel::AllowOverlayScrollbarsOverlap()
{
return (UseOverlayScrollbars());
}
bool
nsLookAndFeel::GetFontImpl(FontID aID, nsString &aFontName,
gfxFontStyle &aFontStyle,
float aDevPixPerCSSPixel)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
// hack for now
if (aID == eFont_Window || aID == eFont_Document) {
aFontStyle.style = NS_FONT_STYLE_NORMAL;
aFontStyle.weight = NS_FONT_WEIGHT_NORMAL;
aFontStyle.stretch = NS_FONT_STRETCH_NORMAL;
aFontStyle.size = 14 * aDevPixPerCSSPixel;
aFontStyle.systemFont = true;
aFontName.AssignLiteral("sans-serif");
return true;
}
gfxPlatformMac::LookupSystemFont(aID, aFontName, aFontStyle,
aDevPixPerCSSPixel);
return true;
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
}
nsTArray<LookAndFeelInt>
nsLookAndFeel::GetIntCacheImpl()
{
nsTArray<LookAndFeelInt> lookAndFeelIntCache =
nsXPLookAndFeel::GetIntCacheImpl();
LookAndFeelInt useOverlayScrollbars;
useOverlayScrollbars.id = eIntID_UseOverlayScrollbars;
useOverlayScrollbars.value = GetInt(eIntID_UseOverlayScrollbars);
lookAndFeelIntCache.AppendElement(useOverlayScrollbars);
LookAndFeelInt allowOverlayScrollbarsOverlap;
allowOverlayScrollbarsOverlap.id = eIntID_AllowOverlayScrollbarsOverlap;
allowOverlayScrollbarsOverlap.value = GetInt(eIntID_AllowOverlayScrollbarsOverlap);
lookAndFeelIntCache.AppendElement(allowOverlayScrollbarsOverlap);
return lookAndFeelIntCache;
}
void
nsLookAndFeel::SetIntCacheImpl(const nsTArray<LookAndFeelInt>& aLookAndFeelIntCache)
{
for (auto entry : aLookAndFeelIntCache) {
switch(entry.id) {
case eIntID_UseOverlayScrollbars:
mUseOverlayScrollbars = entry.value;
mUseOverlayScrollbarsCached = true;
break;
case eIntID_AllowOverlayScrollbarsOverlap:
mAllowOverlayScrollbarsOverlap = entry.value;
mAllowOverlayScrollbarsOverlapCached = true;
break;
}
}
}
void
nsLookAndFeel::RefreshImpl()
{
// We should only clear the cache if we're in the main browser process.
// Otherwise, we should wait for the parent to inform us of new values
// to cache via LookAndFeel::SetIntCache.
if (XRE_IsParentProcess()) {
mUseOverlayScrollbarsCached = false;
mAllowOverlayScrollbarsOverlapCached = false;
}
}

Some files were not shown because too many files have changed in this diff Show More