diff --git a/application/palemoon/base/moz.build b/application/palemoon/base/moz.build index dfa89c7d30..c1470f25c9 100644 --- a/application/palemoon/base/moz.build +++ b/application/palemoon/base/moz.build @@ -6,11 +6,9 @@ DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION'] DEFINES['APP_LICENSE_BLOCK'] = '%s/content/overrides/app-license.html' % SRCDIR -if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3', 'cocoa'): +if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3'): DEFINES['HAVE_SHELL_SERVICE'] = 1 DEFINES['CONTEXT_COPY_IMAGE_CONTENTS'] = 1 - -if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3'): DEFINES['MENUBAR_CAN_AUTOHIDE'] = 1 JAR_MANIFESTS += ['jar.mn'] \ No newline at end of file diff --git a/application/palemoon/branding/shared/branding.mozbuild b/application/palemoon/branding/shared/branding.mozbuild index 284520add8..e253620d27 100644 --- a/application/palemoon/branding/shared/branding.mozbuild +++ b/application/palemoon/branding/shared/branding.mozbuild @@ -30,14 +30,6 @@ def ApplicationBranding(): 'wizHeaderRTL.bmp', 'wizWatermark.bmp', ] - elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': - BRANDING_FILES += [ - '../shared/background.png', - 'disk.icns', - 'document.icns', - 'dsstore', - 'firefox.icns', - ] elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: BRANDING_FILES += [ 'default16.png', diff --git a/application/palemoon/branding/unofficial/disk.icns b/application/palemoon/branding/unofficial/disk.icns deleted file mode 100644 index e97e490585..0000000000 Binary files a/application/palemoon/branding/unofficial/disk.icns and /dev/null differ diff --git a/application/palemoon/branding/unofficial/document.icns b/application/palemoon/branding/unofficial/document.icns deleted file mode 100644 index dd5f7aa892..0000000000 Binary files a/application/palemoon/branding/unofficial/document.icns and /dev/null differ diff --git a/application/palemoon/branding/unofficial/dsstore b/application/palemoon/branding/unofficial/dsstore deleted file mode 100644 index bbba9ecce0..0000000000 Binary files a/application/palemoon/branding/unofficial/dsstore and /dev/null differ diff --git a/application/palemoon/branding/unofficial/firefox.icns b/application/palemoon/branding/unofficial/firefox.icns deleted file mode 100644 index 117ddb1952..0000000000 Binary files a/application/palemoon/branding/unofficial/firefox.icns and /dev/null differ diff --git a/application/palemoon/components/build/moz.build b/application/palemoon/components/build/moz.build index ebacbec8f3..26f2d14237 100644 --- a/application/palemoon/components/build/moz.build +++ b/application/palemoon/components/build/moz.build @@ -29,7 +29,6 @@ if CONFIG['OS_ARCH'] == 'WINNT': 'netapi32.dll', ] -# Mac: Need to link with CoreFoundation for Mac Migrators (PList reading code) -# GTK2: Need to link with glib for GNOME shell service -if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('cocoa', 'gtk2', 'gtk3'): +# GTK: Need to link with glib for GNOME shell service +if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3'): OS_LIBS += CONFIG['TK_LIBS'] diff --git a/application/palemoon/components/preferences/moz.build b/application/palemoon/components/preferences/moz.build index 49b3c3d766..c888607f0f 100644 --- a/application/palemoon/components/preferences/moz.build +++ b/application/palemoon/components/preferences/moz.build @@ -7,7 +7,7 @@ for var in ('MOZ_APP_NAME', 'MOZ_MACBUNDLE_NAME'): DEFINES[var] = CONFIG[var] -if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3', 'cocoa'): +if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3'): DEFINES['HAVE_SHELL_SERVICE'] = 1 JAR_MANIFESTS += ['jar.mn'] \ No newline at end of file diff --git a/application/palemoon/components/shell/moz.build b/application/palemoon/components/shell/moz.build index 6e086f96d0..de34f17fb8 100644 --- a/application/palemoon/components/shell/moz.build +++ b/application/palemoon/components/shell/moz.build @@ -9,8 +9,6 @@ XPIDL_SOURCES += ['nsIShellService.idl'] if CONFIG['OS_ARCH'] == 'WINNT': XPIDL_SOURCES += ['nsIWindowsShellService.idl'] -elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': - XPIDL_SOURCES += ['nsIMacShellService.idl'] elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: XPIDL_SOURCES += ['nsIGNOMEShellService.idl'] @@ -18,8 +16,6 @@ XPIDL_MODULE = 'shellservice' if CONFIG['OS_ARCH'] == 'WINNT': SOURCES += ['nsWindowsShellService.cpp'] -elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': - SOURCES += ['nsMacShellService.cpp'] elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: SOURCES += ['nsGNOMEShellService.cpp'] diff --git a/application/palemoon/components/shell/nsIMacShellService.idl b/application/palemoon/components/shell/nsIMacShellService.idl deleted file mode 100644 index 6a532bbd0b..0000000000 --- a/application/palemoon/components/shell/nsIMacShellService.idl +++ /dev/null @@ -1,15 +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 "nsIShellService.idl" - -[scriptable, uuid(387fdc80-0077-4b60-a0d9-d9e80a83ba64)] -interface nsIMacShellService : nsIShellService -{ - const long APPLICATION_KEYCHAIN_ACCESS = 2; - const long APPLICATION_NETWORK = 3; - const long APPLICATION_DESKTOP = 4; -}; - diff --git a/application/palemoon/components/shell/nsMacShellService.cpp b/application/palemoon/components/shell/nsMacShellService.cpp deleted file mode 100644 index d8d64039d3..0000000000 --- a/application/palemoon/components/shell/nsMacShellService.cpp +++ /dev/null @@ -1,434 +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 "nsDirectoryServiceDefs.h" -#include "nsIDOMElement.h" -#include "nsIDOMHTMLImageElement.h" -#include "nsIImageLoadingContent.h" -#include "nsIDocument.h" -#include "nsIContent.h" -#include "nsILocalFileMac.h" -#include "nsIObserverService.h" -#include "nsIPrefService.h" -#include "nsIServiceManager.h" -#include "nsIStringBundle.h" -#include "nsIURL.h" -#include "nsIWebBrowserPersist.h" -#include "nsMacShellService.h" -#include "nsIProperties.h" -#include "nsServiceManagerUtils.h" -#include "nsShellService.h" -#include "nsStringAPI.h" -#include "nsIDocShell.h" -#include "nsILoadContext.h" - -#include -#include - -#define NETWORK_PREFPANE NS_LITERAL_CSTRING("/System/Library/PreferencePanes/Network.prefPane") -#define DESKTOP_PREFPANE NS_LITERAL_CSTRING("/System/Library/PreferencePanes/DesktopScreenEffectsPref.prefPane") - -#define SAFARI_BUNDLE_IDENTIFIER "com.apple.Safari" - -NS_IMPL_ISUPPORTS(nsMacShellService, nsIMacShellService, nsIShellService, nsIWebProgressListener) - -NS_IMETHODIMP -nsMacShellService::IsDefaultBrowser(bool aStartupCheck, - bool aForAllTypes, - bool* aIsDefaultBrowser) -{ - *aIsDefaultBrowser = false; - - CFStringRef firefoxID = ::CFBundleGetIdentifier(::CFBundleGetMainBundle()); - if (!firefoxID) { - // CFBundleGetIdentifier is expected to return nullptr only if the specified - // bundle doesn't have a bundle identifier in its plist. In this case, that - // means a failure, since our bundle does have an identifier. - return NS_ERROR_FAILURE; - } - - // Get the default http handler's bundle ID (or nullptr if it has not been - // explicitly set) - CFStringRef defaultBrowserID = ::LSCopyDefaultHandlerForURLScheme(CFSTR("http")); - if (defaultBrowserID) { - *aIsDefaultBrowser = ::CFStringCompare(firefoxID, defaultBrowserID, 0) == kCFCompareEqualTo; - ::CFRelease(defaultBrowserID); - } - - return NS_OK; -} - -NS_IMETHODIMP -nsMacShellService::SetDefaultBrowser(bool aClaimAllTypes, bool aForAllUsers) -{ - // Note: We don't support aForAllUsers on Mac OS X. - - CFStringRef firefoxID = ::CFBundleGetIdentifier(::CFBundleGetMainBundle()); - if (!firefoxID) { - return NS_ERROR_FAILURE; - } - - if (::LSSetDefaultHandlerForURLScheme(CFSTR("http"), firefoxID) != noErr) { - return NS_ERROR_FAILURE; - } - if (::LSSetDefaultHandlerForURLScheme(CFSTR("https"), firefoxID) != noErr) { - return NS_ERROR_FAILURE; - } - - if (aClaimAllTypes) { - if (::LSSetDefaultHandlerForURLScheme(CFSTR("ftp"), firefoxID) != noErr) { - return NS_ERROR_FAILURE; - } - if (::LSSetDefaultRoleHandlerForContentType(kUTTypeHTML, kLSRolesAll, firefoxID) != noErr) { - return NS_ERROR_FAILURE; - } - } - - nsCOMPtr prefs(do_GetService(NS_PREFSERVICE_CONTRACTID)); - if (prefs) { - (void) prefs->SetBoolPref(PREF_CHECKDEFAULTBROWSER, true); - // Reset the number of times the dialog should be shown - // before it is silenced. - (void) prefs->SetIntPref(PREF_DEFAULTBROWSERCHECKCOUNT, 0); - } - - return NS_OK; -} - -NS_IMETHODIMP -nsMacShellService::SetDesktopBackground(nsIDOMElement* aElement, - int32_t aPosition) -{ - // Note: We don't support aPosition on OS X. - - // Get the image URI: - nsresult rv; - nsCOMPtr imageContent = do_QueryInterface(aElement, - &rv); - NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr imageURI; - rv = imageContent->GetCurrentURI(getter_AddRefs(imageURI)); - NS_ENSURE_SUCCESS(rv, rv); - - // We need the referer URI for nsIWebBrowserPersist::saveURI - nsCOMPtr content = do_QueryInterface(aElement, &rv); - NS_ENSURE_SUCCESS(rv, rv); - - nsIURI *docURI = content->OwnerDoc()->GetDocumentURI(); - if (!docURI) - return NS_ERROR_FAILURE; - - // Get the desired image file name - nsCOMPtr imageURL(do_QueryInterface(imageURI)); - if (!imageURL) { - // XXXmano (bug 300293): Non-URL images (e.g. the data: protocol) are not - // yet supported. What filename should we take here? - return NS_ERROR_NOT_IMPLEMENTED; - } - - nsAutoCString fileName; - imageURL->GetFileName(fileName); - nsCOMPtr fileLocator - (do_GetService("@mozilla.org/file/directory_service;1", &rv)); - NS_ENSURE_SUCCESS(rv, rv); - - // Get the current user's "Pictures" folder (That's ~/Pictures): - fileLocator->Get(NS_OSX_PICTURE_DOCUMENTS_DIR, NS_GET_IID(nsIFile), - getter_AddRefs(mBackgroundFile)); - if (!mBackgroundFile) - return NS_ERROR_OUT_OF_MEMORY; - - nsAutoString fileNameUnicode; - CopyUTF8toUTF16(fileName, fileNameUnicode); - - // and add the imgage file name itself: - mBackgroundFile->Append(fileNameUnicode); - - // Download the image; the desktop background will be set in OnStateChange() - nsCOMPtr wbp - (do_CreateInstance("@mozilla.org/embedding/browser/nsWebBrowserPersist;1", &rv)); - NS_ENSURE_SUCCESS(rv, rv); - - uint32_t flags = nsIWebBrowserPersist::PERSIST_FLAGS_NO_CONVERSION | - nsIWebBrowserPersist::PERSIST_FLAGS_REPLACE_EXISTING_FILES | - nsIWebBrowserPersist::PERSIST_FLAGS_FROM_CACHE; - - wbp->SetPersistFlags(flags); - wbp->SetProgressListener(this); - - nsCOMPtr loadContext; - nsCOMPtr container = content->OwnerDoc()->GetContainer(); - nsCOMPtr docShell = do_QueryInterface(container); - if (docShell) { - loadContext = do_QueryInterface(docShell); - } - - return wbp->SaveURI(imageURI, nullptr, - docURI, content->OwnerDoc()->GetReferrerPolicy(), - nullptr, nullptr, - mBackgroundFile, loadContext); -} - -NS_IMETHODIMP -nsMacShellService::OnProgressChange(nsIWebProgress* aWebProgress, - nsIRequest* aRequest, - int32_t aCurSelfProgress, - int32_t aMaxSelfProgress, - int32_t aCurTotalProgress, - int32_t aMaxTotalProgress) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsMacShellService::OnLocationChange(nsIWebProgress* aWebProgress, - nsIRequest* aRequest, - nsIURI* aLocation, - uint32_t aFlags) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsMacShellService::OnStatusChange(nsIWebProgress* aWebProgress, - nsIRequest* aRequest, - nsresult aStatus, - const char16_t* aMessage) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsMacShellService::OnSecurityChange(nsIWebProgress* aWebProgress, - nsIRequest* aRequest, - uint32_t aState) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsMacShellService::OnStateChange(nsIWebProgress* aWebProgress, - nsIRequest* aRequest, - uint32_t aStateFlags, - nsresult aStatus) -{ - if (aStateFlags & STATE_STOP) { - nsCOMPtr os(do_GetService("@mozilla.org/observer-service;1")); - if (os) - os->NotifyObservers(nullptr, "shell:desktop-background-changed", nullptr); - - bool exists = false; - mBackgroundFile->Exists(&exists); - if (!exists) - return NS_OK; - - nsAutoCString nativePath; - mBackgroundFile->GetNativePath(nativePath); - - AEDesc tAEDesc = { typeNull, nil }; - OSErr err = noErr; - AliasHandle aliasHandle = nil; - FSRef pictureRef; - OSStatus status; - - // Convert the path into a FSRef - status = ::FSPathMakeRef((const UInt8*)nativePath.get(), &pictureRef, - nullptr); - if (status == noErr) { - err = ::FSNewAlias(nil, &pictureRef, &aliasHandle); - if (err == noErr && aliasHandle == nil) - err = paramErr; - - if (err == noErr) { - // We need the descriptor (based on the picture file reference) - // for the 'Set Desktop Picture' apple event. - char handleState = ::HGetState((Handle)aliasHandle); - ::HLock((Handle)aliasHandle); - err = ::AECreateDesc(typeAlias, *aliasHandle, - GetHandleSize((Handle)aliasHandle), &tAEDesc); - // unlock the alias handler - ::HSetState((Handle)aliasHandle, handleState); - ::DisposeHandle((Handle)aliasHandle); - } - if (err == noErr) { - AppleEvent tAppleEvent; - OSType sig = 'MACS'; - AEBuildError tAEBuildError; - // Create a 'Set Desktop Pictue' Apple Event - err = ::AEBuildAppleEvent(kAECoreSuite, kAESetData, typeApplSignature, - &sig, sizeof(OSType), kAutoGenerateReturnID, - kAnyTransactionID, &tAppleEvent, &tAEBuildError, - "'----':'obj '{want:type (prop),form:prop" \ - ",seld:type('dpic'),from:'null'()},data:(@)", - &tAEDesc); - if (err == noErr) { - AppleEvent reply = { typeNull, nil }; - // Sent the event we built, the reply event isn't necessary - err = ::AESend(&tAppleEvent, &reply, kAENoReply, kAENormalPriority, - kNoTimeOut, nil, nil); - ::AEDisposeDesc(&tAppleEvent); - } - } - } - } - - return NS_OK; -} - -NS_IMETHODIMP -nsMacShellService::OpenApplication(int32_t aApplication) -{ - nsresult rv = NS_OK; - CFURLRef appURL = nil; - OSStatus err = noErr; - - switch (aApplication) { - case nsIShellService::APPLICATION_MAIL: - { - CFURLRef tempURL = ::CFURLCreateWithString(kCFAllocatorDefault, - CFSTR("mailto:"), nullptr); - err = ::LSGetApplicationForURL(tempURL, kLSRolesAll, nullptr, &appURL); - ::CFRelease(tempURL); - } - break; - case nsIShellService::APPLICATION_NEWS: - { - CFURLRef tempURL = ::CFURLCreateWithString(kCFAllocatorDefault, - CFSTR("news:"), nullptr); - err = ::LSGetApplicationForURL(tempURL, kLSRolesAll, nullptr, &appURL); - ::CFRelease(tempURL); - } - break; - case nsIMacShellService::APPLICATION_KEYCHAIN_ACCESS: - err = ::LSGetApplicationForInfo('APPL', 'kcmr', nullptr, kLSRolesAll, - nullptr, &appURL); - break; - case nsIMacShellService::APPLICATION_NETWORK: - { - nsCOMPtr lf; - rv = NS_NewNativeLocalFile(NETWORK_PREFPANE, true, getter_AddRefs(lf)); - NS_ENSURE_SUCCESS(rv, rv); - bool exists; - lf->Exists(&exists); - if (!exists) - return NS_ERROR_FILE_NOT_FOUND; - return lf->Launch(); - } - case nsIMacShellService::APPLICATION_DESKTOP: - { - nsCOMPtr lf; - rv = NS_NewNativeLocalFile(DESKTOP_PREFPANE, true, getter_AddRefs(lf)); - NS_ENSURE_SUCCESS(rv, rv); - bool exists; - lf->Exists(&exists); - if (!exists) - return NS_ERROR_FILE_NOT_FOUND; - return lf->Launch(); - } - } - - if (appURL && err == noErr) { - err = ::LSOpenCFURLRef(appURL, nullptr); - rv = err != noErr ? NS_ERROR_FAILURE : NS_OK; - - ::CFRelease(appURL); - } - - return rv; -} - -NS_IMETHODIMP -nsMacShellService::GetDesktopBackgroundColor(uint32_t *aColor) -{ - // This method and |SetDesktopBackgroundColor| has no meaning on Mac OS X. - // The mac desktop preferences UI uses pictures for the few solid colors it - // supports. - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP -nsMacShellService::SetDesktopBackgroundColor(uint32_t aColor) -{ - // This method and |GetDesktopBackgroundColor| has no meaning on Mac OS X. - // The mac desktop preferences UI uses pictures for the few solid colors it - // supports. - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP -nsMacShellService::OpenApplicationWithURI(nsIFile* aApplication, const nsACString& aURI) -{ - nsCOMPtr lfm(do_QueryInterface(aApplication)); - CFURLRef appURL; - nsresult rv = lfm->GetCFURL(&appURL); - if (NS_FAILED(rv)) - return rv; - - const nsCString spec(aURI); - const UInt8* uriString = (const UInt8*)spec.get(); - CFURLRef uri = ::CFURLCreateWithBytes(nullptr, uriString, aURI.Length(), - kCFStringEncodingUTF8, nullptr); - if (!uri) - return NS_ERROR_OUT_OF_MEMORY; - - CFArrayRef uris = ::CFArrayCreate(nullptr, (const void**)&uri, 1, nullptr); - if (!uris) { - ::CFRelease(uri); - return NS_ERROR_OUT_OF_MEMORY; - } - - LSLaunchURLSpec launchSpec; - launchSpec.appURL = appURL; - launchSpec.itemURLs = uris; - launchSpec.passThruParams = nullptr; - launchSpec.launchFlags = kLSLaunchDefaults; - launchSpec.asyncRefCon = nullptr; - - OSErr err = ::LSOpenFromURLSpec(&launchSpec, nullptr); - - ::CFRelease(uris); - ::CFRelease(uri); - - return err != noErr ? NS_ERROR_FAILURE : NS_OK; -} - -NS_IMETHODIMP -nsMacShellService::GetDefaultFeedReader(nsIFile** _retval) -{ - nsresult rv = NS_ERROR_FAILURE; - *_retval = nullptr; - - CFStringRef defaultHandlerID = ::LSCopyDefaultHandlerForURLScheme(CFSTR("feed")); - if (!defaultHandlerID) { - defaultHandlerID = ::CFStringCreateWithCString(kCFAllocatorDefault, - SAFARI_BUNDLE_IDENTIFIER, - kCFStringEncodingASCII); - } - - CFURLRef defaultHandlerURL = nullptr; - OSStatus status = ::LSFindApplicationForInfo(kLSUnknownCreator, - defaultHandlerID, - nullptr, // inName - nullptr, // outAppRef - &defaultHandlerURL); - - if (status == noErr && defaultHandlerURL) { - nsCOMPtr defaultReader = - do_CreateInstance("@mozilla.org/file/local;1", &rv); - if (NS_SUCCEEDED(rv)) { - rv = defaultReader->InitWithCFURL(defaultHandlerURL); - if (NS_SUCCEEDED(rv)) { - NS_ADDREF(*_retval = defaultReader); - rv = NS_OK; - } - } - - ::CFRelease(defaultHandlerURL); - } - - ::CFRelease(defaultHandlerID); - - return rv; -} diff --git a/application/palemoon/components/shell/nsMacShellService.h b/application/palemoon/components/shell/nsMacShellService.h deleted file mode 100644 index db95278092..0000000000 --- a/application/palemoon/components/shell/nsMacShellService.h +++ /dev/null @@ -1,32 +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 nsmacshellservice_h____ -#define nsmacshellservice_h____ - -#include "nsIMacShellService.h" -#include "nsIWebProgressListener.h" -#include "nsIFile.h" -#include "nsCOMPtr.h" - -class nsMacShellService : public nsIMacShellService, - public nsIWebProgressListener -{ -public: - nsMacShellService() {}; - - NS_DECL_ISUPPORTS - NS_DECL_NSISHELLSERVICE - NS_DECL_NSIMACSHELLSERVICE - NS_DECL_NSIWEBPROGRESSLISTENER - -protected: - virtual ~nsMacShellService() {}; - -private: - nsCOMPtr mBackgroundFile; -}; - -#endif // nsmacshellservice_h____ diff --git a/application/palemoon/themes/moz.build b/application/palemoon/themes/moz.build index 4267990dd9..0fe67acd00 100644 --- a/application/palemoon/themes/moz.build +++ b/application/palemoon/themes/moz.build @@ -5,9 +5,7 @@ toolkit = CONFIG['MOZ_WIDGET_TOOLKIT'] -if toolkit == 'cocoa': - DIRS += ['osx'] -elif toolkit in ('gtk2', 'gtk3', 'qt'): +if toolkit in ('gtk2', 'gtk3', 'qt'): DIRS += ['linux'] else: DIRS += ['windows'] diff --git a/application/palemoon/themes/osx/Geolocation-16.png b/application/palemoon/themes/osx/Geolocation-16.png deleted file mode 100644 index d710e7336d..0000000000 Binary files a/application/palemoon/themes/osx/Geolocation-16.png and /dev/null differ diff --git a/application/palemoon/themes/osx/Geolocation-64.png b/application/palemoon/themes/osx/Geolocation-64.png deleted file mode 100644 index 1bd46ba5e1..0000000000 Binary files a/application/palemoon/themes/osx/Geolocation-64.png and /dev/null differ diff --git a/application/palemoon/themes/osx/Info.png b/application/palemoon/themes/osx/Info.png deleted file mode 100644 index d09e82b6c6..0000000000 Binary files a/application/palemoon/themes/osx/Info.png and /dev/null differ diff --git a/application/palemoon/themes/osx/KUI-background.png b/application/palemoon/themes/osx/KUI-background.png deleted file mode 100644 index 104a49f7b0..0000000000 Binary files a/application/palemoon/themes/osx/KUI-background.png and /dev/null differ diff --git a/application/palemoon/themes/osx/KUI-close.png b/application/palemoon/themes/osx/KUI-close.png deleted file mode 100644 index 08eeb81831..0000000000 Binary files a/application/palemoon/themes/osx/KUI-close.png and /dev/null differ diff --git a/application/palemoon/themes/osx/Makefile.in b/application/palemoon/themes/osx/Makefile.in deleted file mode 100644 index 173ca68435..0000000000 --- a/application/palemoon/themes/osx/Makefile.in +++ /dev/null @@ -1,7 +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/. - -ICON_FILES := icon.png -ICON_DEST = $(FINAL_TARGET)/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd} -INSTALL_TARGETS += ICON diff --git a/application/palemoon/themes/osx/Privacy-16.png b/application/palemoon/themes/osx/Privacy-16.png deleted file mode 100644 index a4be3e9acf..0000000000 Binary files a/application/palemoon/themes/osx/Privacy-16.png and /dev/null differ diff --git a/application/palemoon/themes/osx/Privacy-32.png b/application/palemoon/themes/osx/Privacy-32.png deleted file mode 100644 index dd07c1a128..0000000000 Binary files a/application/palemoon/themes/osx/Privacy-32.png and /dev/null differ diff --git a/application/palemoon/themes/osx/Privacy-48.png b/application/palemoon/themes/osx/Privacy-48.png deleted file mode 100644 index 2396f99e5b..0000000000 Binary files a/application/palemoon/themes/osx/Privacy-48.png and /dev/null differ diff --git a/application/palemoon/themes/osx/Privacy-64.png b/application/palemoon/themes/osx/Privacy-64.png deleted file mode 100644 index d3605015be..0000000000 Binary files a/application/palemoon/themes/osx/Privacy-64.png and /dev/null differ diff --git a/application/palemoon/themes/osx/Search.png b/application/palemoon/themes/osx/Search.png deleted file mode 100644 index 0b71db3b41..0000000000 Binary files a/application/palemoon/themes/osx/Search.png and /dev/null differ diff --git a/application/palemoon/themes/osx/Secure24.png b/application/palemoon/themes/osx/Secure24.png deleted file mode 100644 index 896343afc5..0000000000 Binary files a/application/palemoon/themes/osx/Secure24.png and /dev/null differ diff --git a/application/palemoon/themes/osx/Toolbar-inverted.png b/application/palemoon/themes/osx/Toolbar-inverted.png deleted file mode 100644 index 54d83bf5f2..0000000000 Binary files a/application/palemoon/themes/osx/Toolbar-inverted.png and /dev/null differ diff --git a/application/palemoon/themes/osx/Toolbar-inverted.svg b/application/palemoon/themes/osx/Toolbar-inverted.svg deleted file mode 100644 index ce59313e68..0000000000 --- a/application/palemoon/themes/osx/Toolbar-inverted.svg +++ /dev/null @@ -1,302 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/application/palemoon/themes/osx/Toolbar.png b/application/palemoon/themes/osx/Toolbar.png deleted file mode 100644 index 8ec756e03d..0000000000 Binary files a/application/palemoon/themes/osx/Toolbar.png and /dev/null differ diff --git a/application/palemoon/themes/osx/Toolbar.svg b/application/palemoon/themes/osx/Toolbar.svg deleted file mode 100644 index 7a68c06087..0000000000 --- a/application/palemoon/themes/osx/Toolbar.svg +++ /dev/null @@ -1,1356 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/application/palemoon/themes/osx/aboutCertError.css b/application/palemoon/themes/osx/aboutCertError.css deleted file mode 100644 index 100bb3d3bb..0000000000 --- a/application/palemoon/themes/osx/aboutCertError.css +++ /dev/null @@ -1,73 +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/. */ - - -html { - background: #833; -} - -body { - margin: 0; - padding: 0 1em; - color: -moz-FieldText; - font: message-box; -} - -h1 { - margin: 0 0 .6em 0; - border-bottom: 1px solid ThreeDLightShadow; - font-size: 160%; -} - -h2 { - font-size: 130%; -} - -#errorPageContainer { - position: relative; - min-width: 13em; - max-width: 52em; - margin: 4em auto; - border: 2px solid #DD0D09; - border-radius: 10px; - box-shadow: 0px 0px 8px red; - padding: 3em; - padding-inline-start: 30px; - background: url("chrome://global/skin/icons/sslWarning.png") left 0 no-repeat -moz-Field; - background-origin: content-box; -} - -#errorPageContainer:-moz-dir(rtl) { - background-position: right 0; -} - -#errorTitle { - margin-inline-start: 80px; -} - -#errorLongContent { - margin-inline-start: 80px; -} - -.expander > button { - padding-inline-start: 20px; - margin-inline-start: -20px; - background: url("chrome://browser/skin/aboutCertError_sectionExpanded.png") left center no-repeat; - border: none; - font: inherit; - color: inherit; - cursor: pointer; -} - -.expander > button:-moz-dir(rtl) { - background-position: right center; -} - -.expander[collapsed] > button { - background-image: url("chrome://browser/skin/aboutCertError_sectionCollapsed.png"); -} - -.expander[collapsed] > button:-moz-dir(rtl) { - background-image: url("chrome://browser/skin/aboutCertError_sectionCollapsed-rtl.png"); -} diff --git a/application/palemoon/themes/osx/aboutCertError_sectionCollapsed-rtl.png b/application/palemoon/themes/osx/aboutCertError_sectionCollapsed-rtl.png deleted file mode 100644 index 84ba18c0a3..0000000000 Binary files a/application/palemoon/themes/osx/aboutCertError_sectionCollapsed-rtl.png and /dev/null differ diff --git a/application/palemoon/themes/osx/aboutCertError_sectionCollapsed.png b/application/palemoon/themes/osx/aboutCertError_sectionCollapsed.png deleted file mode 100644 index c9805f654c..0000000000 Binary files a/application/palemoon/themes/osx/aboutCertError_sectionCollapsed.png and /dev/null differ diff --git a/application/palemoon/themes/osx/aboutCertError_sectionExpanded.png b/application/palemoon/themes/osx/aboutCertError_sectionExpanded.png deleted file mode 100644 index 128cef90af..0000000000 Binary files a/application/palemoon/themes/osx/aboutCertError_sectionExpanded.png and /dev/null differ diff --git a/application/palemoon/themes/osx/aboutPrivateBrowsing.css b/application/palemoon/themes/osx/aboutPrivateBrowsing.css deleted file mode 100644 index 35843adce6..0000000000 --- a/application/palemoon/themes/osx/aboutPrivateBrowsing.css +++ /dev/null @@ -1,47 +0,0 @@ -%if 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/. */ -%endif - -body.private > #errorPageContainer { - background-image: url("chrome://browser/skin/Privacy-48.png"); -} - -body.normal > #errorPageContainer { - background-image: url("chrome://global/skin/icons/question-48.png"); -} - -#clearRecentHistoryDesc { - margin-top: 2em; -} - -#clearRecentHistoryDesc > p { - font-size: 110%; /* to match the value set in chrome://global/skin/netError.css */ -} - -#startPrivateBrowsingDesc > button { - margin-inline-start: 0; -} - -#footerDesc > p { - font-size: 110%; /* to match the value set in chrome://global/skin/netError.css */ -} - -#moreInfo { - font-size: 110%; /* to match the value set in chrome://global/skin/netError.css */ - padding-inline-start: 25px; - background: url("chrome://global/skin/icons/information-16.png") no-repeat top left; -} - -#moreInfo:-moz-dir(rtl) { - background-position: top right; -} - -#moreInfoText { - margin-bottom: 0; -} - -#moreInfoLinkContainer { - margin-top: 0.5em; -} diff --git a/application/palemoon/themes/osx/aboutSessionRestore.css b/application/palemoon/themes/osx/aboutSessionRestore.css deleted file mode 100644 index 4fa490798d..0000000000 --- a/application/palemoon/themes/osx/aboutSessionRestore.css +++ /dev/null @@ -1,73 +0,0 @@ -%if 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/. */ -%endif - -html { - background: #f8ffd0; - height: 100%; -} - -body { - height: 100%; - text-align: center; -} - -#errorPageContainer { - background-image: url("chrome://global/skin/icons/warning-large.png"); - display: -moz-box; - width: -moz-available; - max-width: 85%; - height: 75%; - max-height: 85%; - -moz-box-orient: vertical; - text-align: start; - border: 2px solid #efc; - box-shadow: 0px 0px 8px #aaa; -} - -#errorShortDesc > p { - margin-top: 0.4em; - margin-bottom: 0; -} - -#errorLongContent, #errorTrailerDesc { - display: -moz-box; - -moz-box-flex: 1; - -moz-box-orient: vertical; -} - -#tabList { - margin-top: 2.5em; - width: 100%; - min-height: 12em; -} - -treechildren::-moz-tree-image(icon), -treechildren::-moz-tree-image(noicon) { - padding-right: 2px; - margin: 0px 2px; - width: 16px; - height: 16px; -} - -treechildren::-moz-tree-image(noicon) { - list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png"); -} -treechildren::-moz-tree-image(container, noicon) { - list-style-image: url("chrome://browser/skin/aboutSessionRestore-window-icon.png"); -} -treechildren::-moz-tree-image(checked) { - list-style-image: url("chrome://global/skin/checkbox/cbox-check.gif"); -} -treechildren::-moz-tree-image(partial) { - list-style-image: url("chrome://global/skin/checkbox/cbox-check-dis.gif"); -} - -#buttons { - width: 100%; -} -#buttons > button { - margin-top: 2em; -} diff --git a/application/palemoon/themes/osx/aboutSyncTabs.css b/application/palemoon/themes/osx/aboutSyncTabs.css deleted file mode 100644 index 1fcd8304f7..0000000000 --- a/application/palemoon/themes/osx/aboutSyncTabs.css +++ /dev/null @@ -1,101 +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/. */ - -#tabs-display, -#tabsList { - background-color: transparent; - -moz-appearance: none; - margin: 0; -} - -#tabsList { - width: 100%; -} - -#tabs-display { - background: #fff url(chrome://browser/skin/sync-bg.png) repeat-x center -80px; -} - -#headers { - background: url(chrome://browser/skin/sync-32.png) no-repeat; - margin-top: 4px; - width: 45em; - height: 32px; - margin-inline-start: 2em; - margin-inline-end: 2em; -} - -#tabsListHeading { - font-size: 140%; - font-weight: bold; - margin-inline-start: 40px; -} - -richlistitem { - margin-inline-end: 2em; -} - -richlistitem[selected="true"], -richlistitem:focus { - outline-style: none; -} - -richlistitem[type="tab"] { - min-height: 3em; - border: #999999 1px solid !important; - padding: 2px 5px; - margin-bottom: 4px; - margin-inline-start: 4em; - border-radius: 6px; - background-color: menu; - width: 44em; - opacity: 0.9; - box-shadow: - inset rgba(255, 255, 255, 0.5) 0 1px 0px, - inset rgba(0, 0, 0, 0.1) 0 -2px 0px, - rgba(0, 0, 0, 0.1) 0px 1px 0px; -} - -richlistitem[type="tab"][selected="true"] { - background-color: -moz-MenuHover; -} - -richlistitem[type="client"] { - min-height: 2em; - color: #000000; - margin-inline-start: 2em; - margin-top: 2px; - margin-bottom: 3px; - width: 42em; - border-radius: 6px; - background-color: transparent; - -moz-user-focus: ignore !important; -} -richlistitem.mobile[type="client"] { - list-style-image: url("chrome://browser/skin/sync-mobileIcon.png"); -} -richlistitem.desktop[type="client"] { - list-style-image: url("chrome://browser/skin/sync-desktopIcon.png"); -} - -.title, -.clientName { - color: #000000; - font-size: 1.1em; -} - -.title[selected="true"], -.url[selected="true"] { - color: inherit; -} - -.url { - color: -moz-nativehyperlinktext; - font-size: 0.95em; -} - -.tabIcon { - padding-inline-start: 2px; - padding-top: 2px; -} diff --git a/application/palemoon/themes/osx/actionicon-tab.png b/application/palemoon/themes/osx/actionicon-tab.png deleted file mode 100644 index ced958ebbe..0000000000 Binary files a/application/palemoon/themes/osx/actionicon-tab.png and /dev/null differ diff --git a/application/palemoon/themes/osx/autocomplete.css b/application/palemoon/themes/osx/autocomplete.css deleted file mode 100644 index 7f63bef198..0000000000 --- a/application/palemoon/themes/osx/autocomplete.css +++ /dev/null @@ -1,198 +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/. */ - -@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); -@namespace html url("http://www.w3.org/1999/xhtml"); - -/* .padded is used by autocomplete widgets that don't have an icon. Gross. -dwh */ -textbox:not(.padded) { - cursor: default; - padding: 0; -} - -textbox[nomatch="true"][highlightnonmatches="true"] { - color: red; -} - -textbox:not(.padded) .textbox-input-box { - margin: 0 3px; -} - -.textbox-input-box { - -moz-box-align: center; -} - -/* ::::: history button ::::: */ - -.private-autocomplete-history-dropmarker { - -moz-appearance: none !important; - border: none !important; - background-color: transparent !important; - padding: 0px; - list-style-image: url("chrome://global/skin/icons/autocomplete-dropmarker.png"); - margin: 0px; -} - -/* ::::: autocomplete popups ::::: */ - -panel[type="private-autocomplete"], -panel[type="private-autocomplete-richlistbox"], -.private-autocomplete-history-popup { - padding: 0px !important; - color: -moz-FieldText; - background-color: -moz-Field; - font: icon; - -moz-appearance: none; -} - -.private-autocomplete-history-popup { - max-height: 180px; -} - -/* ::::: tree ::::: */ - -.private-autocomplete-tree { - -moz-appearance: none !important; - border: none !important; - background-color: transparent !important; -} - -.private-autocomplete-treecol { - -moz-appearance: none !important; - margin: 0 !important; - border: none !important; - padding: 0 !important; -} - -.private-autocomplete-treebody::-moz-tree-cell-text { - padding-left: 2px; -} - -.private-autocomplete-treebody::-moz-tree-row { - border-top: none; -} - -treechildren.private-autocomplete-treebody::-moz-tree-row(selected) { - background-color: Highlight; -} - -treechildren.private-autocomplete-treebody::-moz-tree-cell-text(selected) { - color: HighlightText !important; -} - -.private-autocomplete-treebody::-moz-tree-image(treecolAutoCompleteValue) { - max-width: 16px; - height: 16px; -} - -/* ::::: richlistbox autocomplete ::::: */ - -.private-autocomplete-richlistbox { - -moz-appearance: none; - margin: 0; -} - -.private-autocomplete-richlistitem[selected="true"] { - background-color: Highlight; - color: HighlightText; - background-image: linear-gradient(rgba(255,255,255,0.3), transparent); -} - -.private-autocomplete-richlistitem { - padding: 5px 2px; -} - -.ac-url-box { - /* When setting a vertical margin here, half of that needs to be added - .ac-title-box's translateY for when .ac-url-box is hidden (see below). */ - margin-top: 1px; -} - -.private-autocomplete-richlistitem[actiontype="keyword"] .ac-url-box, -.private-autocomplete-richlistitem[actiontype="searchengine"] .ac-url-box, -.private-autocomplete-richlistitem[actiontype="visiturl"] .ac-url-box, -.private-autocomplete-richlistitem[type~="autofill"] .ac-url-box { - visibility: hidden; -} - -.private-autocomplete-richlistitem[actiontype="keyword"] .ac-title-box, -.private-autocomplete-richlistitem[actiontype="searchengine"] .ac-title-box, -.private-autocomplete-richlistitem[actiontype="visiturl"] .ac-title-box, -.private-autocomplete-richlistitem[type~="autofill"] .ac-title-box { - /* Center the title by moving it down by half of .ac-url-box's height, - including vertical margins (if any). */ - transform: translateY(.5em); -} - -.ac-site-icon { - width: 16px; - height: 16px; - margin-bottom: -1px; - margin-inline-start: 7px; - margin-inline-end: 5px; -} - -.ac-type-icon { - width: 16px; - height: 16px; - margin-inline-start: 6px; - margin-inline-end: 4px; -} - -.ac-url-box > .ac-site-icon, -.ac-url-box > .ac-type-icon { - /* Otherwise the spacer is big enough to stretch its container */ - height: auto; -} - -.ac-extra > .ac-result-type-tag { - margin: 0 4px; -} - -.ac-extra > .ac-comment { - padding-right: 4px; -} - -.ac-ellipsis-after { - margin: 0 !important; - padding: 0; - min-width: 1.1em; -} - -.ac-normal-text { - margin: 0 !important; - padding: 0; -} - -.ac-normal-text > html|span { - margin: 0 !important; - padding: 0; -} - -html|span.ac-emphasize-text { - box-shadow: inset 0 0 1px 1px rgba(208,208,208,0.4); - background-color: rgba(208,208,208,0.2); - border-radius: 2px; - text-shadow: 0 0 currentColor; -} - -.ac-url-text > html|span.ac-emphasize-text, -.ac-action-text > html|span.ac-emphasize-text { - box-shadow: inset 0 0 1px 1px rgba(183,210,226,0.4); - background-color: rgba(183,210,226,0.3); -} - -.ac-title, .ac-url { - overflow: hidden; -} - -/* ::::: textboxes inside toolbarpaletteitems ::::: */ - -toolbarpaletteitem > toolbaritem > textbox > hbox > hbox > html|*.textbox-input { - visibility: hidden; -} - -toolbarpaletteitem > toolbaritem > * > textbox > hbox > hbox > html|*.textbox-input { - visibility: hidden; -} diff --git a/application/palemoon/themes/osx/browser.css b/application/palemoon/themes/osx/browser.css deleted file mode 100644 index 49c210df44..0000000000 --- a/application/palemoon/themes/osx/browser.css +++ /dev/null @@ -1,2884 +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/. */ - -@import url("chrome://global/skin/"); - -@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); -@namespace html url("http://www.w3.org/1999/xhtml"); - -%include shared.inc -%filter substitution -%define toolbarShadowColor rgba(10%,10%,10%,.4) -%define toolbarShadowOnTab linear-gradient(to top, rgba(10%,10%,10%,.4) 1px, transparent 1px) -%define navbarTextboxCustomBorder border-color: rgba(0,0,0,.32); -%define navbarLargeIcons #navigator-toolbox[iconsize=large][mode=icons] > #nav-bar -%define forwardTransitionLength 150ms -%define conditionalForwardWithUrlbar window:not([chromehidden~=toolbar]) #navigator-toolbox[iconsize=large][mode=icons] > :-moz-any(#nav-bar[currentset*="unified-back-forward-button"],#nav-bar:not([currentset])) > #unified-back-forward-button -%define conditionalForwardWithUrlbarWidth 27 - -:root { - --toolbox-after-color: ThreeDShadow; - - --toolbar-custom-color: -moz-Dialog; - --toolbar-highlight-top: rgba(255,255,255,.5); - --toolbar-highlight-bottom: transparent; - - --toolbarbutton-background-color: hsla(210,32%,93%,.3); - --toolbarbutton-border-radius: 2.5px; - --toolbarbutton-border-color: hsla(210,54%,20%,.2); - - --toolbarbutton-image: url("chrome://browser/skin/Toolbar.png"); - --toolbarbutton-inverted-image: url("chrome://browser/skin/Toolbar-inverted.png"); - - --tab-background: linear-gradient(transparent, hsla(0,0%,45%,.1) 1px, hsla(0,0%,32%,.2) 80%, hsla(0,0%,0%,.2)); - --tab-background-hover: linear-gradient(hsla(0,0%,100%,.3) 1px, hsla(0,0%,75%,.2) 80%, hsla(0,0%,60%,.2)); - --tab-border-radius: 6px; - --tab-box-shadow: inset 0.5px 1px 1px var(--tab-selected-highlight); - --tab-selected-highlight: rgba(255,255,255,.7); -} - -/* Use SVG for HiDPI 133%+ */ -@media (min-resolution: 1.33dppx) { - :root { - --toolbarbutton-image: url("chrome://browser/skin/Toolbar.svg"); - --toolbarbutton-inverted-image: url("chrome://browser/skin/Toolbar-inverted.svg"); - } -} - -:root:-moz-lwtheme-brighttext { - --toolbar-highlight-top: rgba(32,32,32,.8); - --toolbar-highlight-bottom: rgba(32,32,32,0); -} - -:root:-moz-lwtheme-darktext { - --toolbar-highlight-top: rgba(255,255,255,.8); - - --tab-selected-highlight: rgba(255,255,255,.6); -} - -#navigator-toolbox { - -moz-appearance: none; - background-color: transparent; - border-top: none; -} - -#main-window { - -moz-appearance: none; - background-color: #eeeeee; -} - -#navigator-toolbox::after { - content: ""; - display: -moz-box; - -moz-box-ordinal-group: 101; /* tabs toolbar is 100 */ - height: 1px; - background-color: var(--toolbox-after-color); -} -#navigator-toolbox[tabsontop=false]::after, -#main-window[disablechrome] #navigator-toolbox::after { - visibility: collapse; -} - -#navigator-toolbox > toolbar:not(:-moz-lwtheme) { - -moz-appearance: none; - border-style: none; - background-color: var(--toolbar-custom-color); -} - -#nav-bar[tabsontop=true]:not(:-moz-lwtheme), -#nav-bar[tabsontop=true][collapsed=true]:not([customizing]):not(:-moz-lwtheme) + toolbar, -#nav-bar[tabsontop=true][collapsed=true]:not([customizing]):not(:-moz-lwtheme) + #customToolbars + #PersonalToolbar { - background-image: linear-gradient(var(--toolbar-highlight-top), var(--toolbar-highlight-bottom)); -} - -/* Blend the topmost toolbar with the titlebar */ -%ifdef MOZ_CAN_DRAW_IN_TITLEBAR -#main-window[tabsontop=false]:not([privatebrowsingmode=temporary]) #nav-bar:not(:-moz-lwtheme), -#main-window[tabsontop=false]:not([privatebrowsingmode=temporary]) #PersonalToolbar[collapsed=true] - ~ #TabsToolbar:not(:-moz-lwtheme), -#main-window[tabsontop=true]:not([privatebrowsingmode=temporary]) #TabsToolbar:not(:-moz-lwtheme) { - -moz-appearance: toolbar; -} - -#main-window[tabsontop=false][privatebrowsingmode=temporary] #nav-bar:not(:-moz-lwtheme), -#main-window[tabsontop=false][privatebrowsingmode=temporary] #PersonalToolbar[collapsed=true] - ~ #TabsToolbar:not(:-moz-lwtheme), -#main-window[tabsontop=true][privatebrowsingmode=temporary] #TabsToolbar:not(:-moz-lwtheme) { - background-color: transparent; -} - -#main-window[tabsontop=false][privatebrowsingmode=temporary] #nav-bar:not(:-moz-lwtheme) { - border-bottom: 1px solid rgba(26,26,26,0.2); -} -%else -#main-window[tabsontop=false] #nav-bar:not(:-moz-lwtheme), -#main-window[tabsontop=false] #PersonalToolbar[collapsed=true] - ~ #TabsToolbar:not(:-moz-lwtheme), -#main-window[tabsontop=true] #TabsToolbar:not(:-moz-lwtheme) { - -moz-appearance: toolbar; -} -%endif - -#personal-bookmarks { - min-height: 24px; -} - -#print-preview-toolbar:not(:-moz-lwtheme) { - -moz-appearance: toolbox; -} - -#browser-bottombox:not(:-moz-lwtheme) { - background-color: var(--toolbar-custom-color); -} - - -%ifdef MOZ_CAN_DRAW_IN_TITLEBAR -/* ::::: titlebar ::::: */ - -#main-window[sizemode="normal"]:not([privatebrowsingmode=temporary]) > #titlebar { - -moz-appearance: -moz-window-titlebar; -} - -#main-window[sizemode="maximized"] > #titlebar { - -moz-appearance: -moz-window-titlebar-maximized; -} - -#titlebar-buttonbox { - -moz-appearance: -moz-window-button-box; -} - -.titlebar-placeholder[type="appmenu-button"] { - margin-left: 4px; -} - -.titlebar-placeholder[type="caption-buttons"] { - margin-left: 10px; -} - -/* titlebar command buttons */ - -#titlebar-min { - -moz-appearance: -moz-window-button-minimize; -} - -#titlebar-max { - -moz-appearance: -moz-window-button-maximize; -} - -#main-window[sizemode="maximized"] #titlebar-max { - -moz-appearance: -moz-window-button-restore; -} - -#titlebar-close { - -moz-appearance: -moz-window-button-close; -} - -/* ensure titlebar on privacy windows is of correct size */ -#titlebar { - height: 22px; -} - -/* ensure extra titlebar doesn't appear on normal (e.g. non-privacy) windows */ -#main-window:not([privatebrowsingmode=temporary]):not(:-moz-lwtheme) > #titlebar > #titlebar-content > #titlebar-buttonbox-container, -#main-window:not([drawintitlebar=true]):not(:-moz-lwtheme) > #titlebar { - display: none; -} - -#titlebar-buttonbox-container { - margin-left: 7px; - margin-top: 3px; -} -%endif -/* ::::: bookmark toolbar ::::: */ - -#personal-bookmarks { - min-height: 17px; /* 16px button height + 1px margin-bottom */ -} - -toolbarbutton.chevron { - list-style-image: url("chrome://global/skin/icons/chevron.png"); - margin: 1px 0 0; - padding: 0; -} - -toolbarbutton.chevron > .toolbarbutton-text { - display: none; -} - -toolbar[mode="text"] toolbarbutton.chevron > .toolbarbutton-icon { - display: -moz-box; /* display chevron icon in text mode */ -} - -toolbarbutton.chevron:-moz-locale-dir(rtl) > .toolbarbutton-icon { - transform: scaleX(-1); -} - -@media (min-resolution: 2dppx) { - toolbarbutton.chevron { - list-style-image: url("chrome://global/skin/icons/chevron@2x.png"); - } - - toolbarbutton.chevron > .toolbarbutton-icon { - width: 13px; - } -} - -/* ::::: bookmark buttons ::::: */ - -toolbarbutton.bookmark-item { - border: 0; - border-radius: 10000px; - padding: 1px 8px; - margin: 0 0 1px; -} - -toolbarbutton.bookmark-item:not(:-moz-lwtheme) { - color: #222; -} - -toolbarbutton.bookmark-item:-moz-lwtheme { - color: inherit; - text-shadow: inherit; -} - -.bookmark-item > .toolbarbutton-menu-dropmarker { - list-style-image: url("chrome://browser/skin/places/folderDropArrow.png"); - -moz-image-region: rect(0, 7px, 5px, 0); - margin-top: 1px; - margin-inline-start: 3px; - margin-inline-end: -2px; -} - -@media (min-resolution: 2dppx) { - .bookmark-item > .toolbarbutton-menu-dropmarker { - list-style-image: url("chrome://browser/skin/places/folderDropArrow@2x.png"); - -moz-image-region: rect(0, 14px, 10px, 0); - } - - .bookmark-item > .toolbarbutton-menu-dropmarker > .dropmarker-icon { - width: 7px; - } -} - -.bookmark-item > .toolbarbutton-text { - display: -moz-box !important; /* prevent [mode="icons"] from hiding the label */ - margin: 0 !important; -} - -toolbarbutton.bookmark-item:hover, -toolbarbutton.bookmark-item[open="true"] { - background-color: rgba(0, 0, 0, .205); -} - -toolbarbutton.bookmark-item:-moz-lwtheme-brighttext:hover, -toolbarbutton.bookmark-item[open="true"]:-moz-lwtheme-brighttext { - background-color: rgba(255, 255, 255, .3); -} - -toolbarbutton.bookmark-item:not(:-moz-lwtheme):hover, -toolbarbutton.bookmark-item[open="true"]:not(:-moz-lwtheme) { - color: #FFF; - text-shadow: 0 1px rgba(0, 0, 0, .4); -} - -.bookmark-item:-moz-lwtheme-brighttext > .toolbarbutton-menu-dropmarker, -.bookmark-item:hover > .toolbarbutton-menu-dropmarker, -.bookmark-item[open="true"] > .toolbarbutton-menu-dropmarker { - -moz-image-region: rect(5px, 7px, 10px, 0); -} - -@media (min-resolution: 2dppx) { - .bookmark-item:-moz-lwtheme-brighttext > .toolbarbutton-menu-dropmarker, - .bookmark-item:hover > .toolbarbutton-menu-dropmarker, - .bookmark-item[open="true"] > .toolbarbutton-menu-dropmarker { - -moz-image-region: rect(10px, 14px, 20px, 0); - } -} - -toolbarbutton.bookmark-item:active:hover, -toolbarbutton.bookmark-item[open="true"] { - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.4), 0 1px rgba(255, 255, 255, 0.4); - background-color: rgba(0, 0, 0, .5); -} - -toolbarbutton.bookmark-item:-moz-lwtheme-brighttext:hover, -toolbarbutton.bookmark-item[open="true"]:-moz-lwtheme-brighttext { - background-color: rgba(255,255,255, .3); -} - -toolbarbutton.bookmark-item > menupopup { - margin-top: 2px; - margin-inline-start: 3px; -} - -.bookmark-item > .toolbarbutton-icon { - width: 16px; - min-height: 16px; - max-height: 16px; -} - -.bookmark-item > .toolbarbutton-icon[label]:not([label=""]), -.bookmark-item > .toolbarbutton-icon[type="menu"] { - margin-inline-end: 5px; -} - -.bookmark-item[container] { - list-style-image: url("chrome://global/skin/tree/folder.png"); -} - -.bookmark-item[container][livemark] { - list-style-image: url("chrome://browser/skin/page-livemarks.png"); -} - -.bookmark-item[container][livemark] .bookmark-item { - list-style-image: url("chrome://browser/skin/places/livemark-item.png"); - -moz-image-region: rect(0px, 16px, 16px, 0px); -} - -.bookmark-item[container][livemark] .bookmark-item[visited] { - -moz-image-region: rect(0px, 32px, 16px, 16px); -} - -.bookmark-item[container][query] { - list-style-image: url("chrome://browser/skin/places/query.png"); -} - -.bookmark-item[query][tagContainer] { - list-style-image: url("chrome://browser/skin/places/tag.png"); -} - -.bookmark-item[query][dayContainer] { - list-style-image: url("chrome://browser/skin/places/history.png"); -} - -.bookmark-item[query][hostContainer] { - list-style-image: url("chrome://global/skin/tree/folder.png"); -} - -.bookmark-item[query][hostContainer][open] { - list-style-image: url("chrome://global/skin/tree/folder.png"); -} - -@media (min-resolution: 2dppx) { - .bookmark-item[container] { - list-style-image: url("chrome://global/skin/tree/folder@2x.png"); - } - - .bookmark-item[container][livemark] { - list-style-image: url("chrome://browser/skin/page-livemarks@2x.png"); - } - - .bookmark-item[container][livemark] .bookmark-item { - list-style-image: url("chrome://browser/skin/places/livemark-item.png"); - } - - .bookmark-item[container][query] { - list-style-image: url("chrome://browser/skin/places/query@2x.png"); - } - - .bookmark-item[query][tagContainer] { - list-style-image: url("chrome://browser/skin/places/tag@2x.png"); - } - - .bookmark-item[query][dayContainer] { - list-style-image: url("chrome://browser/skin/places/history@2x.png"); - } - - .bookmark-item[query][hostContainer] { - list-style-image: url("chrome://global/skin/tree/folder@2x.png"); - } - - .bookmark-item[query][hostContainer][open] { - list-style-image: url("chrome://global/skin/tree/folder@2x.png"); - } -} - -/* Workaround for native menubar inheritance */ -.openintabs-menuitem, -.openlivemarksite-menuitem, -.livemarkstatus-menuitem { - list-style-image: none; -} - -.bookmark-item[cutting] > .toolbarbutton-icon, -.bookmark-item[cutting] > .menu-iconic-left > .menu-iconic-icon { - opacity: 0.5; -} - -.bookmark-item[cutting] > .toolbarbutton-text, -.bookmark-item[cutting] > .menu-iconic-left > .menu-iconic-text { - opacity: 0.7; -} - -@media (min-resolution: 2dppx) { - .bookmark-item > .toolbarbutton-icon, - .bookmark-item > .menu-iconic-left > .menu-iconic-icon { - image-rendering: -moz-crisp-edges; - } -} - -#wrapper-personal-bookmarks[place="palette"] > .toolbarpaletteitem-box { - background: url("chrome://browser/skin/places/bookmarksToolbar.png") no-repeat center; -} - -.bookmarks-toolbar-customize { - max-width: 15em !important; - list-style-image: url("chrome://browser/skin/places/bookmarksToolbar.png") !important; -} - -@media (min-resolution: 2dppx) { - #wrapper-personal-bookmarks[place="palette"] > .toolbarpaletteitem-box { - background-image: url("chrome://browser/skin/places/bookmarksToolbar@2x.png"); - background-size: 16px; - } - - .bookmarks-toolbar-customize { - list-style-image: url("chrome://browser/skin/places/bookmarksToolbar@2x.png") !important; - } - - .bookmarks-toolbar-customize > .toolbarbutton-icon { - width: 16px; - } -} - -/* ::::: bookmark menus ::::: */ - -.bookmark-item > .menu-iconic-left > .menu-iconic-icon { - width: 16px; - height: 16px; -} - -/* ::::: primary toolbar buttons ::::: */ - -.toolbarbutton-1 { - list-style-image: var(--toolbarbutton-image); -} - -toolbar[brighttext] .toolbarbutton-1 { - list-style-image: var(--toolbarbutton-inverted-image); -} - -.toolbarbutton-1[disabled=true] > .toolbarbutton-icon, -.toolbarbutton-1[disabled=true] > .toolbarbutton-menu-dropmarker, -.toolbarbutton-1[disabled=true] > .toolbarbutton-menubutton-dropmarker, -.toolbarbutton-1[disabled=true] > .toolbarbutton-menubutton-button > .toolbarbutton-icon, -.toolbarbutton-1 > .toolbarbutton-menubutton-button[disabled] > .toolbarbutton-icon { - opacity: .4; -} - -.toolbarbutton-1 > .toolbarbutton-menu-dropmarker, -.toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker { - list-style-image: url("chrome://browser/skin/toolbarbutton-dropdown-arrow.png"); -} - -toolbar[brighttext] .toolbarbutton-1 > .toolbarbutton-menu-dropmarker, -toolbar[brighttext] .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker { - list-style-image: url("chrome://browser/skin/toolbarbutton-dropdown-arrow-inverted.png"); -} - -.toolbarbutton-1 > .toolbarbutton-icon, -.toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon { - margin-inline-end: 0; -} - -toolbar[mode=full] .toolbarbutton-1:not([type=menu-button]) { - -moz-box-orient: vertical; -} - -toolbar[mode=full] .toolbarbutton-1, -toolbar[mode=full] .toolbarbutton-1 > .toolbarbutton-menubutton-button { - min-width: 57px; -} - -#nav-bar { - /* force iconsize="small" on this toolbar */ - counter-reset: smallicons; -} - -@navbarLargeIcons@ .toolbarbutton-1, -@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button { - -moz-appearance: none; - border: none; - padding: 0; - background: none; -} - -@navbarLargeIcons@ .toolbarbutton-1:not([type=menu-button]), -@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button, -@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker { - padding: 5px 2px; - -moz-box-pack: center; -} - -@navbarLargeIcons@ .toolbarbutton-1[type=menu]:not(#back-button):not(#forward-button):not(#feed-button) { - padding-left: 5px; - padding-right: 5px; -} - -@navbarLargeIcons@ .toolbarbutton-1 > menupopup { - margin-top: -3px; -} - -@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button { - padding-inline-end: 0; -} - -@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker { - padding-inline-start: 0; - -moz-box-align: center; -} - -@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-icon, -@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-badge-stack, -@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon, -@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon { - padding: 2px 6px; - background: var(--toolbarbutton-background-color) padding-box; - background-image: linear-gradient(hsla(0,0%,100%,.4), hsla(0,0%,100%,.1)); - background-clip: padding-box; - border-radius: var(--toolbarbutton-border-radius); - border: 1px solid; - border-color: var(--toolbarbutton-border-color) var(--toolbarbutton-border-color) var(--toolbarbutton-border-color); - box-shadow: 0 1px hsla(0,0%,100%,.05) inset, - 0 1px hsla(210,54%,20%,.05), - 0 0 2px hsla(210,54%,20%,.05); - transition-property: background-image, background-color, border-color, box-shadow; - transition-duration: 150ms; -} - -@navbarLargeIcons@ .toolbarbutton-1:not(:-moz-any(@primaryToolbarButtons@)) > .toolbarbutton-icon, -@navbarLargeIcons@ .toolbarbutton-1:not(:-moz-any(@primaryToolbarButtons@)) > .toolbarbutton-badge-stack, -@navbarLargeIcons@ .toolbarbutton-1:not(:-moz-any(@primaryToolbarButtons@)) > .toolbarbutton-menubutton-button > .toolbarbutton-icon { - padding: 3px 7px; -} - -@navbarLargeIcons@ .toolbarbutton-1[type=menu]:not(#back-button):not(#forward-button):not(#feed-button) > .toolbarbutton-icon, -@navbarLargeIcons@ .toolbarbutton-1[type=menu] > .toolbarbutton-text /* hack for add-ons that forcefully display the label */ { - padding-inline-end: 17px; -} - -@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menu-dropmarker { - margin-inline-start: -15px; -} - -@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon { - border-inline-end: none; -} - -@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon { - padding: 8px 5px 7px; -} - -@navbarLargeIcons@ .toolbarbutton-1:not(:hover):not(:active):not([open]) > .toolbarbutton-menubutton-dropmarker::before { - content: ""; - display: -moz-box; - width: 1px; - height: 18px; - margin-inline-end: -1px; - background-image: linear-gradient(var(--toolbarbutton-border-color) 0, var(--toolbarbutton-border-color) 18px); - background-clip: padding-box; - background-position: center; - background-repeat: no-repeat; - background-size: 1px 18px; - box-shadow: 0 0 0 1px hsla(0,0%,100%,.2); -} - -@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon:-moz-locale-dir(ltr), -@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon:-moz-locale-dir(rtl) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} - -@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon:-moz-locale-dir(rtl), -@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon:-moz-locale-dir(ltr) { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} - -@navbarLargeIcons@ .toolbarbutton-1:not([disabled]):-moz-any(:hover,[open]) > .toolbarbutton-menubutton-button > .toolbarbutton-icon, -@navbarLargeIcons@ .toolbarbutton-1:not([disabled]):hover > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon, -@navbarLargeIcons@ .toolbarbutton-1:not([disabled]):not([checked]):not([open]):not(:active):hover > .toolbarbutton-icon, -@navbarLargeIcons@ .toolbarbutton-1:not([disabled]):not([checked]):not([open]):not(:active):hover > .toolbarbutton-badge-stack, -@conditionalForwardWithUrlbar@ > .toolbarbutton-1:-moz-any([disabled],:not([open]):not([disabled]):not(:active)) > .toolbarbutton-icon { - background-image: linear-gradient(hsla(0,0%,100%,.8), hsla(0,0%,100%,.5)); - border-color: hsla(210,54%,20%,.25) hsla(210,54%,20%,.3) hsla(210,54%,20%,.35); - box-shadow: 0 1px hsla(0,0%,100%,.3) inset, - 0 1px hsla(210,54%,20%,.03), - 0 0 2px hsla(210,54%,20%,.1); - transition-property: background-image, background-color, border-color, box-shadow; - transition-duration: 150ms; -} - -@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled]):not([open]):not(:active):hover > .toolbarbutton-icon, -@navbarLargeIcons@ .toolbarbutton-1:not([buttonover]):not([open]):not(:active):hover > .toolbarbutton-menubutton-dropmarker:not([disabled]) > .dropmarker-icon, -@conditionalForwardWithUrlbar@ > #forward-button:not([open]):not(:active):not([disabled]):hover > .toolbarbutton-icon { - border-color: hsla(210,54%,20%,.3) hsla(210,54%,20%,.35) hsla(210,54%,20%,.4); - background-color: hsla(210,48%,96%,.75); - box-shadow: 0 0 1px hsla(210,54%,20%,.03), - 0 0 2px hsla(210,54%,20%,.1); -} - -@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled]):hover:active > .toolbarbutton-icon, -@navbarLargeIcons@ .toolbarbutton-1[open] > .toolbarbutton-menubutton-dropmarker:not([disabled]) > .dropmarker-icon, -@navbarLargeIcons@ .toolbarbutton-1:not([disabled]):-moz-any([open],[checked],:hover:active) > .toolbarbutton-icon, -@navbarLargeIcons@ .toolbarbutton-1:not([disabled]):-moz-any([open],[checked],:hover:active) > .toolbarbutton-badge-stack { - background-image: linear-gradient(hsla(0,0%,100%,.6), hsla(0,0%,100%,.1)); - background-color: hsla(210,54%,20%,.15); - border-color: hsla(210,54%,20%,.3) hsla(210,54%,20%,.35) hsla(210,54%,20%,.4); - box-shadow: 0 1px 1px hsla(210,54%,20%,.1) inset, - 0 0 1px var(--toolbarbutton-border-color) inset, - /* allows osx-keyhole-forward-clip-path to be used for non-hover as well as hover: */ - 0 1px 0 hsla(210,54%,20%,0), - 0 0 2px hsla(210,54%,20%,0); - text-shadow: none; - transition: none; -} - -@navbarLargeIcons@ .toolbarbutton-1:-moz-any(:hover,[open]) > .toolbarbutton-menubutton-dropmarker:not([disabled]) > .dropmarker-icon { - border-inline-start-color: hsla(210,54%,20%,.35); -} - -@navbarLargeIcons@ .toolbarbutton-1[checked]:not(:active):hover > .toolbarbutton-icon { - background-color: rgba(90%,90%,90%,.4); - transition: background-color .4s; -} - -:-moz-any(#TabsToolbar, #addon-bar) .toolbarbutton-1, -:-moz-any(#TabsToolbar, #addon-bar) .toolbarbutton-1 > .toolbarbutton-menubutton-button, -.tabbrowser-arrowscrollbox > .scrollbutton-up, -.tabbrowser-arrowscrollbox > .scrollbutton-down { - -moz-appearance: none; - border-style: none; - padding: 0 3px; -} - -#TabsToolbar .toolbarbutton-1:not([disabled]):hover, -#TabsToolbar .toolbarbutton-1[open], -#TabsToolbar .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled]):hover, -.tabbrowser-arrowscrollbox > .scrollbutton-up:not([disabled]):hover, -.tabbrowser-arrowscrollbox > .scrollbutton-down:not([disabled]):hover { - background-image: linear-gradient(var(--toolbar-highlight-bottom), var(--toolbar-highlight-top)), - linear-gradient(transparent, rgba(0,0,0,.25) 30%), - linear-gradient(transparent, rgba(0,0,0,.25) 30%); - background-position: 1px -1px, 0 -1px, 100% -1px; - background-size: calc(100% - 2px) 100%, 1px 100%, 1px 100%; - background-repeat: no-repeat; -} - -#addon-bar .toolbarbutton-1:not([disabled]):hover, -#addon-bar .toolbarbutton-1[open], -#addon-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled]):hover { - background-image: linear-gradient(to top, transparent, rgba(0,0,0,.15)), - linear-gradient(to top, transparent, rgba(0,0,0,.15) 30%), - linear-gradient(to top, transparent, rgba(0,0,0,.15) 30%); - background-position: left, left, right; - background-size: auto, 1px 100%, 1px 100%; - background-repeat: no-repeat; -} - -/* unified back/forward button */ - -#back-button { - -moz-image-region: rect(0, 18px, 18px, 0); -} - -#forward-button { - -moz-image-region: rect(0, 36px, 18px, 18px); -} - -#back-button:-moz-locale-dir(rtl) > .toolbarbutton-icon, -#forward-button:-moz-locale-dir(rtl), -#forward-button:-moz-locale-dir(rtl) > .toolbarbutton-text { - transform: scaleX(-1); -} - -@conditionalForwardWithUrlbar@ { - -moz-box-align: center; -} - -@conditionalForwardWithUrlbar@ > #forward-button { - padding: 0; -} - -@conditionalForwardWithUrlbar@ > #forward-button > menupopup { - margin-top: 1px; -} - -@conditionalForwardWithUrlbar@ > #forward-button > .toolbarbutton-icon { - /*mask: url(keyhole-forward-mask.svg#mask); XXX: this regresses twinopen */ - clip-path: url(chrome://browser/content/browser.xul#osx-keyhole-forward-clip-path); - margin-inline-start: -9px !important; - border-left-style: none; - border-radius: 0; - padding-left: 7px; - padding-right: 3px; -} - -@conditionalForwardWithUrlbar@:not([switchingtabs]) > #forward-button { - transition: opacity @forwardTransitionLength@ ease-out; -} - -@conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] { - /* opacity: 0; */ -} - -@conditionalForwardWithUrlbar@ > #back-button { - -moz-image-region: rect(18px, 20px, 38px, 0); - padding-top: 3px; - padding-bottom: 3px; - padding-inline-start: 5px; - padding-inline-end: 0; - position: relative; - z-index: 1; - border-radius: 0 10000px 10000px 0; -} - -@conditionalForwardWithUrlbar@ > #back-button:-moz-locale-dir(rtl) { - border-radius: 10000px 0 0 10000px; -} - -@conditionalForwardWithUrlbar@ > #back-button > menupopup { - margin-top: -1px; -} - -@conditionalForwardWithUrlbar@ > #back-button > .toolbarbutton-icon { - border-radius: 10000px; - padding: 5px; - border: none; - background-image: linear-gradient(hsla(0,0%,100%,.6), hsla(0,0%,100%,.1)); - box-shadow: 0 1px 0 hsla(0,0%,100%,.3) inset, - 0 0 0 1px hsla(0,0%,100%,.3) inset, - 0 0 0 1px hsla(210,54%,20%,.25), - 0 1px 0 hsla(210,54%,20%,.35); - transition-property: background-color, box-shadow; - transition-duration: 250ms; -} - -@conditionalForwardWithUrlbar@ > #back-button:not([disabled="true"]):not([open="true"]):not(:active):hover > .toolbarbutton-icon { - background-color: hsla(210,48%,96%,.75); - box-shadow: 0 1px 0 hsla(0,0%,100%,.3) inset, - 0 0 0 1px hsla(0,0%,100%,.3) inset, - 0 0 0 1px hsla(210,54%,20%,.3), - 0 1px 0 hsla(210,54%,20%,.4), - 0 0 4px var(--toolbarbutton-border-color); -} - -@conditionalForwardWithUrlbar@ > #back-button:not([disabled="true"]):hover:active > .toolbarbutton-icon, -@conditionalForwardWithUrlbar@ > #back-button[open="true"] > .toolbarbutton-icon { - background-color: hsla(210,54%,20%,.15); - box-shadow: 0 1px 1px hsla(210,54%,20%,.1) inset, - 0 0 1px var(--toolbarbutton-border-color) inset, - 0 0 0 1px hsla(210,54%,20%,.4), - 0 1px 0 var(--toolbarbutton-border-color); - transition: none; -} - -@conditionalForwardWithUrlbar@ > #back-button[disabled] > .toolbarbutton-icon { - box-shadow: 0 0 0 1px hsla(210,54%,20%,.55), - 0 1px 0 hsla(210,54%,20%,.65); - transition: none; -} - -.unified-nav-back[_moz-menuactive]:-moz-locale-dir(ltr), -.unified-nav-forward[_moz-menuactive]:-moz-locale-dir(rtl) { - list-style-image: url("chrome://browser/skin/menu-back.png") !important; -} - -.unified-nav-forward[_moz-menuactive]:-moz-locale-dir(ltr), -.unified-nav-back[_moz-menuactive]:-moz-locale-dir(rtl) { - list-style-image: url("chrome://browser/skin/menu-forward.png") !important; -} - -#stop-button { - -moz-image-region: rect(0, 54px, 18px, 36px); -} - -#reload-button { - -moz-image-region: rect(0, 72px, 18px, 54px); -} - -#home-button.bookmark-item { - list-style-image: var(--toolbarbutton-image); -} - -toolbar[brighttext] #home-button.bookmark-item { - list-style-image: var(--toolbarbutton-inverted-image); -} - -#home-button { - -moz-image-region: rect(0, 90px, 18px, 72px); -} - -#downloads-button { - -moz-image-region: rect(0, 108px, 18px, 90px); -} - -#history-button, -#history-menu-button { - -moz-image-region: rect(0, 126px, 18px, 108px); -} - -#bookmarks-button, -#bookmarks-menu-button { - -moz-image-region: rect(0, 144px, 18px, 126px); -} - -#bookmarks-menu-button.bookmark-item { - list-style-image: var(--toolbarbutton-image); -} - -toolbar[brighttext] #bookmarks-menu-button.bookmark-item { - list-style-image: var(--toolbarbutton-inverted-image); -} - -#print-button { - -moz-image-region: rect(0, 162px, 18px, 144px); -} - -#new-tab-button { - -moz-image-region: rect(0, 180px, 18px, 162px); -} - -#new-window-button { - -moz-image-region: rect(0, 198px, 18px, 180px); -} - -#cut-button { - -moz-image-region: rect(0, 216px, 18px, 198px); -} - -#copy-button { - -moz-image-region: rect(0, 234px, 18px, 216px); -} - -#paste-button { - -moz-image-region: rect(0, 252px, 18px, 234px); -} - -#fullscreen-button { - -moz-image-region: rect(0, 270px, 18px, 252px); -} - -#zoom-out-button { - -moz-image-region: rect(0, 288px, 18px, 270px); -} - -#zoom-in-button { - -moz-image-region: rect(0, 306px, 18px, 288px); -} - -#sync-button { - -moz-image-region: rect(0, 324px, 18px, 306px); -} -#sync-button[status="active"] { - list-style-image: url("chrome://browser/skin/sync-throbber.png"); - -moz-image-region: rect(0, 18px, 18px, 0); -} - -#feed-button { - -moz-image-region: rect(0, 342px, 18px, 324px); -} - -%ifdef MOZ_WEBRTC -#webrtc-status-button { - -moz-image-region: rect(0, 360px, 18px, 342px); -} -%endif - -/* ::::: Location Bar ::::: */ - -#urlbar, -.searchbar-textbox { - -moz-appearance: none; - margin: 1px 3px; - padding: 0; - background-clip: padding-box; - border: 1px solid ThreeDShadow; - border-radius: 2px; -} - -#urlbar { - width: 7em; - padding-inline-end: 2px; -} - -@media (-moz-mac-lion-theme) { - #urlbar, - .searchbar-textbox { - @navbarTextboxCustomBorder@ - } -} - -#urlbar:-moz-lwtheme, -.searchbar-textbox:-moz-lwtheme { - background-color: rgba(255,255,255,.8); - @navbarTextboxCustomBorder@ - color: black; -} - -@conditionalForwardWithUrlbar@ + #urlbar-container { - padding-left: @conditionalForwardWithUrlbarWidth@px; - margin-inline-start: -@conditionalForwardWithUrlbarWidth@px; - position: relative; - pointer-events: none; -} - -@conditionalForwardWithUrlbar@ + #urlbar-container > #urlbar { - border-inline-start: none; - margin-left: 0; - pointer-events: all; -} - -@conditionalForwardWithUrlbar@:not([switchingtabs]) + #urlbar-container > #urlbar { - transition: margin-left @forwardTransitionLength@ ease-out; -} - -@conditionalForwardWithUrlbar@ + #urlbar-container > #urlbar:-moz-locale-dir(ltr) { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} - -@conditionalForwardWithUrlbar@ + #urlbar-container > #urlbar:-moz-locale-dir(rtl) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} - -@conditionalForwardWithUrlbar@[forwarddisabled] + #urlbar-container { - clip-path: url("chrome://browser/content/browser.xul#windows-urlbar-back-button-clip-path"); -} - -@conditionalForwardWithUrlbar@ + #urlbar-container:-moz-locale-dir(rtl), -@conditionalForwardWithUrlbar@ + #urlbar-container > #urlbar:-moz-locale-dir(rtl) { - /* let windows-urlbar-back-button-mask clip the urlbar's right side for RTL */ - transform: scaleX(-1); -} - -html|*.urlbar-input:-moz-lwtheme::-moz-placeholder, -.searchbar-textbox:-moz-lwtheme > .autocomplete-textbox-container > .textbox-input-box > html|*.textbox-input::-moz-placeholder { - opacity: 1.0; - color: #777; -} - -#urlbar:-moz-lwtheme[focused="true"], -.searchbar-textbox:-moz-lwtheme[focused="true"] { - background-color: white; -} - -#urlbar-container { - -moz-box-orient: horizontal; - -moz-box-align: stretch; -} - -.urlbar-textbox-container { - -moz-box-align: stretch; -} - -.urlbar-input-box { - margin-inline-start: 0; - min-width: 4em; -} - -#urlbar-icons { - -moz-box-align: center; -} - -.urlbar-icon { - padding: 0 3px; -} - -.searchbar-engine-button, -.search-go-container { - padding: 2px 2px; -} - -.urlbar-icon:hover { - background-image: radial-gradient(circle closest-side, hsla(200,100%,70%,.3), hsla(200,100%,70%,0)); -} - -.urlbar-icon[open="true"], -.urlbar-icon:hover:active { - background-image: radial-gradient(circle closest-side, hsla(200,100%,70%,.1), hsla(200,100%,70%,0)); -} - -#urlbar-search-splitter { - min-width: 6px; - margin-inline-start: -3px; - border: none; - background: transparent; -} - -#urlbar-search-splitter + #urlbar-container > #urlbar , -#urlbar-search-splitter + #search-container > #searchbar > .searchbar-textbox { - margin-inline-start: 0; -} - -#urlbar-display-box { - border-inline-end: 1px solid #AAA; - margin-inline-end: 3px; -} - -#urlbar-display { - margin-top: 0; - margin-bottom: 0; - margin-inline-start: 0; - color: GrayText; -} - -/* identity box */ - -#identity-box { - padding: 2px; - font-size: .9em; -} - -#identity-box:-moz-locale-dir(ltr) { - border-top-left-radius: 1.5px; - border-bottom-left-radius: 1.5px; -} - -#identity-box:-moz-locale-dir(rtl) { - border-top-right-radius: 1.5px; - border-bottom-right-radius: 1.5px; -} - -#notification-popup-box:not([hidden]) + #identity-box { - padding-inline-start: 10px; - border-radius: 0; -} - -@conditionalForwardWithUrlbar@ + #urlbar-container > #urlbar > #identity-box { - border-radius: 0; -} - -#urlbar[pageproxystate="valid"] > #identity-box.verifiedIdentity { - color: hsl(92,100%,30%); - margin-inline-end: 4px; - background-image: -moz-linear-gradient(hsla(92,81%,16%,0), - hsla(92,81%,16%,.08) 25%, - hsla(92,81%,16%,.08) 75%, - hsla(92,81%,16%,0)); - background-position: right; - background-repeat: no-repeat; -} - -#urlbar[pageproxystate="valid"] > #identity-box.verifiedDomain { - color: rgb(0,79,168); - margin-inline-end: 4px; - background-image: -moz-linear-gradient(rgba(0,79,168,0), - rgba(0,79,168,.08) 25%, - rgba(0,79,168,.08) 75%, - rgba(0,79,168,0)); - background-position: right; - background-repeat: no-repeat; -} - -#urlbar[pageproxystate="valid"] > #identity-box.mixedContent { - color: rgb(79,79,0); - margin-inline-end: 4px; - background-image: -moz-linear-gradient(rgba(79,79,0,0), - rgba(79,79,0,.08) 25%, - rgba(79,79,0,.08) 75%, - rgba(79,79,0,0)); - background-position: right; - background-repeat: no-repeat; -} - -#identity-box.verifiedIdentity:-moz-locale-dir(rtl) { - background-position: left; -} - -#identity-box.verifiedIdentity:not(:-moz-lwtheme) { - background-color: #fff; - box-shadow: inset 0 0 2px rgb(0,168,0); -} - -#identity-box.verifiedDomain:not(:-moz-lwtheme) { - background-color: rgb(224,234,247); - box-shadow: inset 0 0 2px rgb(0,79,168); -} - -#identity-box:-moz-focusring { - outline: 1px dotted #000; - outline-offset: -3px; -} - -#identity-icon-labels { - padding-inline-start: 2px; - padding-inline-end: 5px; -} - -/* Address bar shading for SSL */ - -#urlbar[https_color="all"][security_level="broken"], -#urlbar[https_color="all"][security_level="low"] { - box-shadow: inset 0 0 4px rgb(168,0,0); -} - -#urlbar[https_color="all"][security_level="mixed"], -#urlbar[https_color="secure-mixed"][security_level="mixed"] { - box-shadow: inset 0 0 4px rgb(168,79,0); -} - -#urlbar[https_color="all"][security_level="high"], -#urlbar[https_color="secure-mixed"][security_level="high"], -#urlbar[https_color="secure-only"][security_level="high"] { - box-shadow: inset 0 0 4px rgb(0,79,168); -} - -#urlbar[https_color="all"][security_level="ev"], -#urlbar[https_color="secure-mixed"][security_level="ev"], -#urlbar[https_color="secure-only"][security_level="ev"] { - box-shadow: inset 0 0 4px rgb(0,168,0); -} - -#urlbar[https_color="all"]:-moz-lwtheme-darktext, -#urlbar[https_color="secure-mixed"]:-moz-lwtheme-darktext, -#urlbar[https_color="secure-only"]:-moz-lwtheme-darktext { - box-shadow: inset 0 0 2px; -} - - -/* Location bar dropmarker */ - -.urlbar-history-dropmarker { - -moz-appearance: none; - padding: 0 3px; - background-color: transparent; - border: none; - width: auto; - list-style-image: url("chrome://browser/skin/urlbar-history-dropmarker.png"); - -moz-image-region: rect(0px, 11px, 14px, 0px); -} - -.urlbar-history-dropmarker:hover { - background-image: radial-gradient(circle closest-side, hsla(205,100%,70%,.3), hsla(205,100%,70%,0)); - -moz-image-region: rect(0px, 22px, 14px, 11px); -} - -.urlbar-history-dropmarker:hover:active, -.urlbar-history-dropmarker[open="true"] { - background-image: radial-gradient(circle closest-side, hsla(205,100%,70%,.1), hsla(205,100%,70%,0)); - -moz-image-region: rect(0px, 33px, 14px, 22px); -} - -/* page proxy icon */ - -#page-proxy-favicon { - width: 16px; - height: 16px; - margin-top: 1px; - margin-bottom: 1px; - margin-inline-start: 3px; - margin-inline-end: 2px; - list-style-image: url(chrome://browser/skin/identity-icons-generic.png); - -moz-image-region: rect(0, 16px, 16px, 0); -} - -@conditionalForwardWithUrlbar@ + #urlbar-container > #urlbar > #identity-box > #page-proxy-favicon { - margin-inline-end: 1px; -} - -/* Since we already have a padlock, always use the generic icon until the favicon loads -.verifiedDomain > #page-proxy-favicon[pageproxystate="valid"] { - list-style-image: url(chrome://browser/skin/identity-icons-https.png); -} - -.verifiedIdentity > #page-proxy-favicon[pageproxystate="valid"] { - list-style-image: url(chrome://browser/skin/identity-icons-https-ev.png); -} - -.mixedActiveContent > #page-proxy-favicon[pageproxystate="valid"] { - list-style-image: url(chrome://browser/skin/identity-icons-https-mixed-active.png); -} -*/ - -#identity-box:hover > #page-proxy-favicon { - -moz-image-region: rect(0, 32px, 16px, 16px); -} - -#identity-box:hover:active > #page-proxy-favicon, -#identity-box[open=true] > #page-proxy-favicon { - -moz-image-region: rect(0, 48px, 16px, 32px); -} - -#page-proxy-favicon[pageproxystate="invalid"] { - opacity: 0.3; -} - -/* autocomplete */ - -#treecolAutoCompleteImage { - max-width: 36px; -} - -.ac-result-type-bookmark, -.autocomplete-treebody::-moz-tree-image(bookmark, treecolAutoCompleteImage) { - list-style-image: url("chrome://browser/skin/places/bookmark.png"); - -moz-image-region: rect(0px 48px 16px 32px); - width: 16px; - height: 16px; -} - -.ac-result-type-keyword, -.autocomplete-treebody::-moz-tree-image(keyword, treecolAutoCompleteImage) { - list-style-image: url(chrome://global/skin/icons/search-textbox.png); - margin: 2px; - width: 12px; - height: 12px; -} - -.ac-result-type-tag, -.autocomplete-treebody::-moz-tree-image(tag, treecolAutoCompleteImage) { - list-style-image: url("chrome://browser/skin/places/tag.png"); - width: 16px; - height: 16px; -} - -.ac-comment { - font-size: 1.06em; -} - -.ac-extra > .ac-comment { - font-size: 1em; -} - -.ac-url-text, -.ac-action-text { - font-size: 1em; - color: -moz-nativehyperlinktext; -} - -@media (-moz-mac-lion-theme) { - .ac-url-text:not([selected="true"]), - .ac-action-text:not([selected="true"]) { - color: #008800; - } -} - -richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-icon { - list-style-image: url("chrome://browser/skin/actionicon-tab.png"); - -moz-image-region: rect(0, 16px, 11px, 0); - padding: 0 3px; -} - -richlistitem[type~="action"][actiontype="switchtab"][selected="true"] > .ac-url-box > .ac-action-icon { - -moz-image-region: rect(11px, 16px, 22px, 0); -} - -.ac-comment[selected="true"], -.ac-url-text[selected="true"], -.ac-action-text[selected="true"] { - color: inherit !important; -} - -.autocomplete-treebody::-moz-tree-cell-text(treecolAutoCompleteComment) { - color: GrayText; -} - -.autocomplete-treebody::-moz-tree-cell-text(suggesthint, treecolAutoCompleteComment), -.autocomplete-treebody::-moz-tree-cell-text(suggestfirst, treecolAutoCompleteComment) -{ - color: GrayText; - font-size: smaller; -} - -.autocomplete-treebody::-moz-tree-cell(suggesthint) { - border-top: 1px solid GrayText; -} - -/* combined go/reload/stop button in location bar */ - -#go-button, -#urlbar > toolbarbutton { - -moz-appearance: none; - padding: 0 2px; - background-origin: border-box; - border: none; - list-style-image: url("chrome://browser/skin/reload-stop-go.png"); -} - -#go-button { - padding: 0 3px; -} - -#urlbar-reload-button { - -moz-image-region: rect(0, 14px, 14px, 0); -} - -#urlbar-reload-button:not([disabled]):hover { - background-image: radial-gradient(circle closest-side, hsla(200,100%,70%,.2), hsla(200,100%,70%,0)); - -moz-image-region: rect(14px, 14px, 28px, 0); -} - -#urlbar-reload-button:not([disabled]):hover:active { - background-image: radial-gradient(circle closest-side, hsla(200,100%,60%,.1), hsla(200,100%,60%,0)); - -moz-image-region: rect(28px, 14px, 42px, 0); -} - -#urlbar-reload-button:-moz-locale-dir(rtl) > .toolbarbutton-icon { - transform: scaleX(-1); -} - -#go-button, -#urlbar-go-button { - -moz-image-region: rect(0, 42px, 14px, 28px); -} - -#go-button:hover, -#urlbar-go-button:hover { - background-image: radial-gradient(circle closest-side, hsla(110,70%,50%,.2), hsla(110,70%,50%,0)); - -moz-image-region: rect(14px, 42px, 28px, 28px); -} - -#go-button:hover:active, -#urlbar-go-button:hover:active { - background-image: radial-gradient(circle closest-side, hsla(110,70%,50%,.1), hsla(110,70%,50%,0)); - -moz-image-region: rect(28px, 42px, 42px, 28px); -} - -#go-button:-moz-locale-dir(rtl) > .toolbarbutton-icon, -#urlbar-go-button:-moz-locale-dir(rtl) > .toolbarbutton-icon { - transform: scaleX(-1); -} - -#urlbar-stop-button { - -moz-image-region: rect(0, 28px, 14px, 14px); -} - -#urlbar-stop-button:not([disabled]):hover { - background-image: radial-gradient(circle closest-side, hsla(5,100%,75%,.3), hsla(5,100%,75%,0)); - -moz-image-region: rect(14px, 28px, 28px, 14px); -} - -#urlbar-stop-button:hover:active { - background-image: radial-gradient(circle closest-side, hsla(5,100%,75%,.1), hsla(5,100%,75%,0)); - -moz-image-region: rect(28px, 28px, 42px, 14px); -} - -/* popup blocker button */ - -#page-report-button { - list-style-image: url("chrome://browser/skin/urlbar-popup-blocked.png"); - -moz-image-region: rect(0, 16px, 16px, 0); -} - -#page-report-button:hover { - -moz-image-region: rect(0, 32px, 16px, 16px); -} - -#page-report-button:hover:active, -#page-report-button[open="true"] { - -moz-image-region: rect(0, 48px, 16px, 32px); -} - - -/* star button */ - -#star-button { - list-style-image: url("chrome://browser/skin/places/bookmark.png"); - -moz-image-region: rect(0px 16px 16px 0px); -} - -#star-button:hover { - background-image: radial-gradient(circle closest-side, hsla(45,100%,73%,.3), hsla(45,100%,73%,0)); - -moz-image-region: rect(0px 32px 16px 16px); -} - -#star-button:hover:active { - background-image: radial-gradient(circle closest-side, hsla(45,100%,73%,.1), hsla(45,100%,73%,0)); - -moz-image-region: rect(0px 48px 16px 32px); -} - -#star-button[starred] { - list-style-image: url("chrome://browser/skin/places/editBookmark.png"); -} - -/* bookmarking panel */ - -#editBookmarkPanelStarIcon { - list-style-image: url("chrome://browser/skin/places/starred48.png"); - width: 48px; - height: 48px; -} - -#editBookmarkPanelStarIcon[unstarred] { - list-style-image: url("chrome://browser/skin/places/unstarred48.png"); -} - -#editBookmarkPanelTitle { - font-size: 130%; -} - -#editBookmarkPanelHeader, -#editBookmarkPanelContent { - margin-bottom: .5em; -} - -/* Implements editBookmarkPanel resizing on folderTree un-collapse. */ -#editBMPanel_folderTree { - min-width: 27em; -} - -/* BOOKMARKING PANEL */ -#editBookmarkPanelStarIcon { - list-style-image: url("chrome://browser/skin/places/starred48.png"); - width: 48px; - height: 48px; -} - -#editBookmarkPanelStarIcon[unstarred] { - list-style-image: url("chrome://browser/skin/places/unstarred48.png"); -} - -#editBookmarkPanelTitle { - font-size: 130%; - font-weight: bold; -} - -#editBMPanel_rows > row { - margin-bottom: 8px; -} - -#editBMPanel_rows > row:last-of-type { - margin-bottom: 0; -} - -/**** Input elements ****/ - -#editBMPanel_rows > row > textbox, -#editBMPanel_rows > row > hbox > textbox { - -moz-appearance: none; - background: linear-gradient(#fafafa, #fff); - background-clip: padding-box; - border-radius: 3px; - border: 1px solid rgba(0,0,0,.3) !important; - box-shadow: inset 0 1px 1px 1px rgba(0,0,0,.05), - 0 1px rgba(255,255,255,.3); - margin: 0; - padding: 3px 6px; -} - -#editBMPanel_rows > row > textbox[focused="true"], -#editBMPanel_rows > row > hbox > textbox[focused="true"] { - border-color: -moz-mac-focusring !important; - box-shadow: @focusRingShadow@; -} - -/**** HUD style buttons ****/ - -.editBookmarkPanelHeaderButton, -.editBookmarkPanelBottomButton { - @hudButton@ - margin: 0; - min-width: 82px; - min-height: 22px; -} - -.editBookmarkPanelHeaderButton:hover:active, -.editBookmarkPanelBottomButton:hover:active { - @hudButtonPressed@ -} - -.editBookmarkPanelHeaderButton:-moz-focusring, -.editBookmarkPanelBottomButton:-moz-focusring { - @hudButtonFocused@ -} - -.editBookmarkPanelBottomButton[default="true"] { - background-color: #666; -} - -#editBookmarkPanelHeader { - margin-bottom: 6px; -} - -.editBookmarkPanelBottomButton:last-child { - margin-inline-start: 8px; -} - -/* The following elements come from editBookmarkOverlay.xul. Styling that's - specific to the editBookmarkPanel should be in browser.css. Styling that - should be shared by all editBookmarkOverlay.xul consumers should be in - editBookmarkOverlay.css. */ - -#editBMPanel_newFolderBox { - background: linear-gradient(#fff, #f2f2f2); - background-origin: padding-box; - background-clip: padding-box; - border-radius: 0 0 3px 3px; - border: 1px solid #a5a5a5; - box-shadow: inset 0 1px rgba(255,255,255,.8), - inset 0 0 1px rgba(255,255, 255,.25), - 0 1px rgba(255,255,255,.3); - margin: 0; - padding: 0; - height: 20px; -} - -#editBMPanel_newFolderButton { - -moz-appearance: none; - border: 0 solid #a5a5a5; - border-inline-end-width: 1px; - padding: 0 9px; - margin: 0; - min-width: 21px; - min-height: 20px; - height: 20px; - color: #fff; - list-style-image: url("chrome://browser/skin/panel-plus-sign.png"); - position: relative; -} - -#editBMPanel_newFolderButton:hover:active { - background: linear-gradient(rgba(40,40,40,.9), rgba(70,70,70,.9)); - box-shadow: inset 0 0 3px rgba(0,0,0,.2), inset 0 1px 7px rgba(0,0,0,.4); -} - -#editBMPanel_newFolderButton:-moz-focusring { - @hudButtonFocused@ -} - -#editBMPanel_newFolderButton .button-text { - display: none; -} - -#editBMPanel_folderMenuList { - @hudButton@ - background-clip: padding-box; - margin: 0; - min-height: 22px; - padding-top: 2px; - padding-bottom: 1px; - padding-inline-start: 8px; - padding-inline-end: 4px; -} - -#editBMPanel_folderMenuList:-moz-focusring { - @hudButtonFocused@ -} - -#editBMPanel_folderMenuList[open="true"], -#editBMPanel_folderMenuList:hover:active { - @hudButtonPressed@ -} - -#editBMPanel_folderMenuList > .menulist-dropmarker { - -moz-appearance: none; - display: -moz-box; - background-color: transparent; - border: 0; - margin: 0; - padding: 0; - padding-inline-end: 4px; - width: 7px; -} - -#editBMPanel_folderMenuList > .menulist-dropmarker > .dropmarker-icon { - list-style-image: url("chrome://global/skin/icons/panel-dropmarker.png"); -} - -/**** folder tree and tag selector ****/ - -#editBMPanel_folderTree, -#editBMPanel_tagsSelector { - -moz-appearance: none; - background: linear-gradient(#fafafa, #fff); - background-clip: padding-box; - border-radius: 3px; - border: 1px solid rgba(0,0,0,.3); - box-shadow: inset 0 1px 1px 1px rgba(0,0,0,.05), - 0 1px rgba(255,255,255,.3); - margin: 0; -} - -#editBMPanel_folderTree:-moz-focusring, -#editBMPanel_tagsSelector:-moz-focusring { - border-color: -moz-mac-focusring; - box-shadow: @focusRingShadow@; -} - -#editBMPanel_folderTree { - border-bottom: none; - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; - /* Implements editBookmarkPanel resizing on folderTree un-collapse. */ - margin: 0 !important; - min-width: 27em; - position: relative; -} - -/**** expanders ****/ - -#editBookmarkPanel .expander-up, -#editBookmarkPanel .expander-down { - @hudButton@ - margin: 0; - margin-inline-start: 4px; - min-width: 27px; - min-height: 22px; -} - -#editBookmarkPanel .expander-up:-moz-focusring, -#editBookmarkPanel .expander-down:-moz-focusring { - @hudButtonFocused@ -} - -#editBookmarkPanel .expander-up:hover:active, -#editBookmarkPanel .expander-down:hover:active { - @hudButtonPressed@ -} - -#editBookmarkPanel .expander-up { - list-style-image: url("chrome://browser/skin/panel-expander-open.png"); -} - -#editBookmarkPanel .expander-down { - list-style-image: url("chrome://browser/skin/panel-expander-closed.png"); -} - -#editBookmarkPanel .expander-up > .button-box > .button-icon, -#editBookmarkPanel .expander-down > .button-box > .button-icon { - margin: 1px 0 0; -} - -#editBookmarkPanel .expander-up > .button-box > .button-text, -#editBookmarkPanel .expander-down > .button-box > .button-text { - display: none; -} - -@media (min-resolution: 2dppx) { - #editBookmarkPanel .expander-up { - list-style-image: url("chrome://browser/skin/panel-expander-open@2x.png"); - } - - #editBookmarkPanel .expander-down { - list-style-image: url("chrome://browser/skin/panel-expander-closed@2x.png"); - } - - #editBookmarkPanel .expander-up > .button-box > .button-icon, - #editBookmarkPanel .expander-down > .button-box > .button-icon { - width: 9px; - } -} - -#editBMPanel_tagsField > .autocomplete-textbox-container > .textbox-input-box > html|*.textbox-input::-moz-placeholder { - opacity: 1.0; - color: #bbb; -} - -.editBMPanel_rowLabel { - text-align: end; -} - -/* ::::: content area ::::: */ - -#sidebar { - background-color: Window; -} - -#sidebar-title { - padding-inline-start: 0px; -} - -/* ::::: throbber ::::: */ - -#navigator-throbber { - width: 16px; - min-height: 16px; - margin: 0 3px; -} - -#navigator-throbber[busy="true"] { - list-style-image: url("chrome://global/skin/icons/loading_16.png"); -} - -#navigator-throbber, -#wrapper-navigator-throbber > #navigator-throbber { - list-style-image: url("chrome://global/skin/icons/notloading_16.png"); -} - -/* Tabstrip */ - -#TabsToolbar { - min-height: 0; - padding: 0; -} - -#TabsToolbar:not(:-moz-lwtheme), -#TabsToolbar[tabsontop=false] { - background-image: linear-gradient(to top, @toolbarShadowColor@ 1px, rgba(0,0,0,.05) 1px, transparent 50%); -} - -/* When the tab bar is collapsed, show a 1px border in its place. */ -#TabsToolbar[tabsontop="false"][collapsed="true"]:not([customizing="true"]) { - visibility: visible; - height: 1px; - border-bottom-width: 1px; - /* !important here to override border-style: none on the toolbar */ - border-bottom-style: solid !important; - border-bottom-color: ThreeDShadow; - overflow: hidden; -} - -@media (-moz-mac-lion-theme) { - #main-window[sizemode=normal] #TabsToolbar { - padding-left: 2px; - padding-right: 2px; - } -} - -/* remove 5 pixel border on left and right of browser screen */ -.tabbrowser-tabbox { - margin: 0; -} - -.tabbrowser-tab, -.tabs-newtab-button { - -moz-appearance: none; - background: @toolbarShadowOnTab@, var(--tab-background), - linear-gradient(var(--toolbar-custom-color), var(--toolbar-custom-color)); - background-clip: padding-box; - padding: 3px 1px 4px; - /* Setting a transparent outer border allows us to have a 1px gap - between the tabs and the top edge of the screen, even when the - tabs have a top margin of 0, which is important for Fitts' law - compliance */ - border: 1.6px solid; - border-bottom: none; - border-radius: var(--tab-border-radius) var(--tab-border-radius) 0px 0px; - -moz-border-top-colors: transparent #929292; - -moz-border-left-colors: transparent #929292; - -moz-border-right-colors: transparent #929292; - /* Hide the transparent top border by default */ - margin-top: -1px; - /* Reduce the gap between the tabs */ - margin-inline-start: -1px; - box-shadow: var(--tab-box-shadow); -} - -.tabbrowser-tab { - padding-inline-end: 3px; -} - -/* Override the default (globally-set) tab width values; increase - by 2px to compensate for the transparent outer border of the tabs */ -.tabbrowser-tab:not([pinned]) { - max-width: 252px; - min-width: 102px; -} - -/* When the tabs are on top and the window is maximized or in full- - screen mode, unhide the transparent top border of the tabs so we - have a 1px gap between the tabs and the top edge of the screen */ -#main-window[sizemode="maximized"][tabsontop=true] .tabbrowser-tab, -#main-window[sizemode="maximized"][tabsontop=true] .tabs-newtab-button, -#main-window[sizemode="fullscreen"][tabsontop=true] .tabbrowser-tab, -#main-window[sizemode="fullscreen"][tabsontop=true] .tabs-newtab-button { - margin-top: 0px; -} - -.tabbrowser-tab:hover, -.tabs-newtab-button:hover { - background-image: @toolbarShadowOnTab@, var(--tab-background-hover), - linear-gradient(var(--toolbar-custom-color), var(--toolbar-custom-color)); -} - -.tabbrowser-tab[selected="true"] { - background-image: linear-gradient(var(--tab-selected-highlight), var(--toolbar-highlight-top) 50%), - linear-gradient(var(--toolbar-custom-color), var(--toolbar-custom-color)); -} - -#main-window[tabsontop=false]:not([disablechrome]) .tabbrowser-tab[selected=true]:not(:-moz-lwtheme) { - background-image: @toolbarShadowOnTab@, - linear-gradient(var(--tab-selected-highlight), var(--toolbar-highlight-top) 50%), - linear-gradient(var(--toolbar-custom-color), var(--toolbar-custom-color)); -} - -.tabbrowser-tab[visuallyselected=true]:not(:-moz-lwtheme) { - /* overriding tabbox.css */ - color: inherit; -} - -.tabbrowser-tab[visuallyselected=true] { - /* overriding tabbox.css */ - text-shadow: inherit; -} - -/* Remove highlight fuzz on dark themes */ -.tabbrowser-tab:-moz-lwtheme-brighttext, -.tabs-newtab-button:-moz-lwtheme-brighttext { - box-shadow:none; - -moz-border-top-colors: transparent #707070; - -moz-border-left-colors: transparent #707070; - -moz-border-right-colors: transparent #707070; -} - -.tabbrowser-tab[selected="true"]:-moz-lwtheme { - background-image: linear-gradient(var(--tab-selected-highlight), var(--toolbar-highlight-top) 50%); -} - -.tabbrowser-tab[selected="true"]:-moz-lwtheme-brighttext { - background-image: linear-gradient(rgba(128,128,128,.9), rgba(32,32,32,.9) 50%, rgba(32,32,32,.9) 80%, var(--toolbar-highlight-top) 100%); - -moz-border-top-colors: transparent #D0D0D0; - -moz-border-left-colors: transparent #D0D0D0; - -moz-border-right-colors: transparent #D0D0D0; -} - -.tabbrowser-tab:-moz-lwtheme-brighttext:not([selected="true"]), -.tabs-newtab-button:-moz-lwtheme-brighttext { - background-image: linear-gradient(hsla(0,0%,25%,.4), hsla(0,0%,15%,.6) 80%); -} - -.tabbrowser-tab:-moz-lwtheme-brighttext:not([selected="true"]):hover, -.tabs-newtab-button:-moz-lwtheme-brighttext:hover { - background-image: linear-gradient(hsla(0,0%,60%,.4), hsla(0,0%,10%,.8) 80%); -} - -.tabbrowser-tab:-moz-lwtheme-darktext:not([selected="true"]), -.tabs-newtab-button:-moz-lwtheme-darktext { - background-image: linear-gradient(hsla(0,0%,75%,.4), hsla(0,0%,85%,.6) 80%); -} - -.tabbrowser-tab:-moz-lwtheme-darktext:not([selected="true"]):hover, -.tabs-newtab-button:-moz-lwtheme-darktext:hover { - background-image: linear-gradient(hsla(0,0%,60%,.4), hsla(0,0%,90%,.8) 80%); -} - -.tabbrowser-tab[pinned][titlechanged]:not([selected="true"]) { - background-image: radial-gradient(circle farthest-corner at 50% 3px, rgba(255,255,255,1) 3%, rgba(186,221,251,.75) 40%, rgba(127,179,255,.5) 80%, rgba(127,179,255,.25)); -} -.tabbrowser-tab[pinned][titlechanged]:not([selected="true"]):hover { - background-image: linear-gradient(hsla(0,0%,100%,.4), hsla(0,0%,75%,.4) 80%), - radial-gradient(circle farthest-corner at 50% 3px, rgba(255,255,255,1) 3%, rgba(186,221,251,.75) 40%, rgba(127,179,255,.5) 80%, rgba(127,179,255,.25)); -} - -.tab-throbber, -.tab-icon-image { - width: 16px; - height: 16px; - list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png"); - margin-inline-start: 2px; - margin-inline-end: 3px; -} - -.tab-throbber { - list-style-image: url("chrome://browser/skin/tabbrowser/connecting.png"); -} - -.tab-throbber[progress] { - list-style-image: url("chrome://browser/skin/tabbrowser/loading.png"); -} - -.tab-throbber[pinned], -.tab-icon-image[pinned] { - margin-inline-start: 5px; - margin-inline-end: 5px; -} - -/* tabbrowser-tab focus ring */ -.tabbrowser-tab:focus > .tab-stack { - outline: 1px dotted; -} - -/* Tab DnD indicator */ -.tab-drop-indicator { - list-style-image: url(chrome://browser/skin/tabbrowser/tabDragIndicator.png); - margin-bottom: -11px; -} - -/* Tab close button */ -.tab-close-button { - -moz-appearance: none; - border: none; - padding: 0px; -} - -.tab-close-button:-moz-lwtheme-brighttext { - list-style-image: url("chrome://global/skin/icons/close-inverted.png"); -} - -@media (min-resolution: 2dppx) { - .tab-close-button:-moz-lwtheme-brighttext { - list-style-image: url("chrome://global/skin/icons/close-inverted@2x.png"); - } -} - -/* Tab sound indicator */ -.tab-icon-sound { - margin-inline-start: 4px; - width: 16px; - height: 16px; - padding: 0; -} - -.allTabs-endimage[soundplaying], -.tab-icon-sound[soundplaying] { - list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio.svg#tab-audio"); -} - -.allTabs-endimage[muted], -.tab-icon-sound[muted] { - list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio.svg#tab-audio-muted"); -} - -.allTabs-endimage[blocked], -.tab-icon-sound[blocked] { - list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio.svg#tab-audio-blocked"); -} - -#TabsToolbar:-moz-lwtheme-brighttext .tab-icon-sound[soundplaying], -#TabsToolbar:-moz-lwtheme-brighttext .tab-icon-sound[blocked], -#TabsToolbar:-moz-lwtheme-brighttext .tab-icon-sound[muted] { - filter: invert(1); -} - -.tab-icon-sound[soundplaying-scheduledremoval]:not([muted]):not(:hover), -.tab-icon-overlay[soundplaying-scheduledremoval]:not([muted]):not(:hover) { - transition: opacity .3s linear var(--soundplaying-removal-delay); - opacity: 0; -} - -/* Tab icon overlay */ -.tab-icon-overlay { - width: 16px; - height: 16px; - margin-top: -8px; - margin-inline-start: -15px; - margin-inline-end: -1px; - position: relative; -} - -.tab-icon-overlay[soundplaying], -.tab-icon-overlay[muted]:not([crashed]), -.tab-icon-overlay[blocked]:not([crashed]) { - border-radius: 10px; -} - -.tab-icon-overlay[soundplaying]:hover, -.tab-icon-overlay[muted]:not([crashed]):hover, -.tab-icon-overlay[blocked]:not([crashed]):hover { - background-color: white; -} - -.tab-icon-overlay[soundplaying] { - list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio"); -} - -.tab-icon-overlay[muted] { - list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio-muted"); -} - -.tab-icon-overlay[blocked] { - list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio-blocked"); -} - -#TabsToolbar:-moz-lwtheme-brighttext .tab-icon-overlay[soundplaying]:not([selected]):not(:hover), -.tab-icon-overlay[soundplaying][selected]:-moz-lwtheme-brighttext:not(:hover) { - list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio-white"); -} - -#TabsToolbar:-moz-lwtheme-brighttext .tab-icon-overlay[muted]:not([crashed]):not([selected]):not(:hover), -.tab-icon-overlay[muted][selected]:-moz-lwtheme-brighttext:not(:hover) { - list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio-white-muted"); -} - -#TabsToolbar:-moz-lwtheme-brighttext .tab-icon-overlay[blocked]:not([crashed]):not([selected]):not(:hover), -.tab-icon-overlay[blocked][selected]:-moz-lwtheme-brighttext:not(:hover) { - list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio-white-blocked"); -} - -/* Tab scrollbox arrow, tabstrip new tab and all-tabs buttons */ - -.tabbrowser-arrowscrollbox > .scrollbutton-up, -.tabbrowser-arrowscrollbox > .scrollbutton-down { - list-style-image: url("chrome://browser/skin/tabbrowser/tab-arrow-left.png"); - margin: 0; - padding-right: 2px; - border-right: 2px solid transparent; - background-origin: border-box; -} - -toolbar[brighttext] .tabbrowser-arrowscrollbox > .scrollbutton-up, -toolbar[brighttext] .tabbrowser-arrowscrollbox > .scrollbutton-down { - list-style-image: url(chrome://browser/skin/tabbrowser/tab-arrow-left-inverted.png); -} - -.tabbrowser-arrowscrollbox > .scrollbutton-up[disabled], -.tabbrowser-arrowscrollbox > .scrollbutton-down[disabled] { - opacity: .4; -} - -.tabbrowser-arrowscrollbox > .scrollbutton-up:-moz-locale-dir(rtl), -.tabbrowser-arrowscrollbox > .scrollbutton-down:-moz-locale-dir(ltr) { - transform: scaleX(-1); -} - -.tabbrowser-arrowscrollbox > .scrollbutton-down { - transition: 1s background-color ease-out; -} - -.tabbrowser-arrowscrollbox > .scrollbutton-down[notifybgtab] { - background-color: Highlight; - transition: none; -} - -.tabbrowser-arrowscrollbox > .scrollbutton-up:not([disabled]), -.tabbrowser-arrowscrollbox > .scrollbutton-down:not([disabled]) { - border-width: 0 2px 0 0; - border-style: solid; - border-image: url("chrome://browser/skin/tabbrowser/tab-overflow-border.png") 0 2 0 2 fill; -} - -.tabs-newtab-button > .toolbarbutton-icon { - margin-top: -1px; - margin-bottom: -1px; -} - -.tabs-newtab-button, -#TabsToolbar > #new-tab-button, -#TabsToolbar > toolbarpaletteitem > #new-tab-button { - list-style-image: url(chrome://browser/skin/tabbrowser/newtab.png); - -moz-image-region: auto; -} - -.tabs-newtab-button:-moz-lwtheme-brighttext, -toolbar[brighttext] #TabsToolbar > #new-tab-button, -toolbar[brighttext] #TabsToolbar > toolbarpaletteitem > #new-tab-button { - list-style-image: url(chrome://browser/skin/tabbrowser/newtab-inverted.png); -} - -.tabs-newtab-button { - width: 28px; -} - -#TabsToolbar > #new-tab-button { - width: 26px; -} - -#alltabs-button { - list-style-image: url("chrome://browser/skin/tabbrowser/alltabs.png"); - -moz-image-region: rect(0, 14px, 16px, 0); -} - -#alltabs-button[type="menu"] { - list-style-image: url("chrome://browser/skin/toolbarbutton-dropdown-arrow.png"); - -moz-image-region: auto; -} - -toolbar[brighttext] #alltabs-button { - list-style-image: url("chrome://browser/skin/tabbrowser/alltabs-inverted.png"); -} - -toolbar[brighttext] #alltabs-button[type="menu"] { - list-style-image: url("chrome://browser/skin/toolbarbutton-dropdown-arrow-inverted.png"); -} - -#alltabs-button[type="menu"] > .toolbarbutton-icon { - margin: 0 2px; -} - -#alltabs-button[type="menu"] > .toolbarbutton-menu-dropmarker { - display: none; -} - -/* All tabs menupopup */ -.alltabs-item > .menu-iconic-left > .menu-iconic-icon { - list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png"); -} - -.alltabs-item[selected="true"] { - font-weight: bold; -} - -.alltabs-item[busy] > .menu-iconic-left > .menu-iconic-icon { - list-style-image: url("chrome://global/skin/icons/loading_16.png"); -} - -.alltabs-item[tabIsVisible] { - /* box-shadow instead of background-color to work around native styling */ - box-shadow: inset -5px 0 ThreeDShadow; -} - -/* Tabstrip close button */ -.tabs-closebutton { - -moz-appearance: none; - padding: 4px 2px; - margin: 0px; - border: none; -} - -toolbar[brighttext] .tabs-closebutton { - list-style-image: url("chrome://global/skin/icons/close-inverted.png"); -} - -@media (min-resolution: 2dppx) { - toolbar[brighttext] .tabs-closebutton { - list-style-image: url("chrome://global/skin/icons/close-inverted@2x.png"); - } -} - -.tabs-closebutton > .toolbarbutton-icon { - margin-inline-end: 0px !important; - padding-inline-end: 2px !important; - padding-inline-start: 2px !important; -} - -#sidebar-throbber[loading="true"] { - list-style-image: url("chrome://global/skin/icons/loading_16.png"); - margin-inline-end: 4px; -} - -/* Pale Moon: Feed icon */ -#ub-feed-button, -#ub-feed-button > .button-box, -#ub-feed-button:hover:active > .button-box { - padding: 0px; - margin: 0px; - border: 0px; - background-color: transparent !important; -} - -#ub-feed-button { - -moz-appearance: none; - min-width: 0px; - list-style-image: url("chrome://browser/skin/feeds/feed-icons-16.png"); - -moz-image-region: rect(0px 16px 16px 0px); -} - -#ub-feed-button:hover { - -moz-image-region: rect(0px 32px 16px 16px); -} - -#ub-feed-button[open="true"], -#ub-feed-button:hover:active { - -moz-image-region: rect(0px 48px 16px 32px); -} - - -/* Bookmarks toolbar */ -#PlacesToolbarDropIndicator { - list-style-image: url(chrome://browser/skin/places/toolbarDropMarker.png); -} - -toolbarbutton.bookmark-item[dragover="true"][open="true"] { - -moz-appearance: none; - background: Highlight !important; - color: HighlightText !important; -} - -/* rules for menupopup drop indicators */ -.menupopup-drop-indicator-bar { - position: relative; - /* these two margins must together compensate the indicator's height */ - margin-top: -1px; - margin-bottom: -1px; -} - -.menupopup-drop-indicator { - list-style-image: none; - height: 2px; - margin-inline-end: -4em; - background-color: Highlight; -} - -/* ::::: Identity Indicator Styling ::::: */ - -/* Popup Icons */ -#identity-popup-icon { - height: 64px; - width: 64px; - padding: 0; - list-style-image: url("chrome://browser/skin/identity.png"); - -moz-image-region: rect(0px, 64px, 64px, 0px); -} - -#identity-popup.verifiedDomain > #identity-popup-container > #identity-popup-icon { - -moz-image-region: rect(64px, 64px, 128px, 0px); -} - -#identity-popup.verifiedIdentity > #identity-popup-container > #identity-popup-icon { - -moz-image-region: rect(128px, 64px, 192px, 0px); -} - -/* Popup Body Text */ -.identity-popup-description { - white-space: pre-wrap; - padding-inline-start: 15px; - margin: 2px 0 4px; -} - -.identity-popup-label { - white-space: pre-wrap; - padding-inline-start: 15px; - margin: 0; -} - -#identity-popup-content-host, -#identity-popup-content-box.verifiedIdentity > #identity-popup-content-owner { - font-size: 1.2em; -} - -#identity-popup-content-host { - margin-top: 3px; - margin-bottom: 5px; - font-weight: bold; - max-width: 300px; -} - -#identity-popup-content-owner { - margin-top: 4px; - margin-bottom: 0 !important; - font-weight: bold; - max-width: 300px; -} - -.verifiedDomain > #identity-popup-content-owner { - font-weight: normal; -} - -#identity-popup-content-verifier { - margin: 4px 0 2px; -} - -#identity-popup-content-box.verifiedIdentity > #identity-popup-encryption , -#identity-popup-content-box.verifiedDomain > #identity-popup-encryption { - margin-top: 10px; - margin-inline-start: -24px; -} - -#identity-popup-content-box.verifiedIdentity > #identity-popup-encryption > vbox > #identity-popup-encryption-icon , -#identity-popup-content-box.verifiedDomain > #identity-popup-encryption > vbox > #identity-popup-encryption-icon { - list-style-image: url("chrome://browser/skin/Secure24.png"); -} - -#identity-popup-more-info-button { - margin-top: 6px; - margin-bottom: 0; - margin-inline-end: 0; -} - -.popup-notification-icon { - width: 64px; - height: 64px; - margin-inline-end: 10px; -} - -.popup-notification-icon[popupid="geolocation"] { - list-style-image: url(chrome://browser/skin/Geolocation-64.png); -} - -.popup-notification-icon[popupid="xpinstall-disabled"], -.popup-notification-icon[popupid="addon-progress"], -.popup-notification-icon[popupid="addon-install-cancelled"], -.popup-notification-icon[popupid="addon-install-blocked"], -.popup-notification-icon[popupid="addon-install-origin-blocked"], -.popup-notification-icon[popupid="addon-install-failed"], -.popup-notification-icon[popupid="addon-install-complete"] { - list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric.png); - width: 32px; - height: 32px; -} - -.popup-notification-icon[popupid="click-to-play-plugins"] { - list-style-image: url(chrome://mozapps/skin/plugins/pluginBlocked-64.png); -} - -.popup-notification-icon[popupid="web-notifications"] { - list-style-image: url(chrome://browser/skin/notification-64.png); -} - -.addon-progress-description { - width: 350px; - max-width: 350px; -} - -.popup-progress-label, -.popup-progress-meter { - margin-inline-start: 0; - margin-inline-end: 0; -} - -.popup-progress-cancel { - -moz-appearance: none; - background: transparent; - border: none; - padding: 0; - min-height: 16px; - min-width: 16px; - max-height: 16px; - max-width: 16px; - margin: 0 1px 0 1px; - list-style-image: url(chrome://mozapps/skin/downloads/buttons.png); - -moz-image-region: rect(0px, 16px, 16px, 0px); -} - -.popup-progress-cancel:hover { - -moz-image-region: rect(16px, 32px, 32px, 16px); -} - -.popup-progress-cancel:active { - -moz-image-region: rect(32px, 32px, 48px, 16px); -} - -.popup-notification-icon[popupid="indexedDB-permissions-prompt"], -.popup-notification-icon[popupid="indexedDB-quota-prompt"], -.popup-notification-icon[popupid*="offline-app-requested"], -.popup-notification-icon[popupid="offline-app-usage"] { - list-style-image: url(chrome://global/skin/icons/question-64.png); -} - -.popup-notification-icon[popupid="password"] { - list-style-image: url(chrome://mozapps/skin/passwordmgr/key-64.png); -} - -.popup-notification-icon[popupid="mixed-content-blocked"] { - list-style-image: url(chrome://browser/skin/mixed-content-blocked-64.png); -} - -%ifdef MOZ_WEBRTC -.popup-notification-icon[popupid="webRTC-sharingDevices"], -.popup-notification-icon[popupid="webRTC-shareDevices"] { - list-style-image: url(chrome://browser/skin/webRTC-shareDevice-64.png); -} - -%endif -.popup-notification-icon[popupid="pointerLock"] { - list-style-image: url(chrome://browser/skin/pointerLock-64.png); -} - -/* Notification icon box */ -#notification-popup-box { - position: relative; - background-color: #fff; - background-clip: padding-box; - padding-left: 3px; - border-radius: var(--toolbarbutton-border-radius) 0 0 var(--toolbarbutton-border-radius); - border-width: 0 8px 0 0; - border-style: solid; - border-image: url("chrome://browser/skin/urlbar-arrow.png") 0 8 0 0 fill; - margin-inline-end: -8px; -} - -@conditionalForwardWithUrlbar@[forwarddisabled] + #urlbar-container > #urlbar > #notification-popup-box { - padding-left: 5px; -} - -#notification-popup-box:-moz-locale-dir(rtl), -.notification-anchor-icon:-moz-locale-dir(rtl) { - transform: scaleX(-1); -} - -.notification-anchor-icon { - width: 16px; - height: 16px; - margin: 0 2px; -} - -.notification-anchor-icon:-moz-focusring { - outline: 1px dotted -moz-DialogText; - outline-offset: -3px; -} - -.default-notification-icon, -#default-notification-icon { - list-style-image: url(chrome://global/skin/icons/information-16.png); -} - -.geo-notification-icon, -#geo-notification-icon { - list-style-image: url(chrome://browser/skin/Geolocation-16.png); -} - -#addons-notification-icon { - list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric-16.png); -} - -.indexedDB-notification-icon, -#indexedDB-notification-icon { - list-style-image: url(chrome://global/skin/icons/question-16.png); -} - -#password-notification-icon { - list-style-image: url(chrome://mozapps/skin/passwordmgr/key-16.png); -} - -#plugins-notification-icon { - list-style-image: url(chrome://browser/skin/notification-pluginNormal.png); -} - -#alert-plugins-notification-icon { - list-style-image: url(chrome://browser/skin/notification-pluginAlert.png); -} - -#blocked-plugins-notification-icon { - list-style-image: url(chrome://browser/skin/notification-pluginBlocked.png); -} - -#plugins-notification-icon, -#alert-plugins-notification-icon, -#blocked-plugins-notification-icon { - -moz-image-region: rect(0, 16px, 16px, 0); -} - -#plugins-notification-icon:hover, -#alert-plugins-notification-icon:hover, -#blocked-plugins-notification-icon:hover { - -moz-image-region: rect(0, 32px, 16px, 16px); -} - -#plugins-notification-icon:active, -#alert-plugins-notification-icon:active, -#blocked-plugins-notification-icon:active { - -moz-image-region: rect(0, 48px, 16px, 32px); -} - -#notification-popup-box[hidden] { - /* Override display:none to make the pluginBlockedNotification animation work - when showing the notification repeatedly. */ - display: -moz-box; - visibility: collapse; -} - -#blocked-plugins-notification-icon[showing] { - animation: pluginBlockedNotification 500ms ease 0s 5 alternate both; -} - -@keyframes pluginBlockedNotification { - from { - opacity: 0; - } - to { - opacity: 1; - } -} - -.mixed-content-blocked-notification-icon, -#mixed-content-blocked-notification-icon { - list-style-image: url(chrome://browser/skin/mixed-content-blocked-16.png); -} - -%ifdef MOZ_WEBRTC -.webRTC-shareDevices-notification-icon, -#webRTC-shareDevices-notification-icon { - list-style-image: url(chrome://browser/skin/webRTC-shareDevice-16.png); -} - -.webRTC-sharingDevices-notification-icon, -#webRTC-sharingDevices-notification-icon { - list-style-image: url(chrome://browser/skin/webRTC-sharingDevice-16.png); -} -%endif - -.web-notifications-notification-icon, -#web-notifications-notification-icon { - list-style-image: url(chrome://browser/skin/web-notifications-tray.svg); - -moz-image-region: rect(0, 16px, 16px, 0); -} - -.web-notifications-notification-icon:hover, -#web-notifications-notification-icon:hover { - -moz-image-region: rect(0, 32px, 16px, 16px); -} - -.web-notifications-notification-icon:hover:active, -#web-notifications-notification-icon:hover:active { - -moz-image-region: rect(0, 48px, 16px, 32px); -} - -#pointerLock-notification-icon { - list-style-image: url(chrome://browser/skin/pointerLock-16.png); -} -#pointerLock-cancel { - margin: 0px; -} - -#identity-popup-container { - min-width: 280px; -} - -/* Bookmarks roots menu-items */ -#appmenu_subscribeToPage:not([disabled]), -#appmenu_subscribeToPageMenu, -#subscribeToPageMenuitem:not([disabled]), -#subscribeToPageMenupopup, -#BMB_subscribeToPageMenuitem:not([disabled]), -#BMB_subscribeToPageMenupopup { - list-style-image: url("chrome://browser/skin/feeds/feedIcon16.png"); -} - -#appmenu_bookmarksToolbar, -#bookmarksToolbarFolderMenu, -#BMB_bookmarksToolbar { - list-style-image: url("chrome://browser/skin/places/bookmarksToolbar.png"); - -moz-image-region: auto; -} - -@media (min-resolution: 2dppx) { - #bookmarksToolbarFolderMenu, - #BMB_bookmarksToolbar { - list-style-image: url("chrome://browser/skin/places/bookmarksToolbar@2x.png"); - -moz-image-region: auto; - } -} - -#appmenu_unsortedBookmarks, -#BMB_unsortedBookmarks { - list-style-image: url("chrome://browser/skin/places/unsortedBookmarks.png"); - -moz-image-region: auto; -} - -/* ::::: Keyboard UI Panel ::::: */ - -.KUI-panel { - -moz-appearance: none; - background: rgba(27%,27%,27%,.9) url(KUI-background.png) repeat-x; - color: white; - border-style: none; - border-radius: 20px; -} - -.KUI-panel[level="top"] { - background-color: rgba(27%,27%,27%,.65); -} - -.KUI-panel-closebutton { - list-style-image: url(KUI-close.png); - -moz-appearance: none; - border: none; - padding: 0; - width: 24px; - height: 24px; -} - -.KUI-panel-closebutton:not(:hover) { - opacity: .6; -} - -.KUI-panel-closebutton > .toolbarbutton-icon { - margin: 0; -} - -/* ::::: Ctrl-Tab and All Tabs Panels ::::: */ - -/* Ctrl-Tab */ - -#ctrlTab-panel { - padding: 20px 10px 10px; - font-weight: bold; - text-shadow: 0 0 1px rgb(27%,27%,27%), 0 0 2px rgb(27%,27%,27%); -} - -.ctrlTab-favicon[src] { - background-color: white; - width: 20px; - height: 20px; - padding: 2px; -} - -.ctrlTab-preview-inner > .tabPreview-canvas { - box-shadow: 1px 1px 2px rgb(12%,12%,12%); -} - -.ctrlTab-preview:not(#ctrlTab-showAll) > * > .ctrlTab-preview-inner > .tabPreview-canvas { - margin-bottom: 2px; -} - -.ctrlTab-preview-inner { - padding-bottom: 10px; -} - -#ctrlTab-showAll:not(:focus) > * > .ctrlTab-preview-inner { - padding: 10px; - background-color: rgba(255,255,255,.2); - border-radius: .5em; -} - -.ctrlTab-preview:focus > * > .ctrlTab-preview-inner { - color: white; - background-color: rgba(0,0,0,.6); - text-shadow: none; - padding: 8px; - border: 2px solid white; - border-radius: .5em; -} - -.ctrlTab-preview:not(#ctrlTab-showAll):focus > * > .ctrlTab-preview-inner { - margin: -10px -10px 0; -} - -#ctrlTab-showAll { - margin-top: .5em; -} - -/* All Tabs */ - -#allTabs-panel { - padding-bottom: 10px; - -moz-appearance: none; - border: none; - background: -moz-dialog; - color: -moz-dialogText; -} - -#allTabs-meta { - margin: 10px; -} - -#allTabs-filter { - margin-inline-start: 24px; - margin-inline-end: 0; -} - -#allTabs-tab-close-button > .toolbarbutton-icon { - margin: 0; -} - -/* Make sure the allTab previews always have regular close buttons */ -#allTabs-tab-close-button:-moz-lwtheme-brighttext { - list-style-image: url("chrome://global/skin/icons/close.png"); -} - -.allTabs-favicon[src] { - background-color: -moz-dialog; - width: 22px; - height: 22px; - padding-top: 1px; - padding-bottom: 5px; - padding-inline-start: 1px; - padding-inline-end: 5px; - margin-top: -2px; - margin-inline-start: -2px; - border-bottom-right-radius: 4px; -} - -.allTabs-favicon[src]:-moz-locale-dir(rtl) { - border-bottom-right-radius: 0; - border-bottom-left-radius: 4px; -} - -.allTabs-preview-inner > .tabPreview-canvas { - background-color: rgb(60%,60%,60%); - box-shadow: 0 0 1.5px ThreeDShadow; -} - -.allTabs-preview:not(:hover):not([closebuttonhover]) > html|canvas { - opacity: .8; -} - -.allTabs-preview:focus > * > .allTabs-preview-inner { - outline: 1px dotted -moz-dialogText; -} - -/* Add-on bar */ - -#addon-bar { - -moz-appearance: none; - min-height: 20px; - border-top-style: none; - border-bottom-style: none; - padding-top: 1px; - background-image: linear-gradient(rgba(0,0,0,.15) 1px, rgba(255,255,255,.15) 1px); - background-size: 100% 2px; - background-repeat: no-repeat; -} - -#status-bar { - -moz-appearance: none; - background-color: transparent; - border: none; - min-height: 0; -} - -#addon-bar[customizing] > #status-bar { - opacity: .5; - background-image: repeating-linear-gradient(135deg, - rgba(255,255,255,.3), rgba(255,255,255,.3) 5px, - rgba(0,0,0,.3) 5px, rgba(0,0,0,.3) 10px); -} - -#status-bar > statusbarpanel { - border-width: 0; - -moz-appearance: none; -} - -#addonbar-closebutton { - border: none; - padding: 0 5px; - -moz-appearance: none; -} - -toolbar[brighttext] #addonbar-closebutton { - list-style-image: url("chrome://global/skin/icons/close-inverted.png"); -} - -@media (min-resolution: 2dppx) { - toolbar[brighttext] #addonbar-closebutton { - list-style-image: url("chrome://global/skin/icons/close-inverted@2x.png"); - } -} - -/* Status panel */ - -.statuspanel-label { - margin: 0; - padding: 2px 4px; - background: linear-gradient(#fff, #ddd); - border: 1px none #ccc; - border-top-style: solid; - color: #333; - text-shadow: none; -} - -.statuspanel-label:-moz-locale-dir(ltr):not([mirror]), -.statuspanel-label:-moz-locale-dir(rtl)[mirror] { - border-right-style: solid; - /* disabled for triggering grayscale AA (bug 659213) - border-top-right-radius: .3em; - */ - margin-right: 1em; -} - -.statuspanel-label:-moz-locale-dir(rtl):not([mirror]), -.statuspanel-label:-moz-locale-dir(ltr)[mirror] { - border-left-style: solid; - /* disabled for triggering grayscale AA (bug 659213) - border-top-left-radius: .3em; - */ - margin-left: 1em; -} - -#full-screen-warning-message { - background-color: hsl(0,0%,15%); - color: white; - border-radius: 8px; - margin-top: 30px; - padding: 30px 50px; - box-shadow: 0 0 2px white; -} - -.full-screen-description { - font-size: 150%; -} - -#full-screen-domain-text { - font-size: 300%; -} - -%ifdef MOZ_DEVTOOLS -%include ../../../../devtools/client/themes/responsivedesign.inc.css -%include ../../../../devtools/client/themes/commandline.inc.css -%endif -%include ../shared/plugin-doorhanger.inc.css - -%ifdef MOZ_DEVTOOLS -/* Error counter */ - -#developer-toolbar-toolbox-button[error-count]:before { - color: #FDF3DE; - min-width: 16px; - text-shadow: none; - background-image: linear-gradient(#B4211B, #8A1915); - border-radius: 1px; - margin-inline-end: 5px; -} -%endif - -.toolbarbutton-badge-stack { - margin: 0; - padding: 0; - position: relative; -} - -@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-badge-stack { - padding: 2px 5px; -} - -.toolbarbutton-1 > .toolbarbutton-badge-stack > .toolbar-icon { - position: absolute; - top: 2px; - right: 2px; -} - -.toolbarbutton-badge-stack > .toolbarbutton-icon[label]:not([label=""]) { - margin-inline-end: 0; -} - -@navbarLargeIcons@ *|* > .toolbarbutton-badge[badge]:not([badge=""])::after { - top: 1px; - right: 1px; -} - -.toolbarbutton-badge[badge]:not([badge=""]):-moz-locale-dir(rtl)::after { - left: 0; - right: auto; -} - -@navbarLargeIcons@ *|* > .toolbarbutton-badge[badge]:not([badge=""]):-moz-locale-dir(rtl)::after { - left: 1px; - right: auto; -} - -%ifdef MOZ_CAN_DRAW_IN_TITLEBAR -#main-window[privatebrowsingmode=temporary] { - background-image: url("chrome://browser/skin/privatebrowsing-mask.png"); - background-position: top right; - background-repeat: no-repeat; - background-color: moz-mac-chrome-active; -} - -@media (min-resolution: 2dppx) { - #main-window[privatebrowsingmode=temporary] { - background-image: url("chrome://browser/skin/privatebrowsing-mask@2x.png"); - background-size: 38px; - } -} - -#main-window[privatebrowsingmode=temporary] { - background-position: top right 40px; -} - -#main-window[privatebrowsingmode=temporary][inFullscreen] { - background-position: top right 10px; -} - -#main-window[privatebrowsingmode=temporary]:-moz-locale-dir(rtl) { - background-position: top left 70px; -} - -#main-window[privatebrowsingmode=temporary][inFullscreen]:-moz-locale-dir(rtl) { - background-position: top left 10px; -} - -#main-window[privatebrowsingmode=temporary]:-moz-window-inactive { - background-color: -moz-mac-chrome-inactive; -} - -#main-window[privatebrowsingmode=temporary][inFullscreen] #nav-bar[tabsontop=false] { - padding-inline-end: 50px !important; -} - -@media (-moz-mac-lion-theme) { - #main-window[privatebrowsingmode=temporary][inFullscreen] #TabsToolbar[tabsontop=true] { - padding-inline-end: 50px; - } -} - -@media not all and (-moz-mac-lion-theme) { - #main-window[privatebrowsingmode=temporary] { - background-position: top right 10px; - } - - #main-window[privatebrowsingmode=temporary][inFullscreen][tabsontop=true] #window-controls { - padding-inline-end: 50px; - } -} -%else -#main-window[privatebrowsingmode=temporary] #TabsToolbar::before { - display: -moz-box; - content: ""; - background: url("chrome://browser/skin/privatebrowsing-dark.png") center no-repeat; - width: 30px; - color: inherit; -} -%endif \ No newline at end of file diff --git a/application/palemoon/themes/osx/click-to-play-warning-stripes.png b/application/palemoon/themes/osx/click-to-play-warning-stripes.png deleted file mode 100644 index 29f15f7b8c..0000000000 Binary files a/application/palemoon/themes/osx/click-to-play-warning-stripes.png and /dev/null differ diff --git a/application/palemoon/themes/osx/communicator/communicator.css b/application/palemoon/themes/osx/communicator/communicator.css deleted file mode 100644 index 0b57574fd2..0000000000 --- a/application/palemoon/themes/osx/communicator/communicator.css +++ /dev/null @@ -1,6 +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/. */ - -@import url("chrome://global/skin/"); - diff --git a/application/palemoon/themes/osx/communicator/jar.mn b/application/palemoon/themes/osx/communicator/jar.mn deleted file mode 100644 index 612d133352..0000000000 --- a/application/palemoon/themes/osx/communicator/jar.mn +++ /dev/null @@ -1,7 +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/. - -browser.jar: -% skin communicator classic/1.0 %skin/classic/communicator/ - skin/classic/communicator/communicator.css diff --git a/application/palemoon/themes/osx/communicator/moz.build b/application/palemoon/themes/osx/communicator/moz.build deleted file mode 100644 index ecb79e730d..0000000000 --- a/application/palemoon/themes/osx/communicator/moz.build +++ /dev/null @@ -1,6 +0,0 @@ -# -*- Mode: python; c-basic-offset: 4; 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/. - -JAR_MANIFESTS += ['jar.mn'] \ No newline at end of file diff --git a/application/palemoon/themes/osx/downloads/allDownloadsViewOverlay.css b/application/palemoon/themes/osx/downloads/allDownloadsViewOverlay.css deleted file mode 100644 index 0cfc5f81be..0000000000 --- a/application/palemoon/themes/osx/downloads/allDownloadsViewOverlay.css +++ /dev/null @@ -1,146 +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/. */ - -#downloadsRichListBox { - /** The default listbox appearance comes with an unwanted margin. **/ - -moz-appearance: none; - margin: 0; -} - -#downloadsRichListBox > richlistitem.download { - height: 6em; - padding: 5px 8px; -} - -.downloadTypeIcon { - margin-inline-end: 8px; - /* explicitly size the icon, so size doesn't vary on hidpi systems */ - height: 32px; - width: 32px; -} - -.blockedIcon { - list-style-image: url("chrome://global/skin/icons/Error.png"); -} - -.downloadTarget { - margin-bottom: 3px; - cursor: inherit; -} - -.downloadDetails { - opacity: 0.7; - font-size: 95%; - cursor: inherit; -} - -.downloadButton { - -moz-appearance: none; - background: transparent; - min-width: 0; - min-height: 0; - margin: 3px; - border: none; - padding: 5px; - list-style-image: url("chrome://browser/skin/downloads/buttons.png"); -} - -/*** Button icons ***/ - -.downloadButton.downloadCancel { - -moz-image-region: rect(0px, 16px, 16px, 0px); -} - -richlistitem.download:hover > .downloadButton.downloadCancel { - -moz-image-region: rect(0px, 32px, 16px, 16px); -} - -richlistitem.download:hover > .downloadButton.downloadCancel:hover { - -moz-image-region: rect(0px, 48px, 16px, 32px); -} - -richlistitem.download:hover > .downloadButton.downloadCancel:active { - -moz-image-region: rect(0px, 64px, 16px, 48px); -} - -.downloadButton.downloadShow { - -moz-image-region: rect(16px, 16px, 32px, 0px); -} - -richlistitem.download:hover > .downloadButton.downloadShow { - -moz-image-region: rect(16px, 32px, 32px, 16px); -} - -richlistitem.download:hover > .downloadButton.downloadShow:hover { - -moz-image-region: rect(16px, 48px, 32px, 32px); -} - -richlistitem.download:hover > .downloadButton.downloadShow:active { - -moz-image-region: rect(16px, 64px, 32px, 48px); -} - -.downloadButton.downloadRetry { - -moz-image-region: rect(32px, 16px, 48px, 0px); -} - -richlistitem.download:hover > .downloadButton.downloadRetry { - -moz-image-region: rect(32px, 32px, 48px, 16px); -} - -richlistitem.download:hover > .downloadButton.downloadRetry:hover { - -moz-image-region: rect(32px, 48px, 48px, 32px); -} - -richlistitem.download:hover > .downloadButton.downloadRetry:active { - -moz-image-region: rect(32px, 64px, 48px, 48px); -} - -richlistitem.download[selected] > .downloadButton.downloadCancel { - -moz-image-region: rect(0px, 80px, 16px, 64px); -} - -richlistitem.download[selected]:hover > .downloadButton.downloadCancel { - -moz-image-region: rect(0px, 96px, 16px, 80px); -} - -richlistitem.download[selected]:hover > .downloadButton.downloadCancel:hover { - -moz-image-region: rect(0px, 112px, 16px, 96px); -} - -richlistitem.download[selected]:hover > .downloadButton.downloadCancel:active { - -moz-image-region: rect(0px, 128px, 16px, 112px); -} - -richlistitem.download[selected] > .downloadButton.downloadShow { - -moz-image-region: rect(16px, 80px, 32px, 64px); -} - -richlistitem.download[selected]:hover > .downloadButton.downloadShow { - -moz-image-region: rect(16px, 96px, 32px, 80px); -} - -richlistitem.download[selected]:hover > .downloadButton.downloadShow:hover { - -moz-image-region: rect(16px, 112px, 32px, 96px); -} - -richlistitem.download[selected]:hover > .downloadButton.downloadShow:active { - -moz-image-region: rect(16px, 128px, 32px, 112px); -} - -richlistitem.download[selected] > .downloadButton.downloadRetry { - -moz-image-region: rect(32px, 80px, 48px, 64px); -} - -richlistitem.download[selected]:hover > .downloadButton.downloadRetry { - -moz-image-region: rect(32px, 96px, 48px, 80px); -} - -richlistitem.download[selected]:hover > .downloadButton.downloadRetry:hover { - -moz-image-region: rect(32px, 112px, 48px, 96px); -} - -richlistitem.download[selected]:hover > .downloadButton.downloadRetry:active { - -moz-image-region: rect(32px, 128px, 48px, 112px); -} - diff --git a/application/palemoon/themes/osx/downloads/buttons.png b/application/palemoon/themes/osx/downloads/buttons.png deleted file mode 100644 index ca87b401b2..0000000000 Binary files a/application/palemoon/themes/osx/downloads/buttons.png and /dev/null differ diff --git a/application/palemoon/themes/osx/downloads/contentAreaDownloadsView.css b/application/palemoon/themes/osx/downloads/contentAreaDownloadsView.css deleted file mode 100644 index ece99eacd3..0000000000 --- a/application/palemoon/themes/osx/downloads/contentAreaDownloadsView.css +++ /dev/null @@ -1,22 +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/. */ - -@import url("chrome://global/skin/inContentUI.css"); - -.downloadButton { - box-shadow: none; -} - -.downloadButton:not([disabled="true"]):hover:active, -.downloadButton:not([disabled]):hover:active { - background: transparent; - border: none; - box-shadow: none; -} - -#downloadsListEmptyDescription { - margin: 1em; - text-align: center; - color: GrayText; -} diff --git a/application/palemoon/themes/osx/downloads/download-notification-finish.png b/application/palemoon/themes/osx/downloads/download-notification-finish.png deleted file mode 100644 index 5194f5d59a..0000000000 Binary files a/application/palemoon/themes/osx/downloads/download-notification-finish.png and /dev/null differ diff --git a/application/palemoon/themes/osx/downloads/download-notification-start.png b/application/palemoon/themes/osx/downloads/download-notification-start.png deleted file mode 100644 index bd548b1838..0000000000 Binary files a/application/palemoon/themes/osx/downloads/download-notification-start.png and /dev/null differ diff --git a/application/palemoon/themes/osx/downloads/download-summary.png b/application/palemoon/themes/osx/downloads/download-summary.png deleted file mode 100644 index 67003c7d7a..0000000000 Binary files a/application/palemoon/themes/osx/downloads/download-summary.png and /dev/null differ diff --git a/application/palemoon/themes/osx/downloads/downloads.css b/application/palemoon/themes/osx/downloads/downloads.css deleted file mode 100644 index 2f9733a98e..0000000000 --- a/application/palemoon/themes/osx/downloads/downloads.css +++ /dev/null @@ -1,396 +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/. */ - -/*** Panel and outer controls ***/ - -#downloadsPanel > .panel-arrowcontainer > .panel-arrowcontent { - padding: 0; -} - -#downloadsListBox { - background-color: transparent; - padding: 4px; - color: inherit; -} - -#downloadsPanel:not([hasdownloads]) > #downloadsListBox { - display: none; -} - -#downloadsPanel[hasdownloads] > #emptyDownloads { - display: none; -} - -#emptyDownloads { - padding: 10px 20px; - max-width: 40ch; -} - -#downloadsHistory { - background: transparent; - color: -moz-nativehyperlinktext; - cursor: pointer; -} - -#downloadsPanel[keyfocus] > #downloadsFooter > #downloadsHistory:focus { - outline: 1px -moz-dialogtext dotted; - outline-offset: -1px; -} - -#downloadsHistory > .button-box { - border: none; - margin: 1em; -} - -@media (-moz-mac-lion-theme) { - #downloadsFooter { - background-color: hsla(216,45%,88%,.98); - box-shadow: 0px 1px 2px rgb(204,214,234) inset; - border-bottom-left-radius: 3px; - border-bottom-right-radius: 3px; - } -} - -/*** Downloads Summary and List items ***/ - -#downloadsSummary, -richlistitem[type="download"] { - height: 7em; - padding-inline-end: 0; - color: inherit; -} - -#downloadsSummary { - padding: 8px 38px 8px 12px; - cursor: pointer; - -moz-user-focus: normal; -} - -#downloadsPanel[keyfocus] > #downloadsFooter > #downloadsSummary:focus { - outline: 1px -moz-dialogtext dotted; - outline-offset: -5px; -} - -#downloadsSummary > .downloadTypeIcon { - list-style-image: url("chrome://browser/skin/downloads/download-summary.png"); -} - -#downloadsSummaryDescription { - color: -moz-nativehyperlinktext; -} - -richlistitem[type="download"] { - margin: 0; - border-top: 1px solid hsla(0,0%,100%,.3); - border-bottom: 1px solid hsla(220,18%,51%,.25); - background: transparent; - padding: 8px; -} - -richlistitem[type="download"]:first-child { - border-top: 1px solid transparent; -} - -@media (-moz-mac-lion-theme) { - richlistitem[type="download"]:last-child { - border-bottom: 1px solid transparent; - } -} - -#downloadsPanel[keyfocus] > #downloadsListBox:focus > richlistitem[type="download"][selected] { - outline: 1px -moz-dialogtext dotted; - outline-offset: -1px; -} - -.downloadTypeIcon { - margin-inline-end: 8px; - /* Prevent flickering when changing states. */ - height: 32px; - width: 32px; -} - -.blockedIcon { - list-style-image: url("chrome://global/skin/icons/Error.png"); -} - -/* We hold .downloadDisplayName, .downloadProgress and .downloadDetails - inside of a vbox with class .downloadContainer. We set the font-size of - the entire container to 90% because: - - 1) This is the size that we want .downloadDetails to be - 2) The container's width is set by localizers by &downloadDetails.width;, - which is a ch unit. Since this is the value that should control the - panel width, we apply it to the outer container to constrain - .downloadDisplayName and .downloadProgress. - - Finally, since we want .downloadDisplayName's font-size to be at 100% of - the font-size of .downloadContainer's parent, we use calc to go from the - smaller font-size back to the original font-size. - */ -#downloadsSummaryDetails, -.downloadContainer { - font-size: 90%; -} - -#downloadsSummaryDescription, -.downloadDisplayName { - margin-bottom: 6px; - cursor: inherit; -} - -.downloadDisplayName { - font-size: calc(100%/0.9); -} - -#downloadsSummaryDetails, -.downloadDetails { - opacity: 0.6; - cursor: inherit; -} - -.downloadButton { - -moz-appearance: none; - min-width: 0; - min-height: 0; - margin: 3px; - border: none; - background: transparent; - padding: 5px; - list-style-image: url("chrome://browser/skin/downloads/buttons.png"); -} - -.downloadButton > .button-box { - border: 1px solid transparent; - padding: 0; -} - -#downloadsPanel[keyfocus] .downloadButton:focus > .button-box { - border: 1px dotted ThreeDDarkShadow; -} - -/*** Highlighted list items ***/ - -#downloadsPanel:not([keyfocus]) > #downloadsListBox > richlistitem[type="download"][state="1"][exists]:hover { - border-radius: 3px; - border-top: 1px solid hsla(0,0%,100%,.2); - border-bottom: 1px solid hsla(0,0%,0%,.2); - background-color: Highlight; - color: HighlightText; - cursor: pointer; -} - -/*** Button icons ***/ - -.downloadButton.downloadCancel { - -moz-image-region: rect(0px, 16px, 16px, 0px); -} -richlistitem[type="download"]:hover > stack > .downloadButton.downloadCancel { - -moz-image-region: rect(0px, 32px, 16px, 16px); -} -richlistitem[type="download"]:hover > stack > .downloadButton.downloadCancel:hover { - -moz-image-region: rect(0px, 48px, 16px, 32px); -} -richlistitem[type="download"]:hover > stack > .downloadButton.downloadCancel:active { - -moz-image-region: rect(0px, 64px, 16px, 48px); -} - -.downloadButton.downloadShow { - -moz-image-region: rect(16px, 16px, 32px, 0px); -} -richlistitem[type="download"]:hover > stack > .downloadButton.downloadShow { - -moz-image-region: rect(16px, 32px, 32px, 16px); -} -richlistitem[type="download"]:hover > stack > .downloadButton.downloadShow:hover { - -moz-image-region: rect(16px, 48px, 32px, 32px); -} -richlistitem[type="download"]:hover > stack > .downloadButton.downloadShow:active { - -moz-image-region: rect(16px, 64px, 32px, 48px); -} -#downloadsPanel[keyfocus] > #downloadsListBox > richlistitem[type="download"][state="1"]:hover > stack > .downloadButton.downloadShow { - -moz-image-region: rect(16px, 32px, 32px, 16px); -} -#downloadsPanel[keyfocus] > #downloadsListBox > richlistitem[type="download"][state="1"]:hover > stack > .downloadButton.downloadShow:hover { - -moz-image-region: rect(16px, 48px, 32px, 32px); -} -#downloadsPanel[keyfocus] > #downloadsListBox > richlistitem[type="download"][state="1"]:hover > stack > .downloadButton.downloadShow:active { - -moz-image-region: rect(16px, 64px, 32px, 48px); -} -#downloadsPanel:not([keyfocus]) > #downloadsListBox > richlistitem[type="download"][state="1"]:hover > stack > .downloadButton.downloadShow { - -moz-image-region: rect(16px, 96px, 32px, 80px); -} -#downloadsPanel:not([keyfocus]) > #downloadsListBox > richlistitem[type="download"][state="1"]:hover > stack > .downloadButton.downloadShow:hover { - -moz-image-region: rect(16px, 112px, 32px, 96px); -} -#downloadsPanel:not([keyfocus]) > #downloadsListBox > richlistitem[type="download"][state="1"]:hover > stack > .downloadButton.downloadShow:active { - -moz-image-region: rect(16px, 128px, 32px, 112px); -} - -.downloadButton.downloadRetry { - -moz-image-region: rect(32px, 16px, 48px, 0px); -} -richlistitem[type="download"]:hover > stack > .downloadButton.downloadRetry { - -moz-image-region: rect(32px, 32px, 48px, 16px); -} -richlistitem[type="download"]:hover > stack > .downloadButton.downloadRetry:hover { - -moz-image-region: rect(32px, 48px, 48px, 32px); -} -richlistitem[type="download"]:hover > stack > .downloadButton.downloadRetry:active { - -moz-image-region: rect(32px, 64px, 48px, 48px); -} - -/*** Status and progress indicator ***/ - -#downloads-indicator-anchor { - /* Makes the outermost stack element positioned, so that its contents are - rendered over the main browser window in the Z order. This is required by - the animated event notification. */ - position: relative; -} - -/*** Main indicator icon ***/ - -#downloads-indicator-icon { - background: -moz-image-rect(var(--toolbarbutton-image), - 0, 108, 18, 90) center no-repeat; - min-width: 18px; - min-height: 18px; -} - -toolbar[brighttext] #downloads-indicator-icon { - background: -moz-image-rect(var(--toolbarbutton-inverted-image), - 0, 108, 18, 90) center no-repeat; -} - -#downloads-indicator[attention] > #downloads-indicator-anchor > #downloads-indicator-icon { - background: -moz-image-rect(var(--toolbarbutton-image), - 19, 108, 36, 90) center no-repeat; -} - -/* In the next few rules, we use :not([counter]) as a shortcut that is - equivalent to -moz-any([progress], [paused]). */ - -#downloads-indicator:not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter { - background: -moz-image-rect(var(--toolbarbutton-image), - 0, 108, 18, 90) center no-repeat; - background-size: 12px; -} - -toolbar[brighttext] #downloads-indicator:not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter { - background: -moz-image-rect(var(--toolbarbutton-inverted-image), - 0, 108, 18, 90) center no-repeat; -} - -#downloads-indicator:not([counter])[attention] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter { - background: -moz-image-rect(var(--toolbarbutton-image), - 19, 108, 36, 90) center no-repeat; -} - -/*** Download notifications ***/ - -#downloads-indicator-notification { - opacity: 0; - background-size: 16px; - background-position: center; - background-repeat: no-repeat; -} - -@keyframes downloadsIndicatorNotificationStartRight { - from { opacity: 0; transform: translate(-128px, 128px) scale(8); } - 20% { opacity: .85; animation-timing-function: ease-out; } - to { opacity: 0; transform: translate(0) scale(1); } -} - -@keyframes downloadsIndicatorNotificationStartLeft { - from { opacity: 0; transform: translate(128px, 128px) scale(8); } - 20% { opacity: .85; animation-timing-function: ease-out; } - to { opacity: 0; transform: translate(0) scale(1); } -} - -#downloads-indicator[notification="start"] > #downloads-indicator-anchor > #downloads-indicator-notification { - background-image: url("chrome://browser/skin/downloads/download-notification-start.png"); - animation-name: downloadsIndicatorNotificationStartRight; - animation-duration: 1s; -} - -#downloads-indicator[notification="start"]:-moz-locale-dir(rtl) > #downloads-indicator-anchor > #downloads-indicator-notification { - animation-name: downloadsIndicatorNotificationStartLeft; -} - -@keyframes downloadsIndicatorNotificationFinish { - from { opacity: 0; transform: scale(1); } - 20% { opacity: .65; animation-timing-function: ease-in; } - to { opacity: 0; transform: scale(8); } -} - -#downloads-indicator[notification="finish"] > #downloads-indicator-anchor > #downloads-indicator-notification { - background-image: url("chrome://browser/skin/downloads/download-notification-finish.png"); - animation-name: downloadsIndicatorNotificationFinish; - animation-duration: 1s; -} - -/*** Progress bar and text ***/ - -#downloads-indicator-counter { - height: 9px; - margin: -3px 0px 0px 0px; - color: hsl(0,0%,30%); - text-shadow: hsla(0,0%,100%,.5) 0 1px; - font-size: 9px; - line-height: 9px; - text-align: center; -} - -toolbar[brighttext] #downloads-indicator-counter { - color: white; - text-shadow: 0 0 1px rgba(0,0,0,.7), - 0 1px 1.5px rgba(0,0,0,.5); -} - -#downloads-indicator-progress { - width: 16px; - height: 5px; - min-width: 0; - min-height: 0; - margin-top: 1px; - margin-bottom: 2px; - border-radius: 2px; - box-shadow: 0 1px 0 hsla(0,0%,100%,.4); -} - -#downloads-indicator-progress > .progress-bar { - -moz-appearance: none; - min-width: 0; - min-height: 0; - /* The background-clip: border-box; and background-image: none; are there to expand the background-color behind the border */ - background-clip: padding-box, border-box; - background-color: rgb(90, 201, 66); - background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px), none; - border: 1px solid; - border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4); - border-radius: 2px 0 0 2px; -} - -#downloads-indicator-progress > .progress-remainder { - -moz-appearance: none; - min-width: 0; - min-height: 0; - background-image: linear-gradient(#505050, #575757); - border: 1px solid; - border-color: hsla(0,0%,0%,.6) hsla(0,0%,0%,.4) hsla(0,0%,0%,.4); - border-inline-start: none; - border-radius: 0 2px 2px 0; -} - -#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-bar { - background-color: rgb(220, 230, 81); -} - -#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-remainder { - background-image: linear-gradient(#4b5000, #515700); -} - -toolbar[mode="full"] > #downloads-indicator > .toolbarbutton-text { - margin: 0; - text-align: center; -} diff --git a/application/palemoon/themes/osx/engineManager.css b/application/palemoon/themes/osx/engineManager.css deleted file mode 100644 index c6d42cce29..0000000000 --- a/application/palemoon/themes/osx/engineManager.css +++ /dev/null @@ -1,16 +0,0 @@ -%if 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/. */ -%endif - -#engineList treechildren::-moz-tree-image(engineName) { - margin-inline-end: 4px; - margin-inline-start: 1px; - width: 16px; - height: 16px; -} - -#engineList treechildren::-moz-tree-row { - height: 20px; -} diff --git a/application/palemoon/themes/osx/feeds/feed-icons-16.png b/application/palemoon/themes/osx/feeds/feed-icons-16.png deleted file mode 100644 index bcca086387..0000000000 Binary files a/application/palemoon/themes/osx/feeds/feed-icons-16.png and /dev/null differ diff --git a/application/palemoon/themes/osx/feeds/feedIcon.png b/application/palemoon/themes/osx/feeds/feedIcon.png deleted file mode 100644 index e69bc44961..0000000000 Binary files a/application/palemoon/themes/osx/feeds/feedIcon.png and /dev/null differ diff --git a/application/palemoon/themes/osx/feeds/feedIcon16.png b/application/palemoon/themes/osx/feeds/feedIcon16.png deleted file mode 100644 index d778807532..0000000000 Binary files a/application/palemoon/themes/osx/feeds/feedIcon16.png and /dev/null differ diff --git a/application/palemoon/themes/osx/feeds/subscribe-ui.css b/application/palemoon/themes/osx/feeds/subscribe-ui.css deleted file mode 100644 index f21c037e67..0000000000 --- a/application/palemoon/themes/osx/feeds/subscribe-ui.css +++ /dev/null @@ -1,29 +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/. */ - -.alwaysUse { - padding: 5px; -} - -.handlersMenuPopup > menuitem { - padding-inline-start: 23px; -} - -.handlersMenuPopup > menuitem.menuitem-iconic { - padding-inline-start: 2px; -} - -.handlersMenuPopup > .menuitem-iconic > .menu-iconic-left { - display: -moz-box; - min-width: 16px; - padding-inline-end: 2px; -} - -.chooseApplicationMenuItem { - list-style-image: url("chrome://browser/skin/preferences/application.png"); -} - -#feedHeader[dir="rtl"] .handlersMenuList > menupopup { - direction: rtl; -} diff --git a/application/palemoon/themes/osx/feeds/subscribe.css b/application/palemoon/themes/osx/feeds/subscribe.css deleted file mode 100644 index 3a93c64563..0000000000 --- a/application/palemoon/themes/osx/feeds/subscribe.css +++ /dev/null @@ -1,159 +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/. */ - -html { - background: -moz-Dialog; - font: 3mm tahoma,arial,helvetica,sans-serif; -} - -#feedBody { - border: 1px solid THreeDShadow; - padding: 3em; - padding-inline-start: 30px; - margin: 2em auto; - background: -moz-Field; -} - -#feedHeaderContainer { - border: 1px solid ThreeDShadow; - border-radius: 10px; - margin: -4em auto 0 auto; - background-color: InfoBackground; -} - -#feedHeader { - margin-top: 4.9em; - margin-bottom: 1em; - margin-inline-start: 1.4em; - margin-inline-end: 1em; - padding-inline-start: 2.9em; - font-size: 110%; - color: InfoText; -} - -#feedIntroText { - display: none; -} - -.feedBackground { - background: url("chrome://browser/skin/feeds/feedIcon.png") 0% 10% no-repeat InfoBackground; -} - -.videoPodcastBackground { - background: url("chrome://browser/skin/feeds/videoFeedIcon.png") 0% 10% no-repeat InfoBackground; -} - -.audioPodcastBackground { - background: url("chrome://browser/skin/feeds/audioFeedIcon.png") 0% 10% no-repeat InfoBackground; -} - -#feedHeader[dir="rtl"] { - background-position: 100% 10%; -} - -#feedHeader[firstrun="true"] #feedIntroText { - padding-top: 0.1em; - padding-inline-start: 0.6em; - display: block; -} - -#feedHeader[firstrun="true"] > #feedSubscribeLine { - padding-inline-start: 1.8em; -} - -#feedSubscribeLine { - padding-top: 0.2em; -} - -/* Don't print subscription UI */ -@media print { - #feedHeaderContainer { - display: none; - } -} - -body { - margin: 0; - padding: 0 3em; - color: -moz-fieldText; - font: message-box; -} - -h1 { - font-size: 160%; - border-bottom: 2px solid ThreeDLightShadow; - margin: 0 0 .2em 0; -} - -h2 { - color: ThreeDDarkShadow; - font-size: 110%; - font-weight: normal; - margin: 0 0 .6em 0; -} - -#feedTitleLink { - float: right; - margin-inline-start: .6em; - margin-inline-end: 0; - margin-top: 0; - margin-bottom: 0; -} - -a[href] img { - border: none; -} - -#feedTitleContainer { - margin-inline-start: 0; - margin-inline-end: .6em; - margin-top: 0; - margin-bottom: 0; -} - -#feedTitleImage { - margin-inline-start: .6em; - margin-inline-end: 0; - margin-top: 0; - margin-bottom: 0; - max-width: 300px; - max-height: 150px; -} - -.feedEntryContent { - font-size: 110%; -} - -.link { - color: #0000FF; - text-decoration: underline; - cursor: pointer; -} - -.link:hover:active { - color: #FF0000; -} - -.lastUpdated { - font-size: 85%; - font-weight: normal; -} - -.type-icon { - vertical-align: bottom; - height: 16px; - width: 16px; -} - -.enclosures { - border: 1px solid THreeDShadow; - padding: 1em; - margin: 1em auto; - background: -moz-Dialog; -} - -.enclosure { - vertical-align: middle; - margin-left: 2px; -} diff --git a/application/palemoon/themes/osx/icon.png b/application/palemoon/themes/osx/icon.png deleted file mode 100644 index ff4f21f9a6..0000000000 Binary files a/application/palemoon/themes/osx/icon.png and /dev/null differ diff --git a/application/palemoon/themes/osx/identity-icons-generic.png b/application/palemoon/themes/osx/identity-icons-generic.png deleted file mode 100644 index a39e493c1e..0000000000 Binary files a/application/palemoon/themes/osx/identity-icons-generic.png and /dev/null differ diff --git a/application/palemoon/themes/osx/identity-icons-https-ev.png b/application/palemoon/themes/osx/identity-icons-https-ev.png deleted file mode 100644 index d49be13cb6..0000000000 Binary files a/application/palemoon/themes/osx/identity-icons-https-ev.png and /dev/null differ diff --git a/application/palemoon/themes/osx/identity-icons-https-mixed-active.png b/application/palemoon/themes/osx/identity-icons-https-mixed-active.png deleted file mode 100644 index 3c77bc84db..0000000000 Binary files a/application/palemoon/themes/osx/identity-icons-https-mixed-active.png and /dev/null differ diff --git a/application/palemoon/themes/osx/identity-icons-https.png b/application/palemoon/themes/osx/identity-icons-https.png deleted file mode 100644 index ffd6694269..0000000000 Binary files a/application/palemoon/themes/osx/identity-icons-https.png and /dev/null differ diff --git a/application/palemoon/themes/osx/identity.png b/application/palemoon/themes/osx/identity.png deleted file mode 100644 index 60d5261ff0..0000000000 Binary files a/application/palemoon/themes/osx/identity.png and /dev/null differ diff --git a/application/palemoon/themes/osx/imagedocument.png b/application/palemoon/themes/osx/imagedocument.png deleted file mode 100644 index ff4f21f9a6..0000000000 Binary files a/application/palemoon/themes/osx/imagedocument.png and /dev/null differ diff --git a/application/palemoon/themes/osx/jar.mn b/application/palemoon/themes/osx/jar.mn deleted file mode 100644 index 9b48763549..0000000000 --- a/application/palemoon/themes/osx/jar.mn +++ /dev/null @@ -1,181 +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/. - -browser.jar: -% skin browser classic/1.0 %skin/classic/browser/ - skin/classic/browser/sanitizeDialog.css -* skin/classic/browser/aboutPrivateBrowsing.css -* skin/classic/browser/aboutSessionRestore.css - skin/classic/browser/aboutSessionRestore-window-icon.png (preferences/application.png) - skin/classic/browser/aboutCertError.css - skin/classic/browser/aboutCertError_sectionCollapsed.png - skin/classic/browser/aboutCertError_sectionCollapsed-rtl.png - skin/classic/browser/aboutCertError_sectionExpanded.png -#ifdef MOZ_SERVICES_SYNC - skin/classic/browser/aboutSyncTabs.css -#endif -* skin/classic/browser/autocomplete.css - skin/classic/browser/actionicon-tab.png -* skin/classic/browser/browser.css - skin/classic/browser/click-to-play-warning-stripes.png -* skin/classic/browser/engineManager.css - skin/classic/browser/Geolocation-16.png - skin/classic/browser/Geolocation-64.png - skin/classic/browser/Info.png - skin/classic/browser/identity.png - skin/classic/browser/imagedocument.png - skin/classic/browser/identity-icons-generic.png - skin/classic/browser/identity-icons-https.png - skin/classic/browser/identity-icons-https-ev.png - skin/classic/browser/identity-icons-https-mixed-active.png - skin/classic/browser/keyhole-forward-mask.svg - skin/classic/browser/KUI-background.png - skin/classic/browser/KUI-close.png - skin/classic/browser/livemark-folder.png - skin/classic/browser/menu-back.png - skin/classic/browser/menu-forward.png - skin/classic/browser/mixed-content-blocked-16.png - skin/classic/browser/mixed-content-blocked-64.png - skin/classic/browser/monitor.png - skin/classic/browser/monitor_16-10.png - skin/classic/browser/panel-expander-closed.png - skin/classic/browser/panel-expander-closed@2x.png - skin/classic/browser/panel-expander-open.png - skin/classic/browser/panel-expander-open@2x.png - skin/classic/browser/panel-plus-sign.png - skin/classic/browser/pageInfo.css - skin/classic/browser/pageInfo.png - skin/classic/browser/page-livemarks.png - skin/classic/browser/page-livemarks@2x.png - skin/classic/browser/pointerLock-16.png - skin/classic/browser/pointerLock-64.png - skin/classic/browser/Privacy-16.png - skin/classic/browser/Privacy-32.png - skin/classic/browser/Privacy-48.png - skin/classic/browser/privatebrowsing-mask.png - skin/classic/browser/privatebrowsing-mask@2x.png - skin/classic/browser/privatebrowsing-light.png - skin/classic/browser/privatebrowsing-dark.png - skin/classic/browser/reload-stop-go.png - skin/classic/browser/Search.png - skin/classic/browser/searchbar.css - skin/classic/browser/searchbar-dropdown-arrow.png - skin/classic/browser/Secure24.png - skin/classic/browser/setDesktopBackground.css - skin/classic/browser/slowStartup-16.png - skin/classic/browser/Toolbar.png - skin/classic/browser/Toolbar-inverted.png - skin/classic/browser/Toolbar.svg - skin/classic/browser/Toolbar-inverted.svg - skin/classic/browser/toolbarbutton-dropdown-arrow.png - skin/classic/browser/toolbarbutton-dropdown-arrow-inverted.png - skin/classic/browser/urlbar-arrow.png - skin/classic/browser/urlbar-popup-blocked.png - skin/classic/browser/urlbar-history-dropmarker.png - skin/classic/browser/web-notifications-icon.svg - skin/classic/browser/web-notifications-tray.svg - skin/classic/browser/notification-pluginNormal.png (../shared/plugins/notification-pluginNormal.png) - skin/classic/browser/notification-pluginAlert.png (../shared/plugins/notification-pluginAlert.png) - skin/classic/browser/notification-pluginBlocked.png (../shared/plugins/notification-pluginBlocked.png) -#ifdef MOZ_WEBRTC - skin/classic/browser/webRTC-shareDevice-16.png - skin/classic/browser/webRTC-shareDevice-64.png - skin/classic/browser/webRTC-sharingDevice-16.png -#endif - skin/classic/browser/downloads/buttons.png (downloads/buttons.png) - skin/classic/browser/downloads/download-notification-finish.png (downloads/download-notification-finish.png) - skin/classic/browser/downloads/download-notification-start.png (downloads/download-notification-start.png) - skin/classic/browser/downloads/download-summary.png (downloads/download-summary.png) -* skin/classic/browser/downloads/downloads.css (downloads/downloads.css) -* skin/classic/browser/downloads/allDownloadsViewOverlay.css (downloads/allDownloadsViewOverlay.css) - skin/classic/browser/downloads/contentAreaDownloadsView.css (downloads/contentAreaDownloadsView.css) - skin/classic/browser/feeds/feedIcon.png (feeds/feedIcon.png) - skin/classic/browser/feeds/feedIcon16.png (feeds/feedIcon16.png) - skin/classic/browser/feeds/feed-icons-16.png (feeds/feed-icons-16.png) - skin/classic/browser/feeds/audioFeedIcon.png (feeds/feedIcon.png) - skin/classic/browser/feeds/audioFeedIcon16.png (feeds/feedIcon16.png) - skin/classic/browser/feeds/videoFeedIcon.png (feeds/feedIcon.png) - skin/classic/browser/feeds/videoFeedIcon16.png (feeds/feedIcon16.png) - skin/classic/browser/feeds/subscribe.css (feeds/subscribe.css) - skin/classic/browser/feeds/subscribe-ui.css (feeds/subscribe-ui.css) -* skin/classic/browser/newtab/newTab.css (newtab/newTab.css) - skin/classic/browser/newtab/controls.png (../shared/newtab/controls.png) - skin/classic/browser/newtab/noise.png (../shared/newtab/noise.png) - skin/classic/browser/newtab/pinned.png (../shared/newtab/pinned.png) - skin/classic/browser/places/places.css (places/places.css) -* skin/classic/browser/places/organizer.css (places/organizer.css) - skin/classic/browser/places/editBookmark.png (places/editBookmark.png) - skin/classic/browser/places/bookmark.png (places/bookmark.png) - skin/classic/browser/places/query.png (places/query.png) - skin/classic/browser/places/query@2x.png (places/query@2x.png) - skin/classic/browser/places/bookmarksMenu.png (places/bookmarksMenu.png) - skin/classic/browser/places/bookmarksToolbar.png (places/bookmarksToolbar.png) - skin/classic/browser/places/bookmarksToolbar@2x.png (places/bookmarksToolbar@2x.png) - skin/classic/browser/places/calendar.png (places/calendar.png) - skin/classic/browser/places/folderDropArrow.png (places/folderDropArrow.png) - skin/classic/browser/places/folderDropArrow@2x.png (places/folderDropArrow@2x.png) - skin/classic/browser/places/toolbarDropMarker.png (places/toolbarDropMarker.png) - skin/classic/browser/places/editBookmarkOverlay.css (places/editBookmarkOverlay.css) - skin/classic/browser/places/libraryToolbar.png (places/libraryToolbar.png) - skin/classic/browser/places/libraryToolbar.svg (places/libraryToolbar.svg) - skin/classic/browser/places/starred48.png (places/starred48.png) - skin/classic/browser/places/unstarred48.png (places/unstarred48.png) - skin/classic/browser/places/unfiledBookmarks.png (places/unfiledBookmarks.png) - skin/classic/browser/places/unfiledBookmarks@2x.png (places/unfiledBookmarks@2x.png) - skin/classic/browser/places/tag.png (places/tag.png) - skin/classic/browser/places/tag@2x.png (places/tag@2x.png) - skin/classic/browser/places/history.png (places/history.png) - skin/classic/browser/places/history@2x.png (places/history@2x.png) - skin/classic/browser/places/allBookmarks.png (places/allBookmarks.png) - skin/classic/browser/places/unsortedBookmarks.png (places/unsortedBookmarks.png) - skin/classic/browser/places/downloads.png (places/downloads.png) - skin/classic/browser/places/expander-closed-active.png (places/expander-closed-active.png) - skin/classic/browser/places/expander-open-active.png (places/expander-open-active.png) - skin/classic/browser/places/livemark-item.png (places/livemark-item.png) - skin/classic/browser/places/expander-closed.png (places/expander-closed.png) - skin/classic/browser/places/expander-open.png (places/expander-open.png) - skin/classic/browser/permissions/aboutPermissions.css (permissions/aboutPermissions.css) - skin/classic/browser/preferences/alwaysAsk.png (preferences/alwaysAsk.png) - skin/classic/browser/preferences/application.png (preferences/application.png) - skin/classic/browser/preferences/mail.png (preferences/mail.png) - skin/classic/browser/preferences/Options.png (preferences/Options.png) -#ifdef MOZ_SERVICES_SYNC - skin/classic/browser/preferences/Options-sync.png (preferences/Options-sync.png) -#endif - skin/classic/browser/preferences/saveFile.png (preferences/saveFile.png) -* skin/classic/browser/preferences/preferences.css (preferences/preferences.css) - skin/classic/browser/preferences/applications.css (preferences/applications.css) - skin/classic/browser/statusbar/dynamic.css (../shared/statusbar/dynamic.css) -* skin/classic/browser/statusbar/overlay.css (statusbar/overlay.css) -* skin/classic/browser/statusbar/prefs.css (statusbar/prefs.css) - skin/classic/browser/statusbar/pulse.png (../shared/statusbar/pulse.png) - skin/classic/browser/statusbar/pms16.png (../shared/statusbar/pms16.png) - skin/classic/browser/statusbar/pms24.png (../shared/statusbar/pms24.png) - skin/classic/browser/statusbar/throbber-idle.png (../shared/statusbar/throbber-idle.png) - skin/classic/browser/statusbar/throbberStatic.png (../shared/statusbar/throbberStatic.png) - skin/classic/browser/tabbrowser/alltabs.png (tabbrowser/alltabs.png) - skin/classic/browser/tabbrowser/alltabs-inverted.png (tabbrowser/alltabs-inverted.png) - skin/classic/browser/tabbrowser/newtab.png (tabbrowser/newtab.png) - skin/classic/browser/tabbrowser/newtab-inverted.png (tabbrowser/newtab-inverted.png) - skin/classic/browser/tabbrowser/connecting.png (tabbrowser/connecting.png) - skin/classic/browser/tabbrowser/loading.png (tabbrowser/loading.png) - skin/classic/browser/tabbrowser/tab-arrow-left.png (tabbrowser/tab-arrow-left.png) - skin/classic/browser/tabbrowser/tab-arrow-left-inverted.png (tabbrowser/tab-arrow-left-inverted.png) - skin/classic/browser/tabbrowser/tab-overflow-border.png (tabbrowser/tab-overflow-border.png) - skin/classic/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png) - skin/classic/browser/tabbrowser/tab-audio.svg (../shared/tabbrowser/tab-audio.svg) - skin/classic/browser/tabbrowser/tab-audio-small.svg (../shared/tabbrowser/tab-audio-small.svg) -#ifdef MOZ_SERVICES_SYNC - skin/classic/browser/sync-throbber.png - skin/classic/browser/sync-16.png - skin/classic/browser/sync-32.png - skin/classic/browser/sync-128.png - skin/classic/browser/sync-bg.png - skin/classic/browser/sync-desktopIcon.png - skin/classic/browser/sync-mobileIcon.png - skin/classic/browser/syncSetup.css - skin/classic/browser/syncCommon.css - skin/classic/browser/syncQuota.css - skin/classic/browser/syncProgress.css -#endif diff --git a/application/palemoon/themes/osx/keyhole-forward-mask.svg b/application/palemoon/themes/osx/keyhole-forward-mask.svg deleted file mode 100644 index 83554471c2..0000000000 --- a/application/palemoon/themes/osx/keyhole-forward-mask.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - diff --git a/application/palemoon/themes/osx/livemark-folder.png b/application/palemoon/themes/osx/livemark-folder.png deleted file mode 100644 index 38a4f10558..0000000000 Binary files a/application/palemoon/themes/osx/livemark-folder.png and /dev/null differ diff --git a/application/palemoon/themes/osx/menu-back.png b/application/palemoon/themes/osx/menu-back.png deleted file mode 100644 index ecb8ccd1a4..0000000000 Binary files a/application/palemoon/themes/osx/menu-back.png and /dev/null differ diff --git a/application/palemoon/themes/osx/menu-forward.png b/application/palemoon/themes/osx/menu-forward.png deleted file mode 100644 index 20834927a3..0000000000 Binary files a/application/palemoon/themes/osx/menu-forward.png and /dev/null differ diff --git a/application/palemoon/themes/osx/mixed-content-blocked-16.png b/application/palemoon/themes/osx/mixed-content-blocked-16.png deleted file mode 100644 index 7cf33ec4c5..0000000000 Binary files a/application/palemoon/themes/osx/mixed-content-blocked-16.png and /dev/null differ diff --git a/application/palemoon/themes/osx/mixed-content-blocked-64.png b/application/palemoon/themes/osx/mixed-content-blocked-64.png deleted file mode 100644 index cac4415140..0000000000 Binary files a/application/palemoon/themes/osx/mixed-content-blocked-64.png and /dev/null differ diff --git a/application/palemoon/themes/osx/monitor.png b/application/palemoon/themes/osx/monitor.png deleted file mode 100644 index 35e7b20562..0000000000 Binary files a/application/palemoon/themes/osx/monitor.png and /dev/null differ diff --git a/application/palemoon/themes/osx/monitor_16-10.png b/application/palemoon/themes/osx/monitor_16-10.png deleted file mode 100644 index 41950340e8..0000000000 Binary files a/application/palemoon/themes/osx/monitor_16-10.png and /dev/null differ diff --git a/application/palemoon/themes/osx/moz.build b/application/palemoon/themes/osx/moz.build deleted file mode 100644 index de50366273..0000000000 --- a/application/palemoon/themes/osx/moz.build +++ /dev/null @@ -1,8 +0,0 @@ -# -*- Mode: python; c-basic-offset: 4; 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/. - -DIRS += ['communicator'] - -JAR_MANIFESTS += ['jar.mn'] \ No newline at end of file diff --git a/application/palemoon/themes/osx/newtab/newTab.css b/application/palemoon/themes/osx/newtab/newTab.css deleted file mode 100644 index 9a5327594e..0000000000 --- a/application/palemoon/themes/osx/newtab/newTab.css +++ /dev/null @@ -1,36 +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 ../../shared/newtab/newTab.css.inc - -.newtab-undo-button { - -moz-appearance: none; - color: -moz-nativehyperlinktext; - color: rgb(0,102,204); - cursor: pointer; - padding: 0; - margin: 0 4px; - border: 0; - background: transparent; - text-decoration: none; - min-width: 0; -} - -.newtab-undo-button > .button-box { - padding: 0; -} - -#newtab-undo-close-button { - background-image: -moz-image-rect(url("chrome://global/skin/icons/close.png"), 0, 16, 16, 0); - background-position: center center; - background-repeat: no-repeat; -} - -#newtab-undo-close-button:hover { - background-image: -moz-image-rect(url("chrome://global/skin/icons/close.png"), 0, 32, 16, 16); -} - -#newtab-undo-close-button:hover:active { - background-image: -moz-image-rect(url("chrome://global/skin/icons/close.png"), 0, 48, 16, 32); -} diff --git a/application/palemoon/themes/osx/page-livemarks.png b/application/palemoon/themes/osx/page-livemarks.png deleted file mode 100644 index e526458462..0000000000 Binary files a/application/palemoon/themes/osx/page-livemarks.png and /dev/null differ diff --git a/application/palemoon/themes/osx/page-livemarks@2x.png b/application/palemoon/themes/osx/page-livemarks@2x.png deleted file mode 100644 index 7b170897cc..0000000000 Binary files a/application/palemoon/themes/osx/page-livemarks@2x.png and /dev/null differ diff --git a/application/palemoon/themes/osx/pageInfo.css b/application/palemoon/themes/osx/pageInfo.css deleted file mode 100644 index f958d9ce2f..0000000000 --- a/application/palemoon/themes/osx/pageInfo.css +++ /dev/null @@ -1,258 +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/. */ - -@import "chrome://global/skin/"; - -/* View buttons */ -#viewGroup { - padding-inline-start: 10px; -} - -#viewGroup > radio { - list-style-image: url("chrome://browser/skin/pageInfo.png"); - -moz-box-orient: vertical; - -moz-box-align: center; - -moz-appearance: none; - padding: 5px 3px 1px 3px; - margin: 0 1px; - min-width: 4.5em; -} - -#viewGroup > radio:hover { - background-color: #E0E8F6; - color: black; -} - -#viewGroup > radio[selected="true"] { - background-color: #C1D2EE; - color: black; -} - -#topBar { - border-bottom: 2px groove ThreeDFace; - padding-inline-start: 10px; - background-color: -moz-Field; - color: -moz-FieldText; -} - -#generalTab { - -moz-image-region: rect(0px, 32px, 32px, 0px) -} - -#generalTab:hover, #generalTab[selected="true"] { - -moz-image-region: rect(32px, 32px, 64px, 0px) -} - -#mediaTab { - -moz-image-region: rect(0px, 64px, 32px, 32px) -} - -#mediaTab:hover, #mediaTab[selected="true"] { - -moz-image-region: rect(32px, 64px, 64px, 32px) -} - -#feedTab { - -moz-image-region: rect(0px, 96px, 32px, 64px) -} - -#feedTab:hover, #feedTab[selected="true"] { - -moz-image-region: rect(32px, 96px, 64px, 64px) -} - -#permTab { - -moz-image-region: rect(0px, 128px, 32px, 96px) -} - -#permTab:hover, #permTab[selected="true"] { - -moz-image-region: rect(32px, 128px, 64px, 96px) -} - -#securityTab { - -moz-image-region: rect(0px, 160px, 32px, 128px) -} - -#securityTab:hover, #securityTab[selected="true"] { - -moz-image-region: rect(32px, 160px, 64px, 128px) -} - -deck { - padding: 10px 10px 10px 10px; -} - -/* Misc */ -tree { - margin: .5em; -} - -.gridSeparator { - width: .5em; -} - -textbox { - background: transparent !important; - border: none; - padding: 0px; - margin-top: 1px; - -moz-appearance: none; -} - -textbox.header { - margin-inline-start: 0; -} - -.iframe { - margin: .5em; - background: white; - overflow: auto; -} - -.fixedsize { - height: 8.5em; -} - -textbox[disabled] { - font-style: italic; -} - -/* General Tab */ -groupbox.collapsable caption .caption-icon { - width: 9px; - height: 9px; - background-repeat: no-repeat; - background-position: center; - margin-inline-start: 2px; - margin-inline-end: 2px; - background-image: url("chrome://global/skin/tree/twisty-open.png"); -} - -groupbox.collapsable[closed="true"] { - border: none; - margin-bottom: 9px; - -moz-appearance: none; -} - -groupbox.collapsable[closed="true"] caption .caption-icon { - background-image: url("chrome://global/skin/tree/twisty-clsd.png"); -} - -groupbox tree { - margin: 0 3px; - border: none; -} - -#securityBox description { - margin-inline-start: 10px; -} - -#general-security-identity { - white-space: pre-wrap; - line-height: 2em; -} - -/* Media Tab */ -#imagetree { - min-height: 10em; - margin-bottom: 0; -} - -#mediaSplitter { - border-style: none; - background: none; - height: .8em; -} - -#mediaGrid { - min-height: 9em; -} - -#mediaLabelColumn { - min-width: 10em; -} - -#thepreviewimage { - margin: 1em; -} - -treechildren::-moz-tree-cell-text(broken) { - font-style: italic; - color: graytext; -} - -/* Feeds Tab */ -#feedtree { - margin-bottom: 0px; -} - -#feedListbox richlistitem { - padding-top: 6px; - padding-bottom: 6px; - padding-inline-start: 7px; - padding-inline-end: 7px; - min-height: 25px; - border-bottom: 1px dotted #C0C0C0; -} - -#feedListbox richlistitem[selected="true"] { - background-color: -moz-Dialog; - color: -moz-DialogText; -} - -#feedListbox { - border: 2px solid; - -moz-border-top-colors: ThreeDShadow ThreeDDarkShadow; - -moz-border-right-colors: ThreeDHighlight ThreeDLightShadow; - -moz-border-bottom-colors: ThreeDHighlight ThreeDLightShadow; - -moz-border-left-colors: ThreeDShadow ThreeDDarkShadow; -} - -.feedTitle { - font-weight: bold; -} - -/* Permissions Tab */ -#permList { - margin-top: .5em; - overflow: auto; - border: 2px solid; - -moz-border-top-colors: ThreeDShadow ThreeDDarkShadow; - -moz-border-right-colors: ThreeDHighlight ThreeDLightShadow; - -moz-border-bottom-colors: ThreeDHighlight ThreeDLightShadow; - -moz-border-left-colors: ThreeDShadow ThreeDDarkShadow; - background-color: -moz-field; -} - -.permission { - padding-top: 6px; - padding-bottom: 6px; - padding-inline-start: 7px; - padding-inline-end: 7px; - min-height: 25px; - border-bottom: 1px dotted #C0C0C0; -} - -.permissionLabel { - font-weight: bold; -} - -.permission:hover { - background-color: -moz-dialog; -} - -/* Security Tab */ -#securityPanel .caption-icon { - display: none; -} - -#securityPanel .header { - font-size: 120%; -} - -#securityPanel .fieldLabel { - margin: 2px 10px 3px 10px; -} - -#securityPanel .fieldValue { - font-weight: bold; - margin: 2px 10px 0px 10px; -} diff --git a/application/palemoon/themes/osx/pageInfo.png b/application/palemoon/themes/osx/pageInfo.png deleted file mode 100644 index 237381b4a7..0000000000 Binary files a/application/palemoon/themes/osx/pageInfo.png and /dev/null differ diff --git a/application/palemoon/themes/osx/panel-expander-closed.png b/application/palemoon/themes/osx/panel-expander-closed.png deleted file mode 100644 index f0e97b22e1..0000000000 Binary files a/application/palemoon/themes/osx/panel-expander-closed.png and /dev/null differ diff --git a/application/palemoon/themes/osx/panel-expander-closed@2x.png b/application/palemoon/themes/osx/panel-expander-closed@2x.png deleted file mode 100644 index 0e7ded50f4..0000000000 Binary files a/application/palemoon/themes/osx/panel-expander-closed@2x.png and /dev/null differ diff --git a/application/palemoon/themes/osx/panel-expander-open.png b/application/palemoon/themes/osx/panel-expander-open.png deleted file mode 100644 index e3febf4ffb..0000000000 Binary files a/application/palemoon/themes/osx/panel-expander-open.png and /dev/null differ diff --git a/application/palemoon/themes/osx/panel-expander-open@2x.png b/application/palemoon/themes/osx/panel-expander-open@2x.png deleted file mode 100644 index 391337030c..0000000000 Binary files a/application/palemoon/themes/osx/panel-expander-open@2x.png and /dev/null differ diff --git a/application/palemoon/themes/osx/panel-plus-sign.png b/application/palemoon/themes/osx/panel-plus-sign.png deleted file mode 100644 index 375601e680..0000000000 Binary files a/application/palemoon/themes/osx/panel-plus-sign.png and /dev/null differ diff --git a/application/palemoon/themes/osx/permissions/aboutPermissions.css b/application/palemoon/themes/osx/permissions/aboutPermissions.css deleted file mode 100644 index 4886da2be9..0000000000 --- a/application/palemoon/themes/osx/permissions/aboutPermissions.css +++ /dev/null @@ -1,153 +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/. */ - -@import url("chrome://global/skin/inContentUI.css"); - -/* header */ - -#permissions-pagetitle { - font-size: 200%; - font-weight: bold; - padding-bottom: 0.5em; -} - -/* content box */ -#permissions-content { - height: 100%; -} - -/* sites box */ - -#sites-box { - padding: 10px; - width: 25em; -} - -#sites-filter { - margin: 0; -} - -#sites-list { - -moz-appearance: none; - border: 1px solid rgba(0, 0, 0, 0.32); - background-color: rgba(255, 255, 255, 0.4); - margin: 5px 0 0 0; -} - -.site { - padding: 4px; - border-bottom: 1px solid ThreeDLightShadow; -} - -.site-favicon { - height: 16px; - width: 16px; - margin-inline-end: 4px; - list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png"); -} - -#all-sites-item > .site-container > .site-favicon { - list-style-image: none; -} - -/* permissions box */ - -#permissions-box { - padding-top: 10px; - overflow-y: auto; -} - -#site-description { - font-size: 125%; - margin-inline-start: 6px; /* to match button margin */ -} - -#site-label { - font-weight: bold; - margin-top: 0; - margin-bottom: 0; -} - -#defaults-description { - font-size: 125%; - font-weight: bold; - margin-inline-start: 6px; -} - -.pref-item { - margin-bottom: 10px; -} - -.pref-icon { - width: 36px; - height: 36px; - margin-inline-end: 10px; -} - -.pref-icon[type="password"] { - list-style-image: url(chrome://mozapps/skin/passwordmgr/key-64.png); -} -.pref-icon[type="image"] { - list-style-image: url(chrome://global/skin/icons/question-64.png); -} -.pref-icon[type="popup"] { - list-style-image: url(chrome://global/skin/icons/question-64.png); -} -.pref-icon[type="cookie"] { - list-style-image: url(chrome://global/skin/icons/question-64.png); -} -.pref-icon[type="desktop-notification"] { - list-style-image: url(chrome://browser/skin/web-notifications-icon.svg); -} -.pref-icon[type="install"] { - list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric.png); -} -.pref-icon[type="geo"] { - list-style-image: url(chrome://browser/skin/Geolocation-64.png); -} -.pref-icon[type="plugins"] { - list-style-image: url(chrome://mozapps/skin/plugins/pluginGeneric.png); -} - -.pref-title { - font-size: 125%; - margin-bottom: 0; - font-weight: bold; - margin-right: 0; - padding-right: 0; -} - -.pref-default { - margin-left: 0.5em; - padding-left: 0; -} - -.pref-set-default { - visibility: collapse; -} - -.pref-menulist { - margin-left: 6px; - margin-right: 6px; - min-width: 10em; /* native menulists ellipsize their longest entries by default on many themes */ -} - -.plugins-label { - margin-right: 0; - padding-right: 0; -} - -.plugins-vulnerable { - margin-left: 0; - padding-left: 0; - margin-right: 0; - padding-right: 0; -} - -.plugins-default { - margin-left: 0.5em; - padding-left: 0; - margin-right: 1em; - padding-right: 0; -} diff --git a/application/palemoon/themes/osx/places/allBookmarks.png b/application/palemoon/themes/osx/places/allBookmarks.png deleted file mode 100644 index d1abe8192b..0000000000 Binary files a/application/palemoon/themes/osx/places/allBookmarks.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/bookmark.png b/application/palemoon/themes/osx/places/bookmark.png deleted file mode 100644 index 2e9a206347..0000000000 Binary files a/application/palemoon/themes/osx/places/bookmark.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/bookmarksMenu.png b/application/palemoon/themes/osx/places/bookmarksMenu.png deleted file mode 100644 index c27bd6a6fe..0000000000 Binary files a/application/palemoon/themes/osx/places/bookmarksMenu.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/bookmarksToolbar.png b/application/palemoon/themes/osx/places/bookmarksToolbar.png deleted file mode 100644 index 2047bffe54..0000000000 Binary files a/application/palemoon/themes/osx/places/bookmarksToolbar.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/bookmarksToolbar@2x.png b/application/palemoon/themes/osx/places/bookmarksToolbar@2x.png deleted file mode 100644 index dd458981e2..0000000000 Binary files a/application/palemoon/themes/osx/places/bookmarksToolbar@2x.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/calendar.png b/application/palemoon/themes/osx/places/calendar.png deleted file mode 100644 index 1855c9f507..0000000000 Binary files a/application/palemoon/themes/osx/places/calendar.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/downloads.png b/application/palemoon/themes/osx/places/downloads.png deleted file mode 100644 index 0756cb6806..0000000000 Binary files a/application/palemoon/themes/osx/places/downloads.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/editBookmark.png b/application/palemoon/themes/osx/places/editBookmark.png deleted file mode 100644 index fbca0523df..0000000000 Binary files a/application/palemoon/themes/osx/places/editBookmark.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/editBookmarkOverlay.css b/application/palemoon/themes/osx/places/editBookmarkOverlay.css deleted file mode 100644 index cc749c1152..0000000000 --- a/application/palemoon/themes/osx/places/editBookmarkOverlay.css +++ /dev/null @@ -1,105 +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/. */ - -@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); -@namespace html url("http://www.w3.org/1999/xhtml"); - -/**** folder menulist ****/ -.folder-icon > .menulist-label-box > .menulist-icon, -.folder-icon > .menu-iconic-left > .menu-iconic-icon { - width: 16px; - height: 16px; -} - -.folder-icon > .menu-iconic-left { - display: -moz-box; -} - -.folder-icon { - list-style-image: url("chrome://global/skin/tree/folder.png") !important; -} - -@media (min-resolution: 2dppx) { - .folder-icon { - list-style-image: url("chrome://global/skin/tree/folder@2x.png") !important; - } -} - -.menulist-icon { - margin: 0 !important; -} - -/**** expanders ****/ - -.expander-up, -.expander-down { - -moz-appearance: none; - margin: 0; - margin-left: 8px; - padding: 0; - min-width: 0; -} - -.expander-up { - list-style-image: url("chrome://browser/skin/places/expander-open.png"); -} - -.expander-down { - list-style-image: url("chrome://browser/skin/places/expander-closed.png"); -} - -.expander-down:hover:active { - list-style-image: url("chrome://browser/skin/places/expander-closed-active.png"); -} - -.expander-up:hover:active { - list-style-image: url("chrome://browser/skin/places/expander-open-active.png"); -} - -#editBookmarkPanelContent { - min-width: 23em; -} - -#editBMPanel_folderTree { - margin: 6px 4px 0 4px; -} - -/* Hide the value column of the tag autocomplete popup - * leaving only the comment column visible. This is - * so that only the tag being edited is shown in the - * popup. - */ -#editBMPanel_tagsField #treecolAutoCompleteValue { - visibility: collapse; -} - - -/* ----- BOOKMARK PANEL DROPDOWN MENU ITEMS ----- */ - -#editBMPanel_folderMenuList[selectedIndex="0"], -#editBMPanel_toolbarFolderItem { - list-style-image: url("chrome://browser/skin/places/bookmarksToolbar.png") !important; -} - -#editBMPanel_folderMenuList[selectedIndex="1"], -#editBMPanel_bmRootItem { - list-style-image: url("chrome://browser/skin/places/bookmarksMenu.png") !important; -} - -#editBMPanel_folderMenuList[selectedIndex="2"], -#editBMPanel_unfiledRootItem { - list-style-image: url("chrome://browser/skin/places/unfiledBookmarks.png") !important; -} - -@media (min-resolution: 2dppx) { - #editBMPanel_folderMenuList[selectedIndex="0"], - #editBMPanel_toolbarFolderItem { - list-style-image: url("chrome://browser/skin/places/bookmarksToolbar@2x.png") !important; - } - - #editBMPanel_folderMenuList[selectedIndex="2"], - #editBMPanel_unfiledRootItem { - list-style-image: url("chrome://browser/skin/places/unfiledBookmarks@2x.png") !important; - } -} diff --git a/application/palemoon/themes/osx/places/expander-closed-active.png b/application/palemoon/themes/osx/places/expander-closed-active.png deleted file mode 100644 index 7ef5f04f9e..0000000000 Binary files a/application/palemoon/themes/osx/places/expander-closed-active.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/expander-closed.png b/application/palemoon/themes/osx/places/expander-closed.png deleted file mode 100644 index 7850c9e951..0000000000 Binary files a/application/palemoon/themes/osx/places/expander-closed.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/expander-open-active.png b/application/palemoon/themes/osx/places/expander-open-active.png deleted file mode 100644 index 673ead568d..0000000000 Binary files a/application/palemoon/themes/osx/places/expander-open-active.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/expander-open.png b/application/palemoon/themes/osx/places/expander-open.png deleted file mode 100644 index 76553571d9..0000000000 Binary files a/application/palemoon/themes/osx/places/expander-open.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/folderDropArrow.png b/application/palemoon/themes/osx/places/folderDropArrow.png deleted file mode 100644 index 8d722ccd5e..0000000000 Binary files a/application/palemoon/themes/osx/places/folderDropArrow.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/folderDropArrow@2x.png b/application/palemoon/themes/osx/places/folderDropArrow@2x.png deleted file mode 100644 index 9efb6d95d8..0000000000 Binary files a/application/palemoon/themes/osx/places/folderDropArrow@2x.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/history.png b/application/palemoon/themes/osx/places/history.png deleted file mode 100644 index e5a00b56d3..0000000000 Binary files a/application/palemoon/themes/osx/places/history.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/history@2x.png b/application/palemoon/themes/osx/places/history@2x.png deleted file mode 100644 index 684b374ff5..0000000000 Binary files a/application/palemoon/themes/osx/places/history@2x.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/libraryToolbar.png b/application/palemoon/themes/osx/places/libraryToolbar.png deleted file mode 100644 index 2ed627acbf..0000000000 Binary files a/application/palemoon/themes/osx/places/libraryToolbar.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/libraryToolbar.svg b/application/palemoon/themes/osx/places/libraryToolbar.svg deleted file mode 100644 index 5fcf42ae3a..0000000000 --- a/application/palemoon/themes/osx/places/libraryToolbar.svg +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/application/palemoon/themes/osx/places/livemark-item.png b/application/palemoon/themes/osx/places/livemark-item.png deleted file mode 100644 index 9184b95187..0000000000 Binary files a/application/palemoon/themes/osx/places/livemark-item.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/organizer.css b/application/palemoon/themes/osx/places/organizer.css deleted file mode 100644 index ffcd6c5237..0000000000 --- a/application/palemoon/themes/osx/places/organizer.css +++ /dev/null @@ -1,136 +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/. */ - -:root { - --toolbarbutton-image: url("chrome://browser/skin/Toolbar.png"); - --library-toolbar-image: url("chrome://browser/skin/places/libraryToolbar.png"); -} - - -/* Use SVG for HiDPI 133%+ */ -@media (min-resolution: 1.33dppx) { - :root { - --toolbarbutton-image: url("chrome://browser/skin/Toolbar.svg"); - --library-toolbar-image: url("chrome://browser/skin/places/libraryToolbar.svg"); - } -} - -/* Toolbar */ -#placesToolbar { - padding: 3px; - padding-inline-end: 6px; -} - -#placesToolbar > toolbarbutton[disabled] > .toolbarbutton-icon { - opacity: .4; -} - -#back-button, -#forward-button { - list-style-image: var(--toolbarbutton-image); -} - -#back-button { - -moz-image-region: rect(0, 18px, 18px, 0); -} - -#forward-button { - -moz-image-region: rect(0, 36px, 18px, 18px); -} - -#back-button:-moz-locale-dir(rtl) > .toolbarbutton-icon, -#forward-button:-moz-locale-dir(rtl) > .toolbarbutton-icon { - transform: scaleX(-1); -} - -/* organize, view and maintenance buttons icons */ -#organizeButton, -#viewMenu, -#maintenanceButton { - list-style-image: var(--library-toolbar-image); -} - -/* organize button */ -#organizeButton { - -moz-image-region: rect(0px, 16px, 16px, 0px); -} - -/* view button */ -#viewMenu { - -moz-image-region: rect(0px, 32px, 16px, 16px); -} - -/* maintenance button */ -#maintenanceButton { - -moz-image-region: rect(0px, 48px, 16px, 32px); -} - -/* Root View */ -#placesView { - border-top: 1px solid ThreeDDarkShadow; -} - -/* Info box */ -#detailsDeck { - border-top: 1px solid ThreeDShadow; - padding: 5px; -} - -#infoBoxExpanderLabel { - padding-inline-start: 2px; -} - -#searchFilter { - margin: 0; -} - -/** - * Downloads pane - */ - -#clearDownloadsButton > .toolbarbutton-icon { - display: none; -} - -#clearDownloadsButton { - padding-inline-start: 9px; - padding-inline-end: 9px; -} - -/* hover-over/open button highlighting */ - -#organizeButton, -#viewMenu, -#maintenanceButton, -#organizeButton, -#clearDownloadsButton { - color: #222; - border: 0; - border-radius: 10000px; - padding: 1px 8px; - margin: 0 0 1px; -} - -#back-button, -#forward-button { - color: #222; - border: 0; - border-radius: 10000px; - padding: 1px 1px; - margin: 0 0 1px; -} - -#organizeButton:hover, -#organizeButton[open="true"], -#viewMenu:hover, -#viewMenu[open="true"], -#maintenanceButton:hover, -#maintenanceButton[open="true"], -#organizeButton:hover, -#organizeButton[open="true"], -#clearDownloadsButton:hover, -#back-button:not([disabled]):hover, -#forward-button:not([disabled]):hover { - background-color: rgba(0, 0, 0, .205); -} diff --git a/application/palemoon/themes/osx/places/places.css b/application/palemoon/themes/osx/places/places.css deleted file mode 100644 index b30c56bd85..0000000000 --- a/application/palemoon/themes/osx/places/places.css +++ /dev/null @@ -1,146 +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/. */ - -/* Sidebars */ -.sidebar-placesTree { - -moz-appearance: none; - border: 0; - margin: 0; - border-top: 1px solid ThreeDShadow; -} - -.sidebar-placesTreechildren::-moz-tree-cell(leaf) , -.sidebar-placesTreechildren::-moz-tree-image(leaf) { - cursor: pointer; -} - -.sidebar-placesTreechildren::-moz-tree-cell-text(leaf, hover) { - cursor: pointer; - text-decoration: underline; -} - -.sidebar-placesTreechildren::-moz-tree-cell(separator) { - cursor: default; -} - -/* Trees */ -treechildren::-moz-tree-image(title) { - list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png"); - padding-right: 2px; - margin: 0px 2px; - width: 16px; - height: 16px; -} - -treechildren::-moz-tree-image(title, livemarkItem) { - list-style-image: url("chrome://browser/skin/places/livemark-item.png"); - -moz-image-region: rect(0px, 16px, 16px, 0px); -} - -treechildren::-moz-tree-image(title, livemarkItem, visited) { - -moz-image-region: rect(0px, 32px, 16px, 16px); -} - -treechildren::-moz-tree-image(title, separator) { - list-style-image: none; - width: 0; - height: 0; -} - -treechildren::-moz-tree-image(title, container), -treechildren::-moz-tree-image(title, open) { - list-style-image: url("chrome://global/skin/tree/folder.png"); - -moz-image-region: rect(0, 16px, 16px, 0); -} - -treechildren::-moz-tree-image(title, container, livemark) { - list-style-image: url("chrome://browser/skin/livemark-folder.png"); - -moz-image-region: auto; -} - -treechildren::-moz-tree-image(container, OrganizerQuery_AllBookmarks) { - list-style-image: url("chrome://browser/skin/places/allBookmarks.png"); - -moz-image-region: auto; -} - -treechildren::-moz-tree-image(container, OrganizerQuery_BookmarksToolbar) { - list-style-image: url("chrome://browser/skin/places/bookmarksToolbar.png"); - -moz-image-region: auto; -} - -treechildren::-moz-tree-image(container, OrganizerQuery_BookmarksMenu) { - list-style-image: url("chrome://browser/skin/places/bookmarksMenu.png"); - -moz-image-region: auto; -} - -treechildren::-moz-tree-image(container, OrganizerQuery_UnfiledBookmarks) { - list-style-image: url("chrome://browser/skin/places/unsortedBookmarks.png"); - -moz-image-region: auto; -} - -/* query-nodes should be styled even if they're not expandable */ -treechildren::-moz-tree-image(title, query) { - list-style-image: url("chrome://browser/skin/places/query.png"); - -moz-image-region: auto; -} - -treechildren::-moz-tree-image(title, query, tagContainer), -treechildren::-moz-tree-image(query, OrganizerQuery_Tags) { - list-style-image: url("chrome://browser/skin/places/tag.png"); - -moz-image-region: auto; -} - -treechildren::-moz-tree-image(query, OrganizerQuery_Downloads) { - list-style-image: url("chrome://browser/skin/places/downloads.png"); - -moz-image-region: auto; -} - -/* calendar icon for folders grouping items by date */ -treechildren::-moz-tree-image(title, query, dayContainer) { - list-style-image: url("chrome://browser/skin/places/calendar.png"); - -moz-image-region: auto; -} - -treechildren::-moz-tree-image(title, query, hostContainer) { - list-style-image: url("chrome://global/skin/tree/folder.png"); -} - -treechildren::-moz-tree-image(title, query, hostContainer, open) { - list-style-image: url("chrome://global/skin/tree/folder.png"); -} - -treechildren::-moz-tree-image(title, query, OrganizerQuery_History) { - list-style-image: url("chrome://browser/skin/places/history.png"); -} - -/* We want some queries to look like ordinary folders. This must come - after the (title, query) selector, or it would get overridden. */ - -treechildren::-moz-tree-image(title, query, folder), -treechildren::-moz-tree-image(title, query, folder, open) { - list-style-image: url("chrome://global/skin/tree/folder.png"); - -moz-image-region: rect(0, 16px, 16px, 0); -} - -treechildren::-moz-tree-image(cutting) { - opacity: 0.5; -} - -treechildren::-moz-tree-cell-text(cutting) { - opacity: 0.7; -} - -/* Browser Sidebars */ - -/* Default button vert. margins are 1px/2px, and this can cause misalignment */ -#viewButton { - margin-top: 2px; - margin-bottom: 2px; -} - -#viewButton > .button-box > .button-menu-dropmarker { - height: auto; - width: auto; - margin-inline-end: -3px; -} diff --git a/application/palemoon/themes/osx/places/query.png b/application/palemoon/themes/osx/places/query.png deleted file mode 100644 index 0ccb847025..0000000000 Binary files a/application/palemoon/themes/osx/places/query.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/query@2x.png b/application/palemoon/themes/osx/places/query@2x.png deleted file mode 100644 index 20b458aaca..0000000000 Binary files a/application/palemoon/themes/osx/places/query@2x.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/starred48.png b/application/palemoon/themes/osx/places/starred48.png deleted file mode 100644 index bfa14599a1..0000000000 Binary files a/application/palemoon/themes/osx/places/starred48.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/tag.png b/application/palemoon/themes/osx/places/tag.png deleted file mode 100644 index a4038bb4fa..0000000000 Binary files a/application/palemoon/themes/osx/places/tag.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/tag@2x.png b/application/palemoon/themes/osx/places/tag@2x.png deleted file mode 100644 index 673814bb5c..0000000000 Binary files a/application/palemoon/themes/osx/places/tag@2x.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/toolbarDropMarker.png b/application/palemoon/themes/osx/places/toolbarDropMarker.png deleted file mode 100644 index a217b0ed88..0000000000 Binary files a/application/palemoon/themes/osx/places/toolbarDropMarker.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/unfiledBookmarks.png b/application/palemoon/themes/osx/places/unfiledBookmarks.png deleted file mode 100644 index 69495dac0f..0000000000 Binary files a/application/palemoon/themes/osx/places/unfiledBookmarks.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/unfiledBookmarks@2x.png b/application/palemoon/themes/osx/places/unfiledBookmarks@2x.png deleted file mode 100644 index 44efd6aba3..0000000000 Binary files a/application/palemoon/themes/osx/places/unfiledBookmarks@2x.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/unsortedBookmarks.png b/application/palemoon/themes/osx/places/unsortedBookmarks.png deleted file mode 100644 index 893e75a79a..0000000000 Binary files a/application/palemoon/themes/osx/places/unsortedBookmarks.png and /dev/null differ diff --git a/application/palemoon/themes/osx/places/unstarred48.png b/application/palemoon/themes/osx/places/unstarred48.png deleted file mode 100644 index 8b82aab4b1..0000000000 Binary files a/application/palemoon/themes/osx/places/unstarred48.png and /dev/null differ diff --git a/application/palemoon/themes/osx/pointerLock-16.png b/application/palemoon/themes/osx/pointerLock-16.png deleted file mode 100644 index 862cd11c6a..0000000000 Binary files a/application/palemoon/themes/osx/pointerLock-16.png and /dev/null differ diff --git a/application/palemoon/themes/osx/pointerLock-64.png b/application/palemoon/themes/osx/pointerLock-64.png deleted file mode 100644 index a35ce040c8..0000000000 Binary files a/application/palemoon/themes/osx/pointerLock-64.png and /dev/null differ diff --git a/application/palemoon/themes/osx/preferences/Options-sync.png b/application/palemoon/themes/osx/preferences/Options-sync.png deleted file mode 100644 index 89901fb698..0000000000 Binary files a/application/palemoon/themes/osx/preferences/Options-sync.png and /dev/null differ diff --git a/application/palemoon/themes/osx/preferences/Options.png b/application/palemoon/themes/osx/preferences/Options.png deleted file mode 100644 index 448eca6e1b..0000000000 Binary files a/application/palemoon/themes/osx/preferences/Options.png and /dev/null differ diff --git a/application/palemoon/themes/osx/preferences/alwaysAsk.png b/application/palemoon/themes/osx/preferences/alwaysAsk.png deleted file mode 100644 index ddd4cb2130..0000000000 Binary files a/application/palemoon/themes/osx/preferences/alwaysAsk.png and /dev/null differ diff --git a/application/palemoon/themes/osx/preferences/application.png b/application/palemoon/themes/osx/preferences/application.png deleted file mode 100644 index ff2ecc2f35..0000000000 Binary files a/application/palemoon/themes/osx/preferences/application.png and /dev/null differ diff --git a/application/palemoon/themes/osx/preferences/applications.css b/application/palemoon/themes/osx/preferences/applications.css deleted file mode 100644 index fdf5614772..0000000000 --- a/application/palemoon/themes/osx/preferences/applications.css +++ /dev/null @@ -1,64 +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/. */ - -/** - * Line up the actions menu with action labels above and below it. - * Equalize the distance from the left side of the action box to the left side - * of the icon for both the menu and the non-menu versions of the action box. - * Also make sure the labels are the same distance away from the icons. - */ -.actionsMenu { - margin-top: 0; - margin-bottom: 0; - margin-inline-start: -2px; - margin-inline-end: 0; -} - -.typeIcon, -.actionIcon { - margin-inline-start: 3px; - margin-inline-end: 3px; -} - -richlistitem label { - margin-inline-start: 1px; - margin-top: 2px; -} - -richlistitem { - min-height: 22px; -} - -richlistitem[appHandlerIcon="ask"], -menuitem[appHandlerIcon="ask"] { - list-style-image: url("chrome://browser/skin/preferences/alwaysAsk.png"); -} - -richlistitem[appHandlerIcon="save"], -menuitem[appHandlerIcon="save"] { - list-style-image: url("chrome://browser/skin/preferences/application.png"); -} - -richlistitem[appHandlerIcon="feed"], -menuitem[appHandlerIcon="feed"] { - list-style-image: url("chrome://browser/skin/page-livemarks.png"); -} - -richlistitem[appHandlerIcon="plugin"], -menuitem[appHandlerIcon="plugin"] { - list-style-image: url("chrome://mozapps/skin/plugins/pluginGeneric-16.png"); -} - -.actionsMenu .menulist-icon { - margin-inline-end: 3px; -} - -.actionsMenu > menupopup > menuitem > .menu-iconic-left { - padding-inline-start: 0px; - padding-inline-end: 2px; -} - -.actionsMenu > menupopup > menuitem { - padding-inline-start: 4px; -} diff --git a/application/palemoon/themes/osx/preferences/mail.png b/application/palemoon/themes/osx/preferences/mail.png deleted file mode 100644 index c40d15991d..0000000000 Binary files a/application/palemoon/themes/osx/preferences/mail.png and /dev/null differ diff --git a/application/palemoon/themes/osx/preferences/preferences.css b/application/palemoon/themes/osx/preferences/preferences.css deleted file mode 100644 index 4075b1e593..0000000000 --- a/application/palemoon/themes/osx/preferences/preferences.css +++ /dev/null @@ -1,142 +0,0 @@ -/* -# -*- Mode: Java; 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/. -*/ - -/* Global Styles */ -#BrowserPreferences radio[pane] { - list-style-image: url("chrome://browser/skin/preferences/Options.png"); - padding: 5px 3px 1px; -} - -radio[pane=paneMain] { - -moz-image-region: rect(0, 32px, 32px, 0); -} - -radio[pane=paneTabs] { - -moz-image-region: rect(0, 64px, 32px, 32px); -} - -radio[pane=paneContent] { - -moz-image-region: rect(0, 96px, 32px, 64px); -} - -radio[pane=paneApplications] { - -moz-image-region: rect(0, 128px, 32px, 96px); -} - -radio[pane=panePrivacy] { - -moz-image-region: rect(0, 160px, 32px, 128px); -} - -radio[pane=paneSecurity] { - -moz-image-region: rect(0, 192px, 32px, 160px); -} - -radio[pane=paneAdvanced] { - -moz-image-region: rect(0, 224px, 32px, 192px); -} - -%ifdef MOZ_SERVICES_SYNC -radio[pane=paneSync] { - list-style-image: url("chrome://browser/skin/preferences/Options-sync.png") !important; -} -%endif - -/* Applications Pane */ -#BrowserPreferences[animated="true"] #handlersView { - height: 25em; -} - -#BrowserPreferences[animated="false"] #handlersView { - -moz-box-flex: 1; -} - -/* Privacy Pane */ - -/* styles for the link elements copied from .text-link in global.css */ -.inline-link { - color: -moz-nativehyperlinktext; - text-decoration: none; -} - -.inline-link:hover { - text-decoration: underline; -} - -/* Modeless Window Dialogs */ -.windowDialog, -.windowDialog prefpane { - padding: 0; -} - -#browserHomePage:-moz-locale-dir(rtl) input { - unicode-bidi: plaintext; - direction: rtl; -} - -.contentPane { - margin: 9px 8px 5px; -} - -.actionButtons { - margin: 0 3px 6px !important; -} - -/* Cookies Manager */ -#cookiesChildren::-moz-tree-image(domainCol) { - width: 16px; - height: 16px; - margin: 0 2px; - list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png") !important; -} - -#cookiesChildren::-moz-tree-image(domainCol, container), -#cookiesChildren::-moz-tree-image(domainCol, container, open) { - list-style-image: url("chrome://global/skin/tree/folder.png") !important; -} - -#cookieInfoBox { - border: 1px solid ThreeDShadow; - border-radius: 0; - margin: 4px; - padding: 0; -} - -/* Advanced Pane */ - -/* Adding padding-bottom prevents the bottom of the tabpanel from being cutoff - when browser.preferences.animateFadeIn = true */ -#advancedPrefs { - padding-bottom: 8px; -} - -/* bottom-most box containing a groupbox in a prefpane. Prevents the bottom - of the groupbox from being cutoff */ -.bottomBox { - padding-bottom: 4px; -} - -%ifdef MOZ_SERVICES_SYNC -/* Sync Pane */ - -#syncDesc { - padding: 0 8em; -} - -.syncGroupBox { - padding: 10px; -} - -#accountCaptionImage { - list-style-image: url("chrome://mozapps/skin/profile/profileicon.png"); -} - -#syncAddDeviceLabel { - margin-top: 1em; - margin-bottom: 1em; -} - -%endif diff --git a/application/palemoon/themes/osx/preferences/saveFile.png b/application/palemoon/themes/osx/preferences/saveFile.png deleted file mode 100644 index c210e8473f..0000000000 Binary files a/application/palemoon/themes/osx/preferences/saveFile.png and /dev/null differ diff --git a/application/palemoon/themes/osx/privatebrowsing-dark.png b/application/palemoon/themes/osx/privatebrowsing-dark.png deleted file mode 100644 index 9eaf3aec7e..0000000000 Binary files a/application/palemoon/themes/osx/privatebrowsing-dark.png and /dev/null differ diff --git a/application/palemoon/themes/osx/privatebrowsing-light.png b/application/palemoon/themes/osx/privatebrowsing-light.png deleted file mode 100644 index c12f507798..0000000000 Binary files a/application/palemoon/themes/osx/privatebrowsing-light.png and /dev/null differ diff --git a/application/palemoon/themes/osx/privatebrowsing-mask.png b/application/palemoon/themes/osx/privatebrowsing-mask.png deleted file mode 100644 index 92f60e29f9..0000000000 Binary files a/application/palemoon/themes/osx/privatebrowsing-mask.png and /dev/null differ diff --git a/application/palemoon/themes/osx/privatebrowsing-mask@2x.png b/application/palemoon/themes/osx/privatebrowsing-mask@2x.png deleted file mode 100644 index ec1cf7452e..0000000000 Binary files a/application/palemoon/themes/osx/privatebrowsing-mask@2x.png and /dev/null differ diff --git a/application/palemoon/themes/osx/reload-stop-go.png b/application/palemoon/themes/osx/reload-stop-go.png deleted file mode 100644 index 1017be9032..0000000000 Binary files a/application/palemoon/themes/osx/reload-stop-go.png and /dev/null differ diff --git a/application/palemoon/themes/osx/sanitizeDialog.css b/application/palemoon/themes/osx/sanitizeDialog.css deleted file mode 100644 index 2fbedeb76a..0000000000 --- a/application/palemoon/themes/osx/sanitizeDialog.css +++ /dev/null @@ -1,93 +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/. */ - -#sanitizeDurationChoice { - margin-inline-end: 0; -} - -/* Align the duration label with the warning box and item list */ -#sanitizeDurationLabel { - margin-inline-start: 3px; -} - - -/* Hide the duration dropdown suffix label if it's empty. Otherwise it - takes up a little space, causing the end of the dropdown to not be aligned - with the warning box. */ -#sanitizeDurationSuffixLabel[value=""] { - display: none; -} - - -/* Places tree */ -#placesTreechildren::-moz-tree-row(selected), -#placesTreechildren::-moz-tree-row(grippyRow) { - background: #999; -} - -#placesTreechildren::-moz-tree-cell-text(selected) { - color: #111; -} - - -/* Sanitize everything warning box */ -#sanitizeEverythingWarningBox { - background-color: Window; - border: 1px solid ThreeDDarkShadow; - border-radius: 5px; - padding: 16px; -} - -#sanitizeEverythingWarningIcon { - list-style-image: url("chrome://global/skin/icons/warning-large.png"); - padding: 0; - margin: 0; -} - -#sanitizeEverythingWarningDescBox { - padding: 0 16px; - margin: 0; -} - - -/* Progressive disclosure button */ -#detailsExpanderWrapper { - padding: 0; - margin: 6px 0; -} - -.expander-up, -.expander-down { - min-width: 0; - margin: 0; -} - -.expander-up > .button-box, -.expander-down > .button-box { - padding: 0; -} - -.expander-up { - list-style-image: url("chrome://browser/skin/places/expander-open.png"); -} - -.expander-down { - list-style-image: url("chrome://browser/skin/places/expander-closed.png"); -} - - -/* Make the item list the same width as the warning box */ -#itemList { - margin-inline-start: 0; - margin-inline-end: 0; -} - - -/* Align the last dialog button with the end of the warning box */ -.prefWindow-dlgbuttons { - margin-inline-end: 0; -} -.dialog-button[dlgtype="cancel"] { - margin-inline-end: 0; -} diff --git a/application/palemoon/themes/osx/searchbar-dropdown-arrow.png b/application/palemoon/themes/osx/searchbar-dropdown-arrow.png deleted file mode 100644 index 7f5f55ef2b..0000000000 Binary files a/application/palemoon/themes/osx/searchbar-dropdown-arrow.png and /dev/null differ diff --git a/application/palemoon/themes/osx/searchbar.css b/application/palemoon/themes/osx/searchbar.css deleted file mode 100644 index e21101ba4f..0000000000 --- a/application/palemoon/themes/osx/searchbar.css +++ /dev/null @@ -1,79 +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/. */ - -.searchbar-textbox { - width: 6em; - min-width: 6em; -} - -.autocomplete-textbox-container { - -moz-box-align: stretch; -} - -.textbox-input-box { - margin: 0; -} - -/* ::::: searchbar-engine-button ::::: */ - -.searchbar-engine-image { - height: 16px; - width: 16px; - list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png"); -} - -.searchbar-engine-button { - -moz-appearance: none; - min-width: 0; - margin: 0; - padding: 0; - padding-inline-end: 2px; - -moz-box-align: center; - background: none; - border: none; -} - -.searchbar-engine-button > .button-box { - -moz-appearance: none; - padding: 0; - border: 0; -} - -.searchbar-dropmarker-image { - list-style-image: url("chrome://browser/skin/searchbar-dropdown-arrow.png"); - -moz-image-region: rect(0, 13px, 11px, 0); -} - -.searchbar-engine-button[open="true"] > .searchbar-dropmarker-image { - -moz-image-region: rect(0, 26px, 11px, 13px); -} - - -/* ::::: search-go-button ::::: */ - -.search-go-container { - -moz-box-align: center; -} - -.search-go-button { - padding: 2px 1px; - opacity: .4; - list-style-image: url("chrome://browser/skin/Search.png"); -} - -.search-go-button:-moz-locale-dir(rtl) { - transform: scaleX(-1); -} - -.search-go-button:hover { - opacity: .6; -} - -.search-go-button:hover:active { - opacity: .8; -} - -.searchbar-engine-menuitem[selected="true"] > .menu-iconic-text { - font-weight: bold; -} diff --git a/application/palemoon/themes/osx/setDesktopBackground.css b/application/palemoon/themes/osx/setDesktopBackground.css deleted file mode 100644 index 585284c7b4..0000000000 --- a/application/palemoon/themes/osx/setDesktopBackground.css +++ /dev/null @@ -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/. */ - -@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); -@namespace html url("http://www.w3.org/1999/xhtml"); - -html|canvas#screen { - margin: 12px 11px 32px; -} - -#monitor { - list-style-image: url("chrome://browser/skin/monitor.png"); -} - -#monitor[aspectratio="16:10"] { - list-style-image: url("chrome://browser/skin/monitor_16-10.png"); -} diff --git a/application/palemoon/themes/osx/shared.inc b/application/palemoon/themes/osx/shared.inc deleted file mode 100644 index 49be77d313..0000000000 --- a/application/palemoon/themes/osx/shared.inc +++ /dev/null @@ -1,6 +0,0 @@ -%include ../../../../toolkit/themes/osx/global/shared.inc -%include ../shared/browser.inc - -%define hudButton -moz-appearance: none; color: #434343; border-radius: 4px; border: 1px solid #b5b5b5; background: linear-gradient(#fff, #f2f2f2); box-shadow: inset 0 1px rgba(255,255,255,.8), inset 0 0 1px rgba(255,255, 255,.25), 0 1px rgba(255,255,255,.3); background-clip: padding-box; background-origin: padding-box; padding: 2px 6px; -%define hudButtonPressed box-shadow: inset 0 1px 4px -3px #000, 0 1px rgba(255,255,255,.3); -%define hudButtonFocused box-shadow: 0 0 1px -moz-mac-focusring inset, 0 0 4px 1px -moz-mac-focusring, 0 0 2px 1px -moz-mac-focusring; diff --git a/application/palemoon/themes/osx/slowStartup-16.png b/application/palemoon/themes/osx/slowStartup-16.png deleted file mode 100644 index 5551ef054e..0000000000 Binary files a/application/palemoon/themes/osx/slowStartup-16.png and /dev/null differ diff --git a/application/palemoon/themes/osx/statusbar/overlay.css b/application/palemoon/themes/osx/statusbar/overlay.css deleted file mode 100644 index d54334206b..0000000000 --- a/application/palemoon/themes/osx/statusbar/overlay.css +++ /dev/null @@ -1,108 +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/. */ - -@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); - -%include ../../shared/statusbar/overlay.css - -/* - * General - */ - -#status4evar-status-text, -#status4evar-progress-bar -{ - margin: 0px 4px; -} - -/* - * Download status - */ - -#status4evar-download-progress-bar -{ - height: 5px; -} - -#status4evar-download-button[attention] #status4evar-download-icon -{ - background-image: url("chrome://browser/skin/downloads/download-glow.png"); -} - -#status-bar -{ - padding-right: 0px; -} - -#browser-bottombox > #addon-bar:last-child -{ - padding-right: 16px; -} - -#status4evar-download-button #status4evar-download-icon -{ - background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"), 0, 108, 18, 90) center no-repeat; - min-width: 18px; - min-height: 18px; -} - -#status4evar-download-button:-moz-lwtheme-brighttext #status4evar-download-icon -{ - background: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"), 0, 108, 18, 90) center no-repeat; -} - -#status4evar-download-button[attention] #status4evar-download-icon -{ - background-image: url("chrome://browser/skin/downloads/download-glow.png"); -} - -toolbar[mode="icons"] #status4evar-download-button[forcelabel="true"] > label -{ - margin: 0px 2px !important; - margin-inline-start: 3px !important; -} - -/* - * Splitter - */ - -splitter.status4evar-status-splitter -{ - width: 8px; - margin: 0px -4px; -} - -/* - * Location bar - */ - -#urlbar-progress-alt -{ - margin-right: -1px; -} - -/* - * Toolbar progress - */ - -#status4evar-progress-bar[s4estyle="true"] -{ - -moz-appearance: none; - border: 1px solid gray; -} - -#status4evar-progress-bar[s4estyle="true"] > .progress-remainder -{ - background-color: white; -} - -/* - * Gripper - */ - -#status4evar-window-gripper -{ - display: none; -} - diff --git a/application/palemoon/themes/osx/statusbar/prefs.css b/application/palemoon/themes/osx/statusbar/prefs.css deleted file mode 100644 index 798a62d74b..0000000000 --- a/application/palemoon/themes/osx/statusbar/prefs.css +++ /dev/null @@ -1,13 +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/. */ - -@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); - -%include ../../shared/statusbar/prefs.css - -#status4evar-addonbar-windowGripper-check -{ - display: none; -} - diff --git a/application/palemoon/themes/osx/sync-128.png b/application/palemoon/themes/osx/sync-128.png deleted file mode 100644 index 1ea34818ce..0000000000 Binary files a/application/palemoon/themes/osx/sync-128.png and /dev/null differ diff --git a/application/palemoon/themes/osx/sync-16.png b/application/palemoon/themes/osx/sync-16.png deleted file mode 100644 index 0afb1c7192..0000000000 Binary files a/application/palemoon/themes/osx/sync-16.png and /dev/null differ diff --git a/application/palemoon/themes/osx/sync-32.png b/application/palemoon/themes/osx/sync-32.png deleted file mode 100644 index 7a762cb986..0000000000 Binary files a/application/palemoon/themes/osx/sync-32.png and /dev/null differ diff --git a/application/palemoon/themes/osx/sync-bg.png b/application/palemoon/themes/osx/sync-bg.png deleted file mode 100644 index 893a27d76e..0000000000 Binary files a/application/palemoon/themes/osx/sync-bg.png and /dev/null differ diff --git a/application/palemoon/themes/osx/sync-desktopIcon.png b/application/palemoon/themes/osx/sync-desktopIcon.png deleted file mode 100644 index d3d1e27c32..0000000000 Binary files a/application/palemoon/themes/osx/sync-desktopIcon.png and /dev/null differ diff --git a/application/palemoon/themes/osx/sync-mobileIcon.png b/application/palemoon/themes/osx/sync-mobileIcon.png deleted file mode 100644 index a3bda57515..0000000000 Binary files a/application/palemoon/themes/osx/sync-mobileIcon.png and /dev/null differ diff --git a/application/palemoon/themes/osx/sync-throbber.png b/application/palemoon/themes/osx/sync-throbber.png deleted file mode 100644 index d25490b4fa..0000000000 Binary files a/application/palemoon/themes/osx/sync-throbber.png and /dev/null differ diff --git a/application/palemoon/themes/osx/syncCommon.css b/application/palemoon/themes/osx/syncCommon.css deleted file mode 100644 index 838788cd52..0000000000 --- a/application/palemoon/themes/osx/syncCommon.css +++ /dev/null @@ -1,49 +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/. */ - -/* The following are used by both sync/setup.xul and sync/genericChange.xul */ -.status { - color: -moz-dialogtext; -} - -.statusIcon { - margin-inline-start: 4px; - max-height: 16px; - max-width: 16px; -} - -.statusIcon[status="active"] { - list-style-image: url("chrome://global/skin/icons/loading_16.png"); -} - -.statusIcon[status="error"] { - list-style-image: url("chrome://global/skin/icons/error-16.png"); -} - -.statusIcon[status="success"] { - list-style-image: url("chrome://global/skin/icons/information-16.png"); -} - -/* .data is only used by sync/genericChange.xul, but it seems unnecessary to have - a separate stylesheet for it. */ -.data { - font-size: 90%; - font-weight: bold; -} - -dialog#change-dialog { - width: 40em; -} - -image#syncIcon { - list-style-image: url("chrome://browser/skin/sync-32.png"); -} - -#introText { - margin-top: 2px; -} - -#feedback { - height: 2em; -} diff --git a/application/palemoon/themes/osx/syncProgress.css b/application/palemoon/themes/osx/syncProgress.css deleted file mode 100644 index d7aa599761..0000000000 --- a/application/palemoon/themes/osx/syncProgress.css +++ /dev/null @@ -1,46 +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/. */ -@import url(chrome://global/skin/inContentUI.css); - -:root { - height: 100%; - width: 100%; - padding: 0; -} - -body { - margin: 0; - padding: 0 2em; -} - -#floatingBox { - margin: 4em auto; - max-width: 40em; - min-width: 23em; - padding: 1em 1.5em; - position: relative; - text-align: center; -} - -#successLogo { - margin: 1em 2em; -} - -#loadingText { - margin: 2em 6em; -} - -#progressBar { - margin: 2em 10em; -} - -#uploadProgressBar{ - width: 100%; -} - -#bottomRow { - margin-top: 2em; - padding: 0; - text-align: end; -} diff --git a/application/palemoon/themes/osx/syncQuota.css b/application/palemoon/themes/osx/syncQuota.css deleted file mode 100644 index 1577de8a3b..0000000000 --- a/application/palemoon/themes/osx/syncQuota.css +++ /dev/null @@ -1,26 +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/. */ - -#quotaDialog { - width: 33em; - height: 25em; -} - -treechildren::-moz-tree-checkbox { - list-style-image: none; -} -treechildren::-moz-tree-checkbox(checked) { - list-style-image: url("chrome://global/skin/checkbox/cbox-check.gif"); -} -treechildren::-moz-tree-checkbox(disabled) { - list-style-image: url("chrome://global/skin/checkbox/cbox-check-dis.gif"); -} - -#treeCaption { - height: 4em; -} - -.captionWarning { - font-weight: bold; -} diff --git a/application/palemoon/themes/osx/syncSetup.css b/application/palemoon/themes/osx/syncSetup.css deleted file mode 100644 index 8898951ebd..0000000000 --- a/application/palemoon/themes/osx/syncSetup.css +++ /dev/null @@ -1,132 +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/. */ - -wizard { - -moz-appearance: none; - width: 55em; - height: 45em; - padding: 0; - background-color: Window; -} - -.wizard-page-box { - -moz-appearance: none; - padding-left: 0; - padding-right: 0; - margin: 0; -} - -wizardpage { - -moz-box-pack: center; - -moz-box-align: center; - margin: 0; - padding: 0 6em; - background-color: Window; -} - -.wizard-header { - -moz-appearance: none; - border: none; - padding: 2em 0 1em 0; - text-align: center; -} -.wizard-header-label { - font-size: 24pt; - font-weight: normal; -} - -.wizard-buttons { - background-color: rgba(0,0,0,0.1); - padding: 1em; -} - -.wizard-buttons-separator { - visibility: collapse; -} - -.wizard-header-icon { - visibility: collapse; -} - -.accountChoiceButton { - font: menu; -} - -.confirm { - border: 1px solid black; - padding: 1em; - border-radius: 5px; -} - -/* Override the text-link style from global.css */ -description > .text-link, -description > .text-link:focus { - margin: 0px; - padding: 0px; - border: 0px; -} - - -.success, -.error { - padding: 2px; - border-radius: 2px; -} - -.error { - background-color: #FF0000 !important; - color: #FFFFFF !important; -} - -.success { - background-color: #00FF00 !important; -} - -.warning { - font-weight: bold; - font-size: 100%; - color: red; -} - -.mainDesc { - font-weight: bold; - font-size: 100%; -} - -.normal { - font-size: 100%; -} - -.inputColumn { - margin-inline-end: 2px -} - -.pin { - font-size: 18pt; - width: 4em; - text-align: center; -} - -#passphraseHelpSpacer { - width: 0.5em; -} - -#pairDeviceThrobber > image, -#login-throbber > image { - list-style-image: url("chrome://global/skin/icons/loading_16.png"); -} - -#captchaFeedback { - visibility: hidden; -} - -#successPageIcon { - /* TODO replace this with a 128px version (bug 591122) */ - list-style-image: url("chrome://browser/skin/sync-32.png"); -} - -#tosDesc { - margin-left: -7px; - margin-bottom: 3px; -} \ No newline at end of file diff --git a/application/palemoon/themes/osx/tabbrowser/alltabs-inverted.png b/application/palemoon/themes/osx/tabbrowser/alltabs-inverted.png deleted file mode 100644 index 002bdd47fd..0000000000 Binary files a/application/palemoon/themes/osx/tabbrowser/alltabs-inverted.png and /dev/null differ diff --git a/application/palemoon/themes/osx/tabbrowser/alltabs.png b/application/palemoon/themes/osx/tabbrowser/alltabs.png deleted file mode 100644 index 172d425f80..0000000000 Binary files a/application/palemoon/themes/osx/tabbrowser/alltabs.png and /dev/null differ diff --git a/application/palemoon/themes/osx/tabbrowser/connecting.png b/application/palemoon/themes/osx/tabbrowser/connecting.png deleted file mode 100644 index e564fb5708..0000000000 Binary files a/application/palemoon/themes/osx/tabbrowser/connecting.png and /dev/null differ diff --git a/application/palemoon/themes/osx/tabbrowser/loading.png b/application/palemoon/themes/osx/tabbrowser/loading.png deleted file mode 100644 index ba54836e98..0000000000 Binary files a/application/palemoon/themes/osx/tabbrowser/loading.png and /dev/null differ diff --git a/application/palemoon/themes/osx/tabbrowser/newtab-inverted.png b/application/palemoon/themes/osx/tabbrowser/newtab-inverted.png deleted file mode 100644 index 4ac1ebaaf0..0000000000 Binary files a/application/palemoon/themes/osx/tabbrowser/newtab-inverted.png and /dev/null differ diff --git a/application/palemoon/themes/osx/tabbrowser/newtab.png b/application/palemoon/themes/osx/tabbrowser/newtab.png deleted file mode 100644 index 7cea7bdd8f..0000000000 Binary files a/application/palemoon/themes/osx/tabbrowser/newtab.png and /dev/null differ diff --git a/application/palemoon/themes/osx/tabbrowser/tab-arrow-left-inverted.png b/application/palemoon/themes/osx/tabbrowser/tab-arrow-left-inverted.png deleted file mode 100644 index 16cd7a2775..0000000000 Binary files a/application/palemoon/themes/osx/tabbrowser/tab-arrow-left-inverted.png and /dev/null differ diff --git a/application/palemoon/themes/osx/tabbrowser/tab-arrow-left.png b/application/palemoon/themes/osx/tabbrowser/tab-arrow-left.png deleted file mode 100644 index e0fb348d66..0000000000 Binary files a/application/palemoon/themes/osx/tabbrowser/tab-arrow-left.png and /dev/null differ diff --git a/application/palemoon/themes/osx/tabbrowser/tab-overflow-border.png b/application/palemoon/themes/osx/tabbrowser/tab-overflow-border.png deleted file mode 100644 index 77f2462e5b..0000000000 Binary files a/application/palemoon/themes/osx/tabbrowser/tab-overflow-border.png and /dev/null differ diff --git a/application/palemoon/themes/osx/tabbrowser/tabDragIndicator.png b/application/palemoon/themes/osx/tabbrowser/tabDragIndicator.png deleted file mode 100644 index c67c2337d2..0000000000 Binary files a/application/palemoon/themes/osx/tabbrowser/tabDragIndicator.png and /dev/null differ diff --git a/application/palemoon/themes/osx/toolbarbutton-dropdown-arrow-inverted.png b/application/palemoon/themes/osx/toolbarbutton-dropdown-arrow-inverted.png deleted file mode 100644 index f3261f1da0..0000000000 Binary files a/application/palemoon/themes/osx/toolbarbutton-dropdown-arrow-inverted.png and /dev/null differ diff --git a/application/palemoon/themes/osx/toolbarbutton-dropdown-arrow.png b/application/palemoon/themes/osx/toolbarbutton-dropdown-arrow.png deleted file mode 100644 index a7abe73963..0000000000 Binary files a/application/palemoon/themes/osx/toolbarbutton-dropdown-arrow.png and /dev/null differ diff --git a/application/palemoon/themes/osx/urlbar-arrow.png b/application/palemoon/themes/osx/urlbar-arrow.png deleted file mode 100644 index fcab253bb3..0000000000 Binary files a/application/palemoon/themes/osx/urlbar-arrow.png and /dev/null differ diff --git a/application/palemoon/themes/osx/urlbar-history-dropmarker.png b/application/palemoon/themes/osx/urlbar-history-dropmarker.png deleted file mode 100644 index fc8b0be983..0000000000 Binary files a/application/palemoon/themes/osx/urlbar-history-dropmarker.png and /dev/null differ diff --git a/application/palemoon/themes/osx/urlbar-popup-blocked.png b/application/palemoon/themes/osx/urlbar-popup-blocked.png deleted file mode 100644 index e6fd29f7d3..0000000000 Binary files a/application/palemoon/themes/osx/urlbar-popup-blocked.png and /dev/null differ diff --git a/application/palemoon/themes/osx/web-notifications-icon.svg b/application/palemoon/themes/osx/web-notifications-icon.svg deleted file mode 100644 index f7186c7275..0000000000 --- a/application/palemoon/themes/osx/web-notifications-icon.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - diff --git a/application/palemoon/themes/osx/web-notifications-tray.svg b/application/palemoon/themes/osx/web-notifications-tray.svg deleted file mode 100644 index 314026a106..0000000000 --- a/application/palemoon/themes/osx/web-notifications-tray.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - diff --git a/application/palemoon/themes/osx/webRTC-shareDevice-16.png b/application/palemoon/themes/osx/webRTC-shareDevice-16.png deleted file mode 100644 index df01b33515..0000000000 Binary files a/application/palemoon/themes/osx/webRTC-shareDevice-16.png and /dev/null differ diff --git a/application/palemoon/themes/osx/webRTC-shareDevice-64.png b/application/palemoon/themes/osx/webRTC-shareDevice-64.png deleted file mode 100644 index d125789fbc..0000000000 Binary files a/application/palemoon/themes/osx/webRTC-shareDevice-64.png and /dev/null differ diff --git a/application/palemoon/themes/osx/webRTC-sharingDevice-16.png b/application/palemoon/themes/osx/webRTC-sharingDevice-16.png deleted file mode 100644 index a670676a01..0000000000 Binary files a/application/palemoon/themes/osx/webRTC-sharingDevice-16.png and /dev/null differ diff --git a/dom/gamepad/cocoa/CocoaGamepad.cpp b/dom/gamepad/cocoa/CocoaGamepad.cpp deleted file mode 100644 index eb6eda9a17..0000000000 --- a/dom/gamepad/cocoa/CocoaGamepad.cpp +++ /dev/null @@ -1,590 +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/. */ - -// mostly derived from the Allegro source code at: -// http://alleg.svn.sourceforge.net/viewvc/alleg/allegro/branches/4.9/src/macosx/hidjoy.m?revision=13760&view=markup - -#include "mozilla/dom/Gamepad.h" -#include "mozilla/dom/GamepadPlatformService.h" -#include "mozilla/ArrayUtils.h" -#include "mozilla/Unused.h" -#include "nsThreadUtils.h" -#include -#include -#include -#include - -#include -#include - -namespace { - -using namespace mozilla; -using namespace mozilla::dom; -using std::vector; - -struct Button { - int id; - bool analog; - IOHIDElementRef element; - CFIndex min; - CFIndex max; - - Button(int aId, IOHIDElementRef aElement, CFIndex aMin, CFIndex aMax) : - id(aId), - analog((aMax - aMin) > 1), - element(aElement), - min(aMin), - max(aMax) {} -}; - -struct Axis { - int id; - IOHIDElementRef element; - uint32_t usagePage; - uint32_t usage; - CFIndex min; - CFIndex max; -}; - -typedef bool dpad_buttons[4]; - -// These values can be found in the USB HID Usage Tables: -// http://www.usb.org/developers/hidpage -const unsigned kDesktopUsagePage = 0x01; -const unsigned kSimUsagePage = 0x02; -const unsigned kAcceleratorUsage = 0xC4; -const unsigned kBrakeUsage = 0xC5; -const unsigned kJoystickUsage = 0x04; -const unsigned kGamepadUsage = 0x05; -const unsigned kAxisUsageMin = 0x30; -const unsigned kAxisUsageMax = 0x35; -const unsigned kDpadUsage = 0x39; -const unsigned kButtonUsagePage = 0x09; -const unsigned kConsumerPage = 0x0C; -const unsigned kHomeUsage = 0x223; -const unsigned kBackUsage = 0x224; - - -class Gamepad { - private: - IOHIDDeviceRef mDevice; - nsTArray - - diff --git a/widget/cocoa/crashtests/403296-1.xhtml b/widget/cocoa/crashtests/403296-1.xhtml deleted file mode 100644 index 800eaa3558..0000000000 --- a/widget/cocoa/crashtests/403296-1.xhtml +++ /dev/null @@ -1,10 +0,0 @@ - - -xxx -yyy - -300 diff --git a/widget/cocoa/crashtests/419737-1.html b/widget/cocoa/crashtests/419737-1.html deleted file mode 100644 index fe6e4532b4..0000000000 --- a/widget/cocoa/crashtests/419737-1.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -
- - diff --git a/widget/cocoa/crashtests/435223-1.html b/widget/cocoa/crashtests/435223-1.html deleted file mode 100644 index 1bbc27ba01..0000000000 --- a/widget/cocoa/crashtests/435223-1.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -
- - diff --git a/widget/cocoa/crashtests/444260-1.xul b/widget/cocoa/crashtests/444260-1.xul deleted file mode 100644 index f1a84023df..0000000000 --- a/widget/cocoa/crashtests/444260-1.xul +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/widget/cocoa/crashtests/444864-1.html b/widget/cocoa/crashtests/444864-1.html deleted file mode 100644 index f8bac76e6a..0000000000 --- a/widget/cocoa/crashtests/444864-1.html +++ /dev/null @@ -1,6 +0,0 @@ - - - -
- - diff --git a/widget/cocoa/crashtests/449111-1.html b/widget/cocoa/crashtests/449111-1.html deleted file mode 100644 index 4494591803..0000000000 --- a/widget/cocoa/crashtests/449111-1.html +++ /dev/null @@ -1,4 +0,0 @@ - - -
- diff --git a/widget/cocoa/crashtests/460349-1.xhtml b/widget/cocoa/crashtests/460349-1.xhtml deleted file mode 100644 index cc9b9700c7..0000000000 --- a/widget/cocoa/crashtests/460349-1.xhtml +++ /dev/null @@ -1,4 +0,0 @@ - - -
- diff --git a/widget/cocoa/crashtests/460387-1.html b/widget/cocoa/crashtests/460387-1.html deleted file mode 100644 index cab7e7eb32..0000000000 --- a/widget/cocoa/crashtests/460387-1.html +++ /dev/null @@ -1,2 +0,0 @@ - -
diff --git a/widget/cocoa/crashtests/464589-1.html b/widget/cocoa/crashtests/464589-1.html deleted file mode 100644 index d25d92315d..0000000000 --- a/widget/cocoa/crashtests/464589-1.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - diff --git a/widget/cocoa/crashtests/crashtests.list b/widget/cocoa/crashtests/crashtests.list deleted file mode 100644 index b65fe01394..0000000000 --- a/widget/cocoa/crashtests/crashtests.list +++ /dev/null @@ -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 diff --git a/widget/cocoa/cursors/arrowN.png b/widget/cocoa/cursors/arrowN.png deleted file mode 100644 index 5ca8ec5ac6..0000000000 Binary files a/widget/cocoa/cursors/arrowN.png and /dev/null differ diff --git a/widget/cocoa/cursors/arrowN@2x.png b/widget/cocoa/cursors/arrowN@2x.png deleted file mode 100644 index d00e87636c..0000000000 Binary files a/widget/cocoa/cursors/arrowN@2x.png and /dev/null differ diff --git a/widget/cocoa/cursors/arrowS.png b/widget/cocoa/cursors/arrowS.png deleted file mode 100644 index 9b2d19e0fd..0000000000 Binary files a/widget/cocoa/cursors/arrowS.png and /dev/null differ diff --git a/widget/cocoa/cursors/arrowS@2x.png b/widget/cocoa/cursors/arrowS@2x.png deleted file mode 100644 index 5d011c1fd1..0000000000 Binary files a/widget/cocoa/cursors/arrowS@2x.png and /dev/null differ diff --git a/widget/cocoa/cursors/cell.png b/widget/cocoa/cursors/cell.png deleted file mode 100644 index 5284eaec57..0000000000 Binary files a/widget/cocoa/cursors/cell.png and /dev/null differ diff --git a/widget/cocoa/cursors/cell@2x.png b/widget/cocoa/cursors/cell@2x.png deleted file mode 100644 index 5e6738cff7..0000000000 Binary files a/widget/cocoa/cursors/cell@2x.png and /dev/null differ diff --git a/widget/cocoa/cursors/colResize.png b/widget/cocoa/cursors/colResize.png deleted file mode 100644 index 4e3e19e223..0000000000 Binary files a/widget/cocoa/cursors/colResize.png and /dev/null differ diff --git a/widget/cocoa/cursors/colResize@2x.png b/widget/cocoa/cursors/colResize@2x.png deleted file mode 100644 index 6a92cf6806..0000000000 Binary files a/widget/cocoa/cursors/colResize@2x.png and /dev/null differ diff --git a/widget/cocoa/cursors/help.png b/widget/cocoa/cursors/help.png deleted file mode 100644 index 5e5416b4e3..0000000000 Binary files a/widget/cocoa/cursors/help.png and /dev/null differ diff --git a/widget/cocoa/cursors/help@2x.png b/widget/cocoa/cursors/help@2x.png deleted file mode 100644 index 0ac53a9733..0000000000 Binary files a/widget/cocoa/cursors/help@2x.png and /dev/null differ diff --git a/widget/cocoa/cursors/move.png b/widget/cocoa/cursors/move.png deleted file mode 100644 index 1360f82277..0000000000 Binary files a/widget/cocoa/cursors/move.png and /dev/null differ diff --git a/widget/cocoa/cursors/move@2x.png b/widget/cocoa/cursors/move@2x.png deleted file mode 100644 index ad146e4863..0000000000 Binary files a/widget/cocoa/cursors/move@2x.png and /dev/null differ diff --git a/widget/cocoa/cursors/rowResize.png b/widget/cocoa/cursors/rowResize.png deleted file mode 100644 index 4c16bb8bd6..0000000000 Binary files a/widget/cocoa/cursors/rowResize.png and /dev/null differ diff --git a/widget/cocoa/cursors/rowResize@2x.png b/widget/cocoa/cursors/rowResize@2x.png deleted file mode 100644 index b48f03ae0d..0000000000 Binary files a/widget/cocoa/cursors/rowResize@2x.png and /dev/null differ diff --git a/widget/cocoa/cursors/sizeNE.png b/widget/cocoa/cursors/sizeNE.png deleted file mode 100644 index f62c046575..0000000000 Binary files a/widget/cocoa/cursors/sizeNE.png and /dev/null differ diff --git a/widget/cocoa/cursors/sizeNE@2x.png b/widget/cocoa/cursors/sizeNE@2x.png deleted file mode 100644 index 98d19e9efa..0000000000 Binary files a/widget/cocoa/cursors/sizeNE@2x.png and /dev/null differ diff --git a/widget/cocoa/cursors/sizeNESW.png b/widget/cocoa/cursors/sizeNESW.png deleted file mode 100644 index 0a077fa674..0000000000 Binary files a/widget/cocoa/cursors/sizeNESW.png and /dev/null differ diff --git a/widget/cocoa/cursors/sizeNESW@2x.png b/widget/cocoa/cursors/sizeNESW@2x.png deleted file mode 100644 index 31bca3c901..0000000000 Binary files a/widget/cocoa/cursors/sizeNESW@2x.png and /dev/null differ diff --git a/widget/cocoa/cursors/sizeNS.png b/widget/cocoa/cursors/sizeNS.png deleted file mode 100644 index 0419be0af7..0000000000 Binary files a/widget/cocoa/cursors/sizeNS.png and /dev/null differ diff --git a/widget/cocoa/cursors/sizeNS@2x.png b/widget/cocoa/cursors/sizeNS@2x.png deleted file mode 100644 index e48fd0cb3a..0000000000 Binary files a/widget/cocoa/cursors/sizeNS@2x.png and /dev/null differ diff --git a/widget/cocoa/cursors/sizeNW.png b/widget/cocoa/cursors/sizeNW.png deleted file mode 100644 index 8f5faee5f7..0000000000 Binary files a/widget/cocoa/cursors/sizeNW.png and /dev/null differ diff --git a/widget/cocoa/cursors/sizeNW@2x.png b/widget/cocoa/cursors/sizeNW@2x.png deleted file mode 100644 index 3a80e7ce91..0000000000 Binary files a/widget/cocoa/cursors/sizeNW@2x.png and /dev/null differ diff --git a/widget/cocoa/cursors/sizeNWSE.png b/widget/cocoa/cursors/sizeNWSE.png deleted file mode 100644 index 0574a584c1..0000000000 Binary files a/widget/cocoa/cursors/sizeNWSE.png and /dev/null differ diff --git a/widget/cocoa/cursors/sizeNWSE@2x.png b/widget/cocoa/cursors/sizeNWSE@2x.png deleted file mode 100644 index 9a0a276c34..0000000000 Binary files a/widget/cocoa/cursors/sizeNWSE@2x.png and /dev/null differ diff --git a/widget/cocoa/cursors/sizeSE.png b/widget/cocoa/cursors/sizeSE.png deleted file mode 100644 index 6a1948f521..0000000000 Binary files a/widget/cocoa/cursors/sizeSE.png and /dev/null differ diff --git a/widget/cocoa/cursors/sizeSE@2x.png b/widget/cocoa/cursors/sizeSE@2x.png deleted file mode 100644 index 7d637f4be6..0000000000 Binary files a/widget/cocoa/cursors/sizeSE@2x.png and /dev/null differ diff --git a/widget/cocoa/cursors/sizeSW.png b/widget/cocoa/cursors/sizeSW.png deleted file mode 100644 index 5dd054dd46..0000000000 Binary files a/widget/cocoa/cursors/sizeSW.png and /dev/null differ diff --git a/widget/cocoa/cursors/sizeSW@2x.png b/widget/cocoa/cursors/sizeSW@2x.png deleted file mode 100644 index 5ac63c25c6..0000000000 Binary files a/widget/cocoa/cursors/sizeSW@2x.png and /dev/null differ diff --git a/widget/cocoa/cursors/vtIBeam.png b/widget/cocoa/cursors/vtIBeam.png deleted file mode 100644 index ee7528c595..0000000000 Binary files a/widget/cocoa/cursors/vtIBeam.png and /dev/null differ diff --git a/widget/cocoa/cursors/vtIBeam@2x.png b/widget/cocoa/cursors/vtIBeam@2x.png deleted file mode 100644 index 41c47af116..0000000000 Binary files a/widget/cocoa/cursors/vtIBeam@2x.png and /dev/null differ diff --git a/widget/cocoa/cursors/zoomIn.png b/widget/cocoa/cursors/zoomIn.png deleted file mode 100644 index 275bf1c69d..0000000000 Binary files a/widget/cocoa/cursors/zoomIn.png and /dev/null differ diff --git a/widget/cocoa/cursors/zoomIn@2x.png b/widget/cocoa/cursors/zoomIn@2x.png deleted file mode 100644 index fdd3f8e71d..0000000000 Binary files a/widget/cocoa/cursors/zoomIn@2x.png and /dev/null differ diff --git a/widget/cocoa/cursors/zoomOut.png b/widget/cocoa/cursors/zoomOut.png deleted file mode 100644 index 19d2d89125..0000000000 Binary files a/widget/cocoa/cursors/zoomOut.png and /dev/null differ diff --git a/widget/cocoa/cursors/zoomOut@2x.png b/widget/cocoa/cursors/zoomOut@2x.png deleted file mode 100644 index 0ed46ce75e..0000000000 Binary files a/widget/cocoa/cursors/zoomOut@2x.png and /dev/null differ diff --git a/widget/cocoa/moz.build b/widget/cocoa/moz.build deleted file mode 100644 index c4f887297d..0000000000 --- a/widget/cocoa/moz.build +++ /dev/null @@ -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'] diff --git a/widget/cocoa/mozView.h b/widget/cocoa/mozView.h deleted file mode 100644 index bd054893ba..0000000000 --- a/widget/cocoa/mozView.h +++ /dev/null @@ -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 -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_ diff --git a/widget/cocoa/nsAppShell.h b/widget/cocoa/nsAppShell.h deleted file mode 100644 index b7836b6391..0000000000 --- a/widget/cocoa/nsAppShell.h +++ /dev/null @@ -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_ diff --git a/widget/cocoa/nsAppShell.mm b/widget/cocoa/nsAppShell.mm deleted file mode 100644 index 33ce8e742a..0000000000 --- a/widget/cocoa/nsAppShell.mm +++ /dev/null @@ -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 - -#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 -#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 - (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 sWakeLockListener; - -static void -AddScreenWakeLockListener() -{ - nsCOMPtr 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 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 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 (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 - (::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 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 diff --git a/widget/cocoa/nsBidiKeyboard.h b/widget/cocoa/nsBidiKeyboard.h deleted file mode 100644 index e7e7ac8722..0000000000 --- a/widget/cocoa/nsBidiKeyboard.h +++ /dev/null @@ -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_ diff --git a/widget/cocoa/nsBidiKeyboard.mm b/widget/cocoa/nsBidiKeyboard.mm deleted file mode 100644 index e0fc86aeb7..0000000000 --- a/widget/cocoa/nsBidiKeyboard.mm +++ /dev/null @@ -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; -} diff --git a/widget/cocoa/nsChangeObserver.h b/widget/cocoa/nsChangeObserver.h deleted file mode 100644 index 1b9a001735..0000000000 --- a/widget/cocoa/nsChangeObserver.h +++ /dev/null @@ -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_ diff --git a/widget/cocoa/nsChildView.h b/widget/cocoa/nsChildView.h deleted file mode 100644 index 2817c8d415..0000000000 --- a/widget/cocoa/nsChildView.h +++ /dev/null @@ -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 -#import -#import - -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& 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 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& 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& aFontRangeArray, - const bool aIsVertical, - const LayoutDeviceIntPoint& aPoint) override; - - void ResetParent(); - - static bool DoHasPendingInputEvent(); - static uint32_t GetCurrentInputEventCount(); - static void UpdateCurrentInputEventCount(); - - NSView* 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 - 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 - AllocateChildPopupWidget() override - { - static NS_DEFINE_IID(kCPopUpCID, NS_POPUP_CID); - nsCOMPtr 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& 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* mView; // my parallel cocoa view, [STRONG] - RefPtr mTextInputHandler; - InputContext mInputContext; - - NSView* 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 mResizerImage; - mozilla::UniquePtr mCornerMaskImage; - mozilla::UniquePtr mTitlebarImage; - mozilla::UniquePtr 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 mGLPresenter; - - mozilla::UniquePtr mVibrancyManager; - RefPtr mSwipeTracker; - mozilla::UniquePtr mSwipeEventQueue; - - // Only used for drawRect-based painting in popups. - RefPtr 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 mSynthesizedTouchInput; -}; - -#endif // nsChildView_h_ diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm deleted file mode 100644 index 868687fe16..0000000000 --- a/widget/cocoa/nsChildView.mm +++ /dev/null @@ -1,6151 +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 "mozilla/ArrayUtils.h" - -#include "mozilla/Logging.h" - -#include -#include - -#include "nsChildView.h" -#include "nsCocoaWindow.h" - -#include "mozilla/MiscEvents.h" -#include "mozilla/MouseEvents.h" -#include "mozilla/TextEvents.h" -#include "mozilla/TouchEvents.h" - -#include "nsArrayUtils.h" -#include "nsObjCExceptions.h" -#include "nsCOMPtr.h" -#include "nsToolkit.h" -#include "nsCRT.h" - -#include "nsFontMetrics.h" -#include "nsIRollupListener.h" -#include "nsViewManager.h" -#include "nsIInterfaceRequestor.h" -#include "nsIFile.h" -#include "nsILocalFileMac.h" -#include "nsGfxCIID.h" -#include "nsIDOMSimpleGestureEvent.h" -#include "nsThemeConstants.h" -#include "nsIWidgetListener.h" -#include "nsIPresShell.h" - -#include "nsDragService.h" -#include "nsClipboard.h" -#include "nsCursorManager.h" -#include "nsWindowMap.h" -#include "nsCocoaFeatures.h" -#include "nsCocoaUtils.h" -#include "nsMenuUtilsX.h" -#include "nsMenuBarX.h" -#include "NativeKeyBindings.h" -#include "ComplexTextInputPanel.h" - -#include "gfxContext.h" -#include "gfxQuartzSurface.h" -#include "gfxUtils.h" -#include "nsRegion.h" -#include "Layers.h" -#include "ClientLayerManager.h" -#include "mozilla/layers/LayerManagerComposite.h" -#include "GfxTexturesReporter.h" -#include "GLTextureImage.h" -#include "GLContextProvider.h" -#include "GLContextCGL.h" -#include "ScopedGLHelpers.h" -#include "HeapCopyOfStackArray.h" -#include "mozilla/layers/IAPZCTreeManager.h" -#include "mozilla/layers/APZThreadUtils.h" -#include "mozilla/layers/GLManager.h" -#include "mozilla/layers/CompositorOGL.h" -#include "mozilla/layers/CompositorBridgeParent.h" -#include "mozilla/layers/BasicCompositor.h" -#include "mozilla/layers/InputAPZContext.h" -#include "mozilla/widget/CompositorWidget.h" -#include "gfxUtils.h" -#include "gfxPrefs.h" -#include "mozilla/gfx/2D.h" -#include "mozilla/gfx/BorrowedContext.h" -#include "mozilla/gfx/MacIOSurface.h" -#ifdef ACCESSIBILITY -#include "nsAccessibilityService.h" -#include "mozilla/a11y/Platform.h" -#endif - -#include "mozilla/Preferences.h" - -#include - -#include - -#include "GeckoProfiler.h" - -#include "nsIDOMWheelEvent.h" -#include "mozilla/layers/ChromeProcessController.h" -#include "nsLayoutUtils.h" -#include "InputData.h" -#include "RectTextureImage.h" -#include "SwipeTracker.h" -#include "VibrancyManager.h" -#include "nsNativeThemeCocoa.h" -#include "nsIDOMWindowUtils.h" -#include "Units.h" -#include "UnitTransforms.h" -#include "mozilla/UniquePtrExtensions.h" - -using namespace mozilla; -using namespace mozilla::layers; -using namespace mozilla::gl; -using namespace mozilla::widget; - -using mozilla::gfx::Matrix4x4; - -#undef DEBUG_UPDATE -#undef INVALIDATE_DEBUGGING // flash areas as they are invalidated - -// Don't put more than this many rects in the dirty region, just fluff -// out to the bounding-box if there are more -#define MAX_RECTS_IN_REGION 100 - -PRLogModuleInfo* sCocoaLog = nullptr; - -extern "C" { - CG_EXTERN void CGContextResetCTM(CGContextRef); - CG_EXTERN void CGContextSetCTM(CGContextRef, CGAffineTransform); - CG_EXTERN void CGContextResetClip(CGContextRef); - - typedef CFTypeRef CGSRegionObj; - CGError CGSNewRegionWithRect(const CGRect *rect, CGSRegionObj *outRegion); - CGError CGSNewRegionWithRectList(const CGRect *rects, int rectCount, CGSRegionObj *outRegion); -} - -// defined in nsMenuBarX.mm -extern NSMenu* sApplicationMenu; // Application menu shared by all menubars - -static bool gChildViewMethodsSwizzled = false; - -extern nsIArray *gDraggedTransferables; - -ChildView* ChildViewMouseTracker::sLastMouseEventView = nil; -NSEvent* ChildViewMouseTracker::sLastMouseMoveEvent = nil; -NSWindow* ChildViewMouseTracker::sWindowUnderMouse = nil; -NSPoint ChildViewMouseTracker::sLastScrollEventScreenLocation = NSZeroPoint; - -#ifdef INVALIDATE_DEBUGGING -static void blinkRect(Rect* r); -static void blinkRgn(RgnHandle rgn); -#endif - -bool gUserCancelledDrag = false; - -uint32_t nsChildView::sLastInputEventCount = 0; - -// The view that will do our drawing or host our NSOpenGLContext or Core Animation layer. -@interface PixelHostingView : NSView { -} -@end - -@interface ChildView(Private) - -// sets up our view, attaching it to its owning gecko view -- (id)initWithFrame:(NSRect)inFrame geckoChild:(nsChildView*)inChild; - -// set up a gecko mouse event based on a cocoa mouse event -- (void) convertCocoaMouseWheelEvent:(NSEvent*)aMouseEvent - toGeckoEvent:(WidgetWheelEvent*)outWheelEvent; -- (void) convertCocoaMouseEvent:(NSEvent*)aMouseEvent - toGeckoEvent:(WidgetInputEvent*)outGeckoEvent; - -- (NSMenu*)contextMenu; - -- (BOOL)isRectObscuredBySubview:(NSRect)inRect; - -- (LayoutDeviceIntRegion)nativeDirtyRegionWithBoundingRect:(NSRect)aRect; -- (BOOL)isUsingOpenGL; -- (void)drawUsingOpenGL; - -- (BOOL)hasRoundedBottomCorners; -- (CGFloat)cornerRadius; -- (void)clearCorners; - --(void)setGLOpaque:(BOOL)aOpaque; - -// Overlay drawing functions for traditional CGContext drawing -- (void)drawTitleString; -- (void)drawTitlebarHighlight; -- (void)maskTopCornersInContext:(CGContextRef)aContext; - -#if USE_CLICK_HOLD_CONTEXTMENU - // called on a timer two seconds after a mouse down to see if we should display - // a context menu (click-hold) -- (void)clickHoldCallback:(id)inEvent; -#endif - -#ifdef ACCESSIBILITY -- (id)accessible; -#endif - -- (LayoutDeviceIntPoint)convertWindowCoordinates:(NSPoint)aPoint; -- (LayoutDeviceIntPoint)convertWindowCoordinatesRoundDown:(NSPoint)aPoint; - -- (BOOL)inactiveWindowAcceptsMouseEvent:(NSEvent*)aEvent; -- (void)updateWindowDraggableState; - -- (bool)shouldConsiderStartingSwipeFromEvent:(NSEvent*)aEvent; - -@end - -@interface NSView(NSThemeFrameCornerRadius) -- (float)roundedCornerRadius; -@end - -@interface NSWindow(NSWindowShouldZoomOnDoubleClick) -+ (BOOL)_shouldZoomOnDoubleClick; // present on 10.7 and above -@end - -// Starting with 10.7 the bottom corners of all windows are rounded. -// Unfortunately, the standard rounding that OS X applies to OpenGL views -// does not use anti-aliasing and looks very crude. Since we want a smooth, -// anti-aliased curve, we'll draw it ourselves. -// Additionally, we need to turn off the OS-supplied rounding because it -// eats into our corner's curve. We do that by overriding an NSSurface method. -@interface NSSurface @end - -@implementation NSSurface(DontCutOffCorners) -- (CGSRegionObj)_createRoundedBottomRegionForRect:(CGRect)rect -{ - // Create a normal rect region without rounded bottom corners. - CGSRegionObj region; - CGSNewRegionWithRect(&rect, ®ion); - return region; -} -@end - -#pragma mark - - -// Flips a screen coordinate from a point in the cocoa coordinate system (bottom-left rect) to a point -// that is a "flipped" cocoa coordinate system (starts in the top-left). -static inline void -FlipCocoaScreenCoordinate(NSPoint &inPoint) -{ - inPoint.y = nsCocoaUtils::FlippedScreenY(inPoint.y); -} - -void EnsureLogInitialized() -{ - if (!sCocoaLog) { - sCocoaLog = PR_NewLogModule("nsCocoaWidgets"); - } -} - -namespace { - -// Used for OpenGL drawing from the compositor thread for OMTC BasicLayers. -// We need to use OpenGL for this because there seems to be no other robust -// way of drawing from a secondary thread without locking, which would cause -// deadlocks in our setup. See bug 882523. -class GLPresenter : public GLManager -{ -public: - static mozilla::UniquePtr CreateForWindow(nsIWidget* aWindow) - { - // Contrary to CompositorOGL, we allow unaccelerated OpenGL contexts to be - // used. BasicCompositor only requires very basic GL functionality. - RefPtr context = gl::GLContextProvider::CreateForWindow(aWindow, false); - return context ? MakeUnique(context) : nullptr; - } - - explicit GLPresenter(GLContext* aContext); - virtual ~GLPresenter(); - - virtual GLContext* gl() const override { return mGLContext; } - virtual ShaderProgramOGL* GetProgram(GLenum aTarget, gfx::SurfaceFormat aFormat) override - { - MOZ_ASSERT(aTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB); - MOZ_ASSERT(aFormat == gfx::SurfaceFormat::R8G8B8A8); - return mRGBARectProgram.get(); - } - virtual const gfx::Matrix4x4& GetProjMatrix() const override - { - return mProjMatrix; - } - virtual void ActivateProgram(ShaderProgramOGL *aProg) override - { - mGLContext->fUseProgram(aProg->GetProgram()); - } - virtual void BindAndDrawQuad(ShaderProgramOGL *aProg, - const gfx::Rect& aLayerRect, - const gfx::Rect& aTextureRect) override; - - void BeginFrame(LayoutDeviceIntSize aRenderSize); - void EndFrame(); - - NSOpenGLContext* GetNSOpenGLContext() - { - return GLContextCGL::Cast(mGLContext)->GetNSOpenGLContext(); - } - -protected: - RefPtr mGLContext; - mozilla::UniquePtr mRGBARectProgram; - gfx::Matrix4x4 mProjMatrix; - GLuint mQuadVBO; -}; - -} // unnamed namespace - -namespace mozilla { - -struct SwipeEventQueue { - SwipeEventQueue(uint32_t aAllowedDirections, uint64_t aInputBlockId) - : allowedDirections(aAllowedDirections) - , inputBlockId(aInputBlockId) - {} - - nsTArray queuedEvents; - uint32_t allowedDirections; - uint64_t inputBlockId; -}; - -} // namespace mozilla - -#pragma mark - - -nsChildView::nsChildView() : nsBaseWidget() -, mView(nullptr) -, mParentView(nullptr) -, mParentWidget(nullptr) -, mViewTearDownLock("ChildViewTearDown") -, mEffectsLock("WidgetEffects") -, mShowsResizeIndicator(false) -, mHasRoundedBottomCorners(false) -, mIsCoveringTitlebar(false) -, mIsFullscreen(false) -, mIsOpaque(false) -, mTitlebarCGContext(nullptr) -, mBackingScaleFactor(0.0) -, mVisible(false) -, mDrawing(false) -, mIsDispatchPaint(false) -{ - EnsureLogInitialized(); -} - -nsChildView::~nsChildView() -{ - ReleaseTitlebarCGContext(); - - if (mSwipeTracker) { - mSwipeTracker->Destroy(); - mSwipeTracker = nullptr; - } - - // Notify the children that we're gone. childView->ResetParent() can change - // our list of children while it's being iterated, so the way we iterate the - // list must allow for this. - for (nsIWidget* kid = mLastChild; kid;) { - nsChildView* childView = static_cast(kid); - kid = kid->GetPrevSibling(); - childView->ResetParent(); - } - - NS_WARNING_ASSERTION( - mOnDestroyCalled, - "nsChildView object destroyed without calling Destroy()"); - - DestroyCompositor(); - - // An nsChildView object that was in use can be destroyed without Destroy() - // ever being called on it. So we also need to do a quick, safe cleanup - // here (it's too late to just call Destroy(), which can cause crashes). - // It's particularly important to make sure widgetDestroyed is called on our - // mView -- this method NULLs mView's mGeckoChild, and NULL checks on - // mGeckoChild are used throughout the ChildView class to tell if it's safe - // to use a ChildView object. - [mView widgetDestroyed]; // Safe if mView is nil. - mParentWidget = nil; - TearDownView(); // Safe if called twice. -} - -void -nsChildView::ReleaseTitlebarCGContext() -{ - if (mTitlebarCGContext) { - CGContextRelease(mTitlebarCGContext); - mTitlebarCGContext = nullptr; - } -} - -nsresult -nsChildView::Create(nsIWidget* aParent, - nsNativeWidget aNativeParent, - const LayoutDeviceIntRect& aRect, - nsWidgetInitData* aInitData) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - // Because the hidden window is created outside of an event loop, - // we need to provide an autorelease pool to avoid leaking cocoa objects - // (see bug 559075). - nsAutoreleasePool localPool; - - // See NSView (MethodSwizzling) below. - if (!gChildViewMethodsSwizzled) { - nsToolkit::SwizzleMethods([NSView class], @selector(mouseDownCanMoveWindow), - @selector(nsChildView_NSView_mouseDownCanMoveWindow)); - gChildViewMethodsSwizzled = true; - } - - mBounds = aRect; - - // Ensure that the toolkit is created. - nsToolkit::GetToolkit(); - - BaseCreate(aParent, aInitData); - - // inherit things from the parent view and create our parallel - // NSView in the Cocoa display system - mParentView = nil; - if (aParent) { - // inherit the top-level window. NS_NATIVE_WIDGET is always a NSView - // regardless of if we're asking a window or a view (for compatibility - // with windows). - mParentView = (NSView*)aParent->GetNativeData(NS_NATIVE_WIDGET); - mParentWidget = aParent; - } else { - // This is the normal case. When we're the root widget of the view hiararchy, - // aNativeParent will be the contentView of our window, since that's what - // nsCocoaWindow returns when asked for an NS_NATIVE_VIEW. - mParentView = reinterpret_cast*>(aNativeParent); - } - - // create our parallel NSView and hook it up to our parent. Recall - // that NS_NATIVE_WIDGET is the NSView. - CGFloat scaleFactor = nsCocoaUtils::GetBackingScaleFactor(mParentView); - NSRect r = nsCocoaUtils::DevPixelsToCocoaPoints(mBounds, scaleFactor); - mView = [[[[ChildView alloc] initWithFrame:r geckoChild:this] autorelease] retain]; - - if (!mView) { - return NS_ERROR_FAILURE; - } - - // If this view was created in a Gecko view hierarchy, the initial state - // is hidden. If the view is attached only to a native NSView but has - // no Gecko parent (as in embedding), the initial state is visible. - if (mParentWidget) - [mView setHidden:YES]; - else - mVisible = true; - - // Hook it up in the NSView hierarchy. - if (mParentView) { - [mParentView addSubview:mView]; - } - - // if this is a ChildView, make sure that our per-window data - // is set up - if ([mView isKindOfClass:[ChildView class]]) - [[WindowDataMap sharedWindowDataMap] ensureDataForWindow:[mView window]]; - - NS_ASSERTION(!mTextInputHandler, "mTextInputHandler has already existed"); - mTextInputHandler = new TextInputHandler(this, mView); - - mPluginFocused = false; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - - -void nsChildView::TearDownView() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mView) - return; - - NSWindow* win = [mView window]; - NSResponder* responder = [win firstResponder]; - - // We're being unhooked from the view hierarchy, don't leave our view - // or a child view as the window first responder. - if (responder && [responder isKindOfClass:[NSView class]] && - [(NSView*)responder isDescendantOf:mView]) { - [win makeFirstResponder:[mView superview]]; - } - - // If mView is win's contentView, win (mView's NSWindow) "owns" mView -- - // win has retained mView, and will detach it from the view hierarchy and - // release it when necessary (when win is itself destroyed (in a call to - // [win dealloc])). So all we need to do here is call [mView release] (to - // match the call to [mView retain] in nsChildView::StandardCreate()). - // Also calling [mView removeFromSuperviewWithoutNeedingDisplay] causes - // mView to be released again and dealloced, while remaining win's - // contentView. So if we do that here, win will (for a short while) have - // an invalid contentView (for the consequences see bmo bugs 381087 and - // 374260). - if ([mView isEqual:[win contentView]]) { - [mView release]; - } else { - // Stop NSView hierarchy being changed during [ChildView drawRect:] - [mView performSelectorOnMainThread:@selector(delayedTearDown) withObject:nil waitUntilDone:false]; - } - mView = nil; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsCocoaWindow* -nsChildView::GetXULWindowWidget() -{ - id windowDelegate = [[mView window] delegate]; - if (windowDelegate && [windowDelegate isKindOfClass:[WindowDelegate class]]) { - return [(WindowDelegate *)windowDelegate geckoWidget]; - } - return nullptr; -} - -void nsChildView::Destroy() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // Make sure that no composition is in progress while disconnecting - // ourselves from the view. - MutexAutoLock lock(mViewTearDownLock); - - if (mOnDestroyCalled) - return; - mOnDestroyCalled = true; - - // Stuff below may delete the last ref to this - nsCOMPtr kungFuDeathGrip(this); - - [mView widgetDestroyed]; - - nsBaseWidget::Destroy(); - - NotifyWindowDestroyed(); - mParentWidget = nil; - - TearDownView(); - - nsBaseWidget::OnDestroy(); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -#pragma mark - - -#if 0 -static void PrintViewHierarchy(NSView *view) -{ - while (view) { - NSLog(@" view is %x, frame %@", view, NSStringFromRect([view frame])); - view = [view superview]; - } -} -#endif - -// Return native data according to aDataType -void* nsChildView::GetNativeData(uint32_t aDataType) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSNULL; - - void* retVal = nullptr; - - switch (aDataType) - { - case NS_NATIVE_WIDGET: - case NS_NATIVE_DISPLAY: - retVal = (void*)mView; - break; - - case NS_NATIVE_WINDOW: - retVal = [mView window]; - break; - - case NS_NATIVE_GRAPHIC: - NS_ERROR("Requesting NS_NATIVE_GRAPHIC on a Mac OS X child view!"); - retVal = nullptr; - break; - - case NS_NATIVE_OFFSETX: - retVal = 0; - break; - - case NS_NATIVE_OFFSETY: - retVal = 0; - break; - - case NS_RAW_NATIVE_IME_CONTEXT: - retVal = GetPseudoIMEContext(); - if (retVal) { - break; - } - retVal = [mView inputContext]; - // If input context isn't available on this widget, we should set |this| - // instead of nullptr since if this returns nullptr, IMEStateManager - // cannot manage composition with TextComposition instance. Although, - // this case shouldn't occur. - if (NS_WARN_IF(!retVal)) { - retVal = this; - } - break; - } - - return retVal; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSNULL; -} - -#pragma mark - - -nsTransparencyMode nsChildView::GetTransparencyMode() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - nsCocoaWindow* windowWidget = GetXULWindowWidget(); - return windowWidget ? windowWidget->GetTransparencyMode() : eTransparencyOpaque; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(eTransparencyOpaque); -} - -// This is called by nsContainerFrame on the root widget for all window types -// except popup windows (when nsCocoaWindow::SetTransparencyMode is used instead). -void nsChildView::SetTransparencyMode(nsTransparencyMode aMode) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - nsCocoaWindow* windowWidget = GetXULWindowWidget(); - if (windowWidget) { - windowWidget->SetTransparencyMode(aMode); - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -bool nsChildView::IsVisible() const -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - if (!mVisible) { - return mVisible; - } - - // mVisible does not accurately reflect the state of a hidden tabbed view - // so verify that the view has a window as well - // then check native widget hierarchy visibility - return ([mView window] != nil) && !NSIsEmptyRect([mView visibleRect]); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false); -} - -// Some NSView methods (e.g. setFrame and setHidden) invalidate the view's -// bounds in our window. However, we don't want these invalidations because -// they are unnecessary and because they actually slow us down since we -// block on the compositor inside drawRect. -// When we actually need something invalidated, there will be an explicit call -// to Invalidate from Gecko, so turning these automatic invalidations off -// won't hurt us in the non-OMTC case. -// The invalidations inside these NSView methods happen via a call to the -// private method -[NSWindow _setNeedsDisplayInRect:]. Our BaseWindow -// implementation of that method is augmented to let us ignore those calls -// using -[BaseWindow disable/enableSetNeedsDisplay]. -static void -ManipulateViewWithoutNeedingDisplay(NSView* aView, void (^aCallback)()) -{ - BaseWindow* win = nil; - if ([[aView window] isKindOfClass:[BaseWindow class]]) { - win = (BaseWindow*)[aView window]; - } - [win disableSetNeedsDisplay]; - aCallback(); - [win enableSetNeedsDisplay]; -} - -// Hide or show this component -NS_IMETHODIMP nsChildView::Show(bool aState) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (aState != mVisible) { - // Provide an autorelease pool because this gets called during startup - // on the "hidden window", resulting in cocoa object leakage if there's - // no pool in place. - nsAutoreleasePool localPool; - - ManipulateViewWithoutNeedingDisplay(mView, ^{ - [mView setHidden:!aState]; - }); - - mVisible = aState; - } - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -// Change the parent of this widget -NS_IMETHODIMP -nsChildView::SetParent(nsIWidget* aNewParent) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (mOnDestroyCalled) - return NS_OK; - - nsCOMPtr kungFuDeathGrip(this); - - if (mParentWidget) { - mParentWidget->RemoveChild(this); - } - - if (aNewParent) { - ReparentNativeWidget(aNewParent); - } else { - [mView removeFromSuperview]; - mParentView = nil; - } - - mParentWidget = aNewParent; - - if (mParentWidget) { - mParentWidget->AddChild(this); - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -void -nsChildView::ReparentNativeWidget(nsIWidget* aNewParent) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - NS_PRECONDITION(aNewParent, ""); - - if (mOnDestroyCalled) - return; - - NSView* newParentView = - (NSView*)aNewParent->GetNativeData(NS_NATIVE_WIDGET); - NS_ENSURE_TRUE_VOID(newParentView); - - // we hold a ref to mView, so this is safe - [mView removeFromSuperview]; - mParentView = newParentView; - [mParentView addSubview:mView]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void nsChildView::ResetParent() -{ - if (!mOnDestroyCalled) { - if (mParentWidget) - mParentWidget->RemoveChild(this); - if (mView) - [mView removeFromSuperview]; - } - mParentWidget = nullptr; -} - -nsIWidget* -nsChildView::GetParent() -{ - return mParentWidget; -} - -float -nsChildView::GetDPI() -{ - NSWindow* window = [mView window]; - if (window && [window isKindOfClass:[BaseWindow class]]) { - return [(BaseWindow*)window getDPI]; - } - - return 96.0; -} - -NS_IMETHODIMP nsChildView::Enable(bool aState) -{ - return NS_OK; -} - -bool nsChildView::IsEnabled() const -{ - return true; -} - -NS_IMETHODIMP nsChildView::SetFocus(bool aRaise) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NSWindow* window = [mView window]; - if (window) - [window makeFirstResponder:mView]; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -// Override to set the cursor on the mac -NS_IMETHODIMP nsChildView::SetCursor(nsCursor aCursor) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if ([mView isDragInProgress]) - return NS_OK; // Don't change the cursor during dragging. - - nsBaseWidget::SetCursor(aCursor); - return [[nsCursorManager sharedInstance] setCursor:aCursor]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -// implement to fix "hidden virtual function" warning -NS_IMETHODIMP nsChildView::SetCursor(imgIContainer* aCursor, - uint32_t aHotspotX, uint32_t aHotspotY) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - nsBaseWidget::SetCursor(aCursor, aHotspotX, aHotspotY); - return [[nsCursorManager sharedInstance] setCursorWithImage:aCursor hotSpotX:aHotspotX hotSpotY:aHotspotY scaleFactor:BackingScaleFactor()]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -#pragma mark - - -// Get this component dimension -LayoutDeviceIntRect -nsChildView::GetBounds() -{ - return !mView ? mBounds : CocoaPointsToDevPixels([mView frame]); -} - -LayoutDeviceIntRect -nsChildView::GetClientBounds() -{ - LayoutDeviceIntRect rect = GetBounds(); - if (!mParentWidget) { - // For top level widgets we want the position on screen, not the position - // of this view inside the window. - rect.MoveTo(WidgetToScreenOffset()); - } - return rect; -} - -LayoutDeviceIntRect -nsChildView::GetScreenBounds() -{ - LayoutDeviceIntRect rect = GetBounds(); - rect.MoveTo(WidgetToScreenOffset()); - return rect; -} - -double -nsChildView::GetDefaultScaleInternal() -{ - return BackingScaleFactor(); -} - -CGFloat -nsChildView::BackingScaleFactor() const -{ - if (mBackingScaleFactor > 0.0) { - return mBackingScaleFactor; - } - if (!mView) { - return 1.0; - } - mBackingScaleFactor = nsCocoaUtils::GetBackingScaleFactor(mView); - return mBackingScaleFactor; -} - -void -nsChildView::BackingScaleFactorChanged() -{ - CGFloat newScale = nsCocoaUtils::GetBackingScaleFactor(mView); - - // ignore notification if it hasn't really changed (or maybe we have - // disabled HiDPI mode via prefs) - if (mBackingScaleFactor == newScale) { - return; - } - - mBackingScaleFactor = newScale; - NSRect frame = [mView frame]; - mBounds = nsCocoaUtils::CocoaRectToGeckoRectDevPix(frame, newScale); - - if (mWidgetListener && !mWidgetListener->GetXULWindow()) { - nsIPresShell* presShell = mWidgetListener->GetPresShell(); - if (presShell) { - presShell->BackingScaleFactorChanged(); - } - } -} - -int32_t -nsChildView::RoundsWidgetCoordinatesTo() -{ - if (BackingScaleFactor() == 2.0) { - return 2; - } - return 1; -} - -// Move this component, aX and aY are in the parent widget coordinate system -NS_IMETHODIMP nsChildView::Move(double aX, double aY) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - int32_t x = NSToIntRound(aX); - int32_t y = NSToIntRound(aY); - - if (!mView || (mBounds.x == x && mBounds.y == y)) - return NS_OK; - - mBounds.x = x; - mBounds.y = y; - - ManipulateViewWithoutNeedingDisplay(mView, ^{ - [mView setFrame:DevPixelsToCocoaPoints(mBounds)]; - }); - - NotifyRollupGeometryChange(); - ReportMoveEvent(); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP nsChildView::Resize(double aWidth, double aHeight, bool aRepaint) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - int32_t width = NSToIntRound(aWidth); - int32_t height = NSToIntRound(aHeight); - - if (!mView || (mBounds.width == width && mBounds.height == height)) - return NS_OK; - - mBounds.width = width; - mBounds.height = height; - - ManipulateViewWithoutNeedingDisplay(mView, ^{ - [mView setFrame:DevPixelsToCocoaPoints(mBounds)]; - }); - - if (mVisible && aRepaint) { - [[mView pixelHostingView] setNeedsDisplay:YES]; - } - - NotifyRollupGeometryChange(); - ReportSizeEvent(); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP nsChildView::Resize(double aX, double aY, - double aWidth, double aHeight, bool aRepaint) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - int32_t x = NSToIntRound(aX); - int32_t y = NSToIntRound(aY); - int32_t width = NSToIntRound(aWidth); - int32_t height = NSToIntRound(aHeight); - - BOOL isMoving = (mBounds.x != x || mBounds.y != y); - BOOL isResizing = (mBounds.width != width || mBounds.height != height); - if (!mView || (!isMoving && !isResizing)) - return NS_OK; - - if (isMoving) { - mBounds.x = x; - mBounds.y = y; - } - if (isResizing) { - mBounds.width = width; - mBounds.height = height; - } - - ManipulateViewWithoutNeedingDisplay(mView, ^{ - [mView setFrame:DevPixelsToCocoaPoints(mBounds)]; - }); - - if (mVisible && aRepaint) { - [[mView pixelHostingView] setNeedsDisplay:YES]; - } - - NotifyRollupGeometryChange(); - if (isMoving) { - ReportMoveEvent(); - if (mOnDestroyCalled) - return NS_OK; - } - if (isResizing) - ReportSizeEvent(); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -static const int32_t resizeIndicatorWidth = 15; -static const int32_t resizeIndicatorHeight = 15; -bool nsChildView::ShowsResizeIndicator(LayoutDeviceIntRect* aResizerRect) -{ - NSView *topLevelView = mView, *superView = nil; - while ((superView = [topLevelView superview])) - topLevelView = superView; - - if (![[topLevelView window] showsResizeIndicator] || - !([[topLevelView window] styleMask] & NSResizableWindowMask)) - return false; - - if (aResizerRect) { - NSSize bounds = [topLevelView bounds].size; - NSPoint corner = NSMakePoint(bounds.width, [topLevelView isFlipped] ? bounds.height : 0); - corner = [topLevelView convertPoint:corner toView:mView]; - aResizerRect->SetRect(NSToIntRound(corner.x) - resizeIndicatorWidth, - NSToIntRound(corner.y) - resizeIndicatorHeight, - resizeIndicatorWidth, resizeIndicatorHeight); - } - return true; -} - -nsresult nsChildView::SynthesizeNativeKeyEvent(int32_t aNativeKeyboardLayout, - int32_t aNativeKeyCode, - uint32_t aModifierFlags, - const nsAString& aCharacters, - const nsAString& aUnmodifiedCharacters, - nsIObserver* aObserver) -{ - AutoObserverNotifier notifier(aObserver, "keyevent"); - return mTextInputHandler->SynthesizeNativeKeyEvent(aNativeKeyboardLayout, - aNativeKeyCode, - aModifierFlags, - aCharacters, - aUnmodifiedCharacters); -} - -nsresult nsChildView::SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint, - uint32_t aNativeMessage, - uint32_t aModifierFlags, - nsIObserver* aObserver) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - AutoObserverNotifier notifier(aObserver, "mouseevent"); - - NSPoint pt = - nsCocoaUtils::DevPixelsToCocoaPoints(aPoint, BackingScaleFactor()); - - // Move the mouse cursor to the requested position and reconnect it to the mouse. - CGWarpMouseCursorPosition(NSPointToCGPoint(pt)); - CGAssociateMouseAndMouseCursorPosition(true); - - // aPoint is given with the origin on the top left, but convertScreenToBase - // expects a point in a coordinate system that has its origin on the bottom left. - NSPoint screenPoint = NSMakePoint(pt.x, nsCocoaUtils::FlippedScreenY(pt.y)); - NSPoint windowPoint = - nsCocoaUtils::ConvertPointFromScreen([mView window], screenPoint); - - NSEvent* event = [NSEvent mouseEventWithType:(NSEventType)aNativeMessage - location:windowPoint - modifierFlags:aModifierFlags - timestamp:[[NSProcessInfo processInfo] systemUptime] - windowNumber:[[mView window] windowNumber] - context:nil - eventNumber:0 - clickCount:1 - pressure:0.0]; - - if (!event) - return NS_ERROR_FAILURE; - - if ([[mView window] isKindOfClass:[BaseWindow class]]) { - // Tracking area events don't end up in their tracking areas when sent - // through [NSApp sendEvent:], so pass them directly to the right methods. - BaseWindow* window = (BaseWindow*)[mView window]; - if (aNativeMessage == NSMouseEntered) { - [window mouseEntered:event]; - return NS_OK; - } - if (aNativeMessage == NSMouseExited) { - [window mouseExited:event]; - return NS_OK; - } - if (aNativeMessage == NSMouseMoved) { - [window mouseMoved:event]; - return NS_OK; - } - } - - [NSApp sendEvent:event]; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -nsresult nsChildView::SynthesizeNativeMouseScrollEvent(mozilla::LayoutDeviceIntPoint aPoint, - uint32_t aNativeMessage, - double aDeltaX, - double aDeltaY, - double aDeltaZ, - uint32_t aModifierFlags, - uint32_t aAdditionalFlags, - nsIObserver* aObserver) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - AutoObserverNotifier notifier(aObserver, "mousescrollevent"); - - NSPoint pt = - nsCocoaUtils::DevPixelsToCocoaPoints(aPoint, BackingScaleFactor()); - - // Move the mouse cursor to the requested position and reconnect it to the mouse. - CGWarpMouseCursorPosition(NSPointToCGPoint(pt)); - CGAssociateMouseAndMouseCursorPosition(true); - - // Mostly copied from http://stackoverflow.com/a/6130349 - CGScrollEventUnit units = - (aAdditionalFlags & nsIDOMWindowUtils::MOUSESCROLL_SCROLL_LINES) - ? kCGScrollEventUnitLine : kCGScrollEventUnitPixel; - CGEventRef cgEvent = CGEventCreateScrollWheelEvent(NULL, units, 3, aDeltaY, aDeltaX, aDeltaZ); - if (!cgEvent) { - return NS_ERROR_FAILURE; - } - - CGEventPost(kCGHIDEventTap, cgEvent); - CFRelease(cgEvent); - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -nsresult nsChildView::SynthesizeNativeTouchPoint(uint32_t aPointerId, - TouchPointerState aPointerState, - mozilla::LayoutDeviceIntPoint aPoint, - double aPointerPressure, - uint32_t aPointerOrientation, - nsIObserver* aObserver) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - AutoObserverNotifier notifier(aObserver, "touchpoint"); - - MOZ_ASSERT(NS_IsMainThread()); - if (aPointerState == TOUCH_HOVER) { - return NS_ERROR_UNEXPECTED; - } - - if (!mSynthesizedTouchInput) { - mSynthesizedTouchInput = MakeUnique(); - } - - LayoutDeviceIntPoint pointInWindow = aPoint - WidgetToScreenOffset(); - MultiTouchInput inputToDispatch = UpdateSynthesizedTouchState( - mSynthesizedTouchInput.get(), PR_IntervalNow(), TimeStamp::Now(), - aPointerId, aPointerState, pointInWindow, aPointerPressure, - aPointerOrientation); - DispatchTouchInput(inputToDispatch); - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -// First argument has to be an NSMenu representing the application's top-level -// menu bar. The returned item is *not* retained. -static NSMenuItem* NativeMenuItemWithLocation(NSMenu* menubar, NSString* locationString) -{ - NSArray* indexes = [locationString componentsSeparatedByString:@"|"]; - unsigned int indexCount = [indexes count]; - if (indexCount == 0) - return nil; - - NSMenu* currentSubmenu = [NSApp mainMenu]; - for (unsigned int i = 0; i < indexCount; i++) { - int targetIndex; - // We remove the application menu from consideration for the top-level menu - if (i == 0) - targetIndex = [[indexes objectAtIndex:i] intValue] + 1; - else - targetIndex = [[indexes objectAtIndex:i] intValue]; - int itemCount = [currentSubmenu numberOfItems]; - if (targetIndex < itemCount) { - NSMenuItem* menuItem = [currentSubmenu itemAtIndex:targetIndex]; - // if this is the last index just return the menu item - if (i == (indexCount - 1)) - return menuItem; - // if this is not the last index find the submenu and keep going - if ([menuItem hasSubmenu]) - currentSubmenu = [menuItem submenu]; - else - return nil; - } - } - - return nil; -} - -// Used for testing native menu system structure and event handling. -NS_IMETHODIMP nsChildView::ActivateNativeMenuItemAt(const nsAString& indexString) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NSString* locationString = [NSString stringWithCharacters:reinterpret_cast(indexString.BeginReading()) - length:indexString.Length()]; - NSMenuItem* item = NativeMenuItemWithLocation([NSApp mainMenu], locationString); - // We can't perform an action on an item with a submenu, that will raise - // an obj-c exception. - if (item && ![item hasSubmenu]) { - NSMenu* parent = [item menu]; - if (parent) { - // NSLog(@"Performing action for native menu item titled: %@\n", - // [[currentSubmenu itemAtIndex:targetIndex] title]); - [parent performActionForItemAtIndex:[parent indexOfItem:item]]; - return NS_OK; - } - } - return NS_ERROR_FAILURE; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -// Used for testing native menu system structure and event handling. -NS_IMETHODIMP nsChildView::ForceUpdateNativeMenuAt(const nsAString& indexString) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - nsCocoaWindow *widget = GetXULWindowWidget(); - if (widget) { - nsMenuBarX* mb = widget->GetMenuBar(); - if (mb) { - if (indexString.IsEmpty()) - mb->ForceNativeMenuReload(); - else - mb->ForceUpdateNativeMenuAt(indexString); - } - } - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -#pragma mark - - -#ifdef INVALIDATE_DEBUGGING - -static Boolean KeyDown(const UInt8 theKey) -{ - KeyMap map; - GetKeys(map); - return ((*((UInt8 *)map + (theKey >> 3)) >> (theKey & 7)) & 1) != 0; -} - -static Boolean caps_lock() -{ - return KeyDown(0x39); -} - -static void blinkRect(Rect* r) -{ - StRegionFromPool oldClip; - if (oldClip != NULL) - ::GetClip(oldClip); - - ::ClipRect(r); - ::InvertRect(r); - UInt32 end = ::TickCount() + 5; - while (::TickCount() < end) ; - ::InvertRect(r); - - if (oldClip != NULL) - ::SetClip(oldClip); -} - -static void blinkRgn(RgnHandle rgn) -{ - StRegionFromPool oldClip; - if (oldClip != NULL) - ::GetClip(oldClip); - - ::SetClip(rgn); - ::InvertRgn(rgn); - UInt32 end = ::TickCount() + 5; - while (::TickCount() < end) ; - ::InvertRgn(rgn); - - if (oldClip != NULL) - ::SetClip(oldClip); -} - -#endif - -// Invalidate this component's visible area -NS_IMETHODIMP nsChildView::Invalidate(const LayoutDeviceIntRect& aRect) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (!mView || !mVisible) - return NS_OK; - - NS_ASSERTION(GetLayerManager()->GetBackendType() != LayersBackend::LAYERS_CLIENT, - "Shouldn't need to invalidate with accelerated OMTC layers!"); - - [[mView pixelHostingView] setNeedsDisplayInRect:DevPixelsToCocoaPoints(aRect)]; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -bool -nsChildView::WidgetTypeSupportsAcceleration() -{ - // Don't use OpenGL for transparent windows or for popup windows. - return mView && [[mView window] isOpaque] && - ![[mView window] isKindOfClass:[PopupWindow class]]; -} - -bool -nsChildView::ShouldUseOffMainThreadCompositing() -{ - // Don't use OMTC for transparent windows or for popup windows. - if (!mView || ![[mView window] isOpaque] || - [[mView window] isKindOfClass:[PopupWindow class]]) - return false; - - return nsBaseWidget::ShouldUseOffMainThreadCompositing(); -} - -inline uint16_t COLOR8TOCOLOR16(uint8_t color8) -{ - // return (color8 == 0xFF ? 0xFFFF : (color8 << 8)); - return (color8 << 8) | color8; /* (color8 * 257) == (color8 * 0x0101) */ -} - -#pragma mark - - -nsresult nsChildView::ConfigureChildren(const nsTArray& aConfigurations) -{ - return NS_OK; -} - -// Invokes callback and ProcessEvent methods on Event Listener object -NS_IMETHODIMP nsChildView::DispatchEvent(WidgetGUIEvent* event, - nsEventStatus& aStatus) -{ - RefPtr kungFuDeathGrip(this); - -#ifdef DEBUG - debug_DumpEvent(stdout, event->mWidget, event, "something", 0); -#endif - - NS_ASSERTION(!(mTextInputHandler && mTextInputHandler->IsIMEComposing() && - event->HasKeyEventMessage()), - "Any key events should not be fired during IME composing"); - - if (event->mFlags.mIsSynthesizedForTests) { - WidgetKeyboardEvent* keyEvent = event->AsKeyboardEvent(); - if (keyEvent) { - nsresult rv = mTextInputHandler->AttachNativeKeyEvent(*keyEvent); - NS_ENSURE_SUCCESS(rv, rv); - } - } - - aStatus = nsEventStatus_eIgnore; - - nsIWidgetListener* listener = mWidgetListener; - - // If the listener is NULL, check if the parent is a popup. If it is, then - // this child is the popup content view attached to a popup. Get the - // listener from the parent popup instead. - nsCOMPtr parentWidget = mParentWidget; - if (!listener && parentWidget) { - if (parentWidget->WindowType() == eWindowType_popup) { - // Check just in case event->mWidget isn't this widget - if (event->mWidget) { - listener = event->mWidget->GetWidgetListener(); - } - if (!listener) { - event->mWidget = parentWidget; - listener = parentWidget->GetWidgetListener(); - } - } - } - - if (listener) - aStatus = listener->HandleEvent(event, mUseAttachedEvents); - - return NS_OK; -} - -bool nsChildView::DispatchWindowEvent(WidgetGUIEvent& event) -{ - nsEventStatus status; - DispatchEvent(&event, status); - return ConvertStatus(status); -} - -nsIWidget* -nsChildView::GetWidgetForListenerEvents() -{ - // If there is no listener, use the parent popup's listener if that exists. - if (!mWidgetListener && mParentWidget && - mParentWidget->WindowType() == eWindowType_popup) { - return mParentWidget; - } - - return this; -} - -void nsChildView::WillPaintWindow() -{ - nsCOMPtr widget = GetWidgetForListenerEvents(); - - nsIWidgetListener* listener = widget->GetWidgetListener(); - if (listener) { - listener->WillPaintWindow(widget); - } -} - -bool nsChildView::PaintWindow(LayoutDeviceIntRegion aRegion) -{ - nsCOMPtr widget = GetWidgetForListenerEvents(); - - nsIWidgetListener* listener = widget->GetWidgetListener(); - if (!listener) - return false; - - bool returnValue = false; - bool oldDispatchPaint = mIsDispatchPaint; - mIsDispatchPaint = true; - returnValue = listener->PaintWindow(widget, aRegion); - - listener = widget->GetWidgetListener(); - if (listener) { - listener->DidPaintWindow(); - } - - mIsDispatchPaint = oldDispatchPaint; - return returnValue; -} - -bool -nsChildView::PaintWindowInContext(CGContextRef aContext, const LayoutDeviceIntRegion& aRegion, gfx::IntSize aSurfaceSize) -{ - if (!mBackingSurface || mBackingSurface->GetSize() != aSurfaceSize) { - mBackingSurface = - gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(aSurfaceSize, - gfx::SurfaceFormat::B8G8R8A8); - if (!mBackingSurface) { - return false; - } - } - - RefPtr targetContext = gfxContext::CreateOrNull(mBackingSurface); - MOZ_ASSERT(targetContext); // already checked the draw target above - - // Set up the clip region and clear existing contents in the backing surface. - targetContext->NewPath(); - for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) { - const LayoutDeviceIntRect& r = iter.Get(); - targetContext->Rectangle(gfxRect(r.x, r.y, r.width, r.height)); - mBackingSurface->ClearRect(gfx::Rect(r.ToUnknownRect())); - } - targetContext->Clip(); - - nsAutoRetainCocoaObject kungFuDeathGrip(mView); - bool painted = false; - if (GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_BASIC) { - nsBaseWidget::AutoLayerManagerSetup - setupLayerManager(this, targetContext, BufferMode::BUFFER_NONE); - painted = PaintWindow(aRegion); - } else if (GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT) { - // We only need this so that we actually get DidPaintWindow fired - painted = PaintWindow(aRegion); - } - - uint8_t* data; - gfx::IntSize size; - int32_t stride; - gfx::SurfaceFormat format; - - if (!mBackingSurface->LockBits(&data, &size, &stride, &format)) { - return false; - } - - // Draw the backing surface onto the window. - CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, data, stride * size.height, NULL); - NSColorSpace* colorSpace = [[mView window] colorSpace]; - CGImageRef image = CGImageCreate(size.width, size.height, 8, 32, stride, - [colorSpace CGColorSpace], - kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst, - provider, NULL, false, kCGRenderingIntentDefault); - CGContextSaveGState(aContext); - CGContextTranslateCTM(aContext, 0, size.height); - CGContextScaleCTM(aContext, 1, -1); - CGContextSetBlendMode(aContext, kCGBlendModeCopy); - CGContextDrawImage(aContext, CGRectMake(0, 0, size.width, size.height), image); - CGImageRelease(image); - CGDataProviderRelease(provider); - CGContextRestoreGState(aContext); - - mBackingSurface->ReleaseBits(data); - - return painted; -} - -#pragma mark - - -void nsChildView::ReportMoveEvent() -{ - NotifyWindowMoved(mBounds.x, mBounds.y); -} - -void nsChildView::ReportSizeEvent() -{ - if (mWidgetListener) - mWidgetListener->WindowResized(this, mBounds.width, mBounds.height); -} - -#pragma mark - - -LayoutDeviceIntPoint nsChildView::GetClientOffset() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - NSPoint origin = [mView convertPoint:NSMakePoint(0, 0) toView:nil]; - origin.y = [[mView window] frame].size.height - origin.y; - return CocoaPointsToDevPixels(origin); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(LayoutDeviceIntPoint(0, 0)); -} - -// Return the offset between this child view and the screen. -// @return -- widget origin in device-pixel coords -LayoutDeviceIntPoint nsChildView::WidgetToScreenOffset() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - NSPoint origin = NSMakePoint(0, 0); - - // 1. First translate view origin point into window coords. - // The returned point is in bottom-left coordinates. - origin = [mView convertPoint:origin toView:nil]; - - // 2. We turn the window-coord rect's origin into screen (still bottom-left) coords. - origin = nsCocoaUtils::ConvertPointToScreen([mView window], origin); - - // 3. Since we're dealing in bottom-left coords, we need to make it top-left coords - // before we pass it back to Gecko. - FlipCocoaScreenCoordinate(origin); - - // convert to device pixels - return CocoaPointsToDevPixels(origin); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(LayoutDeviceIntPoint(0,0)); -} - -NS_IMETHODIMP nsChildView::SetTitle(const nsAString& title) -{ - // child views don't have titles - return NS_OK; -} - -NS_IMETHODIMP nsChildView::GetAttention(int32_t aCycleCount) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - [NSApp requestUserAttention:NSInformationalRequest]; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -/* static */ -bool nsChildView::DoHasPendingInputEvent() -{ - return sLastInputEventCount != GetCurrentInputEventCount(); -} - -/* static */ -uint32_t nsChildView::GetCurrentInputEventCount() -{ - // Can't use kCGAnyInputEventType because that updates too rarely for us (and - // always in increments of 30+!) and because apparently it's sort of broken - // on Tiger. So just go ahead and query the counters we care about. - static const CGEventType eventTypes[] = { - kCGEventLeftMouseDown, - kCGEventLeftMouseUp, - kCGEventRightMouseDown, - kCGEventRightMouseUp, - kCGEventMouseMoved, - kCGEventLeftMouseDragged, - kCGEventRightMouseDragged, - kCGEventKeyDown, - kCGEventKeyUp, - kCGEventScrollWheel, - kCGEventTabletPointer, - kCGEventOtherMouseDown, - kCGEventOtherMouseUp, - kCGEventOtherMouseDragged - }; - - uint32_t eventCount = 0; - for (uint32_t i = 0; i < ArrayLength(eventTypes); ++i) { - eventCount += - CGEventSourceCounterForEventType(kCGEventSourceStateCombinedSessionState, - eventTypes[i]); - } - return eventCount; -} - -/* static */ -void nsChildView::UpdateCurrentInputEventCount() -{ - sLastInputEventCount = GetCurrentInputEventCount(); -} - -bool nsChildView::HasPendingInputEvent() -{ - return DoHasPendingInputEvent(); -} - -#pragma mark - - -NS_IMETHODIMP -nsChildView::StartPluginIME(const mozilla::WidgetKeyboardEvent& aKeyboardEvent, - int32_t aPanelX, int32_t aPanelY, - nsString& aCommitted) -{ - NS_ENSURE_TRUE(mView, NS_ERROR_NOT_AVAILABLE); - - ComplexTextInputPanel* ctiPanel = - ComplexTextInputPanel::GetSharedComplexTextInputPanel(); - - ctiPanel->PlacePanel(aPanelX, aPanelY); - // We deliberately don't use TextInputHandler::GetCurrentKeyEvent() to - // obtain the NSEvent* we pass to InterpretKeyEvent(). This works fine in - // non-e10s mode. But in e10s mode TextInputHandler::HandleKeyDownEvent() - // has already returned, so the relevant KeyEventState* (and its NSEvent*) - // is already out of scope. Furthermore we don't *need* to use it. - // StartPluginIME() is only ever called to start a new IME session when none - // currently exists. So nested IME should never reach here, and so it should - // be fine to use the last key-down event received by -[ChildView keyDown:] - // (as we currently do). - ctiPanel->InterpretKeyEvent([(ChildView*)mView lastKeyDownEvent], aCommitted); - - return NS_OK; -} - -void -nsChildView::SetPluginFocused(bool& aFocused) -{ - if (aFocused == mPluginFocused) { - return; - } - if (!aFocused) { - ComplexTextInputPanel* ctiPanel = - ComplexTextInputPanel::GetSharedComplexTextInputPanel(); - if (ctiPanel) { - ctiPanel->CancelComposition(); - } - } - mPluginFocused = aFocused; -} - -NS_IMETHODIMP_(void) -nsChildView::SetInputContext(const InputContext& aContext, - const InputContextAction& aAction) -{ - NS_ENSURE_TRUE_VOID(mTextInputHandler); - - if (mTextInputHandler->IsFocused()) { - if (aContext.IsPasswordEditor()) { - TextInputHandler::EnableSecureEventInput(); - } else { - TextInputHandler::EnsureSecureEventInputDisabled(); - } - } - - mInputContext = aContext; - switch (aContext.mIMEState.mEnabled) { - case IMEState::ENABLED: - case IMEState::PLUGIN: - mTextInputHandler->SetASCIICapableOnly(false); - mTextInputHandler->EnableIME(true); - if (mInputContext.mIMEState.mOpen != IMEState::DONT_CHANGE_OPEN_STATE) { - mTextInputHandler->SetIMEOpenState( - mInputContext.mIMEState.mOpen == IMEState::OPEN); - } - break; - case IMEState::DISABLED: - mTextInputHandler->SetASCIICapableOnly(false); - mTextInputHandler->EnableIME(false); - break; - case IMEState::PASSWORD: - mTextInputHandler->SetASCIICapableOnly(true); - mTextInputHandler->EnableIME(false); - break; - default: - NS_ERROR("not implemented!"); - } -} - -NS_IMETHODIMP_(InputContext) -nsChildView::GetInputContext() -{ - switch (mInputContext.mIMEState.mEnabled) { - case IMEState::ENABLED: - case IMEState::PLUGIN: - if (mTextInputHandler) { - mInputContext.mIMEState.mOpen = - mTextInputHandler->IsIMEOpened() ? IMEState::OPEN : IMEState::CLOSED; - break; - } - // If mTextInputHandler is null, set CLOSED instead... - MOZ_FALLTHROUGH; - default: - mInputContext.mIMEState.mOpen = IMEState::CLOSED; - break; - } - return mInputContext; -} - -NS_IMETHODIMP_(TextEventDispatcherListener*) -nsChildView::GetNativeTextEventDispatcherListener() -{ - if (NS_WARN_IF(!mTextInputHandler)) { - return nullptr; - } - return mTextInputHandler; -} - -NS_IMETHODIMP -nsChildView::AttachNativeKeyEvent(mozilla::WidgetKeyboardEvent& aEvent) -{ - NS_ENSURE_TRUE(mTextInputHandler, NS_ERROR_NOT_AVAILABLE); - return mTextInputHandler->AttachNativeKeyEvent(aEvent); -} - -bool -nsChildView::ExecuteNativeKeyBindingRemapped(NativeKeyBindingsType aType, - const WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData, - uint32_t aGeckoKeyCode, - uint32_t aCocoaKeyCode) -{ - NSEvent *originalEvent = reinterpret_cast(aEvent.mNativeKeyEvent); - - WidgetKeyboardEvent modifiedEvent(aEvent); - modifiedEvent.mKeyCode = aGeckoKeyCode; - - unichar ch = nsCocoaUtils::ConvertGeckoKeyCodeToMacCharCode(aGeckoKeyCode); - NSString *chars = - [[[NSString alloc] initWithCharacters:&ch length:1] autorelease]; - - modifiedEvent.mNativeKeyEvent = - [NSEvent keyEventWithType:[originalEvent type] - location:[originalEvent locationInWindow] - modifierFlags:[originalEvent modifierFlags] - timestamp:[originalEvent timestamp] - windowNumber:[originalEvent windowNumber] - context:[originalEvent context] - characters:chars - charactersIgnoringModifiers:chars - isARepeat:[originalEvent isARepeat] - keyCode:aCocoaKeyCode]; - - NativeKeyBindings* keyBindings = NativeKeyBindings::GetInstance(aType); - return keyBindings->Execute(modifiedEvent, aCallback, aCallbackData); -} - -NS_IMETHODIMP_(bool) -nsChildView::ExecuteNativeKeyBinding(NativeKeyBindingsType aType, - const WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData) -{ - // If the key is a cursor-movement arrow, and the current selection has - // vertical writing-mode, we'll remap so that the movement command - // generated (in terms of characters/lines) will be appropriate for - // the physical direction of the arrow. - if (aEvent.mKeyCode >= NS_VK_LEFT && aEvent.mKeyCode <= NS_VK_DOWN) { - WidgetQueryContentEvent query(true, eQuerySelectedText, this); - DispatchWindowEvent(query); - - if (query.mSucceeded && query.mReply.mWritingMode.IsVertical()) { - uint32_t geckoKey = 0; - uint32_t cocoaKey = 0; - - switch (aEvent.mKeyCode) { - case NS_VK_LEFT: - if (query.mReply.mWritingMode.IsVerticalLR()) { - geckoKey = NS_VK_UP; - cocoaKey = kVK_UpArrow; - } else { - geckoKey = NS_VK_DOWN; - cocoaKey = kVK_DownArrow; - } - break; - - case NS_VK_RIGHT: - if (query.mReply.mWritingMode.IsVerticalLR()) { - geckoKey = NS_VK_DOWN; - cocoaKey = kVK_DownArrow; - } else { - geckoKey = NS_VK_UP; - cocoaKey = kVK_UpArrow; - } - break; - - case NS_VK_UP: - geckoKey = NS_VK_LEFT; - cocoaKey = kVK_LeftArrow; - break; - - case NS_VK_DOWN: - geckoKey = NS_VK_RIGHT; - cocoaKey = kVK_RightArrow; - break; - } - - return ExecuteNativeKeyBindingRemapped(aType, aEvent, aCallback, - aCallbackData, - geckoKey, cocoaKey); - } - } - - NativeKeyBindings* keyBindings = NativeKeyBindings::GetInstance(aType); - return keyBindings->Execute(aEvent, aCallback, aCallbackData); -} - -nsIMEUpdatePreference -nsChildView::GetIMEUpdatePreference() -{ - // XXX Shouldn't we move floating window which shows composition string - // when plugin has focus and its parent is scrolled or the window is - // moved? - return nsIMEUpdatePreference(); -} - -NSView* nsChildView::GetEditorView() -{ - NSView* editorView = mView; - // We need to get editor's view. E.g., when the focus is in the bookmark - // dialog, the view is element of the dialog. At this time, the key - // events are processed the parent window's view that has native focus. - WidgetQueryContentEvent textContent(true, eQueryTextContent, this); - textContent.InitForQueryTextContent(0, 0); - DispatchWindowEvent(textContent); - if (textContent.mSucceeded && textContent.mReply.mFocusedWidget) { - NSView* view = static_cast*>( - textContent.mReply.mFocusedWidget->GetNativeData(NS_NATIVE_WIDGET)); - if (view) - editorView = view; - } - return editorView; -} - -#pragma mark - - -void -nsChildView::CreateCompositor() -{ - nsBaseWidget::CreateCompositor(); - if (mCompositorBridgeChild) { - [(ChildView *)mView setUsingOMTCompositor:true]; - } -} - -void -nsChildView::ConfigureAPZCTreeManager() -{ - nsBaseWidget::ConfigureAPZCTreeManager(); -} - -void -nsChildView::ConfigureAPZControllerThread() -{ - if (gfxPrefs::AsyncPanZoomSeparateEventThread()) { - // The EventThreadRunner is the controller thread, but it doesn't - // have a MessageLoop. - APZThreadUtils::SetControllerThread(nullptr); - } else { - nsBaseWidget::ConfigureAPZControllerThread(); - } -} - -LayoutDeviceIntRect -nsChildView::RectContainingTitlebarControls() -{ - // Start with a thin strip at the top of the window for the highlight line. - NSRect rect = NSMakeRect(0, 0, [mView bounds].size.width, - [(ChildView*)mView cornerRadius]); - - // If we draw the titlebar title string, increase the height to the default - // titlebar height. This height does not necessarily include all the titlebar - // controls because we may have moved them further down, but at least it will - // include the whole title text. - BaseWindow* window = (BaseWindow*)[mView window]; - if ([window wantsTitleDrawn] && [window isKindOfClass:[ToolbarWindow class]]) { - CGFloat defaultTitlebarHeight = [(ToolbarWindow*)window titlebarHeight]; - rect.size.height = std::max(rect.size.height, defaultTitlebarHeight); - } - - // Add the rects of the titlebar controls. - for (id view in [window titlebarControls]) { - rect = NSUnionRect(rect, [mView convertRect:[view bounds] fromView:view]); - } - return CocoaPointsToDevPixels(rect); -} - -void -nsChildView::PrepareWindowEffects() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - bool canBeOpaque; - { - MutexAutoLock lock(mEffectsLock); - mShowsResizeIndicator = ShowsResizeIndicator(&mResizeIndicatorRect); - mHasRoundedBottomCorners = [(ChildView*)mView hasRoundedBottomCorners]; - CGFloat cornerRadius = [(ChildView*)mView cornerRadius]; - mDevPixelCornerRadius = cornerRadius * BackingScaleFactor(); - mIsCoveringTitlebar = [(ChildView*)mView isCoveringTitlebar]; - NSInteger styleMask = [[mView window] styleMask]; - bool wasFullscreen = mIsFullscreen; - mIsFullscreen = (styleMask & NSFullScreenWindowMask) || !(styleMask & NSTitledWindowMask); - - canBeOpaque = mIsFullscreen && wasFullscreen; - if (canBeOpaque && VibrancyManager::SystemSupportsVibrancy()) { - canBeOpaque = !EnsureVibrancyManager().HasVibrantRegions(); - } - if (mIsCoveringTitlebar) { - mTitlebarRect = RectContainingTitlebarControls(); - UpdateTitlebarCGContext(); - } - } - - // If we've just transitioned into or out of full screen then update the opacity on our GLContext. - if (canBeOpaque != mIsOpaque) { - mIsOpaque = canBeOpaque; - [(ChildView*)mView setGLOpaque:canBeOpaque]; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void -nsChildView::CleanupWindowEffects() -{ - mResizerImage = nullptr; - mCornerMaskImage = nullptr; - mTitlebarImage = nullptr; -} - -bool -nsChildView::PreRender(WidgetRenderingContext* aContext) -{ - UniquePtr manager(GLManager::CreateGLManager(aContext->mLayerManager)); - if (!manager) { - return true; - } - - // The lock makes sure that we don't attempt to tear down the view while - // compositing. That would make us unable to call postRender on it when the - // composition is done, thus keeping the GL context locked forever. - mViewTearDownLock.Lock(); - - NSOpenGLContext *glContext = GLContextCGL::Cast(manager->gl())->GetNSOpenGLContext(); - - if (![(ChildView*)mView preRender:glContext]) { - mViewTearDownLock.Unlock(); - return false; - } - return true; -} - -void -nsChildView::PostRender(WidgetRenderingContext* aContext) -{ - UniquePtr manager(GLManager::CreateGLManager(aContext->mLayerManager)); - if (!manager) { - return; - } - NSOpenGLContext *glContext = GLContextCGL::Cast(manager->gl())->GetNSOpenGLContext(); - [(ChildView*)mView postRender:glContext]; - mViewTearDownLock.Unlock(); -} - -void -nsChildView::DrawWindowOverlay(WidgetRenderingContext* aContext, - LayoutDeviceIntRect aRect) -{ - mozilla::UniquePtr manager(GLManager::CreateGLManager(aContext->mLayerManager)); - if (manager) { - DrawWindowOverlay(manager.get(), aRect); - } -} - -void -nsChildView::DrawWindowOverlay(GLManager* aManager, LayoutDeviceIntRect aRect) -{ - GLContext* gl = aManager->gl(); - ScopedGLState scopedScissorTestState(gl, LOCAL_GL_SCISSOR_TEST, false); - - MaybeDrawTitlebar(aManager); - MaybeDrawResizeIndicator(aManager); - MaybeDrawRoundedCorners(aManager, aRect); -} - -static void -ClearRegion(gfx::DrawTarget *aDT, LayoutDeviceIntRegion aRegion) -{ - gfxUtils::ClipToRegion(aDT, aRegion.ToUnknownRegion()); - aDT->ClearRect(gfx::Rect(0, 0, aDT->GetSize().width, aDT->GetSize().height)); - aDT->PopClip(); -} - -static void -DrawResizer(CGContextRef aCtx) -{ - CGContextSetShouldAntialias(aCtx, false); - CGPoint points[6]; - points[0] = CGPointMake(13.0f, 4.0f); - points[1] = CGPointMake(3.0f, 14.0f); - points[2] = CGPointMake(13.0f, 8.0f); - points[3] = CGPointMake(7.0f, 14.0f); - points[4] = CGPointMake(13.0f, 12.0f); - points[5] = CGPointMake(11.0f, 14.0f); - CGContextSetRGBStrokeColor(aCtx, 0.00f, 0.00f, 0.00f, 0.15f); - CGContextStrokeLineSegments(aCtx, points, 6); - - points[0] = CGPointMake(13.0f, 5.0f); - points[1] = CGPointMake(4.0f, 14.0f); - points[2] = CGPointMake(13.0f, 9.0f); - points[3] = CGPointMake(8.0f, 14.0f); - points[4] = CGPointMake(13.0f, 13.0f); - points[5] = CGPointMake(12.0f, 14.0f); - CGContextSetRGBStrokeColor(aCtx, 0.13f, 0.13f, 0.13f, 0.54f); - CGContextStrokeLineSegments(aCtx, points, 6); - - points[0] = CGPointMake(13.0f, 6.0f); - points[1] = CGPointMake(5.0f, 14.0f); - points[2] = CGPointMake(13.0f, 10.0f); - points[3] = CGPointMake(9.0f, 14.0f); - points[5] = CGPointMake(13.0f, 13.9f); - points[4] = CGPointMake(13.0f, 14.0f); - CGContextSetRGBStrokeColor(aCtx, 0.84f, 0.84f, 0.84f, 0.55f); - CGContextStrokeLineSegments(aCtx, points, 6); -} - -void -nsChildView::MaybeDrawResizeIndicator(GLManager* aManager) -{ - MutexAutoLock lock(mEffectsLock); - if (!mShowsResizeIndicator) { - return; - } - - if (!mResizerImage) { - mResizerImage = MakeUnique(); - } - - LayoutDeviceIntSize size = mResizeIndicatorRect.Size(); - mResizerImage->UpdateIfNeeded(size, LayoutDeviceIntRegion(), ^(gfx::DrawTarget* drawTarget, const LayoutDeviceIntRegion& updateRegion) { - ClearRegion(drawTarget, updateRegion); - gfx::BorrowedCGContext borrow(drawTarget); - DrawResizer(borrow.cg); - borrow.Finish(); - }); - - mResizerImage->Draw(aManager, mResizeIndicatorRect.TopLeft()); -} - -// Draw the highlight line at the top of the titlebar. -// This function draws into the current NSGraphicsContext and assumes flippedness. -static void -DrawTitlebarHighlight(NSSize aWindowSize, CGFloat aRadius, CGFloat aDevicePixelWidth) -{ - [NSGraphicsContext saveGraphicsState]; - - // Set up the clip path. We start with the outer rectangle and cut out a - // slightly smaller inner rectangle with rounded corners. - // The outer corners of the resulting path will be square, but they will be - // masked away in a later step. - NSBezierPath* path = [NSBezierPath bezierPath]; - [path setWindingRule:NSEvenOddWindingRule]; - NSRect pathRect = NSMakeRect(0, 0, aWindowSize.width, aRadius + 2); - [path appendBezierPathWithRect:pathRect]; - pathRect = NSInsetRect(pathRect, aDevicePixelWidth, aDevicePixelWidth); - CGFloat innerRadius = aRadius - aDevicePixelWidth; - [path appendBezierPathWithRoundedRect:pathRect xRadius:innerRadius yRadius:innerRadius]; - [path addClip]; - - // Now we fill the path with a subtle highlight gradient. - // We don't use NSGradient because it's 5x to 15x slower than the manual fill, - // as indicated by the performance test in bug 880620. - for (CGFloat y = 0; y < aRadius; y += aDevicePixelWidth) { - CGFloat t = y / aRadius; - [[NSColor colorWithDeviceWhite:1.0 alpha:0.4 * (1.0 - t)] set]; - NSRectFillUsingOperation(NSMakeRect(0, y, aWindowSize.width, aDevicePixelWidth), NSCompositeSourceOver); - } - - [NSGraphicsContext restoreGraphicsState]; -} - -static CGContextRef -CreateCGContext(const LayoutDeviceIntSize& aSize) -{ - CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB(); - CGContextRef ctx = - CGBitmapContextCreate(NULL, - aSize.width, - aSize.height, - 8 /* bitsPerComponent */, - aSize.width * 4, - cs, - kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst); - CGColorSpaceRelease(cs); - - CGContextTranslateCTM(ctx, 0, aSize.height); - CGContextScaleCTM(ctx, 1, -1); - CGContextSetInterpolationQuality(ctx, kCGInterpolationLow); - - return ctx; -} - -LayoutDeviceIntSize -TextureSizeForSize(const LayoutDeviceIntSize& aSize) -{ - return LayoutDeviceIntSize(RoundUpPow2(aSize.width), - RoundUpPow2(aSize.height)); -} - -// When this method is entered, mEffectsLock is already being held. -void -nsChildView::UpdateTitlebarCGContext() -{ - if (mTitlebarRect.IsEmpty()) { - ReleaseTitlebarCGContext(); - return; - } - - NSRect titlebarRect = DevPixelsToCocoaPoints(mTitlebarRect); - NSRect dirtyRect = [mView convertRect:[(BaseWindow*)[mView window] getAndResetNativeDirtyRect] fromView:nil]; - NSRect dirtyTitlebarRect = NSIntersectionRect(titlebarRect, dirtyRect); - - LayoutDeviceIntSize texSize = TextureSizeForSize(mTitlebarRect.Size()); - if (!mTitlebarCGContext || - CGBitmapContextGetWidth(mTitlebarCGContext) != size_t(texSize.width) || - CGBitmapContextGetHeight(mTitlebarCGContext) != size_t(texSize.height)) { - dirtyTitlebarRect = titlebarRect; - - ReleaseTitlebarCGContext(); - - mTitlebarCGContext = CreateCGContext(texSize); - } - - if (NSIsEmptyRect(dirtyTitlebarRect)) { - return; - } - - CGContextRef ctx = mTitlebarCGContext; - - CGContextSaveGState(ctx); - - double scale = BackingScaleFactor(); - CGContextScaleCTM(ctx, scale, scale); - - CGContextClipToRect(ctx, NSRectToCGRect(dirtyTitlebarRect)); - CGContextClearRect(ctx, NSRectToCGRect(dirtyTitlebarRect)); - - NSGraphicsContext* oldContext = [NSGraphicsContext currentContext]; - - CGContextSaveGState(ctx); - - BaseWindow* window = (BaseWindow*)[mView window]; - NSView* frameView = [[window contentView] superview]; - if (![frameView isFlipped]) { - CGContextTranslateCTM(ctx, 0, [frameView bounds].size.height); - CGContextScaleCTM(ctx, 1, -1); - } - NSGraphicsContext* context = [NSGraphicsContext graphicsContextWithGraphicsPort:ctx flipped:[frameView isFlipped]]; - [NSGraphicsContext setCurrentContext:context]; - - // Draw the title string. - if ([window wantsTitleDrawn] && [frameView respondsToSelector:@selector(_drawTitleBar:)]) { - [frameView _drawTitleBar:[frameView bounds]]; - } - - // Draw the titlebar controls into the titlebar image. - for (id view in [window titlebarControls]) { - NSRect viewFrame = [view frame]; - NSRect viewRect = [mView convertRect:viewFrame fromView:frameView]; - if (!NSIntersectsRect(dirtyTitlebarRect, viewRect)) { - continue; - } - // All of the titlebar controls we're interested in are subclasses of - // NSButton. - if (![view isKindOfClass:[NSButton class]]) { - continue; - } - NSButton *button = (NSButton *) view; - id cellObject = [button cell]; - if (![cellObject isKindOfClass:[NSCell class]]) { - continue; - } - NSCell *cell = (NSCell *) cellObject; - - CGContextSaveGState(ctx); - CGContextTranslateCTM(ctx, viewFrame.origin.x, viewFrame.origin.y); - - if ([context isFlipped] != [view isFlipped]) { - CGContextTranslateCTM(ctx, 0, viewFrame.size.height); - CGContextScaleCTM(ctx, 1, -1); - } - - [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:ctx flipped:[view isFlipped]]]; - - if ([window useBrightTitlebarForeground] && !nsCocoaFeatures::OnYosemiteOrLater() && - view == [window standardWindowButton:NSWindowFullScreenButton]) { - // Make the fullscreen button visible on dark titlebar backgrounds by - // drawing it into a new transparency layer and turning it white. - CGRect r = NSRectToCGRect([view bounds]); - CGContextBeginTransparencyLayerWithRect(ctx, r, nullptr); - - // Draw twice for double opacity. - [cell drawWithFrame:[button bounds] inView:button]; - [cell drawWithFrame:[button bounds] inView:button]; - - // Make it white. - CGContextSetBlendMode(ctx, kCGBlendModeSourceIn); - CGContextSetRGBFillColor(ctx, 1, 1, 1, 1); - CGContextFillRect(ctx, r); - CGContextSetBlendMode(ctx, kCGBlendModeNormal); - - CGContextEndTransparencyLayer(ctx); - } else { - [cell drawWithFrame:[button bounds] inView:button]; - } - - [NSGraphicsContext setCurrentContext:context]; - CGContextRestoreGState(ctx); - } - - CGContextRestoreGState(ctx); - - DrawTitlebarHighlight([frameView bounds].size, [(ChildView*)mView cornerRadius], - DevPixelsToCocoaPoints(1)); - - [NSGraphicsContext setCurrentContext:oldContext]; - - CGContextRestoreGState(ctx); - - mUpdatedTitlebarRegion.OrWith(CocoaPointsToDevPixels(dirtyTitlebarRect)); -} - -// This method draws an overlay in the top of the window which contains the -// titlebar controls (e.g. close, min, zoom, fullscreen) and the titlebar -// highlight effect. -// This is necessary because the real titlebar controls are covered by our -// OpenGL context. Note that in terms of the NSView hierarchy, our ChildView -// is actually below the titlebar controls - that's why hovering and clicking -// them works as expected - but their visual representation is only drawn into -// the normal window buffer, and the window buffer surface lies below the -// GLContext surface. In order to make the titlebar controls visible, we have -// to redraw them inside the OpenGL context surface. -void -nsChildView::MaybeDrawTitlebar(GLManager* aManager) -{ - MutexAutoLock lock(mEffectsLock); - if (!mIsCoveringTitlebar || mIsFullscreen) { - return; - } - - LayoutDeviceIntRegion updatedTitlebarRegion; - updatedTitlebarRegion.And(mUpdatedTitlebarRegion, mTitlebarRect); - mUpdatedTitlebarRegion.SetEmpty(); - - if (!mTitlebarImage) { - mTitlebarImage = MakeUnique(); - } - - mTitlebarImage->UpdateFromCGContext(mTitlebarRect.Size(), - updatedTitlebarRegion, - mTitlebarCGContext); - - mTitlebarImage->Draw(aManager, mTitlebarRect.TopLeft()); -} - -static void -DrawTopLeftCornerMask(CGContextRef aCtx, int aRadius) -{ - CGContextSetRGBFillColor(aCtx, 1.0, 1.0, 1.0, 1.0); - CGContextFillEllipseInRect(aCtx, CGRectMake(0, 0, aRadius * 2, aRadius * 2)); -} - -void -nsChildView::MaybeDrawRoundedCorners(GLManager* aManager, - const LayoutDeviceIntRect& aRect) -{ - MutexAutoLock lock(mEffectsLock); - - if (!mCornerMaskImage) { - mCornerMaskImage = MakeUnique(); - } - - LayoutDeviceIntSize size(mDevPixelCornerRadius, mDevPixelCornerRadius); - mCornerMaskImage->UpdateIfNeeded(size, LayoutDeviceIntRegion(), ^(gfx::DrawTarget* drawTarget, const LayoutDeviceIntRegion& updateRegion) { - ClearRegion(drawTarget, updateRegion); - RefPtr builder = drawTarget->CreatePathBuilder(); - builder->Arc(gfx::Point(mDevPixelCornerRadius, mDevPixelCornerRadius), mDevPixelCornerRadius, 0, 2.0f * M_PI); - RefPtr path = builder->Finish(); - drawTarget->Fill(path, - gfx::ColorPattern(gfx::Color(1.0, 1.0, 1.0, 1.0)), - gfx::DrawOptions(1.0f, gfx::CompositionOp::OP_SOURCE)); - }); - - // Use operator destination in: multiply all 4 channels with source alpha. - aManager->gl()->fBlendFuncSeparate(LOCAL_GL_ZERO, LOCAL_GL_SRC_ALPHA, - LOCAL_GL_ZERO, LOCAL_GL_SRC_ALPHA); - - Matrix4x4 flipX = Matrix4x4::Scaling(-1, 1, 1); - Matrix4x4 flipY = Matrix4x4::Scaling(1, -1, 1); - - if (mIsCoveringTitlebar && !mIsFullscreen) { - // Mask the top corners. - mCornerMaskImage->Draw(aManager, aRect.TopLeft()); - mCornerMaskImage->Draw(aManager, aRect.TopRight(), flipX); - } - - if (mHasRoundedBottomCorners && !mIsFullscreen) { - // Mask the bottom corners. - mCornerMaskImage->Draw(aManager, aRect.BottomLeft(), flipY); - mCornerMaskImage->Draw(aManager, aRect.BottomRight(), flipY * flipX); - } - - // Reset blend mode. - aManager->gl()->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA, - LOCAL_GL_ONE, LOCAL_GL_ONE); -} - -static int32_t -FindTitlebarBottom(const nsTArray& aThemeGeometries, - int32_t aWindowWidth) -{ - int32_t titlebarBottom = 0; - for (uint32_t i = 0; i < aThemeGeometries.Length(); ++i) { - const nsIWidget::ThemeGeometry& g = aThemeGeometries[i]; - if ((g.mType == nsNativeThemeCocoa::eThemeGeometryTypeTitlebar) && - g.mRect.X() <= 0 && - g.mRect.XMost() >= aWindowWidth && - g.mRect.Y() <= 0) { - titlebarBottom = std::max(titlebarBottom, g.mRect.YMost()); - } - } - return titlebarBottom; -} - -static int32_t -FindUnifiedToolbarBottom(const nsTArray& aThemeGeometries, - int32_t aWindowWidth, int32_t aTitlebarBottom) -{ - int32_t unifiedToolbarBottom = aTitlebarBottom; - for (uint32_t i = 0; i < aThemeGeometries.Length(); ++i) { - const nsIWidget::ThemeGeometry& g = aThemeGeometries[i]; - if ((g.mType == nsNativeThemeCocoa::eThemeGeometryTypeToolbar) && - g.mRect.X() <= 0 && - g.mRect.XMost() >= aWindowWidth && - g.mRect.Y() <= aTitlebarBottom) { - unifiedToolbarBottom = std::max(unifiedToolbarBottom, g.mRect.YMost()); - } - } - return unifiedToolbarBottom; -} - -static LayoutDeviceIntRect -FindFirstRectOfType(const nsTArray& aThemeGeometries, - nsITheme::ThemeGeometryType aThemeGeometryType) -{ - for (uint32_t i = 0; i < aThemeGeometries.Length(); ++i) { - const nsIWidget::ThemeGeometry& g = aThemeGeometries[i]; - if (g.mType == aThemeGeometryType) { - return g.mRect; - } - } - return LayoutDeviceIntRect(); -} - -void -nsChildView::UpdateThemeGeometries(const nsTArray& aThemeGeometries) -{ - if (![mView window]) - return; - - UpdateVibrancy(aThemeGeometries); - - if (![[mView window] isKindOfClass:[ToolbarWindow class]]) - return; - - // Update unified toolbar height and sheet attachment position. - int32_t windowWidth = mBounds.width; - int32_t titlebarBottom = FindTitlebarBottom(aThemeGeometries, windowWidth); - int32_t unifiedToolbarBottom = - FindUnifiedToolbarBottom(aThemeGeometries, windowWidth, titlebarBottom); - int32_t toolboxBottom = - FindFirstRectOfType(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeToolbox).YMost(); - - ToolbarWindow* win = (ToolbarWindow*)[mView window]; - bool drawsContentsIntoWindowFrame = [win drawsContentsIntoWindowFrame]; - int32_t titlebarHeight = CocoaPointsToDevPixels([win titlebarHeight]); - int32_t contentOffset = drawsContentsIntoWindowFrame ? titlebarHeight : 0; - int32_t devUnifiedHeight = titlebarHeight + unifiedToolbarBottom - contentOffset; - [win setUnifiedToolbarHeight:DevPixelsToCocoaPoints(devUnifiedHeight)]; - int32_t devSheetPosition = titlebarHeight + std::max(toolboxBottom, unifiedToolbarBottom) - contentOffset; - [win setSheetAttachmentPosition:DevPixelsToCocoaPoints(devSheetPosition)]; - - // Update titlebar control offsets. - LayoutDeviceIntRect windowButtonRect = FindFirstRectOfType(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeWindowButtons); - [win placeWindowButtons:[mView convertRect:DevPixelsToCocoaPoints(windowButtonRect) toView:nil]]; - LayoutDeviceIntRect fullScreenButtonRect = FindFirstRectOfType(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeFullscreenButton); - [win placeFullScreenButton:[mView convertRect:DevPixelsToCocoaPoints(fullScreenButtonRect) toView:nil]]; -} - -static LayoutDeviceIntRegion -GatherThemeGeometryRegion(const nsTArray& aThemeGeometries, - nsITheme::ThemeGeometryType aThemeGeometryType) -{ - LayoutDeviceIntRegion region; - for (size_t i = 0; i < aThemeGeometries.Length(); ++i) { - const nsIWidget::ThemeGeometry& g = aThemeGeometries[i]; - if (g.mType == aThemeGeometryType) { - region.OrWith(g.mRect); - } - } - return region; -} - -template -static void MakeRegionsNonOverlappingImpl(Region& aOutUnion) { } - -template -static void MakeRegionsNonOverlappingImpl(Region& aOutUnion, Region& aFirst, Regions& ... aRest) -{ - MakeRegionsNonOverlappingImpl(aOutUnion, aRest...); - aFirst.SubOut(aOutUnion); - aOutUnion.OrWith(aFirst); -} - -// Subtracts parts from regions in such a way that they don't have any overlap. -// Each region in the argument list will have the union of all the regions -// *following* it subtracted from itself. In other words, the arguments are -// sorted low priority to high priority. -template -static void MakeRegionsNonOverlapping(Region& aFirst, Regions& ... aRest) -{ - Region unionOfAll; - MakeRegionsNonOverlappingImpl(unionOfAll, aFirst, aRest...); -} - -void -nsChildView::UpdateVibrancy(const nsTArray& aThemeGeometries) -{ - if (!VibrancyManager::SystemSupportsVibrancy()) { - return; - } - - LayoutDeviceIntRegion sheetRegion = - GatherThemeGeometryRegion(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeSheet); - LayoutDeviceIntRegion vibrantLightRegion = - GatherThemeGeometryRegion(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeVibrancyLight); - LayoutDeviceIntRegion vibrantDarkRegion = - GatherThemeGeometryRegion(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeVibrancyDark); - LayoutDeviceIntRegion menuRegion = - GatherThemeGeometryRegion(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeMenu); - LayoutDeviceIntRegion tooltipRegion = - GatherThemeGeometryRegion(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeTooltip); - LayoutDeviceIntRegion highlightedMenuItemRegion = - GatherThemeGeometryRegion(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeHighlightedMenuItem); - LayoutDeviceIntRegion sourceListRegion = - GatherThemeGeometryRegion(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeSourceList); - LayoutDeviceIntRegion sourceListSelectionRegion = - GatherThemeGeometryRegion(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeSourceListSelection); - LayoutDeviceIntRegion activeSourceListSelectionRegion = - GatherThemeGeometryRegion(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeActiveSourceListSelection); - - MakeRegionsNonOverlapping(sheetRegion, vibrantLightRegion, vibrantDarkRegion, - menuRegion, tooltipRegion, highlightedMenuItemRegion, - sourceListRegion, sourceListSelectionRegion, - activeSourceListSelectionRegion); - - auto& vm = EnsureVibrancyManager(); - vm.UpdateVibrantRegion(VibrancyType::LIGHT, vibrantLightRegion); - vm.UpdateVibrantRegion(VibrancyType::TOOLTIP, tooltipRegion); - vm.UpdateVibrantRegion(VibrancyType::MENU, menuRegion); - vm.UpdateVibrantRegion(VibrancyType::HIGHLIGHTED_MENUITEM, highlightedMenuItemRegion); - vm.UpdateVibrantRegion(VibrancyType::SHEET, sheetRegion); - vm.UpdateVibrantRegion(VibrancyType::SOURCE_LIST, sourceListRegion); - vm.UpdateVibrantRegion(VibrancyType::SOURCE_LIST_SELECTION, sourceListSelectionRegion); - vm.UpdateVibrantRegion(VibrancyType::ACTIVE_SOURCE_LIST_SELECTION, activeSourceListSelectionRegion); - vm.UpdateVibrantRegion(VibrancyType::DARK, vibrantDarkRegion); -} - -static VibrancyType -ThemeGeometryTypeToVibrancyType(nsITheme::ThemeGeometryType aThemeGeometryType) -{ - switch (aThemeGeometryType) { - case nsNativeThemeCocoa::eThemeGeometryTypeVibrancyLight: - return VibrancyType::LIGHT; - case nsNativeThemeCocoa::eThemeGeometryTypeVibrancyDark: - return VibrancyType::DARK; - case nsNativeThemeCocoa::eThemeGeometryTypeTooltip: - return VibrancyType::TOOLTIP; - case nsNativeThemeCocoa::eThemeGeometryTypeMenu: - return VibrancyType::MENU; - case nsNativeThemeCocoa::eThemeGeometryTypeHighlightedMenuItem: - return VibrancyType::HIGHLIGHTED_MENUITEM; - case nsNativeThemeCocoa::eThemeGeometryTypeSheet: - return VibrancyType::SHEET; - case nsNativeThemeCocoa::eThemeGeometryTypeSourceList: - return VibrancyType::SOURCE_LIST; - case nsNativeThemeCocoa::eThemeGeometryTypeSourceListSelection: - return VibrancyType::SOURCE_LIST_SELECTION; - case nsNativeThemeCocoa::eThemeGeometryTypeActiveSourceListSelection: - return VibrancyType::ACTIVE_SOURCE_LIST_SELECTION; - default: - MOZ_CRASH(); - } -} - -NSColor* -nsChildView::VibrancyFillColorForThemeGeometryType(nsITheme::ThemeGeometryType aThemeGeometryType) -{ - if (VibrancyManager::SystemSupportsVibrancy()) { - return EnsureVibrancyManager().VibrancyFillColorForType( - ThemeGeometryTypeToVibrancyType(aThemeGeometryType)); - } - return [NSColor whiteColor]; -} - -NSColor* -nsChildView::VibrancyFontSmoothingBackgroundColorForThemeGeometryType(nsITheme::ThemeGeometryType aThemeGeometryType) -{ - if (VibrancyManager::SystemSupportsVibrancy()) { - return EnsureVibrancyManager().VibrancyFontSmoothingBackgroundColorForType( - ThemeGeometryTypeToVibrancyType(aThemeGeometryType)); - } - return [NSColor clearColor]; -} - -mozilla::VibrancyManager& -nsChildView::EnsureVibrancyManager() -{ - MOZ_ASSERT(mView, "Only call this once we have a view!"); - if (!mVibrancyManager) { - mVibrancyManager = MakeUnique(*this, [mView vibrancyViewsContainer]); - } - return *mVibrancyManager; -} - -nsChildView::SwipeInfo -nsChildView::SendMayStartSwipe(const mozilla::PanGestureInput& aSwipeStartEvent) -{ - nsCOMPtr kungFuDeathGrip(this); - - uint32_t direction = (aSwipeStartEvent.mPanDisplacement.x > 0.0) - ? (uint32_t)nsIDOMSimpleGestureEvent::DIRECTION_RIGHT - : (uint32_t)nsIDOMSimpleGestureEvent::DIRECTION_LEFT; - - // We're ready to start the animation. Tell Gecko about it, and at the same - // time ask it if it really wants to start an animation for this event. - // This event also reports back the directions that we can swipe in. - LayoutDeviceIntPoint position = - RoundedToInt(aSwipeStartEvent.mPanStartPoint * ScreenToLayoutDeviceScale(1)); - WidgetSimpleGestureEvent geckoEvent = - SwipeTracker::CreateSwipeGestureEvent(eSwipeGestureMayStart, this, - position); - geckoEvent.mDirection = direction; - geckoEvent.mDelta = 0.0; - geckoEvent.mAllowedDirections = 0; - bool shouldStartSwipe = DispatchWindowEvent(geckoEvent); // event cancelled == swipe should start - - SwipeInfo result = { shouldStartSwipe, geckoEvent.mAllowedDirections }; - return result; -} - -void -nsChildView::TrackScrollEventAsSwipe(const mozilla::PanGestureInput& aSwipeStartEvent, - uint32_t aAllowedDirections) -{ - // If a swipe is currently being tracked kill it -- it's been interrupted - // by another gesture event. - if (mSwipeTracker) { - mSwipeTracker->CancelSwipe(); - mSwipeTracker->Destroy(); - mSwipeTracker = nullptr; - } - - uint32_t direction = (aSwipeStartEvent.mPanDisplacement.x > 0.0) - ? (uint32_t)nsIDOMSimpleGestureEvent::DIRECTION_RIGHT - : (uint32_t)nsIDOMSimpleGestureEvent::DIRECTION_LEFT; - - mSwipeTracker = new SwipeTracker(*this, aSwipeStartEvent, - aAllowedDirections, direction); - - if (!mAPZC) { - mCurrentPanGestureBelongsToSwipe = true; - } -} - -void -nsChildView::SwipeFinished() -{ - mSwipeTracker = nullptr; -} - -already_AddRefed -nsChildView::StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion, - BufferMode* aBufferMode) -{ - // should have created the GLPresenter in InitCompositor. - MOZ_ASSERT(mGLPresenter); - if (!mGLPresenter) { - mGLPresenter = GLPresenter::CreateForWindow(this); - - if (!mGLPresenter) { - return nullptr; - } - } - - LayoutDeviceIntRegion dirtyRegion(aInvalidRegion); - LayoutDeviceIntSize renderSize = mBounds.Size(); - - if (!mBasicCompositorImage) { - mBasicCompositorImage = MakeUnique(); - } - - RefPtr drawTarget = - mBasicCompositorImage->BeginUpdate(renderSize, dirtyRegion); - - if (!drawTarget) { - // Composite unchanged textures. - DoRemoteComposition(mBounds); - return nullptr; - } - - aInvalidRegion = mBasicCompositorImage->GetUpdateRegion(); - *aBufferMode = BufferMode::BUFFER_NONE; - - return drawTarget.forget(); -} - -void -nsChildView::EndRemoteDrawing() -{ - mBasicCompositorImage->EndUpdate(); - DoRemoteComposition(mBounds); -} - -void -nsChildView::CleanupRemoteDrawing() -{ - mBasicCompositorImage = nullptr; - mCornerMaskImage = nullptr; - mResizerImage = nullptr; - mTitlebarImage = nullptr; - mGLPresenter = nullptr; -} - -bool -nsChildView::InitCompositor(Compositor* aCompositor) -{ - if (aCompositor->GetBackendType() == LayersBackend::LAYERS_BASIC) { - if (!mGLPresenter) { - mGLPresenter = GLPresenter::CreateForWindow(this); - } - - return !!mGLPresenter; - } - return true; -} - -void -nsChildView::DoRemoteComposition(const LayoutDeviceIntRect& aRenderRect) -{ - if (![(ChildView*)mView preRender:mGLPresenter->GetNSOpenGLContext()]) { - return; - } - mGLPresenter->BeginFrame(aRenderRect.Size()); - - // Draw the result from the basic compositor. - mBasicCompositorImage->Draw(mGLPresenter.get(), LayoutDeviceIntPoint(0, 0)); - - // DrawWindowOverlay doesn't do anything for non-GL, so it didn't paint - // anything during the basic compositor transaction. Draw the overlay now. - DrawWindowOverlay(mGLPresenter.get(), aRenderRect); - - mGLPresenter->EndFrame(); - - [(ChildView*)mView postRender:mGLPresenter->GetNSOpenGLContext()]; -} - -@interface NonDraggableView : NSView -@end - -@implementation NonDraggableView -- (BOOL)mouseDownCanMoveWindow { return NO; } -- (NSView*)hitTest:(NSPoint)aPoint { return nil; } -@end - -void -nsChildView::UpdateWindowDraggingRegion(const LayoutDeviceIntRegion& aRegion) -{ - // mView returns YES from mouseDownCanMoveWindow, so we need to put NSViews - // that return NO from mouseDownCanMoveWindow in the places that shouldn't - // be draggable. We can't do it the other way round because returning - // YES from mouseDownCanMoveWindow doesn't have any effect if there's a - // superview that returns NO. - LayoutDeviceIntRegion nonDraggable; - nonDraggable.Sub(LayoutDeviceIntRect(0, 0, mBounds.width, mBounds.height), aRegion); - - __block bool changed = false; - - // Suppress calls to setNeedsDisplay during NSView geometry changes. - ManipulateViewWithoutNeedingDisplay(mView, ^() { - changed = mNonDraggableRegion.UpdateRegion( - nonDraggable, *this, [mView nonDraggableViewsContainer], ^() { - return [[NonDraggableView alloc] initWithFrame:NSZeroRect]; - }); - }); - - if (changed) { - // Trigger an update to the window server. This will call - // mouseDownCanMoveWindow. - // Doing this manually is only necessary because we're suppressing - // setNeedsDisplay calls above. - [[mView window] setMovableByWindowBackground:NO]; - [[mView window] setMovableByWindowBackground:YES]; - } -} - -void -nsChildView::ReportSwipeStarted(uint64_t aInputBlockId, - bool aStartSwipe) -{ - if (mSwipeEventQueue && mSwipeEventQueue->inputBlockId == aInputBlockId) { - if (aStartSwipe) { - PanGestureInput& startEvent = mSwipeEventQueue->queuedEvents[0]; - TrackScrollEventAsSwipe(startEvent, mSwipeEventQueue->allowedDirections); - for (size_t i = 1; i < mSwipeEventQueue->queuedEvents.Length(); i++) { - mSwipeTracker->ProcessEvent(mSwipeEventQueue->queuedEvents[i]); - } - } - mSwipeEventQueue = nullptr; - } -} - -void -nsChildView::DispatchAPZWheelInputEvent(InputData& aEvent, bool aCanTriggerSwipe) -{ - if (mSwipeTracker && aEvent.mInputType == PANGESTURE_INPUT) { - // Give the swipe tracker a first pass at the event. If a new pan gesture - // has been started since the beginning of the swipe, the swipe tracker - // will know to ignore the event. - nsEventStatus status = mSwipeTracker->ProcessEvent(aEvent.AsPanGestureInput()); - if (status == nsEventStatus_eConsumeNoDefault) { - return; - } - } - - WidgetWheelEvent event(true, eWheel, this); - - if (mAPZC) { - uint64_t inputBlockId = 0; - ScrollableLayerGuid guid; - - nsEventStatus result = mAPZC->ReceiveInputEvent(aEvent, &guid, &inputBlockId); - if (result == nsEventStatus_eConsumeNoDefault) { - return; - } - - switch(aEvent.mInputType) { - case PANGESTURE_INPUT: { - PanGestureInput& panInput = aEvent.AsPanGestureInput(); - - event = panInput.ToWidgetWheelEvent(this); - if (aCanTriggerSwipe) { - SwipeInfo swipeInfo = SendMayStartSwipe(panInput); - event.mCanTriggerSwipe = swipeInfo.wantsSwipe; - if (swipeInfo.wantsSwipe) { - if (result == nsEventStatus_eIgnore) { - // APZ has determined and that scrolling horizontally in the - // requested direction is impossible, so it didn't do any - // scrolling for the event. - // We know now that MayStartSwipe wants a swipe, so we can start - // the swipe now. - TrackScrollEventAsSwipe(panInput, swipeInfo.allowedDirections); - } else { - // We don't know whether this event can start a swipe, so we need - // to queue up events and wait for a call to ReportSwipeStarted. - // APZ might already have started scrolling in response to the - // event if it knew that it's the right thing to do. In that case - // we'll still get a call to ReportSwipeStarted, and we will - // discard the queued events at that point. - mSwipeEventQueue = MakeUnique(swipeInfo.allowedDirections, - inputBlockId); - } - } - } - - if (mSwipeEventQueue && mSwipeEventQueue->inputBlockId == inputBlockId) { - mSwipeEventQueue->queuedEvents.AppendElement(panInput); - } - break; - } - case SCROLLWHEEL_INPUT: { - event = aEvent.AsScrollWheelInput().ToWidgetWheelEvent(this); - break; - }; - default: - MOZ_CRASH("unsupported event type"); - return; - } - if (event.mMessage == eWheel && - (event.mDeltaX != 0 || event.mDeltaY != 0)) { - ProcessUntransformedAPZEvent(&event, guid, inputBlockId, result); - } - return; - } - - nsEventStatus status; - switch(aEvent.mInputType) { - case PANGESTURE_INPUT: { - PanGestureInput panInput = aEvent.AsPanGestureInput(); - if (panInput.mType == PanGestureInput::PANGESTURE_MAYSTART || - panInput.mType == PanGestureInput::PANGESTURE_START) { - mCurrentPanGestureBelongsToSwipe = false; - } - if (mCurrentPanGestureBelongsToSwipe) { - // Ignore this event. It's a momentum event from a scroll gesture - // that was processed as a swipe, and the swipe animation has - // already finished (so mSwipeTracker is already null). - MOZ_ASSERT(panInput.IsMomentum(), - "If the fingers are still on the touchpad, we should still have a SwipeTracker, and it should have consumed this event."); - return; - } - - event = panInput.ToWidgetWheelEvent(this); - if (aCanTriggerSwipe) { - SwipeInfo swipeInfo = SendMayStartSwipe(panInput); - - // We're in the non-APZ case here, but we still want to know whether - // the event was routed to a child process, so we use InputAPZContext - // to get that piece of information. - ScrollableLayerGuid guid; - InputAPZContext context(guid, 0, nsEventStatus_eIgnore); - - event.mCanTriggerSwipe = swipeInfo.wantsSwipe; - DispatchEvent(&event, status); - if (swipeInfo.wantsSwipe) { - if (context.WasRoutedToChildProcess()) { - // We don't know whether this event can start a swipe, so we need - // to queue up events and wait for a call to ReportSwipeStarted. - mSwipeEventQueue = MakeUnique(swipeInfo.allowedDirections, 0); - } else if (event.TriggersSwipe()) { - TrackScrollEventAsSwipe(panInput, swipeInfo.allowedDirections); - } - } - - if (mSwipeEventQueue && mSwipeEventQueue->inputBlockId == 0) { - mSwipeEventQueue->queuedEvents.AppendElement(panInput); - } - return; - } - break; - } - case SCROLLWHEEL_INPUT: { - event = aEvent.AsScrollWheelInput().ToWidgetWheelEvent(this); - break; - } - default: - MOZ_CRASH("unexpected event type"); - return; - } - if (event.mMessage == eWheel && - (event.mDeltaX != 0 || event.mDeltaY != 0)) { - DispatchEvent(&event, status); - } -} - -// When using 10.11, calling showDefinitionForAttributedString causes the -// following exception on LookupViewService. (rdar://26476091) -// -// Exception: decodeObjectForKey: class "TitlebarAndBackgroundColor" not -// loaded or does not exist -// -// So we set temporary color that is NSColor before calling it. - -class MOZ_RAII AutoBackgroundSetter final { -public: - explicit AutoBackgroundSetter(NSView* aView) { - if (nsCocoaFeatures::OnElCapitanOrLater() && - [[aView window] isKindOfClass:[ToolbarWindow class]]) { - mWindow = [(ToolbarWindow*)[aView window] retain]; - [mWindow setTemporaryBackgroundColor]; - } else { - mWindow = nullptr; - } - } - - ~AutoBackgroundSetter() { - if (mWindow) { - [mWindow restoreBackgroundColor]; - [mWindow release]; - } - } - -private: - ToolbarWindow* mWindow; // strong -}; - -void -nsChildView::LookUpDictionary( - const nsAString& aText, - const nsTArray& aFontRangeArray, - const bool aIsVertical, - const LayoutDeviceIntPoint& aPoint) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - NSMutableAttributedString* attrStr = - nsCocoaUtils::GetNSMutableAttributedString(aText, aFontRangeArray, - aIsVertical, - BackingScaleFactor()); - NSPoint pt = - nsCocoaUtils::DevPixelsToCocoaPoints(aPoint, BackingScaleFactor()); - NSDictionary* attributes = [attrStr attributesAtIndex:0 effectiveRange:nil]; - NSFont* font = [attributes objectForKey:NSFontAttributeName]; - if (font) { - if (aIsVertical) { - pt.x -= [font descender]; - } else { - pt.y += [font ascender]; - } - } - - AutoBackgroundSetter setter(mView); - [mView showDefinitionForAttributedString:attrStr atPoint:pt]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -#ifdef ACCESSIBILITY -already_AddRefed -nsChildView::GetDocumentAccessible() -{ - if (!mozilla::a11y::ShouldA11yBeEnabled()) - return nullptr; - - if (mAccessible) { - RefPtr ret; - CallQueryReferent(mAccessible.get(), - static_cast(getter_AddRefs(ret))); - return ret.forget(); - } - - // need to fetch the accessible anew, because it has gone away. - // cache the accessible in our weak ptr - RefPtr acc = GetRootAccessible(); - mAccessible = do_GetWeakReference(acc.get()); - - return acc.forget(); -} -#endif - -// GLPresenter implementation - -GLPresenter::GLPresenter(GLContext* aContext) - : mGLContext(aContext) -{ - mGLContext->MakeCurrent(); - ShaderConfigOGL config; - config.SetTextureTarget(LOCAL_GL_TEXTURE_RECTANGLE_ARB); - mRGBARectProgram = MakeUnique(mGLContext, - ProgramProfileOGL::GetProfileFor(config)); - - // Create mQuadVBO. - mGLContext->fGenBuffers(1, &mQuadVBO); - mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mQuadVBO); - - // 1 quad, with the number of the quad (vertexID) encoded in w. - GLfloat vertices[] = { - 0.0f, 0.0f, 0.0f, 0.0f, - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 1.0f, 1.0f, 0.0f, 0.0f, - }; - HeapCopyOfStackArray verticesOnHeap(vertices); - mGLContext->fBufferData(LOCAL_GL_ARRAY_BUFFER, - verticesOnHeap.ByteLength(), - verticesOnHeap.Data(), - LOCAL_GL_STATIC_DRAW); - mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0); -} - -GLPresenter::~GLPresenter() -{ - if (mQuadVBO) { - mGLContext->MakeCurrent(); - mGLContext->fDeleteBuffers(1, &mQuadVBO); - mQuadVBO = 0; - } -} - -void -GLPresenter::BindAndDrawQuad(ShaderProgramOGL *aProgram, - const gfx::Rect& aLayerRect, - const gfx::Rect& aTextureRect) -{ - mGLContext->MakeCurrent(); - - gfx::Rect layerRects[4]; - gfx::Rect textureRects[4]; - - layerRects[0] = aLayerRect; - textureRects[0] = aTextureRect; - - aProgram->SetLayerRects(layerRects); - aProgram->SetTextureRects(textureRects); - - const GLuint coordAttribIndex = 0; - - mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mQuadVBO); - mGLContext->fVertexAttribPointer(coordAttribIndex, 4, - LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, - (GLvoid*)0); - mGLContext->fEnableVertexAttribArray(coordAttribIndex); - mGLContext->fDrawArrays(LOCAL_GL_TRIANGLES, 0, 6); - mGLContext->fDisableVertexAttribArray(coordAttribIndex); -} - -void -GLPresenter::BeginFrame(LayoutDeviceIntSize aRenderSize) -{ - mGLContext->MakeCurrent(); - - mGLContext->fViewport(0, 0, aRenderSize.width, aRenderSize.height); - - // Matrix to transform (0, 0, width, height) to viewport space (-1.0, 1.0, - // 2, 2) and flip the contents. - gfx::Matrix viewMatrix = gfx::Matrix::Translation(-1.0, 1.0); - viewMatrix.PreScale(2.0f / float(aRenderSize.width), - 2.0f / float(aRenderSize.height)); - viewMatrix.PreScale(1.0f, -1.0f); - - gfx::Matrix4x4 matrix3d = gfx::Matrix4x4::From2D(viewMatrix); - matrix3d._33 = 0.0f; - - // set the projection matrix for the next time the program is activated - mProjMatrix = matrix3d; - - // Default blend function implements "OVER" - mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA, - LOCAL_GL_ONE, LOCAL_GL_ONE); - mGLContext->fEnable(LOCAL_GL_BLEND); - - mGLContext->fClearColor(0.0, 0.0, 0.0, 0.0); - mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT); - - mGLContext->fEnable(LOCAL_GL_TEXTURE_RECTANGLE_ARB); -} - -void -GLPresenter::EndFrame() -{ - mGLContext->SwapBuffers(); - mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0); -} - -class WidgetsReleaserRunnable final : public mozilla::Runnable -{ -public: - explicit WidgetsReleaserRunnable(nsTArray>&& aWidgetArray) - : mWidgetArray(aWidgetArray) - { - } - - // Do nothing; all this runnable does is hold a reference the widgets in - // mWidgetArray, and those references will be dropped when this runnable - // is destroyed. - -private: - nsTArray> mWidgetArray; -}; - -#pragma mark - - -// ViewRegionContainerView is a view class for certain subviews of ChildView -// which contain the NSViews created for ViewRegions (see ViewRegion.h). -// It doesn't do anything interesting, it only acts as a container so that it's -// easier for ChildView to control the z order of its children. -@interface ViewRegionContainerView : NSView { -} -@end - -@implementation ViewRegionContainerView - -- (NSView*)hitTest:(NSPoint)aPoint { - return nil; // Be transparent to mouse events. -} - -- (BOOL)isFlipped { - return [[self superview] isFlipped]; -} - -- (BOOL)mouseDownCanMoveWindow { - return [[self superview] mouseDownCanMoveWindow]; -} - -@end -; - -@implementation ChildView - -// globalDragPboard is non-null during native drag sessions that did not originate -// in our native NSView (it is set in |draggingEntered:|). It is unset when the -// drag session ends for this view, either with the mouse exiting or when a drop -// occurs in this view. -NSPasteboard* globalDragPboard = nil; - -// gLastDragView and gLastDragMouseDownEvent are used to communicate information -// to the drag service during drag invocation (starting a drag in from the view). -// gLastDragView is only non-null while mouseDragged is on the call stack. -NSView* gLastDragView = nil; -NSEvent* gLastDragMouseDownEvent = nil; - -+ (void)initialize -{ - static BOOL initialized = NO; - - if (!initialized) { - // Inform the OS about the types of services (from the "Services" menu) - // that we can handle. - - NSArray *sendTypes = [[NSArray alloc] initWithObjects:NSStringPboardType,NSHTMLPboardType,nil]; - NSArray *returnTypes = [[NSArray alloc] initWithObjects:NSStringPboardType,NSHTMLPboardType,nil]; - - [NSApp registerServicesMenuSendTypes:sendTypes returnTypes:returnTypes]; - - [sendTypes release]; - [returnTypes release]; - - initialized = YES; - } -} - -+ (void)registerViewForDraggedTypes:(NSView*)aView -{ - [aView registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, - NSStringPboardType, - NSHTMLPboardType, - NSURLPboardType, - NSFilesPromisePboardType, - kWildcardPboardType, - kCorePboardType_url, - kCorePboardType_urld, - kCorePboardType_urln, - nil]]; -} - -// initWithFrame:geckoChild: -- (id)initWithFrame:(NSRect)inFrame geckoChild:(nsChildView*)inChild -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - if ((self = [super initWithFrame:inFrame])) { - mGeckoChild = inChild; - mBlockedLastMouseDown = NO; - mExpectingWheelStop = NO; - - mLastMouseDownEvent = nil; - mLastKeyDownEvent = nil; - mClickThroughMouseDownEvent = nil; - mDragService = nullptr; - - mGestureState = eGestureState_None; - mCumulativeMagnification = 0.0; - mCumulativeRotation = 0.0; - - mNeedsGLUpdate = NO; - - [self setFocusRingType:NSFocusRingTypeNone]; - -#ifdef __LP64__ - mCancelSwipeAnimation = nil; -#endif - - mNonDraggableViewsContainer = [[ViewRegionContainerView alloc] initWithFrame:[self bounds]]; - mVibrancyViewsContainer = [[ViewRegionContainerView alloc] initWithFrame:[self bounds]]; - - [mNonDraggableViewsContainer setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; - [mVibrancyViewsContainer setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; - - [self addSubview:mNonDraggableViewsContainer]; - [self addSubview:mVibrancyViewsContainer]; - - mPixelHostingView = [[PixelHostingView alloc] initWithFrame:[self bounds]]; - [mPixelHostingView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; - - [self addSubview:mPixelHostingView]; - - mTopLeftCornerMask = NULL; - } - - // register for things we'll take from other applications - [ChildView registerViewForDraggedTypes:self]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(systemMetricsChanged) - name:NSControlTintDidChangeNotification - object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(systemMetricsChanged) - name:NSSystemColorsDidChangeNotification - object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(scrollbarSystemMetricChanged) - name:NSPreferredScrollerStyleDidChangeNotification - object:nil]; - [[NSDistributedNotificationCenter defaultCenter] addObserver:self - selector:@selector(systemMetricsChanged) - name:@"AppleAquaScrollBarVariantChanged" - object:nil - suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(_surfaceNeedsUpdate:) - name:NSViewGlobalFrameDidChangeNotification - object:mPixelHostingView]; - - return self; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -// ComplexTextInputPanel's interpretKeyEvent hack won't work without this. -// It makes calls to +[NSTextInputContext currentContext], deep in system -// code, return the appropriate context. -- (NSTextInputContext *)inputContext -{ - NSTextInputContext* pluginContext = NULL; - if (mGeckoChild && mGeckoChild->IsPluginFocused()) { - ComplexTextInputPanel* ctiPanel = - ComplexTextInputPanel::GetSharedComplexTextInputPanel(); - if (ctiPanel) { - pluginContext = (NSTextInputContext*) ctiPanel->GetInputContext(); - } - } - if (pluginContext) { - return pluginContext; - } else { - if (!mGeckoChild) { - // -[ChildView widgetDestroyed] has been called, but - // -[ChildView delayedTearDown] has not yet completed. Accessing - // [super inputContext] now would uselessly recreate a text input context - // for us, under which -[ChildView validAttributesForMarkedText] would - // be called and the assertion checking for mTextInputHandler would fail. - // We return nil to avoid that. - return nil; - } - return [super inputContext]; - } -} - -- (void)installTextInputHandler:(TextInputHandler*)aHandler -{ - mTextInputHandler = aHandler; -} - -- (void)uninstallTextInputHandler -{ - mTextInputHandler = nullptr; -} - -- (bool)preRender:(NSOpenGLContext *)aGLContext -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - if (![self window] || - ([[self window] isKindOfClass:[BaseWindow class]] && - ![(BaseWindow*)[self window] isVisibleOrBeingShown])) { - // Before the window is shown, our GL context's front FBO is not - // framebuffer complete, so we refuse to render. - return false; - } - - if (!mGLContext) { - mGLContext = aGLContext; - [mGLContext retain]; - mNeedsGLUpdate = true; - } - - CGLLockContext((CGLContextObj)[aGLContext CGLContextObj]); - - if (mNeedsGLUpdate) { - [self updateGLContext]; - mNeedsGLUpdate = NO; - } - - return true; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false); -} - -- (void)postRender:(NSOpenGLContext *)aGLContext -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - CGLUnlockContext((CGLContextObj)[aGLContext CGLContextObj]); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (NSView*)vibrancyViewsContainer { - return mVibrancyViewsContainer; -} - -- (NSView*)nonDraggableViewsContainer { - return mNonDraggableViewsContainer; -} - -- (NSView*)pixelHostingView { - return mPixelHostingView; -} - -- (void)dealloc -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mGLContext release]; - [mLastMouseDownEvent release]; - [mLastKeyDownEvent release]; - [mClickThroughMouseDownEvent release]; - CGImageRelease(mTopLeftCornerMask); - ChildViewMouseTracker::OnDestroyView(self); - - [[NSNotificationCenter defaultCenter] removeObserver:self]; - [[NSDistributedNotificationCenter defaultCenter] removeObserver:self]; - [mVibrancyViewsContainer removeFromSuperview]; - [mVibrancyViewsContainer release]; - [mNonDraggableViewsContainer removeFromSuperview]; - [mNonDraggableViewsContainer release]; - [mPixelHostingView removeFromSuperview]; - [mPixelHostingView release]; - - [super dealloc]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)widgetDestroyed -{ - if (mTextInputHandler) { - mTextInputHandler->OnDestroyWidget(mGeckoChild); - mTextInputHandler = nullptr; - } - mGeckoChild = nullptr; - - // Just in case we're destroyed abruptly and missed the draggingExited - // or performDragOperation message. - NS_IF_RELEASE(mDragService); -} - -// mozView method, return our gecko child view widget. Note this does not AddRef. -- (nsIWidget*) widget -{ - return static_cast(mGeckoChild); -} - -- (void)systemMetricsChanged -{ - if (mGeckoChild) - mGeckoChild->NotifyThemeChanged(); -} - -- (void)scrollbarSystemMetricChanged -{ - [self systemMetricsChanged]; - - if (mGeckoChild) { - nsIWidgetListener* listener = mGeckoChild->GetWidgetListener(); - if (listener) { - nsIPresShell* presShell = listener->GetPresShell(); - if (presShell) { - presShell->ReconstructFrames(); - } - } - } -} - -- (NSString*)description -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - return [NSString stringWithFormat:@"ChildView %p, gecko child %p, frame %@", self, mGeckoChild, NSStringFromRect([self frame])]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -// Make the origin of this view the topLeft corner (gecko origin) rather -// than the bottomLeft corner (standard cocoa origin). -- (BOOL)isFlipped -{ - return YES; -} - -- (BOOL)isOpaque -{ - return [[self window] isOpaque]; -} - -- (void)sendFocusEvent:(EventMessage)eventMessage -{ - if (!mGeckoChild) - return; - - nsEventStatus status = nsEventStatus_eIgnore; - WidgetGUIEvent focusGuiEvent(true, eventMessage, mGeckoChild); - focusGuiEvent.mTime = PR_IntervalNow(); - mGeckoChild->DispatchEvent(&focusGuiEvent, status); -} - -// We accept key and mouse events, so don't keep passing them up the chain. Allow -// this to be a 'focused' widget for event dispatch. -- (BOOL)acceptsFirstResponder -{ - return YES; -} - -// Accept mouse down events on background windows -- (BOOL)acceptsFirstMouse:(NSEvent*)aEvent -{ - if (![[self window] isKindOfClass:[PopupWindow class]]) { - // We rely on this function to tell us that the mousedown was on a - // background window. Inside mouseDown we can't tell whether we were - // inactive because at that point we've already been made active. - // Unfortunately, acceptsFirstMouse is called for PopupWindows even when - // their parent window is active, so ignore this on them for now. - mClickThroughMouseDownEvent = [aEvent retain]; - } - return YES; -} - -- (BOOL)mouseDownCanMoveWindow -{ - // Return YES so that parts of this view can be draggable. The non-draggable - // parts will be covered by NSViews that return NO from - // mouseDownCanMoveWindow and thus override draggability from the inside. - // These views are assembled in nsChildView::UpdateWindowDraggingRegion. - return YES; -} - --(void)updateGLContext -{ - [mGLContext setView:mPixelHostingView]; - [mGLContext update]; -} - -- (void)_surfaceNeedsUpdate:(NSNotification*)notification -{ - if (mGLContext) { - CGLLockContext((CGLContextObj)[mGLContext CGLContextObj]); - mNeedsGLUpdate = YES; - CGLUnlockContext((CGLContextObj)[mGLContext CGLContextObj]); - } -} - -- (void)viewDidChangeBackingProperties -{ - [super viewDidChangeBackingProperties]; - if (mGeckoChild) { - // actually, it could be the color space that's changed, - // but we can't tell the difference here except by retrieving - // the backing scale factor and comparing to the old value - mGeckoChild->BackingScaleFactorChanged(); - } -} - -- (BOOL)isCoveringTitlebar -{ - return [[self window] isKindOfClass:[BaseWindow class]] && - [(BaseWindow*)[self window] mainChildView] == self && - [(BaseWindow*)[self window] drawsContentsIntoWindowFrame]; -} - -- (void)viewWillStartLiveResize -{ - nsCOMPtr observerService = mozilla::services::GetObserverService(); - - if (!observerService) { - return; - } - - observerService->NotifyObservers(nullptr, "live-resize-start", nullptr); -} - -- (void)viewDidEndLiveResize -{ - nsCOMPtr observerService = mozilla::services::GetObserverService(); - - if (!observerService) { - return; - } - - observerService->NotifyObservers(nullptr, "live-resize-end", nullptr); -} - -- (NSColor*)vibrancyFillColorForThemeGeometryType:(nsITheme::ThemeGeometryType)aThemeGeometryType -{ - if (!mGeckoChild) { - return [NSColor whiteColor]; - } - return mGeckoChild->VibrancyFillColorForThemeGeometryType(aThemeGeometryType); -} - -- (NSColor*)vibrancyFontSmoothingBackgroundColorForThemeGeometryType:(nsITheme::ThemeGeometryType)aThemeGeometryType -{ - if (!mGeckoChild) { - return [NSColor clearColor]; - } - return mGeckoChild->VibrancyFontSmoothingBackgroundColorForThemeGeometryType(aThemeGeometryType); -} - -- (LayoutDeviceIntRegion)nativeDirtyRegionWithBoundingRect:(NSRect)aRect -{ - LayoutDeviceIntRect boundingRect = mGeckoChild->CocoaPointsToDevPixels(aRect); - const NSRect *rects; - NSInteger count; - [mPixelHostingView getRectsBeingDrawn:&rects count:&count]; - - if (count > MAX_RECTS_IN_REGION) { - return boundingRect; - } - - LayoutDeviceIntRegion region; - for (NSInteger i = 0; i < count; ++i) { - region.Or(region, mGeckoChild->CocoaPointsToDevPixels(rects[i])); - } - region.And(region, boundingRect); - return region; -} - -// The display system has told us that a portion of our view is dirty. Tell -// gecko to paint it -// This method is called from mPixelHostingView's drawRect handler. -- (void)doDrawRect:(NSRect)aRect -{ - if (!NS_IsMainThread()) { - // In the presence of CoreAnimation, this method can sometimes be called on - // a non-main thread. Ignore those calls because Gecko can only react to - // them on the main thread. - return; - } - - if (!mGeckoChild || !mGeckoChild->IsVisible()) - return; - CGContextRef cgContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; - - if ([self isUsingOpenGL]) { - // Since this view is usually declared as opaque, the window's pixel - // buffer may now contain garbage which we need to prevent from reaching - // the screen. The only place where garbage can show is in the window - // corners and the vibrant regions of the window - the rest of the window - // is covered by opaque content in our OpenGL surface. - // So we need to clear the pixel buffer contents in these areas. - [self clearCorners]; - - // Force a sync OMTC composite into the OpenGL context and return. - LayoutDeviceIntRect geckoBounds = mGeckoChild->GetBounds(); - LayoutDeviceIntRegion region(geckoBounds); - - mGeckoChild->PaintWindow(region); - return; - } - - PROFILER_LABEL("ChildView", "drawRect", - js::ProfileEntry::Category::GRAPHICS); - - // The CGContext that drawRect supplies us with comes with a transform that - // scales one user space unit to one Cocoa point, which can consist of - // multiple dev pixels. But Gecko expects its supplied context to be scaled - // to device pixels, so we need to reverse the scaling. - double scale = mGeckoChild->BackingScaleFactor(); - CGContextSaveGState(cgContext); - CGContextScaleCTM(cgContext, 1.0 / scale, 1.0 / scale); - - NSSize viewSize = [self bounds].size; - gfx::IntSize backingSize = gfx::IntSize::Truncate(viewSize.width * scale, viewSize.height * scale); - LayoutDeviceIntRegion region = [self nativeDirtyRegionWithBoundingRect:aRect]; - - bool painted = mGeckoChild->PaintWindowInContext(cgContext, region, backingSize); - - // Undo the scale transform so that from now on the context is in - // CocoaPoints again. - CGContextRestoreGState(cgContext); - - if (!painted && [mPixelHostingView isOpaque]) { - // Gecko refused to draw, but we've claimed to be opaque, so we have to - // draw something--fill with white. - CGContextSetRGBFillColor(cgContext, 1, 1, 1, 1); - CGContextFillRect(cgContext, NSRectToCGRect(aRect)); - } - - if ([self isCoveringTitlebar]) { - [self drawTitleString]; - [self drawTitlebarHighlight]; - [self maskTopCornersInContext:cgContext]; - } -} - -- (BOOL)isUsingOpenGL -{ - if (!mGeckoChild || ![self window]) - return NO; - - return mGLContext || mUsingOMTCompositor; -} - - -- (BOOL)hasRoundedBottomCorners -{ - return [[self window] respondsToSelector:@selector(bottomCornerRounded)] && - [[self window] bottomCornerRounded]; -} - -- (CGFloat)cornerRadius -{ - NSView* frameView = [[[self window] contentView] superview]; - if (!frameView || ![frameView respondsToSelector:@selector(roundedCornerRadius)]) - return 4.0f; - return [frameView roundedCornerRadius]; -} - --(void)setGLOpaque:(BOOL)aOpaque -{ - CGLLockContext((CGLContextObj)[mGLContext CGLContextObj]); - // Make the context opaque for fullscreen (since it performs better), and transparent - // for windowed (since we need it for rounded corners). - GLint opaque = aOpaque ? 1 : 0; - [mGLContext setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity]; - CGLUnlockContext((CGLContextObj)[mGLContext CGLContextObj]); -} - -// Accelerated windows have two NSSurfaces: -// (1) The window's pixel buffer in the back and -// (2) the OpenGL view in the front. -// These two surfaces are composited by the window manager. Drawing into the -// CGContext which is provided by drawRect ends up in (1). -// When our window has rounded corners, the OpenGL view has transparent pixels -// in the corners. In these places the contents of the window's pixel buffer -// can show through. So we need to make sure that the pixel buffer is -// transparent in the corners so that no garbage reaches the screen. -// The contents of the pixel buffer in the rest of the window don't matter -// because they're covered by opaque pixels of the OpenGL context. -// Making the corners transparent works even though our window is -// declared "opaque" (in the NSWindow's isOpaque method). -- (void)clearCorners -{ - CGFloat radius = [self cornerRadius]; - CGFloat w = [self bounds].size.width, h = [self bounds].size.height; - [[NSColor clearColor] set]; - - if ([self isCoveringTitlebar]) { - NSRectFill(NSMakeRect(0, 0, radius, radius)); - NSRectFill(NSMakeRect(w - radius, 0, radius, radius)); - } - - if ([self hasRoundedBottomCorners]) { - NSRectFill(NSMakeRect(0, h - radius, radius, radius)); - NSRectFill(NSMakeRect(w - radius, h - radius, radius, radius)); - } -} - -// This is the analog of nsChildView::MaybeDrawRoundedCorners for CGContexts. -// We only need to mask the top corners here because Cocoa does the masking -// for the window's bottom corners automatically (starting with 10.7). -- (void)maskTopCornersInContext:(CGContextRef)aContext -{ - CGFloat radius = [self cornerRadius]; - int32_t devPixelCornerRadius = mGeckoChild->CocoaPointsToDevPixels(radius); - - // First make sure that mTopLeftCornerMask is set up. - if (!mTopLeftCornerMask || - int32_t(CGImageGetWidth(mTopLeftCornerMask)) != devPixelCornerRadius) { - CGImageRelease(mTopLeftCornerMask); - CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB(); - CGContextRef imgCtx = CGBitmapContextCreate(NULL, - devPixelCornerRadius, - devPixelCornerRadius, - 8, devPixelCornerRadius * 4, - rgb, kCGImageAlphaPremultipliedFirst); - CGColorSpaceRelease(rgb); - DrawTopLeftCornerMask(imgCtx, devPixelCornerRadius); - mTopLeftCornerMask = CGBitmapContextCreateImage(imgCtx); - CGContextRelease(imgCtx); - } - - // kCGBlendModeDestinationIn is the secret sauce which allows us to erase - // already painted pixels. It's defined as R = D * Sa: multiply all channels - // of the destination pixel with the alpha of the source pixel. In our case, - // the source is mTopLeftCornerMask. - CGContextSaveGState(aContext); - CGContextSetBlendMode(aContext, kCGBlendModeDestinationIn); - - CGRect destRect = CGRectMake(0, 0, radius, radius); - - // Erase the top left corner... - CGContextDrawImage(aContext, destRect, mTopLeftCornerMask); - - // ... and the top right corner. - CGContextTranslateCTM(aContext, [self bounds].size.width, 0); - CGContextScaleCTM(aContext, -1, 1); - CGContextDrawImage(aContext, destRect, mTopLeftCornerMask); - - CGContextRestoreGState(aContext); -} - -- (void)drawTitleString -{ - BaseWindow* window = (BaseWindow*)[self window]; - if (![window wantsTitleDrawn]) { - return; - } - - NSView* frameView = [[window contentView] superview]; - if (![frameView respondsToSelector:@selector(_drawTitleBar:)]) { - return; - } - - NSGraphicsContext* oldContext = [NSGraphicsContext currentContext]; - CGContextRef ctx = (CGContextRef)[oldContext graphicsPort]; - CGContextSaveGState(ctx); - if ([oldContext isFlipped] != [frameView isFlipped]) { - CGContextTranslateCTM(ctx, 0, [self bounds].size.height); - CGContextScaleCTM(ctx, 1, -1); - } - [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:ctx flipped:[frameView isFlipped]]]; - [frameView _drawTitleBar:[frameView bounds]]; - CGContextRestoreGState(ctx); - [NSGraphicsContext setCurrentContext:oldContext]; -} - -- (void)drawTitlebarHighlight -{ - DrawTitlebarHighlight([self bounds].size, [self cornerRadius], - mGeckoChild->DevPixelsToCocoaPoints(1)); -} - -- (void)viewWillDraw -{ - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - if (mGeckoChild) { - // The OS normally *will* draw our NSWindow, no matter what we do here. - // But Gecko can delete our parent widget(s) (along with mGeckoChild) - // while processing a paint request, which closes our NSWindow and - // makes the OS throw an NSInternalInconsistencyException assertion when - // it tries to draw it. Sometimes the OS also aborts the browser process. - // So we need to retain our parent(s) here and not release it/them until - // the next time through the main thread's run loop. When we do this we - // also need to retain and release mGeckoChild, which holds a strong - // reference to us. See bug 550392. - nsIWidget* parent = mGeckoChild->GetParent(); - if (parent) { - nsTArray> widgetArray; - while (parent) { - widgetArray.AppendElement(parent); - parent = parent->GetParent(); - } - widgetArray.AppendElement(mGeckoChild); - nsCOMPtr releaserRunnable = - new WidgetsReleaserRunnable(Move(widgetArray)); - NS_DispatchToMainThread(releaserRunnable); - } - - if ([self isUsingOpenGL]) { - if (ShadowLayerForwarder* slf = mGeckoChild->GetLayerManager()->AsShadowForwarder()) { - slf->WindowOverlayChanged(); - } - } - - mGeckoChild->WillPaintWindow(); - } - [super viewWillDraw]; -} - -#if USE_CLICK_HOLD_CONTEXTMENU -// -// -clickHoldCallback: -// -// called from a timer two seconds after a mouse down to see if we should display -// a context menu (click-hold). |anEvent| is the original mouseDown event. If we're -// still in that mouseDown by this time, put up the context menu, otherwise just -// fuhgeddaboutit. |anEvent| has been retained by the OS until after this callback -// fires so we're ok there. -// -// This code currently messes in a bunch of edge cases (bugs 234751, 232964, 232314) -// so removing it until we get it straightened out. -// -- (void)clickHoldCallback:(id)theEvent; -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if( theEvent == [NSApp currentEvent] ) { - // we're still in the middle of the same mousedown event here, activate - // click-hold context menu by triggering the right mouseDown action. - NSEvent* clickHoldEvent = [NSEvent mouseEventWithType:NSRightMouseDown - location:[theEvent locationInWindow] - modifierFlags:[theEvent modifierFlags] - timestamp:[theEvent timestamp] - windowNumber:[theEvent windowNumber] - context:[theEvent context] - eventNumber:[theEvent eventNumber] - clickCount:[theEvent clickCount] - pressure:[theEvent pressure]]; - [self rightMouseDown:clickHoldEvent]; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} -#endif - -// If we've just created a non-native context menu, we need to mark it as -// such and let the OS (and other programs) know when it opens and closes -// (this is how the OS knows to close other programs' context menus when -// ours open). We send the initial notification here, but others are sent -// in nsCocoaWindow::Show(). -- (void)maybeInitContextMenuTracking -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - -#ifdef MOZ_USE_NATIVE_POPUP_WINDOWS - return; -#endif /* MOZ_USE_NATIVE_POPUP_WINDOWS */ - - nsIRollupListener* rollupListener = nsBaseWidget::GetActiveRollupListener(); - NS_ENSURE_TRUE_VOID(rollupListener); - nsCOMPtr widget = rollupListener->GetRollupWidget(); - NS_ENSURE_TRUE_VOID(widget); - - NSWindow *popupWindow = (NSWindow*)widget->GetNativeData(NS_NATIVE_WINDOW); - if (!popupWindow || ![popupWindow isKindOfClass:[PopupWindow class]]) - return; - - [[NSDistributedNotificationCenter defaultCenter] - postNotificationName:@"com.apple.HIToolbox.beginMenuTrackingNotification" - object:@"org.mozilla.gecko.PopupWindow"]; - [(PopupWindow*)popupWindow setIsContextMenu:YES]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// Returns true if the event should no longer be processed, false otherwise. -// This does not return whether or not anything was rolled up. -- (BOOL)maybeRollup:(NSEvent*)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - BOOL consumeEvent = NO; - - nsIRollupListener* rollupListener = nsBaseWidget::GetActiveRollupListener(); - NS_ENSURE_TRUE(rollupListener, false); - nsCOMPtr rollupWidget = rollupListener->GetRollupWidget(); - if (rollupWidget) { - NSWindow* currentPopup = static_cast(rollupWidget->GetNativeData(NS_NATIVE_WINDOW)); - if (!nsCocoaUtils::IsEventOverWindow(theEvent, currentPopup)) { - // event is not over the rollup window, default is to roll up - bool shouldRollup = true; - - // check to see if scroll events should roll up the popup - if ([theEvent type] == NSScrollWheel) { - shouldRollup = rollupListener->ShouldRollupOnMouseWheelEvent(); - // consume scroll events that aren't over the popup - // unless the popup is an arrow panel - consumeEvent = rollupListener->ShouldConsumeOnMouseWheelEvent(); - } - - // if we're dealing with menus, we probably have submenus and - // we don't want to rollup if the click is in a parent menu of - // the current submenu - uint32_t popupsToRollup = UINT32_MAX; - AutoTArray widgetChain; - uint32_t sameTypeCount = rollupListener->GetSubmenuWidgetChain(&widgetChain); - for (uint32_t i = 0; i < widgetChain.Length(); i++) { - nsIWidget* widget = widgetChain[i]; - NSWindow* currWindow = (NSWindow*)widget->GetNativeData(NS_NATIVE_WINDOW); - if (nsCocoaUtils::IsEventOverWindow(theEvent, currWindow)) { - // don't roll up if the mouse event occurred within a menu of the - // same type. If the mouse event occurred in a menu higher than - // that, roll up, but pass the number of popups to Rollup so - // that only those of the same type close up. - if (i < sameTypeCount) { - shouldRollup = false; - } - else { - popupsToRollup = sameTypeCount; - } - break; - } - } - - if (shouldRollup) { - if ([theEvent type] == NSLeftMouseDown) { - NSPoint point = [NSEvent mouseLocation]; - FlipCocoaScreenCoordinate(point); - gfx::IntPoint pos = gfx::IntPoint::Truncate(point.x, point.y); - consumeEvent = (BOOL)rollupListener->Rollup(popupsToRollup, true, &pos, nullptr); - } - else { - consumeEvent = (BOOL)rollupListener->Rollup(popupsToRollup, true, nullptr, nullptr); - } - } - } - } - - return consumeEvent; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO); -} - -/* - * In OS X Mountain Lion and above, smart zoom gestures are implemented in - * smartMagnifyWithEvent. In OS X Lion, they are implemented in - * magnifyWithEvent. See inline comments for more info. - * - * The prototypes swipeWithEvent, beginGestureWithEvent, magnifyWithEvent, - * smartMagnifyWithEvent, rotateWithEvent, and endGestureWithEvent were - * obtained from the following links: - * https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSResponder_Class/Reference/Reference.html - * https://developer.apple.com/library/mac/#releasenotes/Cocoa/AppKit.html - */ - -- (void)swipeWithEvent:(NSEvent *)anEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!anEvent || !mGeckoChild) - return; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - float deltaX = [anEvent deltaX]; // left=1.0, right=-1.0 - float deltaY = [anEvent deltaY]; // up=1.0, down=-1.0 - - // Setup the "swipe" event. - WidgetSimpleGestureEvent geckoEvent(true, eSwipeGesture, mGeckoChild); - [self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent]; - - // Record the left/right direction. - if (deltaX > 0.0) - geckoEvent.mDirection |= nsIDOMSimpleGestureEvent::DIRECTION_LEFT; - else if (deltaX < 0.0) - geckoEvent.mDirection |= nsIDOMSimpleGestureEvent::DIRECTION_RIGHT; - - // Record the up/down direction. - if (deltaY > 0.0) - geckoEvent.mDirection |= nsIDOMSimpleGestureEvent::DIRECTION_UP; - else if (deltaY < 0.0) - geckoEvent.mDirection |= nsIDOMSimpleGestureEvent::DIRECTION_DOWN; - - // Send the event. - mGeckoChild->DispatchWindowEvent(geckoEvent); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)beginGestureWithEvent:(NSEvent *)anEvent -{ - if (!anEvent) - return; - - mGestureState = eGestureState_StartGesture; - mCumulativeMagnification = 0; - mCumulativeRotation = 0.0; -} - -- (void)magnifyWithEvent:(NSEvent *)anEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!anEvent || !mGeckoChild) - return; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - float deltaZ = [anEvent deltaZ]; - - EventMessage msg; - switch (mGestureState) { - case eGestureState_StartGesture: - msg = eMagnifyGestureStart; - mGestureState = eGestureState_MagnifyGesture; - break; - - case eGestureState_MagnifyGesture: - msg = eMagnifyGestureUpdate; - break; - - case eGestureState_None: - case eGestureState_RotateGesture: - default: - return; - } - - // Setup the event. - WidgetSimpleGestureEvent geckoEvent(true, msg, mGeckoChild); - geckoEvent.mDelta = deltaZ; - [self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent]; - - // Send the event. - mGeckoChild->DispatchWindowEvent(geckoEvent); - - // Keep track of the cumulative magnification for the final "magnify" event. - mCumulativeMagnification += deltaZ; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)smartMagnifyWithEvent:(NSEvent *)anEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!anEvent || !mGeckoChild) { - return; - } - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - // Setup the "double tap" event. - WidgetSimpleGestureEvent geckoEvent(true, eTapGesture, mGeckoChild); - [self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent]; - geckoEvent.mClickCount = 1; - - // Send the event. - mGeckoChild->DispatchWindowEvent(geckoEvent); - - // Clear the gesture state - mGestureState = eGestureState_None; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)rotateWithEvent:(NSEvent *)anEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!anEvent || !mGeckoChild) - return; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - float rotation = [anEvent rotation]; - - EventMessage msg; - switch (mGestureState) { - case eGestureState_StartGesture: - msg = eRotateGestureStart; - mGestureState = eGestureState_RotateGesture; - break; - - case eGestureState_RotateGesture: - msg = eRotateGestureUpdate; - break; - - case eGestureState_None: - case eGestureState_MagnifyGesture: - default: - return; - } - - // Setup the event. - WidgetSimpleGestureEvent geckoEvent(true, msg, mGeckoChild); - [self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent]; - geckoEvent.mDelta = -rotation; - if (rotation > 0.0) { - geckoEvent.mDirection = nsIDOMSimpleGestureEvent::ROTATION_COUNTERCLOCKWISE; - } else { - geckoEvent.mDirection = nsIDOMSimpleGestureEvent::ROTATION_CLOCKWISE; - } - - // Send the event. - mGeckoChild->DispatchWindowEvent(geckoEvent); - - // Keep track of the cumulative rotation for the final "rotate" event. - mCumulativeRotation += rotation; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)endGestureWithEvent:(NSEvent *)anEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!anEvent || !mGeckoChild) { - // Clear the gestures state if we cannot send an event. - mGestureState = eGestureState_None; - mCumulativeMagnification = 0.0; - mCumulativeRotation = 0.0; - return; - } - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - switch (mGestureState) { - case eGestureState_MagnifyGesture: - { - // Setup the "magnify" event. - WidgetSimpleGestureEvent geckoEvent(true, eMagnifyGesture, mGeckoChild); - geckoEvent.mDelta = mCumulativeMagnification; - [self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent]; - - // Send the event. - mGeckoChild->DispatchWindowEvent(geckoEvent); - } - break; - - case eGestureState_RotateGesture: - { - // Setup the "rotate" event. - WidgetSimpleGestureEvent geckoEvent(true, eRotateGesture, mGeckoChild); - [self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent]; - geckoEvent.mDelta = -mCumulativeRotation; - if (mCumulativeRotation > 0.0) { - geckoEvent.mDirection = nsIDOMSimpleGestureEvent::ROTATION_COUNTERCLOCKWISE; - } else { - geckoEvent.mDirection = nsIDOMSimpleGestureEvent::ROTATION_CLOCKWISE; - } - - // Send the event. - mGeckoChild->DispatchWindowEvent(geckoEvent); - } - break; - - case eGestureState_None: - case eGestureState_StartGesture: - default: - break; - } - - // Clear the gestures state. - mGestureState = eGestureState_None; - mCumulativeMagnification = 0.0; - mCumulativeRotation = 0.0; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (bool)shouldConsiderStartingSwipeFromEvent:(NSEvent*)anEvent -{ - // This method checks whether the AppleEnableSwipeNavigateWithScrolls global - // preference is set. If it isn't, fluid swipe tracking is disabled, and a - // horizontal two-finger gesture is always a scroll (even in Safari). This - // preference can't (currently) be set from the Preferences UI -- only using - // 'defaults write'. - if (![NSEvent isSwipeTrackingFromScrollEventsEnabled]) { - return false; - } - - // Only initiate horizontal tracking for gestures that have just begun -- - // otherwise a scroll to one side of the page can have a swipe tacked on - // to it. - NSEventPhase eventPhase = nsCocoaUtils::EventPhase(anEvent); - if ([anEvent type] != NSScrollWheel || - eventPhase != NSEventPhaseBegan || - ![anEvent hasPreciseScrollingDeltas]) { - return false; - } - - // Only initiate horizontal tracking for events whose horizontal element is - // at least eight times larger than its vertical element. This minimizes - // performance problems with vertical scrolls (by minimizing the possibility - // that they'll be misinterpreted as horizontal swipes), while still - // tolerating a small vertical element to a true horizontal swipe. The number - // '8' was arrived at by trial and error. - CGFloat deltaX = [anEvent scrollingDeltaX]; - CGFloat deltaY = [anEvent scrollingDeltaY]; - return std::abs(deltaX) > std::abs(deltaY) * 8; -} - -- (void)setUsingOMTCompositor:(BOOL)aUseOMTC -{ - mUsingOMTCompositor = aUseOMTC; -} - -// Returning NO from this method only disallows ordering on mousedown - in order -// to prevent it for mouseup too, we need to call [NSApp preventWindowOrdering] -// when handling the mousedown event. -- (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent*)aEvent -{ - // Always using system-provided window ordering for normal windows. - if (![[self window] isKindOfClass:[PopupWindow class]]) - return NO; - - // Don't reorder when we don't have a parent window, like when we're a - // context menu or a tooltip. - return ![[self window] parentWindow]; -} - -- (void)mouseDown:(NSEvent*)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if ([self shouldDelayWindowOrderingForEvent:theEvent]) { - [NSApp preventWindowOrdering]; - } - - // If we've already seen this event due to direct dispatch from menuForEvent: - // just bail; if not, remember it. - if (mLastMouseDownEvent == theEvent) { - [mLastMouseDownEvent release]; - mLastMouseDownEvent = nil; - return; - } - else { - [mLastMouseDownEvent release]; - mLastMouseDownEvent = [theEvent retain]; - } - - [gLastDragMouseDownEvent release]; - gLastDragMouseDownEvent = [theEvent retain]; - - // We need isClickThrough because at this point the window we're in might - // already have become main, so the check for isMainWindow in - // WindowAcceptsEvent isn't enough. It also has to check isClickThrough. - BOOL isClickThrough = (theEvent == mClickThroughMouseDownEvent); - [mClickThroughMouseDownEvent release]; - mClickThroughMouseDownEvent = nil; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - if ([self maybeRollup:theEvent] || - !ChildViewMouseTracker::WindowAcceptsEvent([self window], theEvent, self, isClickThrough)) { - // Remember blocking because that means we want to block mouseup as well. - mBlockedLastMouseDown = YES; - return; - } - -#if USE_CLICK_HOLD_CONTEXTMENU - // fire off timer to check for click-hold after two seconds. retains |theEvent| - [self performSelector:@selector(clickHoldCallback:) withObject:theEvent afterDelay:2.0]; -#endif - - // in order to send gecko events we'll need a gecko widget - if (!mGeckoChild) - return; - if (mTextInputHandler->OnHandleEvent(theEvent)) { - return; - } - - NSUInteger modifierFlags = [theEvent modifierFlags]; - - WidgetMouseEvent geckoEvent(true, eMouseDown, mGeckoChild, - WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - - NSInteger clickCount = [theEvent clickCount]; - if (mBlockedLastMouseDown && clickCount > 1) { - // Don't send a double click if the first click of the double click was - // blocked. - clickCount--; - } - geckoEvent.mClickCount = clickCount; - - if (modifierFlags & NSControlKeyMask) - geckoEvent.button = WidgetMouseEvent::eRightButton; - else - geckoEvent.button = WidgetMouseEvent::eLeftButton; - - mGeckoChild->DispatchInputEvent(&geckoEvent); - mBlockedLastMouseDown = NO; - - // XXX maybe call markedTextSelectionChanged:client: here? - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)mouseUp:(NSEvent *)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mGeckoChild || mBlockedLastMouseDown) - return; - if (mTextInputHandler->OnHandleEvent(theEvent)) { - return; - } - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - WidgetMouseEvent geckoEvent(true, eMouseUp, mGeckoChild, - WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - if ([theEvent modifierFlags] & NSControlKeyMask) - geckoEvent.button = WidgetMouseEvent::eRightButton; - else - geckoEvent.button = WidgetMouseEvent::eLeftButton; - - // This might destroy our widget (and null out mGeckoChild). - bool defaultPrevented = - (mGeckoChild->DispatchInputEvent(&geckoEvent) == nsEventStatus_eConsumeNoDefault); - - // Check to see if we are double-clicking in the titlebar. - CGFloat locationInTitlebar = [[self window] frame].size.height - [theEvent locationInWindow].y; - LayoutDeviceIntPoint pos = geckoEvent.mRefPoint; - if (!defaultPrevented && [theEvent clickCount] == 2 && - !mGeckoChild->GetNonDraggableRegion().Contains(pos.x, pos.y) && - [[self window] isKindOfClass:[ToolbarWindow class]] && - (locationInTitlebar < [(ToolbarWindow*)[self window] titlebarHeight] || - locationInTitlebar < [(ToolbarWindow*)[self window] unifiedToolbarHeight])) { - if ([self shouldZoomOnDoubleClick]) { - [[self window] performZoom:nil]; - } else if ([self shouldMinimizeOnTitlebarDoubleClick]) { - NSButton *minimizeButton = [[self window] standardWindowButton:NSWindowMiniaturizeButton]; - [minimizeButton performClick:self]; - } - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)sendMouseEnterOrExitEvent:(NSEvent*)aEvent - enter:(BOOL)aEnter - exitFrom:(WidgetMouseEvent::ExitFrom)aExitFrom -{ - if (!mGeckoChild) - return; - - NSPoint windowEventLocation = nsCocoaUtils::EventLocationForWindow(aEvent, [self window]); - NSPoint localEventLocation = [self convertPoint:windowEventLocation fromView:nil]; - - EventMessage msg = aEnter ? eMouseEnterIntoWidget : eMouseExitFromWidget; - WidgetMouseEvent event(true, msg, mGeckoChild, WidgetMouseEvent::eReal); - event.mRefPoint = mGeckoChild->CocoaPointsToDevPixels(localEventLocation); - - event.mExitFrom = aExitFrom; - - nsEventStatus status; // ignored - mGeckoChild->DispatchEvent(&event, status); -} - -- (void)handleMouseMoved:(NSEvent*)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mGeckoChild) - return; - if (mTextInputHandler->OnHandleEvent(theEvent)) { - return; - } - - WidgetMouseEvent geckoEvent(true, eMouseMove, mGeckoChild, - WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - - mGeckoChild->DispatchInputEvent(&geckoEvent); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)mouseDragged:(NSEvent*)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mGeckoChild) - return; - if (mTextInputHandler->OnHandleEvent(theEvent)) { - return; - } - - gLastDragView = self; - - WidgetMouseEvent geckoEvent(true, eMouseMove, mGeckoChild, - WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - - mGeckoChild->DispatchInputEvent(&geckoEvent); - - // Note, sending the above event might have destroyed our widget since we didn't retain. - // Fine so long as we don't access any local variables from here on. - gLastDragView = nil; - - // XXX maybe call markedTextSelectionChanged:client: here? - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)rightMouseDown:(NSEvent *)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - [self maybeRollup:theEvent]; - if (!mGeckoChild) - return; - if (mTextInputHandler->OnHandleEvent(theEvent)) { - return; - } - - // The right mouse went down, fire off a right mouse down event to gecko - WidgetMouseEvent geckoEvent(true, eMouseDown, mGeckoChild, - WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - geckoEvent.button = WidgetMouseEvent::eRightButton; - geckoEvent.mClickCount = [theEvent clickCount]; - - mGeckoChild->DispatchInputEvent(&geckoEvent); - if (!mGeckoChild) - return; - - // Let the superclass do the context menu stuff. - [super rightMouseDown:theEvent]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)rightMouseUp:(NSEvent *)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mGeckoChild) - return; - if (mTextInputHandler->OnHandleEvent(theEvent)) { - return; - } - - WidgetMouseEvent geckoEvent(true, eMouseUp, mGeckoChild, - WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - geckoEvent.button = WidgetMouseEvent::eRightButton; - geckoEvent.mClickCount = [theEvent clickCount]; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - mGeckoChild->DispatchInputEvent(&geckoEvent); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)rightMouseDragged:(NSEvent*)theEvent -{ - if (!mGeckoChild) - return; - if (mTextInputHandler->OnHandleEvent(theEvent)) { - return; - } - - WidgetMouseEvent geckoEvent(true, eMouseMove, mGeckoChild, - WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - geckoEvent.button = WidgetMouseEvent::eRightButton; - - // send event into Gecko by going directly to the - // the widget. - mGeckoChild->DispatchInputEvent(&geckoEvent); -} - -- (void)otherMouseDown:(NSEvent *)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - if ([self maybeRollup:theEvent] || - !ChildViewMouseTracker::WindowAcceptsEvent([self window], theEvent, self)) - return; - - if (!mGeckoChild) - return; - if (mTextInputHandler->OnHandleEvent(theEvent)) { - return; - } - - WidgetMouseEvent geckoEvent(true, eMouseDown, mGeckoChild, - WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - geckoEvent.button = WidgetMouseEvent::eMiddleButton; - geckoEvent.mClickCount = [theEvent clickCount]; - - mGeckoChild->DispatchInputEvent(&geckoEvent); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)otherMouseUp:(NSEvent *)theEvent -{ - if (!mGeckoChild) - return; - if (mTextInputHandler->OnHandleEvent(theEvent)) { - return; - } - - WidgetMouseEvent geckoEvent(true, eMouseUp, mGeckoChild, - WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - geckoEvent.button = WidgetMouseEvent::eMiddleButton; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - mGeckoChild->DispatchInputEvent(&geckoEvent); -} - -- (void)otherMouseDragged:(NSEvent*)theEvent -{ - if (!mGeckoChild) - return; - if (mTextInputHandler->OnHandleEvent(theEvent)) { - return; - } - - WidgetMouseEvent geckoEvent(true, eMouseMove, mGeckoChild, - WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - geckoEvent.button = WidgetMouseEvent::eMiddleButton; - - // send event into Gecko by going directly to the - // the widget. - mGeckoChild->DispatchInputEvent(&geckoEvent); -} - -- (void)sendWheelStartOrStop:(EventMessage)msg forEvent:(NSEvent *)theEvent -{ - WidgetWheelEvent wheelEvent(true, msg, mGeckoChild); - [self convertCocoaMouseWheelEvent:theEvent toGeckoEvent:&wheelEvent]; - mExpectingWheelStop = (msg == eWheelOperationStart); - mGeckoChild->DispatchInputEvent(wheelEvent.AsInputEvent()); -} - -- (void)sendWheelCondition:(BOOL)condition - first:(EventMessage)first - second:(EventMessage)second - forEvent:(NSEvent *)theEvent -{ - if (mExpectingWheelStop == condition) { - [self sendWheelStartOrStop:first forEvent:theEvent]; - } - [self sendWheelStartOrStop:second forEvent:theEvent]; -} - -static PanGestureInput::PanGestureType -PanGestureTypeForEvent(NSEvent* aEvent) -{ - switch (nsCocoaUtils::EventPhase(aEvent)) { - case NSEventPhaseMayBegin: - return PanGestureInput::PANGESTURE_MAYSTART; - case NSEventPhaseCancelled: - return PanGestureInput::PANGESTURE_CANCELLED; - case NSEventPhaseBegan: - return PanGestureInput::PANGESTURE_START; - case NSEventPhaseChanged: - return PanGestureInput::PANGESTURE_PAN; - case NSEventPhaseEnded: - return PanGestureInput::PANGESTURE_END; - case NSEventPhaseNone: - switch (nsCocoaUtils::EventMomentumPhase(aEvent)) { - case NSEventPhaseBegan: - return PanGestureInput::PANGESTURE_MOMENTUMSTART; - case NSEventPhaseChanged: - return PanGestureInput::PANGESTURE_MOMENTUMPAN; - case NSEventPhaseEnded: - return PanGestureInput::PANGESTURE_MOMENTUMEND; - default: - NS_ERROR("unexpected event phase"); - return PanGestureInput::PANGESTURE_PAN; - } - default: - NS_ERROR("unexpected event phase"); - return PanGestureInput::PANGESTURE_PAN; - } -} - -static int32_t RoundUp(double aDouble) -{ - return aDouble < 0 ? static_cast(floor(aDouble)) : - static_cast(ceil(aDouble)); -} - -static int32_t -TakeLargestInt(gfx::Float* aFloat) -{ - int32_t result(*aFloat); // truncate towards zero - *aFloat -= result; - return result; -} - -static gfx::IntPoint -AccumulateIntegerDelta(NSEvent* aEvent) -{ - static gfx::Point sAccumulator(0.0f, 0.0f); - if (nsCocoaUtils::EventPhase(aEvent) == NSEventPhaseBegan) { - sAccumulator = gfx::Point(0.0f, 0.0f); - } - sAccumulator.x += [aEvent deltaX]; - sAccumulator.y += [aEvent deltaY]; - return gfx::IntPoint(TakeLargestInt(&sAccumulator.x), - TakeLargestInt(&sAccumulator.y)); -} - -static gfx::IntPoint -GetIntegerDeltaForEvent(NSEvent* aEvent) -{ - if (nsCocoaFeatures::OnSierraOrLater() && [aEvent hasPreciseScrollingDeltas]) { - // Pixel scroll events (events with hasPreciseScrollingDeltas == YES) - // carry pixel deltas in the scrollingDeltaX/Y fields and line scroll - // information in the deltaX/Y fields. - // Prior to 10.12, these line scroll fields would be zero for most pixel - // scroll events and non-zero for some, whenever at least a full line - // worth of pixel scrolling had accumulated. That's the behavior we want. - // Starting with 10.12 however, pixel scroll events no longer accumulate - // deltaX and deltaY; they just report floating point values for every - // single event. So we need to do our own accumulation. - return AccumulateIntegerDelta(aEvent); - } - - // For line scrolls, or pre-10.12, just use the rounded up value of deltaX / deltaY. - return gfx::IntPoint(RoundUp([aEvent deltaX]), RoundUp([aEvent deltaY])); -} - -- (void)scrollWheel:(NSEvent*)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - ChildViewMouseTracker::MouseScrolled(theEvent); - - if ([self maybeRollup:theEvent]) { - return; - } - - if (!mGeckoChild) { - return; - } - - NSEventPhase phase = nsCocoaUtils::EventPhase(theEvent); - // Fire eWheelOperationStart/End events when 2 fingers touch/release the - // touchpad. - if (phase & NSEventPhaseMayBegin) { - [self sendWheelCondition:YES - first:eWheelOperationEnd - second:eWheelOperationStart - forEvent:theEvent]; - } else if (phase & (NSEventPhaseEnded | NSEventPhaseCancelled)) { - [self sendWheelCondition:NO - first:eWheelOperationStart - second:eWheelOperationEnd - forEvent:theEvent]; - } - - if (!mGeckoChild) { - return; - } - RefPtr geckoChildDeathGrip(mGeckoChild); - - NSPoint locationInWindow = nsCocoaUtils::EventLocationForWindow(theEvent, [self window]); - - // Use convertWindowCoordinatesRoundDown when converting the position to - // integer screen pixels in order to ensure that coordinates which are just - // inside the right / bottom edges of the window don't end up outside of the - // window after rounding. - ScreenPoint position = ViewAs( - [self convertWindowCoordinatesRoundDown:locationInWindow], - PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent); - - bool usePreciseDeltas = nsCocoaUtils::HasPreciseScrollingDeltas(theEvent) && - Preferences::GetBool("mousewheel.enable_pixel_scrolling", true); - bool hasPhaseInformation = nsCocoaUtils::EventHasPhaseInformation(theEvent); - - gfx::IntPoint lineOrPageDelta = -GetIntegerDeltaForEvent(theEvent); - - Modifiers modifiers = nsCocoaUtils::ModifiersForEvent(theEvent); - - NSTimeInterval beforeNow = [[NSProcessInfo processInfo] systemUptime] - [theEvent timestamp]; - PRIntervalTime eventIntervalTime = PR_IntervalNow() - PR_MillisecondsToInterval(beforeNow * 1000); - TimeStamp eventTimeStamp = TimeStamp::Now() - TimeDuration::FromSeconds(beforeNow); - - ScreenPoint preciseDelta; - if (usePreciseDeltas) { - CGFloat pixelDeltaX = 0, pixelDeltaY = 0; - nsCocoaUtils::GetScrollingDeltas(theEvent, &pixelDeltaX, &pixelDeltaY); - double scale = geckoChildDeathGrip->BackingScaleFactor(); - preciseDelta = ScreenPoint(-pixelDeltaX * scale, -pixelDeltaY * scale); - } - - if (usePreciseDeltas && hasPhaseInformation) { - PanGestureInput panEvent(PanGestureTypeForEvent(theEvent), - eventIntervalTime, eventTimeStamp, - position, preciseDelta, modifiers); - panEvent.mLineOrPageDeltaX = lineOrPageDelta.x; - panEvent.mLineOrPageDeltaY = lineOrPageDelta.y; - - if (panEvent.mType == PanGestureInput::PANGESTURE_END) { - // Check if there's a momentum start event in the event queue, so that we - // can annotate this event. - NSEvent* nextWheelEvent = - [NSApp nextEventMatchingMask:NSScrollWheelMask - untilDate:[NSDate distantPast] - inMode:NSDefaultRunLoopMode - dequeue:NO]; - if (nextWheelEvent && - PanGestureTypeForEvent(nextWheelEvent) == PanGestureInput::PANGESTURE_MOMENTUMSTART) { - panEvent.mFollowedByMomentum = true; - } - } - - bool canTriggerSwipe = [self shouldConsiderStartingSwipeFromEvent:theEvent]; - panEvent.mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection = canTriggerSwipe; - geckoChildDeathGrip->DispatchAPZWheelInputEvent(panEvent, canTriggerSwipe); - } else if (usePreciseDeltas) { - // This is on 10.6 or old touchpads that don't have any phase information. - ScrollWheelInput wheelEvent(eventIntervalTime, eventTimeStamp, modifiers, - ScrollWheelInput::SCROLLMODE_INSTANT, - ScrollWheelInput::SCROLLDELTA_PIXEL, - position, - preciseDelta.x, - preciseDelta.y, - false); - wheelEvent.mLineOrPageDeltaX = lineOrPageDelta.x; - wheelEvent.mLineOrPageDeltaY = lineOrPageDelta.y; - wheelEvent.mIsMomentum = nsCocoaUtils::IsMomentumScrollEvent(theEvent); - geckoChildDeathGrip->DispatchAPZWheelInputEvent(wheelEvent, false); - } else { - ScrollWheelInput::ScrollMode scrollMode = ScrollWheelInput::SCROLLMODE_INSTANT; - if (gfxPrefs::SmoothScrollEnabled() && gfxPrefs::WheelSmoothScrollEnabled()) { - scrollMode = ScrollWheelInput::SCROLLMODE_SMOOTH; - } - ScrollWheelInput wheelEvent(eventIntervalTime, eventTimeStamp, modifiers, - scrollMode, - ScrollWheelInput::SCROLLDELTA_LINE, - position, - lineOrPageDelta.x, - lineOrPageDelta.y, - false); - wheelEvent.mLineOrPageDeltaX = lineOrPageDelta.x; - wheelEvent.mLineOrPageDeltaY = lineOrPageDelta.y; - geckoChildDeathGrip->DispatchAPZWheelInputEvent(wheelEvent, false); - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - --(NSMenu*)menuForEvent:(NSEvent*)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - if (!mGeckoChild) - return nil; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - [self maybeRollup:theEvent]; - if (!mGeckoChild) - return nil; - - // Cocoa doesn't always dispatch a mouseDown: for a control-click event, - // depends on what we return from menuForEvent:. Gecko always expects one - // and expects the mouse down event before the context menu event, so - // get that event sent first if this is a left mouse click. - if ([theEvent type] == NSLeftMouseDown) { - [self mouseDown:theEvent]; - if (!mGeckoChild) - return nil; - } - - WidgetMouseEvent geckoEvent(true, eContextMenu, mGeckoChild, - WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - geckoEvent.button = WidgetMouseEvent::eRightButton; - mGeckoChild->DispatchInputEvent(&geckoEvent); - if (!mGeckoChild) - return nil; - - [self maybeInitContextMenuTracking]; - - // Go up our view chain to fetch the correct menu to return. - return [self contextMenu]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (NSMenu*)contextMenu -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - NSView* superView = [self superview]; - if ([superView respondsToSelector:@selector(contextMenu)]) - return [(NSView*)superView contextMenu]; - - return nil; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (void) convertCocoaMouseWheelEvent:(NSEvent*)aMouseEvent - toGeckoEvent:(WidgetWheelEvent*)outWheelEvent -{ - [self convertCocoaMouseEvent:aMouseEvent toGeckoEvent:outWheelEvent]; - - bool usePreciseDeltas = nsCocoaUtils::HasPreciseScrollingDeltas(aMouseEvent) && - Preferences::GetBool("mousewheel.enable_pixel_scrolling", true); - - outWheelEvent->mDeltaMode = - usePreciseDeltas ? nsIDOMWheelEvent::DOM_DELTA_PIXEL - : nsIDOMWheelEvent::DOM_DELTA_LINE; - outWheelEvent->mIsMomentum = nsCocoaUtils::IsMomentumScrollEvent(aMouseEvent); -} - -- (void) convertCocoaMouseEvent:(NSEvent*)aMouseEvent - toGeckoEvent:(WidgetInputEvent*)outGeckoEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - NS_ASSERTION(outGeckoEvent, "convertCocoaMouseEvent:toGeckoEvent: requires non-null aoutGeckoEvent"); - if (!outGeckoEvent) - return; - - nsCocoaUtils::InitInputEvent(*outGeckoEvent, aMouseEvent); - - // convert point to view coordinate system - NSPoint locationInWindow = nsCocoaUtils::EventLocationForWindow(aMouseEvent, [self window]); - - outGeckoEvent->mRefPoint = [self convertWindowCoordinates:locationInWindow]; - - WidgetMouseEventBase* mouseEvent = outGeckoEvent->AsMouseEventBase(); - mouseEvent->buttons = 0; - NSUInteger mouseButtons = [NSEvent pressedMouseButtons]; - - if (mouseButtons & 0x01) { - mouseEvent->buttons |= WidgetMouseEvent::eLeftButtonFlag; - } - if (mouseButtons & 0x02) { - mouseEvent->buttons |= WidgetMouseEvent::eRightButtonFlag; - } - if (mouseButtons & 0x04) { - mouseEvent->buttons |= WidgetMouseEvent::eMiddleButtonFlag; - } - if (mouseButtons & 0x08) { - mouseEvent->buttons |= WidgetMouseEvent::e4thButtonFlag; - } - if (mouseButtons & 0x10) { - mouseEvent->buttons |= WidgetMouseEvent::e5thButtonFlag; - } - - switch ([aMouseEvent type]) { - case NSLeftMouseDown: - case NSLeftMouseUp: - case NSLeftMouseDragged: - case NSRightMouseDown: - case NSRightMouseUp: - case NSRightMouseDragged: - case NSOtherMouseDown: - case NSOtherMouseUp: - case NSOtherMouseDragged: - if ([aMouseEvent subtype] == NSTabletPointEventSubtype) { - mouseEvent->pressure = [aMouseEvent pressure]; - MOZ_ASSERT(mouseEvent->pressure >= 0.0 && mouseEvent->pressure <= 1.0); - } - break; - - default: - // Don't check other NSEvents for pressure. - break; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (BOOL)shouldZoomOnDoubleClick -{ - if ([NSWindow respondsToSelector:@selector(_shouldZoomOnDoubleClick)]) { - return [NSWindow _shouldZoomOnDoubleClick]; - } - return nsCocoaFeatures::OnYosemiteOrLater(); -} - -- (BOOL)shouldMinimizeOnTitlebarDoubleClick -{ - NSString *MDAppleMiniaturizeOnDoubleClickKey = - @"AppleMiniaturizeOnDoubleClick"; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - bool shouldMinimize = [[userDefaults - objectForKey:MDAppleMiniaturizeOnDoubleClickKey] boolValue]; - - return shouldMinimize; -} - -#pragma mark - -// NSTextInputClient implementation - -- (NSRange)markedRange -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - NS_ENSURE_TRUE(mTextInputHandler, NSMakeRange(NSNotFound, 0)); - return mTextInputHandler->MarkedRange(); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSMakeRange(0, 0)); -} - -- (NSRange)selectedRange -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - NS_ENSURE_TRUE(mTextInputHandler, NSMakeRange(NSNotFound, 0)); - return mTextInputHandler->SelectedRange(); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSMakeRange(0, 0)); -} - -- (BOOL)drawsVerticallyForCharacterAtIndex:(NSUInteger)charIndex -{ - NS_ENSURE_TRUE(mTextInputHandler, NO); - if (charIndex == NSNotFound) { - return NO; - } - return mTextInputHandler->DrawsVerticallyForCharacterAtIndex(charIndex); -} - -- (NSUInteger)characterIndexForPoint:(NSPoint)thePoint -{ - NS_ENSURE_TRUE(mTextInputHandler, 0); - return mTextInputHandler->CharacterIndexForPoint(thePoint); -} - -- (NSArray*)validAttributesForMarkedText -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - NS_ENSURE_TRUE(mTextInputHandler, [NSArray array]); - return mTextInputHandler->GetValidAttributesForMarkedText(); - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - NS_ENSURE_TRUE_VOID(mGeckoChild); - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - NSAttributedString* attrStr; - if ([aString isKindOfClass:[NSAttributedString class]]) { - attrStr = static_cast(aString); - } else { - attrStr = [[[NSAttributedString alloc] initWithString:aString] autorelease]; - } - - mTextInputHandler->InsertText(attrStr, &replacementRange); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)doCommandBySelector:(SEL)aSelector -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mGeckoChild || !mTextInputHandler) { - return; - } - - const char* sel = reinterpret_cast(aSelector); - if (!mTextInputHandler->DoCommandBySelector(sel)) { - [super doCommandBySelector:aSelector]; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)unmarkText -{ - NS_ENSURE_TRUE_VOID(mTextInputHandler); - mTextInputHandler->CommitIMEComposition(); -} - -- (BOOL) hasMarkedText -{ - NS_ENSURE_TRUE(mTextInputHandler, NO); - return mTextInputHandler->HasMarkedText(); -} - -- (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange - replacementRange:(NSRange)replacementRange -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - NS_ENSURE_TRUE_VOID(mTextInputHandler); - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - NSAttributedString* attrStr; - if ([aString isKindOfClass:[NSAttributedString class]]) { - attrStr = static_cast(aString); - } else { - attrStr = [[[NSAttributedString alloc] initWithString:aString] autorelease]; - } - - mTextInputHandler->SetMarkedText(attrStr, selectedRange, &replacementRange); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)aRange - actualRange:(NSRangePointer)actualRange -{ - NS_ENSURE_TRUE(mTextInputHandler, nil); - return mTextInputHandler->GetAttributedSubstringFromRange(aRange, - actualRange); -} - -- (NSRect)firstRectForCharacterRange:(NSRange)aRange - actualRange:(NSRangePointer)actualRange -{ - NS_ENSURE_TRUE(mTextInputHandler, NSMakeRect(0.0, 0.0, 0.0, 0.0)); - return mTextInputHandler->FirstRectForCharacterRange(aRange, actualRange); -} - -- (void)quickLookWithEvent:(NSEvent*)event -{ - // Show dictionary by current point - WidgetContentCommandEvent - contentCommandEvent(true, eContentCommandLookUpDictionary, mGeckoChild); - NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil]; - contentCommandEvent.mRefPoint = mGeckoChild->CocoaPointsToDevPixels(point); - mGeckoChild->DispatchWindowEvent(contentCommandEvent); - // The widget might have been destroyed. -} - -- (NSInteger)windowLevel -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - NS_ENSURE_TRUE(mTextInputHandler, [[self window] level]); - return mTextInputHandler->GetWindowLevel(); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSNormalWindowLevel); -} - -#pragma mark - - -// This is a private API that Cocoa uses. -// Cocoa will call this after the menu system returns "NO" for "performKeyEquivalent:". -// We want all they key events we can get so just return YES. In particular, this fixes -// ctrl-tab - we don't get a "keyDown:" call for that without this. -- (BOOL)_wantsKeyDownForEvent:(NSEvent*)event -{ - return YES; -} - -- (NSEvent*)lastKeyDownEvent -{ - return mLastKeyDownEvent; -} - -- (void)keyDown:(NSEvent*)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mLastKeyDownEvent release]; - mLastKeyDownEvent = [theEvent retain]; - - // Weird things can happen on keyboard input if the key window isn't in the - // current space. For example see bug 1056251. To get around this, always - // make sure that, if our window is key, it's also made frontmost. Doing - // this automatically switches to whatever space our window is in. Safari - // does something similar. Our window should normally always be key -- - // otherwise why is the OS sending us a key down event? But it's just - // possible we're in Gecko's hidden window, so we check first. - NSWindow *viewWindow = [self window]; - if (viewWindow && [viewWindow isKeyWindow]) { - [viewWindow orderWindow:NSWindowAbove relativeTo:0]; - } - -#if !defined(RELEASE_OR_BETA) || defined(DEBUG) - if (!Preferences::GetBool("intl.allow-insecure-text-input", false) && - mGeckoChild && mTextInputHandler && mTextInputHandler->IsFocused()) { - if (mGeckoChild->GetInputContext().IsPasswordEditor() && - !TextInputHandler::IsSecureEventInputEnabled()) { - #define CRASH_MESSAGE "A password editor has focus, but not in secure input mode" - MOZ_CRASH(CRASH_MESSAGE); - #undef CRASH_MESSAGE - } else if (!mGeckoChild->GetInputContext().IsPasswordEditor() && - TextInputHandler::IsSecureEventInputEnabled()) { - #define CRASH_MESSAGE "A non-password editor has focus, but in secure input mode" - MOZ_CRASH(CRASH_MESSAGE); - #undef CRASH_MESSAGE - } - } -#endif // #if !defined(RELEASE_OR_BETA) || defined(DEBUG) - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - bool handled = false; - if (mGeckoChild && mTextInputHandler) { - handled = mTextInputHandler->HandleKeyDownEvent(theEvent); - } - - // We always allow keyboard events to propagate to keyDown: but if they are not - // handled we give special Application menu items a chance to act. - if (!handled && sApplicationMenu) { - [sApplicationMenu performKeyEquivalent:theEvent]; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)keyUp:(NSEvent*)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - NS_ENSURE_TRUE(mGeckoChild, ); - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - mTextInputHandler->HandleKeyUpEvent(theEvent); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)insertNewline:(id)sender -{ - if (mTextInputHandler) { - NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:@"\n"]; - mTextInputHandler->InsertText(attrStr); - [attrStr release]; - } -} - -- (void)flagsChanged:(NSEvent*)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - NS_ENSURE_TRUE(mGeckoChild, ); - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - mTextInputHandler->HandleFlagsChanged(theEvent); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (BOOL) isFirstResponder -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - NSResponder* resp = [[self window] firstResponder]; - return (resp == (NSResponder*)self); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO); -} - -- (BOOL)isDragInProgress -{ - if (!mDragService) - return NO; - - nsCOMPtr dragSession; - mDragService->GetCurrentSession(getter_AddRefs(dragSession)); - return dragSession != nullptr; -} - -- (BOOL)inactiveWindowAcceptsMouseEvent:(NSEvent*)aEvent -{ - // If we're being destroyed assume the default -- return YES. - if (!mGeckoChild) - return YES; - - WidgetMouseEvent geckoEvent(true, eMouseActivate, mGeckoChild, - WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:aEvent toGeckoEvent:&geckoEvent]; - return (mGeckoChild->DispatchInputEvent(&geckoEvent) != nsEventStatus_eConsumeNoDefault); -} - -// We must always call through to our superclass, even when mGeckoChild is -// nil -- otherwise the keyboard focus can end up in the wrong NSView. -- (BOOL)becomeFirstResponder -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - return [super becomeFirstResponder]; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(YES); -} - -- (void)viewsWindowDidBecomeKey -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mGeckoChild) - return; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - // check to see if the window implements the mozWindow protocol. This - // allows embedders to avoid re-entrant calls to -makeKeyAndOrderFront, - // which can happen because these activate calls propagate out - // to the embedder via nsIEmbeddingSiteWindow::SetFocus(). - BOOL isMozWindow = [[self window] respondsToSelector:@selector(setSuppressMakeKeyFront:)]; - if (isMozWindow) - [[self window] setSuppressMakeKeyFront:YES]; - - nsIWidgetListener* listener = mGeckoChild->GetWidgetListener(); - if (listener) - listener->WindowActivated(); - - if (isMozWindow) - [[self window] setSuppressMakeKeyFront:NO]; - - if (mGeckoChild->GetInputContext().IsPasswordEditor()) { - TextInputHandler::EnableSecureEventInput(); - } else { - TextInputHandler::EnsureSecureEventInputDisabled(); - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)viewsWindowDidResignKey -{ - if (!mGeckoChild) - return; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - nsIWidgetListener* listener = mGeckoChild->GetWidgetListener(); - if (listener) - listener->WindowDeactivated(); - - TextInputHandler::EnsureSecureEventInputDisabled(); -} - -// If the call to removeFromSuperview isn't delayed from nsChildView:: -// TearDownView(), the NSView hierarchy might get changed during calls to -// [ChildView drawRect:], which leads to "beyond bounds" exceptions in -// NSCFArray. For more info see bmo bug 373122. Apple's docs claim that -// removeFromSuperviewWithoutNeedingDisplay "can be safely invoked during -// display" (whatever "display" means). But it's _not_ true that it can be -// safely invoked during calls to [NSView drawRect:]. We use -// removeFromSuperview here because there's no longer any danger of being -// "invoked during display", and because doing do clears up bmo bug 384343. -- (void)delayedTearDown -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [self removeFromSuperview]; - [self release]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -#pragma mark - - -// drag'n'drop stuff -#define kDragServiceContractID "@mozilla.org/widget/dragservice;1" - -- (NSDragOperation)dragOperationFromDragAction:(int32_t)aDragAction -{ - if (nsIDragService::DRAGDROP_ACTION_LINK & aDragAction) - return NSDragOperationLink; - if (nsIDragService::DRAGDROP_ACTION_COPY & aDragAction) - return NSDragOperationCopy; - if (nsIDragService::DRAGDROP_ACTION_MOVE & aDragAction) - return NSDragOperationGeneric; - return NSDragOperationNone; -} - -- (LayoutDeviceIntPoint)convertWindowCoordinates:(NSPoint)aPoint -{ - if (!mGeckoChild) { - return LayoutDeviceIntPoint(0, 0); - } - - NSPoint localPoint = [self convertPoint:aPoint fromView:nil]; - return mGeckoChild->CocoaPointsToDevPixels(localPoint); -} - -- (LayoutDeviceIntPoint)convertWindowCoordinatesRoundDown:(NSPoint)aPoint -{ - if (!mGeckoChild) { - return LayoutDeviceIntPoint(0, 0); - } - - NSPoint localPoint = [self convertPoint:aPoint fromView:nil]; - return mGeckoChild->CocoaPointsToDevPixelsRoundDown(localPoint); -} - -// This is a utility function used by NSView drag event methods -// to send events. It contains all of the logic needed for Gecko -// dragging to work. Returns the appropriate cocoa drag operation code. -- (NSDragOperation)doDragAction:(EventMessage)aMessage sender:(id)aSender -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - if (!mGeckoChild) - return NSDragOperationNone; - - MOZ_LOG(sCocoaLog, LogLevel::Info, ("ChildView doDragAction: entered\n")); - - if (!mDragService) { - CallGetService(kDragServiceContractID, &mDragService); - NS_ASSERTION(mDragService, "Couldn't get a drag service - big problem!"); - if (!mDragService) - return NSDragOperationNone; - } - - if (aMessage == eDragEnter) { - mDragService->StartDragSession(); - } - - nsCOMPtr dragSession; - mDragService->GetCurrentSession(getter_AddRefs(dragSession)); - if (dragSession) { - if (aMessage == eDragOver) { - // fire the drag event at the source. Just ignore whether it was - // cancelled or not as there isn't actually a means to stop the drag - mDragService->FireDragEventAtSource(eDrag); - dragSession->SetCanDrop(false); - } else if (aMessage == eDrop) { - // We make the assumption that the dragOver handlers have correctly set - // the |canDrop| property of the Drag Session. - bool canDrop = false; - if (!NS_SUCCEEDED(dragSession->GetCanDrop(&canDrop)) || !canDrop) { - [self doDragAction:eDragExit sender:aSender]; - - nsCOMPtr sourceNode; - dragSession->GetSourceNode(getter_AddRefs(sourceNode)); - if (!sourceNode) { - mDragService->EndDragSession(false); - } - return NSDragOperationNone; - } - } - - unsigned int modifierFlags = [[NSApp currentEvent] modifierFlags]; - uint32_t action = nsIDragService::DRAGDROP_ACTION_MOVE; - // force copy = option, alias = cmd-option, default is move - if (modifierFlags & NSAlternateKeyMask) { - if (modifierFlags & NSCommandKeyMask) - action = nsIDragService::DRAGDROP_ACTION_LINK; - else - action = nsIDragService::DRAGDROP_ACTION_COPY; - } - dragSession->SetDragAction(action); - } - - // set up gecko event - WidgetDragEvent geckoEvent(true, aMessage, mGeckoChild); - nsCocoaUtils::InitInputEvent(geckoEvent, [NSApp currentEvent]); - - // Use our own coordinates in the gecko event. - // Convert event from gecko global coords to gecko view coords. - NSPoint draggingLoc = [aSender draggingLocation]; - - geckoEvent.mRefPoint = [self convertWindowCoordinates:draggingLoc]; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - mGeckoChild->DispatchInputEvent(&geckoEvent); - if (!mGeckoChild) - return NSDragOperationNone; - - if (dragSession) { - switch (aMessage) { - case eDragEnter: - case eDragOver: { - uint32_t dragAction; - dragSession->GetDragAction(&dragAction); - - // If TakeChildProcessDragAction returns something other than - // DRAGDROP_ACTION_UNINITIALIZED, it means that the last event was sent - // to the child process and this event is also being sent to the child - // process. In this case, use the last event's action instead. - nsDragService* dragService = static_cast(mDragService); - int32_t childDragAction = dragService->TakeChildProcessDragAction(); - if (childDragAction != nsIDragService::DRAGDROP_ACTION_UNINITIALIZED) { - dragAction = childDragAction; - } - - return [self dragOperationFromDragAction:dragAction]; - } - case eDragExit: - case eDrop: { - nsCOMPtr sourceNode; - dragSession->GetSourceNode(getter_AddRefs(sourceNode)); - if (!sourceNode) { - // We're leaving a window while doing a drag that was - // initiated in a different app. End the drag session, - // since we're done with it for now (until the user - // drags back into mozilla). - mDragService->EndDragSession(false); - } - } - default: - break; - } - } - - return NSDragOperationGeneric; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSDragOperationNone); -} - -- (NSDragOperation)draggingEntered:(id )sender -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - MOZ_LOG(sCocoaLog, LogLevel::Info, ("ChildView draggingEntered: entered\n")); - - // there should never be a globalDragPboard when "draggingEntered:" is - // called, but just in case we'll take care of it here. - [globalDragPboard release]; - - // Set the global drag pasteboard that will be used for this drag session. - // This will be set back to nil when the drag session ends (mouse exits - // the view or a drop happens within the view). - globalDragPboard = [[sender draggingPasteboard] retain]; - - return [self doDragAction:eDragEnter sender:sender]; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSDragOperationNone); -} - -- (NSDragOperation)draggingUpdated:(id )sender -{ - MOZ_LOG(sCocoaLog, LogLevel::Info, ("ChildView draggingUpdated: entered\n")); - - return [self doDragAction:eDragOver sender:sender]; -} - -- (void)draggingExited:(id )sender -{ - MOZ_LOG(sCocoaLog, LogLevel::Info, ("ChildView draggingExited: entered\n")); - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - [self doDragAction:eDragExit sender:sender]; - NS_IF_RELEASE(mDragService); -} - -- (BOOL)performDragOperation:(id )sender -{ - nsAutoRetainCocoaObject kungFuDeathGrip(self); - BOOL handled = [self doDragAction:eDrop sender:sender] != NSDragOperationNone; - NS_IF_RELEASE(mDragService); - return handled; -} - -// NSDraggingSource -- (void)draggedImage:(NSImage *)anImage movedTo:(NSPoint)aPoint -{ - // Get the drag service if it isn't already cached. The drag service - // isn't cached when dragging over a different application. - nsCOMPtr dragService = mDragService; - if (!dragService) { - dragService = do_GetService(kDragServiceContractID); - } - - if (dragService) { - NSPoint pnt = [NSEvent mouseLocation]; - FlipCocoaScreenCoordinate(pnt); - - LayoutDeviceIntPoint devPoint = mGeckoChild->CocoaPointsToDevPixels(pnt); - dragService->DragMoved(devPoint.x, devPoint.y); - } -} - -// NSDraggingSource -- (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - gDraggedTransferables = nullptr; - - NSEvent *currentEvent = [NSApp currentEvent]; - gUserCancelledDrag = ([currentEvent type] == NSKeyDown && - [currentEvent keyCode] == kVK_Escape); - - if (!mDragService) { - CallGetService(kDragServiceContractID, &mDragService); - NS_ASSERTION(mDragService, "Couldn't get a drag service - big problem!"); - } - - if (mDragService) { - // set the dragend point from the current mouse location - nsDragService* dragService = static_cast(mDragService); - NSPoint pnt = [NSEvent mouseLocation]; - FlipCocoaScreenCoordinate(pnt); - dragService->SetDragEndPoint(gfx::IntPoint::Round(pnt.x, pnt.y)); - - // XXX: dropEffect should be updated per |operation|. - // As things stand though, |operation| isn't well handled within "our" - // events, that is, when the drop happens within the window: it is set - // either to NSDragOperationGeneric or to NSDragOperationNone. - // For that reason, it's not yet possible to override dropEffect per the - // given OS value, and it's also unclear what's the correct dropEffect - // value for NSDragOperationGeneric that is passed by other applications. - // All that said, NSDragOperationNone is still reliable. - if (operation == NSDragOperationNone) { - nsCOMPtr dataTransfer; - dragService->GetDataTransfer(getter_AddRefs(dataTransfer)); - if (dataTransfer) - dataTransfer->SetDropEffectInt(nsIDragService::DRAGDROP_ACTION_NONE); - } - - mDragService->EndDragSession(true); - NS_RELEASE(mDragService); - } - - [globalDragPboard release]; - globalDragPboard = nil; - [gLastDragMouseDownEvent release]; - gLastDragMouseDownEvent = nil; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// NSDraggingSource -// this is just implemented so we comply with the NSDraggingSource informal protocol -- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal -{ - return UINT_MAX; -} - -// This method is a callback typically invoked in response to a drag ending on the desktop -// or a Findow folder window; the argument passed is a path to the drop location, to be used -// in constructing a complete pathname for the file(s) we want to create as a result of -// the drag. -- (NSArray *)namesOfPromisedFilesDroppedAtDestination:(NSURL*)dropDestination -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - nsresult rv; - - MOZ_LOG(sCocoaLog, LogLevel::Info, ("ChildView namesOfPromisedFilesDroppedAtDestination: entering callback for promised files\n")); - - nsCOMPtr targFile; - NS_NewLocalFile(EmptyString(), true, getter_AddRefs(targFile)); - nsCOMPtr macLocalFile = do_QueryInterface(targFile); - if (!macLocalFile) { - NS_ERROR("No Mac local file"); - return nil; - } - - if (!NS_SUCCEEDED(macLocalFile->InitWithCFURL((CFURLRef)dropDestination))) { - NS_ERROR("failed InitWithCFURL"); - return nil; - } - - if (!gDraggedTransferables) - return nil; - - uint32_t transferableCount; - rv = gDraggedTransferables->GetLength(&transferableCount); - if (NS_FAILED(rv)) - return nil; - - for (uint32_t i = 0; i < transferableCount; i++) { - nsCOMPtr item = do_QueryElementAt(gDraggedTransferables, i); - if (!item) { - NS_ERROR("no transferable"); - return nil; - } - - item->SetTransferData(kFilePromiseDirectoryMime, macLocalFile, sizeof(nsIFile*)); - - // now request the kFilePromiseMime data, which will invoke the data provider - // If successful, the returned data is a reference to the resulting file. - nsCOMPtr fileDataPrimitive; - uint32_t dataSize = 0; - item->GetTransferData(kFilePromiseMime, getter_AddRefs(fileDataPrimitive), &dataSize); - } - - NSPasteboard* generalPboard = [NSPasteboard pasteboardWithName:NSDragPboard]; - NSData* data = [generalPboard dataForType:@"application/x-moz-file-promise-dest-filename"]; - NSString* name = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; - NSArray* rslt = [NSArray arrayWithObject:name]; - - [name release]; - - return rslt; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -#pragma mark - - -// Support for the "Services" menu. We currently only support sending strings -// and HTML to system services. - -- (id)validRequestorForSendType:(NSString *)sendType - returnType:(NSString *)returnType -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - // sendType contains the type of data that the service would like this - // application to send to it. sendType is nil if the service is not - // requesting any data. - // - // returnType contains the type of data the the service would like to - // return to this application (e.g., to overwrite the selection). - // returnType is nil if the service will not return any data. - // - // The following condition thus triggers when the service expects a string - // or HTML from us or no data at all AND when the service will either not - // send back any data to us or will send a string or HTML back to us. - -#define IsSupportedType(typeStr) ([typeStr isEqual:NSStringPboardType] || [typeStr isEqual:NSHTMLPboardType]) - - id result = nil; - - if ((!sendType || IsSupportedType(sendType)) && - (!returnType || IsSupportedType(returnType))) { - if (mGeckoChild) { - // Assume that this object will be able to handle this request. - result = self; - - // Keep the ChildView alive during this operation. - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - if (sendType) { - // Determine if there is a current selection (chrome/content). - if (!nsClipboard::sSelectionCache) { - result = nil; - } - } - - // Determine if we can paste (if receiving data from the service). - if (mGeckoChild && returnType) { - WidgetContentCommandEvent command(true, - eContentCommandPasteTransferable, - mGeckoChild, true); - // This might possibly destroy our widget (and null out mGeckoChild). - mGeckoChild->DispatchWindowEvent(command); - if (!mGeckoChild || !command.mSucceeded || !command.mIsEnabled) - result = nil; - } - } - } - -#undef IsSupportedType - - // Give the superclass a chance if this object will not handle this request. - if (!result) - result = [super validRequestorForSendType:sendType returnType:returnType]; - - return result; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard - types:(NSArray *)types -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - // Make sure that the service will accept strings or HTML. - if ([types containsObject:NSStringPboardType] == NO && - [types containsObject:NSHTMLPboardType] == NO) - return NO; - - // Bail out if there is no Gecko object. - if (!mGeckoChild) - return NO; - - // Transform the transferable to an NSDictionary. - NSDictionary* pasteboardOutputDict = nullptr; - - pasteboardOutputDict = nsClipboard:: - PasteboardDictFromTransferable(nsClipboard::sSelectionCache); - - if (!pasteboardOutputDict) - return NO; - - // Declare the pasteboard types. - unsigned int typeCount = [pasteboardOutputDict count]; - NSMutableArray* declaredTypes = [NSMutableArray arrayWithCapacity:typeCount]; - [declaredTypes addObjectsFromArray:[pasteboardOutputDict allKeys]]; - [pboard declareTypes:declaredTypes owner:nil]; - - // Write the data to the pasteboard. - for (unsigned int i = 0; i < typeCount; i++) { - NSString* currentKey = [declaredTypes objectAtIndex:i]; - id currentValue = [pasteboardOutputDict valueForKey:currentKey]; - - if (currentKey == NSStringPboardType || - currentKey == kCorePboardType_url || - currentKey == kCorePboardType_urld || - currentKey == kCorePboardType_urln) { - [pboard setString:currentValue forType:currentKey]; - } else if (currentKey == NSHTMLPboardType) { - [pboard setString:(nsClipboard::WrapHtmlForSystemPasteboard(currentValue)) forType:currentKey]; - } else if (currentKey == NSTIFFPboardType) { - [pboard setData:currentValue forType:currentKey]; - } else if (currentKey == NSFilesPromisePboardType) { - [pboard setPropertyList:currentValue forType:currentKey]; - } - } - - return YES; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO); -} - -// Called if the service wants us to replace the current selection. -- (BOOL)readSelectionFromPasteboard:(NSPasteboard *)pboard -{ - nsresult rv; - nsCOMPtr trans = do_CreateInstance("@mozilla.org/widget/transferable;1", &rv); - if (NS_FAILED(rv)) - return NO; - trans->Init(nullptr); - - trans->AddDataFlavor(kUnicodeMime); - trans->AddDataFlavor(kHTMLMime); - - rv = nsClipboard::TransferableFromPasteboard(trans, pboard); - if (NS_FAILED(rv)) - return NO; - - NS_ENSURE_TRUE(mGeckoChild, false); - - WidgetContentCommandEvent command(true, - eContentCommandPasteTransferable, - mGeckoChild); - command.mTransferable = trans; - mGeckoChild->DispatchWindowEvent(command); - - return command.mSucceeded && command.mIsEnabled; -} - -NS_IMETHODIMP -nsChildView::GetSelectionAsPlaintext(nsAString& aResult) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (!nsClipboard::sSelectionCache) { - MOZ_ASSERT(aResult.IsEmpty()); - return NS_OK; - } - - // Get the current chrome or content selection. - NSDictionary* pasteboardOutputDict = nullptr; - pasteboardOutputDict = nsClipboard:: - PasteboardDictFromTransferable(nsClipboard::sSelectionCache); - - if (NS_WARN_IF(!pasteboardOutputDict)) { - return NS_ERROR_FAILURE; - } - - // Declare the pasteboard types. - unsigned int typeCount = [pasteboardOutputDict count]; - NSMutableArray* declaredTypes = [NSMutableArray arrayWithCapacity:typeCount]; - [declaredTypes addObjectsFromArray:[pasteboardOutputDict allKeys]]; - NSString* currentKey = [declaredTypes objectAtIndex:0]; - NSString* currentValue = [pasteboardOutputDict valueForKey:currentKey]; - const char* textSelection = [currentValue UTF8String]; - aResult = NS_ConvertUTF8toUTF16(textSelection); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -#pragma mark - - -#ifdef ACCESSIBILITY - -/* Every ChildView has a corresponding mozDocAccessible object that is doing all - the heavy lifting. The topmost ChildView corresponds to a mozRootAccessible - object. - - All ChildView needs to do is to route all accessibility calls (from the NSAccessibility APIs) - down to its object, pretending that they are the same. -*/ -- (id)accessible -{ - if (!mGeckoChild) - return nil; - - id nativeAccessible = nil; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - RefPtr geckoChild(mGeckoChild); - RefPtr accessible = geckoChild->GetDocumentAccessible(); - if (!accessible) - return nil; - - accessible->GetNativeInterface((void**)&nativeAccessible); - -#ifdef DEBUG_hakan - NSAssert(![nativeAccessible isExpired], @"native acc is expired!!!"); -#endif - - return nativeAccessible; -} - -/* Implementation of formal mozAccessible formal protocol (enabling mozViews - to talk to mozAccessible objects in the accessibility module). */ - -- (BOOL)hasRepresentedView -{ - return YES; -} - -- (id)representedView -{ - return self; -} - -- (BOOL)isRoot -{ - return [[self accessible] isRoot]; -} - -#ifdef DEBUG -- (void)printHierarchy -{ - [[self accessible] printHierarchy]; -} -#endif - -#pragma mark - - -// general - -- (BOOL)accessibilityIsIgnored -{ - if (!mozilla::a11y::ShouldA11yBeEnabled()) - return [super accessibilityIsIgnored]; - - return [[self accessible] accessibilityIsIgnored]; -} - -- (id)accessibilityHitTest:(NSPoint)point -{ - if (!mozilla::a11y::ShouldA11yBeEnabled()) - return [super accessibilityHitTest:point]; - - return [[self accessible] accessibilityHitTest:point]; -} - -- (id)accessibilityFocusedUIElement -{ - if (!mozilla::a11y::ShouldA11yBeEnabled()) - return [super accessibilityFocusedUIElement]; - - return [[self accessible] accessibilityFocusedUIElement]; -} - -// actions - -- (NSArray*)accessibilityActionNames -{ - if (!mozilla::a11y::ShouldA11yBeEnabled()) - return [super accessibilityActionNames]; - - return [[self accessible] accessibilityActionNames]; -} - -- (NSString*)accessibilityActionDescription:(NSString*)action -{ - if (!mozilla::a11y::ShouldA11yBeEnabled()) - return [super accessibilityActionDescription:action]; - - return [[self accessible] accessibilityActionDescription:action]; -} - -- (void)accessibilityPerformAction:(NSString*)action -{ - if (!mozilla::a11y::ShouldA11yBeEnabled()) - return [super accessibilityPerformAction:action]; - - return [[self accessible] accessibilityPerformAction:action]; -} - -// attributes - -- (NSArray*)accessibilityAttributeNames -{ - if (!mozilla::a11y::ShouldA11yBeEnabled()) - return [super accessibilityAttributeNames]; - - return [[self accessible] accessibilityAttributeNames]; -} - -- (BOOL)accessibilityIsAttributeSettable:(NSString*)attribute -{ - if (!mozilla::a11y::ShouldA11yBeEnabled()) - return [super accessibilityIsAttributeSettable:attribute]; - - return [[self accessible] accessibilityIsAttributeSettable:attribute]; -} - -- (id)accessibilityAttributeValue:(NSString*)attribute -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - if (!mozilla::a11y::ShouldA11yBeEnabled()) - return [super accessibilityAttributeValue:attribute]; - - id accessible = [self accessible]; - - // if we're the root (topmost) accessible, we need to return our native AXParent as we - // traverse outside to the hierarchy of whoever embeds us. thus, fall back on NSView's - // default implementation for this attribute. - if ([attribute isEqualToString:NSAccessibilityParentAttribute] && [accessible isRoot]) { - id parentAccessible = [super accessibilityAttributeValue:attribute]; - return parentAccessible; - } - - return [accessible accessibilityAttributeValue:attribute]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -#endif /* ACCESSIBILITY */ - -@end - -@implementation PixelHostingView - -- (BOOL)isFlipped { - return YES; -} - -- (NSView*)hitTest:(NSPoint)aPoint { - return nil; -} - -- (void)drawRect:(NSRect)aRect { - [(ChildView*)[self superview] doDrawRect:aRect]; -} - -- (BOOL)wantsBestResolutionOpenGLSurface { - return nsCocoaUtils::HiDPIEnabled() ? YES : NO; -} - -@end - -#pragma mark - - -void -ChildViewMouseTracker::OnDestroyView(ChildView* aView) -{ - if (sLastMouseEventView == aView) { - sLastMouseEventView = nil; - [sLastMouseMoveEvent release]; - sLastMouseMoveEvent = nil; - } -} - -void -ChildViewMouseTracker::OnDestroyWindow(NSWindow* aWindow) -{ - if (sWindowUnderMouse == aWindow) { - sWindowUnderMouse = nil; - } -} - -void -ChildViewMouseTracker::MouseEnteredWindow(NSEvent* aEvent) -{ - sWindowUnderMouse = [aEvent window]; - ReEvaluateMouseEnterState(aEvent); -} - -void -ChildViewMouseTracker::MouseExitedWindow(NSEvent* aEvent) -{ - if (sWindowUnderMouse == [aEvent window]) { - sWindowUnderMouse = nil; - ReEvaluateMouseEnterState(aEvent); - } -} - -void -ChildViewMouseTracker::ReEvaluateMouseEnterState(NSEvent* aEvent, ChildView* aOldView) -{ - ChildView* oldView = aOldView ? aOldView : sLastMouseEventView; - sLastMouseEventView = ViewForEvent(aEvent); - if (sLastMouseEventView != oldView) { - // Send enter and / or exit events. - WidgetMouseEvent::ExitFrom exitFrom = - [sLastMouseEventView window] == [oldView window] ? - WidgetMouseEvent::eChild : WidgetMouseEvent::eTopLevel; - [oldView sendMouseEnterOrExitEvent:aEvent - enter:NO - exitFrom:exitFrom]; - // After the cursor exits the window set it to a visible regular arrow cursor. - if (exitFrom == WidgetMouseEvent::eTopLevel) { - [[nsCursorManager sharedInstance] setCursor:eCursor_standard]; - } - [sLastMouseEventView sendMouseEnterOrExitEvent:aEvent - enter:YES - exitFrom:exitFrom]; - } -} - -void -ChildViewMouseTracker::ResendLastMouseMoveEvent() -{ - if (sLastMouseMoveEvent) { - MouseMoved(sLastMouseMoveEvent); - } -} - -void -ChildViewMouseTracker::MouseMoved(NSEvent* aEvent) -{ - MouseEnteredWindow(aEvent); - [sLastMouseEventView handleMouseMoved:aEvent]; - if (sLastMouseMoveEvent != aEvent) { - [sLastMouseMoveEvent release]; - sLastMouseMoveEvent = [aEvent retain]; - } -} - -void -ChildViewMouseTracker::MouseScrolled(NSEvent* aEvent) -{ - if (!nsCocoaUtils::IsMomentumScrollEvent(aEvent)) { - // Store the position so we can pin future momentum scroll events. - sLastScrollEventScreenLocation = nsCocoaUtils::ScreenLocationForEvent(aEvent); - } -} - -ChildView* -ChildViewMouseTracker::ViewForEvent(NSEvent* aEvent) -{ - NSWindow* window = sWindowUnderMouse; - if (!window) - return nil; - - NSPoint windowEventLocation = nsCocoaUtils::EventLocationForWindow(aEvent, window); - NSView* view = [[[window contentView] superview] hitTest:windowEventLocation]; - - if (![view isKindOfClass:[ChildView class]]) - return nil; - - ChildView* childView = (ChildView*)view; - // If childView is being destroyed return nil. - if (![childView widget]) - return nil; - return WindowAcceptsEvent(window, aEvent, childView) ? childView : nil; -} - -BOOL -ChildViewMouseTracker::WindowAcceptsEvent(NSWindow* aWindow, NSEvent* aEvent, - ChildView* aView, BOOL aIsClickThrough) -{ - // Right mouse down events may get through to all windows, even to a top level - // window with an open sheet. - if (!aWindow || [aEvent type] == NSRightMouseDown) - return YES; - - id delegate = [aWindow delegate]; - if (!delegate || ![delegate isKindOfClass:[WindowDelegate class]]) - return YES; - - nsIWidget *windowWidget = [(WindowDelegate *)delegate geckoWidget]; - if (!windowWidget) - return YES; - - NSWindow* topLevelWindow = nil; - - switch (windowWidget->WindowType()) { - case eWindowType_popup: - // If this is a context menu, it won't have a parent. So we'll always - // accept mouse move events on context menus even when none of our windows - // is active, which is the right thing to do. - // For panels, the parent window is the XUL window that owns the panel. - return WindowAcceptsEvent([aWindow parentWindow], aEvent, aView, aIsClickThrough); - - case eWindowType_toplevel: - case eWindowType_dialog: - if ([aWindow attachedSheet]) - return NO; - - topLevelWindow = aWindow; - break; - case eWindowType_sheet: { - nsIWidget* parentWidget = windowWidget->GetSheetWindowParent(); - if (!parentWidget) - return YES; - - topLevelWindow = (NSWindow*)parentWidget->GetNativeData(NS_NATIVE_WINDOW); - break; - } - - default: - return YES; - } - - if (!topLevelWindow || - ([topLevelWindow isMainWindow] && !aIsClickThrough) || - [aEvent type] == NSOtherMouseDown || - (([aEvent modifierFlags] & NSCommandKeyMask) != 0 && - [aEvent type] != NSMouseMoved)) - return YES; - - // If we're here then we're dealing with a left click or mouse move on an - // inactive window or something similar. Ask Gecko what to do. - return [aView inactiveWindowAcceptsMouseEvent:aEvent]; -} - -#pragma mark - - -@interface NSView (MethodSwizzling) -- (BOOL)nsChildView_NSView_mouseDownCanMoveWindow; -@end - -@implementation NSView (MethodSwizzling) - -// All top-level browser windows belong to the ToolbarWindow class and have -// NSTexturedBackgroundWindowMask turned on in their "style" (see particularly -// [ToolbarWindow initWithContentRect:...] in nsCocoaWindow.mm). This style -// normally means the window "may be moved by clicking and dragging anywhere -// in the window background", but we've suppressed this by giving the -// ChildView class a mouseDownCanMoveWindow method that always returns NO. -// Normally a ToolbarWindow's contentView (not a ChildView) returns YES when -// NSTexturedBackgroundWindowMask is turned on. But normally this makes no -// difference. However, under some (probably very unusual) circumstances -// (and only on Leopard) it *does* make a difference -- for example it -// triggers bmo bugs 431902 and 476393. So here we make sure that a -// ToolbarWindow's contentView always returns NO from the -// mouseDownCanMoveWindow method. -- (BOOL)nsChildView_NSView_mouseDownCanMoveWindow -{ - NSWindow *ourWindow = [self window]; - NSView *contentView = [ourWindow contentView]; - if ([ourWindow isKindOfClass:[ToolbarWindow class]] && (self == contentView)) - return [ourWindow isMovableByWindowBackground]; - return [self nsChildView_NSView_mouseDownCanMoveWindow]; -} - -@end diff --git a/widget/cocoa/nsClipboard.h b/widget/cocoa/nsClipboard.h deleted file mode 100644 index 45871efe10..0000000000 --- a/widget/cocoa/nsClipboard.h +++ /dev/null @@ -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 - -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 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 mClipboardOwner; - nsCOMPtr mTransferable; -}; - -#endif // nsClipboard_h_ diff --git a/widget/cocoa/nsClipboard.mm b/widget/cocoa/nsClipboard.mm deleted file mode 100644 index 4146f17851..0000000000 --- a/widget/cocoa/nsClipboard.mm +++ /dev/null @@ -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 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 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 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 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 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 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 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 currentFlavor = do_QueryElementAt(flavorList, i); - if (!currentFlavor) - continue; - - nsXPIDLCString flavorStr; - currentFlavor->ToString(getter_Copies(flavorStr)); - - nsCOMPtr 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 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 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 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 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 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 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 transferSupports; - aTransferable->GetTransferData(flavorStr, getter_AddRefs(transferSupports), &dataSize); - nsCOMPtr ptrPrimitive(do_QueryInterface(transferSupports)); - if (!ptrPrimitive) - continue; - - nsCOMPtr primitiveData; - ptrPrimitive->GetData(getter_AddRefs(primitiveData)); - - nsCOMPtr image(do_QueryInterface(primitiveData)); - if (!image) { - NS_WARNING("Image isn't an imgIContainer in transferable"); - continue; - } - - RefPtr 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 genericFile; - rv = aTransferable->GetTransferData(flavorStr, getter_AddRefs(genericFile), &len); - if (NS_FAILED(rv)) { - continue; - } - - nsCOMPtr file(do_QueryInterface(genericFile)); - if (!file) { - nsCOMPtr 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 genericURL; - rv = aTransferable->GetTransferData(flavorStr, getter_AddRefs(genericURL), &len); - nsCOMPtr 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(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: - @"" - "" - "" - "" - "" - "%@" - "" - "", 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; -} diff --git a/widget/cocoa/nsCocoaDebugUtils.h b/widget/cocoa/nsCocoaDebugUtils.h deleted file mode 100644 index 814f060878..0000000000 --- a/widget/cocoa/nsCocoaDebugUtils.h +++ /dev/null @@ -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 - -// 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_ diff --git a/widget/cocoa/nsCocoaDebugUtils.mm b/widget/cocoa/nsCocoaDebugUtils.mm deleted file mode 100644 index 35896dc401..0000000000 --- a/widget/cocoa/nsCocoaDebugUtils.mm +++ /dev/null @@ -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 -#include -#include -#include -#include -#include - -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(¤tTime, 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); - } -} diff --git a/widget/cocoa/nsCocoaFeatures.h b/widget/cocoa/nsCocoaFeatures.h deleted file mode 100644 index a9cab95d56..0000000000 --- a/widget/cocoa/nsCocoaFeatures.h +++ /dev/null @@ -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 - -/// 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_ diff --git a/widget/cocoa/nsCocoaFeatures.mm b/widget/cocoa/nsCocoaFeatures.mm deleted file mode 100644 index e0fafb7d96..0000000000 --- a/widget/cocoa/nsCocoaFeatures.mm +++ /dev/null @@ -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 - -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); -} diff --git a/widget/cocoa/nsCocoaUtils.h b/widget/cocoa/nsCocoaUtils.h deleted file mode 100644 index 139e76b4ad..0000000000 --- a/widget/cocoa/nsCocoaUtils.h +++ /dev/null @@ -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 - -#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* mCommands; -} - -- (void)startRecording:(nsTArray&)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 CGImageRef from a frame contained in an imgIContainer. - Copies the pixel data from the indicated frame of the imgIContainer into a new CGImageRef. - The caller owns the CGImageRef. - @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 NSImage from a CGImageRef. - Copies the pixel data from the CGImageRef into a new NSImage. - The caller owns the NSImage. - @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 NSImage from a frame of an imgIContainer. - Combines the two methods above. The caller owns the NSImage. - @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& 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& aFontRanges, - const bool aIsVertical, - const CGFloat aBackingScaleFactor); -}; - -#endif // nsCocoaUtils_h_ diff --git a/widget/cocoa/nsCocoaUtils.mm b/widget/cocoa/nsCocoaUtils.mm deleted file mode 100644 index 3138245aa7..0000000000 --- a/widget/cocoa/nsCocoaUtils.mm +++ /dev/null @@ -1,1022 +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 - -#include "gfx2DGlue.h" -#include "gfxPlatform.h" -#include "gfxUtils.h" -#include "ImageRegion.h" -#include "nsCocoaUtils.h" -#include "nsChildView.h" -#include "nsMenuBarX.h" -#include "nsCocoaWindow.h" -#include "nsCOMPtr.h" -#include "nsIInterfaceRequestorUtils.h" -#include "nsIAppShellService.h" -#include "nsIXULWindow.h" -#include "nsIBaseWindow.h" -#include "nsIServiceManager.h" -#include "nsMenuUtilsX.h" -#include "nsToolkit.h" -#include "nsCRT.h" -#include "SVGImageContext.h" -#include "mozilla/gfx/2D.h" -#include "mozilla/MiscEvents.h" -#include "mozilla/Preferences.h" -#include "mozilla/TextEvents.h" - -using namespace mozilla; -using namespace mozilla::widget; - -using mozilla::gfx::BackendType; -using mozilla::gfx::DataSourceSurface; -using mozilla::gfx::DrawTarget; -using mozilla::gfx::Factory; -using mozilla::gfx::SamplingFilter; -using mozilla::gfx::IntPoint; -using mozilla::gfx::IntRect; -using mozilla::gfx::IntSize; -using mozilla::gfx::SurfaceFormat; -using mozilla::gfx::SourceSurface; -using mozilla::image::ImageRegion; -using std::ceil; - -static float -MenuBarScreenHeight() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - NSArray* allScreens = [NSScreen screens]; - if ([allScreens count]) { - return [[allScreens objectAtIndex:0] frame].size.height; - } - - return 0.0; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0.0); -} - -float -nsCocoaUtils::FlippedScreenY(float y) -{ - return MenuBarScreenHeight() - y; -} - -NSRect nsCocoaUtils::GeckoRectToCocoaRect(const DesktopIntRect &geckoRect) -{ - // We only need to change the Y coordinate by starting with the primary screen - // height and subtracting the gecko Y coordinate of the bottom of the rect. - return NSMakeRect(geckoRect.x, - MenuBarScreenHeight() - geckoRect.YMost(), - geckoRect.width, - geckoRect.height); -} - -NSRect -nsCocoaUtils::GeckoRectToCocoaRectDevPix(const LayoutDeviceIntRect &aGeckoRect, - CGFloat aBackingScale) -{ - return NSMakeRect(aGeckoRect.x / aBackingScale, - MenuBarScreenHeight() - aGeckoRect.YMost() / aBackingScale, - aGeckoRect.width / aBackingScale, - aGeckoRect.height / aBackingScale); -} - -DesktopIntRect nsCocoaUtils::CocoaRectToGeckoRect(const NSRect &cocoaRect) -{ - // We only need to change the Y coordinate by starting with the primary screen - // height and subtracting both the cocoa y origin and the height of the - // cocoa rect. - DesktopIntRect rect; - rect.x = NSToIntRound(cocoaRect.origin.x); - rect.y = NSToIntRound(FlippedScreenY(cocoaRect.origin.y + cocoaRect.size.height)); - rect.width = NSToIntRound(cocoaRect.origin.x + cocoaRect.size.width) - rect.x; - rect.height = NSToIntRound(FlippedScreenY(cocoaRect.origin.y)) - rect.y; - return rect; -} - -LayoutDeviceIntRect nsCocoaUtils::CocoaRectToGeckoRectDevPix( - const NSRect& aCocoaRect, CGFloat aBackingScale) -{ - LayoutDeviceIntRect rect; - rect.x = NSToIntRound(aCocoaRect.origin.x * aBackingScale); - rect.y = NSToIntRound(FlippedScreenY(aCocoaRect.origin.y + aCocoaRect.size.height) * aBackingScale); - rect.width = NSToIntRound((aCocoaRect.origin.x + aCocoaRect.size.width) * aBackingScale) - rect.x; - rect.height = NSToIntRound(FlippedScreenY(aCocoaRect.origin.y) * aBackingScale) - rect.y; - return rect; -} - -NSPoint nsCocoaUtils::ScreenLocationForEvent(NSEvent* anEvent) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - // Don't trust mouse locations of mouse move events, see bug 443178. - if (!anEvent || [anEvent type] == NSMouseMoved) - return [NSEvent mouseLocation]; - - // Pin momentum scroll events to the location of the last user-controlled - // scroll event. - if (IsMomentumScrollEvent(anEvent)) - return ChildViewMouseTracker::sLastScrollEventScreenLocation; - - return nsCocoaUtils::ConvertPointToScreen([anEvent window], [anEvent locationInWindow]); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSMakePoint(0.0, 0.0)); -} - -BOOL nsCocoaUtils::IsEventOverWindow(NSEvent* anEvent, NSWindow* aWindow) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - return NSPointInRect(ScreenLocationForEvent(anEvent), [aWindow frame]); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO); -} - -NSPoint nsCocoaUtils::EventLocationForWindow(NSEvent* anEvent, NSWindow* aWindow) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - return nsCocoaUtils::ConvertPointFromScreen(aWindow, ScreenLocationForEvent(anEvent)); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSMakePoint(0.0, 0.0)); -} - -@interface NSEvent (ScrollPhase) -// 10.5 and 10.6 -- (long long)_scrollPhase; -// 10.7 and above -- (NSEventPhase)phase; -- (NSEventPhase)momentumPhase; -@end - -NSEventPhase nsCocoaUtils::EventPhase(NSEvent* aEvent) -{ - if ([aEvent respondsToSelector:@selector(phase)]) { - return [aEvent phase]; - } - return NSEventPhaseNone; -} - -NSEventPhase nsCocoaUtils::EventMomentumPhase(NSEvent* aEvent) -{ - if ([aEvent respondsToSelector:@selector(momentumPhase)]) { - return [aEvent momentumPhase]; - } - if ([aEvent respondsToSelector:@selector(_scrollPhase)]) { - switch ([aEvent _scrollPhase]) { - case 1: return NSEventPhaseBegan; - case 2: return NSEventPhaseChanged; - case 3: return NSEventPhaseEnded; - default: return NSEventPhaseNone; - } - } - return NSEventPhaseNone; -} - -BOOL nsCocoaUtils::IsMomentumScrollEvent(NSEvent* aEvent) -{ - return [aEvent type] == NSScrollWheel && - EventMomentumPhase(aEvent) != NSEventPhaseNone; -} - -@interface NSEvent (HasPreciseScrollingDeltas) -// 10.7 and above -- (BOOL)hasPreciseScrollingDeltas; -// For 10.6 and below, see the comment in nsChildView.h about _eventRef -- (EventRef)_eventRef; -@end - -BOOL nsCocoaUtils::HasPreciseScrollingDeltas(NSEvent* aEvent) -{ - if ([aEvent respondsToSelector:@selector(hasPreciseScrollingDeltas)]) { - return [aEvent hasPreciseScrollingDeltas]; - } - - // For events that don't contain pixel scrolling information, the event - // kind of their underlaying carbon event is kEventMouseWheelMoved instead - // of kEventMouseScroll. - EventRef carbonEvent = [aEvent _eventRef]; - return carbonEvent && ::GetEventKind(carbonEvent) == kEventMouseScroll; -} - -@interface NSEvent (ScrollingDeltas) -// 10.6 and below -- (CGFloat)deviceDeltaX; -- (CGFloat)deviceDeltaY; -// 10.7 and above -- (CGFloat)scrollingDeltaX; -- (CGFloat)scrollingDeltaY; -@end - -void nsCocoaUtils::GetScrollingDeltas(NSEvent* aEvent, CGFloat* aOutDeltaX, CGFloat* aOutDeltaY) -{ - if ([aEvent respondsToSelector:@selector(scrollingDeltaX)]) { - *aOutDeltaX = [aEvent scrollingDeltaX]; - *aOutDeltaY = [aEvent scrollingDeltaY]; - return; - } - if ([aEvent respondsToSelector:@selector(deviceDeltaX)] && - HasPreciseScrollingDeltas(aEvent)) { - // Calling deviceDeltaX/Y on those events that do not contain pixel - // scrolling information triggers a Cocoa assertion and an - // Objective-C NSInternalInconsistencyException. - *aOutDeltaX = [aEvent deviceDeltaX]; - *aOutDeltaY = [aEvent deviceDeltaY]; - return; - } - - // This is only hit pre-10.7 when we are called on a scroll event that does - // not contain pixel scrolling information. - CGFloat lineDeltaPixels = 12; - *aOutDeltaX = [aEvent deltaX] * lineDeltaPixels; - *aOutDeltaY = [aEvent deltaY] * lineDeltaPixels; -} - -BOOL nsCocoaUtils::EventHasPhaseInformation(NSEvent* aEvent) -{ - if (![aEvent respondsToSelector:@selector(phase)]) { - return NO; - } - return EventPhase(aEvent) != NSEventPhaseNone || - EventMomentumPhase(aEvent) != NSEventPhaseNone; -} - -void nsCocoaUtils::HideOSChromeOnScreen(bool aShouldHide) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // Keep track of how many hiding requests have been made, so that they can - // be nested. - static int sHiddenCount = 0; - - sHiddenCount += aShouldHide ? 1 : -1; - NS_ASSERTION(sHiddenCount >= 0, "Unbalanced HideMenuAndDockForWindow calls"); - - NSApplicationPresentationOptions options = - sHiddenCount <= 0 ? NSApplicationPresentationDefault : - NSApplicationPresentationHideDock | NSApplicationPresentationHideMenuBar; - [NSApp setPresentationOptions:options]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -#define NS_APPSHELLSERVICE_CONTRACTID "@mozilla.org/appshell/appShellService;1" -nsIWidget* nsCocoaUtils::GetHiddenWindowWidget() -{ - nsCOMPtr appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID)); - if (!appShell) { - NS_WARNING("Couldn't get AppShellService in order to get hidden window ref"); - return nullptr; - } - - nsCOMPtr hiddenWindow; - appShell->GetHiddenWindow(getter_AddRefs(hiddenWindow)); - if (!hiddenWindow) { - // Don't warn, this happens during shutdown, bug 358607. - return nullptr; - } - - nsCOMPtr baseHiddenWindow; - baseHiddenWindow = do_GetInterface(hiddenWindow); - if (!baseHiddenWindow) { - NS_WARNING("Couldn't get nsIBaseWindow from hidden window (nsIXULWindow)"); - return nullptr; - } - - nsCOMPtr hiddenWindowWidget; - if (NS_FAILED(baseHiddenWindow->GetMainWidget(getter_AddRefs(hiddenWindowWidget)))) { - NS_WARNING("Couldn't get nsIWidget from hidden window (nsIBaseWindow)"); - return nullptr; - } - - return hiddenWindowWidget; -} - -void nsCocoaUtils::PrepareForNativeAppModalDialog() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // Don't do anything if this is embedding. We'll assume that if there is no hidden - // window we shouldn't do anything, and that should cover the embedding case. - nsMenuBarX* hiddenWindowMenuBar = nsMenuUtilsX::GetHiddenWindowMenuBar(); - if (!hiddenWindowMenuBar) - return; - - // First put up the hidden window menu bar so that app menu event handling is correct. - hiddenWindowMenuBar->Paint(); - - NSMenu* mainMenu = [NSApp mainMenu]; - NS_ASSERTION([mainMenu numberOfItems] > 0, "Main menu does not have any items, something is terribly wrong!"); - - // Create new menu bar for use with modal dialog - NSMenu* newMenuBar = [[NSMenu alloc] initWithTitle:@""]; - - // Swap in our app menu. Note that the event target is whatever window is up when - // the app modal dialog goes up. - NSMenuItem* firstMenuItem = [[mainMenu itemAtIndex:0] retain]; - [mainMenu removeItemAtIndex:0]; - [newMenuBar insertItem:firstMenuItem atIndex:0]; - [firstMenuItem release]; - - // Add standard edit menu - [newMenuBar addItem:nsMenuUtilsX::GetStandardEditMenuItem()]; - - // Show the new menu bar - [NSApp setMainMenu:newMenuBar]; - [newMenuBar release]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void nsCocoaUtils::CleanUpAfterNativeAppModalDialog() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // Don't do anything if this is embedding. We'll assume that if there is no hidden - // window we shouldn't do anything, and that should cover the embedding case. - nsMenuBarX* hiddenWindowMenuBar = nsMenuUtilsX::GetHiddenWindowMenuBar(); - if (!hiddenWindowMenuBar) - return; - - NSWindow* mainWindow = [NSApp mainWindow]; - if (!mainWindow) - hiddenWindowMenuBar->Paint(); - else - [WindowDelegate paintMenubarForWindow:mainWindow]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void data_ss_release_callback(void *aDataSourceSurface, - const void *data, - size_t size) -{ - if (aDataSourceSurface) { - static_cast(aDataSourceSurface)->Unmap(); - static_cast(aDataSourceSurface)->Release(); - } -} - -nsresult nsCocoaUtils::CreateCGImageFromSurface(SourceSurface* aSurface, - CGImageRef* aResult) -{ - RefPtr dataSurface; - - if (aSurface->GetFormat() == SurfaceFormat::B8G8R8A8) { - dataSurface = aSurface->GetDataSurface(); - } else { - // CGImageCreate only supports 16- and 32-bit bit-depth - // Convert format to SurfaceFormat::B8G8R8A8 - dataSurface = gfxUtils:: - CopySurfaceToDataSourceSurfaceWithFormat(aSurface, - SurfaceFormat::B8G8R8A8); - } - - NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE); - - int32_t width = dataSurface->GetSize().width; - int32_t height = dataSurface->GetSize().height; - if (height < 1 || width < 1) { - return NS_ERROR_FAILURE; - } - - DataSourceSurface::MappedSurface map; - if (!dataSurface->Map(DataSourceSurface::MapType::READ, &map)) { - return NS_ERROR_FAILURE; - } - // The Unmap() call happens in data_ss_release_callback - - // Create a CGImageRef with the bits from the image, taking into account - // the alpha ordering and endianness of the machine so we don't have to - // touch the bits ourselves. - CGDataProviderRef dataProvider = ::CGDataProviderCreateWithData(dataSurface.forget().take(), - map.mData, - map.mStride * height, - data_ss_release_callback); - CGColorSpaceRef colorSpace = ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - *aResult = ::CGImageCreate(width, - height, - 8, - 32, - map.mStride, - colorSpace, - kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst, - dataProvider, - NULL, - 0, - kCGRenderingIntentDefault); - ::CGColorSpaceRelease(colorSpace); - ::CGDataProviderRelease(dataProvider); - return *aResult ? NS_OK : NS_ERROR_FAILURE; -} - -nsresult nsCocoaUtils::CreateNSImageFromCGImage(CGImageRef aInputImage, NSImage **aResult) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - // Be very careful when creating the NSImage that the backing NSImageRep is - // exactly 1:1 with the input image. On a retina display, both [NSImage - // lockFocus] and [NSImage initWithCGImage:size:] will create an image with a - // 2x backing NSImageRep. This prevents NSCursor from recognizing a retina - // cursor, which only occurs if pixelsWide and pixelsHigh are exactly 2x the - // size of the NSImage. - // - // For example, if a 32x32 SVG cursor is rendered on a retina display, then - // aInputImage will be 64x64. The resulting NSImage will be scaled back down - // to 32x32 so it stays the correct size on the screen by changing its size - // (resizing a NSImage only scales the image and doesn't resample the data). - // If aInputImage is converted using [NSImage initWithCGImage:size:] then the - // bitmap will be 128x128 and NSCursor won't recognize a retina cursor, since - // it will expect a 64x64 bitmap. - - int32_t width = ::CGImageGetWidth(aInputImage); - int32_t height = ::CGImageGetHeight(aInputImage); - NSRect imageRect = ::NSMakeRect(0.0, 0.0, width, height); - - NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] - initWithBitmapDataPlanes:NULL - pixelsWide:width - pixelsHigh:height - bitsPerSample:8 - samplesPerPixel:4 - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSDeviceRGBColorSpace - bitmapFormat:NSAlphaFirstBitmapFormat - bytesPerRow:0 - bitsPerPixel:0]; - - NSGraphicsContext *context = [NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep]; - [NSGraphicsContext saveGraphicsState]; - [NSGraphicsContext setCurrentContext:context]; - - // Get the Quartz context and draw. - CGContextRef imageContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; - ::CGContextDrawImage(imageContext, *(CGRect*)&imageRect, aInputImage); - - [NSGraphicsContext restoreGraphicsState]; - - *aResult = [[NSImage alloc] initWithSize:NSMakeSize(width, height)]; - [*aResult addRepresentation:offscreenRep]; - [offscreenRep release]; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -nsresult nsCocoaUtils::CreateNSImageFromImageContainer(imgIContainer *aImage, uint32_t aWhichFrame, NSImage **aResult, CGFloat scaleFactor) -{ - RefPtr surface; - int32_t width = 0, height = 0; - aImage->GetWidth(&width); - aImage->GetHeight(&height); - - // Render a vector image at the correct resolution on a retina display - if (aImage->GetType() == imgIContainer::TYPE_VECTOR && scaleFactor != 1.0f) { - IntSize scaledSize = IntSize::Ceil(width * scaleFactor, height * scaleFactor); - - RefPtr drawTarget = gfxPlatform::GetPlatform()-> - CreateOffscreenContentDrawTarget(scaledSize, SurfaceFormat::B8G8R8A8); - if (!drawTarget || !drawTarget->IsValid()) { - NS_ERROR("Failed to create valid DrawTarget"); - return NS_ERROR_FAILURE; - } - - RefPtr context = gfxContext::CreateOrNull(drawTarget); - MOZ_ASSERT(context); - - mozilla::image::DrawResult res = - aImage->Draw(context, scaledSize, ImageRegion::Create(scaledSize), - aWhichFrame, SamplingFilter::POINT, - /* no SVGImageContext */ Nothing(), - imgIContainer::FLAG_SYNC_DECODE); - - if (res != mozilla::image::DrawResult::SUCCESS) { - return NS_ERROR_FAILURE; - } - - surface = drawTarget->Snapshot(); - } else { - surface = aImage->GetFrame(aWhichFrame, imgIContainer::FLAG_SYNC_DECODE); - } - - NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE); - - CGImageRef imageRef = NULL; - nsresult rv = nsCocoaUtils::CreateCGImageFromSurface(surface, &imageRef); - if (NS_FAILED(rv) || !imageRef) { - return NS_ERROR_FAILURE; - } - - rv = nsCocoaUtils::CreateNSImageFromCGImage(imageRef, aResult); - if (NS_FAILED(rv) || !aResult) { - return NS_ERROR_FAILURE; - } - ::CGImageRelease(imageRef); - - // Ensure the image will be rendered the correct size on a retina display - NSSize size = NSMakeSize(width, height); - [*aResult setSize:size]; - [[[*aResult representations] objectAtIndex:0] setSize:size]; - return NS_OK; -} - -// static -void -nsCocoaUtils::GetStringForNSString(const NSString *aSrc, nsAString& aDist) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!aSrc) { - aDist.Truncate(); - return; - } - - aDist.SetLength([aSrc length]); - [aSrc getCharacters: reinterpret_cast(aDist.BeginWriting())]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// static -NSString* -nsCocoaUtils::ToNSString(const nsAString& aString) -{ - if (aString.IsEmpty()) { - return [NSString string]; - } - return [NSString stringWithCharacters:reinterpret_cast(aString.BeginReading()) - length:aString.Length()]; -} - -// static -void -nsCocoaUtils::GeckoRectToNSRect(const nsIntRect& aGeckoRect, - NSRect& aOutCocoaRect) -{ - aOutCocoaRect.origin.x = aGeckoRect.x; - aOutCocoaRect.origin.y = aGeckoRect.y; - aOutCocoaRect.size.width = aGeckoRect.width; - aOutCocoaRect.size.height = aGeckoRect.height; -} - -// static -void -nsCocoaUtils::NSRectToGeckoRect(const NSRect& aCocoaRect, - nsIntRect& aOutGeckoRect) -{ - aOutGeckoRect.x = NSToIntRound(aCocoaRect.origin.x); - aOutGeckoRect.y = NSToIntRound(aCocoaRect.origin.y); - aOutGeckoRect.width = NSToIntRound(aCocoaRect.origin.x + aCocoaRect.size.width) - aOutGeckoRect.x; - aOutGeckoRect.height = NSToIntRound(aCocoaRect.origin.y + aCocoaRect.size.height) - aOutGeckoRect.y; -} - -// static -NSEvent* -nsCocoaUtils::MakeNewCocoaEventWithType(NSEventType aEventType, NSEvent *aEvent) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - NSEvent* newEvent = - [NSEvent keyEventWithType:aEventType - location:[aEvent locationInWindow] - modifierFlags:[aEvent modifierFlags] - timestamp:[aEvent timestamp] - windowNumber:[aEvent windowNumber] - context:[aEvent context] - characters:[aEvent characters] - charactersIgnoringModifiers:[aEvent charactersIgnoringModifiers] - isARepeat:[aEvent isARepeat] - keyCode:[aEvent keyCode]]; - return newEvent; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -// static -void -nsCocoaUtils::InitNPCocoaEvent(NPCocoaEvent* aNPCocoaEvent) -{ - memset(aNPCocoaEvent, 0, sizeof(NPCocoaEvent)); -} - -// static -void -nsCocoaUtils::InitInputEvent(WidgetInputEvent& aInputEvent, - NSEvent* aNativeEvent) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - aInputEvent.mModifiers = ModifiersForEvent(aNativeEvent); - aInputEvent.mTime = PR_IntervalNow(); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// static -Modifiers -nsCocoaUtils::ModifiersForEvent(NSEvent* aNativeEvent) -{ - NSUInteger modifiers = - aNativeEvent ? [aNativeEvent modifierFlags] : [NSEvent modifierFlags]; - Modifiers result = 0; - if (modifiers & NSShiftKeyMask) { - result |= MODIFIER_SHIFT; - } - if (modifiers & NSControlKeyMask) { - result |= MODIFIER_CONTROL; - } - if (modifiers & NSAlternateKeyMask) { - result |= MODIFIER_ALT; - // Mac's option key is similar to other platforms' AltGr key. - // Let's set AltGr flag when option key is pressed for consistency with - // other platforms. - result |= MODIFIER_ALTGRAPH; - } - if (modifiers & NSCommandKeyMask) { - result |= MODIFIER_META; - } - - if (modifiers & NSAlphaShiftKeyMask) { - result |= MODIFIER_CAPSLOCK; - } - // Mac doesn't have NumLock key. We can assume that NumLock is always locked - // if user is using a keyboard which has numpad. Otherwise, if user is using - // a keyboard which doesn't have numpad, e.g., MacBook's keyboard, we can - // assume that NumLock is always unlocked. - // Unfortunately, we cannot know whether current keyboard has numpad or not. - // We should notify locked state only when keys in numpad are pressed. - // By this, web applications may not be confused by unexpected numpad key's - // key event with unlocked state. - if (modifiers & NSNumericPadKeyMask) { - result |= MODIFIER_NUMLOCK; - } - - // Be aware, NSFunctionKeyMask is included when arrow keys, home key or some - // other keys are pressed. We cannot check whether 'fn' key is pressed or - // not by the flag. - - return result; -} - -// static -UInt32 -nsCocoaUtils::ConvertToCarbonModifier(NSUInteger aCocoaModifier) -{ - UInt32 carbonModifier = 0; - if (aCocoaModifier & NSAlphaShiftKeyMask) { - carbonModifier |= alphaLock; - } - if (aCocoaModifier & NSControlKeyMask) { - carbonModifier |= controlKey; - } - if (aCocoaModifier & NSAlternateKeyMask) { - carbonModifier |= optionKey; - } - if (aCocoaModifier & NSShiftKeyMask) { - carbonModifier |= shiftKey; - } - if (aCocoaModifier & NSCommandKeyMask) { - carbonModifier |= cmdKey; - } - if (aCocoaModifier & NSNumericPadKeyMask) { - carbonModifier |= kEventKeyModifierNumLockMask; - } - if (aCocoaModifier & NSFunctionKeyMask) { - carbonModifier |= kEventKeyModifierFnMask; - } - return carbonModifier; -} - -// While HiDPI support is not 100% complete and tested, we'll have a pref -// to allow it to be turned off in case of problems (or for testing purposes). - -// gfx.hidpi.enabled is an integer with the meaning: -// <= 0 : HiDPI support is disabled -// 1 : HiDPI enabled provided all screens have the same backing resolution -// > 1 : HiDPI enabled even if there are a mixture of screen modes - -// All the following code is to be removed once HiDPI work is more complete. - -static bool sHiDPIEnabled = false; -static bool sHiDPIPrefInitialized = false; - -// static -bool -nsCocoaUtils::HiDPIEnabled() -{ - if (!sHiDPIPrefInitialized) { - sHiDPIPrefInitialized = true; - - int prefSetting = Preferences::GetInt("gfx.hidpi.enabled", 1); - if (prefSetting <= 0) { - return false; - } - - // prefSetting is at least 1, need to check attached screens... - - int scaleFactors = 0; // used as a bitset to track the screen types found - NSEnumerator *screenEnum = [[NSScreen screens] objectEnumerator]; - while (NSScreen *screen = [screenEnum nextObject]) { - NSDictionary *desc = [screen deviceDescription]; - if ([desc objectForKey:NSDeviceIsScreen] == nil) { - continue; - } - CGFloat scale = - [screen respondsToSelector:@selector(backingScaleFactor)] ? - [screen backingScaleFactor] : 1.0; - // Currently, we only care about differentiating "1.0" and "2.0", - // so we set one of the two low bits to record which. - if (scale > 1.0) { - scaleFactors |= 2; - } else { - scaleFactors |= 1; - } - } - - // Now scaleFactors will be: - // 0 if no screens (supporting backingScaleFactor) found - // 1 if only lo-DPI screens - // 2 if only hi-DPI screens - // 3 if both lo- and hi-DPI screens - // We'll enable HiDPI support if there's only a single screen type, - // OR if the pref setting is explicitly greater than 1. - sHiDPIEnabled = (scaleFactors <= 2) || (prefSetting > 1); - } - - return sHiDPIEnabled; -} - -void -nsCocoaUtils::GetCommandsFromKeyEvent(NSEvent* aEvent, - nsTArray& aCommands) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - MOZ_ASSERT(aEvent); - - static NativeKeyBindingsRecorder* sNativeKeyBindingsRecorder; - if (!sNativeKeyBindingsRecorder) { - sNativeKeyBindingsRecorder = [NativeKeyBindingsRecorder new]; - } - - [sNativeKeyBindingsRecorder startRecording:aCommands]; - - // This will trigger 0 - N calls to doCommandBySelector: and insertText: - [sNativeKeyBindingsRecorder - interpretKeyEvents:[NSArray arrayWithObject:aEvent]]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -@implementation NativeKeyBindingsRecorder - -- (void)startRecording:(nsTArray&)aCommands -{ - mCommands = &aCommands; - mCommands->Clear(); -} - -- (void)doCommandBySelector:(SEL)aSelector -{ - KeyBindingsCommand command = { - aSelector, - nil - }; - - mCommands->AppendElement(command); -} - -- (void)insertText:(id)aString -{ - KeyBindingsCommand command = { - @selector(insertText:), - aString - }; - - mCommands->AppendElement(command); -} - -@end // NativeKeyBindingsRecorder - -struct KeyConversionData -{ - const char* str; - size_t strLength; - uint32_t geckoKeyCode; - uint32_t charCode; -}; - -static const KeyConversionData gKeyConversions[] = { - -#define KEYCODE_ENTRY(aStr, aCode) \ - {#aStr, sizeof(#aStr) - 1, NS_##aStr, aCode} - -// Some keycodes may have different name in nsIDOMKeyEvent from its key name. -#define KEYCODE_ENTRY2(aStr, aNSName, aCode) \ - {#aStr, sizeof(#aStr) - 1, NS_##aNSName, aCode} - - KEYCODE_ENTRY(VK_CANCEL, 0x001B), - KEYCODE_ENTRY(VK_DELETE, NSDeleteFunctionKey), - KEYCODE_ENTRY(VK_BACK, NSBackspaceCharacter), - KEYCODE_ENTRY2(VK_BACK_SPACE, VK_BACK, NSBackspaceCharacter), - KEYCODE_ENTRY(VK_TAB, NSTabCharacter), - KEYCODE_ENTRY(VK_CLEAR, NSClearLineFunctionKey), - KEYCODE_ENTRY(VK_RETURN, NSEnterCharacter), - KEYCODE_ENTRY(VK_SHIFT, 0), - KEYCODE_ENTRY(VK_CONTROL, 0), - KEYCODE_ENTRY(VK_ALT, 0), - KEYCODE_ENTRY(VK_PAUSE, NSPauseFunctionKey), - KEYCODE_ENTRY(VK_CAPS_LOCK, 0), - KEYCODE_ENTRY(VK_ESCAPE, 0), - KEYCODE_ENTRY(VK_SPACE, ' '), - KEYCODE_ENTRY(VK_PAGE_UP, NSPageUpFunctionKey), - KEYCODE_ENTRY(VK_PAGE_DOWN, NSPageDownFunctionKey), - KEYCODE_ENTRY(VK_END, NSEndFunctionKey), - KEYCODE_ENTRY(VK_HOME, NSHomeFunctionKey), - KEYCODE_ENTRY(VK_LEFT, NSLeftArrowFunctionKey), - KEYCODE_ENTRY(VK_UP, NSUpArrowFunctionKey), - KEYCODE_ENTRY(VK_RIGHT, NSRightArrowFunctionKey), - KEYCODE_ENTRY(VK_DOWN, NSDownArrowFunctionKey), - KEYCODE_ENTRY(VK_PRINTSCREEN, NSPrintScreenFunctionKey), - KEYCODE_ENTRY(VK_INSERT, NSInsertFunctionKey), - KEYCODE_ENTRY(VK_HELP, NSHelpFunctionKey), - KEYCODE_ENTRY(VK_0, '0'), - KEYCODE_ENTRY(VK_1, '1'), - KEYCODE_ENTRY(VK_2, '2'), - KEYCODE_ENTRY(VK_3, '3'), - KEYCODE_ENTRY(VK_4, '4'), - KEYCODE_ENTRY(VK_5, '5'), - KEYCODE_ENTRY(VK_6, '6'), - KEYCODE_ENTRY(VK_7, '7'), - KEYCODE_ENTRY(VK_8, '8'), - KEYCODE_ENTRY(VK_9, '9'), - KEYCODE_ENTRY(VK_SEMICOLON, ':'), - KEYCODE_ENTRY(VK_EQUALS, '='), - KEYCODE_ENTRY(VK_A, 'A'), - KEYCODE_ENTRY(VK_B, 'B'), - KEYCODE_ENTRY(VK_C, 'C'), - KEYCODE_ENTRY(VK_D, 'D'), - KEYCODE_ENTRY(VK_E, 'E'), - KEYCODE_ENTRY(VK_F, 'F'), - KEYCODE_ENTRY(VK_G, 'G'), - KEYCODE_ENTRY(VK_H, 'H'), - KEYCODE_ENTRY(VK_I, 'I'), - KEYCODE_ENTRY(VK_J, 'J'), - KEYCODE_ENTRY(VK_K, 'K'), - KEYCODE_ENTRY(VK_L, 'L'), - KEYCODE_ENTRY(VK_M, 'M'), - KEYCODE_ENTRY(VK_N, 'N'), - KEYCODE_ENTRY(VK_O, 'O'), - KEYCODE_ENTRY(VK_P, 'P'), - KEYCODE_ENTRY(VK_Q, 'Q'), - KEYCODE_ENTRY(VK_R, 'R'), - KEYCODE_ENTRY(VK_S, 'S'), - KEYCODE_ENTRY(VK_T, 'T'), - KEYCODE_ENTRY(VK_U, 'U'), - KEYCODE_ENTRY(VK_V, 'V'), - KEYCODE_ENTRY(VK_W, 'W'), - KEYCODE_ENTRY(VK_X, 'X'), - KEYCODE_ENTRY(VK_Y, 'Y'), - KEYCODE_ENTRY(VK_Z, 'Z'), - KEYCODE_ENTRY(VK_CONTEXT_MENU, NSMenuFunctionKey), - KEYCODE_ENTRY(VK_NUMPAD0, '0'), - KEYCODE_ENTRY(VK_NUMPAD1, '1'), - KEYCODE_ENTRY(VK_NUMPAD2, '2'), - KEYCODE_ENTRY(VK_NUMPAD3, '3'), - KEYCODE_ENTRY(VK_NUMPAD4, '4'), - KEYCODE_ENTRY(VK_NUMPAD5, '5'), - KEYCODE_ENTRY(VK_NUMPAD6, '6'), - KEYCODE_ENTRY(VK_NUMPAD7, '7'), - KEYCODE_ENTRY(VK_NUMPAD8, '8'), - KEYCODE_ENTRY(VK_NUMPAD9, '9'), - KEYCODE_ENTRY(VK_MULTIPLY, '*'), - KEYCODE_ENTRY(VK_ADD, '+'), - KEYCODE_ENTRY(VK_SEPARATOR, 0), - KEYCODE_ENTRY(VK_SUBTRACT, '-'), - KEYCODE_ENTRY(VK_DECIMAL, '.'), - KEYCODE_ENTRY(VK_DIVIDE, '/'), - KEYCODE_ENTRY(VK_F1, NSF1FunctionKey), - KEYCODE_ENTRY(VK_F2, NSF2FunctionKey), - KEYCODE_ENTRY(VK_F3, NSF3FunctionKey), - KEYCODE_ENTRY(VK_F4, NSF4FunctionKey), - KEYCODE_ENTRY(VK_F5, NSF5FunctionKey), - KEYCODE_ENTRY(VK_F6, NSF6FunctionKey), - KEYCODE_ENTRY(VK_F7, NSF7FunctionKey), - KEYCODE_ENTRY(VK_F8, NSF8FunctionKey), - KEYCODE_ENTRY(VK_F9, NSF9FunctionKey), - KEYCODE_ENTRY(VK_F10, NSF10FunctionKey), - KEYCODE_ENTRY(VK_F11, NSF11FunctionKey), - KEYCODE_ENTRY(VK_F12, NSF12FunctionKey), - KEYCODE_ENTRY(VK_F13, NSF13FunctionKey), - KEYCODE_ENTRY(VK_F14, NSF14FunctionKey), - KEYCODE_ENTRY(VK_F15, NSF15FunctionKey), - KEYCODE_ENTRY(VK_F16, NSF16FunctionKey), - KEYCODE_ENTRY(VK_F17, NSF17FunctionKey), - KEYCODE_ENTRY(VK_F18, NSF18FunctionKey), - KEYCODE_ENTRY(VK_F19, NSF19FunctionKey), - KEYCODE_ENTRY(VK_F20, NSF20FunctionKey), - KEYCODE_ENTRY(VK_F21, NSF21FunctionKey), - KEYCODE_ENTRY(VK_F22, NSF22FunctionKey), - KEYCODE_ENTRY(VK_F23, NSF23FunctionKey), - KEYCODE_ENTRY(VK_F24, NSF24FunctionKey), - KEYCODE_ENTRY(VK_NUM_LOCK, NSClearLineFunctionKey), - KEYCODE_ENTRY(VK_SCROLL_LOCK, NSScrollLockFunctionKey), - KEYCODE_ENTRY(VK_COMMA, ','), - KEYCODE_ENTRY(VK_PERIOD, '.'), - KEYCODE_ENTRY(VK_SLASH, '/'), - KEYCODE_ENTRY(VK_BACK_QUOTE, '`'), - KEYCODE_ENTRY(VK_OPEN_BRACKET, '['), - KEYCODE_ENTRY(VK_BACK_SLASH, '\\'), - KEYCODE_ENTRY(VK_CLOSE_BRACKET, ']'), - KEYCODE_ENTRY(VK_QUOTE, '\'') - -#undef KEYCODE_ENTRY - -}; - -uint32_t -nsCocoaUtils::ConvertGeckoNameToMacCharCode(const nsAString& aKeyCodeName) -{ - if (aKeyCodeName.IsEmpty()) { - return 0; - } - - nsAutoCString keyCodeName; - keyCodeName.AssignWithConversion(aKeyCodeName); - // We want case-insensitive comparison with data stored as uppercase. - ToUpperCase(keyCodeName); - - uint32_t keyCodeNameLength = keyCodeName.Length(); - const char* keyCodeNameStr = keyCodeName.get(); - for (uint16_t i = 0; i < ArrayLength(gKeyConversions); ++i) { - if (keyCodeNameLength == gKeyConversions[i].strLength && - nsCRT::strcmp(gKeyConversions[i].str, keyCodeNameStr) == 0) { - return gKeyConversions[i].charCode; - } - } - - return 0; -} - -uint32_t -nsCocoaUtils::ConvertGeckoKeyCodeToMacCharCode(uint32_t aKeyCode) -{ - if (!aKeyCode) { - return 0; - } - - for (uint16_t i = 0; i < ArrayLength(gKeyConversions); ++i) { - if (gKeyConversions[i].geckoKeyCode == aKeyCode) { - return gKeyConversions[i].charCode; - } - } - - return 0; -} - -NSMutableAttributedString* -nsCocoaUtils::GetNSMutableAttributedString( - const nsAString& aText, - const nsTArray& aFontRanges, - const bool aIsVertical, - const CGFloat aBackingScaleFactor) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL - - NSString* nsstr = nsCocoaUtils::ToNSString(aText); - NSMutableAttributedString* attrStr = - [[[NSMutableAttributedString alloc] initWithString:nsstr - attributes:nil] autorelease]; - - int32_t lastOffset = aText.Length(); - for (auto i = aFontRanges.Length(); i > 0; --i) { - const FontRange& fontRange = aFontRanges[i - 1]; - NSString* fontName = nsCocoaUtils::ToNSString(fontRange.mFontName); - CGFloat fontSize = fontRange.mFontSize / aBackingScaleFactor; - NSFont* font = [NSFont fontWithName:fontName size:fontSize]; - if (!font) { - font = [NSFont systemFontOfSize:fontSize]; - } - - NSDictionary* attrs = @{ NSFontAttributeName: font }; - NSRange range = NSMakeRange(fontRange.mStartOffset, - lastOffset - fontRange.mStartOffset); - [attrStr setAttributes:attrs range:range]; - lastOffset = fontRange.mStartOffset; - } - - if (aIsVertical) { - [attrStr addAttribute:NSVerticalGlyphFormAttributeName - value:[NSNumber numberWithInt: 1] - range:NSMakeRange(0, [attrStr length])]; - } - - return attrStr; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL -} diff --git a/widget/cocoa/nsCocoaWindow.h b/widget/cocoa/nsCocoaWindow.h deleted file mode 100644 index 1913696b8c..0000000000 --- a/widget/cocoa/nsCocoaWindow.h +++ /dev/null @@ -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 - -#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 -{ - 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& 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& 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 - AllocateChildPopupWidget() override - { - static NS_DEFINE_IID(kCPopUpCID, NS_POPUP_CID); - nsCOMPtr 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 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_ diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm deleted file mode 100644 index a437504fd1..0000000000 --- a/widget/cocoa/nsCocoaWindow.mm +++ /dev/null @@ -1,3881 +0,0 @@ -/* -*- Mode: Objective-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 "nsCocoaWindow.h" - -#include "NativeKeyBindings.h" -#include "TextInputHandler.h" -#include "nsObjCExceptions.h" -#include "nsCOMPtr.h" -#include "nsWidgetsCID.h" -#include "nsIRollupListener.h" -#include "nsChildView.h" -#include "nsWindowMap.h" -#include "nsAppShell.h" -#include "nsIAppShellService.h" -#include "nsIBaseWindow.h" -#include "nsIInterfaceRequestorUtils.h" -#include "nsIXULWindow.h" -#include "nsToolkit.h" -#include "nsIDOMWindow.h" -#include "nsPIDOMWindow.h" -#include "nsIDOMElement.h" -#include "nsThreadUtils.h" -#include "nsMenuBarX.h" -#include "nsMenuUtilsX.h" -#include "nsStyleConsts.h" -#include "nsNativeThemeColors.h" -#include "nsNativeThemeCocoa.h" -#include "nsChildView.h" -#include "nsCocoaFeatures.h" -#include "nsIScreenManager.h" -#include "nsIWidgetListener.h" -#include "nsIPresShell.h" -#include "nsScreenCocoa.h" -#include "VibrancyManager.h" - -#include "gfxPlatform.h" -#include "qcms.h" - -#include "mozilla/AutoRestore.h" -#include "mozilla/BasicEvents.h" -#include "mozilla/Preferences.h" -#include - -namespace mozilla { -namespace layers { -class LayerManager; -} // namespace layers -} // namespace mozilla -using namespace mozilla::layers; -using namespace mozilla::widget; -using namespace mozilla; - -int32_t gXULModalLevel = 0; - -// In principle there should be only one app-modal window at any given time. -// But sometimes, despite our best efforts, another window appears above the -// current app-modal window. So we need to keep a linked list of app-modal -// windows. (A non-sheet window that appears above an app-modal window is -// also made app-modal.) See nsCocoaWindow::SetModal(). -nsCocoaWindowList *gGeckoAppModalWindowList = NULL; - -// defined in nsMenuBarX.mm -extern NSMenu* sApplicationMenu; // Application menu shared by all menubars - -// defined in nsChildView.mm -extern BOOL gSomeMenuBarPainted; - -#if !defined(MAC_OS_X_VERSION_10_12) || \ - MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12 - -@interface NSWindow(AutomaticWindowTabbing) -+ (void)setAllowsAutomaticWindowTabbing:(BOOL)allow; -@end - -#endif - -extern "C" { - // CGSPrivate.h - typedef NSInteger CGSConnection; - typedef NSInteger CGSWindow; - typedef NSUInteger CGSWindowFilterRef; - extern CGSConnection _CGSDefaultConnection(void); - extern CGError CGSSetWindowShadowAndRimParameters(const CGSConnection cid, CGSWindow wid, float standardDeviation, float density, int offsetX, int offsetY, unsigned int flags); - extern CGError CGSSetWindowBackgroundBlurRadius(CGSConnection cid, CGSWindow wid, NSUInteger blur); -} - -#define NS_APPSHELLSERVICE_CONTRACTID "@mozilla.org/appshell/appShellService;1" - -NS_IMPL_ISUPPORTS_INHERITED(nsCocoaWindow, Inherited, nsPIWidgetCocoa) - -// A note on testing to see if your object is a sheet... -// |mWindowType == eWindowType_sheet| is true if your gecko nsIWidget is a sheet -// widget - whether or not the sheet is showing. |[mWindow isSheet]| will return -// true *only when the sheet is actually showing*. Choose your test wisely. - -static void RollUpPopups() -{ - nsIRollupListener* rollupListener = nsBaseWidget::GetActiveRollupListener(); - NS_ENSURE_TRUE_VOID(rollupListener); - nsCOMPtr rollupWidget = rollupListener->GetRollupWidget(); - if (!rollupWidget) - return; - rollupListener->Rollup(0, true, nullptr, nullptr); -} - -nsCocoaWindow::nsCocoaWindow() -: mParent(nullptr) -, mAncestorLink(nullptr) -, mWindow(nil) -, mDelegate(nil) -, mSheetWindowParent(nil) -, mPopupContentView(nil) -, mFullscreenTransitionAnimation(nil) -, mShadowStyle(NS_STYLE_WINDOW_SHADOW_DEFAULT) -, mBackingScaleFactor(0.0) -, mAnimationType(nsIWidget::eGenericWindowAnimation) -, mWindowMadeHere(false) -, mSheetNeedsShow(false) -, mInFullScreenMode(false) -, mInFullScreenTransition(false) -, mModal(false) -, mFakeModal(false) -, mSupportsNativeFullScreen(false) -, mInNativeFullScreenMode(false) -, mIsAnimationSuppressed(false) -, mInReportMoveEvent(false) -, mInResize(false) -, mAlwaysOnTop(false) -, mNumModalDescendents(0) -{ - if ([NSWindow respondsToSelector:@selector(setAllowsAutomaticWindowTabbing:)]) { - // Disable automatic tabbing on 10.12. We need to do this before we - // orderFront any of our windows. - [NSWindow setAllowsAutomaticWindowTabbing:NO]; - } -} - -void nsCocoaWindow::DestroyNativeWindow() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mWindow) - return; - - // We want to unhook the delegate here because we don't want events - // sent to it after this object has been destroyed. - [mWindow setDelegate:nil]; - [mWindow close]; - mWindow = nil; - [mDelegate autorelease]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsCocoaWindow::~nsCocoaWindow() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // Notify the children that we're gone. Popup windows (e.g. tooltips) can - // have nsChildView children. 'kid' is an nsChildView object if and only if - // its 'type' is 'eWindowType_child'. - // childView->ResetParent() can change our list of children while it's - // being iterated, so the way we iterate the list must allow for this. - for (nsIWidget* kid = mLastChild; kid;) { - nsWindowType kidType = kid->WindowType(); - if (kidType == eWindowType_child) { - nsChildView* childView = static_cast(kid); - kid = kid->GetPrevSibling(); - childView->ResetParent(); - } else { - nsCocoaWindow* childWindow = static_cast(kid); - childWindow->mParent = nullptr; - childWindow->mAncestorLink = mAncestorLink; - kid = kid->GetPrevSibling(); - } - } - - if (mWindow && mWindowMadeHere) { - DestroyNativeWindow(); - } - - NS_IF_RELEASE(mPopupContentView); - - // Deal with the possiblity that we're being destroyed while running modal. - if (mModal) { - NS_WARNING("Widget destroyed while running modal!"); - --gXULModalLevel; - NS_ASSERTION(gXULModalLevel >= 0, "Weirdness setting modality!"); - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// Find the screen that overlaps aRect the most, -// if none are found default to the mainScreen. -static NSScreen* -FindTargetScreenForRect(const DesktopIntRect& aRect) -{ - NSScreen *targetScreen = [NSScreen mainScreen]; - NSEnumerator *screenEnum = [[NSScreen screens] objectEnumerator]; - int largestIntersectArea = 0; - while (NSScreen *screen = [screenEnum nextObject]) { - DesktopIntRect screenRect = - nsCocoaUtils::CocoaRectToGeckoRect([screen visibleFrame]); - screenRect = screenRect.Intersect(aRect); - int area = screenRect.width * screenRect.height; - if (area > largestIntersectArea) { - largestIntersectArea = area; - targetScreen = screen; - } - } - return targetScreen; -} - -// fits the rect to the screen that contains the largest area of it, -// or to aScreen if a screen is passed in -// NB: this operates with aRect in desktop pixels -static void -FitRectToVisibleAreaForScreen(DesktopIntRect& aRect, NSScreen* aScreen) -{ - if (!aScreen) { - aScreen = FindTargetScreenForRect(aRect); - } - - DesktopIntRect screenBounds = - nsCocoaUtils::CocoaRectToGeckoRect([aScreen visibleFrame]); - - if (aRect.width > screenBounds.width) { - aRect.width = screenBounds.width; - } - if (aRect.height > screenBounds.height) { - aRect.height = screenBounds.height; - } - - if (aRect.x - screenBounds.x + aRect.width > screenBounds.width) { - aRect.x += screenBounds.width - (aRect.x - screenBounds.x + aRect.width); - } - if (aRect.y - screenBounds.y + aRect.height > screenBounds.height) { - aRect.y += screenBounds.height - (aRect.y - screenBounds.y + aRect.height); - } - - // If the left/top edge of the window is off the screen in either direction, - // then set the window to start at the left/top edge of the screen. - if (aRect.x < screenBounds.x || aRect.x > (screenBounds.x + screenBounds.width)) { - aRect.x = screenBounds.x; - } - if (aRect.y < screenBounds.y || aRect.y > (screenBounds.y + screenBounds.height)) { - aRect.y = screenBounds.y; - } -} - -// Some applications use native popup windows -// (native context menus, native tooltips) -static bool UseNativePopupWindows() -{ -#ifdef MOZ_USE_NATIVE_POPUP_WINDOWS - return true; -#else - return false; -#endif /* MOZ_USE_NATIVE_POPUP_WINDOWS */ -} - -// aRect here is specified in desktop pixels -nsresult -nsCocoaWindow::Create(nsIWidget* aParent, - nsNativeWidget aNativeParent, - const DesktopIntRect& aRect, - nsWidgetInitData* aInitData) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - // Because the hidden window is created outside of an event loop, - // we have to provide an autorelease pool (see bug 559075). - nsAutoreleasePool localPool; - - DesktopIntRect newBounds = aRect; - FitRectToVisibleAreaForScreen(newBounds, nullptr); - - // Set defaults which can be overriden from aInitData in BaseCreate - mWindowType = eWindowType_toplevel; - mBorderStyle = eBorderStyle_default; - - // Ensure that the toolkit is created. - nsToolkit::GetToolkit(); - - Inherited::BaseCreate(aParent, aInitData); - - mParent = aParent; - mAncestorLink = aParent; - - // Applications that use native popups don't want us to create popup windows. - if ((mWindowType == eWindowType_popup) && UseNativePopupWindows()) - return NS_OK; - - nsresult rv = - CreateNativeWindow(nsCocoaUtils::GeckoRectToCocoaRect(newBounds), - mBorderStyle, false); - NS_ENSURE_SUCCESS(rv, rv); - - if (mWindowType == eWindowType_popup) { - if (aInitData->mMouseTransparent) { - [mWindow setIgnoresMouseEvents:YES]; - } else { - [mWindow setIgnoresMouseEvents:NO]; - } - // now we can convert newBounds to device pixels for the window we created, - // as the child view expects a rect expressed in the dev pix of its parent - LayoutDeviceIntRect devRect = - RoundedToInt(newBounds * GetDesktopToDeviceScale()); - return CreatePopupContentView(devRect, aInitData); - } - - mIsAnimationSuppressed = aInitData->mIsAnimationSuppressed; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -nsresult -nsCocoaWindow::Create(nsIWidget* aParent, - nsNativeWidget aNativeParent, - const LayoutDeviceIntRect& aRect, - nsWidgetInitData* aInitData) -{ - DesktopIntRect desktopRect = - RoundedToInt(aRect / GetDesktopToDeviceScale()); - return Create(aParent, aNativeParent, desktopRect, aInitData); -} - -static unsigned int WindowMaskForBorderStyle(nsBorderStyle aBorderStyle) -{ - bool allOrDefault = (aBorderStyle == eBorderStyle_all || - aBorderStyle == eBorderStyle_default); - - /* Apple's docs on NSWindow styles say that "a window's style mask should - * include NSTitledWindowMask if it includes any of the others [besides - * NSBorderlessWindowMask]". This implies that a borderless window - * shouldn't have any other styles than NSBorderlessWindowMask. - */ - if (!allOrDefault && !(aBorderStyle & eBorderStyle_title)) - return NSBorderlessWindowMask; - - unsigned int mask = NSTitledWindowMask; - if (allOrDefault || aBorderStyle & eBorderStyle_close) - mask |= NSClosableWindowMask; - if (allOrDefault || aBorderStyle & eBorderStyle_minimize) - mask |= NSMiniaturizableWindowMask; - if (allOrDefault || aBorderStyle & eBorderStyle_resizeh) - mask |= NSResizableWindowMask; - - return mask; -} - -// If aRectIsFrameRect, aRect specifies the frame rect of the new window. -// Otherwise, aRect.x/y specify the position of the window's frame relative to -// the bottom of the menubar and aRect.width/height specify the size of the -// content rect. -nsresult nsCocoaWindow::CreateNativeWindow(const NSRect &aRect, - nsBorderStyle aBorderStyle, - bool aRectIsFrameRect) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - // We default to NSBorderlessWindowMask, add features if needed. - unsigned int features = NSBorderlessWindowMask; - - // Configure the window we will create based on the window type. - switch (mWindowType) - { - case eWindowType_invisible: - case eWindowType_child: - case eWindowType_plugin: - break; - case eWindowType_popup: - if (aBorderStyle != eBorderStyle_default && mBorderStyle & eBorderStyle_title) { - features |= NSTitledWindowMask; - if (aBorderStyle & eBorderStyle_close) { - features |= NSClosableWindowMask; - } - } - break; - case eWindowType_toplevel: - case eWindowType_dialog: - features = WindowMaskForBorderStyle(aBorderStyle); - break; - case eWindowType_sheet: - if (mParent->WindowType() != eWindowType_invisible && - aBorderStyle & eBorderStyle_resizeh) { - features = NSResizableWindowMask; - } - else { - features = NSMiniaturizableWindowMask; - } - features |= NSTitledWindowMask; - break; - default: - NS_ERROR("Unhandled window type!"); - return NS_ERROR_FAILURE; - } - - NSRect contentRect; - - if (aRectIsFrameRect) { - contentRect = [NSWindow contentRectForFrameRect:aRect styleMask:features]; - } else { - /* - * We pass a content area rect to initialize the native Cocoa window. The - * content rect we give is the same size as the size we're given by gecko. - * The origin we're given for non-popup windows is moved down by the height - * of the menu bar so that an origin of (0,100) from gecko puts the window - * 100 pixels below the top of the available desktop area. We also move the - * origin down by the height of a title bar if it exists. This is so the - * origin that gecko gives us for the top-left of the window turns out to - * be the top-left of the window we create. This is how it was done in - * Carbon. If it ought to be different we'll probably need to look at all - * the callers. - * - * Note: This means that if you put a secondary screen on top of your main - * screen and open a window in the top screen, it'll be incorrectly shifted - * down by the height of the menu bar. Same thing would happen in Carbon. - * - * Note: If you pass a rect with 0,0 for an origin, the window ends up in a - * weird place for some reason. This stops that without breaking popups. - */ - // Compensate for difference between frame and content area height (e.g. title bar). - NSRect newWindowFrame = [NSWindow frameRectForContentRect:aRect styleMask:features]; - - contentRect = aRect; - contentRect.origin.y -= (newWindowFrame.size.height - aRect.size.height); - - if (mWindowType != eWindowType_popup) - contentRect.origin.y -= [[NSApp mainMenu] menuBarHeight]; - } - - // NSLog(@"Top-level window being created at Cocoa rect: %f, %f, %f, %f\n", - // rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); - - Class windowClass = [BaseWindow class]; - // If we have a titlebar on a top-level window, we want to be able to control the - // titlebar color (for unified windows), so use the special ToolbarWindow class. - // Note that we need to check the window type because we mark sheets as - // having titlebars. - if ((mWindowType == eWindowType_toplevel || mWindowType == eWindowType_dialog) && - (features & NSTitledWindowMask)) - windowClass = [ToolbarWindow class]; - // If we're a popup window we need to use the PopupWindow class. - else if (mWindowType == eWindowType_popup) - windowClass = [PopupWindow class]; - // If we're a non-popup borderless window we need to use the - // BorderlessWindow class. - else if (features == NSBorderlessWindowMask) - windowClass = [BorderlessWindow class]; - - // Create the window - mWindow = [[windowClass alloc] initWithContentRect:contentRect styleMask:features - backing:NSBackingStoreBuffered defer:YES]; - - // Make sure that window titles don't leak to disk in private browsing mode - // due to macOS' resume feature. - [mWindow setRestorable:NO]; - [mWindow disableSnapshotRestoration]; - - // setup our notification delegate. Note that setDelegate: does NOT retain. - mDelegate = [[WindowDelegate alloc] initWithGeckoWindow:this]; - [mWindow setDelegate:mDelegate]; - - // Make sure that the content rect we gave has been honored. - NSRect wantedFrame = [mWindow frameRectForContentRect:contentRect]; - if (!NSEqualRects([mWindow frame], wantedFrame)) { - // This can happen when the window is not on the primary screen. - [mWindow setFrame:wantedFrame display:NO]; - } - UpdateBounds(); - - if (mWindowType == eWindowType_invisible) { - [mWindow setLevel:kCGDesktopWindowLevelKey]; - } - - if (mWindowType == eWindowType_popup) { - SetPopupWindowLevel(); - [mWindow setBackgroundColor:[NSColor clearColor]]; - [mWindow setOpaque:NO]; - } else { - // Make sure that regular windows are opaque from the start, so that - // nsChildView::WidgetTypeSupportsAcceleration returns true for them. - [mWindow setOpaque:YES]; - } - - NSWindowCollectionBehavior newBehavior = [mWindow collectionBehavior]; - if (mAlwaysOnTop) { - [mWindow setLevel:NSFloatingWindowLevel]; - newBehavior |= NSWindowCollectionBehaviorCanJoinAllSpaces; - } - [mWindow setCollectionBehavior:newBehavior]; - - [mWindow setContentMinSize:NSMakeSize(60, 60)]; - [mWindow disableCursorRects]; - - // Make sure the window starts out not draggable by the background. - // We will turn it on as necessary. - [mWindow setMovableByWindowBackground:NO]; - - [[WindowDataMap sharedWindowDataMap] ensureDataForWindow:mWindow]; - mWindowMadeHere = true; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsCocoaWindow::CreatePopupContentView(const LayoutDeviceIntRect &aRect, - nsWidgetInitData* aInitData) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - // We need to make our content view a ChildView. - mPopupContentView = new nsChildView(); - if (!mPopupContentView) - return NS_ERROR_FAILURE; - - NS_ADDREF(mPopupContentView); - - nsIWidget* thisAsWidget = static_cast(this); - nsresult rv = mPopupContentView->Create(thisAsWidget, nullptr, aRect, - aInitData); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - NSView* contentView = [mWindow contentView]; - ChildView* childView = (ChildView*)mPopupContentView->GetNativeData(NS_NATIVE_WIDGET); - [childView setFrame:NSZeroRect]; - [childView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; - [contentView addSubview:childView]; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -void nsCocoaWindow::Destroy() -{ - if (mOnDestroyCalled) - return; - mOnDestroyCalled = true; - - // SetFakeModal(true) is called for non-modal window opened by modal window. - // On Cocoa, it needs corresponding SetFakeModal(false) on destroy to restore - // ancestor windows' state. - if (mFakeModal) { - SetFakeModal(false); - } - - // If we don't hide here we run into problems with panels, this is not ideal. - // (Bug 891424) - Show(false); - - if (mPopupContentView) - mPopupContentView->Destroy(); - - if (mFullscreenTransitionAnimation) { - [mFullscreenTransitionAnimation stopAnimation]; - ReleaseFullscreenTransitionAnimation(); - } - - nsBaseWidget::Destroy(); - // nsBaseWidget::Destroy() calls GetParent()->RemoveChild(this). But we - // don't implement GetParent(), so we need to do the equivalent here. - if (mParent) { - mParent->RemoveChild(this); - } - nsBaseWidget::OnDestroy(); - - if (mInFullScreenMode) { - // On Lion we don't have to mess with the OS chrome when in Full Screen - // mode. But we do have to destroy the native window here (and not wait - // for that to happen in our destructor). We don't switch away from the - // native window's space until the window is destroyed, and otherwise this - // might not happen for several seconds (because at least one object - // holding a reference to ourselves is usually waiting to be garbage- - // collected). See bug 757618. - if (mInNativeFullScreenMode) { - DestroyNativeWindow(); - } else if (mWindow) { - nsCocoaUtils::HideOSChromeOnScreen(false); - } - } -} - -nsIWidget* nsCocoaWindow::GetSheetWindowParent(void) -{ - if (mWindowType != eWindowType_sheet) - return nullptr; - nsCocoaWindow *parent = static_cast(mParent); - while (parent && (parent->mWindowType == eWindowType_sheet)) - parent = static_cast(parent->mParent); - return parent; -} - -void* nsCocoaWindow::GetNativeData(uint32_t aDataType) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSNULL; - - void* retVal = nullptr; - - switch (aDataType) { - // to emulate how windows works, we always have to return a NSView - // for NS_NATIVE_WIDGET - case NS_NATIVE_WIDGET: - case NS_NATIVE_DISPLAY: - retVal = [mWindow contentView]; - break; - - case NS_NATIVE_WINDOW: - retVal = mWindow; - break; - - case NS_NATIVE_GRAPHIC: - // There isn't anything that makes sense to return here, - // and it doesn't matter so just return nullptr. - NS_ERROR("Requesting NS_NATIVE_GRAPHIC on a top-level window!"); - break; - case NS_RAW_NATIVE_IME_CONTEXT: { - retVal = GetPseudoIMEContext(); - if (retVal) { - break; - } - NSView* view = mWindow ? [mWindow contentView] : nil; - if (view) { - retVal = [view inputContext]; - } - // If inputContext isn't available on this window, return this window's - // pointer instead of nullptr since if this returns nullptr, - // IMEStateManager cannot manage composition with TextComposition - // instance. Although, this case shouldn't occur. - if (NS_WARN_IF(!retVal)) { - retVal = this; - } - break; - } - } - - return retVal; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSNULL; -} - -bool nsCocoaWindow::IsVisible() const -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - return (mWindow && ([mWindow isVisibleOrBeingShown] || mSheetNeedsShow)); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false); -} - -void -nsCocoaWindow::SetModal(bool aState) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mWindow) - return; - - // This is used during startup (outside the event loop) when creating - // the add-ons compatibility checking dialog and the profile manager UI; - // therefore, it needs to provide an autorelease pool to avoid cocoa - // objects leaking. - nsAutoreleasePool localPool; - - mModal = aState; - nsCocoaWindow *ancestor = static_cast(mAncestorLink); - if (aState) { - ++gXULModalLevel; - // When a non-sheet window gets "set modal", make the window(s) that it - // appears over behave as they should. We can't rely on native methods to - // do this, for the following reason: The OS runs modal non-sheet windows - // in an event loop (using [NSApplication runModalForWindow:] or similar - // methods) that's incompatible with the modal event loop in nsXULWindow:: - // ShowModal() (each of these event loops is "exclusive", and can't run at - // the same time as other (similar) event loops). - if (mWindowType != eWindowType_sheet) { - while (ancestor) { - if (ancestor->mNumModalDescendents++ == 0) { - NSWindow *aWindow = ancestor->GetCocoaWindow(); - if (ancestor->mWindowType != eWindowType_invisible) { - [[aWindow standardWindowButton:NSWindowCloseButton] setEnabled:NO]; - [[aWindow standardWindowButton:NSWindowMiniaturizeButton] setEnabled:NO]; - [[aWindow standardWindowButton:NSWindowZoomButton] setEnabled:NO]; - } - } - ancestor = static_cast(ancestor->mParent); - } - [mWindow setLevel:NSModalPanelWindowLevel]; - nsCocoaWindowList *windowList = new nsCocoaWindowList; - if (windowList) { - windowList->window = this; // Don't ADDREF - windowList->prev = gGeckoAppModalWindowList; - gGeckoAppModalWindowList = windowList; - } - } - } - else { - --gXULModalLevel; - NS_ASSERTION(gXULModalLevel >= 0, "Mismatched call to nsCocoaWindow::SetModal(false)!"); - if (mWindowType != eWindowType_sheet) { - while (ancestor) { - if (--ancestor->mNumModalDescendents == 0) { - NSWindow *aWindow = ancestor->GetCocoaWindow(); - if (ancestor->mWindowType != eWindowType_invisible) { - [[aWindow standardWindowButton:NSWindowCloseButton] setEnabled:YES]; - [[aWindow standardWindowButton:NSWindowMiniaturizeButton] setEnabled:YES]; - [[aWindow standardWindowButton:NSWindowZoomButton] setEnabled:YES]; - } - } - NS_ASSERTION(ancestor->mNumModalDescendents >= 0, "Widget hierarchy changed while modal!"); - ancestor = static_cast(ancestor->mParent); - } - if (gGeckoAppModalWindowList) { - NS_ASSERTION(gGeckoAppModalWindowList->window == this, "Widget hierarchy changed while modal!"); - nsCocoaWindowList *saved = gGeckoAppModalWindowList; - gGeckoAppModalWindowList = gGeckoAppModalWindowList->prev; - delete saved; // "window" not ADDREFed - } - if (mWindowType == eWindowType_popup) - SetPopupWindowLevel(); - else - [mWindow setLevel:NSNormalWindowLevel]; - } - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void -nsCocoaWindow::SetFakeModal(bool aState) -{ - mFakeModal = aState; - SetModal(aState); -} - -bool -nsCocoaWindow::IsRunningAppModal() -{ - return [NSApp _isRunningAppModal]; -} - -// Hide or show this window -NS_IMETHODIMP nsCocoaWindow::Show(bool bState) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (!mWindow) - return NS_OK; - - // We need to re-execute sometimes in order to bring already-visible - // windows forward. - if (!mSheetNeedsShow && !bState && ![mWindow isVisible]) - return NS_OK; - - // Protect against re-entering. - if (bState && [mWindow isBeingShown]) - return NS_OK; - - [mWindow setBeingShown:bState]; - - nsIWidget* parentWidget = mParent; - nsCOMPtr piParentWidget(do_QueryInterface(parentWidget)); - NSWindow* nativeParentWindow = (parentWidget) ? - (NSWindow*)parentWidget->GetNativeData(NS_NATIVE_WINDOW) : nil; - - if (bState && !mBounds.IsEmpty()) { - // Don't try to show a popup when the parent isn't visible or is minimized. - if (mWindowType == eWindowType_popup && nativeParentWindow) { - if (![nativeParentWindow isVisible] || [nativeParentWindow isMiniaturized]) { - return NS_ERROR_FAILURE; - } - } - - if (mPopupContentView) { - // Ensure our content view is visible. We never need to hide it. - mPopupContentView->Show(true); - } - - if (mWindowType == eWindowType_sheet) { - // bail if no parent window (its basically what we do in Carbon) - if (!nativeParentWindow || !piParentWidget) - return NS_ERROR_FAILURE; - - NSWindow* topNonSheetWindow = nativeParentWindow; - - // If this sheet is the child of another sheet, hide the parent so that - // this sheet can be displayed. Leave the parent mSheetNeedsShow alone, - // that is only used to handle sibling sheet contention. The parent will - // return once there are no more child sheets. - bool parentIsSheet = false; - if (NS_SUCCEEDED(piParentWidget->GetIsSheet(&parentIsSheet)) && - parentIsSheet) { - piParentWidget->GetSheetWindowParent(&topNonSheetWindow); - [NSApp endSheet:nativeParentWindow]; - } - - nsCOMPtr sheetShown; - if (NS_SUCCEEDED(piParentWidget->GetChildSheet( - true, getter_AddRefs(sheetShown))) && - (!sheetShown || sheetShown == this)) { - // If this sheet is already the sheet actually being shown, don't - // tell it to show again. Otherwise the number of calls to - // [NSApp beginSheet...] won't match up with [NSApp endSheet...]. - if (![mWindow isVisible]) { - mSheetNeedsShow = false; - mSheetWindowParent = topNonSheetWindow; - // Only set contextInfo if our parent isn't a sheet. - NSWindow* contextInfo = parentIsSheet ? nil : mSheetWindowParent; - [TopLevelWindowData deactivateInWindow:mSheetWindowParent]; - [NSApp beginSheet:mWindow - modalForWindow:mSheetWindowParent - modalDelegate:mDelegate - didEndSelector:@selector(didEndSheet:returnCode:contextInfo:) - contextInfo:contextInfo]; - [TopLevelWindowData activateInWindow:mWindow]; - SendSetZLevelEvent(); - } - } - else { - // A sibling of this sheet is active, don't show this sheet yet. - // When the active sheet hides, its brothers and sisters that have - // mSheetNeedsShow set will have their opportunities to display. - mSheetNeedsShow = true; - } - } - else if (mWindowType == eWindowType_popup) { - if (!nsCocoaFeatures::OnMojaveOrLater()) { - // If a popup window is shown after being hidden, it needs to be "reset" - // for it to receive any mouse events aside from mouse-moved events - // (because it was removed from the "window cache" when it was hidden - // -- see below). Setting the window number to -1 and then back to its - // original value seems to accomplish this. The idea was "borrowed" - // from the Java Embedding Plugin. This is fixed on macOS 10.14+. - NSInteger windowNumber = [mWindow windowNumber]; - [mWindow _setWindowNumber:-1]; - [mWindow _setWindowNumber:windowNumber]; - } - // For reasons that aren't yet clear, calls to [NSWindow orderFront:] or - // [NSWindow makeKeyAndOrderFront:] can sometimes trigger "Error (1000) - // creating CGSWindow", which in turn triggers an internal inconsistency - // NSException. These errors shouldn't be fatal. So we need to wrap - // calls to ...orderFront: in TRY blocks. See bmo bug 470864. - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - [[mWindow contentView] setNeedsDisplay:YES]; - [mWindow orderFront:nil]; - NS_OBJC_END_TRY_ABORT_BLOCK; - SendSetZLevelEvent(); - AdjustWindowShadow(); - SetWindowBackgroundBlur(); - // If our popup window is a non-native context menu, tell the OS (and - // other programs) that a menu has opened. This is how the OS knows to - // close other programs' context menus when ours open. - if ([mWindow isKindOfClass:[PopupWindow class]] && - [(PopupWindow*) mWindow isContextMenu]) { - [[NSDistributedNotificationCenter defaultCenter] - postNotificationName:@"com.apple.HIToolbox.beginMenuTrackingNotification" - object:@"org.mozilla.gecko.PopupWindow"]; - } - - // If a parent window was supplied and this is a popup at the parent - // level, set its child window. This will cause the child window to - // appear above the parent and move when the parent does. Setting this - // needs to happen after the _setWindowNumber calls above, otherwise the - // window doesn't focus properly. - if (nativeParentWindow && mPopupLevel == ePopupLevelParent) - [nativeParentWindow addChildWindow:mWindow - ordered:NSWindowAbove]; - } - else { - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - if (mWindowType == eWindowType_toplevel && - [mWindow respondsToSelector:@selector(setAnimationBehavior:)]) { - NSWindowAnimationBehavior behavior; - if (mIsAnimationSuppressed) { - behavior = NSWindowAnimationBehaviorNone; - } else { - switch (mAnimationType) { - case nsIWidget::eDocumentWindowAnimation: - behavior = NSWindowAnimationBehaviorDocumentWindow; - break; - default: - NS_NOTREACHED("unexpected mAnimationType value"); - // fall through - case nsIWidget::eGenericWindowAnimation: - behavior = NSWindowAnimationBehaviorDefault; - break; - } - } - [mWindow setAnimationBehavior:behavior]; - } - [mWindow makeKeyAndOrderFront:nil]; - NS_OBJC_END_TRY_ABORT_BLOCK; - SendSetZLevelEvent(); - } - } - else { - // roll up any popups if a top-level window is going away - if (mWindowType == eWindowType_toplevel || mWindowType == eWindowType_dialog) - RollUpPopups(); - - // now get rid of the window/sheet - if (mWindowType == eWindowType_sheet) { - if (mSheetNeedsShow) { - // This is an attempt to hide a sheet that never had a chance to - // be shown. There's nothing to do other than make sure that it - // won't show. - mSheetNeedsShow = false; - } - else { - // get sheet's parent *before* hiding the sheet (which breaks the linkage) - NSWindow* sheetParent = mSheetWindowParent; - - // hide the sheet - [NSApp endSheet:mWindow]; - - [TopLevelWindowData deactivateInWindow:mWindow]; - - nsCOMPtr siblingSheetToShow; - bool parentIsSheet = false; - - if (nativeParentWindow && piParentWidget && - NS_SUCCEEDED(piParentWidget->GetChildSheet( - false, getter_AddRefs(siblingSheetToShow))) && - siblingSheetToShow) { - // First, give sibling sheets an opportunity to show. - siblingSheetToShow->Show(true); - } - else if (nativeParentWindow && piParentWidget && - NS_SUCCEEDED(piParentWidget->GetIsSheet(&parentIsSheet)) && - parentIsSheet) { - // Only set contextInfo if the parent of the parent sheet we're about - // to restore isn't itself a sheet. - NSWindow* contextInfo = sheetParent; - nsIWidget* grandparentWidget = nil; - if (NS_SUCCEEDED(piParentWidget->GetRealParent(&grandparentWidget)) && grandparentWidget) { - nsCOMPtr piGrandparentWidget(do_QueryInterface(grandparentWidget)); - bool grandparentIsSheet = false; - if (piGrandparentWidget && NS_SUCCEEDED(piGrandparentWidget->GetIsSheet(&grandparentIsSheet)) && - grandparentIsSheet) { - contextInfo = nil; - } - } - // If there are no sibling sheets, but the parent is a sheet, restore - // it. It wasn't sent any deactivate events when it was hidden, so - // don't call through Show, just let the OS put it back up. - [NSApp beginSheet:nativeParentWindow - modalForWindow:sheetParent - modalDelegate:[nativeParentWindow delegate] - didEndSelector:@selector(didEndSheet:returnCode:contextInfo:) - contextInfo:contextInfo]; - } - else { - // Sheet, that was hard. No more siblings or parents, going back - // to a real window. - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - [sheetParent makeKeyAndOrderFront:nil]; - NS_OBJC_END_TRY_ABORT_BLOCK; - } - SendSetZLevelEvent(); - } - } - else { - // If the window is a popup window with a parent window we need to - // unhook it here before ordering it out. When you order out the child - // of a window it hides the parent window. - if (mWindowType == eWindowType_popup && nativeParentWindow) - [nativeParentWindow removeChildWindow:mWindow]; - - [mWindow orderOut:nil]; - - if (!nsCocoaFeatures::OnMojaveOrLater()) { - // Unless it's explicitly removed from NSApp's "window cache", a popup - // window will keep receiving mouse-moved events even after it's been - // "ordered out" (instead of the browser window that was underneath it, - // until you click on that window). This is bmo bug 378645, but it's - // surely an Apple bug. 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). This workaround was "borrowed" from the Java Embedding - // Plugin (which uses it for a different purpose). This is fixed on - // macOS 10.14+. - if (mWindowType == eWindowType_popup) { - [NSApp _removeWindowFromCache:mWindow]; - } - } - - // If our popup window is a non-native context menu, tell the OS (and - // other programs) that a menu has closed. - if ([mWindow isKindOfClass:[PopupWindow class]] && - [(PopupWindow*) mWindow isContextMenu]) { - [[NSDistributedNotificationCenter defaultCenter] - postNotificationName:@"com.apple.HIToolbox.endMenuTrackingNotification" - object:@"org.mozilla.gecko.PopupWindow"]; - } - } - } - - [mWindow setBeingShown:NO]; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -struct ShadowParams { - float standardDeviation; - float density; - int offsetX; - int offsetY; - unsigned int flags; -}; - -// These numbers have been determined by looking at the results of -// CGSGetWindowShadowAndRimParameters for native window types. -static const ShadowParams kWindowShadowParametersPreYosemite[] = { - { 0.0f, 0.0f, 0, 0, 0 }, // none - { 8.0f, 0.5f, 0, 6, 1 }, // default - { 10.0f, 0.44f, 0, 10, 512 }, // menu - { 8.0f, 0.5f, 0, 6, 1 }, // tooltip - { 4.0f, 0.6f, 0, 4, 512 } // sheet -}; - -static const ShadowParams kWindowShadowParametersPostYosemite[] = { - { 0.0f, 0.0f, 0, 0, 0 }, // none - { 8.0f, 0.5f, 0, 6, 1 }, // default - { 9.882353f, 0.3f, 0, 4, 0 }, // menu - { 3.294118f, 0.2f, 0, 1, 0 }, // tooltip - { 9.882353f, 0.3f, 0, 4, 0 } // sheet -}; - -// This method will adjust the window shadow style for popup windows after -// they have been made visible. Before they're visible, their window number -// might be -1, which is not useful. -// We won't attempt to change the shadow for windows that can acquire key state -// since OS X will reset the shadow whenever that happens. -void -nsCocoaWindow::AdjustWindowShadow() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mWindow || ![mWindow isVisible] || ![mWindow hasShadow] || - [mWindow canBecomeKeyWindow] || [mWindow windowNumber] == -1) - return; - - const ShadowParams& params = nsCocoaFeatures::OnYosemiteOrLater() - ? kWindowShadowParametersPostYosemite[mShadowStyle] - : kWindowShadowParametersPreYosemite[mShadowStyle]; - CGSConnection cid = _CGSDefaultConnection(); - CGSSetWindowShadowAndRimParameters(cid, [mWindow windowNumber], - params.standardDeviation, params.density, - params.offsetX, params.offsetY, - params.flags); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -static const NSUInteger kWindowBackgroundBlurRadius = 4; - -void -nsCocoaWindow::SetWindowBackgroundBlur() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mWindow || ![mWindow isVisible] || [mWindow windowNumber] == -1) - return; - - // Only blur the background of menus and fake sheets. - if (mShadowStyle != NS_STYLE_WINDOW_SHADOW_MENU && - mShadowStyle != NS_STYLE_WINDOW_SHADOW_SHEET) - return; - - CGSConnection cid = _CGSDefaultConnection(); - CGSSetWindowBackgroundBlurRadius(cid, [mWindow windowNumber], kWindowBackgroundBlurRadius); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsresult -nsCocoaWindow::ConfigureChildren(const nsTArray& aConfigurations) -{ - if (mPopupContentView) { - mPopupContentView->ConfigureChildren(aConfigurations); - } - return NS_OK; -} - -LayerManager* -nsCocoaWindow::GetLayerManager(PLayerTransactionChild* aShadowManager, - LayersBackend aBackendHint, - LayerManagerPersistence aPersistence) -{ - if (mPopupContentView) { - return mPopupContentView->GetLayerManager(aShadowManager, - aBackendHint, - aPersistence); - } - return nullptr; -} - -nsTransparencyMode nsCocoaWindow::GetTransparencyMode() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - return (!mWindow || [mWindow isOpaque]) ? eTransparencyOpaque : eTransparencyTransparent; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(eTransparencyOpaque); -} - -// This is called from nsMenuPopupFrame when making a popup transparent, or -// from nsChildView::SetTransparencyMode for other window types. -void nsCocoaWindow::SetTransparencyMode(nsTransparencyMode aMode) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mWindow) - return; - - // Transparent windows are only supported on popups. - BOOL isTransparent = aMode == eTransparencyTransparent && - mWindowType == eWindowType_popup; - BOOL currentTransparency = ![mWindow isOpaque]; - if (isTransparent != currentTransparency) { - [mWindow setOpaque:!isTransparent]; - [mWindow setBackgroundColor:(isTransparent ? [NSColor clearColor] : [NSColor whiteColor])]; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -NS_IMETHODIMP nsCocoaWindow::Enable(bool aState) -{ - return NS_OK; -} - -bool nsCocoaWindow::IsEnabled() const -{ - return true; -} - -#define kWindowPositionSlop 20 - -void -nsCocoaWindow::ConstrainPosition(bool aAllowSlop, int32_t *aX, int32_t *aY) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mWindow || ![mWindow screen]) { - return; - } - - nsIntRect screenBounds; - - int32_t width, height; - - NSRect frame = [mWindow frame]; - - // zero size rects confuse the screen manager - width = std::max(frame.size.width, 1); - height = std::max(frame.size.height, 1); - - nsCOMPtr screenMgr = do_GetService("@mozilla.org/gfx/screenmanager;1"); - if (screenMgr) { - nsCOMPtr screen; - screenMgr->ScreenForRect(*aX, *aY, width, height, getter_AddRefs(screen)); - - if (screen) { - screen->GetRectDisplayPix(&(screenBounds.x), &(screenBounds.y), - &(screenBounds.width), &(screenBounds.height)); - } - } - - if (aAllowSlop) { - if (*aX < screenBounds.x - width + kWindowPositionSlop) { - *aX = screenBounds.x - width + kWindowPositionSlop; - } else if (*aX >= screenBounds.x + screenBounds.width - kWindowPositionSlop) { - *aX = screenBounds.x + screenBounds.width - kWindowPositionSlop; - } - - if (*aY < screenBounds.y - height + kWindowPositionSlop) { - *aY = screenBounds.y - height + kWindowPositionSlop; - } else if (*aY >= screenBounds.y + screenBounds.height - kWindowPositionSlop) { - *aY = screenBounds.y + screenBounds.height - kWindowPositionSlop; - } - } else { - if (*aX < screenBounds.x) { - *aX = screenBounds.x; - } else if (*aX >= screenBounds.x + screenBounds.width - width) { - *aX = screenBounds.x + screenBounds.width - width; - } - - if (*aY < screenBounds.y) { - *aY = screenBounds.y; - } else if (*aY >= screenBounds.y + screenBounds.height - height) { - *aY = screenBounds.y + screenBounds.height - height; - } - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void nsCocoaWindow::SetSizeConstraints(const SizeConstraints& aConstraints) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // Popups can be smaller than (60, 60) - NSRect rect = - (mWindowType == eWindowType_popup) ? NSZeroRect : NSMakeRect(0.0, 0.0, 60, 60); - rect = [mWindow frameRectForContentRect:rect]; - - CGFloat scaleFactor = BackingScaleFactor(); - - SizeConstraints c = aConstraints; - c.mMinSize.width = - std::max(nsCocoaUtils::CocoaPointsToDevPixels(rect.size.width, scaleFactor), - c.mMinSize.width); - c.mMinSize.height = - std::max(nsCocoaUtils::CocoaPointsToDevPixels(rect.size.height, scaleFactor), - c.mMinSize.height); - - NSSize minSize = { - nsCocoaUtils::DevPixelsToCocoaPoints(c.mMinSize.width, scaleFactor), - nsCocoaUtils::DevPixelsToCocoaPoints(c.mMinSize.height, scaleFactor) - }; - [mWindow setMinSize:minSize]; - - NSSize maxSize = { - c.mMaxSize.width == NS_MAXSIZE ? - FLT_MAX : nsCocoaUtils::DevPixelsToCocoaPoints(c.mMaxSize.width, scaleFactor), - c.mMaxSize.height == NS_MAXSIZE ? - FLT_MAX : nsCocoaUtils::DevPixelsToCocoaPoints(c.mMaxSize.height, scaleFactor) - }; - [mWindow setMaxSize:maxSize]; - - nsBaseWidget::SetSizeConstraints(c); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// Coordinates are desktop pixels -NS_IMETHODIMP nsCocoaWindow::Move(double aX, double aY) -{ - if (!mWindow) { - return NS_OK; - } - - // The point we have is in Gecko coordinates (origin top-left). Convert - // it to Cocoa ones (origin bottom-left). - NSPoint coord = { - static_cast(aX), - static_cast(nsCocoaUtils::FlippedScreenY(NSToIntRound(aY))) - }; - - NSRect frame = [mWindow frame]; - if (frame.origin.x != coord.x || - frame.origin.y + frame.size.height != coord.y) { - [mWindow setFrameTopLeftPoint:coord]; - } - - return NS_OK; -} - -void -nsCocoaWindow::SetSizeMode(nsSizeMode aMode) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mWindow) - return; - - // mSizeMode will be updated in DispatchSizeModeEvent, which will be called - // from a delegate method that handles the state change during one of the - // calls below. - nsSizeMode previousMode = mSizeMode; - - if (aMode == nsSizeMode_Normal) { - if ([mWindow isMiniaturized]) - [mWindow deminiaturize:nil]; - else if (previousMode == nsSizeMode_Maximized && [mWindow isZoomed]) - [mWindow zoom:nil]; - } - else if (aMode == nsSizeMode_Minimized) { - if (![mWindow isMiniaturized]) - [mWindow miniaturize:nil]; - } - else if (aMode == nsSizeMode_Maximized) { - if ([mWindow isMiniaturized]) - [mWindow deminiaturize:nil]; - if (![mWindow isZoomed]) - [mWindow zoom:nil]; - } - else if (aMode == nsSizeMode_Fullscreen) { - if (!mInFullScreenMode) - MakeFullScreen(true); - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// This has to preserve the window's frame bounds. -// This method requires (as does the Windows impl.) that you call Resize shortly -// after calling HideWindowChrome. See bug 498835 for fixing this. -NS_IMETHODIMP nsCocoaWindow::HideWindowChrome(bool aShouldHide) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (!mWindow || !mWindowMadeHere || - (mWindowType != eWindowType_toplevel && mWindowType != eWindowType_dialog)) - return NS_ERROR_FAILURE; - - BOOL isVisible = [mWindow isVisible]; - - // Remove child windows. - NSArray* childWindows = [mWindow childWindows]; - NSEnumerator* enumerator = [childWindows objectEnumerator]; - NSWindow* child = nil; - while ((child = [enumerator nextObject])) { - [mWindow removeChildWindow:child]; - } - - // Remove the content view. - NSView* contentView = [mWindow contentView]; - [contentView retain]; - [contentView removeFromSuperviewWithoutNeedingDisplay]; - - // Save state (like window title). - NSMutableDictionary* state = [mWindow exportState]; - - // Recreate the window with the right border style. - NSRect frameRect = [mWindow frame]; - DestroyNativeWindow(); - nsresult rv = CreateNativeWindow(frameRect, aShouldHide ? eBorderStyle_none : mBorderStyle, true); - NS_ENSURE_SUCCESS(rv, rv); - - // Re-import state. - [mWindow importState:state]; - - // Reparent the content view. - [mWindow setContentView:contentView]; - [contentView release]; - - // Reparent child windows. - enumerator = [childWindows objectEnumerator]; - while ((child = [enumerator nextObject])) { - [mWindow addChildWindow:child ordered:NSWindowAbove]; - } - - // Show the new window. - if (isVisible) { - bool wasAnimationSuppressed = mIsAnimationSuppressed; - mIsAnimationSuppressed = true; - rv = Show(true); - mIsAnimationSuppressed = wasAnimationSuppressed; - NS_ENSURE_SUCCESS(rv, rv); - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -class FullscreenTransitionData : public nsISupports -{ -public: - NS_DECL_ISUPPORTS - - explicit FullscreenTransitionData(NSWindow* aWindow) - : mTransitionWindow(aWindow) { } - - NSWindow* mTransitionWindow; - -private: - virtual ~FullscreenTransitionData() - { - [mTransitionWindow close]; - } -}; - -NS_IMPL_ISUPPORTS0(FullscreenTransitionData) - -@interface FullscreenTransitionDelegate : NSObject -{ -@public - nsCocoaWindow* mWindow; - nsIRunnable* mCallback; -} -@end - -@implementation FullscreenTransitionDelegate -- (void)cleanupAndDispatch:(NSAnimation* )animation -{ - [animation setDelegate:nil]; - [self autorelease]; - // The caller should have added ref for us. - NS_DispatchToMainThread(already_AddRefed(mCallback)); -} - -- (void)animationDidEnd:(NSAnimation *)animation -{ - MOZ_ASSERT(animation == mWindow->FullscreenTransitionAnimation(), - "Should be handling the only animation on the window"); - mWindow->ReleaseFullscreenTransitionAnimation(); - [self cleanupAndDispatch:animation]; -} - -- (void)animationDidStop:(NSAnimation *)animation -{ - [self cleanupAndDispatch:animation]; -} -@end - -/* virtual */ bool -nsCocoaWindow::PrepareForFullscreenTransition(nsISupports** aData) -{ - nsCOMPtr widgetScreen = GetWidgetScreen(); - nsScreenCocoa* screen = static_cast(widgetScreen.get()); - NSScreen* cocoaScreen = screen->CocoaScreen(); - - NSWindow* win = - [[NSWindow alloc] initWithContentRect:[cocoaScreen frame] - styleMask:NSBorderlessWindowMask - backing:NSBackingStoreBuffered - defer:YES]; - [win setBackgroundColor:[NSColor blackColor]]; - [win setAlphaValue:0]; - [win setIgnoresMouseEvents:YES]; - [win setLevel:NSScreenSaverWindowLevel]; - [win makeKeyAndOrderFront:nil]; - - auto data = new FullscreenTransitionData(win); - *aData = data; - NS_ADDREF(data); - return true; -} - -/* virtual */ void -nsCocoaWindow::PerformFullscreenTransition(FullscreenTransitionStage aStage, - uint16_t aDuration, - nsISupports* aData, - nsIRunnable* aCallback) -{ - auto data = static_cast(aData); - FullscreenTransitionDelegate* delegate = - [[FullscreenTransitionDelegate alloc] init]; - delegate->mWindow = this; - // Storing already_AddRefed directly could cause static checking fail. - delegate->mCallback = nsCOMPtr(aCallback).forget().take(); - - if (mFullscreenTransitionAnimation) { - [mFullscreenTransitionAnimation stopAnimation]; - ReleaseFullscreenTransitionAnimation(); - } - - NSDictionary* dict = @{ - NSViewAnimationTargetKey: data->mTransitionWindow, - NSViewAnimationEffectKey: aStage == eBeforeFullscreenToggle ? - NSViewAnimationFadeInEffect : NSViewAnimationFadeOutEffect - }; - mFullscreenTransitionAnimation = - [[NSViewAnimation alloc] initWithViewAnimations:@[dict]]; - [mFullscreenTransitionAnimation setDelegate:delegate]; - [mFullscreenTransitionAnimation setDuration:aDuration / 1000.0]; - [mFullscreenTransitionAnimation startAnimation]; -} - -void nsCocoaWindow::EnteredFullScreen(bool aFullScreen, bool aNativeMode) -{ - mInFullScreenTransition = false; - bool wasInFullscreen = mInFullScreenMode; - mInFullScreenMode = aFullScreen; - if (aNativeMode || mInNativeFullScreenMode) { - mInNativeFullScreenMode = aFullScreen; - } - DispatchSizeModeEvent(); - if (mWidgetListener && wasInFullscreen != aFullScreen) { - mWidgetListener->FullscreenChanged(aFullScreen); - } -} - -inline bool -nsCocoaWindow::ShouldToggleNativeFullscreen(bool aFullScreen, - bool aUseSystemTransition) -{ - if (!mSupportsNativeFullScreen) { - // If we cannot use native fullscreen, don't touch it. - return false; - } - if (mInNativeFullScreenMode) { - // If we are using native fullscreen, go ahead to exit it. - return true; - } - if (!aUseSystemTransition) { - // If we do not want the system fullscreen transition, - // don't use the native fullscreen. - return false; - } - // If we are using native fullscreen, we should have returned earlier. - return aFullScreen; -} - -nsresult -nsCocoaWindow::MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen) -{ - return DoMakeFullScreen(aFullScreen, false); -} - -NS_IMETHODIMP -nsCocoaWindow::MakeFullScreenWithNativeTransition(bool aFullScreen, - nsIScreen* aTargetScreen) -{ - return DoMakeFullScreen(aFullScreen, true); -} - -nsresult -nsCocoaWindow::DoMakeFullScreen(bool aFullScreen, bool aUseSystemTransition) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (!mWindow) { - return NS_OK; - } - - // We will call into MakeFullScreen redundantly when entering/exiting - // fullscreen mode via OS X controls. When that happens we should just handle - // it gracefully - no need to ASSERT. - if (mInFullScreenMode == aFullScreen) { - return NS_OK; - } - - mInFullScreenTransition = true; - - if (ShouldToggleNativeFullscreen(aFullScreen, aUseSystemTransition)) { - // If we're using native fullscreen mode and our native window is invisible, - // our attempt to go into fullscreen mode will fail with an assertion in - // system code, without [WindowDelegate windowDidFailToEnterFullScreen:] - // ever getting called. To pre-empt this we bail here. See bug 752294. - if (aFullScreen && ![mWindow isVisible]) { - EnteredFullScreen(false); - return NS_OK; - } - MOZ_ASSERT(mInNativeFullScreenMode != aFullScreen, - "We shouldn't have been in native fullscreen."); - // Calling toggleFullScreen will result in windowDid(FailTo)?(Enter|Exit)FullScreen - // to be called from the OS. We will call EnteredFullScreen from those methods, - // where mInFullScreenMode will be set and a sizemode event will be dispatched. - [mWindow toggleFullScreen:nil]; - } else { - NSDisableScreenUpdates(); - // The order here matters. When we exit full screen mode, we need to show the - // Dock first, otherwise the newly-created window won't have its minimize - // button enabled. See bug 526282. - nsCocoaUtils::HideOSChromeOnScreen(aFullScreen); - nsBaseWidget::InfallibleMakeFullScreen(aFullScreen); - NSEnableScreenUpdates(); - EnteredFullScreen(aFullScreen, /* aNativeMode */ false); - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -// Coordinates are desktop pixels -nsresult nsCocoaWindow::DoResize(double aX, double aY, - double aWidth, double aHeight, - bool aRepaint, - bool aConstrainToCurrentScreen) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (!mWindow || mInResize) { - return NS_OK; - } - - AutoRestore reentrantResizeGuard(mInResize); - mInResize = true; - - // ConstrainSize operates in device pixels, so we need to convert using - // the backing scale factor here - CGFloat scale = BackingScaleFactor(); - int32_t width = NSToIntRound(aWidth * scale); - int32_t height = NSToIntRound(aHeight * scale); - ConstrainSize(&width, &height); - - DesktopIntRect newBounds(NSToIntRound(aX), NSToIntRound(aY), - NSToIntRound(width / scale), - NSToIntRound(height / scale)); - - // constrain to the screen that contains the largest area of the new rect - FitRectToVisibleAreaForScreen(newBounds, aConstrainToCurrentScreen ? - [mWindow screen] : nullptr); - - // convert requested bounds into Cocoa coordinate system - NSRect newFrame = nsCocoaUtils::GeckoRectToCocoaRect(newBounds); - - NSRect frame = [mWindow frame]; - BOOL isMoving = newFrame.origin.x != frame.origin.x || - newFrame.origin.y != frame.origin.y; - BOOL isResizing = newFrame.size.width != frame.size.width || - newFrame.size.height != frame.size.height; - - if (!isMoving && !isResizing) { - return NS_OK; - } - - // We ignore aRepaint -- we have to call display:YES, otherwise the - // title bar doesn't immediately get repainted and is displayed in - // the wrong place, leading to a visual jump. - [mWindow setFrame:newFrame display:YES]; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -// Coordinates are desktop pixels -NS_IMETHODIMP nsCocoaWindow::Resize(double aX, double aY, - double aWidth, double aHeight, - bool aRepaint) -{ - return DoResize(aX, aY, aWidth, aHeight, aRepaint, false); -} - -// Coordinates are desktop pixels -NS_IMETHODIMP nsCocoaWindow::Resize(double aWidth, double aHeight, bool aRepaint) -{ - double invScale = 1.0 / BackingScaleFactor(); - return DoResize(mBounds.x * invScale, mBounds.y * invScale, - aWidth, aHeight, aRepaint, true); -} - -LayoutDeviceIntRect -nsCocoaWindow::GetClientBounds() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - CGFloat scaleFactor = BackingScaleFactor(); - if (!mWindow) { - return nsCocoaUtils::CocoaRectToGeckoRectDevPix(NSZeroRect, scaleFactor); - } - - NSRect r; - if ([mWindow isKindOfClass:[ToolbarWindow class]] && - [(ToolbarWindow*)mWindow drawsContentsIntoWindowFrame]) { - r = [mWindow frame]; - } else { - r = [mWindow contentRectForFrameRect:[mWindow frame]]; - } - - return nsCocoaUtils::CocoaRectToGeckoRectDevPix(r, scaleFactor); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(LayoutDeviceIntRect(0, 0, 0, 0)); -} - -void -nsCocoaWindow::UpdateBounds() -{ - NSRect frame = NSZeroRect; - if (mWindow) { - frame = [mWindow frame]; - } - mBounds = - nsCocoaUtils::CocoaRectToGeckoRectDevPix(frame, BackingScaleFactor()); -} - -LayoutDeviceIntRect -nsCocoaWindow::GetScreenBounds() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - -#ifdef DEBUG - LayoutDeviceIntRect r = nsCocoaUtils::CocoaRectToGeckoRectDevPix([mWindow frame], BackingScaleFactor()); - NS_ASSERTION(mWindow && mBounds == r, "mBounds out of sync!"); -#endif - - return mBounds; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(LayoutDeviceIntRect(0, 0, 0, 0)); -} - -double -nsCocoaWindow::GetDefaultScaleInternal() -{ - return BackingScaleFactor(); -} - -static CGFloat -GetBackingScaleFactor(NSWindow* aWindow) -{ - NSRect frame = [aWindow frame]; - if (frame.size.width > 0 && frame.size.height > 0) { - return nsCocoaUtils::GetBackingScaleFactor(aWindow); - } - - // For windows with zero width or height, the backingScaleFactor method - // is broken - it will always return 2 on a retina macbook, even when - // the window position implies it's on a non-hidpi external display - // (to the extent that a zero-area window can be said to be "on" a - // display at all!) - // And to make matters worse, Cocoa even fires a - // windowDidChangeBackingProperties notification with the - // NSBackingPropertyOldScaleFactorKey key when a window on an - // external display is resized to/from zero height, even though it hasn't - // really changed screens. - - // This causes us to handle popup window sizing incorrectly when the - // popup is resized to zero height (bug 820327) - nsXULPopupManager - // becomes (incorrectly) convinced the popup has been explicitly forced - // to a non-default size and needs to have size attributes attached. - - // Workaround: instead of asking the window, we'll find the screen it is on - // and ask that for *its* backing scale factor. - - // (See bug 853252 and additional comments in windowDidChangeScreen: below - // for further complications this causes.) - - // First, expand the rect so that it actually has a measurable area, - // for FindTargetScreenForRect to use. - if (frame.size.width == 0) { - frame.size.width = 1; - } - if (frame.size.height == 0) { - frame.size.height = 1; - } - - // Then identify the screen it belongs to, and return its scale factor. - NSScreen *screen = - FindTargetScreenForRect(nsCocoaUtils::CocoaRectToGeckoRect(frame)); - return nsCocoaUtils::GetBackingScaleFactor(screen); -} - -CGFloat -nsCocoaWindow::BackingScaleFactor() -{ - if (mBackingScaleFactor > 0.0) { - return mBackingScaleFactor; - } - if (!mWindow) { - return 1.0; - } - mBackingScaleFactor = GetBackingScaleFactor(mWindow); - return mBackingScaleFactor; -} - -void -nsCocoaWindow::BackingScaleFactorChanged() -{ - CGFloat newScale = GetBackingScaleFactor(mWindow); - - // ignore notification if it hasn't really changed (or maybe we have - // disabled HiDPI mode via prefs) - if (mBackingScaleFactor == newScale) { - return; - } - - if (mBackingScaleFactor > 0.0) { - // convert size constraints to the new device pixel coordinate space - double scaleFactor = newScale / mBackingScaleFactor; - mSizeConstraints.mMinSize.width = - NSToIntRound(mSizeConstraints.mMinSize.width * scaleFactor); - mSizeConstraints.mMinSize.height = - NSToIntRound(mSizeConstraints.mMinSize.height * scaleFactor); - if (mSizeConstraints.mMaxSize.width < NS_MAXSIZE) { - mSizeConstraints.mMaxSize.width = - std::min(NS_MAXSIZE, - NSToIntRound(mSizeConstraints.mMaxSize.width * scaleFactor)); - } - if (mSizeConstraints.mMaxSize.height < NS_MAXSIZE) { - mSizeConstraints.mMaxSize.height = - std::min(NS_MAXSIZE, - NSToIntRound(mSizeConstraints.mMaxSize.height * scaleFactor)); - } - } - - mBackingScaleFactor = newScale; - - if (!mWidgetListener || mWidgetListener->GetXULWindow()) { - return; - } - - nsIPresShell* presShell = mWidgetListener->GetPresShell(); - if (presShell) { - presShell->BackingScaleFactorChanged(); - } -} - -int32_t -nsCocoaWindow::RoundsWidgetCoordinatesTo() -{ - if (BackingScaleFactor() == 2.0) { - return 2; - } - return 1; -} - -NS_IMETHODIMP nsCocoaWindow::SetCursor(nsCursor aCursor) -{ - if (mPopupContentView) - return mPopupContentView->SetCursor(aCursor); - - return NS_OK; -} - -NS_IMETHODIMP nsCocoaWindow::SetCursor(imgIContainer* aCursor, - uint32_t aHotspotX, uint32_t aHotspotY) -{ - if (mPopupContentView) - return mPopupContentView->SetCursor(aCursor, aHotspotX, aHotspotY); - - return NS_OK; -} - -NS_IMETHODIMP nsCocoaWindow::SetTitle(const nsAString& aTitle) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (!mWindow) - return NS_OK; - - const nsString& strTitle = PromiseFlatString(aTitle); - NSString* title = [NSString stringWithCharacters:reinterpret_cast(strTitle.get()) - length:strTitle.Length()]; - - if ([mWindow drawsContentsIntoWindowFrame] && ![mWindow wantsTitleDrawn]) { - // Don't cause invalidations. - [mWindow disableSetNeedsDisplay]; - [mWindow setTitle:title]; - [mWindow enableSetNeedsDisplay]; - } else { - [mWindow setTitle:title]; - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP nsCocoaWindow::Invalidate(const LayoutDeviceIntRect& aRect) -{ - if (mPopupContentView) { - return mPopupContentView->Invalidate(aRect); - } - - return NS_OK; -} - -// Pass notification of some drag event to Gecko -// -// The drag manager has let us know that something related to a drag has -// occurred in this window. It could be any number of things, ranging from -// a drop, to a drag enter/leave, or a drag over event. The actual event -// is passed in |aMessage| and is passed along to our event hanlder so Gecko -// knows about it. -bool nsCocoaWindow::DragEvent(unsigned int aMessage, mozilla::gfx::Point aMouseGlobal, UInt16 aKeyModifiers) -{ - return false; -} - -NS_IMETHODIMP nsCocoaWindow::SendSetZLevelEvent() -{ - nsWindowZ placement = nsWindowZTop; - nsCOMPtr actualBelow; - if (mWidgetListener) - mWidgetListener->ZLevelChanged(true, &placement, nullptr, getter_AddRefs(actualBelow)); - return NS_OK; -} - -NS_IMETHODIMP nsCocoaWindow::GetChildSheet(bool aShown, nsIWidget** _retval) -{ - nsIWidget* child = GetFirstChild(); - - while (child) { - if (child->WindowType() == eWindowType_sheet) { - // if it's a sheet, it must be an nsCocoaWindow - nsCocoaWindow* cocoaWindow = static_cast(child); - if (cocoaWindow->mWindow && - ((aShown && [cocoaWindow->mWindow isVisible]) || - (!aShown && cocoaWindow->mSheetNeedsShow))) { - nsCOMPtr widget = cocoaWindow; - widget.forget(_retval); - return NS_OK; - } - } - child = child->GetNextSibling(); - } - - *_retval = nullptr; - - return NS_OK; -} - -NS_IMETHODIMP nsCocoaWindow::GetRealParent(nsIWidget** parent) -{ - *parent = mParent; - return NS_OK; -} - -NS_IMETHODIMP nsCocoaWindow::GetIsSheet(bool* isSheet) -{ - mWindowType == eWindowType_sheet ? *isSheet = true : *isSheet = false; - return NS_OK; -} - -NS_IMETHODIMP nsCocoaWindow::GetSheetWindowParent(NSWindow** sheetWindowParent) -{ - *sheetWindowParent = mSheetWindowParent; - return NS_OK; -} - -// Invokes callback and ProcessEvent methods on Event Listener object -NS_IMETHODIMP -nsCocoaWindow::DispatchEvent(WidgetGUIEvent* event, nsEventStatus& aStatus) -{ - aStatus = nsEventStatus_eIgnore; - - nsCOMPtr kungFuDeathGrip(event->mWidget); - mozilla::Unused << kungFuDeathGrip; // Not used within this function - - if (mWidgetListener) - aStatus = mWidgetListener->HandleEvent(event, mUseAttachedEvents); - - return NS_OK; -} - -// aFullScreen should be the window's mInFullScreenMode. We don't have access to that -// from here, so we need to pass it in. mInFullScreenMode should be the canonical -// indicator that a window is currently full screen and it makes sense to keep -// all sizemode logic here. -static nsSizeMode -GetWindowSizeMode(NSWindow* aWindow, bool aFullScreen) { - if (aFullScreen) - return nsSizeMode_Fullscreen; - if ([aWindow isMiniaturized]) - return nsSizeMode_Minimized; - if (([aWindow styleMask] & NSResizableWindowMask) && [aWindow isZoomed]) - return nsSizeMode_Maximized; - return nsSizeMode_Normal; -} - -void -nsCocoaWindow::ReportMoveEvent() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // Prevent recursion, which can become infinite (see bug 708278). This - // can happen when the call to [NSWindow setFrameTopLeftPoint:] in - // nsCocoaWindow::Move() triggers an immediate NSWindowDidMove notification - // (and a call to [WindowDelegate windowDidMove:]). - if (mInReportMoveEvent) { - return; - } - mInReportMoveEvent = true; - - UpdateBounds(); - - // Dispatch the move event to Gecko - NotifyWindowMoved(mBounds.x, mBounds.y); - - mInReportMoveEvent = false; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void -nsCocoaWindow::DispatchSizeModeEvent() -{ - if (!mWindow) { - return; - } - - nsSizeMode newMode = GetWindowSizeMode(mWindow, mInFullScreenMode); - - // Don't dispatch a sizemode event if: - // 1. the window is transitioning to fullscreen - // 2. the new sizemode is the same as the current sizemode - if (mInFullScreenTransition || mSizeMode == newMode) { - return; - } - - mSizeMode = newMode; - if (mWidgetListener) { - mWidgetListener->SizeModeChanged(newMode); - } -} - -void -nsCocoaWindow::ReportSizeEvent() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - UpdateBounds(); - - if (mWidgetListener) { - LayoutDeviceIntRect innerBounds = GetClientBounds(); - mWidgetListener->WindowResized(this, innerBounds.width, innerBounds.height); - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void nsCocoaWindow::SetMenuBar(nsMenuBarX *aMenuBar) -{ - if (mMenuBar) - mMenuBar->SetParent(nullptr); - if (!mWindow) { - mMenuBar = nullptr; - return; - } - mMenuBar = aMenuBar; - - // Only paint for active windows, or paint the hidden window menu bar if no - // other menu bar has been painted yet so that some reasonable menu bar is - // displayed when the app starts up. - id windowDelegate = [mWindow delegate]; - if (mMenuBar && - ((!gSomeMenuBarPainted && nsMenuUtilsX::GetHiddenWindowMenuBar() == mMenuBar) || - (windowDelegate && [windowDelegate toplevelActiveState]))) - mMenuBar->Paint(); -} - -NS_IMETHODIMP nsCocoaWindow::SetFocus(bool aState) -{ - if (!mWindow) - return NS_OK; - - if (mPopupContentView) { - mPopupContentView->SetFocus(aState); - } - else if (aState && ([mWindow isVisible] || [mWindow isMiniaturized])) { - if ([mWindow isMiniaturized]) { - [mWindow deminiaturize:nil]; - } - - [mWindow makeKeyAndOrderFront:nil]; - SendSetZLevelEvent(); - } - - return NS_OK; -} - -LayoutDeviceIntPoint nsCocoaWindow::WidgetToScreenOffset() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - NSRect rect = NSZeroRect; - LayoutDeviceIntRect r; - if (mWindow) { - rect = [mWindow contentRectForFrameRect:[mWindow frame]]; - } - r = nsCocoaUtils::CocoaRectToGeckoRectDevPix(rect, BackingScaleFactor()); - - return r.TopLeft(); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(LayoutDeviceIntPoint(0,0)); -} - -LayoutDeviceIntPoint nsCocoaWindow::GetClientOffset() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - LayoutDeviceIntRect clientRect = GetClientBounds(); - - return clientRect.TopLeft() - mBounds.TopLeft(); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(LayoutDeviceIntPoint(0, 0)); -} - -LayoutDeviceIntSize -nsCocoaWindow::ClientToWindowSize(const LayoutDeviceIntSize& aClientSize) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - if (!mWindow) - return LayoutDeviceIntSize(0, 0); - - CGFloat backingScale = BackingScaleFactor(); - LayoutDeviceIntRect r(0, 0, aClientSize.width, aClientSize.height); - NSRect rect = nsCocoaUtils::DevPixelsToCocoaPoints(r, backingScale); - - NSRect inflatedRect = [mWindow frameRectForContentRect:rect]; - r = nsCocoaUtils::CocoaRectToGeckoRectDevPix(inflatedRect, backingScale); - return r.Size(); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(LayoutDeviceIntSize(0,0)); -} - -nsMenuBarX* nsCocoaWindow::GetMenuBar() -{ - return mMenuBar; -} - -void -nsCocoaWindow::CaptureRollupEvents(nsIRollupListener* aListener, - bool aDoCapture) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - gRollupListener = nullptr; - - if (aDoCapture) { - if (![NSApp isActive]) { - // We need to capture mouse event if we aren't - // the active application. We only set this up when needed - // because they cause spurious mouse event after crash - // and gdb sessions. See bug 699538. - nsToolkit::GetToolkit()->RegisterForAllProcessMouseEvents(); - } - gRollupListener = aListener; - - // Sometimes more than one popup window can be visible at the same time - // (e.g. nested non-native context menus, or the test case (attachment - // 276885) for bmo bug 392389, which displays a non-native combo-box in a - // non-native popup window). In these cases the "active" popup window should - // be the topmost -- the (nested) context menu the mouse is currently over, - // or the combo-box's drop-down list (when it's displayed). But (among - // windows that have the same "level") OS X makes topmost the window that - // last received a mouse-down event, which may be incorrect (in the combo- - // box case, it makes topmost the window containing the combo-box). So - // here we fiddle with a non-native popup window's level to make sure the - // "active" one is always above any other non-native popup windows that - // may be visible. - if (mWindow && (mWindowType == eWindowType_popup)) - SetPopupWindowLevel(); - } else { - nsToolkit::GetToolkit()->UnregisterAllProcessMouseEventHandlers(); - - // XXXndeakin this doesn't make sense. - // Why is the new window assumed to be a modal panel? - if (mWindow && (mWindowType == eWindowType_popup)) - [mWindow setLevel:NSModalPanelWindowLevel]; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -NS_IMETHODIMP nsCocoaWindow::GetAttention(int32_t aCycleCount) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - [NSApp requestUserAttention:NSInformationalRequest]; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -bool -nsCocoaWindow::HasPendingInputEvent() -{ - return nsChildView::DoHasPendingInputEvent(); -} - -void -nsCocoaWindow::SetWindowShadowStyle(int32_t aStyle) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mWindow) - return; - - mShadowStyle = aStyle; - - // Shadowless windows are only supported on popups. - if (mWindowType == eWindowType_popup) - [mWindow setHasShadow:(aStyle != NS_STYLE_WINDOW_SHADOW_NONE)]; - - [mWindow setUseMenuStyle:(aStyle == NS_STYLE_WINDOW_SHADOW_MENU)]; - AdjustWindowShadow(); - SetWindowBackgroundBlur(); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void nsCocoaWindow::SetShowsToolbarButton(bool aShow) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (mWindow) - [mWindow setShowsToolbarButton:aShow]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void nsCocoaWindow::SetShowsFullScreenButton(bool aShow) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mWindow || ![mWindow respondsToSelector:@selector(toggleFullScreen:)] || - mSupportsNativeFullScreen == aShow) { - return; - } - - // If the window is currently in fullscreen mode, then we're going to - // transition out first, then set the collection behavior & toggle - // mSupportsNativeFullScreen, then transtion back into fullscreen mode. This - // prevents us from getting into a conflicting state with MakeFullScreen - // where mSupportsNativeFullScreen would lead us down the wrong path. - bool wasFullScreen = mInFullScreenMode; - - if (wasFullScreen) { - MakeFullScreen(false); - } - - NSWindowCollectionBehavior newBehavior = [mWindow collectionBehavior]; - if (aShow) { - newBehavior |= NSWindowCollectionBehaviorFullScreenPrimary; - } else { - newBehavior &= ~NSWindowCollectionBehaviorFullScreenPrimary; - } - [mWindow setCollectionBehavior:newBehavior]; - mSupportsNativeFullScreen = aShow; - - if (wasFullScreen) { - MakeFullScreen(true); - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void nsCocoaWindow::SetWindowAnimationType(nsIWidget::WindowAnimationType aType) -{ - mAnimationType = aType; -} - -void -nsCocoaWindow::SetDrawsTitle(bool aDrawTitle) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mWindow setWantsTitleDrawn:aDrawTitle]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void -nsCocoaWindow::SetUseBrightTitlebarForeground(bool aBrightForeground) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mWindow setUseBrightTitlebarForeground:aBrightForeground]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -NS_IMETHODIMP nsCocoaWindow::SetNonClientMargins(LayoutDeviceIntMargin &margins) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - SetDrawsInTitlebar(margins.top == 0); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -void -nsCocoaWindow::SetWindowTitlebarColor(nscolor aColor, bool aActive) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mWindow) - return; - - // If they pass a color with a complete transparent alpha component, use the - // native titlebar appearance. - if (NS_GET_A(aColor) == 0) { - [mWindow setTitlebarColor:nil forActiveWindow:(BOOL)aActive]; - } else { - // Transform from sRGBA to monitor RGBA. This seems like it would make trying - // to match the system appearance lame, so probably we just shouldn't color - // correct chrome. - if (gfxPlatform::GetCMSMode() == eCMSMode_All) { - qcms_transform *transform = gfxPlatform::GetCMSRGBATransform(); - if (transform) { - uint8_t color[3]; - color[0] = NS_GET_R(aColor); - color[1] = NS_GET_G(aColor); - color[2] = NS_GET_B(aColor); - qcms_transform_data(transform, color, color, 1); - aColor = NS_RGB(color[0], color[1], color[2]); - } - } - - [mWindow setTitlebarColor:[NSColor colorWithDeviceRed:NS_GET_R(aColor)/255.0 - green:NS_GET_G(aColor)/255.0 - blue:NS_GET_B(aColor)/255.0 - alpha:NS_GET_A(aColor)/255.0] - forActiveWindow:(BOOL)aActive]; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void nsCocoaWindow::SetDrawsInTitlebar(bool aState) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (mWindow) - [mWindow setDrawsContentsIntoWindowFrame:aState]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -NS_IMETHODIMP nsCocoaWindow::SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint, - uint32_t aNativeMessage, - uint32_t aModifierFlags, - nsIObserver* aObserver) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - AutoObserverNotifier notifier(aObserver, "mouseevent"); - if (mPopupContentView) - return mPopupContentView->SynthesizeNativeMouseEvent(aPoint, aNativeMessage, - aModifierFlags, nullptr); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -void nsCocoaWindow::UpdateThemeGeometries(const nsTArray& aThemeGeometries) { - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (mPopupContentView) { - return mPopupContentView->UpdateThemeGeometries(aThemeGeometries); - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void nsCocoaWindow::SetPopupWindowLevel() -{ - if (!mWindow) - return; - - // Floating popups are at the floating level and hide when the window is - // deactivated. - if (mPopupLevel == ePopupLevelFloating) { - [mWindow setLevel:NSFloatingWindowLevel]; - [mWindow setHidesOnDeactivate:YES]; - } - else { - // Otherwise, this is a top-level or parent popup. Parent popups always - // appear just above their parent and essentially ignore the level. - [mWindow setLevel:NSPopUpMenuWindowLevel]; - [mWindow setHidesOnDeactivate:NO]; - } -} - -NS_IMETHODIMP_(void) -nsCocoaWindow::SetInputContext(const InputContext& aContext, - const InputContextAction& aAction) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - mInputContext = aContext; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -NS_IMETHODIMP_(bool) -nsCocoaWindow::ExecuteNativeKeyBinding(NativeKeyBindingsType aType, - const WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData) -{ - NativeKeyBindings* keyBindings = NativeKeyBindings::GetInstance(aType); - return keyBindings->Execute(aEvent, aCallback, aCallbackData); -} - -@implementation WindowDelegate - -// We try to find a gecko menu bar to paint. If one does not exist, just paint -// the application menu by itself so that a window doesn't have some other -// window's menu bar. -+ (void)paintMenubarForWindow:(NSWindow*)aWindow -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // make sure we only act on windows that have this kind of - // object as a delegate - id windowDelegate = [aWindow delegate]; - if ([windowDelegate class] != [self class]) - return; - - nsCocoaWindow* geckoWidget = [windowDelegate geckoWidget]; - NS_ASSERTION(geckoWidget, "Window delegate not returning a gecko widget!"); - - nsMenuBarX* geckoMenuBar = geckoWidget->GetMenuBar(); - if (geckoMenuBar) { - geckoMenuBar->Paint(); - } - else { - // sometimes we don't have a native application menu early in launching - if (!sApplicationMenu) - return; - - NSMenu* mainMenu = [NSApp mainMenu]; - NS_ASSERTION([mainMenu numberOfItems] > 0, "Main menu does not have any items, something is terribly wrong!"); - - // Create a new menu bar. - // We create a GeckoNSMenu because all menu bar NSMenu objects should use that subclass for - // key handling reasons. - GeckoNSMenu* newMenuBar = [[GeckoNSMenu alloc] initWithTitle:@"MainMenuBar"]; - - // move the application menu from the existing menu bar to the new one - NSMenuItem* firstMenuItem = [[mainMenu itemAtIndex:0] retain]; - [mainMenu removeItemAtIndex:0]; - [newMenuBar insertItem:firstMenuItem atIndex:0]; - [firstMenuItem release]; - - // set our new menu bar as the main menu - [NSApp setMainMenu:newMenuBar]; - [newMenuBar release]; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (id)initWithGeckoWindow:(nsCocoaWindow*)geckoWind -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - [super init]; - mGeckoWindow = geckoWind; - mToplevelActiveState = false; - mHasEverBeenZoomed = false; - return self; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)proposedFrameSize -{ - RollUpPopups(); - - return proposedFrameSize; -} - -- (void)windowDidResize:(NSNotification *)aNotification -{ - BaseWindow* window = [aNotification object]; - [window updateTrackingArea]; - - if (!mGeckoWindow) - return; - - // Resizing might have changed our zoom state. - mGeckoWindow->DispatchSizeModeEvent(); - mGeckoWindow->ReportSizeEvent(); -} - -- (void)windowDidChangeScreen:(NSNotification *)aNotification -{ - if (!mGeckoWindow) - return; - - // Because of Cocoa's peculiar treatment of zero-size windows (see comments - // at GetBackingScaleFactor() above), we sometimes have a situation where - // our concept of backing scale (based on the screen where the zero-sized - // window is positioned) differs from Cocoa's idea (always based on the - // Retina screen, AFAICT, even when an external non-Retina screen is the - // primary display). - // - // As a result, if the window was created with zero size on an external - // display, but then made visible on the (secondary) Retina screen, we - // will *not* get a windowDidChangeBackingProperties notification for it. - // This leads to an incorrect GetDefaultScale(), and widget coordinate - // confusion, as per bug 853252. - // - // To work around this, we check for a backing scale mismatch when we - // receive a windowDidChangeScreen notification, as we will receive this - // even if Cocoa was already treating the zero-size window as having - // Retina backing scale. - NSWindow *window = (NSWindow *)[aNotification object]; - if ([window respondsToSelector:@selector(backingScaleFactor)]) { - if (GetBackingScaleFactor(window) != mGeckoWindow->BackingScaleFactor()) { - mGeckoWindow->BackingScaleFactorChanged(); - } - } - - mGeckoWindow->ReportMoveEvent(); -} - -// Lion's full screen mode will bypass our internal fullscreen tracking, so -// we need to catch it when we transition and call our own methods, which in -// turn will fire "fullscreen" events. -- (void)windowDidEnterFullScreen:(NSNotification *)notification -{ - if (!mGeckoWindow) { - return; - } - - mGeckoWindow->EnteredFullScreen(true); - - // On Yosemite, the NSThemeFrame class has two new properties -- - // titlebarView (an NSTitlebarView object) and titlebarContainerView (an - // NSTitlebarContainerView object). These are used to display the titlebar - // in fullscreen mode. In Safari they're not transparent. But in Firefox - // for some reason they are, which causes bug 1069658. The following code - // works around this Apple bug or design flaw. - NSWindow *window = (NSWindow *) [notification object]; - NSView *frameView = [[window contentView] superview]; - NSView *titlebarView = nil; - NSView *titlebarContainerView = nil; - if ([frameView respondsToSelector:@selector(titlebarView)]) { - titlebarView = [frameView titlebarView]; - } - if ([frameView respondsToSelector:@selector(titlebarContainerView)]) { - titlebarContainerView = [frameView titlebarContainerView]; - } - if ([titlebarView respondsToSelector:@selector(setTransparent:)]) { - [titlebarView setTransparent:NO]; - } - if ([titlebarContainerView respondsToSelector:@selector(setTransparent:)]) { - [titlebarContainerView setTransparent:NO]; - } -} - -- (void)windowDidExitFullScreen:(NSNotification *)notification -{ - if (!mGeckoWindow) { - return; - } - - mGeckoWindow->EnteredFullScreen(false); -} - -- (void)windowDidFailToEnterFullScreen:(NSWindow *)window -{ - if (!mGeckoWindow) { - return; - } - - mGeckoWindow->EnteredFullScreen(false); -} - -- (void)windowDidFailToExitFullScreen:(NSWindow *)window -{ - if (!mGeckoWindow) { - return; - } - - mGeckoWindow->EnteredFullScreen(true); -} - -- (void)windowDidBecomeMain:(NSNotification *)aNotification -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - RollUpPopups(); - ChildViewMouseTracker::ReEvaluateMouseEnterState(); - - // [NSApp _isRunningAppModal] will return true if we're running an OS dialog - // app modally. If one of those is up then we want it to retain its menu bar. - if ([NSApp _isRunningAppModal]) - return; - NSWindow* window = [aNotification object]; - if (window) - [WindowDelegate paintMenubarForWindow:window]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)windowDidResignMain:(NSNotification *)aNotification -{ - RollUpPopups(); - ChildViewMouseTracker::ReEvaluateMouseEnterState(); - - // [NSApp _isRunningAppModal] will return true if we're running an OS dialog - // app modally. If one of those is up then we want it to retain its menu bar. - if ([NSApp _isRunningAppModal]) - return; - RefPtr hiddenWindowMenuBar = nsMenuUtilsX::GetHiddenWindowMenuBar(); - if (hiddenWindowMenuBar) { - // printf("painting hidden window menu bar due to window losing main status\n"); - hiddenWindowMenuBar->Paint(); - } -} - -- (void)windowDidBecomeKey:(NSNotification *)aNotification -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - RollUpPopups(); - ChildViewMouseTracker::ReEvaluateMouseEnterState(); - - NSWindow* window = [aNotification object]; - if ([window isSheet]) - [WindowDelegate paintMenubarForWindow:window]; - - nsChildView* mainChildView = - static_cast([[(BaseWindow*)window mainChildView] widget]); - if (mainChildView) { - if (mainChildView->GetInputContext().IsPasswordEditor()) { - TextInputHandler::EnableSecureEventInput(); - } else { - TextInputHandler::EnsureSecureEventInputDisabled(); - } - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)windowDidResignKey:(NSNotification *)aNotification -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - RollUpPopups(); - ChildViewMouseTracker::ReEvaluateMouseEnterState(); - - // If a sheet just resigned key then we should paint the menu bar - // for whatever window is now main. - NSWindow* window = [aNotification object]; - if ([window isSheet]) - [WindowDelegate paintMenubarForWindow:[NSApp mainWindow]]; - - TextInputHandler::EnsureSecureEventInputDisabled(); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)windowWillMove:(NSNotification *)aNotification -{ - RollUpPopups(); -} - -- (void)windowDidMove:(NSNotification *)aNotification -{ - if (mGeckoWindow) - mGeckoWindow->ReportMoveEvent(); -} - -- (BOOL)windowShouldClose:(id)sender -{ - nsIWidgetListener* listener = mGeckoWindow ? mGeckoWindow->GetWidgetListener() : nullptr; - if (listener) - listener->RequestWindowClose(mGeckoWindow); - return NO; // gecko will do it -} - -- (void)windowWillClose:(NSNotification *)aNotification -{ - RollUpPopups(); -} - -- (void)windowWillMiniaturize:(NSNotification *)aNotification -{ - RollUpPopups(); -} - -- (void)windowDidMiniaturize:(NSNotification *)aNotification -{ - if (mGeckoWindow) - mGeckoWindow->DispatchSizeModeEvent(); -} - -- (void)windowDidDeminiaturize:(NSNotification *)aNotification -{ - if (mGeckoWindow) - mGeckoWindow->DispatchSizeModeEvent(); -} - -- (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)proposedFrame -{ - if (!mHasEverBeenZoomed && [window isZoomed]) - return NO; // See bug 429954. - - mHasEverBeenZoomed = YES; - return YES; -} - -- (void)didEndSheet:(NSWindow*)sheet returnCode:(int)returnCode contextInfo:(void*)contextInfo -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // Note: 'contextInfo' (if it is set) is the window that is the parent of - // the sheet. The value of contextInfo is determined in - // nsCocoaWindow::Show(). If it's set, 'contextInfo' is always the top- - // level window, not another sheet itself. But 'contextInfo' is nil if - // our parent window is also a sheet -- in that case we shouldn't send - // the top-level window any activate events (because it's our parent - // window that needs to get these events, not the top-level window). - [TopLevelWindowData deactivateInWindow:sheet]; - [sheet orderOut:self]; - if (contextInfo) - [TopLevelWindowData activateInWindow:(NSWindow*)contextInfo]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)windowDidChangeBackingProperties:(NSNotification *)aNotification -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - NSWindow *window = (NSWindow *)[aNotification object]; - - if ([window respondsToSelector:@selector(backingScaleFactor)]) { - CGFloat oldFactor = - [[[aNotification userInfo] - objectForKey:@"NSBackingPropertyOldScaleFactorKey"] doubleValue]; - if ([window backingScaleFactor] != oldFactor) { - mGeckoWindow->BackingScaleFactorChanged(); - } - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (nsCocoaWindow*)geckoWidget -{ - return mGeckoWindow; -} - -- (bool)toplevelActiveState -{ - return mToplevelActiveState; -} - -- (void)sendToplevelActivateEvents -{ - if (!mToplevelActiveState && mGeckoWindow) { - nsIWidgetListener* listener = mGeckoWindow->GetWidgetListener(); - if (listener) { - listener->WindowActivated(); - } - mToplevelActiveState = true; - } -} - -- (void)sendToplevelDeactivateEvents -{ - if (mToplevelActiveState && mGeckoWindow) { - nsIWidgetListener* listener = mGeckoWindow->GetWidgetListener(); - if (listener) { - listener->WindowDeactivated(); - } - mToplevelActiveState = false; - } -} - -@end - -static float -GetDPI(NSWindow* aWindow) -{ - NSScreen* screen = [aWindow screen]; - if (!screen) - return 96.0f; - - CGDirectDisplayID displayID = - [[[screen deviceDescription] objectForKey:@"NSScreenNumber"] intValue]; - CGFloat heightMM = ::CGDisplayScreenSize(displayID).height; - size_t heightPx = ::CGDisplayPixelsHigh(displayID); - if (heightMM < 1 || heightPx < 1) { - // Something extremely bogus is going on - return 96.0f; - } - - float dpi = heightPx / (heightMM / MM_PER_INCH_FLOAT); - - // Account for HiDPI mode where Cocoa's "points" do not correspond to real - // device pixels - CGFloat backingScale = GetBackingScaleFactor(aWindow); - - return dpi * backingScale; -} - -@interface NSView(FrameViewMethodSwizzling) -- (NSPoint)FrameView__closeButtonOrigin; -- (NSPoint)FrameView__fullScreenButtonOrigin; -@end - -@implementation NSView(FrameViewMethodSwizzling) - -- (NSPoint)FrameView__closeButtonOrigin -{ - NSPoint defaultPosition = [self FrameView__closeButtonOrigin]; - if ([[self window] isKindOfClass:[ToolbarWindow class]]) { - return [(ToolbarWindow*)[self window] windowButtonsPositionWithDefaultPosition:defaultPosition]; - } - return defaultPosition; -} - -- (NSPoint)FrameView__fullScreenButtonOrigin -{ - NSPoint defaultPosition = [self FrameView__fullScreenButtonOrigin]; - if ([[self window] isKindOfClass:[ToolbarWindow class]]) { - return [(ToolbarWindow*)[self window] fullScreenButtonPositionWithDefaultPosition:defaultPosition]; - } - return defaultPosition; -} - -@end - -static NSMutableSet *gSwizzledFrameViewClasses = nil; - -@interface NSWindow(PrivateSetNeedsDisplayInRectMethod) - - (void)_setNeedsDisplayInRect:(NSRect)aRect; -@end - -// This method is on NSThemeFrame starting with 10.10, but since NSThemeFrame -// is not a public class, we declare the method on NSView instead. We only have -// this declaration in order to avoid compiler warnings. -@interface NSView(PrivateAddKnownSubviewMethod) - - (void)_addKnownSubview:(NSView*)aView positioned:(NSWindowOrderingMode)place relativeTo:(NSView*)otherView; -@end - -#if !defined(MAC_OS_X_VERSION_10_10) || \ - MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_10 - -@interface NSImage(CapInsets) -- (void)setCapInsets:(NSEdgeInsets)capInsets; -@end - -#endif - -#if !defined(MAC_OS_X_VERSION_10_8) || \ - MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8 - -@interface NSImage(ImageCreationWithDrawingHandler) -+ (NSImage *)imageWithSize:(NSSize)size - flipped:(BOOL)drawingHandlerShouldBeCalledWithFlippedContext - drawingHandler:(BOOL (^)(NSRect dstRect))drawingHandler; -@end - -#endif - -@interface NSView(NSVisualEffectViewSetMaskImage) -- (void)setMaskImage:(NSImage*)image; -@end - -@interface BaseWindow(Private) -- (void)removeTrackingArea; -- (void)cursorUpdated:(NSEvent*)aEvent; -- (void)updateContentViewSize; -- (void)reflowTitlebarElements; -@end - -@implementation BaseWindow - -// The frame of a window is implemented using undocumented NSView subclasses. -// We offset the window buttons by overriding the methods _closeButtonOrigin -// and _fullScreenButtonOrigin on these frame view classes. The class which is -// used for a window is determined in the window's frameViewClassForStyleMask: -// method, so this is where we make sure that we have swizzled the method on -// all encountered classes. -+ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask -{ - Class frameViewClass = [super frameViewClassForStyleMask:styleMask]; - - if (!gSwizzledFrameViewClasses) { - gSwizzledFrameViewClasses = [[NSMutableSet setWithCapacity:3] retain]; - if (!gSwizzledFrameViewClasses) { - return frameViewClass; - } - } - - static IMP our_closeButtonOrigin = - class_getMethodImplementation([NSView class], - @selector(FrameView__closeButtonOrigin)); - static IMP our_fullScreenButtonOrigin = - class_getMethodImplementation([NSView class], - @selector(FrameView__fullScreenButtonOrigin)); - - if (![gSwizzledFrameViewClasses containsObject:frameViewClass]) { - // Either of these methods might be implemented in both a subclass of - // NSFrameView and one of its own subclasses. Which means that if we - // aren't careful we might end up swizzling the same method twice. - // Since method swizzling involves swapping pointers, this would break - // things. - IMP _closeButtonOrigin = - class_getMethodImplementation(frameViewClass, - @selector(_closeButtonOrigin)); - if (_closeButtonOrigin && _closeButtonOrigin != our_closeButtonOrigin) { - nsToolkit::SwizzleMethods(frameViewClass, @selector(_closeButtonOrigin), - @selector(FrameView__closeButtonOrigin)); - } - IMP _fullScreenButtonOrigin = - class_getMethodImplementation(frameViewClass, - @selector(_fullScreenButtonOrigin)); - if (_fullScreenButtonOrigin && - _fullScreenButtonOrigin != our_fullScreenButtonOrigin) { - nsToolkit::SwizzleMethods(frameViewClass, @selector(_fullScreenButtonOrigin), - @selector(FrameView__fullScreenButtonOrigin)); - } - [gSwizzledFrameViewClasses addObject:frameViewClass]; - } - - return frameViewClass; -} - -- (id)initWithContentRect:(NSRect)aContentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)aBufferingType defer:(BOOL)aFlag -{ - mDrawsIntoWindowFrame = NO; - [super initWithContentRect:aContentRect styleMask:aStyle backing:aBufferingType defer:aFlag]; - mState = nil; - mActiveTitlebarColor = nil; - mInactiveTitlebarColor = nil; - mScheduledShadowInvalidation = NO; - mDisabledNeedsDisplay = NO; - mDPI = GetDPI(self); - mTrackingArea = nil; - mDirtyRect = NSZeroRect; - mBeingShown = NO; - mDrawTitle = NO; - mBrightTitlebarForeground = NO; - mUseMenuStyle = NO; - [self updateTrackingArea]; - - return self; -} - -// Returns an autoreleased NSImage. -static NSImage* -GetMenuMaskImage() -{ - CGFloat radius = 4.0f; - NSEdgeInsets insets = { 5, 5, 5, 5 }; - NSSize maskSize = { 12, 12 }; - NSImage* maskImage = [NSImage imageWithSize:maskSize flipped:YES drawingHandler:^BOOL(NSRect dstRect) { - NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:dstRect xRadius:radius yRadius:radius]; - [[NSColor colorWithDeviceWhite:1.0 alpha:1.0] set]; - [path fill]; - return YES; - }]; - [maskImage setCapInsets:insets]; - return maskImage; -} - -- (void)swapOutChildViewWrapper:(NSView*)aNewWrapper -{ - [aNewWrapper setFrame:[[self contentView] frame]]; - NSView* childView = [[self mainChildView] retain]; - [childView removeFromSuperview]; - [aNewWrapper addSubview:childView]; - [childView release]; - [super setContentView:aNewWrapper]; -} - -- (void)setUseMenuStyle:(BOOL)aValue -{ - if (!VibrancyManager::SystemSupportsVibrancy()) { - return; - } - - if (aValue && !mUseMenuStyle) { - // Turn on rounded corner masking. - NSView* effectView = VibrancyManager::CreateEffectView(VibrancyType::MENU, YES); - if ([effectView respondsToSelector:@selector(setMaskImage:)]) { - [effectView setMaskImage:GetMenuMaskImage()]; - } - [self swapOutChildViewWrapper:effectView]; - [effectView release]; - } else if (mUseMenuStyle && !aValue) { - // Turn off rounded corner masking. - NSView* wrapper = [[NSView alloc] initWithFrame:NSZeroRect]; - [self swapOutChildViewWrapper:wrapper]; - [wrapper release]; - } - mUseMenuStyle = aValue; -} - -- (void)setBeingShown:(BOOL)aValue -{ - mBeingShown = aValue; -} - -- (BOOL)isBeingShown -{ - return mBeingShown; -} - -- (BOOL)isVisibleOrBeingShown -{ - return [super isVisible] || mBeingShown; -} - -- (void)disableSetNeedsDisplay -{ - mDisabledNeedsDisplay = YES; -} - -- (void)enableSetNeedsDisplay -{ - mDisabledNeedsDisplay = NO; -} - -- (void)dealloc -{ - [mActiveTitlebarColor release]; - [mInactiveTitlebarColor release]; - [self removeTrackingArea]; - ChildViewMouseTracker::OnDestroyWindow(self); - [super dealloc]; -} - -static const NSString* kStateTitleKey = @"title"; -static const NSString* kStateDrawsContentsIntoWindowFrameKey = @"drawsContentsIntoWindowFrame"; -static const NSString* kStateActiveTitlebarColorKey = @"activeTitlebarColor"; -static const NSString* kStateInactiveTitlebarColorKey = @"inactiveTitlebarColor"; -static const NSString* kStateShowsToolbarButton = @"showsToolbarButton"; -static const NSString* kStateCollectionBehavior = @"collectionBehavior"; - -- (void)importState:(NSDictionary*)aState -{ - [self setTitle:[aState objectForKey:kStateTitleKey]]; - [self setDrawsContentsIntoWindowFrame:[[aState objectForKey:kStateDrawsContentsIntoWindowFrameKey] boolValue]]; - [self setTitlebarColor:[aState objectForKey:kStateActiveTitlebarColorKey] forActiveWindow:YES]; - [self setTitlebarColor:[aState objectForKey:kStateInactiveTitlebarColorKey] forActiveWindow:NO]; - [self setShowsToolbarButton:[[aState objectForKey:kStateShowsToolbarButton] boolValue]]; - [self setCollectionBehavior:[[aState objectForKey:kStateCollectionBehavior] unsignedIntValue]]; -} - -- (NSMutableDictionary*)exportState -{ - NSMutableDictionary* state = [NSMutableDictionary dictionaryWithCapacity:10]; - [state setObject:[self title] forKey:kStateTitleKey]; - [state setObject:[NSNumber numberWithBool:[self drawsContentsIntoWindowFrame]] - forKey:kStateDrawsContentsIntoWindowFrameKey]; - NSColor* activeTitlebarColor = [self titlebarColorForActiveWindow:YES]; - if (activeTitlebarColor) { - [state setObject:activeTitlebarColor forKey:kStateActiveTitlebarColorKey]; - } - NSColor* inactiveTitlebarColor = [self titlebarColorForActiveWindow:NO]; - if (inactiveTitlebarColor) { - [state setObject:inactiveTitlebarColor forKey:kStateInactiveTitlebarColorKey]; - } - [state setObject:[NSNumber numberWithBool:[self showsToolbarButton]] - forKey:kStateShowsToolbarButton]; - [state setObject:[NSNumber numberWithUnsignedInt: [self collectionBehavior]] - forKey:kStateCollectionBehavior]; - return state; -} - -- (void)setDrawsContentsIntoWindowFrame:(BOOL)aState -{ - bool changed = (aState != mDrawsIntoWindowFrame); - mDrawsIntoWindowFrame = aState; - if (changed) { - [self updateContentViewSize]; - [self reflowTitlebarElements]; - } -} - -- (BOOL)drawsContentsIntoWindowFrame -{ - return mDrawsIntoWindowFrame; -} - -- (void)setWantsTitleDrawn:(BOOL)aDrawTitle -{ - mDrawTitle = aDrawTitle; -} - -- (BOOL)wantsTitleDrawn -{ - return mDrawTitle; -} - -- (void)setUseBrightTitlebarForeground:(BOOL)aBrightForeground -{ - mBrightTitlebarForeground = aBrightForeground; - [[self standardWindowButton:NSWindowFullScreenButton] setNeedsDisplay:YES]; -} - -- (BOOL)useBrightTitlebarForeground -{ - return mBrightTitlebarForeground; -} - -// Pass nil here to get the default appearance. -- (void)setTitlebarColor:(NSColor*)aColor forActiveWindow:(BOOL)aActive -{ - [aColor retain]; - if (aActive) { - [mActiveTitlebarColor release]; - mActiveTitlebarColor = aColor; - } else { - [mInactiveTitlebarColor release]; - mInactiveTitlebarColor = aColor; - } -} - -- (NSColor*)titlebarColorForActiveWindow:(BOOL)aActive -{ - return aActive ? mActiveTitlebarColor : mInactiveTitlebarColor; -} - -- (void)deferredInvalidateShadow -{ - if (mScheduledShadowInvalidation || [self isOpaque] || ![self hasShadow]) - return; - - [self performSelector:@selector(invalidateShadow) withObject:nil afterDelay:0]; - mScheduledShadowInvalidation = YES; -} - -- (void)invalidateShadow -{ - [super invalidateShadow]; - mScheduledShadowInvalidation = NO; -} - -- (float)getDPI -{ - return mDPI; -} - -- (NSView*)trackingAreaView -{ - NSView* contentView = [self contentView]; - return [contentView superview] ? [contentView superview] : contentView; -} - -- (ChildView*)mainChildView -{ - NSView *contentView = [self contentView]; - NSView* lastView = [[contentView subviews] lastObject]; - if ([lastView isKindOfClass:[ChildView class]]) { - return (ChildView*)lastView; - } - return nil; -} - -- (void)removeTrackingArea -{ - if (mTrackingArea) { - [[self trackingAreaView] removeTrackingArea:mTrackingArea]; - [mTrackingArea release]; - mTrackingArea = nil; - } -} - -- (void)updateTrackingArea -{ - [self removeTrackingArea]; - - NSView* view = [self trackingAreaView]; - const NSTrackingAreaOptions options = - NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveAlways; - mTrackingArea = [[NSTrackingArea alloc] initWithRect:[view bounds] - options:options - owner:self - userInfo:nil]; - [view addTrackingArea:mTrackingArea]; -} - -- (void)mouseEntered:(NSEvent*)aEvent -{ - ChildViewMouseTracker::MouseEnteredWindow(aEvent); -} - -- (void)mouseExited:(NSEvent*)aEvent -{ - ChildViewMouseTracker::MouseExitedWindow(aEvent); -} - -- (void)mouseMoved:(NSEvent*)aEvent -{ - ChildViewMouseTracker::MouseMoved(aEvent); -} - -- (void)cursorUpdated:(NSEvent*)aEvent -{ - // Nothing to do here, but NSTrackingArea wants us to implement this method. -} - -- (void)_setNeedsDisplayInRect:(NSRect)aRect -{ - // Prevent unnecessary invalidations due to moving NSViews (e.g. for plugins) - if (!mDisabledNeedsDisplay) { - // This method is only called by Cocoa, so when we're here, we know that - // it's available and don't need to check whether our superclass responds - // to the selector. - [super _setNeedsDisplayInRect:aRect]; - mDirtyRect = NSUnionRect(mDirtyRect, aRect); - } -} - -- (NSRect)getAndResetNativeDirtyRect -{ - NSRect dirtyRect = mDirtyRect; - mDirtyRect = NSZeroRect; - return dirtyRect; -} - -- (void)updateContentViewSize -{ - NSRect rect = [self contentRectForFrameRect:[self frame]]; - [[self contentView] setFrameSize:rect.size]; -} - -// Possibly move the titlebar buttons. -- (void)reflowTitlebarElements -{ - NSView *frameView = [[self contentView] superview]; - if ([frameView respondsToSelector:@selector(_tileTitlebarAndRedisplay:)]) { - [frameView _tileTitlebarAndRedisplay:NO]; - } -} - -// Override methods that translate between content rect and frame rect. -- (NSRect)contentRectForFrameRect:(NSRect)aRect -{ - if ([self drawsContentsIntoWindowFrame]) { - return aRect; - } - return [super contentRectForFrameRect:aRect]; -} - -- (NSRect)contentRectForFrameRect:(NSRect)aRect styleMask:(NSUInteger)aMask -{ - if ([self drawsContentsIntoWindowFrame]) { - return aRect; - } - if ([super respondsToSelector:@selector(contentRectForFrameRect:styleMask:)]) { - return [super contentRectForFrameRect:aRect styleMask:aMask]; - } else { - return [NSWindow contentRectForFrameRect:aRect styleMask:aMask]; - } -} - -- (NSRect)frameRectForContentRect:(NSRect)aRect -{ - if ([self drawsContentsIntoWindowFrame]) { - return aRect; - } - return [super frameRectForContentRect:aRect]; -} - -- (NSRect)frameRectForContentRect:(NSRect)aRect styleMask:(NSUInteger)aMask -{ - if ([self drawsContentsIntoWindowFrame]) { - return aRect; - } - if ([super respondsToSelector:@selector(frameRectForContentRect:styleMask:)]) { - return [super frameRectForContentRect:aRect styleMask:aMask]; - } else { - return [NSWindow frameRectForContentRect:aRect styleMask:aMask]; - } -} - -- (void)setContentView:(NSView*)aView -{ - [super setContentView:aView]; - - // Now move the contentView to the bottommost layer so that it's guaranteed - // to be under the window buttons. - NSView* frameView = [aView superview]; - [aView removeFromSuperview]; - if ([frameView respondsToSelector:@selector(_addKnownSubview:positioned:relativeTo:)]) { - // 10.10 prints a warning when we call addSubview on the frame view, so we - // silence the warning by calling a private method instead. - [frameView _addKnownSubview:aView positioned:NSWindowBelow relativeTo:nil]; - } else { - [frameView addSubview:aView positioned:NSWindowBelow relativeTo:nil]; - } -} - -- (NSArray*)titlebarControls -{ - // Return all subviews of the frameView which are not the content view. - NSView* frameView = [[self contentView] superview]; - NSMutableArray* array = [[[frameView subviews] mutableCopy] autorelease]; - [array removeObject:[self contentView]]; - return array; -} - -- (BOOL)respondsToSelector:(SEL)aSelector -{ - // Claim the window doesn't respond to this so that the system - // doesn't steal keyboard equivalents for it. Bug 613710. - if (aSelector == @selector(cancelOperation:)) { - return NO; - } - - return [super respondsToSelector:aSelector]; -} - -- (void) doCommandBySelector:(SEL)aSelector -{ - // We override this so that it won't beep if it can't act. - // We want to control the beeping for missing or disabled - // commands ourselves. - [self tryToPerform:aSelector with:nil]; -} - -- (id)accessibilityAttributeValue:(NSString *)attribute -{ - id retval = [super accessibilityAttributeValue:attribute]; - - // The following works around a problem with Text-to-Speech on OS X 10.7. - // See bug 674612 for more info. - // - // When accessibility is off, AXUIElementCopyAttributeValue(), when called - // on an AXApplication object to get its AXFocusedUIElement attribute, - // always returns an AXWindow object (the actual browser window -- never a - // mozAccessible object). This also happens with accessibility turned on, - // if no other object in the browser window has yet been focused. But if - // the browser window has a title bar (as it currently always does), the - // AXWindow object will always have four "accessible" children, one of which - // is an AXStaticText object (the title bar's "title"; the other three are - // the close, minimize and zoom buttons). This means that (for complicated - // reasons, for which see bug 674612) Text-to-Speech on OS X 10.7 will often - // "speak" the window title, no matter what text is selected, or even if no - // text at all is selected. (This always happens when accessibility is off. - // It doesn't happen in Firefox releases because Apple has (on OS X 10.7) - // special-cased the handling of apps whose CFBundleIdentifier is - // org.mozilla.firefox.) - // - // We work around this problem by only returning AXChildren that are - // mozAccessible object or are one of the titlebar's buttons (which - // instantiate subclasses of NSButtonCell). - if ([retval isKindOfClass:[NSArray class]] && - [attribute isEqualToString:@"AXChildren"]) { - NSMutableArray *holder = [NSMutableArray arrayWithCapacity:10]; - [holder addObjectsFromArray:(NSArray *)retval]; - NSUInteger count = [holder count]; - for (NSInteger i = count - 1; i >= 0; --i) { - id item = [holder objectAtIndex:i]; - // Remove anything from holder that isn't one of the titlebar's buttons - // (which instantiate subclasses of NSButtonCell) or a mozAccessible - // object (or one of its subclasses). - if (![item isKindOfClass:[NSButtonCell class]] && - ![item respondsToSelector:@selector(hasRepresentedView)]) { - [holder removeObjectAtIndex:i]; - } - } - retval = [NSArray arrayWithArray:holder]; - } - - return retval; -} - -@end - -// This class allows us to exercise control over the window's title bar. This -// allows for a "unified toolbar" look without having to extend the content -// area into the title bar. It works like this: -// 1) We set the window's style to textured. -// 2) Because of this, the background color applies to the entire window, including -// the titlebar area. For normal textured windows, the default pattern is a -// "brushed metal" image on Tiger and a unified gradient on Leopard. -// 3) We set the background color to a custom NSColor subclass that knows how tall the window is. -// When -set is called on it, it sets a pattern (with a draw callback) as the fill. In that callback, -// it paints the the titlebar and background colors in the correct areas of the context it's given, -// which will fill the entire window (CG will tile it horizontally for us). -// 4) Whenever the window's main state changes and when [window display] is called, -// Cocoa redraws the titlebar using the patternDraw callback function. -// -// This class also provides us with a pill button to show/hide the toolbar up to 10.6. -// -// Drawing the unified gradient in the titlebar and the toolbar works like this: -// 1) In the style sheet we set the toolbar's -moz-appearance to toolbar. -// 2) When the toolbar is visible and we paint the application chrome -// window, the array that Gecko passes nsChildView::UpdateThemeGeometries -// will contain an entry for the widget type NS_THEME_TOOLBAR. -// 3) nsChildView::UpdateThemeGeometries finds the toolbar frame's ToolbarWindow -// and passes the toolbar frame's height to setUnifiedToolbarHeight. -// 4) If the toolbar height has changed, a titlebar redraw is triggered and the -// upper part of the unified gradient is drawn in the titlebar. -// 5) The lower part of the unified gradient in the toolbar is drawn during -// normal window content painting in nsNativeThemeCocoa::DrawUnifiedToolbar. -// -// Whenever the unified gradient is drawn in the titlebar or the toolbar, both -// titlebar height and toolbar height must be known in order to construct the -// correct gradient. But you can only get from the toolbar frame -// to the containing window - the other direction doesn't work. That's why the -// toolbar height is cached in the ToolbarWindow but nsNativeThemeCocoa can simply -// query the window for its titlebar height when drawing the toolbar. -// -// Note that in drawsContentsIntoWindowFrame mode, titlebar drawing works in a -// completely different way: In that mode, the window's mainChildView will -// cover the titlebar completely and nothing that happens in the window -// background will reach the screen. -@implementation ToolbarWindow - -- (id)initWithContentRect:(NSRect)aContentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)aBufferingType defer:(BOOL)aFlag -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - aStyle = aStyle | NSTexturedBackgroundWindowMask; - if ((self = [super initWithContentRect:aContentRect styleMask:aStyle backing:aBufferingType defer:aFlag])) { - mColor = [[TitlebarAndBackgroundColor alloc] initWithWindow:self]; - // Bypass our guard method below. - [super setBackgroundColor:mColor]; - mBackgroundColor = [[NSColor whiteColor] retain]; - - mUnifiedToolbarHeight = 22.0f; - mWindowButtonsRect = NSZeroRect; - mFullScreenButtonRect = NSZeroRect; - - // setBottomCornerRounded: is a private API call, so we check to make sure - // we respond to it just in case. - if ([self respondsToSelector:@selector(setBottomCornerRounded:)]) - [self setBottomCornerRounded:YES]; - - [self setAutorecalculatesContentBorderThickness:NO forEdge:NSMaxYEdge]; - [self setContentBorderThickness:0.0f forEdge:NSMaxYEdge]; - } - return self; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (void)dealloc -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [super setBackgroundColor:[NSColor whiteColor]]; - [mColor release]; - [mBackgroundColor release]; - [mTitlebarView release]; - [super dealloc]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)setTitlebarColor:(NSColor*)aColor forActiveWindow:(BOOL)aActive -{ - [super setTitlebarColor:aColor forActiveWindow:aActive]; - [self setTitlebarNeedsDisplayInRect:[self titlebarRect]]; -} - -- (void)setBackgroundColor:(NSColor*)aColor -{ - [aColor retain]; - [mBackgroundColor release]; - mBackgroundColor = aColor; -} - -- (NSColor*)windowBackgroundColor -{ - return mBackgroundColor; -} - -- (void)setTemporaryBackgroundColor -{ - [super setBackgroundColor:[NSColor whiteColor]]; -} - -- (void)restoreBackgroundColor -{ - [super setBackgroundColor:mBackgroundColor]; -} - -- (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect -{ - [self setTitlebarNeedsDisplayInRect:aRect sync:NO]; -} - -- (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect sync:(BOOL)aSync -{ - NSRect titlebarRect = [self titlebarRect]; - NSRect rect = NSIntersectionRect(titlebarRect, aRect); - if (NSIsEmptyRect(rect)) - return; - - NSView* borderView = [[self contentView] superview]; - if (!borderView) - return; - - if (aSync) { - [borderView displayRect:rect]; - } else { - [borderView setNeedsDisplayInRect:rect]; - } -} - -- (NSRect)titlebarRect -{ - CGFloat titlebarHeight = [self titlebarHeight]; - return NSMakeRect(0, [self frame].size.height - titlebarHeight, - [self frame].size.width, titlebarHeight); -} - -// Returns the unified height of titlebar + toolbar. -- (CGFloat)unifiedToolbarHeight -{ - return mUnifiedToolbarHeight; -} - -- (CGFloat)titlebarHeight -{ - // We use the original content rect here, not what we return from - // [self contentRectForFrameRect:], because that would give us a - // titlebarHeight of zero in drawsContentsIntoWindowFrame mode. - NSRect frameRect = [self frame]; - NSRect originalContentRect = [NSWindow contentRectForFrameRect:frameRect styleMask:[self styleMask]]; - return NSMaxY(frameRect) - NSMaxY(originalContentRect); -} - -// Stores the complete height of titlebar + toolbar. -- (void)setUnifiedToolbarHeight:(CGFloat)aHeight -{ - if (aHeight == mUnifiedToolbarHeight) - return; - - mUnifiedToolbarHeight = aHeight; - - if (![self drawsContentsIntoWindowFrame]) { - // Redraw the title bar. If we're inside painting, we'll do it right now, - // otherwise we'll just invalidate it. - BOOL needSyncRedraw = ([NSView focusView] != nil); - [self setTitlebarNeedsDisplayInRect:[self titlebarRect] sync:needSyncRedraw]; - } -} - -// Extending the content area into the title bar works by resizing the -// mainChildView so that it covers the titlebar. -- (void)setDrawsContentsIntoWindowFrame:(BOOL)aState -{ - BOOL stateChanged = ([self drawsContentsIntoWindowFrame] != aState); - [super setDrawsContentsIntoWindowFrame:aState]; - if (stateChanged && [[self delegate] isKindOfClass:[WindowDelegate class]]) { - // Here we extend / shrink our mainChildView. We do that by firing a resize - // event which will cause the ChildView to be resized to the rect returned - // by nsCocoaWindow::GetClientBounds. GetClientBounds bases its return - // value on what we return from drawsContentsIntoWindowFrame. - WindowDelegate *windowDelegate = (WindowDelegate *)[self delegate]; - nsCocoaWindow *geckoWindow = [windowDelegate geckoWidget]; - if (geckoWindow) { - // Re-layout our contents. - geckoWindow->ReportSizeEvent(); - } - - // Resizing the content area causes a reflow which would send a synthesized - // mousemove event to the old mouse position relative to the top left - // corner of the content area. But the mouse has shifted relative to the - // content area, so that event would have wrong position information. So - // we'll send a mouse move event with the correct new position. - ChildViewMouseTracker::ResendLastMouseMoveEvent(); - } -} - -- (void)setWantsTitleDrawn:(BOOL)aDrawTitle -{ - [super setWantsTitleDrawn:aDrawTitle]; - [self setTitlebarNeedsDisplayInRect:[self titlebarRect]]; -} - -- (void)setSheetAttachmentPosition:(CGFloat)aY -{ - CGFloat topMargin = aY - [self titlebarHeight]; - [self setContentBorderThickness:topMargin forEdge:NSMaxYEdge]; -} - -- (void)placeWindowButtons:(NSRect)aRect -{ - if (!NSEqualRects(mWindowButtonsRect, aRect)) { - mWindowButtonsRect = aRect; - [self reflowTitlebarElements]; - } -} - -- (NSPoint)windowButtonsPositionWithDefaultPosition:(NSPoint)aDefaultPosition -{ - NSInteger styleMask = [self styleMask]; - if ([self drawsContentsIntoWindowFrame] && - !(styleMask & NSFullScreenWindowMask) && (styleMask & NSTitledWindowMask)) { - if (NSIsEmptyRect(mWindowButtonsRect)) { - // Empty rect. Let's hide the buttons. - // Position is in non-flipped window coordinates. Using frame's height - // for the vertical coordinate will move the buttons above the window, - // making them invisible. - return NSMakePoint(0, [self frame].size.height); - } - return NSMakePoint(mWindowButtonsRect.origin.x, mWindowButtonsRect.origin.y); - } - return aDefaultPosition; -} - -- (void)placeFullScreenButton:(NSRect)aRect -{ - if (!NSEqualRects(mFullScreenButtonRect, aRect)) { - mFullScreenButtonRect = aRect; - [self reflowTitlebarElements]; - } -} - -- (NSPoint)fullScreenButtonPositionWithDefaultPosition:(NSPoint)aDefaultPosition -{ - if ([self drawsContentsIntoWindowFrame] && !NSIsEmptyRect(mFullScreenButtonRect)) { - return NSMakePoint(std::min(mFullScreenButtonRect.origin.x, aDefaultPosition.x), - std::min(mFullScreenButtonRect.origin.y, aDefaultPosition.y)); - } - return aDefaultPosition; -} - -// Returning YES here makes the setShowsToolbarButton method work even though -// the window doesn't contain an NSToolbar. -- (BOOL)_hasToolbar -{ - return YES; -} - -// Dispatch a toolbar pill button clicked message to Gecko. -- (void)_toolbarPillButtonClicked:(id)sender -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - RollUpPopups(); - - if ([[self delegate] isKindOfClass:[WindowDelegate class]]) { - WindowDelegate *windowDelegate = (WindowDelegate *)[self delegate]; - nsCocoaWindow *geckoWindow = [windowDelegate geckoWidget]; - if (!geckoWindow) - return; - - nsIWidgetListener* listener = geckoWindow->GetWidgetListener(); - if (listener) - listener->OSToolbarButtonPressed(); - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// Retain and release "self" to avoid crashes when our widget (and its native -// window) is closed as a result of processing a key equivalent (e.g. -// Command+w or Command+q). This workaround is only needed for a window -// that can become key. -- (BOOL)performKeyEquivalent:(NSEvent*)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - NSWindow *nativeWindow = [self retain]; - BOOL retval = [super performKeyEquivalent:theEvent]; - [nativeWindow release]; - return retval; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO); -} - -- (void)sendEvent:(NSEvent *)anEvent -{ - NSEventType type = [anEvent type]; - - switch (type) { - case NSScrollWheel: - case NSLeftMouseDown: - case NSLeftMouseUp: - case NSRightMouseDown: - case NSRightMouseUp: - case NSOtherMouseDown: - case NSOtherMouseUp: - case NSMouseMoved: - case NSLeftMouseDragged: - case NSRightMouseDragged: - case NSOtherMouseDragged: - { - // Drop all mouse events if a modal window has appeared above us. - // This helps make us behave as if the OS were running a "real" modal - // event loop. - id delegate = [self delegate]; - if (delegate && [delegate isKindOfClass:[WindowDelegate class]]) { - nsCocoaWindow *widget = [(WindowDelegate *)delegate geckoWidget]; - if (widget) { - if (gGeckoAppModalWindowList && (widget != gGeckoAppModalWindowList->window)) - return; - if (widget->HasModalDescendents()) - return; - } - } - break; - } - default: - break; - } - - [super sendEvent:anEvent]; -} - -@end - -// Custom NSColor subclass where most of the work takes place for drawing in -// the titlebar area. Not used in drawsContentsIntoWindowFrame mode. -@implementation TitlebarAndBackgroundColor - -- (id)initWithWindow:(ToolbarWindow*)aWindow -{ - if ((self = [super init])) { - mWindow = aWindow; // weak ref to avoid a cycle - } - return self; -} - -static void -DrawNativeTitlebar(CGContextRef aContext, CGRect aTitlebarRect, - CGFloat aUnifiedToolbarHeight, BOOL aIsMain) -{ - nsNativeThemeCocoa::DrawNativeTitlebar(aContext, aTitlebarRect, aUnifiedToolbarHeight, aIsMain, NO); - - // The call to CUIDraw doesn't draw the top pixel strip at some window widths. - // We don't want to have a flickering transparent line, so we overdraw it. - CGContextSetRGBFillColor(aContext, 0.95, 0.95, 0.95, 1); - CGContextFillRect(aContext, CGRectMake(0, CGRectGetMaxY(aTitlebarRect) - 1, - aTitlebarRect.size.width, 1)); -} - -// Pattern draw callback for standard titlebar gradients and solid titlebar colors -static void -TitlebarDrawCallback(void* aInfo, CGContextRef aContext) -{ - ToolbarWindow *window = (ToolbarWindow*)aInfo; - if (![window drawsContentsIntoWindowFrame]) { - NSRect titlebarRect = [window titlebarRect]; - BOOL isMain = [window isMainWindow]; - NSColor *titlebarColor = [window titlebarColorForActiveWindow:isMain]; - if (!titlebarColor) { - // If the titlebar color is nil, draw the default titlebar shading. - DrawNativeTitlebar(aContext, NSRectToCGRect(titlebarRect), - [window unifiedToolbarHeight], isMain); - } else { - // If the titlebar color is not nil, just set and draw it normally. - [NSGraphicsContext saveGraphicsState]; - [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:aContext flipped:NO]]; - [titlebarColor set]; - NSRectFill(titlebarRect); - [NSGraphicsContext restoreGraphicsState]; - } - } -} - -- (void)setFill -{ - float patternWidth = [mWindow frame].size.width; - - CGPatternCallbacks callbacks = {0, &TitlebarDrawCallback, NULL}; - CGPatternRef pattern = CGPatternCreate(mWindow, CGRectMake(0.0f, 0.0f, patternWidth, [mWindow frame].size.height), - CGAffineTransformIdentity, patternWidth, [mWindow frame].size.height, - kCGPatternTilingConstantSpacing, true, &callbacks); - - // Set the pattern as the fill, which is what we were asked to do. All our - // drawing will take place in the patternDraw callback. - CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL); - CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; - CGContextSetFillColorSpace(context, patternSpace); - CGColorSpaceRelease(patternSpace); - CGFloat component = 1.0f; - CGContextSetFillPattern(context, pattern, &component); - CGPatternRelease(pattern); -} - -- (void)set -{ - [self setFill]; -} - -- (NSString*)colorSpaceName -{ - return NSDeviceRGBColorSpace; -} - -@end - -@implementation PopupWindow - -- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask - backing:(NSBackingStoreType)bufferingType defer:(BOOL)deferCreation -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - mIsContextMenu = false; - return [super initWithContentRect:contentRect styleMask:styleMask - backing:bufferingType defer:deferCreation]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (BOOL)isContextMenu -{ - return mIsContextMenu; -} - -- (void)setIsContextMenu:(BOOL)flag -{ - mIsContextMenu = flag; -} - -- (BOOL)canBecomeMainWindow -{ - // This is overriden because the default is 'yes' when a titlebar is present. - return NO; -} - -@end - -// According to Apple's docs on [NSWindow canBecomeKeyWindow] and [NSWindow -// canBecomeMainWindow], windows without a title bar or resize bar can't (by -// default) become key or main. But if a window can't become key, it can't -// accept keyboard input (bmo bug 393250). And it should also be possible for -// an otherwise "ordinary" window to become main. We need to override these -// two methods to make this happen. -@implementation BorderlessWindow - -- (BOOL)canBecomeKeyWindow -{ - return YES; -} - -- (void)sendEvent:(NSEvent *)anEvent -{ - NSEventType type = [anEvent type]; - - switch (type) { - case NSScrollWheel: - case NSLeftMouseDown: - case NSLeftMouseUp: - case NSRightMouseDown: - case NSRightMouseUp: - case NSOtherMouseDown: - case NSOtherMouseUp: - case NSMouseMoved: - case NSLeftMouseDragged: - case NSRightMouseDragged: - case NSOtherMouseDragged: - { - // Drop all mouse events if a modal window has appeared above us. - // This helps make us behave as if the OS were running a "real" modal - // event loop. - id delegate = [self delegate]; - if (delegate && [delegate isKindOfClass:[WindowDelegate class]]) { - nsCocoaWindow *widget = [(WindowDelegate *)delegate geckoWidget]; - if (widget) { - if (gGeckoAppModalWindowList && (widget != gGeckoAppModalWindowList->window)) - return; - if (widget->HasModalDescendents()) - return; - } - } - break; - } - default: - break; - } - - [super sendEvent:anEvent]; -} - -// Apple's doc on this method says that the NSWindow class's default is not to -// become main if the window isn't "visible" -- so we should replicate that -// behavior here. As best I can tell, the [NSWindow isVisible] method is an -// accurate test of what Apple means by "visibility". -- (BOOL)canBecomeMainWindow -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - if (![self isVisible]) - return NO; - return YES; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO); -} - -// Retain and release "self" to avoid crashes when our widget (and its native -// window) is closed as a result of processing a key equivalent (e.g. -// Command+w or Command+q). This workaround is only needed for a window -// that can become key. -- (BOOL)performKeyEquivalent:(NSEvent*)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - NSWindow *nativeWindow = [self retain]; - BOOL retval = [super performKeyEquivalent:theEvent]; - [nativeWindow release]; - return retval; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO); -} - -@end diff --git a/widget/cocoa/nsColorPicker.h b/widget/cocoa/nsColorPicker.h deleted file mode 100644 index 4b3e262188..0000000000 --- a/widget/cocoa/nsColorPicker.h +++ /dev/null @@ -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 mCallback; -}; - -#endif // nsColorPicker_h_ diff --git a/widget/cocoa/nsColorPicker.mm b/widget/cocoa/nsColorPicker.mm deleted file mode 100644 index 263ea349b0..0000000000 --- a/widget/cocoa/nsColorPicker.mm +++ /dev/null @@ -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 - -#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 -{ - 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(); -} diff --git a/widget/cocoa/nsCursorManager.h b/widget/cocoa/nsCursorManager.h deleted file mode 100644 index 6dba8f9034..0000000000 --- a/widget/cocoa/nsCursorManager.h +++ /dev/null @@ -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 -#include "nsIWidget.h" -#include "nsMacCursor.h" - -/*! @class nsCursorManager - @abstract Singleton service provides access to all cursors available in the application. - @discussion Use nsCusorManager to set the current cursor using an XP nsCusor enum value. - nsCursorManager 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_ diff --git a/widget/cocoa/nsCursorManager.mm b/widget/cocoa/nsCursorManager.mm deleted file mode 100644 index c4281a438a..0000000000 --- a/widget/cocoa/nsCursorManager.mm +++ /dev/null @@ -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 - -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 diff --git a/widget/cocoa/nsDeviceContextSpecX.h b/widget/cocoa/nsDeviceContextSpecX.h deleted file mode 100644 index 2df52418a7..0000000000 --- a/widget/cocoa/nsDeviceContextSpecX.h +++ /dev/null @@ -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 - -class nsDeviceContextSpecX : public nsIDeviceContextSpec -{ -public: - NS_DECL_ISUPPORTS - - nsDeviceContextSpecX(); - - NS_IMETHOD Init(nsIWidget *aWidget, nsIPrintSettings* aPS, bool aIsPrintPreview) override; - virtual already_AddRefed 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_ diff --git a/widget/cocoa/nsDeviceContextSpecX.mm b/widget/cocoa/nsDeviceContextSpecX.mm deleted file mode 100644 index d252adef69..0000000000 --- a/widget/cocoa/nsDeviceContextSpecX.mm +++ /dev/null @@ -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 - -#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 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(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 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; -} diff --git a/widget/cocoa/nsDragService.h b/widget/cocoa/nsDragService.h deleted file mode 100644 index ea6702812a..0000000000 --- a/widget/cocoa/nsDragService.h +++ /dev/null @@ -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 - -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 mDataItems; // only valid for a drag started within gecko - NSView* mNativeDragView; - NSEvent* mNativeDragEvent; -}; - -#endif // nsDragService_h_ diff --git a/widget/cocoa/nsDragService.mm b/widget/cocoa/nsDragService.mm deleted file mode 100644 index c4d8e6ff06..0000000000 --- a/widget/cocoa/nsDragService.mm +++ /dev/null @@ -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 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 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 dataSurface = - Factory::CreateDataSourceSurface(IntSize(width, height), - SurfaceFormat::B8G8R8A8); - DataSourceSurface::MappedSurface map; - if (!dataSurface->Map(DataSourceSurface::MapType::READ_WRITE, &map)) { - return nil; - } - - RefPtr 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 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 currentTransferable = do_QueryElementAt(mDataItems, aItemIndex); - if (currentTransferable) { - for (uint32_t i = 0; i < acceptableFlavorCount; i++) { - nsCOMPtr currentFlavor = do_QueryElementAt(flavorList, i); - if (!currentFlavor) - continue; - nsXPIDLCString flavorStr; - currentFlavor->ToString(getter_Copies(flavorStr)); - - nsCOMPtr 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 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(clipboardDataPtr)]; - clipboardDataPtr[stringLength] = 0; // null terminate - - nsCOMPtr 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 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 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 currentTransferable = do_QueryElementAt(mDataItems, i); - if (!currentTransferable) - continue; - - nsCOMPtr 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 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; -} diff --git a/widget/cocoa/nsFilePicker.h b/widget/cocoa/nsFilePicker.h deleted file mode 100644 index 1aeb22cc18..0000000000 --- a/widget/cocoa/nsFilePicker.h +++ /dev/null @@ -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& 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 mFiles; - nsString mDefault; - - nsTArray mFilters; - nsTArray mTitles; - - int32_t mSelectedTypeIndex; -}; - -#endif // nsFilePicker_h_ diff --git a/widget/cocoa/nsFilePicker.mm b/widget/cocoa/nsFilePicker.mm deleted file mode 100644 index 5213dee241..0000000000 --- a/widget/cocoa/nsFilePicker.mm +++ /dev/null @@ -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 - -#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 sbs = do_GetService(NS_STRINGBUNDLE_CONTRACTID); - nsCOMPtr 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(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(currentFilter.get()) - length:currentFilter.Length()]; - } - else { - titleString = [[NSString alloc] initWithCharacters:reinterpret_cast(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 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& 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 localFile; - NS_NewLocalFile(EmptyString(), true, getter_AddRefs(localFile)); - nsCOMPtr 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 localFile; - NS_NewLocalFile(EmptyString(), true, getter_AddRefs(localFile)); - nsCOMPtr 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 localFile; - NS_NewLocalFile(EmptyString(), true, getter_AddRefs(localFile)); - nsCOMPtr 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(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(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; -} diff --git a/widget/cocoa/nsIdleServiceX.h b/widget/cocoa/nsIdleServiceX.h deleted file mode 100644 index f0b3d92ed5..0000000000 --- a/widget/cocoa/nsIdleServiceX.h +++ /dev/null @@ -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 GetInstance() - { - RefPtr idleService = nsIdleService::GetInstance(); - if (!idleService) { - idleService = new nsIdleServiceX(); - } - - return idleService.forget().downcast(); - } - -protected: - nsIdleServiceX() { } - virtual ~nsIdleServiceX() { } - bool UsePollMode() override; -}; - -#endif // nsIdleServiceX_h_ diff --git a/widget/cocoa/nsIdleServiceX.mm b/widget/cocoa/nsIdleServiceX.mm deleted file mode 100644 index 234a154146..0000000000 --- a/widget/cocoa/nsIdleServiceX.mm +++ /dev/null @@ -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 - -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(time); - - return true; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false); -} - -bool -nsIdleServiceX::UsePollMode() -{ - return true; -} - diff --git a/widget/cocoa/nsLookAndFeel.h b/widget/cocoa/nsLookAndFeel.h deleted file mode 100644 index 2ad31a2aa1..0000000000 --- a/widget/cocoa/nsLookAndFeel.h +++ /dev/null @@ -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 GetIntCacheImpl(); - virtual void SetIntCacheImpl(const nsTArray& 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_ diff --git a/widget/cocoa/nsLookAndFeel.mm b/widget/cocoa/nsLookAndFeel.mm deleted file mode 100644 index 0b68cd0e4f..0000000000 --- a/widget/cocoa/nsLookAndFeel.mm +++ /dev/null @@ -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 - -// 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 -nsLookAndFeel::GetIntCacheImpl() -{ - nsTArray 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& 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; - } -} diff --git a/widget/cocoa/nsMacCursor.h b/widget/cocoa/nsMacCursor.h deleted file mode 100644 index cf9c84c7ea..0000000000 --- a/widget/cocoa/nsMacCursor.h +++ /dev/null @@ -1,105 +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 nsMacCursor_h_ -#define nsMacCursor_h_ - -#import -#import "nsIWidget.h" - -/*! @class nsMacCursor - @abstract Represents a native Mac cursor. - @discussion nsMacCursor provides a simple API for creating and working with native Macintosh cursors. - Cursors can be created used without needing to be aware of the way different cursors are implemented, - in particular the details of managing an animated cursor are hidden. -*/ -@interface nsMacCursor : NSObject -{ - @private - NSTimer *mTimer; - @protected - nsCursor mType; - int mFrameCounter; -} - -/*! @method cursorWithCursor: - @abstract Create a cursor by specifying a Cocoa NSCursor. - @discussion Creates a cursor representing the given Cocoa built-in cursor. - @param aCursor the NSCursor to use - @param aType the corresponding nsCursor constant - @result an autoreleased instance of nsMacCursor representing the given NSCursor - */ -+ (nsMacCursor *) cursorWithCursor: (NSCursor *) aCursor type: (nsCursor) aType; - -/*! @method cursorWithImageNamed:hotSpot:type: - @abstract Create a cursor by specifying the name of an image resource to use for the cursor and a hotspot. - @discussion Creates a cursor by loading the named image using the +[NSImage imageNamed:] method. -

The image must be compatible with any restrictions laid down by NSCursor. These vary - by operating system version.

-

The hotspot precisely determines the point where the user clicks when using the cursor.

- @param aCursor the name of the image to use for the cursor - @param aPoint the point within the cursor to use as the hotspot - @param aType the corresponding nsCursor constant - @result an autoreleased instance of nsMacCursor that uses the given image and hotspot - */ -+ (nsMacCursor *) cursorWithImageNamed: (NSString *) aCursorImage hotSpot: (NSPoint) aPoint type: (nsCursor) aType; - -/*! @method cursorWithFrames:type: - @abstract Create an animated cursor by specifying the frames to use for the animation. - @discussion Creates a cursor that will animate by cycling through the given frames. Each element of the array - must be an instance of NSCursor - @param aCursorFrames an array of NSCursor, representing the frames of an animated cursor, in the - order they should be played. - @param aType the corresponding nsCursor constant - @result an autoreleased instance of nsMacCursor that will animate the given cursor frames - */ -+ (nsMacCursor *) cursorWithFrames: (NSArray *) aCursorFrames type: (nsCursor) aType; - -/*! @method cocoaCursorWithImageNamed:hotSpot: - @abstract Create a Cocoa NSCursor object with a Gecko image resource name and a hotspot point. - @discussion Create a Cocoa NSCursor object with a Gecko image resource name and a hotspot point. - @param imageName the name of the gecko image resource, "tiff" extension is assumed, do not append. - @param aPoint the point within the cursor to use as the hotspot - @result an autoreleased instance of nsMacCursor that will animate the given cursor frames - */ -+ (NSCursor *) cocoaCursorWithImageNamed: (NSString *) imageName hotSpot: (NSPoint) aPoint; - -/*! @method isSet - @abstract Determines whether this cursor is currently active. - @discussion This can be helpful when the Cocoa NSCursor state can be influenced without going - through nsCursorManager. - @result whether the cursor is currently set - */ -- (BOOL) isSet; - -/*! @method set - @abstract Set the cursor. - @discussion Makes this cursor the current cursor. If the cursor is animated, the animation is started. - */ -- (void) set; - -/*! @method unset - @abstract Unset the cursor. The cursor will return to the default (usually the arrow cursor). - @discussion Unsets the cursor. If the cursor is animated, the animation is stopped. - */ -- (void) unset; - -/*! @method isAnimated - @abstract Tests whether this cursor is animated. - @discussion Use this method to determine whether a cursor is animated - @result YES if the cursor is animated (has more than one frame), NO if it is a simple static cursor. - */ -- (BOOL) isAnimated; - -/** @method cursorType - @abstract Get the cursor type for this cursor - @discussion This method returns the nsCursor constant that corresponds to this cursor, which is - equivalent to the CSS name for the cursor. - @result The nsCursor constant corresponding to this cursor, or nsCursor's 'eCursorCount' if the cursor - is a custom cursor loaded from a URI - */ -- (nsCursor) type; -@end - -#endif // nsMacCursor_h_ diff --git a/widget/cocoa/nsMacCursor.mm b/widget/cocoa/nsMacCursor.mm deleted file mode 100644 index 4fcdfd3e5d..0000000000 --- a/widget/cocoa/nsMacCursor.mm +++ /dev/null @@ -1,382 +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 "nsMacCursor.h" -#include "nsObjCExceptions.h" -#include "nsDebug.h" -#include "nsDirectoryServiceDefs.h" -#include "nsCOMPtr.h" -#include "nsIFile.h" -#include "nsString.h" - -/*! @category nsMacCursor (PrivateMethods) - @abstract Private methods internal to the nsMacCursor class. - @discussion nsMacCursor is effectively an abstract class. It does not define complete - behaviour in and of itself, the subclasses defined in this file provide the useful implementations. -*/ -@interface nsMacCursor (PrivateMethods) - -/*! @method getNextCursorFrame - @abstract get the index of the next cursor frame to display. - @discussion Increments and returns the frame counter of an animated cursor. - @result The index of the next frame to display in the cursor animation -*/ -- (int) getNextCursorFrame; - -/*! @method numFrames - @abstract Query the number of frames in this cursor's animation. - @discussion Returns the number of frames in this cursor's animation. Static cursors return 1. -*/ -- (int) numFrames; - -/*! @method createTimer - @abstract Create a Timer to use to animate the cursor. - @discussion Creates an instance of NSTimer which is used to drive the cursor animation. - This method should only be called for cursors that are animated. -*/ -- (void) createTimer; - -/*! @method destroyTimer - @abstract Destroy any timer instance associated with this cursor. - @discussion Invalidates and releases any NSTimer instance associated with this cursor. - */ -- (void) destroyTimer; -/*! @method destroyTimer - @abstract Destroy any timer instance associated with this cursor. - @discussion Invalidates and releases any NSTimer instance associated with this cursor. -*/ - -/*! @method advanceAnimatedCursor: - @abstract Method called by animation timer to perform animation. - @discussion Called by an animated cursor's associated timer to advance the animation to the next frame. - Determines which frame should occur next and sets the cursor to that frame. - @param aTimer the timer causing the animation -*/ -- (void) advanceAnimatedCursor: (NSTimer *) aTimer; - -/*! @method setFrame: - @abstract Sets the current cursor, using an index to determine which frame in the animation to display. - @discussion Sets the current cursor. The frame index determines which frame is shown if the cursor is animated. - Frames and numbered from 0 to -[nsMacCursor numFrames] - 1. A static cursor - has a single frame, numbered 0. - @param aFrameIndex the index indicating which frame from the animation to display -*/ -- (void) setFrame: (int) aFrameIndex; - -@end - -/*! @class nsCocoaCursor - @abstract Implementation of nsMacCursor that uses Cocoa NSCursor instances. - @discussion Displays a static or animated cursor, using Cocoa NSCursor instances. These can be either - built-in NSCursor instances, or custom NSCursors created from images. - When more than one NSCursor is provided, the cursor will use these as animation frames. -*/ -@interface nsCocoaCursor : nsMacCursor -{ - @private - NSArray *mFrames; - NSCursor *mLastSetCocoaCursor; -} - -/*! @method initWithFrames: - @abstract Create an animated cursor by specifying the frames to use for the animation. - @discussion Creates a cursor that will animate by cycling through the given frames. Each element of the array - must be an instance of NSCursor - @param aCursorFrames an array of NSCursor, representing the frames of an animated cursor, in the - order they should be played. - @param aType the corresponding nsCursor constant - @result an instance of nsCocoaCursor that will animate the given cursor frames - */ -- (id) initWithFrames: (NSArray *) aCursorFrames type: (nsCursor) aType; - -/*! @method initWithCursor: - @abstract Create a cursor by specifying a Cocoa NSCursor. - @discussion Creates a cursor representing the given Cocoa built-in cursor. - @param aCursor the NSCursor to use - @param aType the corresponding nsCursor constant - @result an instance of nsCocoaCursor representing the given NSCursor -*/ -- (id) initWithCursor: (NSCursor *) aCursor type: (nsCursor) aType; - -/*! @method initWithImageNamed:hotSpot: - @abstract Create a cursor by specifying the name of an image resource to use for the cursor and a hotspot. - @discussion Creates a cursor by loading the named image using the +[NSImage imageNamed:] method. -

The image must be compatible with any restrictions laid down by NSCursor. These vary - by operating system version.

-

The hotspot precisely determines the point where the user clicks when using the cursor.

- @param aCursor the name of the image to use for the cursor - @param aPoint the point within the cursor to use as the hotspot - @param aType the corresponding nsCursor constant - @result an instance of nsCocoaCursor that uses the given image and hotspot -*/ -- (id) initWithImageNamed: (NSString *) aCursorImage hotSpot: (NSPoint) aPoint type: (nsCursor) aType; - -@end - -@implementation nsMacCursor - -+ (nsMacCursor *) cursorWithCursor: (NSCursor *) aCursor type: (nsCursor) aType -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - return [[[nsCocoaCursor alloc] initWithCursor:aCursor type:aType] autorelease]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -+ (nsMacCursor *) cursorWithImageNamed: (NSString *) aCursorImage hotSpot: (NSPoint) aPoint type: (nsCursor) aType -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - return [[[nsCocoaCursor alloc] initWithImageNamed:aCursorImage hotSpot:aPoint type:aType] autorelease]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -+ (nsMacCursor *) cursorWithFrames: (NSArray *) aCursorFrames type: (nsCursor) aType -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - return [[[nsCocoaCursor alloc] initWithFrames:aCursorFrames type:aType] autorelease]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -+ (NSCursor *) cocoaCursorWithImageNamed: (NSString *) imageName hotSpot: (NSPoint) aPoint -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - nsCOMPtr resDir; - nsAutoCString resPath; - NSString* pathToImage, *pathToHiDpiImage; - NSImage* cursorImage, *hiDpiCursorImage; - - nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(resDir)); - if (NS_FAILED(rv)) - goto INIT_FAILURE; - resDir->AppendNative(NS_LITERAL_CSTRING("res")); - resDir->AppendNative(NS_LITERAL_CSTRING("cursors")); - - rv = resDir->GetNativePath(resPath); - if (NS_FAILED(rv)) - goto INIT_FAILURE; - - pathToImage = [NSString stringWithUTF8String:(const char*)resPath.get()]; - if (!pathToImage) - goto INIT_FAILURE; - pathToImage = [pathToImage stringByAppendingPathComponent:imageName]; - pathToHiDpiImage = [pathToImage stringByAppendingString:@"@2x"]; - // Add same extension to both image paths. - pathToImage = [pathToImage stringByAppendingPathExtension:@"png"]; - pathToHiDpiImage = [pathToHiDpiImage stringByAppendingPathExtension:@"png"]; - - cursorImage = [[[NSImage alloc] initWithContentsOfFile:pathToImage] autorelease]; - if (!cursorImage) - goto INIT_FAILURE; - - // Note 1: There are a few different ways to get a hidpi image via - // initWithContentsOfFile. We let the OS handle this here: when the - // file basename ends in "@2x", it will be displayed at native resolution - // instead of being pixel-doubled. See bug 784909 comment 7 for alternates ways. - // - // Note 2: The OS is picky, and will ignore the hidpi representation - // unless it is exactly twice the size of the lowdpi image. - hiDpiCursorImage = [[[NSImage alloc] initWithContentsOfFile:pathToHiDpiImage] autorelease]; - if (hiDpiCursorImage) { - NSImageRep *imageRep = [[hiDpiCursorImage representations] objectAtIndex:0]; - [cursorImage addRepresentation: imageRep]; - } - return [[[NSCursor alloc] initWithImage:cursorImage hotSpot:aPoint] autorelease]; - -INIT_FAILURE: - NS_WARNING("Problem getting path to cursor image file!"); - [self release]; - return nil; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (BOOL) isSet -{ - // implemented by subclasses - return NO; -} - -- (void) set -{ - if ([self isAnimated]) { - [self createTimer]; - } - // if the cursor isn't animated or the timer creation fails for any reason... - if (!mTimer) { - [self setFrame:0]; - } -} - -- (void) unset -{ - [self destroyTimer]; -} - -- (BOOL) isAnimated -{ - return [self numFrames] > 1; -} - -- (int) numFrames -{ - // subclasses need to override this to support animation - return 1; -} - -- (int) getNextCursorFrame -{ - mFrameCounter = (mFrameCounter + 1) % [self numFrames]; - return mFrameCounter; -} - -- (void) createTimer -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mTimer) { - mTimer = [[NSTimer scheduledTimerWithTimeInterval:0.25 - target:self - selector:@selector(advanceAnimatedCursor:) - userInfo:nil - repeats:YES] retain]; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void) destroyTimer -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (mTimer) { - [mTimer invalidate]; - [mTimer release]; - mTimer = nil; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void) advanceAnimatedCursor: (NSTimer *) aTimer -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if ([aTimer isValid]) { - [self setFrame:[self getNextCursorFrame]]; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void) setFrame: (int) aFrameIndex -{ - // subclasses need to do something useful here -} - -- (nsCursor) type { - return mType; -} - -- (void) dealloc -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [self destroyTimer]; - [super dealloc]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -@end - -@implementation nsCocoaCursor - -- (id) initWithFrames: (NSArray *) aCursorFrames type: (nsCursor) aType -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - self = [super init]; - NSEnumerator *it = [aCursorFrames objectEnumerator]; - NSObject *frame = nil; - while ((frame = [it nextObject])) { - NS_ASSERTION([frame isKindOfClass:[NSCursor class]], "Invalid argument: All frames must be of type NSCursor"); - } - mFrames = [aCursorFrames retain]; - mFrameCounter = 0; - mType = aType; - return self; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (id) initWithCursor: (NSCursor *) aCursor type: (nsCursor) aType -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - NSArray *frame = [NSArray arrayWithObjects:aCursor, nil]; - return [self initWithFrames:frame type:aType]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (id) initWithImageNamed: (NSString *) aCursorImage hotSpot: (NSPoint) aPoint type: (nsCursor) aType -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - return [self initWithCursor:[nsMacCursor cocoaCursorWithImageNamed:aCursorImage hotSpot:aPoint] type:aType]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (BOOL) isSet -{ - return [NSCursor currentCursor] == mLastSetCocoaCursor; -} - -- (void) setFrame: (int) aFrameIndex -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - NSCursor* newCursor = [mFrames objectAtIndex:aFrameIndex]; - [newCursor set]; - mLastSetCocoaCursor = newCursor; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (int) numFrames -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - return [mFrames count]; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0); -} - -- (NSString *) description -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - return [mFrames description]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (void) dealloc -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mFrames release]; - [super dealloc]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -@end diff --git a/widget/cocoa/nsMacDockSupport.h b/widget/cocoa/nsMacDockSupport.h deleted file mode 100644 index a638b89e03..0000000000 --- a/widget/cocoa/nsMacDockSupport.h +++ /dev/null @@ -1,41 +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/. */ - -#include "nsIMacDockSupport.h" -#include "nsIStandaloneNativeMenu.h" -#include "nsITaskbarProgress.h" -#include "nsITimer.h" -#include "nsCOMPtr.h" -#include "nsString.h" -#include "nsNativeThemeCocoa.h" - -class nsMacDockSupport : public nsIMacDockSupport, public nsITaskbarProgress -{ -public: - nsMacDockSupport(); - - NS_DECL_ISUPPORTS - NS_DECL_NSIMACDOCKSUPPORT - NS_DECL_NSITASKBARPROGRESS - -protected: - virtual ~nsMacDockSupport(); - - nsCOMPtr mDockMenu; - nsString mBadgeText; - - NSImage *mAppIcon, *mProgressBackground; - - HIRect mProgressBounds; - nsTaskbarProgressState mProgressState; - double mProgressFraction; - nsCOMPtr mProgressTimer; - RefPtr mTheme; - - static void RedrawIconCallback(nsITimer* aTimer, void* aClosure); - - bool InitProgress(); - nsresult RedrawIcon(); -}; diff --git a/widget/cocoa/nsMacDockSupport.mm b/widget/cocoa/nsMacDockSupport.mm deleted file mode 100644 index 56b37822bd..0000000000 --- a/widget/cocoa/nsMacDockSupport.mm +++ /dev/null @@ -1,174 +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/. */ - -#import - -#include "nsComponentManagerUtils.h" -#include "nsMacDockSupport.h" -#include "nsObjCExceptions.h" - -NS_IMPL_ISUPPORTS(nsMacDockSupport, nsIMacDockSupport, nsITaskbarProgress) - -nsMacDockSupport::nsMacDockSupport() -: mAppIcon(nil) -, mProgressBackground(nil) -, mProgressState(STATE_NO_PROGRESS) -, mProgressFraction(0.0) -{ - mProgressTimer = do_CreateInstance(NS_TIMER_CONTRACTID); -} - -nsMacDockSupport::~nsMacDockSupport() -{ - if (mAppIcon) { - [mAppIcon release]; - mAppIcon = nil; - } - if (mProgressBackground) { - [mProgressBackground release]; - mProgressBackground = nil; - } - if (mProgressTimer) { - mProgressTimer->Cancel(); - mProgressTimer = nullptr; - } -} - -NS_IMETHODIMP -nsMacDockSupport::GetDockMenu(nsIStandaloneNativeMenu ** aDockMenu) -{ - nsCOMPtr dockMenu(mDockMenu); - dockMenu.forget(aDockMenu); - return NS_OK; -} - -NS_IMETHODIMP -nsMacDockSupport::SetDockMenu(nsIStandaloneNativeMenu * aDockMenu) -{ - mDockMenu = aDockMenu; - return NS_OK; -} - -NS_IMETHODIMP -nsMacDockSupport::ActivateApplication(bool aIgnoreOtherApplications) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - [[NSApplication sharedApplication] activateIgnoringOtherApps:aIgnoreOtherApplications]; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsMacDockSupport::SetBadgeText(const nsAString& aBadgeText) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NSDockTile *tile = [[NSApplication sharedApplication] dockTile]; - mBadgeText = aBadgeText; - if (aBadgeText.IsEmpty()) - [tile setBadgeLabel: nil]; - else - [tile setBadgeLabel:[NSString stringWithCharacters:reinterpret_cast(mBadgeText.get()) - length:mBadgeText.Length()]]; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsMacDockSupport::GetBadgeText(nsAString& aBadgeText) -{ - aBadgeText = mBadgeText; - return NS_OK; -} - -NS_IMETHODIMP -nsMacDockSupport::SetProgressState(nsTaskbarProgressState aState, - uint64_t aCurrentValue, - uint64_t aMaxValue) -{ - NS_ENSURE_ARG_RANGE(aState, 0, STATE_PAUSED); - if (aState == STATE_NO_PROGRESS || aState == STATE_INDETERMINATE) { - NS_ENSURE_TRUE(aCurrentValue == 0, NS_ERROR_INVALID_ARG); - NS_ENSURE_TRUE(aMaxValue == 0, NS_ERROR_INVALID_ARG); - } - if (aCurrentValue > aMaxValue) { - return NS_ERROR_ILLEGAL_VALUE; - } - - mProgressState = aState; - if (aMaxValue == 0) { - mProgressFraction = 0; - } else { - mProgressFraction = (double)aCurrentValue / aMaxValue; - } - - if (mProgressState == STATE_NORMAL || mProgressState == STATE_INDETERMINATE) { - int perSecond = 8; // Empirically determined, see bug 848792 - mProgressTimer->InitWithFuncCallback(RedrawIconCallback, this, 1000 / perSecond, - nsITimer::TYPE_REPEATING_SLACK); - return NS_OK; - } else { - mProgressTimer->Cancel(); - return RedrawIcon(); - } -} - -// static -void nsMacDockSupport::RedrawIconCallback(nsITimer* aTimer, void* aClosure) -{ - static_cast(aClosure)->RedrawIcon(); -} - -// Return whether to draw progress -bool nsMacDockSupport::InitProgress() -{ - if (mProgressState != STATE_NORMAL && mProgressState != STATE_INDETERMINATE) { - return false; - } - - if (!mAppIcon) { - mProgressTimer = do_CreateInstance(NS_TIMER_CONTRACTID); - mAppIcon = [[NSImage imageNamed:@"NSApplicationIcon"] retain]; - mProgressBackground = [mAppIcon copyWithZone:nil]; - mTheme = new nsNativeThemeCocoa(); - - NSSize sz = [mProgressBackground size]; - mProgressBounds = CGRectMake(sz.width * 1/32, sz.height * 3/32, - sz.width * 30/32, sz.height * 4/32); - [mProgressBackground lockFocus]; - [[NSColor whiteColor] set]; - NSRectFill(NSRectFromCGRect(mProgressBounds)); - [mProgressBackground unlockFocus]; - } - return true; -} - -nsresult -nsMacDockSupport::RedrawIcon() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (InitProgress()) { - // TODO: - Implement ERROR and PAUSED states? - NSImage *icon = [mProgressBackground copyWithZone:nil]; - bool isIndeterminate = (mProgressState != STATE_NORMAL); - - [icon lockFocus]; - CGContextRef ctx = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; - mTheme->DrawProgress(ctx, mProgressBounds, isIndeterminate, - true, mProgressFraction, 1.0, NULL); - [icon unlockFocus]; - [NSApp setApplicationIconImage:icon]; - [icon release]; - } else { - [NSApp setApplicationIconImage:mAppIcon]; - } - - return NS_OK; - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} diff --git a/widget/cocoa/nsMacWebAppUtils.h b/widget/cocoa/nsMacWebAppUtils.h deleted file mode 100644 index 98ef235615..0000000000 --- a/widget/cocoa/nsMacWebAppUtils.h +++ /dev/null @@ -1,22 +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 _MAC_WEB_APP_UTILS_H_ -#define _MAC_WEB_APP_UTILS_H_ - -#include "nsIMacWebAppUtils.h" - -#define NS_MACWEBAPPUTILS_CONTRACTID "@mozilla.org/widget/mac-web-app-utils;1" - -class nsMacWebAppUtils : public nsIMacWebAppUtils { -public: - nsMacWebAppUtils() {} - - NS_DECL_ISUPPORTS - NS_DECL_NSIMACWEBAPPUTILS - -protected: - virtual ~nsMacWebAppUtils() {} -}; - -#endif //_MAC_WEB_APP_UTILS_H_ diff --git a/widget/cocoa/nsMacWebAppUtils.mm b/widget/cocoa/nsMacWebAppUtils.mm deleted file mode 100644 index 1b98cef7cc..0000000000 --- a/widget/cocoa/nsMacWebAppUtils.mm +++ /dev/null @@ -1,82 +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/. */ - -#import - -#include "nsMacWebAppUtils.h" -#include "nsCOMPtr.h" -#include "nsCocoaUtils.h" -#include "nsString.h" - -// This must be included last: -#include "nsObjCExceptions.h" - -// Find the path to the app with the given bundleIdentifier, if any. -// Note that the OS will return the path to the newest binary, if there is more than one. -// The determination of 'newest' is complex and beyond the scope of this comment. - -NS_IMPL_ISUPPORTS(nsMacWebAppUtils, nsIMacWebAppUtils) - -NS_IMETHODIMP nsMacWebAppUtils::PathForAppWithIdentifier(const nsAString& bundleIdentifier, nsAString& outPath) { - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - outPath.Truncate(); - - nsAutoreleasePool localPool; - - //note that the result of this expression might be nil, meaning no matching app was found. - NSString* temp = [[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier: - [NSString stringWithCharacters:reinterpret_cast(((nsString)bundleIdentifier).get()) - length:((nsString)bundleIdentifier).Length()]]; - - if (temp) { - // Copy out the resultant absolute path into outPath if non-nil. - nsCocoaUtils::GetStringForNSString(temp, outPath); - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP nsMacWebAppUtils::LaunchAppWithIdentifier(const nsAString& bundleIdentifier) { - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - nsAutoreleasePool localPool; - - // Note this might return false, meaning the app wasnt launched for some reason. - BOOL success = [[NSWorkspace sharedWorkspace] launchAppWithBundleIdentifier: - [NSString stringWithCharacters:reinterpret_cast(((nsString)bundleIdentifier).get()) - length:((nsString)bundleIdentifier).Length()] - options: (NSWorkspaceLaunchOptions)0 - additionalEventParamDescriptor: nil - launchIdentifier: NULL]; - - return success ? NS_OK : NS_ERROR_FAILURE; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP nsMacWebAppUtils::TrashApp(const nsAString& path, nsITrashAppCallback* aCallback) { - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (NS_WARN_IF(!aCallback)) { - return NS_ERROR_INVALID_ARG; - } - - nsCOMPtr callback = aCallback; - - NSString* tempString = [NSString stringWithCharacters:reinterpret_cast(((nsString)path).get()) - length:path.Length()]; - - [[NSWorkspace sharedWorkspace] recycleURLs: [NSArray arrayWithObject:[NSURL fileURLWithPath:tempString]] - completionHandler: ^(NSDictionary *newURLs, NSError *error) { - nsresult rv = (error == nil) ? NS_OK : NS_ERROR_FAILURE; - callback->TrashAppFinished(rv); - }]; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} diff --git a/widget/cocoa/nsMenuBarX.h b/widget/cocoa/nsMenuBarX.h deleted file mode 100644 index 7cbb8ce62a..0000000000 --- a/widget/cocoa/nsMenuBarX.h +++ /dev/null @@ -1,128 +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 nsMenuBarX_h_ -#define nsMenuBarX_h_ - -#import - -#include "mozilla/UniquePtr.h" -#include "nsMenuBaseX.h" -#include "nsMenuGroupOwnerX.h" -#include "nsChangeObserver.h" -#include "nsINativeMenuService.h" -#include "nsString.h" - -class nsMenuX; -class nsIWidget; -class nsIContent; - -// The native menu service for creating native menu bars. -class nsNativeMenuServiceX : public nsINativeMenuService -{ -public: - NS_DECL_ISUPPORTS - - nsNativeMenuServiceX() {} - - NS_IMETHOD CreateNativeMenuBar(nsIWidget* aParent, nsIContent* aMenuBarNode) override; - -protected: - virtual ~nsNativeMenuServiceX() {} -}; - -// Objective-C class used to allow us to intervene with keyboard event handling. -// We allow mouse actions to work normally. -@interface GeckoNSMenu : NSMenu -{ -} -@end - -// Objective-C class used as action target for menu items -@interface NativeMenuItemTarget : NSObject -{ -} --(IBAction)menuItemHit:(id)sender; -@end - -// Objective-C class used for menu items on the Services menu to allow Gecko -// to override their standard behavior in order to stop key equivalents from -// firing in certain instances. -@interface GeckoServicesNSMenuItem : NSMenuItem -{ -} -- (id) target; -- (SEL) action; -- (void) _doNothing:(id)sender; -@end - -// Objective-C class used as the Services menu so that Gecko can override the -// standard behavior of the Services menu in order to stop key equivalents -// from firing in certain instances. -@interface GeckoServicesNSMenu : NSMenu -{ -} -- (void)addItem:(NSMenuItem *)newItem; -- (NSMenuItem *)addItemWithTitle:(NSString *)aString action:(SEL)aSelector keyEquivalent:(NSString *)keyEquiv; -- (void)insertItem:(NSMenuItem *)newItem atIndex:(NSInteger)index; -- (NSMenuItem *)insertItemWithTitle:(NSString *)aString action:(SEL)aSelector keyEquivalent:(NSString *)keyEquiv atIndex:(NSInteger)index; -- (void) _overrideClassOfMenuItem:(NSMenuItem *)menuItem; -@end - -// Once instantiated, this object lives until its DOM node or its parent window is destroyed. -// Do not hold references to this, they can become invalid any time the DOM node can be destroyed. -class nsMenuBarX : public nsMenuGroupOwnerX, public nsChangeObserver -{ -public: - nsMenuBarX(); - virtual ~nsMenuBarX(); - - static NativeMenuItemTarget* sNativeEventTarget; - static nsMenuBarX* sLastGeckoMenuBarPainted; - - // The following content nodes have been removed from the menu system. - // We save them here for use in command handling. - nsCOMPtr mAboutItemContent; - nsCOMPtr mPrefItemContent; - nsCOMPtr mQuitItemContent; - - // nsChangeObserver - NS_DECL_CHANGEOBSERVER - - // nsMenuObjectX - void* NativeData() override {return (void*)mNativeMenu;} - nsMenuObjectTypeX MenuObjectType() override {return eMenuBarObjectType;} - - // nsMenuBarX - nsresult Create(nsIWidget* aParent, nsIContent* aContent); - void SetParent(nsIWidget* aParent); - uint32_t GetMenuCount(); - bool MenuContainsAppMenu(); - nsMenuX* GetMenuAt(uint32_t aIndex); - nsMenuX* GetXULHelpMenu(); - void SetSystemHelpMenu(); - nsresult Paint(); - void ForceUpdateNativeMenuAt(const nsAString& indexString); - void ForceNativeMenuReload(); // used for testing - static char GetLocalizedAccelKey(const char *shortcutID); - static void ResetNativeApplicationMenu(); - -protected: - void ConstructNativeMenus(); - void ConstructFallbackNativeMenus(); - nsresult InsertMenuAtIndex(nsMenuX* aMenu, uint32_t aIndex); - void RemoveMenuAtIndex(uint32_t aIndex); - void HideItem(nsIDOMDocument* inDoc, const nsAString & inID, nsIContent** outHiddenNode); - void AquifyMenuBar(); - NSMenuItem* CreateNativeAppMenuItem(nsMenuX* inMenu, const nsAString& nodeID, SEL action, - int tag, NativeMenuItemTarget* target); - nsresult CreateApplicationMenu(nsMenuX* inMenu); - - nsTArray> mMenuArray; - nsIWidget* mParentWindow; // [weak] - GeckoNSMenu* mNativeMenu; // root menu, representing entire menu bar -}; - -#endif // nsMenuBarX_h_ diff --git a/widget/cocoa/nsMenuBarX.mm b/widget/cocoa/nsMenuBarX.mm deleted file mode 100644 index ff25eb81fc..0000000000 --- a/widget/cocoa/nsMenuBarX.mm +++ /dev/null @@ -1,979 +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 - -#include "nsMenuBarX.h" -#include "nsMenuX.h" -#include "nsMenuItemX.h" -#include "nsMenuUtilsX.h" -#include "nsCocoaUtils.h" -#include "nsCocoaWindow.h" -#include "nsChildView.h" - -#include "nsCOMPtr.h" -#include "nsString.h" -#include "nsGkAtoms.h" -#include "nsObjCExceptions.h" -#include "nsThreadUtils.h" - -#include "nsIContent.h" -#include "nsIWidget.h" -#include "nsIDocument.h" -#include "nsIDOMDocument.h" -#include "nsIDOMElement.h" -#include "nsIAppStartup.h" -#include "nsIStringBundle.h" -#include "nsToolkitCompsCID.h" - -NativeMenuItemTarget* nsMenuBarX::sNativeEventTarget = nil; -nsMenuBarX* nsMenuBarX::sLastGeckoMenuBarPainted = nullptr; -NSMenu* sApplicationMenu = nil; -BOOL sApplicationMenuIsFallback = NO; -BOOL gSomeMenuBarPainted = NO; - -// We keep references to the first quit and pref item content nodes we find, which -// will be from the hidden window. We use these when the document for the current -// window does not have a quit or pref item. We don't need strong refs here because -// these items are always strong ref'd by their owning menu bar (instance variable). -static nsIContent* sAboutItemContent = nullptr; -static nsIContent* sPrefItemContent = nullptr; -static nsIContent* sQuitItemContent = nullptr; - -NS_IMPL_ISUPPORTS(nsNativeMenuServiceX, nsINativeMenuService) - -NS_IMETHODIMP nsNativeMenuServiceX::CreateNativeMenuBar(nsIWidget* aParent, nsIContent* aMenuBarNode) -{ - NS_ASSERTION(NS_IsMainThread(), "Attempting to create native menu bar on wrong thread!"); - - RefPtr mb = new nsMenuBarX(); - if (!mb) - return NS_ERROR_OUT_OF_MEMORY; - - return mb->Create(aParent, aMenuBarNode); -} - -nsMenuBarX::nsMenuBarX() -: nsMenuGroupOwnerX(), mParentWindow(nullptr) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - mNativeMenu = [[GeckoNSMenu alloc] initWithTitle:@"MainMenuBar"]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsMenuBarX::~nsMenuBarX() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (nsMenuBarX::sLastGeckoMenuBarPainted == this) - nsMenuBarX::sLastGeckoMenuBarPainted = nullptr; - - // the quit/pref items of a random window might have been used if there was no - // hidden window, thus we need to invalidate the weak references. - if (sAboutItemContent == mAboutItemContent) - sAboutItemContent = nullptr; - if (sQuitItemContent == mQuitItemContent) - sQuitItemContent = nullptr; - if (sPrefItemContent == mPrefItemContent) - sPrefItemContent = nullptr; - - // make sure we unregister ourselves as a content observer - if (mContent) { - UnregisterForContentChanges(mContent); - } - - // We have to manually clear the array here because clearing causes menu items - // to call back into the menu bar to unregister themselves. We don't want to - // depend on member variable ordering to ensure that the array gets cleared - // before the registration hash table is destroyed. - mMenuArray.Clear(); - - [mNativeMenu release]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsresult nsMenuBarX::Create(nsIWidget* aParent, nsIContent* aContent) -{ - if (!aParent) - return NS_ERROR_INVALID_ARG; - - mParentWindow = aParent; - mContent = aContent; - - if (mContent) { - AquifyMenuBar(); - - nsresult rv = nsMenuGroupOwnerX::Create(mContent); - if (NS_FAILED(rv)) - return rv; - - RegisterForContentChanges(mContent, this); - ConstructNativeMenus(); - } else { - ConstructFallbackNativeMenus(); - } - - // Give this to the parent window. The parent takes ownership. - static_cast(mParentWindow)->SetMenuBar(this); - - return NS_OK; -} - -void nsMenuBarX::ConstructNativeMenus() -{ - uint32_t count = mContent->GetChildCount(); - for (uint32_t i = 0; i < count; i++) { - nsIContent *menuContent = mContent->GetChildAt(i); - if (menuContent && - menuContent->IsXULElement(nsGkAtoms::menu)) { - nsMenuX* newMenu = new nsMenuX(); - if (newMenu) { - nsresult rv = newMenu->Create(this, this, menuContent); - if (NS_SUCCEEDED(rv)) - InsertMenuAtIndex(newMenu, GetMenuCount()); - else - delete newMenu; - } - } - } -} - -void nsMenuBarX::ConstructFallbackNativeMenus() -{ - if (sApplicationMenu) { - // Menu has already been built. - return; - } - - nsCOMPtr stringBundle; - - nsCOMPtr bundleSvc = do_GetService(NS_STRINGBUNDLE_CONTRACTID); - bundleSvc->CreateBundle("chrome://global/locale/fallbackMenubar.properties", getter_AddRefs(stringBundle)); - - if (!stringBundle) { - return; - } - - nsXPIDLString labelUTF16; - nsXPIDLString keyUTF16; - - const char16_t* labelProp = u"quitMenuitem.label"; - const char16_t* keyProp = u"quitMenuitem.key"; - - stringBundle->GetStringFromName(labelProp, getter_Copies(labelUTF16)); - stringBundle->GetStringFromName(keyProp, getter_Copies(keyUTF16)); - - NSString* labelStr = [NSString stringWithUTF8String: - NS_ConvertUTF16toUTF8(labelUTF16).get()]; - NSString* keyStr= [NSString stringWithUTF8String: - NS_ConvertUTF16toUTF8(keyUTF16).get()]; - - if (!nsMenuBarX::sNativeEventTarget) { - nsMenuBarX::sNativeEventTarget = [[NativeMenuItemTarget alloc] init]; - } - - sApplicationMenu = [[[[NSApp mainMenu] itemAtIndex:0] submenu] retain]; - NSMenuItem* quitMenuItem = [[[NSMenuItem alloc] initWithTitle:labelStr - action:@selector(menuItemHit:) - keyEquivalent:keyStr] autorelease]; - [quitMenuItem setTarget:nsMenuBarX::sNativeEventTarget]; - [quitMenuItem setTag:eCommand_ID_Quit]; - [sApplicationMenu addItem:quitMenuItem]; - sApplicationMenuIsFallback = YES; -} - -uint32_t nsMenuBarX::GetMenuCount() -{ - return mMenuArray.Length(); -} - -bool nsMenuBarX::MenuContainsAppMenu() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - return ([mNativeMenu numberOfItems] > 0 && - [[mNativeMenu itemAtIndex:0] submenu] == sApplicationMenu); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false); -} - -nsresult nsMenuBarX::InsertMenuAtIndex(nsMenuX* aMenu, uint32_t aIndex) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - // If we've only yet created a fallback global Application menu (using - // ContructFallbackNativeMenus()), destroy it before recreating it properly. - if (sApplicationMenu && sApplicationMenuIsFallback) { - ResetNativeApplicationMenu(); - } - // If we haven't created a global Application menu yet, do it. - if (!sApplicationMenu) { - nsresult rv = NS_OK; // avoid warning about rv being unused - rv = CreateApplicationMenu(aMenu); - NS_ASSERTION(NS_SUCCEEDED(rv), "Can't create Application menu"); - - // Hook the new Application menu up to the menu bar. - NSMenu* mainMenu = [NSApp mainMenu]; - NS_ASSERTION([mainMenu numberOfItems] > 0, "Main menu does not have any items, something is terribly wrong!"); - [[mainMenu itemAtIndex:0] setSubmenu:sApplicationMenu]; - } - - // add menu to array that owns our menus - mMenuArray.InsertElementAt(aIndex, aMenu); - - // hook up submenus - nsIContent* menuContent = aMenu->Content(); - if (menuContent->GetChildCount() > 0 && - !nsMenuUtilsX::NodeIsHiddenOrCollapsed(menuContent)) { - int insertionIndex = nsMenuUtilsX::CalculateNativeInsertionPoint(this, aMenu); - if (MenuContainsAppMenu()) - insertionIndex++; - [mNativeMenu insertItem:aMenu->NativeMenuItem() atIndex:insertionIndex]; - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -void nsMenuBarX::RemoveMenuAtIndex(uint32_t aIndex) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (mMenuArray.Length() <= aIndex) { - NS_ERROR("Attempting submenu removal with bad index!"); - return; - } - - // Our native menu and our internal menu object array might be out of sync. - // This happens, for example, when a submenu is hidden. Because of this we - // should not assume that a native submenu is hooked up. - NSMenuItem* nativeMenuItem = mMenuArray[aIndex]->NativeMenuItem(); - int nativeMenuItemIndex = [mNativeMenu indexOfItem:nativeMenuItem]; - if (nativeMenuItemIndex != -1) - [mNativeMenu removeItemAtIndex:nativeMenuItemIndex]; - - mMenuArray.RemoveElementAt(aIndex); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void nsMenuBarX::ObserveAttributeChanged(nsIDocument* aDocument, - nsIContent* aContent, - nsIAtom* aAttribute) -{ -} - -void nsMenuBarX::ObserveContentRemoved(nsIDocument* aDocument, - nsIContent* aChild, - int32_t aIndexInContainer) -{ - RemoveMenuAtIndex(aIndexInContainer); -} - -void nsMenuBarX::ObserveContentInserted(nsIDocument* aDocument, - nsIContent* aContainer, - nsIContent* aChild) -{ - nsMenuX* newMenu = new nsMenuX(); - if (newMenu) { - nsresult rv = newMenu->Create(this, this, aChild); - if (NS_SUCCEEDED(rv)) - InsertMenuAtIndex(newMenu, aContainer->IndexOf(aChild)); - else - delete newMenu; - } -} - -void nsMenuBarX::ForceUpdateNativeMenuAt(const nsAString& indexString) -{ - NSString* locationString = [NSString stringWithCharacters:reinterpret_cast(indexString.BeginReading()) - length:indexString.Length()]; - NSArray* indexes = [locationString componentsSeparatedByString:@"|"]; - unsigned int indexCount = [indexes count]; - if (indexCount == 0) - return; - - nsMenuX* currentMenu = NULL; - int targetIndex = [[indexes objectAtIndex:0] intValue]; - int visible = 0; - uint32_t length = mMenuArray.Length(); - // first find a menu in the menu bar - for (unsigned int i = 0; i < length; i++) { - nsMenuX* menu = mMenuArray[i].get(); - if (!nsMenuUtilsX::NodeIsHiddenOrCollapsed(menu->Content())) { - visible++; - if (visible == (targetIndex + 1)) { - currentMenu = menu; - break; - } - } - } - - if (!currentMenu) - return; - - // fake open/close to cause lazy update to happen so submenus populate - currentMenu->MenuOpened(); - currentMenu->MenuClosed(); - - // now find the correct submenu - for (unsigned int i = 1; currentMenu && i < indexCount; i++) { - targetIndex = [[indexes objectAtIndex:i] intValue]; - visible = 0; - length = currentMenu->GetItemCount(); - for (unsigned int j = 0; j < length; j++) { - nsMenuObjectX* targetMenu = currentMenu->GetItemAt(j); - if (!targetMenu) - return; - if (!nsMenuUtilsX::NodeIsHiddenOrCollapsed(targetMenu->Content())) { - visible++; - if (targetMenu->MenuObjectType() == eSubmenuObjectType && visible == (targetIndex + 1)) { - currentMenu = static_cast(targetMenu); - // fake open/close to cause lazy update to happen - currentMenu->MenuOpened(); - currentMenu->MenuClosed(); - break; - } - } - } - } -} - -// Calling this forces a full reload of the menu system, reloading all native -// menus and their items. -// Without this testing is hard because changes to the DOM affect the native -// menu system lazily. -void nsMenuBarX::ForceNativeMenuReload() -{ - // tear down everything - while (GetMenuCount() > 0) - RemoveMenuAtIndex(0); - - // construct everything - ConstructNativeMenus(); -} - -nsMenuX* nsMenuBarX::GetMenuAt(uint32_t aIndex) -{ - if (mMenuArray.Length() <= aIndex) { - NS_ERROR("Requesting menu at invalid index!"); - return NULL; - } - return mMenuArray[aIndex].get(); -} - -nsMenuX* nsMenuBarX::GetXULHelpMenu() -{ - // The Help menu is usually (always?) the last one, so we start there and - // count back. - for (int32_t i = GetMenuCount() - 1; i >= 0; --i) { - nsMenuX* aMenu = GetMenuAt(i); - if (aMenu && nsMenuX::IsXULHelpMenu(aMenu->Content())) - return aMenu; - } - return nil; -} - -// On SnowLeopard and later we must tell the OS which is our Help menu. -// Otherwise it will only add Spotlight for Help (the Search item) to our -// Help menu if its label/title is "Help" -- i.e. if the menu is in English. -// This resolves bugs 489196 and 539317. -void nsMenuBarX::SetSystemHelpMenu() -{ - nsMenuX* xulHelpMenu = GetXULHelpMenu(); - if (xulHelpMenu) { - NSMenu* helpMenu = (NSMenu*)xulHelpMenu->NativeData(); - if (helpMenu) - [NSApp setHelpMenu:helpMenu]; - } -} - -nsresult nsMenuBarX::Paint() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - // Don't try to optimize anything in this painting by checking - // sLastGeckoMenuBarPainted because the menubar can be manipulated by - // native dialogs and sheet code and other things besides this paint method. - - // We have to keep the same menu item for the Application menu so we keep - // passing it along. - NSMenu* outgoingMenu = [NSApp mainMenu]; - NS_ASSERTION([outgoingMenu numberOfItems] > 0, "Main menu does not have any items, something is terribly wrong!"); - - NSMenuItem* appMenuItem = [[outgoingMenu itemAtIndex:0] retain]; - [outgoingMenu removeItemAtIndex:0]; - [mNativeMenu insertItem:appMenuItem atIndex:0]; - [appMenuItem release]; - - // Set menu bar and event target. - [NSApp setMainMenu:mNativeMenu]; - SetSystemHelpMenu(); - nsMenuBarX::sLastGeckoMenuBarPainted = this; - - gSomeMenuBarPainted = YES; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -// Returns the 'key' attribute of the 'shortcutID' object (if any) in the -// currently active menubar's DOM document. 'shortcutID' should be the id -// (i.e. the name) of a component that defines a commonly used (and -// localized) cmd+key shortcut, and belongs to a keyset containing similar -// objects. For example "key_selectAll". Returns a value that can be -// compared to the first character of [NSEvent charactersIgnoringModifiers] -// when [NSEvent modifierFlags] == NSCommandKeyMask. -char nsMenuBarX::GetLocalizedAccelKey(const char *shortcutID) -{ - if (!sLastGeckoMenuBarPainted) - return 0; - - nsCOMPtr domDoc(do_QueryInterface(sLastGeckoMenuBarPainted->mContent->OwnerDoc())); - if (!domDoc) - return 0; - - NS_ConvertASCIItoUTF16 shortcutIDStr((const char *)shortcutID); - nsCOMPtr shortcutElement; - domDoc->GetElementById(shortcutIDStr, getter_AddRefs(shortcutElement)); - nsCOMPtr shortcutContent = do_QueryInterface(shortcutElement); - if (!shortcutContent) - return 0; - - nsAutoString key; - shortcutContent->GetAttr(kNameSpaceID_None, nsGkAtoms::key, key); - NS_LossyConvertUTF16toASCII keyASC(key.get()); - const char *keyASCPtr = keyASC.get(); - if (!keyASCPtr) - return 0; - // If keyID's 'key' attribute isn't exactly one character long, it's not - // what we're looking for. - if (strlen(keyASCPtr) != sizeof(char)) - return 0; - // Make sure retval is lower case. - char retval = tolower(keyASCPtr[0]); - - return retval; -} - -/* static */ -void nsMenuBarX::ResetNativeApplicationMenu() -{ - [sApplicationMenu removeAllItems]; - [sApplicationMenu release]; - sApplicationMenu = nil; - sApplicationMenuIsFallback = NO; -} - -// Hide the item in the menu by setting the 'hidden' attribute. Returns it in |outHiddenNode| so -// the caller can hang onto it if they so choose. It is acceptable to pass nsull -// for |outHiddenNode| if the caller doesn't care about the hidden node. -void nsMenuBarX::HideItem(nsIDOMDocument* inDoc, const nsAString & inID, nsIContent** outHiddenNode) -{ - nsCOMPtr menuItem; - inDoc->GetElementById(inID, getter_AddRefs(menuItem)); - nsCOMPtr menuContent(do_QueryInterface(menuItem)); - if (menuContent) { - menuContent->SetAttr(kNameSpaceID_None, nsGkAtoms::hidden, NS_LITERAL_STRING("true"), false); - if (outHiddenNode) { - *outHiddenNode = menuContent.get(); - NS_IF_ADDREF(*outHiddenNode); - } - } -} - -// Do what is necessary to conform to the Aqua guidelines for menus. -void nsMenuBarX::AquifyMenuBar() -{ - nsCOMPtr domDoc(do_QueryInterface(mContent->GetComposedDoc())); - if (domDoc) { - // remove the "About..." item and its separator - HideItem(domDoc, NS_LITERAL_STRING("aboutSeparator"), nullptr); - HideItem(domDoc, NS_LITERAL_STRING("aboutName"), getter_AddRefs(mAboutItemContent)); - if (!sAboutItemContent) - sAboutItemContent = mAboutItemContent; - - // remove quit item and its separator - HideItem(domDoc, NS_LITERAL_STRING("menu_FileQuitSeparator"), nullptr); - HideItem(domDoc, NS_LITERAL_STRING("menu_FileQuitItem"), getter_AddRefs(mQuitItemContent)); - if (!sQuitItemContent) - sQuitItemContent = mQuitItemContent; - - // remove prefs item and its separator, but save off the pref content node - // so we can invoke its command later. - HideItem(domDoc, NS_LITERAL_STRING("menu_PrefsSeparator"), nullptr); - HideItem(domDoc, NS_LITERAL_STRING("menu_preferences"), getter_AddRefs(mPrefItemContent)); - if (!sPrefItemContent) - sPrefItemContent = mPrefItemContent; - - // hide items that we use for the Application menu - HideItem(domDoc, NS_LITERAL_STRING("menu_mac_services"), nullptr); - HideItem(domDoc, NS_LITERAL_STRING("menu_mac_hide_app"), nullptr); - HideItem(domDoc, NS_LITERAL_STRING("menu_mac_hide_others"), nullptr); - HideItem(domDoc, NS_LITERAL_STRING("menu_mac_show_all"), nullptr); - } -} - -// for creating menu items destined for the Application menu -NSMenuItem* nsMenuBarX::CreateNativeAppMenuItem(nsMenuX* inMenu, const nsAString& nodeID, SEL action, - int tag, NativeMenuItemTarget* target) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - nsCOMPtr doc = inMenu->Content()->GetUncomposedDoc(); - if (!doc) { - return nil; - } - - nsCOMPtr domdoc(do_QueryInterface(doc)); - if (!domdoc) { - return nil; - } - - // Get information from the gecko menu item - nsAutoString label; - nsAutoString modifiers; - nsAutoString key; - nsCOMPtr menuItem; - domdoc->GetElementById(nodeID, getter_AddRefs(menuItem)); - if (menuItem) { - menuItem->GetAttribute(NS_LITERAL_STRING("label"), label); - menuItem->GetAttribute(NS_LITERAL_STRING("modifiers"), modifiers); - menuItem->GetAttribute(NS_LITERAL_STRING("key"), key); - } - else { - return nil; - } - - // Get more information about the key equivalent. Start by - // finding the key node we need. - NSString* keyEquiv = nil; - unsigned int macKeyModifiers = 0; - if (!key.IsEmpty()) { - nsCOMPtr keyElement; - domdoc->GetElementById(key, getter_AddRefs(keyElement)); - if (keyElement) { - nsCOMPtr keyContent (do_QueryInterface(keyElement)); - // first grab the key equivalent character - nsAutoString keyChar(NS_LITERAL_STRING(" ")); - keyContent->GetAttr(kNameSpaceID_None, nsGkAtoms::key, keyChar); - if (!keyChar.EqualsLiteral(" ")) { - keyEquiv = [[NSString stringWithCharacters:reinterpret_cast(keyChar.get()) - length:keyChar.Length()] lowercaseString]; - } - // now grab the key equivalent modifiers - nsAutoString modifiersStr; - keyContent->GetAttr(kNameSpaceID_None, nsGkAtoms::modifiers, modifiersStr); - uint8_t geckoModifiers = nsMenuUtilsX::GeckoModifiersForNodeAttribute(modifiersStr); - macKeyModifiers = nsMenuUtilsX::MacModifiersForGeckoModifiers(geckoModifiers); - } - } - // get the label into NSString-form - NSString* labelString = [NSString stringWithCharacters:reinterpret_cast(label.get()) - length:label.Length()]; - - if (!labelString) - labelString = @""; - if (!keyEquiv) - keyEquiv = @""; - - // put together the actual NSMenuItem - NSMenuItem* newMenuItem = [[NSMenuItem alloc] initWithTitle:labelString action:action keyEquivalent:keyEquiv]; - - [newMenuItem setTag:tag]; - [newMenuItem setTarget:target]; - [newMenuItem setKeyEquivalentModifierMask:macKeyModifiers]; - - MenuItemInfo * info = [[MenuItemInfo alloc] initWithMenuGroupOwner:this]; - [newMenuItem setRepresentedObject:info]; - [info release]; - - return newMenuItem; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -// build the Application menu shared by all menu bars -nsresult nsMenuBarX::CreateApplicationMenu(nsMenuX* inMenu) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - // At this point, the application menu is the application menu from - // the nib in cocoa widgets. We do not have a way to create an application - // menu manually, so we grab the one from the nib and use that. - sApplicationMenu = [[[[NSApp mainMenu] itemAtIndex:0] submenu] retain]; - -/* - We support the following menu items here: - - Menu Item DOM Node ID Notes - - ======================== - = About This App = <- aboutName - ======================== - = Preferences... = <- menu_preferences - ======================== - = Services > = <- menu_mac_services <- (do not define key equivalent) - ======================== - = Hide App = <- menu_mac_hide_app - = Hide Others = <- menu_mac_hide_others - = Show All = <- menu_mac_show_all - ======================== - = Quit = <- menu_FileQuitItem - ======================== - - If any of them are ommitted from the application's DOM, we just don't add - them. We always add a "Quit" item, but if an app developer does not provide a - DOM node with the right ID for the Quit item, we add it in English. App - developers need only add each node with a label and a key equivalent (if they - want one). Other attributes are optional. Like so: - - - - We need to use this system for localization purposes, until we have a better way - to define the Application menu to be used on Mac OS X. -*/ - - if (sApplicationMenu) { - // This code reads attributes we are going to care about from the DOM elements - - NSMenuItem *itemBeingAdded = nil; - BOOL addAboutSeparator = FALSE; - - // Add the About menu item - itemBeingAdded = CreateNativeAppMenuItem(inMenu, NS_LITERAL_STRING("aboutName"), @selector(menuItemHit:), - eCommand_ID_About, nsMenuBarX::sNativeEventTarget); - if (itemBeingAdded) { - [sApplicationMenu addItem:itemBeingAdded]; - [itemBeingAdded release]; - itemBeingAdded = nil; - - addAboutSeparator = TRUE; - } - - // Add separator if either the About item or software update item exists - if (addAboutSeparator) - [sApplicationMenu addItem:[NSMenuItem separatorItem]]; - - // Add the Preferences menu item - itemBeingAdded = CreateNativeAppMenuItem(inMenu, NS_LITERAL_STRING("menu_preferences"), @selector(menuItemHit:), - eCommand_ID_Prefs, nsMenuBarX::sNativeEventTarget); - if (itemBeingAdded) { - [sApplicationMenu addItem:itemBeingAdded]; - [itemBeingAdded release]; - itemBeingAdded = nil; - - // Add separator after Preferences menu - [sApplicationMenu addItem:[NSMenuItem separatorItem]]; - } - - // Add Services menu item - itemBeingAdded = CreateNativeAppMenuItem(inMenu, NS_LITERAL_STRING("menu_mac_services"), nil, - 0, nil); - if (itemBeingAdded) { - [sApplicationMenu addItem:itemBeingAdded]; - - // set this menu item up as the Mac OS X Services menu - NSMenu* servicesMenu = [[GeckoServicesNSMenu alloc] initWithTitle:@""]; - [itemBeingAdded setSubmenu:servicesMenu]; - [NSApp setServicesMenu:servicesMenu]; - - [itemBeingAdded release]; - itemBeingAdded = nil; - - // Add separator after Services menu - [sApplicationMenu addItem:[NSMenuItem separatorItem]]; - } - - BOOL addHideShowSeparator = FALSE; - - // Add menu item to hide this application - itemBeingAdded = CreateNativeAppMenuItem(inMenu, NS_LITERAL_STRING("menu_mac_hide_app"), @selector(menuItemHit:), - eCommand_ID_HideApp, nsMenuBarX::sNativeEventTarget); - if (itemBeingAdded) { - [sApplicationMenu addItem:itemBeingAdded]; - [itemBeingAdded release]; - itemBeingAdded = nil; - - addHideShowSeparator = TRUE; - } - - // Add menu item to hide other applications - itemBeingAdded = CreateNativeAppMenuItem(inMenu, NS_LITERAL_STRING("menu_mac_hide_others"), @selector(menuItemHit:), - eCommand_ID_HideOthers, nsMenuBarX::sNativeEventTarget); - if (itemBeingAdded) { - [sApplicationMenu addItem:itemBeingAdded]; - [itemBeingAdded release]; - itemBeingAdded = nil; - - addHideShowSeparator = TRUE; - } - - // Add menu item to show all applications - itemBeingAdded = CreateNativeAppMenuItem(inMenu, NS_LITERAL_STRING("menu_mac_show_all"), @selector(menuItemHit:), - eCommand_ID_ShowAll, nsMenuBarX::sNativeEventTarget); - if (itemBeingAdded) { - [sApplicationMenu addItem:itemBeingAdded]; - [itemBeingAdded release]; - itemBeingAdded = nil; - - addHideShowSeparator = TRUE; - } - - // Add a separator after the hide/show menus if at least one exists - if (addHideShowSeparator) - [sApplicationMenu addItem:[NSMenuItem separatorItem]]; - - // Add quit menu item - itemBeingAdded = CreateNativeAppMenuItem(inMenu, NS_LITERAL_STRING("menu_FileQuitItem"), @selector(menuItemHit:), - eCommand_ID_Quit, nsMenuBarX::sNativeEventTarget); - if (itemBeingAdded) { - [sApplicationMenu addItem:itemBeingAdded]; - [itemBeingAdded release]; - itemBeingAdded = nil; - } - else { - // the current application does not have a DOM node for "Quit". Add one - // anyway, in English. - NSMenuItem* defaultQuitItem = [[[NSMenuItem alloc] initWithTitle:@"Quit" action:@selector(menuItemHit:) - keyEquivalent:@"q"] autorelease]; - [defaultQuitItem setTarget:nsMenuBarX::sNativeEventTarget]; - [defaultQuitItem setTag:eCommand_ID_Quit]; - [sApplicationMenu addItem:defaultQuitItem]; - } - } - - return (sApplicationMenu) ? NS_OK : NS_ERROR_FAILURE; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -void nsMenuBarX::SetParent(nsIWidget* aParent) -{ - mParentWindow = aParent; -} - -// -// Objective-C class used to allow us to have keyboard commands -// look like they are doing something but actually do nothing. -// We allow mouse actions to work normally. -// - -// Controls whether or not native menu items should invoke their commands. -static BOOL gMenuItemsExecuteCommands = YES; - -@implementation GeckoNSMenu - -// Keyboard commands should not cause menu items to invoke their -// commands when there is a key window because we'd rather send -// the keyboard command to the window. We still have the menus -// go through the mechanics so they'll give the proper visual -// feedback. -- (BOOL)performKeyEquivalent:(NSEvent *)theEvent -{ - // We've noticed that Mac OS X expects this check in subclasses before - // calling NSMenu's "performKeyEquivalent:". - // - // There is no case in which we'd need to do anything or return YES - // when we have no items so we can just do this check first. - if ([self numberOfItems] <= 0) { - return NO; - } - - NSWindow *keyWindow = [NSApp keyWindow]; - - // If there is no key window then just behave normally. This - // probably means that this menu is associated with Gecko's - // hidden window. - if (!keyWindow) { - return [super performKeyEquivalent:theEvent]; - } - - NSResponder *firstResponder = [keyWindow firstResponder]; - - gMenuItemsExecuteCommands = NO; - [super performKeyEquivalent:theEvent]; - gMenuItemsExecuteCommands = YES; // return to default - - // Return YES if we invoked a command and there is now no key window or we changed - // the first responder. In this case we do not want to propagate the event because - // we don't want it handled again. - if (![NSApp keyWindow] || [[NSApp keyWindow] firstResponder] != firstResponder) { - return YES; - } - - // Return NO so that we can handle the event via NSView's "keyDown:". - return NO; -} - -@end - -// -// Objective-C class used as action target for menu items -// - -@implementation NativeMenuItemTarget - -// called when some menu item in this menu gets hit --(IBAction)menuItemHit:(id)sender -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!gMenuItemsExecuteCommands) { - return; - } - - int tag = [sender tag]; - - nsMenuGroupOwnerX* menuGroupOwner = nullptr; - nsMenuBarX* menuBar = nullptr; - MenuItemInfo* info = [sender representedObject]; - - if (info) { - menuGroupOwner = [info menuGroupOwner]; - if (!menuGroupOwner) { - return; - } - if (menuGroupOwner->MenuObjectType() == eMenuBarObjectType) { - menuBar = static_cast(menuGroupOwner); - } - } - - // Do special processing if this is for an app-global command. - if (tag == eCommand_ID_About) { - nsIContent* mostSpecificContent = sAboutItemContent; - if (menuBar && menuBar->mAboutItemContent) - mostSpecificContent = menuBar->mAboutItemContent; - nsMenuUtilsX::DispatchCommandTo(mostSpecificContent); - return; - } - else if (tag == eCommand_ID_Prefs) { - nsIContent* mostSpecificContent = sPrefItemContent; - if (menuBar && menuBar->mPrefItemContent) - mostSpecificContent = menuBar->mPrefItemContent; - nsMenuUtilsX::DispatchCommandTo(mostSpecificContent); - return; - } - else if (tag == eCommand_ID_HideApp) { - [NSApp hide:sender]; - return; - } - else if (tag == eCommand_ID_HideOthers) { - [NSApp hideOtherApplications:sender]; - return; - } - else if (tag == eCommand_ID_ShowAll) { - [NSApp unhideAllApplications:sender]; - return; - } - else if (tag == eCommand_ID_Quit) { - nsIContent* mostSpecificContent = sQuitItemContent; - if (menuBar && menuBar->mQuitItemContent) - mostSpecificContent = menuBar->mQuitItemContent; - // If we have some content for quit we execute it. Otherwise we send a native app terminate - // message. If you want to stop a quit from happening, provide quit content and return - // the event as unhandled. - if (mostSpecificContent) { - nsMenuUtilsX::DispatchCommandTo(mostSpecificContent); - } - else { - nsCOMPtr appStartup = do_GetService(NS_APPSTARTUP_CONTRACTID); - if (appStartup) { - appStartup->Quit(nsIAppStartup::eAttemptQuit); - } - } - return; - } - - // given the commandID, look it up in our hashtable and dispatch to - // that menu item. - if (menuGroupOwner) { - nsMenuItemX* menuItem = menuGroupOwner->GetMenuItemForCommandID(static_cast(tag)); - if (menuItem) - menuItem->DoCommand(); - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -@end - -// Objective-C class used for menu items on the Services menu to allow Gecko -// to override their standard behavior in order to stop key equivalents from -// firing in certain instances. When gMenuItemsExecuteCommands is NO, we return -// a dummy target and action instead of the actual target and action. - -@implementation GeckoServicesNSMenuItem - -- (id) target -{ - id realTarget = [super target]; - if (gMenuItemsExecuteCommands) - return realTarget; - else - return realTarget ? self : nil; -} - -- (SEL) action -{ - SEL realAction = [super action]; - if (gMenuItemsExecuteCommands) - return realAction; - else - return realAction ? @selector(_doNothing:) : NULL; -} - -- (void) _doNothing:(id)sender -{ -} - -@end - -// Objective-C class used as the Services menu so that Gecko can override the -// standard behavior of the Services menu in order to stop key equivalents -// from firing in certain instances. - -@implementation GeckoServicesNSMenu - -- (void)addItem:(NSMenuItem *)newItem -{ - [self _overrideClassOfMenuItem:newItem]; - [super addItem:newItem]; -} - -- (NSMenuItem *)addItemWithTitle:(NSString *)aString action:(SEL)aSelector keyEquivalent:(NSString *)keyEquiv -{ - NSMenuItem * newItem = [super addItemWithTitle:aString action:aSelector keyEquivalent:keyEquiv]; - [self _overrideClassOfMenuItem:newItem]; - return newItem; -} - -- (void)insertItem:(NSMenuItem *)newItem atIndex:(NSInteger)index -{ - [self _overrideClassOfMenuItem:newItem]; - [super insertItem:newItem atIndex:index]; -} - -- (NSMenuItem *)insertItemWithTitle:(NSString *)aString action:(SEL)aSelector keyEquivalent:(NSString *)keyEquiv atIndex:(NSInteger)index -{ - NSMenuItem * newItem = [super insertItemWithTitle:aString action:aSelector keyEquivalent:keyEquiv atIndex:index]; - [self _overrideClassOfMenuItem:newItem]; - return newItem; -} - -- (void) _overrideClassOfMenuItem:(NSMenuItem *)menuItem -{ - if ([menuItem class] == [NSMenuItem class]) - object_setClass(menuItem, [GeckoServicesNSMenuItem class]); -} - -@end diff --git a/widget/cocoa/nsMenuBaseX.h b/widget/cocoa/nsMenuBaseX.h deleted file mode 100644 index 5b9f89c560..0000000000 --- a/widget/cocoa/nsMenuBaseX.h +++ /dev/null @@ -1,79 +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 nsMenuBaseX_h_ -#define nsMenuBaseX_h_ - -#import - -#include "nsCOMPtr.h" -#include "nsIContent.h" - -enum nsMenuObjectTypeX { - eMenuBarObjectType, - eSubmenuObjectType, - eMenuItemObjectType, - eStandaloneNativeMenuObjectType, -}; - -// All menu objects subclass this. -// Menu bars are owned by their top-level nsIWidgets. -// All other objects are memory-managed based on the DOM. -// Content removal deletes them immediately and nothing else should. -// Do not attempt to hold strong references to them or delete them. -class nsMenuObjectX -{ -public: - virtual ~nsMenuObjectX() { } - virtual nsMenuObjectTypeX MenuObjectType()=0; - virtual void* NativeData()=0; - nsIContent* Content() { return mContent; } - - /** - * Called when an icon of a menu item somewhere in this menu has updated. - * Menu objects with parents need to propagate the notification to their - * parent. - */ - virtual void IconUpdated() {} - -protected: - nsCOMPtr mContent; -}; - - -// -// Object stored as "representedObject" for all menu items -// - -class nsMenuGroupOwnerX; - -@interface MenuItemInfo : NSObject -{ - nsMenuGroupOwnerX * mMenuGroupOwner; -} - -- (id) initWithMenuGroupOwner:(nsMenuGroupOwnerX *)aMenuGroupOwner; -- (nsMenuGroupOwnerX *) menuGroupOwner; -- (void) setMenuGroupOwner:(nsMenuGroupOwnerX *)aMenuGroupOwner; - -@end - - -// Special command IDs that we know Mac OS X does not use for anything else. -// We use these in place of carbon's IDs for these commands in order to stop -// Carbon from messing with our event handlers. See bug 346883. - -enum { - eCommand_ID_About = 1, - eCommand_ID_Prefs = 2, - eCommand_ID_Quit = 3, - eCommand_ID_HideApp = 4, - eCommand_ID_HideOthers = 5, - eCommand_ID_ShowAll = 6, - eCommand_ID_Update = 7, - eCommand_ID_Last = 8 -}; - -#endif // nsMenuBaseX_h_ diff --git a/widget/cocoa/nsMenuGroupOwnerX.h b/widget/cocoa/nsMenuGroupOwnerX.h deleted file mode 100644 index 657f420b56..0000000000 --- a/widget/cocoa/nsMenuGroupOwnerX.h +++ /dev/null @@ -1,61 +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 nsMenuGroupOwnerX_h_ -#define nsMenuGroupOwnerX_h_ - -#import - -#include "nsMenuBaseX.h" -#include "nsIMutationObserver.h" -#include "nsHashKeys.h" -#include "nsDataHashtable.h" -#include "nsString.h" - -class nsMenuItemX; -class nsChangeObserver; -class nsIWidget; -class nsIContent; - -class nsMenuGroupOwnerX : public nsMenuObjectX, public nsIMutationObserver -{ -public: - nsMenuGroupOwnerX(); - - nsresult Create(nsIContent * aContent); - - void RegisterForContentChanges(nsIContent* aContent, - nsChangeObserver* aMenuObject); - void UnregisterForContentChanges(nsIContent* aContent); - uint32_t RegisterForCommand(nsMenuItemX* aItem); - void UnregisterCommand(uint32_t aCommandID); - nsMenuItemX* GetMenuItemForCommandID(uint32_t inCommandID); - void AddMenuItemInfoToSet(MenuItemInfo* info); - - NS_DECL_ISUPPORTS - NS_DECL_NSIMUTATIONOBSERVER - -protected: - virtual ~nsMenuGroupOwnerX(); - - nsChangeObserver* LookupContentChangeObserver(nsIContent* aContent); - - uint32_t mCurrentCommandID; // unique command id (per menu-bar) to - // give to next item that asks - - // stores observers for content change notification - nsDataHashtable, nsChangeObserver *> mContentToObserverTable; - - // stores mapping of command IDs to menu objects - nsDataHashtable mCommandToMenuObjectTable; - - // Stores references to all the MenuItemInfo objects created with weak - // references to us. They may live longer than we do, so when we're - // destroyed we need to clear all their weak references. This avoids - // crashes in -[NativeMenuItemTarget menuItemHit:]. See bug 1131473. - NSMutableSet* mInfoSet; -}; - -#endif // nsMenuGroupOwner_h_ diff --git a/widget/cocoa/nsMenuGroupOwnerX.mm b/widget/cocoa/nsMenuGroupOwnerX.mm deleted file mode 100644 index 661a52bd80..0000000000 --- a/widget/cocoa/nsMenuGroupOwnerX.mm +++ /dev/null @@ -1,261 +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 "nsMenuGroupOwnerX.h" -#include "nsMenuBarX.h" -#include "nsMenuX.h" -#include "nsMenuItemX.h" -#include "nsMenuUtilsX.h" -#include "nsCocoaUtils.h" -#include "nsCocoaWindow.h" - -#include "nsCOMPtr.h" -#include "nsString.h" -#include "nsObjCExceptions.h" -#include "nsThreadUtils.h" - -#include "mozilla/dom/Element.h" -#include "nsIWidget.h" -#include "nsIDocument.h" -#include "nsIDOMDocument.h" -#include "nsIDOMElement.h" - -#include "nsINode.h" - -using namespace mozilla; - -NS_IMPL_ISUPPORTS(nsMenuGroupOwnerX, nsIMutationObserver) - - -nsMenuGroupOwnerX::nsMenuGroupOwnerX() -: mCurrentCommandID(eCommand_ID_Last) -{ - mInfoSet = [[NSMutableSet setWithCapacity:10] retain]; -} - - -nsMenuGroupOwnerX::~nsMenuGroupOwnerX() -{ - MOZ_ASSERT(mContentToObserverTable.Count() == 0, "have outstanding mutation observers!\n"); - - // The MenuItemInfo objects in mInfoSet may live longer than we do. So when - // we get destroyed we need to invalidate all their mMenuGroupOwner pointers. - NSEnumerator* counter = [mInfoSet objectEnumerator]; - MenuItemInfo* info; - while ((info = (MenuItemInfo*) [counter nextObject])) { - [info setMenuGroupOwner:nil]; - } - [mInfoSet release]; -} - - -nsresult nsMenuGroupOwnerX::Create(nsIContent* aContent) -{ - if (!aContent) - return NS_ERROR_INVALID_ARG; - - mContent = aContent; - - return NS_OK; -} - - -// -// nsIMutationObserver -// - - -void nsMenuGroupOwnerX::CharacterDataWillChange(nsIDocument* aDocument, - nsIContent* aContent, - CharacterDataChangeInfo* aInfo) -{ -} - - -void nsMenuGroupOwnerX::CharacterDataChanged(nsIDocument* aDocument, - nsIContent* aContent, - CharacterDataChangeInfo* aInfo) -{ -} - - -void nsMenuGroupOwnerX::ContentAppended(nsIDocument* aDocument, - nsIContent* aContainer, - nsIContent* aFirstNewContent, - int32_t /* unused */) -{ - for (nsIContent* cur = aFirstNewContent; cur; cur = cur->GetNextSibling()) { - ContentInserted(aDocument, aContainer, cur, 0); - } -} - - -void nsMenuGroupOwnerX::NodeWillBeDestroyed(const nsINode * aNode) -{ -} - - -void nsMenuGroupOwnerX::AttributeWillChange(nsIDocument* aDocument, - dom::Element* aContent, - int32_t aNameSpaceID, - nsIAtom* aAttribute, - int32_t aModType, - const nsAttrValue* aNewValue) -{ -} - -void nsMenuGroupOwnerX::NativeAnonymousChildListChange(nsIDocument* aDocument, - nsIContent* aContent, - bool aIsRemove) -{ -} - -void nsMenuGroupOwnerX::AttributeChanged(nsIDocument* aDocument, - dom::Element* aElement, - int32_t aNameSpaceID, - nsIAtom* aAttribute, - int32_t aModType, - const nsAttrValue* aOldValue) -{ - nsCOMPtr kungFuDeathGrip(this); - nsChangeObserver* obs = LookupContentChangeObserver(aElement); - if (obs) - obs->ObserveAttributeChanged(aDocument, aElement, aAttribute); -} - - -void nsMenuGroupOwnerX::ContentRemoved(nsIDocument * aDocument, - nsIContent * aContainer, - nsIContent * aChild, - int32_t aIndexInContainer, - nsIContent * aPreviousSibling) -{ - if (!aContainer) { - return; - } - - nsCOMPtr kungFuDeathGrip(this); - nsChangeObserver* obs = LookupContentChangeObserver(aContainer); - if (obs) - obs->ObserveContentRemoved(aDocument, aChild, aIndexInContainer); - else if (aContainer != mContent) { - // We do a lookup on the parent container in case things were removed - // under a "menupopup" item. That is basically a wrapper for the contents - // of a "menu" node. - nsCOMPtr parent = aContainer->GetParent(); - if (parent) { - obs = LookupContentChangeObserver(parent); - if (obs) - obs->ObserveContentRemoved(aDocument, aChild, aIndexInContainer); - } - } -} - - -void nsMenuGroupOwnerX::ContentInserted(nsIDocument * aDocument, - nsIContent * aContainer, - nsIContent * aChild, - int32_t /* unused */) -{ - if (!aContainer) { - return; - } - - nsCOMPtr kungFuDeathGrip(this); - nsChangeObserver* obs = LookupContentChangeObserver(aContainer); - if (obs) - obs->ObserveContentInserted(aDocument, aContainer, aChild); - else if (aContainer != mContent) { - // We do a lookup on the parent container in case things were removed - // under a "menupopup" item. That is basically a wrapper for the contents - // of a "menu" node. - nsCOMPtr parent = aContainer->GetParent(); - if (parent) { - obs = LookupContentChangeObserver(parent); - if (obs) - obs->ObserveContentInserted(aDocument, aContainer, aChild); - } - } -} - - -void nsMenuGroupOwnerX::ParentChainChanged(nsIContent *aContent) -{ -} - - -// For change management, we don't use a |nsSupportsHashtable| because -// we know that the lifetime of all these items is bounded by the -// lifetime of the menubar. No need to add any more strong refs to the -// picture because the containment hierarchy already uses strong refs. -void nsMenuGroupOwnerX::RegisterForContentChanges(nsIContent *aContent, - nsChangeObserver *aMenuObject) -{ - if (!mContentToObserverTable.Contains(aContent)) { - aContent->AddMutationObserver(this); - } - mContentToObserverTable.Put(aContent, aMenuObject); -} - - -void nsMenuGroupOwnerX::UnregisterForContentChanges(nsIContent *aContent) -{ - if (mContentToObserverTable.Contains(aContent)) { - aContent->RemoveMutationObserver(this); - } - mContentToObserverTable.Remove(aContent); -} - - -nsChangeObserver* nsMenuGroupOwnerX::LookupContentChangeObserver(nsIContent* aContent) -{ - nsChangeObserver * result; - if (mContentToObserverTable.Get(aContent, &result)) - return result; - else - return nullptr; -} - - -// Given a menu item, creates a unique 4-character command ID and -// maps it to the item. Returns the id for use by the client. -uint32_t nsMenuGroupOwnerX::RegisterForCommand(nsMenuItemX* inMenuItem) -{ - // no real need to check for uniqueness. We always start afresh with each - // window at 1. Even if we did get close to the reserved Apple command id's, - // those don't start until at least ' ', which is integer 538976288. If - // we have that many menu items in one window, I think we have other - // problems. - - // make id unique - ++mCurrentCommandID; - - mCommandToMenuObjectTable.Put(mCurrentCommandID, inMenuItem); - - return mCurrentCommandID; -} - - -// Removes the mapping between the given 4-character command ID -// and its associated menu item. -void nsMenuGroupOwnerX::UnregisterCommand(uint32_t inCommandID) -{ - mCommandToMenuObjectTable.Remove(inCommandID); -} - - -nsMenuItemX* nsMenuGroupOwnerX::GetMenuItemForCommandID(uint32_t inCommandID) -{ - nsMenuItemX * result; - if (mCommandToMenuObjectTable.Get(inCommandID, &result)) - return result; - else - return nullptr; -} - -void nsMenuGroupOwnerX::AddMenuItemInfoToSet(MenuItemInfo* info) -{ - [mInfoSet addObject:info]; -} diff --git a/widget/cocoa/nsMenuItemIconX.h b/widget/cocoa/nsMenuItemIconX.h deleted file mode 100644 index 7352a94e2a..0000000000 --- a/widget/cocoa/nsMenuItemIconX.h +++ /dev/null @@ -1,66 +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/. */ - -/* - * Retrieves and displays icons in native menu items on Mac OS X. - */ - -#ifndef nsMenuItemIconX_h_ -#define nsMenuItemIconX_h_ - -#include "mozilla/RefPtr.h" -#include "nsCOMPtr.h" -#include "imgINotificationObserver.h" - -class nsIURI; -class nsIContent; -class imgRequestProxy; -class nsMenuObjectX; - -#import - -class nsMenuItemIconX : public imgINotificationObserver -{ -public: - nsMenuItemIconX(nsMenuObjectX* aMenuItem, - nsIContent* aContent, - NSMenuItem* aNativeMenuItem); -private: - virtual ~nsMenuItemIconX(); - -public: - NS_DECL_ISUPPORTS - NS_DECL_IMGINOTIFICATIONOBSERVER - - // SetupIcon succeeds if it was able to set up the icon, or if there should - // be no icon, in which case it clears any existing icon but still succeeds. - nsresult SetupIcon(); - - // GetIconURI fails if the item should not have any icon. - nsresult GetIconURI(nsIURI** aIconURI); - - // LoadIcon will set a placeholder image and start a load request for the - // icon. The request may not complete until after LoadIcon returns. - nsresult LoadIcon(nsIURI* aIconURI); - - // Unless we take precautions, we may outlive the object that created us - // (mMenuObject, which owns our native menu item (mNativeMenuItem)). - // Destroy() should be called from mMenuObject's destructor to prevent - // this from happening. See bug 499600. - void Destroy(); - -protected: - nsresult OnFrameComplete(imgIRequest* aRequest); - - nsCOMPtr mContent; - RefPtr mIconRequest; - nsMenuObjectX* mMenuObject; // [weak] - nsIntRect mImageRegionRect; - bool mLoadedIcon; - bool mSetIcon; - NSMenuItem* mNativeMenuItem; // [weak] -}; - -#endif // nsMenuItemIconX_h_ diff --git a/widget/cocoa/nsMenuItemIconX.mm b/widget/cocoa/nsMenuItemIconX.mm deleted file mode 100644 index 7589c279e5..0000000000 --- a/widget/cocoa/nsMenuItemIconX.mm +++ /dev/null @@ -1,466 +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/. */ - -/* - * Retrieves and displays icons in native menu items on Mac OS X. - */ - -/* exception_defines.h defines 'try' to 'if (true)' which breaks objective-c - exceptions and produces errors like: error: unexpected '@' in program'. - If we define __EXCEPTIONS exception_defines.h will avoid doing this. - - See bug 666609 for more information. - - We use to get the libstdc++ version. */ -#include -#if __GLIBCXX__ <= 20070719 -#ifndef __EXCEPTIONS -#define __EXCEPTIONS -#endif -#endif - -#include "nsMenuItemIconX.h" -#include "nsObjCExceptions.h" -#include "nsIContent.h" -#include "nsIDocument.h" -#include "nsNameSpaceManager.h" -#include "nsGkAtoms.h" -#include "nsIDOMElement.h" -#include "nsICSSDeclaration.h" -#include "nsIDOMCSSValue.h" -#include "nsIDOMCSSPrimitiveValue.h" -#include "nsIDOMRect.h" -#include "nsThreadUtils.h" -#include "nsToolkit.h" -#include "nsNetUtil.h" -#include "imgLoader.h" -#include "imgRequestProxy.h" -#include "nsMenuItemX.h" -#include "gfxPlatform.h" -#include "imgIContainer.h" -#include "nsCocoaUtils.h" -#include "nsContentUtils.h" -#include "nsIContentPolicy.h" - -using mozilla::dom::Element; -using mozilla::gfx::SourceSurface; - -static const uint32_t kIconWidth = 16; -static const uint32_t kIconHeight = 16; - -typedef NS_STDCALL_FUNCPROTO(nsresult, GetRectSideMethod, nsIDOMRect, - GetBottom, (nsIDOMCSSPrimitiveValue**)); - -NS_IMPL_ISUPPORTS(nsMenuItemIconX, imgINotificationObserver) - -nsMenuItemIconX::nsMenuItemIconX(nsMenuObjectX* aMenuItem, - nsIContent* aContent, - NSMenuItem* aNativeMenuItem) -: mContent(aContent) -, mMenuObject(aMenuItem) -, mLoadedIcon(false) -, mSetIcon(false) -, mNativeMenuItem(aNativeMenuItem) -{ - // printf("Creating icon for menu item %d, menu %d, native item is %d\n", aMenuItem, aMenu, aNativeMenuItem); -} - -nsMenuItemIconX::~nsMenuItemIconX() -{ - if (mIconRequest) - mIconRequest->CancelAndForgetObserver(NS_BINDING_ABORTED); -} - -// Called from mMenuObjectX's destructor, to prevent us from outliving it -// (as might otherwise happen if calls to our imgINotificationObserver methods -// are still outstanding). mMenuObjectX owns our nNativeMenuItem. -void nsMenuItemIconX::Destroy() -{ - if (mIconRequest) { - mIconRequest->CancelAndForgetObserver(NS_BINDING_ABORTED); - mIconRequest = nullptr; - } - mMenuObject = nullptr; - mNativeMenuItem = nil; -} - -nsresult -nsMenuItemIconX::SetupIcon() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - // Still don't have one, then something is wrong, get out of here. - if (!mNativeMenuItem) { - NS_ERROR("No native menu item"); - return NS_ERROR_FAILURE; - } - - nsCOMPtr iconURI; - nsresult rv = GetIconURI(getter_AddRefs(iconURI)); - if (NS_FAILED(rv)) { - // There is no icon for this menu item. An icon might have been set - // earlier. Clear it. - [mNativeMenuItem setImage:nil]; - - return NS_OK; - } - - rv = LoadIcon(iconURI); - if (NS_FAILED(rv)) { - // There is no icon for this menu item, as an error occurred while loading it. - // An icon might have been set earlier or the place holder icon may have - // been set. Clear it. - [mNativeMenuItem setImage:nil]; - } - return rv; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -static int32_t -GetDOMRectSide(nsIDOMRect* aRect, GetRectSideMethod aMethod) -{ - nsCOMPtr dimensionValue; - (aRect->*aMethod)(getter_AddRefs(dimensionValue)); - if (!dimensionValue) - return -1; - - uint16_t primitiveType; - nsresult rv = dimensionValue->GetPrimitiveType(&primitiveType); - if (NS_FAILED(rv) || primitiveType != nsIDOMCSSPrimitiveValue::CSS_PX) - return -1; - - float dimension = 0; - rv = dimensionValue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_PX, - &dimension); - if (NS_FAILED(rv)) - return -1; - - return NSToIntRound(dimension); -} - -nsresult -nsMenuItemIconX::GetIconURI(nsIURI** aIconURI) -{ - if (!mMenuObject) - return NS_ERROR_FAILURE; - - // Mac native menu items support having both a checkmark and an icon - // simultaneously, but this is unheard of in the cross-platform toolkit, - // seemingly because the win32 theme is unable to cope with both at once. - // The downside is that it's possible to get a menu item marked with a - // native checkmark and a checkmark for an icon. Head off that possibility - // by pretending that no icon exists if this is a checkable menu item. - if (mMenuObject->MenuObjectType() == eMenuItemObjectType) { - nsMenuItemX* menuItem = static_cast(mMenuObject); - if (menuItem->GetMenuItemType() != eRegularMenuItemType) - return NS_ERROR_FAILURE; - } - - if (!mContent) - return NS_ERROR_FAILURE; - - // First, look at the content node's "image" attribute. - nsAutoString imageURIString; - bool hasImageAttr = mContent->GetAttr(kNameSpaceID_None, - nsGkAtoms::image, - imageURIString); - - nsresult rv; - nsCOMPtr cssValue; - nsCOMPtr cssStyleDecl; - nsCOMPtr primitiveValue; - uint16_t primitiveType; - if (!hasImageAttr) { - // If the content node has no "image" attribute, get the - // "list-style-image" property from CSS. - nsCOMPtr document = mContent->GetComposedDoc(); - if (!document) - return NS_ERROR_FAILURE; - - nsCOMPtr window = document->GetInnerWindow(); - if (!window) - return NS_ERROR_FAILURE; - - nsCOMPtr domElement = do_QueryInterface(mContent); - if (!domElement) - return NS_ERROR_FAILURE; - - ErrorResult dummy; - cssStyleDecl = window->GetComputedStyle(*domElement, EmptyString(), dummy); - dummy.SuppressException(); - if (!cssStyleDecl) - return NS_ERROR_FAILURE; - - NS_NAMED_LITERAL_STRING(listStyleImage, "list-style-image"); - rv = cssStyleDecl->GetPropertyCSSValue(listStyleImage, - getter_AddRefs(cssValue)); - if (NS_FAILED(rv)) return rv; - - primitiveValue = do_QueryInterface(cssValue); - if (!primitiveValue) return NS_ERROR_FAILURE; - - rv = primitiveValue->GetPrimitiveType(&primitiveType); - if (NS_FAILED(rv)) return rv; - if (primitiveType != nsIDOMCSSPrimitiveValue::CSS_URI) - return NS_ERROR_FAILURE; - - rv = primitiveValue->GetStringValue(imageURIString); - if (NS_FAILED(rv)) return rv; - } - - // Empty the mImageRegionRect initially as the image region CSS could - // have been changed and now have an error or have been removed since the - // last GetIconURI call. - mImageRegionRect.SetEmpty(); - - // If this menu item shouldn't have an icon, the string will be empty, - // and NS_NewURI will fail. - nsCOMPtr iconURI; - rv = NS_NewURI(getter_AddRefs(iconURI), imageURIString); - if (NS_FAILED(rv)) return rv; - - *aIconURI = iconURI; - NS_ADDREF(*aIconURI); - - if (!hasImageAttr) { - // Check if the icon has a specified image region so that it can be - // cropped appropriately before being displayed. - NS_NAMED_LITERAL_STRING(imageRegion, "-moz-image-region"); - rv = cssStyleDecl->GetPropertyCSSValue(imageRegion, - getter_AddRefs(cssValue)); - // Just return NS_OK if there if there is a failure due to no - // moz-image region specified so the whole icon will be drawn anyway. - if (NS_FAILED(rv)) return NS_OK; - - primitiveValue = do_QueryInterface(cssValue); - if (!primitiveValue) return NS_OK; - - rv = primitiveValue->GetPrimitiveType(&primitiveType); - if (NS_FAILED(rv)) return NS_OK; - if (primitiveType != nsIDOMCSSPrimitiveValue::CSS_RECT) - return NS_OK; - - nsCOMPtr imageRegionRect; - rv = primitiveValue->GetRectValue(getter_AddRefs(imageRegionRect)); - if (NS_FAILED(rv)) return NS_OK; - - if (imageRegionRect) { - // Return NS_ERROR_FAILURE if the image region is invalid so the image - // is not drawn, and behavior is similar to XUL menus. - int32_t bottom = GetDOMRectSide(imageRegionRect, &nsIDOMRect::GetBottom); - int32_t right = GetDOMRectSide(imageRegionRect, &nsIDOMRect::GetRight); - int32_t top = GetDOMRectSide(imageRegionRect, &nsIDOMRect::GetTop); - int32_t left = GetDOMRectSide(imageRegionRect, &nsIDOMRect::GetLeft); - - if (top < 0 || left < 0 || bottom <= top || right <= left) - return NS_ERROR_FAILURE; - - mImageRegionRect.SetRect(left, top, right - left, bottom - top); - } - } - - return NS_OK; -} - -nsresult -nsMenuItemIconX::LoadIcon(nsIURI* aIconURI) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (mIconRequest) { - // Another icon request is already in flight. Kill it. - mIconRequest->Cancel(NS_BINDING_ABORTED); - mIconRequest = nullptr; - } - - mLoadedIcon = false; - - if (!mContent) return NS_ERROR_FAILURE; - - nsCOMPtr document = mContent->OwnerDoc(); - - nsCOMPtr loadGroup = document->GetDocumentLoadGroup(); - if (!loadGroup) return NS_ERROR_FAILURE; - - RefPtr loader = nsContentUtils::GetImgLoaderForDocument(document); - if (!loader) return NS_ERROR_FAILURE; - - if (!mSetIcon) { - // Set a completely transparent 16x16 image as the icon on this menu item - // as a placeholder. This keeps the menu item text displayed in the same - // position that it will be displayed when the real icon is loaded, and - // prevents it from jumping around or looking misaligned. - - static bool sInitializedPlaceholder; - static NSImage* sPlaceholderIconImage; - if (!sInitializedPlaceholder) { - sInitializedPlaceholder = true; - - // Note that we only create the one and reuse it forever, so this is not a leak. - sPlaceholderIconImage = [[NSImage alloc] initWithSize:NSMakeSize(kIconWidth, kIconHeight)]; - } - - if (!sPlaceholderIconImage) return NS_ERROR_FAILURE; - - if (mNativeMenuItem) - [mNativeMenuItem setImage:sPlaceholderIconImage]; - } - - nsresult rv = loader->LoadImage(aIconURI, nullptr, nullptr, - mozilla::net::RP_Default, - nullptr, loadGroup, this, - nullptr, nullptr, nsIRequest::LOAD_NORMAL, nullptr, - nsIContentPolicy::TYPE_INTERNAL_IMAGE, EmptyString(), - getter_AddRefs(mIconRequest)); - if (NS_FAILED(rv)) return rv; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -// -// imgINotificationObserver -// - -NS_IMETHODIMP -nsMenuItemIconX::Notify(imgIRequest* aRequest, - int32_t aType, - const nsIntRect* aData) -{ - if (aType == imgINotificationObserver::LOAD_COMPLETE) { - // Make sure the image loaded successfully. - uint32_t status = imgIRequest::STATUS_ERROR; - if (NS_FAILED(aRequest->GetImageStatus(&status)) || - (status & imgIRequest::STATUS_ERROR)) { - mIconRequest->Cancel(NS_BINDING_ABORTED); - mIconRequest = nullptr; - return NS_ERROR_FAILURE; - } - - nsCOMPtr image; - aRequest->GetImage(getter_AddRefs(image)); - MOZ_ASSERT(image); - - // Ask the image to decode at its intrinsic size. - int32_t width = 0, height = 0; - image->GetWidth(&width); - image->GetHeight(&height); - image->RequestDecodeForSize(nsIntSize(width, height), imgIContainer::FLAG_NONE); - } - - if (aType == imgINotificationObserver::FRAME_COMPLETE) { - return OnFrameComplete(aRequest); - } - - if (aType == imgINotificationObserver::DECODE_COMPLETE) { - if (mIconRequest && mIconRequest == aRequest) { - mIconRequest->Cancel(NS_BINDING_ABORTED); - mIconRequest = nullptr; - } - } - - return NS_OK; -} - -nsresult -nsMenuItemIconX::OnFrameComplete(imgIRequest* aRequest) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (aRequest != mIconRequest) - return NS_ERROR_FAILURE; - - // Only support one frame. - if (mLoadedIcon) - return NS_OK; - - if (!mNativeMenuItem) - return NS_ERROR_FAILURE; - - nsCOMPtr imageContainer; - aRequest->GetImage(getter_AddRefs(imageContainer)); - if (!imageContainer) { - [mNativeMenuItem setImage:nil]; - return NS_ERROR_FAILURE; - } - - int32_t origWidth = 0, origHeight = 0; - imageContainer->GetWidth(&origWidth); - imageContainer->GetHeight(&origHeight); - - // If the image region is invalid, don't draw the image to almost match - // the behavior of other platforms. - if (!mImageRegionRect.IsEmpty() && - (mImageRegionRect.XMost() > origWidth || - mImageRegionRect.YMost() > origHeight)) { - [mNativeMenuItem setImage:nil]; - return NS_ERROR_FAILURE; - } - - if (mImageRegionRect.IsEmpty()) { - mImageRegionRect.SetRect(0, 0, origWidth, origHeight); - } - - RefPtr surface = - imageContainer->GetFrame(imgIContainer::FRAME_CURRENT, - imgIContainer::FLAG_SYNC_DECODE); - if (!surface) { - [mNativeMenuItem setImage:nil]; - return NS_ERROR_FAILURE; - } - - CGImageRef origImage = NULL; - nsresult rv = nsCocoaUtils::CreateCGImageFromSurface(surface, &origImage); - if (NS_FAILED(rv) || !origImage) { - [mNativeMenuItem setImage:nil]; - return NS_ERROR_FAILURE; - } - - bool createSubImage = !(mImageRegionRect.x == 0 && mImageRegionRect.y == 0 && - mImageRegionRect.width == origWidth && mImageRegionRect.height == origHeight); - - CGImageRef finalImage = origImage; - if (createSubImage) { - // if mImageRegionRect is set using CSS, we need to slice a piece out of the overall - // image to use as the icon - finalImage = ::CGImageCreateWithImageInRect(origImage, - ::CGRectMake(mImageRegionRect.x, - mImageRegionRect.y, - mImageRegionRect.width, - mImageRegionRect.height)); - ::CGImageRelease(origImage); - if (!finalImage) { - [mNativeMenuItem setImage:nil]; - return NS_ERROR_FAILURE; - } - } - - NSImage *newImage = nil; - rv = nsCocoaUtils::CreateNSImageFromCGImage(finalImage, &newImage); - if (NS_FAILED(rv) || !newImage) { - [mNativeMenuItem setImage:nil]; - ::CGImageRelease(finalImage); - return NS_ERROR_FAILURE; - } - - [newImage setSize:NSMakeSize(kIconWidth, kIconHeight)]; - [mNativeMenuItem setImage:newImage]; - - [newImage release]; - ::CGImageRelease(finalImage); - - mLoadedIcon = true; - mSetIcon = true; - - if (mMenuObject) { - mMenuObject->IconUpdated(); - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} diff --git a/widget/cocoa/nsMenuItemX.h b/widget/cocoa/nsMenuItemX.h deleted file mode 100644 index 67ae32c99c..0000000000 --- a/widget/cocoa/nsMenuItemX.h +++ /dev/null @@ -1,75 +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 nsMenuItemX_h_ -#define nsMenuItemX_h_ - -#include "mozilla/RefPtr.h" -#include "nsMenuBaseX.h" -#include "nsMenuGroupOwnerX.h" -#include "nsChangeObserver.h" - -#import - -class nsString; -class nsMenuItemIconX; -class nsMenuX; - -enum { - knsMenuItemNoModifier = 0, - knsMenuItemShiftModifier = (1 << 0), - knsMenuItemAltModifier = (1 << 1), - knsMenuItemControlModifier = (1 << 2), - knsMenuItemCommandModifier = (1 << 3) -}; - -enum EMenuItemType { - eRegularMenuItemType = 0, - eCheckboxMenuItemType, - eRadioMenuItemType, - eSeparatorMenuItemType -}; - - -// Once instantiated, this object lives until its DOM node or its parent window is destroyed. -// Do not hold references to this, they can become invalid any time the DOM node can be destroyed. -class nsMenuItemX : public nsMenuObjectX, - public nsChangeObserver -{ -public: - nsMenuItemX(); - virtual ~nsMenuItemX(); - - NS_DECL_CHANGEOBSERVER - - // nsMenuObjectX - void* NativeData() override {return (void*)mNativeMenuItem;} - nsMenuObjectTypeX MenuObjectType() override {return eMenuItemObjectType;} - - // nsMenuItemX - nsresult Create(nsMenuX* aParent, const nsString& aLabel, EMenuItemType aItemType, - nsMenuGroupOwnerX* aMenuGroupOwner, nsIContent* aNode); - nsresult SetChecked(bool aIsChecked); - EMenuItemType GetMenuItemType(); - void DoCommand(); - nsresult DispatchDOMEvent(const nsString &eventName, bool* preventDefaultCalled); - void SetupIcon(); - -protected: - void UncheckRadioSiblings(nsIContent* inCheckedElement); - void SetKeyEquiv(); - - EMenuItemType mType; - // nsMenuItemX objects should always have a valid native menu item. - NSMenuItem* mNativeMenuItem; // [strong] - nsMenuX* mMenuParent; // [weak] - nsMenuGroupOwnerX* mMenuGroupOwner; // [weak] - nsCOMPtr mCommandContent; - // The icon object should never outlive its creating nsMenuItemX object. - RefPtr mIcon; - bool mIsChecked; -}; - -#endif // nsMenuItemX_h_ diff --git a/widget/cocoa/nsMenuItemX.mm b/widget/cocoa/nsMenuItemX.mm deleted file mode 100644 index 114b69f430..0000000000 --- a/widget/cocoa/nsMenuItemX.mm +++ /dev/null @@ -1,369 +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 "nsMenuItemX.h" -#include "nsMenuBarX.h" -#include "nsMenuX.h" -#include "nsMenuItemIconX.h" -#include "nsMenuUtilsX.h" -#include "nsCocoaUtils.h" - -#include "nsObjCExceptions.h" - -#include "nsCOMPtr.h" -#include "nsGkAtoms.h" - -#include "mozilla/dom/Element.h" -#include "nsIWidget.h" -#include "nsIDocument.h" -#include "nsIDOMDocument.h" -#include "nsIDOMElement.h" -#include "nsIDOMEvent.h" - -nsMenuItemX::nsMenuItemX() -{ - mType = eRegularMenuItemType; - mNativeMenuItem = nil; - mMenuParent = nullptr; - mMenuGroupOwner = nullptr; - mIsChecked = false; - - MOZ_COUNT_CTOR(nsMenuItemX); -} - -nsMenuItemX::~nsMenuItemX() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // Prevent the icon object from outliving us. - if (mIcon) - mIcon->Destroy(); - - // autorelease the native menu item so that anything else happening to this - // object happens before the native menu item actually dies - [mNativeMenuItem autorelease]; - - if (mContent) - mMenuGroupOwner->UnregisterForContentChanges(mContent); - if (mCommandContent) - mMenuGroupOwner->UnregisterForContentChanges(mCommandContent); - - MOZ_COUNT_DTOR(nsMenuItemX); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsresult nsMenuItemX::Create(nsMenuX* aParent, const nsString& aLabel, EMenuItemType aItemType, - nsMenuGroupOwnerX* aMenuGroupOwner, nsIContent* aNode) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - mType = aItemType; - mMenuParent = aParent; - mContent = aNode; - - mMenuGroupOwner = aMenuGroupOwner; - NS_ASSERTION(mMenuGroupOwner, "No menu owner given, must have one!"); - - mMenuGroupOwner->RegisterForContentChanges(mContent, this); - - nsIDocument *doc = mContent->GetUncomposedDoc(); - - // if we have a command associated with this menu item, register for changes - // to the command DOM node - if (doc) { - nsAutoString ourCommand; - mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::command, ourCommand); - - if (!ourCommand.IsEmpty()) { - nsIContent *commandElement = doc->GetElementById(ourCommand); - - if (commandElement) { - mCommandContent = commandElement; - // register to observe the command DOM element - mMenuGroupOwner->RegisterForContentChanges(mCommandContent, this); - } - } - } - - // decide enabled state based on command content if it exists, otherwise do it based - // on our own content - bool isEnabled; - if (mCommandContent) - isEnabled = !mCommandContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled, nsGkAtoms::_true, eCaseMatters); - else - isEnabled = !mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled, nsGkAtoms::_true, eCaseMatters); - - // set up the native menu item - if (mType == eSeparatorMenuItemType) { - mNativeMenuItem = [[NSMenuItem separatorItem] retain]; - } - else { - NSString *newCocoaLabelString = nsMenuUtilsX::GetTruncatedCocoaLabel(aLabel); - mNativeMenuItem = [[NSMenuItem alloc] initWithTitle:newCocoaLabelString action:nil keyEquivalent:@""]; - - [mNativeMenuItem setEnabled:(BOOL)isEnabled]; - - SetChecked(mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::checked, - nsGkAtoms::_true, eCaseMatters)); - SetKeyEquiv(); - } - - mIcon = new nsMenuItemIconX(this, mContent, mNativeMenuItem); - if (!mIcon) - return NS_ERROR_OUT_OF_MEMORY; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -nsresult nsMenuItemX::SetChecked(bool aIsChecked) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - mIsChecked = aIsChecked; - - // update the content model. This will also handle unchecking our siblings - // if we are a radiomenu - mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::checked, - mIsChecked ? NS_LITERAL_STRING("true") : NS_LITERAL_STRING("false"), true); - - // update native menu item - if (mIsChecked) - [mNativeMenuItem setState:NSOnState]; - else - [mNativeMenuItem setState:NSOffState]; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -EMenuItemType nsMenuItemX::GetMenuItemType() -{ - return mType; -} - -// Executes the "cached" javaScript command. -// Returns NS_OK if the command was executed properly, otherwise an error code. -void nsMenuItemX::DoCommand() -{ - // flip "checked" state if we're a checkbox menu, or an un-checked radio menu - if (mType == eCheckboxMenuItemType || - (mType == eRadioMenuItemType && !mIsChecked)) { - if (!mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::autocheck, - nsGkAtoms::_false, eCaseMatters)) - SetChecked(!mIsChecked); - /* the AttributeChanged code will update all the internal state */ - } - - nsMenuUtilsX::DispatchCommandTo(mContent); -} - -nsresult nsMenuItemX::DispatchDOMEvent(const nsString &eventName, bool *preventDefaultCalled) -{ - if (!mContent) - return NS_ERROR_FAILURE; - - // get owner document for content - nsCOMPtr parentDoc = mContent->OwnerDoc(); - - // get interface for creating DOM events from content owner document - nsCOMPtr domDoc = do_QueryInterface(parentDoc); - if (!domDoc) { - NS_WARNING("Failed to QI parent nsIDocument to nsIDOMDocument"); - return NS_ERROR_FAILURE; - } - - // create DOM event - nsCOMPtr event; - nsresult rv = domDoc->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event)); - if (NS_FAILED(rv)) { - NS_WARNING("Failed to create nsIDOMEvent"); - return rv; - } - event->InitEvent(eventName, true, true); - - // mark DOM event as trusted - event->SetTrusted(true); - - // send DOM event - rv = mContent->DispatchEvent(event, preventDefaultCalled); - if (NS_FAILED(rv)) { - NS_WARNING("Failed to send DOM event via EventTarget"); - return rv; - } - - return NS_OK; -} - -// Walk the sibling list looking for nodes with the same name and -// uncheck them all. -void nsMenuItemX::UncheckRadioSiblings(nsIContent* inCheckedContent) -{ - nsAutoString myGroupName; - inCheckedContent->GetAttr(kNameSpaceID_None, nsGkAtoms::name, myGroupName); - if (!myGroupName.Length()) // no groupname, nothing to do - return; - - nsCOMPtr parent = inCheckedContent->GetParent(); - if (!parent) - return; - - // loop over siblings - uint32_t count = parent->GetChildCount(); - for (uint32_t i = 0; i < count; i++) { - nsIContent *sibling = parent->GetChildAt(i); - if (sibling) { - if (sibling != inCheckedContent) { // skip this node - // if the current sibling is in the same group, clear it - if (sibling->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name, - myGroupName, eCaseMatters)) - sibling->SetAttr(kNameSpaceID_None, nsGkAtoms::checked, NS_LITERAL_STRING("false"), true); - } - } - } -} - -void nsMenuItemX::SetKeyEquiv() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // Set key shortcut and modifiers - nsAutoString keyValue; - mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::key, keyValue); - if (!keyValue.IsEmpty() && mContent->GetUncomposedDoc()) { - nsIContent *keyContent = mContent->GetUncomposedDoc()->GetElementById(keyValue); - if (keyContent) { - nsAutoString keyChar; - bool hasKey = keyContent->GetAttr(kNameSpaceID_None, nsGkAtoms::key, keyChar); - - if (!hasKey || keyChar.IsEmpty()) { - nsAutoString keyCodeName; - keyContent->GetAttr(kNameSpaceID_None, nsGkAtoms::keycode, keyCodeName); - uint32_t charCode = - nsCocoaUtils::ConvertGeckoNameToMacCharCode(keyCodeName); - if (charCode) { - keyChar.Assign(charCode); - } - else { - keyChar.Assign(NS_LITERAL_STRING(" ")); - } - } - - nsAutoString modifiersStr; - keyContent->GetAttr(kNameSpaceID_None, nsGkAtoms::modifiers, modifiersStr); - uint8_t modifiers = nsMenuUtilsX::GeckoModifiersForNodeAttribute(modifiersStr); - - unsigned int macModifiers = nsMenuUtilsX::MacModifiersForGeckoModifiers(modifiers); - [mNativeMenuItem setKeyEquivalentModifierMask:macModifiers]; - - NSString *keyEquivalent = [[NSString stringWithCharacters:(unichar*)keyChar.get() - length:keyChar.Length()] lowercaseString]; - if ([keyEquivalent isEqualToString:@" "]) - [mNativeMenuItem setKeyEquivalent:@""]; - else - [mNativeMenuItem setKeyEquivalent:keyEquivalent]; - - return; - } - } - - // if the key was removed, clear the key - [mNativeMenuItem setKeyEquivalent:@""]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// -// nsChangeObserver -// - -void -nsMenuItemX::ObserveAttributeChanged(nsIDocument *aDocument, nsIContent *aContent, nsIAtom *aAttribute) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!aContent) - return; - - if (aContent == mContent) { // our own content node changed - if (aAttribute == nsGkAtoms::checked) { - // if we're a radio menu, uncheck our sibling radio items. No need to - // do any of this if we're just a normal check menu. - if (mType == eRadioMenuItemType) { - if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::checked, - nsGkAtoms::_true, eCaseMatters)) - UncheckRadioSiblings(mContent); - } - mMenuParent->SetRebuild(true); - } - else if (aAttribute == nsGkAtoms::hidden || - aAttribute == nsGkAtoms::collapsed || - aAttribute == nsGkAtoms::label) { - mMenuParent->SetRebuild(true); - } - else if (aAttribute == nsGkAtoms::key) { - SetKeyEquiv(); - } - else if (aAttribute == nsGkAtoms::image) { - SetupIcon(); - } - else if (aAttribute == nsGkAtoms::disabled) { - if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled, nsGkAtoms::_true, eCaseMatters)) - [mNativeMenuItem setEnabled:NO]; - else - [mNativeMenuItem setEnabled:YES]; - } - } - else if (aContent == mCommandContent) { - // the only thing that really matters when the menu isn't showing is the - // enabled state since it enables/disables keyboard commands - if (aAttribute == nsGkAtoms::disabled) { - // first we sync our menu item DOM node with the command DOM node - nsAutoString commandDisabled; - nsAutoString menuDisabled; - aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::disabled, commandDisabled); - mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::disabled, menuDisabled); - if (!commandDisabled.Equals(menuDisabled)) { - // The menu's disabled state needs to be updated to match the command. - if (commandDisabled.IsEmpty()) - mContent->UnsetAttr(kNameSpaceID_None, nsGkAtoms::disabled, true); - else - mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::disabled, commandDisabled, true); - } - // now we sync our native menu item with the command DOM node - if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled, nsGkAtoms::_true, eCaseMatters)) - [mNativeMenuItem setEnabled:NO]; - else - [mNativeMenuItem setEnabled:YES]; - } - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void nsMenuItemX::ObserveContentRemoved(nsIDocument *aDocument, nsIContent *aChild, int32_t aIndexInContainer) -{ - if (aChild == mCommandContent) { - mMenuGroupOwner->UnregisterForContentChanges(mCommandContent); - mCommandContent = nullptr; - } - - mMenuParent->SetRebuild(true); -} - -void nsMenuItemX::ObserveContentInserted(nsIDocument *aDocument, nsIContent* aContainer, - nsIContent *aChild) -{ - mMenuParent->SetRebuild(true); -} - -void nsMenuItemX::SetupIcon() -{ - if (mIcon) - mIcon->SetupIcon(); -} diff --git a/widget/cocoa/nsMenuUtilsX.h b/widget/cocoa/nsMenuUtilsX.h deleted file mode 100644 index 1571cdfb0a..0000000000 --- a/widget/cocoa/nsMenuUtilsX.h +++ /dev/null @@ -1,31 +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 nsMenuUtilsX_h_ -#define nsMenuUtilsX_h_ - -#include "nscore.h" -#include "nsMenuBaseX.h" - -#import - -class nsIContent; -class nsString; -class nsMenuBarX; - -// Namespace containing utility functions used in our native menu implementation. -namespace nsMenuUtilsX -{ - void DispatchCommandTo(nsIContent* aTargetContent); - NSString* GetTruncatedCocoaLabel(const nsString& itemLabel); - uint8_t GeckoModifiersForNodeAttribute(const nsString& modifiersAttribute); - unsigned int MacModifiersForGeckoModifiers(uint8_t geckoModifiers); - nsMenuBarX* GetHiddenWindowMenuBar(); // returned object is not retained - NSMenuItem* GetStandardEditMenuItem(); // returned object is not retained - bool NodeIsHiddenOrCollapsed(nsIContent* inContent); - int CalculateNativeInsertionPoint(nsMenuObjectX* aParent, nsMenuObjectX* aChild); -} // namespace nsMenuUtilsX - -#endif // nsMenuUtilsX_h_ diff --git a/widget/cocoa/nsMenuUtilsX.mm b/widget/cocoa/nsMenuUtilsX.mm deleted file mode 100644 index db64717127..0000000000 --- a/widget/cocoa/nsMenuUtilsX.mm +++ /dev/null @@ -1,223 +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/dom/Event.h" -#include "nsMenuUtilsX.h" -#include "nsMenuBarX.h" -#include "nsMenuX.h" -#include "nsMenuItemX.h" -#include "nsStandaloneNativeMenu.h" -#include "nsObjCExceptions.h" -#include "nsCocoaUtils.h" -#include "nsCocoaWindow.h" -#include "nsGkAtoms.h" -#include "nsIDocument.h" -#include "nsIDOMDocument.h" -#include "nsIDOMXULCommandEvent.h" -#include "nsPIDOMWindow.h" -#include "nsQueryObject.h" - -using namespace mozilla; - -void nsMenuUtilsX::DispatchCommandTo(nsIContent* aTargetContent) -{ - NS_PRECONDITION(aTargetContent, "null ptr"); - - nsIDocument* doc = aTargetContent->OwnerDoc(); - if (doc) { - ErrorResult rv; - RefPtr event = - doc->CreateEvent(NS_LITERAL_STRING("xulcommandevent"), rv); - nsCOMPtr command = do_QueryObject(event); - - // FIXME: Should probably figure out how to init this with the actual - // pressed keys, but this is a big old edge case anyway. -dwh - if (command && - NS_SUCCEEDED(command->InitCommandEvent(NS_LITERAL_STRING("command"), - true, true, - doc->GetInnerWindow(), 0, - false, false, false, - false, nullptr))) { - event->SetTrusted(true); - bool dummy; - aTargetContent->DispatchEvent(event, &dummy); - } - } -} - -NSString* nsMenuUtilsX::GetTruncatedCocoaLabel(const nsString& itemLabel) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - // We want to truncate long strings to some reasonable pixel length but there is no - // good API for doing that which works for all OS versions and architectures. For now - // we'll do nothing for consistency and depend on good user interface design to limit - // string lengths. - return [NSString stringWithCharacters:reinterpret_cast(itemLabel.get()) - length:itemLabel.Length()]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -uint8_t nsMenuUtilsX::GeckoModifiersForNodeAttribute(const nsString& modifiersAttribute) -{ - uint8_t modifiers = knsMenuItemNoModifier; - char* str = ToNewCString(modifiersAttribute); - char* newStr; - char* token = strtok_r(str, ", \t", &newStr); - while (token != NULL) { - if (strcmp(token, "shift") == 0) - modifiers |= knsMenuItemShiftModifier; - else if (strcmp(token, "alt") == 0) - modifiers |= knsMenuItemAltModifier; - else if (strcmp(token, "control") == 0) - modifiers |= knsMenuItemControlModifier; - else if ((strcmp(token, "accel") == 0) || - (strcmp(token, "meta") == 0)) { - modifiers |= knsMenuItemCommandModifier; - } - token = strtok_r(newStr, ", \t", &newStr); - } - free(str); - - return modifiers; -} - -unsigned int nsMenuUtilsX::MacModifiersForGeckoModifiers(uint8_t geckoModifiers) -{ - unsigned int macModifiers = 0; - - if (geckoModifiers & knsMenuItemShiftModifier) - macModifiers |= NSShiftKeyMask; - if (geckoModifiers & knsMenuItemAltModifier) - macModifiers |= NSAlternateKeyMask; - if (geckoModifiers & knsMenuItemControlModifier) - macModifiers |= NSControlKeyMask; - if (geckoModifiers & knsMenuItemCommandModifier) - macModifiers |= NSCommandKeyMask; - - return macModifiers; -} - -nsMenuBarX* nsMenuUtilsX::GetHiddenWindowMenuBar() -{ - nsIWidget* hiddenWindowWidgetNoCOMPtr = nsCocoaUtils::GetHiddenWindowWidget(); - if (hiddenWindowWidgetNoCOMPtr) - return static_cast(hiddenWindowWidgetNoCOMPtr)->GetMenuBar(); - else - return nullptr; -} - -// It would be nice if we could localize these edit menu names. -NSMenuItem* nsMenuUtilsX::GetStandardEditMenuItem() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - // In principle we should be able to allocate this once and then always - // return the same object. But weird interactions happen between native - // app-modal dialogs and Gecko-modal dialogs that open above them. So what - // we return here isn't always released before it needs to be added to - // another menu. See bmo bug 468393. - NSMenuItem* standardEditMenuItem = - [[[NSMenuItem alloc] initWithTitle:@"Edit" action:nil keyEquivalent:@""] autorelease]; - NSMenu* standardEditMenu = [[NSMenu alloc] initWithTitle:@"Edit"]; - [standardEditMenuItem setSubmenu:standardEditMenu]; - [standardEditMenu release]; - - // Add Undo - NSMenuItem* undoItem = [[NSMenuItem alloc] initWithTitle:@"Undo" action:@selector(undo:) keyEquivalent:@"z"]; - [standardEditMenu addItem:undoItem]; - [undoItem release]; - - // Add Redo - NSMenuItem* redoItem = [[NSMenuItem alloc] initWithTitle:@"Redo" action:@selector(redo:) keyEquivalent:@"Z"]; - [standardEditMenu addItem:redoItem]; - [redoItem release]; - - // Add separator - [standardEditMenu addItem:[NSMenuItem separatorItem]]; - - // Add Cut - NSMenuItem* cutItem = [[NSMenuItem alloc] initWithTitle:@"Cut" action:@selector(cut:) keyEquivalent:@"x"]; - [standardEditMenu addItem:cutItem]; - [cutItem release]; - - // Add Copy - NSMenuItem* copyItem = [[NSMenuItem alloc] initWithTitle:@"Copy" action:@selector(copy:) keyEquivalent:@"c"]; - [standardEditMenu addItem:copyItem]; - [copyItem release]; - - // Add Paste - NSMenuItem* pasteItem = [[NSMenuItem alloc] initWithTitle:@"Paste" action:@selector(paste:) keyEquivalent:@"v"]; - [standardEditMenu addItem:pasteItem]; - [pasteItem release]; - - // Add Delete - NSMenuItem* deleteItem = [[NSMenuItem alloc] initWithTitle:@"Delete" action:@selector(delete:) keyEquivalent:@""]; - [standardEditMenu addItem:deleteItem]; - [deleteItem release]; - - // Add Select All - NSMenuItem* selectAllItem = [[NSMenuItem alloc] initWithTitle:@"Select All" action:@selector(selectAll:) keyEquivalent:@"a"]; - [standardEditMenu addItem:selectAllItem]; - [selectAllItem release]; - - return standardEditMenuItem; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -bool nsMenuUtilsX::NodeIsHiddenOrCollapsed(nsIContent* inContent) -{ - return (inContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::hidden, - nsGkAtoms::_true, eCaseMatters) || - inContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::collapsed, - nsGkAtoms::_true, eCaseMatters)); -} - -// Determines how many items are visible among the siblings in a menu that are -// before the given child. This will not count the application menu. -int nsMenuUtilsX::CalculateNativeInsertionPoint(nsMenuObjectX* aParent, - nsMenuObjectX* aChild) -{ - int insertionPoint = 0; - nsMenuObjectTypeX parentType = aParent->MenuObjectType(); - if (parentType == eMenuBarObjectType) { - nsMenuBarX* menubarParent = static_cast(aParent); - uint32_t numMenus = menubarParent->GetMenuCount(); - for (uint32_t i = 0; i < numMenus; i++) { - nsMenuX* currMenu = menubarParent->GetMenuAt(i); - if (currMenu == aChild) - return insertionPoint; // we found ourselves, break out - if (currMenu && [currMenu->NativeMenuItem() menu]) - insertionPoint++; - } - } - else if (parentType == eSubmenuObjectType || - parentType == eStandaloneNativeMenuObjectType) { - nsMenuX* menuParent; - if (parentType == eSubmenuObjectType) - menuParent = static_cast(aParent); - else - menuParent = static_cast(aParent)->GetMenuXObject(); - - uint32_t numItems = menuParent->GetItemCount(); - for (uint32_t i = 0; i < numItems; i++) { - // Using GetItemAt instead of GetVisibleItemAt to avoid O(N^2) - nsMenuObjectX* currItem = menuParent->GetItemAt(i); - if (currItem == aChild) - return insertionPoint; // we found ourselves, break out - NSMenuItem* nativeItem = nil; - nsMenuObjectTypeX currItemType = currItem->MenuObjectType(); - if (currItemType == eSubmenuObjectType) - nativeItem = static_cast(currItem)->NativeMenuItem(); - else - nativeItem = (NSMenuItem*)(currItem->NativeData()); - if ([nativeItem menu]) - insertionPoint++; - } - } - return insertionPoint; -} diff --git a/widget/cocoa/nsMenuX.h b/widget/cocoa/nsMenuX.h deleted file mode 100644 index 7b5146a0b8..0000000000 --- a/widget/cocoa/nsMenuX.h +++ /dev/null @@ -1,101 +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 nsMenuX_h_ -#define nsMenuX_h_ - -#import - -#include "mozilla/RefPtr.h" -#include "mozilla/UniquePtr.h" -#include "nsMenuBaseX.h" -#include "nsMenuBarX.h" -#include "nsMenuGroupOwnerX.h" -#include "nsCOMPtr.h" -#include "nsChangeObserver.h" - -class nsMenuX; -class nsMenuItemIconX; -class nsMenuItemX; -class nsIWidget; - -// MenuDelegate is used to receive Cocoa notifications for setting -// up carbon events. Protocol is defined as of 10.6 SDK. -@interface MenuDelegate : NSObject < NSMenuDelegate > -{ - nsMenuX* mGeckoMenu; // weak ref -} -- (id)initWithGeckoMenu:(nsMenuX*)geckoMenu; -@end - -// Once instantiated, this object lives until its DOM node or its parent window is destroyed. -// Do not hold references to this, they can become invalid any time the DOM node can be destroyed. -class nsMenuX : public nsMenuObjectX, - public nsChangeObserver -{ -public: - nsMenuX(); - virtual ~nsMenuX(); - - // If > 0, the OS is indexing all the app's menus (triggered by opening - // Help menu on Leopard and higher). There are some things that are - // unsafe to do while this is happening. - static int32_t sIndexingMenuLevel; - - NS_DECL_CHANGEOBSERVER - - // nsMenuObjectX - void* NativeData() override {return (void*)mNativeMenu;} - nsMenuObjectTypeX MenuObjectType() override {return eSubmenuObjectType;} - void IconUpdated() override { mParent->IconUpdated(); } - - // nsMenuX - nsresult Create(nsMenuObjectX* aParent, nsMenuGroupOwnerX* aMenuGroupOwner, nsIContent* aNode); - uint32_t GetItemCount(); - nsMenuObjectX* GetItemAt(uint32_t aPos); - nsresult GetVisibleItemCount(uint32_t &aCount); - nsMenuObjectX* GetVisibleItemAt(uint32_t aPos); - nsEventStatus MenuOpened(); - void MenuClosed(); - void SetRebuild(bool aMenuEvent); - NSMenuItem* NativeMenuItem(); - nsresult SetupIcon(); - - static bool IsXULHelpMenu(nsIContent* aMenuContent); - -protected: - void MenuConstruct(); - nsresult RemoveAll(); - nsresult SetEnabled(bool aIsEnabled); - nsresult GetEnabled(bool* aIsEnabled); - void GetMenuPopupContent(nsIContent** aResult); - bool OnOpen(); - bool OnClose(); - nsresult AddMenuItem(nsMenuItemX* aMenuItem); - nsMenuX* AddMenu(mozilla::UniquePtr aMenu); - void LoadMenuItem(nsIContent* inMenuItemContent); - void LoadSubMenu(nsIContent* inMenuContent); - GeckoNSMenu* CreateMenuWithGeckoString(nsString& menuTitle); - - nsTArray> mMenuObjectsArray; - nsString mLabel; - uint32_t mVisibleItemsCount; // cache - nsMenuObjectX* mParent; // [weak] - nsMenuGroupOwnerX* mMenuGroupOwner; // [weak] - // The icon object should never outlive its creating nsMenuX object. - RefPtr mIcon; - GeckoNSMenu* mNativeMenu; // [strong] - MenuDelegate* mMenuDelegate; // [strong] - // nsMenuX objects should always have a valid native menu item. - NSMenuItem* mNativeMenuItem; // [strong] - bool mIsEnabled; - bool mDestroyHandlerCalled; - bool mNeedsRebuild; - bool mConstructed; - bool mVisible; - bool mXBLAttached; -}; - -#endif // nsMenuX_h_ diff --git a/widget/cocoa/nsMenuX.mm b/widget/cocoa/nsMenuX.mm deleted file mode 100644 index 757221eac6..0000000000 --- a/widget/cocoa/nsMenuX.mm +++ /dev/null @@ -1,1051 +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 - -#include "nsMenuX.h" -#include "nsMenuItemX.h" -#include "nsMenuUtilsX.h" -#include "nsMenuItemIconX.h" -#include "nsStandaloneNativeMenu.h" - -#include "nsObjCExceptions.h" - -#include "nsToolkit.h" -#include "nsCocoaUtils.h" -#include "nsCOMPtr.h" -#include "prinrval.h" -#include "nsString.h" -#include "nsReadableUtils.h" -#include "nsUnicharUtils.h" -#include "plstr.h" -#include "nsGkAtoms.h" -#include "nsCRT.h" -#include "nsBaseWidget.h" - -#include "nsIDocument.h" -#include "nsIContent.h" -#include "nsIDOMDocument.h" -#include "nsIDocumentObserver.h" -#include "nsIComponentManager.h" -#include "nsIRollupListener.h" -#include "nsIDOMElement.h" -#include "nsBindingManager.h" -#include "nsIServiceManager.h" -#include "nsXULPopupManager.h" -#include "mozilla/dom/ScriptSettings.h" - -#include "jsapi.h" -#include "nsIScriptGlobalObject.h" -#include "nsIScriptContext.h" -#include "nsIXPConnect.h" - -#include "mozilla/MouseEvents.h" - -using namespace mozilla; - -static bool gConstructingMenu = false; -static bool gMenuMethodsSwizzled = false; - -int32_t nsMenuX::sIndexingMenuLevel = 0; - - -// -// Objective-C class used for representedObject -// - -@implementation MenuItemInfo - -- (id) initWithMenuGroupOwner:(nsMenuGroupOwnerX *)aMenuGroupOwner -{ - if ((self = [super init]) != nil) { - [self setMenuGroupOwner:aMenuGroupOwner]; - } - return self; -} - -- (void) dealloc -{ - [self setMenuGroupOwner:nullptr]; - [super dealloc]; -} - -- (nsMenuGroupOwnerX *) menuGroupOwner -{ - return mMenuGroupOwner; -} - -- (void) setMenuGroupOwner:(nsMenuGroupOwnerX *)aMenuGroupOwner -{ - // weak reference as the nsMenuGroupOwnerX owns all of its sub-objects - mMenuGroupOwner = aMenuGroupOwner; - if (aMenuGroupOwner) { - aMenuGroupOwner->AddMenuItemInfoToSet(self); - } -} - -@end - - -// -// nsMenuX -// - -nsMenuX::nsMenuX() -: mVisibleItemsCount(0), mParent(nullptr), mMenuGroupOwner(nullptr), - mNativeMenu(nil), mNativeMenuItem(nil), mIsEnabled(true), - mDestroyHandlerCalled(false), mNeedsRebuild(true), - mConstructed(false), mVisible(true), mXBLAttached(false) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!gMenuMethodsSwizzled) { - nsToolkit::SwizzleMethods([NSMenu class], @selector(_addItem:toTable:), - @selector(nsMenuX_NSMenu_addItem:toTable:), true); - nsToolkit::SwizzleMethods([NSMenu class], @selector(_removeItem:fromTable:), - @selector(nsMenuX_NSMenu_removeItem:fromTable:), true); - // On SnowLeopard the Shortcut framework (which contains the - // SCTGRLIndex class) is loaded on demand, whenever the user first opens - // a menu (which normally hasn't happened yet). So we need to load it - // here explicitly. - dlopen("/System/Library/PrivateFrameworks/Shortcut.framework/Shortcut", RTLD_LAZY); - Class SCTGRLIndexClass = ::NSClassFromString(@"SCTGRLIndex"); - nsToolkit::SwizzleMethods(SCTGRLIndexClass, @selector(indexMenuBarDynamically), - @selector(nsMenuX_SCTGRLIndex_indexMenuBarDynamically)); - - gMenuMethodsSwizzled = true; - } - - mMenuDelegate = [[MenuDelegate alloc] initWithGeckoMenu:this]; - - if (!nsMenuBarX::sNativeEventTarget) - nsMenuBarX::sNativeEventTarget = [[NativeMenuItemTarget alloc] init]; - - MOZ_COUNT_CTOR(nsMenuX); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsMenuX::~nsMenuX() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // Prevent the icon object from outliving us. - if (mIcon) - mIcon->Destroy(); - - RemoveAll(); - - [mNativeMenu setDelegate:nil]; - [mNativeMenu release]; - [mMenuDelegate release]; - // autorelease the native menu item so that anything else happening to this - // object happens before the native menu item actually dies - [mNativeMenuItem autorelease]; - - // alert the change notifier we don't care no more - if (mContent) - mMenuGroupOwner->UnregisterForContentChanges(mContent); - - MOZ_COUNT_DTOR(nsMenuX); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsresult nsMenuX::Create(nsMenuObjectX* aParent, nsMenuGroupOwnerX* aMenuGroupOwner, nsIContent* aNode) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - mContent = aNode; - mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::label, mLabel); - mNativeMenu = CreateMenuWithGeckoString(mLabel); - - // register this menu to be notified when changes are made to our content object - mMenuGroupOwner = aMenuGroupOwner; // weak ref - NS_ASSERTION(mMenuGroupOwner, "No menu owner given, must have one"); - mMenuGroupOwner->RegisterForContentChanges(mContent, this); - - mParent = aParent; - // our parent could be either a menu bar (if we're toplevel) or a menu (if we're a submenu) - -#ifdef DEBUG - nsMenuObjectTypeX parentType = -#endif - mParent->MenuObjectType(); - NS_ASSERTION((parentType == eMenuBarObjectType || parentType == eSubmenuObjectType || parentType == eStandaloneNativeMenuObjectType), - "Menu parent not a menu bar, menu, or native menu!"); - - if (nsMenuUtilsX::NodeIsHiddenOrCollapsed(mContent)) - mVisible = false; - if (mContent->GetChildCount() == 0) - mVisible = false; - - NSString *newCocoaLabelString = nsMenuUtilsX::GetTruncatedCocoaLabel(mLabel); - mNativeMenuItem = [[NSMenuItem alloc] initWithTitle:newCocoaLabelString action:nil keyEquivalent:@""]; - [mNativeMenuItem setSubmenu:mNativeMenu]; - - SetEnabled(!mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled, - nsGkAtoms::_true, eCaseMatters)); - - // We call MenuConstruct here because keyboard commands are dependent upon - // native menu items being created. If we only call MenuConstruct when a menu - // is actually selected, then we can't access keyboard commands until the - // menu gets selected, which is bad. - MenuConstruct(); - - mIcon = new nsMenuItemIconX(this, mContent, mNativeMenuItem); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -nsresult nsMenuX::AddMenuItem(nsMenuItemX* aMenuItem) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (!aMenuItem) - return NS_ERROR_INVALID_ARG; - - mMenuObjectsArray.AppendElement(aMenuItem); - if (nsMenuUtilsX::NodeIsHiddenOrCollapsed(aMenuItem->Content())) - return NS_OK; - ++mVisibleItemsCount; - - NSMenuItem* newNativeMenuItem = (NSMenuItem*)aMenuItem->NativeData(); - - // add the menu item to this menu - [mNativeMenu addItem:newNativeMenuItem]; - - // set up target/action - [newNativeMenuItem setTarget:nsMenuBarX::sNativeEventTarget]; - [newNativeMenuItem setAction:@selector(menuItemHit:)]; - - // set its command. we get the unique command id from the menubar - [newNativeMenuItem setTag:mMenuGroupOwner->RegisterForCommand(aMenuItem)]; - MenuItemInfo * info = [[MenuItemInfo alloc] initWithMenuGroupOwner:mMenuGroupOwner]; - [newNativeMenuItem setRepresentedObject:info]; - [info release]; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -nsMenuX* nsMenuX::AddMenu(UniquePtr aMenu) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - // aMenu transfers ownership to mMenuObjectsArray and becomes nullptr, so - // we need to keep a raw pointer to access it conveniently. - nsMenuX* menu = aMenu.get(); - mMenuObjectsArray.AppendElement(Move(aMenu)); - - if (nsMenuUtilsX::NodeIsHiddenOrCollapsed(menu->Content())) { - return menu; - } - - ++mVisibleItemsCount; - - // We have to add a menu item and then associate the menu with it - NSMenuItem* newNativeMenuItem = menu->NativeMenuItem(); - if (newNativeMenuItem) { - [mNativeMenu addItem:newNativeMenuItem]; - [newNativeMenuItem setSubmenu:(NSMenu*)menu->NativeData()]; - } - - return menu; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(nullptr); -} - -// Includes all items, including hidden/collapsed ones -uint32_t nsMenuX::GetItemCount() -{ - return mMenuObjectsArray.Length(); -} - -// Includes all items, including hidden/collapsed ones -nsMenuObjectX* nsMenuX::GetItemAt(uint32_t aPos) -{ - if (aPos >= (uint32_t)mMenuObjectsArray.Length()) - return NULL; - - return mMenuObjectsArray[aPos].get(); -} - -// Only includes visible items -nsresult nsMenuX::GetVisibleItemCount(uint32_t &aCount) -{ - aCount = mVisibleItemsCount; - return NS_OK; -} - -// Only includes visible items. Note that this is provides O(N) access -// If you need to iterate or search, consider using GetItemAt and doing your own filtering -nsMenuObjectX* nsMenuX::GetVisibleItemAt(uint32_t aPos) -{ - - uint32_t count = mMenuObjectsArray.Length(); - if (aPos >= mVisibleItemsCount || aPos >= count) - return NULL; - - // If there are no invisible items, can provide direct access - if (mVisibleItemsCount == count) - return mMenuObjectsArray[aPos].get(); - - // Otherwise, traverse the array until we find the the item we're looking for. - nsMenuObjectX* item; - uint32_t visibleNodeIndex = 0; - for (uint32_t i = 0; i < count; i++) { - item = mMenuObjectsArray[i].get(); - if (!nsMenuUtilsX::NodeIsHiddenOrCollapsed(item->Content())) { - if (aPos == visibleNodeIndex) { - // we found the visible node we're looking for, return it - return item; - } - visibleNodeIndex++; - } - } - - return NULL; -} - -nsresult nsMenuX::RemoveAll() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (mNativeMenu) { - // clear command id's - int itemCount = [mNativeMenu numberOfItems]; - for (int i = 0; i < itemCount; i++) - mMenuGroupOwner->UnregisterCommand((uint32_t)[[mNativeMenu itemAtIndex:i] tag]); - // get rid of Cocoa menu items - for (int i = [mNativeMenu numberOfItems] - 1; i >= 0; i--) - [mNativeMenu removeItemAtIndex:i]; - } - - mMenuObjectsArray.Clear(); - mVisibleItemsCount = 0; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -nsEventStatus nsMenuX::MenuOpened() -{ - // Open the node. - mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::open, NS_LITERAL_STRING("true"), true); - - // Fire a handler. If we're told to stop, don't build the menu at all - bool keepProcessing = OnOpen(); - - if (!mNeedsRebuild || !keepProcessing) - return nsEventStatus_eConsumeNoDefault; - - if (!mConstructed || mNeedsRebuild) { - if (mNeedsRebuild) - RemoveAll(); - - MenuConstruct(); - mConstructed = true; - } - - nsEventStatus status = nsEventStatus_eIgnore; - WidgetMouseEvent event(true, eXULPopupShown, nullptr, - WidgetMouseEvent::eReal); - - nsCOMPtr popupContent; - GetMenuPopupContent(getter_AddRefs(popupContent)); - nsIContent* dispatchTo = popupContent ? popupContent : mContent; - dispatchTo->DispatchDOMEvent(&event, nullptr, nullptr, &status); - - return nsEventStatus_eConsumeNoDefault; -} - -void nsMenuX::MenuClosed() -{ - if (mConstructed) { - // Don't close if a handler tells us to stop. - if (!OnClose()) - return; - - if (mNeedsRebuild) - mConstructed = false; - - mContent->UnsetAttr(kNameSpaceID_None, nsGkAtoms::open, true); - - nsEventStatus status = nsEventStatus_eIgnore; - WidgetMouseEvent event(true, eXULPopupHidden, nullptr, - WidgetMouseEvent::eReal); - - nsCOMPtr popupContent; - GetMenuPopupContent(getter_AddRefs(popupContent)); - nsIContent* dispatchTo = popupContent ? popupContent : mContent; - dispatchTo->DispatchDOMEvent(&event, nullptr, nullptr, &status); - - mDestroyHandlerCalled = true; - mConstructed = false; - } -} - -void nsMenuX::MenuConstruct() -{ - mConstructed = false; - gConstructingMenu = true; - - // reset destroy handler flag so that we'll know to fire it next time this menu goes away. - mDestroyHandlerCalled = false; - - //printf("nsMenuX::MenuConstruct called for %s = %d \n", NS_LossyConvertUTF16toASCII(mLabel).get(), mNativeMenu); - - // Retrieve our menupopup. - nsCOMPtr menuPopup; - GetMenuPopupContent(getter_AddRefs(menuPopup)); - if (!menuPopup) { - gConstructingMenu = false; - return; - } - - // bug 365405: Manually wrap the menupopup node to make sure it's bounded - if (!mXBLAttached) { - nsresult rv; - nsCOMPtr xpconnect = - do_GetService(nsIXPConnect::GetCID(), &rv); - if (NS_SUCCEEDED(rv)) { - nsIDocument* ownerDoc = menuPopup->OwnerDoc(); - dom::AutoJSAPI jsapi; - if (ownerDoc && jsapi.Init(ownerDoc->GetInnerWindow())) { - JSContext* cx = jsapi.cx(); - JS::RootedObject ignoredObj(cx); - xpconnect->WrapNative(cx, JS::CurrentGlobalOrNull(cx), menuPopup, - NS_GET_IID(nsISupports), ignoredObj.address()); - mXBLAttached = true; - } - } - } - - // Iterate over the kids - uint32_t count = menuPopup->GetChildCount(); - for (uint32_t i = 0; i < count; i++) { - nsIContent *child = menuPopup->GetChildAt(i); - if (child) { - // depending on the type, create a menu item, separator, or submenu - if (child->IsAnyOfXULElements(nsGkAtoms::menuitem, - nsGkAtoms::menuseparator)) { - LoadMenuItem(child); - } else if (child->IsXULElement(nsGkAtoms::menu)) { - LoadSubMenu(child); - } - } - } // for each menu item - - gConstructingMenu = false; - mNeedsRebuild = false; - // printf("Done building, mMenuObjectsArray.Count() = %d \n", mMenuObjectsArray.Count()); -} - -void nsMenuX::SetRebuild(bool aNeedsRebuild) -{ - if (!gConstructingMenu) - mNeedsRebuild = aNeedsRebuild; -} - -nsresult nsMenuX::SetEnabled(bool aIsEnabled) -{ - if (aIsEnabled != mIsEnabled) { - // we always want to rebuild when this changes - mIsEnabled = aIsEnabled; - [mNativeMenuItem setEnabled:(BOOL)mIsEnabled]; - } - return NS_OK; -} - -nsresult nsMenuX::GetEnabled(bool* aIsEnabled) -{ - NS_ENSURE_ARG_POINTER(aIsEnabled); - *aIsEnabled = mIsEnabled; - return NS_OK; -} - -GeckoNSMenu* nsMenuX::CreateMenuWithGeckoString(nsString& menuTitle) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - NSString* title = [NSString stringWithCharacters:(UniChar*)menuTitle.get() length:menuTitle.Length()]; - GeckoNSMenu* myMenu = [[GeckoNSMenu alloc] initWithTitle:title]; - [myMenu setDelegate:mMenuDelegate]; - - // We don't want this menu to auto-enable menu items because then Cocoa - // overrides our decisions and things get incorrectly enabled/disabled. - [myMenu setAutoenablesItems:NO]; - - // we used to install Carbon event handlers here, but since NSMenu* doesn't - // create its underlying MenuRef until just before display, we delay until - // that happens. Now we install the event handlers when Cocoa notifies - // us that a menu is about to display - see the Cocoa MenuDelegate class. - - return myMenu; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -void nsMenuX::LoadMenuItem(nsIContent* inMenuItemContent) -{ - if (!inMenuItemContent) - return; - - nsAutoString menuitemName; - inMenuItemContent->GetAttr(kNameSpaceID_None, nsGkAtoms::label, menuitemName); - - // printf("menuitem %s \n", NS_LossyConvertUTF16toASCII(menuitemName).get()); - - EMenuItemType itemType = eRegularMenuItemType; - if (inMenuItemContent->IsXULElement(nsGkAtoms::menuseparator)) { - itemType = eSeparatorMenuItemType; - } - else { - static nsIContent::AttrValuesArray strings[] = - {&nsGkAtoms::checkbox, &nsGkAtoms::radio, nullptr}; - switch (inMenuItemContent->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::type, - strings, eCaseMatters)) { - case 0: itemType = eCheckboxMenuItemType; break; - case 1: itemType = eRadioMenuItemType; break; - } - } - - // Create the item. - nsMenuItemX* menuItem = new nsMenuItemX(); - if (!menuItem) - return; - - nsresult rv = menuItem->Create(this, menuitemName, itemType, mMenuGroupOwner, inMenuItemContent); - if (NS_FAILED(rv)) { - delete menuItem; - return; - } - - AddMenuItem(menuItem); - - // This needs to happen after the nsIMenuItem object is inserted into - // our item array in AddMenuItem() - menuItem->SetupIcon(); -} - -void nsMenuX::LoadSubMenu(nsIContent* inMenuContent) -{ - auto menu = MakeUnique(); - if (!menu) - return; - - nsresult rv = menu->Create(this, mMenuGroupOwner, inMenuContent); - if (NS_FAILED(rv)) - return; - - // |menu|'s ownership is transfer to AddMenu but, if it is successfully - // added, we can access it via the returned raw pointer. - nsMenuX* menu_ptr = AddMenu(Move(menu)); - - // This needs to happen after the nsIMenu object is inserted into - // our item array in AddMenu() - if (menu_ptr) { - menu_ptr->SetupIcon(); - } -} - -// This menu is about to open. Returns TRUE if we should keep processing the event, -// FALSE if the handler wants to stop the opening of the menu. -bool nsMenuX::OnOpen() -{ - nsEventStatus status = nsEventStatus_eIgnore; - WidgetMouseEvent event(true, eXULPopupShowing, nullptr, - WidgetMouseEvent::eReal); - - nsCOMPtr popupContent; - GetMenuPopupContent(getter_AddRefs(popupContent)); - - nsresult rv = NS_OK; - nsIContent* dispatchTo = popupContent ? popupContent : mContent; - rv = dispatchTo->DispatchDOMEvent(&event, nullptr, nullptr, &status); - if (NS_FAILED(rv) || status == nsEventStatus_eConsumeNoDefault) - return false; - - // If the open is going to succeed we need to walk our menu items, checking to - // see if any of them have a command attribute. If so, several attributes - // must potentially be updated. - - // Get new popup content first since it might have changed as a result of the - // eXULPopupShowing event above. - GetMenuPopupContent(getter_AddRefs(popupContent)); - if (!popupContent) - return true; - - nsXULPopupManager* pm = nsXULPopupManager::GetInstance(); - if (pm) { - pm->UpdateMenuItems(popupContent); - } - - return true; -} - -// Returns TRUE if we should keep processing the event, FALSE if the handler -// wants to stop the closing of the menu. -bool nsMenuX::OnClose() -{ - if (mDestroyHandlerCalled) - return true; - - nsEventStatus status = nsEventStatus_eIgnore; - WidgetMouseEvent event(true, eXULPopupHiding, nullptr, - WidgetMouseEvent::eReal); - - nsCOMPtr popupContent; - GetMenuPopupContent(getter_AddRefs(popupContent)); - - nsresult rv = NS_OK; - nsIContent* dispatchTo = popupContent ? popupContent : mContent; - rv = dispatchTo->DispatchDOMEvent(&event, nullptr, nullptr, &status); - - mDestroyHandlerCalled = true; - - if (NS_FAILED(rv) || status == nsEventStatus_eConsumeNoDefault) - return false; - - return true; -} - -// Find the |menupopup| child in the |popup| representing this menu. It should be one -// of a very few children so we won't be iterating over a bazillion menu items to find -// it (so the strcmp won't kill us). -void nsMenuX::GetMenuPopupContent(nsIContent** aResult) -{ - if (!aResult) - return; - *aResult = nullptr; - - // Check to see if we are a "menupopup" node (if we are a native menu). - { - int32_t dummy; - nsCOMPtr tag = mContent->OwnerDoc()->BindingManager()->ResolveTag(mContent, &dummy); - if (tag == nsGkAtoms::menupopup) { - *aResult = mContent; - NS_ADDREF(*aResult); - return; - } - } - - // Otherwise check our child nodes. - - uint32_t count = mContent->GetChildCount(); - - for (uint32_t i = 0; i < count; i++) { - int32_t dummy; - nsIContent *child = mContent->GetChildAt(i); - nsCOMPtr tag = child->OwnerDoc()->BindingManager()->ResolveTag(child, &dummy); - if (tag == nsGkAtoms::menupopup) { - *aResult = child; - NS_ADDREF(*aResult); - return; - } - } -} - -NSMenuItem* nsMenuX::NativeMenuItem() -{ - return mNativeMenuItem; -} - -bool nsMenuX::IsXULHelpMenu(nsIContent* aMenuContent) -{ - bool retval = false; - if (aMenuContent) { - nsAutoString id; - aMenuContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, id); - if (id.Equals(NS_LITERAL_STRING("helpMenu"))) - retval = true; - } - return retval; -} - -// -// nsChangeObserver -// - -void nsMenuX::ObserveAttributeChanged(nsIDocument *aDocument, nsIContent *aContent, - nsIAtom *aAttribute) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // ignore the |open| attribute, which is by far the most common - if (gConstructingMenu || (aAttribute == nsGkAtoms::open)) - return; - - nsMenuObjectTypeX parentType = mParent->MenuObjectType(); - - if (aAttribute == nsGkAtoms::disabled) { - SetEnabled(!mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled, - nsGkAtoms::_true, eCaseMatters)); - } - else if (aAttribute == nsGkAtoms::label) { - mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::label, mLabel); - - // invalidate my parent. If we're a submenu parent, we have to rebuild - // the parent menu in order for the changes to be picked up. If we're - // a regular menu, just change the title and redraw the menubar. - if (parentType == eMenuBarObjectType) { - // reuse the existing menu, to avoid rebuilding the root menu bar. - NS_ASSERTION(mNativeMenu, "nsMenuX::AttributeChanged: invalid menu handle."); - NSString *newCocoaLabelString = nsMenuUtilsX::GetTruncatedCocoaLabel(mLabel); - [mNativeMenu setTitle:newCocoaLabelString]; - } - else if (parentType == eSubmenuObjectType) { - static_cast(mParent)->SetRebuild(true); - } - else if (parentType == eStandaloneNativeMenuObjectType) { - static_cast(mParent)->GetMenuXObject()->SetRebuild(true); - } - } - else if (aAttribute == nsGkAtoms::hidden || aAttribute == nsGkAtoms::collapsed) { - SetRebuild(true); - - bool contentIsHiddenOrCollapsed = nsMenuUtilsX::NodeIsHiddenOrCollapsed(mContent); - - // don't do anything if the state is correct already - if (contentIsHiddenOrCollapsed != mVisible) - return; - - if (contentIsHiddenOrCollapsed) { - if (parentType == eMenuBarObjectType || - parentType == eSubmenuObjectType || - parentType == eStandaloneNativeMenuObjectType) { - NSMenu* parentMenu = (NSMenu*)mParent->NativeData(); - // An exception will get thrown if we try to remove an item that isn't - // in the menu. - if ([parentMenu indexOfItem:mNativeMenuItem] != -1) - [parentMenu removeItem:mNativeMenuItem]; - mVisible = false; - } - } - else { - if (parentType == eMenuBarObjectType || - parentType == eSubmenuObjectType || - parentType == eStandaloneNativeMenuObjectType) { - int insertionIndex = nsMenuUtilsX::CalculateNativeInsertionPoint(mParent, this); - if (parentType == eMenuBarObjectType) { - // Before inserting we need to figure out if we should take the native - // application menu into account. - nsMenuBarX* mb = static_cast(mParent); - if (mb->MenuContainsAppMenu()) - insertionIndex++; - } - NSMenu* parentMenu = (NSMenu*)mParent->NativeData(); - [parentMenu insertItem:mNativeMenuItem atIndex:insertionIndex]; - [mNativeMenuItem setSubmenu:mNativeMenu]; - mVisible = true; - } - } - } - else if (aAttribute == nsGkAtoms::image) { - SetupIcon(); - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void nsMenuX::ObserveContentRemoved(nsIDocument *aDocument, nsIContent *aChild, - int32_t aIndexInContainer) -{ - if (gConstructingMenu) - return; - - SetRebuild(true); - mMenuGroupOwner->UnregisterForContentChanges(aChild); -} - -void nsMenuX::ObserveContentInserted(nsIDocument *aDocument, nsIContent* aContainer, - nsIContent *aChild) -{ - if (gConstructingMenu) - return; - - SetRebuild(true); -} - -nsresult nsMenuX::SetupIcon() -{ - // In addition to out-of-memory, menus that are children of the menu bar - // will not have mIcon set. - if (!mIcon) - return NS_ERROR_OUT_OF_MEMORY; - - return mIcon->SetupIcon(); -} - -// -// MenuDelegate Objective-C class, used to set up Carbon events -// - -@implementation MenuDelegate - -- (id)initWithGeckoMenu:(nsMenuX*)geckoMenu -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - if ((self = [super init])) { - NS_ASSERTION(geckoMenu, "Cannot initialize native menu delegate with NULL gecko menu! Will crash!"); - mGeckoMenu = geckoMenu; - } - return self; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (void)menu:(NSMenu *)menu willHighlightItem:(NSMenuItem *)item -{ - if (!menu || !item || !mGeckoMenu) - return; - - nsMenuObjectX* target = mGeckoMenu->GetVisibleItemAt((uint32_t)[menu indexOfItem:item]); - if (target && (target->MenuObjectType() == eMenuItemObjectType)) { - nsMenuItemX* targetMenuItem = static_cast(target); - bool handlerCalledPreventDefault; // but we don't actually care - targetMenuItem->DispatchDOMEvent(NS_LITERAL_STRING("DOMMenuItemActive"), &handlerCalledPreventDefault); - } -} - -- (void)menuWillOpen:(NSMenu *)menu -{ - if (!mGeckoMenu) - return; - - // Don't do anything while the OS is (re)indexing our menus (on Leopard and - // higher). This stops the Help menu from being able to search in our - // menus, but it also resolves many other problems. - if (nsMenuX::sIndexingMenuLevel > 0) - return; - - nsIRollupListener* rollupListener = nsBaseWidget::GetActiveRollupListener(); - if (rollupListener) { - nsCOMPtr rollupWidget = rollupListener->GetRollupWidget(); - if (rollupWidget) { - rollupListener->Rollup(0, true, nullptr, nullptr); - [menu cancelTracking]; - return; - } - } - mGeckoMenu->MenuOpened(); -} - -- (void)menuDidClose:(NSMenu *)menu -{ - if (!mGeckoMenu) - return; - - // Don't do anything while the OS is (re)indexing our menus (on Leopard and - // higher). This stops the Help menu from being able to search in our - // menus, but it also resolves many other problems. - if (nsMenuX::sIndexingMenuLevel > 0) - return; - - mGeckoMenu->MenuClosed(); -} - -@end - -// OS X Leopard (at least as of 10.5.2) has an obscure bug triggered by some -// behavior that's present in Mozilla.org browsers but not (as best I can -// tell) in Apple products like Safari. (It's not yet clear exactly what this -// behavior is.) -// -// The bug is that sometimes you crash on quit in nsMenuX::RemoveAll(), on a -// call to [NSMenu removeItemAtIndex:]. The crash is caused by trying to -// access a deleted NSMenuItem object (sometimes (perhaps always?) by trying -// to send it a _setChangedFlags: message). Though this object was deleted -// some time ago, it remains registered as a potential target for a particular -// key equivalent. So when [NSMenu removeItemAtIndex:] removes the current -// target for that same key equivalent, the OS tries to "activate" the -// previous target. -// -// The underlying reason appears to be that NSMenu's _addItem:toTable: and -// _removeItem:fromTable: methods (which are used to keep a hashtable of -// registered key equivalents) don't properly "retain" and "release" -// NSMenuItem objects as they are added to and removed from the hashtable. -// -// Our (hackish) workaround is to shadow the OS's hashtable with another -// hastable of our own (gShadowKeyEquivDB), and use it to "retain" and -// "release" NSMenuItem objects as needed. This resolves bmo bugs 422287 and -// 423669. When (if) Apple fixes this bug, we can remove this workaround. - -static NSMutableDictionary *gShadowKeyEquivDB = nil; - -// Class for values in gShadowKeyEquivDB. - -@interface KeyEquivDBItem : NSObject -{ - NSMenuItem *mItem; - NSMutableSet *mTables; -} - -- (id)initWithItem:(NSMenuItem *)aItem table:(NSMapTable *)aTable; -- (BOOL)hasTable:(NSMapTable *)aTable; -- (int)addTable:(NSMapTable *)aTable; -- (int)removeTable:(NSMapTable *)aTable; - -@end - -@implementation KeyEquivDBItem - -- (id)initWithItem:(NSMenuItem *)aItem table:(NSMapTable *)aTable -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - if (!gShadowKeyEquivDB) - gShadowKeyEquivDB = [[NSMutableDictionary alloc] init]; - self = [super init]; - if (aItem && aTable) { - mTables = [[NSMutableSet alloc] init]; - mItem = [aItem retain]; - [mTables addObject:[NSValue valueWithPointer:aTable]]; - } else { - mTables = nil; - mItem = nil; - } - return self; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (void)dealloc -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (mTables) - [mTables release]; - if (mItem) - [mItem release]; - [super dealloc]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (BOOL)hasTable:(NSMapTable *)aTable -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - return [mTables member:[NSValue valueWithPointer:aTable]] ? YES : NO; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO); -} - -// Does nothing if aTable (its index value) is already present in mTables. -- (int)addTable:(NSMapTable *)aTable -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - if (aTable) - [mTables addObject:[NSValue valueWithPointer:aTable]]; - return [mTables count]; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0); -} - -- (int)removeTable:(NSMapTable *)aTable -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - if (aTable) { - NSValue *objectToRemove = - [mTables member:[NSValue valueWithPointer:aTable]]; - if (objectToRemove) - [mTables removeObject:objectToRemove]; - } - return [mTables count]; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0); -} - -@end - -@interface NSMenu (MethodSwizzling) -+ (void)nsMenuX_NSMenu_addItem:(NSMenuItem *)aItem toTable:(NSMapTable *)aTable; -+ (void)nsMenuX_NSMenu_removeItem:(NSMenuItem *)aItem fromTable:(NSMapTable *)aTable; -@end - -@implementation NSMenu (MethodSwizzling) - -+ (void)nsMenuX_NSMenu_addItem:(NSMenuItem *)aItem toTable:(NSMapTable *)aTable -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (aItem && aTable) { - NSValue *key = [NSValue valueWithPointer:aItem]; - KeyEquivDBItem *shadowItem = [gShadowKeyEquivDB objectForKey:key]; - if (shadowItem) { - [shadowItem addTable:aTable]; - } else { - shadowItem = [[KeyEquivDBItem alloc] initWithItem:aItem table:aTable]; - [gShadowKeyEquivDB setObject:shadowItem forKey:key]; - // Release after [NSMutableDictionary setObject:forKey:] retains it (so - // that it will get dealloced when removeObjectForKey: is called). - [shadowItem release]; - } - } - - NS_OBJC_END_TRY_ABORT_BLOCK; - - [self nsMenuX_NSMenu_addItem:aItem toTable:aTable]; -} - -+ (void)nsMenuX_NSMenu_removeItem:(NSMenuItem *)aItem fromTable:(NSMapTable *)aTable -{ - [self nsMenuX_NSMenu_removeItem:aItem fromTable:aTable]; - - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (aItem && aTable) { - NSValue *key = [NSValue valueWithPointer:aItem]; - KeyEquivDBItem *shadowItem = [gShadowKeyEquivDB objectForKey:key]; - if (shadowItem && [shadowItem hasTable:aTable]) { - if (![shadowItem removeTable:aTable]) - [gShadowKeyEquivDB removeObjectForKey:key]; - } - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -@end - -// This class is needed to keep track of when the OS is (re)indexing all of -// our menus. This appears to only happen on Leopard and higher, and can -// be triggered by opening the Help menu. Some operations are unsafe while -// this is happening -- notably the calls to [[NSImage alloc] -// initWithSize:imageRect.size] and [newImage lockFocus] in nsMenuItemIconX:: -// OnStopFrame(). But we don't yet have a complete list, and Apple doesn't -// yet have any documentation on this subject. (Apple also doesn't yet have -// any documented way to find the information we seek here.) The "original" -// of this class (the one whose indexMenuBarDynamically method we hook) is -// defined in the Shortcut framework in /System/Library/PrivateFrameworks. -@interface NSObject (SCTGRLIndexMethodSwizzling) -- (void)nsMenuX_SCTGRLIndex_indexMenuBarDynamically; -@end - -@implementation NSObject (SCTGRLIndexMethodSwizzling) - -- (void)nsMenuX_SCTGRLIndex_indexMenuBarDynamically -{ - // This method appears to be called (once) whenever the OS (re)indexes our - // menus. sIndexingMenuLevel is a int32_t just in case it might be - // reentered. As it's running, it spawns calls to two undocumented - // HIToolbox methods (_SimulateMenuOpening() and _SimulateMenuClosed()), - // which "simulate" the opening and closing of our menus without actually - // displaying them. - ++nsMenuX::sIndexingMenuLevel; - [self nsMenuX_SCTGRLIndex_indexMenuBarDynamically]; - --nsMenuX::sIndexingMenuLevel; -} - -@end diff --git a/widget/cocoa/nsNativeThemeCocoa.h b/widget/cocoa/nsNativeThemeCocoa.h deleted file mode 100644 index 23f2bc4d32..0000000000 --- a/widget/cocoa/nsNativeThemeCocoa.h +++ /dev/null @@ -1,178 +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 nsNativeThemeCocoa_h_ -#define nsNativeThemeCocoa_h_ - -#import -#import - -#include "nsITheme.h" -#include "nsCOMPtr.h" -#include "nsIAtom.h" -#include "nsNativeTheme.h" - -@class CellDrawView; -@class NSProgressBarCell; -@class ContextAwareSearchFieldCell; -class nsDeviceContext; -struct SegmentedControlRenderSettings; - -namespace mozilla { -class EventStates; -} // namespace mozilla - -class nsNativeThemeCocoa : private nsNativeTheme, - public nsITheme -{ -public: - enum { - eThemeGeometryTypeTitlebar = eThemeGeometryTypeUnknown + 1, - eThemeGeometryTypeToolbar, - eThemeGeometryTypeToolbox, - eThemeGeometryTypeWindowButtons, - eThemeGeometryTypeFullscreenButton, - eThemeGeometryTypeMenu, - eThemeGeometryTypeHighlightedMenuItem, - eThemeGeometryTypeVibrancyLight, - eThemeGeometryTypeVibrancyDark, - eThemeGeometryTypeTooltip, - eThemeGeometryTypeSheet, - eThemeGeometryTypeSourceList, - eThemeGeometryTypeSourceListSelection, - eThemeGeometryTypeActiveSourceListSelection - }; - - nsNativeThemeCocoa(); - - NS_DECL_ISUPPORTS_INHERITED - - // The nsITheme interface. - NS_IMETHOD DrawWidgetBackground(nsRenderingContext* aContext, - nsIFrame* aFrame, - uint8_t aWidgetType, - const nsRect& aRect, - const nsRect& aDirtyRect) override; - NS_IMETHOD GetWidgetBorder(nsDeviceContext* aContext, - nsIFrame* aFrame, - uint8_t aWidgetType, - nsIntMargin* aResult) override; - - virtual bool GetWidgetPadding(nsDeviceContext* aContext, - nsIFrame* aFrame, - uint8_t aWidgetType, - nsIntMargin* aResult) override; - - virtual bool GetWidgetOverflow(nsDeviceContext* aContext, nsIFrame* aFrame, - uint8_t aWidgetType, nsRect* aOverflowRect) override; - - NS_IMETHOD GetMinimumWidgetSize(nsPresContext* aPresContext, nsIFrame* aFrame, - uint8_t aWidgetType, - mozilla::LayoutDeviceIntSize* aResult, bool* aIsOverridable) override; - NS_IMETHOD WidgetStateChanged(nsIFrame* aFrame, uint8_t aWidgetType, - nsIAtom* aAttribute, bool* aShouldRepaint, - const nsAttrValue* aOldValue) override; - NS_IMETHOD ThemeChanged() override; - bool ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* aFrame, uint8_t aWidgetType) override; - bool WidgetIsContainer(uint8_t aWidgetType) override; - bool ThemeDrawsFocusForWidget(uint8_t aWidgetType) override; - bool ThemeNeedsComboboxDropmarker() override; - virtual bool WidgetAppearanceDependsOnWindowFocus(uint8_t aWidgetType) override; - virtual bool NeedToClearBackgroundBehindWidget(nsIFrame* aFrame, - uint8_t aWidgetType) override; - virtual bool WidgetProvidesFontSmoothingBackgroundColor(nsIFrame* aFrame, uint8_t aWidgetType, - nscolor* aColor) override; - virtual ThemeGeometryType ThemeGeometryTypeForWidget(nsIFrame* aFrame, - uint8_t aWidgetType) override; - virtual Transparency GetWidgetTransparency(nsIFrame* aFrame, uint8_t aWidgetType) override; - - void DrawProgress(CGContextRef context, const HIRect& inBoxRect, - bool inIsIndeterminate, bool inIsHorizontal, - double inValue, double inMaxValue, nsIFrame* aFrame); - - static void DrawNativeTitlebar(CGContextRef aContext, CGRect aTitlebarRect, - CGFloat aUnifiedHeight, BOOL aIsMain, BOOL aIsFlipped); - -protected: - virtual ~nsNativeThemeCocoa(); - - nsIntMargin DirectionAwareMargin(const nsIntMargin& aMargin, nsIFrame* aFrame); - nsIFrame* SeparatorResponsibility(nsIFrame* aBefore, nsIFrame* aAfter); - CGRect SeparatorAdjustedRect(CGRect aRect, nsIFrame* aLeft, - nsIFrame* aCurrent, nsIFrame* aRight); - bool IsWindowSheet(nsIFrame* aFrame); - - // HITheme drawing routines - void DrawFrame(CGContextRef context, HIThemeFrameKind inKind, - const HIRect& inBoxRect, bool inReadOnly, - mozilla::EventStates inState); - void DrawMeter(CGContextRef context, const HIRect& inBoxRect, - nsIFrame* aFrame); - void DrawSegment(CGContextRef cgContext, const HIRect& inBoxRect, - mozilla::EventStates inState, nsIFrame* aFrame, - const SegmentedControlRenderSettings& aSettings); - void DrawTabPanel(CGContextRef context, const HIRect& inBoxRect, nsIFrame* aFrame); - void DrawScale(CGContextRef context, const HIRect& inBoxRect, - mozilla::EventStates inState, bool inDirection, - bool inIsReverse, int32_t inCurrentValue, int32_t inMinValue, - int32_t inMaxValue, nsIFrame* aFrame); - void DrawCheckboxOrRadio(CGContextRef cgContext, bool inCheckbox, - const HIRect& inBoxRect, bool inSelected, - mozilla::EventStates inState, nsIFrame* aFrame); - void DrawSearchField(CGContextRef cgContext, const HIRect& inBoxRect, - nsIFrame* aFrame, mozilla::EventStates inState); - void DrawPushButton(CGContextRef cgContext, const HIRect& inBoxRect, - mozilla::EventStates inState, uint8_t aWidgetType, - nsIFrame* aFrame, float aOriginalHeight); - void DrawMenuIcon(CGContextRef cgContext, const CGRect& aRect, - mozilla::EventStates inState, nsIFrame* aFrame, - const NSSize& aIconSize, NSString* aImageName, - bool aCenterHorizontally); - void DrawButton(CGContextRef context, ThemeButtonKind inKind, - const HIRect& inBoxRect, bool inIsDefault, - ThemeButtonValue inValue, ThemeButtonAdornment inAdornment, - mozilla::EventStates inState, nsIFrame* aFrame); - void DrawFocusOutline(CGContextRef cgContext, const HIRect& inBoxRect, - mozilla::EventStates inState, uint8_t aWidgetType, - nsIFrame* aFrame); - void DrawDropdown(CGContextRef context, const HIRect& inBoxRect, - mozilla::EventStates inState, uint8_t aWidgetType, - nsIFrame* aFrame); - void DrawSpinButtons(CGContextRef context, ThemeButtonKind inKind, - const HIRect& inBoxRect, ThemeDrawState inDrawState, - ThemeButtonAdornment inAdornment, - mozilla::EventStates inState, nsIFrame* aFrame); - void DrawSpinButton(CGContextRef context, ThemeButtonKind inKind, - const HIRect& inBoxRect, ThemeDrawState inDrawState, - ThemeButtonAdornment inAdornment, - mozilla::EventStates inState, - nsIFrame* aFrame, uint8_t aWidgetType); - void DrawUnifiedToolbar(CGContextRef cgContext, const HIRect& inBoxRect, - NSWindow* aWindow); - void DrawStatusBar(CGContextRef cgContext, const HIRect& inBoxRect, - nsIFrame *aFrame); - void DrawResizer(CGContextRef cgContext, const HIRect& aRect, nsIFrame *aFrame); - - // Scrollbars - void GetScrollbarPressStates(nsIFrame *aFrame, - mozilla::EventStates aButtonStates[]); - nsIFrame* GetParentScrollbarFrame(nsIFrame *aFrame); - bool IsParentScrollbarRolledOver(nsIFrame* aFrame); - -private: - NSButtonCell* mDisclosureButtonCell; - NSButtonCell* mHelpButtonCell; - NSButtonCell* mPushButtonCell; - NSButtonCell* mRadioButtonCell; - NSButtonCell* mCheckboxCell; - ContextAwareSearchFieldCell* mSearchFieldCell; - NSPopUpButtonCell* mDropdownCell; - NSComboBoxCell* mComboBoxCell; - NSProgressBarCell* mProgressBarCell; - NSLevelIndicatorCell* mMeterBarCell; - CellDrawView* mCellDrawView; -}; - -#endif // nsNativeThemeCocoa_h_ diff --git a/widget/cocoa/nsNativeThemeCocoa.mm b/widget/cocoa/nsNativeThemeCocoa.mm deleted file mode 100644 index 056c453f2a..0000000000 --- a/widget/cocoa/nsNativeThemeCocoa.mm +++ /dev/null @@ -1,3961 +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 "nsNativeThemeCocoa.h" - -#include "mozilla/gfx/2D.h" -#include "mozilla/gfx/Helpers.h" -#include "nsChildView.h" -#include "nsDeviceContext.h" -#include "nsLayoutUtils.h" -#include "nsObjCExceptions.h" -#include "nsNumberControlFrame.h" -#include "nsRangeFrame.h" -#include "nsRenderingContext.h" -#include "nsRect.h" -#include "nsSize.h" -#include "nsThemeConstants.h" -#include "nsIPresShell.h" -#include "nsPresContext.h" -#include "nsIContent.h" -#include "nsIDocument.h" -#include "nsIFrame.h" -#include "nsIAtom.h" -#include "nsNameSpaceManager.h" -#include "nsPresContext.h" -#include "nsGkAtoms.h" -#include "nsCocoaFeatures.h" -#include "nsCocoaWindow.h" -#include "nsNativeThemeColors.h" -#include "nsIScrollableFrame.h" -#include "mozilla/EventStates.h" -#include "mozilla/dom/Element.h" -#include "mozilla/dom/HTMLMeterElement.h" -#include "nsLookAndFeel.h" -#include "VibrancyManager.h" - -#include "gfxContext.h" -#include "gfxQuartzSurface.h" -#include "gfxQuartzNativeDrawing.h" -#include - -using namespace mozilla; -using namespace mozilla::gfx; -using mozilla::dom::HTMLMeterElement; - -#define DRAW_IN_FRAME_DEBUG 0 -#define SCROLLBARS_VISUAL_DEBUG 0 - -// private Quartz routines needed here -extern "C" { - CG_EXTERN void CGContextSetCTM(CGContextRef, CGAffineTransform); - CG_EXTERN void CGContextSetBaseCTM(CGContextRef, CGAffineTransform); - typedef CFTypeRef CUIRendererRef; - void CUIDraw(CUIRendererRef r, CGRect rect, CGContextRef ctx, CFDictionaryRef options, CFDictionaryRef* result); -} - -// Workaround for NSCell control tint drawing -// Without this workaround, NSCells are always drawn with the clear control tint -// as long as they're not attached to an NSControl which is a subview of an active window. -// XXXmstange Why doesn't Webkit need this? -@implementation NSCell (ControlTintWorkaround) -- (int)_realControlTint { return [self controlTint]; } -@end - -// The purpose of this class is to provide objects that can be used when drawing -// NSCells using drawWithFrame:inView: without causing any harm. The only -// messages that will be sent to such an object are "isFlipped" and -// "currentEditor": isFlipped needs to return YES in order to avoid drawing bugs -// on 10.4 (see bug 465069); currentEditor (which isn't even a method of -// NSView) will be called when drawing search fields, and we only provide it in -// order to prevent "unrecognized selector" exceptions. -// There's no need to pass the actual NSView that we're drawing into to -// drawWithFrame:inView:. What's more, doing so even causes unnecessary -// invalidations as soon as we draw a focusring! -@interface CellDrawView : NSView - -@end; - -@implementation CellDrawView - -- (BOOL)isFlipped -{ - return YES; -} - -- (NSText*)currentEditor -{ - return nil; -} - -@end - -// These two classes don't actually add any behavior over NSButtonCell. Their -// purpose is to make it easy to distinguish NSCell objects that are used for -// drawing radio buttons / checkboxes from other cell types. -// The class names are made up, there are no classes with these names in AppKit. -// The reason we need them is that calling [cell setButtonType:NSRadioButton] -// doesn't leave an easy-to-check "marker" on the cell object - there is no -// -[NSButtonCell buttonType] method. -@interface RadioButtonCell : NSButtonCell -@end; -@implementation RadioButtonCell @end; -@interface CheckboxCell : NSButtonCell -@end; -@implementation CheckboxCell @end; - -static void -DrawFocusRingForCellIfNeeded(NSCell* aCell, NSRect aWithFrame, NSView* aInView) -{ - if ([aCell showsFirstResponder]) { - CGContextRef cgContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; - CGContextSaveGState(cgContext); - - // It's important to set the focus ring style before we enter the - // transparency layer so that the transparency layer only contains - // the normal button mask without the focus ring, and the conversion - // to the focus ring shape happens only when the transparency layer is - // ended. - NSSetFocusRingStyle(NSFocusRingOnly); - - // We need to draw the whole button into a transparency layer because - // many button types are composed of multiple parts, and if these parts - // were drawn while the focus ring style was active, each individual part - // would produce a focus ring for itself. But we only want one focus ring - // for the whole button. The transparency layer is a way to merge the - // individual button parts together before the focus ring shape is - // calculated. - CGContextBeginTransparencyLayerWithRect(cgContext, NSRectToCGRect(aWithFrame), 0); - [aCell drawFocusRingMaskWithFrame:aWithFrame inView:aInView]; - CGContextEndTransparencyLayer(cgContext); - - CGContextRestoreGState(cgContext); - } -} - -static bool -FocusIsDrawnByDrawWithFrame(NSCell* aCell) -{ -#if defined(MAC_OS_X_VERSION_10_8) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8 - // When building with the 10.8 SDK or higher, focus rings don't draw as part - // of -[NSCell drawWithFrame:inView:] and must be drawn by a separate call - // to -[NSCell drawFocusRingMaskWithFrame:inView:]; . - // See the NSButtonCell section under - // https://developer.apple.com/library/mac/releasenotes/AppKit/RN-AppKitOlderNotes/#X10_8Notes - return false; -#else - if (!nsCocoaFeatures::OnYosemiteOrLater()) { - // When building with the 10.7 SDK or lower, focus rings always draw as - // part of -[NSCell drawWithFrame:inView:] if the build is run on 10.9 or - // lower. - return true; - } - - // On 10.10, whether the focus ring is drawn as part of - // -[NSCell drawWithFrame:inView:] depends on the cell type. - // Radio buttons and checkboxes draw their own focus rings, other cell - // types need -[NSCell drawFocusRingMaskWithFrame:inView:]. - return [aCell isKindOfClass:[RadioButtonCell class]] || - [aCell isKindOfClass:[CheckboxCell class]]; -#endif -} - -static void -DrawCellIncludingFocusRing(NSCell* aCell, NSRect aWithFrame, NSView* aInView) -{ - [aCell drawWithFrame:aWithFrame inView:aInView]; - - if (!FocusIsDrawnByDrawWithFrame(aCell)) { - DrawFocusRingForCellIfNeeded(aCell, aWithFrame, aInView); - } -} - -/** - * NSProgressBarCell is used to draw progress bars of any size. - */ -@interface NSProgressBarCell : NSCell -{ - /*All instance variables are private*/ - double mValue; - double mMax; - bool mIsIndeterminate; - bool mIsHorizontal; -} - -- (void)setValue:(double)value; -- (double)value; -- (void)setMax:(double)max; -- (double)max; -- (void)setIndeterminate:(bool)aIndeterminate; -- (bool)isIndeterminate; -- (void)setHorizontal:(bool)aIsHorizontal; -- (bool)isHorizontal; -- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView; -@end - -@implementation NSProgressBarCell - -- (void)setMax:(double)aMax -{ - mMax = aMax; -} - -- (double)max -{ - return mMax; -} - -- (void)setValue:(double)aValue -{ - mValue = aValue; -} - -- (double)value -{ - return mValue; -} - -- (void)setIndeterminate:(bool)aIndeterminate -{ - mIsIndeterminate = aIndeterminate; -} - -- (bool)isIndeterminate -{ - return mIsIndeterminate; -} - -- (void)setHorizontal:(bool)aIsHorizontal -{ - mIsHorizontal = aIsHorizontal; -} - -- (bool)isHorizontal -{ - return mIsHorizontal; -} - -- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView -{ - CGContext* cgContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; - - HIThemeTrackDrawInfo tdi; - - tdi.version = 0; - tdi.min = 0; - - tdi.value = INT32_MAX * (mValue / mMax); - tdi.max = INT32_MAX; - tdi.bounds = NSRectToCGRect(cellFrame); - tdi.attributes = mIsHorizontal ? kThemeTrackHorizontal : 0; - tdi.enableState = [self controlTint] == NSClearControlTint ? kThemeTrackInactive - : kThemeTrackActive; - - NSControlSize size = [self controlSize]; - if (size == NSRegularControlSize) { - tdi.kind = mIsIndeterminate ? kThemeLargeIndeterminateBar - : kThemeLargeProgressBar; - } else { - NS_ASSERTION(size == NSSmallControlSize, - "We shouldn't have another size than small and regular for the moment"); - tdi.kind = mIsIndeterminate ? kThemeMediumIndeterminateBar - : kThemeMediumProgressBar; - } - - int32_t stepsPerSecond = mIsIndeterminate ? 60 : 30; - int32_t milliSecondsPerStep = 1000 / stepsPerSecond; - tdi.trackInfo.progress.phase = uint8_t(PR_IntervalToMilliseconds(PR_IntervalNow()) / - milliSecondsPerStep); - - HIThemeDrawTrack(&tdi, NULL, cgContext, kHIThemeOrientationNormal); -} - -@end - -@interface ContextAwareSearchFieldCell : NSSearchFieldCell -{ - nsIFrame* mContext; -} - -// setContext: stores the searchfield nsIFrame so that it can be consulted -// during painting. Please reset this by calling setContext:nullptr as soon as -// you're done with painting because we don't want to keep a dangling pointer. -- (void)setContext:(nsIFrame*)aContext; -@end - -@implementation ContextAwareSearchFieldCell - -- (id)initTextCell:(NSString*)aString -{ - if ((self = [super initTextCell:aString])) { - mContext = nullptr; - } - return self; -} - -- (void)setContext:(nsIFrame*)aContext -{ - mContext = aContext; -} - -static BOOL IsToolbarStyleContainer(nsIFrame* aFrame) -{ - nsIContent* content = aFrame->GetContent(); - if (!content) - return NO; - - if (content->IsAnyOfXULElements(nsGkAtoms::toolbar, - nsGkAtoms::toolbox, - nsGkAtoms::statusbar)) - return YES; - - switch (aFrame->StyleDisplay()->mAppearance) { - case NS_THEME_TOOLBAR: - case NS_THEME_STATUSBAR: - return YES; - default: - return NO; - } -} - -- (BOOL)_isToolbarMode -{ - // On 10.7, searchfields have two different styles, depending on whether - // the searchfield is on top of of window chrome. This function is called on - // 10.7 during drawing in order to determine which style to use. - for (nsIFrame* frame = mContext; frame; frame = frame->GetParent()) { - if (IsToolbarStyleContainer(frame)) { - return YES; - } - } - return NO; -} - -@end - -// Workaround for Bug 542048 -// On 64-bit, NSSearchFieldCells don't draw focus rings. -#if defined(__x86_64__) - -@interface SearchFieldCellWithFocusRing : ContextAwareSearchFieldCell {} @end - -@implementation SearchFieldCellWithFocusRing - -- (void)drawWithFrame:(NSRect)rect inView:(NSView*)controlView -{ - [super drawWithFrame:rect inView:controlView]; - - if (FocusIsDrawnByDrawWithFrame(self)) { - // For some reason, -[NSSearchFieldCell drawWithFrame:inView] doesn't draw a - // focus ring in 64 bit mode, no matter what SDK is used or what OS X version - // we're running on. But if FocusIsDrawnByDrawWithFrame(self), then our - // caller expects us to draw a focus ring. So we just do that here. - DrawFocusRingForCellIfNeeded(self, rect, controlView); - } -} - -- (void)drawFocusRingMaskWithFrame:(NSRect)rect inView:(NSView*)controlView -{ - // By default this draws nothing. I don't know why. - // We just draw the search field again. It's a great mask shape for its own - // focus ring. - [super drawWithFrame:rect inView:controlView]; -} - -@end - -#endif - -#define HITHEME_ORIENTATION kHIThemeOrientationNormal - -static CGFloat kMaxFocusRingWidth = 0; // initialized by the nsNativeThemeCocoa constructor - -// These enums are for indexing into the margin array. -enum { - leopardOSorlater = 0, // 10.6 - 10.9 - yosemiteOSorlater = 1 // 10.10+ -}; - -enum { - miniControlSize, - smallControlSize, - regularControlSize -}; - -enum { - leftMargin, - topMargin, - rightMargin, - bottomMargin -}; - -static size_t EnumSizeForCocoaSize(NSControlSize cocoaControlSize) { - if (cocoaControlSize == NSMiniControlSize) - return miniControlSize; - else if (cocoaControlSize == NSSmallControlSize) - return smallControlSize; - else - return regularControlSize; -} - -static NSControlSize CocoaSizeForEnum(int32_t enumControlSize) { - if (enumControlSize == miniControlSize) - return NSMiniControlSize; - else if (enumControlSize == smallControlSize) - return NSSmallControlSize; - else - return NSRegularControlSize; -} - -static NSString* CUIControlSizeForCocoaSize(NSControlSize aControlSize) -{ - if (aControlSize == NSRegularControlSize) - return @"regular"; - else if (aControlSize == NSSmallControlSize) - return @"small"; - else - return @"mini"; -} - -static void InflateControlRect(NSRect* rect, NSControlSize cocoaControlSize, const float marginSet[][3][4]) -{ - if (!marginSet) - return; - - static int osIndex = nsCocoaFeatures::OnYosemiteOrLater() ? - yosemiteOSorlater : leopardOSorlater; - size_t controlSize = EnumSizeForCocoaSize(cocoaControlSize); - const float* buttonMargins = marginSet[osIndex][controlSize]; - rect->origin.x -= buttonMargins[leftMargin]; - rect->origin.y -= buttonMargins[bottomMargin]; - rect->size.width += buttonMargins[leftMargin] + buttonMargins[rightMargin]; - rect->size.height += buttonMargins[bottomMargin] + buttonMargins[topMargin]; -} - -static ChildView* ChildViewForFrame(nsIFrame* aFrame) -{ - if (!aFrame) - return nil; - - nsIWidget* widget = aFrame->GetNearestWidget(); - if (!widget) - return nil; - - NSWindow* window = (NSWindow*)widget->GetNativeData(NS_NATIVE_WINDOW); - return [window isKindOfClass:[BaseWindow class]] ? [(BaseWindow*)window mainChildView] : nil; -} - -static NSWindow* NativeWindowForFrame(nsIFrame* aFrame, - nsIWidget** aTopLevelWidget = NULL) -{ - if (!aFrame) - return nil; - - nsIWidget* widget = aFrame->GetNearestWidget(); - if (!widget) - return nil; - - nsIWidget* topLevelWidget = widget->GetTopLevelWidget(); - if (aTopLevelWidget) - *aTopLevelWidget = topLevelWidget; - - return (NSWindow*)topLevelWidget->GetNativeData(NS_NATIVE_WINDOW); -} - -static NSSize -WindowButtonsSize(nsIFrame* aFrame) -{ - NSWindow* window = NativeWindowForFrame(aFrame); - if (!window) { - // Return fallback values. - return NSMakeSize(54, 16); - } - - NSRect buttonBox = NSZeroRect; - NSButton* closeButton = [window standardWindowButton:NSWindowCloseButton]; - if (closeButton) { - buttonBox = NSUnionRect(buttonBox, [closeButton frame]); - } - NSButton* minimizeButton = [window standardWindowButton:NSWindowMiniaturizeButton]; - if (minimizeButton) { - buttonBox = NSUnionRect(buttonBox, [minimizeButton frame]); - } - NSButton* zoomButton = [window standardWindowButton:NSWindowZoomButton]; - if (zoomButton) { - buttonBox = NSUnionRect(buttonBox, [zoomButton frame]); - } - return buttonBox.size; -} - -static BOOL FrameIsInActiveWindow(nsIFrame* aFrame) -{ - nsIWidget* topLevelWidget = NULL; - NSWindow* win = NativeWindowForFrame(aFrame, &topLevelWidget); - if (!topLevelWidget || !win) - return YES; - - // XUL popups, e.g. the toolbar customization popup, can't become key windows, - // but controls in these windows should still get the active look. - if (topLevelWidget->WindowType() == eWindowType_popup) - return YES; - if ([win isSheet]) - return [win isKeyWindow]; - return [win isMainWindow] && ![win attachedSheet]; -} - -// Toolbar controls and content controls respond to different window -// activeness states. -static BOOL IsActive(nsIFrame* aFrame, BOOL aIsToolbarControl) -{ - if (aIsToolbarControl) - return [NativeWindowForFrame(aFrame) isMainWindow]; - return FrameIsInActiveWindow(aFrame); -} - -static bool IsInSourceList(nsIFrame* aFrame) { - for (nsIFrame* frame = aFrame->GetParent(); frame; frame = frame->GetParent()) { - if (frame->StyleDisplay()->mAppearance == NS_THEME_MAC_SOURCE_LIST) { - return true; - } - } - return false; -} - -NS_IMPL_ISUPPORTS_INHERITED(nsNativeThemeCocoa, nsNativeTheme, nsITheme) - -nsNativeThemeCocoa::nsNativeThemeCocoa() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - kMaxFocusRingWidth = nsCocoaFeatures::OnYosemiteOrLater() ? 7 : 4; - - // provide a local autorelease pool, as this is called during startup - // before the main event-loop pool is in place - nsAutoreleasePool pool; - - mDisclosureButtonCell = [[NSButtonCell alloc] initTextCell:@""]; - [mDisclosureButtonCell setBezelStyle:NSRoundedDisclosureBezelStyle]; - [mDisclosureButtonCell setButtonType:NSPushOnPushOffButton]; - [mDisclosureButtonCell setHighlightsBy:NSPushInCellMask]; - - mHelpButtonCell = [[NSButtonCell alloc] initTextCell:@""]; - [mHelpButtonCell setBezelStyle:NSHelpButtonBezelStyle]; - [mHelpButtonCell setButtonType:NSMomentaryPushInButton]; - [mHelpButtonCell setHighlightsBy:NSPushInCellMask]; - - mPushButtonCell = [[NSButtonCell alloc] initTextCell:@""]; - [mPushButtonCell setButtonType:NSMomentaryPushInButton]; - [mPushButtonCell setHighlightsBy:NSPushInCellMask]; - - mRadioButtonCell = [[RadioButtonCell alloc] initTextCell:@""]; - [mRadioButtonCell setButtonType:NSRadioButton]; - - mCheckboxCell = [[CheckboxCell alloc] initTextCell:@""]; - [mCheckboxCell setButtonType:NSSwitchButton]; - [mCheckboxCell setAllowsMixedState:YES]; - -#if defined(__x86_64__) - mSearchFieldCell = [[SearchFieldCellWithFocusRing alloc] initTextCell:@""]; -#else - mSearchFieldCell = [[ContextAwareSearchFieldCell alloc] initTextCell:@""]; -#endif - [mSearchFieldCell setBezelStyle:NSTextFieldRoundedBezel]; - [mSearchFieldCell setBezeled:YES]; - [mSearchFieldCell setEditable:YES]; - [mSearchFieldCell setFocusRingType:NSFocusRingTypeExterior]; - - mDropdownCell = [[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]; - - mComboBoxCell = [[NSComboBoxCell alloc] initTextCell:@""]; - [mComboBoxCell setBezeled:YES]; - [mComboBoxCell setEditable:YES]; - [mComboBoxCell setFocusRingType:NSFocusRingTypeExterior]; - - mProgressBarCell = [[NSProgressBarCell alloc] init]; - - mMeterBarCell = [[NSLevelIndicatorCell alloc] - initWithLevelIndicatorStyle:NSContinuousCapacityLevelIndicatorStyle]; - - mCellDrawView = [[CellDrawView alloc] init]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsNativeThemeCocoa::~nsNativeThemeCocoa() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mMeterBarCell release]; - [mProgressBarCell release]; - [mDisclosureButtonCell release]; - [mHelpButtonCell release]; - [mPushButtonCell release]; - [mRadioButtonCell release]; - [mCheckboxCell release]; - [mSearchFieldCell release]; - [mDropdownCell release]; - [mComboBoxCell release]; - [mCellDrawView release]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// Limit on the area of the target rect (in pixels^2) in -// DrawCellWithScaling() and DrawButton() and above which we -// don't draw the object into a bitmap buffer. This is to avoid crashes in -// [NSGraphicsContext graphicsContextWithGraphicsPort:flipped:] and -// CGContextDrawImage(), and also to avoid very poor drawing performance in -// CGContextDrawImage() when it scales the bitmap (particularly if xscale or -// yscale is less than but near 1 -- e.g. 0.9). This value was determined -// by trial and error, on OS X 10.4.11 and 10.5.4, and on systems with -// different amounts of RAM. -#define BITMAP_MAX_AREA 500000 - -static int -GetBackingScaleFactorForRendering(CGContextRef cgContext) -{ - CGAffineTransform ctm = CGContextGetUserSpaceToDeviceSpaceTransform(cgContext); - CGRect transformedUserSpacePixel = CGRectApplyAffineTransform(CGRectMake(0, 0, 1, 1), ctm); - float maxScale = std::max(fabs(transformedUserSpacePixel.size.width), - fabs(transformedUserSpacePixel.size.height)); - return maxScale > 1.0 ? 2 : 1; -} - -/* - * Draw the given NSCell into the given cgContext. - * - * destRect - the size and position of the resulting control rectangle - * controlSize - the NSControlSize which will be given to the NSCell before - * asking it to render - * naturalSize - The natural dimensions of this control. - * If the control rect size is not equal to either of these, a scale - * will be applied to the context so that rendering the control at the - * natural size will result in it filling the destRect space. - * If a control has no natural dimensions in either/both axes, pass 0.0f. - * minimumSize - The minimum dimensions of this control. - * If the control rect size is less than the minimum for a given axis, - * a scale will be applied to the context so that the minimum is used - * for drawing. If a control has no minimum dimensions in either/both - * axes, pass 0.0f. - * marginSet - an array of margins; a multidimensional array of [2][3][4], - * with the first dimension being the OS version (Tiger or Leopard), - * the second being the control size (mini, small, regular), and the third - * being the 4 margin values (left, top, right, bottom). - * view - The NSView that we're drawing into. As far as I can tell, it doesn't - * matter if this is really the right view; it just has to return YES when - * asked for isFlipped. Otherwise we'll get drawing bugs on 10.4. - * mirrorHorizontal - whether to mirror the cell horizontally - */ -static void DrawCellWithScaling(NSCell *cell, - CGContextRef cgContext, - const HIRect& destRect, - NSControlSize controlSize, - NSSize naturalSize, - NSSize minimumSize, - const float marginSet[][3][4], - NSView* view, - BOOL mirrorHorizontal) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - NSRect drawRect = NSMakeRect(destRect.origin.x, destRect.origin.y, destRect.size.width, destRect.size.height); - - if (naturalSize.width != 0.0f) - drawRect.size.width = naturalSize.width; - if (naturalSize.height != 0.0f) - drawRect.size.height = naturalSize.height; - - // Keep aspect ratio when scaling if one dimension is free. - if (naturalSize.width == 0.0f && naturalSize.height != 0.0f) - drawRect.size.width = destRect.size.width * naturalSize.height / destRect.size.height; - if (naturalSize.height == 0.0f && naturalSize.width != 0.0f) - drawRect.size.height = destRect.size.height * naturalSize.width / destRect.size.width; - - // Honor minimum sizes. - if (drawRect.size.width < minimumSize.width) - drawRect.size.width = minimumSize.width; - if (drawRect.size.height < minimumSize.height) - drawRect.size.height = minimumSize.height; - - [NSGraphicsContext saveGraphicsState]; - - // Only skip the buffer if the area of our cell (in pixels^2) is too large. - if (drawRect.size.width * drawRect.size.height > BITMAP_MAX_AREA) { - // Inflate the rect Gecko gave us by the margin for the control. - InflateControlRect(&drawRect, controlSize, marginSet); - - NSGraphicsContext* savedContext = [NSGraphicsContext currentContext]; - [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:cgContext flipped:YES]]; - - DrawCellIncludingFocusRing(cell, drawRect, view); - - [NSGraphicsContext setCurrentContext:savedContext]; - } - else { - float w = ceil(drawRect.size.width); - float h = ceil(drawRect.size.height); - NSRect tmpRect = NSMakeRect(kMaxFocusRingWidth, kMaxFocusRingWidth, w, h); - - // inflate to figure out the frame we need to tell NSCell to draw in, to get something that's 0,0,w,h - InflateControlRect(&tmpRect, controlSize, marginSet); - - // and then, expand by kMaxFocusRingWidth size to make sure we can capture any focus ring - w += kMaxFocusRingWidth * 2.0; - h += kMaxFocusRingWidth * 2.0; - - int backingScaleFactor = GetBackingScaleFactorForRendering(cgContext); - CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB(); - CGContextRef ctx = CGBitmapContextCreate(NULL, - (int) w * backingScaleFactor, (int) h * backingScaleFactor, - 8, (int) w * backingScaleFactor * 4, - rgb, kCGImageAlphaPremultipliedFirst); - CGColorSpaceRelease(rgb); - - // We need to flip the image twice in order to avoid drawing bugs on 10.4, see bug 465069. - // This is the first flip transform, applied to cgContext. - CGContextScaleCTM(cgContext, 1.0f, -1.0f); - CGContextTranslateCTM(cgContext, 0.0f, -(2.0 * destRect.origin.y + destRect.size.height)); - if (mirrorHorizontal) { - CGContextScaleCTM(cgContext, -1.0f, 1.0f); - CGContextTranslateCTM(cgContext, -(2.0 * destRect.origin.x + destRect.size.width), 0.0f); - } - - NSGraphicsContext* savedContext = [NSGraphicsContext currentContext]; - [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:ctx flipped:YES]]; - - CGContextScaleCTM(ctx, backingScaleFactor, backingScaleFactor); - - // Set the context's "base transform" to in order to get correctly-sized focus rings. - CGContextSetBaseCTM(ctx, CGAffineTransformMakeScale(backingScaleFactor, backingScaleFactor)); - - // This is the second flip transform, applied to ctx. - CGContextScaleCTM(ctx, 1.0f, -1.0f); - CGContextTranslateCTM(ctx, 0.0f, -(2.0 * tmpRect.origin.y + tmpRect.size.height)); - - DrawCellIncludingFocusRing(cell, tmpRect, view); - - [NSGraphicsContext setCurrentContext:savedContext]; - - CGImageRef img = CGBitmapContextCreateImage(ctx); - - // Drop the image into the original destination rectangle, scaling to fit - // Only scale kMaxFocusRingWidth by xscale/yscale when the resulting rect - // doesn't extend beyond the overflow rect - float xscale = destRect.size.width / drawRect.size.width; - float yscale = destRect.size.height / drawRect.size.height; - float scaledFocusRingX = xscale < 1.0f ? kMaxFocusRingWidth * xscale : kMaxFocusRingWidth; - float scaledFocusRingY = yscale < 1.0f ? kMaxFocusRingWidth * yscale : kMaxFocusRingWidth; - CGContextDrawImage(cgContext, CGRectMake(destRect.origin.x - scaledFocusRingX, - destRect.origin.y - scaledFocusRingY, - destRect.size.width + scaledFocusRingX * 2, - destRect.size.height + scaledFocusRingY * 2), - img); - - CGImageRelease(img); - CGContextRelease(ctx); - } - - [NSGraphicsContext restoreGraphicsState]; - -#if DRAW_IN_FRAME_DEBUG - CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25); - CGContextFillRect(cgContext, destRect); -#endif - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -struct CellRenderSettings { - // The natural dimensions of the control. - // If a control has no natural dimensions in either/both axes, set to 0.0f. - NSSize naturalSizes[3]; - - // The minimum dimensions of the control. - // If a control has no minimum dimensions in either/both axes, set to 0.0f. - NSSize minimumSizes[3]; - - // A three-dimensional array, - // with the first dimension being the OS version ([0] 10.6-10.9, [1] 10.10 and above), - // the second being the control size (mini, small, regular), and the third - // being the 4 margin values (left, top, right, bottom). - float margins[2][3][4]; -}; - -/* - * This is a helper method that returns the required NSControlSize given a size - * and the size of the three controls plus a tolerance. - * size - The width or the height of the element to draw. - * sizes - An array with the all the width/height of the element for its - * different sizes. - * tolerance - The tolerance as passed to DrawCellWithSnapping. - * NOTE: returns NSRegularControlSize if all values in 'sizes' are zero. - */ -static NSControlSize FindControlSize(CGFloat size, const CGFloat* sizes, CGFloat tolerance) -{ - for (uint32_t i = miniControlSize; i <= regularControlSize; ++i) { - if (sizes[i] == 0) { - continue; - } - - CGFloat next = 0; - // Find next value. - for (uint32_t j = i+1; j <= regularControlSize; ++j) { - if (sizes[j] != 0) { - next = sizes[j]; - break; - } - } - - // If it's the latest value, we pick it. - if (next == 0) { - return CocoaSizeForEnum(i); - } - - if (size <= sizes[i] + tolerance && size < next) { - return CocoaSizeForEnum(i); - } - } - - // If we are here, that means sizes[] was an array with only empty values - // or the algorithm above is wrong. - // The former can happen but the later would be wrong. - NS_ASSERTION(sizes[0] == 0 && sizes[1] == 0 && sizes[2] == 0, - "We found no control! We shouldn't be there!"); - return CocoaSizeForEnum(regularControlSize); -} - -/* - * Draw the given NSCell into the given cgContext with a nice control size. - * - * This function is similar to DrawCellWithScaling, but it decides what - * control size to use based on the destRect's size. - * Scaling is only applied when the difference between the destRect's size - * and the next smaller natural size is greater than snapTolerance. Otherwise - * it snaps to the next smaller control size without scaling because unscaled - * controls look nicer. - */ -static void DrawCellWithSnapping(NSCell *cell, - CGContextRef cgContext, - const HIRect& destRect, - const CellRenderSettings settings, - float verticalAlignFactor, - NSView* view, - BOOL mirrorHorizontal, - float snapTolerance = 2.0f) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - const float rectWidth = destRect.size.width, rectHeight = destRect.size.height; - const NSSize *sizes = settings.naturalSizes; - const NSSize miniSize = sizes[EnumSizeForCocoaSize(NSMiniControlSize)]; - const NSSize smallSize = sizes[EnumSizeForCocoaSize(NSSmallControlSize)]; - const NSSize regularSize = sizes[EnumSizeForCocoaSize(NSRegularControlSize)]; - - HIRect drawRect = destRect; - - CGFloat controlWidths[3] = { miniSize.width, smallSize.width, regularSize.width }; - NSControlSize controlSizeX = FindControlSize(rectWidth, controlWidths, snapTolerance); - CGFloat controlHeights[3] = { miniSize.height, smallSize.height, regularSize.height }; - NSControlSize controlSizeY = FindControlSize(rectHeight, controlHeights, snapTolerance); - - NSControlSize controlSize = NSRegularControlSize; - size_t sizeIndex = 0; - - // At some sizes, don't scale but snap. - const NSControlSize smallerControlSize = - EnumSizeForCocoaSize(controlSizeX) < EnumSizeForCocoaSize(controlSizeY) ? - controlSizeX : controlSizeY; - const size_t smallerControlSizeIndex = EnumSizeForCocoaSize(smallerControlSize); - const NSSize size = sizes[smallerControlSizeIndex]; - float diffWidth = size.width ? rectWidth - size.width : 0.0f; - float diffHeight = size.height ? rectHeight - size.height : 0.0f; - if (diffWidth >= 0.0f && diffHeight >= 0.0f && - diffWidth <= snapTolerance && diffHeight <= snapTolerance) { - // Snap to the smaller control size. - controlSize = smallerControlSize; - sizeIndex = smallerControlSizeIndex; - MOZ_ASSERT(sizeIndex < ArrayLength(settings.naturalSizes)); - - // Resize and center the drawRect. - if (sizes[sizeIndex].width) { - drawRect.origin.x += ceil((destRect.size.width - sizes[sizeIndex].width) / 2); - drawRect.size.width = sizes[sizeIndex].width; - } - if (sizes[sizeIndex].height) { - drawRect.origin.y += floor((destRect.size.height - sizes[sizeIndex].height) * verticalAlignFactor); - drawRect.size.height = sizes[sizeIndex].height; - } - } else { - // Use the larger control size. - controlSize = EnumSizeForCocoaSize(controlSizeX) > EnumSizeForCocoaSize(controlSizeY) ? - controlSizeX : controlSizeY; - sizeIndex = EnumSizeForCocoaSize(controlSize); - } - - [cell setControlSize:controlSize]; - - MOZ_ASSERT(sizeIndex < ArrayLength(settings.minimumSizes)); - const NSSize minimumSize = settings.minimumSizes[sizeIndex]; - DrawCellWithScaling(cell, cgContext, drawRect, controlSize, sizes[sizeIndex], - minimumSize, settings.margins, view, mirrorHorizontal); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -@interface NSWindow(CoreUIRendererPrivate) -+ (CUIRendererRef)coreUIRenderer; -@end - -static id -GetAquaAppearance() -{ - // We only need NSAppearance on 10.10 and up. - if (nsCocoaFeatures::OnYosemiteOrLater()) { - Class NSAppearanceClass = NSClassFromString(@"NSAppearance"); - if (NSAppearanceClass && - [NSAppearanceClass respondsToSelector:@selector(appearanceNamed:)]) { - return [NSAppearanceClass performSelector:@selector(appearanceNamed:) - withObject:@"NSAppearanceNameAqua"]; - } - } - return nil; -} - -@interface NSObject(NSAppearanceCoreUIRendering) -- (void)_drawInRect:(CGRect)rect context:(CGContextRef)cgContext options:(id)options; -@end - -static void -RenderWithCoreUI(CGRect aRect, CGContextRef cgContext, NSDictionary* aOptions, bool aSkipAreaCheck = false) -{ - id appearance = GetAquaAppearance(); - - if (!aSkipAreaCheck && aRect.size.width * aRect.size.height > BITMAP_MAX_AREA) { - return; - } - - if (appearance && [appearance respondsToSelector:@selector(_drawInRect:context:options:)]) { - // Render through NSAppearance on Mac OS 10.10 and up. This will call - // CUIDraw with a CoreUI renderer that will give us the correct 10.10 - // style. Calling CUIDraw directly with [NSWindow coreUIRenderer] still - // renders 10.9-style widgets on 10.10. - [appearance _drawInRect:aRect context:cgContext options:aOptions]; - } else { - // 10.9 and below - CUIRendererRef renderer = [NSWindow respondsToSelector:@selector(coreUIRenderer)] - ? [NSWindow coreUIRenderer] : nil; - CUIDraw(renderer, aRect, cgContext, (CFDictionaryRef)aOptions, NULL); - } -} - -static float VerticalAlignFactor(nsIFrame *aFrame) -{ - if (!aFrame) - return 0.5f; // default: center - - const nsStyleCoord& va = aFrame->StyleDisplay()->mVerticalAlign; - uint8_t intval = (va.GetUnit() == eStyleUnit_Enumerated) - ? va.GetIntValue() - : NS_STYLE_VERTICAL_ALIGN_MIDDLE; - switch (intval) { - case NS_STYLE_VERTICAL_ALIGN_TOP: - case NS_STYLE_VERTICAL_ALIGN_TEXT_TOP: - return 0.0f; - - case NS_STYLE_VERTICAL_ALIGN_SUB: - case NS_STYLE_VERTICAL_ALIGN_SUPER: - case NS_STYLE_VERTICAL_ALIGN_MIDDLE: - case NS_STYLE_VERTICAL_ALIGN_MIDDLE_WITH_BASELINE: - return 0.5f; - - case NS_STYLE_VERTICAL_ALIGN_BASELINE: - case NS_STYLE_VERTICAL_ALIGN_TEXT_BOTTOM: - case NS_STYLE_VERTICAL_ALIGN_BOTTOM: - return 1.0f; - - default: - NS_NOTREACHED("invalid vertical-align"); - return 0.5f; - } -} - -// These are the sizes that Gecko needs to request to draw if it wants -// to get a standard-sized Aqua radio button drawn. Note that the rects -// that draw these are actually a little bigger. -static const CellRenderSettings radioSettings = { - { - NSMakeSize(11, 11), // mini - NSMakeSize(13, 13), // small - NSMakeSize(16, 16) // regular - }, - { - NSZeroSize, NSZeroSize, NSZeroSize - }, - { - { // Leopard - {0, 0, 0, 0}, // mini - {0, 1, 1, 1}, // small - {0, 0, 0, 0} // regular - }, - { // Yosemite - {0, 0, 0, 0}, // mini - {1, 1, 1, 2}, // small - {0, 0, 0, 0} // regular - } - } -}; - -static const CellRenderSettings checkboxSettings = { - { - NSMakeSize(11, 11), // mini - NSMakeSize(13, 13), // small - NSMakeSize(16, 16) // regular - }, - { - NSZeroSize, NSZeroSize, NSZeroSize - }, - { - { // Leopard - {0, 1, 0, 0}, // mini - {0, 1, 0, 1}, // small - {0, 1, 0, 1} // regular - }, - { // Yosemite - {0, 1, 0, 0}, // mini - {0, 1, 0, 1}, // small - {0, 1, 0, 1} // regular - } - } -}; - -void -nsNativeThemeCocoa::DrawCheckboxOrRadio(CGContextRef cgContext, bool inCheckbox, - const HIRect& inBoxRect, bool inSelected, - EventStates inState, nsIFrame* aFrame) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - NSButtonCell *cell = inCheckbox ? mCheckboxCell : mRadioButtonCell; - NSCellStateValue state = inSelected ? NSOnState : NSOffState; - - // Check if we have an indeterminate checkbox - if (inCheckbox && GetIndeterminate(aFrame)) - state = NSMixedState; - - [cell setEnabled:!IsDisabled(aFrame, inState)]; - [cell setShowsFirstResponder:inState.HasState(NS_EVENT_STATE_FOCUS)]; - [cell setState:state]; - [cell setHighlighted:inState.HasAllStates(NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_HOVER)]; - [cell setControlTint:(FrameIsInActiveWindow(aFrame) ? [NSColor currentControlTint] : NSClearControlTint)]; - - // Ensure that the control is square. - float length = std::min(inBoxRect.size.width, inBoxRect.size.height); - HIRect drawRect = CGRectMake(inBoxRect.origin.x + (int)((inBoxRect.size.width - length) / 2.0f), - inBoxRect.origin.y + (int)((inBoxRect.size.height - length) / 2.0f), - length, length); - - DrawCellWithSnapping(cell, cgContext, drawRect, - inCheckbox ? checkboxSettings : radioSettings, - VerticalAlignFactor(aFrame), mCellDrawView, NO); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -static const CellRenderSettings searchFieldSettings = { - { - NSMakeSize(0, 16), // mini - NSMakeSize(0, 19), // small - NSMakeSize(0, 22) // regular - }, - { - NSMakeSize(32, 0), // mini - NSMakeSize(38, 0), // small - NSMakeSize(44, 0) // regular - }, - { - { // Leopard - {0, 0, 0, 0}, // mini - {0, 0, 0, 0}, // small - {0, 0, 0, 0} // regular - }, - { // Yosemite - {0, 0, 0, 0}, // mini - {0, 0, 0, 0}, // small - {0, 0, 0, 0} // regular - } - } -}; - -void -nsNativeThemeCocoa::DrawSearchField(CGContextRef cgContext, const HIRect& inBoxRect, - nsIFrame* aFrame, EventStates inState) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - ContextAwareSearchFieldCell* cell = mSearchFieldCell; - [cell setContext:aFrame]; - [cell setEnabled:!IsDisabled(aFrame, inState)]; - // NOTE: this could probably use inState - [cell setShowsFirstResponder:IsFocused(aFrame)]; - - // When using the 10.11 SDK, the default string will be shown if we don't - // set the placeholder string. - [cell setPlaceholderString:@""]; - - DrawCellWithSnapping(cell, cgContext, inBoxRect, searchFieldSettings, - VerticalAlignFactor(aFrame), mCellDrawView, - IsFrameRTL(aFrame)); - - [cell setContext:nullptr]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -static const NSSize kCheckmarkSize = NSMakeSize(11, 11); -static const NSSize kMenuarrowSize = NSMakeSize(9, 10); -static const NSSize kMenuScrollArrowSize = NSMakeSize(10, 8); -static NSString* kCheckmarkImage = @"MenuOnState"; -static NSString* kMenuarrowRightImage = @"MenuSubmenu"; -static NSString* kMenuarrowLeftImage = @"MenuSubmenuLeft"; -static NSString* kMenuDownScrollArrowImage = @"MenuScrollDown"; -static NSString* kMenuUpScrollArrowImage = @"MenuScrollUp"; -static const CGFloat kMenuIconIndent = 6.0f; - -void -nsNativeThemeCocoa::DrawMenuIcon(CGContextRef cgContext, const CGRect& aRect, - EventStates inState, nsIFrame* aFrame, - const NSSize& aIconSize, NSString* aImageName, - bool aCenterHorizontally) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // Adjust size and position of our drawRect. - CGFloat paddingX = std::max(CGFloat(0.0), aRect.size.width - aIconSize.width); - CGFloat paddingY = std::max(CGFloat(0.0), aRect.size.height - aIconSize.height); - CGFloat paddingStartX = std::min(paddingX, kMenuIconIndent); - CGFloat paddingEndX = std::max(CGFloat(0.0), paddingX - kMenuIconIndent); - CGRect drawRect = CGRectMake( - aRect.origin.x + (aCenterHorizontally ? ceil(paddingX / 2) : - IsFrameRTL(aFrame) ? paddingEndX : paddingStartX), - aRect.origin.y + ceil(paddingY / 2), - aIconSize.width, aIconSize.height); - - NSString* state = IsDisabled(aFrame, inState) ? @"disabled" : - (CheckBooleanAttr(aFrame, nsGkAtoms::menuactive) ? @"pressed" : @"normal"); - - NSString* imageName = aImageName; - if (!nsCocoaFeatures::OnElCapitanOrLater()) { - // Pre-10.11, image names are prefixed with "image." - imageName = [@"image." stringByAppendingString:aImageName]; - } - - RenderWithCoreUI(drawRect, cgContext, - [NSDictionary dictionaryWithObjectsAndKeys: - @"kCUIBackgroundTypeMenu", @"backgroundTypeKey", - imageName, @"imageNameKey", - state, @"state", - @"image", @"widget", - [NSNumber numberWithBool:YES], @"is.flipped", - nil]); - -#if DRAW_IN_FRAME_DEBUG - CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25); - CGContextFillRect(cgContext, drawRect); -#endif - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -static const NSSize kHelpButtonSize = NSMakeSize(20, 20); -static const NSSize kDisclosureButtonSize = NSMakeSize(21, 21); - -static const CellRenderSettings pushButtonSettings = { - { - NSMakeSize(0, 16), // mini - NSMakeSize(0, 19), // small - NSMakeSize(0, 22) // regular - }, - { - NSMakeSize(18, 0), // mini - NSMakeSize(26, 0), // small - NSMakeSize(30, 0) // regular - }, - { - { // Leopard - {0, 0, 0, 0}, // mini - {4, 0, 4, 1}, // small - {5, 0, 5, 2} // regular - }, - { // Yosemite - {0, 0, 0, 0}, // mini - {4, 0, 4, 1}, // small - {5, 0, 5, 2} // regular - } - } -}; - -// The height at which we start doing square buttons instead of rounded buttons -// Rounded buttons look bad if drawn at a height greater than 26, so at that point -// we switch over to doing square buttons which looks fine at any size. -#define DO_SQUARE_BUTTON_HEIGHT 26 - -void -nsNativeThemeCocoa::DrawPushButton(CGContextRef cgContext, const HIRect& inBoxRect, - EventStates inState, uint8_t aWidgetType, - nsIFrame* aFrame, float aOriginalHeight) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - BOOL isActive = FrameIsInActiveWindow(aFrame); - BOOL isDisabled = IsDisabled(aFrame, inState); - - NSButtonCell* cell = (aWidgetType == NS_THEME_BUTTON) ? mPushButtonCell : - (aWidgetType == NS_THEME_MAC_HELP_BUTTON) ? mHelpButtonCell : mDisclosureButtonCell; - [cell setEnabled:!isDisabled]; - [cell setHighlighted:isActive && - inState.HasAllStates(NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_HOVER)]; - [cell setShowsFirstResponder:inState.HasState(NS_EVENT_STATE_FOCUS) && !isDisabled && isActive]; - - if (aWidgetType != NS_THEME_BUTTON) { // Help button or disclosure button. - NSSize buttonSize = NSMakeSize(0, 0); - if (aWidgetType == NS_THEME_MAC_HELP_BUTTON) { - buttonSize = kHelpButtonSize; - } else { // Disclosure button. - buttonSize = kDisclosureButtonSize; - [cell setState:(aWidgetType == NS_THEME_MAC_DISCLOSURE_BUTTON_CLOSED) ? NSOffState : NSOnState]; - } - - DrawCellWithScaling(cell, cgContext, inBoxRect, NSRegularControlSize, - NSZeroSize, buttonSize, NULL, mCellDrawView, - false); // Don't mirror icon in RTL. - } else { - // If the button is tall enough, draw the square button style so that - // buttons with non-standard content look good. Otherwise draw normal - // rounded aqua buttons. - // This comparison is done based on the height that is calculated without - // the top, because the snapped height can be affected by the top of the - // rect and that may result in different height depending on the top value. - if (aOriginalHeight > DO_SQUARE_BUTTON_HEIGHT) { - [cell setBezelStyle:NSShadowlessSquareBezelStyle]; - DrawCellWithScaling(cell, cgContext, inBoxRect, NSRegularControlSize, - NSZeroSize, NSMakeSize(14, 0), NULL, mCellDrawView, - IsFrameRTL(aFrame)); - } else { - [cell setBezelStyle:NSRoundedBezelStyle]; - DrawCellWithSnapping(cell, cgContext, inBoxRect, pushButtonSettings, 0.5f, - mCellDrawView, IsFrameRTL(aFrame), 1.0f); - } - } - -#if DRAW_IN_FRAME_DEBUG - CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25); - CGContextFillRect(cgContext, inBoxRect); -#endif - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void -nsNativeThemeCocoa::DrawFocusOutline(CGContextRef cgContext, const HIRect& inBoxRect, - EventStates inState, uint8_t aWidgetType, - nsIFrame* aFrame) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - HIThemeFrameDrawInfo fdi; - fdi.version = 0; - fdi.kind = kHIThemeFrameTextFieldSquare; - fdi.state = kThemeStateActive; - fdi.isFocused = TRUE; - -#if DRAW_IN_FRAME_DEBUG - CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25); - CGContextFillRect(cgContext, inBoxRect); -#endif - - HIThemeDrawFrame(&inBoxRect, &fdi, cgContext, HITHEME_ORIENTATION); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -typedef void (*RenderHIThemeControlFunction)(CGContextRef cgContext, const HIRect& aRenderRect, void* aData); - -static void -RenderTransformedHIThemeControl(CGContextRef aCGContext, const HIRect& aRect, - RenderHIThemeControlFunction aFunc, void* aData, - BOOL mirrorHorizontally = NO) -{ - CGAffineTransform savedCTM = CGContextGetCTM(aCGContext); - CGContextTranslateCTM(aCGContext, aRect.origin.x, aRect.origin.y); - - bool drawDirect; - HIRect drawRect = aRect; - drawRect.origin = CGPointZero; - - if (!mirrorHorizontally && savedCTM.a == 1.0f && savedCTM.b == 0.0f && - savedCTM.c == 0.0f && (savedCTM.d == 1.0f || savedCTM.d == -1.0f)) { - drawDirect = TRUE; - } else { - drawDirect = FALSE; - } - - // Fall back to no bitmap buffer if the area of our control (in pixels^2) - // is too large. - if (drawDirect || (aRect.size.width * aRect.size.height > BITMAP_MAX_AREA)) { - aFunc(aCGContext, drawRect, aData); - } else { - // Inflate the buffer to capture focus rings. - int w = ceil(drawRect.size.width) + 2 * kMaxFocusRingWidth; - int h = ceil(drawRect.size.height) + 2 * kMaxFocusRingWidth; - - int backingScaleFactor = GetBackingScaleFactorForRendering(aCGContext); - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - CGContextRef bitmapctx = CGBitmapContextCreate(NULL, - w * backingScaleFactor, - h * backingScaleFactor, - 8, - w * backingScaleFactor * 4, - colorSpace, - kCGImageAlphaPremultipliedFirst); - CGColorSpaceRelease(colorSpace); - - CGContextScaleCTM(bitmapctx, backingScaleFactor, backingScaleFactor); - CGContextTranslateCTM(bitmapctx, kMaxFocusRingWidth, kMaxFocusRingWidth); - - // Set the context's "base transform" to in order to get correctly-sized focus rings. - CGContextSetBaseCTM(bitmapctx, CGAffineTransformMakeScale(backingScaleFactor, backingScaleFactor)); - - // HITheme always wants to draw into a flipped context, or things - // get confused. - CGContextTranslateCTM(bitmapctx, 0.0f, aRect.size.height); - CGContextScaleCTM(bitmapctx, 1.0f, -1.0f); - - aFunc(bitmapctx, drawRect, aData); - - CGImageRef bitmap = CGBitmapContextCreateImage(bitmapctx); - - CGAffineTransform ctm = CGContextGetCTM(aCGContext); - - // We need to unflip, so that we can do a DrawImage without getting a flipped image. - CGContextTranslateCTM(aCGContext, 0.0f, aRect.size.height); - CGContextScaleCTM(aCGContext, 1.0f, -1.0f); - - if (mirrorHorizontally) { - CGContextTranslateCTM(aCGContext, aRect.size.width, 0); - CGContextScaleCTM(aCGContext, -1.0f, 1.0f); - } - - HIRect inflatedDrawRect = CGRectMake(-kMaxFocusRingWidth, -kMaxFocusRingWidth, w, h); - CGContextDrawImage(aCGContext, inflatedDrawRect, bitmap); - - CGContextSetCTM(aCGContext, ctm); - - CGImageRelease(bitmap); - CGContextRelease(bitmapctx); - } - - CGContextSetCTM(aCGContext, savedCTM); -} - -static void -RenderButton(CGContextRef cgContext, const HIRect& aRenderRect, void* aData) -{ - HIThemeButtonDrawInfo* bdi = (HIThemeButtonDrawInfo*)aData; - HIThemeDrawButton(&aRenderRect, bdi, cgContext, kHIThemeOrientationNormal, NULL); -} - -void -nsNativeThemeCocoa::DrawButton(CGContextRef cgContext, ThemeButtonKind inKind, - const HIRect& inBoxRect, bool inIsDefault, - ThemeButtonValue inValue, ThemeButtonAdornment inAdornment, - EventStates inState, nsIFrame* aFrame) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - BOOL isActive = FrameIsInActiveWindow(aFrame); - BOOL isDisabled = IsDisabled(aFrame, inState); - - HIThemeButtonDrawInfo bdi; - bdi.version = 0; - bdi.kind = inKind; - bdi.value = inValue; - bdi.adornment = inAdornment; - - if (isDisabled) { - bdi.state = kThemeStateUnavailable; - } - else if (inState.HasAllStates(NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_HOVER)) { - bdi.state = kThemeStatePressed; - } - else { - if (inKind == kThemeArrowButton) - bdi.state = kThemeStateUnavailable; // these are always drawn as unavailable - else if (!isActive && inKind == kThemeListHeaderButton) - bdi.state = kThemeStateInactive; - else - bdi.state = kThemeStateActive; - } - - if (inState.HasState(NS_EVENT_STATE_FOCUS) && isActive) - bdi.adornment |= kThemeAdornmentFocus; - - if (inIsDefault && !isDisabled && - !inState.HasState(NS_EVENT_STATE_ACTIVE)) { - bdi.adornment |= kThemeAdornmentDefault; - bdi.animation.time.start = 0; - bdi.animation.time.current = CFAbsoluteTimeGetCurrent(); - } - - HIRect drawFrame = inBoxRect; - - if (inKind == kThemePushButton) { - drawFrame.size.height -= 2; - if (inBoxRect.size.height < pushButtonSettings.naturalSizes[smallControlSize].height) { - bdi.kind = kThemePushButtonMini; - } - else if (inBoxRect.size.height < pushButtonSettings.naturalSizes[regularControlSize].height) { - bdi.kind = kThemePushButtonSmall; - drawFrame.origin.y -= 1; - drawFrame.origin.x += 1; - drawFrame.size.width -= 2; - } - } - else if (inKind == kThemeListHeaderButton) { - CGContextClipToRect(cgContext, inBoxRect); - // Always remove the top border. - drawFrame.origin.y -= 1; - drawFrame.size.height += 1; - // Remove the left border in LTR mode and the right border in RTL mode. - drawFrame.size.width += 1; - bool isLast = IsLastTreeHeaderCell(aFrame); - if (isLast) - drawFrame.size.width += 1; // Also remove the other border. - if (!IsFrameRTL(aFrame) || isLast) - drawFrame.origin.x -= 1; - } - - RenderTransformedHIThemeControl(cgContext, drawFrame, RenderButton, &bdi, - IsFrameRTL(aFrame)); - -#if DRAW_IN_FRAME_DEBUG - CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25); - CGContextFillRect(cgContext, inBoxRect); -#endif - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -static const CellRenderSettings dropdownSettings = { - { - NSMakeSize(0, 16), // mini - NSMakeSize(0, 19), // small - NSMakeSize(0, 22) // regular - }, - { - NSMakeSize(18, 0), // mini - NSMakeSize(38, 0), // small - NSMakeSize(44, 0) // regular - }, - { - { // Leopard - {1, 1, 2, 1}, // mini - {3, 0, 3, 1}, // small - {3, 0, 3, 0} // regular - }, - { // Yosemite - {1, 1, 2, 1}, // mini - {3, 0, 3, 1}, // small - {3, 0, 3, 0} // regular - } - } -}; - -static const CellRenderSettings editableMenulistSettings = { - { - NSMakeSize(0, 15), // mini - NSMakeSize(0, 18), // small - NSMakeSize(0, 21) // regular - }, - { - NSMakeSize(18, 0), // mini - NSMakeSize(38, 0), // small - NSMakeSize(44, 0) // regular - }, - { - { // Leopard - {0, 0, 2, 2}, // mini - {0, 0, 3, 2}, // small - {0, 1, 3, 3} // regular - }, - { // Yosemite - {0, 0, 2, 2}, // mini - {0, 0, 3, 2}, // small - {0, 1, 3, 3} // regular - } - } -}; - -void -nsNativeThemeCocoa::DrawDropdown(CGContextRef cgContext, const HIRect& inBoxRect, - EventStates inState, uint8_t aWidgetType, - nsIFrame* aFrame) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mDropdownCell setPullsDown:(aWidgetType == NS_THEME_BUTTON)]; - - BOOL isEditable = (aWidgetType == NS_THEME_MENULIST_TEXTFIELD); - NSCell* cell = isEditable ? (NSCell*)mComboBoxCell : (NSCell*)mDropdownCell; - - [cell setEnabled:!IsDisabled(aFrame, inState)]; - [cell setShowsFirstResponder:(IsFocused(aFrame) || inState.HasState(NS_EVENT_STATE_FOCUS))]; - [cell setHighlighted:IsOpenButton(aFrame)]; - [cell setControlTint:(FrameIsInActiveWindow(aFrame) ? [NSColor currentControlTint] : NSClearControlTint)]; - - const CellRenderSettings& settings = isEditable ? editableMenulistSettings : dropdownSettings; - DrawCellWithSnapping(cell, cgContext, inBoxRect, settings, - 0.5f, mCellDrawView, IsFrameRTL(aFrame)); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -static const CellRenderSettings spinnerSettings = { - { - NSMakeSize(11, 16), // mini (width trimmed by 2px to reduce blank border) - NSMakeSize(15, 22), // small - NSMakeSize(19, 27) // regular - }, - { - NSMakeSize(11, 16), // mini (width trimmed by 2px to reduce blank border) - NSMakeSize(15, 22), // small - NSMakeSize(19, 27) // regular - }, - { - { // Leopard - {0, 0, 0, 0}, // mini - {0, 0, 0, 0}, // small - {0, 0, 0, 0} // regular - }, - { // Yosemite - {0, 0, 0, 0}, // mini - {0, 0, 0, 0}, // small - {0, 0, 0, 0} // regular - } - } -}; - -void -nsNativeThemeCocoa::DrawSpinButtons(CGContextRef cgContext, ThemeButtonKind inKind, - const HIRect& inBoxRect, ThemeDrawState inDrawState, - ThemeButtonAdornment inAdornment, - EventStates inState, nsIFrame* aFrame) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - HIThemeButtonDrawInfo bdi; - bdi.version = 0; - bdi.kind = inKind; - bdi.value = kThemeButtonOff; - bdi.adornment = inAdornment; - - if (IsDisabled(aFrame, inState)) - bdi.state = kThemeStateUnavailable; - else - bdi.state = FrameIsInActiveWindow(aFrame) ? inDrawState : kThemeStateActive; - - HIThemeDrawButton(&inBoxRect, &bdi, cgContext, HITHEME_ORIENTATION, NULL); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void -nsNativeThemeCocoa::DrawSpinButton(CGContextRef cgContext, - ThemeButtonKind inKind, - const HIRect& inBoxRect, - ThemeDrawState inDrawState, - ThemeButtonAdornment inAdornment, - EventStates inState, - nsIFrame* aFrame, - uint8_t aWidgetType) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - MOZ_ASSERT(aWidgetType == NS_THEME_SPINNER_UPBUTTON || - aWidgetType == NS_THEME_SPINNER_DOWNBUTTON); - - HIThemeButtonDrawInfo bdi; - bdi.version = 0; - bdi.kind = inKind; - bdi.value = kThemeButtonOff; - bdi.adornment = inAdornment; - - if (IsDisabled(aFrame, inState)) - bdi.state = kThemeStateUnavailable; - else - bdi.state = FrameIsInActiveWindow(aFrame) ? inDrawState : kThemeStateActive; - - // Cocoa only allows kThemeIncDecButton to paint the up and down spin buttons - // together as a single unit (presumably because when one button is active, - // the appearance of both changes (in different ways)). Here we have to paint - // both buttons, using clip to hide the one we don't want to paint. - HIRect drawRect = inBoxRect; - drawRect.size.height *= 2; - if (aWidgetType == NS_THEME_SPINNER_DOWNBUTTON) { - drawRect.origin.y -= inBoxRect.size.height; - } - - // Shift the drawing a little to the left, since cocoa paints with more - // blank space around the visual buttons than we'd like: - drawRect.origin.x -= 1; - - CGContextSaveGState(cgContext); - CGContextClipToRect(cgContext, inBoxRect); - - HIThemeDrawButton(&drawRect, &bdi, cgContext, HITHEME_ORIENTATION, NULL); - - CGContextRestoreGState(cgContext); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void -nsNativeThemeCocoa::DrawFrame(CGContextRef cgContext, HIThemeFrameKind inKind, - const HIRect& inBoxRect, bool inDisabled, - EventStates inState) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - HIThemeFrameDrawInfo fdi; - fdi.version = 0; - fdi.kind = inKind; - - // We don't ever set an inactive state for this because it doesn't - // look right (see other apps). - fdi.state = inDisabled ? kThemeStateUnavailable : kThemeStateActive; - - // for some reason focus rings on listboxes draw incorrectly - if (inKind == kHIThemeFrameListBox) - fdi.isFocused = 0; - else - fdi.isFocused = inState.HasState(NS_EVENT_STATE_FOCUS); - - // HIThemeDrawFrame takes the rect for the content area of the frame, not - // the bounding rect for the frame. Here we reduce the size of the rect we - // will pass to make it the size of the content. - HIRect drawRect = inBoxRect; - if (inKind == kHIThemeFrameTextFieldSquare) { - SInt32 frameOutset = 0; - ::GetThemeMetric(kThemeMetricEditTextFrameOutset, &frameOutset); - drawRect.origin.x += frameOutset; - drawRect.origin.y += frameOutset; - drawRect.size.width -= frameOutset * 2; - drawRect.size.height -= frameOutset * 2; - } - else if (inKind == kHIThemeFrameListBox) { - SInt32 frameOutset = 0; - ::GetThemeMetric(kThemeMetricListBoxFrameOutset, &frameOutset); - drawRect.origin.x += frameOutset; - drawRect.origin.y += frameOutset; - drawRect.size.width -= frameOutset * 2; - drawRect.size.height -= frameOutset * 2; - } - -#if DRAW_IN_FRAME_DEBUG - CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25); - CGContextFillRect(cgContext, inBoxRect); -#endif - - HIThemeDrawFrame(&drawRect, &fdi, cgContext, HITHEME_ORIENTATION); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -static const CellRenderSettings progressSettings[2][2] = { - // Vertical progress bar. - { - // Determined settings. - { - { - NSZeroSize, // mini - NSMakeSize(10, 0), // small - NSMakeSize(16, 0) // regular - }, - { - NSZeroSize, NSZeroSize, NSZeroSize - }, - { - { // Leopard - {0, 0, 0, 0}, // mini - {1, 1, 1, 1}, // small - {1, 1, 1, 1} // regular - } - } - }, - // There is no horizontal margin in regular undetermined size. - { - { - NSZeroSize, // mini - NSMakeSize(10, 0), // small - NSMakeSize(16, 0) // regular - }, - { - NSZeroSize, NSZeroSize, NSZeroSize - }, - { - { // Leopard - {0, 0, 0, 0}, // mini - {1, 1, 1, 1}, // small - {1, 0, 1, 0} // regular - }, - { // Yosemite - {0, 0, 0, 0}, // mini - {1, 1, 1, 1}, // small - {1, 0, 1, 0} // regular - } - } - } - }, - // Horizontal progress bar. - { - // Determined settings. - { - { - NSZeroSize, // mini - NSMakeSize(0, 10), // small - NSMakeSize(0, 16) // regular - }, - { - NSZeroSize, NSZeroSize, NSZeroSize - }, - { - { // Leopard - {0, 0, 0, 0}, // mini - {1, 1, 1, 1}, // small - {1, 1, 1, 1} // regular - }, - { // Yosemite - {0, 0, 0, 0}, // mini - {1, 1, 1, 1}, // small - {1, 1, 1, 1} // regular - } - } - }, - // There is no horizontal margin in regular undetermined size. - { - { - NSZeroSize, // mini - NSMakeSize(0, 10), // small - NSMakeSize(0, 16) // regular - }, - { - NSZeroSize, NSZeroSize, NSZeroSize - }, - { - { // Leopard - {0, 0, 0, 0}, // mini - {1, 1, 1, 1}, // small - {0, 1, 0, 1} // regular - }, - { // Yosemite - {0, 0, 0, 0}, // mini - {1, 1, 1, 1}, // small - {0, 1, 0, 1} // regular - } - } - } - } -}; - -void -nsNativeThemeCocoa::DrawProgress(CGContextRef cgContext, const HIRect& inBoxRect, - bool inIsIndeterminate, bool inIsHorizontal, - double inValue, double inMaxValue, - nsIFrame* aFrame) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - NSProgressBarCell* cell = mProgressBarCell; - - [cell setValue:inValue]; - [cell setMax:inMaxValue]; - [cell setIndeterminate:inIsIndeterminate]; - [cell setHorizontal:inIsHorizontal]; - [cell setControlTint:(FrameIsInActiveWindow(aFrame) ? [NSColor currentControlTint] - : NSClearControlTint)]; - - DrawCellWithSnapping(cell, cgContext, inBoxRect, - progressSettings[inIsHorizontal][inIsIndeterminate], - VerticalAlignFactor(aFrame), mCellDrawView, - IsFrameRTL(aFrame)); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -static const CellRenderSettings meterSetting = { - { - NSMakeSize(0, 16), // mini - NSMakeSize(0, 16), // small - NSMakeSize(0, 16) // regular - }, - { - NSZeroSize, NSZeroSize, NSZeroSize - }, - { - { // Leopard - {1, 1, 1, 1}, // mini - {1, 1, 1, 1}, // small - {1, 1, 1, 1} // regular - }, - { // Yosemite - {1, 1, 1, 1}, // mini - {1, 1, 1, 1}, // small - {1, 1, 1, 1} // regular - } - } -}; - -void -nsNativeThemeCocoa::DrawMeter(CGContextRef cgContext, const HIRect& inBoxRect, - nsIFrame* aFrame) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK - - NS_PRECONDITION(aFrame, "aFrame should not be null here!"); - - // When using -moz-meterbar on an non meter element, we will not be able to - // get all the needed information so we just draw an empty meter. - nsIContent* content = aFrame->GetContent(); - if (!(content && content->IsHTMLElement(nsGkAtoms::meter))) { - DrawCellWithSnapping(mMeterBarCell, cgContext, inBoxRect, - meterSetting, VerticalAlignFactor(aFrame), - mCellDrawView, IsFrameRTL(aFrame)); - return; - } - - HTMLMeterElement* meterElement = static_cast(content); - double value = meterElement->Value(); - double min = meterElement->Min(); - double max = meterElement->Max(); - - NSLevelIndicatorCell* cell = mMeterBarCell; - - [cell setMinValue:min]; - [cell setMaxValue:max]; - [cell setDoubleValue:value]; - - /** - * The way HTML and Cocoa defines the meter/indicator widget are different. - * So, we are going to use a trick to get the Cocoa widget showing what we - * are expecting: we set the warningValue or criticalValue to the current - * value when we want to have the widget to be in the warning or critical - * state. - */ - EventStates states = aFrame->GetContent()->AsElement()->State(); - - // Reset previously set warning and critical values. - [cell setWarningValue:max+1]; - [cell setCriticalValue:max+1]; - - if (states.HasState(NS_EVENT_STATE_SUB_OPTIMUM)) { - [cell setWarningValue:value]; - } else if (states.HasState(NS_EVENT_STATE_SUB_SUB_OPTIMUM)) { - [cell setCriticalValue:value]; - } - - HIRect rect = CGRectStandardize(inBoxRect); - BOOL vertical = IsVerticalMeter(aFrame); - - CGContextSaveGState(cgContext); - - if (vertical) { - /** - * Cocoa doesn't provide a vertical meter bar so to show one, we have to - * show a rotated horizontal meter bar. - * Given that we want to show a vertical meter bar, we assume that the rect - * has vertical dimensions but we can't correctly draw a meter widget inside - * such a rectangle so we need to inverse width and height (and re-position) - * to get a rectangle with horizontal dimensions. - * Finally, we want to show a vertical meter so we want to rotate the result - * so it is vertical. We do that by changing the context. - */ - CGFloat tmp = rect.size.width; - rect.size.width = rect.size.height; - rect.size.height = tmp; - rect.origin.x += rect.size.height / 2.f - rect.size.width / 2.f; - rect.origin.y += rect.size.width / 2.f - rect.size.height / 2.f; - - CGContextTranslateCTM(cgContext, CGRectGetMidX(rect), CGRectGetMidY(rect)); - CGContextRotateCTM(cgContext, -M_PI / 2.f); - CGContextTranslateCTM(cgContext, -CGRectGetMidX(rect), -CGRectGetMidY(rect)); - } - - DrawCellWithSnapping(cell, cgContext, rect, - meterSetting, VerticalAlignFactor(aFrame), - mCellDrawView, !vertical && IsFrameRTL(aFrame)); - - CGContextRestoreGState(cgContext); - - NS_OBJC_END_TRY_ABORT_BLOCK -} - -void -nsNativeThemeCocoa::DrawTabPanel(CGContextRef cgContext, const HIRect& inBoxRect, - nsIFrame* aFrame) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - HIThemeTabPaneDrawInfo tpdi; - - tpdi.version = 1; - tpdi.state = FrameIsInActiveWindow(aFrame) ? kThemeStateActive : kThemeStateInactive; - tpdi.direction = kThemeTabNorth; - tpdi.size = kHIThemeTabSizeNormal; - tpdi.kind = kHIThemeTabKindNormal; - - HIThemeDrawTabPane(&inBoxRect, &tpdi, cgContext, HITHEME_ORIENTATION); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void -nsNativeThemeCocoa::DrawScale(CGContextRef cgContext, const HIRect& inBoxRect, - EventStates inState, bool inIsVertical, - bool inIsReverse, int32_t inCurrentValue, - int32_t inMinValue, int32_t inMaxValue, - nsIFrame* aFrame) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - HIThemeTrackDrawInfo tdi; - - tdi.version = 0; - tdi.kind = kThemeMediumSlider; - tdi.bounds = inBoxRect; - tdi.min = inMinValue; - tdi.max = inMaxValue; - tdi.value = inCurrentValue; - tdi.attributes = kThemeTrackShowThumb; - if (!inIsVertical) - tdi.attributes |= kThemeTrackHorizontal; - if (inIsReverse) - tdi.attributes |= kThemeTrackRightToLeft; - if (inState.HasState(NS_EVENT_STATE_FOCUS)) - tdi.attributes |= kThemeTrackHasFocus; - if (IsDisabled(aFrame, inState)) - tdi.enableState = kThemeTrackDisabled; - else - tdi.enableState = FrameIsInActiveWindow(aFrame) ? kThemeTrackActive : kThemeTrackInactive; - tdi.trackInfo.slider.thumbDir = kThemeThumbPlain; - tdi.trackInfo.slider.pressState = 0; - - HIThemeDrawTrack(&tdi, NULL, cgContext, HITHEME_ORIENTATION); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsIFrame* -nsNativeThemeCocoa::SeparatorResponsibility(nsIFrame* aBefore, nsIFrame* aAfter) -{ - // Usually a separator is drawn by the segment to the right of the - // separator, but pressed and selected segments have higher priority. - if (!aBefore || !aAfter) - return nullptr; - if (IsSelectedButton(aAfter)) - return aAfter; - if (IsSelectedButton(aBefore) || IsPressedButton(aBefore)) - return aBefore; - return aAfter; -} - -CGRect -nsNativeThemeCocoa::SeparatorAdjustedRect(CGRect aRect, nsIFrame* aLeft, - nsIFrame* aCurrent, nsIFrame* aRight) -{ - // A separator between two segments should always be located in the leftmost - // pixel column of the segment to the right of the separator, regardless of - // who ends up drawing it. - // CoreUI draws the separators inside the drawing rect. - if (aLeft && SeparatorResponsibility(aLeft, aCurrent) == aLeft) { - // The left button draws the separator, so we need to make room for it. - aRect.origin.x += 1; - aRect.size.width -= 1; - } - if (SeparatorResponsibility(aCurrent, aRight) == aCurrent) { - // We draw the right separator, so we need to extend the draw rect into the - // segment to our right. - aRect.size.width += 1; - } - return aRect; -} - -static NSString* ToolbarButtonPosition(BOOL aIsFirst, BOOL aIsLast) -{ - if (aIsFirst) { - if (aIsLast) - return @"kCUISegmentPositionOnly"; - return @"kCUISegmentPositionFirst"; - } - if (aIsLast) - return @"kCUISegmentPositionLast"; - return @"kCUISegmentPositionMiddle"; -} - -struct SegmentedControlRenderSettings { - const CGFloat* heights; - const NSString* widgetName; - const BOOL ignoresPressedWhenSelected; - const BOOL isToolbarControl; -}; - -static const CGFloat tabHeights[3] = { 17, 20, 23 }; - -static const SegmentedControlRenderSettings tabRenderSettings = { - tabHeights, @"tab", YES, NO -}; - -static const CGFloat toolbarButtonHeights[3] = { 15, 18, 22 }; - -static const SegmentedControlRenderSettings toolbarButtonRenderSettings = { - toolbarButtonHeights, @"kCUIWidgetButtonSegmentedSCurve", NO, YES -}; - -void -nsNativeThemeCocoa::DrawSegment(CGContextRef cgContext, const HIRect& inBoxRect, - EventStates inState, nsIFrame* aFrame, - const SegmentedControlRenderSettings& aSettings) -{ - BOOL isActive = IsActive(aFrame, aSettings.isToolbarControl); - BOOL isFocused = inState.HasState(NS_EVENT_STATE_FOCUS); - BOOL isSelected = IsSelectedButton(aFrame); - BOOL isPressed = IsPressedButton(aFrame); - if (isSelected && aSettings.ignoresPressedWhenSelected) { - isPressed = NO; - } - - BOOL isRTL = IsFrameRTL(aFrame); - nsIFrame* left = GetAdjacentSiblingFrameWithSameAppearance(aFrame, isRTL); - nsIFrame* right = GetAdjacentSiblingFrameWithSameAppearance(aFrame, !isRTL); - CGRect drawRect = SeparatorAdjustedRect(inBoxRect, left, aFrame, right); - BOOL drawLeftSeparator = SeparatorResponsibility(left, aFrame) == aFrame; - BOOL drawRightSeparator = SeparatorResponsibility(aFrame, right) == aFrame; - NSControlSize controlSize = FindControlSize(drawRect.size.height, aSettings.heights, 4.0f); - - RenderWithCoreUI(drawRect, cgContext, [NSDictionary dictionaryWithObjectsAndKeys: - aSettings.widgetName, @"widget", - (isActive ? @"kCUIPresentationStateActiveKey" : @"kCUIPresentationStateInactive"), @"kCUIPresentationStateKey", - ToolbarButtonPosition(!left, !right), @"kCUIPositionKey", - [NSNumber numberWithBool:drawLeftSeparator], @"kCUISegmentLeadingSeparatorKey", - [NSNumber numberWithBool:drawRightSeparator], @"kCUISegmentTrailingSeparatorKey", - [NSNumber numberWithBool:isSelected], @"value", - (isPressed ? @"pressed" : (isActive ? @"normal" : @"inactive")), @"state", - [NSNumber numberWithBool:isFocused], @"focus", - CUIControlSizeForCocoaSize(controlSize), @"size", - [NSNumber numberWithBool:YES], @"is.flipped", - @"up", @"direction", - nil]); -} - -void -nsNativeThemeCocoa::GetScrollbarPressStates(nsIFrame* aFrame, - EventStates aButtonStates[]) -{ - static nsIContent::AttrValuesArray attributeValues[] = { - &nsGkAtoms::scrollbarUpTop, - &nsGkAtoms::scrollbarDownTop, - &nsGkAtoms::scrollbarUpBottom, - &nsGkAtoms::scrollbarDownBottom, - nullptr - }; - - // Get the state of any scrollbar buttons in our child frames - for (nsIFrame *childFrame : aFrame->PrincipalChildList()) { - nsIContent *childContent = childFrame->GetContent(); - if (!childContent) continue; - int32_t attrIndex = childContent->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::sbattr, - attributeValues, eCaseMatters); - if (attrIndex < 0) continue; - - aButtonStates[attrIndex] = GetContentState(childFrame, NS_THEME_BUTTON); - } -} - -nsIFrame* -nsNativeThemeCocoa::GetParentScrollbarFrame(nsIFrame *aFrame) -{ - // Walk our parents to find a scrollbar frame - nsIFrame *scrollbarFrame = aFrame; - do { - if (scrollbarFrame->GetType() == nsGkAtoms::scrollbarFrame) break; - } while ((scrollbarFrame = scrollbarFrame->GetParent())); - - // We return null if we can't find a parent scrollbar frame - return scrollbarFrame; -} - -static bool -ToolbarCanBeUnified(CGContextRef cgContext, const HIRect& inBoxRect, NSWindow* aWindow) -{ - if (![aWindow isKindOfClass:[ToolbarWindow class]]) - return false; - - ToolbarWindow* win = (ToolbarWindow*)aWindow; - float unifiedToolbarHeight = [win unifiedToolbarHeight]; - return inBoxRect.origin.x == 0 && - inBoxRect.size.width >= [win frame].size.width && - CGRectGetMaxY(inBoxRect) <= unifiedToolbarHeight; -} - -// By default, kCUIWidgetWindowFrame drawing draws rounded corners in the -// upper corners. Depending on the context type, it fills the background in -// the corners with black or leaves it transparent. Unfortunately, this corner -// rounding interacts poorly with the window corner masking we apply during -// titlebar drawing and results in small remnants of the corner background -// appearing at the rounded edge. -// So we draw square corners. -static void -DrawNativeTitlebarToolbarWithSquareCorners(CGContextRef aContext, const CGRect& aRect, - CGFloat aUnifiedHeight, BOOL aIsMain, BOOL aIsFlipped) -{ - // We extend the draw rect horizontally and clip away the rounded corners. - const CGFloat extendHorizontal = 10; - CGRect drawRect = CGRectInset(aRect, -extendHorizontal, 0); - CGContextSaveGState(aContext); - CGContextClipToRect(aContext, aRect); - - RenderWithCoreUI(drawRect, aContext, - [NSDictionary dictionaryWithObjectsAndKeys: - @"kCUIWidgetWindowFrame", @"widget", - @"regularwin", @"windowtype", - (aIsMain ? @"normal" : @"inactive"), @"state", - [NSNumber numberWithDouble:aUnifiedHeight], @"kCUIWindowFrameUnifiedTitleBarHeightKey", - [NSNumber numberWithBool:YES], @"kCUIWindowFrameDrawTitleSeparatorKey", - [NSNumber numberWithBool:aIsFlipped], @"is.flipped", - nil]); - - CGContextRestoreGState(aContext); -} - -void -nsNativeThemeCocoa::DrawUnifiedToolbar(CGContextRef cgContext, const HIRect& inBoxRect, - NSWindow* aWindow) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - CGContextSaveGState(cgContext); - CGContextClipToRect(cgContext, inBoxRect); - - CGFloat unifiedHeight = std::max([(ToolbarWindow*)aWindow unifiedToolbarHeight], - inBoxRect.size.height); - BOOL isMain = [aWindow isMainWindow]; - CGFloat titlebarHeight = unifiedHeight - inBoxRect.size.height; - CGRect drawRect = CGRectMake(inBoxRect.origin.x, inBoxRect.origin.y - titlebarHeight, - inBoxRect.size.width, inBoxRect.size.height + titlebarHeight); - DrawNativeTitlebarToolbarWithSquareCorners(cgContext, drawRect, unifiedHeight, isMain, YES); - - CGContextRestoreGState(cgContext); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void -nsNativeThemeCocoa::DrawStatusBar(CGContextRef cgContext, const HIRect& inBoxRect, - nsIFrame *aFrame) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (inBoxRect.size.height < 2.0f) - return; - - CGContextSaveGState(cgContext); - CGContextClipToRect(cgContext, inBoxRect); - - // kCUIWidgetWindowFrame draws a complete window frame with both title bar - // and bottom bar. We only want the bottom bar, so we extend the draw rect - // upwards to make space for the title bar, and then we clip it away. - CGRect drawRect = inBoxRect; - const int extendUpwards = 40; - drawRect.origin.y -= extendUpwards; - drawRect.size.height += extendUpwards; - RenderWithCoreUI(drawRect, cgContext, - [NSDictionary dictionaryWithObjectsAndKeys: - @"kCUIWidgetWindowFrame", @"widget", - @"regularwin", @"windowtype", - (IsActive(aFrame, YES) ? @"normal" : @"inactive"), @"state", - [NSNumber numberWithInt:inBoxRect.size.height], @"kCUIWindowFrameBottomBarHeightKey", - [NSNumber numberWithBool:YES], @"kCUIWindowFrameDrawBottomBarSeparatorKey", - [NSNumber numberWithBool:YES], @"is.flipped", - nil]); - - CGContextRestoreGState(cgContext); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void -nsNativeThemeCocoa::DrawNativeTitlebar(CGContextRef aContext, CGRect aTitlebarRect, - CGFloat aUnifiedHeight, BOOL aIsMain, BOOL aIsFlipped) -{ - CGFloat unifiedHeight = std::max(aUnifiedHeight, aTitlebarRect.size.height); - DrawNativeTitlebarToolbarWithSquareCorners(aContext, aTitlebarRect, unifiedHeight, aIsMain, aIsFlipped); -} - -static void -RenderResizer(CGContextRef cgContext, const HIRect& aRenderRect, void* aData) -{ - HIThemeGrowBoxDrawInfo* drawInfo = (HIThemeGrowBoxDrawInfo*)aData; - HIThemeDrawGrowBox(&CGPointZero, drawInfo, cgContext, kHIThemeOrientationNormal); -} - -void -nsNativeThemeCocoa::DrawResizer(CGContextRef cgContext, const HIRect& aRect, - nsIFrame *aFrame) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - HIThemeGrowBoxDrawInfo drawInfo; - drawInfo.version = 0; - drawInfo.state = kThemeStateActive; - drawInfo.kind = kHIThemeGrowBoxKindNormal; - drawInfo.direction = kThemeGrowRight | kThemeGrowDown; - drawInfo.size = kHIThemeGrowBoxSizeNormal; - - RenderTransformedHIThemeControl(cgContext, aRect, RenderResizer, &drawInfo, - IsFrameRTL(aFrame)); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -static void -DrawVibrancyBackground(CGContextRef cgContext, CGRect inBoxRect, - nsIFrame* aFrame, nsITheme::ThemeGeometryType aThemeGeometryType, - int aCornerRadiusIfOpaque = 0) -{ - ChildView* childView = ChildViewForFrame(aFrame); - if (childView) { - NSRect rect = NSRectFromCGRect(inBoxRect); - NSGraphicsContext* savedContext = [NSGraphicsContext currentContext]; - [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:cgContext flipped:YES]]; - [NSGraphicsContext saveGraphicsState]; - - NSColor* fillColor = [childView vibrancyFillColorForThemeGeometryType:aThemeGeometryType]; - if ([fillColor alphaComponent] == 1.0 && aCornerRadiusIfOpaque > 0) { - // The fillColor being opaque means that the system-wide pref "reduce - // transparency" is set. In that scenario, we still go through all the - // vibrancy rendering paths (VibrancyManager::SystemSupportsVibrancy() - // will still return true), but the result just won't look "vibrant". - // However, there's one unfortunate change of behavior that this pref - // has: It stops the window server from applying window masks. We use - // a window mask to get rounded corners on menus. So since the mask - // doesn't work in "reduce vibrancy" mode, we need to do our own rounded - // corner clipping here. - [[NSBezierPath bezierPathWithRoundedRect:rect - xRadius:aCornerRadiusIfOpaque - yRadius:aCornerRadiusIfOpaque] addClip]; - } - - [fillColor set]; - NSRectFill(rect); - - [NSGraphicsContext restoreGraphicsState]; - [NSGraphicsContext setCurrentContext:savedContext]; - } -} - -bool -nsNativeThemeCocoa::IsParentScrollbarRolledOver(nsIFrame* aFrame) -{ - nsIFrame* scrollbarFrame = GetParentScrollbarFrame(aFrame); - return nsLookAndFeel::UseOverlayScrollbars() - ? CheckBooleanAttr(scrollbarFrame, nsGkAtoms::hover) - : GetContentState(scrollbarFrame, NS_THEME_NONE).HasState(NS_EVENT_STATE_HOVER); -} - -static bool -IsHiDPIContext(nsPresContext* aContext) -{ - return nsPresContext::AppUnitsPerCSSPixel() >= - 2 * aContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom(); -} - -static bool -IsScrollbarWidthThin(nsIFrame* aFrame) -{ - return aFrame->StyleUserInterface()->mScrollbarWidth == StyleScrollbarWidth::Thin; -} - -NS_IMETHODIMP -nsNativeThemeCocoa::DrawWidgetBackground(nsRenderingContext* aContext, - nsIFrame* aFrame, - uint8_t aWidgetType, - const nsRect& aRect, - const nsRect& aDirtyRect) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - DrawTarget& aDrawTarget = *aContext->GetDrawTarget(); - - // setup to draw into the correct port - int32_t p2a = aFrame->PresContext()->AppUnitsPerDevPixel(); - - gfx::Rect nativeDirtyRect = NSRectToRect(aDirtyRect, p2a); - gfxRect nativeWidgetRect(aRect.x, aRect.y, aRect.width, aRect.height); - nativeWidgetRect.ScaleInverse(gfxFloat(p2a)); - float nativeWidgetHeight = round(nativeWidgetRect.Height()); - nativeWidgetRect.Round(); - if (nativeWidgetRect.IsEmpty()) - return NS_OK; // Don't attempt to draw invisible widgets. - - AutoRestoreTransform autoRestoreTransform(&aDrawTarget); - - bool hidpi = IsHiDPIContext(aFrame->PresContext()); - if (hidpi) { - // Use high-resolution drawing. - nativeWidgetRect.Scale(0.5f); - nativeWidgetHeight *= 0.5f; - nativeDirtyRect.Scale(0.5f); - aDrawTarget.SetTransform(aDrawTarget.GetTransform().PreScale(2.0f, 2.0f)); - } - - gfxQuartzNativeDrawing nativeDrawing(aDrawTarget, nativeDirtyRect); - - CGContextRef cgContext = nativeDrawing.BeginNativeDrawing(); - if (cgContext == nullptr) { - // The Quartz surface handles 0x0 surfaces by internally - // making all operations no-ops; there's no cgcontext created for them. - // Unfortunately, this means that callers that want to render - // directly to the CGContext need to be aware of this quirk. - return NS_OK; - } - - if (hidpi) { - // Set the context's "base transform" to in order to get correctly-sized focus rings. - CGContextSetBaseCTM(cgContext, CGAffineTransformMakeScale(2, 2)); - } - -#if 0 - if (1 /*aWidgetType == NS_THEME_TEXTFIELD*/) { - fprintf(stderr, "Native theme drawing widget %d [%p] dis:%d in rect [%d %d %d %d]\n", - aWidgetType, aFrame, IsDisabled(aFrame), aRect.x, aRect.y, aRect.width, aRect.height); - fprintf(stderr, "Cairo matrix: [%f %f %f %f %f %f]\n", - mat._11, mat._12, mat._21, mat._22, mat._31, mat._32); - fprintf(stderr, "Native theme xform[0]: [%f %f %f %f %f %f]\n", - mm0.a, mm0.b, mm0.c, mm0.d, mm0.tx, mm0.ty); - CGAffineTransform mm = CGContextGetCTM(cgContext); - fprintf(stderr, "Native theme xform[1]: [%f %f %f %f %f %f]\n", - mm.a, mm.b, mm.c, mm.d, mm.tx, mm.ty); - } -#endif - - CGRect macRect = CGRectMake(nativeWidgetRect.X(), nativeWidgetRect.Y(), - nativeWidgetRect.Width(), nativeWidgetRect.Height()); - -#if 0 - fprintf(stderr, " --> macRect %f %f %f %f\n", - macRect.origin.x, macRect.origin.y, macRect.size.width, macRect.size.height); - CGRect bounds = CGContextGetClipBoundingBox(cgContext); - fprintf(stderr, " --> clip bounds: %f %f %f %f\n", - bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height); - - //CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 1.0, 0.1); - //CGContextFillRect(cgContext, bounds); -#endif - - EventStates eventState = GetContentState(aFrame, aWidgetType); - - switch (aWidgetType) { - case NS_THEME_DIALOG: { - if (IsWindowSheet(aFrame)) { - if (VibrancyManager::SystemSupportsVibrancy()) { - ThemeGeometryType type = ThemeGeometryTypeForWidget(aFrame, aWidgetType); - DrawVibrancyBackground(cgContext, macRect, aFrame, type); - } else { - HIThemeSetFill(kThemeBrushSheetBackgroundTransparent, NULL, cgContext, HITHEME_ORIENTATION); - CGContextFillRect(cgContext, macRect); - } - } else { - HIThemeSetFill(kThemeBrushDialogBackgroundActive, NULL, cgContext, HITHEME_ORIENTATION); - CGContextFillRect(cgContext, macRect); - } - - } - break; - - case NS_THEME_MENUPOPUP: - if (VibrancyManager::SystemSupportsVibrancy()) { - DrawVibrancyBackground(cgContext, macRect, aFrame, eThemeGeometryTypeMenu, 4); - } else { - HIThemeMenuDrawInfo mdi; - memset(&mdi, 0, sizeof(mdi)); - mdi.version = 0; - mdi.menuType = IsDisabled(aFrame, eventState) ? - static_cast(kThemeMenuTypeInactive) : - static_cast(kThemeMenuTypePopUp); - - bool isLeftOfParent = false; - if (IsSubmenu(aFrame, &isLeftOfParent) && !isLeftOfParent) { - mdi.menuType = kThemeMenuTypeHierarchical; - } - - // The rounded corners draw outside the frame. - CGRect deflatedRect = CGRectMake(macRect.origin.x, macRect.origin.y + 4, - macRect.size.width, macRect.size.height - 8); - HIThemeDrawMenuBackground(&deflatedRect, &mdi, cgContext, HITHEME_ORIENTATION); - } - break; - - case NS_THEME_MENUARROW: { - bool isRTL = IsFrameRTL(aFrame); - DrawMenuIcon(cgContext, macRect, eventState, aFrame, kMenuarrowSize, - isRTL ? kMenuarrowLeftImage : kMenuarrowRightImage, true); - } - break; - - case NS_THEME_MENUITEM: - case NS_THEME_CHECKMENUITEM: { - if (VibrancyManager::SystemSupportsVibrancy()) { - ThemeGeometryType type = ThemeGeometryTypeForWidget(aFrame, aWidgetType); - DrawVibrancyBackground(cgContext, macRect, aFrame, type); - } else { - bool isDisabled = IsDisabled(aFrame, eventState); - bool isSelected = !isDisabled && CheckBooleanAttr(aFrame, nsGkAtoms::menuactive); - // maybe use kThemeMenuItemHierBackground or PopUpBackground instead of just Plain? - HIThemeMenuItemDrawInfo drawInfo; - memset(&drawInfo, 0, sizeof(drawInfo)); - drawInfo.version = 0; - drawInfo.itemType = kThemeMenuItemPlain; - drawInfo.state = (isDisabled ? - static_cast(kThemeMenuDisabled) : - isSelected ? - static_cast(kThemeMenuSelected) : - static_cast(kThemeMenuActive)); - - // XXX pass in the menu rect instead of always using the item rect - HIRect ignored; - HIThemeDrawMenuItem(&macRect, &macRect, &drawInfo, cgContext, HITHEME_ORIENTATION, &ignored); - } - - if (aWidgetType == NS_THEME_CHECKMENUITEM) { - DrawMenuIcon(cgContext, macRect, eventState, aFrame, kCheckmarkSize, kCheckmarkImage, false); - } - } - break; - - case NS_THEME_MENUSEPARATOR: { - // Workaround for visual artifacts issues with - // HIThemeDrawMenuSeparator on macOS Big Sur. - if (nsCocoaFeatures::OnBigSurOrLater()) { - CGRect separatorRect = macRect; - separatorRect.size.height = 1; - separatorRect.size.width -= 42; - separatorRect.origin.x += 21; - // Use a gray color similar to the native separator - CGContextSetRGBFillColor(cgContext, 0.816, 0.816, 0.816, 1.0); - CGContextFillRect(cgContext, separatorRect); - } - else - { - ThemeMenuState menuState; - if (IsDisabled(aFrame, eventState)) { - menuState = kThemeMenuDisabled; - } - else { - menuState = CheckBooleanAttr(aFrame, nsGkAtoms::menuactive) ? - kThemeMenuSelected : kThemeMenuActive; - } - HIThemeMenuItemDrawInfo midi = { 0, kThemeMenuItemPlain, menuState }; - HIThemeDrawMenuSeparator(&macRect, &macRect, &midi, cgContext, HITHEME_ORIENTATION); - } - } - break; - - case NS_THEME_BUTTON_ARROW_UP: - case NS_THEME_BUTTON_ARROW_DOWN: - DrawMenuIcon(cgContext, macRect, eventState, aFrame, kMenuScrollArrowSize, - aWidgetType == NS_THEME_BUTTON_ARROW_UP ? - kMenuUpScrollArrowImage : kMenuDownScrollArrowImage, true); - break; - - case NS_THEME_TOOLTIP: - if (VibrancyManager::SystemSupportsVibrancy()) { - DrawVibrancyBackground(cgContext, macRect, aFrame, ThemeGeometryTypeForWidget(aFrame, aWidgetType)); - } else { - CGContextSetRGBFillColor(cgContext, 0.996, 1.000, 0.792, 0.950); - CGContextFillRect(cgContext, macRect); - } - break; - - case NS_THEME_CHECKBOX: - case NS_THEME_RADIO: { - bool isCheckbox = (aWidgetType == NS_THEME_CHECKBOX); - DrawCheckboxOrRadio(cgContext, isCheckbox, macRect, GetCheckedOrSelected(aFrame, !isCheckbox), - eventState, aFrame); - } - break; - - case NS_THEME_BUTTON: - if (IsDefaultButton(aFrame)) { - // Check whether the default button is in a document that does not - // match the :-moz-window-inactive pseudoclass. This activeness check - // is different from the other "active window" checks in this file - // because we absolutely need the button's default button appearance to - // be in sync with its text color, and the text color is changed by - // such a :-moz-window-inactive rule. (That's because on 10.10 and up, - // default buttons in active windows have blue background and white - // text, and default buttons in inactive windows have white background - // and black text.) - EventStates docState = aFrame->GetContent()->OwnerDoc()->GetDocumentState(); - bool isInActiveWindow = !docState.HasState(NS_DOCUMENT_STATE_WINDOW_INACTIVE); - if (!IsDisabled(aFrame, eventState) && isInActiveWindow && - !QueueAnimatedContentForRefresh(aFrame->GetContent(), 10)) { - NS_WARNING("Unable to animate button!"); - } - DrawButton(cgContext, kThemePushButton, macRect, isInActiveWindow, - kThemeButtonOff, kThemeAdornmentNone, eventState, aFrame); - } else if (IsButtonTypeMenu(aFrame)) { - DrawDropdown(cgContext, macRect, eventState, aWidgetType, aFrame); - } else { - DrawPushButton(cgContext, macRect, eventState, aWidgetType, aFrame, - nativeWidgetHeight); - } - break; - - case NS_THEME_FOCUS_OUTLINE: - DrawFocusOutline(cgContext, macRect, eventState, aWidgetType, aFrame); - break; - - case NS_THEME_MAC_HELP_BUTTON: - case NS_THEME_MAC_DISCLOSURE_BUTTON_OPEN: - case NS_THEME_MAC_DISCLOSURE_BUTTON_CLOSED: - DrawPushButton(cgContext, macRect, eventState, aWidgetType, aFrame, - nativeWidgetHeight); - break; - - case NS_THEME_BUTTON_BEVEL: - DrawButton(cgContext, kThemeMediumBevelButton, macRect, - IsDefaultButton(aFrame), kThemeButtonOff, kThemeAdornmentNone, - eventState, aFrame); - break; - - case NS_THEME_SPINNER: { - nsIContent* content = aFrame->GetContent(); - if (content->IsHTMLElement()) { - // In HTML the theming for the spin buttons is drawn individually into - // their own backgrounds instead of being drawn into the background of - // their spinner parent as it is for XUL. - break; - } - ThemeDrawState state = kThemeStateActive; - if (content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::state, - NS_LITERAL_STRING("up"), eCaseMatters)) { - state = kThemeStatePressedUp; - } - else if (content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::state, - NS_LITERAL_STRING("down"), eCaseMatters)) { - state = kThemeStatePressedDown; - } - - DrawSpinButtons(cgContext, kThemeIncDecButton, macRect, state, - kThemeAdornmentNone, eventState, aFrame); - } - break; - - case NS_THEME_SPINNER_UPBUTTON: - case NS_THEME_SPINNER_DOWNBUTTON: { - nsNumberControlFrame* numberControlFrame = - nsNumberControlFrame::GetNumberControlFrameForSpinButton(aFrame); - if (numberControlFrame) { - ThemeDrawState state = kThemeStateActive; - if (numberControlFrame->SpinnerUpButtonIsDepressed()) { - state = kThemeStatePressedUp; - } else if (numberControlFrame->SpinnerDownButtonIsDepressed()) { - state = kThemeStatePressedDown; - } - DrawSpinButton(cgContext, kThemeIncDecButtonMini, macRect, state, - kThemeAdornmentNone, eventState, aFrame, aWidgetType); - } - } - break; - - case NS_THEME_TOOLBARBUTTON: - DrawSegment(cgContext, macRect, eventState, aFrame, toolbarButtonRenderSettings); - break; - - case NS_THEME_SEPARATOR: { - HIThemeSeparatorDrawInfo sdi = { 0, kThemeStateActive }; - HIThemeDrawSeparator(&macRect, &sdi, cgContext, HITHEME_ORIENTATION); - } - break; - - case NS_THEME_TOOLBAR: { - NSWindow* win = NativeWindowForFrame(aFrame); - if (ToolbarCanBeUnified(cgContext, macRect, win)) { - DrawUnifiedToolbar(cgContext, macRect, win); - break; - } - BOOL isMain = [win isMainWindow]; - CGRect drawRect = macRect; - - // top border - drawRect.size.height = 1.0f; - DrawNativeGreyColorInRect(cgContext, toolbarTopBorderGrey, drawRect, isMain); - - // background - drawRect.origin.y += drawRect.size.height; - drawRect.size.height = macRect.size.height - 2.0f; - DrawNativeGreyColorInRect(cgContext, toolbarFillGrey, drawRect, isMain); - - // bottom border - drawRect.origin.y += drawRect.size.height; - drawRect.size.height = 1.0f; - DrawNativeGreyColorInRect(cgContext, toolbarBottomBorderGrey, drawRect, isMain); - } - break; - - case NS_THEME_WINDOW_TITLEBAR: { - NSWindow* win = NativeWindowForFrame(aFrame); - BOOL isMain = [win isMainWindow]; - float unifiedToolbarHeight = [win isKindOfClass:[ToolbarWindow class]] ? - [(ToolbarWindow*)win unifiedToolbarHeight] : macRect.size.height; - DrawNativeTitlebar(cgContext, macRect, unifiedToolbarHeight, isMain, YES); - } - break; - - case NS_THEME_STATUSBAR: - DrawStatusBar(cgContext, macRect, aFrame); - break; - - case NS_THEME_MENULIST: - case NS_THEME_MENULIST_TEXTFIELD: - DrawDropdown(cgContext, macRect, eventState, aWidgetType, aFrame); - break; - - case NS_THEME_MENULIST_BUTTON: - DrawButton(cgContext, kThemeArrowButton, macRect, false, kThemeButtonOn, - kThemeAdornmentArrowDownArrow, eventState, aFrame); - break; - - case NS_THEME_GROUPBOX: { - HIThemeGroupBoxDrawInfo gdi = { 0, kThemeStateActive, kHIThemeGroupBoxKindPrimary }; - HIThemeDrawGroupBox(&macRect, &gdi, cgContext, HITHEME_ORIENTATION); - break; - } - - case NS_THEME_TEXTFIELD: - case NS_THEME_NUMBER_INPUT: - // HIThemeSetFill is not available on 10.3 - CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 1.0, 1.0); - CGContextFillRect(cgContext, macRect); - - // XUL textboxes set the native appearance on the containing box, while - // concrete focus is set on the html:input element within it. We can - // though, check the focused attribute of xul textboxes in this case. - // On Mac, focus rings are always shown for textboxes, so we do not need - // to check the window's focus ring state here - if (aFrame->GetContent()->IsXULElement() && IsFocused(aFrame)) { - eventState |= NS_EVENT_STATE_FOCUS; - } - - DrawFrame(cgContext, kHIThemeFrameTextFieldSquare, macRect, - IsDisabled(aFrame, eventState) || IsReadOnly(aFrame), eventState); - break; - - case NS_THEME_SEARCHFIELD: - DrawSearchField(cgContext, macRect, aFrame, eventState); - break; - - case NS_THEME_PROGRESSBAR: - { - double value = GetProgressValue(aFrame); - double maxValue = GetProgressMaxValue(aFrame); - // Don't request repaints for scrollbars at 100% because those don't animate. - if (value < maxValue) { - if (!QueueAnimatedContentForRefresh(aFrame->GetContent(), 30)) { - NS_WARNING("Unable to animate progressbar!"); - } - } - DrawProgress(cgContext, macRect, IsIndeterminateProgress(aFrame, eventState), - !IsVerticalProgress(aFrame), - value, maxValue, aFrame); - break; - } - - case NS_THEME_PROGRESSBAR_VERTICAL: - DrawProgress(cgContext, macRect, IsIndeterminateProgress(aFrame, eventState), - false, GetProgressValue(aFrame), - GetProgressMaxValue(aFrame), aFrame); - break; - - case NS_THEME_METERBAR: - DrawMeter(cgContext, macRect, aFrame); - break; - - case NS_THEME_PROGRESSCHUNK: - case NS_THEME_PROGRESSCHUNK_VERTICAL: - case NS_THEME_METERCHUNK: - // Do nothing: progress and meter bars cases will draw chunks. - break; - - case NS_THEME_TREETWISTY: - DrawButton(cgContext, kThemeDisclosureButton, macRect, false, - kThemeDisclosureRight, kThemeAdornmentNone, eventState, aFrame); - break; - - case NS_THEME_TREETWISTYOPEN: - DrawButton(cgContext, kThemeDisclosureButton, macRect, false, - kThemeDisclosureDown, kThemeAdornmentNone, eventState, aFrame); - break; - - case NS_THEME_TREEHEADERCELL: { - TreeSortDirection sortDirection = GetTreeSortDirection(aFrame); - DrawButton(cgContext, kThemeListHeaderButton, macRect, false, - sortDirection == eTreeSortDirection_Natural ? kThemeButtonOff : kThemeButtonOn, - sortDirection == eTreeSortDirection_Ascending ? - kThemeAdornmentHeaderButtonSortUp : kThemeAdornmentNone, eventState, aFrame); - } - break; - - case NS_THEME_TREEITEM: - case NS_THEME_TREEVIEW: - // HIThemeSetFill is not available on 10.3 - // HIThemeSetFill(kThemeBrushWhite, NULL, cgContext, HITHEME_ORIENTATION); - CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 1.0, 1.0); - CGContextFillRect(cgContext, macRect); - break; - - case NS_THEME_TREEHEADER: - // do nothing, taken care of by individual header cells - case NS_THEME_TREEHEADERSORTARROW: - // do nothing, taken care of by treeview header - case NS_THEME_TREELINE: - // do nothing, these lines don't exist on macos - break; - - case NS_THEME_SCALE_HORIZONTAL: - case NS_THEME_SCALE_VERTICAL: { - int32_t curpos = CheckIntAttr(aFrame, nsGkAtoms::curpos, 0); - int32_t minpos = CheckIntAttr(aFrame, nsGkAtoms::minpos, 0); - int32_t maxpos = CheckIntAttr(aFrame, nsGkAtoms::maxpos, 100); - if (!maxpos) - maxpos = 100; - - bool reverse = aFrame->GetContent()-> - AttrValueIs(kNameSpaceID_None, nsGkAtoms::dir, - NS_LITERAL_STRING("reverse"), eCaseMatters); - DrawScale(cgContext, macRect, eventState, - (aWidgetType == NS_THEME_SCALE_VERTICAL), reverse, - curpos, minpos, maxpos, aFrame); - } - break; - - case NS_THEME_SCALETHUMB_HORIZONTAL: - case NS_THEME_SCALETHUMB_VERTICAL: - // do nothing, drawn by scale - break; - - case NS_THEME_RANGE: { - nsRangeFrame *rangeFrame = do_QueryFrame(aFrame); - if (!rangeFrame) { - break; - } - // DrawScale requires integer min, max and value. This is purely for - // drawing, so we normalize to a range 0-1000 here. - int32_t value = int32_t(rangeFrame->GetValueAsFractionOfRange() * 1000); - int32_t min = 0; - int32_t max = 1000; - bool isVertical = !IsRangeHorizontal(aFrame); - bool reverseDir = isVertical || rangeFrame->IsRightToLeft(); - DrawScale(cgContext, macRect, eventState, isVertical, reverseDir, - value, min, max, aFrame); - break; - } - - case NS_THEME_SCROLLBAR_SMALL: - case NS_THEME_SCROLLBAR: - break; - case NS_THEME_SCROLLBARTHUMB_VERTICAL: - case NS_THEME_SCROLLBARTHUMB_HORIZONTAL: { - BOOL isOverlay = nsLookAndFeel::UseOverlayScrollbars(); - BOOL isHorizontal = (aWidgetType == NS_THEME_SCROLLBARTHUMB_HORIZONTAL); - BOOL isRolledOver = IsParentScrollbarRolledOver(aFrame); - nsIFrame* scrollbarFrame = GetParentScrollbarFrame(aFrame); - bool isSmall = (scrollbarFrame && scrollbarFrame->StyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL); - if (isOverlay && !isRolledOver) { - if (isHorizontal) { - macRect.origin.y += 4; - macRect.size.height -= 4; - } else { - if (aFrame->StyleVisibility()->mDirection != - NS_STYLE_DIRECTION_RTL) { - macRect.origin.x += 4; - } - macRect.size.width -= 4; - } - } - const BOOL isOnTopOfDarkBackground = IsDarkBackground(aFrame); - NSMutableDictionary* options = [NSMutableDictionary dictionaryWithObjectsAndKeys: - (isOverlay ? @"kCUIWidgetOverlayScrollBar" : @"scrollbar"), @"widget", - (isSmall ? @"small" : @"regular"), @"size", - (isHorizontal ? @"kCUIOrientHorizontal" : @"kCUIOrientVertical"), @"kCUIOrientationKey", - (isOverlay && isOnTopOfDarkBackground ? @"kCUIVariantWhite" : @""), @"kCUIVariantKey", - [NSNumber numberWithBool:YES], @"indiconly", - [NSNumber numberWithBool:YES], @"kCUIThumbProportionKey", - [NSNumber numberWithBool:YES], @"is.flipped", - nil]; - if (isRolledOver) { - [options setObject:@"rollover" forKey:@"state"]; - } - RenderWithCoreUI(macRect, cgContext, options, true); - } - break; - - case NS_THEME_SCROLLBARBUTTON_UP: - case NS_THEME_SCROLLBARBUTTON_LEFT: -#if SCROLLBARS_VISUAL_DEBUG - CGContextSetRGBFillColor(cgContext, 1.0, 0, 0, 0.6); - CGContextFillRect(cgContext, macRect); -#endif - break; - case NS_THEME_SCROLLBARBUTTON_DOWN: - case NS_THEME_SCROLLBARBUTTON_RIGHT: -#if SCROLLBARS_VISUAL_DEBUG - CGContextSetRGBFillColor(cgContext, 0, 1.0, 0, 0.6); - CGContextFillRect(cgContext, macRect); -#endif - break; - case NS_THEME_SCROLLBARTRACK_HORIZONTAL: - case NS_THEME_SCROLLBARTRACK_VERTICAL: { - BOOL isOverlay = nsLookAndFeel::UseOverlayScrollbars(); - if (!isOverlay || IsParentScrollbarRolledOver(aFrame)) { - BOOL isHorizontal = (aWidgetType == NS_THEME_SCROLLBARTRACK_HORIZONTAL); - nsIFrame* scrollbarFrame = GetParentScrollbarFrame(aFrame); - bool isSmall = (scrollbarFrame && scrollbarFrame->StyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL); - const BOOL isOnTopOfDarkBackground = IsDarkBackground(aFrame); - RenderWithCoreUI(macRect, cgContext, - [NSDictionary dictionaryWithObjectsAndKeys: - (isOverlay ? @"kCUIWidgetOverlayScrollBar" : @"scrollbar"), @"widget", - (isSmall ? @"small" : @"regular"), @"size", - (isHorizontal ? @"kCUIOrientHorizontal" : @"kCUIOrientVertical"), @"kCUIOrientationKey", - (isOnTopOfDarkBackground ? @"kCUIVariantWhite" : @""), @"kCUIVariantKey", - [NSNumber numberWithBool:YES], @"noindicator", - [NSNumber numberWithBool:YES], @"kCUIThumbProportionKey", - [NSNumber numberWithBool:YES], @"is.flipped", - nil], - true); - } - } - break; - - case NS_THEME_TEXTFIELD_MULTILINE: { - // we have to draw this by hand because there is no HITheme value for it - CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 1.0, 1.0); - - CGContextFillRect(cgContext, macRect); - - // #737373 for the top border, #999999 for the rest. - float x = macRect.origin.x, y = macRect.origin.y; - float w = macRect.size.width, h = macRect.size.height; - CGContextSetRGBFillColor(cgContext, 0.4510, 0.4510, 0.4510, 1.0); - CGContextFillRect(cgContext, CGRectMake(x, y, w, 1)); - CGContextSetRGBFillColor(cgContext, 0.6, 0.6, 0.6, 1.0); - CGContextFillRect(cgContext, CGRectMake(x, y + 1, 1, h - 1)); - CGContextFillRect(cgContext, CGRectMake(x + w - 1, y + 1, 1, h - 1)); - CGContextFillRect(cgContext, CGRectMake(x + 1, y + h - 1, w - 2, 1)); - - // draw a focus ring - if (eventState.HasState(NS_EVENT_STATE_FOCUS)) { - NSGraphicsContext* savedContext = [NSGraphicsContext currentContext]; - [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:cgContext flipped:YES]]; - CGContextSaveGState(cgContext); - NSSetFocusRingStyle(NSFocusRingOnly); - NSRectFill(NSRectFromCGRect(macRect)); - CGContextRestoreGState(cgContext); - [NSGraphicsContext setCurrentContext:savedContext]; - } - } - break; - - case NS_THEME_LISTBOX: { - // We have to draw this by hand because kHIThemeFrameListBox drawing - // is buggy on 10.5, see bug 579259. - CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 1.0, 1.0); - CGContextFillRect(cgContext, macRect); - - // #8E8E8E for the top border, #BEBEBE for the rest. - float x = macRect.origin.x, y = macRect.origin.y; - float w = macRect.size.width, h = macRect.size.height; - CGContextSetRGBFillColor(cgContext, 0.557, 0.557, 0.557, 1.0); - CGContextFillRect(cgContext, CGRectMake(x, y, w, 1)); - CGContextSetRGBFillColor(cgContext, 0.745, 0.745, 0.745, 1.0); - CGContextFillRect(cgContext, CGRectMake(x, y + 1, 1, h - 1)); - CGContextFillRect(cgContext, CGRectMake(x + w - 1, y + 1, 1, h - 1)); - CGContextFillRect(cgContext, CGRectMake(x + 1, y + h - 1, w - 2, 1)); - } - break; - - case NS_THEME_MAC_SOURCE_LIST: { - if (VibrancyManager::SystemSupportsVibrancy()) { - ThemeGeometryType type = ThemeGeometryTypeForWidget(aFrame, aWidgetType); - DrawVibrancyBackground(cgContext, macRect, aFrame, type); - } else { - CGGradientRef backgroundGradient; - CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB(); - CGFloat activeGradientColors[8] = { 0.9137, 0.9294, 0.9490, 1.0, - 0.8196, 0.8471, 0.8784, 1.0 }; - CGFloat inactiveGradientColors[8] = { 0.9686, 0.9686, 0.9686, 1.0, - 0.9216, 0.9216, 0.9216, 1.0 }; - CGPoint start = macRect.origin; - CGPoint end = CGPointMake(macRect.origin.x, - macRect.origin.y + macRect.size.height); - BOOL isActive = FrameIsInActiveWindow(aFrame); - backgroundGradient = - CGGradientCreateWithColorComponents(rgb, isActive ? activeGradientColors - : inactiveGradientColors, NULL, 2); - CGContextDrawLinearGradient(cgContext, backgroundGradient, start, end, 0); - CGGradientRelease(backgroundGradient); - CGColorSpaceRelease(rgb); - } - } - break; - - case NS_THEME_MAC_SOURCE_LIST_SELECTION: - case NS_THEME_MAC_ACTIVE_SOURCE_LIST_SELECTION: { - // If we're in XUL tree, we need to rely on the source list's clear - // background display item. If we cleared the background behind the - // selections, the source list would not pick up the right font - // smoothing background. So, to simplify a bit, we only support vibrancy - // if we're in a source list. - if (VibrancyManager::SystemSupportsVibrancy() && IsInSourceList(aFrame)) { - ThemeGeometryType type = ThemeGeometryTypeForWidget(aFrame, aWidgetType); - DrawVibrancyBackground(cgContext, macRect, aFrame, type); - } else { - BOOL isActiveSelection = - aWidgetType == NS_THEME_MAC_ACTIVE_SOURCE_LIST_SELECTION; - RenderWithCoreUI(macRect, cgContext, - [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithBool:isActiveSelection], @"focus", - [NSNumber numberWithBool:YES], @"is.flipped", - @"kCUIVariantGradientSideBarSelection", @"kCUIVariantKey", - (FrameIsInActiveWindow(aFrame) ? @"normal" : @"inactive"), @"state", - @"gradient", @"widget", - nil]); - } - } - break; - - case NS_THEME_TAB: - DrawSegment(cgContext, macRect, eventState, aFrame, tabRenderSettings); - break; - - case NS_THEME_TABPANELS: - DrawTabPanel(cgContext, macRect, aFrame); - break; - - case NS_THEME_RESIZER: - DrawResizer(cgContext, macRect, aFrame); - break; - - case NS_THEME_MAC_VIBRANCY_LIGHT: - case NS_THEME_MAC_VIBRANCY_DARK: { - ThemeGeometryType type = ThemeGeometryTypeForWidget(aFrame, aWidgetType); - DrawVibrancyBackground(cgContext, macRect, aFrame, type); - break; - } - } - - if (hidpi) { - // Reset the base CTM. - CGContextSetBaseCTM(cgContext, CGAffineTransformIdentity); - } - - nativeDrawing.EndNativeDrawing(); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -nsIntMargin -nsNativeThemeCocoa::DirectionAwareMargin(const nsIntMargin& aMargin, - nsIFrame* aFrame) -{ - // Assuming aMargin was originally specified for a horizontal LTR context, - // reinterpret the values as logical, and then map to physical coords - // according to aFrame's actual writing mode. - WritingMode wm = aFrame->GetWritingMode(); - nsMargin m = LogicalMargin(wm, aMargin.top, aMargin.right, aMargin.bottom, - aMargin.left).GetPhysicalMargin(wm); - return nsIntMargin(m.top, m.right, m.bottom, m.left); -} - -static const nsIntMargin kAquaDropdownBorder(1, 22, 2, 5); -static const nsIntMargin kAquaComboboxBorder(3, 20, 3, 4); -static const nsIntMargin kAquaSearchfieldBorder(3, 5, 2, 19); - -NS_IMETHODIMP -nsNativeThemeCocoa::GetWidgetBorder(nsDeviceContext* aContext, - nsIFrame* aFrame, - uint8_t aWidgetType, - nsIntMargin* aResult) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - aResult->SizeTo(0, 0, 0, 0); - - switch (aWidgetType) { - case NS_THEME_BUTTON: - { - if (IsButtonTypeMenu(aFrame)) { - *aResult = DirectionAwareMargin(kAquaDropdownBorder, aFrame); - } else { - *aResult = DirectionAwareMargin(nsIntMargin(1, 7, 3, 7), aFrame); - } - break; - } - - case NS_THEME_TOOLBARBUTTON: - { - *aResult = DirectionAwareMargin(nsIntMargin(1, 4, 1, 4), aFrame); - break; - } - - case NS_THEME_CHECKBOX: - case NS_THEME_RADIO: - { - // nsFormControlFrame::GetIntrinsicWidth and nsFormControlFrame::GetIntrinsicHeight - // assume a border width of 2px. - aResult->SizeTo(2, 2, 2, 2); - break; - } - - case NS_THEME_MENULIST: - case NS_THEME_MENULIST_BUTTON: - *aResult = DirectionAwareMargin(kAquaDropdownBorder, aFrame); - break; - - case NS_THEME_MENULIST_TEXTFIELD: - *aResult = DirectionAwareMargin(kAquaComboboxBorder, aFrame); - break; - - case NS_THEME_NUMBER_INPUT: - case NS_THEME_TEXTFIELD: - { - SInt32 frameOutset = 0; - ::GetThemeMetric(kThemeMetricEditTextFrameOutset, &frameOutset); - - SInt32 textPadding = 0; - ::GetThemeMetric(kThemeMetricEditTextWhitespace, &textPadding); - - frameOutset += textPadding; - - aResult->SizeTo(frameOutset, frameOutset, frameOutset, frameOutset); - break; - } - - case NS_THEME_TEXTFIELD_MULTILINE: - aResult->SizeTo(1, 1, 1, 1); - break; - - case NS_THEME_SEARCHFIELD: - *aResult = DirectionAwareMargin(kAquaSearchfieldBorder, aFrame); - break; - - case NS_THEME_LISTBOX: - { - SInt32 frameOutset = 0; - ::GetThemeMetric(kThemeMetricListBoxFrameOutset, &frameOutset); - aResult->SizeTo(frameOutset, frameOutset, frameOutset, frameOutset); - break; - } - - case NS_THEME_SCROLLBARTRACK_HORIZONTAL: - case NS_THEME_SCROLLBARTRACK_VERTICAL: - { - bool isHorizontal = (aWidgetType == NS_THEME_SCROLLBARTRACK_HORIZONTAL); - if (nsLookAndFeel::UseOverlayScrollbars()) { - if (!nsCocoaFeatures::OnYosemiteOrLater()) { - // Pre-10.10, we have to center the thumb rect in the middle of the - // scrollbar. Starting with 10.10, the expected rect for thumb - // rendering is the full width of the scrollbar. - if (isHorizontal) { - aResult->top = 2; - aResult->bottom = 1; - } else { - aResult->left = 2; - aResult->right = 1; - } - } - // Leave a bit of space at the start and the end on all OS X versions. - if (isHorizontal) { - aResult->left = 1; - aResult->right = 1; - } else { - aResult->top = 1; - aResult->bottom = 1; - } - } - - break; - } - - case NS_THEME_STATUSBAR: - aResult->SizeTo(1, 0, 0, 0); - break; - } - - if (IsHiDPIContext(aFrame->PresContext())) { - *aResult = *aResult + *aResult; // doubled - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -// Return false here to indicate that CSS padding values should be used. There is -// no reason to make a distinction between padding and border values, just specify -// whatever values you want in GetWidgetBorder and only use this to return true -// if you want to override CSS padding values. -bool -nsNativeThemeCocoa::GetWidgetPadding(nsDeviceContext* aContext, - nsIFrame* aFrame, - uint8_t aWidgetType, - nsIntMargin* aResult) -{ - // We don't want CSS padding being used for certain widgets. - // See bug 381639 for an example of why. - switch (aWidgetType) { - // Radios and checkboxes return a fixed size in GetMinimumWidgetSize - // and have a meaningful baseline, so they can't have - // author-specified padding. - case NS_THEME_CHECKBOX: - case NS_THEME_RADIO: - aResult->SizeTo(0, 0, 0, 0); - return true; - } - return false; -} - -bool -nsNativeThemeCocoa::GetWidgetOverflow(nsDeviceContext* aContext, nsIFrame* aFrame, - uint8_t aWidgetType, nsRect* aOverflowRect) -{ - int32_t p2a = aFrame->PresContext()->AppUnitsPerDevPixel(); - switch (aWidgetType) { - case NS_THEME_BUTTON: - case NS_THEME_MAC_DISCLOSURE_BUTTON_OPEN: - case NS_THEME_MAC_DISCLOSURE_BUTTON_CLOSED: - case NS_THEME_MAC_HELP_BUTTON: - case NS_THEME_TOOLBARBUTTON: - case NS_THEME_NUMBER_INPUT: - case NS_THEME_TEXTFIELD: - case NS_THEME_TEXTFIELD_MULTILINE: - case NS_THEME_SEARCHFIELD: - case NS_THEME_LISTBOX: - case NS_THEME_MENULIST: - case NS_THEME_MENULIST_BUTTON: - case NS_THEME_MENULIST_TEXTFIELD: - case NS_THEME_CHECKBOX: - case NS_THEME_RADIO: - case NS_THEME_TAB: - { - // We assume that the above widgets can draw a focus ring that will be less than - // or equal to 4 pixels thick. - nsIntMargin extraSize = nsIntMargin(kMaxFocusRingWidth, - kMaxFocusRingWidth, - kMaxFocusRingWidth, - kMaxFocusRingWidth); - nsMargin m(NSIntPixelsToAppUnits(extraSize.top, p2a), - NSIntPixelsToAppUnits(extraSize.right, p2a), - NSIntPixelsToAppUnits(extraSize.bottom, p2a), - NSIntPixelsToAppUnits(extraSize.left, p2a)); - aOverflowRect->Inflate(m); - return true; - } - case NS_THEME_PROGRESSBAR: - { - // Progress bars draw a 2 pixel white shadow under their progress indicators - nsMargin m(0, 0, NSIntPixelsToAppUnits(2, p2a), 0); - aOverflowRect->Inflate(m); - return true; - } - case NS_THEME_FOCUS_OUTLINE: - { - aOverflowRect->Inflate(NSIntPixelsToAppUnits(2, p2a)); - return true; - } - } - - return false; -} - -static const int32_t kRegularScrollbarThumbMinSize = 26; -static const int32_t kSmallScrollbarThumbMinSize = 26; - -NS_IMETHODIMP -nsNativeThemeCocoa::GetMinimumWidgetSize(nsPresContext* aPresContext, - nsIFrame* aFrame, - uint8_t aWidgetType, - LayoutDeviceIntSize* aResult, - bool* aIsOverridable) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - aResult->SizeTo(0,0); - *aIsOverridable = true; - - switch (aWidgetType) { - case NS_THEME_BUTTON: - { - aResult->SizeTo(pushButtonSettings.minimumSizes[miniControlSize].width, - pushButtonSettings.naturalSizes[miniControlSize].height); - break; - } - - case NS_THEME_BUTTON_ARROW_UP: - case NS_THEME_BUTTON_ARROW_DOWN: - { - aResult->SizeTo(kMenuScrollArrowSize.width, kMenuScrollArrowSize.height); - *aIsOverridable = false; - break; - } - - case NS_THEME_MENUARROW: - { - aResult->SizeTo(kMenuarrowSize.width, kMenuarrowSize.height); - *aIsOverridable = false; - break; - } - - case NS_THEME_MAC_DISCLOSURE_BUTTON_OPEN: - case NS_THEME_MAC_DISCLOSURE_BUTTON_CLOSED: - { - aResult->SizeTo(kDisclosureButtonSize.width, kDisclosureButtonSize.height); - *aIsOverridable = false; - break; - } - - case NS_THEME_MAC_HELP_BUTTON: - { - aResult->SizeTo(kHelpButtonSize.width, kHelpButtonSize.height); - *aIsOverridable = false; - break; - } - - case NS_THEME_TOOLBARBUTTON: - { - aResult->SizeTo(0, toolbarButtonHeights[miniControlSize]); - break; - } - - case NS_THEME_SPINNER: - case NS_THEME_SPINNER_UPBUTTON: - case NS_THEME_SPINNER_DOWNBUTTON: - { - SInt32 buttonHeight = 0, buttonWidth = 0; - if (aFrame->GetContent()->IsXULElement()) { - ::GetThemeMetric(kThemeMetricLittleArrowsWidth, &buttonWidth); - ::GetThemeMetric(kThemeMetricLittleArrowsHeight, &buttonHeight); - } else { - NSSize size = - spinnerSettings.minimumSizes[EnumSizeForCocoaSize(NSMiniControlSize)]; - buttonWidth = size.width; - buttonHeight = size.height; - if (aWidgetType != NS_THEME_SPINNER) { - // the buttons are half the height of the spinner - buttonHeight /= 2; - } - } - aResult->SizeTo(buttonWidth, buttonHeight); - *aIsOverridable = true; - break; - } - - case NS_THEME_MENULIST: - case NS_THEME_MENULIST_BUTTON: - { - SInt32 popupHeight = 0; - ::GetThemeMetric(kThemeMetricPopupButtonHeight, &popupHeight); - aResult->SizeTo(0, popupHeight); - break; - } - - case NS_THEME_NUMBER_INPUT: - case NS_THEME_TEXTFIELD: - case NS_THEME_TEXTFIELD_MULTILINE: - case NS_THEME_SEARCHFIELD: - { - // at minimum, we should be tall enough for 9pt text. - // I'm using hardcoded values here because the appearance manager - // values for the frame size are incorrect. - aResult->SizeTo(0, (2 + 2) /* top */ + 9 + (1 + 1) /* bottom */); - break; - } - - case NS_THEME_WINDOW_BUTTON_BOX: { - NSSize size = WindowButtonsSize(aFrame); - aResult->SizeTo(size.width, size.height); - *aIsOverridable = false; - break; - } - - case NS_THEME_MAC_FULLSCREEN_BUTTON: { - if ([NativeWindowForFrame(aFrame) respondsToSelector:@selector(toggleFullScreen:)] && - !nsCocoaFeatures::OnYosemiteOrLater()) { - // This value is hardcoded because it's needed before we can measure the - // position and size of the fullscreen button. - aResult->SizeTo(16, 17); - } - *aIsOverridable = false; - break; - } - - case NS_THEME_PROGRESSBAR: - { - SInt32 barHeight = 0; - ::GetThemeMetric(kThemeMetricNormalProgressBarThickness, &barHeight); - aResult->SizeTo(0, barHeight); - break; - } - - case NS_THEME_TREETWISTY: - case NS_THEME_TREETWISTYOPEN: - { - SInt32 twistyHeight = 0, twistyWidth = 0; - ::GetThemeMetric(kThemeMetricDisclosureButtonWidth, &twistyWidth); - ::GetThemeMetric(kThemeMetricDisclosureButtonHeight, &twistyHeight); - aResult->SizeTo(twistyWidth, twistyHeight); - *aIsOverridable = false; - break; - } - - case NS_THEME_TREEHEADER: - case NS_THEME_TREEHEADERCELL: - { - SInt32 headerHeight = 0; - ::GetThemeMetric(kThemeMetricListHeaderHeight, &headerHeight); - aResult->SizeTo(0, headerHeight - 1); // We don't need the top border. - break; - } - - case NS_THEME_TAB: - { - aResult->SizeTo(0, tabHeights[miniControlSize]); - break; - } - - case NS_THEME_RANGE: - { - // The Mac Appearance Manager API (the old API we're currently using) - // doesn't define constants to obtain a minimum size for sliders. We use - // the "thickness" of a slider that has default dimensions for both the - // minimum width and height to get something sane and so that paint - // invalidation works. - SInt32 size = 0; - if (IsRangeHorizontal(aFrame)) { - ::GetThemeMetric(kThemeMetricHSliderHeight, &size); - } else { - ::GetThemeMetric(kThemeMetricVSliderWidth, &size); - } - aResult->SizeTo(size, size); - *aIsOverridable = true; - break; - } - - case NS_THEME_RANGE_THUMB: - { - SInt32 width = 0; - SInt32 height = 0; - ::GetThemeMetric(kThemeMetricSliderMinThumbWidth, &width); - ::GetThemeMetric(kThemeMetricSliderMinThumbHeight, &height); - aResult->SizeTo(width, height); - *aIsOverridable = false; - break; - } - - case NS_THEME_SCALE_HORIZONTAL: - { - SInt32 scaleHeight = 0; - ::GetThemeMetric(kThemeMetricHSliderHeight, &scaleHeight); - aResult->SizeTo(scaleHeight, scaleHeight); - *aIsOverridable = false; - break; - } - - case NS_THEME_SCALE_VERTICAL: - { - SInt32 scaleWidth = 0; - ::GetThemeMetric(kThemeMetricVSliderWidth, &scaleWidth); - aResult->SizeTo(scaleWidth, scaleWidth); - *aIsOverridable = false; - break; - } - - case NS_THEME_SCROLLBARTHUMB_HORIZONTAL: - case NS_THEME_SCROLLBARTHUMB_VERTICAL: - { - // Find our parent scrollbar frame in order to find out whether we're in - // a small or a large scrollbar. - nsIFrame *scrollbarFrame = GetParentScrollbarFrame(aFrame); - if (!scrollbarFrame) { - return NS_ERROR_FAILURE; - } - - bool isSmall = (scrollbarFrame->StyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL); - bool isHorizontal = (aWidgetType == NS_THEME_SCROLLBARTHUMB_HORIZONTAL); - int32_t& minSize = isHorizontal ? aResult->width : aResult->height; - minSize = isSmall ? kSmallScrollbarThumbMinSize : kRegularScrollbarThumbMinSize; - break; - } - - case NS_THEME_SCROLLBAR: - case NS_THEME_SCROLLBAR_SMALL: - case NS_THEME_SCROLLBARTRACK_VERTICAL: - case NS_THEME_SCROLLBARTRACK_HORIZONTAL: - { - *aIsOverridable = false; - - if (nsLookAndFeel::UseOverlayScrollbars()) { - nsIFrame* scrollbarFrame = GetParentScrollbarFrame(aFrame); - if (scrollbarFrame && - scrollbarFrame->StyleDisplay()->mAppearance == - NS_THEME_SCROLLBAR_SMALL) { - aResult->SizeTo(14, 14); - } - else { - aResult->SizeTo(16, 16); - } - if (IsScrollbarWidthThin(aFrame)) { - aResult->SizeTo(8, 8); - } - break; - } - - // yeah, i know i'm cheating a little here, but i figure that it - // really doesn't matter if the scrollbar is vertical or horizontal - // and the width metric is a really good metric for every piece - // of the scrollbar. - - nsIFrame *scrollbarFrame = GetParentScrollbarFrame(aFrame); - if (!scrollbarFrame) return NS_ERROR_FAILURE; - - int32_t themeMetric = (scrollbarFrame->StyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL) ? - kThemeMetricSmallScrollBarWidth : - kThemeMetricScrollBarWidth; - SInt32 scrollbarWidth = 0; - ::GetThemeMetric(themeMetric, &scrollbarWidth); - if (IsScrollbarWidthThin(aFrame)) { - scrollbarWidth /= 2; - } - aResult->SizeTo(scrollbarWidth, scrollbarWidth); - break; - } - - case NS_THEME_SCROLLBAR_NON_DISAPPEARING: - { - int32_t themeMetric = kThemeMetricScrollBarWidth; - - if (aFrame) { - nsIFrame* scrollbarFrame = GetParentScrollbarFrame(aFrame); - if (scrollbarFrame && - scrollbarFrame->StyleDisplay()->mAppearance == - NS_THEME_SCROLLBAR_SMALL) { - // XXX We're interested in the width of non-disappearing scrollbars - // to leave enough space for a dropmarker in non-native styled - // comboboxes (bug 869314). It isn't clear to me if comboboxes can - // ever have small scrollbars. - themeMetric = kThemeMetricSmallScrollBarWidth; - } - } - - SInt32 scrollbarWidth = 0; - ::GetThemeMetric(themeMetric, &scrollbarWidth); - aResult->SizeTo(scrollbarWidth, scrollbarWidth); - break; - } - - case NS_THEME_SCROLLBARBUTTON_UP: - case NS_THEME_SCROLLBARBUTTON_DOWN: - case NS_THEME_SCROLLBARBUTTON_LEFT: - case NS_THEME_SCROLLBARBUTTON_RIGHT: - { - if (!IsScrollbarWidthThin(aFrame)) { - // Get scrollbar button metrics from the system, except in the case of - // thin scrollbars, where we leave them at 0 (collapse) - - nsIFrame *scrollbarFrame = GetParentScrollbarFrame(aFrame); - if (!scrollbarFrame) return NS_ERROR_FAILURE; - - // Since there is no NS_THEME_SCROLLBARBUTTON_UP_SMALL we need to ask the parent what appearance style it has. - int32_t themeMetric = (scrollbarFrame->StyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL) ? - kThemeMetricSmallScrollBarWidth : - kThemeMetricScrollBarWidth; - SInt32 scrollbarWidth = 0; - ::GetThemeMetric(themeMetric, &scrollbarWidth); - - // It seems that for both sizes of scrollbar, the buttons are one pixel "longer". - if (aWidgetType == NS_THEME_SCROLLBARBUTTON_LEFT || aWidgetType == NS_THEME_SCROLLBARBUTTON_RIGHT) - aResult->SizeTo(scrollbarWidth+1, scrollbarWidth); - else - aResult->SizeTo(scrollbarWidth, scrollbarWidth+1); - } - *aIsOverridable = false; - break; - } - case NS_THEME_RESIZER: - { - HIThemeGrowBoxDrawInfo drawInfo; - drawInfo.version = 0; - drawInfo.state = kThemeStateActive; - drawInfo.kind = kHIThemeGrowBoxKindNormal; - drawInfo.direction = kThemeGrowRight | kThemeGrowDown; - drawInfo.size = kHIThemeGrowBoxSizeNormal; - HIPoint pnt = { 0, 0 }; - HIRect bounds; - HIThemeGetGrowBoxBounds(&pnt, &drawInfo, &bounds); - aResult->SizeTo(bounds.size.width, bounds.size.height); - *aIsOverridable = false; - } - } - - if (IsHiDPIContext(aPresContext)) { - *aResult = *aResult * 2; - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsNativeThemeCocoa::WidgetStateChanged(nsIFrame* aFrame, uint8_t aWidgetType, - nsIAtom* aAttribute, bool* aShouldRepaint, - const nsAttrValue* aOldValue) -{ - // Some widget types just never change state. - switch (aWidgetType) { - case NS_THEME_WINDOW_TITLEBAR: - case NS_THEME_TOOLBOX: - case NS_THEME_TOOLBAR: - case NS_THEME_STATUSBAR: - case NS_THEME_STATUSBARPANEL: - case NS_THEME_RESIZERPANEL: - case NS_THEME_TOOLTIP: - case NS_THEME_TABPANELS: - case NS_THEME_TABPANEL: - case NS_THEME_DIALOG: - case NS_THEME_MENUPOPUP: - case NS_THEME_GROUPBOX: - case NS_THEME_PROGRESSCHUNK: - case NS_THEME_PROGRESSCHUNK_VERTICAL: - case NS_THEME_PROGRESSBAR: - case NS_THEME_PROGRESSBAR_VERTICAL: - case NS_THEME_METERBAR: - case NS_THEME_METERCHUNK: - case NS_THEME_MAC_VIBRANCY_LIGHT: - case NS_THEME_MAC_VIBRANCY_DARK: - *aShouldRepaint = false; - return NS_OK; - } - - // XXXdwh Not sure what can really be done here. Can at least guess for - // specific widgets that they're highly unlikely to have certain states. - // For example, a toolbar doesn't care about any states. - if (!aAttribute) { - // Hover/focus/active changed. Always repaint. - *aShouldRepaint = true; - } else { - // Check the attribute to see if it's relevant. - // disabled, checked, dlgtype, default, etc. - *aShouldRepaint = false; - if (aAttribute == nsGkAtoms::disabled || - aAttribute == nsGkAtoms::checked || - aAttribute == nsGkAtoms::selected || - aAttribute == nsGkAtoms::visuallyselected || - aAttribute == nsGkAtoms::menuactive || - aAttribute == nsGkAtoms::sortDirection || - aAttribute == nsGkAtoms::focused || - aAttribute == nsGkAtoms::_default || - aAttribute == nsGkAtoms::open || - aAttribute == nsGkAtoms::hover) - *aShouldRepaint = true; - } - - return NS_OK; -} - -NS_IMETHODIMP -nsNativeThemeCocoa::ThemeChanged() -{ - // This is unimplemented because we don't care if gecko changes its theme - // and Mac OS X doesn't have themes. - return NS_OK; -} - -bool -nsNativeThemeCocoa::ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* aFrame, - uint8_t aWidgetType) -{ - // We don't have CSS set up to render non-native scrollbars on Mac OS X so we - // render natively even if native theme support is disabled. - if (aWidgetType != NS_THEME_SCROLLBAR && - aPresContext && !aPresContext->PresShell()->IsThemeSupportEnabled()) - return false; - - // if this is a dropdown button in a combobox the answer is always no - if (aWidgetType == NS_THEME_MENULIST_BUTTON) { - nsIFrame* parentFrame = aFrame->GetParent(); - if (parentFrame && (parentFrame->GetType() == nsGkAtoms::comboboxControlFrame)) - return false; - } - - switch (aWidgetType) { - // Combobox dropdowns don't support native theming in vertical mode. - case NS_THEME_MENULIST: - case NS_THEME_MENULIST_BUTTON: - case NS_THEME_MENULIST_TEXT: - case NS_THEME_MENULIST_TEXTFIELD: - if (aFrame && aFrame->GetWritingMode().IsVertical()) { - return false; - } - MOZ_FALLTHROUGH; - - case NS_THEME_LISTBOX: - - case NS_THEME_DIALOG: - case NS_THEME_WINDOW: - case NS_THEME_WINDOW_BUTTON_BOX: - case NS_THEME_WINDOW_TITLEBAR: - case NS_THEME_CHECKMENUITEM: - case NS_THEME_MENUPOPUP: - case NS_THEME_MENUARROW: - case NS_THEME_MENUITEM: - case NS_THEME_MENUSEPARATOR: - case NS_THEME_MAC_FULLSCREEN_BUTTON: - case NS_THEME_TOOLTIP: - - case NS_THEME_CHECKBOX: - case NS_THEME_CHECKBOX_CONTAINER: - case NS_THEME_RADIO: - case NS_THEME_RADIO_CONTAINER: - case NS_THEME_GROUPBOX: - case NS_THEME_MAC_HELP_BUTTON: - case NS_THEME_MAC_DISCLOSURE_BUTTON_OPEN: - case NS_THEME_MAC_DISCLOSURE_BUTTON_CLOSED: - case NS_THEME_BUTTON: - case NS_THEME_BUTTON_ARROW_UP: - case NS_THEME_BUTTON_ARROW_DOWN: - case NS_THEME_BUTTON_BEVEL: - case NS_THEME_TOOLBARBUTTON: - case NS_THEME_SPINNER: - case NS_THEME_SPINNER_UPBUTTON: - case NS_THEME_SPINNER_DOWNBUTTON: - case NS_THEME_TOOLBAR: - case NS_THEME_STATUSBAR: - case NS_THEME_NUMBER_INPUT: - case NS_THEME_TEXTFIELD: - case NS_THEME_TEXTFIELD_MULTILINE: - case NS_THEME_SEARCHFIELD: - case NS_THEME_TOOLBOX: - //case NS_THEME_TOOLBARBUTTON: - case NS_THEME_PROGRESSBAR: - case NS_THEME_PROGRESSBAR_VERTICAL: - case NS_THEME_PROGRESSCHUNK: - case NS_THEME_PROGRESSCHUNK_VERTICAL: - case NS_THEME_METERBAR: - case NS_THEME_METERCHUNK: - case NS_THEME_SEPARATOR: - - case NS_THEME_TABPANELS: - case NS_THEME_TAB: - - case NS_THEME_TREETWISTY: - case NS_THEME_TREETWISTYOPEN: - case NS_THEME_TREEVIEW: - case NS_THEME_TREEHEADER: - case NS_THEME_TREEHEADERCELL: - case NS_THEME_TREEHEADERSORTARROW: - case NS_THEME_TREEITEM: - case NS_THEME_TREELINE: - case NS_THEME_MAC_SOURCE_LIST: - case NS_THEME_MAC_SOURCE_LIST_SELECTION: - case NS_THEME_MAC_ACTIVE_SOURCE_LIST_SELECTION: - - case NS_THEME_RANGE: - - case NS_THEME_SCALE_HORIZONTAL: - case NS_THEME_SCALETHUMB_HORIZONTAL: - case NS_THEME_SCALE_VERTICAL: - case NS_THEME_SCALETHUMB_VERTICAL: - - case NS_THEME_SCROLLBAR: - case NS_THEME_SCROLLBAR_SMALL: - case NS_THEME_SCROLLBARBUTTON_UP: - case NS_THEME_SCROLLBARBUTTON_DOWN: - case NS_THEME_SCROLLBARBUTTON_LEFT: - case NS_THEME_SCROLLBARBUTTON_RIGHT: - case NS_THEME_SCROLLBARTHUMB_HORIZONTAL: - case NS_THEME_SCROLLBARTHUMB_VERTICAL: - case NS_THEME_SCROLLBARTRACK_VERTICAL: - case NS_THEME_SCROLLBARTRACK_HORIZONTAL: - case NS_THEME_SCROLLBAR_NON_DISAPPEARING: - return !IsWidgetStyled(aPresContext, aFrame, aWidgetType); - - case NS_THEME_RESIZER: - { - nsIFrame* parentFrame = aFrame->GetParent(); - if (!parentFrame || parentFrame->GetType() != nsGkAtoms::scrollFrame) - return true; - - // Note that IsWidgetStyled is not called for resizers on Mac. This is - // because for scrollable containers, the native resizer looks better - // when (non-overlay) scrollbars are present even when the style is - // overriden, and the custom transparent resizer looks better when - // scrollbars are not present. - nsIScrollableFrame* scrollFrame = do_QueryFrame(parentFrame); - return (!nsLookAndFeel::UseOverlayScrollbars() && - scrollFrame && scrollFrame->GetScrollbarVisibility()); - } - - case NS_THEME_FOCUS_OUTLINE: - return true; - - case NS_THEME_MAC_VIBRANCY_LIGHT: - case NS_THEME_MAC_VIBRANCY_DARK: - return VibrancyManager::SystemSupportsVibrancy(); - } - - return false; -} - -bool -nsNativeThemeCocoa::WidgetIsContainer(uint8_t aWidgetType) -{ - // flesh this out at some point - switch (aWidgetType) { - case NS_THEME_MENULIST_BUTTON: - case NS_THEME_RADIO: - case NS_THEME_CHECKBOX: - case NS_THEME_PROGRESSBAR: - case NS_THEME_METERBAR: - case NS_THEME_RANGE: - case NS_THEME_MAC_HELP_BUTTON: - case NS_THEME_MAC_DISCLOSURE_BUTTON_OPEN: - case NS_THEME_MAC_DISCLOSURE_BUTTON_CLOSED: - return false; - } - return true; -} - -bool -nsNativeThemeCocoa::ThemeDrawsFocusForWidget(uint8_t aWidgetType) -{ - if (aWidgetType == NS_THEME_MENULIST || - aWidgetType == NS_THEME_MENULIST_TEXTFIELD || - aWidgetType == NS_THEME_BUTTON || - aWidgetType == NS_THEME_MAC_HELP_BUTTON || - aWidgetType == NS_THEME_MAC_DISCLOSURE_BUTTON_OPEN || - aWidgetType == NS_THEME_MAC_DISCLOSURE_BUTTON_CLOSED || - aWidgetType == NS_THEME_RADIO || - aWidgetType == NS_THEME_RANGE || - aWidgetType == NS_THEME_CHECKBOX) - return true; - - return false; -} - -bool -nsNativeThemeCocoa::ThemeNeedsComboboxDropmarker() -{ - return false; -} - -bool -nsNativeThemeCocoa::WidgetAppearanceDependsOnWindowFocus(uint8_t aWidgetType) -{ - switch (aWidgetType) { - case NS_THEME_DIALOG: - case NS_THEME_GROUPBOX: - case NS_THEME_TABPANELS: - case NS_THEME_BUTTON_ARROW_UP: - case NS_THEME_BUTTON_ARROW_DOWN: - case NS_THEME_CHECKMENUITEM: - case NS_THEME_MENUPOPUP: - case NS_THEME_MENUARROW: - case NS_THEME_MENUITEM: - case NS_THEME_MENUSEPARATOR: - case NS_THEME_TOOLTIP: - case NS_THEME_SPINNER: - case NS_THEME_SPINNER_UPBUTTON: - case NS_THEME_SPINNER_DOWNBUTTON: - case NS_THEME_SEPARATOR: - case NS_THEME_TOOLBOX: - case NS_THEME_NUMBER_INPUT: - case NS_THEME_TEXTFIELD: - case NS_THEME_TREEVIEW: - case NS_THEME_TREELINE: - case NS_THEME_TEXTFIELD_MULTILINE: - case NS_THEME_LISTBOX: - case NS_THEME_RESIZER: - return false; - default: - return true; - } -} - -bool -nsNativeThemeCocoa::IsWindowSheet(nsIFrame* aFrame) -{ - NSWindow* win = NativeWindowForFrame(aFrame); - id winDelegate = [win delegate]; - nsIWidget* widget = [(WindowDelegate *)winDelegate geckoWidget]; - if (!widget) { - return false; - } - return (widget->WindowType() == eWindowType_sheet); -} - -bool -nsNativeThemeCocoa::NeedToClearBackgroundBehindWidget(nsIFrame* aFrame, - uint8_t aWidgetType) -{ - switch (aWidgetType) { - case NS_THEME_MAC_SOURCE_LIST: - // If we're in a XUL tree, we don't want to clear the background behind the - // selections below, since that would make our source list to not pick up - // the right font smoothing background. But since we don't call this method - // in nsTreeBodyFrame::BuildDisplayList, we never get here. - case NS_THEME_MAC_SOURCE_LIST_SELECTION: - case NS_THEME_MAC_ACTIVE_SOURCE_LIST_SELECTION: - case NS_THEME_MAC_VIBRANCY_LIGHT: - case NS_THEME_MAC_VIBRANCY_DARK: - case NS_THEME_TOOLTIP: - case NS_THEME_MENUPOPUP: - case NS_THEME_MENUITEM: - case NS_THEME_CHECKMENUITEM: - return true; - case NS_THEME_DIALOG: - return IsWindowSheet(aFrame); - default: - return false; - } -} - -static nscolor ConvertNSColor(NSColor* aColor) -{ - 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)([deviceColor alphaComponent] * 255.0)); -} - -bool -nsNativeThemeCocoa::WidgetProvidesFontSmoothingBackgroundColor(nsIFrame* aFrame, - uint8_t aWidgetType, - nscolor* aColor) -{ - switch (aWidgetType) { - case NS_THEME_MAC_SOURCE_LIST: - case NS_THEME_MAC_SOURCE_LIST_SELECTION: - case NS_THEME_MAC_ACTIVE_SOURCE_LIST_SELECTION: - case NS_THEME_MAC_VIBRANCY_LIGHT: - case NS_THEME_MAC_VIBRANCY_DARK: - case NS_THEME_TOOLTIP: - case NS_THEME_MENUPOPUP: - case NS_THEME_MENUITEM: - case NS_THEME_CHECKMENUITEM: - case NS_THEME_DIALOG: - { - if ((aWidgetType == NS_THEME_DIALOG && !IsWindowSheet(aFrame)) || - ((aWidgetType == NS_THEME_MAC_SOURCE_LIST_SELECTION || - aWidgetType == NS_THEME_MAC_ACTIVE_SOURCE_LIST_SELECTION) && - !IsInSourceList(aFrame))) { - return false; - } - ChildView* childView = ChildViewForFrame(aFrame); - if (childView) { - ThemeGeometryType type = ThemeGeometryTypeForWidget(aFrame, aWidgetType); - NSColor* color = [childView vibrancyFontSmoothingBackgroundColorForThemeGeometryType:type]; - *aColor = ConvertNSColor(color); - return true; - } - return false; - } - default: - return false; - } -} - -nsITheme::ThemeGeometryType -nsNativeThemeCocoa::ThemeGeometryTypeForWidget(nsIFrame* aFrame, uint8_t aWidgetType) -{ - switch (aWidgetType) { - case NS_THEME_WINDOW_TITLEBAR: - return eThemeGeometryTypeTitlebar; - case NS_THEME_TOOLBAR: - return eThemeGeometryTypeToolbar; - case NS_THEME_TOOLBOX: - return eThemeGeometryTypeToolbox; - case NS_THEME_WINDOW_BUTTON_BOX: - return eThemeGeometryTypeWindowButtons; - case NS_THEME_MAC_FULLSCREEN_BUTTON: - return eThemeGeometryTypeFullscreenButton; - case NS_THEME_MAC_VIBRANCY_LIGHT: - return eThemeGeometryTypeVibrancyLight; - case NS_THEME_MAC_VIBRANCY_DARK: - return eThemeGeometryTypeVibrancyDark; - case NS_THEME_TOOLTIP: - return eThemeGeometryTypeTooltip; - case NS_THEME_MENUPOPUP: - return eThemeGeometryTypeMenu; - case NS_THEME_MENUITEM: - case NS_THEME_CHECKMENUITEM: { - EventStates eventState = GetContentState(aFrame, aWidgetType); - bool isDisabled = IsDisabled(aFrame, eventState); - bool isSelected = !isDisabled && CheckBooleanAttr(aFrame, nsGkAtoms::menuactive); - return isSelected ? eThemeGeometryTypeHighlightedMenuItem : eThemeGeometryTypeMenu; - } - case NS_THEME_DIALOG: - return IsWindowSheet(aFrame) ? eThemeGeometryTypeSheet : eThemeGeometryTypeUnknown; - case NS_THEME_MAC_SOURCE_LIST: - return eThemeGeometryTypeSourceList; - case NS_THEME_MAC_SOURCE_LIST_SELECTION: - return IsInSourceList(aFrame) ? eThemeGeometryTypeSourceListSelection - : eThemeGeometryTypeUnknown; - case NS_THEME_MAC_ACTIVE_SOURCE_LIST_SELECTION: - return IsInSourceList(aFrame) ? eThemeGeometryTypeActiveSourceListSelection - : eThemeGeometryTypeUnknown; - default: - return eThemeGeometryTypeUnknown; - } -} - -nsITheme::Transparency -nsNativeThemeCocoa::GetWidgetTransparency(nsIFrame* aFrame, uint8_t aWidgetType) -{ - switch (aWidgetType) { - case NS_THEME_MENUPOPUP: - case NS_THEME_TOOLTIP: - return eTransparent; - - case NS_THEME_DIALOG: - return IsWindowSheet(aFrame) ? eTransparent : eOpaque; - - case NS_THEME_SCROLLBAR_SMALL: - case NS_THEME_SCROLLBAR: - return nsLookAndFeel::UseOverlayScrollbars() ? eTransparent : eOpaque; - - case NS_THEME_STATUSBAR: - // Knowing that scrollbars and statusbars are opaque improves - // performance, because we create layers for them. - return eOpaque; - - case NS_THEME_TOOLBAR: - return eOpaque; - - default: - return eUnknownTransparency; - } -} diff --git a/widget/cocoa/nsNativeThemeColors.h b/widget/cocoa/nsNativeThemeColors.h deleted file mode 100644 index b1691b5163..0000000000 --- a/widget/cocoa/nsNativeThemeColors.h +++ /dev/null @@ -1,57 +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 nsNativeThemeColors_h_ -#define nsNativeThemeColors_h_ - -#include "nsCocoaFeatures.h" -#import - -enum ColorName { - toolbarTopBorderGrey, - toolbarFillGrey, - toolbarBottomBorderGrey, -}; - -static const int sLionThemeColors[][2] = { - /* { active window, inactive window } */ - // toolbar: - { 0xD0, 0xF0 }, // top separator line - { 0xB2, 0xE1 }, // fill color - { 0x59, 0x87 }, // bottom separator line -}; - -static const int sYosemiteThemeColors[][2] = { - /* { active window, inactive window } */ - // toolbar: - { 0xBD, 0xDF }, // top separator line - { 0xD3, 0xF6 }, // fill color - { 0xB3, 0xD1 }, // bottom separator line -}; - -__attribute__((unused)) -static int NativeGreyColorAsInt(ColorName name, BOOL isMain) -{ - if (nsCocoaFeatures::OnYosemiteOrLater()) - return sYosemiteThemeColors[name][isMain ? 0 : 1]; - return sLionThemeColors[name][isMain ? 0 : 1]; -} - -__attribute__((unused)) -static float NativeGreyColorAsFloat(ColorName name, BOOL isMain) -{ - return NativeGreyColorAsInt(name, isMain) / 255.0f; -} - -__attribute__((unused)) -static void DrawNativeGreyColorInRect(CGContextRef context, ColorName name, - CGRect rect, BOOL isMain) -{ - float grey = NativeGreyColorAsFloat(name, isMain); - CGContextSetRGBFillColor(context, grey, grey, grey, 1.0f); - CGContextFillRect(context, rect); -} - -#endif // nsNativeThemeColors_h_ diff --git a/widget/cocoa/nsPIWidgetCocoa.idl b/widget/cocoa/nsPIWidgetCocoa.idl deleted file mode 100644 index a8fd8149ce..0000000000 --- a/widget/cocoa/nsPIWidgetCocoa.idl +++ /dev/null @@ -1,37 +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 "nsISupports.idl" - -interface nsIWidget; - -[ptr] native NSWindowPtr(NSWindow); - -// -// nsPIWidgetCocoa -// -// A private interface (unfrozen, private to the widget implementation) that -// gives us access to some extra features on a widget/window. -// -[uuid(f75ff69e-3a51-419e-bd29-042f804bc2ed)] -interface nsPIWidgetCocoa : nsISupports -{ - void SendSetZLevelEvent(); - - // Find the displayed child sheet (if aShown) or a child sheet that - // wants to be displayed (if !aShown) - nsIWidget GetChildSheet(in boolean aShown); - - // Get the parent widget (if any) StandardCreate() was called with. - nsIWidget GetRealParent(); - - // If the object implementing this interface is a sheet, this will return the - // native NSWindow it is attached to - readonly attribute NSWindowPtr sheetWindowParent; - - // True if window is a sheet - readonly attribute boolean isSheet; - -}; // nsPIWidgetCocoa diff --git a/widget/cocoa/nsPrintDialogX.h b/widget/cocoa/nsPrintDialogX.h deleted file mode 100644 index 470f17d99d..0000000000 --- a/widget/cocoa/nsPrintDialogX.h +++ /dev/null @@ -1,68 +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 nsPrintDialog_h_ -#define nsPrintDialog_h_ - -#include "nsIPrintDialogService.h" -#include "nsCOMPtr.h" -#include "nsCocoaUtils.h" - -#import - -class nsIPrintSettings; -class nsIStringBundle; - -class nsPrintDialogServiceX : public nsIPrintDialogService -{ -public: - nsPrintDialogServiceX(); - - NS_DECL_ISUPPORTS - - NS_IMETHOD Init() override; - NS_IMETHOD Show(nsPIDOMWindowOuter *aParent, nsIPrintSettings *aSettings, - nsIWebBrowserPrint *aWebBrowserPrint) override; - NS_IMETHOD ShowPageSetup(nsPIDOMWindowOuter *aParent, - nsIPrintSettings *aSettings) override; - -protected: - virtual ~nsPrintDialogServiceX(); -}; - -@interface PrintPanelAccessoryView : NSView -{ - nsIPrintSettings* mSettings; - nsIStringBundle* mPrintBundle; - NSButton* mPrintSelectionOnlyCheckbox; - NSButton* mShrinkToFitCheckbox; - NSButton* mPrintBGColorsCheckbox; - NSButton* mPrintBGImagesCheckbox; - NSButtonCell* mAsLaidOutRadio; - NSButtonCell* mSelectedFrameRadio; - NSButtonCell* mSeparateFramesRadio; - NSPopUpButton* mHeaderLeftList; - NSPopUpButton* mHeaderCenterList; - NSPopUpButton* mHeaderRightList; - NSPopUpButton* mFooterLeftList; - NSPopUpButton* mFooterCenterList; - NSPopUpButton* mFooterRightList; -} - -- (id)initWithSettings:(nsIPrintSettings*)aSettings; - -- (void)exportSettings; - -@end - -@interface PrintPanelAccessoryController : NSViewController - -- (id)initWithSettings:(nsIPrintSettings*)aSettings; - -- (void)exportSettings; - -@end - -#endif // nsPrintDialog_h_ diff --git a/widget/cocoa/nsPrintDialogX.mm b/widget/cocoa/nsPrintDialogX.mm deleted file mode 100644 index a6d58d5bfb..0000000000 --- a/widget/cocoa/nsPrintDialogX.mm +++ /dev/null @@ -1,682 +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/ArrayUtils.h" - -#include "nsPrintDialogX.h" -#include "nsIPrintSettings.h" -#include "nsIPrintSettingsService.h" -#include "nsPrintSettingsX.h" -#include "nsCOMPtr.h" -#include "nsQueryObject.h" -#include "nsServiceManagerUtils.h" -#include "nsIWebProgressListener.h" -#include "nsIStringBundle.h" -#include "nsIWebBrowserPrint.h" -#include "nsCRT.h" - -#import -#include "nsObjCExceptions.h" - -using namespace mozilla; - -NS_IMPL_ISUPPORTS(nsPrintDialogServiceX, nsIPrintDialogService) - -nsPrintDialogServiceX::nsPrintDialogServiceX() -{ -} - -nsPrintDialogServiceX::~nsPrintDialogServiceX() -{ -} - -NS_IMETHODIMP -nsPrintDialogServiceX::Init() -{ - return NS_OK; -} - -NS_IMETHODIMP -nsPrintDialogServiceX::Show(nsPIDOMWindowOuter *aParent, nsIPrintSettings *aSettings, - nsIWebBrowserPrint *aWebBrowserPrint) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NS_PRECONDITION(aSettings, "aSettings must not be null"); - - RefPtr settingsX(do_QueryObject(aSettings)); - if (!settingsX) - return NS_ERROR_FAILURE; - - nsCOMPtr printSettingsSvc - = do_GetService("@mozilla.org/gfx/printsettings-service;1"); - - // Set the print job title - char16_t** docTitles; - uint32_t titleCount; - nsresult rv = aWebBrowserPrint->EnumerateDocumentNames(&titleCount, &docTitles); - if (NS_SUCCEEDED(rv) && titleCount > 0) { - CFStringRef cfTitleString = CFStringCreateWithCharacters(NULL, reinterpret_cast(docTitles[0]), - NS_strlen(docTitles[0])); - if (cfTitleString) { - ::PMPrintSettingsSetJobName(settingsX->GetPMPrintSettings(), cfTitleString); - CFRelease(cfTitleString); - } - for (int32_t i = titleCount - 1; i >= 0; i--) { - free(docTitles[i]); - } - free(docTitles); - docTitles = NULL; - titleCount = 0; - } - - // Read default print settings from prefs - printSettingsSvc->InitPrintSettingsFromPrefs(settingsX, true, - nsIPrintSettings::kInitSaveNativeData); - NSPrintInfo* printInfo = settingsX->GetCocoaPrintInfo(); - - // Put the print info into the current print operation, since that's where - // [panel runModal] will look for it. We create the view because otherwise - // we'll get unrelated warnings printed to the console. - NSView* tmpView = [[NSView alloc] init]; - NSPrintOperation* printOperation = [NSPrintOperation printOperationWithView:tmpView printInfo:printInfo]; - [NSPrintOperation setCurrentOperation:printOperation]; - - NSPrintPanel* panel = [NSPrintPanel printPanel]; - [panel setOptions:NSPrintPanelShowsCopies - | NSPrintPanelShowsPageRange - | NSPrintPanelShowsPaperSize - | NSPrintPanelShowsOrientation - | NSPrintPanelShowsScaling ]; - PrintPanelAccessoryController* viewController = - [[PrintPanelAccessoryController alloc] initWithSettings:aSettings]; - [panel addAccessoryController:viewController]; - [viewController release]; - - // Show the dialog. - nsCocoaUtils::PrepareForNativeAppModalDialog(); - int button = [panel runModal]; - nsCocoaUtils::CleanUpAfterNativeAppModalDialog(); - - NSPrintInfo* copy = [[[NSPrintOperation currentOperation] printInfo] copy]; - if (!copy) { - return NS_ERROR_OUT_OF_MEMORY; - } - - [NSPrintOperation setCurrentOperation:nil]; - [tmpView release]; - - if (button != NSFileHandlingPanelOKButton) - return NS_ERROR_ABORT; - - settingsX->SetCocoaPrintInfo(copy); - settingsX->InitUnwriteableMargin(); - - // Save settings unless saving is pref'd off - if (Preferences::GetBool("print.save_print_settings", false)) { - printSettingsSvc->SavePrintSettingsToPrefs(settingsX, true, - nsIPrintSettings::kInitSaveNativeData); - } - - // Get coordinate space resolution for converting paper size units to inches - NSWindow *win = [[NSApplication sharedApplication] mainWindow]; - if (win) { - NSDictionary *devDesc = [win deviceDescription]; - if (devDesc) { - NSSize res = [[devDesc objectForKey: NSDeviceResolution] sizeValue]; - float scale = [win backingScaleFactor]; - if (scale > 0) { - settingsX->SetInchesScale(res.width / scale, res.height / scale); - } - } - } - - // Export settings. - [viewController exportSettings]; - - // If "ignore scaling" is checked, overwrite scaling factor with 1. - bool isShrinkToFitChecked; - settingsX->GetShrinkToFit(&isShrinkToFitChecked); - if (isShrinkToFitChecked) { - NSMutableDictionary* dict = [copy dictionary]; - if (dict) { - [dict setObject: [NSNumber numberWithFloat: 1] - forKey: NSPrintScalingFactor]; - } - // Set the scaling factor to 100% in the NSPrintInfo - // object so that it will not affect the paper size - // retrieved from the PMPageFormat routines. - [copy setScalingFactor:1.0]; - } else { - aSettings->SetScaling([copy scalingFactor]); - } - - // Set the adjusted paper size now that we've updated - // the scaling factor. - settingsX->InitAdjustedPaperSize(); - - [copy release]; - - int16_t pageRange; - aSettings->GetPrintRange(&pageRange); - if (pageRange != nsIPrintSettings::kRangeSelection) { - PMPrintSettings nativePrintSettings = settingsX->GetPMPrintSettings(); - UInt32 firstPage, lastPage; - OSStatus status = ::PMGetFirstPage(nativePrintSettings, &firstPage); - if (status == noErr) { - status = ::PMGetLastPage(nativePrintSettings, &lastPage); - if (status == noErr && lastPage != UINT32_MAX) { - aSettings->SetPrintRange(nsIPrintSettings::kRangeSpecifiedPageRange); - aSettings->SetStartPageRange(firstPage); - aSettings->SetEndPageRange(lastPage); - } - } - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsPrintDialogServiceX::ShowPageSetup(nsPIDOMWindowOuter *aParent, - nsIPrintSettings *aNSSettings) -{ - NS_PRECONDITION(aParent, "aParent must not be null"); - NS_PRECONDITION(aNSSettings, "aSettings must not be null"); - NS_ENSURE_TRUE(aNSSettings, NS_ERROR_FAILURE); - - RefPtr settingsX(do_QueryObject(aNSSettings)); - if (!settingsX) - return NS_ERROR_FAILURE; - - NSPrintInfo* printInfo = settingsX->GetCocoaPrintInfo(); - NSPageLayout *pageLayout = [NSPageLayout pageLayout]; - nsCocoaUtils::PrepareForNativeAppModalDialog(); - int button = [pageLayout runModalWithPrintInfo:printInfo]; - nsCocoaUtils::CleanUpAfterNativeAppModalDialog(); - - return button == NSFileHandlingPanelOKButton ? NS_OK : NS_ERROR_ABORT; -} - -// Accessory view - -@interface PrintPanelAccessoryView (Private) - -- (NSString*)localizedString:(const char*)aKey; - -- (int16_t)chosenFrameSetting; - -- (const char*)headerFooterStringForList:(NSPopUpButton*)aList; - -- (void)exportHeaderFooterSettings; - -- (void)initBundle; - -- (NSTextField*)label:(const char*)aLabel - withFrame:(NSRect)aRect - alignment:(NSTextAlignment)aAlignment; - -- (void)addLabel:(const char*)aLabel - withFrame:(NSRect)aRect - alignment:(NSTextAlignment)aAlignment; - -- (void)addLabel:(const char*)aLabel withFrame:(NSRect)aRect; - -- (void)addCenteredLabel:(const char*)aLabel withFrame:(NSRect)aRect; - -- (NSButton*)checkboxWithLabel:(const char*)aLabel andFrame:(NSRect)aRect; - -- (NSPopUpButton*)headerFooterItemListWithFrame:(NSRect)aRect - selectedItem:(const char16_t*)aCurrentString; - -- (void)addOptionsSection; - -- (void)addAppearanceSection; - -- (void)addFramesSection; - -- (void)addHeaderFooterSection; - -- (NSString*)summaryValueForCheckbox:(NSButton*)aCheckbox; - -- (NSString*)framesSummaryValue; - -- (NSString*)headerSummaryValue; - -- (NSString*)footerSummaryValue; - -@end - -static const char sHeaderFooterTags[][4] = {"", "&T", "&U", "&D", "&P", "&PT"}; - -@implementation PrintPanelAccessoryView - -// Public methods - -- (id)initWithSettings:(nsIPrintSettings*)aSettings -{ - [super initWithFrame:NSMakeRect(0, 0, 540, 270)]; - - mSettings = aSettings; - [self initBundle]; - [self addOptionsSection]; - [self addAppearanceSection]; - [self addFramesSection]; - [self addHeaderFooterSection]; - - return self; -} - -- (void)exportSettings -{ - mSettings->SetPrintRange([mPrintSelectionOnlyCheckbox state] == NSOnState ? - (int16_t)nsIPrintSettings::kRangeSelection : - (int16_t)nsIPrintSettings::kRangeAllPages); - mSettings->SetShrinkToFit([mShrinkToFitCheckbox state] == NSOnState); - mSettings->SetPrintBGColors([mPrintBGColorsCheckbox state] == NSOnState); - mSettings->SetPrintBGImages([mPrintBGImagesCheckbox state] == NSOnState); - mSettings->SetPrintFrameType([self chosenFrameSetting]); - - [self exportHeaderFooterSettings]; -} - -- (void)dealloc -{ - NS_IF_RELEASE(mPrintBundle); - [super dealloc]; -} - -// Localization - -- (void)initBundle -{ - nsCOMPtr bundleSvc = do_GetService(NS_STRINGBUNDLE_CONTRACTID); - bundleSvc->CreateBundle("chrome://global/locale/printdialog.properties", &mPrintBundle); -} - -- (NSString*)localizedString:(const char*)aKey -{ - if (!mPrintBundle) - return @""; - - nsXPIDLString intlString; - mPrintBundle->GetStringFromName(NS_ConvertUTF8toUTF16(aKey).get(), getter_Copies(intlString)); - NSMutableString* s = [NSMutableString stringWithUTF8String:NS_ConvertUTF16toUTF8(intlString).get()]; - - // Remove all underscores (they're used in the GTK dialog for accesskeys). - [s replaceOccurrencesOfString:@"_" withString:@"" options:0 range:NSMakeRange(0, [s length])]; - return s; -} - -// Widget helpers - -- (NSTextField*)label:(const char*)aLabel - withFrame:(NSRect)aRect - alignment:(NSTextAlignment)aAlignment -{ - NSTextField* label = [[[NSTextField alloc] initWithFrame:aRect] autorelease]; - [label setStringValue:[self localizedString:aLabel]]; - [label setEditable:NO]; - [label setSelectable:NO]; - [label setBezeled:NO]; - [label setBordered:NO]; - [label setDrawsBackground:NO]; - [label setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]]; - [label setAlignment:aAlignment]; - return label; -} - -- (void)addLabel:(const char*)aLabel - withFrame:(NSRect)aRect - alignment:(NSTextAlignment)aAlignment -{ - NSTextField* label = [self label:aLabel withFrame:aRect alignment:aAlignment]; - [self addSubview:label]; -} - -- (void)addLabel:(const char*)aLabel withFrame:(NSRect)aRect -{ - [self addLabel:aLabel withFrame:aRect alignment:NSRightTextAlignment]; -} - -- (void)addCenteredLabel:(const char*)aLabel withFrame:(NSRect)aRect -{ - [self addLabel:aLabel withFrame:aRect alignment:NSCenterTextAlignment]; -} - -- (NSButton*)checkboxWithLabel:(const char*)aLabel andFrame:(NSRect)aRect -{ - aRect.origin.y += 4.0f; - NSButton* checkbox = [[[NSButton alloc] initWithFrame:aRect] autorelease]; - [checkbox setButtonType:NSSwitchButton]; - [checkbox setTitle:[self localizedString:aLabel]]; - [checkbox setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]]; - [checkbox sizeToFit]; - return checkbox; -} - -- (NSPopUpButton*)headerFooterItemListWithFrame:(NSRect)aRect - selectedItem:(const char16_t*)aCurrentString -{ - NSPopUpButton* list = [[[NSPopUpButton alloc] initWithFrame:aRect pullsDown:NO] autorelease]; - [list setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; - [[list cell] setControlSize:NSSmallControlSize]; - NSArray* items = - [NSArray arrayWithObjects:[self localizedString:"headerFooterBlank"], - [self localizedString:"headerFooterTitle"], - [self localizedString:"headerFooterURL"], - [self localizedString:"headerFooterDate"], - [self localizedString:"headerFooterPage"], - [self localizedString:"headerFooterPageTotal"], - nil]; - [list addItemsWithTitles:items]; - - NS_ConvertUTF16toUTF8 currentStringUTF8(aCurrentString); - for (unsigned int i = 0; i < ArrayLength(sHeaderFooterTags); i++) { - if (!strcmp(currentStringUTF8.get(), sHeaderFooterTags[i])) { - [list selectItemAtIndex:i]; - break; - } - } - - return list; -} - -// Build sections - -- (void)addOptionsSection -{ - // Title - [self addLabel:"optionsTitleMac" withFrame:NSMakeRect(0, 240, 151, 22)]; - - // "Print Selection Only" - mPrintSelectionOnlyCheckbox = [self checkboxWithLabel:"selectionOnly" - andFrame:NSMakeRect(156, 240, 0, 0)]; - - bool canPrintSelection; - mSettings->GetPrintOptions(nsIPrintSettings::kEnableSelectionRB, - &canPrintSelection); - [mPrintSelectionOnlyCheckbox setEnabled:canPrintSelection]; - - int16_t printRange; - mSettings->GetPrintRange(&printRange); - if (printRange == nsIPrintSettings::kRangeSelection) { - [mPrintSelectionOnlyCheckbox setState:NSOnState]; - } - - [self addSubview:mPrintSelectionOnlyCheckbox]; - - // "Shrink To Fit" - mShrinkToFitCheckbox = [self checkboxWithLabel:"shrinkToFit" - andFrame:NSMakeRect(156, 218, 0, 0)]; - - bool shrinkToFit; - mSettings->GetShrinkToFit(&shrinkToFit); - [mShrinkToFitCheckbox setState:(shrinkToFit ? NSOnState : NSOffState)]; - - [self addSubview:mShrinkToFitCheckbox]; -} - -- (void)addAppearanceSection -{ - // Title - [self addLabel:"appearanceTitleMac" withFrame:NSMakeRect(0, 188, 151, 22)]; - - // "Print Background Colors" - mPrintBGColorsCheckbox = [self checkboxWithLabel:"printBGColors" - andFrame:NSMakeRect(156, 188, 0, 0)]; - - bool geckoBool; - mSettings->GetPrintBGColors(&geckoBool); - [mPrintBGColorsCheckbox setState:(geckoBool ? NSOnState : NSOffState)]; - - [self addSubview:mPrintBGColorsCheckbox]; - - // "Print Background Images" - mPrintBGImagesCheckbox = [self checkboxWithLabel:"printBGImages" - andFrame:NSMakeRect(156, 166, 0, 0)]; - - mSettings->GetPrintBGImages(&geckoBool); - [mPrintBGImagesCheckbox setState:(geckoBool ? NSOnState : NSOffState)]; - - [self addSubview:mPrintBGImagesCheckbox]; -} - -- (void)addFramesSection -{ - // Title - [self addLabel:"framesTitleMac" withFrame:NSMakeRect(0, 124, 151, 22)]; - - // Radio matrix - NSButtonCell *radio = [[NSButtonCell alloc] init]; - [radio setButtonType:NSRadioButton]; - [radio setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]]; - NSMatrix *matrix = [[NSMatrix alloc] initWithFrame:NSMakeRect(156, 81, 400, 66) - mode:NSRadioModeMatrix - prototype:(NSCell*)radio - numberOfRows:3 - numberOfColumns:1]; - [radio release]; - [matrix setCellSize:NSMakeSize(400, 21)]; - [self addSubview:matrix]; - [matrix release]; - NSArray *cellArray = [matrix cells]; - mAsLaidOutRadio = [cellArray objectAtIndex:0]; - mSelectedFrameRadio = [cellArray objectAtIndex:1]; - mSeparateFramesRadio = [cellArray objectAtIndex:2]; - [mAsLaidOutRadio setTitle:[self localizedString:"asLaidOut"]]; - [mSelectedFrameRadio setTitle:[self localizedString:"selectedFrame"]]; - [mSeparateFramesRadio setTitle:[self localizedString:"separateFrames"]]; - - // Radio enabled state - int16_t frameUIFlag; - mSettings->GetHowToEnableFrameUI(&frameUIFlag); - if (frameUIFlag == nsIPrintSettings::kFrameEnableNone) { - [mAsLaidOutRadio setEnabled:NO]; - [mSelectedFrameRadio setEnabled:NO]; - [mSeparateFramesRadio setEnabled:NO]; - } else if (frameUIFlag == nsIPrintSettings::kFrameEnableAsIsAndEach) { - [mSelectedFrameRadio setEnabled:NO]; - } - - // Radio values - int16_t printFrameType; - mSettings->GetPrintFrameType(&printFrameType); - switch (printFrameType) { - case nsIPrintSettings::kFramesAsIs: - [mAsLaidOutRadio setState:NSOnState]; - break; - case nsIPrintSettings::kSelectedFrame: - [mSelectedFrameRadio setState:NSOnState]; - break; - case nsIPrintSettings::kEachFrameSep: - [mSeparateFramesRadio setState:NSOnState]; - break; - } -} - -- (void)addHeaderFooterSection -{ - // Labels - [self addLabel:"pageHeadersTitleMac" withFrame:NSMakeRect(0, 44, 151, 22)]; - [self addLabel:"pageFootersTitleMac" withFrame:NSMakeRect(0, 0, 151, 22)]; - [self addCenteredLabel:"left" withFrame:NSMakeRect(156, 22, 100, 22)]; - [self addCenteredLabel:"center" withFrame:NSMakeRect(256, 22, 100, 22)]; - [self addCenteredLabel:"right" withFrame:NSMakeRect(356, 22, 100, 22)]; - - // Lists - nsXPIDLString sel; - - mSettings->GetHeaderStrLeft(getter_Copies(sel)); - mHeaderLeftList = [self headerFooterItemListWithFrame:NSMakeRect(156, 44, 100, 22) - selectedItem:sel]; - [self addSubview:mHeaderLeftList]; - - mSettings->GetHeaderStrCenter(getter_Copies(sel)); - mHeaderCenterList = [self headerFooterItemListWithFrame:NSMakeRect(256, 44, 100, 22) - selectedItem:sel]; - [self addSubview:mHeaderCenterList]; - - mSettings->GetHeaderStrRight(getter_Copies(sel)); - mHeaderRightList = [self headerFooterItemListWithFrame:NSMakeRect(356, 44, 100, 22) - selectedItem:sel]; - [self addSubview:mHeaderRightList]; - - mSettings->GetFooterStrLeft(getter_Copies(sel)); - mFooterLeftList = [self headerFooterItemListWithFrame:NSMakeRect(156, 0, 100, 22) - selectedItem:sel]; - [self addSubview:mFooterLeftList]; - - mSettings->GetFooterStrCenter(getter_Copies(sel)); - mFooterCenterList = [self headerFooterItemListWithFrame:NSMakeRect(256, 0, 100, 22) - selectedItem:sel]; - [self addSubview:mFooterCenterList]; - - mSettings->GetFooterStrRight(getter_Copies(sel)); - mFooterRightList = [self headerFooterItemListWithFrame:NSMakeRect(356, 0, 100, 22) - selectedItem:sel]; - [self addSubview:mFooterRightList]; -} - -// Export settings - -- (int16_t)chosenFrameSetting -{ - if ([mAsLaidOutRadio state] == NSOnState) - return nsIPrintSettings::kFramesAsIs; - if ([mSelectedFrameRadio state] == NSOnState) - return nsIPrintSettings::kSelectedFrame; - if ([mSeparateFramesRadio state] == NSOnState) - return nsIPrintSettings::kEachFrameSep; - return nsIPrintSettings::kNoFrames; -} - -- (const char*)headerFooterStringForList:(NSPopUpButton*)aList -{ - NSInteger index = [aList indexOfSelectedItem]; - NS_ASSERTION(index < NSInteger(ArrayLength(sHeaderFooterTags)), "Index of dropdown is higher than expected!"); - return sHeaderFooterTags[index]; -} - -- (void)exportHeaderFooterSettings -{ - const char* headerFooterStr; - headerFooterStr = [self headerFooterStringForList:mHeaderLeftList]; - mSettings->SetHeaderStrLeft(NS_ConvertUTF8toUTF16(headerFooterStr).get()); - - headerFooterStr = [self headerFooterStringForList:mHeaderCenterList]; - mSettings->SetHeaderStrCenter(NS_ConvertUTF8toUTF16(headerFooterStr).get()); - - headerFooterStr = [self headerFooterStringForList:mHeaderRightList]; - mSettings->SetHeaderStrRight(NS_ConvertUTF8toUTF16(headerFooterStr).get()); - - headerFooterStr = [self headerFooterStringForList:mFooterLeftList]; - mSettings->SetFooterStrLeft(NS_ConvertUTF8toUTF16(headerFooterStr).get()); - - headerFooterStr = [self headerFooterStringForList:mFooterCenterList]; - mSettings->SetFooterStrCenter(NS_ConvertUTF8toUTF16(headerFooterStr).get()); - - headerFooterStr = [self headerFooterStringForList:mFooterRightList]; - mSettings->SetFooterStrRight(NS_ConvertUTF8toUTF16(headerFooterStr).get()); -} - -// Summary - -- (NSString*)summaryValueForCheckbox:(NSButton*)aCheckbox -{ - if (![aCheckbox isEnabled]) - return [self localizedString:"summaryNAValue"]; - - return [aCheckbox state] == NSOnState ? - [self localizedString:"summaryOnValue"] : - [self localizedString:"summaryOffValue"]; -} - -- (NSString*)framesSummaryValue -{ - switch([self chosenFrameSetting]) { - case nsIPrintSettings::kFramesAsIs: - return [self localizedString:"asLaidOut"]; - case nsIPrintSettings::kSelectedFrame: - return [self localizedString:"selectedFrame"]; - case nsIPrintSettings::kEachFrameSep: - return [self localizedString:"separateFrames"]; - } - return [self localizedString:"summaryNAValue"]; -} - -- (NSString*)headerSummaryValue -{ - return [[mHeaderLeftList titleOfSelectedItem] stringByAppendingString: - [@", " stringByAppendingString: - [[mHeaderCenterList titleOfSelectedItem] stringByAppendingString: - [@", " stringByAppendingString: - [mHeaderRightList titleOfSelectedItem]]]]]; -} - -- (NSString*)footerSummaryValue -{ - return [[mFooterLeftList titleOfSelectedItem] stringByAppendingString: - [@", " stringByAppendingString: - [[mFooterCenterList titleOfSelectedItem] stringByAppendingString: - [@", " stringByAppendingString: - [mFooterRightList titleOfSelectedItem]]]]]; -} - -- (NSArray*)localizedSummaryItems -{ - return [NSArray arrayWithObjects: - [NSDictionary dictionaryWithObjectsAndKeys: - [self localizedString:"summaryFramesTitle"], NSPrintPanelAccessorySummaryItemNameKey, - [self framesSummaryValue], NSPrintPanelAccessorySummaryItemDescriptionKey, nil], - [NSDictionary dictionaryWithObjectsAndKeys: - [self localizedString:"summarySelectionOnlyTitle"], NSPrintPanelAccessorySummaryItemNameKey, - [self summaryValueForCheckbox:mPrintSelectionOnlyCheckbox], NSPrintPanelAccessorySummaryItemDescriptionKey, nil], - [NSDictionary dictionaryWithObjectsAndKeys: - [self localizedString:"summaryShrinkToFitTitle"], NSPrintPanelAccessorySummaryItemNameKey, - [self summaryValueForCheckbox:mShrinkToFitCheckbox], NSPrintPanelAccessorySummaryItemDescriptionKey, nil], - [NSDictionary dictionaryWithObjectsAndKeys: - [self localizedString:"summaryPrintBGColorsTitle"], NSPrintPanelAccessorySummaryItemNameKey, - [self summaryValueForCheckbox:mPrintBGColorsCheckbox], NSPrintPanelAccessorySummaryItemDescriptionKey, nil], - [NSDictionary dictionaryWithObjectsAndKeys: - [self localizedString:"summaryPrintBGImagesTitle"], NSPrintPanelAccessorySummaryItemNameKey, - [self summaryValueForCheckbox:mPrintBGImagesCheckbox], NSPrintPanelAccessorySummaryItemDescriptionKey, nil], - [NSDictionary dictionaryWithObjectsAndKeys: - [self localizedString:"summaryHeaderTitle"], NSPrintPanelAccessorySummaryItemNameKey, - [self headerSummaryValue], NSPrintPanelAccessorySummaryItemDescriptionKey, nil], - [NSDictionary dictionaryWithObjectsAndKeys: - [self localizedString:"summaryFooterTitle"], NSPrintPanelAccessorySummaryItemNameKey, - [self footerSummaryValue], NSPrintPanelAccessorySummaryItemDescriptionKey, nil], - nil]; -} - -@end - -// Accessory controller - -@implementation PrintPanelAccessoryController - -- (id)initWithSettings:(nsIPrintSettings*)aSettings -{ - [super initWithNibName:nil bundle:nil]; - - NSView* accView = [[PrintPanelAccessoryView alloc] initWithSettings:aSettings]; - [self setView:accView]; - [accView release]; - return self; -} - -- (void)exportSettings -{ - return [(PrintPanelAccessoryView*)[self view] exportSettings]; -} - -- (NSArray *)localizedSummaryItems -{ - return [(PrintPanelAccessoryView*)[self view] localizedSummaryItems]; -} - -@end diff --git a/widget/cocoa/nsPrintOptionsX.h b/widget/cocoa/nsPrintOptionsX.h deleted file mode 100644 index e34e75059e..0000000000 --- a/widget/cocoa/nsPrintOptionsX.h +++ /dev/null @@ -1,44 +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 nsPrintOptionsX_h_ -#define nsPrintOptionsX_h_ - -#include "nsPrintOptionsImpl.h" - -namespace mozilla -{ -namespace embedding -{ - class PrintData; -} // namespace embedding -} // namespace mozilla - -class nsPrintOptionsX : public nsPrintOptions -{ -public: - nsPrintOptionsX(); - virtual ~nsPrintOptionsX(); - - /* - * These serialize and deserialize methods are not symmetrical in that - * printSettingsX != deserialize(serialize(printSettingsX)). This is because - * the native print settings stored in the nsPrintSettingsX's NSPrintInfo - * object are not fully serialized. Only the values needed for successful - * printing are. - */ - NS_IMETHODIMP SerializeToPrintData(nsIPrintSettings* aSettings, - nsIWebBrowserPrint* aWBP, - mozilla::embedding::PrintData* data); - NS_IMETHODIMP DeserializeToPrintSettings(const mozilla::embedding::PrintData& data, - nsIPrintSettings* settings); - -protected: - nsresult _CreatePrintSettings(nsIPrintSettings **_retval); - nsresult ReadPrefs(nsIPrintSettings* aPS, const nsAString& aPrinterName, uint32_t aFlags); - nsresult WritePrefs(nsIPrintSettings* aPS, const nsAString& aPrinterName, uint32_t aFlags); -}; - -#endif // nsPrintOptionsX_h_ diff --git a/widget/cocoa/nsPrintOptionsX.mm b/widget/cocoa/nsPrintOptionsX.mm deleted file mode 100644 index d9aa17b42e..0000000000 --- a/widget/cocoa/nsPrintOptionsX.mm +++ /dev/null @@ -1,349 +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 "nsCOMPtr.h" -#include "nsQueryObject.h" -#include "nsIServiceManager.h" -#include "nsPrintOptionsX.h" -#include "nsPrintSettingsX.h" - -// The constants for paper orientation were renamed in 10.9. __MAC_10_9 is -// defined on OS X 10.9 and later. Although 10.8 and earlier are not supported -// at this time, this allows for building on those older OS versions. The -// values are consistent across OS versions so the rename does not affect -// runtime, just compilation. -#ifdef __MAC_10_9 -#define NS_PAPER_ORIENTATION_PORTRAIT (NSPaperOrientationPortrait) -#define NS_PAPER_ORIENTATION_LANDSCAPE (NSPaperOrientationLandscape) -#else -#define NS_PAPER_ORIENTATION_PORTRAIT (NSPortraitOrientation) -#define NS_PAPER_ORIENTATION_LANDSCAPE (NSLandscapeOrientation) -#endif - -using namespace mozilla::embedding; - -nsPrintOptionsX::nsPrintOptionsX() -{ -} - -nsPrintOptionsX::~nsPrintOptionsX() -{ -} - -NS_IMETHODIMP -nsPrintOptionsX::SerializeToPrintData(nsIPrintSettings* aSettings, - nsIWebBrowserPrint* aWBP, - PrintData* data) -{ - nsresult rv = nsPrintOptions::SerializeToPrintData(aSettings, aWBP, data); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - if (aWBP) { - // When serializing an nsIWebBrowserPrint, we need to pass up the first - // document name. We could pass up the entire collection of document - // names, but the OS X printing prompt code only really cares about - // the first one, so we just send the first to save IPC traffic. - char16_t** docTitles; - uint32_t titleCount; - rv = aWBP->EnumerateDocumentNames(&titleCount, &docTitles); - if (NS_SUCCEEDED(rv) && titleCount > 0) { - data->printJobName().Assign(docTitles[0]); - } - - for (int32_t i = titleCount - 1; i >= 0; i--) { - free(docTitles[i]); - } - free(docTitles); - docTitles = nullptr; - } - - RefPtr settingsX(do_QueryObject(aSettings)); - if (NS_WARN_IF(!settingsX)) { - return NS_ERROR_FAILURE; - } - - NSPrintInfo* printInfo = settingsX->GetCocoaPrintInfo(); - if (NS_WARN_IF(!printInfo)) { - return NS_ERROR_FAILURE; - } - - double adjustedWidth, adjustedHeight; - settingsX->GetAdjustedPaperSize(&adjustedWidth, &adjustedHeight); - data->adjustedPaperWidth() = adjustedWidth; - data->adjustedPaperHeight() = adjustedHeight; - - NSDictionary* dict = [printInfo dictionary]; - if (NS_WARN_IF(!dict)) { - return NS_ERROR_FAILURE; - } - - NSString* printerName = [dict objectForKey: NSPrintPrinterName]; - if (printerName) { - nsCocoaUtils::GetStringForNSString(printerName, data->printerName()); - } - - NSString* faxNumber = [dict objectForKey: NSPrintFaxNumber]; - if (faxNumber) { - nsCocoaUtils::GetStringForNSString(faxNumber, data->faxNumber()); - } - - NSURL* printToFileURL = [dict objectForKey: NSPrintJobSavingURL]; - if (printToFileURL) { - nsCocoaUtils::GetStringForNSString([printToFileURL absoluteString], - data->toFileName()); - } - - NSDate* printTime = [dict objectForKey: NSPrintTime]; - if (printTime) { - NSTimeInterval timestamp = [printTime timeIntervalSinceReferenceDate]; - data->printTime() = timestamp; - } - - NSString* disposition = [dict objectForKey: NSPrintJobDisposition]; - if (disposition) { - nsCocoaUtils::GetStringForNSString(disposition, data->disposition()); - } - - NSString* paperName = [dict objectForKey: NSPrintPaperName]; - if (paperName) { - nsCocoaUtils::GetStringForNSString(paperName, data->paperName()); - } - - float scalingFactor = [[dict objectForKey: NSPrintScalingFactor] floatValue]; - data->scalingFactor() = scalingFactor; - - int32_t orientation; - if ([printInfo orientation] == NS_PAPER_ORIENTATION_PORTRAIT) { - orientation = nsIPrintSettings::kPortraitOrientation; - } else { - orientation = nsIPrintSettings::kLandscapeOrientation; - } - data->orientation() = orientation; - - NSSize paperSize = [printInfo paperSize]; - float widthScale, heightScale; - settingsX->GetInchesScale(&widthScale, &heightScale); - if (orientation == nsIPrintSettings::kLandscapeOrientation) { - // switch widths and heights - data->widthScale() = heightScale; - data->heightScale() = widthScale; - data->paperWidth() = paperSize.height / heightScale; - data->paperHeight() = paperSize.width / widthScale; - } else { - data->widthScale() = widthScale; - data->heightScale() = heightScale; - data->paperWidth() = paperSize.width / widthScale; - data->paperHeight() = paperSize.height / heightScale; - } - - data->numCopies() = [[dict objectForKey: NSPrintCopies] intValue]; - data->printAllPages() = [[dict objectForKey: NSPrintAllPages] boolValue]; - data->startPageRange() = [[dict objectForKey: NSPrintFirstPage] intValue]; - data->endPageRange() = [[dict objectForKey: NSPrintLastPage] intValue]; - data->mustCollate() = [[dict objectForKey: NSPrintMustCollate] boolValue]; - data->printReversed() = [[dict objectForKey: NSPrintReversePageOrder] boolValue]; - data->pagesAcross() = [[dict objectForKey: NSPrintPagesAcross] unsignedShortValue]; - data->pagesDown() = [[dict objectForKey: NSPrintPagesDown] unsignedShortValue]; - data->detailedErrorReporting() = [[dict objectForKey: NSPrintDetailedErrorReporting] boolValue]; - data->addHeaderAndFooter() = [[dict objectForKey: NSPrintHeaderAndFooter] boolValue]; - data->fileNameExtensionHidden() = - [[dict objectForKey: NSPrintJobSavingFileNameExtensionHidden] boolValue]; - - bool printSelectionOnly = [[dict objectForKey: NSPrintSelectionOnly] boolValue]; - aSettings->SetPrintOptions(nsIPrintSettings::kEnableSelectionRB, - printSelectionOnly); - aSettings->GetPrintOptionsBits(&data->optionFlags()); - - return NS_OK; -} - -NS_IMETHODIMP -nsPrintOptionsX::DeserializeToPrintSettings(const PrintData& data, - nsIPrintSettings* settings) -{ - nsresult rv = nsPrintOptions::DeserializeToPrintSettings(data, settings); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - RefPtr settingsX(do_QueryObject(settings)); - if (NS_WARN_IF(!settingsX)) { - return NS_ERROR_FAILURE; - } - - NSPrintInfo* sharedPrintInfo = [NSPrintInfo sharedPrintInfo]; - if (NS_WARN_IF(!sharedPrintInfo)) { - return NS_ERROR_FAILURE; - } - - NSDictionary* sharedDict = [sharedPrintInfo dictionary]; - if (NS_WARN_IF(!sharedDict)) { - return NS_ERROR_FAILURE; - } - - // We need to create a new NSMutableDictionary to pass to NSPrintInfo with - // the values that we got from the other process. - NSMutableDictionary* newPrintInfoDict = - [NSMutableDictionary dictionaryWithDictionary:sharedDict]; - if (NS_WARN_IF(!newPrintInfoDict)) { - return NS_ERROR_OUT_OF_MEMORY; - } - - NSString* printerName = nsCocoaUtils::ToNSString(data.printerName()); - if (printerName) { - NSPrinter* printer = [NSPrinter printerWithName: printerName]; - if (printer) { - [newPrintInfoDict setObject: printer forKey: NSPrintPrinter]; - [newPrintInfoDict setObject: printerName forKey: NSPrintPrinterName]; - } - } - - [newPrintInfoDict setObject: [NSNumber numberWithInt: data.numCopies()] - forKey: NSPrintCopies]; - [newPrintInfoDict setObject: [NSNumber numberWithBool: data.printAllPages()] - forKey: NSPrintAllPages]; - [newPrintInfoDict setObject: [NSNumber numberWithInt: data.startPageRange()] - forKey: NSPrintFirstPage]; - [newPrintInfoDict setObject: [NSNumber numberWithInt: data.endPageRange()] - forKey: NSPrintLastPage]; - [newPrintInfoDict setObject: [NSNumber numberWithBool: data.mustCollate()] - forKey: NSPrintMustCollate]; - [newPrintInfoDict setObject: [NSNumber numberWithBool: data.printReversed()] - forKey: NSPrintReversePageOrder]; - - [newPrintInfoDict setObject: nsCocoaUtils::ToNSString(data.disposition()) - forKey: NSPrintJobDisposition]; - - [newPrintInfoDict setObject: nsCocoaUtils::ToNSString(data.paperName()) - forKey: NSPrintPaperName]; - - [newPrintInfoDict setObject: [NSNumber numberWithFloat: data.scalingFactor()] - forKey: NSPrintScalingFactor]; - - CGFloat width = data.paperWidth() * data.widthScale(); - CGFloat height = data.paperHeight() * data.heightScale(); - [newPrintInfoDict setObject: [NSValue valueWithSize:NSMakeSize(width,height)] - forKey: NSPrintPaperSize]; - - int paperOrientation; - if (data.orientation() == nsIPrintSettings::kPortraitOrientation) { - paperOrientation = NS_PAPER_ORIENTATION_PORTRAIT; - settings->SetOrientation(nsIPrintSettings::kPortraitOrientation); - } else { - paperOrientation = NS_PAPER_ORIENTATION_LANDSCAPE; - settings->SetOrientation(nsIPrintSettings::kLandscapeOrientation); - } - [newPrintInfoDict setObject: [NSNumber numberWithInt:paperOrientation] - forKey: NSPrintOrientation]; - - [newPrintInfoDict setObject: [NSNumber numberWithShort: data.pagesAcross()] - forKey: NSPrintPagesAcross]; - [newPrintInfoDict setObject: [NSNumber numberWithShort: data.pagesDown()] - forKey: NSPrintPagesDown]; - [newPrintInfoDict setObject: [NSNumber numberWithBool: data.detailedErrorReporting()] - forKey: NSPrintDetailedErrorReporting]; - [newPrintInfoDict setObject: nsCocoaUtils::ToNSString(data.faxNumber()) - forKey: NSPrintFaxNumber]; - [newPrintInfoDict setObject: [NSNumber numberWithBool: data.addHeaderAndFooter()] - forKey: NSPrintHeaderAndFooter]; - [newPrintInfoDict setObject: [NSNumber numberWithBool: data.fileNameExtensionHidden()] - forKey: NSPrintJobSavingFileNameExtensionHidden]; - - // At this point, the base class should have properly deserialized the print - // options bitfield for nsIPrintSettings, so that it holds the correct value - // for kEnableSelectionRB, which we use to set NSPrintSelectionOnly. - - bool printSelectionOnly = false; - rv = settings->GetPrintOptions(nsIPrintSettings::kEnableSelectionRB, &printSelectionOnly); - if (NS_SUCCEEDED(rv)) { - [newPrintInfoDict setObject: [NSNumber numberWithBool: printSelectionOnly] - forKey: NSPrintSelectionOnly]; - } else { - [newPrintInfoDict setObject: [NSNumber numberWithBool: NO] - forKey: NSPrintSelectionOnly]; - } - - NSURL* jobSavingURL = - [NSURL URLWithString: nsCocoaUtils::ToNSString(data.toFileName())]; - if (jobSavingURL) { - [newPrintInfoDict setObject: jobSavingURL forKey: NSPrintJobSavingURL]; - } - - NSTimeInterval timestamp = data.printTime(); - NSDate* printTime = [NSDate dateWithTimeIntervalSinceReferenceDate: timestamp]; - if (printTime) { - [newPrintInfoDict setObject: printTime forKey: NSPrintTime]; - } - - // Next, we create a new NSPrintInfo with the values in our dictionary. - NSPrintInfo* newPrintInfo = - [[NSPrintInfo alloc] initWithDictionary: newPrintInfoDict]; - if (NS_WARN_IF(!newPrintInfo)) { - return NS_ERROR_OUT_OF_MEMORY; - } - - // And now swap in the new NSPrintInfo we've just populated. - settingsX->SetCocoaPrintInfo(newPrintInfo); - [newPrintInfo release]; - - settingsX->SetAdjustedPaperSize(data.adjustedPaperWidth(), - data.adjustedPaperHeight()); - - return NS_OK; -} - -nsresult -nsPrintOptionsX::ReadPrefs(nsIPrintSettings* aPS, const nsAString& aPrinterName, uint32_t aFlags) -{ - nsresult rv; - - rv = nsPrintOptions::ReadPrefs(aPS, aPrinterName, aFlags); - NS_ASSERTION(NS_SUCCEEDED(rv), "nsPrintOptions::ReadPrefs() failed"); - - RefPtr printSettingsX(do_QueryObject(aPS)); - if (!printSettingsX) - return NS_ERROR_NO_INTERFACE; - rv = printSettingsX->ReadPageFormatFromPrefs(); - - return NS_OK; -} - -nsresult nsPrintOptionsX::_CreatePrintSettings(nsIPrintSettings **_retval) -{ - nsresult rv; - *_retval = nullptr; - - nsPrintSettingsX* printSettings = new nsPrintSettingsX; // does not initially ref count - NS_ENSURE_TRUE(printSettings, NS_ERROR_OUT_OF_MEMORY); - NS_ADDREF(*_retval = printSettings); - - rv = printSettings->Init(); - if (NS_FAILED(rv)) { - NS_RELEASE(*_retval); - return rv; - } - - InitPrintSettingsFromPrefs(*_retval, false, nsIPrintSettings::kInitSaveAll); - return rv; -} - -nsresult -nsPrintOptionsX::WritePrefs(nsIPrintSettings* aPS, const nsAString& aPrinterName, uint32_t aFlags) -{ - nsresult rv; - - rv = nsPrintOptions::WritePrefs(aPS, aPrinterName, aFlags); - NS_ASSERTION(NS_SUCCEEDED(rv), "nsPrintOptions::WritePrefs() failed"); - - RefPtr printSettingsX(do_QueryObject(aPS)); - if (!printSettingsX) - return NS_ERROR_NO_INTERFACE; - rv = printSettingsX->WritePageFormatToPrefs(); - NS_ASSERTION(NS_SUCCEEDED(rv), "nsPrintSettingsX::WritePageFormatToPrefs() failed"); - - return NS_OK; -} diff --git a/widget/cocoa/nsPrintSettingsX.h b/widget/cocoa/nsPrintSettingsX.h deleted file mode 100644 index 1d755b2505..0000000000 --- a/widget/cocoa/nsPrintSettingsX.h +++ /dev/null @@ -1,82 +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 nsPrintSettingsX_h_ -#define nsPrintSettingsX_h_ - -#include "nsPrintSettingsImpl.h" -#import - -#define NS_PRINTSETTINGSX_IID \ -{ 0x0DF2FDBD, 0x906D, 0x4726, \ - { 0x9E, 0x4D, 0xCF, 0xE0, 0x87, 0x8D, 0x70, 0x7C } } - -class nsPrintSettingsX : public nsPrintSettings -{ -public: - NS_DECLARE_STATIC_IID_ACCESSOR(NS_PRINTSETTINGSX_IID) - NS_DECL_ISUPPORTS_INHERITED - - nsPrintSettingsX(); - nsresult Init(); - NSPrintInfo* GetCocoaPrintInfo() { return mPrintInfo; } - void SetCocoaPrintInfo(NSPrintInfo* aPrintInfo); - virtual nsresult ReadPageFormatFromPrefs(); - virtual nsresult WritePageFormatToPrefs(); - virtual nsresult GetEffectivePageSize(double *aWidth, - double *aHeight) override; - - // In addition to setting the paper width and height, these - // overrides set the adjusted width and height returned from - // GetEffectivePageSize. This is needed when a paper size is - // set manually without using a print dialog a la reftest-print. - virtual nsresult SetPaperWidth(double aPaperWidth) override; - virtual nsresult SetPaperHeight(double aPaperWidth) override; - - PMPrintSettings GetPMPrintSettings(); - PMPrintSession GetPMPrintSession(); - PMPageFormat GetPMPageFormat(); - void SetPMPageFormat(PMPageFormat aPageFormat); - - // Re-initialize mUnwriteableMargin with values from mPageFormat. - // Should be called whenever mPageFormat is initialized or overwritten. - nsresult InitUnwriteableMargin(); - - // Re-initialize mAdjustedPaper{Width,Height} with values from mPageFormat. - // Should be called whenever mPageFormat is initialized or overwritten. - nsresult InitAdjustedPaperSize(); - - void SetInchesScale(float aWidthScale, float aHeightScale); - void GetInchesScale(float *aWidthScale, float *aHeightScale); - - void SetAdjustedPaperSize(double aWidth, double aHeight); - void GetAdjustedPaperSize(double *aWidth, double *aHeight); - -protected: - virtual ~nsPrintSettingsX(); - - nsPrintSettingsX(const nsPrintSettingsX& src); - nsPrintSettingsX& operator=(const nsPrintSettingsX& rhs); - - nsresult _Clone(nsIPrintSettings **_retval) override; - nsresult _Assign(nsIPrintSettings *aPS) override; - - // The out param has a ref count of 1 on return so caller needs to PMRelase() when done. - OSStatus CreateDefaultPageFormat(PMPrintSession aSession, PMPageFormat& outFormat); - OSStatus CreateDefaultPrintSettings(PMPrintSession aSession, PMPrintSettings& outSettings); - - NSPrintInfo* mPrintInfo; - - // Scaling factors used to convert the NSPrintInfo - // paper size units to inches - float mWidthScale; - float mHeightScale; - double mAdjustedPaperWidth; - double mAdjustedPaperHeight; -}; - -NS_DEFINE_STATIC_IID_ACCESSOR(nsPrintSettingsX, NS_PRINTSETTINGSX_IID) - -#endif // nsPrintSettingsX_h_ diff --git a/widget/cocoa/nsPrintSettingsX.mm b/widget/cocoa/nsPrintSettingsX.mm deleted file mode 100644 index 73a8e78d2b..0000000000 --- a/widget/cocoa/nsPrintSettingsX.mm +++ /dev/null @@ -1,272 +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 "nsPrintSettingsX.h" -#include "nsObjCExceptions.h" - -#include "plbase64.h" -#include "plstr.h" - -#include "nsCocoaUtils.h" - -#include "mozilla/Preferences.h" - -using namespace mozilla; - -#define MAC_OS_X_PAGE_SETUP_PREFNAME "print.macosx.pagesetup-2" -#define COCOA_PAPER_UNITS_PER_INCH 72.0 - -NS_IMPL_ISUPPORTS_INHERITED(nsPrintSettingsX, nsPrintSettings, nsPrintSettingsX) - -nsPrintSettingsX::nsPrintSettingsX() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - mPrintInfo = [[NSPrintInfo sharedPrintInfo] copy]; - mWidthScale = COCOA_PAPER_UNITS_PER_INCH; - mHeightScale = COCOA_PAPER_UNITS_PER_INCH; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsPrintSettingsX::nsPrintSettingsX(const nsPrintSettingsX& src) -{ - *this = src; -} - -nsPrintSettingsX::~nsPrintSettingsX() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mPrintInfo release]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsPrintSettingsX& nsPrintSettingsX::operator=(const nsPrintSettingsX& rhs) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - if (this == &rhs) { - return *this; - } - - nsPrintSettings::operator=(rhs); - - [mPrintInfo release]; - mPrintInfo = [rhs.mPrintInfo copy]; - - return *this; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(*this); -} - -nsresult nsPrintSettingsX::Init() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - InitUnwriteableMargin(); - InitAdjustedPaperSize(); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -// Should be called whenever the page format changes. -NS_IMETHODIMP nsPrintSettingsX::InitUnwriteableMargin() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - PMPaper paper; - PMPaperMargins paperMargin; - PMPageFormat pageFormat = GetPMPageFormat(); - ::PMGetPageFormatPaper(pageFormat, &paper); - ::PMPaperGetMargins(paper, &paperMargin); - mUnwriteableMargin.top = NS_POINTS_TO_INT_TWIPS(paperMargin.top); - mUnwriteableMargin.left = NS_POINTS_TO_INT_TWIPS(paperMargin.left); - mUnwriteableMargin.bottom = NS_POINTS_TO_INT_TWIPS(paperMargin.bottom); - mUnwriteableMargin.right = NS_POINTS_TO_INT_TWIPS(paperMargin.right); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP nsPrintSettingsX::InitAdjustedPaperSize() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - PMPageFormat pageFormat = GetPMPageFormat(); - - PMRect paperRect; - ::PMGetAdjustedPaperRect(pageFormat, &paperRect); - - mAdjustedPaperWidth = paperRect.right - paperRect.left; - mAdjustedPaperHeight = paperRect.bottom - paperRect.top; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -void -nsPrintSettingsX::SetCocoaPrintInfo(NSPrintInfo* aPrintInfo) -{ - if (mPrintInfo != aPrintInfo) { - [mPrintInfo release]; - mPrintInfo = [aPrintInfo retain]; - } -} - -NS_IMETHODIMP nsPrintSettingsX::ReadPageFormatFromPrefs() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - nsAutoCString encodedData; - nsresult rv = - Preferences::GetCString(MAC_OS_X_PAGE_SETUP_PREFNAME, &encodedData); - if (NS_FAILED(rv)) { - return rv; - } - - // decode the base64 - char* decodedData = PL_Base64Decode(encodedData.get(), encodedData.Length(), nullptr); - NSData* data = [NSData dataWithBytes:decodedData length:strlen(decodedData)]; - if (!data) - return NS_ERROR_FAILURE; - - PMPageFormat newPageFormat; - OSStatus status = ::PMPageFormatCreateWithDataRepresentation((CFDataRef)data, &newPageFormat); - if (status == noErr) { - SetPMPageFormat(newPageFormat); - } - InitUnwriteableMargin(); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP nsPrintSettingsX::WritePageFormatToPrefs() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - PMPageFormat pageFormat = GetPMPageFormat(); - if (pageFormat == kPMNoPageFormat) - return NS_ERROR_NOT_INITIALIZED; - - NSData* data = nil; - OSStatus err = ::PMPageFormatCreateDataRepresentation(pageFormat, (CFDataRef*)&data, kPMDataFormatXMLDefault); - if (err != noErr) - return NS_ERROR_FAILURE; - - nsAutoCString encodedData; - encodedData.Adopt(PL_Base64Encode((char*)[data bytes], [data length], nullptr)); - if (!encodedData.get()) - return NS_ERROR_OUT_OF_MEMORY; - - return Preferences::SetCString(MAC_OS_X_PAGE_SETUP_PREFNAME, encodedData); - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -nsresult nsPrintSettingsX::_Clone(nsIPrintSettings **_retval) -{ - NS_ENSURE_ARG_POINTER(_retval); - *_retval = nullptr; - - nsPrintSettingsX *newSettings = new nsPrintSettingsX(*this); - if (!newSettings) - return NS_ERROR_FAILURE; - *_retval = newSettings; - NS_ADDREF(*_retval); - return NS_OK; -} - -NS_IMETHODIMP nsPrintSettingsX::_Assign(nsIPrintSettings *aPS) -{ - nsPrintSettingsX *printSettingsX = static_cast(aPS); - if (!printSettingsX) - return NS_ERROR_UNEXPECTED; - *this = *printSettingsX; - return NS_OK; -} - -PMPrintSettings -nsPrintSettingsX::GetPMPrintSettings() -{ - return static_cast([mPrintInfo PMPrintSettings]); -} - -PMPrintSession -nsPrintSettingsX::GetPMPrintSession() -{ - return static_cast([mPrintInfo PMPrintSession]); -} - -PMPageFormat -nsPrintSettingsX::GetPMPageFormat() -{ - return static_cast([mPrintInfo PMPageFormat]); -} - -void -nsPrintSettingsX::SetPMPageFormat(PMPageFormat aPageFormat) -{ - PMPageFormat oldPageFormat = GetPMPageFormat(); - ::PMCopyPageFormat(aPageFormat, oldPageFormat); - [mPrintInfo updateFromPMPageFormat]; -} - -void -nsPrintSettingsX::SetInchesScale(float aWidthScale, float aHeightScale) -{ - if (aWidthScale > 0 && aHeightScale > 0) { - mWidthScale = aWidthScale; - mHeightScale = aHeightScale; - } -} - -void -nsPrintSettingsX::GetInchesScale(float *aWidthScale, float *aHeightScale) -{ - *aWidthScale = mWidthScale; - *aHeightScale = mHeightScale; -} - -NS_IMETHODIMP nsPrintSettingsX::SetPaperWidth(double aPaperWidth) -{ - mPaperWidth = aPaperWidth; - mAdjustedPaperWidth = aPaperWidth * mWidthScale; - return NS_OK; -} - -NS_IMETHODIMP nsPrintSettingsX::SetPaperHeight(double aPaperHeight) -{ - mPaperHeight = aPaperHeight; - mAdjustedPaperHeight = aPaperHeight * mHeightScale; - return NS_OK; -} - -NS_IMETHODIMP -nsPrintSettingsX::GetEffectivePageSize(double *aWidth, double *aHeight) -{ - *aWidth = NS_INCHES_TO_TWIPS(mAdjustedPaperWidth / mWidthScale); - *aHeight = NS_INCHES_TO_TWIPS(mAdjustedPaperHeight / mHeightScale); - return NS_OK; -} - -void nsPrintSettingsX::SetAdjustedPaperSize(double aWidth, double aHeight) -{ - mAdjustedPaperWidth = aWidth; - mAdjustedPaperHeight = aHeight; -} - -void nsPrintSettingsX::GetAdjustedPaperSize(double *aWidth, double *aHeight) -{ - *aWidth = mAdjustedPaperWidth; - *aHeight = mAdjustedPaperHeight; -} diff --git a/widget/cocoa/nsSandboxViolationSink.h b/widget/cocoa/nsSandboxViolationSink.h deleted file mode 100644 index 35b5d89af5..0000000000 --- a/widget/cocoa/nsSandboxViolationSink.h +++ /dev/null @@ -1,36 +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 nsSandboxViolationSink_h_ -#define nsSandboxViolationSink_h_ - -#include - -// Class for tracking sandbox violations. Currently it just logs them to -// stdout and the system console. In the future it may do more. - -// What makes this possible is the fact that Apple' sandboxd calls -// notify_post("com.apple.sandbox.violation.*") whenever it's notified by the -// Sandbox kernel extension of a sandbox violation. We register to receive -// these notifications. But the notifications are empty, and are sent for -// every violation in every process. So we need to do more to get only "our" -// violations, and to find out what kind of violation they were. See the -// implementation of nsSandboxViolationSink::ViolationHandler(). - -#define SANDBOX_VIOLATION_QUEUE_NAME "org.mozilla.sandbox.violation.queue" -#define SANDBOX_VIOLATION_NOTIFICATION_NAME "com.apple.sandbox.violation.*" - -class nsSandboxViolationSink -{ -public: - static void Start(); - static void Stop(); -private: - static void ViolationHandler(); - static int mNotifyToken; - static uint64_t mLastMsgReceived; -}; - -#endif // nsSandboxViolationSink_h_ diff --git a/widget/cocoa/nsSandboxViolationSink.mm b/widget/cocoa/nsSandboxViolationSink.mm deleted file mode 100644 index 0572173344..0000000000 --- a/widget/cocoa/nsSandboxViolationSink.mm +++ /dev/null @@ -1,115 +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 "nsSandboxViolationSink.h" - -#include -#include -#include -#include -#include -#include "nsCocoaDebugUtils.h" -#include "mozilla/Preferences.h" -#include "mozilla/Sprintf.h" - -int nsSandboxViolationSink::mNotifyToken = 0; -uint64_t nsSandboxViolationSink::mLastMsgReceived = 0; - -void -nsSandboxViolationSink::Start() -{ - if (mNotifyToken) { - return; - } - notify_register_dispatch(SANDBOX_VIOLATION_NOTIFICATION_NAME, - &mNotifyToken, - dispatch_queue_create(SANDBOX_VIOLATION_QUEUE_NAME, - DISPATCH_QUEUE_SERIAL), - ^(int token) { ViolationHandler(); }); -} - -void -nsSandboxViolationSink::Stop() -{ - if (!mNotifyToken) { - return; - } - notify_cancel(mNotifyToken); - mNotifyToken = 0; -} - -// We need to query syslogd to find out what violations occurred, and whether -// they were "ours". We can use the Apple System Log facility to do this. -// Besides calling notify_post("com.apple.sandbox.violation.*"), Apple's -// sandboxd also reports all sandbox violations (sent to it by the Sandbox -// kernel extension) to syslogd, which stores them and makes them viewable -// in the system console. This is the database we query. - -// ViolationHandler() is always called on its own secondary thread. This -// makes it unlikely it will interfere with other browser activity. - -void -nsSandboxViolationSink::ViolationHandler() -{ - aslmsg query = asl_new(ASL_TYPE_QUERY); - - asl_set_query(query, ASL_KEY_FACILITY, "com.apple.sandbox", - ASL_QUERY_OP_EQUAL); - - // Only get reports that were generated very recently. - char query_time[30] = {0}; - SprintfLiteral(query_time, "%li", time(NULL) - 2); - asl_set_query(query, ASL_KEY_TIME, query_time, - ASL_QUERY_OP_NUMERIC | ASL_QUERY_OP_GREATER_EQUAL); - - // This code is easier to test if we don't just track "our" violations, - // which are (normally) few and far between. For example (for the time - // being at least) four appleeventsd sandbox violations happen every time - // we start the browser in e10s mode. But it makes sense to default to - // only tracking "our" violations. - if (mozilla::Preferences::GetBool( - "security.sandbox.mac.track.violations.oursonly", true)) { - // This makes each of our processes log its own violations. It might - // be better to make the chrome process log all the other processes' - // violations. - char query_pid[20] = {0}; - SprintfLiteral(query_pid, "%u", getpid()); - asl_set_query(query, ASL_KEY_REF_PID, query_pid, ASL_QUERY_OP_EQUAL); - } - - aslresponse response = asl_search(nullptr, query); - - // Each time ViolationHandler() is called we grab as many messages as are - // available. Otherwise we might not get them all. - if (response) { - while (true) { - aslmsg hit = nullptr; - aslmsg found = nullptr; - const char* id_str; - - while ((hit = aslresponse_next(response))) { - // Record the message id to avoid logging the same violation more - // than once. - id_str = asl_get(hit, ASL_KEY_MSG_ID); - uint64_t id_val = atoll(id_str); - if (id_val <= mLastMsgReceived) { - continue; - } - mLastMsgReceived = id_val; - found = hit; - break; - } - if (!found) { - break; - } - - const char* pid_str = asl_get(found, ASL_KEY_REF_PID); - const char* message_str = asl_get(found, ASL_KEY_MSG); - nsCocoaDebugUtils::DebugLog("nsSandboxViolationSink::ViolationHandler(): id %s, pid %s, message %s", - id_str, pid_str, message_str); - } - aslresponse_free(response); - } -} diff --git a/widget/cocoa/nsScreenCocoa.h b/widget/cocoa/nsScreenCocoa.h deleted file mode 100644 index 268d5beb0a..0000000000 --- a/widget/cocoa/nsScreenCocoa.h +++ /dev/null @@ -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 nsScreenCocoa_h_ -#define nsScreenCocoa_h_ - -#import - -#include "nsBaseScreen.h" - -class nsScreenCocoa : public nsBaseScreen -{ -public: - explicit nsScreenCocoa (NSScreen *screen); - ~nsScreenCocoa (); - - NS_IMETHOD GetId(uint32_t* outId); - NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight); - NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight); - NS_IMETHOD GetRectDisplayPix(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight); - NS_IMETHOD GetAvailRectDisplayPix(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight); - NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth); - NS_IMETHOD GetColorDepth(int32_t* aColorDepth); - NS_IMETHOD GetContentsScaleFactor(double* aContentsScaleFactor); - NS_IMETHOD GetDefaultCSSScaleFactor(double* aScaleFactor) - { - return GetContentsScaleFactor(aScaleFactor); - } - - NSScreen *CocoaScreen() { return mScreen; } - -private: - CGFloat BackingScaleFactor(); - - NSScreen *mScreen; - uint32_t mId; -}; - -#endif // nsScreenCocoa_h_ diff --git a/widget/cocoa/nsScreenCocoa.mm b/widget/cocoa/nsScreenCocoa.mm deleted file mode 100644 index 08905bf0ad..0000000000 --- a/widget/cocoa/nsScreenCocoa.mm +++ /dev/null @@ -1,147 +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 "nsScreenCocoa.h" -#include "nsObjCExceptions.h" -#include "nsCocoaUtils.h" - -static uint32_t sScreenId = 0; - -nsScreenCocoa::nsScreenCocoa (NSScreen *screen) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - mScreen = [screen retain]; - mId = ++sScreenId; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsScreenCocoa::~nsScreenCocoa () -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mScreen release]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -NS_IMETHODIMP -nsScreenCocoa::GetId(uint32_t *outId) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - *outId = mId; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -NS_IMETHODIMP -nsScreenCocoa::GetRect(int32_t *outX, int32_t *outY, int32_t *outWidth, int32_t *outHeight) -{ - NSRect frame = [mScreen frame]; - - mozilla::LayoutDeviceIntRect r = - nsCocoaUtils::CocoaRectToGeckoRectDevPix(frame, BackingScaleFactor()); - - *outX = r.x; - *outY = r.y; - *outWidth = r.width; - *outHeight = r.height; - - return NS_OK; -} - -NS_IMETHODIMP -nsScreenCocoa::GetAvailRect(int32_t *outX, int32_t *outY, int32_t *outWidth, int32_t *outHeight) -{ - NSRect frame = [mScreen visibleFrame]; - - mozilla::LayoutDeviceIntRect r = - nsCocoaUtils::CocoaRectToGeckoRectDevPix(frame, BackingScaleFactor()); - - *outX = r.x; - *outY = r.y; - *outWidth = r.width; - *outHeight = r.height; - - return NS_OK; -} - -NS_IMETHODIMP -nsScreenCocoa::GetRectDisplayPix(int32_t *outX, int32_t *outY, int32_t *outWidth, int32_t *outHeight) -{ - NSRect frame = [mScreen frame]; - - mozilla::DesktopIntRect r = nsCocoaUtils::CocoaRectToGeckoRect(frame); - - *outX = r.x; - *outY = r.y; - *outWidth = r.width; - *outHeight = r.height; - - return NS_OK; -} - -NS_IMETHODIMP -nsScreenCocoa::GetAvailRectDisplayPix(int32_t *outX, int32_t *outY, int32_t *outWidth, int32_t *outHeight) -{ - NSRect frame = [mScreen visibleFrame]; - - mozilla::DesktopIntRect r = nsCocoaUtils::CocoaRectToGeckoRect(frame); - - *outX = r.x; - *outY = r.y; - *outWidth = r.width; - *outHeight = r.height; - - return NS_OK; -} - -NS_IMETHODIMP -nsScreenCocoa::GetPixelDepth(int32_t *aPixelDepth) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NSWindowDepth depth = [mScreen depth]; - int bpp = NSBitsPerPixelFromDepth(depth); - - *aPixelDepth = bpp; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsScreenCocoa::GetColorDepth(int32_t *aColorDepth) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NSWindowDepth depth = [mScreen depth]; - int bpp = NSBitsPerPixelFromDepth (depth); - - *aColorDepth = bpp; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsScreenCocoa::GetContentsScaleFactor(double *aContentsScaleFactor) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - *aContentsScaleFactor = (double) BackingScaleFactor(); - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -CGFloat -nsScreenCocoa::BackingScaleFactor() -{ - return nsCocoaUtils::GetBackingScaleFactor(mScreen); -} diff --git a/widget/cocoa/nsScreenManagerCocoa.h b/widget/cocoa/nsScreenManagerCocoa.h deleted file mode 100644 index 61a059d977..0000000000 --- a/widget/cocoa/nsScreenManagerCocoa.h +++ /dev/null @@ -1,33 +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 nsScreenManagerCocoa_h_ -#define nsScreenManagerCocoa_h_ - -#import - -#include "mozilla/RefPtr.h" -#include "nsTArray.h" -#include "nsIScreenManager.h" -#include "nsScreenCocoa.h" - -class nsScreenManagerCocoa : public nsIScreenManager -{ -public: - nsScreenManagerCocoa(); - - NS_DECL_ISUPPORTS - NS_DECL_NSISCREENMANAGER - -protected: - virtual ~nsScreenManagerCocoa(); - -private: - - nsScreenCocoa *ScreenForCocoaScreen(NSScreen *screen); - nsTArray< RefPtr > mScreenList; -}; - -#endif // nsScreenManagerCocoa_h_ diff --git a/widget/cocoa/nsScreenManagerCocoa.mm b/widget/cocoa/nsScreenManagerCocoa.mm deleted file mode 100644 index 9a0cbb9cc5..0000000000 --- a/widget/cocoa/nsScreenManagerCocoa.mm +++ /dev/null @@ -1,152 +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 "nsScreenManagerCocoa.h" -#include "nsObjCExceptions.h" -#include "nsCOMPtr.h" -#include "nsCocoaUtils.h" - -using namespace mozilla; - -NS_IMPL_ISUPPORTS(nsScreenManagerCocoa, nsIScreenManager) - -nsScreenManagerCocoa::nsScreenManagerCocoa() -{ -} - -nsScreenManagerCocoa::~nsScreenManagerCocoa() -{ -} - -nsScreenCocoa* -nsScreenManagerCocoa::ScreenForCocoaScreen(NSScreen *screen) -{ - for (uint32_t i = 0; i < mScreenList.Length(); ++i) { - nsScreenCocoa* sc = mScreenList[i]; - if (sc->CocoaScreen() == screen) { - // doesn't addref - return sc; - } - } - - // didn't find it; create and insert - RefPtr sc = new nsScreenCocoa(screen); - mScreenList.AppendElement(sc); - return sc.get(); -} - -NS_IMETHODIMP -nsScreenManagerCocoa::ScreenForId (uint32_t aId, nsIScreen **outScreen) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT - - *outScreen = nullptr; - - for (uint32_t i = 0; i < mScreenList.Length(); ++i) { - nsScreenCocoa* sc = mScreenList[i]; - uint32_t id; - nsresult rv = sc->GetId(&id); - - if (NS_SUCCEEDED(rv) && id == aId) { - *outScreen = sc; - NS_ADDREF(*outScreen); - return NS_OK; - } - } - - return NS_ERROR_FAILURE; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsScreenManagerCocoa::ScreenForRect (int32_t aX, int32_t aY, - int32_t aWidth, int32_t aHeight, - nsIScreen **outScreen) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NSEnumerator *screenEnum = [[NSScreen screens] objectEnumerator]; - NSRect inRect = - nsCocoaUtils::GeckoRectToCocoaRect(DesktopIntRect(aX, aY, - aWidth, aHeight)); - NSScreen *screenWindowIsOn = [NSScreen mainScreen]; - float greatestArea = 0; - - while (NSScreen *screen = [screenEnum nextObject]) { - NSDictionary *desc = [screen deviceDescription]; - if ([desc objectForKey:NSDeviceIsScreen] == nil) - continue; - - NSRect r = NSIntersectionRect([screen frame], inRect); - float area = r.size.width * r.size.height; - if (area > greatestArea) { - greatestArea = area; - screenWindowIsOn = screen; - } - } - - *outScreen = ScreenForCocoaScreen(screenWindowIsOn); - NS_ADDREF(*outScreen); - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsScreenManagerCocoa::GetPrimaryScreen (nsIScreen **outScreen) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - // the mainScreen is the screen with the "key window" (focus, I assume?) - NSScreen *sc = [[NSScreen screens] objectAtIndex:0]; - - *outScreen = ScreenForCocoaScreen(sc); - NS_ADDREF(*outScreen); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsScreenManagerCocoa::GetNumberOfScreens (uint32_t *aNumberOfScreens) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NSArray *ss = [NSScreen screens]; - - *aNumberOfScreens = [ss count]; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsScreenManagerCocoa::GetSystemDefaultScale(float *aDefaultScale) -{ - *aDefaultScale = 1.0f; - return NS_OK; -} - -NS_IMETHODIMP -nsScreenManagerCocoa::ScreenForNativeWidget (void *nativeWidget, nsIScreen **outScreen) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NSWindow *window = static_cast(nativeWidget); - if (window) { - nsIScreen *screen = ScreenForCocoaScreen([window screen]); - *outScreen = screen; - NS_ADDREF(*outScreen); - return NS_OK; - } - - *outScreen = nullptr; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} diff --git a/widget/cocoa/nsSound.h b/widget/cocoa/nsSound.h deleted file mode 100644 index 0e0293ae28..0000000000 --- a/widget/cocoa/nsSound.h +++ /dev/null @@ -1,27 +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 nsSound_h_ -#define nsSound_h_ - -#include "nsISound.h" -#include "nsIStreamLoader.h" - -class nsSound : public nsISound, - public nsIStreamLoaderObserver -{ -public: - nsSound(); - - NS_DECL_ISUPPORTS - NS_DECL_NSISOUND - NS_DECL_NSISTREAMLOADEROBSERVER - -protected: - virtual ~nsSound(); -}; - -#endif // nsSound_h_ diff --git a/widget/cocoa/nsSound.mm b/widget/cocoa/nsSound.mm deleted file mode 100644 index 04c6b4d764..0000000000 --- a/widget/cocoa/nsSound.mm +++ /dev/null @@ -1,108 +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 "nsSound.h" -#include "nsContentUtils.h" -#include "nsObjCExceptions.h" -#include "nsNetUtil.h" -#include "nsCOMPtr.h" -#include "nsIURL.h" -#include "nsString.h" - -#import - -NS_IMPL_ISUPPORTS(nsSound, nsISound, nsIStreamLoaderObserver) - -nsSound::nsSound() -{ -} - -nsSound::~nsSound() -{ -} - -NS_IMETHODIMP -nsSound::Beep() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NSBeep(); - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsSound::OnStreamComplete(nsIStreamLoader *aLoader, - nsISupports *context, - nsresult aStatus, - uint32_t dataLen, - const uint8_t *data) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NSData *value = [NSData dataWithBytes:data length:dataLen]; - - NSSound *sound = [[NSSound alloc] initWithData:value]; - - [sound play]; - - [sound autorelease]; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsSound::Play(nsIURL *aURL) -{ - nsCOMPtr uri(do_QueryInterface(aURL)); - nsCOMPtr loader; - return NS_NewStreamLoader(getter_AddRefs(loader), - uri, - this, // aObserver - nsContentUtils::GetSystemPrincipal(), - nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL, - nsIContentPolicy::TYPE_OTHER); -} - -NS_IMETHODIMP -nsSound::Init() -{ - return NS_OK; -} - -NS_IMETHODIMP -nsSound::PlaySystemSound(const nsAString &aSoundAlias) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (NS_IsMozAliasSound(aSoundAlias)) { - NS_WARNING("nsISound::playSystemSound is called with \"_moz_\" events, they are obsolete, use nsISound::playEventSound instead"); - // Mac doesn't have system sound settings for each user actions. - return NS_OK; - } - - NSString *name = [NSString stringWithCharacters:reinterpret_cast(aSoundAlias.BeginReading()) - length:aSoundAlias.Length()]; - NSSound *sound = [NSSound soundNamed:name]; - if (sound) { - [sound stop]; - [sound play]; - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsSound::PlayEventSound(uint32_t aEventId) -{ - // Mac doesn't have system sound settings for each user actions. - return NS_OK; -} diff --git a/widget/cocoa/nsStandaloneNativeMenu.h b/widget/cocoa/nsStandaloneNativeMenu.h deleted file mode 100644 index e03742b1e0..0000000000 --- a/widget/cocoa/nsStandaloneNativeMenu.h +++ /dev/null @@ -1,40 +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/. */ - -#ifndef nsStandaloneNativeMenu_h_ -#define nsStandaloneNativeMenu_h_ - -#include "nsMenuGroupOwnerX.h" -#include "nsMenuX.h" -#include "nsIStandaloneNativeMenu.h" - -class nsStandaloneNativeMenu : public nsMenuGroupOwnerX, public nsIStandaloneNativeMenu -{ -public: - nsStandaloneNativeMenu(); - - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSISTANDALONENATIVEMENU - - // nsMenuObjectX - nsMenuObjectTypeX MenuObjectType() override { return eStandaloneNativeMenuObjectType; } - void * NativeData() override { return mMenu != nullptr ? mMenu->NativeData() : nullptr; } - virtual void IconUpdated() override; - - nsMenuX * GetMenuXObject() { return mMenu; } - - // If this menu is the menu of a system status bar item (NSStatusItem), - // let the menu know about the status item so that it can propagate - // any icon changes to the status item. - void SetContainerStatusBarItem(NSStatusItem* aItem); - -protected: - virtual ~nsStandaloneNativeMenu(); - - nsMenuX * mMenu; - NSStatusItem* mContainerStatusBarItem; -}; - -#endif diff --git a/widget/cocoa/nsStandaloneNativeMenu.mm b/widget/cocoa/nsStandaloneNativeMenu.mm deleted file mode 100644 index 98a5fd8f6f..0000000000 --- a/widget/cocoa/nsStandaloneNativeMenu.mm +++ /dev/null @@ -1,213 +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/. */ - -#import - -#include "nsStandaloneNativeMenu.h" -#include "nsMenuUtilsX.h" -#include "nsIDOMElement.h" -#include "nsIMutationObserver.h" -#include "nsGkAtoms.h" -#include "nsObjCExceptions.h" - - -NS_IMPL_ISUPPORTS_INHERITED(nsStandaloneNativeMenu, nsMenuGroupOwnerX, - nsIMutationObserver, nsIStandaloneNativeMenu) - -nsStandaloneNativeMenu::nsStandaloneNativeMenu() -: mMenu(nullptr) -, mContainerStatusBarItem(nil) -{ -} - -nsStandaloneNativeMenu::~nsStandaloneNativeMenu() -{ - if (mMenu) delete mMenu; -} - -NS_IMETHODIMP -nsStandaloneNativeMenu::Init(nsIDOMElement * aDOMElement) -{ - NS_ASSERTION(mMenu == nullptr, "nsNativeMenu::Init - mMenu not null!"); - - nsresult rv; - - nsCOMPtr content = do_QueryInterface(aDOMElement, &rv); - NS_ENSURE_SUCCESS(rv, rv); - - if (!content->IsAnyOfXULElements(nsGkAtoms::menu, nsGkAtoms::menupopup)) - return NS_ERROR_FAILURE; - - rv = nsMenuGroupOwnerX::Create(content); - if (NS_FAILED(rv)) - return rv; - - mMenu = new nsMenuX(); - rv = mMenu->Create(this, this, content); - if (NS_FAILED(rv)) { - delete mMenu; - mMenu = nullptr; - return rv; - } - - mMenu->SetupIcon(); - - return NS_OK; -} - -static void -UpdateMenu(nsMenuX * aMenu) -{ - aMenu->MenuOpened(); - aMenu->MenuClosed(); - - uint32_t itemCount = aMenu->GetItemCount(); - for (uint32_t i = 0; i < itemCount; i++) { - nsMenuObjectX * menuObject = aMenu->GetItemAt(i); - if (menuObject->MenuObjectType() == eSubmenuObjectType) { - UpdateMenu(static_cast(menuObject)); - } - } -} - -NS_IMETHODIMP -nsStandaloneNativeMenu::MenuWillOpen(bool * aResult) -{ - NS_ASSERTION(mMenu != nullptr, "nsStandaloneNativeMenu::OnOpen - mMenu is null!"); - - // Force an update on the mMenu by faking an open/close on all of - // its submenus. - UpdateMenu(mMenu); - - *aResult = true; - return NS_OK; -} - -NS_IMETHODIMP -nsStandaloneNativeMenu::GetNativeMenu(void ** aVoidPointer) -{ - if (mMenu) { - *aVoidPointer = mMenu->NativeData(); - [[(NSObject *)(*aVoidPointer) retain] autorelease]; - return NS_OK; - } else { - *aVoidPointer = nullptr; - return NS_ERROR_NOT_INITIALIZED; - } -} - -static NSMenuItem * -NativeMenuItemWithLocation(NSMenu * currentSubmenu, NSString * locationString) -{ - NSArray * indexes = [locationString componentsSeparatedByString:@"|"]; - NSUInteger indexCount = [indexes count]; - if (indexCount == 0) - return nil; - - for (NSUInteger i = 0; i < indexCount; i++) { - NSInteger targetIndex = [[indexes objectAtIndex:i] integerValue]; - NSInteger itemCount = [currentSubmenu numberOfItems]; - if (targetIndex < itemCount) { - NSMenuItem* menuItem = [currentSubmenu itemAtIndex:targetIndex]; - - // If this is the last index, just return the menu item. - if (i == (indexCount - 1)) - return menuItem; - - // If this is not the last index, find the submenu and keep going. - if ([menuItem hasSubmenu]) - currentSubmenu = [menuItem submenu]; - else - return nil; - } - } - - return nil; -} - -NS_IMETHODIMP -nsStandaloneNativeMenu::ActivateNativeMenuItemAt(const nsAString& indexString) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (!mMenu) - return NS_ERROR_NOT_INITIALIZED; - - NSString * locationString = [NSString stringWithCharacters:reinterpret_cast(indexString.BeginReading()) - length:indexString.Length()]; - NSMenu * menu = static_cast (mMenu->NativeData()); - NSMenuItem * item = NativeMenuItemWithLocation(menu, locationString); - - // We can't perform an action on an item with a submenu, that will raise - // an obj-c exception. - if (item && ![item hasSubmenu]) { - NSMenu * parent = [item menu]; - if (parent) { - // NSLog(@"Performing action for native menu item titled: %@\n", - // [[currentSubmenu itemAtIndex:targetIndex] title]); - [parent performActionForItemAtIndex:[parent indexOfItem:item]]; - return NS_OK; - } - } - - return NS_ERROR_FAILURE; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsStandaloneNativeMenu::ForceUpdateNativeMenuAt(const nsAString& indexString) -{ - if (!mMenu) - return NS_ERROR_NOT_INITIALIZED; - - NSString* locationString = [NSString stringWithCharacters:reinterpret_cast(indexString.BeginReading()) - length:indexString.Length()]; - NSArray* indexes = [locationString componentsSeparatedByString:@"|"]; - unsigned int indexCount = [indexes count]; - if (indexCount == 0) - return NS_OK; - - nsMenuX* currentMenu = mMenu; - - // now find the correct submenu - for (unsigned int i = 1; currentMenu && i < indexCount; i++) { - int targetIndex = [[indexes objectAtIndex:i] intValue]; - int visible = 0; - uint32_t length = currentMenu->GetItemCount(); - for (unsigned int j = 0; j < length; j++) { - nsMenuObjectX* targetMenu = currentMenu->GetItemAt(j); - if (!targetMenu) - return NS_OK; - if (!nsMenuUtilsX::NodeIsHiddenOrCollapsed(targetMenu->Content())) { - visible++; - if (targetMenu->MenuObjectType() == eSubmenuObjectType && visible == (targetIndex + 1)) { - currentMenu = static_cast(targetMenu); - // fake open/close to cause lazy update to happen - currentMenu->MenuOpened(); - currentMenu->MenuClosed(); - break; - } - } - } - } - - return NS_OK; -} - -void -nsStandaloneNativeMenu::IconUpdated() -{ - if (mContainerStatusBarItem) { - [mContainerStatusBarItem setImage:[mMenu->NativeMenuItem() image]]; - } -} - -void -nsStandaloneNativeMenu::SetContainerStatusBarItem(NSStatusItem* aItem) -{ - mContainerStatusBarItem = aItem; - IconUpdated(); -} diff --git a/widget/cocoa/nsSystemStatusBarCocoa.h b/widget/cocoa/nsSystemStatusBarCocoa.h deleted file mode 100644 index 51aa4df00d..0000000000 --- a/widget/cocoa/nsSystemStatusBarCocoa.h +++ /dev/null @@ -1,40 +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/. */ - -#ifndef nsSystemStatusBarCocoa_h_ -#define nsSystemStatusBarCocoa_h_ - -#include "mozilla/RefPtr.h" -#include "nsISystemStatusBar.h" -#include "nsClassHashtable.h" - -class nsStandaloneNativeMenu; -@class NSStatusItem; - -class nsSystemStatusBarCocoa : public nsISystemStatusBar -{ -public: - nsSystemStatusBarCocoa() {} - - NS_DECL_ISUPPORTS - NS_DECL_NSISYSTEMSTATUSBAR - -protected: - virtual ~nsSystemStatusBarCocoa() {} - - struct StatusItem - { - explicit StatusItem(nsStandaloneNativeMenu* aMenu); - ~StatusItem(); - - private: - RefPtr mMenu; - NSStatusItem* mStatusItem; - }; - - nsClassHashtable mItems; -}; - -#endif // nsSystemStatusBarCocoa_h_ diff --git a/widget/cocoa/nsSystemStatusBarCocoa.mm b/widget/cocoa/nsSystemStatusBarCocoa.mm deleted file mode 100644 index 522da71451..0000000000 --- a/widget/cocoa/nsSystemStatusBarCocoa.mm +++ /dev/null @@ -1,74 +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/. */ - -#import - -#include "nsComponentManagerUtils.h" -#include "nsSystemStatusBarCocoa.h" -#include "nsStandaloneNativeMenu.h" -#include "nsObjCExceptions.h" -#include "nsIDOMElement.h" - -NS_IMPL_ISUPPORTS(nsSystemStatusBarCocoa, nsISystemStatusBar) - -NS_IMETHODIMP -nsSystemStatusBarCocoa::AddItem(nsIDOMElement* aDOMElement) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - RefPtr menu = new nsStandaloneNativeMenu(); - nsresult rv = menu->Init(aDOMElement); - if (NS_FAILED(rv)) { - return rv; - } - - nsCOMPtr keyPtr = aDOMElement; - mItems.Put(keyPtr, new StatusItem(menu)); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsSystemStatusBarCocoa::RemoveItem(nsIDOMElement* aDOMElement) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - mItems.Remove(aDOMElement); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -nsSystemStatusBarCocoa::StatusItem::StatusItem(nsStandaloneNativeMenu* aMenu) - : mMenu(aMenu) -{ - MOZ_COUNT_CTOR(nsSystemStatusBarCocoa::StatusItem); - - NSMenu* nativeMenu = nil; - mMenu->GetNativeMenu(reinterpret_cast(&nativeMenu)); - - mStatusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain]; - [mStatusItem setMenu:nativeMenu]; - [mStatusItem setHighlightMode:YES]; - - // We want the status item to get its image from menu item that mMenu was - // initialized with. Icon loads are asynchronous, so we need to let the menu - // know about the item so that it can update its icon as soon as it has - // loaded. - mMenu->SetContainerStatusBarItem(mStatusItem); -} - -nsSystemStatusBarCocoa::StatusItem::~StatusItem() -{ - mMenu->SetContainerStatusBarItem(nil); - [[NSStatusBar systemStatusBar] removeStatusItem:mStatusItem]; - [mStatusItem release]; - mStatusItem = nil; - - MOZ_COUNT_DTOR(nsSystemStatusBarCocoa::StatusItem); -} diff --git a/widget/cocoa/nsToolkit.h b/widget/cocoa/nsToolkit.h deleted file mode 100644 index 1631a8ac24..0000000000 --- a/widget/cocoa/nsToolkit.h +++ /dev/null @@ -1,53 +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 nsToolkit_h_ -#define nsToolkit_h_ - -#include "nscore.h" - -#import -#import -#import -#import - -class nsToolkit -{ -public: - nsToolkit(); - virtual ~nsToolkit(); - - static nsToolkit* GetToolkit(); - - static void Shutdown() { - delete gToolkit; - gToolkit = nullptr; - } - - static void PostSleepWakeNotification(const char* aNotification); - - static nsresult SwizzleMethods(Class aClass, SEL orgMethod, SEL posedMethod, - bool classMethods = false); - - void RegisterForAllProcessMouseEvents(); - void UnregisterAllProcessMouseEventHandlers(); - -protected: - - nsresult RegisterForSleepWakeNotifications(); - void RemoveSleepWakeNotifications(); - -protected: - - static nsToolkit* gToolkit; - - CFRunLoopSourceRef mSleepWakeNotificationRLS; - io_object_t mPowerNotifier; - - CFMachPortRef mEventTapPort; - CFRunLoopSourceRef mEventTapRLS; -}; - -#endif // nsToolkit_h_ diff --git a/widget/cocoa/nsToolkit.mm b/widget/cocoa/nsToolkit.mm deleted file mode 100644 index 4d0222d5d3..0000000000 --- a/widget/cocoa/nsToolkit.mm +++ /dev/null @@ -1,326 +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 "nsToolkit.h" - -#include -#include -#include - -#include -#include -#include - -extern "C" { -#include -} -#include -#include - -#import -#import -#import - -#include "nsCocoaUtils.h" -#include "nsObjCExceptions.h" - -#include "nsGkAtoms.h" -#include "nsIRollupListener.h" -#include "nsIWidget.h" -#include "nsBaseWidget.h" - -#include "nsIObserverService.h" -#include "nsIServiceManager.h" - -#include "mozilla/Preferences.h" -#include "mozilla/Services.h" - -using namespace mozilla; - -static io_connect_t gRootPort = MACH_PORT_NULL; - -nsToolkit* nsToolkit::gToolkit = nullptr; - -nsToolkit::nsToolkit() -: mSleepWakeNotificationRLS(nullptr) -, mEventTapPort(nullptr) -, mEventTapRLS(nullptr) -{ - MOZ_COUNT_CTOR(nsToolkit); - RegisterForSleepWakeNotifications(); -} - -nsToolkit::~nsToolkit() -{ - MOZ_COUNT_DTOR(nsToolkit); - RemoveSleepWakeNotifications(); - UnregisterAllProcessMouseEventHandlers(); -} - -void -nsToolkit::PostSleepWakeNotification(const char* aNotification) -{ - nsCOMPtr observerService = services::GetObserverService(); - if (observerService) - observerService->NotifyObservers(nullptr, aNotification, nullptr); -} - -// http://developer.apple.com/documentation/DeviceDrivers/Conceptual/IOKitFundamentals/PowerMgmt/chapter_10_section_3.html -static void ToolkitSleepWakeCallback(void *refCon, io_service_t service, natural_t messageType, void * messageArgument) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - switch (messageType) - { - case kIOMessageSystemWillSleep: - // System is going to sleep now. - nsToolkit::PostSleepWakeNotification(NS_WIDGET_SLEEP_OBSERVER_TOPIC); - ::IOAllowPowerChange(gRootPort, (long)messageArgument); - break; - - case kIOMessageCanSystemSleep: - // In this case, the computer has been idle for several minutes - // and will sleep soon so you must either allow or cancel - // this notification. Important: if you don’t respond, there will - // be a 30-second timeout before the computer sleeps. - // In Mozilla's case, we always allow sleep. - ::IOAllowPowerChange(gRootPort,(long)messageArgument); - break; - - case kIOMessageSystemHasPoweredOn: - // Handle wakeup. - nsToolkit::PostSleepWakeNotification(NS_WIDGET_WAKE_OBSERVER_TOPIC); - break; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsresult -nsToolkit::RegisterForSleepWakeNotifications() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - IONotificationPortRef notifyPortRef; - - NS_ASSERTION(!mSleepWakeNotificationRLS, "Already registered for sleep/wake"); - - gRootPort = ::IORegisterForSystemPower(0, ¬ifyPortRef, ToolkitSleepWakeCallback, &mPowerNotifier); - if (gRootPort == MACH_PORT_NULL) { - NS_ERROR("IORegisterForSystemPower failed"); - return NS_ERROR_FAILURE; - } - - mSleepWakeNotificationRLS = ::IONotificationPortGetRunLoopSource(notifyPortRef); - ::CFRunLoopAddSource(::CFRunLoopGetCurrent(), - mSleepWakeNotificationRLS, - kCFRunLoopDefaultMode); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -void -nsToolkit::RemoveSleepWakeNotifications() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (mSleepWakeNotificationRLS) { - ::IODeregisterForSystemPower(&mPowerNotifier); - ::CFRunLoopRemoveSource(::CFRunLoopGetCurrent(), - mSleepWakeNotificationRLS, - kCFRunLoopDefaultMode); - - mSleepWakeNotificationRLS = nullptr; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// Converts aPoint from the CoreGraphics "global display coordinate" system -// (which includes all displays/screens and has a top-left origin) to its -// (presumed) Cocoa counterpart (assumed to be the same as the "screen -// coordinates" system), which has a bottom-left origin. -static NSPoint ConvertCGGlobalToCocoaScreen(CGPoint aPoint) -{ - NSPoint cocoaPoint; - cocoaPoint.x = aPoint.x; - cocoaPoint.y = nsCocoaUtils::FlippedScreenY(aPoint.y); - return cocoaPoint; -} - -// Since our event tap is "listen only", events arrive here a little after -// they've already been processed. -static CGEventRef EventTapCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - if ((type == kCGEventTapDisabledByUserInput) || - (type == kCGEventTapDisabledByTimeout)) - return event; - if ([NSApp isActive]) - return event; - - nsIRollupListener* rollupListener = nsBaseWidget::GetActiveRollupListener(); - NS_ENSURE_TRUE(rollupListener, event); - nsCOMPtr rollupWidget = rollupListener->GetRollupWidget(); - if (!rollupWidget) - return event; - - // Don't bother with rightMouseDown events here -- because of the delay, - // we'll end up closing browser context menus that we just opened. Since - // these events usually raise a context menu, we'll handle them by hooking - // the @"com.apple.HIToolbox.beginMenuTrackingNotification" distributed - // notification (in nsAppShell.mm's AppShellDelegate). - if (type == kCGEventRightMouseDown) - return event; - NSWindow *ctxMenuWindow = (NSWindow*) rollupWidget->GetNativeData(NS_NATIVE_WINDOW); - if (!ctxMenuWindow) - return event; - NSPoint screenLocation = ConvertCGGlobalToCocoaScreen(CGEventGetLocation(event)); - // Don't roll up the rollup widget if our mouseDown happens over it (doing - // so would break the corresponding context menu). - if (NSPointInRect(screenLocation, [ctxMenuWindow frame])) - return event; - rollupListener->Rollup(0, false, nullptr, nullptr); - return event; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NULL); -} - -// Cocoa Firefox's use of custom context menus requires that we explicitly -// handle mouse events from other processes that the OS handles -// "automatically" for native context menus -- mouseMoved events so that -// right-click context menus work properly when our browser doesn't have the -// focus (bmo bug 368077), and mouseDown events so that our browser can -// dismiss a context menu when a mouseDown happens in another process (bmo -// bug 339945). -void -nsToolkit::RegisterForAllProcessMouseEvents() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (getenv("MOZ_DEBUG")) - return; - - // Don't do this for apps that use native context menus. -#ifdef MOZ_USE_NATIVE_POPUP_WINDOWS - return; -#endif /* MOZ_USE_NATIVE_POPUP_WINDOWS */ - - if (!mEventTapRLS) { - // Using an event tap for mouseDown events (instead of installing a - // handler for them on the EventMonitor target) works around an Apple - // bug that causes OS menus (like the Clock menu) not to work properly - // on OS X 10.4.X and below (bmo bug 381448). - // We install our event tap "listen only" to get around yet another Apple - // bug -- when we install it as an event filter on any kind of mouseDown - // event, that kind of event stops working in the main menu, and usually - // mouse event processing stops working in all apps in the current login - // session (so the entire OS appears to be hung)! The downside of - // installing listen-only is that events arrive at our handler slightly - // after they've already been processed. - mEventTapPort = CGEventTapCreate(kCGSessionEventTap, - kCGHeadInsertEventTap, - kCGEventTapOptionListenOnly, - CGEventMaskBit(kCGEventLeftMouseDown) - | CGEventMaskBit(kCGEventRightMouseDown) - | CGEventMaskBit(kCGEventOtherMouseDown), - EventTapCallback, - nullptr); - if (!mEventTapPort) - return; - mEventTapRLS = CFMachPortCreateRunLoopSource(nullptr, mEventTapPort, 0); - if (!mEventTapRLS) { - CFRelease(mEventTapPort); - mEventTapPort = nullptr; - return; - } - CFRunLoopAddSource(CFRunLoopGetCurrent(), mEventTapRLS, kCFRunLoopDefaultMode); - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void -nsToolkit::UnregisterAllProcessMouseEventHandlers() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (mEventTapRLS) { - CFRunLoopRemoveSource(CFRunLoopGetCurrent(), mEventTapRLS, - kCFRunLoopDefaultMode); - CFRelease(mEventTapRLS); - mEventTapRLS = nullptr; - } - if (mEventTapPort) { - // mEventTapPort must be invalidated as well as released. Otherwise the - // event tap doesn't get destroyed until the browser process ends (it - // keeps showing up in the list returned by CGGetEventTapList()). - CFMachPortInvalidate(mEventTapPort); - CFRelease(mEventTapPort); - mEventTapPort = nullptr; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// Return the nsToolkit instance. If a toolkit does not yet exist, then one -// will be created. -// static -nsToolkit* nsToolkit::GetToolkit() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - if (!gToolkit) { - gToolkit = new nsToolkit(); - } - - return gToolkit; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(nullptr); -} - -// An alternative to [NSObject poseAsClass:] that isn't deprecated on OS X -// Leopard and is available to 64-bit binaries on Leopard and above. Based on -// ideas and code from http://www.cocoadev.com/index.pl?MethodSwizzling. -// Since the Method type becomes an opaque type as of Objective-C 2.0, we'll -// have to switch to using accessor methods like method_exchangeImplementations() -// when we build 64-bit binaries that use Objective-C 2.0 (on and for Leopard -// and above). -// -// Be aware that, if aClass doesn't have an orgMethod selector but one of its -// superclasses does, the method substitution will (in effect) take place in -// that superclass (rather than in aClass itself). The substitution has -// effect on the class where it takes place and all of that class's -// subclasses. In order for method swizzling to work properly, posedMethod -// needs to be unique in the class where the substitution takes place and all -// of its subclasses. -nsresult nsToolkit::SwizzleMethods(Class aClass, SEL orgMethod, SEL posedMethod, - bool classMethods) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - Method original = nil; - Method posed = nil; - - if (classMethods) { - original = class_getClassMethod(aClass, orgMethod); - posed = class_getClassMethod(aClass, posedMethod); - } else { - original = class_getInstanceMethod(aClass, orgMethod); - posed = class_getInstanceMethod(aClass, posedMethod); - } - - if (!original || !posed) - return NS_ERROR_FAILURE; - - method_exchangeImplementations(original, posed); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} diff --git a/widget/cocoa/nsWidgetFactory.mm b/widget/cocoa/nsWidgetFactory.mm deleted file mode 100644 index 3bddaf95ce..0000000000 --- a/widget/cocoa/nsWidgetFactory.mm +++ /dev/null @@ -1,219 +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/. */ - -#include "nsIFactory.h" -#include "nsISupports.h" -#include "nsIComponentManager.h" -#include "mozilla/ModuleUtils.h" -#include "mozilla/WidgetUtils.h" - -#include "nsWidgetsCID.h" - -#include "nsChildView.h" -#include "nsCocoaWindow.h" -#include "nsAppShell.h" -#include "nsAppShellSingleton.h" -#include "nsFilePicker.h" -#include "nsColorPicker.h" - -#include "nsClipboard.h" -#include "nsClipboardHelper.h" -#include "nsTransferable.h" -#include "nsHTMLFormatConverter.h" -#include "nsDragService.h" -#include "nsToolkit.h" - -#include "nsLookAndFeel.h" - -#include "nsSound.h" -#include "nsIdleServiceX.h" -#include "NativeKeyBindings.h" -#include "OSXNotificationCenter.h" - -#include "nsScreenManagerCocoa.h" -#include "nsDeviceContextSpecX.h" -#include "nsPrintOptionsX.h" -#include "nsPrintDialogX.h" -#include "nsPrintSession.h" -#include "nsToolkitCompsCID.h" - -using namespace mozilla; -using namespace mozilla::widget; - -NS_GENERIC_FACTORY_CONSTRUCTOR(nsCocoaWindow) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsChildView) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePicker) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsColorPicker) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsSound) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboard) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardHelper) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragService) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsScreenManagerCocoa) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsDeviceContextSpecX) -NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintOptionsX, Init) -NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintDialogServiceX, Init) -NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintSession, Init) -NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIdleServiceX, nsIdleServiceX::GetInstance) -NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(OSXNotificationCenter, Init) - -#include "nsMenuBarX.h" -NS_GENERIC_FACTORY_CONSTRUCTOR(nsNativeMenuServiceX) - -#include "nsBidiKeyboard.h" -NS_GENERIC_FACTORY_CONSTRUCTOR(nsBidiKeyboard) - -#include "nsNativeThemeCocoa.h" -NS_GENERIC_FACTORY_CONSTRUCTOR(nsNativeThemeCocoa) - -#include "nsMacDockSupport.h" -NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacDockSupport) - -#include "nsMacWebAppUtils.h" -NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacWebAppUtils) - -#include "nsStandaloneNativeMenu.h" -NS_GENERIC_FACTORY_CONSTRUCTOR(nsStandaloneNativeMenu) - -#include "nsSystemStatusBarCocoa.h" -NS_GENERIC_FACTORY_CONSTRUCTOR(nsSystemStatusBarCocoa) - -#include "GfxInfo.h" -namespace mozilla { -namespace widget { -// This constructor should really be shared with all platforms. -NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(GfxInfo, Init) -} // namespace widget -} // namespace mozilla - -NS_DEFINE_NAMED_CID(NS_WINDOW_CID); -NS_DEFINE_NAMED_CID(NS_POPUP_CID); -NS_DEFINE_NAMED_CID(NS_CHILD_CID); -NS_DEFINE_NAMED_CID(NS_FILEPICKER_CID); -NS_DEFINE_NAMED_CID(NS_COLORPICKER_CID); -NS_DEFINE_NAMED_CID(NS_APPSHELL_CID); -NS_DEFINE_NAMED_CID(NS_SOUND_CID); -NS_DEFINE_NAMED_CID(NS_TRANSFERABLE_CID); -NS_DEFINE_NAMED_CID(NS_HTMLFORMATCONVERTER_CID); -NS_DEFINE_NAMED_CID(NS_CLIPBOARD_CID); -NS_DEFINE_NAMED_CID(NS_CLIPBOARDHELPER_CID); -NS_DEFINE_NAMED_CID(NS_DRAGSERVICE_CID); -NS_DEFINE_NAMED_CID(NS_BIDIKEYBOARD_CID); -NS_DEFINE_NAMED_CID(NS_THEMERENDERER_CID); -NS_DEFINE_NAMED_CID(NS_SCREENMANAGER_CID); -NS_DEFINE_NAMED_CID(NS_DEVICE_CONTEXT_SPEC_CID); -NS_DEFINE_NAMED_CID(NS_PRINTSESSION_CID); -NS_DEFINE_NAMED_CID(NS_PRINTSETTINGSSERVICE_CID); -NS_DEFINE_NAMED_CID(NS_PRINTDIALOGSERVICE_CID); -NS_DEFINE_NAMED_CID(NS_IDLE_SERVICE_CID); -NS_DEFINE_NAMED_CID(NS_SYSTEMALERTSSERVICE_CID); -NS_DEFINE_NAMED_CID(NS_NATIVEMENUSERVICE_CID); -NS_DEFINE_NAMED_CID(NS_MACDOCKSUPPORT_CID); -NS_DEFINE_NAMED_CID(NS_MACWEBAPPUTILS_CID); -NS_DEFINE_NAMED_CID(NS_STANDALONENATIVEMENU_CID); -NS_DEFINE_NAMED_CID(NS_MACSYSTEMSTATUSBAR_CID); -NS_DEFINE_NAMED_CID(NS_GFXINFO_CID); - -static const mozilla::Module::CIDEntry kWidgetCIDs[] = { - { &kNS_WINDOW_CID, false, NULL, nsCocoaWindowConstructor }, - { &kNS_POPUP_CID, false, NULL, nsCocoaWindowConstructor }, - { &kNS_CHILD_CID, false, NULL, nsChildViewConstructor }, - { &kNS_FILEPICKER_CID, false, NULL, nsFilePickerConstructor, - mozilla::Module::MAIN_PROCESS_ONLY }, - { &kNS_COLORPICKER_CID, false, NULL, nsColorPickerConstructor, - mozilla::Module::MAIN_PROCESS_ONLY }, - { &kNS_APPSHELL_CID, false, NULL, nsAppShellConstructor, mozilla::Module::ALLOW_IN_GPU_PROCESS }, - { &kNS_SOUND_CID, false, NULL, nsSoundConstructor, - mozilla::Module::MAIN_PROCESS_ONLY }, - { &kNS_TRANSFERABLE_CID, false, NULL, nsTransferableConstructor }, - { &kNS_HTMLFORMATCONVERTER_CID, false, NULL, nsHTMLFormatConverterConstructor }, - { &kNS_CLIPBOARD_CID, false, NULL, nsClipboardConstructor, - mozilla::Module::MAIN_PROCESS_ONLY }, - { &kNS_CLIPBOARDHELPER_CID, false, NULL, nsClipboardHelperConstructor }, - { &kNS_DRAGSERVICE_CID, false, NULL, nsDragServiceConstructor, - mozilla::Module::MAIN_PROCESS_ONLY }, - { &kNS_BIDIKEYBOARD_CID, false, NULL, nsBidiKeyboardConstructor, - mozilla::Module::MAIN_PROCESS_ONLY }, - { &kNS_THEMERENDERER_CID, false, NULL, nsNativeThemeCocoaConstructor }, - { &kNS_SCREENMANAGER_CID, false, NULL, nsScreenManagerCocoaConstructor, - mozilla::Module::MAIN_PROCESS_ONLY }, - { &kNS_DEVICE_CONTEXT_SPEC_CID, false, NULL, nsDeviceContextSpecXConstructor }, - { &kNS_PRINTSESSION_CID, false, NULL, nsPrintSessionConstructor }, - { &kNS_PRINTSETTINGSSERVICE_CID, false, NULL, nsPrintOptionsXConstructor }, - { &kNS_PRINTDIALOGSERVICE_CID, false, NULL, nsPrintDialogServiceXConstructor }, - { &kNS_IDLE_SERVICE_CID, false, NULL, nsIdleServiceXConstructor }, - { &kNS_SYSTEMALERTSSERVICE_CID, false, NULL, OSXNotificationCenterConstructor }, - { &kNS_NATIVEMENUSERVICE_CID, false, NULL, nsNativeMenuServiceXConstructor }, - { &kNS_MACDOCKSUPPORT_CID, false, NULL, nsMacDockSupportConstructor }, - { &kNS_MACWEBAPPUTILS_CID, false, NULL, nsMacWebAppUtilsConstructor }, - { &kNS_STANDALONENATIVEMENU_CID, false, NULL, nsStandaloneNativeMenuConstructor }, - { &kNS_MACSYSTEMSTATUSBAR_CID, false, NULL, nsSystemStatusBarCocoaConstructor }, - { &kNS_GFXINFO_CID, false, NULL, mozilla::widget::GfxInfoConstructor }, - { NULL } -}; - -static const mozilla::Module::ContractIDEntry kWidgetContracts[] = { - { "@mozilla.org/widgets/window/mac;1", &kNS_WINDOW_CID }, - { "@mozilla.org/widgets/popup/mac;1", &kNS_POPUP_CID }, - { "@mozilla.org/widgets/childwindow/mac;1", &kNS_CHILD_CID }, - { "@mozilla.org/filepicker;1", &kNS_FILEPICKER_CID, - mozilla::Module::MAIN_PROCESS_ONLY }, - { "@mozilla.org/colorpicker;1", &kNS_COLORPICKER_CID, - mozilla::Module::MAIN_PROCESS_ONLY }, - { "@mozilla.org/widget/appshell/mac;1", &kNS_APPSHELL_CID, mozilla::Module::ALLOW_IN_GPU_PROCESS }, - { "@mozilla.org/sound;1", &kNS_SOUND_CID, - mozilla::Module::MAIN_PROCESS_ONLY }, - { "@mozilla.org/widget/transferable;1", &kNS_TRANSFERABLE_CID }, - { "@mozilla.org/widget/htmlformatconverter;1", &kNS_HTMLFORMATCONVERTER_CID }, - { "@mozilla.org/widget/clipboard;1", &kNS_CLIPBOARD_CID, - mozilla::Module::MAIN_PROCESS_ONLY }, - { "@mozilla.org/widget/clipboardhelper;1", &kNS_CLIPBOARDHELPER_CID }, - { "@mozilla.org/widget/dragservice;1", &kNS_DRAGSERVICE_CID, - mozilla::Module::MAIN_PROCESS_ONLY }, - { "@mozilla.org/widget/bidikeyboard;1", &kNS_BIDIKEYBOARD_CID, - mozilla::Module::MAIN_PROCESS_ONLY }, - { "@mozilla.org/chrome/chrome-native-theme;1", &kNS_THEMERENDERER_CID }, - { "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID, - mozilla::Module::MAIN_PROCESS_ONLY }, - { "@mozilla.org/gfx/devicecontextspec;1", &kNS_DEVICE_CONTEXT_SPEC_CID }, - { "@mozilla.org/gfx/printsession;1", &kNS_PRINTSESSION_CID }, - { "@mozilla.org/gfx/printsettings-service;1", &kNS_PRINTSETTINGSSERVICE_CID }, - { NS_PRINTDIALOGSERVICE_CONTRACTID, &kNS_PRINTDIALOGSERVICE_CID }, - { "@mozilla.org/widget/idleservice;1", &kNS_IDLE_SERVICE_CID }, - { "@mozilla.org/system-alerts-service;1", &kNS_SYSTEMALERTSSERVICE_CID }, - { "@mozilla.org/widget/nativemenuservice;1", &kNS_NATIVEMENUSERVICE_CID }, - { "@mozilla.org/widget/macdocksupport;1", &kNS_MACDOCKSUPPORT_CID }, - { "@mozilla.org/widget/mac-web-app-utils;1", &kNS_MACWEBAPPUTILS_CID }, - { "@mozilla.org/widget/standalonenativemenu;1", &kNS_STANDALONENATIVEMENU_CID }, - { "@mozilla.org/widget/macsystemstatusbar;1", &kNS_MACSYSTEMSTATUSBAR_CID }, - { "@mozilla.org/gfx/info;1", &kNS_GFXINFO_CID }, - { NULL } -}; - -static void -nsWidgetCocoaModuleDtor() -{ - // Shutdown all XP level widget classes. - WidgetUtils::Shutdown(); - - NativeKeyBindings::Shutdown(); - nsLookAndFeel::Shutdown(); - nsToolkit::Shutdown(); - nsAppShellShutdown(); -} - -static const mozilla::Module kWidgetModule = { - mozilla::Module::kVersion, - kWidgetCIDs, - kWidgetContracts, - NULL, - NULL, - nsAppShellInit, - nsWidgetCocoaModuleDtor, - mozilla::Module::ALLOW_IN_GPU_PROCESS -}; - -NSMODULE_DEFN(nsWidgetMacModule) = &kWidgetModule; diff --git a/widget/cocoa/nsWindowMap.h b/widget/cocoa/nsWindowMap.h deleted file mode 100644 index c6ad72c010..0000000000 --- a/widget/cocoa/nsWindowMap.h +++ /dev/null @@ -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 nsWindowMap_h_ -#define nsWindowMap_h_ - -#import - -// WindowDataMap -// -// In both mozilla and embedding apps, we need to have a place to put -// per-top-level-window logic and data, to handle such things as IME -// commit when the window gains/loses focus. We can't use a window -// delegate, because an embeddor probably already has one. Nor can we -// subclass NSWindow, again because we can't impose that burden on the -// embeddor. -// -// So we have a global map of NSWindow -> TopLevelWindowData, and set -// up TopLevelWindowData as a notification observer etc. - -@interface WindowDataMap : NSObject -{ -@private - NSMutableDictionary* mWindowMap; // dict of TopLevelWindowData keyed by address of NSWindow -} - -+ (WindowDataMap*)sharedWindowDataMap; - -- (void)ensureDataForWindow:(NSWindow*)inWindow; -- (id)dataForWindow:(NSWindow*)inWindow; - -// set data for a given window. inData is retained (and any previously set data -// is released). -- (void)setData:(id)inData forWindow:(NSWindow*)inWindow; - -// remove the data for the given window. the data is released. -- (void)removeDataForWindow:(NSWindow*)inWindow; - -@end - -@class ChildView; - -// TopLevelWindowData -// -// Class to hold per-window data, and handle window state changes. - -@interface TopLevelWindowData : NSObject -{ -@private -} - -- (id)initWithWindow:(NSWindow*)inWindow; -+ (void)activateInWindow:(NSWindow*)aWindow; -+ (void)deactivateInWindow:(NSWindow*)aWindow; -+ (void)activateInWindowViews:(NSWindow*)aWindow; -+ (void)deactivateInWindowViews:(NSWindow*)aWindow; - -@end - -#endif // nsWindowMap_h_ diff --git a/widget/cocoa/nsWindowMap.mm b/widget/cocoa/nsWindowMap.mm deleted file mode 100644 index c43b024086..0000000000 --- a/widget/cocoa/nsWindowMap.mm +++ /dev/null @@ -1,311 +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 "nsWindowMap.h" -#include "nsObjCExceptions.h" -#include "nsChildView.h" -#include "nsCocoaWindow.h" - -@interface WindowDataMap(Private) - -- (NSString*)keyForWindow:(NSWindow*)inWindow; - -@end - -@interface TopLevelWindowData(Private) - -- (void)windowResignedKey:(NSNotification*)inNotification; -- (void)windowBecameKey:(NSNotification*)inNotification; -- (void)windowWillClose:(NSNotification*)inNotification; - -@end - -#pragma mark - - -@implementation WindowDataMap - -+ (WindowDataMap*)sharedWindowDataMap -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - static WindowDataMap* sWindowMap = nil; - if (!sWindowMap) - sWindowMap = [[WindowDataMap alloc] init]; - - return sWindowMap; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (id)init -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - if ((self = [super init])) { - mWindowMap = [[NSMutableDictionary alloc] initWithCapacity:10]; - } - return self; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (void)dealloc -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mWindowMap release]; - [super dealloc]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)ensureDataForWindow:(NSWindow*)inWindow -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!inWindow || [self dataForWindow:inWindow]) - return; - - TopLevelWindowData* windowData = [[TopLevelWindowData alloc] initWithWindow:inWindow]; - [self setData:windowData forWindow:inWindow]; // takes ownership - [windowData release]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (id)dataForWindow:(NSWindow*)inWindow -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - return [mWindowMap objectForKey:[self keyForWindow:inWindow]]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (void)setData:(id)inData forWindow:(NSWindow*)inWindow -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mWindowMap setObject:inData forKey:[self keyForWindow:inWindow]]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)removeDataForWindow:(NSWindow*)inWindow -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mWindowMap removeObjectForKey:[self keyForWindow:inWindow]]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (NSString*)keyForWindow:(NSWindow*)inWindow -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - return [NSString stringWithFormat:@"%p", inWindow]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -@end - -// TopLevelWindowData -// -// This class holds data about top-level windows. We can't use a window -// delegate, because an embedder may already have one. - -@implementation TopLevelWindowData - -- (id)initWithWindow:(NSWindow*)inWindow -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - if ((self = [super init])) { - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(windowBecameKey:) - name:NSWindowDidBecomeKeyNotification - object:inWindow]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(windowResignedKey:) - name:NSWindowDidResignKeyNotification - object:inWindow]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(windowBecameMain:) - name:NSWindowDidBecomeMainNotification - object:inWindow]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(windowResignedMain:) - name:NSWindowDidResignMainNotification - object:inWindow]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(windowWillClose:) - name:NSWindowWillCloseNotification - object:inWindow]; - } - return self; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (void)dealloc -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [[NSNotificationCenter defaultCenter] removeObserver:self]; - [super dealloc]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// As best I can tell, if the notification's object has a corresponding -// top-level widget (an nsCocoaWindow object), it has a delegate (set in -// nsCocoaWindow::StandardCreate()) of class WindowDelegate, and otherwise -// not (Camino didn't use top-level widgets (nsCocoaWindow objects) -- -// only child widgets (nsChildView objects)). (The notification is sent -// to windowBecameKey: or windowBecameMain: below.) -// -// For use with clients that (like Firefox) do use top-level widgets (and -// have NSWindow delegates of class WindowDelegate). -+ (void)activateInWindow:(NSWindow*)aWindow -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - WindowDelegate* delegate = (WindowDelegate*) [aWindow delegate]; - if (!delegate || ![delegate isKindOfClass:[WindowDelegate class]]) - return; - - if ([delegate toplevelActiveState]) - return; - [delegate sendToplevelActivateEvents]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// See comments above activateInWindow: -// -// If we're using top-level widgets (nsCocoaWindow objects), we send them -// NS_DEACTIVATE events (which propagate to child widgets (nsChildView -// objects) via nsWebShellWindow::HandleEvent()). -// -// For use with clients that (like Firefox) do use top-level widgets (and -// have NSWindow delegates of class WindowDelegate). -+ (void)deactivateInWindow:(NSWindow*)aWindow -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - WindowDelegate* delegate = (WindowDelegate*) [aWindow delegate]; - if (!delegate || ![delegate isKindOfClass:[WindowDelegate class]]) - return; - - if (![delegate toplevelActiveState]) - return; - [delegate sendToplevelDeactivateEvents]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// For use with clients that (like Camino) don't use top-level widgets (and -// don't have NSWindow delegates of class WindowDelegate). -+ (void)activateInWindowViews:(NSWindow*)aWindow -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - id firstResponder = [aWindow firstResponder]; - if ([firstResponder isKindOfClass:[ChildView class]]) - [firstResponder viewsWindowDidBecomeKey]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// For use with clients that (like Camino) don't use top-level widgets (and -// don't have NSWindow delegates of class WindowDelegate). -+ (void)deactivateInWindowViews:(NSWindow*)aWindow -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - id firstResponder = [aWindow firstResponder]; - if ([firstResponder isKindOfClass:[ChildView class]]) - [firstResponder viewsWindowDidResignKey]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// We make certain exceptions for top-level windows in non-embedders (see -// comment above windowBecameMain below). And we need (elsewhere) to guard -// against sending duplicate events. But in general the NS_ACTIVATE event -// should be sent when a native window becomes key, and the NS_DEACTIVATE -// event should be sent when it resignes key. -- (void)windowBecameKey:(NSNotification*)inNotification -{ - NSWindow* window = (NSWindow*)[inNotification object]; - - id delegate = [window delegate]; - if (!delegate || ![delegate isKindOfClass:[WindowDelegate class]]) { - [TopLevelWindowData activateInWindowViews:window]; - } else if ([window isSheet]) { - [TopLevelWindowData activateInWindow:window]; - } - - [[window contentView] setNeedsDisplay:YES]; -} - -- (void)windowResignedKey:(NSNotification*)inNotification -{ - NSWindow* window = (NSWindow*)[inNotification object]; - - id delegate = [window delegate]; - if (!delegate || ![delegate isKindOfClass:[WindowDelegate class]]) { - [TopLevelWindowData deactivateInWindowViews:window]; - } else if ([window isSheet]) { - [TopLevelWindowData deactivateInWindow:window]; - } - - [[window contentView] setNeedsDisplay:YES]; -} - -// The appearance of a top-level window depends on its main state (not its key -// state). So (for non-embedders) we need to ensure that a top-level window -// is main when an NS_ACTIVATE event is sent to Gecko for it. -- (void)windowBecameMain:(NSNotification*)inNotification -{ - NSWindow* window = (NSWindow*)[inNotification object]; - - id delegate = [window delegate]; - // Don't send events to a top-level window that has a sheet open above it -- - // as far as Gecko is concerned, it's inactive, and stays so until the sheet - // closes. - if (delegate && [delegate isKindOfClass:[WindowDelegate class]] && ![window attachedSheet]) - [TopLevelWindowData activateInWindow:window]; -} - -- (void)windowResignedMain:(NSNotification*)inNotification -{ - NSWindow* window = (NSWindow*)[inNotification object]; - - id delegate = [window delegate]; - if (delegate && [delegate isKindOfClass:[WindowDelegate class]] && ![window attachedSheet]) - [TopLevelWindowData deactivateInWindow:window]; -} - -- (void)windowWillClose:(NSNotification*)inNotification -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // postpone our destruction - [[self retain] autorelease]; - - // remove ourselves from the window map (which owns us) - [[WindowDataMap sharedWindowDataMap] removeDataForWindow:[inNotification object]]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -@end diff --git a/widget/cocoa/resources/MainMenu.nib/classes.nib b/widget/cocoa/resources/MainMenu.nib/classes.nib deleted file mode 100644 index b9b4b09f6b..0000000000 --- a/widget/cocoa/resources/MainMenu.nib/classes.nib +++ /dev/null @@ -1,4 +0,0 @@ -{ - IBClasses = ({CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }); - IBVersion = 1; -} \ No newline at end of file diff --git a/widget/cocoa/resources/MainMenu.nib/info.nib b/widget/cocoa/resources/MainMenu.nib/info.nib deleted file mode 100644 index bcf3ace841..0000000000 --- a/widget/cocoa/resources/MainMenu.nib/info.nib +++ /dev/null @@ -1,21 +0,0 @@ - - - - - IBDocumentLocation - 159 127 356 240 0 0 1920 1178 - IBEditorPositions - - 29 - 413 971 130 44 0 0 1920 1178 - - IBFramework Version - 443.0 - IBOpenObjects - - 29 - - IBSystem Version - 8F46 - - diff --git a/widget/cocoa/resources/MainMenu.nib/keyedobjects.nib b/widget/cocoa/resources/MainMenu.nib/keyedobjects.nib deleted file mode 100644 index 16b3f7e523..0000000000 Binary files a/widget/cocoa/resources/MainMenu.nib/keyedobjects.nib and /dev/null differ diff --git a/widget/moz.build b/widget/moz.build index c72b2066c3..acb1387341 100644 --- a/widget/moz.build +++ b/widget/moz.build @@ -5,9 +5,6 @@ toolkit = CONFIG['MOZ_WIDGET_TOOLKIT'] -if toolkit in ('cocoa', 'uikit'): - DIRS += [toolkit] - if toolkit in ('gtk2', 'gtk3'): EXPORTS += ['nsIPrintDialogService.h'] @@ -28,19 +25,8 @@ if toolkit == 'windows': 'nsIWindowsUIUtils.idl', 'nsIWinTaskbar.idl', ] -elif toolkit == 'cocoa': - XPIDL_SOURCES += [ - 'nsIMacDockSupport.idl', - 'nsIMacWebAppUtils.idl', - 'nsIStandaloneNativeMenu.idl', - 'nsISystemStatusBar.idl', - 'nsITaskbarProgress.idl', - ] - EXPORTS += [ - 'nsIPrintDialogService.h', - ] -if toolkit in ('cocoa', 'gtk2', 'gtk3'): +if toolkit in ('gtk2', 'gtk3'): EXPORTS += ['nsINativeMenuService.h'] # Don't build the DSO under the 'build' directory as windows does. @@ -216,15 +202,15 @@ if CONFIG['MOZ_X11']: 'WindowSurfaceX11SHM.cpp', ] -if toolkit in ('cocoa', 'windows'): +if toolkit in ('windows'): UNIFIED_SOURCES += [ 'nsBaseClipboard.cpp', ] -if toolkit in {'gtk2', 'gtk3', 'cocoa', 'windows', 'uikit'}: +if toolkit in {'gtk2', 'gtk3', 'windows', 'uikit'}: UNIFIED_SOURCES += ['nsBaseFilePicker.cpp'] -if toolkit in ('gtk2', 'gtk3', 'windows', 'cocoa'): +if toolkit in ('gtk2', 'gtk3', 'windows'): UNIFIED_SOURCES += ['nsNativeTheme.cpp'] if toolkit == 'gtk3': diff --git a/widget/nsIMacDockSupport.idl b/widget/nsIMacDockSupport.idl deleted file mode 100644 index 5783e9c0b9..0000000000 --- a/widget/nsIMacDockSupport.idl +++ /dev/null @@ -1,39 +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 "nsISupports.idl" - -interface nsIStandaloneNativeMenu; - -/** - * Allow applications to interface with the Mac OS X Dock. - * - * Applications may indicate progress on their Dock icon. Only one such - * progress indicator is available to the entire application. - */ - -[scriptable, uuid(8BE66B0C-5F71-4B74-98CF-6C2551B999B1)] -interface nsIMacDockSupport : nsISupports -{ - /** - * Menu to use for application-specific dock menu items. - */ - attribute nsIStandaloneNativeMenu dockMenu; - - /** - * Activate the application. This should be used by an application to - * activate itself when a dock menu is selected as selection of a dock menu - * item does not automatically activate the application. - * - * @param aIgnoreOtherApplications If false, the application is activated - * only if no other application is currently active. If true, the - * application activates regardless. - */ - void activateApplication(in boolean aIgnoreOtherApplications); - - /** - * Text used to badge the dock tile. - */ - attribute AString badgeText; -}; diff --git a/widget/nsIMacWebAppUtils.idl b/widget/nsIMacWebAppUtils.idl deleted file mode 100644 index 4d570a8bf0..0000000000 --- a/widget/nsIMacWebAppUtils.idl +++ /dev/null @@ -1,35 +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 "nsISupports.idl" - -interface nsIMacWebAppUtils; - -[scriptable, function, uuid(8c899c4f-58c1-4b74-9034-3bb64e484b68)] -interface nsITrashAppCallback : nsISupports -{ - void trashAppFinished(in nsresult rv); -}; - -/** - * Allow MozApps API to locate and manipulate natively installed apps - */ - -[scriptable, uuid(c69cf343-ea41-428b-b161-4655fd54d8e7)] -interface nsIMacWebAppUtils : nsISupports { - /** - * Find the path for an app with the given signature. - */ - AString pathForAppWithIdentifier(in AString bundleIdentifier); - - /** - * Launch the app with the given identifier, if it exists. - */ - void launchAppWithIdentifier(in AString bundleIdentifier); - - /** - * Move the app from the given directory to the Trash. - */ - void trashApp(in AString path, in nsITrashAppCallback callback); -}; diff --git a/widget/nsISystemStatusBar.idl b/widget/nsISystemStatusBar.idl deleted file mode 100644 index 9db8015199..0000000000 --- a/widget/nsISystemStatusBar.idl +++ /dev/null @@ -1,36 +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 "nsISupports.idl" - -interface nsIDOMElement; - -/** - * Allow applications to interface with the Mac OS X system status bar. - */ - -[scriptable, uuid(24493180-ee81-4b7c-8b17-9e69480b7b8a)] -interface nsISystemStatusBar : nsISupports -{ - /** - * Add an item to the system status bar. Each item can only be present once, - * subsequent addItem calls with the same element will be ignored. - * The system status bar holds a strong reference to the added XUL menu - * element and the item will stay in the status bar until it is removed via - * a call to removeItem, or until the process shuts down. - * @param aDOMMenuElement A XUL menu element that contains a XUL menupopup - * with regular menu content. The menu's icon is put - * into the system status bar; clicking it will open - * a menu with the contents of the menupopup. - * The menu label is not shown. - */ - void addItem(in nsIDOMElement aDOMMenuElement); - - /** - * Remove a previously-added item from the menu bar. Calling this with an - * element that has not been added before will be silently ignored. - * @param aDOMMenuElement The XUL menu element that you called addItem with. - */ - void removeItem(in nsIDOMElement aDOMMenuElement); -}; diff --git a/widget/uikit/GfxInfo.cpp b/widget/uikit/GfxInfo.cpp deleted file mode 100644 index cabe993dd0..0000000000 --- a/widget/uikit/GfxInfo.cpp +++ /dev/null @@ -1,222 +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 "GfxInfo.h" -#include "nsServiceManagerUtils.h" - -namespace mozilla { -namespace widget { - - -#ifdef DEBUG -NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, GfxInfoBase, nsIGfxInfoDebug) -#endif - -GfxInfo::GfxInfo() -{ -} - -GfxInfo::~GfxInfo() -{ -} - -nsresult -GfxInfo::GetD2DEnabled(bool *aEnabled) -{ - return NS_ERROR_FAILURE; -} - -nsresult -GfxInfo::GetDWriteEnabled(bool *aEnabled) -{ - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion) -{ - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -GfxInfo::GetCleartypeParameters(nsAString & aCleartypeParams) -{ - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -GfxInfo::GetAdapterDescription(nsAString & aAdapterDescription) -{ - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -GfxInfo::GetAdapterDescription2(nsAString & aAdapterDescription) -{ - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -GfxInfo::GetAdapterRAM(nsAString & aAdapterRAM) -{ - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -GfxInfo::GetAdapterRAM2(nsAString & aAdapterRAM) -{ - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -GfxInfo::GetAdapterDriver(nsAString & aAdapterDriver) -{ - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -GfxInfo::GetAdapterDriver2(nsAString & aAdapterDriver) -{ - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -GfxInfo::GetAdapterDriverVersion(nsAString & aAdapterDriverVersion) -{ - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -GfxInfo::GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion) -{ - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -GfxInfo::GetAdapterDriverDate(nsAString & aAdapterDriverDate) -{ - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -GfxInfo::GetAdapterDriverDate2(nsAString & aAdapterDriverDate) -{ - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -GfxInfo::GetAdapterVendorID(nsAString & aAdapterVendorID) -{ - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -GfxInfo::GetAdapterVendorID2(nsAString & aAdapterVendorID) -{ - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -GfxInfo::GetAdapterDeviceID(nsAString & aAdapterDeviceID) -{ - return NS_ERROR_FAILURE; - return NS_OK; -} - -NS_IMETHODIMP -GfxInfo::GetAdapterDeviceID2(nsAString & aAdapterDeviceID) -{ - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -GfxInfo::GetAdapterSubsysID(nsAString & aAdapterSubsysID) -{ - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -GfxInfo::GetAdapterSubsysID2(nsAString & aAdapterSubsysID) -{ - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active) -{ - return NS_ERROR_FAILURE; -} - -const nsTArray& -GfxInfo::GetGfxDriverInfo() -{ - if (mDriverInfo->IsEmpty()) { - APPEND_TO_DRIVER_BLOCKLIST2(OperatingSystem::Ios, - (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorAll), GfxDriverInfo::allDevices, - nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_STATUS_OK, - DRIVER_COMPARISON_IGNORED, GfxDriverInfo::allDriverVersions ); - } - - return *mDriverInfo; -} - -nsresult -GfxInfo::GetFeatureStatusImpl(int32_t aFeature, - int32_t *aStatus, - nsAString & aSuggestedDriverVersion, - const nsTArray& aDriverInfo, - OperatingSystem* aOS /* = nullptr */) -{ - NS_ENSURE_ARG_POINTER(aStatus); - aSuggestedDriverVersion.SetIsVoid(true); - *aStatus = nsIGfxInfo::FEATURE_STATUS_UNKNOWN; - if (aOS) - *aOS = OperatingSystem::Ios; - - if (mShutdownOccurred) { - return NS_OK; - } - - // OpenGL layers are never blacklisted on iOS. - // This early return is so we avoid potentially slow - // GLStrings initialization on startup when we initialize GL layers. - if (aFeature == nsIGfxInfo::FEATURE_OPENGL_LAYERS || - aFeature == nsIGfxInfo::FEATURE_WEBGL_OPENGL || - aFeature == nsIGfxInfo::FEATURE_WEBGL_MSAA) { - *aStatus = nsIGfxInfo::FEATURE_STATUS_OK; - return NS_OK; - } - - return GfxInfoBase::GetFeatureStatusImpl(aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, aOS); -} - -#ifdef DEBUG - -// Implement nsIGfxInfoDebug - -NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString & aVendorID) -{ - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP GfxInfo::SpoofDeviceID(const nsAString & aDeviceID) -{ - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP GfxInfo::SpoofDriverVersion(const nsAString & aDriverVersion) -{ - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP GfxInfo::SpoofOSVersion(uint32_t aVersion) -{ - return NS_ERROR_FAILURE; -} - -#endif - -} -} diff --git a/widget/uikit/GfxInfo.h b/widget/uikit/GfxInfo.h deleted file mode 100644 index 16a2242515..0000000000 --- a/widget/uikit/GfxInfo.h +++ /dev/null @@ -1,78 +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 "GfxDriverInfo.h" - -#include "nsString.h" -#include "mozilla/UniquePtr.h" - -namespace mozilla { - -namespace gl { -class GLContext; -} - -namespace widget { - -class GfxInfo : public GfxInfoBase -{ -private: - ~GfxInfo(); - -public: - GfxInfo(); - - // We only declare the subset of nsIGfxInfo that we actually implement. The - // rest is brought forward from GfxInfoBase. - NS_IMETHOD GetD2DEnabled(bool *aD2DEnabled); - NS_IMETHOD GetDWriteEnabled(bool *aDWriteEnabled); - NS_IMETHOD GetDWriteVersion(nsAString & aDwriteVersion); - NS_IMETHOD GetCleartypeParameters(nsAString & aCleartypeParams); - NS_IMETHOD GetAdapterDescription(nsAString & aAdapterDescription); - NS_IMETHOD GetAdapterDriver(nsAString & aAdapterDriver); - NS_IMETHOD GetAdapterVendorID(nsAString & aAdapterVendorID); - NS_IMETHOD GetAdapterDeviceID(nsAString & aAdapterDeviceID); - NS_IMETHOD GetAdapterSubsysID(nsAString & aAdapterSubsysID); - NS_IMETHOD GetAdapterRAM(nsAString & aAdapterRAM); - NS_IMETHOD GetAdapterDriverVersion(nsAString & aAdapterDriverVersion); - NS_IMETHOD GetAdapterDriverDate(nsAString & aAdapterDriverDate); - NS_IMETHOD GetAdapterDescription2(nsAString & aAdapterDescription); - NS_IMETHOD GetAdapterDriver2(nsAString & aAdapterDriver); - NS_IMETHOD GetAdapterVendorID2(nsAString & aAdapterVendorID); - NS_IMETHOD GetAdapterDeviceID2(nsAString & aAdapterDeviceID); - NS_IMETHOD GetAdapterSubsysID2(nsAString & aAdapterSubsysID); - NS_IMETHOD GetAdapterRAM2(nsAString & aAdapterRAM); - NS_IMETHOD GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion); - NS_IMETHOD GetAdapterDriverDate2(nsAString & aAdapterDriverDate); - NS_IMETHOD GetIsGPU2Active(bool *aIsGPU2Active); - using GfxInfoBase::GetFeatureStatus; - using GfxInfoBase::GetFeatureSuggestedDriverVersion; - using GfxInfoBase::GetWebGLParameter; - -#ifdef DEBUG - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSIGFXINFODEBUG -#endif - -protected: - - virtual nsresult GetFeatureStatusImpl(int32_t aFeature, - int32_t *aStatus, - nsAString & aSuggestedDriverVersion, - const nsTArray& aDriverInfo, - OperatingSystem* aOS = nullptr); - virtual const nsTArray& GetGfxDriverInfo(); -}; - -} // namespace widget -} // namespace mozilla - -#endif /* __mozilla_widget_GfxInfo_h__ */ diff --git a/widget/uikit/moz.build b/widget/uikit/moz.build deleted file mode 100644 index 2c6c188de6..0000000000 --- a/widget/uikit/moz.build +++ /dev/null @@ -1,18 +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/. - -SOURCES += [ - 'GfxInfo.cpp', - 'nsAppShell.mm', - 'nsLookAndFeel.mm', - 'nsScreenManager.mm', - 'nsWidgetFactory.mm', - 'nsWindow.mm', -] - -FINAL_LIBRARY = 'xul' -LOCAL_INCLUDES += [ - '/widget', -] diff --git a/widget/uikit/nsAppShell.h b/widget/uikit/nsAppShell.h deleted file mode 100644 index a88fa8b4f1..0000000000 --- a/widget/uikit/nsAppShell.h +++ /dev/null @@ -1,57 +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/. */ - -/* - * Runs the main native UIKit run loop, interrupting it as needed to process - * Gecko events. - */ - -#ifndef nsAppShell_h_ -#define nsAppShell_h_ - -#include "nsBaseAppShell.h" -#include "nsTArray.h" - -#include -#include -#include - -@class AppShellDelegate; - -class nsAppShell : public nsBaseAppShell -{ -public: - NS_IMETHOD ResumeNative(void); - - nsAppShell(); - - nsresult Init(); - - NS_IMETHOD Run(void); - NS_IMETHOD Exit(void); - // Called by the application delegate - void WillTerminate(void); - - static nsAppShell* gAppShell; - static UIWindow* gWindow; - static NSMutableArray* gTopLevelViews; - -protected: - virtual ~nsAppShell(); - - static void ProcessGeckoEvents(void* aInfo); - virtual void ScheduleNativeEventCallback(); - virtual bool ProcessNextNativeEvent(bool aMayWait); - - NSAutoreleasePool* mAutoreleasePool; - AppShellDelegate* mDelegate; - CFRunLoopRef mCFRunLoop; - CFRunLoopSourceRef mCFRunLoopSource; - - bool mTerminated; - bool mNotifiedWillTerminate; -}; - -#endif // nsAppShell_h_ diff --git a/widget/uikit/nsAppShell.mm b/widget/uikit/nsAppShell.mm deleted file mode 100644 index ac007132fd..0000000000 --- a/widget/uikit/nsAppShell.mm +++ /dev/null @@ -1,271 +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/. */ - -#import -#import -#import -#import - -#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 "nsMemoryPressure.h" -#include "nsServiceManagerUtils.h" -#include "nsIInterfaceRequestor.h" -#include "nsIWebBrowserChrome.h" - -nsAppShell *nsAppShell::gAppShell = NULL; -UIWindow *nsAppShell::gWindow = nil; -NSMutableArray *nsAppShell::gTopLevelViews = [[NSMutableArray alloc] init]; - -#define ALOG(args...) fprintf(stderr, args); fprintf(stderr, "\n") - -// ViewController -@interface ViewController : UIViewController -@end - - -@implementation ViewController - -- (void)loadView { - ALOG("[ViewController loadView]"); - CGRect r = {{0, 0}, {100, 100}}; - self.view = [[UIView alloc] initWithFrame:r]; - [self.view setBackgroundColor:[UIColor lightGrayColor]]; - // add all of the top level views as children - for (UIView* v in nsAppShell::gTopLevelViews) { - ALOG("[ViewController.view addSubView:%p]", v); - [self.view addSubview:v]; - } - [nsAppShell::gTopLevelViews release]; - nsAppShell::gTopLevelViews = nil; -} -@end - -// AppShellDelegate -// -// Acts as a delegate for the UIApplication - -@interface AppShellDelegate : NSObject { -} -@property (strong, nonatomic) UIWindow *window; -@end - -@implementation AppShellDelegate - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ - ALOG("[AppShellDelegate application:didFinishLaunchingWithOptions:]"); - // We only create one window, since we can only display one window at - // a time anyway. Also, iOS 4 fails to display UIWindows if you - // create them before calling UIApplicationMain, so this makes more sense. - nsAppShell::gWindow = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] retain]; - self.window = nsAppShell::gWindow; - - self.window.rootViewController = [[ViewController alloc] init]; - - // just to make things more visible for now - nsAppShell::gWindow.backgroundColor = [UIColor blueColor]; - [nsAppShell::gWindow makeKeyAndVisible]; - - return YES; -} - -- (void)applicationWillTerminate:(UIApplication *)application -{ - ALOG("[AppShellDelegate applicationWillTerminate:]"); - nsAppShell::gAppShell->WillTerminate(); -} - -- (void)applicationDidBecomeActive:(UIApplication *)application -{ - ALOG("[AppShellDelegate applicationDidBecomeActive:]"); -} - -- (void)applicationWillResignActive:(UIApplication *)application -{ - ALOG("[AppShellDelegate applicationWillResignActive:]"); -} - -- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application -{ - ALOG("[AppShellDelegate applicationDidReceiveMemoryWarning:]"); - NS_DispatchMemoryPressure(MemPressure_New); -} -@end - -// nsAppShell implementation - -NS_IMETHODIMP -nsAppShell::ResumeNative(void) -{ - return nsBaseAppShell::ResumeNative(); -} - -nsAppShell::nsAppShell() - : mAutoreleasePool(NULL), - mDelegate(NULL), - mCFRunLoop(NULL), - mCFRunLoopSource(NULL), - mTerminated(false), - mNotifiedWillTerminate(false) -{ - gAppShell = this; -} - -nsAppShell::~nsAppShell() -{ - if (mAutoreleasePool) { - [mAutoreleasePool release]; - mAutoreleasePool = NULL; - } - - if (mCFRunLoop) { - if (mCFRunLoopSource) { - ::CFRunLoopRemoveSource(mCFRunLoop, mCFRunLoopSource, - kCFRunLoopCommonModes); - ::CFRelease(mCFRunLoopSource); - } - ::CFRelease(mCFRunLoop); - } - - gAppShell = NULL; -} - -// Init -// -// public -nsresult -nsAppShell::Init() -{ - mAutoreleasePool = [[NSAutoreleasePool alloc] init]; - - // 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); - - return nsBaseAppShell::Init(); -} - -// ProcessGeckoEvents -// -// The "perform" target of mCFRunLoop, called when mCFRunLoopSource is -// signalled from ScheduleNativeEventCallback. -// -// protected static -void -nsAppShell::ProcessGeckoEvents(void* aInfo) -{ - nsAppShell* self = static_cast (aInfo); - self->NativeEventCallback(); - self->Release(); -} - -// WillTerminate -// -// public -void -nsAppShell::WillTerminate() -{ - mNotifiedWillTerminate = true; - if (mTerminated) - return; - mTerminated = true; - // We won't get another chance to process events - NS_ProcessPendingEvents(NS_GetCurrentThread()); - - // Unless we call nsBaseAppShell::Exit() here, it might not get called - // at all. - nsBaseAppShell::Exit(); -} - -// ScheduleNativeEventCallback -// -// protected virtual -void -nsAppShell::ScheduleNativeEventCallback() -{ - if (mTerminated) - return; - - NS_ADDREF_THIS(); - - // This will invoke ProcessGeckoEvents on the main thread. - ::CFRunLoopSourceSignal(mCFRunLoopSource); - ::CFRunLoopWakeUp(mCFRunLoop); -} - -// ProcessNextNativeEvent -// -// protected virtual -bool -nsAppShell::ProcessNextNativeEvent(bool aMayWait) -{ - if (mTerminated) - return false; - - NSString* currentMode = nil; - NSDate* waitUntil = nil; - if (aMayWait) - waitUntil = [NSDate distantFuture]; - NSRunLoop* currentRunLoop = [NSRunLoop currentRunLoop]; - - BOOL eventProcessed = NO; - do { - currentMode = [currentRunLoop currentMode]; - if (!currentMode) - currentMode = NSDefaultRunLoopMode; - - if (aMayWait) - eventProcessed = [currentRunLoop runMode:currentMode beforeDate:waitUntil]; - else - [currentRunLoop acceptInputForMode:currentMode beforeDate:waitUntil]; - } while(eventProcessed && aMayWait); - - return false; -} - -// Run -// -// public -NS_IMETHODIMP -nsAppShell::Run(void) -{ - ALOG("nsAppShell::Run"); - char argv[1][4] = {"app"}; - UIApplicationMain(1, (char**)argv, nil, @"AppShellDelegate"); - // UIApplicationMain doesn't exit. :-( - return NS_OK; -} - -NS_IMETHODIMP -nsAppShell::Exit(void) -{ - if (mTerminated) - return NS_OK; - - mTerminated = true; - return nsBaseAppShell::Exit(); -} diff --git a/widget/uikit/nsLookAndFeel.h b/widget/uikit/nsLookAndFeel.h deleted file mode 100644 index 91c0c2d73e..0000000000 --- a/widget/uikit/nsLookAndFeel.h +++ /dev/null @@ -1,35 +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 -#define __nsLookAndFeel - -#include "nsXPLookAndFeel.h" - -class nsLookAndFeel: public nsXPLookAndFeel -{ -public: - nsLookAndFeel(); - virtual ~nsLookAndFeel(); - - virtual nsresult NativeGetColor(const 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() - { - return true; - } -}; - -#endif diff --git a/widget/uikit/nsLookAndFeel.mm b/widget/uikit/nsLookAndFeel.mm deleted file mode 100644 index bb593eb51e..0000000000 --- a/widget/uikit/nsLookAndFeel.mm +++ /dev/null @@ -1,401 +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/. */ - -#import -#import - -#include "nsLookAndFeel.h" -#include "nsStyleConsts.h" -#include "gfxFont.h" -#include "gfxFontConstants.h" - -nsLookAndFeel::nsLookAndFeel() - : nsXPLookAndFeel() -{ -} - -nsLookAndFeel::~nsLookAndFeel() -{ -} - -static nscolor GetColorFromUIColor(UIColor* aColor) -{ - CGColorRef cgColor = [aColor CGColor]; - CGColorSpaceModel model = CGColorSpaceGetModel(CGColorGetColorSpace(cgColor)); - const CGFloat* components = CGColorGetComponents(cgColor); - if (model == kCGColorSpaceModelRGB) { - return NS_RGB((unsigned int)(components[0] * 255.0), - (unsigned int)(components[1] * 255.0), - (unsigned int)(components[2] * 255.0)); - } - else if (model == kCGColorSpaceModelMonochrome) { - unsigned int val = (unsigned int)(components[0] * 255.0); - return NS_RGBA(val, val, val, - (unsigned int)(components[1] * 255.0)); - } - NS_NOTREACHED("Unhandled color space!"); - return 0; -} - -nsresult -nsLookAndFeel::NativeGetColor(const ColorID aID, nscolor &aResult) -{ - nsresult res = NS_OK; - - switch (aID) { - case eColorID_WindowBackground: - aResult = NS_RGB(0xff,0xff,0xff); - break; - case eColorID_WindowForeground: - aResult = NS_RGB(0x00,0x00,0x00); - break; - case eColorID_WidgetBackground: - aResult = NS_RGB(0xdd,0xdd,0xdd); - break; - case eColorID_WidgetForeground: - aResult = NS_RGB(0x00,0x00,0x00); - break; - case eColorID_WidgetSelectBackground: - aResult = NS_RGB(0x80,0x80,0x80); - break; - case eColorID_WidgetSelectForeground: - aResult = NS_RGB(0x00,0x00,0x80); - break; - case eColorID_Widget3DHighlight: - aResult = NS_RGB(0xa0,0xa0,0xa0); - break; - case eColorID_Widget3DShadow: - aResult = NS_RGB(0x40,0x40,0x40); - break; - case eColorID_TextBackground: - aResult = NS_RGB(0xff,0xff,0xff); - break; - case eColorID_TextForeground: - aResult = NS_RGB(0x00,0x00,0x00); - break; - case eColorID_TextSelectBackground: - case eColorID_highlight: // CSS2 color - aResult = NS_RGB(0xaa,0xaa,0xaa); - break; - case eColorID__moz_menuhover: - aResult = NS_RGB(0xee,0xee,0xee); - break; - case eColorID_TextSelectForeground: - case eColorID_highlighttext: // CSS2 color - case eColorID__moz_menuhovertext: - GetColor(eColorID_TextSelectBackground, aResult); - if (aResult == 0x000000) - aResult = NS_RGB(0xff,0xff,0xff); - else - aResult = NS_DONT_CHANGE_COLOR; - break; - case eColorID_IMESelectedRawTextBackground: - case eColorID_IMESelectedConvertedTextBackground: - case eColorID_IMERawInputBackground: - case eColorID_IMEConvertedTextBackground: - aResult = NS_TRANSPARENT; - break; - case eColorID_IMESelectedRawTextForeground: - case eColorID_IMESelectedConvertedTextForeground: - case eColorID_IMERawInputForeground: - case eColorID_IMEConvertedTextForeground: - aResult = NS_SAME_AS_FOREGROUND_COLOR; - break; - case eColorID_IMERawInputUnderline: - case eColorID_IMEConvertedTextUnderline: - aResult = NS_40PERCENT_FOREGROUND_COLOR; - break; - case eColorID_IMESelectedRawTextUnderline: - case eColorID_IMESelectedConvertedTextUnderline: - aResult = NS_SAME_AS_FOREGROUND_COLOR; - break; - case eColorID_SpellCheckerUnderline: - aResult = NS_RGB(0xff, 0, 0); - break; - - // - // css2 system colors http://www.w3.org/TR/REC-CSS2/ui.html#system-colors - // - case eColorID_buttontext: - case eColorID__moz_buttonhovertext: - case eColorID_captiontext: - case eColorID_menutext: - case eColorID_infotext: - case eColorID__moz_menubartext: - case eColorID_windowtext: - aResult = GetColorFromUIColor([UIColor darkTextColor]); - break; - case eColorID_activecaption: - aResult = NS_RGB(0xff,0xff,0xff); - break; - case eColorID_activeborder: - aResult = NS_RGB(0x00,0x00,0x00); - break; - case eColorID_appworkspace: - aResult = NS_RGB(0xFF,0xFF,0xFF); - break; - case eColorID_background: - aResult = NS_RGB(0x63,0x63,0xCE); - break; - case eColorID_buttonface: - case eColorID__moz_buttonhoverface: - aResult = NS_RGB(0xF0,0xF0,0xF0); - break; - case eColorID_buttonhighlight: - aResult = NS_RGB(0xFF,0xFF,0xFF); - break; - case eColorID_buttonshadow: - aResult = NS_RGB(0xDC,0xDC,0xDC); - break; - case eColorID_graytext: - aResult = NS_RGB(0x44,0x44,0x44); - break; - case eColorID_inactiveborder: - aResult = NS_RGB(0xff,0xff,0xff); - break; - case eColorID_inactivecaption: - aResult = NS_RGB(0xaa,0xaa,0xaa); - break; - case eColorID_inactivecaptiontext: - aResult = NS_RGB(0x45,0x45,0x45); - break; - case eColorID_scrollbar: - aResult = NS_RGB(0,0,0); //XXX - break; - case eColorID_threeddarkshadow: - aResult = NS_RGB(0xDC,0xDC,0xDC); - break; - case eColorID_threedshadow: - aResult = NS_RGB(0xE0,0xE0,0xE0); - break; - case eColorID_threedface: - aResult = NS_RGB(0xF0,0xF0,0xF0); - break; - case eColorID_threedhighlight: - aResult = NS_RGB(0xff,0xff,0xff); - break; - case eColorID_threedlightshadow: - aResult = NS_RGB(0xDA,0xDA,0xDA); - break; - case eColorID_menu: - aResult = NS_RGB(0xff,0xff,0xff); - break; - case eColorID_infobackground: - aResult = NS_RGB(0xFF,0xFF,0xC7); - break; - case eColorID_windowframe: - aResult = NS_RGB(0xaa,0xaa,0xaa); - break; - case eColorID_window: - case eColorID__moz_field: - case eColorID__moz_combobox: - aResult = NS_RGB(0xff,0xff,0xff); - break; - case eColorID__moz_fieldtext: - case eColorID__moz_comboboxtext: - aResult = GetColorFromUIColor([UIColor darkTextColor]); - break; - case eColorID__moz_dialog: - aResult = NS_RGB(0xaa,0xaa,0xaa); - break; - case eColorID__moz_dialogtext: - case eColorID__moz_cellhighlighttext: - case eColorID__moz_html_cellhighlighttext: - aResult = GetColorFromUIColor([UIColor darkTextColor]); - break; - case eColorID__moz_dragtargetzone: - case eColorID__moz_mac_chrome_active: - case eColorID__moz_mac_chrome_inactive: - aResult = NS_RGB(0xaa,0xaa,0xaa); - break; - case eColorID__moz_mac_focusring: - aResult = NS_RGB(0x3F,0x98,0xDD); - break; - case eColorID__moz_mac_menushadow: - aResult = NS_RGB(0xA3,0xA3,0xA3); - break; - case eColorID__moz_mac_menutextdisable: - aResult = NS_RGB(0x88,0x88,0x88); - break; - case eColorID__moz_mac_menutextselect: - aResult = NS_RGB(0xaa,0xaa,0xaa); - break; - case eColorID__moz_mac_disabledtoolbartext: - aResult = NS_RGB(0x3F,0x3F,0x3F); - break; - case eColorID__moz_mac_menuselect: - aResult = NS_RGB(0xaa,0xaa,0xaa); - break; - case eColorID__moz_buttondefault: - aResult = NS_RGB(0xDC,0xDC,0xDC); - break; - case eColorID__moz_cellhighlight: - case eColorID__moz_html_cellhighlight: - case eColorID__moz_mac_secondaryhighlight: - // For inactive list selection - aResult = NS_RGB(0xaa,0xaa,0xaa); - break; - case eColorID__moz_eventreerow: - // Background color of even list rows. - aResult = NS_RGB(0xff,0xff,0xff); - break; - case eColorID__moz_oddtreerow: - // Background color of odd list rows. - aResult = NS_TRANSPARENT; - break; - case eColorID__moz_nativehyperlinktext: - // There appears to be no available system defined color. HARDCODING to the appropriate color. - aResult = NS_RGB(0x14,0x4F,0xAE); - break; - default: - NS_WARNING("Someone asked nsILookAndFeel for a color I don't know about"); - aResult = NS_RGB(0xff,0xff,0xff); - res = NS_ERROR_FAILURE; - break; - } - - return res; -} - -NS_IMETHODIMP -nsLookAndFeel::GetIntImpl(IntID aID, int32_t &aResult) -{ - 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 nsEventStateManager::sTextfieldSelectModel - aResult = 1; - break; - case eIntID_SubmenuDelay: - aResult = 200; - 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_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: - aResult = 0; - res = NS_ERROR_NOT_IMPLEMENTED; - break; - case eIntID_MacGraphiteTheme: - aResult = 0; - break; - case eIntID_TabFocusModel: - aResult = 1; // default to just textboxes - break; - case eIntID_ScrollToClick: - aResult = 0; - 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_ContextMenuOffsetVertical: - case eIntID_ContextMenuOffsetHorizontal: - aResult = 2; - break; - default: - aResult = 0; - res = NS_ERROR_FAILURE; - } - return res; -} - -NS_IMETHODIMP -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::GetFontImpl(FontID aID, nsString &aFontName, - gfxFontStyle &aFontStyle, - float aDevPixPerCSSPixel) -{ - // 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; - } - - //TODO: implement more here? - return false; -} diff --git a/widget/uikit/nsScreenManager.h b/widget/uikit/nsScreenManager.h deleted file mode 100644 index 1ff6a87ec7..0000000000 --- a/widget/uikit/nsScreenManager.h +++ /dev/null @@ -1,60 +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 nsScreenManager_h_ -#define nsScreenManager_h_ - -#include "nsBaseScreen.h" -#include "nsIScreenManager.h" -#include "nsCOMPtr.h" -#include "nsRect.h" - -@class UIScreen; - -class UIKitScreen : public nsBaseScreen -{ -public: - explicit UIKitScreen (UIScreen* screen); - ~UIKitScreen () {} - - NS_IMETHOD GetId(uint32_t* outId) { - *outId = 0; - return NS_OK; - } - - NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight); - NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight); - NS_IMETHOD GetRectDisplayPix(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight); - NS_IMETHOD GetAvailRectDisplayPix(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight); - NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth); - NS_IMETHOD GetColorDepth(int32_t* aColorDepth); - NS_IMETHOD GetContentsScaleFactor(double* aContentsScaleFactor); - NS_IMETHOD GetDefaultCSSScaleFactor(double* aScaleFactor) - { - return GetContentsScaleFactor(aScaleFactor); - } - -private: - UIScreen* mScreen; -}; - -class UIKitScreenManager : public nsIScreenManager -{ -public: - UIKitScreenManager (); - - NS_DECL_ISUPPORTS - - NS_DECL_NSISCREENMANAGER - - static LayoutDeviceIntRect GetBounds(); - -private: - virtual ~UIKitScreenManager () {} - //TODO: support >1 screen, iPad supports external displays - nsCOMPtr mScreen; -}; - -#endif // nsScreenManager_h_ diff --git a/widget/uikit/nsScreenManager.mm b/widget/uikit/nsScreenManager.mm deleted file mode 100644 index 601c911cd9..0000000000 --- a/widget/uikit/nsScreenManager.mm +++ /dev/null @@ -1,146 +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/. */ - -#import - -#include "gfxPoint.h" -#include "nsScreenManager.h" -#include "nsAppShell.h" - -static LayoutDeviceIntRect gScreenBounds; -static bool gScreenBoundsSet = false; - -UIKitScreen::UIKitScreen(UIScreen* aScreen) -{ - mScreen = [aScreen retain]; -} - -NS_IMETHODIMP -UIKitScreen::GetRect(int32_t *outX, int32_t *outY, int32_t *outWidth, int32_t *outHeight) -{ - return GetRectDisplayPix(outX, outY, outWidth, outHeight); -} - -NS_IMETHODIMP -UIKitScreen::GetAvailRect(int32_t *outX, int32_t *outY, int32_t *outWidth, int32_t *outHeight) -{ - return GetAvailRectDisplayPix(outX, outY, outWidth, outHeight); -} - -NS_IMETHODIMP -UIKitScreen::GetRectDisplayPix(int32_t *outX, int32_t *outY, int32_t *outWidth, int32_t *outHeight) -{ - nsIntRect rect = UIKitScreenManager::GetBounds(); - *outX = rect.x; - *outY = rect.y; - *outWidth = rect.width; - *outHeight = rect.height; - - return NS_OK; -} - -NS_IMETHODIMP -UIKitScreen::GetAvailRectDisplayPix(int32_t *outX, int32_t *outY, int32_t *outWidth, int32_t *outHeight) -{ - CGRect rect = [mScreen applicationFrame]; - CGFloat scale = [mScreen scale]; - - *outX = rect.origin.x * scale; - *outY = rect.origin.y * scale; - *outWidth = rect.size.width * scale; - *outHeight = rect.size.height * scale; - - return NS_OK; -} - -NS_IMETHODIMP -UIKitScreen::GetPixelDepth(int32_t *aPixelDepth) -{ - // Close enough. - *aPixelDepth = 24; - return NS_OK; -} - -NS_IMETHODIMP -UIKitScreen::GetColorDepth(int32_t *aColorDepth) -{ - return GetPixelDepth(aColorDepth); -} - -NS_IMETHODIMP -UIKitScreen::GetContentsScaleFactor(double* aContentsScaleFactor) -{ - *aContentsScaleFactor = [mScreen scale]; - return NS_OK; -} - -NS_IMPL_ISUPPORTS(UIKitScreenManager, nsIScreenManager) - -UIKitScreenManager::UIKitScreenManager() -: mScreen(new UIKitScreen([UIScreen mainScreen])) -{ -} - -LayoutDeviceIntRect -UIKitScreenManager::GetBounds() -{ - if (!gScreenBoundsSet) { - CGRect rect = [[UIScreen mainScreen] bounds]; - CGFloat scale = [[UIScreen mainScreen] scale]; - gScreenBounds.x = rect.origin.x * scale; - gScreenBounds.y = rect.origin.y * scale; - gScreenBounds.width = rect.size.width * scale; - gScreenBounds.height = rect.size.height * scale; - gScreenBoundsSet = true; - } - printf("UIKitScreenManager::GetBounds: %d %d %d %d\n", - gScreenBounds.x, gScreenBounds.y, gScreenBounds.width, gScreenBounds.height); - return gScreenBounds; -} - -NS_IMETHODIMP -UIKitScreenManager::GetPrimaryScreen(nsIScreen** outScreen) -{ - NS_IF_ADDREF(*outScreen = mScreen.get()); - return NS_OK; -} - -NS_IMETHODIMP -UIKitScreenManager::ScreenForRect(int32_t inLeft, - int32_t inTop, - int32_t inWidth, - int32_t inHeight, - nsIScreen** outScreen) -{ - return GetPrimaryScreen(outScreen); -} - -NS_IMETHODIMP -UIKitScreenManager::ScreenForId(uint32_t id, - nsIScreen** outScreen) -{ - return GetPrimaryScreen(outScreen); -} - -NS_IMETHODIMP -UIKitScreenManager::ScreenForNativeWidget(void* aWidget, nsIScreen** outScreen) -{ - return GetPrimaryScreen(outScreen); -} - -NS_IMETHODIMP -UIKitScreenManager::GetNumberOfScreens(uint32_t* aNumberOfScreens) -{ - //TODO: support multiple screens - *aNumberOfScreens = 1; - return NS_OK; -} - -NS_IMETHODIMP -UIKitScreenManager::GetSystemDefaultScale(float* aScale) -{ - *aScale = [UIScreen mainScreen].scale; - return NS_OK; -} diff --git a/widget/uikit/nsWidgetFactory.mm b/widget/uikit/nsWidgetFactory.mm deleted file mode 100644 index 9e4f028ff6..0000000000 --- a/widget/uikit/nsWidgetFactory.mm +++ /dev/null @@ -1,71 +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 "nsIFactory.h" -#include "nsISupports.h" -#include "nsIComponentManager.h" -#include "mozilla/ModuleUtils.h" - -#include "nsWidgetsCID.h" - -#include "nsAppShell.h" -#include "nsAppShellSingleton.h" -#include "nsLookAndFeel.h" -#include "nsScreenManager.h" -#include "nsWindow.h" - -NS_GENERIC_FACTORY_CONSTRUCTOR(UIKitScreenManager) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindow) - -#include "GfxInfo.h" -namespace mozilla { -namespace widget { -// This constructor should really be shared with all platforms. -NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(GfxInfo, Init) -} -} - -NS_DEFINE_NAMED_CID(NS_WINDOW_CID); -NS_DEFINE_NAMED_CID(NS_CHILD_CID); -NS_DEFINE_NAMED_CID(NS_APPSHELL_CID); -NS_DEFINE_NAMED_CID(NS_SCREENMANAGER_CID); -NS_DEFINE_NAMED_CID(NS_GFXINFO_CID); - -static const mozilla::Module::CIDEntry kWidgetCIDs[] = { - { &kNS_WINDOW_CID, false, nullptr, nsWindowConstructor }, - { &kNS_CHILD_CID, false, nullptr, nsWindowConstructor }, - { &kNS_APPSHELL_CID, false, nullptr, nsAppShellConstructor }, - { &kNS_SCREENMANAGER_CID, false, nullptr, UIKitScreenManagerConstructor }, - { &kNS_GFXINFO_CID, false, nullptr, mozilla::widget::GfxInfoConstructor }, - { nullptr } -}; - -static const mozilla::Module::ContractIDEntry kWidgetContracts[] = { - { "@mozilla.org/widgets/window/uikit;1", &kNS_WINDOW_CID }, - { "@mozilla.org/widgets/childwindow/uikit;1", &kNS_CHILD_CID }, - { "@mozilla.org/widget/appshell/uikit;1", &kNS_APPSHELL_CID }, - { "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID }, - { "@mozilla.org/gfx/info;1", &kNS_GFXINFO_CID }, - { nullptr } -}; - -static void -nsWidgetUIKitModuleDtor() -{ - nsLookAndFeel::Shutdown(); - nsAppShellShutdown(); -} - -static const mozilla::Module kWidgetModule = { - mozilla::Module::kVersion, - kWidgetCIDs, - kWidgetContracts, - nullptr, - nullptr, - nsAppShellInit, - nsWidgetUIKitModuleDtor -}; - -NSMODULE_DEFN(nsWidgetUIKitModule) = &kWidgetModule; diff --git a/widget/uikit/nsWindow.h b/widget/uikit/nsWindow.h deleted file mode 100644 index cb18c09069..0000000000 --- a/widget/uikit/nsWindow.h +++ /dev/null @@ -1,125 +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 NSWINDOW_H_ -#define NSWINDOW_H_ - -#include "nsBaseWidget.h" -#include "gfxPoint.h" - -#include "nsTArray.h" - -@class UIWindow; -@class UIView; -@class ChildView; - -class nsWindow : - public nsBaseWidget -{ - typedef nsBaseWidget Inherited; - -public: - nsWindow(); - - NS_DECL_ISUPPORTS_INHERITED - - // - // nsIWidget - // - - 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; - NS_IMETHOD Enable(bool aState) override { - return NS_OK; - } - virtual bool IsEnabled() const override { - return true; - } - virtual bool IsVisible() const override { - return mVisible; - } - NS_IMETHOD SetFocus(bool aState=false) override; - virtual LayoutDeviceIntPoint WidgetToScreenOffset() override; - - virtual void SetBackgroundColor(const nscolor &aColor) override; - virtual void* GetNativeData(uint32_t aDataType) override; - - NS_IMETHOD Move(double aX, double aY) override; - virtual void SetSizeMode(nsSizeMode aMode) override; - void EnteredFullScreen(bool aFullScreen); - 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 GetScreenBounds() override; - void ReportMoveEvent(); - void ReportSizeEvent(); - void ReportSizeModeEvent(nsSizeMode aMode); - - CGFloat BackingScaleFactor(); - void BackingScaleFactorChanged(); - virtual float GetDPI() override { - //XXX: terrible - return 326.0f; - } - virtual double GetDefaultScaleInternal() override { - return BackingScaleFactor(); - } - virtual int32_t RoundsWidgetCoordinatesTo() override; - - NS_IMETHOD SetTitle(const nsAString& aTitle) override { - return NS_OK; - } - - NS_IMETHOD Invalidate(const LayoutDeviceIntRect& aRect) override; - virtual nsresult ConfigureChildren(const nsTArray& aConfigurations) override; - NS_IMETHOD DispatchEvent(mozilla::WidgetGUIEvent* aEvent, - nsEventStatus& aStatus) override; - - void WillPaintWindow(); - bool PaintWindow(LayoutDeviceIntRegion aRegion); - - bool HasModalDescendents() { return false; } - - //NS_IMETHOD NotifyIME(const IMENotification& aIMENotification) override; - NS_IMETHOD_(void) SetInputContext( - const InputContext& aContext, - const InputContextAction& aAction); - NS_IMETHOD_(InputContext) GetInputContext(); - /* - NS_IMETHOD_(bool) ExecuteNativeKeyBinding( - NativeKeyBindingsType aType, - const mozilla::WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData) override; - */ - -protected: - virtual ~nsWindow(); - void BringToFront(); - nsWindow *FindTopLevel(); - bool IsTopLevel(); - nsresult GetCurrentOffset(uint32_t &aOffset, uint32_t &aLength); - nsresult DeleteRange(int aOffset, int aLen); - - void TearDownView(); - - ChildView* mNativeView; - bool mVisible; - nsTArray mChildren; - nsWindow* mParent; - InputContext mInputContext; - - void OnSizeChanged(const mozilla::gfx::IntSize& aSize); - - static void DumpWindows(); - static void DumpWindows(const nsTArray& wins, int indent = 0); - static void LogWindow(nsWindow *win, int index, int indent); -}; - -#endif /* NSWINDOW_H_ */ diff --git a/widget/uikit/nsWindow.mm b/widget/uikit/nsWindow.mm deleted file mode 100644 index 874626237c..0000000000 --- a/widget/uikit/nsWindow.mm +++ /dev/null @@ -1,862 +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/. */ - -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import - -#include - -#include "nsWindow.h" -#include "nsScreenManager.h" -#include "nsAppShell.h" - -#include "nsWidgetsCID.h" -#include "nsGfxCIID.h" - -#include "gfxQuartzSurface.h" -#include "gfxUtils.h" -#include "gfxImageSurface.h" -#include "gfxContext.h" -#include "nsRegion.h" -#include "Layers.h" -#include "nsTArray.h" - -#include "mozilla/BasicEvents.h" -#include "mozilla/TouchEvents.h" -#include "mozilla/Unused.h" - -#include "GeckoProfiler.h" - -using namespace mozilla; -using namespace mozilla::dom; -using namespace mozilla::layers; - -#define ALOG(args...) fprintf(stderr, args); fprintf(stderr, "\n") - -static LayoutDeviceIntPoint -UIKitPointsToDevPixels(CGPoint aPoint, CGFloat aBackingScale) -{ - return LayoutDeviceIntPoint(NSToIntRound(aPoint.x * aBackingScale), - NSToIntRound(aPoint.y * aBackingScale)); -} - -static CGRect -DevPixelsToUIKitPoints(const LayoutDeviceIntRect& aRect, CGFloat aBackingScale) -{ - return CGRectMake((CGFloat)aRect.x / aBackingScale, - (CGFloat)aRect.y / aBackingScale, - (CGFloat)aRect.width / aBackingScale, - (CGFloat)aRect.height / aBackingScale); -} - -// Used to retain a Cocoa object for the remainder of a method's execution. -class nsAutoRetainUIKitObject { -public: -nsAutoRetainUIKitObject(id anObject) -{ - mObject = [anObject retain]; -} -~nsAutoRetainUIKitObject() -{ - [mObject release]; -} -private: - id mObject; // [STRONG] -}; - -@interface ChildView : UIView -{ -@public - nsWindow* mGeckoChild; // weak ref - BOOL mWaitingForPaint; - CFMutableDictionaryRef mTouches; - int mNextTouchID; -} -// sets up our view, attaching it to its owning gecko view -- (id)initWithFrame:(CGRect)inFrame geckoChild:(nsWindow*)inChild; -// Our Gecko child was Destroy()ed -- (void)widgetDestroyed; -// Tear down this ChildView -- (void)delayedTearDown; -- (void)sendMouseEvent:(EventMessage) aType point:(LayoutDeviceIntPoint)aPoint widget:(nsWindow*)aWindow; -- (void)handleTap:(UITapGestureRecognizer *)sender; -- (BOOL)isUsingMainThreadOpenGL; -- (void)drawUsingOpenGL; -- (void)drawUsingOpenGLCallback; -- (void)sendTouchEvent:(EventMessage) aType touches:(NSSet*)aTouches widget:(nsWindow*)aWindow; -// Event handling (UIResponder) -- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; -- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event; -- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; -- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; -@end - -@implementation ChildView -+ (Class)layerClass { - return [CAEAGLLayer class]; -} - -- (id)initWithFrame:(CGRect)inFrame geckoChild:(nsWindow*)inChild -{ - self.multipleTouchEnabled = YES; - if ((self = [super initWithFrame:inFrame])) { - mGeckoChild = inChild; - } - ALOG("[ChildView[%p] initWithFrame:] (mGeckoChild = %p)", (void*)self, (void*)mGeckoChild); - self.opaque = YES; - self.alpha = 1.0; - - UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] - initWithTarget:self action:@selector(handleTap:)]; - tapRecognizer.numberOfTapsRequired = 1; - [self addGestureRecognizer:tapRecognizer]; - - mTouches = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr); - mNextTouchID = 0; - return self; -} - -- (void)widgetDestroyed -{ - mGeckoChild = nullptr; - CFRelease(mTouches); -} - -- (void)delayedTearDown -{ - [self removeFromSuperview]; - [self release]; -} - -- (void)sendMouseEvent:(EventMessage) aType point:(LayoutDeviceIntPoint)aPoint widget:(nsWindow*)aWindow -{ - WidgetMouseEvent event(true, aType, aWindow, - WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal); - - event.mRefPoint = aPoint; - event.mClickCount = 1; - event.button = WidgetMouseEvent::eLeftButton; - event.mTime = PR_IntervalNow(); - event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN; - - nsEventStatus status; - aWindow->DispatchEvent(&event, status); -} - -- (void)handleTap:(UITapGestureRecognizer *)sender -{ - if (sender.state == UIGestureRecognizerStateEnded) { - ALOG("[ChildView[%p] handleTap]", self); - LayoutDeviceIntPoint lp = UIKitPointsToDevPixels([sender locationInView:self], [self contentScaleFactor]); - [self sendMouseEvent:eMouseMove point:lp widget:mGeckoChild]; - [self sendMouseEvent:eMouseDown point:lp widget:mGeckoChild]; - [self sendMouseEvent:eMouseUp point:lp widget:mGeckoChild]; - } -} - -- (void)sendTouchEvent:(EventMessage) aType touches:(NSSet*)aTouches widget:(nsWindow*)aWindow -{ - WidgetTouchEvent event(true, aType, aWindow); - //XXX: I think nativeEvent.timestamp * 1000 is probably usable here but - // I don't care that much right now. - event.mTime = PR_IntervalNow(); - event.mTouches.SetCapacity(aTouches.count); - for (UITouch* touch in aTouches) { - LayoutDeviceIntPoint loc = UIKitPointsToDevPixels([touch locationInView:self], [self contentScaleFactor]); - LayoutDeviceIntPoint radius = UIKitPointsToDevPixels([touch majorRadius], [touch majorRadius]); - void* value; - if (!CFDictionaryGetValueIfPresent(mTouches, touch, (const void**)&value)) { - // This shouldn't happen. - NS_ASSERTION(false, "Got a touch that we didn't know about"); - continue; - } - int id = reinterpret_cast(value); - RefPtr t = new Touch(id, loc, radius, 0.0f, 1.0f); - event.mRefPoint = loc; - event.mTouches.AppendElement(t); - } - aWindow->DispatchInputEvent(&event); -} - -- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event -{ - ALOG("[ChildView[%p] touchesBegan", self); - if (!mGeckoChild) - return; - - for (UITouch* touch : touches) { - CFDictionaryAddValue(mTouches, touch, (void*)mNextTouchID); - mNextTouchID++; - } - [self sendTouchEvent:eTouchStart - touches:[event allTouches] - widget:mGeckoChild]; -} - -- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event -{ - ALOG("[ChildView[%p] touchesCancelled", self); - [self sendTouchEvent:eTouchCancel touches:touches widget:mGeckoChild]; - for (UITouch* touch : touches) { - CFDictionaryRemoveValue(mTouches, touch); - } - if (CFDictionaryGetCount(mTouches) == 0) { - mNextTouchID = 0; - } -} - -- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event -{ - ALOG("[ChildView[%p] touchesEnded", self); - if (!mGeckoChild) - return; - - [self sendTouchEvent:eTouchEnd touches:touches widget:mGeckoChild]; - for (UITouch* touch : touches) { - CFDictionaryRemoveValue(mTouches, touch); - } - if (CFDictionaryGetCount(mTouches) == 0) { - mNextTouchID = 0; - } -} - -- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event -{ - ALOG("[ChildView[%p] touchesMoved", self); - if (!mGeckoChild) - return; - - [self sendTouchEvent:eTouchMove - touches:[event allTouches] - widget:mGeckoChild]; -} - -- (void)setNeedsDisplayInRect:(CGRect)aRect -{ - if ([self isUsingMainThreadOpenGL]) { - // Draw without calling drawRect. This prevent us from - // needing to access the normal window buffer surface unnecessarily, so we - // waste less time synchronizing the two surfaces. - if (!mWaitingForPaint) { - mWaitingForPaint = YES; - // Use NSRunLoopCommonModes instead of the default NSDefaultRunLoopMode - // so that the timer also fires while a native menu is open. - [self performSelector:@selector(drawUsingOpenGLCallback) - withObject:nil - afterDelay:0 - inModes:[NSArray arrayWithObject:NSRunLoopCommonModes]]; - } - } -} - -- (BOOL)isUsingMainThreadOpenGL -{ - if (!mGeckoChild || ![self window]) - return NO; - - return mGeckoChild->GetLayerManager(nullptr)->GetBackendType() == mozilla::layers::LayersBackend::LAYERS_OPENGL; -} - -- (void)drawUsingOpenGL -{ - ALOG("drawUsingOpenGL"); - PROFILER_LABEL("ChildView", "drawUsingOpenGL", - js::ProfileEntry::Category::GRAPHICS); - - if (!mGeckoChild->IsVisible()) - return; - - mWaitingForPaint = NO; - - LayoutDeviceIntRect geckoBounds = mGeckoChild->GetBounds(); - LayoutDeviceIntRegion region(geckoBounds); - - mGeckoChild->PaintWindow(region); -} - -// Called asynchronously after setNeedsDisplay in order to avoid entering the -// normal drawing machinery. -- (void)drawUsingOpenGLCallback -{ - if (mWaitingForPaint) { - [self drawUsingOpenGL]; - } -} - -// The display system has told us that a portion of our view is dirty. Tell -// gecko to paint it -- (void)drawRect:(CGRect)aRect -{ - CGContextRef cgContext = UIGraphicsGetCurrentContext(); - [self drawRect:aRect inContext:cgContext]; -} - -- (void)drawRect:(CGRect)aRect inContext:(CGContextRef)aContext -{ -#ifdef DEBUG_UPDATE - LayoutDeviceIntRect geckoBounds = mGeckoChild->GetBounds(); - - fprintf (stderr, "---- Update[%p][%p] [%f %f %f %f] cgc: %p\n gecko bounds: [%d %d %d %d]\n", - self, mGeckoChild, - aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height, aContext, - geckoBounds.x, geckoBounds.y, geckoBounds.width, geckoBounds.height); - - CGAffineTransform xform = CGContextGetCTM(aContext); - fprintf (stderr, " xform in: [%f %f %f %f %f %f]\n", xform.a, xform.b, xform.c, xform.d, xform.tx, xform.ty); -#endif - - if (true) { - // For Gecko-initiated repaints in OpenGL mode, drawUsingOpenGL is - // directly called from a delayed perform callback - without going through - // drawRect. - // Paints that come through here are triggered by something that Cocoa - // controls, for example by window resizing or window focus changes. - - // Do GL composition and return. - [self drawUsingOpenGL]; - return; - } - PROFILER_LABEL("ChildView", "drawRect", - js::ProfileEntry::Category::GRAPHICS); - - // The CGContext that drawRect supplies us with comes with a transform that - // scales one user space unit to one Cocoa point, which can consist of - // multiple dev pixels. But Gecko expects its supplied context to be scaled - // to device pixels, so we need to reverse the scaling. - double scale = mGeckoChild->BackingScaleFactor(); - CGContextSaveGState(aContext); - CGContextScaleCTM(aContext, 1.0 / scale, 1.0 / scale); - - CGSize viewSize = [self bounds].size; - gfx::IntSize backingSize(viewSize.width * scale, viewSize.height * scale); - - CGContextSaveGState(aContext); - - LayoutDeviceIntRegion region = - LayoutDeviceIntRect(NSToIntRound(aRect.origin.x * scale), - NSToIntRound(aRect.origin.y * scale), - NSToIntRound(aRect.size.width * scale), - NSToIntRound(aRect.size.height * scale)); - - // Create Cairo objects. - RefPtr targetSurface; - - RefPtr targetContext; - if (gfxPlatform::GetPlatform()->SupportsAzureContentForType(gfx::BackendType::CAIRO)) { - // This is dead code unless you mess with prefs, but keep it around for - // debugging. - targetSurface = new gfxQuartzSurface(aContext, backingSize); - targetSurface->SetAllowUseAsSource(false); - RefPtr dt = - gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(targetSurface, - backingSize); - if (!dt || !dt->IsValid()) { - gfxDevCrash(mozilla::gfx::LogReason::InvalidContext) << "Window context problem 2 " << backingSize; - return; - } - dt->AddUserData(&gfxContext::sDontUseAsSourceKey, dt, nullptr); - targetContext = gfxContext::CreateOrNull(dt); - } else { - MOZ_ASSERT_UNREACHABLE("COREGRAPHICS is the only supported backend"); - } - MOZ_ASSERT(targetContext); // already checked for valid draw targets above - - // Set up the clip region. - targetContext->NewPath(); - for (auto iter = region.RectIter(); !iter.Done(); iter.Next()) { - const LayoutDeviceIntRect& r = iter.Get(); - targetContext->Rectangle(gfxRect(r.x, r.y, r.width, r.height)); - } - targetContext->Clip(); - - //nsAutoRetainCocoaObject kungFuDeathGrip(self); - bool painted = false; - if (mGeckoChild->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_BASIC) { - nsBaseWidget::AutoLayerManagerSetup - setupLayerManager(mGeckoChild, targetContext, BufferMode::BUFFER_NONE); - painted = mGeckoChild->PaintWindow(region); - } else if (mGeckoChild->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT) { - // We only need this so that we actually get DidPaintWindow fired - painted = mGeckoChild->PaintWindow(region); - } - - targetContext = nullptr; - targetSurface = nullptr; - - CGContextRestoreGState(aContext); - - // Undo the scale transform so that from now on the context is in - // CocoaPoints again. - CGContextRestoreGState(aContext); - if (!painted && [self isOpaque]) { - // Gecko refused to draw, but we've claimed to be opaque, so we have to - // draw something--fill with white. - CGContextSetRGBFillColor(aContext, 1, 1, 1, 1); - CGContextFillRect(aContext, aRect); - } - -#ifdef DEBUG_UPDATE - fprintf (stderr, "---- update done ----\n"); - -#if 0 - CGContextSetRGBStrokeColor (aContext, - ((((unsigned long)self) & 0xff)) / 255.0, - ((((unsigned long)self) & 0xff00) >> 8) / 255.0, - ((((unsigned long)self) & 0xff0000) >> 16) / 255.0, - 0.5); -#endif - CGContextSetRGBStrokeColor(aContext, 1, 0, 0, 0.8); - CGContextSetLineWidth(aContext, 4.0); - CGContextStrokeRect(aContext, aRect); -#endif -} -@end - -NS_IMPL_ISUPPORTS_INHERITED0(nsWindow, Inherited) - -nsWindow::nsWindow() -: mNativeView(nullptr), - mVisible(false), - mParent(nullptr) -{ -} - -nsWindow::~nsWindow() -{ - [mNativeView widgetDestroyed]; // Safe if mNativeView is nil. - TearDownView(); // Safe if called twice. -} - -void nsWindow::TearDownView() -{ - if (!mNativeView) - return; - - [mNativeView performSelectorOnMainThread:@selector(delayedTearDown) withObject:nil waitUntilDone:false]; - mNativeView = nil; -} - -bool -nsWindow::IsTopLevel() -{ - return mWindowType == eWindowType_toplevel || - mWindowType == eWindowType_dialog || - mWindowType == eWindowType_invisible; -} - -// -// nsIWidget -// - -nsresult -nsWindow::Create(nsIWidget* aParent, - nsNativeWidget aNativeParent, - const LayoutDeviceIntRect& aRect, - nsWidgetInitData* aInitData) -{ - ALOG("nsWindow[%p]::Create %p/%p [%d %d %d %d]", (void*)this, (void*)aParent, (void*)aNativeParent, aRect.x, aRect.y, aRect.width, aRect.height); - nsWindow* parent = (nsWindow*) aParent; - ChildView* nativeParent = (ChildView*)aNativeParent; - - if (parent == nullptr && nativeParent) - parent = nativeParent->mGeckoChild; - if (parent && nativeParent == nullptr) - nativeParent = parent->mNativeView; - - // for toplevel windows, bounds are fixed to full screen size - if (parent == nullptr) { - if (nsAppShell::gWindow == nil) { - mBounds = UIKitScreenManager::GetBounds(); - } else { - CGRect cgRect = [nsAppShell::gWindow bounds]; - mBounds.x = cgRect.origin.x; - mBounds.y = cgRect.origin.y; - mBounds.width = cgRect.size.width; - mBounds.height = cgRect.size.height; - } - } else { - mBounds = aRect; - } - - ALOG("nsWindow[%p]::Create bounds: %d %d %d %d", (void*)this, - mBounds.x, mBounds.y, mBounds.width, mBounds.height); - - // Set defaults which can be overriden from aInitData in BaseCreate - mWindowType = eWindowType_toplevel; - mBorderStyle = eBorderStyle_default; - - Inherited::BaseCreate(aParent, aInitData); - - NS_ASSERTION(IsTopLevel() || parent, "non top level window doesn't have a parent!"); - - mNativeView = [[ChildView alloc] initWithFrame:DevPixelsToUIKitPoints(mBounds, BackingScaleFactor()) geckoChild:this]; - mNativeView.hidden = YES; - - if (parent) { - parent->mChildren.AppendElement(this); - mParent = parent; - } - - if (nativeParent) { - [nativeParent addSubview:mNativeView]; - } else if (nsAppShell::gWindow) { - [nsAppShell::gWindow.rootViewController.view addSubview:mNativeView]; - } - else { - [nsAppShell::gTopLevelViews addObject:mNativeView]; - } - - return NS_OK; -} - -void -nsWindow::Destroy() -{ - for (uint32_t i = 0; i < mChildren.Length(); ++i) { - // why do we still have children? - mChildren[i]->SetParent(nullptr); - } - - if (mParent) - mParent->mChildren.RemoveElement(this); - - [mNativeView widgetDestroyed]; - - nsBaseWidget::Destroy(); - - //ReportDestroyEvent(); - - TearDownView(); - - nsBaseWidget::OnDestroy(); - - return NS_OK; -} - -NS_IMETHODIMP -nsWindow::ConfigureChildren(const nsTArray& config) -{ - for (uint32_t i = 0; i < config.Length(); ++i) { - nsWindow *childWin = (nsWindow*) config[i].mChild.get(); - childWin->Resize(config[i].mBounds.x, - config[i].mBounds.y, - config[i].mBounds.width, - config[i].mBounds.height, - false); - } - - return NS_OK; -} - -NS_IMETHODIMP -nsWindow::Show(bool aState) -{ - if (aState != mVisible) { - mNativeView.hidden = aState ? NO : YES; - if (aState) { - UIView* parentView = mParent ? mParent->mNativeView : nsAppShell::gWindow.rootViewController.view; - [parentView bringSubviewToFront:mNativeView]; - [mNativeView setNeedsDisplay]; - } - mVisible = aState; - } - return NS_OK; -} - -NS_IMETHODIMP -nsWindow::Move(double aX, double aY) -{ - if (!mNativeView || (mBounds.x == aX && mBounds.y == aY)) - return NS_OK; - - //XXX: handle this - // The point we have is in Gecko coordinates (origin top-left). Convert - // it to Cocoa ones (origin bottom-left). - mBounds.x = aX; - mBounds.y = aY; - - mNativeView.frame = DevPixelsToUIKitPoints(mBounds, BackingScaleFactor()); - - if (mVisible) - [mNativeView setNeedsDisplay]; - - ReportMoveEvent(); - return NS_OK; -} - -NS_IMETHODIMP -nsWindow::Resize(double aX, double aY, - double aWidth, double aHeight, - bool aRepaint) -{ - BOOL isMoving = (mBounds.x != aX || mBounds.y != aY); - BOOL isResizing = (mBounds.width != aWidth || mBounds.height != aHeight); - if (!mNativeView || (!isMoving && !isResizing)) - return NS_OK; - - if (isMoving) { - mBounds.x = aX; - mBounds.y = aY; - } - if (isResizing) { - mBounds.width = aWidth; - mBounds.height = aHeight; - } - - [mNativeView setFrame:DevPixelsToUIKitPoints(mBounds, BackingScaleFactor())]; - - if (mVisible && aRepaint) - [mNativeView setNeedsDisplay]; - - if (isMoving) - ReportMoveEvent(); - - if (isResizing) - ReportSizeEvent(); - - return NS_OK; -} - -NS_IMETHODIMP nsWindow::Resize(double aWidth, double aHeight, bool aRepaint) -{ - if (!mNativeView || (mBounds.width == aWidth && mBounds.height == aHeight)) - return NS_OK; - - mBounds.width = aWidth; - mBounds.height = aHeight; - - [mNativeView setFrame:DevPixelsToUIKitPoints(mBounds, BackingScaleFactor())]; - - if (mVisible && aRepaint) - [mNativeView setNeedsDisplay]; - - ReportSizeEvent(); - - return NS_OK; -} - -void -nsWindow::SetSizeMode(nsSizeMode aMode) -{ - if (aMode == static_cast(mSizeMode)) { - return; - } - - mSizeMode = static_cast(aMode); - if (aMode == nsSizeMode_Maximized || aMode == nsSizeMode_Fullscreen) { - // Resize to fill screen - nsBaseWidget::InfallibleMakeFullScreen(true); - } - ReportSizeModeEvent(aMode); -} - -NS_IMETHODIMP -nsWindow::Invalidate(const LayoutDeviceIntRect& aRect) -{ - if (!mNativeView || !mVisible) - return NS_OK; - - MOZ_RELEASE_ASSERT(GetLayerManager()->GetBackendType() != LayersBackend::LAYERS_CLIENT, - "Shouldn't need to invalidate with accelerated OMTC layers!"); - - - [mNativeView setNeedsLayout]; - [mNativeView setNeedsDisplayInRect:DevPixelsToUIKitPoints(mBounds, BackingScaleFactor())]; - - return NS_OK; -} - -NS_IMETHODIMP -nsWindow::SetFocus(bool aRaise) -{ - [[mNativeView window] makeKeyWindow]; - [mNativeView becomeFirstResponder]; - return NS_OK; -} - -void nsWindow::WillPaintWindow() -{ - if (mWidgetListener) { - mWidgetListener->WillPaintWindow(this); - } -} - -bool nsWindow::PaintWindow(LayoutDeviceIntRegion aRegion) -{ - if (!mWidgetListener) - return false; - - bool returnValue = false; - returnValue = mWidgetListener->PaintWindow(this, aRegion); - - if (mWidgetListener) { - mWidgetListener->DidPaintWindow(); - } - - return returnValue; -} - -void nsWindow::ReportMoveEvent() -{ - NotifyWindowMoved(mBounds.x, mBounds.y); -} - -void nsWindow::ReportSizeModeEvent(nsSizeMode aMode) -{ - if (mWidgetListener) { - // This is terrible. - nsSizeMode theMode; - switch (aMode) { - case nsSizeMode_Maximized: - theMode = nsSizeMode_Maximized; - break; - case nsSizeMode_Fullscreen: - theMode = nsSizeMode_Fullscreen; - break; - default: - return; - } - mWidgetListener->SizeModeChanged(theMode); - } -} - -void nsWindow::ReportSizeEvent() -{ - if (mWidgetListener) { - LayoutDeviceIntRect innerBounds = GetClientBounds(); - mWidgetListener->WindowResized(this, innerBounds.width, innerBounds.height); - } -} - -LayoutDeviceIntRect -nsWindow::GetScreenBounds() -{ - return LayoutDeviceIntRect(WidgetToScreenOffset(), mBounds.Size()); -} - -LayoutDeviceIntPoint nsWindow::WidgetToScreenOffset() -{ - LayoutDeviceIntPoint offset(0, 0); - if (mParent) { - offset = mParent->WidgetToScreenOffset(); - } - - CGPoint temp = [mNativeView convertPoint:temp toView:nil]; - - if (!mParent && nsAppShell::gWindow) { - // convert to screen coords - temp = [nsAppShell::gWindow convertPoint:temp toWindow:nil]; - } - - offset.x += temp.x; - offset.y += temp.y; - - return offset; -} - -NS_IMETHODIMP -nsWindow::DispatchEvent(mozilla::WidgetGUIEvent* aEvent, - nsEventStatus& aStatus) -{ - aStatus = nsEventStatus_eIgnore; - nsCOMPtr kungFuDeathGrip(aEvent->mWidget); - - if (mWidgetListener) - aStatus = mWidgetListener->HandleEvent(aEvent, mUseAttachedEvents); - - return NS_OK; -} - -NS_IMETHODIMP_(void) -nsWindow::SetInputContext(const InputContext& aContext, - const InputContextAction& aAction) -{ - //TODO: actually show VKB - mInputContext = aContext; -} - -NS_IMETHODIMP_(mozilla::widget::InputContext) -nsWindow::GetInputContext() -{ - return mInputContext; -} - -void -nsWindow::SetBackgroundColor(const nscolor &aColor) -{ - mNativeView.backgroundColor = [UIColor colorWithRed:NS_GET_R(aColor) - green:NS_GET_G(aColor) - blue:NS_GET_B(aColor) - alpha:NS_GET_A(aColor)]; -} - -void* nsWindow::GetNativeData(uint32_t aDataType) -{ - void* retVal = nullptr; - - switch (aDataType) - { - case NS_NATIVE_WIDGET: - case NS_NATIVE_DISPLAY: - retVal = (void*)mNativeView; - break; - - case NS_NATIVE_WINDOW: - retVal = [mNativeView window]; - break; - - case NS_NATIVE_GRAPHIC: - NS_ERROR("Requesting NS_NATIVE_GRAPHIC on a UIKit child view!"); - break; - - case NS_NATIVE_OFFSETX: - retVal = 0; - break; - - case NS_NATIVE_OFFSETY: - retVal = 0; - break; - - case NS_NATIVE_PLUGIN_PORT: - // not implemented - break; - - case NS_RAW_NATIVE_IME_CONTEXT: - retVal = GetPseudoIMEContext(); - if (retVal) { - break; - } - retVal = NS_ONLY_ONE_NATIVE_IME_CONTEXT; - break; - } - - return retVal; -} - -CGFloat -nsWindow::BackingScaleFactor() -{ - if (mNativeView) { - return [mNativeView contentScaleFactor]; - } - return [UIScreen mainScreen].scale; -} - -int32_t -nsWindow::RoundsWidgetCoordinatesTo() -{ - if (BackingScaleFactor() == 2.0) { - return 2; - } - return 1; -}