summaryrefslogtreecommitdiff
path: root/widget
diff options
context:
space:
mode:
authorMoonchild <moonchild@palemoon.org>2021-05-08 21:00:49 +0000
committerMoonchild <moonchild@palemoon.org>2021-05-08 21:00:49 +0000
commit08da125d9cc6eea0bc514023e3a75efd64587259 (patch)
tree1fd18aee3b81c3b0da3c38b15af100db0be776af /widget
parentca35efb84ebae522f9ab7803d8e017f721e03207 (diff)
downloaduxp-08da125d9cc6eea0bc514023e3a75efd64587259.tar.gz
Issue #1751 -- Remove cocoa and uikit widget support code
Diffstat (limited to 'widget')
-rw-r--r--widget/cocoa/ComplexTextInputPanel.h48
-rw-r--r--widget/cocoa/ComplexTextInputPanel.mm261
-rw-r--r--widget/cocoa/CustomCocoaEvents.h18
-rw-r--r--widget/cocoa/GfxInfo.h95
-rw-r--r--widget/cocoa/GfxInfo.mm426
-rw-r--r--widget/cocoa/NativeKeyBindings.h48
-rw-r--r--widget/cocoa/NativeKeyBindings.mm292
-rw-r--r--widget/cocoa/OSXNotificationCenter.h55
-rw-r--r--widget/cocoa/OSXNotificationCenter.mm589
-rw-r--r--widget/cocoa/RectTextureImage.h80
-rw-r--r--widget/cocoa/RectTextureImage.mm171
-rw-r--r--widget/cocoa/SwipeTracker.h95
-rw-r--r--widget/cocoa/SwipeTracker.mm219
-rw-r--r--widget/cocoa/TextInputHandler.h1194
-rw-r--r--widget/cocoa/TextInputHandler.mm4533
-rw-r--r--widget/cocoa/VibrancyManager.h120
-rw-r--r--widget/cocoa/VibrancyManager.mm244
-rw-r--r--widget/cocoa/ViewRegion.h52
-rw-r--r--widget/cocoa/ViewRegion.mm70
-rw-r--r--widget/cocoa/WidgetTraceEvent.mm85
-rw-r--r--widget/cocoa/crashtests/373122-1-inner.html39
-rw-r--r--widget/cocoa/crashtests/373122-1.html9
-rw-r--r--widget/cocoa/crashtests/397209-1.html7
-rw-r--r--widget/cocoa/crashtests/403296-1.xhtml10
-rw-r--r--widget/cocoa/crashtests/419737-1.html8
-rw-r--r--widget/cocoa/crashtests/435223-1.html8
-rw-r--r--widget/cocoa/crashtests/444260-1.xul3
-rw-r--r--widget/cocoa/crashtests/444864-1.html6
-rw-r--r--widget/cocoa/crashtests/449111-1.html4
-rw-r--r--widget/cocoa/crashtests/460349-1.xhtml4
-rw-r--r--widget/cocoa/crashtests/460387-1.html2
-rw-r--r--widget/cocoa/crashtests/464589-1.html20
-rw-r--r--widget/cocoa/crashtests/crashtests.list11
-rw-r--r--widget/cocoa/cursors/arrowN.pngbin256 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/arrowN@2x.pngbin655 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/arrowS.pngbin256 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/arrowS@2x.pngbin649 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/cell.pngbin268 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/cell@2x.pngbin647 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/colResize.pngbin321 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/colResize@2x.pngbin836 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/help.pngbin723 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/help@2x.pngbin1693 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/move.pngbin284 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/move@2x.pngbin621 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/rowResize.pngbin331 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/rowResize@2x.pngbin852 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/sizeNE.pngbin279 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/sizeNE@2x.pngbin794 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/sizeNESW.pngbin300 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/sizeNESW@2x.pngbin975 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/sizeNS.pngbin282 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/sizeNS@2x.pngbin660 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/sizeNW.pngbin278 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/sizeNW@2x.pngbin790 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/sizeNWSE.pngbin295 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/sizeNWSE@2x.pngbin976 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/sizeSE.pngbin270 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/sizeSE@2x.pngbin802 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/sizeSW.pngbin271 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/sizeSW@2x.pngbin806 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/vtIBeam.pngbin120 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/vtIBeam@2x.pngbin336 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/zoomIn.pngbin655 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/zoomIn@2x.pngbin1717 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/zoomOut.pngbin650 -> 0 bytes
-rw-r--r--widget/cocoa/cursors/zoomOut@2x.pngbin1714 -> 0 bytes
-rw-r--r--widget/cocoa/moz.build140
-rw-r--r--widget/cocoa/mozView.h62
-rw-r--r--widget/cocoa/nsAppShell.h71
-rw-r--r--widget/cocoa/nsAppShell.mm907
-rw-r--r--widget/cocoa/nsBidiKeyboard.h24
-rw-r--r--widget/cocoa/nsBidiKeyboard.mm42
-rw-r--r--widget/cocoa/nsChangeObserver.h44
-rw-r--r--widget/cocoa/nsChildView.h666
-rw-r--r--widget/cocoa/nsChildView.mm6151
-rw-r--r--widget/cocoa/nsClipboard.h55
-rw-r--r--widget/cocoa/nsClipboard.mm775
-rw-r--r--widget/cocoa/nsCocoaDebugUtils.h136
-rw-r--r--widget/cocoa/nsCocoaDebugUtils.mm284
-rw-r--r--widget/cocoa/nsCocoaFeatures.h46
-rw-r--r--widget/cocoa/nsCocoaFeatures.mm209
-rw-r--r--widget/cocoa/nsCocoaUtils.h389
-rw-r--r--widget/cocoa/nsCocoaUtils.mm1022
-rw-r--r--widget/cocoa/nsCocoaWindow.h426
-rw-r--r--widget/cocoa/nsCocoaWindow.mm3881
-rw-r--r--widget/cocoa/nsColorPicker.h50
-rw-r--r--widget/cocoa/nsColorPicker.mm188
-rw-r--r--widget/cocoa/nsCursorManager.h65
-rw-r--r--widget/cocoa/nsCursorManager.mm308
-rw-r--r--widget/cocoa/nsDeviceContextSpecX.h41
-rw-r--r--widget/cocoa/nsDeviceContextSpecX.mm165
-rw-r--r--widget/cocoa/nsDragService.h55
-rw-r--r--widget/cocoa/nsDragService.mm669
-rw-r--r--widget/cocoa/nsFilePicker.h74
-rw-r--r--widget/cocoa/nsFilePicker.mm676
-rw-r--r--widget/cocoa/nsIdleServiceX.h33
-rw-r--r--widget/cocoa/nsIdleServiceX.mm77
-rw-r--r--widget/cocoa/nsLookAndFeel.h46
-rw-r--r--widget/cocoa/nsLookAndFeel.mm584
-rw-r--r--widget/cocoa/nsMacCursor.h105
-rw-r--r--widget/cocoa/nsMacCursor.mm382
-rw-r--r--widget/cocoa/nsMacDockSupport.h41
-rw-r--r--widget/cocoa/nsMacDockSupport.mm174
-rw-r--r--widget/cocoa/nsMacWebAppUtils.h22
-rw-r--r--widget/cocoa/nsMacWebAppUtils.mm82
-rw-r--r--widget/cocoa/nsMenuBarX.h128
-rw-r--r--widget/cocoa/nsMenuBarX.mm979
-rw-r--r--widget/cocoa/nsMenuBaseX.h79
-rw-r--r--widget/cocoa/nsMenuGroupOwnerX.h61
-rw-r--r--widget/cocoa/nsMenuGroupOwnerX.mm261
-rw-r--r--widget/cocoa/nsMenuItemIconX.h66
-rw-r--r--widget/cocoa/nsMenuItemIconX.mm466
-rw-r--r--widget/cocoa/nsMenuItemX.h75
-rw-r--r--widget/cocoa/nsMenuItemX.mm369
-rw-r--r--widget/cocoa/nsMenuUtilsX.h31
-rw-r--r--widget/cocoa/nsMenuUtilsX.mm223
-rw-r--r--widget/cocoa/nsMenuX.h101
-rw-r--r--widget/cocoa/nsMenuX.mm1051
-rw-r--r--widget/cocoa/nsNativeThemeCocoa.h178
-rw-r--r--widget/cocoa/nsNativeThemeCocoa.mm3961
-rw-r--r--widget/cocoa/nsNativeThemeColors.h57
-rw-r--r--widget/cocoa/nsPIWidgetCocoa.idl37
-rw-r--r--widget/cocoa/nsPrintDialogX.h68
-rw-r--r--widget/cocoa/nsPrintDialogX.mm682
-rw-r--r--widget/cocoa/nsPrintOptionsX.h44
-rw-r--r--widget/cocoa/nsPrintOptionsX.mm349
-rw-r--r--widget/cocoa/nsPrintSettingsX.h82
-rw-r--r--widget/cocoa/nsPrintSettingsX.mm272
-rw-r--r--widget/cocoa/nsSandboxViolationSink.h36
-rw-r--r--widget/cocoa/nsSandboxViolationSink.mm115
-rw-r--r--widget/cocoa/nsScreenCocoa.h41
-rw-r--r--widget/cocoa/nsScreenCocoa.mm147
-rw-r--r--widget/cocoa/nsScreenManagerCocoa.h33
-rw-r--r--widget/cocoa/nsScreenManagerCocoa.mm152
-rw-r--r--widget/cocoa/nsSound.h27
-rw-r--r--widget/cocoa/nsSound.mm108
-rw-r--r--widget/cocoa/nsStandaloneNativeMenu.h40
-rw-r--r--widget/cocoa/nsStandaloneNativeMenu.mm213
-rw-r--r--widget/cocoa/nsSystemStatusBarCocoa.h40
-rw-r--r--widget/cocoa/nsSystemStatusBarCocoa.mm74
-rw-r--r--widget/cocoa/nsToolkit.h53
-rw-r--r--widget/cocoa/nsToolkit.mm326
-rw-r--r--widget/cocoa/nsWidgetFactory.mm219
-rw-r--r--widget/cocoa/nsWindowMap.h62
-rw-r--r--widget/cocoa/nsWindowMap.mm311
-rw-r--r--widget/cocoa/resources/MainMenu.nib/classes.nib4
-rw-r--r--widget/cocoa/resources/MainMenu.nib/info.nib21
-rw-r--r--widget/cocoa/resources/MainMenu.nib/keyedobjects.nibbin1877 -> 0 bytes
-rw-r--r--widget/moz.build22
-rw-r--r--widget/nsIMacDockSupport.idl39
-rw-r--r--widget/nsIMacWebAppUtils.idl35
-rw-r--r--widget/nsISystemStatusBar.idl36
-rw-r--r--widget/uikit/GfxInfo.cpp222
-rw-r--r--widget/uikit/GfxInfo.h78
-rw-r--r--widget/uikit/moz.build18
-rw-r--r--widget/uikit/nsAppShell.h57
-rw-r--r--widget/uikit/nsAppShell.mm271
-rw-r--r--widget/uikit/nsLookAndFeel.h35
-rw-r--r--widget/uikit/nsLookAndFeel.mm401
-rw-r--r--widget/uikit/nsScreenManager.h60
-rw-r--r--widget/uikit/nsScreenManager.mm146
-rw-r--r--widget/uikit/nsWidgetFactory.mm71
-rw-r--r--widget/uikit/nsWindow.h125
-rw-r--r--widget/uikit/nsWindow.mm862
165 files changed, 4 insertions, 42109 deletions
diff --git a/widget/cocoa/ComplexTextInputPanel.h b/widget/cocoa/ComplexTextInputPanel.h
deleted file mode 100644
index 648e6d9114..0000000000
--- a/widget/cocoa/ComplexTextInputPanel.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2009 Apple Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Modified by Josh Aas of Mozilla Corporation.
- */
-
-#ifndef ComplexTextInputPanel_h_
-#define ComplexTextInputPanel_h_
-
-#include "nsString.h"
-#include "npapi.h"
-
-class ComplexTextInputPanel
-{
-public:
- static ComplexTextInputPanel* GetSharedComplexTextInputPanel();
- virtual void PlacePanel(int32_t x, int32_t y) = 0; // Bottom left coordinate of plugin in screen coords
- virtual void InterpretKeyEvent(void* aEvent, nsAString& aOutText) = 0;
- virtual bool IsInComposition() = 0;
- virtual void* GetInputContext() = 0;
- virtual void CancelComposition() = 0;
-
-protected:
- virtual ~ComplexTextInputPanel() {};
-};
-
-#endif // ComplexTextInputPanel_h_
diff --git a/widget/cocoa/ComplexTextInputPanel.mm b/widget/cocoa/ComplexTextInputPanel.mm
deleted file mode 100644
index a4b58955e2..0000000000
--- a/widget/cocoa/ComplexTextInputPanel.mm
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Copyright (C) 2009 Apple Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Modified by Josh Aas of Mozilla Corporation.
- */
-
-#import "ComplexTextInputPanel.h"
-
-#import <Cocoa/Cocoa.h>
-
-#include <algorithm>
-#include "mozilla/Preferences.h"
-#include "nsChildView.h"
-
-using namespace mozilla;
-
-extern "C" OSStatus TSMProcessRawKeyEvent(EventRef anEvent);
-
-#define kInputWindowHeight 20
-
-@interface ComplexTextInputPanelImpl : NSPanel {
- NSTextView *mInputTextView;
-}
-
-+ (ComplexTextInputPanelImpl*)sharedComplexTextInputPanelImpl;
-
-- (NSTextInputContext*)inputContext;
-- (void)interpretKeyEvent:(NSEvent*)event string:(NSString**)string;
-- (void)cancelComposition;
-- (BOOL)inComposition;
-
-// This places the text input panel fully onscreen and below the lower left
-// corner of the focused plugin.
-- (void)adjustTo:(NSPoint)point;
-
-@end
-
-@implementation ComplexTextInputPanelImpl
-
-+ (ComplexTextInputPanelImpl*)sharedComplexTextInputPanelImpl
-{
- static ComplexTextInputPanelImpl *sComplexTextInputPanelImpl;
- if (!sComplexTextInputPanelImpl)
- sComplexTextInputPanelImpl = [[ComplexTextInputPanelImpl alloc] init];
- return sComplexTextInputPanelImpl;
-}
-
-- (id)init
-{
- // In the original Apple code the style mask is given by a function which is not open source.
- // What could possibly be worth hiding in that function, I do not know.
- // Courtesy of gdb: stylemask: 011000011111, 0x61f
- self = [super initWithContentRect:NSZeroRect styleMask:0x61f backing:NSBackingStoreBuffered defer:YES];
- if (!self)
- return nil;
-
- // Set the frame size.
- NSRect visibleFrame = [[NSScreen mainScreen] visibleFrame];
- NSRect frame = NSMakeRect(visibleFrame.origin.x, visibleFrame.origin.y, visibleFrame.size.width, kInputWindowHeight);
-
- [self setFrame:frame display:NO];
-
- mInputTextView = [[NSTextView alloc] initWithFrame:[self.contentView frame]];
- mInputTextView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable | NSViewMaxXMargin | NSViewMinXMargin | NSViewMaxYMargin | NSViewMinYMargin;
-
- NSScrollView* scrollView = [[NSScrollView alloc] initWithFrame:[self.contentView frame]];
- scrollView.documentView = mInputTextView;
- self.contentView = scrollView;
- [scrollView release];
-
- [self setFloatingPanel:YES];
-
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(keyboardInputSourceChanged:)
- name:NSTextInputContextKeyboardSelectionDidChangeNotification
- object:nil];
-
- return self;
-}
-
-- (void)dealloc
-{
- [[NSNotificationCenter defaultCenter] removeObserver:self];
-
- [mInputTextView release];
-
- [super dealloc];
-}
-
-- (void)keyboardInputSourceChanged:(NSNotification *)notification
-{
- static int8_t sDoCancel = -1;
- if (!sDoCancel || ![self inComposition]) {
- return;
- }
- if (sDoCancel < 0) {
- bool cancelComposition = false;
- static const char* kPrefName =
- "ui.plugin.cancel_composition_at_input_source_changed";
- nsresult rv = Preferences::GetBool(kPrefName, &cancelComposition);
- NS_ENSURE_SUCCESS(rv, );
- sDoCancel = cancelComposition ? 1 : 0;
- }
- if (sDoCancel) {
- [self cancelComposition];
- }
-}
-
-- (void)interpretKeyEvent:(NSEvent*)event string:(NSString**)string
-{
- *string = nil;
-
- if (![[mInputTextView inputContext] handleEvent:event]) {
- return;
- }
-
- if ([mInputTextView hasMarkedText]) {
- // Don't show the input method window for dead keys
- if ([[event characters] length] > 0) {
- [self orderFront:nil];
- }
- return;
- } else {
- [self orderOut:nil];
-
- NSString *text = [[mInputTextView textStorage] string];
- if ([text length] > 0) {
- *string = [[text copy] autorelease];
- }
- }
-
- [mInputTextView setString:@""];
-}
-
-- (NSTextInputContext*)inputContext
-{
- return [mInputTextView inputContext];
-}
-
-- (void)cancelComposition
-{
- [mInputTextView setString:@""];
- [self orderOut:nil];
-}
-
-- (BOOL)inComposition
-{
- return [mInputTextView hasMarkedText];
-}
-
-- (void)adjustTo:(NSPoint)point
-{
- NSRect selfRect = [self frame];
- NSRect rect = NSMakeRect(point.x,
- point.y - selfRect.size.height,
- 500,
- selfRect.size.height);
-
- // Adjust to screen.
- NSRect screenRect = [[NSScreen mainScreen] visibleFrame];
- if (rect.origin.x < screenRect.origin.x) {
- rect.origin.x = screenRect.origin.x;
- }
- if (rect.origin.y < screenRect.origin.y) {
- rect.origin.y = screenRect.origin.y;
- }
- CGFloat xMostOfScreen = screenRect.origin.x + screenRect.size.width;
- CGFloat yMostOfScreen = screenRect.origin.y + screenRect.size.height;
- CGFloat xMost = rect.origin.x + rect.size.width;
- CGFloat yMost = rect.origin.y + rect.size.height;
- if (xMostOfScreen < xMost) {
- rect.origin.x -= xMost - xMostOfScreen;
- }
- if (yMostOfScreen < yMost) {
- rect.origin.y -= yMost - yMostOfScreen;
- }
-
- [self setFrame:rect display:[self isVisible]];
-}
-
-@end
-
-class ComplexTextInputPanelPrivate : public ComplexTextInputPanel
-{
-public:
- ComplexTextInputPanelPrivate();
-
- virtual void InterpretKeyEvent(void* aEvent, nsAString& aOutText);
- virtual bool IsInComposition();
- virtual void PlacePanel(int32_t x, int32_t y);
- virtual void* GetInputContext() { return [mPanel inputContext]; }
- virtual void CancelComposition() { [mPanel cancelComposition]; }
-
-private:
- ~ComplexTextInputPanelPrivate();
- ComplexTextInputPanelImpl* mPanel;
-};
-
-ComplexTextInputPanelPrivate::ComplexTextInputPanelPrivate()
-{
- mPanel = [[ComplexTextInputPanelImpl alloc] init];
-}
-
-ComplexTextInputPanelPrivate::~ComplexTextInputPanelPrivate()
-{
- [mPanel release];
-}
-
-ComplexTextInputPanel*
-ComplexTextInputPanel::GetSharedComplexTextInputPanel()
-{
- static ComplexTextInputPanelPrivate *sComplexTextInputPanelPrivate;
- if (!sComplexTextInputPanelPrivate) {
- sComplexTextInputPanelPrivate = new ComplexTextInputPanelPrivate();
- }
- return sComplexTextInputPanelPrivate;
-}
-
-void
-ComplexTextInputPanelPrivate::InterpretKeyEvent(void* aEvent, nsAString& aOutText)
-{
- NSString* textString = nil;
- [mPanel interpretKeyEvent:(NSEvent*)aEvent string:&textString];
-
- if (textString) {
- nsCocoaUtils::GetStringForNSString(textString, aOutText);
- }
-}
-
-bool
-ComplexTextInputPanelPrivate::IsInComposition()
-{
- return !![mPanel inComposition];
-}
-
-void
-ComplexTextInputPanelPrivate::PlacePanel(int32_t x, int32_t y)
-{
- [mPanel adjustTo:NSMakePoint(x, y)];
-}
diff --git a/widget/cocoa/CustomCocoaEvents.h b/widget/cocoa/CustomCocoaEvents.h
deleted file mode 100644
index 0043f0d695..0000000000
--- a/widget/cocoa/CustomCocoaEvents.h
+++ /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/. */
-
-/*
- * This file defines constants to be used in the "subtype" field of
- * NSApplicationDefined type NSEvents.
- */
-
-#ifndef WIDGET_COCOA_CUSTOMCOCOAEVENTS_H_
-#define WIDGET_COCOA_CUSTOMCOCOAEVENTS_H_
-
-// Empty event, just used for prodding the event loop into responding.
-const short kEventSubtypeNone = 0;
-// Tracer event, used for timing the event loop responsiveness.
-const short kEventSubtypeTrace = 1;
-
-#endif /* WIDGET_COCOA_CUSTOMCOCOAEVENTS_H_ */
diff --git a/widget/cocoa/GfxInfo.h b/widget/cocoa/GfxInfo.h
deleted file mode 100644
index 05bdad158b..0000000000
--- a/widget/cocoa/GfxInfo.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* vim: se cin sw=2 ts=2 et : */
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef __mozilla_widget_GfxInfo_h__
-#define __mozilla_widget_GfxInfo_h__
-
-#include "GfxInfoBase.h"
-
-#include "nsString.h"
-
-namespace mozilla {
-namespace widget {
-
-class GfxInfo : public GfxInfoBase
-{
-public:
-
- GfxInfo();
- // We only declare the subset of nsIGfxInfo that we actually implement. The
- // rest is brought forward from GfxInfoBase.
- NS_IMETHOD GetD2DEnabled(bool *aD2DEnabled) override;
- NS_IMETHOD GetDWriteEnabled(bool *aDWriteEnabled) override;
- NS_IMETHOD GetDWriteVersion(nsAString & aDwriteVersion) override;
- NS_IMETHOD GetCleartypeParameters(nsAString & aCleartypeParams) override;
- NS_IMETHOD GetAdapterDescription(nsAString & aAdapterDescription) override;
- NS_IMETHOD GetAdapterDriver(nsAString & aAdapterDriver) override;
- NS_IMETHOD GetAdapterVendorID(nsAString & aAdapterVendorID) override;
- NS_IMETHOD GetAdapterDeviceID(nsAString & aAdapterDeviceID) override;
- NS_IMETHOD GetAdapterSubsysID(nsAString & aAdapterSubsysID) override;
- NS_IMETHOD GetAdapterRAM(nsAString & aAdapterRAM) override;
- NS_IMETHOD GetAdapterDriverVersion(nsAString & aAdapterDriverVersion) override;
- NS_IMETHOD GetAdapterDriverDate(nsAString & aAdapterDriverDate) override;
- NS_IMETHOD GetAdapterDescription2(nsAString & aAdapterDescription) override;
- NS_IMETHOD GetAdapterDriver2(nsAString & aAdapterDriver) override;
- NS_IMETHOD GetAdapterVendorID2(nsAString & aAdapterVendorID) override;
- NS_IMETHOD GetAdapterDeviceID2(nsAString & aAdapterDeviceID) override;
- NS_IMETHOD GetAdapterSubsysID2(nsAString & aAdapterSubsysID) override;
- NS_IMETHOD GetAdapterRAM2(nsAString & aAdapterRAM) override;
- NS_IMETHOD GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion) override;
- NS_IMETHOD GetAdapterDriverDate2(nsAString & aAdapterDriverDate) override;
- NS_IMETHOD GetIsGPU2Active(bool *aIsGPU2Active) override;
-
- using GfxInfoBase::GetFeatureStatus;
- using GfxInfoBase::GetFeatureSuggestedDriverVersion;
- using GfxInfoBase::GetWebGLParameter;
-
- virtual nsresult Init() override;
-
-#ifdef DEBUG
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_NSIGFXINFODEBUG
-#endif
-
- virtual uint32_t OperatingSystemVersion() override { return mOSXVersion; }
-
- nsresult FindMonitors(JSContext* cx, JS::HandleObject array) override;
-
-protected:
-
- virtual ~GfxInfo() {}
-
- virtual nsresult GetFeatureStatusImpl(int32_t aFeature,
- int32_t *aStatus,
- nsAString & aSuggestedDriverVersion,
- const nsTArray<GfxDriverInfo>& aDriverInfo,
- nsACString &aFailureId,
- OperatingSystem* aOS = nullptr) override;
- virtual const nsTArray<GfxDriverInfo>& GetGfxDriverInfo() override;
-
-private:
-
- void GetDeviceInfo();
- void GetSelectedCityInfo();
- void AddCrashReportAnnotations();
-
- nsString mAdapterRAMString;
- nsString mDeviceID;
- nsString mDriverVersion;
- nsString mDriverDate;
- nsString mDeviceKey;
-
- nsString mAdapterVendorID;
- nsString mAdapterDeviceID;
-
- uint32_t mOSXVersion;
-};
-
-} // namespace widget
-} // namespace mozilla
-
-#endif /* __mozilla_widget_GfxInfo_h__ */
diff --git a/widget/cocoa/GfxInfo.mm b/widget/cocoa/GfxInfo.mm
deleted file mode 100644
index 97bb4c8324..0000000000
--- a/widget/cocoa/GfxInfo.mm
+++ /dev/null
@@ -1,426 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <OpenGL/OpenGL.h>
-#include <OpenGL/CGLRenderers.h>
-
-#include "mozilla/ArrayUtils.h"
-
-#include "GfxInfo.h"
-#include "nsUnicharUtils.h"
-#include "nsCocoaFeatures.h"
-#include "mozilla/Preferences.h"
-#include <algorithm>
-
-#import <Foundation/Foundation.h>
-#import <IOKit/IOKitLib.h>
-#import <Cocoa/Cocoa.h>
-
-using namespace mozilla;
-using namespace mozilla::widget;
-
-#ifdef DEBUG
-NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, GfxInfoBase, nsIGfxInfoDebug)
-#endif
-
-GfxInfo::GfxInfo()
-{
-}
-
-static OperatingSystem
-OSXVersionToOperatingSystem(uint32_t aOSXVersion) {
- switch (nsCocoaFeatures::ExtractMajorVersion(aOSXVersion)) {
- case 10:
- switch (nsCocoaFeatures::ExtractMinorVersion(aOSXVersion)) {
- case 6:
- return OperatingSystem::OSX10_6;
- case 7:
- return OperatingSystem::OSX10_7;
- case 8:
- return OperatingSystem::OSX10_8;
- case 9:
- return OperatingSystem::OSX10_9;
- case 10:
- return OperatingSystem::OSX10_10;
- case 11:
- return OperatingSystem::OSX10_11;
- case 12:
- return OperatingSystem::OSX10_12;
- case 13:
- return OperatingSystem::OSX10_13;
- case 14:
- return OperatingSystem::OSX10_14;
- case 15:
- return OperatingSystem::OSX10_15;
- case 16:
- // Depending on the SDK version, we either get 10.16 or 11.0.
- // Normalize this to 11.0.
- return OperatingSystem::OSX11_0;
- default:
- break;
- }
- break;
- case 11:
- switch (nsCocoaFeatures::ExtractMinorVersion(aOSXVersion)) {
- case 0:
- return OperatingSystem::OSX11_0;
- default:
- break;
- }
- break;
- }
-
- return OperatingSystem::Unknown;
-}
-// The following three functions are derived from Chromium code
-static CFTypeRef SearchPortForProperty(io_registry_entry_t dspPort,
- CFStringRef propertyName)
-{
- return IORegistryEntrySearchCFProperty(dspPort,
- kIOServicePlane,
- propertyName,
- kCFAllocatorDefault,
- kIORegistryIterateRecursively |
- kIORegistryIterateParents);
-}
-
-static uint32_t IntValueOfCFData(CFDataRef d)
-{
- uint32_t value = 0;
-
- if (d) {
- const uint32_t *vp = reinterpret_cast<const uint32_t*>(CFDataGetBytePtr(d));
- if (vp != NULL)
- value = *vp;
- }
-
- return value;
-}
-
-void
-GfxInfo::GetDeviceInfo()
-{
- io_registry_entry_t dsp_port = CGDisplayIOServicePort(kCGDirectMainDisplay);
- CFTypeRef vendor_id_ref = SearchPortForProperty(dsp_port, CFSTR("vendor-id"));
- if (vendor_id_ref) {
- mAdapterVendorID.AppendPrintf("0x%04x", IntValueOfCFData((CFDataRef)vendor_id_ref));
- CFRelease(vendor_id_ref);
- }
- CFTypeRef device_id_ref = SearchPortForProperty(dsp_port, CFSTR("device-id"));
- if (device_id_ref) {
- mAdapterDeviceID.AppendPrintf("0x%04x", IntValueOfCFData((CFDataRef)device_id_ref));
- CFRelease(device_id_ref);
- }
-}
-
-nsresult
-GfxInfo::Init()
-{
- nsresult rv = GfxInfoBase::Init();
-
- // Calling CGLQueryRendererInfo causes us to switch to the discrete GPU
- // even when we don't want to. We'll avoid doing so for now and just
- // use the device ids.
-
- GetDeviceInfo();
-
- AddCrashReportAnnotations();
-
- mOSXVersion = nsCocoaFeatures::macOSVersion();
-
- return rv;
-}
-
-NS_IMETHODIMP
-GfxInfo::GetD2DEnabled(bool *aEnabled)
-{
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-GfxInfo::GetDWriteEnabled(bool *aEnabled)
-{
- return NS_ERROR_FAILURE;
-}
-
-/* readonly attribute DOMString DWriteVersion; */
-NS_IMETHODIMP
-GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)
-{
- return NS_ERROR_FAILURE;
-}
-
-/* readonly attribute DOMString cleartypeParameters; */
-NS_IMETHODIMP
-GfxInfo::GetCleartypeParameters(nsAString & aCleartypeParams)
-{
- return NS_ERROR_FAILURE;
-}
-
-/* readonly attribute DOMString adapterDescription; */
-NS_IMETHODIMP
-GfxInfo::GetAdapterDescription(nsAString & aAdapterDescription)
-{
- aAdapterDescription.AssignLiteral("");
- return NS_OK;
-}
-
-/* readonly attribute DOMString adapterDescription2; */
-NS_IMETHODIMP
-GfxInfo::GetAdapterDescription2(nsAString & aAdapterDescription)
-{
- return NS_ERROR_FAILURE;
-}
-
-/* readonly attribute DOMString adapterRAM; */
-NS_IMETHODIMP
-GfxInfo::GetAdapterRAM(nsAString & aAdapterRAM)
-{
- aAdapterRAM = mAdapterRAMString;
- return NS_OK;
-}
-
-/* readonly attribute DOMString adapterRAM2; */
-NS_IMETHODIMP
-GfxInfo::GetAdapterRAM2(nsAString & aAdapterRAM)
-{
- return NS_ERROR_FAILURE;
-}
-
-/* readonly attribute DOMString adapterDriver; */
-NS_IMETHODIMP
-GfxInfo::GetAdapterDriver(nsAString & aAdapterDriver)
-{
- aAdapterDriver.AssignLiteral("");
- return NS_OK;
-}
-
-/* readonly attribute DOMString adapterDriver2; */
-NS_IMETHODIMP
-GfxInfo::GetAdapterDriver2(nsAString & aAdapterDriver)
-{
- return NS_ERROR_FAILURE;
-}
-
-/* readonly attribute DOMString adapterDriverVersion; */
-NS_IMETHODIMP
-GfxInfo::GetAdapterDriverVersion(nsAString & aAdapterDriverVersion)
-{
- aAdapterDriverVersion.AssignLiteral("");
- return NS_OK;
-}
-
-/* readonly attribute DOMString adapterDriverVersion2; */
-NS_IMETHODIMP
-GfxInfo::GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion)
-{
- return NS_ERROR_FAILURE;
-}
-
-/* readonly attribute DOMString adapterDriverDate; */
-NS_IMETHODIMP
-GfxInfo::GetAdapterDriverDate(nsAString & aAdapterDriverDate)
-{
- aAdapterDriverDate.AssignLiteral("");
- return NS_OK;
-}
-
-/* readonly attribute DOMString adapterDriverDate2; */
-NS_IMETHODIMP
-GfxInfo::GetAdapterDriverDate2(nsAString & aAdapterDriverDate)
-{
- return NS_ERROR_FAILURE;
-}
-
-/* readonly attribute DOMString adapterVendorID; */
-NS_IMETHODIMP
-GfxInfo::GetAdapterVendorID(nsAString & aAdapterVendorID)
-{
- aAdapterVendorID = mAdapterVendorID;
- return NS_OK;
-}
-
-/* readonly attribute DOMString adapterVendorID2; */
-NS_IMETHODIMP
-GfxInfo::GetAdapterVendorID2(nsAString & aAdapterVendorID)
-{
- return NS_ERROR_FAILURE;
-}
-
-/* readonly attribute DOMString adapterDeviceID; */
-NS_IMETHODIMP
-GfxInfo::GetAdapterDeviceID(nsAString & aAdapterDeviceID)
-{
- aAdapterDeviceID = mAdapterDeviceID;
- return NS_OK;
-}
-
-/* readonly attribute DOMString adapterDeviceID2; */
-NS_IMETHODIMP
-GfxInfo::GetAdapterDeviceID2(nsAString & aAdapterDeviceID)
-{
- return NS_ERROR_FAILURE;
-}
-
-/* readonly attribute DOMString adapterSubsysID; */
-NS_IMETHODIMP
-GfxInfo::GetAdapterSubsysID(nsAString & aAdapterSubsysID)
-{
- return NS_ERROR_FAILURE;
-}
-
-/* readonly attribute DOMString adapterSubsysID2; */
-NS_IMETHODIMP
-GfxInfo::GetAdapterSubsysID2(nsAString & aAdapterSubsysID)
-{
- return NS_ERROR_FAILURE;
-}
-
-/* readonly attribute boolean isGPU2Active; */
-NS_IMETHODIMP
-GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active)
-{
- return NS_ERROR_FAILURE;
-}
-
-void
-GfxInfo::AddCrashReportAnnotations()
-{
- /*** STUB ***/
-}
-
-// We don't support checking driver versions on Mac.
-#define IMPLEMENT_MAC_DRIVER_BLOCKLIST(os, vendor, device, features, blockOn, ruleId) \
- APPEND_TO_DRIVER_BLOCKLIST(os, vendor, device, features, blockOn, \
- DRIVER_COMPARISON_IGNORED, V(0,0,0,0), ruleId, "")
-
-
-const nsTArray<GfxDriverInfo>&
-GfxInfo::GetGfxDriverInfo()
-{
- if (!mDriverInfo->Length()) {
- IMPLEMENT_MAC_DRIVER_BLOCKLIST(OperatingSystem::OSX,
- (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices,
- nsIGfxInfo::FEATURE_WEBGL_MSAA, nsIGfxInfo::FEATURE_BLOCKED_OS_VERSION, "FEATURE_FAILURE_MAC_ATI_NO_MSAA");
- IMPLEMENT_MAC_DRIVER_BLOCKLIST(OperatingSystem::OSX,
- (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(RadeonX1000),
- nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_BLOCKED_DEVICE, "FEATURE_FAILURE_MAC_RADEONX1000_NO_TEXTURE2D");
- IMPLEMENT_MAC_DRIVER_BLOCKLIST(OperatingSystem::OSX,
- (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(Geforce7300GT),
- nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_BLOCKED_DEVICE, "FEATURE_FAILURE_MAC_7300_NO_WEBGL");
- }
- return *mDriverInfo;
-}
-
-nsresult
-GfxInfo::GetFeatureStatusImpl(int32_t aFeature,
- int32_t* aStatus,
- nsAString& aSuggestedDriverVersion,
- const nsTArray<GfxDriverInfo>& aDriverInfo,
- nsACString& aFailureId,
- OperatingSystem* aOS /* = nullptr */)
-{
- NS_ENSURE_ARG_POINTER(aStatus);
- aSuggestedDriverVersion.SetIsVoid(true);
- *aStatus = nsIGfxInfo::FEATURE_STATUS_UNKNOWN;
- OperatingSystem os = OSXVersionToOperatingSystem(mOSXVersion);
- if (aOS)
- *aOS = os;
-
- if (mShutdownOccurred) {
- return NS_OK;
- }
-
- // Don't evaluate special cases when we're evaluating the downloaded blocklist.
- if (!aDriverInfo.Length()) {
- if (aFeature == nsIGfxInfo::FEATURE_WEBGL_MSAA) {
- // Blacklist all ATI cards on OSX, except for
- // 0x6760 and 0x9488
- if (mAdapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorATI), nsCaseInsensitiveStringComparator()) &&
- (mAdapterDeviceID.LowerCaseEqualsLiteral("0x6760") ||
- mAdapterDeviceID.LowerCaseEqualsLiteral("0x9488"))) {
- *aStatus = nsIGfxInfo::FEATURE_STATUS_OK;
- return NS_OK;
- }
- } else if (aFeature == nsIGfxInfo::FEATURE_CANVAS2D_ACCELERATION) {
- // See bug 1249659
- switch(os) {
- case OperatingSystem::OSX10_5:
- case OperatingSystem::OSX10_6:
- case OperatingSystem::OSX10_7:
- *aStatus = nsIGfxInfo::FEATURE_BLOCKED_OS_VERSION;
- aFailureId = "FEATURE_FAILURE_CANVAS_OSX_VERSION";
- break;
- default:
- *aStatus = nsIGfxInfo::FEATURE_STATUS_OK;
- break;
- }
- return NS_OK;
- }
- }
-
- return GfxInfoBase::GetFeatureStatusImpl(aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, aFailureId, &os);
-}
-
-nsresult
-GfxInfo::FindMonitors(JSContext* aCx, JS::HandleObject aOutArray)
-{
- // Getting the refresh rate is a little hard on OS X. We could use
- // CVDisplayLinkGetNominalOutputVideoRefreshPeriod, but that's a little
- // involved. Ideally we could query it from vsync. For now, we leave it out.
- int32_t deviceCount = 0;
- for (NSScreen* screen in [NSScreen screens]) {
- NSRect rect = [screen frame];
-
- JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
-
- JS::Rooted<JS::Value> screenWidth(aCx, JS::Int32Value((int)rect.size.width));
- JS_SetProperty(aCx, obj, "screenWidth", screenWidth);
-
- JS::Rooted<JS::Value> screenHeight(aCx, JS::Int32Value((int)rect.size.height));
- JS_SetProperty(aCx, obj, "screenHeight", screenHeight);
-
- JS::Rooted<JS::Value> scale(aCx, JS::NumberValue(nsCocoaUtils::GetBackingScaleFactor(screen)));
- JS_SetProperty(aCx, obj, "scale", scale);
-
- JS::Rooted<JS::Value> element(aCx, JS::ObjectValue(*obj));
- JS_SetElement(aCx, aOutArray, deviceCount++, element);
- }
- return NS_OK;
-}
-
-#ifdef DEBUG
-
-// Implement nsIGfxInfoDebug
-
-/* void spoofVendorID (in DOMString aVendorID); */
-NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString & aVendorID)
-{
- mAdapterVendorID = aVendorID;
- return NS_OK;
-}
-
-/* void spoofDeviceID (in unsigned long aDeviceID); */
-NS_IMETHODIMP GfxInfo::SpoofDeviceID(const nsAString & aDeviceID)
-{
- mAdapterDeviceID = aDeviceID;
- return NS_OK;
-}
-
-/* void spoofDriverVersion (in DOMString aDriverVersion); */
-NS_IMETHODIMP GfxInfo::SpoofDriverVersion(const nsAString & aDriverVersion)
-{
- mDriverVersion = aDriverVersion;
- return NS_OK;
-}
-
-/* void spoofOSVersion (in unsigned long aVersion); */
-NS_IMETHODIMP GfxInfo::SpoofOSVersion(uint32_t aVersion)
-{
- mOSXVersion = aVersion;
- return NS_OK;
-}
-
-#endif
diff --git a/widget/cocoa/NativeKeyBindings.h b/widget/cocoa/NativeKeyBindings.h
deleted file mode 100644
index d1ba2c3701..0000000000
--- a/widget/cocoa/NativeKeyBindings.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_widget_NativeKeyBindings_h_
-#define mozilla_widget_NativeKeyBindings_h_
-
-#import <Cocoa/Cocoa.h>
-#include "mozilla/Attributes.h"
-#include "mozilla/EventForwards.h"
-#include "nsDataHashtable.h"
-#include "nsIWidget.h"
-
-namespace mozilla {
-namespace widget {
-
-typedef nsDataHashtable<nsPtrHashKey<struct objc_selector>, CommandInt>
- SelectorCommandHashtable;
-
-class NativeKeyBindings final
-{
- typedef nsIWidget::NativeKeyBindingsType NativeKeyBindingsType;
- typedef nsIWidget::DoCommandCallback DoCommandCallback;
-
-public:
- static NativeKeyBindings* GetInstance(NativeKeyBindingsType aType);
- static void Shutdown();
-
- void Init(NativeKeyBindingsType aType);
-
- bool Execute(const WidgetKeyboardEvent& aEvent,
- DoCommandCallback aCallback,
- void* aCallbackData);
-
-private:
- NativeKeyBindings();
-
- SelectorCommandHashtable mSelectorToCommand;
-
- static NativeKeyBindings* sInstanceForSingleLineEditor;
- static NativeKeyBindings* sInstanceForMultiLineEditor;
-}; // NativeKeyBindings
-
-} // namespace widget
-} // namespace mozilla
-
-#endif // mozilla_widget_NativeKeyBindings_h_
diff --git a/widget/cocoa/NativeKeyBindings.mm b/widget/cocoa/NativeKeyBindings.mm
deleted file mode 100644
index 2f4ecadff0..0000000000
--- a/widget/cocoa/NativeKeyBindings.mm
+++ /dev/null
@@ -1,292 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "NativeKeyBindings.h"
-
-#include "nsTArray.h"
-#include "nsCocoaUtils.h"
-#include "mozilla/Logging.h"
-#include "mozilla/TextEvents.h"
-
-namespace mozilla {
-namespace widget {
-
-PRLogModuleInfo* gNativeKeyBindingsLog = nullptr;
-
-NativeKeyBindings* NativeKeyBindings::sInstanceForSingleLineEditor = nullptr;
-NativeKeyBindings* NativeKeyBindings::sInstanceForMultiLineEditor = nullptr;
-
-// static
-NativeKeyBindings*
-NativeKeyBindings::GetInstance(NativeKeyBindingsType aType)
-{
- switch (aType) {
- case nsIWidget::NativeKeyBindingsForSingleLineEditor:
- if (!sInstanceForSingleLineEditor) {
- sInstanceForSingleLineEditor = new NativeKeyBindings();
- sInstanceForSingleLineEditor->Init(aType);
- }
- return sInstanceForSingleLineEditor;
- case nsIWidget::NativeKeyBindingsForMultiLineEditor:
- case nsIWidget::NativeKeyBindingsForRichTextEditor:
- if (!sInstanceForMultiLineEditor) {
- sInstanceForMultiLineEditor = new NativeKeyBindings();
- sInstanceForMultiLineEditor->Init(aType);
- }
- return sInstanceForMultiLineEditor;
- default:
- MOZ_CRASH("Not implemented");
- return nullptr;
- }
-}
-
-// static
-void
-NativeKeyBindings::Shutdown()
-{
- delete sInstanceForSingleLineEditor;
- sInstanceForSingleLineEditor = nullptr;
- delete sInstanceForMultiLineEditor;
- sInstanceForMultiLineEditor = nullptr;
-}
-
-NativeKeyBindings::NativeKeyBindings()
-{
-}
-
-#define SEL_TO_COMMAND(aSel, aCommand) \
- mSelectorToCommand.Put( \
- reinterpret_cast<struct objc_selector *>(@selector(aSel)), aCommand)
-
-void
-NativeKeyBindings::Init(NativeKeyBindingsType aType)
-{
- if (!gNativeKeyBindingsLog) {
- gNativeKeyBindingsLog = PR_NewLogModule("NativeKeyBindings");
- }
-
- MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info,
- ("%p NativeKeyBindings::Init", this));
-
- // Many selectors have a one-to-one mapping to a Gecko command. Those mappings
- // are registered in mSelectorToCommand.
-
- // Selectors from NSResponder's "Responding to Action Messages" section and
- // from NSText's "Action Methods for Editing" section
-
- // TODO: Improves correctness of left / right meaning
- // TODO: Add real paragraph motions
-
- // SEL_TO_COMMAND(cancelOperation:, );
- // SEL_TO_COMMAND(capitalizeWord:, );
- // SEL_TO_COMMAND(centerSelectionInVisibleArea:, );
- // SEL_TO_COMMAND(changeCaseOfLetter:, );
- // SEL_TO_COMMAND(complete:, );
- SEL_TO_COMMAND(copy:, CommandCopy);
- // SEL_TO_COMMAND(copyFont:, );
- // SEL_TO_COMMAND(copyRuler:, );
- SEL_TO_COMMAND(cut:, CommandCut);
- SEL_TO_COMMAND(delete:, CommandDelete);
- SEL_TO_COMMAND(deleteBackward:, CommandDeleteCharBackward);
- // SEL_TO_COMMAND(deleteBackwardByDecomposingPreviousCharacter:, );
- SEL_TO_COMMAND(deleteForward:, CommandDeleteCharForward);
-
- // TODO: deleteTo* selectors are also supposed to add text to a kill buffer
- SEL_TO_COMMAND(deleteToBeginningOfLine:, CommandDeleteToBeginningOfLine);
- SEL_TO_COMMAND(deleteToBeginningOfParagraph:, CommandDeleteToBeginningOfLine);
- SEL_TO_COMMAND(deleteToEndOfLine:, CommandDeleteToEndOfLine);
- SEL_TO_COMMAND(deleteToEndOfParagraph:, CommandDeleteToEndOfLine);
- // SEL_TO_COMMAND(deleteToMark:, );
-
- SEL_TO_COMMAND(deleteWordBackward:, CommandDeleteWordBackward);
- SEL_TO_COMMAND(deleteWordForward:, CommandDeleteWordForward);
- // SEL_TO_COMMAND(indent:, );
- // SEL_TO_COMMAND(insertBacktab:, );
- // SEL_TO_COMMAND(insertContainerBreak:, );
- // SEL_TO_COMMAND(insertLineBreak:, );
- // SEL_TO_COMMAND(insertNewline:, );
- // SEL_TO_COMMAND(insertNewlineIgnoringFieldEditor:, );
- // SEL_TO_COMMAND(insertParagraphSeparator:, );
- // SEL_TO_COMMAND(insertTab:, );
- // SEL_TO_COMMAND(insertTabIgnoringFieldEditor:, );
- // SEL_TO_COMMAND(insertDoubleQuoteIgnoringSubstitution:, );
- // SEL_TO_COMMAND(insertSingleQuoteIgnoringSubstitution:, );
- // SEL_TO_COMMAND(lowercaseWord:, );
- SEL_TO_COMMAND(moveBackward:, CommandCharPrevious);
- SEL_TO_COMMAND(moveBackwardAndModifySelection:, CommandSelectCharPrevious);
- if (aType == nsIWidget::NativeKeyBindingsForSingleLineEditor) {
- SEL_TO_COMMAND(moveDown:, CommandEndLine);
- } else {
- SEL_TO_COMMAND(moveDown:, CommandLineNext);
- }
- SEL_TO_COMMAND(moveDownAndModifySelection:, CommandSelectLineNext);
- SEL_TO_COMMAND(moveForward:, CommandCharNext);
- SEL_TO_COMMAND(moveForwardAndModifySelection:, CommandSelectCharNext);
- SEL_TO_COMMAND(moveLeft:, CommandCharPrevious);
- SEL_TO_COMMAND(moveLeftAndModifySelection:, CommandSelectCharPrevious);
- SEL_TO_COMMAND(moveParagraphBackwardAndModifySelection:,
- CommandSelectBeginLine);
- SEL_TO_COMMAND(moveParagraphForwardAndModifySelection:, CommandSelectEndLine);
- SEL_TO_COMMAND(moveRight:, CommandCharNext);
- SEL_TO_COMMAND(moveRightAndModifySelection:, CommandSelectCharNext);
- SEL_TO_COMMAND(moveToBeginningOfDocument:, CommandMoveTop);
- SEL_TO_COMMAND(moveToBeginningOfDocumentAndModifySelection:,
- CommandSelectTop);
- SEL_TO_COMMAND(moveToBeginningOfLine:, CommandBeginLine);
- SEL_TO_COMMAND(moveToBeginningOfLineAndModifySelection:,
- CommandSelectBeginLine);
- SEL_TO_COMMAND(moveToBeginningOfParagraph:, CommandBeginLine);
- SEL_TO_COMMAND(moveToBeginningOfParagraphAndModifySelection:,
- CommandSelectBeginLine);
- SEL_TO_COMMAND(moveToEndOfDocument:, CommandMoveBottom);
- SEL_TO_COMMAND(moveToEndOfDocumentAndModifySelection:, CommandSelectBottom);
- SEL_TO_COMMAND(moveToEndOfLine:, CommandEndLine);
- SEL_TO_COMMAND(moveToEndOfLineAndModifySelection:, CommandSelectEndLine);
- SEL_TO_COMMAND(moveToEndOfParagraph:, CommandEndLine);
- SEL_TO_COMMAND(moveToEndOfParagraphAndModifySelection:, CommandSelectEndLine);
- SEL_TO_COMMAND(moveToLeftEndOfLine:, CommandBeginLine);
- SEL_TO_COMMAND(moveToLeftEndOfLineAndModifySelection:,
- CommandSelectBeginLine);
- SEL_TO_COMMAND(moveToRightEndOfLine:, CommandEndLine);
- SEL_TO_COMMAND(moveToRightEndOfLineAndModifySelection:, CommandSelectEndLine);
- if (aType == nsIWidget::NativeKeyBindingsForSingleLineEditor) {
- SEL_TO_COMMAND(moveUp:, CommandBeginLine);
- } else {
- SEL_TO_COMMAND(moveUp:, CommandLinePrevious);
- }
- SEL_TO_COMMAND(moveUpAndModifySelection:, CommandSelectLinePrevious);
- SEL_TO_COMMAND(moveWordBackward:, CommandWordPrevious);
- SEL_TO_COMMAND(moveWordBackwardAndModifySelection:,
- CommandSelectWordPrevious);
- SEL_TO_COMMAND(moveWordForward:, CommandWordNext);
- SEL_TO_COMMAND(moveWordForwardAndModifySelection:, CommandSelectWordNext);
- SEL_TO_COMMAND(moveWordLeft:, CommandWordPrevious);
- SEL_TO_COMMAND(moveWordLeftAndModifySelection:, CommandSelectWordPrevious);
- SEL_TO_COMMAND(moveWordRight:, CommandWordNext);
- SEL_TO_COMMAND(moveWordRightAndModifySelection:, CommandSelectWordNext);
- SEL_TO_COMMAND(pageDown:, CommandMovePageDown);
- SEL_TO_COMMAND(pageDownAndModifySelection:, CommandSelectPageDown);
- SEL_TO_COMMAND(pageUp:, CommandMovePageUp);
- SEL_TO_COMMAND(pageUpAndModifySelection:, CommandSelectPageUp);
- SEL_TO_COMMAND(paste:, CommandPaste);
- // SEL_TO_COMMAND(pasteFont:, );
- // SEL_TO_COMMAND(pasteRuler:, );
- SEL_TO_COMMAND(scrollLineDown:, CommandScrollLineDown);
- SEL_TO_COMMAND(scrollLineUp:, CommandScrollLineUp);
- SEL_TO_COMMAND(scrollPageDown:, CommandScrollPageDown);
- SEL_TO_COMMAND(scrollPageUp:, CommandScrollPageUp);
- SEL_TO_COMMAND(scrollToBeginningOfDocument:, CommandScrollTop);
- SEL_TO_COMMAND(scrollToEndOfDocument:, CommandScrollBottom);
- SEL_TO_COMMAND(selectAll:, CommandSelectAll);
- // selectLine: is complex, see KeyDown
- if (aType == nsIWidget::NativeKeyBindingsForSingleLineEditor) {
- SEL_TO_COMMAND(selectParagraph:, CommandSelectAll);
- }
- // SEL_TO_COMMAND(selectToMark:, );
- // selectWord: is complex, see KeyDown
- // SEL_TO_COMMAND(setMark:, );
- // SEL_TO_COMMAND(showContextHelp:, );
- // SEL_TO_COMMAND(supplementalTargetForAction:sender:, );
- // SEL_TO_COMMAND(swapWithMark:, );
- // SEL_TO_COMMAND(transpose:, );
- // SEL_TO_COMMAND(transposeWords:, );
- // SEL_TO_COMMAND(uppercaseWord:, );
- // SEL_TO_COMMAND(yank:, );
-}
-
-#undef SEL_TO_COMMAND
-
-bool
-NativeKeyBindings::Execute(const WidgetKeyboardEvent& aEvent,
- DoCommandCallback aCallback,
- void* aCallbackData)
-{
- MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info,
- ("%p NativeKeyBindings::KeyPress", this));
-
- // Recover the current event, which should always be the key down we are
- // responding to.
-
- NSEvent* cocoaEvent = reinterpret_cast<NSEvent*>(aEvent.mNativeKeyEvent);
-
- if (!cocoaEvent || [cocoaEvent type] != NSKeyDown) {
- MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info,
- ("%p NativeKeyBindings::KeyPress, no Cocoa key down event", this));
-
- return false;
- }
-
- MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info,
- ("%p NativeKeyBindings::KeyPress, interpreting", this));
-
- AutoTArray<KeyBindingsCommand, 2> bindingCommands;
- nsCocoaUtils::GetCommandsFromKeyEvent(cocoaEvent, bindingCommands);
-
- MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info,
- ("%p NativeKeyBindings::KeyPress, bindingCommands=%u",
- this, bindingCommands.Length()));
-
- AutoTArray<Command, 4> geckoCommands;
-
- for (uint32_t i = 0; i < bindingCommands.Length(); i++) {
- SEL selector = bindingCommands[i].selector;
-
- if (MOZ_LOG_TEST(gNativeKeyBindingsLog, LogLevel::Info)) {
- NSString* selectorString = NSStringFromSelector(selector);
- nsAutoString nsSelectorString;
- nsCocoaUtils::GetStringForNSString(selectorString, nsSelectorString);
-
- MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info,
- ("%p NativeKeyBindings::KeyPress, selector=%s",
- this, NS_LossyConvertUTF16toASCII(nsSelectorString).get()));
- }
-
- // Try to find a simple mapping in the hashtable
- Command geckoCommand = static_cast<Command>(mSelectorToCommand.Get(
- reinterpret_cast<struct objc_selector*>(selector)));
-
- if (geckoCommand) {
- geckoCommands.AppendElement(geckoCommand);
- } else if (selector == @selector(selectLine:)) {
- // This is functional, but Cocoa's version is direction-less in that
- // selection direction is not determined until some future directed action
- // is taken. See bug 282097, comment 79 for more details.
- geckoCommands.AppendElement(CommandBeginLine);
- geckoCommands.AppendElement(CommandSelectEndLine);
- } else if (selector == @selector(selectWord:)) {
- // This is functional, but Cocoa's version is direction-less in that
- // selection direction is not determined until some future directed action
- // is taken. See bug 282097, comment 79 for more details.
- geckoCommands.AppendElement(CommandWordPrevious);
- geckoCommands.AppendElement(CommandSelectWordNext);
- }
- }
-
- if (geckoCommands.IsEmpty()) {
- MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info,
- ("%p NativeKeyBindings::KeyPress, handled=false", this));
-
- return false;
- }
-
- for (uint32_t i = 0; i < geckoCommands.Length(); i++) {
- Command geckoCommand = geckoCommands[i];
-
- MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info,
- ("%p NativeKeyBindings::KeyPress, command=%s",
- this, WidgetKeyboardEvent::GetCommandStr(geckoCommand)));
-
- // Execute the Gecko command
- aCallback(geckoCommand, aCallbackData);
- }
-
- MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info,
- ("%p NativeKeyBindings::KeyPress, handled=true", this));
-
- return true;
-}
-
-} // namespace widget
-} // namespace mozilla
diff --git a/widget/cocoa/OSXNotificationCenter.h b/widget/cocoa/OSXNotificationCenter.h
deleted file mode 100644
index 30767b5c55..0000000000
--- a/widget/cocoa/OSXNotificationCenter.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 OSXNotificationCenter_h
-#define OSXNotificationCenter_h
-
-#import <Foundation/Foundation.h>
-#include "nsIAlertsService.h"
-#include "imgINotificationObserver.h"
-#include "nsITimer.h"
-#include "nsTArray.h"
-#include "mozilla/RefPtr.h"
-
-@class mozNotificationCenterDelegate;
-
-#if !defined(MAC_OS_X_VERSION_10_8) || (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8)
-typedef NSInteger NSUserNotificationActivationType;
-#endif
-
-namespace mozilla {
-
-class OSXNotificationInfo;
-
-class OSXNotificationCenter : public nsIAlertsService,
- public nsIAlertsIconData,
- public nsIAlertNotificationImageListener
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIALERTSSERVICE
- NS_DECL_NSIALERTSICONDATA
- NS_DECL_NSIALERTNOTIFICATIONIMAGELISTENER
-
- OSXNotificationCenter();
-
- nsresult Init();
- void CloseAlertCocoaString(NSString *aAlertName);
- void OnActivate(NSString *aAlertName, NSUserNotificationActivationType aActivationType,
- unsigned long long aAdditionalActionIndex);
- void ShowPendingNotification(OSXNotificationInfo *osxni);
-
-protected:
- virtual ~OSXNotificationCenter();
-
-private:
- mozNotificationCenterDelegate *mDelegate;
- nsTArray<RefPtr<OSXNotificationInfo> > mActiveAlerts;
- nsTArray<RefPtr<OSXNotificationInfo> > mPendingAlerts;
-};
-
-} // namespace mozilla
-
-#endif // OSXNotificationCenter_h
diff --git a/widget/cocoa/OSXNotificationCenter.mm b/widget/cocoa/OSXNotificationCenter.mm
deleted file mode 100644
index e9e36a96be..0000000000
--- a/widget/cocoa/OSXNotificationCenter.mm
+++ /dev/null
@@ -1,589 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "OSXNotificationCenter.h"
-#import <AppKit/AppKit.h>
-#include "imgIRequest.h"
-#include "imgIContainer.h"
-#include "nsICancelable.h"
-#include "nsIStringBundle.h"
-#include "nsNetUtil.h"
-#import "nsCocoaUtils.h"
-#include "nsComponentManagerUtils.h"
-#include "nsContentUtils.h"
-#include "nsObjCExceptions.h"
-#include "nsString.h"
-#include "nsCOMPtr.h"
-#include "nsIObserver.h"
-
-using namespace mozilla;
-
-#define MAX_NOTIFICATION_NAME_LEN 5000
-
-#if !defined(MAC_OS_X_VERSION_10_8) || (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8)
-@protocol NSUserNotificationCenterDelegate
-@end
-static NSString * const NSUserNotificationDefaultSoundName = @"DefaultSoundName";
-enum {
- NSUserNotificationActivationTypeNone = 0,
- NSUserNotificationActivationTypeContentsClicked = 1,
- NSUserNotificationActivationTypeActionButtonClicked = 2,
-};
-#endif
-
-#if !defined(MAC_OS_X_VERSION_10_9) || (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_9)
-enum {
- NSUserNotificationActivationTypeReplied = 3,
-};
-#endif
-
-#if !defined(MAC_OS_X_VERSION_10_10) || (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_10)
-enum {
- NSUserNotificationActivationTypeAdditionalActionClicked = 4
-};
-#endif
-
-@protocol FakeNSUserNotification <NSObject>
-@property (copy) NSString* title;
-@property (copy) NSString* subtitle;
-@property (copy) NSString* informativeText;
-@property (copy) NSString* actionButtonTitle;
-@property (copy) NSDictionary* userInfo;
-@property (copy) NSDate* deliveryDate;
-@property (copy) NSTimeZone* deliveryTimeZone;
-@property (copy) NSDateComponents* deliveryRepeatInterval;
-@property (readonly) NSDate* actualDeliveryDate;
-@property (readonly, getter=isPresented) BOOL presented;
-@property (readonly, getter=isRemote) BOOL remote;
-@property (copy) NSString* soundName;
-@property BOOL hasActionButton;
-@property (readonly) NSUserNotificationActivationType activationType;
-@property (copy) NSString *otherButtonTitle;
-@property (copy) NSImage *contentImage;
-@end
-
-@protocol FakeNSUserNotificationCenter <NSObject>
-+ (id<FakeNSUserNotificationCenter>)defaultUserNotificationCenter;
-@property (assign) id <NSUserNotificationCenterDelegate> delegate;
-@property (copy) NSArray *scheduledNotifications;
-- (void)scheduleNotification:(id<FakeNSUserNotification>)notification;
-- (void)removeScheduledNotification:(id<FakeNSUserNotification>)notification;
-@property (readonly) NSArray *deliveredNotifications;
-- (void)deliverNotification:(id<FakeNSUserNotification>)notification;
-- (void)removeDeliveredNotification:(id<FakeNSUserNotification>)notification;
-- (void)removeAllDeliveredNotifications;
-- (void)_removeAllDisplayedNotifications;
-- (void)_removeDisplayedNotification:(id<FakeNSUserNotification>)notification;
-@end
-
-@interface mozNotificationCenterDelegate : NSObject <NSUserNotificationCenterDelegate>
-{
- OSXNotificationCenter *mOSXNC;
-}
- - (id)initWithOSXNC:(OSXNotificationCenter*)osxnc;
-@end
-
-@implementation mozNotificationCenterDelegate
-
-- (id)initWithOSXNC:(OSXNotificationCenter*)osxnc
-{
- [super init];
- // We should *never* outlive this OSXNotificationCenter.
- mOSXNC = osxnc;
- return self;
-}
-
-- (void)userNotificationCenter:(id<FakeNSUserNotificationCenter>)center
- didDeliverNotification:(id<FakeNSUserNotification>)notification
-{
-
-}
-
-- (void)userNotificationCenter:(id<FakeNSUserNotificationCenter>)center
- didActivateNotification:(id<FakeNSUserNotification>)notification
-{
- unsigned long long additionalActionIndex = ULLONG_MAX;
- if ([notification respondsToSelector:@selector(_alternateActionIndex)]) {
- NSNumber *alternateActionIndex = [(NSObject*)notification valueForKey:@"_alternateActionIndex"];
- additionalActionIndex = [alternateActionIndex unsignedLongLongValue];
- }
- mOSXNC->OnActivate([[notification userInfo] valueForKey:@"name"],
- notification.activationType,
- additionalActionIndex);
-}
-
-- (BOOL)userNotificationCenter:(id<FakeNSUserNotificationCenter>)center
- shouldPresentNotification:(id<FakeNSUserNotification>)notification
-{
- return YES;
-}
-
-// This is an undocumented method that we need for parity with Safari.
-// Apple bug #15440664.
-- (void)userNotificationCenter:(id<FakeNSUserNotificationCenter>)center
- didRemoveDeliveredNotifications:(NSArray *)notifications
-{
- for (id<FakeNSUserNotification> notification in notifications) {
- NSString *name = [[notification userInfo] valueForKey:@"name"];
- mOSXNC->CloseAlertCocoaString(name);
- }
-}
-
-// This is an undocumented method that we need to be notified if a user clicks the close button.
-- (void)userNotificationCenter:(id<FakeNSUserNotificationCenter>)center
- didDismissAlert:(id<FakeNSUserNotification>)notification
-{
- NSString *name = [[notification userInfo] valueForKey:@"name"];
- mOSXNC->CloseAlertCocoaString(name);
-}
-
-@end
-
-namespace mozilla {
-
-enum {
- OSXNotificationActionDisable = 0,
- OSXNotificationActionSettings = 1,
-};
-
-class OSXNotificationInfo final : public nsISupports {
-private:
- virtual ~OSXNotificationInfo();
-
-public:
- NS_DECL_ISUPPORTS
- OSXNotificationInfo(NSString *name, nsIObserver *observer,
- const nsAString & alertCookie);
-
- NSString *mName;
- nsCOMPtr<nsIObserver> mObserver;
- nsString mCookie;
- RefPtr<nsICancelable> mIconRequest;
- id<FakeNSUserNotification> mPendingNotifiction;
-};
-
-NS_IMPL_ISUPPORTS0(OSXNotificationInfo)
-
-OSXNotificationInfo::OSXNotificationInfo(NSString *name, nsIObserver *observer,
- const nsAString & alertCookie)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- NS_ASSERTION(name, "Cannot create OSXNotificationInfo without a name!");
- mName = [name retain];
- mObserver = observer;
- mCookie = alertCookie;
- mPendingNotifiction = nil;
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-OSXNotificationInfo::~OSXNotificationInfo()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- [mName release];
- [mPendingNotifiction release];
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-static id<FakeNSUserNotificationCenter> GetNotificationCenter() {
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
-
- Class c = NSClassFromString(@"NSUserNotificationCenter");
- return [c performSelector:@selector(defaultUserNotificationCenter)];
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
-}
-
-OSXNotificationCenter::OSXNotificationCenter()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- mDelegate = [[mozNotificationCenterDelegate alloc] initWithOSXNC:this];
- GetNotificationCenter().delegate = mDelegate;
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-OSXNotificationCenter::~OSXNotificationCenter()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- [GetNotificationCenter() removeAllDeliveredNotifications];
- [mDelegate release];
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-NS_IMPL_ISUPPORTS(OSXNotificationCenter, nsIAlertsService, nsIAlertsIconData,
- nsIAlertNotificationImageListener)
-
-nsresult OSXNotificationCenter::Init()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- return (!!NSClassFromString(@"NSUserNotification")) ? NS_OK : NS_ERROR_FAILURE;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP
-OSXNotificationCenter::ShowAlertNotification(const nsAString & aImageUrl, const nsAString & aAlertTitle,
- const nsAString & aAlertText, bool aAlertTextClickable,
- const nsAString & aAlertCookie,
- nsIObserver * aAlertListener,
- const nsAString & aAlertName,
- const nsAString & aBidi,
- const nsAString & aLang,
- const nsAString & aData,
- nsIPrincipal * aPrincipal,
- bool aInPrivateBrowsing,
- bool aRequireInteraction)
-{
- nsCOMPtr<nsIAlertNotification> alert =
- do_CreateInstance(ALERT_NOTIFICATION_CONTRACTID);
- NS_ENSURE_TRUE(alert, NS_ERROR_FAILURE);
- nsresult rv = alert->Init(aAlertName, aImageUrl, aAlertTitle,
- aAlertText, aAlertTextClickable,
- aAlertCookie, aBidi, aLang, aData,
- aPrincipal, aInPrivateBrowsing,
- aRequireInteraction);
- NS_ENSURE_SUCCESS(rv, rv);
- return ShowAlert(alert, aAlertListener);
-}
-
-NS_IMETHODIMP
-OSXNotificationCenter::ShowPersistentNotification(const nsAString& aPersistentData,
- nsIAlertNotification* aAlert,
- nsIObserver* aAlertListener)
-{
- return ShowAlert(aAlert, aAlertListener);
-}
-
-NS_IMETHODIMP
-OSXNotificationCenter::ShowAlert(nsIAlertNotification* aAlert,
- nsIObserver* aAlertListener)
-{
- return ShowAlertWithIconData(aAlert, aAlertListener, 0, nullptr);
-}
-
-NS_IMETHODIMP
-OSXNotificationCenter::ShowAlertWithIconData(nsIAlertNotification* aAlert,
- nsIObserver* aAlertListener,
- uint32_t aIconSize,
- const uint8_t* aIconData)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- NS_ENSURE_ARG(aAlert);
-
- Class unClass = NSClassFromString(@"NSUserNotification");
- id<FakeNSUserNotification> notification = [[unClass alloc] init];
-
- nsAutoString title;
- nsresult rv = aAlert->GetTitle(title);
- NS_ENSURE_SUCCESS(rv, rv);
- notification.title = nsCocoaUtils::ToNSString(title);
-
- nsAutoString hostPort;
- rv = aAlert->GetSource(hostPort);
- NS_ENSURE_SUCCESS(rv, rv);
- nsCOMPtr<nsIStringBundle> bundle;
- nsCOMPtr<nsIStringBundleService> sbs = do_GetService(NS_STRINGBUNDLE_CONTRACTID);
- sbs->CreateBundle("chrome://alerts/locale/alert.properties", getter_AddRefs(bundle));
-
- if (!hostPort.IsEmpty() && bundle) {
- const char16_t* formatStrings[] = { hostPort.get() };
- nsXPIDLString notificationSource;
- bundle->FormatStringFromName(u"source.label",
- formatStrings,
- ArrayLength(formatStrings),
- getter_Copies(notificationSource));
- notification.subtitle = nsCocoaUtils::ToNSString(notificationSource);
- }
-
- nsAutoString text;
- rv = aAlert->GetText(text);
- NS_ENSURE_SUCCESS(rv, rv);
- notification.informativeText = nsCocoaUtils::ToNSString(text);
-
- notification.soundName = NSUserNotificationDefaultSoundName;
- notification.hasActionButton = NO;
-
- // If this is not an application/extension alert, show additional actions dealing with permissions.
- bool isActionable;
- if (bundle && NS_SUCCEEDED(aAlert->GetActionable(&isActionable)) && isActionable) {
- nsXPIDLString closeButtonTitle, actionButtonTitle, disableButtonTitle, settingsButtonTitle;
- bundle->GetStringFromName(u"closeButton.title",
- getter_Copies(closeButtonTitle));
- bundle->GetStringFromName(u"actionButton.label",
- getter_Copies(actionButtonTitle));
- if (!hostPort.IsEmpty()) {
- const char16_t* formatStrings[] = { hostPort.get() };
- bundle->FormatStringFromName(u"webActions.disableForOrigin.label",
- formatStrings,
- ArrayLength(formatStrings),
- getter_Copies(disableButtonTitle));
- }
- bundle->GetStringFromName(u"webActions.settings.label",
- getter_Copies(settingsButtonTitle));
-
- notification.otherButtonTitle = nsCocoaUtils::ToNSString(closeButtonTitle);
-
- // OS X 10.8 only shows action buttons if the "Alerts" style is set in
- // Notification Center preferences, and doesn't support the alternate
- // action menu.
- if ([notification respondsToSelector:@selector(set_showsButtons:)] &&
- [notification respondsToSelector:@selector(set_alwaysShowAlternateActionMenu:)] &&
- [notification respondsToSelector:@selector(set_alternateActionButtonTitles:)]) {
-
- notification.hasActionButton = YES;
- notification.actionButtonTitle = nsCocoaUtils::ToNSString(actionButtonTitle);
-
- [(NSObject*)notification setValue:@(YES) forKey:@"_showsButtons"];
- [(NSObject*)notification setValue:@(YES) forKey:@"_alwaysShowAlternateActionMenu"];
- [(NSObject*)notification setValue:@[
- nsCocoaUtils::ToNSString(disableButtonTitle),
- nsCocoaUtils::ToNSString(settingsButtonTitle)
- ]
- forKey:@"_alternateActionButtonTitles"];
- }
- }
- nsAutoString name;
- rv = aAlert->GetName(name);
- // Don't let an alert name be more than MAX_NOTIFICATION_NAME_LEN characters.
- // More than that shouldn't be necessary and userInfo (assigned to below) has
- // a length limit of 16k on OS X 10.11. Exception thrown if limit exceeded.
- if (name.Length() > MAX_NOTIFICATION_NAME_LEN) {
- return NS_ERROR_FAILURE;
- }
-
- NS_ENSURE_SUCCESS(rv, rv);
- NSString *alertName = nsCocoaUtils::ToNSString(name);
- if (!alertName) {
- return NS_ERROR_FAILURE;
- }
- notification.userInfo = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:alertName, nil]
- forKeys:[NSArray arrayWithObjects:@"name", nil]];
-
- nsAutoString cookie;
- rv = aAlert->GetCookie(cookie);
- NS_ENSURE_SUCCESS(rv, rv);
-
- OSXNotificationInfo *osxni = new OSXNotificationInfo(alertName, aAlertListener, cookie);
-
- // Show the favicon if supported on this version of OS X.
- if (aIconSize > 0 &&
- [notification respondsToSelector:@selector(set_identityImage:)] &&
- [notification respondsToSelector:@selector(set_identityImageHasBorder:)]) {
-
- NSData *iconData = [NSData dataWithBytes:aIconData length:aIconSize];
- NSImage *icon = [[[NSImage alloc] initWithData:iconData] autorelease];
-
- [(NSObject*)notification setValue:icon forKey:@"_identityImage"];
- [(NSObject*)notification setValue:@(NO) forKey:@"_identityImageHasBorder"];
- }
-
- bool inPrivateBrowsing;
- rv = aAlert->GetInPrivateBrowsing(&inPrivateBrowsing);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Show the notification without waiting for an image if there is no icon URL or
- // notification icons are not supported on this version of OS X.
- if (![unClass instancesRespondToSelector:@selector(setContentImage:)]) {
- CloseAlertCocoaString(alertName);
- mActiveAlerts.AppendElement(osxni);
- [GetNotificationCenter() deliverNotification:notification];
- [notification release];
- if (aAlertListener) {
- aAlertListener->Observe(nullptr, "alertshow", cookie.get());
- }
- } else {
- mPendingAlerts.AppendElement(osxni);
- osxni->mPendingNotifiction = notification;
- // Wait six seconds for the image to load.
- rv = aAlert->LoadImage(6000, this, osxni,
- getter_AddRefs(osxni->mIconRequest));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- ShowPendingNotification(osxni);
- }
- }
-
- return NS_OK;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP
-OSXNotificationCenter::CloseAlert(const nsAString& aAlertName,
- nsIPrincipal* aPrincipal)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- NSString *alertName = nsCocoaUtils::ToNSString(aAlertName);
- CloseAlertCocoaString(alertName);
- return NS_OK;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-void
-OSXNotificationCenter::CloseAlertCocoaString(NSString *aAlertName)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- if (!aAlertName) {
- return; // Can't do anything without a name
- }
-
- NSArray *notifications = [GetNotificationCenter() deliveredNotifications];
- for (id<FakeNSUserNotification> notification in notifications) {
- NSString *name = [[notification userInfo] valueForKey:@"name"];
- if ([name isEqualToString:aAlertName]) {
- [GetNotificationCenter() removeDeliveredNotification:notification];
- [GetNotificationCenter() _removeDisplayedNotification:notification];
- break;
- }
- }
-
- for (unsigned int i = 0; i < mActiveAlerts.Length(); i++) {
- OSXNotificationInfo *osxni = mActiveAlerts[i];
- if ([aAlertName isEqualToString:osxni->mName]) {
- if (osxni->mObserver) {
- osxni->mObserver->Observe(nullptr, "alertfinished", osxni->mCookie.get());
- }
- if (osxni->mIconRequest) {
- osxni->mIconRequest->Cancel(NS_BINDING_ABORTED);
- osxni->mIconRequest = nullptr;
- }
- mActiveAlerts.RemoveElementAt(i);
- break;
- }
- }
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-void
-OSXNotificationCenter::OnActivate(NSString *aAlertName,
- NSUserNotificationActivationType aActivationType,
- unsigned long long aAdditionalActionIndex)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- if (!aAlertName) {
- return; // Can't do anything without a name
- }
-
- for (unsigned int i = 0; i < mActiveAlerts.Length(); i++) {
- OSXNotificationInfo *osxni = mActiveAlerts[i];
- if ([aAlertName isEqualToString:osxni->mName]) {
- if (osxni->mObserver) {
- switch ((int)aActivationType) {
- case NSUserNotificationActivationTypeAdditionalActionClicked:
- case NSUserNotificationActivationTypeActionButtonClicked:
- switch (aAdditionalActionIndex) {
- case OSXNotificationActionDisable:
- osxni->mObserver->Observe(nullptr, "alertdisablecallback", osxni->mCookie.get());
- break;
- case OSXNotificationActionSettings:
- osxni->mObserver->Observe(nullptr, "alertsettingscallback", osxni->mCookie.get());
- break;
- default:
- NS_WARNING("Unknown NSUserNotification additional action clicked");
- break;
- }
- break;
- default:
- osxni->mObserver->Observe(nullptr, "alertclickcallback", osxni->mCookie.get());
- break;
- }
- }
- return;
- }
- }
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-void
-OSXNotificationCenter::ShowPendingNotification(OSXNotificationInfo *osxni)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- if (osxni->mIconRequest) {
- osxni->mIconRequest->Cancel(NS_BINDING_ABORTED);
- osxni->mIconRequest = nullptr;
- }
-
- CloseAlertCocoaString(osxni->mName);
-
- for (unsigned int i = 0; i < mPendingAlerts.Length(); i++) {
- if (mPendingAlerts[i] == osxni) {
- mActiveAlerts.AppendElement(osxni);
- mPendingAlerts.RemoveElementAt(i);
- break;
- }
- }
-
- [GetNotificationCenter() deliverNotification:osxni->mPendingNotifiction];
-
- if (osxni->mObserver) {
- osxni->mObserver->Observe(nullptr, "alertshow", osxni->mCookie.get());
- }
-
- [osxni->mPendingNotifiction release];
- osxni->mPendingNotifiction = nil;
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-NS_IMETHODIMP
-OSXNotificationCenter::OnImageMissing(nsISupports* aUserData)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- OSXNotificationInfo *osxni = static_cast<OSXNotificationInfo*>(aUserData);
- if (osxni->mPendingNotifiction) {
- // If there was an error getting the image, or the request timed out, show
- // the notification without a content image.
- ShowPendingNotification(osxni);
- }
- return NS_OK;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP
-OSXNotificationCenter::OnImageReady(nsISupports* aUserData,
- imgIRequest* aRequest)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- nsCOMPtr<imgIContainer> image;
- nsresult rv = aRequest->GetImage(getter_AddRefs(image));
- if (NS_WARN_IF(NS_FAILED(rv) || !image)) {
- return rv;
- }
-
- OSXNotificationInfo *osxni = static_cast<OSXNotificationInfo*>(aUserData);
- if (!osxni->mPendingNotifiction) {
- return NS_ERROR_FAILURE;
- }
-
- NSImage *cocoaImage = nil;
- nsCocoaUtils::CreateNSImageFromImageContainer(image, imgIContainer::FRAME_FIRST, &cocoaImage, 1.0f);
- (osxni->mPendingNotifiction).contentImage = cocoaImage;
- [cocoaImage release];
- ShowPendingNotification(osxni);
-
- return NS_OK;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-} // namespace mozilla
diff --git a/widget/cocoa/RectTextureImage.h b/widget/cocoa/RectTextureImage.h
deleted file mode 100644
index 022b216c6b..0000000000
--- a/widget/cocoa/RectTextureImage.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef RectTextureImage_h_
-#define RectTextureImage_h_
-
-#include "mozilla/RefPtr.h"
-
-class MacIOSurface;
-
-namespace mozilla {
-
-namespace gl {
-class GLContext;
-} // namespace gl
-
-namespace widget {
-
-// Manages a texture which can resize dynamically, binds to the
-// LOCAL_GL_TEXTURE_RECTANGLE_ARB texture target and is automatically backed
-// by a power-of-two size GL texture. The latter two features are used for
-// compatibility with older Mac hardware which we block GL layers on.
-// RectTextureImages are used both for accelerated GL layers drawing and for
-// OMTC BasicLayers drawing.
-class RectTextureImage {
-public:
- RectTextureImage();
-
- virtual ~RectTextureImage();
-
- already_AddRefed<gfx::DrawTarget>
- BeginUpdate(const LayoutDeviceIntSize& aNewSize,
- const LayoutDeviceIntRegion& aDirtyRegion =
- LayoutDeviceIntRegion());
- void EndUpdate();
-
- void UpdateIfNeeded(const LayoutDeviceIntSize& aNewSize,
- const LayoutDeviceIntRegion& aDirtyRegion,
- void (^aCallback)(gfx::DrawTarget*,
- const LayoutDeviceIntRegion&))
- {
- RefPtr<gfx::DrawTarget> drawTarget = BeginUpdate(aNewSize, aDirtyRegion);
- if (drawTarget) {
- aCallback(drawTarget, GetUpdateRegion());
- EndUpdate();
- }
- }
-
- void UpdateFromCGContext(const LayoutDeviceIntSize& aNewSize,
- const LayoutDeviceIntRegion& aDirtyRegion,
- CGContextRef aCGContext);
-
- LayoutDeviceIntRegion GetUpdateRegion() {
- MOZ_ASSERT(mInUpdate, "update region only valid during update");
- return mUpdateRegion;
- }
-
- void Draw(mozilla::layers::GLManager* aManager,
- const LayoutDeviceIntPoint& aLocation,
- const gfx::Matrix4x4& aTransform = gfx::Matrix4x4());
-
-
-protected:
- void DeleteTexture();
- void BindIOSurfaceToTexture(gl::GLContext* aGL);
-
- RefPtr<MacIOSurface> mIOSurface;
- gl::GLContext* mGLContext;
- LayoutDeviceIntRegion mUpdateRegion;
- LayoutDeviceIntSize mBufferSize;
- GLuint mTexture;
- bool mInUpdate;
-};
-
-} // namespace widget
-} // namespace mozilla
-
-#endif // RectTextureImage_h_
diff --git a/widget/cocoa/RectTextureImage.mm b/widget/cocoa/RectTextureImage.mm
deleted file mode 100644
index c67af97d0a..0000000000
--- a/widget/cocoa/RectTextureImage.mm
+++ /dev/null
@@ -1,171 +0,0 @@
-/* -*- Mode: objc; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "RectTextureImage.h"
-
-#include "gfxUtils.h"
-#include "GLContextCGL.h"
-#include "mozilla/layers/GLManager.h"
-#include "mozilla/gfx/MacIOSurface.h"
-#include "OGLShaderProgram.h"
-#include "ScopedGLHelpers.h"
-
-namespace mozilla {
-namespace widget {
-
-RectTextureImage::RectTextureImage()
- : mGLContext(nullptr)
- , mTexture(0)
- , mInUpdate(false)
-{
-}
-
-RectTextureImage::~RectTextureImage()
-{
- DeleteTexture();
-}
-
-already_AddRefed<gfx::DrawTarget>
-RectTextureImage::BeginUpdate(const LayoutDeviceIntSize& aNewSize,
- const LayoutDeviceIntRegion& aDirtyRegion)
-{
- MOZ_ASSERT(!mInUpdate, "Beginning update during update!");
- mUpdateRegion = aDirtyRegion;
- bool needRecreate = false;
- if (aNewSize != mBufferSize) {
- mBufferSize = aNewSize;
- mUpdateRegion =
- LayoutDeviceIntRect(LayoutDeviceIntPoint(0, 0), aNewSize);
- needRecreate = true;
- }
-
- if (mUpdateRegion.IsEmpty()) {
- return nullptr;
- }
-
- if (!mIOSurface || needRecreate) {
- DeleteTexture();
- mIOSurface = MacIOSurface::CreateIOSurface(mBufferSize.width,
- mBufferSize.height);
-
- if (!mIOSurface) {
- return nullptr;
- }
- }
-
- mInUpdate = true;
-
- mIOSurface->Lock(false);
- unsigned char* ioData = (unsigned char*)mIOSurface->GetBaseAddress();
- gfx::IntSize size(mBufferSize.width, mBufferSize.height);
- int32_t stride = mIOSurface->GetBytesPerRow();
- gfx::SurfaceFormat format = gfx::SurfaceFormat::B8G8R8A8;
- RefPtr<gfx::DrawTarget> drawTarget =
- gfx::Factory::CreateDrawTargetForData(gfx::BackendType::SKIA,
- ioData, size,
- stride, format);
- return drawTarget.forget();
-}
-
-void
-RectTextureImage::EndUpdate()
-{
- MOZ_ASSERT(mInUpdate, "Ending update while not in update");
- mIOSurface->Unlock(false);
- mInUpdate = false;
-}
-
-void
-RectTextureImage::UpdateFromCGContext(const LayoutDeviceIntSize& aNewSize,
- const LayoutDeviceIntRegion& aDirtyRegion,
- CGContextRef aCGContext)
-{
- gfx::IntSize size = gfx::IntSize(CGBitmapContextGetWidth(aCGContext),
- CGBitmapContextGetHeight(aCGContext));
- RefPtr<gfx::DrawTarget> dt = BeginUpdate(aNewSize, aDirtyRegion);
- if (dt) {
- gfx::Rect rect(0, 0, size.width, size.height);
- gfxUtils::ClipToRegion(dt, GetUpdateRegion().ToUnknownRegion());
- RefPtr<gfx::SourceSurface> sourceSurface =
- dt->CreateSourceSurfaceFromData(static_cast<uint8_t *>(CGBitmapContextGetData(aCGContext)),
- size,
- CGBitmapContextGetBytesPerRow(aCGContext),
- gfx::SurfaceFormat::B8G8R8A8);
- dt->DrawSurface(sourceSurface, rect, rect,
- gfx::DrawSurfaceOptions(),
- gfx::DrawOptions(1.0, gfx::CompositionOp::OP_SOURCE));
- dt->PopClip();
- EndUpdate();
- }
-}
-
-void
-RectTextureImage::Draw(layers::GLManager* aManager,
- const LayoutDeviceIntPoint& aLocation,
- const gfx::Matrix4x4& aTransform)
-{
- gl::GLContext* gl = aManager->gl();
-
- BindIOSurfaceToTexture(gl);
-
- layers::ShaderProgramOGL* program =
- aManager->GetProgram(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
- gfx::SurfaceFormat::R8G8B8A8);
-
- gl->fActiveTexture(LOCAL_GL_TEXTURE0);
- gl::ScopedBindTexture texture(gl, mTexture, LOCAL_GL_TEXTURE_RECTANGLE_ARB);
-
- aManager->ActivateProgram(program);
- program->SetProjectionMatrix(aManager->GetProjMatrix());
- program->SetLayerTransform(gfx::Matrix4x4(aTransform).PostTranslate(aLocation.x, aLocation.y, 0));
- program->SetTextureTransform(gfx::Matrix4x4());
- program->SetRenderOffset(nsIntPoint(0, 0));
- program->SetTexCoordMultiplier(mBufferSize.width, mBufferSize.height);
- program->SetTextureUnit(0);
-
- aManager->BindAndDrawQuad(program,
- gfx::Rect(0.0, 0.0, mBufferSize.width, mBufferSize.height),
- gfx::Rect(0.0, 0.0, 1.0f, 1.0f));
-}
-
-void
-RectTextureImage::DeleteTexture()
-{
- if (mTexture) {
- MOZ_ASSERT(mGLContext);
- mGLContext->MakeCurrent();
- mGLContext->fDeleteTextures(1, &mTexture);
- mTexture = 0;
- }
-}
-
-void
-RectTextureImage::BindIOSurfaceToTexture(gl::GLContext* aGL)
-{
- if (!mTexture) {
- MOZ_ASSERT(aGL);
- aGL->fGenTextures(1, &mTexture);
- aGL->fActiveTexture(LOCAL_GL_TEXTURE0);
- gl::ScopedBindTexture texture(aGL, mTexture, LOCAL_GL_TEXTURE_RECTANGLE_ARB);
- aGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
- LOCAL_GL_TEXTURE_MIN_FILTER,
- LOCAL_GL_LINEAR);
- aGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
- LOCAL_GL_TEXTURE_MAG_FILTER,
- LOCAL_GL_LINEAR);
- aGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
- LOCAL_GL_TEXTURE_WRAP_T,
- LOCAL_GL_CLAMP_TO_EDGE);
- aGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
- LOCAL_GL_TEXTURE_WRAP_S,
- LOCAL_GL_CLAMP_TO_EDGE);
-
- mIOSurface->CGLTexImageIOSurface2D(gl::GLContextCGL::Cast(aGL)->GetCGLContext());
- mGLContext = aGL;
- }
-}
-
-} // namespace widget
-} // namespace mozilla
diff --git a/widget/cocoa/SwipeTracker.h b/widget/cocoa/SwipeTracker.h
deleted file mode 100644
index 78940d15cc..0000000000
--- a/widget/cocoa/SwipeTracker.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef SwipeTracker_h
-#define SwipeTracker_h
-
-#include "EventForwards.h"
-#include "mozilla/layers/AxisPhysicsMSDModel.h"
-#include "mozilla/RefPtr.h"
-#include "mozilla/TimeStamp.h"
-#include "nsRefreshDriver.h"
-#include "Units.h"
-
-class nsIPresShell;
-
-namespace mozilla {
-
-class PanGestureInput;
-
-/**
- * SwipeTracker turns PanGestureInput events into swipe events
- * (WidgetSimpleGestureEvent) and dispatches them into Gecko.
- * The swiping behavior mirrors the behavior of the Cocoa API
- * -[NSEvent trackSwipeEventWithOptions:dampenAmountThresholdMin:max:usingHandler:].
- * The advantage of using this class over the Cocoa API is that this class
- * properly supports submitting queued up events to it, and that it hopefully
- * doesn't intermittently break scrolling the way the Cocoa API does (bug 927702).
- *
- * The swipe direction is either left or right. It is determined before the
- * SwipeTracker is created and stays fixed during the swipe.
- * During the swipe, the swipe has a current "value" which is between 0 and the
- * target value. The target value is either 1 (swiping left) or -1 (swiping
- * right) - see SwipeSuccessTargetValue().
- * A swipe can either succeed or fail. If it succeeds, the swipe animation
- * animates towards the success target value; if it fails, it animates back to
- * a value of 0. A swipe can only succeed if the user is swiping in an allowed
- * direction. (Since both the allowed directions and the swipe direction are
- * known at swipe start time, it's clear from the beginning whether a swipe is
- * doomed to fail. In that case, the purpose of the SwipeTracker is to simulate
- * a bounce-back animation.)
- */
-class SwipeTracker final : public nsARefreshObserver {
-public:
- NS_INLINE_DECL_REFCOUNTING(SwipeTracker, override)
-
- SwipeTracker(nsChildView& aWidget,
- const PanGestureInput& aSwipeStartEvent,
- uint32_t aAllowedDirections,
- uint32_t aSwipeDirection);
-
- void Destroy();
-
- nsEventStatus ProcessEvent(const PanGestureInput& aEvent);
- void CancelSwipe();
-
- static WidgetSimpleGestureEvent
- CreateSwipeGestureEvent(EventMessage aMsg, nsIWidget* aWidget,
- const LayoutDeviceIntPoint& aPosition);
-
-
- // nsARefreshObserver
- void WillRefresh(mozilla::TimeStamp aTime) override;
-
-protected:
- ~SwipeTracker();
-
- bool SwipingInAllowedDirection() const { return mAllowedDirections & mSwipeDirection; }
- double SwipeSuccessTargetValue() const;
- double ClampToAllowedRange(double aGestureAmount) const;
- bool ComputeSwipeSuccess() const;
- void StartAnimating(double aTargetValue);
- void SwipeFinished();
- void UnregisterFromRefreshDriver();
- bool SendSwipeEvent(EventMessage aMsg, uint32_t aDirection, double aDelta);
-
- nsChildView& mWidget;
- RefPtr<nsRefreshDriver> mRefreshDriver;
- layers::AxisPhysicsMSDModel mAxis;
- const LayoutDeviceIntPoint mEventPosition;
- TimeStamp mLastEventTimeStamp;
- TimeStamp mLastAnimationFrameTime;
- const uint32_t mAllowedDirections;
- const uint32_t mSwipeDirection;
- double mGestureAmount;
- double mCurrentVelocity;
- bool mEventsAreControllingSwipe;
- bool mEventsHaveStartedNewGesture;
- bool mRegisteredWithRefreshDriver;
-};
-
-} // namespace mozilla
-
-#endif // SwipeTracker_h
diff --git a/widget/cocoa/SwipeTracker.mm b/widget/cocoa/SwipeTracker.mm
deleted file mode 100644
index 51169171a4..0000000000
--- a/widget/cocoa/SwipeTracker.mm
+++ /dev/null
@@ -1,219 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "SwipeTracker.h"
-
-#include "InputData.h"
-#include "mozilla/TimeStamp.h"
-#include "mozilla/TouchEvents.h"
-#include "nsAlgorithm.h"
-#include "nsChildView.h"
-#include "UnitTransforms.h"
-
-// These values were tweaked to make the physics feel similar to the native swipe.
-static const double kSpringForce = 250.0;
-static const double kVelocityTwitchTolerance = 0.0000001;
-static const double kWholePagePixelSize = 1000.0;
-static const double kRubberBandResistanceFactor = 4.0;
-static const double kSwipeSuccessThreshold = 0.25;
-static const double kSwipeSuccessVelocityContribution = 0.3;
-
-namespace mozilla {
-
-static already_AddRefed<nsRefreshDriver>
-GetRefreshDriver(nsIWidget& aWidget)
-{
- nsIWidgetListener* widgetListener = aWidget.GetWidgetListener();
- nsIPresShell* presShell = widgetListener ? widgetListener->GetPresShell() : nullptr;
- nsPresContext* presContext = presShell ? presShell->GetPresContext() : nullptr;
- RefPtr<nsRefreshDriver> refreshDriver = presContext ? presContext->RefreshDriver() : nullptr;
- return refreshDriver.forget();
-}
-
-SwipeTracker::SwipeTracker(nsChildView& aWidget,
- const PanGestureInput& aSwipeStartEvent,
- uint32_t aAllowedDirections,
- uint32_t aSwipeDirection)
- : mWidget(aWidget)
- , mRefreshDriver(GetRefreshDriver(mWidget))
- , mAxis(0.0, 0.0, 0.0, kSpringForce, 1.0)
- , mEventPosition(RoundedToInt(ViewAs<LayoutDevicePixel>(aSwipeStartEvent.mPanStartPoint,
- PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent)))
- , mLastEventTimeStamp(aSwipeStartEvent.mTimeStamp)
- , mAllowedDirections(aAllowedDirections)
- , mSwipeDirection(aSwipeDirection)
- , mGestureAmount(0.0)
- , mCurrentVelocity(0.0)
- , mEventsAreControllingSwipe(true)
- , mEventsHaveStartedNewGesture(false)
- , mRegisteredWithRefreshDriver(false)
-{
- SendSwipeEvent(eSwipeGestureStart, 0, 0.0);
- ProcessEvent(aSwipeStartEvent);
-}
-
-void
-SwipeTracker::Destroy()
-{
- UnregisterFromRefreshDriver();
-}
-
-SwipeTracker::~SwipeTracker()
-{
- MOZ_ASSERT(!mRegisteredWithRefreshDriver, "Destroy needs to be called before deallocating");
-}
-
-double
-SwipeTracker::SwipeSuccessTargetValue() const
-{
- return (mSwipeDirection == nsIDOMSimpleGestureEvent::DIRECTION_RIGHT) ? -1.0 : 1.0;
-}
-
-double
-SwipeTracker::ClampToAllowedRange(double aGestureAmount) const
-{
- // gestureAmount needs to stay between -1 and 0 when swiping right and
- // between 0 and 1 when swiping left.
- double min = (mSwipeDirection == nsIDOMSimpleGestureEvent::DIRECTION_RIGHT) ? -1.0 : 0.0;
- double max = (mSwipeDirection == nsIDOMSimpleGestureEvent::DIRECTION_LEFT) ? 1.0 : 0.0;
- return clamped(aGestureAmount, min, max);
-}
-
-bool
-SwipeTracker::ComputeSwipeSuccess() const
-{
- double targetValue = SwipeSuccessTargetValue();
-
- // If the fingers were moving away from the target direction when they were
- // lifted from the touchpad, abort the swipe.
- if (mCurrentVelocity * targetValue < -kVelocityTwitchTolerance) {
- return false;
- }
-
- return (mGestureAmount * targetValue +
- mCurrentVelocity * targetValue * kSwipeSuccessVelocityContribution) >= kSwipeSuccessThreshold;
-}
-
-nsEventStatus
-SwipeTracker::ProcessEvent(const PanGestureInput& aEvent)
-{
- // If the fingers have already been lifted, don't process this event for swiping.
- if (!mEventsAreControllingSwipe) {
- // Return nsEventStatus_eConsumeNoDefault for events from the swipe gesture
- // and nsEventStatus_eIgnore for events of subsequent scroll gestures.
- if (aEvent.mType == PanGestureInput::PANGESTURE_MAYSTART ||
- aEvent.mType == PanGestureInput::PANGESTURE_START) {
- mEventsHaveStartedNewGesture = true;
- }
- return mEventsHaveStartedNewGesture ? nsEventStatus_eIgnore : nsEventStatus_eConsumeNoDefault;
- }
-
- double delta = -aEvent.mPanDisplacement.x / mWidget.BackingScaleFactor() / kWholePagePixelSize;
- if (!SwipingInAllowedDirection()) {
- delta /= kRubberBandResistanceFactor;
- }
- mGestureAmount = ClampToAllowedRange(mGestureAmount + delta);
- SendSwipeEvent(eSwipeGestureUpdate, 0, mGestureAmount);
-
- if (aEvent.mType != PanGestureInput::PANGESTURE_END) {
- double elapsedSeconds = std::max(0.008, (aEvent.mTimeStamp - mLastEventTimeStamp).ToSeconds());
- mCurrentVelocity = delta / elapsedSeconds;
- mLastEventTimeStamp = aEvent.mTimeStamp;
- } else {
- mEventsAreControllingSwipe = false;
- bool didSwipeSucceed = SwipingInAllowedDirection() && ComputeSwipeSuccess();
- double targetValue = 0.0;
- if (didSwipeSucceed) {
- SendSwipeEvent(eSwipeGesture, mSwipeDirection, 0.0);
- targetValue = SwipeSuccessTargetValue();
- }
- StartAnimating(targetValue);
- }
-
- return nsEventStatus_eConsumeNoDefault;
-}
-
-void
-SwipeTracker::StartAnimating(double aTargetValue)
-{
- mAxis.SetPosition(mGestureAmount);
- mAxis.SetDestination(aTargetValue);
- mAxis.SetVelocity(mCurrentVelocity);
-
- mLastAnimationFrameTime = TimeStamp::Now();
-
- // Add ourselves as a refresh driver observer. The refresh driver
- // will call WillRefresh for each animation frame until we
- // unregister ourselves.
- MOZ_ASSERT(!mRegisteredWithRefreshDriver);
- if (mRefreshDriver) {
- mRefreshDriver->AddRefreshObserver(this, Flush_Style);
- mRegisteredWithRefreshDriver = true;
- }
-}
-
-void
-SwipeTracker::WillRefresh(mozilla::TimeStamp aTime)
-{
- TimeStamp now = TimeStamp::Now();
- mAxis.Simulate(now - mLastAnimationFrameTime);
- mLastAnimationFrameTime = now;
-
- bool isFinished = mAxis.IsFinished(1.0 / kWholePagePixelSize);
- mGestureAmount = (isFinished ? mAxis.GetDestination() : mAxis.GetPosition());
- SendSwipeEvent(eSwipeGestureUpdate, 0, mGestureAmount);
-
- if (isFinished) {
- UnregisterFromRefreshDriver();
- SwipeFinished();
- }
-}
-
-void
-SwipeTracker::CancelSwipe()
-{
- SendSwipeEvent(eSwipeGestureEnd, 0, 0.0);
-}
-
-void SwipeTracker::SwipeFinished()
-{
- SendSwipeEvent(eSwipeGestureEnd, 0, 0.0);
- mWidget.SwipeFinished();
-}
-
-void
-SwipeTracker::UnregisterFromRefreshDriver()
-{
- if (mRegisteredWithRefreshDriver) {
- MOZ_ASSERT(mRefreshDriver, "How were we able to register, then?");
- mRefreshDriver->RemoveRefreshObserver(this, Flush_Style);
- }
- mRegisteredWithRefreshDriver = false;
-}
-
-/* static */ WidgetSimpleGestureEvent
-SwipeTracker::CreateSwipeGestureEvent(EventMessage aMsg, nsIWidget* aWidget,
- const LayoutDeviceIntPoint& aPosition)
-{
- WidgetSimpleGestureEvent geckoEvent(true, aMsg, aWidget);
- geckoEvent.mModifiers = 0;
- geckoEvent.mTimeStamp = TimeStamp::Now();
- geckoEvent.mRefPoint = aPosition;
- geckoEvent.buttons = 0;
- return geckoEvent;
-}
-
-bool
-SwipeTracker::SendSwipeEvent(EventMessage aMsg, uint32_t aDirection, double aDelta)
-{
- WidgetSimpleGestureEvent geckoEvent =
- CreateSwipeGestureEvent(aMsg, &mWidget, mEventPosition);
- geckoEvent.mDirection = aDirection;
- geckoEvent.mDelta = aDelta;
- geckoEvent.mAllowedDirections = mAllowedDirections;
- return mWidget.DispatchWindowEvent(geckoEvent);
-}
-
-} // namespace mozilla
diff --git a/widget/cocoa/TextInputHandler.h b/widget/cocoa/TextInputHandler.h
deleted file mode 100644
index 86da354abb..0000000000
--- a/widget/cocoa/TextInputHandler.h
+++ /dev/null
@@ -1,1194 +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 TextInputHandler_h_
-#define TextInputHandler_h_
-
-#include "nsCocoaUtils.h"
-
-#import <Carbon/Carbon.h>
-#import <Cocoa/Cocoa.h>
-#include "mozView.h"
-#include "nsString.h"
-#include "nsCOMPtr.h"
-#include "nsITimer.h"
-#include "nsTArray.h"
-#include "mozilla/EventForwards.h"
-#include "mozilla/TextEventDispatcherListener.h"
-#include "WritingModes.h"
-
-class nsChildView;
-
-namespace mozilla {
-namespace widget {
-
-// Key code constants
-enum
-{
-#if !defined(MAC_OS_X_VERSION_10_12) || \
- MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12
- kVK_RightCommand = 0x36, // right command key
-#endif
-
- kVK_PC_PrintScreen = kVK_F13,
- kVK_PC_ScrollLock = kVK_F14,
- kVK_PC_Pause = kVK_F15,
-
- kVK_PC_Insert = kVK_Help,
- kVK_PC_Backspace = kVK_Delete,
- kVK_PC_Delete = kVK_ForwardDelete,
-
- kVK_PC_ContextMenu = 0x6E,
-
- kVK_Powerbook_KeypadEnter = 0x34 // Enter on Powerbook's keyboard is different
-};
-
-/**
- * TISInputSourceWrapper is a wrapper for the TISInputSourceRef. If we get the
- * TISInputSourceRef from InputSourceID, we need to release the CFArray instance
- * which is returned by TISCreateInputSourceList. However, when we release the
- * list, we cannot access the TISInputSourceRef. So, it's not usable, and it
- * may cause the memory leak bugs. nsTISInputSource automatically releases the
- * list when the instance is destroyed.
- */
-class TISInputSourceWrapper
-{
-public:
- static TISInputSourceWrapper& CurrentInputSource();
- /**
- * Shutdown() should be called when nobody doesn't need to use this class.
- */
- static void Shutdown();
-
- TISInputSourceWrapper()
- {
- mInputSourceList = nullptr;
- Clear();
- }
-
- explicit TISInputSourceWrapper(const char* aID)
- {
- mInputSourceList = nullptr;
- InitByInputSourceID(aID);
- }
-
- explicit TISInputSourceWrapper(SInt32 aLayoutID)
- {
- mInputSourceList = nullptr;
- InitByLayoutID(aLayoutID);
- }
-
- explicit TISInputSourceWrapper(TISInputSourceRef aInputSource)
- {
- mInputSourceList = nullptr;
- InitByTISInputSourceRef(aInputSource);
- }
-
- ~TISInputSourceWrapper() { Clear(); }
-
- void InitByInputSourceID(const char* aID);
- void InitByInputSourceID(const nsAFlatString &aID);
- void InitByInputSourceID(const CFStringRef aID);
- /**
- * InitByLayoutID() initializes the keyboard layout by the layout ID.
- *
- * @param aLayoutID An ID of keyboard layout.
- * 0: US
- * 1: Greek
- * 2: German
- * 3: Swedish-Pro
- * 4: Dvorak-Qwerty Cmd
- * 5: Thai
- * 6: Arabic
- * 7: French
- * 8: Hebrew
- * 9: Lithuanian
- * 10: Norwegian
- * 11: Spanish
- * @param aOverrideKeyboard When testing set to TRUE, otherwise, set to
- * FALSE. When TRUE, we use an ANSI keyboard
- * instead of the actual keyboard.
- */
- void InitByLayoutID(SInt32 aLayoutID, bool aOverrideKeyboard = false);
- void InitByCurrentInputSource();
- void InitByCurrentKeyboardLayout();
- void InitByCurrentASCIICapableInputSource();
- void InitByCurrentASCIICapableKeyboardLayout();
- void InitByCurrentInputMethodKeyboardLayoutOverride();
- void InitByTISInputSourceRef(TISInputSourceRef aInputSource);
- void InitByLanguage(CFStringRef aLanguage);
-
- /**
- * If the instance is initialized with a keyboard layout input source,
- * returns it.
- * If the instance is initialized with an IME mode input source, the result
- * references the keyboard layout for the IME mode. However, this can be
- * initialized only when the IME mode is actually selected. I.e, if IME mode
- * input source is initialized with LayoutID or SourceID, this returns null.
- */
- TISInputSourceRef GetKeyboardLayoutInputSource() const
- {
- return mKeyboardLayout;
- }
- const UCKeyboardLayout* GetUCKeyboardLayout();
-
- bool IsOpenedIMEMode();
- bool IsIMEMode();
- bool IsKeyboardLayout();
-
- bool IsASCIICapable()
- {
- NS_ENSURE_TRUE(mInputSource, false);
- return GetBoolProperty(kTISPropertyInputSourceIsASCIICapable);
- }
-
- bool IsEnabled()
- {
- NS_ENSURE_TRUE(mInputSource, false);
- return GetBoolProperty(kTISPropertyInputSourceIsEnabled);
- }
-
- bool GetLanguageList(CFArrayRef &aLanguageList);
- bool GetPrimaryLanguage(CFStringRef &aPrimaryLanguage);
- bool GetPrimaryLanguage(nsAString &aPrimaryLanguage);
-
- bool GetLocalizedName(CFStringRef &aName)
- {
- NS_ENSURE_TRUE(mInputSource, false);
- return GetStringProperty(kTISPropertyLocalizedName, aName);
- }
-
- bool GetLocalizedName(nsAString &aName)
- {
- NS_ENSURE_TRUE(mInputSource, false);
- return GetStringProperty(kTISPropertyLocalizedName, aName);
- }
-
- bool GetInputSourceID(CFStringRef &aID)
- {
- NS_ENSURE_TRUE(mInputSource, false);
- return GetStringProperty(kTISPropertyInputSourceID, aID);
- }
-
- bool GetInputSourceID(nsAString &aID)
- {
- NS_ENSURE_TRUE(mInputSource, false);
- return GetStringProperty(kTISPropertyInputSourceID, aID);
- }
-
- bool GetBundleID(CFStringRef &aBundleID)
- {
- NS_ENSURE_TRUE(mInputSource, false);
- return GetStringProperty(kTISPropertyBundleID, aBundleID);
- }
-
- bool GetBundleID(nsAString &aBundleID)
- {
- NS_ENSURE_TRUE(mInputSource, false);
- return GetStringProperty(kTISPropertyBundleID, aBundleID);
- }
-
- bool GetInputSourceType(CFStringRef &aType)
- {
- NS_ENSURE_TRUE(mInputSource, false);
- return GetStringProperty(kTISPropertyInputSourceType, aType);
- }
-
- bool GetInputSourceType(nsAString &aType)
- {
- NS_ENSURE_TRUE(mInputSource, false);
- return GetStringProperty(kTISPropertyInputSourceType, aType);
- }
-
- bool IsForRTLLanguage();
- bool IsInitializedByCurrentInputSource();
-
- enum {
- // 40 is an actual result of the ::LMGetKbdType() when we connect an
- // unknown keyboard and set the keyboard type to ANSI manually on the
- // set up dialog.
- eKbdType_ANSI = 40
- };
-
- void Select();
- void Clear();
-
- /**
- * InitKeyEvent() initializes aKeyEvent for aNativeKeyEvent.
- *
- * @param aNativeKeyEvent A native key event for which you want to
- * dispatch a Gecko key event.
- * @param aKeyEvent The result -- a Gecko key event initialized
- * from the native key event.
- * @param aInsertString If caller expects that the event will cause
- * a character to be input (say in an editor),
- * the caller should set this. Otherwise,
- * if caller sets null to this, this method will
- * compute the character to be input from
- * characters of aNativeKeyEvent.
- */
- void InitKeyEvent(NSEvent *aNativeKeyEvent, WidgetKeyboardEvent& aKeyEvent,
- const nsAString *aInsertString = nullptr);
-
- /**
- * WillDispatchKeyboardEvent() computes aKeyEvent.mAlternativeCharCodes and
- * recompute aKeyEvent.mCharCode if it's necessary.
- *
- * @param aNativeKeyEvent A native key event for which you want to
- * dispatch a Gecko key event.
- * @param aInsertString If caller expects that the event will cause
- * a character to be input (say in an editor),
- * the caller should set this. Otherwise,
- * if caller sets null to this, this method will
- * compute the character to be input from
- * characters of aNativeKeyEvent.
- * @param aKeyEvent The result -- a Gecko key event initialized
- * from the native key event. This must be
- * eKeyPress event.
- */
- void WillDispatchKeyboardEvent(NSEvent* aNativeKeyEvent,
- const nsAString* aInsertString,
- WidgetKeyboardEvent& aKeyEvent);
-
- /**
- * ComputeGeckoKeyCode() returns Gecko keycode for aNativeKeyCode on current
- * keyboard layout.
- *
- * @param aNativeKeyCode A native keycode.
- * @param aKbType A native Keyboard Type value. Typically,
- * this is a result of ::LMGetKbdType().
- * @param aCmdIsPressed TRUE if Cmd key is pressed. Otherwise, FALSE.
- * @return The computed Gecko keycode.
- */
- uint32_t ComputeGeckoKeyCode(UInt32 aNativeKeyCode, UInt32 aKbType,
- bool aCmdIsPressed);
-
- /**
- * ComputeGeckoKeyNameIndex() returns Gecko key name index for the key.
- *
- * @param aNativeKeyCode A native keycode.
- */
- static KeyNameIndex ComputeGeckoKeyNameIndex(UInt32 aNativeKeyCode);
-
- /**
- * ComputeGeckoCodeNameIndex() returns Gecko code name index for the key.
- *
- * @param aNativeKeyCode A native keycode.
- */
- static CodeNameIndex ComputeGeckoCodeNameIndex(UInt32 aNativeKeyCode);
-
-protected:
- /**
- * TranslateToString() computes the inputted text from the native keyCode,
- * modifier flags and keyboard type.
- *
- * @param aKeyCode A native keyCode.
- * @param aModifiers Combination of native modifier flags.
- * @param aKbType A native Keyboard Type value. Typically,
- * this is a result of ::LMGetKbdType().
- * @param aStr Result, i.e., inputted text.
- * The result can be two or more characters.
- * @return If succeeded, TRUE. Otherwise, FALSE.
- * Even if TRUE, aStr can be empty string.
- */
- bool TranslateToString(UInt32 aKeyCode, UInt32 aModifiers,
- UInt32 aKbType, nsAString &aStr);
-
- /**
- * TranslateToChar() computes the inputted character from the native keyCode,
- * modifier flags and keyboard type. If two or more characters would be
- * input, this returns 0.
- *
- * @param aKeyCode A native keyCode.
- * @param aModifiers Combination of native modifier flags.
- * @param aKbType A native Keyboard Type value. Typically,
- * this is a result of ::LMGetKbdType().
- * @return If succeeded and the result is one character,
- * returns the charCode of it. Otherwise,
- * returns 0.
- */
- uint32_t TranslateToChar(UInt32 aKeyCode, UInt32 aModifiers, UInt32 aKbType);
-
- /**
- * ComputeInsertString() computes string to be inserted with the key event.
- *
- * @param aNativeKeyEvent The native key event which causes our keyboard
- * event(s).
- * @param aKeyEvent A Gecko key event which was partially
- * initialized with aNativeKeyEvent.
- * @param aInsertString The string to be inputting by aNativeKeyEvent.
- * This should be specified by InsertText().
- * In other words, if the key event doesn't cause
- * a call of InsertText(), this can be nullptr.
- * @param aResult The string which should be set to charCode of
- * keypress event(s).
- */
- void ComputeInsertStringForCharCode(NSEvent* aNativeKeyEvent,
- const WidgetKeyboardEvent& aKeyEvent,
- const nsAString* aInsertString,
- nsAString& aResult);
-
- /**
- * IsPrintableKeyEvent() returns true if aNativeKeyEvent is caused by
- * a printable key. Otherwise, returns false.
- */
- bool IsPrintableKeyEvent(NSEvent* aNativeKeyEvent) const;
-
- /**
- * GetKbdType() returns physical keyboard type.
- */
- UInt32 GetKbdType() const;
-
- bool GetBoolProperty(const CFStringRef aKey);
- bool GetStringProperty(const CFStringRef aKey, CFStringRef &aStr);
- bool GetStringProperty(const CFStringRef aKey, nsAString &aStr);
-
- TISInputSourceRef mInputSource;
- TISInputSourceRef mKeyboardLayout;
- CFArrayRef mInputSourceList;
- const UCKeyboardLayout* mUCKeyboardLayout;
- int8_t mIsRTL;
-
- bool mOverrideKeyboard;
-
- static TISInputSourceWrapper* sCurrentInputSource;
-};
-
-/**
- * TextInputHandlerBase is a base class of IMEInputHandler and TextInputHandler.
- * Utility methods should be implemented this level.
- */
-
-class TextInputHandlerBase : public TextEventDispatcherListener
-{
-public:
- /**
- * Other TextEventDispatcherListener methods should be implemented in
- * IMEInputHandler.
- */
- NS_DECL_ISUPPORTS
-
- /**
- * DispatchEvent() dispatches aEvent on mWidget.
- *
- * @param aEvent An event which you want to dispatch.
- * @return TRUE if the event is consumed by web contents
- * or chrome contents. Otherwise, FALSE.
- */
- bool DispatchEvent(WidgetGUIEvent& aEvent);
-
- /**
- * SetSelection() dispatches eSetSelection event for the aRange.
- *
- * @param aRange The range which will be selected.
- * @return TRUE if setting selection is succeeded and
- * the widget hasn't been destroyed.
- * Otherwise, FALSE.
- */
- bool SetSelection(NSRange& aRange);
-
- /**
- * InitKeyEvent() initializes aKeyEvent for aNativeKeyEvent.
- *
- * @param aNativeKeyEvent A native key event for which you want to
- * dispatch a Gecko key event.
- * @param aKeyEvent The result -- a Gecko key event initialized
- * from the native key event.
- * @param aInsertString If caller expects that the event will cause
- * a character to be input (say in an editor),
- * the caller should set this. Otherwise,
- * if caller sets null to this, this method will
- * compute the character to be input from
- * characters of aNativeKeyEvent.
- */
- void InitKeyEvent(NSEvent *aNativeKeyEvent, WidgetKeyboardEvent& aKeyEvent,
- const nsAString *aInsertString = nullptr);
-
- /**
- * SynthesizeNativeKeyEvent() is an implementation of
- * nsIWidget::SynthesizeNativeKeyEvent(). See the document in nsIWidget.h
- * for the detail.
- */
- nsresult SynthesizeNativeKeyEvent(int32_t aNativeKeyboardLayout,
- int32_t aNativeKeyCode,
- uint32_t aModifierFlags,
- const nsAString& aCharacters,
- const nsAString& aUnmodifiedCharacters);
-
- /**
- * Utility method intended for testing. Attempts to construct a native key
- * event that would have been generated during an actual key press. This
- * *does not dispatch* the native event. Instead, it is attached to the
- * |mNativeKeyEvent| field of the Gecko event that is passed in.
- * @param aKeyEvent Gecko key event to attach the native event to
- */
- NS_IMETHOD AttachNativeKeyEvent(WidgetKeyboardEvent& aKeyEvent);
-
- /**
- * GetWindowLevel() returns the window level of current focused (in Gecko)
- * window. E.g., if an <input> element in XUL panel has focus, this returns
- * the XUL panel's window level.
- */
- NSInteger GetWindowLevel();
-
- /**
- * IsSpecialGeckoKey() checks whether aNativeKeyCode is mapped to a special
- * Gecko keyCode. A key is "special" if it isn't used for text input.
- *
- * @param aNativeKeyCode A native keycode.
- * @return If the keycode is mapped to a special key,
- * TRUE. Otherwise, FALSE.
- */
- static bool IsSpecialGeckoKey(UInt32 aNativeKeyCode);
-
-
- /**
- * EnableSecureEventInput() and DisableSecureEventInput() wrap the Carbon
- * Event Manager APIs with the same names. In addition they keep track of
- * how many times we've called them (in the same process) -- unlike the
- * Carbon Event Manager APIs, which only keep track of how many times they've
- * been called from any and all processes.
- *
- * The Carbon Event Manager's IsSecureEventInputEnabled() returns whether
- * secure event input mode is enabled (in any process). This class's
- * IsSecureEventInputEnabled() returns whether we've made any calls to
- * EnableSecureEventInput() that are not (yet) offset by the calls we've
- * made to DisableSecureEventInput().
- */
- static void EnableSecureEventInput();
- static void DisableSecureEventInput();
- static bool IsSecureEventInputEnabled();
-
- /**
- * EnsureSecureEventInputDisabled() calls DisableSecureEventInput() until
- * our call count becomes 0.
- */
- static void EnsureSecureEventInputDisabled();
-
-public:
- /**
- * mWidget must not be destroyed without OnDestroyWidget being called.
- *
- * @param aDestroyingWidget Destroying widget. This might not be mWidget.
- * @return This result doesn't have any meaning for
- * callers. When aDstroyingWidget isn't the same
- * as mWidget, FALSE. Then, inherited methods in
- * sub classes should return from this method
- * without cleaning up.
- */
- virtual bool OnDestroyWidget(nsChildView* aDestroyingWidget);
-
-protected:
- // The creator of this instance, client and its text event dispatcher.
- // These members must not be nullptr after initialized until
- // OnDestroyWidget() is called.
- nsChildView* mWidget; // [WEAK]
- RefPtr<TextEventDispatcher> mDispatcher;
-
- // The native view for mWidget.
- // This view handles the actual text inputting.
- NSView<mozView>* mView; // [STRONG]
-
- TextInputHandlerBase(nsChildView* aWidget, NSView<mozView> *aNativeView);
- virtual ~TextInputHandlerBase();
-
- bool Destroyed() { return !mWidget; }
-
- /**
- * mCurrentKeyEvent indicates what key event we are handling. While
- * handling a native keydown event, we need to store the event for insertText,
- * doCommandBySelector and various action message handlers of NSResponder
- * such as [NSResponder insertNewline:sender].
- */
- struct KeyEventState
- {
- // Handling native key event
- NSEvent* mKeyEvent;
- // String specified by InsertText(). This is not null only during a
- // call of InsertText().
- nsAString* mInsertString;
- // String which are included in [mKeyEvent characters] and already handled
- // by InsertText() call(s).
- nsString mInsertedString;
- // Whether keydown event was consumed by web contents or chrome contents.
- bool mKeyDownHandled;
- // Whether keypress event was dispatched for mKeyEvent.
- bool mKeyPressDispatched;
- // Whether keypress event was consumed by web contents or chrome contents.
- bool mKeyPressHandled;
- // Whether the key event causes other key events via IME or something.
- bool mCausedOtherKeyEvents;
- // Whether the key event causes composition change or committing
- // composition. So, even if InsertText() is called, this may be false
- // if it dispatches keypress event.
- bool mCompositionDispatched;
-
- KeyEventState() : mKeyEvent(nullptr)
- {
- Clear();
- }
-
- explicit KeyEventState(NSEvent* aNativeKeyEvent) : mKeyEvent(nullptr)
- {
- Clear();
- Set(aNativeKeyEvent);
- }
-
- KeyEventState(const KeyEventState &aOther) = delete;
-
- ~KeyEventState()
- {
- Clear();
- }
-
- void Set(NSEvent* aNativeKeyEvent)
- {
- NS_PRECONDITION(aNativeKeyEvent, "aNativeKeyEvent must not be NULL");
- Clear();
- mKeyEvent = [aNativeKeyEvent retain];
- }
-
- void Clear()
- {
- if (mKeyEvent) {
- [mKeyEvent release];
- mKeyEvent = nullptr;
- }
- mInsertString = nullptr;
- mInsertedString.Truncate();
- mKeyDownHandled = false;
- mKeyPressDispatched = false;
- mKeyPressHandled = false;
- mCausedOtherKeyEvents = false;
- mCompositionDispatched = false;
- }
-
- bool IsDefaultPrevented() const
- {
- return mKeyDownHandled || mKeyPressHandled || mCausedOtherKeyEvents ||
- mCompositionDispatched;
- }
-
- bool CanDispatchKeyPressEvent() const
- {
- return !mKeyPressDispatched && !IsDefaultPrevented();
- }
-
- void InitKeyEvent(TextInputHandlerBase* aHandler,
- WidgetKeyboardEvent& aKeyEvent);
-
- /**
- * GetUnhandledString() returns characters of the event which have not been
- * handled with InsertText() yet. For example, if there is a composition
- * caused by a dead key press like '`' and it's committed by some key
- * combinations like |Cmd+v|, then, the |v|'s KeyDown event's |characters|
- * is |`v|. Then, after |`| is committed with a call of InsertString(),
- * this returns only 'v'.
- */
- void GetUnhandledString(nsAString& aUnhandledString) const;
- };
-
- /**
- * Helper classes for guaranteeing cleaning mCurrentKeyEvent
- */
- class AutoKeyEventStateCleaner
- {
- public:
- explicit AutoKeyEventStateCleaner(TextInputHandlerBase* aHandler) :
- mHandler(aHandler)
- {
- }
-
- ~AutoKeyEventStateCleaner()
- {
- mHandler->RemoveCurrentKeyEvent();
- }
- private:
- RefPtr<TextInputHandlerBase> mHandler;
- };
-
- class MOZ_STACK_CLASS AutoInsertStringClearer
- {
- public:
- explicit AutoInsertStringClearer(KeyEventState* aState)
- : mState(aState)
- {
- }
- ~AutoInsertStringClearer();
-
- private:
- KeyEventState* mState;
- };
-
- /**
- * mCurrentKeyEvents stores all key events which are being processed.
- * When we call interpretKeyEvents, IME may generate other key events.
- * mCurrentKeyEvents[0] is the latest key event.
- */
- nsTArray<KeyEventState*> mCurrentKeyEvents;
-
- /**
- * mFirstKeyEvent must be used for first key event. This member prevents
- * memory fragmentation for most key events.
- */
- KeyEventState mFirstKeyEvent;
-
- /**
- * PushKeyEvent() adds the current key event to mCurrentKeyEvents.
- */
- KeyEventState* PushKeyEvent(NSEvent* aNativeKeyEvent)
- {
- uint32_t nestCount = mCurrentKeyEvents.Length();
- for (uint32_t i = 0; i < nestCount; i++) {
- // When the key event is caused by another key event, all key events
- // which are being handled should be marked as "consumed".
- mCurrentKeyEvents[i]->mCausedOtherKeyEvents = true;
- }
-
- KeyEventState* keyEvent = nullptr;
- if (nestCount == 0) {
- mFirstKeyEvent.Set(aNativeKeyEvent);
- keyEvent = &mFirstKeyEvent;
- } else {
- keyEvent = new KeyEventState(aNativeKeyEvent);
- }
- return *mCurrentKeyEvents.AppendElement(keyEvent);
- }
-
- /**
- * RemoveCurrentKeyEvent() removes the current key event from
- * mCurrentKeyEvents.
- */
- void RemoveCurrentKeyEvent()
- {
- NS_ASSERTION(mCurrentKeyEvents.Length() > 0,
- "RemoveCurrentKeyEvent() is called unexpectedly");
- KeyEventState* keyEvent = GetCurrentKeyEvent();
- mCurrentKeyEvents.RemoveElementAt(mCurrentKeyEvents.Length() - 1);
- if (keyEvent == &mFirstKeyEvent) {
- keyEvent->Clear();
- } else {
- delete keyEvent;
- }
- }
-
- /**
- * GetCurrentKeyEvent() returns current processing key event.
- */
- KeyEventState* GetCurrentKeyEvent()
- {
- if (mCurrentKeyEvents.Length() == 0) {
- return nullptr;
- }
- return mCurrentKeyEvents[mCurrentKeyEvents.Length() - 1];
- }
-
- struct KeyboardLayoutOverride final
- {
- int32_t mKeyboardLayout;
- bool mOverrideEnabled;
-
- KeyboardLayoutOverride() :
- mKeyboardLayout(0), mOverrideEnabled(false)
- {
- }
- };
-
- const KeyboardLayoutOverride& KeyboardLayoutOverrideRef() const
- {
- return mKeyboardOverride;
- }
-
- /**
- * IsPrintableChar() checks whether the unicode character is
- * a non-printable ASCII character or not. Note that this returns
- * TRUE even if aChar is a non-printable UNICODE character.
- *
- * @param aChar A unicode character.
- * @return TRUE if aChar is a printable ASCII character
- * or a unicode character. Otherwise, i.e,
- * if aChar is a non-printable ASCII character,
- * FALSE.
- */
- static bool IsPrintableChar(char16_t aChar);
-
- /**
- * IsNormalCharInputtingEvent() checks whether aKeyEvent causes text input.
- *
- * @param aKeyEvent A key event.
- * @return TRUE if the key event causes text input.
- * Otherwise, FALSE.
- */
- static bool IsNormalCharInputtingEvent(const WidgetKeyboardEvent& aKeyEvent);
-
- /**
- * IsModifierKey() checks whether the native keyCode is for a modifier key.
- *
- * @param aNativeKeyCode A native keyCode.
- * @return TRUE if aNativeKeyCode is for a modifier key.
- * Otherwise, FALSE.
- */
- static bool IsModifierKey(UInt32 aNativeKeyCode);
-
-private:
- KeyboardLayoutOverride mKeyboardOverride;
-
- static int32_t sSecureEventInputCount;
-};
-
-/**
- * IMEInputHandler manages:
- * 1. The IME/keyboard layout statement of nsChildView.
- * 2. The IME composition statement of nsChildView.
- * And also provides the methods which controls the current IME transaction of
- * the instance.
- *
- * Note that an nsChildView handles one or more NSView's events. E.g., even if
- * a text editor on XUL panel element, the input events handled on the parent
- * (or its ancestor) widget handles it (the native focus is set to it). The
- * actual focused view is notified by OnFocusChangeInGecko.
- */
-
-class IMEInputHandler : public TextInputHandlerBase
-{
-public:
- // TextEventDispatcherListener methods
- NS_IMETHOD NotifyIME(TextEventDispatcher* aTextEventDispatcher,
- const IMENotification& aNotification) override;
- NS_IMETHOD_(void) OnRemovedFrom(
- TextEventDispatcher* aTextEventDispatcher) override;
- NS_IMETHOD_(void) WillDispatchKeyboardEvent(
- TextEventDispatcher* aTextEventDispatcher,
- WidgetKeyboardEvent& aKeyboardEvent,
- uint32_t aIndexOfKeypress,
- void* aData) override;
-
-public:
- virtual bool OnDestroyWidget(nsChildView* aDestroyingWidget) override;
-
- virtual void OnFocusChangeInGecko(bool aFocus);
-
- void OnSelectionChange(const IMENotification& aIMENotification);
-
- /**
- * Call [NSTextInputContext handleEvent] for mouse event support of IME
- */
- bool OnHandleEvent(NSEvent* aEvent);
-
- /**
- * SetMarkedText() is a handler of setMarkedText of NSTextInput.
- *
- * @param aAttrString This mut be an instance of NSAttributedString.
- * If the aString parameter to
- * [ChildView setMarkedText:setSelectedRange:]
- * isn't an instance of NSAttributedString,
- * create an NSAttributedString from it and pass
- * that instead.
- * @param aSelectedRange Current selected range (or caret position).
- * @param aReplacementRange The range which will be replaced with the
- * aAttrString instead of current marked range.
- */
- void SetMarkedText(NSAttributedString* aAttrString,
- NSRange& aSelectedRange,
- NSRange* aReplacementRange = nullptr);
-
- /**
- * GetAttributedSubstringFromRange() returns an NSAttributedString instance
- * which is allocated as autorelease for aRange.
- *
- * @param aRange The range of string which you want.
- * @param aActualRange The actual range of the result.
- * @return The string in aRange. If the string is empty,
- * this returns nil. If succeeded, this returns
- * an instance which is allocated as autorelease.
- * If this has some troubles, returns nil.
- */
- NSAttributedString* GetAttributedSubstringFromRange(
- NSRange& aRange,
- NSRange* aActualRange = nullptr);
-
- /**
- * SelectedRange() returns current selected range.
- *
- * @return If an editor has focus, this returns selection
- * range in the editor. Otherwise, this returns
- * selection range in the focused document.
- */
- NSRange SelectedRange();
-
- /**
- * DrawsVerticallyForCharacterAtIndex() returns whether the character at
- * the given index is being rendered vertically.
- *
- * @param aCharIndex The character offset to query.
- *
- * @return True if writing-mode is vertical at the given
- * character offset; otherwise false.
- */
- bool DrawsVerticallyForCharacterAtIndex(uint32_t aCharIndex);
-
- /**
- * FirstRectForCharacterRange() returns first *character* rect in the range.
- * Cocoa needs the first line rect in the range, but we cannot compute it
- * on current implementation.
- *
- * @param aRange A range of text to examine. Its position is
- * an offset from the beginning of the focused
- * editor or document.
- * @param aActualRange If this is not null, this returns the actual
- * range used for computing the result.
- * @return An NSRect containing the first character in
- * aRange, in screen coordinates.
- * If the length of aRange is 0, the width will
- * be 0.
- */
- NSRect FirstRectForCharacterRange(NSRange& aRange,
- NSRange* aActualRange = nullptr);
-
- /**
- * CharacterIndexForPoint() returns an offset of a character at aPoint.
- * XXX This isn't implemented, always returns 0.
- *
- * @param The point in screen coordinates.
- * @return The offset of the character at aPoint from
- * the beginning of the focused editor or
- * document.
- */
- NSUInteger CharacterIndexForPoint(NSPoint& aPoint);
-
- /**
- * GetValidAttributesForMarkedText() returns attributes which we support.
- *
- * @return Always empty array for now.
- */
- NSArray* GetValidAttributesForMarkedText();
-
- bool HasMarkedText();
- NSRange MarkedRange();
-
- bool IsIMEComposing() { return mIsIMEComposing; }
- bool IsIMEOpened();
- bool IsIMEEnabled() { return mIsIMEEnabled; }
- bool IsASCIICapableOnly() { return mIsASCIICapableOnly; }
- bool IgnoreIMECommit() { return mIgnoreIMECommit; }
-
- bool IgnoreIMEComposition()
- {
- // Ignore the IME composition events when we're pending to discard the
- // composition and we are not to handle the IME composition now.
- return (mPendingMethods & kDiscardIMEComposition) &&
- (mIsInFocusProcessing || !IsFocused());
- }
-
- void CommitIMEComposition();
- void CancelIMEComposition();
-
- void EnableIME(bool aEnableIME);
- void SetIMEOpenState(bool aOpen);
- void SetASCIICapableOnly(bool aASCIICapableOnly);
-
- /**
- * True if OSX believes that our view has keyboard focus.
- */
- bool IsFocused();
-
- static CFArrayRef CreateAllIMEModeList();
- static void DebugPrintAllIMEModes();
-
- // Don't use ::TSMGetActiveDocument() API directly, the document may not
- // be what you want.
- static TSMDocumentID GetCurrentTSMDocumentID();
-
-protected:
- // We cannot do some jobs in the given stack by some reasons.
- // Following flags and the timer provide the execution pending mechanism,
- // See the comment in nsCocoaTextInputHandler.mm.
- nsCOMPtr<nsITimer> mTimer;
- enum {
- kNotifyIMEOfFocusChangeInGecko = 1,
- kDiscardIMEComposition = 2,
- kSyncASCIICapableOnly = 4
- };
- uint32_t mPendingMethods;
-
- IMEInputHandler(nsChildView* aWidget, NSView<mozView> *aNativeView);
- virtual ~IMEInputHandler();
-
- void ResetTimer();
-
- virtual void ExecutePendingMethods();
-
- /**
- * InsertTextAsCommittingComposition() commits current composition. If there
- * is no composition, this starts a composition and commits it immediately.
- *
- * @param aAttrString A string which is committed.
- * @param aReplacementRange The range which will be replaced with the
- * aAttrString instead of current selection.
- */
- void InsertTextAsCommittingComposition(NSAttributedString* aAttrString,
- NSRange* aReplacementRange);
-
-private:
- // If mIsIMEComposing is true, the composition string is stored here.
- NSString* mIMECompositionString;
- // If mIsIMEComposing is true, the start offset of the composition string.
- uint32_t mIMECompositionStart;
-
- NSRange mMarkedRange;
- NSRange mSelectedRange;
-
- NSRange mRangeForWritingMode; // range within which mWritingMode applies
- mozilla::WritingMode mWritingMode;
-
- bool mIsIMEComposing;
- bool mIsIMEEnabled;
- bool mIsASCIICapableOnly;
- bool mIgnoreIMECommit;
- // This flag is enabled by OnFocusChangeInGecko, and will be cleared by
- // ExecutePendingMethods. When this is true, IsFocus() returns TRUE. At
- // that time, the focus processing in Gecko might not be finished yet. So,
- // you cannot use WidgetQueryContentEvent or something.
- bool mIsInFocusProcessing;
- bool mIMEHasFocus;
-
- void KillIMEComposition();
- void SendCommittedText(NSString *aString);
- void OpenSystemPreferredLanguageIME();
-
- // Pending methods
- void NotifyIMEOfFocusChangeInGecko();
- void DiscardIMEComposition();
- void SyncASCIICapableOnly();
-
- static bool sStaticMembersInitialized;
- static CFStringRef sLatestIMEOpenedModeInputSourceID;
- static void InitStaticMembers();
- static void OnCurrentTextInputSourceChange(CFNotificationCenterRef aCenter,
- void* aObserver,
- CFStringRef aName,
- const void* aObject,
- CFDictionaryRef aUserInfo);
-
- static void FlushPendingMethods(nsITimer* aTimer, void* aClosure);
-
- /**
- * ConvertToTextRangeStyle converts the given native underline style to
- * our defined text range type.
- *
- * @param aUnderlineStyle NSUnderlineStyleSingle or
- * NSUnderlineStyleThick.
- * @param aSelectedRange Current selected range (or caret position).
- * @return NS_TEXTRANGE_*.
- */
- TextRangeType ConvertToTextRangeType(uint32_t aUnderlineStyle,
- NSRange& aSelectedRange);
-
- /**
- * GetRangeCount() computes the range count of aAttrString.
- *
- * @param aAttrString An NSAttributedString instance whose number of
- * NSUnderlineStyleAttributeName ranges you with
- * to know.
- * @return The count of NSUnderlineStyleAttributeName
- * ranges in aAttrString.
- */
- uint32_t GetRangeCount(NSAttributedString *aString);
-
- /**
- * CreateTextRangeArray() returns text ranges for clauses and/or caret.
- *
- * @param aAttrString An NSAttributedString instance which indicates
- * current composition string.
- * @param aSelectedRange Current selected range (or caret position).
- * @return The result is set to the
- * NSUnderlineStyleAttributeName ranges in
- * aAttrString.
- */
- already_AddRefed<mozilla::TextRangeArray>
- CreateTextRangeArray(NSAttributedString *aAttrString,
- NSRange& aSelectedRange);
-
- /**
- * DispatchCompositionStartEvent() dispatches a compositionstart event and
- * initializes the members indicating composition state.
- *
- * @return true if it can continues handling composition.
- * Otherwise, e.g., canceled by the web page,
- * this returns false.
- */
- bool DispatchCompositionStartEvent();
-
- /**
- * DispatchCompositionChangeEvent() dispatches a compositionchange event on
- * mWidget and modifies the members indicating composition state.
- *
- * @param aText User text input.
- * @param aAttrString An NSAttributedString instance which indicates
- * current composition string.
- * @param aSelectedRange Current selected range (or caret position).
- *
- * @return true if it can continues handling composition.
- * Otherwise, e.g., canceled by the web page,
- * this returns false.
- */
- bool DispatchCompositionChangeEvent(const nsString& aText,
- NSAttributedString* aAttrString,
- NSRange& aSelectedRange);
-
- /**
- * DispatchCompositionCommitEvent() dispatches a compositioncommit event or
- * compositioncommitasis event. If aCommitString is null, dispatches
- * compositioncommitasis event. I.e., if aCommitString is null, this
- * commits the composition with the last data. Otherwise, commits the
- * composition with aCommitString value.
- *
- * @return true if the widget isn't destroyed.
- * Otherwise, false.
- */
- bool DispatchCompositionCommitEvent(const nsAString* aCommitString = nullptr);
-
- // The focused IME handler. Please note that the handler might lost the
- // actual focus by deactivating the application. If we are active, this
- // must have the actual focused handle.
- // We cannot access to the NSInputManager during we aren't active, so, the
- // focused handler can have an IME transaction even if we are deactive.
- static IMEInputHandler* sFocusedIMEHandler;
-
- static bool sCachedIsForRTLLangage;
-};
-
-/**
- * TextInputHandler implements the NSTextInput protocol.
- */
-class TextInputHandler : public IMEInputHandler
-{
-public:
- static NSUInteger sLastModifierState;
-
- static CFArrayRef CreateAllKeyboardLayoutList();
- static void DebugPrintAllKeyboardLayouts();
-
- TextInputHandler(nsChildView* aWidget, NSView<mozView> *aNativeView);
- virtual ~TextInputHandler();
-
- /**
- * KeyDown event handler.
- *
- * @param aNativeEvent A native NSKeyDown event.
- * @return TRUE if the event is consumed by web contents
- * or chrome contents. Otherwise, FALSE.
- */
- bool HandleKeyDownEvent(NSEvent* aNativeEvent);
-
- /**
- * KeyUp event handler.
- *
- * @param aNativeEvent A native NSKeyUp event.
- */
- void HandleKeyUpEvent(NSEvent* aNativeEvent);
-
- /**
- * FlagsChanged event handler.
- *
- * @param aNativeEvent A native NSFlagsChanged event.
- */
- void HandleFlagsChanged(NSEvent* aNativeEvent);
-
- /**
- * Insert the string to content. I.e., this is a text input event handler.
- * If this is called during keydown event handling, this may dispatch a
- * eKeyPress event. If this is called during composition, this commits
- * the composition by the aAttrString.
- *
- * @param aAttrString An inserted string.
- * @param aReplacementRange The range which will be replaced with the
- * aAttrString instead of current selection.
- */
- void InsertText(NSAttributedString *aAttrString,
- NSRange* aReplacementRange = nullptr);
-
- /**
- * doCommandBySelector event handler.
- *
- * @param aSelector A selector of the command.
- * @return TRUE if the command is consumed. Otherwise,
- * FALSE.
- */
- bool DoCommandBySelector(const char* aSelector);
-
- /**
- * KeyPressWasHandled() checks whether keypress event was handled or not.
- *
- * @return TRUE if keypress event for latest native key
- * event was handled. Otherwise, FALSE.
- * If this handler isn't handling any key events,
- * always returns FALSE.
- */
- bool KeyPressWasHandled()
- {
- KeyEventState* currentKeyEvent = GetCurrentKeyEvent();
- return currentKeyEvent && currentKeyEvent->mKeyPressHandled;
- }
-
-protected:
- // Stores the association of device dependent modifier flags with a modifier
- // keyCode. Being device dependent, this association may differ from one kind
- // of hardware to the next.
- struct ModifierKey
- {
- NSUInteger flags;
- unsigned short keyCode;
-
- ModifierKey(NSUInteger aFlags, unsigned short aKeyCode) :
- flags(aFlags), keyCode(aKeyCode)
- {
- }
-
- NSUInteger GetDeviceDependentFlags() const
- {
- return (flags & ~NSDeviceIndependentModifierFlagsMask);
- }
-
- NSUInteger GetDeviceIndependentFlags() const
- {
- return (flags & NSDeviceIndependentModifierFlagsMask);
- }
- };
- typedef nsTArray<ModifierKey> ModifierKeyArray;
- ModifierKeyArray mModifierKeys;
-
- /**
- * GetModifierKeyForNativeKeyCode() returns the stored ModifierKey for
- * the key.
- */
- const ModifierKey*
- GetModifierKeyForNativeKeyCode(unsigned short aKeyCode) const;
-
- /**
- * GetModifierKeyForDeviceDependentFlags() returns the stored ModifierKey for
- * the device dependent flags.
- */
- const ModifierKey*
- GetModifierKeyForDeviceDependentFlags(NSUInteger aFlags) const;
-
- /**
- * DispatchKeyEventForFlagsChanged() dispatches keydown event or keyup event
- * for the aNativeEvent.
- *
- * @param aNativeEvent A native flagschanged event which you want to
- * dispatch our key event for.
- * @param aDispatchKeyDown TRUE if you want to dispatch a keydown event.
- * Otherwise, i.e., to dispatch keyup event,
- * FALSE.
- */
- void DispatchKeyEventForFlagsChanged(NSEvent* aNativeEvent,
- bool aDispatchKeyDown);
-};
-
-} // namespace widget
-} // namespace mozilla
-
-#endif // TextInputHandler_h_
diff --git a/widget/cocoa/TextInputHandler.mm b/widget/cocoa/TextInputHandler.mm
deleted file mode 100644
index 348d99ab69..0000000000
--- a/widget/cocoa/TextInputHandler.mm
+++ /dev/null
@@ -1,4533 +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 "TextInputHandler.h"
-
-#include "mozilla/Logging.h"
-
-#include "mozilla/ArrayUtils.h"
-#include "mozilla/AutoRestore.h"
-#include "mozilla/MiscEvents.h"
-#include "mozilla/MouseEvents.h"
-#include "mozilla/TextEventDispatcher.h"
-#include "mozilla/TextEvents.h"
-
-#include "nsChildView.h"
-#include "nsObjCExceptions.h"
-#include "nsBidiUtils.h"
-#include "nsToolkit.h"
-#include "nsCocoaUtils.h"
-#include "WidgetUtils.h"
-#include "nsPrintfCString.h"
-#include "ComplexTextInputPanel.h"
-
-using namespace mozilla;
-using namespace mozilla::widget;
-
-LazyLogModule gLog("TextInputHandlerWidgets");
-
-static const char*
-OnOrOff(bool aBool)
-{
- return aBool ? "ON" : "off";
-}
-
-static const char*
-TrueOrFalse(bool aBool)
-{
- return aBool ? "TRUE" : "FALSE";
-}
-
-static const char*
-GetKeyNameForNativeKeyCode(unsigned short aNativeKeyCode)
-{
- switch (aNativeKeyCode) {
- case kVK_Escape: return "Escape";
- case kVK_RightCommand: return "Right-Command";
- case kVK_Command: return "Command";
- case kVK_Shift: return "Shift";
- case kVK_CapsLock: return "CapsLock";
- case kVK_Option: return "Option";
- case kVK_Control: return "Control";
- case kVK_RightShift: return "Right-Shift";
- case kVK_RightOption: return "Right-Option";
- case kVK_RightControl: return "Right-Control";
- case kVK_ANSI_KeypadClear: return "Clear";
-
- case kVK_F1: return "F1";
- case kVK_F2: return "F2";
- case kVK_F3: return "F3";
- case kVK_F4: return "F4";
- case kVK_F5: return "F5";
- case kVK_F6: return "F6";
- case kVK_F7: return "F7";
- case kVK_F8: return "F8";
- case kVK_F9: return "F9";
- case kVK_F10: return "F10";
- case kVK_F11: return "F11";
- case kVK_F12: return "F12";
- case kVK_F13: return "F13/PrintScreen";
- case kVK_F14: return "F14/ScrollLock";
- case kVK_F15: return "F15/Pause";
-
- case kVK_ANSI_Keypad0: return "NumPad-0";
- case kVK_ANSI_Keypad1: return "NumPad-1";
- case kVK_ANSI_Keypad2: return "NumPad-2";
- case kVK_ANSI_Keypad3: return "NumPad-3";
- case kVK_ANSI_Keypad4: return "NumPad-4";
- case kVK_ANSI_Keypad5: return "NumPad-5";
- case kVK_ANSI_Keypad6: return "NumPad-6";
- case kVK_ANSI_Keypad7: return "NumPad-7";
- case kVK_ANSI_Keypad8: return "NumPad-8";
- case kVK_ANSI_Keypad9: return "NumPad-9";
-
- case kVK_ANSI_KeypadMultiply: return "NumPad-*";
- case kVK_ANSI_KeypadPlus: return "NumPad-+";
- case kVK_ANSI_KeypadMinus: return "NumPad--";
- case kVK_ANSI_KeypadDecimal: return "NumPad-.";
- case kVK_ANSI_KeypadDivide: return "NumPad-/";
- case kVK_ANSI_KeypadEquals: return "NumPad-=";
- case kVK_ANSI_KeypadEnter: return "NumPad-Enter";
- case kVK_Return: return "Return";
- case kVK_Powerbook_KeypadEnter: return "NumPad-EnterOnPowerBook";
-
- case kVK_PC_Insert: return "Insert/Help";
- case kVK_PC_Delete: return "Delete";
- case kVK_Tab: return "Tab";
- case kVK_PC_Backspace: return "Backspace";
- case kVK_Home: return "Home";
- case kVK_End: return "End";
- case kVK_PageUp: return "PageUp";
- case kVK_PageDown: return "PageDown";
- case kVK_LeftArrow: return "LeftArrow";
- case kVK_RightArrow: return "RightArrow";
- case kVK_UpArrow: return "UpArrow";
- case kVK_DownArrow: return "DownArrow";
- case kVK_PC_ContextMenu: return "ContextMenu";
-
- case kVK_Function: return "Function";
- case kVK_VolumeUp: return "VolumeUp";
- case kVK_VolumeDown: return "VolumeDown";
- case kVK_Mute: return "Mute";
-
- case kVK_ISO_Section: return "ISO_Section";
-
- case kVK_JIS_Yen: return "JIS_Yen";
- case kVK_JIS_Underscore: return "JIS_Underscore";
- case kVK_JIS_KeypadComma: return "JIS_KeypadComma";
- case kVK_JIS_Eisu: return "JIS_Eisu";
- case kVK_JIS_Kana: return "JIS_Kana";
-
- case kVK_ANSI_A: return "A";
- case kVK_ANSI_B: return "B";
- case kVK_ANSI_C: return "C";
- case kVK_ANSI_D: return "D";
- case kVK_ANSI_E: return "E";
- case kVK_ANSI_F: return "F";
- case kVK_ANSI_G: return "G";
- case kVK_ANSI_H: return "H";
- case kVK_ANSI_I: return "I";
- case kVK_ANSI_J: return "J";
- case kVK_ANSI_K: return "K";
- case kVK_ANSI_L: return "L";
- case kVK_ANSI_M: return "M";
- case kVK_ANSI_N: return "N";
- case kVK_ANSI_O: return "O";
- case kVK_ANSI_P: return "P";
- case kVK_ANSI_Q: return "Q";
- case kVK_ANSI_R: return "R";
- case kVK_ANSI_S: return "S";
- case kVK_ANSI_T: return "T";
- case kVK_ANSI_U: return "U";
- case kVK_ANSI_V: return "V";
- case kVK_ANSI_W: return "W";
- case kVK_ANSI_X: return "X";
- case kVK_ANSI_Y: return "Y";
- case kVK_ANSI_Z: return "Z";
-
- case kVK_ANSI_1: return "1";
- case kVK_ANSI_2: return "2";
- case kVK_ANSI_3: return "3";
- case kVK_ANSI_4: return "4";
- case kVK_ANSI_5: return "5";
- case kVK_ANSI_6: return "6";
- case kVK_ANSI_7: return "7";
- case kVK_ANSI_8: return "8";
- case kVK_ANSI_9: return "9";
- case kVK_ANSI_0: return "0";
- case kVK_ANSI_Equal: return "Equal";
- case kVK_ANSI_Minus: return "Minus";
- case kVK_ANSI_RightBracket: return "RightBracket";
- case kVK_ANSI_LeftBracket: return "LeftBracket";
- case kVK_ANSI_Quote: return "Quote";
- case kVK_ANSI_Semicolon: return "Semicolon";
- case kVK_ANSI_Backslash: return "Backslash";
- case kVK_ANSI_Comma: return "Comma";
- case kVK_ANSI_Slash: return "Slash";
- case kVK_ANSI_Period: return "Period";
- case kVK_ANSI_Grave: return "Grave";
-
- default: return "undefined";
- }
-}
-
-static const char*
-GetCharacters(const NSString* aString)
-{
- nsAutoString str;
- nsCocoaUtils::GetStringForNSString(aString, str);
- if (str.IsEmpty()) {
- return "";
- }
-
- nsAutoString escapedStr;
- for (uint32_t i = 0; i < str.Length(); i++) {
- char16_t ch = str[i];
- if (ch < 0x20) {
- nsPrintfCString utf8str("(U+%04X)", ch);
- escapedStr += NS_ConvertUTF8toUTF16(utf8str);
- } else if (ch <= 0x7E) {
- escapedStr += ch;
- } else {
- nsPrintfCString utf8str("(U+%04X)", ch);
- escapedStr += ch;
- escapedStr += NS_ConvertUTF8toUTF16(utf8str);
- }
- }
-
- // the result will be freed automatically by cocoa.
- NSString* result = nsCocoaUtils::ToNSString(escapedStr);
- return [result UTF8String];
-}
-
-static const char*
-GetCharacters(const CFStringRef aString)
-{
- const NSString* str = reinterpret_cast<const NSString*>(aString);
- return GetCharacters(str);
-}
-
-static const char*
-GetNativeKeyEventType(NSEvent* aNativeEvent)
-{
- switch ([aNativeEvent type]) {
- case NSKeyDown: return "NSKeyDown";
- case NSKeyUp: return "NSKeyUp";
- case NSFlagsChanged: return "NSFlagsChanged";
- default: return "not key event";
- }
-}
-
-static const char*
-GetGeckoKeyEventType(const WidgetEvent& aEvent)
-{
- switch (aEvent.mMessage) {
- case eKeyDown: return "eKeyDown";
- case eKeyUp: return "eKeyUp";
- case eKeyPress: return "eKeyPress";
- default: return "not key event";
- }
-}
-
-static const char*
-GetWindowLevelName(NSInteger aWindowLevel)
-{
- switch (aWindowLevel) {
- case kCGBaseWindowLevelKey:
- return "kCGBaseWindowLevelKey (NSNormalWindowLevel)";
- case kCGMinimumWindowLevelKey:
- return "kCGMinimumWindowLevelKey";
- case kCGDesktopWindowLevelKey:
- return "kCGDesktopWindowLevelKey";
- case kCGBackstopMenuLevelKey:
- return "kCGBackstopMenuLevelKey";
- case kCGNormalWindowLevelKey:
- return "kCGNormalWindowLevelKey";
- case kCGFloatingWindowLevelKey:
- return "kCGFloatingWindowLevelKey (NSFloatingWindowLevel)";
- case kCGTornOffMenuWindowLevelKey:
- return "kCGTornOffMenuWindowLevelKey (NSSubmenuWindowLevel, NSTornOffMenuWindowLevel)";
- case kCGDockWindowLevelKey:
- return "kCGDockWindowLevelKey (NSDockWindowLevel)";
- case kCGMainMenuWindowLevelKey:
- return "kCGMainMenuWindowLevelKey (NSMainMenuWindowLevel)";
- case kCGStatusWindowLevelKey:
- return "kCGStatusWindowLevelKey (NSStatusWindowLevel)";
- case kCGModalPanelWindowLevelKey:
- return "kCGModalPanelWindowLevelKey (NSModalPanelWindowLevel)";
- case kCGPopUpMenuWindowLevelKey:
- return "kCGPopUpMenuWindowLevelKey (NSPopUpMenuWindowLevel)";
- case kCGDraggingWindowLevelKey:
- return "kCGDraggingWindowLevelKey";
- case kCGScreenSaverWindowLevelKey:
- return "kCGScreenSaverWindowLevelKey (NSScreenSaverWindowLevel)";
- case kCGMaximumWindowLevelKey:
- return "kCGMaximumWindowLevelKey";
- case kCGOverlayWindowLevelKey:
- return "kCGOverlayWindowLevelKey";
- case kCGHelpWindowLevelKey:
- return "kCGHelpWindowLevelKey";
- case kCGUtilityWindowLevelKey:
- return "kCGUtilityWindowLevelKey";
- case kCGDesktopIconWindowLevelKey:
- return "kCGDesktopIconWindowLevelKey";
- case kCGCursorWindowLevelKey:
- return "kCGCursorWindowLevelKey";
- case kCGNumberOfWindowLevelKeys:
- return "kCGNumberOfWindowLevelKeys";
- default:
- return "unknown window level";
- }
-}
-
-static bool
-IsControlChar(uint32_t aCharCode)
-{
- return aCharCode < ' ' || aCharCode == 0x7F;
-}
-
-static uint32_t gHandlerInstanceCount = 0;
-
-static void
-EnsureToLogAllKeyboardLayoutsAndIMEs()
-{
- static bool sDone = false;
- if (!sDone) {
- sDone = true;
- TextInputHandler::DebugPrintAllKeyboardLayouts();
- IMEInputHandler::DebugPrintAllIMEModes();
- }
-}
-
-#pragma mark -
-
-
-/******************************************************************************
- *
- * TISInputSourceWrapper implementation
- *
- ******************************************************************************/
-
-TISInputSourceWrapper* TISInputSourceWrapper::sCurrentInputSource = nullptr;
-
-// static
-TISInputSourceWrapper&
-TISInputSourceWrapper::CurrentInputSource()
-{
- if (!sCurrentInputSource) {
- sCurrentInputSource = new TISInputSourceWrapper();
- }
- if (!sCurrentInputSource->IsInitializedByCurrentInputSource()) {
- sCurrentInputSource->InitByCurrentInputSource();
- }
- return *sCurrentInputSource;
-}
-
-// static
-void
-TISInputSourceWrapper::Shutdown()
-{
- if (!sCurrentInputSource) {
- return;
- }
- sCurrentInputSource->Clear();
- delete sCurrentInputSource;
- sCurrentInputSource = nullptr;
-}
-
-bool
-TISInputSourceWrapper::TranslateToString(UInt32 aKeyCode, UInt32 aModifiers,
- UInt32 aKbType, nsAString &aStr)
-{
- aStr.Truncate();
-
- const UCKeyboardLayout* UCKey = GetUCKeyboardLayout();
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TISInputSourceWrapper::TranslateToString, aKeyCode=0x%X, "
- "aModifiers=0x%X, aKbType=0x%X UCKey=%p\n "
- "Shift: %s, Ctrl: %s, Opt: %s, Cmd: %s, CapsLock: %s, NumLock: %s",
- this, aKeyCode, aModifiers, aKbType, UCKey,
- OnOrOff(aModifiers & shiftKey), OnOrOff(aModifiers & controlKey),
- OnOrOff(aModifiers & optionKey), OnOrOff(aModifiers & cmdKey),
- OnOrOff(aModifiers & alphaLock),
- OnOrOff(aModifiers & kEventKeyModifierNumLockMask)));
-
- NS_ENSURE_TRUE(UCKey, false);
-
- UInt32 deadKeyState = 0;
- UniCharCount len;
- UniChar chars[5];
- OSStatus err = ::UCKeyTranslate(UCKey, aKeyCode,
- kUCKeyActionDown, aModifiers >> 8,
- aKbType, kUCKeyTranslateNoDeadKeysMask,
- &deadKeyState, 5, &len, chars);
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TISInputSourceWrapper::TranslateToString, err=0x%X, len=%llu",
- this, err, len));
-
- NS_ENSURE_TRUE(err == noErr, false);
- if (len == 0) {
- return true;
- }
- NS_ENSURE_TRUE(EnsureStringLength(aStr, len), false);
- NS_ASSERTION(sizeof(char16_t) == sizeof(UniChar),
- "size of char16_t and size of UniChar are different");
- memcpy(aStr.BeginWriting(), chars, len * sizeof(char16_t));
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TISInputSourceWrapper::TranslateToString, aStr=\"%s\"",
- this, NS_ConvertUTF16toUTF8(aStr).get()));
-
- return true;
-}
-
-uint32_t
-TISInputSourceWrapper::TranslateToChar(UInt32 aKeyCode, UInt32 aModifiers,
- UInt32 aKbType)
-{
- nsAutoString str;
- if (!TranslateToString(aKeyCode, aModifiers, aKbType, str) ||
- str.Length() != 1) {
- return 0;
- }
- return static_cast<uint32_t>(str.CharAt(0));
-}
-
-void
-TISInputSourceWrapper::InitByInputSourceID(const char* aID)
-{
- Clear();
- if (!aID)
- return;
-
- CFStringRef idstr = ::CFStringCreateWithCString(kCFAllocatorDefault, aID,
- kCFStringEncodingASCII);
- InitByInputSourceID(idstr);
- ::CFRelease(idstr);
-}
-
-void
-TISInputSourceWrapper::InitByInputSourceID(const nsAFlatString &aID)
-{
- Clear();
- if (aID.IsEmpty())
- return;
- CFStringRef idstr = ::CFStringCreateWithCharacters(kCFAllocatorDefault,
- reinterpret_cast<const UniChar*>(aID.get()),
- aID.Length());
- InitByInputSourceID(idstr);
- ::CFRelease(idstr);
-}
-
-void
-TISInputSourceWrapper::InitByInputSourceID(const CFStringRef aID)
-{
- Clear();
- if (!aID)
- return;
- const void* keys[] = { kTISPropertyInputSourceID };
- const void* values[] = { aID };
- CFDictionaryRef filter =
- ::CFDictionaryCreate(kCFAllocatorDefault, keys, values, 1, NULL, NULL);
- NS_ASSERTION(filter, "failed to create the filter");
- mInputSourceList = ::TISCreateInputSourceList(filter, true);
- ::CFRelease(filter);
- if (::CFArrayGetCount(mInputSourceList) > 0) {
- mInputSource = static_cast<TISInputSourceRef>(
- const_cast<void *>(::CFArrayGetValueAtIndex(mInputSourceList, 0)));
- if (IsKeyboardLayout()) {
- mKeyboardLayout = mInputSource;
- }
- }
-}
-
-void
-TISInputSourceWrapper::InitByLayoutID(SInt32 aLayoutID,
- bool aOverrideKeyboard)
-{
- // NOTE: Doument new layout IDs in TextInputHandler.h when you add ones.
- switch (aLayoutID) {
- case 0:
- InitByInputSourceID("com.apple.keylayout.US");
- break;
- case 1:
- InitByInputSourceID("com.apple.keylayout.Greek");
- break;
- case 2:
- InitByInputSourceID("com.apple.keylayout.German");
- break;
- case 3:
- InitByInputSourceID("com.apple.keylayout.Swedish-Pro");
- break;
- case 4:
- InitByInputSourceID("com.apple.keylayout.DVORAK-QWERTYCMD");
- break;
- case 5:
- InitByInputSourceID("com.apple.keylayout.Thai");
- break;
- case 6:
- InitByInputSourceID("com.apple.keylayout.Arabic");
- break;
- case 7:
- InitByInputSourceID("com.apple.keylayout.ArabicPC");
- break;
- case 8:
- InitByInputSourceID("com.apple.keylayout.French");
- break;
- case 9:
- InitByInputSourceID("com.apple.keylayout.Hebrew");
- break;
- case 10:
- InitByInputSourceID("com.apple.keylayout.Lithuanian");
- break;
- case 11:
- InitByInputSourceID("com.apple.keylayout.Norwegian");
- break;
- case 12:
- InitByInputSourceID("com.apple.keylayout.Spanish");
- break;
- default:
- Clear();
- break;
- }
- mOverrideKeyboard = aOverrideKeyboard;
-}
-
-void
-TISInputSourceWrapper::InitByCurrentInputSource()
-{
- Clear();
- mInputSource = ::TISCopyCurrentKeyboardInputSource();
- mKeyboardLayout = ::TISCopyInputMethodKeyboardLayoutOverride();
- if (!mKeyboardLayout) {
- mKeyboardLayout = ::TISCopyCurrentKeyboardLayoutInputSource();
- }
- // If this causes composition, the current keyboard layout may input non-ASCII
- // characters such as Japanese Kana characters or Hangul characters.
- // However, we need to set ASCII characters to DOM key events for consistency
- // with other platforms.
- if (IsOpenedIMEMode()) {
- TISInputSourceWrapper tis(mKeyboardLayout);
- if (!tis.IsASCIICapable()) {
- mKeyboardLayout =
- ::TISCopyCurrentASCIICapableKeyboardLayoutInputSource();
- }
- }
-}
-
-void
-TISInputSourceWrapper::InitByCurrentKeyboardLayout()
-{
- Clear();
- mInputSource = ::TISCopyCurrentKeyboardLayoutInputSource();
- mKeyboardLayout = mInputSource;
-}
-
-void
-TISInputSourceWrapper::InitByCurrentASCIICapableInputSource()
-{
- Clear();
- mInputSource = ::TISCopyCurrentASCIICapableKeyboardInputSource();
- mKeyboardLayout = ::TISCopyInputMethodKeyboardLayoutOverride();
- if (mKeyboardLayout) {
- TISInputSourceWrapper tis(mKeyboardLayout);
- if (!tis.IsASCIICapable()) {
- mKeyboardLayout = nullptr;
- }
- }
- if (!mKeyboardLayout) {
- mKeyboardLayout =
- ::TISCopyCurrentASCIICapableKeyboardLayoutInputSource();
- }
-}
-
-void
-TISInputSourceWrapper::InitByCurrentASCIICapableKeyboardLayout()
-{
- Clear();
- mInputSource = ::TISCopyCurrentASCIICapableKeyboardLayoutInputSource();
- mKeyboardLayout = mInputSource;
-}
-
-void
-TISInputSourceWrapper::InitByCurrentInputMethodKeyboardLayoutOverride()
-{
- Clear();
- mInputSource = ::TISCopyInputMethodKeyboardLayoutOverride();
- mKeyboardLayout = mInputSource;
-}
-
-void
-TISInputSourceWrapper::InitByTISInputSourceRef(TISInputSourceRef aInputSource)
-{
- Clear();
- mInputSource = aInputSource;
- if (IsKeyboardLayout()) {
- mKeyboardLayout = mInputSource;
- }
-}
-
-void
-TISInputSourceWrapper::InitByLanguage(CFStringRef aLanguage)
-{
- Clear();
- mInputSource = ::TISCopyInputSourceForLanguage(aLanguage);
- if (IsKeyboardLayout()) {
- mKeyboardLayout = mInputSource;
- }
-}
-
-const UCKeyboardLayout*
-TISInputSourceWrapper::GetUCKeyboardLayout()
-{
- NS_ENSURE_TRUE(mKeyboardLayout, nullptr);
- if (mUCKeyboardLayout) {
- return mUCKeyboardLayout;
- }
- CFDataRef uchr = static_cast<CFDataRef>(
- ::TISGetInputSourceProperty(mKeyboardLayout,
- kTISPropertyUnicodeKeyLayoutData));
-
- // We should be always able to get the layout here.
- NS_ENSURE_TRUE(uchr, nullptr);
- mUCKeyboardLayout =
- reinterpret_cast<const UCKeyboardLayout*>(CFDataGetBytePtr(uchr));
- return mUCKeyboardLayout;
-}
-
-bool
-TISInputSourceWrapper::GetBoolProperty(const CFStringRef aKey)
-{
- CFBooleanRef ret = static_cast<CFBooleanRef>(
- ::TISGetInputSourceProperty(mInputSource, aKey));
- return ::CFBooleanGetValue(ret);
-}
-
-bool
-TISInputSourceWrapper::GetStringProperty(const CFStringRef aKey,
- CFStringRef &aStr)
-{
- aStr = static_cast<CFStringRef>(
- ::TISGetInputSourceProperty(mInputSource, aKey));
- return aStr != nullptr;
-}
-
-bool
-TISInputSourceWrapper::GetStringProperty(const CFStringRef aKey,
- nsAString &aStr)
-{
- CFStringRef str;
- GetStringProperty(aKey, str);
- nsCocoaUtils::GetStringForNSString((const NSString*)str, aStr);
- return !aStr.IsEmpty();
-}
-
-bool
-TISInputSourceWrapper::IsOpenedIMEMode()
-{
- NS_ENSURE_TRUE(mInputSource, false);
- if (!IsIMEMode())
- return false;
- return !IsASCIICapable();
-}
-
-bool
-TISInputSourceWrapper::IsIMEMode()
-{
- NS_ENSURE_TRUE(mInputSource, false);
- CFStringRef str;
- GetInputSourceType(str);
- NS_ENSURE_TRUE(str, false);
- return ::CFStringCompare(kTISTypeKeyboardInputMode,
- str, 0) == kCFCompareEqualTo;
-}
-
-bool
-TISInputSourceWrapper::IsKeyboardLayout()
-{
- NS_ENSURE_TRUE(mInputSource, false);
- CFStringRef str;
- GetInputSourceType(str);
- NS_ENSURE_TRUE(str, false);
- return ::CFStringCompare(kTISTypeKeyboardLayout,
- str, 0) == kCFCompareEqualTo;
-}
-
-bool
-TISInputSourceWrapper::GetLanguageList(CFArrayRef &aLanguageList)
-{
- NS_ENSURE_TRUE(mInputSource, false);
- aLanguageList = static_cast<CFArrayRef>(
- ::TISGetInputSourceProperty(mInputSource,
- kTISPropertyInputSourceLanguages));
- return aLanguageList != nullptr;
-}
-
-bool
-TISInputSourceWrapper::GetPrimaryLanguage(CFStringRef &aPrimaryLanguage)
-{
- NS_ENSURE_TRUE(mInputSource, false);
- CFArrayRef langList;
- NS_ENSURE_TRUE(GetLanguageList(langList), false);
- if (::CFArrayGetCount(langList) == 0)
- return false;
- aPrimaryLanguage =
- static_cast<CFStringRef>(::CFArrayGetValueAtIndex(langList, 0));
- return aPrimaryLanguage != nullptr;
-}
-
-bool
-TISInputSourceWrapper::GetPrimaryLanguage(nsAString &aPrimaryLanguage)
-{
- NS_ENSURE_TRUE(mInputSource, false);
- CFStringRef primaryLanguage;
- NS_ENSURE_TRUE(GetPrimaryLanguage(primaryLanguage), false);
- nsCocoaUtils::GetStringForNSString((const NSString*)primaryLanguage,
- aPrimaryLanguage);
- return !aPrimaryLanguage.IsEmpty();
-}
-
-bool
-TISInputSourceWrapper::IsForRTLLanguage()
-{
- if (mIsRTL < 0) {
- // Get the input character of the 'A' key of ANSI keyboard layout.
- nsAutoString str;
- bool ret = TranslateToString(kVK_ANSI_A, 0, eKbdType_ANSI, str);
- NS_ENSURE_TRUE(ret, ret);
- char16_t ch = str.IsEmpty() ? char16_t(0) : str.CharAt(0);
- mIsRTL = UCS2_CHAR_IS_BIDI(ch);
- }
- return mIsRTL != 0;
-}
-
-bool
-TISInputSourceWrapper::IsInitializedByCurrentInputSource()
-{
- return mInputSource == ::TISCopyCurrentKeyboardInputSource();
-}
-
-void
-TISInputSourceWrapper::Select()
-{
- if (!mInputSource)
- return;
- ::TISSelectInputSource(mInputSource);
-}
-
-void
-TISInputSourceWrapper::Clear()
-{
- // Clear() is always called when TISInputSourceWrappper is created.
- EnsureToLogAllKeyboardLayoutsAndIMEs();
-
- if (mInputSourceList) {
- ::CFRelease(mInputSourceList);
- }
- mInputSourceList = nullptr;
- mInputSource = nullptr;
- mKeyboardLayout = nullptr;
- mIsRTL = -1;
- mUCKeyboardLayout = nullptr;
- mOverrideKeyboard = false;
-}
-
-bool
-TISInputSourceWrapper::IsPrintableKeyEvent(NSEvent* aNativeKeyEvent) const
-{
- UInt32 nativeKeyCode = [aNativeKeyEvent keyCode];
-
- bool isPrintableKey = !TextInputHandler::IsSpecialGeckoKey(nativeKeyCode);
- if (isPrintableKey &&
- [aNativeKeyEvent type] != NSKeyDown &&
- [aNativeKeyEvent type] != NSKeyUp) {
- NS_WARNING("Why the printable key doesn't cause NSKeyDown or NSKeyUp?");
- isPrintableKey = false;
- }
- return isPrintableKey;
-}
-
-UInt32
-TISInputSourceWrapper::GetKbdType() const
-{
- // If a keyboard layout override is set, we also need to force the keyboard
- // type to something ANSI to avoid test failures on machines with JIS
- // keyboards (since the pair of keyboard layout and physical keyboard type
- // form the actual key layout). This assumes that the test setting the
- // override was written assuming an ANSI keyboard.
- return mOverrideKeyboard ? eKbdType_ANSI : ::LMGetKbdType();
-}
-
-void
-TISInputSourceWrapper::ComputeInsertStringForCharCode(
- NSEvent* aNativeKeyEvent,
- const WidgetKeyboardEvent& aKeyEvent,
- const nsAString* aInsertString,
- nsAString& aResult)
-{
- if (aInsertString) {
- // If the caller expects that the aInsertString will be input, we shouldn't
- // change it.
- aResult = *aInsertString;
- } else if (IsPrintableKeyEvent(aNativeKeyEvent)) {
- // If IME is open, [aNativeKeyEvent characters] may be a character
- // which will be appended to the composition string. However, especially,
- // while IME is disabled, most users and developers expect the key event
- // works as IME closed. So, we should compute the aResult with
- // the ASCII capable keyboard layout.
- // NOTE: Such keyboard layouts typically change the layout to its ASCII
- // capable layout when Command key is pressed. And we don't worry
- // when Control key is pressed too because it causes inputting
- // control characters.
- // Additionally, if the key event doesn't input any text, the event may be
- // dead key event. In this case, the charCode value should be the dead
- // character.
- UInt32 nativeKeyCode = [aNativeKeyEvent keyCode];
- if ((!aKeyEvent.IsMeta() && !aKeyEvent.IsControl() && IsOpenedIMEMode()) ||
- ![[aNativeKeyEvent characters] length]) {
- UInt32 state =
- nsCocoaUtils::ConvertToCarbonModifier([aNativeKeyEvent modifierFlags]);
- uint32_t ch = TranslateToChar(nativeKeyCode, state, GetKbdType());
- if (ch) {
- aResult = ch;
- }
- } else {
- // If the caller isn't sure what string will be input, let's use
- // characters of NSEvent.
- nsCocoaUtils::GetStringForNSString([aNativeKeyEvent characters], aResult);
- }
-
- // If control key is pressed and the eventChars is a non-printable control
- // character, we should convert it to ASCII alphabet.
- if (aKeyEvent.IsControl() &&
- !aResult.IsEmpty() && aResult[0] <= char16_t(26)) {
- aResult = (aKeyEvent.IsShift() ^ aKeyEvent.IsCapsLocked()) ?
- static_cast<char16_t>(aResult[0] + ('A' - 1)) :
- static_cast<char16_t>(aResult[0] + ('a' - 1));
- }
- // If Meta key is pressed, it may cause to switch the keyboard layout like
- // Arabic, Russian, Hebrew, Greek and Dvorak-QWERTY.
- else if (aKeyEvent.IsMeta() &&
- !(aKeyEvent.IsControl() || aKeyEvent.IsAlt())) {
- UInt32 kbType = GetKbdType();
- UInt32 numLockState =
- aKeyEvent.IsNumLocked() ? kEventKeyModifierNumLockMask : 0;
- UInt32 capsLockState = aKeyEvent.IsCapsLocked() ? alphaLock : 0;
- UInt32 shiftState = aKeyEvent.IsShift() ? shiftKey : 0;
- uint32_t uncmdedChar =
- TranslateToChar(nativeKeyCode, numLockState, kbType);
- uint32_t cmdedChar =
- TranslateToChar(nativeKeyCode, cmdKey | numLockState, kbType);
- // If we can make a good guess at the characters that the user would
- // expect this key combination to produce (with and without Shift) then
- // use those characters. This also corrects for CapsLock.
- uint32_t ch = 0;
- if (uncmdedChar == cmdedChar) {
- // The characters produced with Command seem similar to those without
- // Command.
- ch = TranslateToChar(nativeKeyCode,
- shiftState | capsLockState | numLockState, kbType);
- } else {
- TISInputSourceWrapper USLayout("com.apple.keylayout.US");
- uint32_t uncmdedUSChar =
- USLayout.TranslateToChar(nativeKeyCode, numLockState, kbType);
- // If it looks like characters from US keyboard layout when Command key
- // is pressed, we should compute a character in the layout.
- if (uncmdedUSChar == cmdedChar) {
- ch = USLayout.TranslateToChar(nativeKeyCode,
- shiftState | capsLockState | numLockState, kbType);
- }
- }
-
- // If there is a more preferred character for the commanded key event,
- // we should use it.
- if (ch) {
- aResult = ch;
- }
- }
- }
-
- // Remove control characters which shouldn't be inputted on editor.
- // XXX Currently, we don't find any cases inserting control characters with
- // printable character. So, just checking first character is enough.
- if (!aResult.IsEmpty() && IsControlChar(aResult[0])) {
- aResult.Truncate();
- }
-}
-
-void
-TISInputSourceWrapper::InitKeyEvent(NSEvent *aNativeKeyEvent,
- WidgetKeyboardEvent& aKeyEvent,
- const nsAString *aInsertString)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TISInputSourceWrapper::InitKeyEvent, aNativeKeyEvent=%p, "
- "aKeyEvent.mMessage=%s, aInsertString=%p, IsOpenedIMEMode()=%s",
- this, aNativeKeyEvent, GetGeckoKeyEventType(aKeyEvent), aInsertString,
- TrueOrFalse(IsOpenedIMEMode())));
-
- NS_ENSURE_TRUE(aNativeKeyEvent, );
-
- nsCocoaUtils::InitInputEvent(aKeyEvent, aNativeKeyEvent);
-
- // This is used only while dispatching the event (which is a synchronous
- // call), so there is no need to retain and release this data.
- aKeyEvent.mNativeKeyEvent = aNativeKeyEvent;
-
- // Fill in fields used for Cocoa NPAPI plugins
- if ([aNativeKeyEvent type] == NSKeyDown ||
- [aNativeKeyEvent type] == NSKeyUp) {
- aKeyEvent.mNativeKeyCode = [aNativeKeyEvent keyCode];
- aKeyEvent.mNativeModifierFlags = [aNativeKeyEvent modifierFlags];
- nsAutoString nativeChars;
- nsCocoaUtils::GetStringForNSString([aNativeKeyEvent characters], nativeChars);
- aKeyEvent.mNativeCharacters.Assign(nativeChars);
- nsAutoString nativeCharsIgnoringModifiers;
- nsCocoaUtils::GetStringForNSString([aNativeKeyEvent charactersIgnoringModifiers], nativeCharsIgnoringModifiers);
- aKeyEvent.mNativeCharactersIgnoringModifiers.Assign(nativeCharsIgnoringModifiers);
- } else if ([aNativeKeyEvent type] == NSFlagsChanged) {
- aKeyEvent.mNativeKeyCode = [aNativeKeyEvent keyCode];
- aKeyEvent.mNativeModifierFlags = [aNativeKeyEvent modifierFlags];
- }
-
- aKeyEvent.mRefPoint = LayoutDeviceIntPoint(0, 0);
- aKeyEvent.mIsChar = false; // XXX not used in XP level
-
- UInt32 kbType = GetKbdType();
- UInt32 nativeKeyCode = [aNativeKeyEvent keyCode];
-
- aKeyEvent.mKeyCode =
- ComputeGeckoKeyCode(nativeKeyCode, kbType, aKeyEvent.IsMeta());
-
- switch (nativeKeyCode) {
- case kVK_Command:
- case kVK_Shift:
- case kVK_Option:
- case kVK_Control:
- aKeyEvent.mLocation = nsIDOMKeyEvent::DOM_KEY_LOCATION_LEFT;
- break;
-
- case kVK_RightCommand:
- case kVK_RightShift:
- case kVK_RightOption:
- case kVK_RightControl:
- aKeyEvent.mLocation = nsIDOMKeyEvent::DOM_KEY_LOCATION_RIGHT;
- break;
-
- case kVK_ANSI_Keypad0:
- case kVK_ANSI_Keypad1:
- case kVK_ANSI_Keypad2:
- case kVK_ANSI_Keypad3:
- case kVK_ANSI_Keypad4:
- case kVK_ANSI_Keypad5:
- case kVK_ANSI_Keypad6:
- case kVK_ANSI_Keypad7:
- case kVK_ANSI_Keypad8:
- case kVK_ANSI_Keypad9:
- case kVK_ANSI_KeypadMultiply:
- case kVK_ANSI_KeypadPlus:
- case kVK_ANSI_KeypadMinus:
- case kVK_ANSI_KeypadDecimal:
- case kVK_ANSI_KeypadDivide:
- case kVK_ANSI_KeypadEquals:
- case kVK_ANSI_KeypadEnter:
- case kVK_JIS_KeypadComma:
- case kVK_Powerbook_KeypadEnter:
- aKeyEvent.mLocation = nsIDOMKeyEvent::DOM_KEY_LOCATION_NUMPAD;
- break;
-
- default:
- aKeyEvent.mLocation = nsIDOMKeyEvent::DOM_KEY_LOCATION_STANDARD;
- break;
- }
-
- aKeyEvent.mIsRepeat =
- ([aNativeKeyEvent type] == NSKeyDown) ? [aNativeKeyEvent isARepeat] : false;
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TISInputSourceWrapper::InitKeyEvent, "
- "shift=%s, ctrl=%s, alt=%s, meta=%s",
- this, OnOrOff(aKeyEvent.IsShift()), OnOrOff(aKeyEvent.IsControl()),
- OnOrOff(aKeyEvent.IsAlt()), OnOrOff(aKeyEvent.IsMeta())));
-
- if (IsPrintableKeyEvent(aNativeKeyEvent)) {
- aKeyEvent.mKeyNameIndex = KEY_NAME_INDEX_USE_STRING;
- // If insertText calls this method, let's use the string.
- if (aInsertString && !aInsertString->IsEmpty() &&
- !IsControlChar((*aInsertString)[0])) {
- aKeyEvent.mKeyValue = *aInsertString;
- }
- // If meta key is pressed, the printable key layout may be switched from
- // non-ASCII capable layout to ASCII capable, or from Dvorak to QWERTY.
- // KeyboardEvent.key value should be the switched layout's character.
- else if (aKeyEvent.IsMeta()) {
- nsCocoaUtils::GetStringForNSString([aNativeKeyEvent characters],
- aKeyEvent.mKeyValue);
- }
- // If control key is pressed, some keys may produce printable character via
- // [aNativeKeyEvent characters]. Otherwise, translate input character of
- // the key without control key.
- else if (aKeyEvent.IsControl()) {
- nsCocoaUtils::GetStringForNSString([aNativeKeyEvent characters],
- aKeyEvent.mKeyValue);
- if (aKeyEvent.mKeyValue.IsEmpty() ||
- IsControlChar(aKeyEvent.mKeyValue[0])) {
- NSUInteger cocoaState =
- [aNativeKeyEvent modifierFlags] & ~NSControlKeyMask;
- UInt32 carbonState = nsCocoaUtils::ConvertToCarbonModifier(cocoaState);
- aKeyEvent.mKeyValue =
- TranslateToChar(nativeKeyCode, carbonState, kbType);
- }
- }
- // Otherwise, KeyboardEvent.key expose
- // [aNativeKeyEvent characters] value. However, if IME is open and the
- // keyboard layout isn't ASCII capable, exposing the non-ASCII character
- // doesn't match with other platform's behavior. For the compatibility
- // with other platform's Gecko, we need to set a translated character.
- else if (IsOpenedIMEMode()) {
- UInt32 state =
- nsCocoaUtils::ConvertToCarbonModifier([aNativeKeyEvent modifierFlags]);
- aKeyEvent.mKeyValue = TranslateToChar(nativeKeyCode, state, kbType);
- } else {
- nsCocoaUtils::GetStringForNSString([aNativeKeyEvent characters],
- aKeyEvent.mKeyValue);
- // If the key value is empty, the event may be a dead key event.
- // If TranslateToChar() returns non-zero value, that means that
- // the key may input a character with different dead key state.
- if (aKeyEvent.mKeyValue.IsEmpty()) {
- NSUInteger cocoaState = [aNativeKeyEvent modifierFlags];
- UInt32 carbonState = nsCocoaUtils::ConvertToCarbonModifier(cocoaState);
- if (TranslateToChar(nativeKeyCode, carbonState, kbType)) {
- aKeyEvent.mKeyNameIndex = KEY_NAME_INDEX_Dead;
- }
- }
- }
-
- // Last resort. If .key value becomes empty string, we should use
- // charactersIgnoringModifiers, if it's available.
- if (aKeyEvent.mKeyNameIndex == KEY_NAME_INDEX_USE_STRING &&
- (aKeyEvent.mKeyValue.IsEmpty() ||
- IsControlChar(aKeyEvent.mKeyValue[0]))) {
- nsCocoaUtils::GetStringForNSString(
- [aNativeKeyEvent charactersIgnoringModifiers], aKeyEvent.mKeyValue);
- // But don't expose it if it's a control character.
- if (!aKeyEvent.mKeyValue.IsEmpty() &&
- IsControlChar(aKeyEvent.mKeyValue[0])) {
- aKeyEvent.mKeyValue.Truncate();
- }
- }
- } else {
- // Compute the key for non-printable keys and some special printable keys.
- aKeyEvent.mKeyNameIndex = ComputeGeckoKeyNameIndex(nativeKeyCode);
- }
-
- aKeyEvent.mCodeNameIndex = ComputeGeckoCodeNameIndex(nativeKeyCode);
- MOZ_ASSERT(aKeyEvent.mCodeNameIndex != CODE_NAME_INDEX_USE_STRING);
-
- NS_OBJC_END_TRY_ABORT_BLOCK
-}
-
-void
-TISInputSourceWrapper::WillDispatchKeyboardEvent(
- NSEvent* aNativeKeyEvent,
- const nsAString* aInsertString,
- WidgetKeyboardEvent& aKeyEvent)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- // Nothing to do here if the native key event is neither NSKeyDown nor
- // NSKeyUp because accessing [aNativeKeyEvent characters] causes throwing
- // an exception.
- if ([aNativeKeyEvent type] != NSKeyDown &&
- [aNativeKeyEvent type] != NSKeyUp) {
- return;
- }
-
- UInt32 kbType = GetKbdType();
-
- if (MOZ_LOG_TEST(gLog, LogLevel::Info)) {
- nsAutoString chars;
- nsCocoaUtils::GetStringForNSString([aNativeKeyEvent characters], chars);
- NS_ConvertUTF16toUTF8 utf8Chars(chars);
- char16_t uniChar = static_cast<char16_t>(aKeyEvent.mCharCode);
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TISInputSourceWrapper::WillDispatchKeyboardEvent, "
- "aNativeKeyEvent=%p, [aNativeKeyEvent characters]=\"%s\", "
- "aKeyEvent={ mMessage=%s, mCharCode=0x%X(%s) }, kbType=0x%X, "
- "IsOpenedIMEMode()=%s",
- this, aNativeKeyEvent, utf8Chars.get(),
- GetGeckoKeyEventType(aKeyEvent), aKeyEvent.mCharCode,
- uniChar ? NS_ConvertUTF16toUTF8(&uniChar, 1).get() : "",
- kbType, TrueOrFalse(IsOpenedIMEMode())));
- }
-
- nsAutoString insertStringForCharCode;
- ComputeInsertStringForCharCode(aNativeKeyEvent, aKeyEvent, aInsertString,
- insertStringForCharCode);
-
- // The mCharCode was set from mKeyValue. However, for example, when Ctrl key
- // is pressed, its value should indicate an ASCII character for backward
- // compatibility rather than inputting character without the modifiers.
- // Therefore, we need to modify mCharCode value here.
- uint32_t charCode =
- insertStringForCharCode.IsEmpty() ? 0 : insertStringForCharCode[0];
- aKeyEvent.SetCharCode(charCode);
- // this is not a special key XXX not used in XP
- aKeyEvent.mIsChar = (aKeyEvent.mMessage == eKeyPress);
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TISInputSourceWrapper::WillDispatchKeyboardEvent, "
- "aKeyEvent.mKeyCode=0x%X, aKeyEvent.mCharCode=0x%X",
- this, aKeyEvent.mKeyCode, aKeyEvent.mCharCode));
-
- TISInputSourceWrapper USLayout("com.apple.keylayout.US");
- bool isRomanKeyboardLayout = IsASCIICapable();
-
- UInt32 key = [aNativeKeyEvent keyCode];
-
- // Caps lock and num lock modifier state:
- UInt32 lockState = 0;
- if ([aNativeKeyEvent modifierFlags] & NSAlphaShiftKeyMask) {
- lockState |= alphaLock;
- }
- if ([aNativeKeyEvent modifierFlags] & NSNumericPadKeyMask) {
- lockState |= kEventKeyModifierNumLockMask;
- }
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TISInputSourceWrapper::WillDispatchKeyboardEvent, "
- "isRomanKeyboardLayout=%s, key=0x%X",
- this, TrueOrFalse(isRomanKeyboardLayout), kbType, key));
-
- nsString str;
-
- // normal chars
- uint32_t unshiftedChar = TranslateToChar(key, lockState, kbType);
- UInt32 shiftLockMod = shiftKey | lockState;
- uint32_t shiftedChar = TranslateToChar(key, shiftLockMod, kbType);
-
- // characters generated with Cmd key
- // XXX we should remove CapsLock state, which changes characters from
- // Latin to Cyrillic with Russian layout on 10.4 only when Cmd key
- // is pressed.
- UInt32 numState = (lockState & ~alphaLock); // only num lock state
- uint32_t uncmdedChar = TranslateToChar(key, numState, kbType);
- UInt32 shiftNumMod = numState | shiftKey;
- uint32_t uncmdedShiftChar = TranslateToChar(key, shiftNumMod, kbType);
- uint32_t uncmdedUSChar = USLayout.TranslateToChar(key, numState, kbType);
- UInt32 cmdNumMod = cmdKey | numState;
- uint32_t cmdedChar = TranslateToChar(key, cmdNumMod, kbType);
- UInt32 cmdShiftNumMod = shiftKey | cmdNumMod;
- uint32_t cmdedShiftChar = TranslateToChar(key, cmdShiftNumMod, kbType);
-
- // Is the keyboard layout changed by Cmd key?
- // E.g., Arabic, Russian, Hebrew, Greek and Dvorak-QWERTY.
- bool isCmdSwitchLayout = uncmdedChar != cmdedChar;
- // Is the keyboard layout for Latin, but Cmd key switches the layout?
- // I.e., Dvorak-QWERTY
- bool isDvorakQWERTY = isCmdSwitchLayout && isRomanKeyboardLayout;
-
- // If the current keyboard is not Dvorak-QWERTY or Cmd is not pressed,
- // we should append unshiftedChar and shiftedChar for handling the
- // normal characters. These are the characters that the user is most
- // likely to associate with this key.
- if ((unshiftedChar || shiftedChar) &&
- (!aKeyEvent.IsMeta() || !isDvorakQWERTY)) {
- AlternativeCharCode altCharCodes(unshiftedChar, shiftedChar);
- aKeyEvent.mAlternativeCharCodes.AppendElement(altCharCodes);
- }
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TISInputSourceWrapper::WillDispatchKeyboardEvent, "
- "aKeyEvent.isMeta=%s, isDvorakQWERTY=%s, "
- "unshiftedChar=U+%X, shiftedChar=U+%X",
- this, OnOrOff(aKeyEvent.IsMeta()), TrueOrFalse(isDvorakQWERTY),
- unshiftedChar, shiftedChar));
-
- // Most keyboard layouts provide the same characters in the NSEvents
- // with Command+Shift as with Command. However, with Command+Shift we
- // want the character on the second level. e.g. With a US QWERTY
- // layout, we want "?" when the "/","?" key is pressed with
- // Command+Shift.
-
- // On a German layout, the OS gives us '/' with Cmd+Shift+SS(eszett)
- // even though Cmd+SS is 'SS' and Shift+'SS' is '?'. This '/' seems
- // like a hack to make the Cmd+"?" event look the same as the Cmd+"?"
- // event on a US keyboard. The user thinks they are typing Cmd+"?", so
- // we'll prefer the "?" character, replacing mCharCode with shiftedChar
- // when Shift is pressed. However, in case there is a layout where the
- // character unique to Cmd+Shift is the character that the user expects,
- // we'll send it as an alternative char.
- bool hasCmdShiftOnlyChar =
- cmdedChar != cmdedShiftChar && uncmdedShiftChar != cmdedShiftChar;
- uint32_t originalCmdedShiftChar = cmdedShiftChar;
-
- // If we can make a good guess at the characters that the user would
- // expect this key combination to produce (with and without Shift) then
- // use those characters. This also corrects for CapsLock, which was
- // ignored above.
- if (!isCmdSwitchLayout) {
- // The characters produced with Command seem similar to those without
- // Command.
- if (unshiftedChar) {
- cmdedChar = unshiftedChar;
- }
- if (shiftedChar) {
- cmdedShiftChar = shiftedChar;
- }
- } else if (uncmdedUSChar == cmdedChar) {
- // It looks like characters from a US layout are provided when Command
- // is down.
- uint32_t ch = USLayout.TranslateToChar(key, lockState, kbType);
- if (ch) {
- cmdedChar = ch;
- }
- ch = USLayout.TranslateToChar(key, shiftLockMod, kbType);
- if (ch) {
- cmdedShiftChar = ch;
- }
- }
-
- // If the current keyboard layout is switched by the Cmd key,
- // we should append cmdedChar and shiftedCmdChar that are
- // Latin char for the key.
- // If the keyboard layout is Dvorak-QWERTY, we should append them only when
- // command key is pressed because when command key isn't pressed, uncmded
- // chars have been appended already.
- if ((cmdedChar || cmdedShiftChar) && isCmdSwitchLayout &&
- (aKeyEvent.IsMeta() || !isDvorakQWERTY)) {
- AlternativeCharCode altCharCodes(cmdedChar, cmdedShiftChar);
- aKeyEvent.mAlternativeCharCodes.AppendElement(altCharCodes);
- }
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TISInputSourceWrapper::WillDispatchKeyboardEvent, "
- "hasCmdShiftOnlyChar=%s, isCmdSwitchLayout=%s, isDvorakQWERTY=%s, "
- "cmdedChar=U+%X, cmdedShiftChar=U+%X",
- this, TrueOrFalse(hasCmdShiftOnlyChar), TrueOrFalse(isDvorakQWERTY),
- TrueOrFalse(isDvorakQWERTY), cmdedChar, cmdedShiftChar));
- // Special case for 'SS' key of German layout. See the comment of
- // hasCmdShiftOnlyChar definition for the detail.
- if (hasCmdShiftOnlyChar && originalCmdedShiftChar) {
- AlternativeCharCode altCharCodes(0, originalCmdedShiftChar);
- aKeyEvent.mAlternativeCharCodes.AppendElement(altCharCodes);
- }
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TISInputSourceWrapper::WillDispatchKeyboardEvent, "
- "hasCmdShiftOnlyChar=%s, originalCmdedShiftChar=U+%X",
- this, TrueOrFalse(hasCmdShiftOnlyChar), originalCmdedShiftChar));
-
- NS_OBJC_END_TRY_ABORT_BLOCK
-}
-
-uint32_t
-TISInputSourceWrapper::ComputeGeckoKeyCode(UInt32 aNativeKeyCode,
- UInt32 aKbType,
- bool aCmdIsPressed)
-{
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TISInputSourceWrapper::ComputeGeckoKeyCode, aNativeKeyCode=0x%X, "
- "aKbType=0x%X, aCmdIsPressed=%s, IsOpenedIMEMode()=%s, "
- "IsASCIICapable()=%s",
- this, aNativeKeyCode, aKbType, TrueOrFalse(aCmdIsPressed),
- TrueOrFalse(IsOpenedIMEMode()), TrueOrFalse(IsASCIICapable())));
-
- switch (aNativeKeyCode) {
- case kVK_Space: return NS_VK_SPACE;
- case kVK_Escape: return NS_VK_ESCAPE;
-
- // modifiers
- case kVK_RightCommand:
- case kVK_Command: return NS_VK_META;
- case kVK_RightShift:
- case kVK_Shift: return NS_VK_SHIFT;
- case kVK_CapsLock: return NS_VK_CAPS_LOCK;
- case kVK_RightControl:
- case kVK_Control: return NS_VK_CONTROL;
- case kVK_RightOption:
- case kVK_Option: return NS_VK_ALT;
-
- case kVK_ANSI_KeypadClear: return NS_VK_CLEAR;
-
- // function keys
- case kVK_F1: return NS_VK_F1;
- case kVK_F2: return NS_VK_F2;
- case kVK_F3: return NS_VK_F3;
- case kVK_F4: return NS_VK_F4;
- case kVK_F5: return NS_VK_F5;
- case kVK_F6: return NS_VK_F6;
- case kVK_F7: return NS_VK_F7;
- case kVK_F8: return NS_VK_F8;
- case kVK_F9: return NS_VK_F9;
- case kVK_F10: return NS_VK_F10;
- case kVK_F11: return NS_VK_F11;
- case kVK_F12: return NS_VK_F12;
- // case kVK_F13: return NS_VK_F13; // clash with the 3 below
- // case kVK_F14: return NS_VK_F14;
- // case kVK_F15: return NS_VK_F15;
- case kVK_F16: return NS_VK_F16;
- case kVK_F17: return NS_VK_F17;
- case kVK_F18: return NS_VK_F18;
- case kVK_F19: return NS_VK_F19;
-
- case kVK_PC_Pause: return NS_VK_PAUSE;
- case kVK_PC_ScrollLock: return NS_VK_SCROLL_LOCK;
- case kVK_PC_PrintScreen: return NS_VK_PRINTSCREEN;
-
- // keypad
- case kVK_ANSI_Keypad0: return NS_VK_NUMPAD0;
- case kVK_ANSI_Keypad1: return NS_VK_NUMPAD1;
- case kVK_ANSI_Keypad2: return NS_VK_NUMPAD2;
- case kVK_ANSI_Keypad3: return NS_VK_NUMPAD3;
- case kVK_ANSI_Keypad4: return NS_VK_NUMPAD4;
- case kVK_ANSI_Keypad5: return NS_VK_NUMPAD5;
- case kVK_ANSI_Keypad6: return NS_VK_NUMPAD6;
- case kVK_ANSI_Keypad7: return NS_VK_NUMPAD7;
- case kVK_ANSI_Keypad8: return NS_VK_NUMPAD8;
- case kVK_ANSI_Keypad9: return NS_VK_NUMPAD9;
-
- case kVK_ANSI_KeypadMultiply: return NS_VK_MULTIPLY;
- case kVK_ANSI_KeypadPlus: return NS_VK_ADD;
- case kVK_ANSI_KeypadMinus: return NS_VK_SUBTRACT;
- case kVK_ANSI_KeypadDecimal: return NS_VK_DECIMAL;
- case kVK_ANSI_KeypadDivide: return NS_VK_DIVIDE;
-
- case kVK_JIS_KeypadComma: return NS_VK_SEPARATOR;
-
- // IME keys
- case kVK_JIS_Eisu: return NS_VK_EISU;
- case kVK_JIS_Kana: return NS_VK_KANA;
-
- // these may clash with forward delete and help
- case kVK_PC_Insert: return NS_VK_INSERT;
- case kVK_PC_Delete: return NS_VK_DELETE;
-
- case kVK_PC_Backspace: return NS_VK_BACK;
- case kVK_Tab: return NS_VK_TAB;
-
- case kVK_Home: return NS_VK_HOME;
- case kVK_End: return NS_VK_END;
-
- case kVK_PageUp: return NS_VK_PAGE_UP;
- case kVK_PageDown: return NS_VK_PAGE_DOWN;
-
- case kVK_LeftArrow: return NS_VK_LEFT;
- case kVK_RightArrow: return NS_VK_RIGHT;
- case kVK_UpArrow: return NS_VK_UP;
- case kVK_DownArrow: return NS_VK_DOWN;
-
- case kVK_PC_ContextMenu: return NS_VK_CONTEXT_MENU;
-
- case kVK_ANSI_1: return NS_VK_1;
- case kVK_ANSI_2: return NS_VK_2;
- case kVK_ANSI_3: return NS_VK_3;
- case kVK_ANSI_4: return NS_VK_4;
- case kVK_ANSI_5: return NS_VK_5;
- case kVK_ANSI_6: return NS_VK_6;
- case kVK_ANSI_7: return NS_VK_7;
- case kVK_ANSI_8: return NS_VK_8;
- case kVK_ANSI_9: return NS_VK_9;
- case kVK_ANSI_0: return NS_VK_0;
-
- case kVK_ANSI_KeypadEnter:
- case kVK_Return:
- case kVK_Powerbook_KeypadEnter: return NS_VK_RETURN;
- }
-
- // If Cmd key is pressed, that causes switching keyboard layout temporarily.
- // E.g., Dvorak-QWERTY. Therefore, if Cmd key is pressed, we should honor it.
- UInt32 modifiers = aCmdIsPressed ? cmdKey : 0;
-
- uint32_t charCode = TranslateToChar(aNativeKeyCode, modifiers, aKbType);
-
- // Special case for Mac. Mac inputs Yen sign (U+00A5) directly instead of
- // Back slash (U+005C). We should return NS_VK_BACK_SLASH for compatibility
- // with other platforms.
- // XXX How about Won sign (U+20A9) which has same problem as Yen sign?
- if (charCode == 0x00A5) {
- return NS_VK_BACK_SLASH;
- }
-
- uint32_t keyCode = WidgetUtils::ComputeKeyCodeFromChar(charCode);
- if (keyCode) {
- return keyCode;
- }
-
- // If the unshifed char isn't an ASCII character, use shifted char.
- charCode = TranslateToChar(aNativeKeyCode, modifiers | shiftKey, aKbType);
- keyCode = WidgetUtils::ComputeKeyCodeFromChar(charCode);
- if (keyCode) {
- return keyCode;
- }
-
- // If this is ASCII capable, give up to compute it.
- if (IsASCIICapable()) {
- return 0;
- }
-
- // Retry with ASCII capable keyboard layout.
- TISInputSourceWrapper currentKeyboardLayout;
- currentKeyboardLayout.InitByCurrentASCIICapableKeyboardLayout();
- NS_ENSURE_TRUE(mInputSource != currentKeyboardLayout.mInputSource, 0);
- keyCode = currentKeyboardLayout.ComputeGeckoKeyCode(aNativeKeyCode, aKbType,
- aCmdIsPressed);
-
- // However, if keyCode isn't for an alphabet keys or a numeric key, we should
- // ignore it. For example, comma key of Thai layout is same as close-square-
- // bracket key of US layout and an unicode character key of Thai layout is
- // same as comma key of US layout. If we return NS_VK_COMMA for latter key,
- // web application developers cannot distinguish with the former key.
- return ((keyCode >= NS_VK_A && keyCode <= NS_VK_Z) ||
- (keyCode >= NS_VK_0 && keyCode <= NS_VK_9)) ? keyCode : 0;
-}
-
-// static
-KeyNameIndex
-TISInputSourceWrapper::ComputeGeckoKeyNameIndex(UInt32 aNativeKeyCode)
-{
- // NOTE:
- // When unsupported keys like Convert, Nonconvert of Japanese keyboard is
- // pressed:
- // on 10.6.x, 'A' key event is fired (and also actually 'a' is inserted).
- // on 10.7.x, Nothing happens.
- // on 10.8.x, Nothing happens.
- // on 10.9.x, FlagsChanged event is fired with keyCode 0xFF.
- switch (aNativeKeyCode) {
-
-#define NS_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX(aNativeKey, aKeyNameIndex) \
- case aNativeKey: return aKeyNameIndex;
-
-#include "NativeKeyToDOMKeyName.h"
-
-#undef NS_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX
-
- default:
- return KEY_NAME_INDEX_Unidentified;
- }
-}
-
-// static
-CodeNameIndex
-TISInputSourceWrapper::ComputeGeckoCodeNameIndex(UInt32 aNativeKeyCode)
-{
- switch (aNativeKeyCode) {
-
-#define NS_NATIVE_KEY_TO_DOM_CODE_NAME_INDEX(aNativeKey, aCodeNameIndex) \
- case aNativeKey: return aCodeNameIndex;
-
-#include "NativeKeyToDOMCodeName.h"
-
-#undef NS_NATIVE_KEY_TO_DOM_CODE_NAME_INDEX
-
- default:
- return CODE_NAME_INDEX_UNKNOWN;
- }
-}
-
-
-#pragma mark -
-
-
-/******************************************************************************
- *
- * TextInputHandler implementation (static methods)
- *
- ******************************************************************************/
-
-NSUInteger TextInputHandler::sLastModifierState = 0;
-
-// static
-CFArrayRef
-TextInputHandler::CreateAllKeyboardLayoutList()
-{
- const void* keys[] = { kTISPropertyInputSourceType };
- const void* values[] = { kTISTypeKeyboardLayout };
- CFDictionaryRef filter =
- ::CFDictionaryCreate(kCFAllocatorDefault, keys, values, 1, NULL, NULL);
- NS_ASSERTION(filter, "failed to create the filter");
- CFArrayRef list = ::TISCreateInputSourceList(filter, true);
- ::CFRelease(filter);
- return list;
-}
-
-// static
-void
-TextInputHandler::DebugPrintAllKeyboardLayouts()
-{
- if (MOZ_LOG_TEST(gLog, LogLevel::Info)) {
- CFArrayRef list = CreateAllKeyboardLayoutList();
- MOZ_LOG(gLog, LogLevel::Info, ("Keyboard layout configuration:"));
- CFIndex idx = ::CFArrayGetCount(list);
- TISInputSourceWrapper tis;
- for (CFIndex i = 0; i < idx; ++i) {
- TISInputSourceRef inputSource = static_cast<TISInputSourceRef>(
- const_cast<void *>(::CFArrayGetValueAtIndex(list, i)));
- tis.InitByTISInputSourceRef(inputSource);
- nsAutoString name, isid;
- tis.GetLocalizedName(name);
- tis.GetInputSourceID(isid);
- MOZ_LOG(gLog, LogLevel::Info,
- (" %s\t<%s>%s%s\n",
- NS_ConvertUTF16toUTF8(name).get(),
- NS_ConvertUTF16toUTF8(isid).get(),
- tis.IsASCIICapable() ? "" : "\t(Isn't ASCII capable)",
- tis.IsKeyboardLayout() && tis.GetUCKeyboardLayout() ?
- "" : "\t(uchr is NOT AVAILABLE)"));
- }
- ::CFRelease(list);
- }
-}
-
-
-#pragma mark -
-
-
-/******************************************************************************
- *
- * TextInputHandler implementation
- *
- ******************************************************************************/
-
-TextInputHandler::TextInputHandler(nsChildView* aWidget,
- NSView<mozView> *aNativeView) :
- IMEInputHandler(aWidget, aNativeView)
-{
- EnsureToLogAllKeyboardLayoutsAndIMEs();
- [mView installTextInputHandler:this];
-}
-
-TextInputHandler::~TextInputHandler()
-{
- [mView uninstallTextInputHandler];
-}
-
-bool
-TextInputHandler::HandleKeyDownEvent(NSEvent* aNativeEvent)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
-
- if (Destroyed()) {
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TextInputHandler::HandleKeyDownEvent, "
- "widget has been already destroyed", this));
- return false;
- }
-
- // Insert empty line to the log for easier to read.
- MOZ_LOG(gLog, LogLevel::Info, (""));
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TextInputHandler::HandleKeyDownEvent, aNativeEvent=%p, "
- "type=%s, keyCode=%lld (0x%X), modifierFlags=0x%X, characters=\"%s\", "
- "charactersIgnoringModifiers=\"%s\"",
- this, aNativeEvent, GetNativeKeyEventType(aNativeEvent),
- [aNativeEvent keyCode], [aNativeEvent keyCode],
- [aNativeEvent modifierFlags], GetCharacters([aNativeEvent characters]),
- GetCharacters([aNativeEvent charactersIgnoringModifiers])));
-
- // Except when Command key is pressed, we should hide mouse cursor until
- // next mousemove. Handling here means that:
- // - Don't hide mouse cursor at pressing modifier key
- // - Hide mouse cursor even if the key event will be handled by IME (i.e.,
- // even without dispatching eKeyPress events)
- // - Hide mouse cursor even when a plugin has focus
- if (!([aNativeEvent modifierFlags] & NSCommandKeyMask)) {
- [NSCursor setHiddenUntilMouseMoves:YES];
- }
-
- RefPtr<nsChildView> widget(mWidget);
-
- KeyEventState* currentKeyEvent = PushKeyEvent(aNativeEvent);
- AutoKeyEventStateCleaner remover(this);
-
- ComplexTextInputPanel* ctiPanel = ComplexTextInputPanel::GetSharedComplexTextInputPanel();
- if (ctiPanel && ctiPanel->IsInComposition()) {
- nsAutoString committed;
- ctiPanel->InterpretKeyEvent(aNativeEvent, committed);
- if (!committed.IsEmpty()) {
- nsresult rv = mDispatcher->BeginNativeInputTransaction();
- if (NS_WARN_IF(NS_FAILED(rv))) {
- MOZ_LOG(gLog, LogLevel::Error,
- ("%p IMEInputHandler::HandleKeyDownEvent, "
- "FAILED, due to BeginNativeInputTransaction() failure "
- "at dispatching keydown for ComplexTextInputPanel", this));
- return false;
- }
-
- WidgetKeyboardEvent imeEvent(true, eKeyDown, widget);
- currentKeyEvent->InitKeyEvent(this, imeEvent);
- imeEvent.mPluginTextEventString.Assign(committed);
- nsEventStatus status = nsEventStatus_eIgnore;
- mDispatcher->DispatchKeyboardEvent(eKeyDown, imeEvent, status,
- currentKeyEvent);
- }
- return true;
- }
-
- NSResponder* firstResponder = [[mView window] firstResponder];
-
- nsresult rv = mDispatcher->BeginNativeInputTransaction();
- if (NS_WARN_IF(NS_FAILED(rv))) {
- MOZ_LOG(gLog, LogLevel::Error,
- ("%p IMEInputHandler::HandleKeyDownEvent, "
- "FAILED, due to BeginNativeInputTransaction() failure "
- "at dispatching keydown for ordinal cases", this));
- return false;
- }
-
- WidgetKeyboardEvent keydownEvent(true, eKeyDown, widget);
- currentKeyEvent->InitKeyEvent(this, keydownEvent);
-
- nsEventStatus status = nsEventStatus_eIgnore;
- mDispatcher->DispatchKeyboardEvent(eKeyDown, keydownEvent, status,
- currentKeyEvent);
- currentKeyEvent->mKeyDownHandled =
- (status == nsEventStatus_eConsumeNoDefault);
-
- if (Destroyed()) {
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TextInputHandler::HandleKeyDownEvent, "
- "widget was destroyed by keydown event", this));
- return currentKeyEvent->IsDefaultPrevented();
- }
-
- // The key down event may have shifted the focus, in which
- // case we should not fire the key press.
- // XXX This is a special code only on Cocoa widget, why is this needed?
- if (firstResponder != [[mView window] firstResponder]) {
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TextInputHandler::HandleKeyDownEvent, "
- "view lost focus by keydown event", this));
- return currentKeyEvent->IsDefaultPrevented();
- }
-
- if (currentKeyEvent->IsDefaultPrevented()) {
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TextInputHandler::HandleKeyDownEvent, "
- "keydown event's default is prevented", this));
- return true;
- }
-
- // Let Cocoa interpret the key events, caching IsIMEComposing first.
- bool wasComposing = IsIMEComposing();
- bool interpretKeyEventsCalled = false;
- // Don't call interpretKeyEvents when a plugin has focus. If we call it,
- // for example, a character is inputted twice during a composition in e10s
- // mode.
- if (!widget->IsPluginFocused() && (IsIMEEnabled() || IsASCIICapableOnly())) {
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TextInputHandler::HandleKeyDownEvent, calling interpretKeyEvents",
- this));
- [mView interpretKeyEvents:[NSArray arrayWithObject:aNativeEvent]];
- interpretKeyEventsCalled = true;
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TextInputHandler::HandleKeyDownEvent, called interpretKeyEvents",
- this));
- }
-
- if (Destroyed()) {
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TextInputHandler::HandleKeyDownEvent, widget was destroyed",
- this));
- return currentKeyEvent->IsDefaultPrevented();
- }
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TextInputHandler::HandleKeyDownEvent, wasComposing=%s, "
- "IsIMEComposing()=%s",
- this, TrueOrFalse(wasComposing), TrueOrFalse(IsIMEComposing())));
-
- if (currentKeyEvent->CanDispatchKeyPressEvent() &&
- !wasComposing && !IsIMEComposing()) {
- rv = mDispatcher->BeginNativeInputTransaction();
- if (NS_WARN_IF(NS_FAILED(rv))) {
- MOZ_LOG(gLog, LogLevel::Error,
- ("%p IMEInputHandler::HandleKeyDownEvent, "
- "FAILED, due to BeginNativeInputTransaction() failure "
- "at dispatching keypress", this));
- return false;
- }
-
- WidgetKeyboardEvent keypressEvent(true, eKeyPress, widget);
- currentKeyEvent->InitKeyEvent(this, keypressEvent);
-
- // If we called interpretKeyEvents and this isn't normal character input
- // then IME probably ate the event for some reason. We do not want to
- // send a key press event in that case.
- // TODO:
- // There are some other cases which IME eats the current event.
- // 1. If key events were nested during calling interpretKeyEvents, it means
- // that IME did something. Then, we should do nothing.
- // 2. If one or more commands are called like "deleteBackward", we should
- // dispatch keypress event at that time. Note that the command may have
- // been a converted or generated action by IME. Then, we shouldn't do
- // our default action for this key.
- if (!(interpretKeyEventsCalled &&
- IsNormalCharInputtingEvent(keypressEvent))) {
- currentKeyEvent->mKeyPressDispatched =
- mDispatcher->MaybeDispatchKeypressEvents(keypressEvent, status,
- currentKeyEvent);
- currentKeyEvent->mKeyPressHandled =
- (status == nsEventStatus_eConsumeNoDefault);
- currentKeyEvent->mKeyPressDispatched = true;
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TextInputHandler::HandleKeyDownEvent, keypress event dispatched",
- this));
- }
- }
-
- // Note: mWidget might have become null here. Don't count on it from here on.
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TextInputHandler::HandleKeyDownEvent, "
- "keydown handled=%s, keypress handled=%s, causedOtherKeyEvents=%s, "
- "compositionDispatched=%s",
- this, TrueOrFalse(currentKeyEvent->mKeyDownHandled),
- TrueOrFalse(currentKeyEvent->mKeyPressHandled),
- TrueOrFalse(currentKeyEvent->mCausedOtherKeyEvents),
- TrueOrFalse(currentKeyEvent->mCompositionDispatched)));
- // Insert empty line to the log for easier to read.
- MOZ_LOG(gLog, LogLevel::Info, (""));
- return currentKeyEvent->IsDefaultPrevented();
-
- NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
-}
-
-void
-TextInputHandler::HandleKeyUpEvent(NSEvent* aNativeEvent)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TextInputHandler::HandleKeyUpEvent, aNativeEvent=%p, "
- "type=%s, keyCode=%lld (0x%X), modifierFlags=0x%X, characters=\"%s\", "
- "charactersIgnoringModifiers=\"%s\", "
- "IsIMEComposing()=%s",
- this, aNativeEvent, GetNativeKeyEventType(aNativeEvent),
- [aNativeEvent keyCode], [aNativeEvent keyCode],
- [aNativeEvent modifierFlags], GetCharacters([aNativeEvent characters]),
- GetCharacters([aNativeEvent charactersIgnoringModifiers]),
- TrueOrFalse(IsIMEComposing())));
-
- if (Destroyed()) {
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TextInputHandler::HandleKeyUpEvent, "
- "widget has been already destroyed", this));
- return;
- }
-
- nsresult rv = mDispatcher->BeginNativeInputTransaction();
- if (NS_WARN_IF(NS_FAILED(rv))) {
- MOZ_LOG(gLog, LogLevel::Error,
- ("%p IMEInputHandler::HandleKeyUpEvent, "
- "FAILED, due to BeginNativeInputTransaction() failure", this));
- return;
- }
-
- WidgetKeyboardEvent keyupEvent(true, eKeyUp, mWidget);
- InitKeyEvent(aNativeEvent, keyupEvent);
-
- KeyEventState currentKeyEvent(aNativeEvent);
- nsEventStatus status = nsEventStatus_eIgnore;
- mDispatcher->DispatchKeyboardEvent(eKeyUp, keyupEvent, status,
- &currentKeyEvent);
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-void
-TextInputHandler::HandleFlagsChanged(NSEvent* aNativeEvent)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- if (Destroyed()) {
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TextInputHandler::HandleFlagsChanged, "
- "widget has been already destroyed", this));
- return;
- }
-
- RefPtr<nsChildView> kungFuDeathGrip(mWidget);
- mozilla::Unused << kungFuDeathGrip; // Not referenced within this function
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TextInputHandler::HandleFlagsChanged, aNativeEvent=%p, "
- "type=%s, keyCode=%s (0x%X), modifierFlags=0x%08X, "
- "sLastModifierState=0x%08X, IsIMEComposing()=%s",
- this, aNativeEvent, GetNativeKeyEventType(aNativeEvent),
- GetKeyNameForNativeKeyCode([aNativeEvent keyCode]), [aNativeEvent keyCode],
- [aNativeEvent modifierFlags], sLastModifierState,
- TrueOrFalse(IsIMEComposing())));
-
- MOZ_ASSERT([aNativeEvent type] == NSFlagsChanged);
-
- NSUInteger diff = [aNativeEvent modifierFlags] ^ sLastModifierState;
- // Device dependent flags for left-control key, both shift keys, both command
- // keys and both option keys have been defined in Next's SDK. But we
- // shouldn't use it directly as far as possible since Cocoa SDK doesn't
- // define them. Fortunately, we need them only when we dispatch keyup
- // events. So, we can usually know the actual relation between keyCode and
- // device dependent flags. However, we need to remove following flags first
- // since the differences don't indicate modifier key state.
- // NX_STYLUSPROXIMITYMASK: Probably used for pen like device.
- // kCGEventFlagMaskNonCoalesced (= NX_NONCOALSESCEDMASK): See the document for
- // Quartz Event Services.
- diff &= ~(NX_STYLUSPROXIMITYMASK | kCGEventFlagMaskNonCoalesced);
-
- switch ([aNativeEvent keyCode]) {
- // CapsLock state and other modifier states are different:
- // CapsLock state does not revert when the CapsLock key goes up, as the
- // modifier state does for other modifier keys on key up.
- case kVK_CapsLock: {
- // Fire key down event for caps lock.
- DispatchKeyEventForFlagsChanged(aNativeEvent, true);
- // XXX should we fire keyup event too? The keyup event for CapsLock key
- // is never dispatched on Gecko.
- // XXX WebKit dispatches keydown event when CapsLock is locked, otherwise,
- // keyup event. If we do so, we cannot keep the consistency with other
- // platform's behavior...
- break;
- }
-
- // If the event is caused by pressing or releasing a modifier key, just
- // dispatch the key's event.
- case kVK_Shift:
- case kVK_RightShift:
- case kVK_Command:
- case kVK_RightCommand:
- case kVK_Control:
- case kVK_RightControl:
- case kVK_Option:
- case kVK_RightOption:
- case kVK_Help: {
- // We assume that at most one modifier is changed per event if the event
- // is caused by pressing or releasing a modifier key.
- bool isKeyDown = ([aNativeEvent modifierFlags] & diff) != 0;
- DispatchKeyEventForFlagsChanged(aNativeEvent, isKeyDown);
- // XXX Some applications might send the event with incorrect device-
- // dependent flags.
- if (isKeyDown && ((diff & ~NSDeviceIndependentModifierFlagsMask) != 0)) {
- unsigned short keyCode = [aNativeEvent keyCode];
- const ModifierKey* modifierKey =
- GetModifierKeyForDeviceDependentFlags(diff);
- if (modifierKey && modifierKey->keyCode != keyCode) {
- // Although, we're not sure the actual cause of this case, the stored
- // modifier information and the latest key event information may be
- // mismatched. Then, let's reset the stored information.
- // NOTE: If this happens, it may fail to handle NSFlagsChanged event
- // in the default case (below). However, it's the rare case handler
- // and this case occurs rarely. So, we can ignore the edge case bug.
- NS_WARNING("Resetting stored modifier key information");
- mModifierKeys.Clear();
- modifierKey = nullptr;
- }
- if (!modifierKey) {
- mModifierKeys.AppendElement(ModifierKey(diff, keyCode));
- }
- }
- break;
- }
-
- // Currently we don't support Fn key since other browsers don't dispatch
- // events for it and we don't have keyCode for this key.
- // It should be supported when we implement .key and .char.
- case kVK_Function:
- break;
-
- // If the event is caused by something else than pressing or releasing a
- // single modifier key (for example by the app having been deactivated
- // using command-tab), use the modifiers themselves to determine which
- // key's event to dispatch, and whether it's a keyup or keydown event.
- // In all cases we assume one or more modifiers are being deactivated
- // (never activated) -- otherwise we'd have received one or more events
- // corresponding to a single modifier key being pressed.
- default: {
- NSUInteger modifiers = sLastModifierState;
- for (int32_t bit = 0; bit < 32; ++bit) {
- NSUInteger flag = 1 << bit;
- if (!(diff & flag)) {
- continue;
- }
-
- // Given correct information from the application, a flag change here
- // will normally be a deactivation (except for some lockable modifiers
- // such as CapsLock). But some applications (like VNC) can send an
- // activating event with a zero keyCode. So we need to check for that
- // here.
- bool dispatchKeyDown = ((flag & [aNativeEvent modifierFlags]) != 0);
-
- unsigned short keyCode = 0;
- if (flag & NSDeviceIndependentModifierFlagsMask) {
- switch (flag) {
- case NSAlphaShiftKeyMask:
- keyCode = kVK_CapsLock;
- dispatchKeyDown = true;
- break;
-
- case NSNumericPadKeyMask:
- // NSNumericPadKeyMask is fired by VNC a lot. But not all of
- // these events can really be Clear key events, so we just ignore
- // them.
- continue;
-
- case NSHelpKeyMask:
- keyCode = kVK_Help;
- break;
-
- case NSFunctionKeyMask:
- // An NSFunctionKeyMask change here will normally be a
- // deactivation. But sometimes it will be an activation send (by
- // VNC for example) with a zero keyCode.
- continue;
-
- // These cases (NSShiftKeyMask, NSControlKeyMask, NSAlternateKeyMask
- // and NSCommandKeyMask) should be handled by the other branch of
- // the if statement, below (which handles device dependent flags).
- // However, some applications (like VNC) can send key events without
- // any device dependent flags, so we handle them here instead.
- case NSShiftKeyMask:
- keyCode = (modifiers & 0x0004) ? kVK_RightShift : kVK_Shift;
- break;
- case NSControlKeyMask:
- keyCode = (modifiers & 0x2000) ? kVK_RightControl : kVK_Control;
- break;
- case NSAlternateKeyMask:
- keyCode = (modifiers & 0x0040) ? kVK_RightOption : kVK_Option;
- break;
- case NSCommandKeyMask:
- keyCode = (modifiers & 0x0010) ? kVK_RightCommand : kVK_Command;
- break;
-
- default:
- continue;
- }
- } else {
- const ModifierKey* modifierKey =
- GetModifierKeyForDeviceDependentFlags(flag);
- if (!modifierKey) {
- // See the note above (in the other branch of the if statement)
- // about the NSShiftKeyMask, NSControlKeyMask, NSAlternateKeyMask
- // and NSCommandKeyMask cases.
- continue;
- }
- keyCode = modifierKey->keyCode;
- }
-
- // Remove flags
- modifiers &= ~flag;
- switch (keyCode) {
- case kVK_Shift: {
- const ModifierKey* modifierKey =
- GetModifierKeyForNativeKeyCode(kVK_RightShift);
- if (!modifierKey ||
- !(modifiers & modifierKey->GetDeviceDependentFlags())) {
- modifiers &= ~NSShiftKeyMask;
- }
- break;
- }
- case kVK_RightShift: {
- const ModifierKey* modifierKey =
- GetModifierKeyForNativeKeyCode(kVK_Shift);
- if (!modifierKey ||
- !(modifiers & modifierKey->GetDeviceDependentFlags())) {
- modifiers &= ~NSShiftKeyMask;
- }
- break;
- }
- case kVK_Command: {
- const ModifierKey* modifierKey =
- GetModifierKeyForNativeKeyCode(kVK_RightCommand);
- if (!modifierKey ||
- !(modifiers & modifierKey->GetDeviceDependentFlags())) {
- modifiers &= ~NSCommandKeyMask;
- }
- break;
- }
- case kVK_RightCommand: {
- const ModifierKey* modifierKey =
- GetModifierKeyForNativeKeyCode(kVK_Command);
- if (!modifierKey ||
- !(modifiers & modifierKey->GetDeviceDependentFlags())) {
- modifiers &= ~NSCommandKeyMask;
- }
- break;
- }
- case kVK_Control: {
- const ModifierKey* modifierKey =
- GetModifierKeyForNativeKeyCode(kVK_RightControl);
- if (!modifierKey ||
- !(modifiers & modifierKey->GetDeviceDependentFlags())) {
- modifiers &= ~NSControlKeyMask;
- }
- break;
- }
- case kVK_RightControl: {
- const ModifierKey* modifierKey =
- GetModifierKeyForNativeKeyCode(kVK_Control);
- if (!modifierKey ||
- !(modifiers & modifierKey->GetDeviceDependentFlags())) {
- modifiers &= ~NSControlKeyMask;
- }
- break;
- }
- case kVK_Option: {
- const ModifierKey* modifierKey =
- GetModifierKeyForNativeKeyCode(kVK_RightOption);
- if (!modifierKey ||
- !(modifiers & modifierKey->GetDeviceDependentFlags())) {
- modifiers &= ~NSAlternateKeyMask;
- }
- break;
- }
- case kVK_RightOption: {
- const ModifierKey* modifierKey =
- GetModifierKeyForNativeKeyCode(kVK_Option);
- if (!modifierKey ||
- !(modifiers & modifierKey->GetDeviceDependentFlags())) {
- modifiers &= ~NSAlternateKeyMask;
- }
- break;
- }
- case kVK_Help:
- modifiers &= ~NSHelpKeyMask;
- break;
- default:
- break;
- }
-
- NSEvent* event =
- [NSEvent keyEventWithType:NSFlagsChanged
- location:[aNativeEvent locationInWindow]
- modifierFlags:modifiers
- timestamp:[aNativeEvent timestamp]
- windowNumber:[aNativeEvent windowNumber]
- context:[aNativeEvent context]
- characters:@""
- charactersIgnoringModifiers:@""
- isARepeat:NO
- keyCode:keyCode];
- DispatchKeyEventForFlagsChanged(event, dispatchKeyDown);
- if (Destroyed()) {
- break;
- }
-
- // Stop if focus has changed.
- // Check to see if mView is still the first responder.
- if (![mView isFirstResponder]) {
- break;
- }
-
- }
- break;
- }
- }
-
- // Be aware, the widget may have been destroyed.
- sLastModifierState = [aNativeEvent modifierFlags];
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-const TextInputHandler::ModifierKey*
-TextInputHandler::GetModifierKeyForNativeKeyCode(unsigned short aKeyCode) const
-{
- for (ModifierKeyArray::index_type i = 0; i < mModifierKeys.Length(); ++i) {
- if (mModifierKeys[i].keyCode == aKeyCode) {
- return &((ModifierKey&)mModifierKeys[i]);
- }
- }
- return nullptr;
-}
-
-const TextInputHandler::ModifierKey*
-TextInputHandler::GetModifierKeyForDeviceDependentFlags(NSUInteger aFlags) const
-{
- for (ModifierKeyArray::index_type i = 0; i < mModifierKeys.Length(); ++i) {
- if (mModifierKeys[i].GetDeviceDependentFlags() ==
- (aFlags & ~NSDeviceIndependentModifierFlagsMask)) {
- return &((ModifierKey&)mModifierKeys[i]);
- }
- }
- return nullptr;
-}
-
-void
-TextInputHandler::DispatchKeyEventForFlagsChanged(NSEvent* aNativeEvent,
- bool aDispatchKeyDown)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- if (Destroyed()) {
- return;
- }
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TextInputHandler::DispatchKeyEventForFlagsChanged, aNativeEvent=%p, "
- "type=%s, keyCode=%s (0x%X), aDispatchKeyDown=%s, IsIMEComposing()=%s",
- this, aNativeEvent, GetNativeKeyEventType(aNativeEvent),
- GetKeyNameForNativeKeyCode([aNativeEvent keyCode]), [aNativeEvent keyCode],
- TrueOrFalse(aDispatchKeyDown), TrueOrFalse(IsIMEComposing())));
-
- if ([aNativeEvent type] != NSFlagsChanged || IsIMEComposing()) {
- return;
- }
-
- nsresult rv = mDispatcher->BeginNativeInputTransaction();
- if (NS_WARN_IF(NS_FAILED(rv))) {
- MOZ_LOG(gLog, LogLevel::Error,
- ("%p IMEInputHandler::DispatchKeyEventForFlagsChanged, "
- "FAILED, due to BeginNativeInputTransaction() failure", this));
- return;
- }
-
- EventMessage message = aDispatchKeyDown ? eKeyDown : eKeyUp;
-
- // Fire a key event.
- WidgetKeyboardEvent keyEvent(true, message, mWidget);
- InitKeyEvent(aNativeEvent, keyEvent);
-
- // Attach a plugin event, in case keyEvent gets dispatched to a plugin. Only
- // one field is needed -- the type. The other fields can be constructed as
- // the need arises. But Gecko doesn't have anything equivalent to the
- // NPCocoaEventFlagsChanged type, and this needs to be passed accurately to
- // any plugin to which this event is sent.
- NPCocoaEvent cocoaEvent;
- nsCocoaUtils::InitNPCocoaEvent(&cocoaEvent);
- cocoaEvent.type = NPCocoaEventFlagsChanged;
- keyEvent.mPluginEvent.Copy(cocoaEvent);
-
- KeyEventState currentKeyEvent(aNativeEvent);
- nsEventStatus status = nsEventStatus_eIgnore;
- mDispatcher->DispatchKeyboardEvent(message, keyEvent, status,
- &currentKeyEvent);
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-void
-TextInputHandler::InsertText(NSAttributedString* aAttrString,
- NSRange* aReplacementRange)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- if (Destroyed()) {
- return;
- }
-
- KeyEventState* currentKeyEvent = GetCurrentKeyEvent();
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TextInputHandler::InsertText, aAttrString=\"%s\", "
- "aReplacementRange=%p { location=%llu, length=%llu }, "
- "IsIMEComposing()=%s, IgnoreIMEComposition()=%s, "
- "keyevent=%p, keydownHandled=%s, keypressDispatched=%s, "
- "causedOtherKeyEvents=%s, compositionDispatched=%s",
- this, GetCharacters([aAttrString string]), aReplacementRange,
- aReplacementRange ? aReplacementRange->location : 0,
- aReplacementRange ? aReplacementRange->length : 0,
- TrueOrFalse(IsIMEComposing()), TrueOrFalse(IgnoreIMEComposition()),
- currentKeyEvent ? currentKeyEvent->mKeyEvent : nullptr,
- currentKeyEvent ?
- TrueOrFalse(currentKeyEvent->mKeyDownHandled) : "N/A",
- currentKeyEvent ?
- TrueOrFalse(currentKeyEvent->mKeyPressDispatched) : "N/A",
- currentKeyEvent ?
- TrueOrFalse(currentKeyEvent->mCausedOtherKeyEvents) : "N/A",
- currentKeyEvent ?
- TrueOrFalse(currentKeyEvent->mCompositionDispatched) : "N/A"));
-
- if (IgnoreIMEComposition()) {
- return;
- }
-
- InputContext context = mWidget->GetInputContext();
- bool isEditable = (context.mIMEState.mEnabled == IMEState::ENABLED ||
- context.mIMEState.mEnabled == IMEState::PASSWORD);
- NSRange selectedRange = SelectedRange();
-
- nsAutoString str;
- nsCocoaUtils::GetStringForNSString([aAttrString string], str);
-
- AutoInsertStringClearer clearer(currentKeyEvent);
- if (currentKeyEvent) {
- currentKeyEvent->mInsertString = &str;
- }
-
- if (!IsIMEComposing() && str.IsEmpty()) {
- // nothing to do if there is no content which can be removed.
- if (!isEditable) {
- return;
- }
- // If replacement range is specified, we need to remove the range.
- // Otherwise, we need to remove the selected range if it's not collapsed.
- if (aReplacementRange && aReplacementRange->location != NSNotFound) {
- // nothing to do since the range is collapsed.
- if (aReplacementRange->length == 0) {
- return;
- }
- // If the replacement range is different from current selected range,
- // select the range.
- if (!NSEqualRanges(selectedRange, *aReplacementRange)) {
- NS_ENSURE_TRUE_VOID(SetSelection(*aReplacementRange));
- }
- selectedRange = SelectedRange();
- }
- NS_ENSURE_TRUE_VOID(selectedRange.location != NSNotFound);
- if (selectedRange.length == 0) {
- return; // nothing to do
- }
- // If this is caused by a key input, the keypress event which will be
- // dispatched later should cause the delete. Therefore, nothing to do here.
- // Although, we're not sure if such case is actually possible.
- if (!currentKeyEvent) {
- return;
- }
- // Delete the selected range.
- RefPtr<TextInputHandler> kungFuDeathGrip(this);
- WidgetContentCommandEvent deleteCommandEvent(true, eContentCommandDelete,
- mWidget);
- DispatchEvent(deleteCommandEvent);
- NS_ENSURE_TRUE_VOID(deleteCommandEvent.mSucceeded);
- // Be aware! The widget might be destroyed here.
- return;
- }
-
- bool isReplacingSpecifiedRange =
- isEditable && aReplacementRange &&
- aReplacementRange->location != NSNotFound &&
- !NSEqualRanges(selectedRange, *aReplacementRange);
-
- // If this is not caused by pressing a key, there is a composition or
- // replacing a range which is different from current selection, let's
- // insert the text as committing a composition.
- // If InsertText() is called two or more times, we should insert all
- // text with composition events.
- // XXX When InsertText() is called multiple times, Chromium dispatches
- // only one composition event. So, we need to store InsertText()
- // calls and flush later.
- if (!currentKeyEvent || currentKeyEvent->mCompositionDispatched ||
- IsIMEComposing() || isReplacingSpecifiedRange) {
- InsertTextAsCommittingComposition(aAttrString, aReplacementRange);
- if (currentKeyEvent) {
- currentKeyEvent->mCompositionDispatched = true;
- }
- return;
- }
-
- // Don't let the same event be fired twice when hitting
- // enter/return for Bug 420502. However, Korean IME (or some other
- // simple IME) may work without marked text. For example, composing
- // character may be inserted as committed text and it's modified with
- // aReplacementRange. When a keydown starts new composition with
- // committing previous character, InsertText() may be called twice,
- // one is for committing previous character and then, inserting new
- // composing character as committed character. In the latter case,
- // |CanDispatchKeyPressEvent()| returns true but we need to dispatch
- // keypress event for the new character. So, when IME tries to insert
- // printable characters, we should ignore current key event state even
- // after the keydown has already caused dispatching composition event.
- // XXX Anyway, we should sort out around this at fixing bug 1338460.
- if (currentKeyEvent && !currentKeyEvent->CanDispatchKeyPressEvent() &&
- (str.IsEmpty() || (str.Length() == 1 && !IsPrintableChar(str[0])))) {
- return;
- }
-
- // XXX Shouldn't we hold mDispatcher instead of mWidget?
- RefPtr<nsChildView> widget(mWidget);
- nsresult rv = mDispatcher->BeginNativeInputTransaction();
- if (NS_WARN_IF(NS_FAILED(rv))) {
- MOZ_LOG(gLog, LogLevel::Error,
- ("%p IMEInputHandler::HandleKeyUpEvent, "
- "FAILED, due to BeginNativeInputTransaction() failure", this));
- return;
- }
-
- // Dispatch keypress event with char instead of compositionchange event
- WidgetKeyboardEvent keypressEvent(true, eKeyPress, widget);
- // XXX Why do we need to dispatch keypress event for not inputting any
- // string? If it wants to delete the specified range, should we
- // dispatch an eContentCommandDelete event instead? Because this
- // must not be caused by a key operation, a part of IME's processing.
- keypressEvent.mIsChar = IsPrintableChar(str.CharAt(0));
-
- // Don't set other modifiers from the current event, because here in
- // -insertText: they've already been taken into account in creating
- // the input string.
-
- if (currentKeyEvent) {
- currentKeyEvent->InitKeyEvent(this, keypressEvent);
- } else {
- nsCocoaUtils::InitInputEvent(keypressEvent, static_cast<NSEvent*>(nullptr));
- keypressEvent.mKeyNameIndex = KEY_NAME_INDEX_USE_STRING;
- keypressEvent.mKeyValue = str;
- // FYI: TextEventDispatcher will set mKeyCode to 0 for printable key's
- // keypress events even if they don't cause inputting non-empty string.
- }
-
- // Remove basic modifiers from keypress event because if they are included,
- // nsPlaintextEditor ignores the event.
- keypressEvent.mModifiers &= ~(MODIFIER_CONTROL |
- MODIFIER_ALT |
- MODIFIER_META);
-
- // TODO:
- // If mCurrentKeyEvent.mKeyEvent is null, the text should be inputted as
- // composition events.
- nsEventStatus status = nsEventStatus_eIgnore;
- bool keyPressDispatched =
- mDispatcher->MaybeDispatchKeypressEvents(keypressEvent, status,
- currentKeyEvent);
- bool keyPressHandled = (status == nsEventStatus_eConsumeNoDefault);
-
- // Note: mWidget might have become null here. Don't count on it from here on.
-
- if (currentKeyEvent) {
- currentKeyEvent->mKeyPressHandled = keyPressHandled;
- currentKeyEvent->mKeyPressDispatched = keyPressDispatched;
- }
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-bool
-TextInputHandler::DoCommandBySelector(const char* aSelector)
-{
- RefPtr<nsChildView> widget(mWidget);
-
- KeyEventState* currentKeyEvent = GetCurrentKeyEvent();
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TextInputHandler::DoCommandBySelector, aSelector=\"%s\", "
- "Destroyed()=%s, keydownHandled=%s, keypressHandled=%s, "
- "causedOtherKeyEvents=%s",
- this, aSelector ? aSelector : "", TrueOrFalse(Destroyed()),
- currentKeyEvent ?
- TrueOrFalse(currentKeyEvent->mKeyDownHandled) : "N/A",
- currentKeyEvent ?
- TrueOrFalse(currentKeyEvent->mKeyPressHandled) : "N/A",
- currentKeyEvent ?
- TrueOrFalse(currentKeyEvent->mCausedOtherKeyEvents) : "N/A"));
-
- if (currentKeyEvent && currentKeyEvent->CanDispatchKeyPressEvent()) {
- nsresult rv = mDispatcher->BeginNativeInputTransaction();
- if (NS_WARN_IF(NS_FAILED(rv))) {
- MOZ_LOG(gLog, LogLevel::Error,
- ("%p IMEInputHandler::DoCommandBySelector, "
- "FAILED, due to BeginNativeInputTransaction() failure "
- "at dispatching keypress", this));
- return false;
- }
-
- WidgetKeyboardEvent keypressEvent(true, eKeyPress, widget);
- currentKeyEvent->InitKeyEvent(this, keypressEvent);
-
- nsEventStatus status = nsEventStatus_eIgnore;
- currentKeyEvent->mKeyPressDispatched =
- mDispatcher->MaybeDispatchKeypressEvents(keypressEvent, status,
- currentKeyEvent);
- currentKeyEvent->mKeyPressHandled =
- (status == nsEventStatus_eConsumeNoDefault);
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TextInputHandler::DoCommandBySelector, keypress event "
- "dispatched, Destroyed()=%s, keypressHandled=%s",
- this, TrueOrFalse(Destroyed()),
- TrueOrFalse(currentKeyEvent->mKeyPressHandled)));
- }
-
- return (!Destroyed() && currentKeyEvent &&
- currentKeyEvent->IsDefaultPrevented());
-}
-
-
-#pragma mark -
-
-
-/******************************************************************************
- *
- * IMEInputHandler implementation (static methods)
- *
- ******************************************************************************/
-
-bool IMEInputHandler::sStaticMembersInitialized = false;
-bool IMEInputHandler::sCachedIsForRTLLangage = false;
-CFStringRef IMEInputHandler::sLatestIMEOpenedModeInputSourceID = nullptr;
-IMEInputHandler* IMEInputHandler::sFocusedIMEHandler = nullptr;
-
-// static
-void
-IMEInputHandler::InitStaticMembers()
-{
- if (sStaticMembersInitialized)
- return;
- sStaticMembersInitialized = true;
- // We need to check the keyboard layout changes on all applications.
- CFNotificationCenterRef center = ::CFNotificationCenterGetDistributedCenter();
- // XXX Don't we need to remove the observer at shut down?
- // Mac Dev Center's document doesn't say how to remove the observer if
- // the second parameter is NULL.
- ::CFNotificationCenterAddObserver(center, NULL,
- OnCurrentTextInputSourceChange,
- kTISNotifySelectedKeyboardInputSourceChanged, NULL,
- CFNotificationSuspensionBehaviorDeliverImmediately);
- // Initiailize with the current keyboard layout
- OnCurrentTextInputSourceChange(NULL, NULL,
- kTISNotifySelectedKeyboardInputSourceChanged,
- NULL, NULL);
-}
-
-// static
-void
-IMEInputHandler::OnCurrentTextInputSourceChange(CFNotificationCenterRef aCenter,
- void* aObserver,
- CFStringRef aName,
- const void* aObject,
- CFDictionaryRef aUserInfo)
-{
- // Cache the latest IME opened mode to sLatestIMEOpenedModeInputSourceID.
- TISInputSourceWrapper tis;
- tis.InitByCurrentInputSource();
- if (tis.IsOpenedIMEMode()) {
- tis.GetInputSourceID(sLatestIMEOpenedModeInputSourceID);
- }
-
- if (MOZ_LOG_TEST(gLog, LogLevel::Info)) {
- static CFStringRef sLastTIS = nullptr;
- CFStringRef newTIS;
- tis.GetInputSourceID(newTIS);
- if (!sLastTIS ||
- ::CFStringCompare(sLastTIS, newTIS, 0) != kCFCompareEqualTo) {
- TISInputSourceWrapper tis1, tis2, tis3, tis4, tis5;
- tis1.InitByCurrentKeyboardLayout();
- tis2.InitByCurrentASCIICapableInputSource();
- tis3.InitByCurrentASCIICapableKeyboardLayout();
- tis4.InitByCurrentInputMethodKeyboardLayoutOverride();
- tis5.InitByTISInputSourceRef(tis.GetKeyboardLayoutInputSource());
- CFStringRef is0 = nullptr, is1 = nullptr, is2 = nullptr, is3 = nullptr,
- is4 = nullptr, is5 = nullptr, type0 = nullptr,
- lang0 = nullptr, bundleID0 = nullptr;
- tis.GetInputSourceID(is0);
- tis1.GetInputSourceID(is1);
- tis2.GetInputSourceID(is2);
- tis3.GetInputSourceID(is3);
- tis4.GetInputSourceID(is4);
- tis5.GetInputSourceID(is5);
- tis.GetInputSourceType(type0);
- tis.GetPrimaryLanguage(lang0);
- tis.GetBundleID(bundleID0);
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("IMEInputHandler::OnCurrentTextInputSourceChange,\n"
- " Current Input Source is changed to:\n"
- " currentInputContext=%p\n"
- " %s\n"
- " type=%s %s\n"
- " overridden keyboard layout=%s\n"
- " used keyboard layout for translation=%s\n"
- " primary language=%s\n"
- " bundle ID=%s\n"
- " current ASCII capable Input Source=%s\n"
- " current Keyboard Layout=%s\n"
- " current ASCII capable Keyboard Layout=%s",
- [NSTextInputContext currentInputContext], GetCharacters(is0),
- GetCharacters(type0), tis.IsASCIICapable() ? "- ASCII capable " : "",
- GetCharacters(is4), GetCharacters(is5),
- GetCharacters(lang0), GetCharacters(bundleID0),
- GetCharacters(is2), GetCharacters(is1), GetCharacters(is3)));
- }
- sLastTIS = newTIS;
- }
-
- /**
- * When the direction is changed, all the children are notified.
- * No need to treat the initial case separately because it is covered
- * by the general case (sCachedIsForRTLLangage is initially false)
- */
- if (sCachedIsForRTLLangage != tis.IsForRTLLanguage()) {
- WidgetUtils::SendBidiKeyboardInfoToContent();
- sCachedIsForRTLLangage = tis.IsForRTLLanguage();
- }
-}
-
-// static
-void
-IMEInputHandler::FlushPendingMethods(nsITimer* aTimer, void* aClosure)
-{
- NS_ASSERTION(aClosure, "aClosure is null");
- static_cast<IMEInputHandler*>(aClosure)->ExecutePendingMethods();
-}
-
-// static
-CFArrayRef
-IMEInputHandler::CreateAllIMEModeList()
-{
- const void* keys[] = { kTISPropertyInputSourceType };
- const void* values[] = { kTISTypeKeyboardInputMode };
- CFDictionaryRef filter =
- ::CFDictionaryCreate(kCFAllocatorDefault, keys, values, 1, NULL, NULL);
- NS_ASSERTION(filter, "failed to create the filter");
- CFArrayRef list = ::TISCreateInputSourceList(filter, true);
- ::CFRelease(filter);
- return list;
-}
-
-// static
-void
-IMEInputHandler::DebugPrintAllIMEModes()
-{
- if (MOZ_LOG_TEST(gLog, LogLevel::Info)) {
- CFArrayRef list = CreateAllIMEModeList();
- MOZ_LOG(gLog, LogLevel::Info, ("IME mode configuration:"));
- CFIndex idx = ::CFArrayGetCount(list);
- TISInputSourceWrapper tis;
- for (CFIndex i = 0; i < idx; ++i) {
- TISInputSourceRef inputSource = static_cast<TISInputSourceRef>(
- const_cast<void *>(::CFArrayGetValueAtIndex(list, i)));
- tis.InitByTISInputSourceRef(inputSource);
- nsAutoString name, isid;
- tis.GetLocalizedName(name);
- tis.GetInputSourceID(isid);
- MOZ_LOG(gLog, LogLevel::Info,
- (" %s\t<%s>%s%s\n",
- NS_ConvertUTF16toUTF8(name).get(),
- NS_ConvertUTF16toUTF8(isid).get(),
- tis.IsASCIICapable() ? "" : "\t(Isn't ASCII capable)",
- tis.IsEnabled() ? "" : "\t(Isn't Enabled)"));
- }
- ::CFRelease(list);
- }
-}
-
-//static
-TSMDocumentID
-IMEInputHandler::GetCurrentTSMDocumentID()
-{
- // At least on Mac OS X 10.6.x and 10.7.x, ::TSMGetActiveDocument() has a bug.
- // The result of ::TSMGetActiveDocument() isn't modified for new active text
- // input context until [NSTextInputContext currentInputContext] is called.
- // Therefore, we need to call it here.
- [NSTextInputContext currentInputContext];
- return ::TSMGetActiveDocument();
-}
-
-
-#pragma mark -
-
-
-/******************************************************************************
- *
- * IMEInputHandler implementation #1
- * The methods are releated to the pending methods. Some jobs should be
- * run after the stack is finished, e.g, some methods cannot run the jobs
- * during processing the focus event. And also some other jobs should be
- * run at the next focus event is processed.
- * The pending methods are recorded in mPendingMethods. They are executed
- * by ExecutePendingMethods via FlushPendingMethods.
- *
- ******************************************************************************/
-
-NS_IMETHODIMP
-IMEInputHandler::NotifyIME(TextEventDispatcher* aTextEventDispatcher,
- const IMENotification& aNotification)
-{
- switch (aNotification.mMessage) {
- case REQUEST_TO_COMMIT_COMPOSITION:
- CommitIMEComposition();
- return NS_OK;
- case REQUEST_TO_CANCEL_COMPOSITION:
- CancelIMEComposition();
- return NS_OK;
- case NOTIFY_IME_OF_FOCUS:
- if (IsFocused()) {
- nsIWidget* widget = aTextEventDispatcher->GetWidget();
- if (widget && widget->GetInputContext().IsPasswordEditor()) {
- EnableSecureEventInput();
- } else {
- EnsureSecureEventInputDisabled();
- }
- }
- OnFocusChangeInGecko(true);
- return NS_OK;
- case NOTIFY_IME_OF_BLUR:
- OnFocusChangeInGecko(false);
- return NS_OK;
- case NOTIFY_IME_OF_SELECTION_CHANGE:
- OnSelectionChange(aNotification);
- return NS_OK;
- default:
- return NS_ERROR_NOT_IMPLEMENTED;
- }
-}
-
-NS_IMETHODIMP_(void)
-IMEInputHandler::OnRemovedFrom(TextEventDispatcher* aTextEventDispatcher)
-{
- // XXX When input transaction is being stolen by add-on, what should we do?
-}
-
-NS_IMETHODIMP_(void)
-IMEInputHandler::WillDispatchKeyboardEvent(
- TextEventDispatcher* aTextEventDispatcher,
- WidgetKeyboardEvent& aKeyboardEvent,
- uint32_t aIndexOfKeypress,
- void* aData)
-{
- // If the keyboard event is not caused by a native key event, we can do
- // nothing here.
- if (!aData) {
- return;
- }
-
- KeyEventState* currentKeyEvent = static_cast<KeyEventState*>(aData);
- NSEvent* nativeEvent = currentKeyEvent->mKeyEvent;
- nsAString* insertString = currentKeyEvent->mInsertString;
- if (KeyboardLayoutOverrideRef().mOverrideEnabled) {
- TISInputSourceWrapper tis;
- tis.InitByLayoutID(KeyboardLayoutOverrideRef().mKeyboardLayout, true);
- tis.WillDispatchKeyboardEvent(nativeEvent, insertString, aKeyboardEvent);
- return;
- }
- TISInputSourceWrapper::CurrentInputSource().
- WillDispatchKeyboardEvent(nativeEvent, insertString, aKeyboardEvent);
-}
-
-void
-IMEInputHandler::NotifyIMEOfFocusChangeInGecko()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::NotifyIMEOfFocusChangeInGecko, "
- "Destroyed()=%s, IsFocused()=%s, inputContext=%p",
- this, TrueOrFalse(Destroyed()), TrueOrFalse(IsFocused()),
- mView ? [mView inputContext] : nullptr));
-
- if (Destroyed()) {
- return;
- }
-
- if (!IsFocused()) {
- // retry at next focus event
- mPendingMethods |= kNotifyIMEOfFocusChangeInGecko;
- return;
- }
-
- MOZ_ASSERT(mView);
- NSTextInputContext* inputContext = [mView inputContext];
- NS_ENSURE_TRUE_VOID(inputContext);
-
- // When an <input> element on a XUL <panel> element gets focus from an <input>
- // element on the opener window of the <panel> element, the owner window
- // still has native focus. Therefore, IMEs may store the opener window's
- // level at this time because they don't know the actual focus is moved to
- // different window. If IMEs try to get the newest window level after the
- // focus change, we return the window level of the XUL <panel>'s widget.
- // Therefore, let's emulate the native focus change. Then, IMEs can refresh
- // the stored window level.
- [inputContext deactivate];
- [inputContext activate];
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-void
-IMEInputHandler::DiscardIMEComposition()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::DiscardIMEComposition, "
- "Destroyed()=%s, IsFocused()=%s, mView=%p, inputContext=%p",
- this, TrueOrFalse(Destroyed()), TrueOrFalse(IsFocused()),
- mView, mView ? [mView inputContext] : nullptr));
-
- if (Destroyed()) {
- return;
- }
-
- if (!IsFocused()) {
- // retry at next focus event
- mPendingMethods |= kDiscardIMEComposition;
- return;
- }
-
- NS_ENSURE_TRUE_VOID(mView);
- NSTextInputContext* inputContext = [mView inputContext];
- NS_ENSURE_TRUE_VOID(inputContext);
- mIgnoreIMECommit = true;
- [inputContext discardMarkedText];
- mIgnoreIMECommit = false;
-
- NS_OBJC_END_TRY_ABORT_BLOCK
-}
-
-void
-IMEInputHandler::SyncASCIICapableOnly()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::SyncASCIICapableOnly, "
- "Destroyed()=%s, IsFocused()=%s, mIsASCIICapableOnly=%s, "
- "GetCurrentTSMDocumentID()=%p",
- this, TrueOrFalse(Destroyed()), TrueOrFalse(IsFocused()),
- TrueOrFalse(mIsASCIICapableOnly), GetCurrentTSMDocumentID()));
-
- if (Destroyed()) {
- return;
- }
-
- if (!IsFocused()) {
- // retry at next focus event
- mPendingMethods |= kSyncASCIICapableOnly;
- return;
- }
-
- TSMDocumentID doc = GetCurrentTSMDocumentID();
- if (!doc) {
- // retry
- mPendingMethods |= kSyncASCIICapableOnly;
- NS_WARNING("Application is active but there is no active document");
- ResetTimer();
- return;
- }
-
- if (mIsASCIICapableOnly) {
- CFArrayRef ASCIICapableTISList = ::TISCreateASCIICapableInputSourceList();
- ::TSMSetDocumentProperty(doc,
- kTSMDocumentEnabledInputSourcesPropertyTag,
- sizeof(CFArrayRef),
- &ASCIICapableTISList);
- ::CFRelease(ASCIICapableTISList);
- } else {
- ::TSMRemoveDocumentProperty(doc,
- kTSMDocumentEnabledInputSourcesPropertyTag);
- }
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-void
-IMEInputHandler::ResetTimer()
-{
- NS_ASSERTION(mPendingMethods != 0,
- "There are not pending methods, why this is called?");
- if (mTimer) {
- mTimer->Cancel();
- } else {
- mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
- NS_ENSURE_TRUE(mTimer, );
- }
- mTimer->InitWithFuncCallback(FlushPendingMethods, this, 0,
- nsITimer::TYPE_ONE_SHOT);
-}
-
-void
-IMEInputHandler::ExecutePendingMethods()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- if (mTimer) {
- mTimer->Cancel();
- mTimer = nullptr;
- }
-
- if (![[NSApplication sharedApplication] isActive]) {
- mIsInFocusProcessing = false;
- // If we're not active, we should retry at focus event
- return;
- }
-
- uint32_t pendingMethods = mPendingMethods;
- // First, reset the pending method flags because if each methods cannot
- // run now, they can reentry to the pending flags by theirselves.
- mPendingMethods = 0;
-
- if (pendingMethods & kDiscardIMEComposition)
- DiscardIMEComposition();
- if (pendingMethods & kSyncASCIICapableOnly)
- SyncASCIICapableOnly();
- if (pendingMethods & kNotifyIMEOfFocusChangeInGecko) {
- NotifyIMEOfFocusChangeInGecko();
- }
-
- mIsInFocusProcessing = false;
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-#pragma mark -
-
-
-/******************************************************************************
- *
- * IMEInputHandler implementation (native event handlers)
- *
- ******************************************************************************/
-
-TextRangeType
-IMEInputHandler::ConvertToTextRangeType(uint32_t aUnderlineStyle,
- NSRange& aSelectedRange)
-{
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::ConvertToTextRangeType, "
- "aUnderlineStyle=%llu, aSelectedRange.length=%llu,",
- this, aUnderlineStyle, aSelectedRange.length));
-
- // We assume that aUnderlineStyle is NSUnderlineStyleSingle or
- // NSUnderlineStyleThick. NSUnderlineStyleThick should indicate a selected
- // clause. Otherwise, should indicate non-selected clause.
-
- if (aSelectedRange.length == 0) {
- switch (aUnderlineStyle) {
- case NSUnderlineStyleSingle:
- return TextRangeType::eRawClause;
- case NSUnderlineStyleThick:
- return TextRangeType::eSelectedRawClause;
- default:
- NS_WARNING("Unexpected line style");
- return TextRangeType::eSelectedRawClause;
- }
- }
-
- switch (aUnderlineStyle) {
- case NSUnderlineStyleSingle:
- return TextRangeType::eConvertedClause;
- case NSUnderlineStyleThick:
- return TextRangeType::eSelectedClause;
- default:
- NS_WARNING("Unexpected line style");
- return TextRangeType::eSelectedClause;
- }
-}
-
-uint32_t
-IMEInputHandler::GetRangeCount(NSAttributedString *aAttrString)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
-
- // Iterate through aAttrString for the NSUnderlineStyleAttributeName and
- // count the different segments adjusting limitRange as we go.
- uint32_t count = 0;
- NSRange effectiveRange;
- NSRange limitRange = NSMakeRange(0, [aAttrString length]);
- while (limitRange.length > 0) {
- [aAttrString attribute:NSUnderlineStyleAttributeName
- atIndex:limitRange.location
- longestEffectiveRange:&effectiveRange
- inRange:limitRange];
- limitRange =
- NSMakeRange(NSMaxRange(effectiveRange),
- NSMaxRange(limitRange) - NSMaxRange(effectiveRange));
- count++;
- }
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::GetRangeCount, aAttrString=\"%s\", count=%llu",
- this, GetCharacters([aAttrString string]), count));
-
- return count;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0);
-}
-
-already_AddRefed<mozilla::TextRangeArray>
-IMEInputHandler::CreateTextRangeArray(NSAttributedString *aAttrString,
- NSRange& aSelectedRange)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
-
- RefPtr<mozilla::TextRangeArray> textRangeArray =
- new mozilla::TextRangeArray();
-
- // Note that we shouldn't append ranges when composition string
- // is empty because it may cause TextComposition confused.
- if (![aAttrString length]) {
- return textRangeArray.forget();
- }
-
- // Convert the Cocoa range into the TextRange Array used in Gecko.
- // Iterate through the attributed string and map the underline attribute to
- // Gecko IME textrange attributes. We may need to change the code here if
- // we change the implementation of validAttributesForMarkedText.
- NSRange limitRange = NSMakeRange(0, [aAttrString length]);
- uint32_t rangeCount = GetRangeCount(aAttrString);
- for (uint32_t i = 0; i < rangeCount && limitRange.length > 0; i++) {
- NSRange effectiveRange;
- id attributeValue = [aAttrString attribute:NSUnderlineStyleAttributeName
- atIndex:limitRange.location
- longestEffectiveRange:&effectiveRange
- inRange:limitRange];
-
- TextRange range;
- range.mStartOffset = effectiveRange.location;
- range.mEndOffset = NSMaxRange(effectiveRange);
- range.mRangeType =
- ConvertToTextRangeType([attributeValue intValue], aSelectedRange);
- textRangeArray->AppendElement(range);
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::CreateTextRangeArray, "
- "range={ mStartOffset=%llu, mEndOffset=%llu, mRangeType=%s }",
- this, range.mStartOffset, range.mEndOffset,
- ToChar(range.mRangeType)));
-
- limitRange =
- NSMakeRange(NSMaxRange(effectiveRange),
- NSMaxRange(limitRange) - NSMaxRange(effectiveRange));
- }
-
- // Get current caret position.
- TextRange range;
- range.mStartOffset = aSelectedRange.location + aSelectedRange.length;
- range.mEndOffset = range.mStartOffset;
- range.mRangeType = TextRangeType::eCaret;
- textRangeArray->AppendElement(range);
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::CreateTextRangeArray, "
- "range={ mStartOffset=%llu, mEndOffset=%llu, mRangeType=%s }",
- this, range.mStartOffset, range.mEndOffset,
- ToChar(range.mRangeType)));
-
- return textRangeArray.forget();
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSNULL;
-}
-
-bool
-IMEInputHandler::DispatchCompositionStartEvent()
-{
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::DispatchCompositionStartEvent, "
- "mSelectedRange={ location=%llu, length=%llu }, Destroyed()=%s, "
- "mView=%p, mWidget=%p, inputContext=%p, mIsIMEComposing=%s",
- this, SelectedRange().location, mSelectedRange.length,
- TrueOrFalse(Destroyed()), mView, mWidget,
- mView ? [mView inputContext] : nullptr, TrueOrFalse(mIsIMEComposing)));
-
- RefPtr<IMEInputHandler> kungFuDeathGrip(this);
-
- nsresult rv = mDispatcher->BeginNativeInputTransaction();
- if (NS_WARN_IF(NS_FAILED(rv))) {
- MOZ_LOG(gLog, LogLevel::Error,
- ("%p IMEInputHandler::DispatchCompositionStartEvent, "
- "FAILED, due to BeginNativeInputTransaction() failure", this));
- return false;
- }
-
- NS_ASSERTION(!mIsIMEComposing, "There is a composition already");
- mIsIMEComposing = true;
-
- nsEventStatus status;
- rv = mDispatcher->StartComposition(status);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- MOZ_LOG(gLog, LogLevel::Error,
- ("%p IMEInputHandler::DispatchCompositionStartEvent, "
- "FAILED, due to StartComposition() failure", this));
- return false;
- }
-
- if (Destroyed()) {
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::DispatchCompositionStartEvent, "
- "destroyed by compositionstart event", this));
- return false;
- }
-
- // FYI: compositionstart may cause committing composition by the webapp.
- if (!mIsIMEComposing) {
- return false;
- }
-
- // FYI: The selection range might have been modified by a compositionstart
- // event handler.
- mIMECompositionStart = SelectedRange().location;
- return true;
-}
-
-bool
-IMEInputHandler::DispatchCompositionChangeEvent(const nsString& aText,
- NSAttributedString* aAttrString,
- NSRange& aSelectedRange)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::DispatchCompositionChangeEvent, "
- "aText=\"%s\", aAttrString=\"%s\", "
- "aSelectedRange={ location=%llu, length=%llu }, Destroyed()=%s, mView=%p, "
- "mWidget=%p, inputContext=%p, mIsIMEComposing=%s",
- this, NS_ConvertUTF16toUTF8(aText).get(),
- GetCharacters([aAttrString string]),
- aSelectedRange.location, aSelectedRange.length,
- TrueOrFalse(Destroyed()), mView, mWidget,
- mView ? [mView inputContext] : nullptr, TrueOrFalse(mIsIMEComposing)));
-
- NS_ENSURE_TRUE(!Destroyed(), false);
-
- NS_ASSERTION(mIsIMEComposing, "We're not in composition");
-
- RefPtr<IMEInputHandler> kungFuDeathGrip(this);
-
- nsresult rv = mDispatcher->BeginNativeInputTransaction();
- if (NS_WARN_IF(NS_FAILED(rv))) {
- MOZ_LOG(gLog, LogLevel::Error,
- ("%p IMEInputHandler::DispatchCompositionChangeEvent, "
- "FAILED, due to BeginNativeInputTransaction() failure", this));
- return false;
- }
-
- RefPtr<TextRangeArray> rangeArray =
- CreateTextRangeArray(aAttrString, aSelectedRange);
-
- rv = mDispatcher->SetPendingComposition(aText, rangeArray);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- MOZ_LOG(gLog, LogLevel::Error,
- ("%p IMEInputHandler::DispatchCompositionChangeEvent, "
- "FAILED, due to SetPendingComposition() failure", this));
- return false;
- }
-
- mSelectedRange.location = mIMECompositionStart + aSelectedRange.location;
- mSelectedRange.length = aSelectedRange.length;
-
- if (mIMECompositionString) {
- [mIMECompositionString release];
- }
- mIMECompositionString = [[aAttrString string] retain];
-
- nsEventStatus status;
- rv = mDispatcher->FlushPendingComposition(status);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- MOZ_LOG(gLog, LogLevel::Error,
- ("%p IMEInputHandler::DispatchCompositionChangeEvent, "
- "FAILED, due to FlushPendingComposition() failure", this));
- return false;
- }
-
- if (Destroyed()) {
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::DispatchCompositionChangeEvent, "
- "destroyed by compositionchange event", this));
- return false;
- }
-
- // FYI: compositionstart may cause committing composition by the webapp.
- return mIsIMEComposing;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
-}
-
-bool
-IMEInputHandler::DispatchCompositionCommitEvent(const nsAString* aCommitString)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::DispatchCompositionCommitEvent, "
- "aCommitString=0x%p (\"%s\"), Destroyed()=%s, mView=%p, mWidget=%p, "
- "inputContext=%p, mIsIMEComposing=%s",
- this, aCommitString,
- aCommitString ? NS_ConvertUTF16toUTF8(*aCommitString).get() : "",
- TrueOrFalse(Destroyed()), mView, mWidget,
- mView ? [mView inputContext] : nullptr, TrueOrFalse(mIsIMEComposing)));
-
- NS_ASSERTION(mIsIMEComposing, "We're not in composition");
-
- RefPtr<IMEInputHandler> kungFuDeathGrip(this);
-
- if (!Destroyed()) {
- // IME may query selection immediately after this, however, in e10s mode,
- // OnSelectionChange() will be called asynchronously. Until then, we
- // should emulate expected selection range if the webapp does nothing.
- mSelectedRange.location = mIMECompositionStart;
- if (aCommitString) {
- mSelectedRange.location += aCommitString->Length();
- } else if (mIMECompositionString) {
- nsAutoString commitString;
- nsCocoaUtils::GetStringForNSString(mIMECompositionString, commitString);
- mSelectedRange.location += commitString.Length();
- }
- mSelectedRange.length = 0;
-
- nsresult rv = mDispatcher->BeginNativeInputTransaction();
- if (NS_WARN_IF(NS_FAILED(rv))) {
- MOZ_LOG(gLog, LogLevel::Error,
- ("%p IMEInputHandler::DispatchCompositionCommitEvent, "
- "FAILED, due to BeginNativeInputTransaction() failure", this));
- } else {
- nsEventStatus status;
- rv = mDispatcher->CommitComposition(status, aCommitString);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- MOZ_LOG(gLog, LogLevel::Error,
- ("%p IMEInputHandler::DispatchCompositionCommitEvent, "
- "FAILED, due to BeginNativeInputTransaction() failure", this));
- }
- }
- }
-
- mIsIMEComposing = false;
- mIMECompositionStart = UINT32_MAX;
- if (mIMECompositionString) {
- [mIMECompositionString release];
- mIMECompositionString = nullptr;
- }
-
- if (Destroyed()) {
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::DispatchCompositionCommitEvent, "
- "destroyed by compositioncommit event", this));
- return false;
- }
-
- return true;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
-}
-
-void
-IMEInputHandler::InsertTextAsCommittingComposition(
- NSAttributedString* aAttrString,
- NSRange* aReplacementRange)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::InsertTextAsCommittingComposition, "
- "aAttrString=\"%s\", aReplacementRange=%p { location=%llu, length=%llu }, "
- "Destroyed()=%s, IsIMEComposing()=%s, "
- "mMarkedRange={ location=%llu, length=%llu }",
- this, GetCharacters([aAttrString string]), aReplacementRange,
- aReplacementRange ? aReplacementRange->location : 0,
- aReplacementRange ? aReplacementRange->length : 0,
- TrueOrFalse(Destroyed()), TrueOrFalse(IsIMEComposing()),
- mMarkedRange.location, mMarkedRange.length));
-
- if (IgnoreIMECommit()) {
- MOZ_CRASH("IMEInputHandler::InsertTextAsCommittingComposition() must not"
- "be called while canceling the composition");
- }
-
- if (Destroyed()) {
- return;
- }
-
- // First, commit current composition with the latest composition string if the
- // replacement range is different from marked range.
- if (IsIMEComposing() && aReplacementRange &&
- aReplacementRange->location != NSNotFound &&
- !NSEqualRanges(MarkedRange(), *aReplacementRange)) {
- if (!DispatchCompositionCommitEvent()) {
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::InsertTextAsCommittingComposition, "
- "destroyed by commiting composition for setting replacement range",
- this));
- return;
- }
- }
-
- RefPtr<IMEInputHandler> kungFuDeathGrip(this);
-
- nsString str;
- nsCocoaUtils::GetStringForNSString([aAttrString string], str);
-
- if (!IsIMEComposing()) {
- // If there is no selection and replacement range is specified, set the
- // range as selection.
- if (aReplacementRange && aReplacementRange->location != NSNotFound &&
- !NSEqualRanges(SelectedRange(), *aReplacementRange)) {
- NS_ENSURE_TRUE_VOID(SetSelection(*aReplacementRange));
- }
-
- if (!DispatchCompositionStartEvent()) {
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::InsertTextAsCommittingComposition, "
- "cannot continue handling composition after compositionstart", this));
- return;
- }
- }
-
- if (!DispatchCompositionCommitEvent(&str)) {
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::InsertTextAsCommittingComposition, "
- "destroyed by compositioncommit event", this));
- return;
- }
-
- mMarkedRange = NSMakeRange(NSNotFound, 0);
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-void
-IMEInputHandler::SetMarkedText(NSAttributedString* aAttrString,
- NSRange& aSelectedRange,
- NSRange* aReplacementRange)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- KeyEventState* currentKeyEvent = GetCurrentKeyEvent();
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::SetMarkedText, "
- "aAttrString=\"%s\", aSelectedRange={ location=%llu, length=%llu }, "
- "aReplacementRange=%p { location=%llu, length=%llu }, "
- "Destroyed()=%s, IgnoreIMEComposition()=%s, IsIMEComposing()=%s, "
- "mMarkedRange={ location=%llu, length=%llu }, keyevent=%p, "
- "keydownHandled=%s, keypressDispatched=%s, causedOtherKeyEvents=%s, "
- "compositionDispatched=%s",
- this, GetCharacters([aAttrString string]),
- aSelectedRange.location, aSelectedRange.length, aReplacementRange,
- aReplacementRange ? aReplacementRange->location : 0,
- aReplacementRange ? aReplacementRange->length : 0,
- TrueOrFalse(Destroyed()), TrueOrFalse(IgnoreIMEComposition()),
- TrueOrFalse(IsIMEComposing()),
- mMarkedRange.location, mMarkedRange.length,
- currentKeyEvent ? currentKeyEvent->mKeyEvent : nullptr,
- currentKeyEvent ?
- TrueOrFalse(currentKeyEvent->mKeyDownHandled) : "N/A",
- currentKeyEvent ?
- TrueOrFalse(currentKeyEvent->mKeyPressDispatched) : "N/A",
- currentKeyEvent ?
- TrueOrFalse(currentKeyEvent->mCausedOtherKeyEvents) : "N/A",
- currentKeyEvent ?
- TrueOrFalse(currentKeyEvent->mCompositionDispatched) : "N/A"));
-
- // If SetMarkedText() is called during handling a key press, that means that
- // the key event caused this composition. So, keypress event shouldn't
- // be dispatched later, let's mark the key event causing composition event.
- if (currentKeyEvent) {
- currentKeyEvent->mCompositionDispatched = true;
- }
-
- if (Destroyed() || IgnoreIMEComposition()) {
- return;
- }
-
- RefPtr<IMEInputHandler> kungFuDeathGrip(this);
-
- // First, commit current composition with the latest composition string if the
- // replacement range is different from marked range.
- if (IsIMEComposing() && aReplacementRange &&
- aReplacementRange->location != NSNotFound &&
- !NSEqualRanges(MarkedRange(), *aReplacementRange)) {
- AutoRestore<bool> ignoreIMECommit(mIgnoreIMECommit);
- mIgnoreIMECommit = false;
- if (!DispatchCompositionCommitEvent()) {
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::SetMarkedText, "
- "destroyed by commiting composition for setting replacement range",
- this));
- return;
- }
- }
-
- nsString str;
- nsCocoaUtils::GetStringForNSString([aAttrString string], str);
-
- mMarkedRange.length = str.Length();
-
- if (!IsIMEComposing() && !str.IsEmpty()) {
- // If there is no selection and replacement range is specified, set the
- // range as selection.
- if (aReplacementRange && aReplacementRange->location != NSNotFound &&
- !NSEqualRanges(SelectedRange(), *aReplacementRange)) {
- NS_ENSURE_TRUE_VOID(SetSelection(*aReplacementRange));
- }
-
- mMarkedRange.location = SelectedRange().location;
-
- if (!DispatchCompositionStartEvent()) {
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::SetMarkedText, cannot continue handling "
- "composition after dispatching compositionstart", this));
- return;
- }
- }
-
- if (!str.IsEmpty()) {
- if (!DispatchCompositionChangeEvent(str, aAttrString, aSelectedRange)) {
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::SetMarkedText, cannot continue handling "
- "composition after dispatching compositionchange", this));
- }
- return;
- }
-
- // If the composition string becomes empty string, we should commit
- // current composition.
- if (!DispatchCompositionCommitEvent(&EmptyString())) {
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::SetMarkedText, "
- "destroyed by compositioncommit event", this));
- }
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-NSAttributedString*
-IMEInputHandler::GetAttributedSubstringFromRange(NSRange& aRange,
- NSRange* aActualRange)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::GetAttributedSubstringFromRange, "
- "aRange={ location=%llu, length=%llu }, aActualRange=%p, Destroyed()=%s",
- this, aRange.location, aRange.length, aActualRange,
- TrueOrFalse(Destroyed())));
-
- if (aActualRange) {
- *aActualRange = NSMakeRange(NSNotFound, 0);
- }
-
- if (Destroyed() || aRange.location == NSNotFound || aRange.length == 0) {
- return nil;
- }
-
- RefPtr<IMEInputHandler> kungFuDeathGrip(this);
-
- // If we're in composing, the queried range may be in the composition string.
- // In such case, we should use mIMECompositionString since if the composition
- // string is handled by a remote process, the content cache may be out of
- // date.
- // XXX Should we set composition string attributes? Although, Blink claims
- // that some attributes of marked text are supported, but they return
- // just marked string without any style. So, let's keep current behavior
- // at least for now.
- NSUInteger compositionLength =
- mIMECompositionString ? [mIMECompositionString length] : 0;
- if (mIMECompositionStart != UINT32_MAX &&
- mIMECompositionStart >= aRange.location &&
- mIMECompositionStart + compositionLength <=
- aRange.location + aRange.length) {
- NSRange range =
- NSMakeRange(aRange.location - mIMECompositionStart, aRange.length);
- NSString* nsstr = [mIMECompositionString substringWithRange:range];
- NSMutableAttributedString* result =
- [[[NSMutableAttributedString alloc] initWithString:nsstr
- attributes:nil] autorelease];
- // XXX We cannot return font information in this case. However, this
- // case must occur only when IME tries to confirm if composing string
- // is handled as expected.
- if (aActualRange) {
- *aActualRange = aRange;
- }
-
- if (MOZ_LOG_TEST(gLog, LogLevel::Info)) {
- nsAutoString str;
- nsCocoaUtils::GetStringForNSString(nsstr, str);
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::GetAttributedSubstringFromRange, "
- "computed with mIMECompositionString (result string=\"%s\")",
- this, NS_ConvertUTF16toUTF8(str).get()));
- }
- return result;
- }
-
- nsAutoString str;
- WidgetQueryContentEvent textContent(true, eQueryTextContent, mWidget);
- WidgetQueryContentEvent::Options options;
- int64_t startOffset = aRange.location;
- if (IsIMEComposing()) {
- // The composition may be at different offset from the selection start
- // offset at dispatching compositionstart because start of composition
- // is fixed when composition string becomes non-empty in the editor.
- // Therefore, we need to use query event which is relative to insertion
- // point.
- options.mRelativeToInsertionPoint = true;
- startOffset -= mIMECompositionStart;
- }
- textContent.InitForQueryTextContent(startOffset, aRange.length, options);
- textContent.RequestFontRanges();
- DispatchEvent(textContent);
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::GetAttributedSubstringFromRange, "
- "textContent={ mSucceeded=%s, mReply={ mString=\"%s\", mOffset=%u } }",
- this, TrueOrFalse(textContent.mSucceeded),
- NS_ConvertUTF16toUTF8(textContent.mReply.mString).get(),
- textContent.mReply.mOffset));
-
- if (!textContent.mSucceeded) {
- return nil;
- }
-
- // We don't set vertical information at this point. If required,
- // OS will calls drawsVerticallyForCharacterAtIndex.
- NSMutableAttributedString* result =
- nsCocoaUtils::GetNSMutableAttributedString(textContent.mReply.mString,
- textContent.mReply.mFontRanges,
- false,
- mWidget->BackingScaleFactor());
- if (aActualRange) {
- aActualRange->location = textContent.mReply.mOffset;
- aActualRange->length = textContent.mReply.mString.Length();
- }
- return result;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
-}
-
-bool
-IMEInputHandler::HasMarkedText()
-{
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::HasMarkedText, "
- "mMarkedRange={ location=%llu, length=%llu }",
- this, mMarkedRange.location, mMarkedRange.length));
-
- return (mMarkedRange.location != NSNotFound) && (mMarkedRange.length != 0);
-}
-
-NSRange
-IMEInputHandler::MarkedRange()
-{
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::MarkedRange, "
- "mMarkedRange={ location=%llu, length=%llu }",
- this, mMarkedRange.location, mMarkedRange.length));
-
- if (!HasMarkedText()) {
- return NSMakeRange(NSNotFound, 0);
- }
- return mMarkedRange;
-}
-
-NSRange
-IMEInputHandler::SelectedRange()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::SelectedRange, Destroyed()=%s, mSelectedRange={ "
- "location=%llu, length=%llu }",
- this, TrueOrFalse(Destroyed()), mSelectedRange.location,
- mSelectedRange.length));
-
- if (Destroyed()) {
- return mSelectedRange;
- }
-
- if (mSelectedRange.location != NSNotFound) {
- MOZ_ASSERT(mIMEHasFocus);
- return mSelectedRange;
- }
-
- RefPtr<IMEInputHandler> kungFuDeathGrip(this);
-
- WidgetQueryContentEvent selection(true, eQuerySelectedText, mWidget);
- DispatchEvent(selection);
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::SelectedRange, selection={ mSucceeded=%s, "
- "mReply={ mOffset=%u, mString.Length()=%u } }",
- this, TrueOrFalse(selection.mSucceeded), selection.mReply.mOffset,
- selection.mReply.mString.Length()));
-
- if (!selection.mSucceeded) {
- return mSelectedRange;
- }
-
- mWritingMode = selection.GetWritingMode();
- mRangeForWritingMode = NSMakeRange(selection.mReply.mOffset,
- selection.mReply.mString.Length());
-
- if (mIMEHasFocus) {
- mSelectedRange = mRangeForWritingMode;
- }
-
- return mRangeForWritingMode;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(mSelectedRange);
-}
-
-bool
-IMEInputHandler::DrawsVerticallyForCharacterAtIndex(uint32_t aCharIndex)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
-
- if (Destroyed()) {
- return false;
- }
-
- if (mRangeForWritingMode.location == NSNotFound) {
- // Update cached writing-mode value for the current selection.
- SelectedRange();
- }
-
- if (aCharIndex < mRangeForWritingMode.location ||
- aCharIndex > mRangeForWritingMode.location + mRangeForWritingMode.length) {
- // It's not clear to me whether this ever happens in practice, but if an
- // IME ever wants to query writing mode at an offset outside the current
- // selection, the writing-mode value may not be correct for the index.
- // In that case, use FirstRectForCharacterRange to get a fresh value.
- // This does more work than strictly necessary (we don't need the rect here),
- // but should be a rare case.
- NS_WARNING("DrawsVerticallyForCharacterAtIndex not using cached writing mode");
- NSRange range = NSMakeRange(aCharIndex, 1);
- NSRange actualRange;
- FirstRectForCharacterRange(range, &actualRange);
- }
-
- return mWritingMode.IsVertical();
-
- NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
-}
-
-NSRect
-IMEInputHandler::FirstRectForCharacterRange(NSRange& aRange,
- NSRange* aActualRange)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::FirstRectForCharacterRange, Destroyed()=%s, "
- "aRange={ location=%llu, length=%llu }, aActualRange=%p }",
- this, TrueOrFalse(Destroyed()), aRange.location, aRange.length,
- aActualRange));
-
- // XXX this returns first character rect or caret rect, it is limitation of
- // now. We need more work for returns first line rect. But current
- // implementation is enough for IMEs.
-
- NSRect rect = NSMakeRect(0.0, 0.0, 0.0, 0.0);
- NSRange actualRange = NSMakeRange(NSNotFound, 0);
- if (aActualRange) {
- *aActualRange = actualRange;
- }
- if (Destroyed() || aRange.location == NSNotFound) {
- return rect;
- }
-
- RefPtr<IMEInputHandler> kungFuDeathGrip(this);
-
- LayoutDeviceIntRect r;
- bool useCaretRect = (aRange.length == 0);
- if (!useCaretRect) {
- WidgetQueryContentEvent charRect(true, eQueryTextRect, mWidget);
- WidgetQueryContentEvent::Options options;
- int64_t startOffset = aRange.location;
- if (IsIMEComposing()) {
- // The composition may be at different offset from the selection start
- // offset at dispatching compositionstart because start of composition
- // is fixed when composition string becomes non-empty in the editor.
- // Therefore, we need to use query event which is relative to insertion
- // point.
- options.mRelativeToInsertionPoint = true;
- startOffset -= mIMECompositionStart;
- }
- charRect.InitForQueryTextRect(startOffset, 1, options);
- DispatchEvent(charRect);
- if (charRect.mSucceeded) {
- r = charRect.mReply.mRect;
- actualRange.location = charRect.mReply.mOffset;
- actualRange.length = charRect.mReply.mString.Length();
- mWritingMode = charRect.GetWritingMode();
- mRangeForWritingMode = actualRange;
- } else {
- useCaretRect = true;
- }
- }
-
- if (useCaretRect) {
- WidgetQueryContentEvent caretRect(true, eQueryCaretRect, mWidget);
- WidgetQueryContentEvent::Options options;
- int64_t startOffset = aRange.location;
- if (IsIMEComposing()) {
- // The composition may be at different offset from the selection start
- // offset at dispatching compositionstart because start of composition
- // is fixed when composition string becomes non-empty in the editor.
- // Therefore, we need to use query event which is relative to insertion
- // point.
- options.mRelativeToInsertionPoint = true;
- startOffset -= mIMECompositionStart;
- }
- caretRect.InitForQueryCaretRect(startOffset, options);
- DispatchEvent(caretRect);
- if (!caretRect.mSucceeded) {
- return rect;
- }
- r = caretRect.mReply.mRect;
- r.width = 0;
- actualRange.location = caretRect.mReply.mOffset;
- actualRange.length = 0;
- }
-
- nsIWidget* rootWidget = mWidget->GetTopLevelWidget();
- NSWindow* rootWindow =
- static_cast<NSWindow*>(rootWidget->GetNativeData(NS_NATIVE_WINDOW));
- NSView* rootView =
- static_cast<NSView*>(rootWidget->GetNativeData(NS_NATIVE_WIDGET));
- if (!rootWindow || !rootView) {
- return rect;
- }
- rect = nsCocoaUtils::DevPixelsToCocoaPoints(r, mWidget->BackingScaleFactor());
- rect = [rootView convertRect:rect toView:nil];
- rect.origin = nsCocoaUtils::ConvertPointToScreen(rootWindow, rect.origin);
-
- if (aActualRange) {
- *aActualRange = actualRange;
- }
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::FirstRectForCharacterRange, "
- "useCaretRect=%s rect={ x=%f, y=%f, width=%f, height=%f }, "
- "actualRange={ location=%llu, length=%llu }",
- this, TrueOrFalse(useCaretRect), rect.origin.x, rect.origin.y,
- rect.size.width, rect.size.height, actualRange.location,
- actualRange.length));
-
- return rect;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSMakeRect(0.0, 0.0, 0.0, 0.0));
-}
-
-NSUInteger
-IMEInputHandler::CharacterIndexForPoint(NSPoint& aPoint)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::CharacterIndexForPoint, aPoint={ x=%f, y=%f }",
- this, aPoint.x, aPoint.y));
-
- NSWindow* mainWindow = [NSApp mainWindow];
- if (!mWidget || !mainWindow) {
- return NSNotFound;
- }
-
- WidgetQueryContentEvent charAt(true, eQueryCharacterAtPoint, mWidget);
- NSPoint ptInWindow = nsCocoaUtils::ConvertPointFromScreen(mainWindow, aPoint);
- NSPoint ptInView = [mView convertPoint:ptInWindow fromView:nil];
- charAt.mRefPoint.x =
- static_cast<int32_t>(ptInView.x) * mWidget->BackingScaleFactor();
- charAt.mRefPoint.y =
- static_cast<int32_t>(ptInView.y) * mWidget->BackingScaleFactor();
- mWidget->DispatchWindowEvent(charAt);
- if (!charAt.mSucceeded ||
- charAt.mReply.mOffset == WidgetQueryContentEvent::NOT_FOUND ||
- charAt.mReply.mOffset >= static_cast<uint32_t>(NSNotFound)) {
- return NSNotFound;
- }
-
- return charAt.mReply.mOffset;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSNotFound);
-}
-
-extern "C" {
-extern NSString *NSTextInputReplacementRangeAttributeName;
-}
-
-NSArray*
-IMEInputHandler::GetValidAttributesForMarkedText()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::GetValidAttributesForMarkedText", this));
-
- // Return same attributes as Chromium (see render_widget_host_view_mac.mm)
- // because most IMEs must be tested with Safari (OS default) and Chrome
- // (having most market share). Therefore, we need to follow their behavior.
- // XXX It might be better to reuse an array instance for this result because
- // this may be called a lot. Note that Chromium does so.
- return [NSArray arrayWithObjects:NSUnderlineStyleAttributeName,
- NSUnderlineColorAttributeName,
- NSMarkedClauseSegmentAttributeName,
- NSTextInputReplacementRangeAttributeName,
- nil];
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
-}
-
-
-#pragma mark -
-
-
-/******************************************************************************
- *
- * IMEInputHandler implementation #2
- *
- ******************************************************************************/
-
-IMEInputHandler::IMEInputHandler(nsChildView* aWidget,
- NSView<mozView> *aNativeView)
- : TextInputHandlerBase(aWidget, aNativeView)
- , mPendingMethods(0)
- , mIMECompositionString(nullptr)
- , mIMECompositionStart(UINT32_MAX)
- , mIsIMEComposing(false)
- , mIsIMEEnabled(true)
- , mIsASCIICapableOnly(false)
- , mIgnoreIMECommit(false)
- , mIsInFocusProcessing(false)
- , mIMEHasFocus(false)
-{
- InitStaticMembers();
-
- mMarkedRange.location = NSNotFound;
- mMarkedRange.length = 0;
- mSelectedRange.location = NSNotFound;
- mSelectedRange.length = 0;
-}
-
-IMEInputHandler::~IMEInputHandler()
-{
- if (mTimer) {
- mTimer->Cancel();
- mTimer = nullptr;
- }
- if (sFocusedIMEHandler == this) {
- sFocusedIMEHandler = nullptr;
- }
- if (mIMECompositionString) {
- [mIMECompositionString release];
- mIMECompositionString = nullptr;
- }
-}
-
-void
-IMEInputHandler::OnFocusChangeInGecko(bool aFocus)
-{
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::OnFocusChangeInGecko, aFocus=%s, Destroyed()=%s, "
- "sFocusedIMEHandler=%p",
- this, TrueOrFalse(aFocus), TrueOrFalse(Destroyed()), sFocusedIMEHandler));
-
- mSelectedRange.location = NSNotFound; // Marking dirty
- mIMEHasFocus = aFocus;
-
- // This is called when the native focus is changed and when the native focus
- // isn't changed but the focus is changed in Gecko.
- if (!aFocus) {
- if (sFocusedIMEHandler == this)
- sFocusedIMEHandler = nullptr;
- return;
- }
-
- sFocusedIMEHandler = this;
- mIsInFocusProcessing = true;
-
- // We need to notify IME of focus change in Gecko as native focus change
- // because the window level of the focused element in Gecko may be changed.
- mPendingMethods |= kNotifyIMEOfFocusChangeInGecko;
- ResetTimer();
-}
-
-bool
-IMEInputHandler::OnDestroyWidget(nsChildView* aDestroyingWidget)
-{
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::OnDestroyWidget, aDestroyingWidget=%p, "
- "sFocusedIMEHandler=%p, IsIMEComposing()=%s",
- this, aDestroyingWidget, sFocusedIMEHandler,
- TrueOrFalse(IsIMEComposing())));
-
- // If we're not focused, the focused IMEInputHandler may have been
- // created by another widget/nsChildView.
- if (sFocusedIMEHandler && sFocusedIMEHandler != this) {
- sFocusedIMEHandler->OnDestroyWidget(aDestroyingWidget);
- }
-
- if (!TextInputHandlerBase::OnDestroyWidget(aDestroyingWidget)) {
- return false;
- }
-
- if (IsIMEComposing()) {
- // If our view is in the composition, we should clean up it.
- CancelIMEComposition();
- }
-
- mSelectedRange.location = NSNotFound; // Marking dirty
- mIMEHasFocus = false;
-
- return true;
-}
-
-void
-IMEInputHandler::SendCommittedText(NSString *aString)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::SendCommittedText, mView=%p, mWidget=%p, "
- "inputContext=%p, mIsIMEComposing=%s",
- this, mView, mWidget, mView ? [mView inputContext] : nullptr,
- TrueOrFalse(mIsIMEComposing), mWidget));
-
- NS_ENSURE_TRUE(mWidget, );
- // XXX We should send the string without mView.
- if (!mView) {
- return;
- }
-
- NSAttributedString* attrStr =
- [[NSAttributedString alloc] initWithString:aString];
- if ([mView conformsToProtocol:@protocol(NSTextInputClient)]) {
- NSObject<NSTextInputClient>* textInputClient =
- static_cast<NSObject<NSTextInputClient>*>(mView);
- [textInputClient insertText:attrStr
- replacementRange:NSMakeRange(NSNotFound, 0)];
- }
-
- // Last resort. If we cannot retrieve NSTextInputProtocol from mView
- // or blocking to call our InsertText(), we should call InsertText()
- // directly to commit composition forcibly.
- if (mIsIMEComposing) {
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::SendCommittedText, trying to insert text directly "
- "due to IME not calling our InsertText()", this));
- static_cast<TextInputHandler*>(this)->InsertText(attrStr);
- MOZ_ASSERT(!mIsIMEComposing);
- }
-
- [attrStr release];
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-void
-IMEInputHandler::KillIMEComposition()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::KillIMEComposition, mView=%p, mWidget=%p, "
- "inputContext=%p, mIsIMEComposing=%s, "
- "Destroyed()=%s, IsFocused()=%s",
- this, mView, mWidget, mView ? [mView inputContext] : nullptr,
- TrueOrFalse(mIsIMEComposing), TrueOrFalse(Destroyed()),
- TrueOrFalse(IsFocused())));
-
- if (Destroyed()) {
- return;
- }
-
- if (IsFocused()) {
- NS_ENSURE_TRUE_VOID(mView);
- NSTextInputContext* inputContext = [mView inputContext];
- NS_ENSURE_TRUE_VOID(inputContext);
- [inputContext discardMarkedText];
- return;
- }
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::KillIMEComposition, Pending...", this));
-
- // Commit the composition internally.
- SendCommittedText(mIMECompositionString);
- NS_ASSERTION(!mIsIMEComposing, "We're still in a composition");
- // The pending method will be fired by the next focus event.
- mPendingMethods |= kDiscardIMEComposition;
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-void
-IMEInputHandler::CommitIMEComposition()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- if (!IsIMEComposing())
- return;
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::CommitIMEComposition, mIMECompositionString=%s",
- this, GetCharacters(mIMECompositionString)));
-
- KillIMEComposition();
-
- if (!IsIMEComposing())
- return;
-
- // If the composition is still there, KillIMEComposition only kills the
- // composition in TSM. We also need to finish the our composition too.
- SendCommittedText(mIMECompositionString);
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-void
-IMEInputHandler::CancelIMEComposition()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- if (!IsIMEComposing())
- return;
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::CancelIMEComposition, mIMECompositionString=%s",
- this, GetCharacters(mIMECompositionString)));
-
- // For canceling the current composing, we need to ignore the param of
- // insertText. But this code is ugly...
- mIgnoreIMECommit = true;
- KillIMEComposition();
- mIgnoreIMECommit = false;
-
- if (!IsIMEComposing())
- return;
-
- // If the composition is still there, KillIMEComposition only kills the
- // composition in TSM. We also need to kill the our composition too.
- SendCommittedText(@"");
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-bool
-IMEInputHandler::IsFocused()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- NS_ENSURE_TRUE(!Destroyed(), false);
- NSWindow* window = [mView window];
- NS_ENSURE_TRUE(window, false);
- return [window firstResponder] == mView &&
- [window isKeyWindow] &&
- [[NSApplication sharedApplication] isActive];
-
- NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
-}
-
-bool
-IMEInputHandler::IsIMEOpened()
-{
- TISInputSourceWrapper tis;
- tis.InitByCurrentInputSource();
- return tis.IsOpenedIMEMode();
-}
-
-void
-IMEInputHandler::SetASCIICapableOnly(bool aASCIICapableOnly)
-{
- if (aASCIICapableOnly == mIsASCIICapableOnly)
- return;
-
- CommitIMEComposition();
- mIsASCIICapableOnly = aASCIICapableOnly;
- SyncASCIICapableOnly();
-}
-
-void
-IMEInputHandler::EnableIME(bool aEnableIME)
-{
- if (aEnableIME == mIsIMEEnabled)
- return;
-
- CommitIMEComposition();
- mIsIMEEnabled = aEnableIME;
-}
-
-void
-IMEInputHandler::SetIMEOpenState(bool aOpenIME)
-{
- if (!IsFocused() || IsIMEOpened() == aOpenIME)
- return;
-
- if (!aOpenIME) {
- TISInputSourceWrapper tis;
- tis.InitByCurrentASCIICapableInputSource();
- tis.Select();
- return;
- }
-
- // If we know the latest IME opened mode, we should select it.
- if (sLatestIMEOpenedModeInputSourceID) {
- TISInputSourceWrapper tis;
- tis.InitByInputSourceID(sLatestIMEOpenedModeInputSourceID);
- tis.Select();
- return;
- }
-
- // XXX If the current input source is a mode of IME, we should turn on it,
- // but we haven't found such way...
-
- // Finally, we should refer the system locale but this is a little expensive,
- // we shouldn't retry this (if it was succeeded, we already set
- // sLatestIMEOpenedModeInputSourceID at that time).
- static bool sIsPrefferredIMESearched = false;
- if (sIsPrefferredIMESearched)
- return;
- sIsPrefferredIMESearched = true;
- OpenSystemPreferredLanguageIME();
-}
-
-void
-IMEInputHandler::OpenSystemPreferredLanguageIME()
-{
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::OpenSystemPreferredLanguageIME", this));
-
- CFArrayRef langList = ::CFLocaleCopyPreferredLanguages();
- if (!langList) {
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::OpenSystemPreferredLanguageIME, langList is NULL",
- this));
- return;
- }
- CFIndex count = ::CFArrayGetCount(langList);
- for (CFIndex i = 0; i < count; i++) {
- CFLocaleRef locale =
- ::CFLocaleCreate(kCFAllocatorDefault,
- static_cast<CFStringRef>(::CFArrayGetValueAtIndex(langList, i)));
- if (!locale) {
- continue;
- }
-
- bool changed = false;
- CFStringRef lang = static_cast<CFStringRef>(
- ::CFLocaleGetValue(locale, kCFLocaleLanguageCode));
- NS_ASSERTION(lang, "lang is null");
- if (lang) {
- TISInputSourceWrapper tis;
- tis.InitByLanguage(lang);
- if (tis.IsOpenedIMEMode()) {
- if (MOZ_LOG_TEST(gLog, LogLevel::Info)) {
- CFStringRef foundTIS;
- tis.GetInputSourceID(foundTIS);
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::OpenSystemPreferredLanguageIME, "
- "foundTIS=%s, lang=%s",
- this, GetCharacters(foundTIS), GetCharacters(lang)));
- }
- tis.Select();
- changed = true;
- }
- }
- ::CFRelease(locale);
- if (changed) {
- break;
- }
- }
- ::CFRelease(langList);
-}
-
-void
-IMEInputHandler::OnSelectionChange(const IMENotification& aIMENotification)
-{
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p IMEInputHandler::OnSelectionChange", this));
-
- if (aIMENotification.mSelectionChangeData.mOffset == UINT32_MAX) {
- mSelectedRange.location = NSNotFound;
- mSelectedRange.length = 0;
- mRangeForWritingMode.location = NSNotFound;
- mRangeForWritingMode.length = 0;
- return;
- }
-
- mWritingMode = aIMENotification.mSelectionChangeData.GetWritingMode();
- mRangeForWritingMode =
- NSMakeRange(aIMENotification.mSelectionChangeData.mOffset,
- aIMENotification.mSelectionChangeData.Length());
- if (mIMEHasFocus) {
- mSelectedRange = mRangeForWritingMode;
- }
-}
-
-bool
-IMEInputHandler::OnHandleEvent(NSEvent* aEvent)
-{
- if (!IsFocused()) {
- return false;
- }
- NSTextInputContext* inputContext = [mView inputContext];
- return [inputContext handleEvent:aEvent];
-}
-
-#pragma mark -
-
-
-/******************************************************************************
- *
- * TextInputHandlerBase implementation
- *
- ******************************************************************************/
-
-int32_t TextInputHandlerBase::sSecureEventInputCount = 0;
-
-NS_IMPL_ISUPPORTS(TextInputHandlerBase,
- TextEventDispatcherListener,
- nsISupportsWeakReference)
-
-TextInputHandlerBase::TextInputHandlerBase(nsChildView* aWidget,
- NSView<mozView> *aNativeView)
- : mWidget(aWidget)
- , mDispatcher(aWidget->GetTextEventDispatcher())
-{
- gHandlerInstanceCount++;
- mView = [aNativeView retain];
-}
-
-TextInputHandlerBase::~TextInputHandlerBase()
-{
- [mView release];
- if (--gHandlerInstanceCount == 0) {
- TISInputSourceWrapper::Shutdown();
- }
-}
-
-bool
-TextInputHandlerBase::OnDestroyWidget(nsChildView* aDestroyingWidget)
-{
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TextInputHandlerBase::OnDestroyWidget, "
- "aDestroyingWidget=%p, mWidget=%p",
- this, aDestroyingWidget, mWidget));
-
- if (aDestroyingWidget != mWidget) {
- return false;
- }
-
- mWidget = nullptr;
- mDispatcher = nullptr;
- return true;
-}
-
-bool
-TextInputHandlerBase::DispatchEvent(WidgetGUIEvent& aEvent)
-{
- return mWidget->DispatchWindowEvent(aEvent);
-}
-
-void
-TextInputHandlerBase::InitKeyEvent(NSEvent *aNativeKeyEvent,
- WidgetKeyboardEvent& aKeyEvent,
- const nsAString* aInsertString)
-{
- NS_ASSERTION(aNativeKeyEvent, "aNativeKeyEvent must not be NULL");
-
- if (mKeyboardOverride.mOverrideEnabled) {
- TISInputSourceWrapper tis;
- tis.InitByLayoutID(mKeyboardOverride.mKeyboardLayout, true);
- tis.InitKeyEvent(aNativeKeyEvent, aKeyEvent, aInsertString);
- return;
- }
- TISInputSourceWrapper::CurrentInputSource().
- InitKeyEvent(aNativeKeyEvent, aKeyEvent, aInsertString);
-}
-
-nsresult
-TextInputHandlerBase::SynthesizeNativeKeyEvent(
- int32_t aNativeKeyboardLayout,
- int32_t aNativeKeyCode,
- uint32_t aModifierFlags,
- const nsAString& aCharacters,
- const nsAString& aUnmodifiedCharacters)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- static const uint32_t sModifierFlagMap[][2] = {
- { nsIWidget::CAPS_LOCK, NSAlphaShiftKeyMask },
- { nsIWidget::SHIFT_L, NSShiftKeyMask | 0x0002 },
- { nsIWidget::SHIFT_R, NSShiftKeyMask | 0x0004 },
- { nsIWidget::CTRL_L, NSControlKeyMask | 0x0001 },
- { nsIWidget::CTRL_R, NSControlKeyMask | 0x2000 },
- { nsIWidget::ALT_L, NSAlternateKeyMask | 0x0020 },
- { nsIWidget::ALT_R, NSAlternateKeyMask | 0x0040 },
- { nsIWidget::COMMAND_L, NSCommandKeyMask | 0x0008 },
- { nsIWidget::COMMAND_R, NSCommandKeyMask | 0x0010 },
- { nsIWidget::NUMERIC_KEY_PAD, NSNumericPadKeyMask },
- { nsIWidget::HELP, NSHelpKeyMask },
- { nsIWidget::FUNCTION, NSFunctionKeyMask }
- };
-
- uint32_t modifierFlags = 0;
- for (uint32_t i = 0; i < ArrayLength(sModifierFlagMap); ++i) {
- if (aModifierFlags & sModifierFlagMap[i][0]) {
- modifierFlags |= sModifierFlagMap[i][1];
- }
- }
-
- NSInteger windowNumber = [[mView window] windowNumber];
- bool sendFlagsChangedEvent = IsModifierKey(aNativeKeyCode);
- NSEventType eventType = sendFlagsChangedEvent ? NSFlagsChanged : NSKeyDown;
- NSEvent* downEvent =
- [NSEvent keyEventWithType:eventType
- location:NSMakePoint(0,0)
- modifierFlags:modifierFlags
- timestamp:0
- windowNumber:windowNumber
- context:[NSGraphicsContext currentContext]
- characters:nsCocoaUtils::ToNSString(aCharacters)
- charactersIgnoringModifiers:nsCocoaUtils::ToNSString(aUnmodifiedCharacters)
- isARepeat:NO
- keyCode:aNativeKeyCode];
-
- NSEvent* upEvent = sendFlagsChangedEvent ?
- nil : nsCocoaUtils::MakeNewCocoaEventWithType(NSKeyUp, downEvent);
-
- if (downEvent && (sendFlagsChangedEvent || upEvent)) {
- KeyboardLayoutOverride currentLayout = mKeyboardOverride;
- mKeyboardOverride.mKeyboardLayout = aNativeKeyboardLayout;
- mKeyboardOverride.mOverrideEnabled = true;
- [NSApp sendEvent:downEvent];
- if (upEvent) {
- [NSApp sendEvent:upEvent];
- }
- // processKeyDownEvent and keyUp block exceptions so we're sure to
- // reach here to restore mKeyboardOverride
- mKeyboardOverride = currentLayout;
- }
-
- return NS_OK;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NSInteger
-TextInputHandlerBase::GetWindowLevel()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TextInputHandlerBase::GetWindowLevel, Destryoed()=%s",
- this, TrueOrFalse(Destroyed())));
-
- if (Destroyed()) {
- return NSNormalWindowLevel;
- }
-
- // When an <input> element on a XUL <panel> is focused, the actual focused view
- // is the panel's parent view (mView). But the editor is displayed on the
- // popped-up widget's view (editorView). We want the latter's window level.
- NSView<mozView>* editorView = mWidget->GetEditorView();
- NS_ENSURE_TRUE(editorView, NSNormalWindowLevel);
- NSInteger windowLevel = [[editorView window] level];
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TextInputHandlerBase::GetWindowLevel, windowLevel=%s (%X)",
- this, GetWindowLevelName(windowLevel), windowLevel));
-
- return windowLevel;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSNormalWindowLevel);
-}
-
-NS_IMETHODIMP
-TextInputHandlerBase::AttachNativeKeyEvent(WidgetKeyboardEvent& aKeyEvent)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- // Don't try to replace a native event if one already exists.
- // OS X doesn't have an OS modifier, can't make a native event.
- if (aKeyEvent.mNativeKeyEvent || aKeyEvent.mModifiers & MODIFIER_OS) {
- return NS_OK;
- }
-
- MOZ_LOG(gLog, LogLevel::Info,
- ("%p TextInputHandlerBase::AttachNativeKeyEvent, key=0x%X, char=0x%X, "
- "mod=0x%X", this, aKeyEvent.mKeyCode, aKeyEvent.mCharCode,
- aKeyEvent.mModifiers));
-
- NSEventType eventType;
- if (aKeyEvent.mMessage == eKeyUp) {
- eventType = NSKeyUp;
- } else {
- eventType = NSKeyDown;
- }
-
- static const uint32_t sModifierFlagMap[][2] = {
- { MODIFIER_SHIFT, NSShiftKeyMask },
- { MODIFIER_CONTROL, NSControlKeyMask },
- { MODIFIER_ALT, NSAlternateKeyMask },
- { MODIFIER_ALTGRAPH, NSAlternateKeyMask },
- { MODIFIER_META, NSCommandKeyMask },
- { MODIFIER_CAPSLOCK, NSAlphaShiftKeyMask },
- { MODIFIER_NUMLOCK, NSNumericPadKeyMask }
- };
-
- NSUInteger modifierFlags = 0;
- for (uint32_t i = 0; i < ArrayLength(sModifierFlagMap); ++i) {
- if (aKeyEvent.mModifiers & sModifierFlagMap[i][0]) {
- modifierFlags |= sModifierFlagMap[i][1];
- }
- }
-
- NSInteger windowNumber = [[mView window] windowNumber];
-
- NSString* characters;
- if (aKeyEvent.mCharCode) {
- characters = [NSString stringWithCharacters:
- reinterpret_cast<const unichar*>(&(aKeyEvent.mCharCode)) length:1];
- } else {
- uint32_t cocoaCharCode =
- nsCocoaUtils::ConvertGeckoKeyCodeToMacCharCode(aKeyEvent.mKeyCode);
- characters = [NSString stringWithCharacters:
- reinterpret_cast<const unichar*>(&cocoaCharCode) length:1];
- }
-
- aKeyEvent.mNativeKeyEvent =
- [NSEvent keyEventWithType:eventType
- location:NSMakePoint(0,0)
- modifierFlags:modifierFlags
- timestamp:0
- windowNumber:windowNumber
- context:[NSGraphicsContext currentContext]
- characters:characters
- charactersIgnoringModifiers:characters
- isARepeat:NO
- keyCode:0]; // Native key code not currently needed
-
- return NS_OK;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-bool
-TextInputHandlerBase::SetSelection(NSRange& aRange)
-{
- MOZ_ASSERT(!Destroyed());
-
- RefPtr<TextInputHandlerBase> kungFuDeathGrip(this);
- WidgetSelectionEvent selectionEvent(true, eSetSelection, mWidget);
- selectionEvent.mOffset = aRange.location;
- selectionEvent.mLength = aRange.length;
- selectionEvent.mReversed = false;
- selectionEvent.mExpandToClusterBoundary = false;
- DispatchEvent(selectionEvent);
- NS_ENSURE_TRUE(selectionEvent.mSucceeded, false);
- return !Destroyed();
-}
-
-/* static */ bool
-TextInputHandlerBase::IsPrintableChar(char16_t aChar)
-{
- return (aChar >= 0x20 && aChar <= 0x7E) || aChar >= 0xA0;
-}
-
-
-/* static */ bool
-TextInputHandlerBase::IsSpecialGeckoKey(UInt32 aNativeKeyCode)
-{
- // this table is used to determine which keys are special and should not
- // generate a charCode
- switch (aNativeKeyCode) {
- // modifiers - we don't get separate events for these yet
- case kVK_Escape:
- case kVK_Shift:
- case kVK_RightShift:
- case kVK_Command:
- case kVK_RightCommand:
- case kVK_CapsLock:
- case kVK_Control:
- case kVK_RightControl:
- case kVK_Option:
- case kVK_RightOption:
- case kVK_ANSI_KeypadClear:
- case kVK_Function:
-
- // function keys
- case kVK_F1:
- case kVK_F2:
- case kVK_F3:
- case kVK_F4:
- case kVK_F5:
- case kVK_F6:
- case kVK_F7:
- case kVK_F8:
- case kVK_F9:
- case kVK_F10:
- case kVK_F11:
- case kVK_F12:
- case kVK_PC_Pause:
- case kVK_PC_ScrollLock:
- case kVK_PC_PrintScreen:
- case kVK_F16:
- case kVK_F17:
- case kVK_F18:
- case kVK_F19:
-
- case kVK_PC_Insert:
- case kVK_PC_Delete:
- case kVK_Tab:
- case kVK_PC_Backspace:
- case kVK_PC_ContextMenu:
-
- case kVK_JIS_Eisu:
- case kVK_JIS_Kana:
-
- case kVK_Home:
- case kVK_End:
- case kVK_PageUp:
- case kVK_PageDown:
- case kVK_LeftArrow:
- case kVK_RightArrow:
- case kVK_UpArrow:
- case kVK_DownArrow:
- case kVK_Return:
- case kVK_ANSI_KeypadEnter:
- case kVK_Powerbook_KeypadEnter:
- return true;
- }
- return false;
-}
-
-/* static */ bool
-TextInputHandlerBase::IsNormalCharInputtingEvent(
- const WidgetKeyboardEvent& aKeyEvent)
-{
- // this is not character inputting event, simply.
- if (aKeyEvent.mNativeCharacters.IsEmpty() ||
- aKeyEvent.IsMeta()) {
- return false;
- }
- return !IsControlChar(aKeyEvent.mNativeCharacters[0]);
-}
-
-/* static */ bool
-TextInputHandlerBase::IsModifierKey(UInt32 aNativeKeyCode)
-{
- switch (aNativeKeyCode) {
- case kVK_CapsLock:
- case kVK_RightCommand:
- case kVK_Command:
- case kVK_Shift:
- case kVK_Option:
- case kVK_Control:
- case kVK_RightShift:
- case kVK_RightOption:
- case kVK_RightControl:
- case kVK_Function:
- return true;
- }
- return false;
-}
-
-/* static */ void
-TextInputHandlerBase::EnableSecureEventInput()
-{
- sSecureEventInputCount++;
- ::EnableSecureEventInput();
-}
-
-/* static */ void
-TextInputHandlerBase::DisableSecureEventInput()
-{
- if (!sSecureEventInputCount) {
- return;
- }
- sSecureEventInputCount--;
- ::DisableSecureEventInput();
-}
-
-/* static */ bool
-TextInputHandlerBase::IsSecureEventInputEnabled()
-{
- NS_ASSERTION(!!sSecureEventInputCount == !!::IsSecureEventInputEnabled(),
- "Some other process has enabled secure event input");
- return !!sSecureEventInputCount;
-}
-
-/* static */ void
-TextInputHandlerBase::EnsureSecureEventInputDisabled()
-{
- while (sSecureEventInputCount) {
- TextInputHandlerBase::DisableSecureEventInput();
- }
-}
-
-#pragma mark -
-
-
-/******************************************************************************
- *
- * TextInputHandlerBase::KeyEventState implementation
- *
- ******************************************************************************/
-
-void
-TextInputHandlerBase::KeyEventState::InitKeyEvent(
- TextInputHandlerBase* aHandler,
- WidgetKeyboardEvent& aKeyEvent)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- MOZ_ASSERT(aHandler);
- MOZ_RELEASE_ASSERT(mKeyEvent);
-
- NSEvent* nativeEvent = mKeyEvent;
- if (!mInsertedString.IsEmpty()) {
- nsAutoString unhandledString;
- GetUnhandledString(unhandledString);
- NSString* unhandledNSString =
- nsCocoaUtils::ToNSString(unhandledString);
- // If the key event's some characters were already handled by
- // InsertString() calls, we need to create a dummy event which doesn't
- // include the handled characters.
- nativeEvent =
- [NSEvent keyEventWithType:[mKeyEvent type]
- location:[mKeyEvent locationInWindow]
- modifierFlags:[mKeyEvent modifierFlags]
- timestamp:[mKeyEvent timestamp]
- windowNumber:[mKeyEvent windowNumber]
- context:[mKeyEvent context]
- characters:unhandledNSString
- charactersIgnoringModifiers:[mKeyEvent charactersIgnoringModifiers]
- isARepeat:[mKeyEvent isARepeat]
- keyCode:[mKeyEvent keyCode]];
- }
-
- aHandler->InitKeyEvent(nativeEvent, aKeyEvent, mInsertString);
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-void
-TextInputHandlerBase::KeyEventState::GetUnhandledString(
- nsAString& aUnhandledString) const
-{
- aUnhandledString.Truncate();
- if (NS_WARN_IF(!mKeyEvent)) {
- return;
- }
- nsAutoString characters;
- nsCocoaUtils::GetStringForNSString([mKeyEvent characters],
- characters);
- if (characters.IsEmpty()) {
- return;
- }
- if (mInsertedString.IsEmpty()) {
- aUnhandledString = characters;
- return;
- }
-
- // The insertes string must match with the start of characters.
- MOZ_ASSERT(StringBeginsWith(characters, mInsertedString));
-
- aUnhandledString = nsDependentSubstring(characters, mInsertedString.Length());
-}
-
-#pragma mark -
-
-
-/******************************************************************************
- *
- * TextInputHandlerBase::AutoInsertStringClearer implementation
- *
- ******************************************************************************/
-
-TextInputHandlerBase::AutoInsertStringClearer::~AutoInsertStringClearer()
-{
- if (mState && mState->mInsertString) {
- // If inserting string is a part of characters of the event,
- // we should record it as inserted string.
- nsAutoString characters;
- nsCocoaUtils::GetStringForNSString([mState->mKeyEvent characters],
- characters);
- nsAutoString insertedString(mState->mInsertedString);
- insertedString += *mState->mInsertString;
- if (StringBeginsWith(characters, insertedString)) {
- mState->mInsertedString = insertedString;
- }
- }
- if (mState) {
- mState->mInsertString = nullptr;
- }
-}
diff --git a/widget/cocoa/VibrancyManager.h b/widget/cocoa/VibrancyManager.h
deleted file mode 100644
index 04b1ad1cda..0000000000
--- a/widget/cocoa/VibrancyManager.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef VibrancyManager_h
-#define VibrancyManager_h
-
-#include "mozilla/Assertions.h"
-#include "nsClassHashtable.h"
-#include "nsRegion.h"
-#include "nsTArray.h"
-#include "ViewRegion.h"
-
-#import <Foundation/NSGeometry.h>
-
-@class NSColor;
-@class NSView;
-class nsChildView;
-
-namespace mozilla {
-
-enum class VibrancyType {
- LIGHT,
- DARK,
- TOOLTIP,
- MENU,
- HIGHLIGHTED_MENUITEM,
- SHEET,
- SOURCE_LIST,
- SOURCE_LIST_SELECTION,
- ACTIVE_SOURCE_LIST_SELECTION
-};
-
-/**
- * VibrancyManager takes care of updating the vibrant regions of a window.
- * Vibrancy is a visual look that was introduced on OS X starting with 10.10.
- * An app declares vibrant window regions to the window server, and the window
- * server will display a blurred rendering of the screen contents from behind
- * the window in these areas, behind the actual window contents. Consequently,
- * the effect is only visible in areas where the window contents are not
- * completely opaque. Usually this is achieved by clearing the background of
- * the window prior to drawing in the vibrant areas. This is possible even if
- * the window is declared as opaque.
- */
-class VibrancyManager {
-public:
- /**
- * Create a new VibrancyManager instance and provide it with an NSView
- * to attach NSVisualEffectViews to.
- *
- * @param aCoordinateConverter The nsChildView to use for converting
- * nsIntRect device pixel coordinates into Cocoa NSRect coordinates. Must
- * outlive this VibrancyManager instance.
- * @param aContainerView The view that's going to be the superview of the
- * NSVisualEffectViews which will be created for vibrant regions.
- */
- VibrancyManager(const nsChildView& aCoordinateConverter,
- NSView* aContainerView)
- : mCoordinateConverter(aCoordinateConverter)
- , mContainerView(aContainerView)
- {
- MOZ_ASSERT(SystemSupportsVibrancy(),
- "Don't instantiate this if !SystemSupportsVibrancy()");
- }
-
- /**
- * Update the placement of the NSVisualEffectViews inside the container
- * NSView so that they cover aRegion, and create new NSVisualEffectViews
- * or remove existing ones as needed.
- * @param aType The vibrancy type to use in the region.
- * @param aRegion The vibrant area, in device pixels.
- */
- void UpdateVibrantRegion(VibrancyType aType,
- const LayoutDeviceIntRegion& aRegion);
-
- bool HasVibrantRegions() { return !mVibrantRegions.IsEmpty(); }
-
- /**
- * Return the fill color that should be drawn on top of the cleared window
- * parts. Usually this would be drawn by -[NSVisualEffectView drawRect:].
- * The returned color is opaque if the system-wide "Reduce transparency"
- * preference is set.
- */
- NSColor* VibrancyFillColorForType(VibrancyType aType);
-
- /**
- * Return the font smoothing background color that should be used for text
- * drawn on top of the vibrant window parts.
- */
- NSColor* VibrancyFontSmoothingBackgroundColorForType(VibrancyType aType);
-
- /**
- * Check whether the operating system supports vibrancy at all.
- * You may only create a VibrancyManager instance if this returns true.
- * @return Whether VibrancyManager can be used on this OS.
- */
- static bool SystemSupportsVibrancy();
-
- /**
- * Create an NSVisualEffectView for the specified vibrancy type. The return
- * value is not autoreleased. We return an object of type NSView* because we
- * compile with an SDK that does not contain a definition for
- * NSVisualEffectView.
- * @param aIsContainer Whether this NSView will have child views. This value
- * affects hit testing: Container views will pass through
- * hit testing requests to their children, and leaf views
- * will be transparent to hit testing.
- */
- static NSView* CreateEffectView(VibrancyType aType, BOOL aIsContainer = NO);
-
-protected:
- const nsChildView& mCoordinateConverter;
- NSView* mContainerView;
- nsClassHashtable<nsUint32HashKey, ViewRegion> mVibrantRegions;
-};
-
-} // namespace mozilla
-
-#endif // VibrancyManager_h
diff --git a/widget/cocoa/VibrancyManager.mm b/widget/cocoa/VibrancyManager.mm
deleted file mode 100644
index d02338eb6b..0000000000
--- a/widget/cocoa/VibrancyManager.mm
+++ /dev/null
@@ -1,244 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "VibrancyManager.h"
-#include "nsChildView.h"
-#import <objc/message.h>
-
-using namespace mozilla;
-
-void
-VibrancyManager::UpdateVibrantRegion(VibrancyType aType,
- const LayoutDeviceIntRegion& aRegion)
-{
- if (aRegion.IsEmpty()) {
- mVibrantRegions.Remove(uint32_t(aType));
- return;
- }
- auto& vr = *mVibrantRegions.LookupOrAdd(uint32_t(aType));
- vr.UpdateRegion(aRegion, mCoordinateConverter, mContainerView, ^() {
- return this->CreateEffectView(aType);
- });
-}
-
-@interface NSView(CurrentFillColor)
-- (NSColor*)_currentFillColor;
-@end
-
-static NSColor*
-AdjustedColor(NSColor* aFillColor, VibrancyType aType)
-{
- if (aType == VibrancyType::MENU && [aFillColor alphaComponent] == 1.0) {
- // The opaque fill color that's used for the menu background when "Reduce
- // vibrancy" is checked in the system accessibility prefs is too dark.
- // This is probably because we're not using the right material for menus,
- // see VibrancyManager::CreateEffectView.
- return [NSColor colorWithDeviceWhite:0.96 alpha:1.0];
- }
- return aFillColor;
-}
-
-NSColor*
-VibrancyManager::VibrancyFillColorForType(VibrancyType aType)
-{
- NSView* view = mVibrantRegions.LookupOrAdd(uint32_t(aType))->GetAnyView();
-
- if (view && [view respondsToSelector:@selector(_currentFillColor)]) {
- // -[NSVisualEffectView _currentFillColor] is the color that the view
- // draws in its drawRect implementation.
- return AdjustedColor([view _currentFillColor], aType);
- }
- return [NSColor whiteColor];
-}
-
-@interface NSView(FontSmoothingBackgroundColor)
-- (NSColor*)fontSmoothingBackgroundColor;
-@end
-
-NSColor*
-VibrancyManager::VibrancyFontSmoothingBackgroundColorForType(VibrancyType aType)
-{
- NSView* view = mVibrantRegions.LookupOrAdd(uint32_t(aType))->GetAnyView();
-
- if (view && [view respondsToSelector:@selector(fontSmoothingBackgroundColor)]) {
- return [view fontSmoothingBackgroundColor];
- }
- return [NSColor clearColor];
-}
-
-static NSView*
-HitTestNil(id self, SEL _cmd, NSPoint aPoint)
-{
- // This view must be transparent to mouse events.
- return nil;
-}
-
-static BOOL
-AllowsVibrancyYes(id self, SEL _cmd)
-{
- // Means that the foreground is blended using a vibrant blend mode.
- return YES;
-}
-
-static Class
-CreateEffectViewClass(BOOL aForegroundVibrancy, BOOL aIsContainer)
-{
- // Create a class that inherits from NSVisualEffectView and overrides the
- // methods -[NSView hitTest:] and -[NSVisualEffectView allowsVibrancy].
- Class NSVisualEffectViewClass = NSClassFromString(@"NSVisualEffectView");
- const char* className = aForegroundVibrancy
- ? "EffectViewWithForegroundVibrancy" : "EffectViewWithoutForegroundVibrancy";
- Class EffectViewClass = objc_allocateClassPair(NSVisualEffectViewClass, className, 0);
- if (!aIsContainer) {
- class_addMethod(EffectViewClass, @selector(hitTest:), (IMP)HitTestNil,
- "@@:{CGPoint=dd}");
- }
- if (aForegroundVibrancy) {
- // Override the -[NSView allowsVibrancy] method to return YES.
- class_addMethod(EffectViewClass, @selector(allowsVibrancy), (IMP)AllowsVibrancyYes, "I@:");
- }
- return EffectViewClass;
-}
-
-static id
-AppearanceForVibrancyType(VibrancyType aType)
-{
- Class NSAppearanceClass = NSClassFromString(@"NSAppearance");
- switch (aType) {
- case VibrancyType::LIGHT:
- case VibrancyType::TOOLTIP:
- case VibrancyType::MENU:
- case VibrancyType::HIGHLIGHTED_MENUITEM:
- case VibrancyType::SHEET:
- case VibrancyType::SOURCE_LIST:
- case VibrancyType::SOURCE_LIST_SELECTION:
- case VibrancyType::ACTIVE_SOURCE_LIST_SELECTION:
- return [NSAppearanceClass performSelector:@selector(appearanceNamed:)
- withObject:@"NSAppearanceNameVibrantLight"];
- case VibrancyType::DARK:
- return [NSAppearanceClass performSelector:@selector(appearanceNamed:)
- withObject:@"NSAppearanceNameVibrantDark"];
- }
-}
-
-#if !defined(MAC_OS_X_VERSION_10_10) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_10
-enum {
- NSVisualEffectStateFollowsWindowActiveState,
- NSVisualEffectStateActive,
- NSVisualEffectStateInactive
-};
-
-enum {
- NSVisualEffectMaterialTitlebar = 3
-};
-#endif
-
-#if !defined(MAC_OS_X_VERSION_10_11) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_11
-enum {
- NSVisualEffectMaterialMenu = 5,
- NSVisualEffectMaterialSidebar = 7
-};
-#endif
-
-static NSUInteger
-VisualEffectStateForVibrancyType(VibrancyType aType)
-{
- switch (aType) {
- case VibrancyType::TOOLTIP:
- case VibrancyType::MENU:
- case VibrancyType::HIGHLIGHTED_MENUITEM:
- case VibrancyType::SHEET:
- // Tooltip and menu windows are never "key" and sheets always looks
- // active, so we need to tell the vibrancy effect to look active
- // regardless of window state.
- return NSVisualEffectStateActive;
- default:
- return NSVisualEffectStateFollowsWindowActiveState;
- }
-}
-
-static BOOL
-HasVibrantForeground(VibrancyType aType)
-{
- switch (aType) {
- case VibrancyType::MENU:
- return YES;
- default:
- return NO;
- }
-}
-
-#if !defined(MAC_OS_X_VERSION_10_12) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12
-enum {
- NSVisualEffectMaterialSelection = 4
-};
-#endif
-
-@interface NSView(NSVisualEffectViewMethods)
-- (void)setState:(NSUInteger)state;
-- (void)setMaterial:(NSUInteger)material;
-- (void)setEmphasized:(BOOL)emphasized;
-@end
-
-NSView*
-VibrancyManager::CreateEffectView(VibrancyType aType, BOOL aIsContainer)
-{
- static Class EffectViewWithoutForegroundVibrancy = CreateEffectViewClass(NO, NO);
- static Class EffectViewWithForegroundVibrancy = CreateEffectViewClass(YES, NO);
- static Class EffectViewContainer = CreateEffectViewClass(NO, YES);
-
- // Pick the right NSVisualEffectView subclass for the desired vibrancy mode.
- // For "container" views, never use foreground vibrancy, because returning
- // YES from allowsVibrancy forces on foreground vibrancy for all descendant
- // views which can have unintended effects.
- Class EffectViewClass = aIsContainer
- ? EffectViewContainer
- : (HasVibrantForeground(aType) ? EffectViewWithForegroundVibrancy
- : EffectViewWithoutForegroundVibrancy);
- NSView* effectView = [[EffectViewClass alloc] initWithFrame:NSZeroRect];
- [effectView performSelector:@selector(setAppearance:)
- withObject:AppearanceForVibrancyType(aType)];
- [effectView setState:VisualEffectStateForVibrancyType(aType)];
-
- BOOL canUseElCapitanMaterials = nsCocoaFeatures::OnElCapitanOrLater();
- if (aType == VibrancyType::MENU) {
- // Before 10.11 there is no material that perfectly matches the menu
- // look. Of all available material types, NSVisualEffectMaterialTitlebar
- // is the one that comes closest.
- [effectView setMaterial:canUseElCapitanMaterials ? NSVisualEffectMaterialMenu
- : NSVisualEffectMaterialTitlebar];
- } else if (aType == VibrancyType::SOURCE_LIST && canUseElCapitanMaterials) {
- [effectView setMaterial:NSVisualEffectMaterialSidebar];
- } else if (aType == VibrancyType::HIGHLIGHTED_MENUITEM ||
- aType == VibrancyType::SOURCE_LIST_SELECTION ||
- aType == VibrancyType::ACTIVE_SOURCE_LIST_SELECTION) {
- [effectView setMaterial:NSVisualEffectMaterialSelection];
- if ([effectView respondsToSelector:@selector(setEmphasized:)] &&
- aType != VibrancyType::SOURCE_LIST_SELECTION) {
- [effectView setEmphasized:YES];
- }
- }
-
- return effectView;
-}
-
-static bool
-ComputeSystemSupportsVibrancy()
-{
-#ifdef __x86_64__
- return NSClassFromString(@"NSAppearance") &&
- NSClassFromString(@"NSVisualEffectView");
-#else
- // objc_allocateClassPair doesn't work in 32 bit mode, so turn off vibrancy.
- return false;
-#endif
-}
-
-/* static */ bool
-VibrancyManager::SystemSupportsVibrancy()
-{
- static bool supportsVibrancy = ComputeSystemSupportsVibrancy();
- return supportsVibrancy;
-}
diff --git a/widget/cocoa/ViewRegion.h b/widget/cocoa/ViewRegion.h
deleted file mode 100644
index 9ff7e6d091..0000000000
--- a/widget/cocoa/ViewRegion.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef ViewRegion_h
-#define ViewRegion_h
-
-#include "Units.h"
-#include "nsTArray.h"
-
-@class NSView;
-
-namespace mozilla {
-
-/**
- * Manages a set of NSViews to cover a LayoutDeviceIntRegion.
- */
-class ViewRegion {
-public:
- ~ViewRegion();
-
- mozilla::LayoutDeviceIntRegion Region() { return mRegion; }
-
- /**
- * Update the region.
- * @param aRegion The new region.
- * @param aCoordinateConverter The nsChildView to use for converting
- * LayoutDeviceIntRect device pixel coordinates into Cocoa NSRect coordinates.
- * @param aContainerView The view that's going to be the superview of the
- * NSViews which will be created for this region.
- * @param aViewCreationCallback A block that instantiates new NSViews.
- * @return Whether or not the region changed.
- */
- bool UpdateRegion(const mozilla::LayoutDeviceIntRegion& aRegion,
- const nsChildView& aCoordinateConverter,
- NSView* aContainerView,
- NSView* (^aViewCreationCallback)());
-
- /**
- * Return an NSView from the region, if there is any.
- */
- NSView* GetAnyView() { return mViews.Length() > 0 ? mViews[0] : nil; }
-
-private:
- mozilla::LayoutDeviceIntRegion mRegion;
- nsTArray<NSView*> mViews;
-};
-
-} // namespace mozilla
-
-#endif // ViewRegion_h
diff --git a/widget/cocoa/ViewRegion.mm b/widget/cocoa/ViewRegion.mm
deleted file mode 100644
index 455d54fdad..0000000000
--- a/widget/cocoa/ViewRegion.mm
+++ /dev/null
@@ -1,70 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "ViewRegion.h"
-#import <Cocoa/Cocoa.h>
-
-using namespace mozilla;
-
-ViewRegion::~ViewRegion()
-{
- for (size_t i = 0; i < mViews.Length(); i++) {
- [mViews[i] removeFromSuperview];
- }
-}
-
-bool
-ViewRegion::UpdateRegion(const LayoutDeviceIntRegion& aRegion,
- const nsChildView& aCoordinateConverter,
- NSView* aContainerView,
- NSView* (^aViewCreationCallback)())
-{
- if (mRegion == aRegion) {
- return false;
- }
-
- // We need to construct the required region using as many EffectViews
- // as necessary. We try to update the geometry of existing views if
- // possible, or create new ones or remove old ones if the number of
- // rects in the region has changed.
-
- nsTArray<NSView*> viewsToRecycle;
- mViews.SwapElements(viewsToRecycle);
- // The mViews array is now empty.
-
- size_t i = 0;
- for (auto iter = aRegion.RectIter();
- !iter.Done() || i < viewsToRecycle.Length();
- i++) {
- if (!iter.Done()) {
- NSView* view = nil;
- NSRect rect = aCoordinateConverter.DevPixelsToCocoaPoints(iter.Get());
- if (i < viewsToRecycle.Length()) {
- view = viewsToRecycle[i];
- } else {
- view = aViewCreationCallback();
- [aContainerView addSubview:view];
-
- // Now that the view is in the view hierarchy, it'll be kept alive by
- // its superview, so we can drop our reference.
- [view release];
- }
- if (!NSEqualRects(rect, [view frame])) {
- [view setFrame:rect];
- }
- [view setNeedsDisplay:YES];
- mViews.AppendElement(view);
- iter.Next();
- } else {
- // Our new region is made of fewer rects than the old region, so we can
- // remove this view. We only have a weak reference to it, so removing it
- // from the view hierarchy will release it.
- [viewsToRecycle[i] removeFromSuperview];
- }
- }
-
- mRegion = aRegion;
- return true;
-}
diff --git a/widget/cocoa/WidgetTraceEvent.mm b/widget/cocoa/WidgetTraceEvent.mm
deleted file mode 100644
index 7023a17ba0..0000000000
--- a/widget/cocoa/WidgetTraceEvent.mm
+++ /dev/null
@@ -1,85 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <Cocoa/Cocoa.h>
-#include "CustomCocoaEvents.h"
-#include <Foundation/NSAutoreleasePool.h>
-#include <mozilla/CondVar.h>
-#include <mozilla/Mutex.h>
-#include "mozilla/WidgetTraceEvent.h"
-
-using mozilla::CondVar;
-using mozilla::Mutex;
-using mozilla::MutexAutoLock;
-
-namespace {
-
-Mutex* sMutex = NULL;
-CondVar* sCondVar = NULL;
-bool sTracerProcessed = false;
-
-} // namespace
-
-namespace mozilla {
-
-bool InitWidgetTracing()
-{
- sMutex = new Mutex("Event tracer thread mutex");
- sCondVar = new CondVar(*sMutex, "Event tracer thread condvar");
- return sMutex && sCondVar;
-}
-
-void CleanUpWidgetTracing()
-{
- delete sMutex;
- delete sCondVar;
- sMutex = NULL;
- sCondVar = NULL;
-}
-
-// This function is called from the main (UI) thread.
-void SignalTracerThread()
-{
- if (!sMutex || !sCondVar)
- return;
- MutexAutoLock lock(*sMutex);
- if (!sTracerProcessed) {
- sTracerProcessed = true;
- sCondVar->Notify();
- }
-}
-
-// This function is called from the background tracer thread.
-bool FireAndWaitForTracerEvent()
-{
- MOZ_ASSERT(sMutex && sCondVar, "Tracing not initialized!");
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- MutexAutoLock lock(*sMutex);
- if (sTracerProcessed) {
- // Things are out of sync. This is likely because we're in
- // the middle of shutting down. Just return false and hope the
- // tracer thread is quitting anyway.
- return false;
- }
-
- // Post an application-defined event to the main thread's event queue
- // and wait for it to get processed.
- [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined
- location:NSMakePoint(0,0)
- modifierFlags:0
- timestamp:0
- windowNumber:0
- context:NULL
- subtype:kEventSubtypeTrace
- data1:0
- data2:0]
- atStart:NO];
- while (!sTracerProcessed)
- sCondVar->Wait();
- sTracerProcessed = false;
- [pool release];
- return true;
-}
-
-} // namespace mozilla
diff --git a/widget/cocoa/crashtests/373122-1-inner.html b/widget/cocoa/crashtests/373122-1-inner.html
deleted file mode 100644
index 5c14166b75..0000000000
--- a/widget/cocoa/crashtests/373122-1-inner.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<html>
-<head>
-
-<script>
-function boom()
-{
- document.body.style.position = "fixed"
-
- setTimeout(boom2, 1);
-}
-
-function boom2()
-{
- lappy = document.getElementById("lappy");
- lappy.style.display = "none"
-
- setTimeout(boom3, 200);
-}
-
-function boom3()
-{
- dump("Reloading\n");
- location.reload();
-}
-
-</script>
-
-
-</head>
-
-
-<body bgcolor="black" onload="boom()">
-
- <span style="overflow: scroll; display: -moz-box;"></span>
-
- <embed id="lappy" src="" width=550 height=400 TYPE="application/x-shockwave-flash" ></embed>
-
-</body>
-</html>
diff --git a/widget/cocoa/crashtests/373122-1.html b/widget/cocoa/crashtests/373122-1.html
deleted file mode 100644
index a57e5f4249..0000000000
--- a/widget/cocoa/crashtests/373122-1.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<html class="reftest-wait">
-<head>
-<script>
-setTimeout('document.documentElement.className = ""', 1000);
-</script>
-<body>
-<iframe src="373122-1-inner.html"></iframe>
-</body>
-</html>
diff --git a/widget/cocoa/crashtests/397209-1.html b/widget/cocoa/crashtests/397209-1.html
deleted file mode 100644
index 554b2dac72..0000000000
--- a/widget/cocoa/crashtests/397209-1.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<html>
-<head>
-</head>
-<body>
-<button style="width: 8205em;"></button>
-</body>
-</html>
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 @@
-<html xmlns="http://www.w3.org/1999/xhtml"
- class="reftest-wait"
- style="margin: 12em; padding: 20px 10em; opacity: 0.2; font-size: 11.2px; -moz-appearance: toolbar; white-space: nowrap;"><body
- style="position: absolute;"
- onload="setTimeout(function() { document.body.removeChild(document.getElementById('tr')); document.documentElement.removeAttribute('class'); }, 30);">
-
-xxx
-yyy
-
-<tr id="tr">300</tr></body></html>
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 @@
-<!DOCTYPE html>
-<html>
-<head>
-</head>
-<body>
-<div><span style="-moz-appearance: radio; padding: 15000px;"></span></div>
-</body>
-</html>
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 @@
-<!DOCTYPE html>
-<html>
-<head>
-</head>
-<body>
-<div style="min-width: -moz-max-content;"><div style="-moz-appearance: button;"><div style="margin: 0 100%;"></div></div></div>
-</body>
-</html>
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 @@
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-<hbox><button width="7788025414616">S</button></hbox>
-</window>
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 @@
-<!DOCTYPE html>
-<html>
-<body>
-<div style="padding: 10px;"><input type="button" value="Go" style="letter-spacing: 331989pt;"></div>
-</body>
-</html>
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 @@
-<html>
-<head></head>
-<body><div style="display: -moz-box; word-spacing: 549755813889px;"><button>T </button></div></body>
-</html>
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 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head></head>
-<body><div><mstyle xmlns="http://www.w3.org/1998/Math/MathML" style="-moz-appearance: button;"/></div></body>
-</html>
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 @@
-<!DOCTYPE html>
-<html><head></head><body><div style="display: table; padding: 625203mm; -moz-appearance: menulist;"></div></body></html>
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 @@
-<html>
-<head>
-<script type="text/javascript">
-
-function boom()
-{
- var o2 = document.createElement("option");
- document.getElementById("o1").appendChild(o2);
- o2.style.padding = "131072cm";
-}
-
-</script>
-</head>
-
-<body onload="boom();">
-
-<select><option id="o1" style="height: 0cm;"></option></select>
-
-</body>
-</html>
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
--- a/widget/cocoa/cursors/arrowN.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/arrowN@2x.png b/widget/cocoa/cursors/arrowN@2x.png
deleted file mode 100644
index d00e87636c..0000000000
--- a/widget/cocoa/cursors/arrowN@2x.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/arrowS.png b/widget/cocoa/cursors/arrowS.png
deleted file mode 100644
index 9b2d19e0fd..0000000000
--- a/widget/cocoa/cursors/arrowS.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/arrowS@2x.png b/widget/cocoa/cursors/arrowS@2x.png
deleted file mode 100644
index 5d011c1fd1..0000000000
--- a/widget/cocoa/cursors/arrowS@2x.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/cell.png b/widget/cocoa/cursors/cell.png
deleted file mode 100644
index 5284eaec57..0000000000
--- a/widget/cocoa/cursors/cell.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/cell@2x.png b/widget/cocoa/cursors/cell@2x.png
deleted file mode 100644
index 5e6738cff7..0000000000
--- a/widget/cocoa/cursors/cell@2x.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/colResize.png b/widget/cocoa/cursors/colResize.png
deleted file mode 100644
index 4e3e19e223..0000000000
--- a/widget/cocoa/cursors/colResize.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/colResize@2x.png b/widget/cocoa/cursors/colResize@2x.png
deleted file mode 100644
index 6a92cf6806..0000000000
--- a/widget/cocoa/cursors/colResize@2x.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/help.png b/widget/cocoa/cursors/help.png
deleted file mode 100644
index 5e5416b4e3..0000000000
--- a/widget/cocoa/cursors/help.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/help@2x.png b/widget/cocoa/cursors/help@2x.png
deleted file mode 100644
index 0ac53a9733..0000000000
--- a/widget/cocoa/cursors/help@2x.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/move.png b/widget/cocoa/cursors/move.png
deleted file mode 100644
index 1360f82277..0000000000
--- a/widget/cocoa/cursors/move.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/move@2x.png b/widget/cocoa/cursors/move@2x.png
deleted file mode 100644
index ad146e4863..0000000000
--- a/widget/cocoa/cursors/move@2x.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/rowResize.png b/widget/cocoa/cursors/rowResize.png
deleted file mode 100644
index 4c16bb8bd6..0000000000
--- a/widget/cocoa/cursors/rowResize.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/rowResize@2x.png b/widget/cocoa/cursors/rowResize@2x.png
deleted file mode 100644
index b48f03ae0d..0000000000
--- a/widget/cocoa/cursors/rowResize@2x.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/sizeNE.png b/widget/cocoa/cursors/sizeNE.png
deleted file mode 100644
index f62c046575..0000000000
--- a/widget/cocoa/cursors/sizeNE.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/sizeNE@2x.png b/widget/cocoa/cursors/sizeNE@2x.png
deleted file mode 100644
index 98d19e9efa..0000000000
--- a/widget/cocoa/cursors/sizeNE@2x.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/sizeNESW.png b/widget/cocoa/cursors/sizeNESW.png
deleted file mode 100644
index 0a077fa674..0000000000
--- a/widget/cocoa/cursors/sizeNESW.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/sizeNESW@2x.png b/widget/cocoa/cursors/sizeNESW@2x.png
deleted file mode 100644
index 31bca3c901..0000000000
--- a/widget/cocoa/cursors/sizeNESW@2x.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/sizeNS.png b/widget/cocoa/cursors/sizeNS.png
deleted file mode 100644
index 0419be0af7..0000000000
--- a/widget/cocoa/cursors/sizeNS.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/sizeNS@2x.png b/widget/cocoa/cursors/sizeNS@2x.png
deleted file mode 100644
index e48fd0cb3a..0000000000
--- a/widget/cocoa/cursors/sizeNS@2x.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/sizeNW.png b/widget/cocoa/cursors/sizeNW.png
deleted file mode 100644
index 8f5faee5f7..0000000000
--- a/widget/cocoa/cursors/sizeNW.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/sizeNW@2x.png b/widget/cocoa/cursors/sizeNW@2x.png
deleted file mode 100644
index 3a80e7ce91..0000000000
--- a/widget/cocoa/cursors/sizeNW@2x.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/sizeNWSE.png b/widget/cocoa/cursors/sizeNWSE.png
deleted file mode 100644
index 0574a584c1..0000000000
--- a/widget/cocoa/cursors/sizeNWSE.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/sizeNWSE@2x.png b/widget/cocoa/cursors/sizeNWSE@2x.png
deleted file mode 100644
index 9a0a276c34..0000000000
--- a/widget/cocoa/cursors/sizeNWSE@2x.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/sizeSE.png b/widget/cocoa/cursors/sizeSE.png
deleted file mode 100644
index 6a1948f521..0000000000
--- a/widget/cocoa/cursors/sizeSE.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/sizeSE@2x.png b/widget/cocoa/cursors/sizeSE@2x.png
deleted file mode 100644
index 7d637f4be6..0000000000
--- a/widget/cocoa/cursors/sizeSE@2x.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/sizeSW.png b/widget/cocoa/cursors/sizeSW.png
deleted file mode 100644
index 5dd054dd46..0000000000
--- a/widget/cocoa/cursors/sizeSW.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/sizeSW@2x.png b/widget/cocoa/cursors/sizeSW@2x.png
deleted file mode 100644
index 5ac63c25c6..0000000000
--- a/widget/cocoa/cursors/sizeSW@2x.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/vtIBeam.png b/widget/cocoa/cursors/vtIBeam.png
deleted file mode 100644
index ee7528c595..0000000000
--- a/widget/cocoa/cursors/vtIBeam.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/vtIBeam@2x.png b/widget/cocoa/cursors/vtIBeam@2x.png
deleted file mode 100644
index 41c47af116..0000000000
--- a/widget/cocoa/cursors/vtIBeam@2x.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/zoomIn.png b/widget/cocoa/cursors/zoomIn.png
deleted file mode 100644
index 275bf1c69d..0000000000
--- a/widget/cocoa/cursors/zoomIn.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/zoomIn@2x.png b/widget/cocoa/cursors/zoomIn@2x.png
deleted file mode 100644
index fdd3f8e71d..0000000000
--- a/widget/cocoa/cursors/zoomIn@2x.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/zoomOut.png b/widget/cocoa/cursors/zoomOut.png
deleted file mode 100644
index 19d2d89125..0000000000
--- a/widget/cocoa/cursors/zoomOut.png
+++ /dev/null
Binary files differ
diff --git a/widget/cocoa/cursors/zoomOut@2x.png b/widget/cocoa/cursors/zoomOut@2x.png
deleted file mode 100644
index 0ed46ce75e..0000000000
--- a/widget/cocoa/cursors/zoomOut@2x.png
+++ /dev/null
Binary files 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 <Cocoa/Cocoa.h>
-class nsIWidget;
-
-namespace mozilla {
-namespace widget{
-class TextInputHandler;
-} // namespace widget
-} // namespace mozilla
-
-// A protocol listing all the methods that an object which wants
-// to live in gecko's widget hierarchy must implement. |nsChildView|
-// makes assumptions that any NSView with which it comes in contact will
-// implement this protocol.
-@protocol mozView
-
- // aHandler is Gecko's default text input handler: It implements the
- // NSTextInput protocol to handle key events. Don't make aHandler a
- // strong reference -- that causes a memory leak.
-- (void)installTextInputHandler:(mozilla::widget::TextInputHandler*)aHandler;
-- (void)uninstallTextInputHandler;
-
- // access the nsIWidget associated with this view. DOES NOT ADDREF.
-- (nsIWidget*)widget;
-
- // return a context menu for this view
-- (NSMenu*)contextMenu;
-
- // called when our corresponding Gecko view goes away
-- (void)widgetDestroyed;
-
-- (BOOL)isDragInProgress;
-
- // Checks whether the view is first responder or not
-- (BOOL)isFirstResponder;
-
- // Call when you dispatch an event which may cause to open context menu.
-- (void)maybeInitContextMenuTracking;
-
-@end
-
-// An informal protocol implemented by the NSWindow of the host application.
-//
-// It's used to prevent re-entrant calls to -makeKeyAndOrderFront: when gecko
-// focus/activate events propagate out to the embedder's
-// nsIEmbeddingSiteWindow::SetFocus implementation.
-@interface NSObject(mozWindow)
-
-- (BOOL)suppressMakeKeyFront;
-- (void)setSuppressMakeKeyFront:(BOOL)inSuppress;
-
-@end
-
-#endif // mozView_h_
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 <Cocoa/Cocoa.h>
-
-#include "CustomCocoaEvents.h"
-#include "mozilla/WidgetTraceEvent.h"
-#include "nsAppShell.h"
-#include "nsCOMPtr.h"
-#include "nsIFile.h"
-#include "nsDirectoryServiceDefs.h"
-#include "nsString.h"
-#include "nsIRollupListener.h"
-#include "nsIWidget.h"
-#include "nsThreadUtils.h"
-#include "nsIWindowMediator.h"
-#include "nsServiceManagerUtils.h"
-#include "nsIInterfaceRequestor.h"
-#include "nsIWebBrowserChrome.h"
-#include "nsObjCExceptions.h"
-#include "nsCocoaFeatures.h"
-#include "nsCocoaUtils.h"
-#include "nsChildView.h"
-#include "nsToolkit.h"
-#include "TextInputHandler.h"
-#include "mozilla/HangMonitor.h"
-#include "GeckoProfiler.h"
-#include "pratom.h"
-#if !defined(RELEASE_OR_BETA) || defined(DEBUG)
-#include "nsSandboxViolationSink.h"
-#endif
-
-#include <IOKit/pwr_mgt/IOPMLib.h>
-#include "nsIDOMWakeLockListener.h"
-#include "nsIPowerManagerService.h"
-
-using namespace mozilla::widget;
-
-// A wake lock listener that disables screen saver when requested by
-// Gecko. For example when we're playing video in a foreground tab we
-// don't want the screen saver to turn on.
-
-class MacWakeLockListener final : public nsIDOMMozWakeLockListener {
-public:
- NS_DECL_ISUPPORTS;
-
-private:
- ~MacWakeLockListener() {}
-
- IOPMAssertionID mAssertionID = kIOPMNullAssertionID;
-
- NS_IMETHOD Callback(const nsAString& aTopic, const nsAString& aState) override {
- if (!aTopic.EqualsASCII("screen")) {
- return NS_OK;
- }
- // Note the wake lock code ensures that we're not sent duplicate
- // "locked-foreground" notifications when multiple wake locks are held.
- if (aState.EqualsASCII("locked-foreground")) {
- // Prevent screen saver.
- CFStringRef cf_topic =
- ::CFStringCreateWithCharacters(kCFAllocatorDefault,
- reinterpret_cast<const UniChar*>
- (aTopic.Data()),
- aTopic.Length());
- IOReturn success =
- ::IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep,
- kIOPMAssertionLevelOn,
- cf_topic,
- &mAssertionID);
- CFRelease(cf_topic);
- if (success != kIOReturnSuccess) {
- NS_WARNING("failed to disable screensaver");
- }
- } else {
- // Re-enable screen saver.
- NS_WARNING("Releasing screensaver");
- if (mAssertionID != kIOPMNullAssertionID) {
- IOReturn result = ::IOPMAssertionRelease(mAssertionID);
- if (result != kIOReturnSuccess) {
- NS_WARNING("failed to release screensaver");
- }
- }
- }
- return NS_OK;
- }
-}; // MacWakeLockListener
-
-// defined in nsCocoaWindow.mm
-extern int32_t gXULModalLevel;
-
-static bool gAppShellMethodsSwizzled = false;
-
-@implementation GeckoNSApplication
-
-- (void)sendEvent:(NSEvent *)anEvent
-{
- mozilla::HangMonitor::NotifyActivity();
- if ([anEvent type] == NSApplicationDefined &&
- [anEvent subtype] == kEventSubtypeTrace) {
- mozilla::SignalTracerThread();
- return;
- }
- [super sendEvent:anEvent];
-}
-
-#if defined(MAC_OS_X_VERSION_10_12) && \
- MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12 && \
- __LP64__
-// 10.12 changed `mask` to NSEventMask (unsigned long long) for x86_64 builds.
-- (NSEvent*)nextEventMatchingMask:(NSEventMask)mask
-#else
-- (NSEvent*)nextEventMatchingMask:(NSUInteger)mask
-#endif
- untilDate:(NSDate*)expiration
- inMode:(NSString*)mode
- dequeue:(BOOL)flag
-{
- if (expiration) {
- mozilla::HangMonitor::Suspend();
- }
- NSEvent* nextEvent = [super nextEventMatchingMask:mask
- untilDate:expiration inMode:mode dequeue:flag];
- if (expiration) {
- mozilla::HangMonitor::NotifyActivity();
- }
- return nextEvent;
-}
-
-@end
-
-// AppShellDelegate
-//
-// Cocoa bridge class. An object of this class is registered to receive
-// notifications.
-//
-@interface AppShellDelegate : NSObject
-{
- @private
- nsAppShell* mAppShell;
-}
-
-- (id)initWithAppShell:(nsAppShell*)aAppShell;
-- (void)applicationWillTerminate:(NSNotification*)aNotification;
-- (void)beginMenuTracking:(NSNotification*)aNotification;
-@end
-
-// nsAppShell implementation
-
-NS_IMETHODIMP
-nsAppShell::ResumeNative(void)
-{
- nsresult retval = nsBaseAppShell::ResumeNative();
- if (NS_SUCCEEDED(retval) && (mSuspendNativeCount == 0) &&
- mSkippedNativeCallback)
- {
- mSkippedNativeCallback = false;
- ScheduleNativeEventCallback();
- }
- return retval;
-}
-
-nsAppShell::nsAppShell()
-: mAutoreleasePools(nullptr)
-, mDelegate(nullptr)
-, mCFRunLoop(NULL)
-, mCFRunLoopSource(NULL)
-, mRunningEventLoop(false)
-, mStarted(false)
-, mTerminated(false)
-, mSkippedNativeCallback(false)
-, mNativeEventCallbackDepth(0)
-, mNativeEventScheduledDepth(0)
-{
- // A Cocoa event loop is running here if (and only if) we've been embedded
- // by a Cocoa app.
- mRunningCocoaEmbedded = [NSApp isRunning] ? true : false;
-}
-
-nsAppShell::~nsAppShell()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- if (mCFRunLoop) {
- if (mCFRunLoopSource) {
- ::CFRunLoopRemoveSource(mCFRunLoop, mCFRunLoopSource,
- kCFRunLoopCommonModes);
- ::CFRelease(mCFRunLoopSource);
- }
- ::CFRelease(mCFRunLoop);
- }
-
- if (mAutoreleasePools) {
- NS_ASSERTION(::CFArrayGetCount(mAutoreleasePools) == 0,
- "nsAppShell destroyed without popping all autorelease pools");
- ::CFRelease(mAutoreleasePools);
- }
-
- [mDelegate release];
-
- NS_OBJC_END_TRY_ABORT_BLOCK
-}
-
-NS_IMPL_ISUPPORTS(MacWakeLockListener, nsIDOMMozWakeLockListener)
-mozilla::StaticRefPtr<MacWakeLockListener> sWakeLockListener;
-
-static void
-AddScreenWakeLockListener()
-{
- nsCOMPtr<nsIPowerManagerService> sPowerManagerService = do_GetService(
- POWERMANAGERSERVICE_CONTRACTID);
- if (sPowerManagerService) {
- sWakeLockListener = new MacWakeLockListener();
- sPowerManagerService->AddWakeLockListener(sWakeLockListener);
- } else {
- NS_WARNING("Failed to retrieve PowerManagerService, wakelocks will be broken!");
- }
-}
-
-static void
-RemoveScreenWakeLockListener()
-{
- nsCOMPtr<nsIPowerManagerService> sPowerManagerService = do_GetService(
- POWERMANAGERSERVICE_CONTRACTID);
- if (sPowerManagerService) {
- sPowerManagerService->RemoveWakeLockListener(sWakeLockListener);
- sPowerManagerService = nullptr;
- sWakeLockListener = nullptr;
- }
-}
-
-// An undocumented CoreGraphics framework method, present in the same form
-// since at least OS X 10.5.
-extern "C" CGError CGSSetDebugOptions(int options);
-
-// Init
-//
-// Loads the nib (see bug 316076c21) and sets up the CFRunLoopSource used to
-// interrupt the main native run loop.
-//
-// public
-nsresult
-nsAppShell::Init()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- // No event loop is running yet (unless an embedding app that uses
- // NSApplicationMain() is running).
- NSAutoreleasePool* localPool = [[NSAutoreleasePool alloc] init];
-
- // mAutoreleasePools is used as a stack of NSAutoreleasePool objects created
- // by |this|. CFArray is used instead of NSArray because NSArray wants to
- // retain each object you add to it, and you can't retain an
- // NSAutoreleasePool.
- mAutoreleasePools = ::CFArrayCreateMutable(nullptr, 0, nullptr);
- NS_ENSURE_STATE(mAutoreleasePools);
-
- // Get the path of the nib file, which lives in the GRE location
- nsCOMPtr<nsIFile> nibFile;
- nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(nibFile));
- NS_ENSURE_SUCCESS(rv, rv);
-
- nibFile->AppendNative(NS_LITERAL_CSTRING("res"));
- nibFile->AppendNative(NS_LITERAL_CSTRING("MainMenu.nib"));
-
- nsAutoCString nibPath;
- rv = nibFile->GetNativePath(nibPath);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // This call initializes NSApplication unless:
- // 1) we're using xre -- NSApp's already been initialized by
- // MacApplicationDelegate.mm's EnsureUseCocoaDockAPI().
- // 2) an embedding app that uses NSApplicationMain() is running -- NSApp's
- // already been initialized and its main run loop is already running.
- [NSBundle loadNibFile:
- [NSString stringWithUTF8String:(const char*)nibPath.get()]
- externalNameTable:
- [NSDictionary dictionaryWithObject:[GeckoNSApplication sharedApplication]
- forKey:@"NSOwner"]
- withZone:NSDefaultMallocZone()];
-
- mDelegate = [[AppShellDelegate alloc] initWithAppShell:this];
- NS_ENSURE_STATE(mDelegate);
-
- // Add a CFRunLoopSource to the main native run loop. The source is
- // responsible for interrupting the run loop when Gecko events are ready.
-
- mCFRunLoop = [[NSRunLoop currentRunLoop] getCFRunLoop];
- NS_ENSURE_STATE(mCFRunLoop);
- ::CFRetain(mCFRunLoop);
-
- CFRunLoopSourceContext context;
- bzero(&context, sizeof(context));
- // context.version = 0;
- context.info = this;
- context.perform = ProcessGeckoEvents;
-
- mCFRunLoopSource = ::CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
- NS_ENSURE_STATE(mCFRunLoopSource);
-
- ::CFRunLoopAddSource(mCFRunLoop, mCFRunLoopSource, kCFRunLoopCommonModes);
-
- rv = nsBaseAppShell::Init();
-
- if (!gAppShellMethodsSwizzled) {
- // We should only replace the original terminate: method if we're not
- // running in a Cocoa embedder. See bug 604901.
- if (!mRunningCocoaEmbedded) {
- nsToolkit::SwizzleMethods([NSApplication class], @selector(terminate:),
- @selector(nsAppShell_NSApplication_terminate:));
- }
- gAppShellMethodsSwizzled = true;
- }
-
- if (nsCocoaFeatures::OnYosemiteOrLater()) {
- // Explicitly turn off CGEvent logging. This works around bug 1092855.
- // If there are already CGEvents in the log, turning off logging also
- // causes those events to be written to disk. But at this point no
- // CGEvents have yet been processed. CGEvents are events (usually
- // input events) pulled from the WindowServer. An option of 0x80000008
- // turns on CGEvent logging.
- CGSSetDebugOptions(0x80000007);
- }
-
-#if !defined(RELEASE_OR_BETA) || defined(DEBUG)
- if (Preferences::GetBool("security.sandbox.mac.track.violations", false)) {
- nsSandboxViolationSink::Start();
- }
-#endif
-
- [localPool release];
-
- return rv;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-// ProcessGeckoEvents
-//
-// The "perform" target of mCFRunLoop, called when mCFRunLoopSource is
-// signalled from ScheduleNativeEventCallback.
-//
-// Arrange for Gecko events to be processed on demand (in response to a call
-// to ScheduleNativeEventCallback(), if processing of Gecko events via "native
-// methods" hasn't been suspended). This happens in NativeEventCallback().
-//
-// protected static
-void
-nsAppShell::ProcessGeckoEvents(void* aInfo)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
- PROFILER_LABEL("Events", "ProcessGeckoEvents",
- js::ProfileEntry::Category::EVENTS);
-
- nsAppShell* self = static_cast<nsAppShell*> (aInfo);
-
- if (self->mRunningEventLoop) {
- self->mRunningEventLoop = false;
-
- // The run loop may be sleeping -- [NSRunLoop runMode:...]
- // won't return until it's given a reason to wake up. Awaken it by
- // posting a bogus event. There's no need to make the event
- // presentable.
- //
- // But _don't_ set windowNumber to '-1' -- that can lead to nasty
- // weirdness like bmo bug 397039 (a crash in [NSApp sendEvent:] on one of
- // these fake events, because the -1 has gotten changed into the number
- // of an actual NSWindow object, and that NSWindow object has just been
- // destroyed). Setting windowNumber to '0' seems to work fine -- this
- // seems to prevent the OS from ever trying to associate our bogus event
- // with a particular NSWindow object.
- [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined
- location:NSMakePoint(0,0)
- modifierFlags:0
- timestamp:0
- windowNumber:0
- context:NULL
- subtype:kEventSubtypeNone
- data1:0
- data2:0]
- atStart:NO];
- }
-
- if (self->mSuspendNativeCount <= 0) {
- ++self->mNativeEventCallbackDepth;
- self->NativeEventCallback();
- --self->mNativeEventCallbackDepth;
- } else {
- self->mSkippedNativeCallback = true;
- }
-
- // Still needed to avoid crashes on quit in most Mochitests.
- [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined
- location:NSMakePoint(0,0)
- modifierFlags:0
- timestamp:0
- windowNumber:0
- context:NULL
- subtype:kEventSubtypeNone
- data1:0
- data2:0]
- atStart:NO];
-
- // Normally every call to ScheduleNativeEventCallback() results in
- // exactly one call to ProcessGeckoEvents(). So each Release() here
- // normally balances exactly one AddRef() in ScheduleNativeEventCallback().
- // But if Exit() is called just after ScheduleNativeEventCallback(), the
- // corresponding call to ProcessGeckoEvents() will never happen. We check
- // for this possibility in two different places -- here and in Exit()
- // itself. If we find here that Exit() has been called (that mTerminated
- // is true), it's because we've been called recursively, that Exit() was
- // called from self->NativeEventCallback() above, and that we're unwinding
- // the recursion. In this case we'll never be called again, and we balance
- // here any extra calls to ScheduleNativeEventCallback().
- //
- // When ProcessGeckoEvents() is called recursively, it's because of a
- // call to ScheduleNativeEventCallback() from NativeEventCallback(). We
- // balance the "extra" AddRefs here (rather than always in Exit()) in order
- // to ensure that 'self' stays alive until the end of this method. We also
- // make sure not to finish the balancing until all the recursion has been
- // unwound.
- if (self->mTerminated) {
- int32_t releaseCount = 0;
- if (self->mNativeEventScheduledDepth > self->mNativeEventCallbackDepth) {
- releaseCount = PR_ATOMIC_SET(&self->mNativeEventScheduledDepth,
- self->mNativeEventCallbackDepth);
- }
- while (releaseCount-- > self->mNativeEventCallbackDepth)
- self->Release();
- } else {
- // As best we can tell, every call to ProcessGeckoEvents() is triggered
- // by a call to ScheduleNativeEventCallback(). But we've seen a few
- // (non-reproducible) cases of double-frees that *might* have been caused
- // by spontaneous calls (from the OS) to ProcessGeckoEvents(). So we
- // deal with that possibility here.
- if (PR_ATOMIC_DECREMENT(&self->mNativeEventScheduledDepth) < 0) {
- PR_ATOMIC_SET(&self->mNativeEventScheduledDepth, 0);
- NS_WARNING("Spontaneous call to ProcessGeckoEvents()!");
- } else {
- self->Release();
- }
- }
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-// WillTerminate
-//
-// Called by the AppShellDelegate when an NSApplicationWillTerminate
-// notification is posted. After this method is called, native events should
-// no longer be processed. The NSApplicationWillTerminate notification is
-// only posted when [NSApp terminate:] is called, which doesn't happen on a
-// "normal" application quit.
-//
-// public
-void
-nsAppShell::WillTerminate()
-{
- if (mTerminated)
- return;
-
- // Make sure that the nsAppExitEvent posted by nsAppStartup::Quit() (called
- // from [MacApplicationDelegate applicationShouldTerminate:]) gets run.
- NS_ProcessPendingEvents(NS_GetCurrentThread());
-
- mTerminated = true;
-}
-
-// ScheduleNativeEventCallback
-//
-// Called (possibly on a non-main thread) when Gecko has an event that
-// needs to be processed. The Gecko event needs to be processed on the
-// main thread, so the native run loop must be interrupted.
-//
-// In nsBaseAppShell.cpp, the mNativeEventPending variable is used to
-// ensure that ScheduleNativeEventCallback() is called no more than once
-// per call to NativeEventCallback(). ProcessGeckoEvents() can skip its
-// call to NativeEventCallback() if processing of Gecko events by native
-// means is suspended (using nsIAppShell::SuspendNative()), which will
-// suspend calls from nsBaseAppShell::OnDispatchedEvent() to
-// ScheduleNativeEventCallback(). But when Gecko event processing by
-// native means is resumed (in ResumeNative()), an extra call is made to
-// ScheduleNativeEventCallback() (from ResumeNative()). This triggers
-// another call to ProcessGeckoEvents(), which calls NativeEventCallback(),
-// and nsBaseAppShell::OnDispatchedEvent() resumes calling
-// ScheduleNativeEventCallback().
-//
-// protected virtual
-void
-nsAppShell::ScheduleNativeEventCallback()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- if (mTerminated)
- return;
-
- // Each AddRef() here is normally balanced by exactly one Release() in
- // ProcessGeckoEvents(). But there are exceptions, for which see
- // ProcessGeckoEvents() and Exit().
- NS_ADDREF_THIS();
- PR_ATOMIC_INCREMENT(&mNativeEventScheduledDepth);
-
- // This will invoke ProcessGeckoEvents on the main thread.
- ::CFRunLoopSourceSignal(mCFRunLoopSource);
- ::CFRunLoopWakeUp(mCFRunLoop);
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-// Undocumented Cocoa Event Manager function, present in the same form since
-// at least OS X 10.6.
-extern "C" EventAttributes GetEventAttributes(EventRef inEvent);
-
-// ProcessNextNativeEvent
-//
-// If aMayWait is false, process a single native event. If it is true, run
-// the native run loop until stopped by ProcessGeckoEvents.
-//
-// Returns true if more events are waiting in the native event queue.
-//
-// protected virtual
-bool
-nsAppShell::ProcessNextNativeEvent(bool aMayWait)
-{
- bool moreEvents = false;
-
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- bool eventProcessed = false;
- NSString* currentMode = nil;
-
- if (mTerminated)
- return false;
-
- bool wasRunningEventLoop = mRunningEventLoop;
- mRunningEventLoop = aMayWait;
- NSDate* waitUntil = nil;
- if (aMayWait)
- waitUntil = [NSDate distantFuture];
-
- NSRunLoop* currentRunLoop = [NSRunLoop currentRunLoop];
-
- EventQueueRef currentEventQueue = GetCurrentEventQueue();
- EventTargetRef eventDispatcherTarget = GetEventDispatcherTarget();
-
- if (aMayWait) {
- mozilla::HangMonitor::Suspend();
- }
-
- // Only call -[NSApp sendEvent:] (and indirectly send user-input events to
- // Gecko) if aMayWait is true. Tbis ensures most calls to -[NSApp
- // sendEvent:] happen under nsAppShell::Run(), at the lowest level of
- // recursion -- thereby making it less likely Gecko will process user-input
- // events in the wrong order or skip some of them. It also avoids eating
- // too much CPU in nsBaseAppShell::OnProcessNextEvent() (which calls
- // us) -- thereby avoiding the starvation of nsIRunnable events in
- // nsThread::ProcessNextEvent(). For more information see bug 996848.
- do {
- // No autorelease pool is provided here, because OnProcessNextEvent
- // and AfterProcessNextEvent are responsible for maintaining it.
- NS_ASSERTION(mAutoreleasePools && ::CFArrayGetCount(mAutoreleasePools),
- "No autorelease pool for native event");
-
- if (aMayWait) {
- currentMode = [currentRunLoop currentMode];
- if (!currentMode)
- currentMode = NSDefaultRunLoopMode;
- NSEvent *nextEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
- untilDate:waitUntil
- inMode:currentMode
- dequeue:YES];
- if (nextEvent) {
- mozilla::HangMonitor::NotifyActivity();
- [NSApp sendEvent:nextEvent];
- eventProcessed = true;
- }
- } else {
- // AcquireFirstMatchingEventInQueue() doesn't spin the (native) event
- // loop, though it does queue up any newly available events from the
- // window server.
- EventRef currentEvent = AcquireFirstMatchingEventInQueue(currentEventQueue, 0, NULL,
- kEventQueueOptionsNone);
- if (!currentEvent) {
- continue;
- }
- EventAttributes attrs = GetEventAttributes(currentEvent);
- UInt32 eventKind = GetEventKind(currentEvent);
- UInt32 eventClass = GetEventClass(currentEvent);
- bool osCocoaEvent =
- ((eventClass == 'appl') || (eventClass == kEventClassAppleEvent) ||
- ((eventClass == 'cgs ') && (eventKind != NSApplicationDefined)));
- // If attrs is kEventAttributeUserEvent or kEventAttributeMonitored
- // (i.e. a user input event), we shouldn't process it here while
- // aMayWait is false. Likewise if currentEvent will eventually be
- // turned into an OS-defined Cocoa event, or otherwise needs AppKit
- // processing. Doing otherwise risks doing too much work here, and
- // preventing the event from being properly processed by the AppKit
- // framework.
- if ((attrs != kEventAttributeNone) || osCocoaEvent) {
- // Since we can't process the next event here (while aMayWait is false),
- // we want moreEvents to be false on return.
- eventProcessed = false;
- // This call to ReleaseEvent() matches a call to RetainEvent() in
- // AcquireFirstMatchingEventInQueue() above.
- ReleaseEvent(currentEvent);
- break;
- }
- // This call to RetainEvent() matches a call to ReleaseEvent() in
- // RemoveEventFromQueue() below.
- RetainEvent(currentEvent);
- RemoveEventFromQueue(currentEventQueue, currentEvent);
- SendEventToEventTarget(currentEvent, eventDispatcherTarget);
- // This call to ReleaseEvent() matches a call to RetainEvent() in
- // AcquireFirstMatchingEventInQueue() above.
- ReleaseEvent(currentEvent);
- eventProcessed = true;
- }
- } while (mRunningEventLoop);
-
- if (eventProcessed) {
- moreEvents =
- (AcquireFirstMatchingEventInQueue(currentEventQueue, 0, NULL,
- kEventQueueOptionsNone) != NULL);
- }
-
- mRunningEventLoop = wasRunningEventLoop;
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-
- if (!moreEvents) {
- nsChildView::UpdateCurrentInputEventCount();
- }
-
- return moreEvents;
-}
-
-// Run
-//
-// Overrides the base class's Run() method to call [NSApp run] (which spins
-// the native run loop until the application quits). Since (unlike the base
-// class's Run() method) we don't process any Gecko events here, they need
-// to be processed elsewhere (in NativeEventCallback(), called from
-// ProcessGeckoEvents()).
-//
-// Camino called [NSApp run] on its own (via NSApplicationMain()), and so
-// didn't call nsAppShell::Run().
-//
-// public
-NS_IMETHODIMP
-nsAppShell::Run(void)
-{
- NS_ASSERTION(!mStarted, "nsAppShell::Run() called multiple times");
- if (mStarted || mTerminated)
- return NS_OK;
-
- mStarted = true;
-
- AddScreenWakeLockListener();
-
- NS_OBJC_TRY_ABORT([NSApp run]);
-
- RemoveScreenWakeLockListener();
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsAppShell::Exit(void)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- // This method is currently called more than once -- from (according to
- // mento) an nsAppExitEvent dispatched by nsAppStartup::Quit() and from an
- // XPCOM shutdown notification that nsBaseAppShell has registered to
- // receive. So we need to ensure that multiple calls won't break anything.
- // But we should also complain about it (since it isn't quite kosher).
- if (mTerminated) {
- NS_WARNING("nsAppShell::Exit() called redundantly");
- return NS_OK;
- }
-
- mTerminated = true;
-
-#if !defined(RELEASE_OR_BETA) || defined(DEBUG)
- nsSandboxViolationSink::Stop();
-#endif
-
- // Quoting from Apple's doc on the [NSApplication stop:] method (from their
- // doc on the NSApplication class): "If this method is invoked during a
- // modal event loop, it will break that loop but not the main event loop."
- // nsAppShell::Exit() shouldn't be called from a modal event loop. So if
- // it is we complain about it (to users of debug builds) and call [NSApp
- // stop:] one extra time. (I'm not sure if modal event loops can be nested
- // -- Apple's docs don't say one way or the other. But the return value
- // of [NSApp _isRunningModal] doesn't change immediately after a call to
- // [NSApp stop:], so we have to assume that one extra call to [NSApp stop:]
- // will do the job.)
- BOOL cocoaModal = [NSApp _isRunningModal];
- NS_ASSERTION(!cocoaModal,
- "Don't call nsAppShell::Exit() from a modal event loop!");
- if (cocoaModal)
- [NSApp stop:nullptr];
- [NSApp stop:nullptr];
-
- // A call to Exit() just after a call to ScheduleNativeEventCallback()
- // prevents the (normally) matching call to ProcessGeckoEvents() from
- // happening. If we've been called from ProcessGeckoEvents() (as usually
- // happens), we take care of it there. But if we have an unbalanced call
- // to ScheduleNativeEventCallback() and ProcessGeckoEvents() isn't on the
- // stack, we need to take care of the problem here.
- if (!mNativeEventCallbackDepth && mNativeEventScheduledDepth) {
- int32_t releaseCount = PR_ATOMIC_SET(&mNativeEventScheduledDepth, 0);
- while (releaseCount-- > 0)
- NS_RELEASE_THIS();
- }
-
- return nsBaseAppShell::Exit();
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-// OnProcessNextEvent
-//
-// This nsIThreadObserver method is called prior to processing an event.
-// Set up an autorelease pool that will service any autoreleased Cocoa
-// objects during this event. This includes native events processed by
-// ProcessNextNativeEvent. The autorelease pool will be popped by
-// AfterProcessNextEvent, it is important for these two methods to be
-// tightly coupled.
-//
-// public
-NS_IMETHODIMP
-nsAppShell::OnProcessNextEvent(nsIThreadInternal *aThread, bool aMayWait)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- NS_ASSERTION(mAutoreleasePools,
- "No stack on which to store autorelease pool");
-
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- ::CFArrayAppendValue(mAutoreleasePools, pool);
-
- return nsBaseAppShell::OnProcessNextEvent(aThread, aMayWait);
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-// AfterProcessNextEvent
-//
-// This nsIThreadObserver method is called after event processing is complete.
-// The Cocoa implementation cleans up the autorelease pool create by the
-// previous OnProcessNextEvent call.
-//
-// public
-NS_IMETHODIMP
-nsAppShell::AfterProcessNextEvent(nsIThreadInternal *aThread,
- bool aEventWasProcessed)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- CFIndex count = ::CFArrayGetCount(mAutoreleasePools);
-
- NS_ASSERTION(mAutoreleasePools && count,
- "Processed an event, but there's no autorelease pool?");
-
- const NSAutoreleasePool* pool = static_cast<const NSAutoreleasePool*>
- (::CFArrayGetValueAtIndex(mAutoreleasePools, count - 1));
- ::CFArrayRemoveValueAtIndex(mAutoreleasePools, count - 1);
- [pool release];
-
- return nsBaseAppShell::AfterProcessNextEvent(aThread, aEventWasProcessed);
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-
-// AppShellDelegate implementation
-
-
-@implementation AppShellDelegate
-// initWithAppShell:
-//
-// Constructs the AppShellDelegate object
-- (id)initWithAppShell:(nsAppShell*)aAppShell
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
-
- if ((self = [self init])) {
- mAppShell = aAppShell;
-
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(applicationWillTerminate:)
- name:NSApplicationWillTerminateNotification
- object:NSApp];
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(applicationDidBecomeActive:)
- name:NSApplicationDidBecomeActiveNotification
- object:NSApp];
- [[NSDistributedNotificationCenter defaultCenter] addObserver:self
- selector:@selector(beginMenuTracking:)
- name:@"com.apple.HIToolbox.beginMenuTrackingNotification"
- object:nil];
- }
-
- return self;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
-}
-
-- (void)dealloc
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- [[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
- [super dealloc];
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-// applicationWillTerminate:
-//
-// Notify the nsAppShell that native event processing should be discontinued.
-- (void)applicationWillTerminate:(NSNotification*)aNotification
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- mAppShell->WillTerminate();
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-// applicationDidBecomeActive
-//
-// Make sure TextInputHandler::sLastModifierState is updated when we become
-// active (since we won't have received [ChildView flagsChanged:] messages
-// while inactive).
-- (void)applicationDidBecomeActive:(NSNotification*)aNotification
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- // [NSEvent modifierFlags] is valid on every kind of event, so we don't need
- // to worry about getting an NSInternalInconsistencyException here.
- NSEvent* currentEvent = [NSApp currentEvent];
- if (currentEvent) {
- TextInputHandler::sLastModifierState =
- [currentEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask;
- }
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-// beginMenuTracking
-//
-// Roll up our context menu (if any) when some other app (or the OS) opens
-// any sort of menu. But make sure we don't do this for notifications we
-// send ourselves (whose 'sender' will be @"org.mozilla.gecko.PopupWindow").
-- (void)beginMenuTracking:(NSNotification*)aNotification
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- NSString *sender = [aNotification object];
- if (!sender || ![sender isEqualToString:@"org.mozilla.gecko.PopupWindow"]) {
- nsIRollupListener* rollupListener = nsBaseWidget::GetActiveRollupListener();
- nsCOMPtr<nsIWidget> rollupWidget = rollupListener->GetRollupWidget();
- if (rollupWidget)
- rollupListener->Rollup(0, true, nullptr, nullptr);
- }
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-@end
-
-// We hook terminate: in order to make OS-initiated termination work nicely
-// with Gecko's shutdown sequence. (Two ways to trigger OS-initiated
-// termination: 1) Quit from the Dock menu; 2) Log out from (or shut down)
-// your computer while the browser is active.)
-@interface NSApplication (MethodSwizzling)
-- (void)nsAppShell_NSApplication_terminate:(id)sender;
-@end
-
-@implementation NSApplication (MethodSwizzling)
-
-// Called by the OS after [MacApplicationDelegate applicationShouldTerminate:]
-// has returned NSTerminateNow. This method "subclasses" and replaces the
-// OS's original implementation. The only thing the orginal method does which
-// we need is that it posts NSApplicationWillTerminateNotification. Everything
-// else is unneeded (because it's handled elsewhere), or actively interferes
-// with Gecko's shutdown sequence. For example the original terminate: method
-// causes the app to exit() inside [NSApp run] (called from nsAppShell::Run()
-// above), which means that nothing runs after the call to nsAppStartup::Run()
-// in XRE_Main(), which in particular means that ScopedXPCOMStartup's destructor
-// and NS_ShutdownXPCOM() never get called.
-- (void)nsAppShell_NSApplication_terminate:(id)sender
-{
- [[NSNotificationCenter defaultCenter] postNotificationName:NSApplicationWillTerminateNotification
- object:NSApp];
-}
-
-@end
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 <Carbon/Carbon.h>
-#import <Cocoa/Cocoa.h>
-#import <AppKit/NSOpenGL.h>
-
-class nsChildView;
-class nsCocoaWindow;
-
-namespace {
-class GLPresenter;
-} // namespace
-
-namespace mozilla {
-class InputData;
-class PanGestureInput;
-class SwipeTracker;
-struct SwipeEventQueue;
-class VibrancyManager;
-namespace layers {
-class GLManager;
-class IAPZCTreeManager;
-} // namespace layers
-namespace widget {
-class RectTextureImage;
-class WidgetRenderingContext;
-} // namespace widget
-} // namespace mozilla
-
-@class PixelHostingView;
-
-@interface NSEvent (Undocumented)
-
-// Return Cocoa event's corresponding Carbon event. Not initialized (on
-// synthetic events) until the OS actually "sends" the event. This method
-// has been present in the same form since at least OS X 10.2.8.
-- (EventRef)_eventRef;
-
-@end
-
-@interface NSView (Undocumented)
-
-// Draws the title string of a window.
-// Present on NSThemeFrame since at least 10.6.
-// _drawTitleBar is somewhat complex, and has changed over the years
-// since OS X 10.6. But in that time it's never done anything that
-// would break when called outside of -[NSView drawRect:] (which we
-// sometimes do), or whose output can't be redirected to a
-// CGContextRef object (which we also sometimes do). This is likely
-// to remain true for the indefinite future. However we should
-// check _drawTitleBar in each new major version of OS X. For more
-// information see bug 877767.
-- (void)_drawTitleBar:(NSRect)aRect;
-
-// Returns an NSRect that is the bounding box for all an NSView's dirty
-// rectangles (ones that need to be redrawn). The full list of dirty
-// rectangles can be obtained by calling -[NSView _dirtyRegion] and then
-// calling -[NSRegion getRects:count:] on what it returns. Both these
-// methods have been present in the same form since at least OS X 10.5.
-// Unlike -[NSView getRectsBeingDrawn:count:], these methods can be called
-// outside a call to -[NSView drawRect:].
-- (NSRect)_dirtyRect;
-
-// Undocumented method of one or more of NSFrameView's subclasses. Called
-// when one or more of the titlebar buttons needs to be repositioned, to
-// disappear, or to reappear (say if the window's style changes). If
-// 'redisplay' is true, the entire titlebar (the window's top 22 pixels) is
-// marked as needing redisplay. This method has been present in the same
-// format since at least OS X 10.5.
-- (void)_tileTitlebarAndRedisplay:(BOOL)redisplay;
-
-// The following undocumented methods are used to work around bug 1069658,
-// which is an Apple bug or design flaw that effects Yosemite. None of them
-// were present prior to Yosemite (OS X 10.10).
-- (NSView *)titlebarView; // Method of NSThemeFrame
-- (NSView *)titlebarContainerView; // Method of NSThemeFrame
-- (BOOL)transparent; // Method of NSTitlebarView and NSTitlebarContainerView
-- (void)setTransparent:(BOOL)transparent; // Method of NSTitlebarView and
- // NSTitlebarContainerView
-
-@end
-
-@interface ChildView : NSView<
-#ifdef ACCESSIBILITY
- mozAccessible,
-#endif
- mozView, NSTextInputClient>
-{
-@private
- // the nsChildView that created the view. It retains this NSView, so
- // the link back to it must be weak.
- nsChildView* mGeckoChild;
-
- // Text input handler for mGeckoChild and us. Note that this is a weak
- // reference. Ideally, this should be a strong reference but a ChildView
- // object can live longer than the mGeckoChild that owns it. And if
- // mTextInputHandler were a strong reference, this would make it difficult
- // for Gecko's leak detector to detect leaked TextInputHandler objects.
- // This is initialized by [mozView installTextInputHandler:aHandler] and
- // cleared by [mozView uninstallTextInputHandler].
- mozilla::widget::TextInputHandler* mTextInputHandler; // [WEAK]
-
- // when mouseDown: is called, we store its event here (strong)
- NSEvent* mLastMouseDownEvent;
-
- // Needed for IME support in e10s mode. Strong.
- NSEvent* mLastKeyDownEvent;
-
- // Whether the last mouse down event was blocked from Gecko.
- BOOL mBlockedLastMouseDown;
-
- // when acceptsFirstMouse: is called, we store the event here (strong)
- NSEvent* mClickThroughMouseDownEvent;
-
- // WheelStart/Stop events should always come in pairs. This BOOL records the
- // last received event so that, when we receive one of the events, we make sure
- // to send its pair event first, in case we didn't yet for any reason.
- BOOL mExpectingWheelStop;
-
- // Set to YES when our GL surface has been updated and we need to call
- // updateGLContext before we composite.
- BOOL mNeedsGLUpdate;
-
- // Holds our drag service across multiple drag calls. The reference to the
- // service is obtained when the mouse enters the view and is released when
- // the mouse exits or there is a drop. This prevents us from having to
- // re-establish the connection to the service manager many times per second
- // when handling |draggingUpdated:| messages.
- nsIDragService* mDragService;
-
- NSOpenGLContext *mGLContext;
-
- // Simple gestures support
- //
- // mGestureState is used to detect when Cocoa has called both
- // magnifyWithEvent and rotateWithEvent within the same
- // beginGestureWithEvent and endGestureWithEvent sequence. We
- // discard the spurious gesture event so as not to confuse Gecko.
- //
- // mCumulativeMagnification keeps track of the total amount of
- // magnification peformed during a magnify gesture so that we can
- // send that value with the final MozMagnifyGesture event.
- //
- // mCumulativeRotation keeps track of the total amount of rotation
- // performed during a rotate gesture so we can send that value with
- // the final MozRotateGesture event.
- enum {
- eGestureState_None,
- eGestureState_StartGesture,
- eGestureState_MagnifyGesture,
- eGestureState_RotateGesture
- } mGestureState;
- float mCumulativeMagnification;
- float mCumulativeRotation;
-
-#ifdef __LP64__
- // Support for fluid swipe tracking.
- BOOL* mCancelSwipeAnimation;
-#endif
-
- // Whether this uses off-main-thread compositing.
- BOOL mUsingOMTCompositor;
-
- // The mask image that's used when painting into the titlebar using basic
- // CGContext painting (i.e. non-accelerated).
- CGImageRef mTopLeftCornerMask;
-
- // Subviews of self, which act as container views for vibrancy views and
- // non-draggable views.
- NSView* mVibrancyViewsContainer; // [STRONG]
- NSView* mNonDraggableViewsContainer; // [STRONG]
-
- // The view that does our drawing. This is a subview of self so that it can
- // be ordered on top of mVibrancyViewsContainer.
- PixelHostingView* mPixelHostingView;
-}
-
-// class initialization
-+ (void)initialize;
-
-+ (void)registerViewForDraggedTypes:(NSView*)aView;
-
-// these are sent to the first responder when the window key status changes
-- (void)viewsWindowDidBecomeKey;
-- (void)viewsWindowDidResignKey;
-
-// Stop NSView hierarchy being changed during [ChildView drawRect:]
-- (void)delayedTearDown;
-
-- (void)sendFocusEvent:(mozilla::EventMessage)eventMessage;
-
-- (void)handleMouseMoved:(NSEvent*)aEvent;
-
-- (void)sendMouseEnterOrExitEvent:(NSEvent*)aEvent
- enter:(BOOL)aEnter
- exitFrom:(mozilla::WidgetMouseEvent::ExitFrom)aExitFrom;
-
-- (void)updateGLContext;
-- (void)_surfaceNeedsUpdate:(NSNotification*)notification;
-
-- (bool)preRender:(NSOpenGLContext *)aGLContext;
-- (void)postRender:(NSOpenGLContext *)aGLContext;
-
-- (NSView*)vibrancyViewsContainer;
-- (NSView*)nonDraggableViewsContainer;
-- (NSView*)pixelHostingView;
-
-- (BOOL)isCoveringTitlebar;
-
-- (void)viewWillStartLiveResize;
-- (void)viewDidEndLiveResize;
-
-- (NSColor*)vibrancyFillColorForThemeGeometryType:(nsITheme::ThemeGeometryType)aThemeGeometryType;
-- (NSColor*)vibrancyFontSmoothingBackgroundColorForThemeGeometryType:(nsITheme::ThemeGeometryType)aThemeGeometryType;
-
-// Simple gestures support
-//
-// XXX - The swipeWithEvent, beginGestureWithEvent, magnifyWithEvent,
-// rotateWithEvent, and endGestureWithEvent methods are part of a
-// PRIVATE interface exported by nsResponder and reverse-engineering
-// was necessary to obtain the methods' prototypes. Thus, Apple may
-// change the interface in the future without notice.
-//
-// The prototypes were obtained from the following link:
-// http://cocoadex.com/2008/02/nsevent-modifications-swipe-ro.html
-- (void)swipeWithEvent:(NSEvent *)anEvent;
-- (void)beginGestureWithEvent:(NSEvent *)anEvent;
-- (void)magnifyWithEvent:(NSEvent *)anEvent;
-- (void)smartMagnifyWithEvent:(NSEvent *)anEvent;
-- (void)rotateWithEvent:(NSEvent *)anEvent;
-- (void)endGestureWithEvent:(NSEvent *)anEvent;
-
-- (void)scrollWheel:(NSEvent *)anEvent;
-
-- (void)setUsingOMTCompositor:(BOOL)aUseOMTC;
-
-- (NSEvent*)lastKeyDownEvent;
-@end
-
-class ChildViewMouseTracker {
-
-public:
-
- static void MouseMoved(NSEvent* aEvent);
- static void MouseScrolled(NSEvent* aEvent);
- static void OnDestroyView(ChildView* aView);
- static void OnDestroyWindow(NSWindow* aWindow);
- static BOOL WindowAcceptsEvent(NSWindow* aWindow, NSEvent* aEvent,
- ChildView* aView, BOOL isClickThrough = NO);
- static void MouseExitedWindow(NSEvent* aEvent);
- static void MouseEnteredWindow(NSEvent* aEvent);
- static void ReEvaluateMouseEnterState(NSEvent* aEvent = nil, ChildView* aOldView = nil);
- static void ResendLastMouseMoveEvent();
- static ChildView* ViewForEvent(NSEvent* aEvent);
-
- static ChildView* sLastMouseEventView;
- static NSEvent* sLastMouseMoveEvent;
- static NSWindow* sWindowUnderMouse;
- static NSPoint sLastScrollEventScreenLocation;
-};
-
-//-------------------------------------------------------------------------
-//
-// nsChildView
-//
-//-------------------------------------------------------------------------
-
-class nsChildView : public nsBaseWidget
-{
-private:
- typedef nsBaseWidget Inherited;
- typedef mozilla::layers::IAPZCTreeManager IAPZCTreeManager;
-
-public:
- nsChildView();
-
- // nsIWidget interface
- virtual MOZ_MUST_USE nsresult Create(nsIWidget* aParent,
- nsNativeWidget aNativeParent,
- const LayoutDeviceIntRect& aRect,
- nsWidgetInitData* aInitData = nullptr)
- override;
-
- virtual void Destroy() override;
-
- NS_IMETHOD Show(bool aState) override;
- virtual bool IsVisible() const override;
-
- NS_IMETHOD SetParent(nsIWidget* aNewParent) override;
- virtual nsIWidget* GetParent(void) override;
- virtual float GetDPI() override;
-
- NS_IMETHOD Move(double aX, double aY) override;
- NS_IMETHOD Resize(double aWidth, double aHeight, bool aRepaint) override;
- NS_IMETHOD Resize(double aX, double aY,
- double aWidth, double aHeight, bool aRepaint) override;
-
- NS_IMETHOD Enable(bool aState) override;
- virtual bool IsEnabled() const override;
- NS_IMETHOD SetFocus(bool aRaise) override;
- virtual LayoutDeviceIntRect GetBounds() override;
- virtual LayoutDeviceIntRect GetClientBounds() override;
- virtual LayoutDeviceIntRect GetScreenBounds() override;
-
- // Returns the "backing scale factor" of the view's window, which is the
- // ratio of pixels in the window's backing store to Cocoa points. Prior to
- // HiDPI support in OS X 10.7, this was always 1.0, but in HiDPI mode it
- // will be 2.0 (and might potentially other values as screen resolutions
- // evolve). This gives the relationship between what Gecko calls "device
- // pixels" and the Cocoa "points" coordinate system.
- CGFloat BackingScaleFactor() const;
-
- mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale() final {
- return mozilla::DesktopToLayoutDeviceScale(BackingScaleFactor());
- }
-
- // Call if the window's backing scale factor changes - i.e., it is moved
- // between HiDPI and non-HiDPI screens
- void BackingScaleFactorChanged();
-
- virtual double GetDefaultScaleInternal() override;
-
- virtual int32_t RoundsWidgetCoordinatesTo() override;
-
- NS_IMETHOD Invalidate(const LayoutDeviceIntRect &aRect) override;
-
- virtual void* GetNativeData(uint32_t aDataType) override;
- virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations) override;
- virtual LayoutDeviceIntPoint WidgetToScreenOffset() override;
- virtual bool ShowsResizeIndicator(LayoutDeviceIntRect* aResizerRect) override;
-
- static bool ConvertStatus(nsEventStatus aStatus)
- { return aStatus == nsEventStatus_eConsumeNoDefault; }
- NS_IMETHOD DispatchEvent(mozilla::WidgetGUIEvent* aEvent,
- nsEventStatus& aStatus) override;
-
- virtual bool WidgetTypeSupportsAcceleration() override;
- virtual bool ShouldUseOffMainThreadCompositing() override;
-
- NS_IMETHOD SetCursor(nsCursor aCursor) override;
- NS_IMETHOD SetCursor(imgIContainer* aCursor, uint32_t aHotspotX, uint32_t aHotspotY) override;
-
- NS_IMETHOD SetTitle(const nsAString& title) override;
-
- NS_IMETHOD GetAttention(int32_t aCycleCount) override;
-
- virtual bool HasPendingInputEvent() override;
-
- NS_IMETHOD ActivateNativeMenuItemAt(const nsAString& indexString) override;
- NS_IMETHOD ForceUpdateNativeMenuAt(const nsAString& indexString) override;
- NS_IMETHOD GetSelectionAsPlaintext(nsAString& aResult) override;
-
- NS_IMETHOD_(void) SetInputContext(const InputContext& aContext,
- const InputContextAction& aAction) override;
- NS_IMETHOD_(InputContext) GetInputContext() override;
- NS_IMETHOD_(TextEventDispatcherListener*)
- GetNativeTextEventDispatcherListener() override;
- NS_IMETHOD AttachNativeKeyEvent(mozilla::WidgetKeyboardEvent& aEvent) override;
- NS_IMETHOD_(bool) ExecuteNativeKeyBinding(
- NativeKeyBindingsType aType,
- const mozilla::WidgetKeyboardEvent& aEvent,
- DoCommandCallback aCallback,
- void* aCallbackData) override;
- bool ExecuteNativeKeyBindingRemapped(
- NativeKeyBindingsType aType,
- const mozilla::WidgetKeyboardEvent& aEvent,
- DoCommandCallback aCallback,
- void* aCallbackData,
- uint32_t aGeckoKeyCode,
- uint32_t aCocoaKeyCode);
- virtual nsIMEUpdatePreference GetIMEUpdatePreference() override;
-
- virtual nsTransparencyMode GetTransparencyMode() override;
- virtual void SetTransparencyMode(nsTransparencyMode aMode) override;
-
- virtual nsresult SynthesizeNativeKeyEvent(int32_t aNativeKeyboardLayout,
- int32_t aNativeKeyCode,
- uint32_t aModifierFlags,
- const nsAString& aCharacters,
- const nsAString& aUnmodifiedCharacters,
- nsIObserver* aObserver) override;
-
- virtual nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint,
- uint32_t aNativeMessage,
- uint32_t aModifierFlags,
- nsIObserver* aObserver) override;
-
- virtual nsresult SynthesizeNativeMouseMove(LayoutDeviceIntPoint aPoint,
- nsIObserver* aObserver) override
- { return SynthesizeNativeMouseEvent(aPoint, NSMouseMoved, 0, aObserver); }
- virtual nsresult SynthesizeNativeMouseScrollEvent(LayoutDeviceIntPoint aPoint,
- uint32_t aNativeMessage,
- double aDeltaX,
- double aDeltaY,
- double aDeltaZ,
- uint32_t aModifierFlags,
- uint32_t aAdditionalFlags,
- nsIObserver* aObserver) override;
- virtual nsresult SynthesizeNativeTouchPoint(uint32_t aPointerId,
- TouchPointerState aPointerState,
- LayoutDeviceIntPoint aPoint,
- double aPointerPressure,
- uint32_t aPointerOrientation,
- nsIObserver* aObserver) override;
-
- // Mac specific methods
-
- virtual bool DispatchWindowEvent(mozilla::WidgetGUIEvent& event);
-
- void WillPaintWindow();
- bool PaintWindow(LayoutDeviceIntRegion aRegion);
- bool PaintWindowInContext(CGContextRef aContext, const LayoutDeviceIntRegion& aRegion,
- mozilla::gfx::IntSize aSurfaceSize);
-
-#ifdef ACCESSIBILITY
- already_AddRefed<mozilla::a11y::Accessible> GetDocumentAccessible();
-#endif
-
- virtual void CreateCompositor() override;
- virtual void PrepareWindowEffects() override;
- virtual void CleanupWindowEffects() override;
- virtual bool PreRender(mozilla::widget::WidgetRenderingContext* aContext) override;
- virtual void PostRender(mozilla::widget::WidgetRenderingContext* aContext) override;
- virtual void DrawWindowOverlay(mozilla::widget::WidgetRenderingContext* aManager,
- LayoutDeviceIntRect aRect) override;
-
- virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) override;
-
- virtual void UpdateWindowDraggingRegion(const LayoutDeviceIntRegion& aRegion) override;
- LayoutDeviceIntRegion GetNonDraggableRegion() { return mNonDraggableRegion.Region(); }
-
- virtual void ReportSwipeStarted(uint64_t aInputBlockId, bool aStartSwipe) override;
-
- virtual void LookUpDictionary(
- const nsAString& aText,
- const nsTArray<mozilla::FontRange>& aFontRangeArray,
- const bool aIsVertical,
- const LayoutDeviceIntPoint& aPoint) override;
-
- void ResetParent();
-
- static bool DoHasPendingInputEvent();
- static uint32_t GetCurrentInputEventCount();
- static void UpdateCurrentInputEventCount();
-
- NSView<mozView>* GetEditorView();
-
- nsCocoaWindow* GetXULWindowWidget();
-
- virtual void ReparentNativeWidget(nsIWidget* aNewParent) override;
-
- mozilla::widget::TextInputHandler* GetTextInputHandler()
- {
- return mTextInputHandler;
- }
-
- void ClearVibrantAreas();
- NSColor* VibrancyFillColorForThemeGeometryType(nsITheme::ThemeGeometryType aThemeGeometryType);
- NSColor* VibrancyFontSmoothingBackgroundColorForThemeGeometryType(nsITheme::ThemeGeometryType aThemeGeometryType);
-
- // unit conversion convenience functions
- int32_t CocoaPointsToDevPixels(CGFloat aPts) const {
- return nsCocoaUtils::CocoaPointsToDevPixels(aPts, BackingScaleFactor());
- }
- LayoutDeviceIntPoint CocoaPointsToDevPixels(const NSPoint& aPt) const {
- return nsCocoaUtils::CocoaPointsToDevPixels(aPt, BackingScaleFactor());
- }
- LayoutDeviceIntPoint CocoaPointsToDevPixelsRoundDown(const NSPoint& aPt) const {
- return nsCocoaUtils::CocoaPointsToDevPixelsRoundDown(aPt, BackingScaleFactor());
- }
- LayoutDeviceIntRect CocoaPointsToDevPixels(const NSRect& aRect) const {
- return nsCocoaUtils::CocoaPointsToDevPixels(aRect, BackingScaleFactor());
- }
- CGFloat DevPixelsToCocoaPoints(int32_t aPixels) const {
- return nsCocoaUtils::DevPixelsToCocoaPoints(aPixels, BackingScaleFactor());
- }
- NSRect DevPixelsToCocoaPoints(const LayoutDeviceIntRect& aRect) const {
- return nsCocoaUtils::DevPixelsToCocoaPoints(aRect, BackingScaleFactor());
- }
-
- already_AddRefed<mozilla::gfx::DrawTarget>
- StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion,
- mozilla::layers::BufferMode* aBufferMode) override;
- void EndRemoteDrawing() override;
- void CleanupRemoteDrawing() override;
- bool InitCompositor(mozilla::layers::Compositor* aCompositor) override;
-
- NS_IMETHOD StartPluginIME(const mozilla::WidgetKeyboardEvent& aKeyboardEvent,
- int32_t aPanelX, int32_t aPanelY,
- nsString& aCommitted) override;
-
- virtual void SetPluginFocused(bool& aFocused) override;
-
- bool IsPluginFocused() { return mPluginFocused; }
-
- virtual LayoutDeviceIntPoint GetClientOffset() override;
-
- void DispatchAPZWheelInputEvent(mozilla::InputData& aEvent, bool aCanTriggerSwipe);
-
- void SwipeFinished();
-
-protected:
- virtual ~nsChildView();
-
- void ReportMoveEvent();
- void ReportSizeEvent();
-
- void TearDownView();
-
- virtual already_AddRefed<nsIWidget>
- AllocateChildPopupWidget() override
- {
- static NS_DEFINE_IID(kCPopUpCID, NS_POPUP_CID);
- nsCOMPtr<nsIWidget> widget = do_CreateInstance(kCPopUpCID);
- return widget.forget();
- }
-
- void ConfigureAPZCTreeManager() override;
- void ConfigureAPZControllerThread() override;
-
- void DoRemoteComposition(const LayoutDeviceIntRect& aRenderRect);
-
- // Overlay drawing functions for OpenGL drawing
- void DrawWindowOverlay(mozilla::layers::GLManager* aManager, LayoutDeviceIntRect aRect);
- void MaybeDrawResizeIndicator(mozilla::layers::GLManager* aManager);
- void MaybeDrawRoundedCorners(mozilla::layers::GLManager* aManager, const LayoutDeviceIntRect& aRect);
- void MaybeDrawTitlebar(mozilla::layers::GLManager* aManager);
-
- // Redraw the contents of mTitlebarCGContext on the main thread, as
- // determined by mDirtyTitlebarRegion.
- void UpdateTitlebarCGContext();
-
- LayoutDeviceIntRect RectContainingTitlebarControls();
- void UpdateVibrancy(const nsTArray<ThemeGeometry>& aThemeGeometries);
- mozilla::VibrancyManager& EnsureVibrancyManager();
-
- nsIWidget* GetWidgetForListenerEvents();
-
- struct SwipeInfo {
- bool wantsSwipe;
- uint32_t allowedDirections;
- };
-
- SwipeInfo SendMayStartSwipe(const mozilla::PanGestureInput& aSwipeStartEvent);
- void TrackScrollEventAsSwipe(const mozilla::PanGestureInput& aSwipeStartEvent,
- uint32_t aAllowedDirections);
-
-protected:
-
- ChildView<mozView>* mView; // my parallel cocoa view, [STRONG]
- RefPtr<mozilla::widget::TextInputHandler> mTextInputHandler;
- InputContext mInputContext;
-
- NSView<mozView>* mParentView;
- nsIWidget* mParentWidget;
-
-#ifdef ACCESSIBILITY
- // weak ref to this childview's associated mozAccessible for speed reasons
- // (we get queried for it *a lot* but don't want to own it)
- nsWeakPtr mAccessible;
-#endif
-
- // Protects the view from being teared down while a composition is in
- // progress on the compositor thread.
- mozilla::Mutex mViewTearDownLock;
-
- mozilla::Mutex mEffectsLock;
-
- // May be accessed from any thread, protected
- // by mEffectsLock.
- bool mShowsResizeIndicator;
- LayoutDeviceIntRect mResizeIndicatorRect;
- bool mHasRoundedBottomCorners;
- int mDevPixelCornerRadius;
- bool mIsCoveringTitlebar;
- bool mIsFullscreen;
- bool mIsOpaque;
- LayoutDeviceIntRect mTitlebarRect;
-
- // The area of mTitlebarCGContext that needs to be redrawn during the next
- // transaction. Accessed from any thread, protected by mEffectsLock.
- LayoutDeviceIntRegion mUpdatedTitlebarRegion;
- CGContextRef mTitlebarCGContext;
-
- // Compositor thread only
- mozilla::UniquePtr<mozilla::widget::RectTextureImage> mResizerImage;
- mozilla::UniquePtr<mozilla::widget::RectTextureImage> mCornerMaskImage;
- mozilla::UniquePtr<mozilla::widget::RectTextureImage> mTitlebarImage;
- mozilla::UniquePtr<mozilla::widget::RectTextureImage> mBasicCompositorImage;
-
- // The area of mTitlebarCGContext that has changed and needs to be
- // uploaded to to mTitlebarImage. Main thread only.
- nsIntRegion mDirtyTitlebarRegion;
-
- mozilla::ViewRegion mNonDraggableRegion;
-
- // Cached value of [mView backingScaleFactor], to avoid sending two obj-c
- // messages (respondsToSelector, backingScaleFactor) every time we need to
- // use it.
- // ** We'll need to reinitialize this if the backing resolution changes. **
- mutable CGFloat mBackingScaleFactor;
-
- bool mVisible;
- bool mDrawing;
- bool mIsDispatchPaint; // Is a paint event being dispatched
-
- bool mPluginFocused;
-
- // Used in OMTC BasicLayers mode. Presents the BasicCompositor result
- // surface to the screen using an OpenGL context.
- mozilla::UniquePtr<GLPresenter> mGLPresenter;
-
- mozilla::UniquePtr<mozilla::VibrancyManager> mVibrancyManager;
- RefPtr<mozilla::SwipeTracker> mSwipeTracker;
- mozilla::UniquePtr<mozilla::SwipeEventQueue> mSwipeEventQueue;
-
- // Only used for drawRect-based painting in popups.
- RefPtr<mozilla::gfx::DrawTarget> mBackingSurface;
-
- // This flag is only used when APZ is off. It indicates that the current pan
- // gesture was processed as a swipe. Sometimes the swipe animation can finish
- // before momentum events of the pan gesture have stopped firing, so this
- // flag tells us that we shouldn't allow the remaining events to cause
- // scrolling. It is reset to false once a new gesture starts (as indicated by
- // a PANGESTURE_(MAY)START event).
- bool mCurrentPanGestureBelongsToSwipe;
-
- static uint32_t sLastInputEventCount;
-
- void ReleaseTitlebarCGContext();
-
- // This is used by SynthesizeNativeTouchPoint to maintain state between
- // multiple synthesized points
- mozilla::UniquePtr<mozilla::MultiTouchInput> mSynthesizedTouchInput;
-};
-
-#endif // nsChildView_h_
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 <unistd.h>
-#include <math.h>
-
-#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 <dlfcn.h>
-
-#include <ApplicationServices/ApplicationServices.h>
-
-#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<mozAccessible>)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, &region);
- 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<GLPresenter> CreateForWindow(nsIWidget* aWindow)
- {
- // Contrary to CompositorOGL, we allow unaccelerated OpenGL contexts to be
- // used. BasicCompositor only requires very basic GL functionality.
- RefPtr<GLContext> context = gl::GLContextProvider::CreateForWindow(aWindow, false);
- return context ? MakeUnique<GLPresenter>(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<mozilla::gl::GLContext> mGLContext;
- mozilla::UniquePtr<mozilla::layers::ShaderProgramOGL> mRGBARectProgram;
- gfx::Matrix4x4 mProjMatrix;
- GLuint mQuadVBO;
-};
-
-} // unnamed namespace
-
-namespace mozilla {
-
-struct SwipeEventQueue {
- SwipeEventQueue(uint32_t aAllowedDirections, uint64_t aInputBlockId)
- : allowedDirections(aAllowedDirections)
- , inputBlockId(aInputBlockId)
- {}
-
- nsTArray<PanGestureInput> 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<nsChildView*>(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<mozView>*)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<NSView<mozView>*>(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<nsIWidget> 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<nsIWidget> 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<mozView>* newParentView =
- (NSView<mozView>*)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<MultiTouchInput>();
- }
-
- 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<const unichar*>(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<Configuration>& aConfigurations)
-{
- return NS_OK;
-}
-
-// Invokes callback and ProcessEvent methods on Event Listener object
-NS_IMETHODIMP nsChildView::DispatchEvent(WidgetGUIEvent* event,
- nsEventStatus& aStatus)
-{
- RefPtr<nsChildView> 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<nsIWidget> 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<nsIWidget> widget = GetWidgetForListenerEvents();
-
- nsIWidgetListener* listener = widget->GetWidgetListener();
- if (listener) {
- listener->WillPaintWindow(widget);
- }
-}
-
-bool nsChildView::PaintWindow(LayoutDeviceIntRegion aRegion)
-{
- nsCOMPtr<nsIWidget> 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<gfxContext> 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<NSEvent*>(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<mozView>* nsChildView::GetEditorView()
-{
- NSView<mozView>* editorView = mView;
- // We need to get editor's view. E.g., when the focus is in the bookmark
- // dialog, the view is <panel> 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<mozView>* view = static_cast<NSView<mozView>*>(
- 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<GLManager> 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<GLManager> 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<GLManager> 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<RectTextureImage>();
- }
-
- 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<RectTextureImage>();
- }
-
- 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<RectTextureImage>();
- }
-
- LayoutDeviceIntSize size(mDevPixelCornerRadius, mDevPixelCornerRadius);
- mCornerMaskImage->UpdateIfNeeded(size, LayoutDeviceIntRegion(), ^(gfx::DrawTarget* drawTarget, const LayoutDeviceIntRegion& updateRegion) {
- ClearRegion(drawTarget, updateRegion);
- RefPtr<gfx::PathBuilder> builder = drawTarget->CreatePathBuilder();
- builder->Arc(gfx::Point(mDevPixelCornerRadius, mDevPixelCornerRadius), mDevPixelCornerRadius, 0, 2.0f * M_PI);
- RefPtr<gfx::Path> 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<nsIWidget::ThemeGeometry>& 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<nsIWidget::ThemeGeometry>& 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<nsIWidget::ThemeGeometry>& 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<ThemeGeometry>& 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<nsIWidget::ThemeGeometry>& 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<typename Region>
-static void MakeRegionsNonOverlappingImpl(Region& aOutUnion) { }
-
-template<typename Region, typename ... Regions>
-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<typename Region, typename ... Regions>
-static void MakeRegionsNonOverlapping(Region& aFirst, Regions& ... aRest)
-{
- Region unionOfAll;
- MakeRegionsNonOverlappingImpl(unionOfAll, aFirst, aRest...);
-}
-
-void
-nsChildView::UpdateVibrancy(const nsTArray<ThemeGeometry>& 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<VibrancyManager>(*this, [mView vibrancyViewsContainer]);
- }
- return *mVibrancyManager;
-}
-
-nsChildView::SwipeInfo
-nsChildView::SendMayStartSwipe(const mozilla::PanGestureInput& aSwipeStartEvent)
-{
- nsCOMPtr<nsIWidget> 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<gfx::DrawTarget>
-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<RectTextureImage>();
- }
-
- RefPtr<gfx::DrawTarget> 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<SwipeEventQueue>(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<SwipeEventQueue>(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<mozilla::FontRange>& 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<a11y::Accessible>
-nsChildView::GetDocumentAccessible()
-{
- if (!mozilla::a11y::ShouldA11yBeEnabled())
- return nullptr;
-
- if (mAccessible) {
- RefPtr<a11y::Accessible> ret;
- CallQueryReferent(mAccessible.get(),
- static_cast<a11y::Accessible**>(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<a11y::Accessible> 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<ShaderProgramOGL>(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<GLfloat> 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<nsCOMPtr<nsIWidget>>&& 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<nsCOMPtr<nsIWidget>> 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<nsIWidget*>(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<nsIObserverService> observerService = mozilla::services::GetObserverService();
-
- if (!observerService) {
- return;
- }
-
- observerService->NotifyObservers(nullptr, "live-resize-start", nullptr);
-}
-
-- (void)viewDidEndLiveResize
-{
- nsCOMPtr<nsIObserverService> 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<nsCOMPtr<nsIWidget>> widgetArray;
- while (parent) {
- widgetArray.AppendElement(parent);
- parent = parent->GetParent();
- }
- widgetArray.AppendElement(mGeckoChild);
- nsCOMPtr<nsIRunnable> 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<nsIWidget> 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<nsIWidget> rollupWidget = rollupListener->GetRollupWidget();
- if (rollupWidget) {
- NSWindow* currentPopup = static_cast<NSWindow*>(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<nsIWidget*, 5> 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<int32_t>(floor(aDouble)) :
- static_cast<int32_t>(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<nsChildView> 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<ScreenPixel>(
- [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<mozView>*)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<NSAttributedString*>(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<const char*>(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<NSAttributedString*>(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<nsIDragSession> 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<nsIDragSession> 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<nsIDOMNode> 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<nsDragService *>(mDragService);
- int32_t childDragAction = dragService->TakeChildProcessDragAction();
- if (childDragAction != nsIDragService::DRAGDROP_ACTION_UNINITIALIZED) {
- dragAction = childDragAction;
- }
-
- return [self dragOperationFromDragAction:dragAction];
- }
- case eDragExit:
- case eDrop: {
- nsCOMPtr<nsIDOMNode> 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 <NSDraggingInfo>)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 <NSDraggingInfo>)sender
-{
- MOZ_LOG(sCocoaLog, LogLevel::Info, ("ChildView draggingUpdated: entered\n"));
-
- return [self doDragAction:eDragOver sender:sender];
-}
-
-- (void)draggingExited:(id <NSDraggingInfo>)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 <NSDraggingInfo>)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<nsIDragService> 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<nsDragService *>(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<nsIDOMDataTransfer> 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<nsIFile> targFile;
- NS_NewLocalFile(EmptyString(), true, getter_AddRefs(targFile));
- nsCOMPtr<nsILocalFileMac> 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<nsITransferable> 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<nsISupports> 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<nsITransferable> 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<mozAccessible>)accessible
-{
- if (!mGeckoChild)
- return nil;
-
- id<mozAccessible> nativeAccessible = nil;
-
- nsAutoRetainCocoaObject kungFuDeathGrip(self);
- RefPtr<nsChildView> geckoChild(mGeckoChild);
- RefPtr<a11y::Accessible> 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<mozAccessible> 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 <Cocoa/Cocoa.h>
-
-class nsITransferable;
-
-class nsClipboard : public nsIClipboard
-{
-
-public:
- nsClipboard();
-
- NS_DECL_ISUPPORTS
- NS_DECL_NSICLIPBOARD
-
- // On macOS, cache the transferable of the current selection (chrome/content)
- // in the parent process. This is needed for the services menu which
- // requires synchronous access to the current selection.
- static mozilla::StaticRefPtr<nsITransferable> sSelectionCache;
-
- // Helper methods, used also by nsDragService
- static NSDictionary* PasteboardDictFromTransferable(nsITransferable *aTransferable);
- static bool IsStringType(const nsCString& aMIMEType, NSString** aPasteboardType);
- static NSString* WrapHtmlForSystemPasteboard(NSString* aString);
- static nsresult TransferableFromPasteboard(nsITransferable *aTransferable, NSPasteboard *pboard);
-
-protected:
-
- // impelement the native clipboard behavior
- NS_IMETHOD SetNativeClipboardData(int32_t aWhichClipboard);
- NS_IMETHOD GetNativeClipboardData(nsITransferable * aTransferable, int32_t aWhichClipboard);
- void ClearSelectionCache();
- void SetSelectionCache(nsITransferable* aTransferable);
-
-private:
- virtual ~nsClipboard();
- int32_t mCachedClipboard;
- int32_t mChangeCount; // Set to the native change count after any modification of the clipboard.
-
- bool mIgnoreEmptyNotification;
- nsCOMPtr<nsIClipboardOwner> mClipboardOwner;
- nsCOMPtr<nsITransferable> mTransferable;
-};
-
-#endif // nsClipboard_h_
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<nsITransferable> nsClipboard::sSelectionCache;
-
-nsClipboard::nsClipboard()
- : mCachedClipboard(-1)
- , mChangeCount(0)
- , mIgnoreEmptyNotification(false)
-{
- EnsureLogInitialized();
-}
-
-nsClipboard::~nsClipboard()
-{
- EmptyClipboard(kGlobalClipboard);
- EmptyClipboard(kFindClipboard);
- ClearSelectionCache();
-}
-
-NS_IMPL_ISUPPORTS(nsClipboard, nsIClipboard)
-
-// We separate this into its own function because after an @try, all local
-// variables within that function get marked as volatile, and our C++ type
-// system doesn't like volatile things.
-static NSData*
-GetDataFromPasteboard(NSPasteboard* aPasteboard, NSString* aType)
-{
- NSData *data = nil;
- @try {
- data = [aPasteboard dataForType:aType];
- } @catch (NSException* e) {
- NS_WARNING(nsPrintfCString("Exception raised while getting data from the pasteboard: \"%s - %s\"",
- [[e name] UTF8String], [[e reason] UTF8String]).get());
- mozilla::Unused << e;
- }
- return data;
-}
-
-void
-nsClipboard::SetSelectionCache(nsITransferable *aTransferable)
-{
- sSelectionCache = aTransferable;
-}
-
-void
-nsClipboard::ClearSelectionCache()
-{
- sSelectionCache = nullptr;
-}
-
-NS_IMETHODIMP
-nsClipboard::SetNativeClipboardData(int32_t aWhichClipboard)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- if ((aWhichClipboard != kGlobalClipboard && aWhichClipboard != kFindClipboard) || !mTransferable)
- return NS_ERROR_FAILURE;
-
- mIgnoreEmptyNotification = true;
-
- NSDictionary* pasteboardOutputDict = PasteboardDictFromTransferable(mTransferable);
- if (!pasteboardOutputDict)
- return NS_ERROR_FAILURE;
-
- unsigned int outputCount = [pasteboardOutputDict count];
- NSArray* outputKeys = [pasteboardOutputDict allKeys];
- NSPasteboard* cocoaPasteboard;
- if (aWhichClipboard == kFindClipboard) {
- cocoaPasteboard = [NSPasteboard pasteboardWithName:NSFindPboard];
- [cocoaPasteboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
- } else {
- // Write everything else out to the general pasteboard.
- cocoaPasteboard = [NSPasteboard generalPasteboard];
- [cocoaPasteboard declareTypes:outputKeys owner:nil];
- }
-
- for (unsigned int i = 0; i < outputCount; i++) {
- NSString* currentKey = [outputKeys objectAtIndex:i];
- id currentValue = [pasteboardOutputDict valueForKey:currentKey];
- if (aWhichClipboard == kFindClipboard) {
- if (currentKey == NSStringPboardType)
- [cocoaPasteboard setString:currentValue forType:currentKey];
- } else {
- if (currentKey == NSStringPboardType ||
- currentKey == kCorePboardType_url ||
- currentKey == kCorePboardType_urld ||
- currentKey == kCorePboardType_urln) {
- [cocoaPasteboard setString:currentValue forType:currentKey];
- } else if (currentKey == NSHTMLPboardType) {
- [cocoaPasteboard setString:(nsClipboard::WrapHtmlForSystemPasteboard(currentValue))
- forType:currentKey];
- } else {
- [cocoaPasteboard setData:currentValue forType:currentKey];
- }
- }
- }
-
- mCachedClipboard = aWhichClipboard;
- mChangeCount = [cocoaPasteboard changeCount];
-
- mIgnoreEmptyNotification = false;
-
- return NS_OK;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-nsresult
-nsClipboard::TransferableFromPasteboard(nsITransferable *aTransferable, NSPasteboard *cocoaPasteboard)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- // get flavor list that includes all acceptable flavors (including ones obtained through conversion)
- nsCOMPtr<nsIArray> flavorList;
- nsresult rv = aTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList));
- if (NS_FAILED(rv))
- return NS_ERROR_FAILURE;
-
- uint32_t flavorCount;
- flavorList->GetLength(&flavorCount);
-
- for (uint32_t i = 0; i < flavorCount; i++) {
- nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryElementAt(flavorList, i);
- if (!currentFlavor)
- continue;
-
- nsXPIDLCString flavorStr;
- currentFlavor->ToString(getter_Copies(flavorStr)); // i has a flavr
-
- // printf("looking for clipboard data of type %s\n", flavorStr.get());
-
- NSString *pboardType = nil;
- if (nsClipboard::IsStringType(flavorStr, &pboardType)) {
- NSString* pString = [cocoaPasteboard stringForType:pboardType];
- if (!pString)
- continue;
-
- NSData* stringData;
- if ([pboardType isEqualToString:NSRTFPboardType]) {
- stringData = [pString dataUsingEncoding:NSASCIIStringEncoding];
- } else {
- stringData = [pString dataUsingEncoding:NSUnicodeStringEncoding];
- }
- unsigned int dataLength = [stringData length];
- void* clipboardDataPtr = malloc(dataLength);
- if (!clipboardDataPtr)
- return NS_ERROR_OUT_OF_MEMORY;
- [stringData getBytes:clipboardDataPtr];
-
- // The DOM only wants LF, so convert from MacOS line endings to DOM line endings.
- int32_t signedDataLength = dataLength;
- nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks(flavorStr, &clipboardDataPtr, &signedDataLength);
- dataLength = signedDataLength;
-
- // skip BOM (Byte Order Mark to distinguish little or big endian)
- char16_t* clipboardDataPtrNoBOM = (char16_t*)clipboardDataPtr;
- if ((dataLength > 2) &&
- ((clipboardDataPtrNoBOM[0] == 0xFEFF) ||
- (clipboardDataPtrNoBOM[0] == 0xFFFE))) {
- dataLength -= sizeof(char16_t);
- clipboardDataPtrNoBOM += 1;
- }
-
- nsCOMPtr<nsISupports> genericDataWrapper;
- nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr, clipboardDataPtrNoBOM, dataLength,
- getter_AddRefs(genericDataWrapper));
- aTransferable->SetTransferData(flavorStr, genericDataWrapper, dataLength);
- free(clipboardDataPtr);
- break;
- }
- else if (flavorStr.EqualsLiteral(kCustomTypesMime)) {
- NSString* type = [cocoaPasteboard availableTypeFromArray:[NSArray arrayWithObject:kCustomTypesPboardType]];
- if (!type) {
- continue;
- }
-
- NSData* pasteboardData = GetDataFromPasteboard(cocoaPasteboard, type);
- if (!pasteboardData) {
- continue;
- }
-
- unsigned int dataLength = [pasteboardData length];
- void* clipboardDataPtr = malloc(dataLength);
- if (!clipboardDataPtr) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- [pasteboardData getBytes:clipboardDataPtr];
-
- nsCOMPtr<nsISupports> genericDataWrapper;
- nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr, clipboardDataPtr, dataLength,
- getter_AddRefs(genericDataWrapper));
-
- aTransferable->SetTransferData(flavorStr, genericDataWrapper, dataLength);
- free(clipboardDataPtr);
- }
- else if (flavorStr.EqualsLiteral(kJPEGImageMime) ||
- flavorStr.EqualsLiteral(kJPGImageMime) ||
- flavorStr.EqualsLiteral(kPNGImageMime) ||
- flavorStr.EqualsLiteral(kGIFImageMime)) {
- // Figure out if there's data on the pasteboard we can grab (sanity check)
- NSString *type = [cocoaPasteboard availableTypeFromArray:[NSArray arrayWithObjects:IMAGE_PASTEBOARD_TYPES]];
- if (!type)
- continue;
-
- // Read data off the clipboard
- NSData *pasteboardData = GetDataFromPasteboard(cocoaPasteboard, type);
- if (!pasteboardData)
- continue;
-
- // Figure out what type we're converting to
- CFStringRef outputType = NULL;
- if (flavorStr.EqualsLiteral(kJPEGImageMime) ||
- flavorStr.EqualsLiteral(kJPGImageMime))
- outputType = CFSTR("public.jpeg");
- else if (flavorStr.EqualsLiteral(kPNGImageMime))
- outputType = CFSTR("public.png");
- else if (flavorStr.EqualsLiteral(kGIFImageMime))
- outputType = CFSTR("com.compuserve.gif");
- else
- continue;
-
- // Use ImageIO to interpret the data on the clipboard and transcode.
- // Note that ImageIO, like all CF APIs, allows NULLs to propagate freely
- // and safely in most cases (like ObjC). A notable exception is CFRelease.
- NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
- (NSNumber*)kCFBooleanTrue, kCGImageSourceShouldAllowFloat,
- (type == NSTIFFPboardType ? @"public.tiff" : @"public.png"),
- kCGImageSourceTypeIdentifierHint, nil];
-
- CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)pasteboardData,
- (CFDictionaryRef)options);
- NSMutableData *encodedData = [NSMutableData data];
- CGImageDestinationRef dest = CGImageDestinationCreateWithData((CFMutableDataRef)encodedData,
- outputType,
- 1, NULL);
- CGImageDestinationAddImageFromSource(dest, source, 0, NULL);
- bool successfullyConverted = CGImageDestinationFinalize(dest);
-
- if (successfullyConverted) {
- // Put the converted data in a form Gecko can understand
- nsCOMPtr<nsIInputStream> byteStream;
- NS_NewByteInputStream(getter_AddRefs(byteStream), (const char*)[encodedData bytes],
- [encodedData length], NS_ASSIGNMENT_COPY);
-
- aTransferable->SetTransferData(flavorStr, byteStream, sizeof(nsIInputStream*));
- }
-
- if (dest)
- CFRelease(dest);
- if (source)
- CFRelease(source);
-
- if (successfullyConverted)
- break;
- else
- continue;
- }
- }
-
- return NS_OK;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP
-nsClipboard::GetNativeClipboardData(nsITransferable* aTransferable, int32_t aWhichClipboard)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- if ((aWhichClipboard != kGlobalClipboard && aWhichClipboard != kFindClipboard) || !aTransferable)
- return NS_ERROR_FAILURE;
-
- NSPasteboard* cocoaPasteboard;
- if (aWhichClipboard == kFindClipboard) {
- cocoaPasteboard = [NSPasteboard pasteboardWithName:NSFindPboard];
- } else {
- cocoaPasteboard = [NSPasteboard generalPasteboard];
- }
- if (!cocoaPasteboard)
- return NS_ERROR_FAILURE;
-
- // get flavor list that includes all acceptable flavors (including ones obtained through conversion)
- nsCOMPtr<nsIArray> flavorList;
- nsresult rv = aTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList));
- if (NS_FAILED(rv))
- return NS_ERROR_FAILURE;
-
- uint32_t flavorCount;
- flavorList->GetLength(&flavorCount);
-
- // If we were the last ones to put something on the pasteboard, then just use the cached
- // transferable. Otherwise clear it because it isn't relevant any more.
- if (mCachedClipboard == aWhichClipboard &&
- mChangeCount == [cocoaPasteboard changeCount]) {
- if (mTransferable) {
- for (uint32_t i = 0; i < flavorCount; i++) {
- nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryElementAt(flavorList, i);
- if (!currentFlavor)
- continue;
-
- nsXPIDLCString flavorStr;
- currentFlavor->ToString(getter_Copies(flavorStr));
-
- nsCOMPtr<nsISupports> dataSupports;
- uint32_t dataSize = 0;
- rv = mTransferable->GetTransferData(flavorStr, getter_AddRefs(dataSupports), &dataSize);
- if (NS_SUCCEEDED(rv)) {
- aTransferable->SetTransferData(flavorStr, dataSupports, dataSize);
- return NS_OK; // maybe try to fill in more types? Is there a point?
- }
- }
- }
- } else {
- EmptyClipboard(aWhichClipboard);
- }
-
- // at this point we can't satisfy the request from cache data so let's look
- // for things other people put on the system clipboard
-
- return nsClipboard::TransferableFromPasteboard(aTransferable, cocoaPasteboard);
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-// returns true if we have *any* of the passed in flavors available for pasting
-NS_IMETHODIMP
-nsClipboard::HasDataMatchingFlavors(const char** aFlavorList, uint32_t aLength,
- int32_t aWhichClipboard, bool* outResult)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- *outResult = false;
-
- if ((aWhichClipboard != kGlobalClipboard) || !aFlavorList)
- return NS_OK;
-
- // first see if we have data for this in our cached transferable
- if (mTransferable) {
- nsCOMPtr<nsIArray> transferableFlavorList;
- nsresult rv = mTransferable->FlavorsTransferableCanImport(getter_AddRefs(transferableFlavorList));
- if (NS_SUCCEEDED(rv)) {
- uint32_t transferableFlavorCount;
- transferableFlavorList->GetLength(&transferableFlavorCount);
- for (uint32_t j = 0; j < transferableFlavorCount; j++) {
- nsCOMPtr<nsISupportsCString> currentTransferableFlavor =
- do_QueryElementAt(transferableFlavorList, j);
- if (!currentTransferableFlavor)
- continue;
- nsXPIDLCString transferableFlavorStr;
- currentTransferableFlavor->ToString(getter_Copies(transferableFlavorStr));
-
- for (uint32_t k = 0; k < aLength; k++) {
- if (transferableFlavorStr.Equals(aFlavorList[k])) {
- *outResult = true;
- return NS_OK;
- }
- }
- }
- }
- }
-
- NSPasteboard* generalPBoard = [NSPasteboard generalPasteboard];
-
- for (uint32_t i = 0; i < aLength; i++) {
- nsDependentCString mimeType(aFlavorList[i]);
- NSString *pboardType = nil;
-
- if (nsClipboard::IsStringType(mimeType, &pboardType)) {
- NSString* availableType = [generalPBoard availableTypeFromArray:[NSArray arrayWithObject:pboardType]];
- if (availableType && [availableType isEqualToString:pboardType]) {
- *outResult = true;
- break;
- }
- } else if (!strcmp(aFlavorList[i], kCustomTypesMime)) {
- NSString* availableType = [generalPBoard availableTypeFromArray:[NSArray arrayWithObject:kCustomTypesPboardType]];
- if (availableType) {
- *outResult = true;
- break;
- }
- } else if (!strcmp(aFlavorList[i], kJPEGImageMime) ||
- !strcmp(aFlavorList[i], kJPGImageMime) ||
- !strcmp(aFlavorList[i], kPNGImageMime) ||
- !strcmp(aFlavorList[i], kGIFImageMime)) {
- NSString* availableType = [generalPBoard availableTypeFromArray:
- [NSArray arrayWithObjects:IMAGE_PASTEBOARD_TYPES]];
- if (availableType) {
- *outResult = true;
- break;
- }
- }
- }
-
- return NS_OK;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP
-nsClipboard::SupportsFindClipboard(bool *_retval)
-{
- NS_ENSURE_ARG_POINTER(_retval);
- *_retval = true;
- return NS_OK;
-}
-
-// This function converts anything that other applications might understand into the system format
-// and puts it into a dictionary which it returns.
-// static
-NSDictionary*
-nsClipboard::PasteboardDictFromTransferable(nsITransferable* aTransferable)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
-
- if (!aTransferable)
- return nil;
-
- NSMutableDictionary* pasteboardOutputDict = [NSMutableDictionary dictionary];
-
- nsCOMPtr<nsIArray> flavorList;
- nsresult rv = aTransferable->FlavorsTransferableCanExport(getter_AddRefs(flavorList));
- if (NS_FAILED(rv))
- return nil;
-
- uint32_t flavorCount;
- flavorList->GetLength(&flavorCount);
- for (uint32_t i = 0; i < flavorCount; i++) {
- nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryElementAt(flavorList, i);
- if (!currentFlavor)
- continue;
-
- nsXPIDLCString flavorStr;
- currentFlavor->ToString(getter_Copies(flavorStr));
-
- MOZ_LOG(sCocoaLog, LogLevel::Info, ("writing out clipboard data of type %s (%d)\n", flavorStr.get(), i));
-
- NSString *pboardType = nil;
-
- if (nsClipboard::IsStringType(flavorStr, &pboardType)) {
- void* data = nullptr;
- uint32_t dataSize = 0;
- nsCOMPtr<nsISupports> genericDataWrapper;
- rv = aTransferable->GetTransferData(flavorStr, getter_AddRefs(genericDataWrapper), &dataSize);
- nsPrimitiveHelpers::CreateDataFromPrimitive(flavorStr, genericDataWrapper, &data, dataSize);
-
- NSString* nativeString;
- if (data)
- nativeString = [NSString stringWithCharacters:(const unichar*)data length:(dataSize / sizeof(char16_t))];
- else
- nativeString = [NSString string];
-
- // be nice to Carbon apps, normalize the receiver's contents using Form C.
- nativeString = [nativeString precomposedStringWithCanonicalMapping];
-
- [pasteboardOutputDict setObject:nativeString forKey:pboardType];
-
- free(data);
- }
- else if (flavorStr.EqualsLiteral(kCustomTypesMime)) {
- void* data = nullptr;
- uint32_t dataSize = 0;
- nsCOMPtr<nsISupports> genericDataWrapper;
- rv = aTransferable->GetTransferData(flavorStr, getter_AddRefs(genericDataWrapper), &dataSize);
- nsPrimitiveHelpers::CreateDataFromPrimitive(flavorStr, genericDataWrapper, &data, dataSize);
-
- if (data) {
- NSData* nativeData = [NSData dataWithBytes:data length:dataSize];
-
- [pasteboardOutputDict setObject:nativeData forKey:kCustomTypesPboardType];
- free(data);
- }
- }
- else if (flavorStr.EqualsLiteral(kPNGImageMime) || flavorStr.EqualsLiteral(kJPEGImageMime) ||
- flavorStr.EqualsLiteral(kJPGImageMime) || flavorStr.EqualsLiteral(kGIFImageMime) ||
- flavorStr.EqualsLiteral(kNativeImageMime)) {
- uint32_t dataSize = 0;
- nsCOMPtr<nsISupports> transferSupports;
- aTransferable->GetTransferData(flavorStr, getter_AddRefs(transferSupports), &dataSize);
- nsCOMPtr<nsISupportsInterfacePointer> ptrPrimitive(do_QueryInterface(transferSupports));
- if (!ptrPrimitive)
- continue;
-
- nsCOMPtr<nsISupports> primitiveData;
- ptrPrimitive->GetData(getter_AddRefs(primitiveData));
-
- nsCOMPtr<imgIContainer> image(do_QueryInterface(primitiveData));
- if (!image) {
- NS_WARNING("Image isn't an imgIContainer in transferable");
- continue;
- }
-
- RefPtr<SourceSurface> surface =
- image->GetFrame(imgIContainer::FRAME_CURRENT,
- imgIContainer::FLAG_SYNC_DECODE);
- if (!surface) {
- continue;
- }
- CGImageRef imageRef = NULL;
- rv = nsCocoaUtils::CreateCGImageFromSurface(surface, &imageRef);
- if (NS_FAILED(rv) || !imageRef) {
- continue;
- }
-
- // Convert the CGImageRef to TIFF data.
- CFMutableDataRef tiffData = CFDataCreateMutable(kCFAllocatorDefault, 0);
- CGImageDestinationRef destRef = CGImageDestinationCreateWithData(tiffData,
- CFSTR("public.tiff"),
- 1,
- NULL);
- CGImageDestinationAddImage(destRef, imageRef, NULL);
- bool successfullyConverted = CGImageDestinationFinalize(destRef);
-
- CGImageRelease(imageRef);
- if (destRef)
- CFRelease(destRef);
-
- if (!successfullyConverted) {
- if (tiffData)
- CFRelease(tiffData);
- continue;
- }
-
- [pasteboardOutputDict setObject:(NSMutableData*)tiffData forKey:NSTIFFPboardType];
- if (tiffData)
- CFRelease(tiffData);
- }
- else if (flavorStr.EqualsLiteral(kFileMime)) {
- uint32_t len = 0;
- nsCOMPtr<nsISupports> genericFile;
- rv = aTransferable->GetTransferData(flavorStr, getter_AddRefs(genericFile), &len);
- if (NS_FAILED(rv)) {
- continue;
- }
-
- nsCOMPtr<nsIFile> file(do_QueryInterface(genericFile));
- if (!file) {
- nsCOMPtr<nsISupportsInterfacePointer> ptr(do_QueryInterface(genericFile));
-
- if (ptr) {
- ptr->GetData(getter_AddRefs(genericFile));
- file = do_QueryInterface(genericFile);
- }
- }
-
- if (!file) {
- continue;
- }
-
- nsAutoString fileURI;
- rv = file->GetPath(fileURI);
- if (NS_FAILED(rv)) {
- continue;
- }
-
- NSString* str = nsCocoaUtils::ToNSString(fileURI);
- NSArray* fileList = [NSArray arrayWithObjects:str, nil];
- [pasteboardOutputDict setObject:fileList forKey:NSFilenamesPboardType];
- }
- else if (flavorStr.EqualsLiteral(kFilePromiseMime)) {
- [pasteboardOutputDict setObject:[NSArray arrayWithObject:@""] forKey:NSFilesPromisePboardType];
- }
- else if (flavorStr.EqualsLiteral(kURLMime)) {
- uint32_t len = 0;
- nsCOMPtr<nsISupports> genericURL;
- rv = aTransferable->GetTransferData(flavorStr, getter_AddRefs(genericURL), &len);
- nsCOMPtr<nsISupportsString> urlObject(do_QueryInterface(genericURL));
-
- nsAutoString url;
- urlObject->GetData(url);
-
- // A newline embedded in the URL means that the form is actually URL + title.
- int32_t newlinePos = url.FindChar(char16_t('\n'));
- if (newlinePos >= 0) {
- url.Truncate(newlinePos);
-
- nsAutoString urlTitle;
- urlObject->GetData(urlTitle);
- urlTitle.Mid(urlTitle, newlinePos + 1, len - (newlinePos + 1));
-
- NSString *nativeTitle = [[NSString alloc] initWithCharacters:reinterpret_cast<const unichar*>(urlTitle.get())
- length:urlTitle.Length()];
- // be nice to Carbon apps, normalize the receiver's contents using Form C.
- [pasteboardOutputDict setObject:[nativeTitle precomposedStringWithCanonicalMapping] forKey:kCorePboardType_urln];
- // Also put the title out as 'urld', since some recipients will look for that.
- [pasteboardOutputDict setObject:[nativeTitle precomposedStringWithCanonicalMapping] forKey:kCorePboardType_urld];
- [nativeTitle release];
- }
-
- // The Finder doesn't like getting random binary data aka
- // Unicode, so change it into an escaped URL containing only
- // ASCII.
- nsAutoCString utf8Data = NS_ConvertUTF16toUTF8(url.get(), url.Length());
- nsAutoCString escData;
- NS_EscapeURL(utf8Data.get(), utf8Data.Length(), esc_OnlyNonASCII|esc_AlwaysCopy, escData);
-
- // printf("Escaped url is %s, length %d\n", escData.get(), escData.Length());
-
- NSString *nativeURL = [NSString stringWithUTF8String:escData.get()];
- [pasteboardOutputDict setObject:nativeURL forKey:kCorePboardType_url];
- }
- // If it wasn't a type that we recognize as exportable we don't put it on the system
- // clipboard. We'll just access it from our cached transferable when we need it.
- }
-
- return pasteboardOutputDict;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
-}
-
-bool nsClipboard::IsStringType(const nsCString& aMIMEType, NSString** aPasteboardType)
-{
- if (aMIMEType.EqualsLiteral(kUnicodeMime)) {
- *aPasteboardType = NSStringPboardType;
- return true;
- } else if (aMIMEType.EqualsLiteral(kRTFMime)) {
- *aPasteboardType = NSRTFPboardType;
- return true;
- } else if (aMIMEType.EqualsLiteral(kHTMLMime)) {
- *aPasteboardType = NSHTMLPboardType;
- return true;
- } else {
- return false;
- }
-}
-
-NSString* nsClipboard::WrapHtmlForSystemPasteboard(NSString* aString)
-{
- NSString* wrapped =
- [NSString stringWithFormat:
- @"<html>"
- "<head>"
- "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">"
- "</head>"
- "<body>"
- "%@"
- "</body>"
- "</html>", aString];
- return wrapped;
-}
-
-/**
- * Sets the transferable object
- *
- */
-NS_IMETHODIMP
-nsClipboard::SetData(nsITransferable* aTransferable, nsIClipboardOwner* anOwner,
- int32_t aWhichClipboard)
-{
- NS_ASSERTION (aTransferable, "clipboard given a null transferable");
-
- if (aWhichClipboard == kSelectionCache) {
- if (aTransferable) {
- SetSelectionCache(aTransferable);
- return NS_OK;
- }
- return NS_ERROR_FAILURE;
- }
-
- if (aTransferable == mTransferable && anOwner == mClipboardOwner) {
- return NS_OK;
- }
- bool selectClipPresent;
- SupportsSelectionClipboard(&selectClipPresent);
- bool findClipPresent;
- SupportsFindClipboard(&findClipPresent);
- if (!selectClipPresent && !findClipPresent && aWhichClipboard != kGlobalClipboard) {
- return NS_ERROR_FAILURE;
- }
-
- EmptyClipboard(aWhichClipboard);
-
- mClipboardOwner = anOwner;
- mTransferable = aTransferable;
-
- nsresult rv = NS_ERROR_FAILURE;
- if (mTransferable) {
- rv = SetNativeClipboardData(aWhichClipboard);
- }
-
- return rv;
-}
-
-/**
- * Gets the transferable object
- *
- */
-NS_IMETHODIMP
-nsClipboard::GetData(nsITransferable* aTransferable, int32_t aWhichClipboard)
-{
- NS_ASSERTION (aTransferable, "clipboard given a null transferable");
-
- bool selectClipPresent;
- SupportsSelectionClipboard(&selectClipPresent);
- bool findClipPresent;
- SupportsFindClipboard(&findClipPresent);
- if (!selectClipPresent && !findClipPresent && aWhichClipboard != kGlobalClipboard)
- return NS_ERROR_FAILURE;
-
- if (aTransferable) {
- return GetNativeClipboardData(aTransferable, aWhichClipboard);
- }
-
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-nsClipboard::EmptyClipboard(int32_t aWhichClipboard)
-{
- if (aWhichClipboard == kSelectionCache) {
- ClearSelectionCache();
- return NS_OK;
- }
-
- bool selectClipPresent;
- SupportsSelectionClipboard(&selectClipPresent);
- bool findClipPresent;
- SupportsFindClipboard(&findClipPresent);
- if (!selectClipPresent && !findClipPresent && aWhichClipboard != kGlobalClipboard) {
- return NS_ERROR_FAILURE;
- }
-
- if (mIgnoreEmptyNotification) {
- return NS_OK;
- }
-
- if (mClipboardOwner) {
- mClipboardOwner->LosingOwnership(mTransferable);
- mClipboardOwner = nullptr;
- }
-
- mTransferable = nullptr;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsClipboard::SupportsSelectionClipboard(bool* _retval)
-{
- *_retval = false; // we don't support the selection clipboard by default.
- return NS_OK;
-}
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 <CoreServices/CoreServices.h>
-
-// Definitions and declarations of stuff used by us from the CoreSymbolication
-// framework. This is an undocumented, private framework available on OS X
-// 10.6 and up. It's used by Apple utilities like dtrace, atos, ReportCrash
-// and crashreporterd.
-
-typedef struct _CSTypeRef {
- unsigned long type;
- void* contents;
-} CSTypeRef;
-
-typedef CSTypeRef CSSymbolicatorRef;
-typedef CSTypeRef CSSymbolOwnerRef;
-typedef CSTypeRef CSSymbolRef;
-typedef CSTypeRef CSSourceInfoRef;
-
-typedef struct _CSRange {
- unsigned long long location;
- unsigned long long length;
-} CSRange;
-
-typedef unsigned long long CSArchitecture;
-
-#define kCSNow LONG_MAX
-
-extern "C" {
-
-CSSymbolicatorRef
-CSSymbolicatorCreateWithPid(pid_t pid);
-
-CSSymbolicatorRef
-CSSymbolicatorCreateWithPidFlagsAndNotification(pid_t pid,
- uint32_t flags,
- uint32_t notification);
-
-CSArchitecture
-CSSymbolicatorGetArchitecture(CSSymbolicatorRef symbolicator);
-
-CSSymbolOwnerRef
-CSSymbolicatorGetSymbolOwnerWithAddressAtTime(CSSymbolicatorRef symbolicator,
- unsigned long long address,
- long time);
-
-const char*
-CSSymbolOwnerGetName(CSSymbolOwnerRef owner);
-
-unsigned long long
-CSSymbolOwnerGetBaseAddress(CSSymbolOwnerRef owner);
-
-CSSymbolRef
-CSSymbolOwnerGetSymbolWithAddress(CSSymbolOwnerRef owner,
- unsigned long long address);
-
-CSSourceInfoRef
-CSSymbolOwnerGetSourceInfoWithAddress(CSSymbolOwnerRef owner,
- unsigned long long address);
-
-const char*
-CSSymbolGetName(CSSymbolRef symbol);
-
-CSRange
-CSSymbolGetRange(CSSymbolRef symbol);
-
-const char*
-CSSourceInfoGetFilename(CSSourceInfoRef info);
-
-uint32_t
-CSSourceInfoGetLineNumber(CSSourceInfoRef info);
-
-CSTypeRef
-CSRetain(CSTypeRef);
-
-void
-CSRelease(CSTypeRef);
-
-bool
-CSIsNull(CSTypeRef);
-
-void
-CSShow(CSTypeRef);
-
-const char*
-CSArchitectureGetFamilyName(CSArchitecture);
-
-} // extern "C"
-
-class nsCocoaDebugUtils
-{
-public:
- // Like NSLog() but records more information (for example the full path to
- // the executable and the "thread name"). Like NSLog(), writes to both
- // stdout and the system log.
- static void DebugLog(const char* aFormat, ...);
-
- // Logs a stack trace of the current point of execution, to both stdout and
- // the system log.
- static void PrintStackTrace();
-
- // Returns the name of the module that "owns" aAddress. This must be
- // free()ed by the caller.
- static char* GetOwnerName(void* aAddress);
-
- // Returns a symbolicated representation of aAddress. This must be
- // free()ed by the caller.
- static char* GetAddressString(void* aAddress);
-
-private:
- static void DebugLogInt(bool aDecorate, const char* aFormat, ...);
- static void DebugLogV(bool aDecorate, CFStringRef aFormat, va_list aArgs);
-
- static void PrintAddress(void* aAddress);
-
- // The values returned by GetOwnerNameInt() and GetAddressStringInt() must
- // be free()ed by the caller.
- static char* GetOwnerNameInt(void* aAddress,
- CSTypeRef aOwner = sInitializer);
- static char* GetAddressStringInt(void* aAddress,
- CSTypeRef aOwner = sInitializer);
-
- static CSSymbolicatorRef GetSymbolicatorRef();
- static void ReleaseSymbolicator();
-
- static CSTypeRef sInitializer;
- static CSSymbolicatorRef sSymbolicator;
-};
-
-#endif // nsCocoaDebugUtils_h_
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 <pthread.h>
-#include <libproc.h>
-#include <stdarg.h>
-#include <time.h>
-#include <execinfo.h>
-#include <asl.h>
-
-static char gProcPath[PROC_PIDPATHINFO_MAXSIZE] = {0};
-static char gBundleID[MAXPATHLEN] = {0};
-
-static void MaybeGetPathAndID()
-{
- if (!gProcPath[0]) {
- proc_pidpath(getpid(), gProcPath, sizeof(gProcPath));
- }
- if (!gBundleID[0]) {
- // Apple's CFLog() uses "com.apple.console" (in its call to asl_open()) if
- // it can't find the bundle id.
- CFStringRef bundleID = NULL;
- CFBundleRef mainBundle = CFBundleGetMainBundle();
- if (mainBundle) {
- bundleID = CFBundleGetIdentifier(mainBundle);
- }
- if (!bundleID) {
- strcpy(gBundleID, "com.apple.console");
- } else {
- CFStringGetCString(bundleID, gBundleID, sizeof(gBundleID),
- kCFStringEncodingUTF8);
- }
- }
-}
-
-static void GetThreadName(char* aName, size_t aSize)
-{
- pthread_getname_np(pthread_self(), aName, aSize);
-}
-
-void
-nsCocoaDebugUtils::DebugLog(const char* aFormat, ...)
-{
- va_list args;
- va_start(args, aFormat);
- CFStringRef formatCFSTR =
- CFStringCreateWithCString(kCFAllocatorDefault, aFormat,
- kCFStringEncodingUTF8);
- DebugLogV(true, formatCFSTR, args);
- CFRelease(formatCFSTR);
- va_end(args);
-}
-
-void
-nsCocoaDebugUtils::DebugLogInt(bool aDecorate, const char* aFormat, ...)
-{
- va_list args;
- va_start(args, aFormat);
- CFStringRef formatCFSTR =
- CFStringCreateWithCString(kCFAllocatorDefault, aFormat,
- kCFStringEncodingUTF8);
- DebugLogV(aDecorate, formatCFSTR, args);
- CFRelease(formatCFSTR);
- va_end(args);
-}
-
-void
-nsCocoaDebugUtils::DebugLogV(bool aDecorate, CFStringRef aFormat,
- va_list aArgs)
-{
- MaybeGetPathAndID();
-
- CFStringRef message =
- CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, NULL,
- aFormat, aArgs);
-
- int msgLength =
- CFStringGetMaximumSizeForEncoding(CFStringGetLength(message),
- kCFStringEncodingUTF8);
- char* msgUTF8 = (char*) calloc(msgLength, 1);
- CFStringGetCString(message, msgUTF8, msgLength, kCFStringEncodingUTF8);
- CFRelease(message);
-
- int finishedLength = msgLength + PROC_PIDPATHINFO_MAXSIZE;
- char* finished = (char*) calloc(finishedLength, 1);
- const time_t currentTime = time(NULL);
- char timestamp[30] = {0};
- ctime_r(&currentTime, timestamp);
- if (aDecorate) {
- char threadName[MAXPATHLEN] = {0};
- GetThreadName(threadName, sizeof(threadName));
- snprintf(finished, finishedLength, "(%s) %s[%u] %s[%p] %s\n",
- timestamp, gProcPath, getpid(), threadName, pthread_self(), msgUTF8);
- } else {
- snprintf(finished, finishedLength, "%s\n", msgUTF8);
- }
- free(msgUTF8);
-
- fputs(finished, stdout);
-
- // Use the Apple System Log facility, as NSLog and CFLog do.
- aslclient asl = asl_open(NULL, gBundleID, ASL_OPT_NO_DELAY);
- aslmsg msg = asl_new(ASL_TYPE_MSG);
- asl_set(msg, ASL_KEY_LEVEL, "4"); // kCFLogLevelWarning, used by NSLog()
- asl_set(msg, ASL_KEY_MSG, finished);
- asl_send(asl, msg);
- asl_free(msg);
- asl_close(asl);
-
- free(finished);
-}
-
-CSTypeRef
-nsCocoaDebugUtils::sInitializer = {0};
-
-CSSymbolicatorRef
-nsCocoaDebugUtils::sSymbolicator = {0};
-
-#define STACK_MAX 256
-
-void
-nsCocoaDebugUtils::PrintStackTrace()
-{
- void** addresses = (void**) calloc(STACK_MAX, sizeof(void*));
- if (!addresses) {
- return;
- }
-
- CSSymbolicatorRef symbolicator = GetSymbolicatorRef();
- if (CSIsNull(symbolicator)) {
- free(addresses);
- return;
- }
-
- uint32_t count = backtrace(addresses, STACK_MAX);
- for (uint32_t i = 0; i < count; ++i) {
- PrintAddress(addresses[i]);
- }
-
- ReleaseSymbolicator();
- free(addresses);
-}
-
-void
-nsCocoaDebugUtils::PrintAddress(void* aAddress)
-{
- const char* ownerName = "unknown";
- const char* addressString = "unknown + 0";
-
- char* allocatedOwnerName = nullptr;
- char* allocatedAddressString = nullptr;
-
- CSSymbolOwnerRef owner = {0};
- CSSymbolicatorRef symbolicator = GetSymbolicatorRef();
-
- if (!CSIsNull(symbolicator)) {
- owner =
- CSSymbolicatorGetSymbolOwnerWithAddressAtTime(symbolicator,
- (unsigned long long) aAddress,
- kCSNow);
- }
- if (!CSIsNull(owner)) {
- ownerName = allocatedOwnerName = GetOwnerNameInt(aAddress, owner);
- addressString = allocatedAddressString = GetAddressStringInt(aAddress, owner);
- }
- DebugLogInt(false, " (%s) %s", ownerName, addressString);
-
- free(allocatedOwnerName);
- free(allocatedAddressString);
-
- ReleaseSymbolicator();
-}
-
-char*
-nsCocoaDebugUtils::GetOwnerName(void* aAddress)
-{
- return GetOwnerNameInt(aAddress);
-}
-
-char*
-nsCocoaDebugUtils::GetOwnerNameInt(void* aAddress, CSTypeRef aOwner)
-{
- char* retval = (char*) calloc(MAXPATHLEN, 1);
-
- const char* ownerName = "unknown";
-
- CSSymbolicatorRef symbolicator = GetSymbolicatorRef();
- CSTypeRef owner = aOwner;
-
- if (CSIsNull(owner) && !CSIsNull(symbolicator)) {
- owner =
- CSSymbolicatorGetSymbolOwnerWithAddressAtTime(symbolicator,
- (unsigned long long) aAddress,
- kCSNow);
- }
-
- if (!CSIsNull(owner)) {
- ownerName = CSSymbolOwnerGetName(owner);
- }
-
- snprintf(retval, MAXPATHLEN, "%s", ownerName);
- ReleaseSymbolicator();
-
- return retval;
-}
-
-char*
-nsCocoaDebugUtils::GetAddressString(void* aAddress)
-{
- return GetAddressStringInt(aAddress);
-}
-
-char*
-nsCocoaDebugUtils::GetAddressStringInt(void* aAddress, CSTypeRef aOwner)
-{
- char* retval = (char*) calloc(MAXPATHLEN, 1);
-
- const char* addressName = "unknown";
- unsigned long long addressOffset = 0;
-
- CSSymbolicatorRef symbolicator = GetSymbolicatorRef();
- CSTypeRef owner = aOwner;
-
- if (CSIsNull(owner) && !CSIsNull(symbolicator)) {
- owner =
- CSSymbolicatorGetSymbolOwnerWithAddressAtTime(symbolicator,
- (unsigned long long) aAddress,
- kCSNow);
- }
-
- if (!CSIsNull(owner)) {
- CSSymbolRef symbol =
- CSSymbolOwnerGetSymbolWithAddress(owner,
- (unsigned long long) aAddress);
- if (!CSIsNull(symbol)) {
- addressName = CSSymbolGetName(symbol);
- CSRange range = CSSymbolGetRange(symbol);
- addressOffset = (unsigned long long) aAddress - range.location;
- } else {
- addressOffset = (unsigned long long)
- aAddress - CSSymbolOwnerGetBaseAddress(owner);
- }
- }
-
- snprintf(retval, MAXPATHLEN, "%s + 0x%llx",
- addressName, addressOffset);
- ReleaseSymbolicator();
-
- return retval;
-}
-
-CSSymbolicatorRef
-nsCocoaDebugUtils::GetSymbolicatorRef()
-{
- if (CSIsNull(sSymbolicator)) {
- // 0x40e0000 is the value returned by
- // uint32_t CSSymbolicatorGetFlagsForNListOnlyData(void). We don't use
- // this method directly because it doesn't exist on OS X 10.6. Unless
- // we limit ourselves to NList data, it will take too long to get a
- // stack trace where Dwarf debugging info is available (about 15 seconds
- // with Firefox). This means we won't be able to get a CSSourceInfoRef,
- // or line number information. Oh well.
- sSymbolicator =
- CSSymbolicatorCreateWithPidFlagsAndNotification(getpid(),
- 0x40e0000, 0);
- }
- // Retaining just after creation prevents crashes when calling symbolicator
- // code (for example from PrintStackTrace()) as Firefox is quitting. Not
- // sure why. Doing this may mean that we leak sSymbolicator on quitting
- // (if we ever created it). No particular harm in that, though.
- return CSRetain(sSymbolicator);
-}
-
-void
-nsCocoaDebugUtils::ReleaseSymbolicator()
-{
- if (!CSIsNull(sSymbolicator)) {
- CSRelease(sSymbolicator);
- }
-}
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 <stdint.h>
-
-/// Note that this class assumes we support the platform we are running on.
-/// For better or worse, if the version is unknown or less than what we
-/// support, we set it to the minimum supported version. GetSystemVersion
-/// is the only call that returns the unadjusted values.
-class nsCocoaFeatures {
-public:
- static int32_t macOSVersion();
- static int32_t macOSVersionMajor();
- static int32_t macOSVersionMinor();
- static int32_t macOSVersionBugFix();
- static bool OnYosemiteOrLater();
- static bool OnElCapitanOrLater();
- static bool OnSierraOrLater();
- static bool OnHighSierraOrLater();
- static bool OnMojaveOrLater();
- static bool OnCatalinaOrLater();
- static bool OnBigSurOrLater();
-
- static bool IsAtLeastVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFix=0);
-
- // These are utilities that do not change or depend on the value of mOSXVersion
- // and instead just encapsulate the encoding algorithm. Note that GetVersion
- // actually adjusts to the lowest supported OS, so it will always return
- // a "supported" version. GetSystemVersion does not make any modifications.
- static void GetSystemVersion(int &aMajor, int &aMinor, int &aBugFix);
- static int32_t GetVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFix);
- static int32_t ExtractMajorVersion(int32_t aVersion);
- static int32_t ExtractMinorVersion(int32_t aVersion);
- static int32_t ExtractBugFixVersion(int32_t aVersion);
-
-private:
- static void InitializeVersionNumbers();
-
- static int32_t mOSVersion;
-};
-#endif // nsCocoaFeatures_h_
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 <Cocoa/Cocoa.h>
-
-int32_t nsCocoaFeatures::mOSVersion = 0;
-
-// This should not be called with unchecked aMajor, which should be >= 10.
-inline int32_t AssembleVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFix)
-{
- MOZ_ASSERT(aMajor >= 10);
- return (aMajor << 16) + (aMinor << 8) + aBugFix;
-}
-
-int32_t nsCocoaFeatures::ExtractMajorVersion(int32_t aVersion)
-{
- MOZ_ASSERT((aVersion & MACOS_VERSION_MASK) == aVersion);
- return (aVersion & 0xFF0000) >> 16;
-}
-
-int32_t nsCocoaFeatures::ExtractMinorVersion(int32_t aVersion)
-{
- MOZ_ASSERT((aVersion & MACOS_VERSION_MASK) == aVersion);
- return (aVersion & 0xFF00) >> 8;
-}
-
-int32_t nsCocoaFeatures::ExtractBugFixVersion(int32_t aVersion)
-{
- MOZ_ASSERT((aVersion & MACOS_VERSION_MASK) == aVersion);
- return aVersion & 0xFF;
-}
-
-static int intAtStringIndex(NSArray *array, int index)
-{
- return [(NSString*)[array objectAtIndex:index] integerValue];
-}
-
-void nsCocoaFeatures::GetSystemVersion(int &major, int &minor, int &bugfix)
-{
- major = minor = bugfix = 0;
-
- NSString* versionString = [[NSDictionary dictionaryWithContentsOfFile:
- @"/System/Library/CoreServices/SystemVersion.plist"] objectForKey:@"ProductVersion"];
- NSArray* versions = [versionString componentsSeparatedByString:@"."];
- NSUInteger count = [versions count];
- if (count > 0) {
- major = intAtStringIndex(versions, 0);
- if (count > 1) {
- minor = intAtStringIndex(versions, 1);
- if (count > 2) {
- bugfix = intAtStringIndex(versions, 2);
- }
- }
- }
-}
-
-int32_t nsCocoaFeatures::GetVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFix)
-{
- int32_t macOSVersion;
- if (aMajor < 10) {
- aMajor = 10;
- NS_ERROR("Couldn't determine macOS version, assuming 10.7");
- macOSVersion = MACOS_VERSION_10_7_HEX;
- } else if (aMajor == 10 && aMinor < 7) {
- aMinor = 7;
- NS_ERROR("macOS version too old, assuming 10.7");
- macOSVersion = MACOS_VERSION_10_7_HEX;
- } else {
- MOZ_ASSERT(aMajor >= 10);
- MOZ_ASSERT(aMajor < 256);
- MOZ_ASSERT(aMinor >= 0);
- MOZ_ASSERT(aMinor < 256);
- MOZ_ASSERT(aBugFix >= 0);
- MOZ_ASSERT(aBugFix < 256);
- macOSVersion = AssembleVersion(aMajor, aMinor, aBugFix);
- }
- MOZ_ASSERT(aMajor == ExtractMajorVersion(macOSVersion));
- MOZ_ASSERT(aMinor == ExtractMinorVersion(macOSVersion));
- MOZ_ASSERT(aBugFix == ExtractBugFixVersion(macOSVersion));
- return macOSVersion;
-}
-
-/*static*/ void
-nsCocoaFeatures::InitializeVersionNumbers()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- // Provide an autorelease pool to avoid leaking Cocoa objects,
- // as this gets called before the main autorelease pool is in place.
- nsAutoreleasePool localPool;
-
- int major, minor, bugfix;
- GetSystemVersion(major, minor, bugfix);
- mOSVersion = GetVersion(major, minor, bugfix);
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-/* static */ int32_t
-nsCocoaFeatures::macOSVersion()
-{
- // Don't let this be called while we're first setting the value...
- MOZ_ASSERT((mOSVersion & MACOS_VERSION_MASK) >= 0);
- if (!mOSVersion) {
- mOSVersion = -1;
- InitializeVersionNumbers();
- }
- return mOSVersion;
-}
-
-/* static */ int32_t
-nsCocoaFeatures::macOSVersionMajor()
-{
- return ExtractMajorVersion(macOSVersion());
-}
-
-/* static */ int32_t
-nsCocoaFeatures::macOSVersionMinor()
-{
- return ExtractMinorVersion(macOSVersion());
-}
-
-/* static */ int32_t
-nsCocoaFeatures::macOSVersionBugFix()
-{
- return ExtractBugFixVersion(macOSVersion());
-}
-
-/* static */ bool
-nsCocoaFeatures::OnYosemiteOrLater()
-{
- return (macOSVersion() >= MACOS_VERSION_10_10_HEX);
-}
-
-/* static */ bool
-nsCocoaFeatures::OnElCapitanOrLater()
-{
- return (macOSVersion() >= MACOS_VERSION_10_11_HEX);
-}
-
-/* static */ bool
-nsCocoaFeatures::OnSierraOrLater()
-{
- return (macOSVersion() >= MACOS_VERSION_10_12_HEX);
-}
-
-/* static */ bool
-nsCocoaFeatures::OnHighSierraOrLater()
-{
- return (macOSVersion() >= MACOS_VERSION_10_13_HEX);
-}
-
-/* static */ bool
-nsCocoaFeatures::OnMojaveOrLater()
-{
- return (macOSVersion() >= MACOS_VERSION_10_14_HEX);
-}
-
-/* static */ bool
-nsCocoaFeatures::OnCatalinaOrLater()
-{
- return (macOSVersion() >= MACOS_VERSION_10_15_HEX);
-}
-
-/* static */ bool
-nsCocoaFeatures::OnBigSurOrLater()
-{
- // Account for the version being 10.16 (which occurs when the
- // application is linked with an older SDK) or 11.0 on Big Sur.
- return ((macOSVersion() >= MACOS_VERSION_10_16_HEX) ||
- (macOSVersion() >= MACOS_VERSION_11_0_HEX));
-}
-
-/* static */ bool
-nsCocoaFeatures::IsAtLeastVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFix)
-{
- return macOSVersion() >= GetVersion(aMajor, aMinor, aBugFix);
-}
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 <Cocoa/Cocoa.h>
-
-#include "nsRect.h"
-#include "imgIContainer.h"
-#include "npapi.h"
-#include "nsTArray.h"
-#include "Units.h"
-
-// This must be the last include:
-#include "nsObjCExceptions.h"
-
-#include "mozilla/EventForwards.h"
-
-// Declare the backingScaleFactor method that we want to call
-// on NSView/Window/Screen objects, if they recognize it.
-@interface NSObject (BackingScaleFactorCategory)
-- (CGFloat)backingScaleFactor;
-@end
-
-#if !defined(MAC_OS_X_VERSION_10_8) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8
-enum {
- NSEventPhaseMayBegin = 0x1 << 5
-};
-#endif
-
-class nsIWidget;
-
-namespace mozilla {
-namespace gfx {
-class SourceSurface;
-} // namespace gfx
-} // namespace mozilla
-
-// Used to retain a Cocoa object for the remainder of a method's execution.
-class nsAutoRetainCocoaObject {
-public:
-explicit nsAutoRetainCocoaObject(id anObject)
-{
- mObject = NS_OBJC_TRY_EXPR_ABORT([anObject retain]);
-}
-~nsAutoRetainCocoaObject()
-{
- NS_OBJC_TRY_ABORT([mObject release]);
-}
-private:
- id mObject; // [STRONG]
-};
-
-// Provide a local autorelease pool for the remainder of a method's execution.
-class nsAutoreleasePool {
-public:
- nsAutoreleasePool()
- {
- mLocalPool = [[NSAutoreleasePool alloc] init];
- }
- ~nsAutoreleasePool()
- {
- [mLocalPool release];
- }
-private:
- NSAutoreleasePool *mLocalPool;
-};
-
-@interface NSApplication (Undocumented)
-
-// Present in all versions of OS X from (at least) 10.2.8 through 10.5.
-- (BOOL)_isRunningModal;
-- (BOOL)_isRunningAppModal;
-
-// It's sometimes necessary to explicitly remove a window from the "window
-// cache" in order to deactivate it. The "window cache" is an undocumented
-// subsystem, all of whose methods are included in the NSWindowCache category
-// of the NSApplication class (in header files generated using class-dump).
-// Present in all versions of OS X from (at least) 10.2.8 through 10.5.
-- (void)_removeWindowFromCache:(NSWindow *)aWindow;
-
-// Send an event to the current Cocoa app-modal session. Present in all
-// versions of OS X from (at least) 10.2.8 through 10.5.
-- (void)_modalSession:(NSModalSession)aSession sendEvent:(NSEvent *)theEvent;
-
-@end
-
-struct KeyBindingsCommand
-{
- SEL selector;
- id data;
-};
-
-@interface NativeKeyBindingsRecorder : NSResponder
-{
-@private
- nsTArray<KeyBindingsCommand>* mCommands;
-}
-
-- (void)startRecording:(nsTArray<KeyBindingsCommand>&)aCommands;
-
-- (void)doCommandBySelector:(SEL)aSelector;
-
-- (void)insertText:(id)aString;
-
-@end // NativeKeyBindingsRecorder
-
-class nsCocoaUtils
-{
- typedef mozilla::gfx::SourceSurface SourceSurface;
- typedef mozilla::LayoutDeviceIntPoint LayoutDeviceIntPoint;
- typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect;
-
-public:
-
- // Get the backing scale factor from an object that supports this selector
- // (NSView/Window/Screen, on 10.7 or later), returning 1.0 if not supported
- static CGFloat
- GetBackingScaleFactor(id aObject)
- {
- if (HiDPIEnabled() &&
- [aObject respondsToSelector:@selector(backingScaleFactor)]) {
- return [aObject backingScaleFactor];
- }
- return 1.0;
- }
-
- // Conversions between Cocoa points and device pixels, given the backing
- // scale factor from a view/window/screen.
- static int32_t
- CocoaPointsToDevPixels(CGFloat aPts, CGFloat aBackingScale)
- {
- return NSToIntRound(aPts * aBackingScale);
- }
-
- static LayoutDeviceIntPoint
- CocoaPointsToDevPixels(const NSPoint& aPt, CGFloat aBackingScale)
- {
- return LayoutDeviceIntPoint(NSToIntRound(aPt.x * aBackingScale),
- NSToIntRound(aPt.y * aBackingScale));
- }
-
- static LayoutDeviceIntPoint
- CocoaPointsToDevPixelsRoundDown(const NSPoint& aPt, CGFloat aBackingScale)
- {
- return LayoutDeviceIntPoint(NSToIntFloor(aPt.x * aBackingScale),
- NSToIntFloor(aPt.y * aBackingScale));
- }
-
- static LayoutDeviceIntRect
- CocoaPointsToDevPixels(const NSRect& aRect, CGFloat aBackingScale)
- {
- return LayoutDeviceIntRect(NSToIntRound(aRect.origin.x * aBackingScale),
- NSToIntRound(aRect.origin.y * aBackingScale),
- NSToIntRound(aRect.size.width * aBackingScale),
- NSToIntRound(aRect.size.height * aBackingScale));
- }
-
- static CGFloat
- DevPixelsToCocoaPoints(int32_t aPixels, CGFloat aBackingScale)
- {
- return (CGFloat)aPixels / aBackingScale;
- }
-
- static NSPoint
- DevPixelsToCocoaPoints(const mozilla::LayoutDeviceIntPoint& aPt,
- CGFloat aBackingScale)
- {
- return NSMakePoint((CGFloat)aPt.x / aBackingScale,
- (CGFloat)aPt.y / aBackingScale);
- }
-
- // Implements an NSPoint equivalent of -[NSWindow convertRectFromScreen:].
- static NSPoint
- ConvertPointFromScreen(NSWindow* aWindow, const NSPoint& aPt)
- {
- return [aWindow convertRectFromScreen:NSMakeRect(aPt.x, aPt.y, 0, 0)].origin;
- }
-
- // Implements an NSPoint equivalent of -[NSWindow convertRectToScreen:].
- static NSPoint
- ConvertPointToScreen(NSWindow* aWindow, const NSPoint& aPt)
- {
- return [aWindow convertRectToScreen:NSMakeRect(aPt.x, aPt.y, 0, 0)].origin;
- }
-
- static NSRect
- DevPixelsToCocoaPoints(const LayoutDeviceIntRect& aRect,
- CGFloat aBackingScale)
- {
- return NSMakeRect((CGFloat)aRect.x / aBackingScale,
- (CGFloat)aRect.y / aBackingScale,
- (CGFloat)aRect.width / aBackingScale,
- (CGFloat)aRect.height / aBackingScale);
- }
-
- // Returns the given y coordinate, which must be in screen coordinates,
- // flipped from Gecko to Cocoa or Cocoa to Gecko.
- static float FlippedScreenY(float y);
-
- // The following functions come in "DevPix" variants that work with
- // backing-store (device pixel) coordinates, as well as the original
- // versions that expect coordinates in Cocoa points/CSS pixels.
- // The difference becomes important in HiDPI display modes, where Cocoa
- // points and backing-store pixels are no longer 1:1.
-
- // Gecko rects (nsRect) contain an origin (x,y) in a coordinate
- // system with (0,0) in the top-left of the primary screen. Cocoa rects
- // (NSRect) contain an origin (x,y) in a coordinate system with (0,0)
- // in the bottom-left of the primary screen. Both nsRect and NSRect
- // contain width/height info, with no difference in their use.
- // This function does no scaling, so the Gecko coordinates are
- // expected to be desktop pixels, which are equal to Cocoa points
- // (by definition).
- static NSRect GeckoRectToCocoaRect(const mozilla::DesktopIntRect &geckoRect);
-
- // Converts aGeckoRect in dev pixels to points in Cocoa coordinates
- static NSRect
- GeckoRectToCocoaRectDevPix(const mozilla::LayoutDeviceIntRect &aGeckoRect,
- CGFloat aBackingScale);
-
- // See explanation for geckoRectToCocoaRect, guess what this does...
- static mozilla::DesktopIntRect CocoaRectToGeckoRect(const NSRect &cocoaRect);
-
- static mozilla::LayoutDeviceIntRect CocoaRectToGeckoRectDevPix(
- const NSRect& aCocoaRect, CGFloat aBackingScale);
-
- // Gives the location for the event in screen coordinates. Do not call this
- // unless the window the event was originally targeted at is still alive!
- // anEvent may be nil -- in that case the current mouse location is returned.
- static NSPoint ScreenLocationForEvent(NSEvent* anEvent);
-
- // Determines if an event happened over a window, whether or not the event
- // is for the window. Does not take window z-order into account.
- static BOOL IsEventOverWindow(NSEvent* anEvent, NSWindow* aWindow);
-
- // Events are set up so that their coordinates refer to the window to which they
- // were originally sent. If we reroute the event somewhere else, we'll have
- // to get the window coordinates this way. Do not call this unless the window
- // the event was originally targeted at is still alive!
- static NSPoint EventLocationForWindow(NSEvent* anEvent, NSWindow* aWindow);
-
- // Compatibility wrappers for the -[NSEvent phase], -[NSEvent momentumPhase],
- // -[NSEvent hasPreciseScrollingDeltas] and -[NSEvent scrollingDeltaX/Y] APIs
- // that became availaible starting with the 10.7 SDK.
- // All of these can be removed once we drop support for 10.6.
- static NSEventPhase EventPhase(NSEvent* aEvent);
- static NSEventPhase EventMomentumPhase(NSEvent* aEvent);
- static BOOL IsMomentumScrollEvent(NSEvent* aEvent);
- static BOOL HasPreciseScrollingDeltas(NSEvent* aEvent);
- static void GetScrollingDeltas(NSEvent* aEvent, CGFloat* aOutDeltaX, CGFloat* aOutDeltaY);
- static BOOL EventHasPhaseInformation(NSEvent* aEvent);
-
- // Hides the Menu bar and the Dock. Multiple hide/show requests can be nested.
- static void HideOSChromeOnScreen(bool aShouldHide);
-
- static nsIWidget* GetHiddenWindowWidget();
-
- static void PrepareForNativeAppModalDialog();
- static void CleanUpAfterNativeAppModalDialog();
-
- // 3 utility functions to go from a frame of imgIContainer to CGImage and then to NSImage
- // Convert imgIContainer -> CGImageRef, caller owns result
-
- /** Creates a <code>CGImageRef</code> from a frame contained in an <code>imgIContainer</code>.
- Copies the pixel data from the indicated frame of the <code>imgIContainer</code> into a new <code>CGImageRef</code>.
- The caller owns the <code>CGImageRef</code>.
- @param aFrame the frame to convert
- @param aResult the resulting CGImageRef
- @return NS_OK if the conversion worked, NS_ERROR_FAILURE otherwise
- */
- static nsresult CreateCGImageFromSurface(SourceSurface* aSurface,
- CGImageRef* aResult);
-
- /** Creates a Cocoa <code>NSImage</code> from a <code>CGImageRef</code>.
- Copies the pixel data from the <code>CGImageRef</code> into a new <code>NSImage</code>.
- The caller owns the <code>NSImage</code>.
- @param aInputImage the image to convert
- @param aResult the resulting NSImage
- @return NS_OK if the conversion worked, NS_ERROR_FAILURE otherwise
- */
- static nsresult CreateNSImageFromCGImage(CGImageRef aInputImage, NSImage **aResult);
-
- /** Creates a Cocoa <code>NSImage</code> from a frame of an <code>imgIContainer</code>.
- Combines the two methods above. The caller owns the <code>NSImage</code>.
- @param aImage the image to extract a frame from
- @param aWhichFrame the frame to extract (see imgIContainer FRAME_*)
- @param aResult the resulting NSImage
- @param scaleFactor the desired scale factor of the NSImage (2 for a retina display)
- @return NS_OK if the conversion worked, NS_ERROR_FAILURE otherwise
- */
- static nsresult CreateNSImageFromImageContainer(imgIContainer *aImage, uint32_t aWhichFrame, NSImage **aResult, CGFloat scaleFactor);
-
- /**
- * Returns nsAString for aSrc.
- */
- static void GetStringForNSString(const NSString *aSrc, nsAString& aDist);
-
- /**
- * Makes NSString instance for aString.
- */
- static NSString* ToNSString(const nsAString& aString);
-
- /**
- * Returns NSRect for aGeckoRect.
- * Just copies values between the two types; it does no coordinate-system
- * conversion, so both rects must have the same coordinate origin/direction.
- */
- static void GeckoRectToNSRect(const nsIntRect& aGeckoRect,
- NSRect& aOutCocoaRect);
-
- /**
- * Returns Gecko rect for aCocoaRect.
- * Just copies values between the two types; it does no coordinate-system
- * conversion, so both rects must have the same coordinate origin/direction.
- */
- static void NSRectToGeckoRect(const NSRect& aCocoaRect,
- nsIntRect& aOutGeckoRect);
-
- /**
- * Makes NSEvent instance for aEventTytpe and aEvent.
- */
- static NSEvent* MakeNewCocoaEventWithType(NSEventType aEventType,
- NSEvent *aEvent);
-
- /**
- * Initializes aNPCocoaEvent.
- */
- static void InitNPCocoaEvent(NPCocoaEvent* aNPCocoaEvent);
-
- /**
- * Initializes WidgetInputEvent for aNativeEvent or aModifiers.
- */
- static void InitInputEvent(mozilla::WidgetInputEvent &aInputEvent,
- NSEvent* aNativeEvent);
-
- /**
- * Converts the native modifiers from aNativeEvent into WidgetMouseEvent
- * Modifiers. aNativeEvent can be null.
- */
- static mozilla::Modifiers ModifiersForEvent(NSEvent* aNativeEvent);
-
- /**
- * ConvertToCarbonModifier() returns carbon modifier flags for the cocoa
- * modifier flags.
- * NOTE: The result never includes right*Key.
- */
- static UInt32 ConvertToCarbonModifier(NSUInteger aCocoaModifier);
-
- /**
- * Whether to support HiDPI rendering. For testing purposes, to be removed
- * once we're comfortable with the HiDPI behavior.
- */
- static bool HiDPIEnabled();
-
- /**
- * Keys can optionally be bound by system or user key bindings to one or more
- * commands based on selectors. This collects any such commands in the
- * provided array.
- */
- static void GetCommandsFromKeyEvent(NSEvent* aEvent,
- nsTArray<KeyBindingsCommand>& aCommands);
-
- /**
- * Converts the string name of a Gecko key (like "VK_HOME") to the
- * corresponding Cocoa Unicode character.
- */
- static uint32_t ConvertGeckoNameToMacCharCode(const nsAString& aKeyCodeName);
-
- /**
- * Converts a Gecko key code (like NS_VK_HOME) to the corresponding Cocoa
- * Unicode character.
- */
- static uint32_t ConvertGeckoKeyCodeToMacCharCode(uint32_t aKeyCode);
-
- /**
- * Convert string with font attribute to NSMutableAttributedString
- */
- static NSMutableAttributedString* GetNSMutableAttributedString(
- const nsAString& aText,
- const nsTArray<mozilla::FontRange>& aFontRanges,
- const bool aIsVertical,
- const CGFloat aBackingScaleFactor);
-};
-
-#endif // nsCocoaUtils_h_
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 <cmath>
-
-#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<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
- if (!appShell) {
- NS_WARNING("Couldn't get AppShellService in order to get hidden window ref");
- return nullptr;
- }
-
- nsCOMPtr<nsIXULWindow> hiddenWindow;
- appShell->GetHiddenWindow(getter_AddRefs(hiddenWindow));
- if (!hiddenWindow) {
- // Don't warn, this happens during shutdown, bug 358607.
- return nullptr;
- }
-
- nsCOMPtr<nsIBaseWindow> baseHiddenWindow;
- baseHiddenWindow = do_GetInterface(hiddenWindow);
- if (!baseHiddenWindow) {
- NS_WARNING("Couldn't get nsIBaseWindow from hidden window (nsIXULWindow)");
- return nullptr;
- }
-
- nsCOMPtr<nsIWidget> 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<DataSourceSurface*>(aDataSourceSurface)->Unmap();
- static_cast<DataSourceSurface*>(aDataSourceSurface)->Release();
- }
-}
-
-nsresult nsCocoaUtils::CreateCGImageFromSurface(SourceSurface* aSurface,
- CGImageRef* aResult)
-{
- RefPtr<DataSourceSurface> 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<SourceSurface> 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> drawTarget = gfxPlatform::GetPlatform()->
- CreateOffscreenContentDrawTarget(scaledSize, SurfaceFormat::B8G8R8A8);
- if (!drawTarget || !drawTarget->IsValid()) {
- NS_ERROR("Failed to create valid DrawTarget");
- return NS_ERROR_FAILURE;
- }
-
- RefPtr<gfxContext> 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<unichar*>(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<const unichar*>(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<KeyBindingsCommand>& 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<KeyBindingsCommand>&)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<mozilla::FontRange>& 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 <Cocoa/Cocoa.h>
-
-#include "mozilla/RefPtr.h"
-#include "nsBaseWidget.h"
-#include "nsPIWidgetCocoa.h"
-#include "nsCocoaUtils.h"
-
-class nsCocoaWindow;
-class nsChildView;
-class nsMenuBarX;
-@class ChildView;
-
-typedef struct _nsCocoaWindowList {
- _nsCocoaWindowList() : prev(nullptr), window(nullptr) {}
- struct _nsCocoaWindowList *prev;
- nsCocoaWindow *window; // Weak
-} nsCocoaWindowList;
-
-// NSWindow subclass that is the base class for all of our own window classes.
-// Among other things, this class handles the storage of those settings that
-// need to be persisted across window destruction and reconstruction, i.e. when
-// switching to and from fullscreen mode.
-// We don't save shadow, transparency mode or background color because it's not
-// worth the hassle - Gecko will reset them anyway as soon as the window is
-// resized.
-@interface BaseWindow : NSWindow
-{
- // Data Storage
- NSMutableDictionary* mState;
- BOOL mDrawsIntoWindowFrame;
- NSColor* mActiveTitlebarColor;
- NSColor* mInactiveTitlebarColor;
-
- // Shadow
- BOOL mScheduledShadowInvalidation;
-
- // Invalidation disabling
- BOOL mDisabledNeedsDisplay;
-
- // DPI cache. Getting the physical screen size (CGDisplayScreenSize)
- // is ridiculously slow, so we cache it in the toplevel window for all
- // descendants to use.
- float mDPI;
-
- NSTrackingArea* mTrackingArea;
-
- NSRect mDirtyRect;
-
- BOOL mBeingShown;
- BOOL mDrawTitle;
- BOOL mBrightTitlebarForeground;
- BOOL mUseMenuStyle;
-}
-
-- (void)importState:(NSDictionary*)aState;
-- (NSMutableDictionary*)exportState;
-- (void)setDrawsContentsIntoWindowFrame:(BOOL)aState;
-- (BOOL)drawsContentsIntoWindowFrame;
-- (void)setTitlebarColor:(NSColor*)aColor forActiveWindow:(BOOL)aActive;
-- (NSColor*)titlebarColorForActiveWindow:(BOOL)aActive;
-
-- (void)deferredInvalidateShadow;
-- (void)invalidateShadow;
-- (float)getDPI;
-
-- (void)mouseEntered:(NSEvent*)aEvent;
-- (void)mouseExited:(NSEvent*)aEvent;
-- (void)mouseMoved:(NSEvent*)aEvent;
-- (void)updateTrackingArea;
-- (NSView*)trackingAreaView;
-
-- (void)setBeingShown:(BOOL)aValue;
-- (BOOL)isBeingShown;
-- (BOOL)isVisibleOrBeingShown;
-
-- (ChildView*)mainChildView;
-
-- (NSArray*)titlebarControls;
-
-- (void)setWantsTitleDrawn:(BOOL)aDrawTitle;
-- (BOOL)wantsTitleDrawn;
-
-- (void)setUseBrightTitlebarForeground:(BOOL)aBrightForeground;
-- (BOOL)useBrightTitlebarForeground;
-
-- (void)disableSetNeedsDisplay;
-- (void)enableSetNeedsDisplay;
-
-- (NSRect)getAndResetNativeDirtyRect;
-
-- (void)setUseMenuStyle:(BOOL)aValue;
-
-@end
-
-@interface NSWindow (Undocumented)
-
-// If a window has been explicitly removed from the "window cache" (to
-// deactivate it), it's sometimes necessary to "reset" it to reactivate it
-// (and put it back in the "window cache"). One way to do this, which Apple
-// often uses, is to set the "window number" to '-1' and then back to its
-// original value.
-- (void)_setWindowNumber:(NSInteger)aNumber;
-
-// If we set the window's stylemask to be textured, the corners on the bottom of
-// the window are rounded by default. We use this private method to make
-// the corners square again, a la Safari. Starting with 10.7, all windows have
-// rounded bottom corners, so this call doesn't have any effect there.
-- (void)setBottomCornerRounded:(BOOL)rounded;
-- (BOOL)bottomCornerRounded;
-
-// Present in the same form on OS X since at least OS X 10.5.
-- (NSRect)contentRectForFrameRect:(NSRect)windowFrame styleMask:(NSUInteger)windowStyle;
-- (NSRect)frameRectForContentRect:(NSRect)windowContentRect styleMask:(NSUInteger)windowStyle;
-
-// Present since at least OS X 10.5. The OS calls this method on NSWindow
-// (and its subclasses) to find out which NSFrameView subclass to instantiate
-// to create its "frame view".
-+ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask;
-
-@end
-
-@interface PopupWindow : BaseWindow
-{
-@private
- BOOL mIsContextMenu;
-}
-
-- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask
- backing:(NSBackingStoreType)bufferingType defer:(BOOL)deferCreation;
-- (BOOL)isContextMenu;
-- (void)setIsContextMenu:(BOOL)flag;
-- (BOOL)canBecomeMainWindow;
-
-@end
-
-@interface BorderlessWindow : BaseWindow
-{
-}
-
-- (BOOL)canBecomeKeyWindow;
-- (BOOL)canBecomeMainWindow;
-
-@end
-
-@interface WindowDelegate : NSObject <NSWindowDelegate>
-{
- nsCocoaWindow* mGeckoWindow; // [WEAK] (we are owned by the window)
- // Used to avoid duplication when we send NS_ACTIVATE and
- // NS_DEACTIVATE to Gecko for toplevel widgets. Starts out
- // false.
- bool mToplevelActiveState;
- BOOL mHasEverBeenZoomed;
-}
-+ (void)paintMenubarForWindow:(NSWindow*)aWindow;
-- (id)initWithGeckoWindow:(nsCocoaWindow*)geckoWind;
-- (void)windowDidResize:(NSNotification*)aNotification;
-- (nsCocoaWindow*)geckoWidget;
-- (bool)toplevelActiveState;
-- (void)sendToplevelActivateEvents;
-- (void)sendToplevelDeactivateEvents;
-@end
-
-@class ToolbarWindow;
-
-// NSColor subclass that allows us to draw separate colors both in the titlebar
-// and for background of the window.
-@interface TitlebarAndBackgroundColor : NSColor
-{
- ToolbarWindow *mWindow; // [WEAK] (we are owned by the window)
-}
-
-- (id)initWithWindow:(ToolbarWindow*)aWindow;
-
-@end
-
-// NSWindow subclass for handling windows with toolbars.
-@interface ToolbarWindow : BaseWindow
-{
- TitlebarAndBackgroundColor *mColor; // strong
- CGFloat mUnifiedToolbarHeight;
- NSColor *mBackgroundColor; // strong
- NSView *mTitlebarView; // strong
- NSRect mWindowButtonsRect;
- NSRect mFullScreenButtonRect;
-}
-// Pass nil here to get the default appearance.
-- (void)setTitlebarColor:(NSColor*)aColor forActiveWindow:(BOOL)aActive;
-- (void)setUnifiedToolbarHeight:(CGFloat)aHeight;
-- (CGFloat)unifiedToolbarHeight;
-- (CGFloat)titlebarHeight;
-- (NSRect)titlebarRect;
-- (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect sync:(BOOL)aSync;
-- (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect;
-- (void)setDrawsContentsIntoWindowFrame:(BOOL)aState;
-- (void)setSheetAttachmentPosition:(CGFloat)aY;
-- (void)placeWindowButtons:(NSRect)aRect;
-- (void)placeFullScreenButton:(NSRect)aRect;
-- (NSPoint)windowButtonsPositionWithDefaultPosition:(NSPoint)aDefaultPosition;
-- (NSPoint)fullScreenButtonPositionWithDefaultPosition:(NSPoint)aDefaultPosition;
-- (void)setTemporaryBackgroundColor;
-- (void)restoreBackgroundColor;
-@end
-
-class nsCocoaWindow : public nsBaseWidget, public nsPIWidgetCocoa
-{
-private:
- typedef nsBaseWidget Inherited;
-
-public:
-
- nsCocoaWindow();
-
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_NSPIWIDGETCOCOA
-
- virtual MOZ_MUST_USE nsresult Create(nsIWidget* aParent,
- nsNativeWidget aNativeParent,
- const DesktopIntRect& aRect,
- nsWidgetInitData* aInitData = nullptr)
- override;
-
- virtual MOZ_MUST_USE nsresult Create(nsIWidget* aParent,
- nsNativeWidget aNativeParent,
- const LayoutDeviceIntRect& aRect,
- nsWidgetInitData* aInitData = nullptr)
- override;
-
- virtual void Destroy() override;
-
- NS_IMETHOD Show(bool aState) override;
- virtual nsIWidget* GetSheetWindowParent(void) override;
- NS_IMETHOD Enable(bool aState) override;
- virtual bool IsEnabled() const override;
- virtual void SetModal(bool aState) override;
- virtual void SetFakeModal(bool aState) override;
- virtual bool IsRunningAppModal() override;
- virtual bool IsVisible() const override;
- NS_IMETHOD SetFocus(bool aState=false) override;
- virtual LayoutDeviceIntPoint WidgetToScreenOffset() override;
- virtual LayoutDeviceIntPoint GetClientOffset() override;
- virtual LayoutDeviceIntSize
- ClientToWindowSize(const LayoutDeviceIntSize& aClientSize) override;
-
- virtual void* GetNativeData(uint32_t aDataType) override;
-
- virtual void ConstrainPosition(bool aAllowSlop,
- int32_t *aX, int32_t *aY) override;
- virtual void SetSizeConstraints(const SizeConstraints& aConstraints) override;
- NS_IMETHOD Move(double aX, double aY) override;
- virtual void SetSizeMode(nsSizeMode aMode) override;
- NS_IMETHOD HideWindowChrome(bool aShouldHide) override;
-
- void EnteredFullScreen(bool aFullScreen, bool aNativeMode = true);
- virtual bool PrepareForFullscreenTransition(nsISupports** aData) override;
- virtual void PerformFullscreenTransition(FullscreenTransitionStage aStage,
- uint16_t aDuration,
- nsISupports* aData,
- nsIRunnable* aCallback) override;
- virtual nsresult MakeFullScreen(
- bool aFullScreen, nsIScreen* aTargetScreen = nullptr) override final;
- NS_IMETHOD MakeFullScreenWithNativeTransition(
- bool aFullScreen, nsIScreen* aTargetScreen = nullptr) override final;
- NSAnimation* FullscreenTransitionAnimation() const { return mFullscreenTransitionAnimation; }
- void ReleaseFullscreenTransitionAnimation()
- {
- MOZ_ASSERT(mFullscreenTransitionAnimation,
- "Should only be called when there is animation");
- [mFullscreenTransitionAnimation release];
- mFullscreenTransitionAnimation = nil;
- }
-
- NS_IMETHOD Resize(double aWidth, double aHeight, bool aRepaint) override;
- NS_IMETHOD Resize(double aX, double aY, double aWidth, double aHeight, bool aRepaint) override;
- virtual LayoutDeviceIntRect GetClientBounds() override;
- virtual LayoutDeviceIntRect GetScreenBounds() override;
- void ReportMoveEvent();
- void ReportSizeEvent();
- NS_IMETHOD SetCursor(nsCursor aCursor) override;
- NS_IMETHOD SetCursor(imgIContainer* aCursor, uint32_t aHotspotX, uint32_t aHotspotY) override;
-
- CGFloat BackingScaleFactor();
- void BackingScaleFactorChanged();
- virtual double GetDefaultScaleInternal() override;
- virtual int32_t RoundsWidgetCoordinatesTo() override;
-
- mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale() final {
- return mozilla::DesktopToLayoutDeviceScale(BackingScaleFactor());
- }
-
- NS_IMETHOD SetTitle(const nsAString& aTitle) override;
-
- NS_IMETHOD Invalidate(const LayoutDeviceIntRect& aRect) override;
- virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations) override;
- virtual LayerManager* GetLayerManager(PLayerTransactionChild* aShadowManager = nullptr,
- LayersBackend aBackendHint = mozilla::layers::LayersBackend::LAYERS_NONE,
- LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT) override;
- NS_IMETHOD DispatchEvent(mozilla::WidgetGUIEvent* aEvent,
- nsEventStatus& aStatus) override;
- virtual void CaptureRollupEvents(nsIRollupListener * aListener,
- bool aDoCapture) override;
- NS_IMETHOD GetAttention(int32_t aCycleCount) override;
- virtual bool HasPendingInputEvent() override;
- virtual nsTransparencyMode GetTransparencyMode() override;
- virtual void SetTransparencyMode(nsTransparencyMode aMode) override;
- virtual void SetWindowShadowStyle(int32_t aStyle) override;
- virtual void SetShowsToolbarButton(bool aShow) override;
- virtual void SetShowsFullScreenButton(bool aShow) override;
- virtual void SetWindowAnimationType(WindowAnimationType aType) override;
- virtual void SetDrawsTitle(bool aDrawTitle) override;
- virtual void SetUseBrightTitlebarForeground(bool aBrightForeground) override;
- NS_IMETHOD SetNonClientMargins(LayoutDeviceIntMargin& aMargins) override;
- virtual void SetWindowTitlebarColor(nscolor aColor, bool aActive) override;
- virtual void SetDrawsInTitlebar(bool aState) override;
- virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) override;
- virtual nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint,
- uint32_t aNativeMessage,
- uint32_t aModifierFlags,
- nsIObserver* aObserver) override;
-
- void DispatchSizeModeEvent();
-
- // be notified that a some form of drag event needs to go into Gecko
- virtual bool DragEvent(unsigned int aMessage, mozilla::gfx::Point aMouseGlobal, UInt16 aKeyModifiers);
-
- bool HasModalDescendents() { return mNumModalDescendents > 0; }
- NSWindow *GetCocoaWindow() { return mWindow; }
-
- void SetMenuBar(nsMenuBarX* aMenuBar);
- nsMenuBarX *GetMenuBar();
-
- NS_IMETHOD_(void) SetInputContext(
- const InputContext& aContext,
- const InputContextAction& aAction) override;
- NS_IMETHOD_(InputContext) GetInputContext() override
- {
- return mInputContext;
- }
- NS_IMETHOD_(bool) ExecuteNativeKeyBinding(
- NativeKeyBindingsType aType,
- const mozilla::WidgetKeyboardEvent& aEvent,
- DoCommandCallback aCallback,
- void* aCallbackData) override;
-
- void SetPopupWindowLevel();
-
-protected:
- virtual ~nsCocoaWindow();
-
- nsresult CreateNativeWindow(const NSRect &aRect,
- nsBorderStyle aBorderStyle,
- bool aRectIsFrameRect);
- nsresult CreatePopupContentView(const LayoutDeviceIntRect &aRect,
- nsWidgetInitData* aInitData);
- void DestroyNativeWindow();
- void AdjustWindowShadow();
- void SetWindowBackgroundBlur();
- void UpdateBounds();
-
- nsresult DoResize(double aX, double aY, double aWidth, double aHeight,
- bool aRepaint, bool aConstrainToCurrentScreen);
-
- inline bool ShouldToggleNativeFullscreen(bool aFullScreen,
- bool aUseSystemTransition);
- nsresult DoMakeFullScreen(bool aFullScreen, bool aUseSystemTransition);
-
- virtual already_AddRefed<nsIWidget>
- AllocateChildPopupWidget() override
- {
- static NS_DEFINE_IID(kCPopUpCID, NS_POPUP_CID);
- nsCOMPtr<nsIWidget> widget = do_CreateInstance(kCPopUpCID);
- return widget.forget();
- }
-
- nsIWidget* mParent; // if we're a popup, this is our parent [WEAK]
- nsIWidget* mAncestorLink; // link to traverse ancestors [WEAK]
- BaseWindow* mWindow; // our cocoa window [STRONG]
- WindowDelegate* mDelegate; // our delegate for processing window msgs [STRONG]
- RefPtr<nsMenuBarX> mMenuBar;
- NSWindow* mSheetWindowParent; // if this is a sheet, this is the NSWindow it's attached to
- nsChildView* mPopupContentView; // if this is a popup, this is its content widget
- // if this is a toplevel window, and there is any ongoing fullscreen
- // transition, it is the animation object.
- NSAnimation* mFullscreenTransitionAnimation;
- int32_t mShadowStyle;
-
- CGFloat mBackingScaleFactor;
-
- WindowAnimationType mAnimationType;
-
- bool mWindowMadeHere; // true if we created the window, false for embedding
- bool mSheetNeedsShow; // if this is a sheet, are we waiting to be shown?
- // this is used for sibling sheet contention only
- bool mInFullScreenMode;
- bool mInFullScreenTransition; // true from the request to enter/exit fullscreen
- // (MakeFullScreen() call) to EnteredFullScreen()
- bool mModal;
- bool mFakeModal;
-
- // Only true on 10.7+ if SetShowsFullScreenButton(true) is called.
- bool mSupportsNativeFullScreen;
- // Whether we are currently using native fullscreen. It could be false because
- // we are in the DOM fullscreen where we do not use the native fullscreen.
- bool mInNativeFullScreenMode;
-
- bool mIsAnimationSuppressed;
-
- bool mInReportMoveEvent; // true if in a call to ReportMoveEvent().
- bool mInResize; // true if in a call to DoResize().
-
- bool mAlwaysOnTop;
-
- int32_t mNumModalDescendents;
- InputContext mInputContext;
-};
-
-#endif // nsCocoaWindow_h_
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 <algorithm>
-
-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<nsIWidget> 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<nsChildView*>(kid);
- kid = kid->GetPrevSibling();
- childView->ResetParent();
- } else {
- nsCocoaWindow* childWindow = static_cast<nsCocoaWindow*>(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<nsIWidget*>(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<nsCocoaWindow*>(mParent);
- while (parent && (parent->mWindowType == eWindowType_sheet))
- parent = static_cast<nsCocoaWindow*>(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<nsCocoaWindow*>(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<nsCocoaWindow*>(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<nsCocoaWindow*>(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<nsPIWidgetCocoa> 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<nsIWidget> 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<nsIWidget> 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<nsPIWidgetCocoa> 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<Configuration>& 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<int32_t>(frame.size.width, 1);
- height = std::max<int32_t>(frame.size.height, 1);
-
- nsCOMPtr<nsIScreenManager> screenMgr = do_GetService("@mozilla.org/gfx/screenmanager;1");
- if (screenMgr) {
- nsCOMPtr<nsIScreen> 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<float>(aX),
- static_cast<float>(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 <NSAnimationDelegate>
-{
-@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<nsIRunnable>(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<nsIScreen> widgetScreen = GetWidgetScreen();
- nsScreenCocoa* screen = static_cast<nsScreenCocoa*>(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<FullscreenTransitionData*>(aData);
- FullscreenTransitionDelegate* delegate =
- [[FullscreenTransitionDelegate alloc] init];
- delegate->mWindow = this;
- // Storing already_AddRefed directly could cause static checking fail.
- delegate->mCallback = nsCOMPtr<nsIRunnable>(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<bool> 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<const unichar*>(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<nsIWidget> 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<nsCocoaWindow*>(child);
- if (cocoaWindow->mWindow &&
- ((aShown && [cocoaWindow->mWindow isVisible]) ||
- (!aShown && cocoaWindow->mSheetNeedsShow))) {
- nsCOMPtr<nsIWidget> 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<nsIWidget> 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<ThemeGeometry>& 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<nsMenuBarX> 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<nsChildView*>([[(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<nsIColorPickerShownCallback> 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 <Cocoa/Cocoa.h>
-
-#include "nsColorPicker.h"
-#include "nsCocoaUtils.h"
-#include "nsThreadUtils.h"
-
-using namespace mozilla;
-
-static unsigned int
-HexStrToInt(NSString* str)
-{
- unsigned int result = 0;
-
- for (unsigned int i = 0; i < [str length]; ++i) {
- char c = [str characterAtIndex:i];
- result *= 16;
- if (c >= '0' && c <= '9') {
- result += c - '0';
- } else if (c >= 'A' && c <= 'F') {
- result += 10 + (c - 'A');
- } else {
- result += 10 + (c - 'a');
- }
- }
-
- return result;
-}
-
-@interface NSColorPanelWrapper : NSObject <NSWindowDelegate>
-{
- NSColorPanel* mColorPanel;
- nsColorPicker* mColorPicker;
-}
-- (id)initWithPicker:(nsColorPicker*)aPicker;
-- (void)open:(NSColor*)aInitialColor title:(NSString*)aTitle;
-- (void)retarget:(nsColorPicker*)aPicker;
-- (void)colorChanged:(NSColorPanel*)aPanel;
-@end
-
-@implementation NSColorPanelWrapper
-- (id)initWithPicker:(nsColorPicker*)aPicker
-{
- mColorPicker = aPicker;
- mColorPanel = [NSColorPanel sharedColorPanel];
-
- self = [super init];
- return self;
-}
-
-- (void)open:(NSColor*)aInitialColor title:(NSString*)aTitle
-{
- [mColorPanel setTarget:self];
- [mColorPanel setAction:@selector(colorChanged:)];
- [mColorPanel setDelegate:self];
- [mColorPanel setTitle:aTitle];
- [mColorPanel setColor:aInitialColor];
- [mColorPanel makeKeyAndOrderFront:nil];
-}
-
-- (void)colorChanged:(NSColorPanel*)aPanel
-{
- mColorPicker->Update([mColorPanel color]);
-}
-
-- (void)windowWillClose:(NSNotification*)aNotification
-{
- mColorPicker->Done();
-}
-
-- (void)retarget:(nsColorPicker*)aPicker
-{
- mColorPicker->DoneWithRetarget();
- mColorPicker = aPicker;
-}
-
-- (void)dealloc
-{
- [mColorPanel setTarget:nil];
- [mColorPanel setAction:nil];
- [mColorPanel setDelegate:nil];
-
- mColorPanel = nil;
- mColorPicker = nullptr;
-
- [super dealloc];
-}
-@end
-
-NS_IMPL_ISUPPORTS(nsColorPicker, nsIColorPicker)
-
-NSColorPanelWrapper* nsColorPicker::sColorPanelWrapper = nullptr;
-
-nsColorPicker::~nsColorPicker()
-{
-}
-
-NS_IMETHODIMP
-nsColorPicker::Init(mozIDOMWindowProxy* aParent, const nsAString& aTitle,
- const nsAString& aInitialColor)
-{
- MOZ_ASSERT(NS_IsMainThread(),
- "Color pickers can only be opened from main thread currently");
- mTitle = aTitle;
- mColor = aInitialColor;
-
- if (sColorPanelWrapper) {
- // Update current wrapper to target the new input instead
- [sColorPanelWrapper retarget:this];
- } else {
- // Create a brand new color panel wrapper
- sColorPanelWrapper = [[NSColorPanelWrapper alloc] initWithPicker:this];
- }
- return NS_OK;
-}
-
-/* static */ NSColor*
-nsColorPicker::GetNSColorFromHexString(const nsAString& aColor)
-{
- NSString* str = nsCocoaUtils::ToNSString(aColor);
-
- double red = HexStrToInt([str substringWithRange:NSMakeRange(1, 2)]) / 255.0;
- double green = HexStrToInt([str substringWithRange:NSMakeRange(3, 2)]) / 255.0;
- double blue = HexStrToInt([str substringWithRange:NSMakeRange(5, 2)]) / 255.0;
-
- return [NSColor colorWithDeviceRed: red green: green blue: blue alpha: 1.0];
-}
-
-/* static */ void
-nsColorPicker::GetHexStringFromNSColor(NSColor* aColor, nsAString& aResult)
-{
- CGFloat redFloat, greenFloat, blueFloat;
-
- NSColor* color = aColor;
- @try {
- [color getRed:&redFloat green:&greenFloat blue:&blueFloat alpha: nil];
- } @catch (NSException* e) {
- color = [color colorUsingColorSpace:[NSColorSpace genericRGBColorSpace]];
- [color getRed:&redFloat green:&greenFloat blue:&blueFloat alpha: nil];
- }
-
- nsCocoaUtils::GetStringForNSString([NSString stringWithFormat:@"#%02x%02x%02x",
- (int)(redFloat * 255),
- (int)(greenFloat * 255),
- (int)(blueFloat * 255)],
- aResult);
-}
-
-NS_IMETHODIMP
-nsColorPicker::Open(nsIColorPickerShownCallback* aCallback)
-{
- MOZ_ASSERT(aCallback);
- mCallback = aCallback;
-
- [sColorPanelWrapper open:GetNSColorFromHexString(mColor)
- title:nsCocoaUtils::ToNSString(mTitle)];
-
- NS_ADDREF_THIS();
-
- return NS_OK;
-}
-
-void
-nsColorPicker::Update(NSColor* aColor)
-{
- GetHexStringFromNSColor(aColor, mColor);
- mCallback->Update(mColor);
-}
-
-void
-nsColorPicker::DoneWithRetarget()
-{
- mCallback->Done(EmptyString());
- mCallback = nullptr;
- NS_RELEASE_THIS();
-}
-
-void
-nsColorPicker::Done()
-{
- [sColorPanelWrapper release];
- sColorPanelWrapper = nullptr;
- DoneWithRetarget();
-}
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 <Foundation/Foundation.h>
-#include "nsIWidget.h"
-#include "nsMacCursor.h"
-
-/*! @class nsCursorManager
- @abstract Singleton service provides access to all cursors available in the application.
- @discussion Use <code>nsCusorManager</code> to set the current cursor using an XP <code>nsCusor</code> enum value.
- <code>nsCursorManager</code> encapsulates the details of setting different types of cursors, animating
- cursors and cleaning up cursors when they are no longer in use.
- */
-@interface nsCursorManager : NSObject
-{
- @private
- NSMutableDictionary *mCursors;
- nsMacCursor *mCurrentMacCursor;
-}
-
-/*! @method setCursor:
- @abstract Sets the current cursor.
- @discussion Sets the current cursor to the cursor indicated by the XP cursor constant given as an argument.
- Resources associated with the previous cursor are cleaned up.
- @param aCursor the cursor to use
-*/
-- (nsresult) setCursor: (nsCursor) aCursor;
-
-/*! @method setCursorWithImage:hotSpotX:hotSpotY:
- @abstract Sets the current cursor to a custom image
- @discussion Sets the current cursor to the cursor given by the aCursorImage argument.
- Resources associated with the previous cursor are cleaned up.
- @param aCursorImage the cursor image to use
- @param aHotSpotX the x coordinate of the cursor's hotspot
- @param aHotSpotY the y coordinate of the cursor's hotspot
- @param scaleFactor the scale factor of the target display (2 for a retina display)
- */
-- (nsresult) setCursorWithImage: (imgIContainer*) aCursorImage hotSpotX: (uint32_t) aHotspotX hotSpotY: (uint32_t) aHotspotY scaleFactor: (CGFloat) scaleFactor;
-
-
-/*! @method sharedInstance
- @abstract Get the Singleton instance of the cursor manager.
- @discussion Use this method to obtain a reference to the cursor manager.
- @result a reference to the cursor manager
-*/
-+ (nsCursorManager *) sharedInstance;
-
-/*! @method dispose
- @abstract Releases the shared instance of the cursor manager.
- @discussion Use dispose to clean up the cursor manager and associated cursors.
-*/
-+ (void) dispose;
-@end
-
-@interface NSCursor (Undocumented)
-// busyButClickableCursor is an undocumented NSCursor API, but has been in use since
-// at least OS X 10.4 and through 10.9.
-+ (NSCursor*)busyButClickableCursor;
-@end
-
-#endif // nsCursorManager_h_
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 <math.h>
-
-static nsCursorManager *gInstance;
-static CGFloat sCursorScaleFactor = 0.0f;
-static imgIContainer *sCursorImgContainer = nullptr;
-static const nsCursor sCustomCursor = eCursorCount;
-
-/*! @category nsCursorManager(PrivateMethods)
- Private methods for the cursor manager class.
-*/
-@interface nsCursorManager(PrivateMethods)
-/*! @method getCursor:
- @abstract Get a reference to the native Mac representation of a cursor.
- @discussion Gets a reference to the Mac native implementation of a cursor.
- If the cursor has been requested before, it is retreived from the cursor cache,
- otherwise it is created and cached.
- @param aCursor the cursor to get
- @result the Mac native implementation of the cursor
-*/
-- (nsMacCursor *) getCursor: (nsCursor) aCursor;
-
-/*! @method setMacCursor:
- @abstract Set the current Mac native cursor
- @discussion Sets the current cursor - this routine is what actually causes the cursor to change.
- The argument is retained and the old cursor is released.
- @param aMacCursor the cursor to set
- @result NS_OK
- */
-- (nsresult) setMacCursor: (nsMacCursor*) aMacCursor;
-
-/*! @method createCursor:
- @abstract Create a Mac native representation of a cursor.
- @discussion Creates a version of the Mac native representation of this cursor
- @param aCursor the cursor to create
- @result the Mac native implementation of the cursor
-*/
-+ (nsMacCursor *) createCursor: (enum nsCursor) aCursor;
-
-@end
-
-@implementation nsCursorManager
-
-+ (nsCursorManager *) sharedInstance
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
-
- if (!gInstance) {
- gInstance = [[nsCursorManager alloc] init];
- }
- return gInstance;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
-}
-
-+ (void) dispose
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- [gInstance release];
- gInstance = nil;
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-+ (nsMacCursor *) createCursor: (enum nsCursor) aCursor
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
-
- switch(aCursor)
- {
- SEL cursorSelector;
- case eCursor_standard:
- return [nsMacCursor cursorWithCursor:[NSCursor arrowCursor] type:aCursor];
- case eCursor_wait:
- case eCursor_spinning:
- {
- return [nsMacCursor cursorWithCursor:[NSCursor busyButClickableCursor] type:aCursor];
- }
- case eCursor_select:
- return [nsMacCursor cursorWithCursor:[NSCursor IBeamCursor] type:aCursor];
- case eCursor_hyperlink:
- return [nsMacCursor cursorWithCursor:[NSCursor pointingHandCursor] type:aCursor];
- case eCursor_crosshair:
- return [nsMacCursor cursorWithCursor:[NSCursor crosshairCursor] type:aCursor];
- case eCursor_move:
- return [nsMacCursor cursorWithImageNamed:@"move" hotSpot:NSMakePoint(12,12) type:aCursor];
- case eCursor_help:
- return [nsMacCursor cursorWithImageNamed:@"help" hotSpot:NSMakePoint(12,12) type:aCursor];
- case eCursor_copy:
- cursorSelector = @selector(dragCopyCursor);
- return [nsMacCursor cursorWithCursor:[NSCursor respondsToSelector:cursorSelector] ?
- [NSCursor performSelector:cursorSelector] :
- [NSCursor arrowCursor] type:aCursor];
- case eCursor_alias:
- cursorSelector = @selector(dragLinkCursor);
- return [nsMacCursor cursorWithCursor:[NSCursor respondsToSelector:cursorSelector] ?
- [NSCursor performSelector:cursorSelector] :
- [NSCursor arrowCursor] type:aCursor];
- case eCursor_context_menu:
- cursorSelector = @selector(contextualMenuCursor);
- return [nsMacCursor cursorWithCursor:[NSCursor respondsToSelector:cursorSelector] ?
- [NSCursor performSelector:cursorSelector] :
- [NSCursor arrowCursor] type:aCursor];
- case eCursor_cell:
- return [nsMacCursor cursorWithImageNamed:@"cell" hotSpot:NSMakePoint(12,12) type:aCursor];
- case eCursor_grab:
- return [nsMacCursor cursorWithCursor:[NSCursor openHandCursor] type:aCursor];
- case eCursor_grabbing:
- return [nsMacCursor cursorWithCursor:[NSCursor closedHandCursor] type:aCursor];
- case eCursor_zoom_in:
- return [nsMacCursor cursorWithImageNamed:@"zoomIn" hotSpot:NSMakePoint(10,10) type:aCursor];
- case eCursor_zoom_out:
- return [nsMacCursor cursorWithImageNamed:@"zoomOut" hotSpot:NSMakePoint(10,10) type:aCursor];
- case eCursor_vertical_text:
- return [nsMacCursor cursorWithImageNamed:@"vtIBeam" hotSpot:NSMakePoint(12,11) type:aCursor];
- case eCursor_all_scroll:
- return [nsMacCursor cursorWithCursor:[NSCursor openHandCursor] type:aCursor];
- case eCursor_not_allowed:
- case eCursor_no_drop:
- cursorSelector = @selector(operationNotAllowedCursor);
- return [nsMacCursor cursorWithCursor:[NSCursor respondsToSelector:cursorSelector] ?
- [NSCursor performSelector:cursorSelector] :
- [NSCursor arrowCursor] type:aCursor];
- // Resize Cursors:
- // North
- case eCursor_n_resize:
- return [nsMacCursor cursorWithCursor:[NSCursor resizeUpCursor] type:aCursor];
- // North East
- case eCursor_ne_resize:
- return [nsMacCursor cursorWithImageNamed:@"sizeNE" hotSpot:NSMakePoint(12,11) type:aCursor];
- // East
- case eCursor_e_resize:
- return [nsMacCursor cursorWithCursor:[NSCursor resizeRightCursor] type:aCursor];
- // South East
- case eCursor_se_resize:
- return [nsMacCursor cursorWithImageNamed:@"sizeSE" hotSpot:NSMakePoint(12,12) type:aCursor];
- // South
- case eCursor_s_resize:
- return [nsMacCursor cursorWithCursor:[NSCursor resizeDownCursor] type:aCursor];
- // South West
- case eCursor_sw_resize:
- return [nsMacCursor cursorWithImageNamed:@"sizeSW" hotSpot:NSMakePoint(10,12) type:aCursor];
- // West
- case eCursor_w_resize:
- return [nsMacCursor cursorWithCursor:[NSCursor resizeLeftCursor] type:aCursor];
- // North West
- case eCursor_nw_resize:
- return [nsMacCursor cursorWithImageNamed:@"sizeNW" hotSpot:NSMakePoint(11,11) type:aCursor];
- // North & South
- case eCursor_ns_resize:
- return [nsMacCursor cursorWithCursor:[NSCursor resizeUpDownCursor] type:aCursor];
- // East & West
- case eCursor_ew_resize:
- return [nsMacCursor cursorWithCursor:[NSCursor resizeLeftRightCursor] type:aCursor];
- // North East & South West
- case eCursor_nesw_resize:
- return [nsMacCursor cursorWithImageNamed:@"sizeNESW" hotSpot:NSMakePoint(12,12) type:aCursor];
- // North West & South East
- case eCursor_nwse_resize:
- return [nsMacCursor cursorWithImageNamed:@"sizeNWSE" hotSpot:NSMakePoint(12,12) type:aCursor];
- // Column Resize
- case eCursor_col_resize:
- return [nsMacCursor cursorWithImageNamed:@"colResize" hotSpot:NSMakePoint(12,12) type:aCursor];
- // Row Resize
- case eCursor_row_resize:
- return [nsMacCursor cursorWithImageNamed:@"rowResize" hotSpot:NSMakePoint(12,12) type:aCursor];
- default:
- return [nsMacCursor cursorWithCursor:[NSCursor arrowCursor] type:aCursor];
- }
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
-}
-
-- (id) init
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
-
- if ((self = [super init])) {
- mCursors = [[NSMutableDictionary alloc] initWithCapacity:25];
- }
- return self;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
-}
-
-- (nsresult) setCursor: (enum nsCursor) aCursor
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- // Some plugins mess with our cursors and set a cursor that even
- // [NSCursor currentCursor] doesn't know about. In case that happens, just
- // reset the state.
- [[NSCursor currentCursor] set];
-
- nsCursor oldType = [mCurrentMacCursor type];
- if (oldType != aCursor) {
- if (aCursor == eCursor_none) {
- [NSCursor hide];
- } else if (oldType == eCursor_none) {
- [NSCursor unhide];
- }
- }
- [self setMacCursor:[self getCursor:aCursor]];
-
- // if a custom cursor was previously set, release sCursorImgContainer
- if (oldType == sCustomCursor) {
- NS_IF_RELEASE(sCursorImgContainer);
- }
- return NS_OK;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-- (nsresult) setMacCursor: (nsMacCursor*) aMacCursor
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- if (mCurrentMacCursor != aMacCursor || ![mCurrentMacCursor isSet]) {
- [aMacCursor retain];
- [mCurrentMacCursor unset];
- [aMacCursor set];
- [mCurrentMacCursor release];
- mCurrentMacCursor = aMacCursor;
- }
-
- return NS_OK;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-- (nsresult) setCursorWithImage: (imgIContainer*) aCursorImage hotSpotX: (uint32_t) aHotspotX hotSpotY: (uint32_t) aHotspotY scaleFactor: (CGFloat) scaleFactor
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
- // As the user moves the mouse, this gets called repeatedly with the same aCursorImage
- if (sCursorImgContainer == aCursorImage && sCursorScaleFactor == scaleFactor && mCurrentMacCursor) {
- [self setMacCursor:mCurrentMacCursor];
- return NS_OK;
- }
-
- [[NSCursor currentCursor] set];
- int32_t width = 0, height = 0;
- aCursorImage->GetWidth(&width);
- aCursorImage->GetHeight(&height);
- // prevent DoS attacks
- if (width > 128 || height > 128) {
- return NS_OK;
- }
-
- NSImage *cursorImage;
- nsresult rv = nsCocoaUtils::CreateNSImageFromImageContainer(aCursorImage, imgIContainer::FRAME_FIRST, &cursorImage, scaleFactor);
- if (NS_FAILED(rv) || !cursorImage) {
- return NS_ERROR_FAILURE;
- }
-
- // if the hotspot is nonsensical, make it 0,0
- aHotspotX = (aHotspotX > (uint32_t)width - 1) ? 0 : aHotspotX;
- aHotspotY = (aHotspotY > (uint32_t)height - 1) ? 0 : aHotspotY;
-
- NSPoint hotSpot = ::NSMakePoint(aHotspotX, aHotspotY);
- [self setMacCursor:[nsMacCursor cursorWithCursor:[[NSCursor alloc] initWithImage:cursorImage hotSpot:hotSpot] type:sCustomCursor]];
- [cursorImage release];
-
- NS_IF_RELEASE(sCursorImgContainer);
- sCursorImgContainer = aCursorImage;
- sCursorScaleFactor = scaleFactor;
- NS_ADDREF(sCursorImgContainer);
-
- return NS_OK;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-- (nsMacCursor *) getCursor: (enum nsCursor) aCursor
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
-
- nsMacCursor * result = [mCursors objectForKey:[NSNumber numberWithInt:aCursor]];
- if (!result) {
- result = [nsCursorManager createCursor:aCursor];
- [mCursors setObject:result forKey:[NSNumber numberWithInt:aCursor]];
- }
- return result;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
-}
-
-- (void) dealloc
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- [mCurrentMacCursor unset];
- [mCurrentMacCursor release];
- [mCursors release];
- NS_IF_RELEASE(sCursorImgContainer);
- [super dealloc];
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-@end
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 <ApplicationServices/ApplicationServices.h>
-
-class nsDeviceContextSpecX : public nsIDeviceContextSpec
-{
-public:
- NS_DECL_ISUPPORTS
-
- nsDeviceContextSpecX();
-
- NS_IMETHOD Init(nsIWidget *aWidget, nsIPrintSettings* aPS, bool aIsPrintPreview) override;
- virtual already_AddRefed<PrintTarget> MakePrintTarget() final;
- NS_IMETHOD BeginDocument(const nsAString& aTitle,
- const nsAString& aPrintToFileName,
- int32_t aStartPage,
- int32_t aEndPage) override;
- NS_IMETHOD EndDocument() override;
- NS_IMETHOD BeginPage() override;
- NS_IMETHOD EndPage() override;
-
- void GetPaperRect(double* aTop, double* aLeft, double* aBottom, double* aRight);
-
-protected:
- virtual ~nsDeviceContextSpecX();
-
-protected:
- PMPrintSession mPrintSession; // printing context.
- PMPageFormat mPageFormat; // page format.
- PMPrintSettings mPrintSettings; // print settings.
-};
-
-#endif //nsDeviceContextSpecX_h_
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 <unistd.h>
-
-#include "nsQueryObject.h"
-#include "nsIServiceManager.h"
-#include "nsPrintSettingsX.h"
-
-// This must be the last include:
-#include "nsObjCExceptions.h"
-
-using namespace mozilla;
-using namespace mozilla::gfx;
-
-nsDeviceContextSpecX::nsDeviceContextSpecX()
-: mPrintSession(NULL)
-, mPageFormat(kPMNoPageFormat)
-, mPrintSettings(kPMNoPrintSettings)
-{
-}
-
-nsDeviceContextSpecX::~nsDeviceContextSpecX()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- if (mPrintSession)
- ::PMRelease(mPrintSession);
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-NS_IMPL_ISUPPORTS(nsDeviceContextSpecX, nsIDeviceContextSpec)
-
-NS_IMETHODIMP nsDeviceContextSpecX::Init(nsIWidget *aWidget,
- nsIPrintSettings* aPS,
- bool aIsPrintPreview)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- RefPtr<nsPrintSettingsX> settings(do_QueryObject(aPS));
- if (!settings)
- return NS_ERROR_NO_INTERFACE;
-
- mPrintSession = settings->GetPMPrintSession();
- ::PMRetain(mPrintSession);
- mPageFormat = settings->GetPMPageFormat();
- mPrintSettings = settings->GetPMPrintSettings();
-
- return NS_OK;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsDeviceContextSpecX::BeginDocument(const nsAString& aTitle,
- const nsAString& aPrintToFileName,
- int32_t aStartPage,
- int32_t aEndPage)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- if (!aTitle.IsEmpty()) {
- CFStringRef cfString =
- ::CFStringCreateWithCharacters(NULL, reinterpret_cast<const UniChar*>(aTitle.BeginReading()),
- aTitle.Length());
- if (cfString) {
- ::PMPrintSettingsSetJobName(mPrintSettings, cfString);
- ::CFRelease(cfString);
- }
- }
-
- OSStatus status;
- status = ::PMSetFirstPage(mPrintSettings, aStartPage, false);
- NS_ASSERTION(status == noErr, "PMSetFirstPage failed");
- status = ::PMSetLastPage(mPrintSettings, aEndPage, false);
- NS_ASSERTION(status == noErr, "PMSetLastPage failed");
-
- status = ::PMSessionBeginCGDocumentNoDialog(mPrintSession, mPrintSettings, mPageFormat);
- if (status != noErr)
- return NS_ERROR_ABORT;
-
- return NS_OK;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsDeviceContextSpecX::EndDocument()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- ::PMSessionEndDocumentNoDialog(mPrintSession);
- return NS_OK;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsDeviceContextSpecX::BeginPage()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- PMSessionError(mPrintSession);
- OSStatus status = ::PMSessionBeginPageNoDialog(mPrintSession, mPageFormat, NULL);
- if (status != noErr) return NS_ERROR_ABORT;
- return NS_OK;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsDeviceContextSpecX::EndPage()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- OSStatus status = ::PMSessionEndPageNoDialog(mPrintSession);
- if (status != noErr) return NS_ERROR_ABORT;
- return NS_OK;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-void nsDeviceContextSpecX::GetPaperRect(double* aTop, double* aLeft, double* aBottom, double* aRight)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- PMRect paperRect;
- ::PMGetAdjustedPaperRect(mPageFormat, &paperRect);
-
- *aTop = paperRect.top, *aLeft = paperRect.left;
- *aBottom = paperRect.bottom, *aRight = paperRect.right;
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-already_AddRefed<PrintTarget> nsDeviceContextSpecX::MakePrintTarget()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- double top, left, bottom, right;
- GetPaperRect(&top, &left, &bottom, &right);
- const double width = right - left;
- const double height = bottom - top;
- IntSize size = IntSize::Floor(width, height);
-
- CGContextRef context;
- ::PMSessionGetCGGraphicsContext(mPrintSession, &context);
-
- if (context) {
- // Initially, origin is at bottom-left corner of the paper.
- // Here, we translate it to top-left corner of the paper.
- CGContextTranslateCTM(context, 0, height);
- CGContextScaleCTM(context, 1.0, -1.0);
- return PrintTargetCG::CreateOrNull(context, size);
- }
-
- // Apparently we do need this branch - bug 368933.
- return PrintTargetCG::CreateOrNull(size, SurfaceFormat::A8R8G8B8_UINT32);
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSNULL;
-}
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 <Cocoa/Cocoa.h>
-
-extern NSString* const kWildcardPboardType;
-extern NSString* const kCorePboardType_url;
-extern NSString* const kCorePboardType_urld;
-extern NSString* const kCorePboardType_urln;
-extern NSString* const kCustomTypesPboardType;
-
-class nsDragService : public nsBaseDragService
-{
-public:
- nsDragService();
-
- // nsBaseDragService
- virtual nsresult InvokeDragSessionImpl(nsIArray* anArrayTransferables,
- nsIScriptableRegion* aRegion,
- uint32_t aActionType);
- // nsIDragService
- NS_IMETHOD EndDragSession(bool aDoneDrag);
-
- // nsIDragSession
- NS_IMETHOD GetData(nsITransferable * aTransferable, uint32_t aItemIndex);
- NS_IMETHOD IsDataFlavorSupported(const char *aDataFlavor, bool *_retval);
- NS_IMETHOD GetNumDropItems(uint32_t * aNumItems);
-
-protected:
- virtual ~nsDragService();
-
-private:
-
- NSImage* ConstructDragImage(nsIDOMNode* aDOMNode,
- mozilla::LayoutDeviceIntRect* aDragRect,
- nsIScriptableRegion* aRegion);
- bool IsValidType(NSString* availableType, bool allowFileURL);
- NSString* GetStringForType(NSPasteboardItem* item, const NSString* type,
- bool allowFileURL = false);
- NSString* GetTitleForURL(NSPasteboardItem* item);
- NSString* GetFilePath(NSPasteboardItem* item);
-
- nsCOMPtr<nsIArray> mDataItems; // only valid for a drag started within gecko
- NSView* mNativeDragView;
- NSEvent* mNativeDragEvent;
-};
-
-#endif // nsDragService_h_
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<nsITransferable> currentTransferable = do_QueryElementAt(aTransferableArray, j);
- if (!currentTransferable)
- return NS_ERROR_FAILURE;
-
- // Transform the transferable to an NSDictionary
- NSDictionary* pasteboardOutputDict = nsClipboard::PasteboardDictFromTransferable(currentTransferable);
- if (!pasteboardOutputDict)
- return NS_ERROR_FAILURE;
-
- // write everything out to the general pasteboard
- unsigned int typeCount = [pasteboardOutputDict count];
- NSMutableArray* types = [NSMutableArray arrayWithCapacity:typeCount + 1];
- [types addObjectsFromArray:[pasteboardOutputDict allKeys]];
- // Gecko is initiating this drag so we always want its own views to consider
- // it. Add our wildcard type to the pasteboard to accomplish this.
- [types addObject:kWildcardPboardType]; // we don't increase the count for the loop below on purpose
- [dragPBoard declareTypes:types owner:nil];
- for (unsigned int k = 0; k < typeCount; k++) {
- NSString* currentKey = [types objectAtIndex:k];
- id currentValue = [pasteboardOutputDict valueForKey:currentKey];
- if (currentKey == NSStringPboardType ||
- currentKey == kCorePboardType_url ||
- currentKey == kCorePboardType_urld ||
- currentKey == kCorePboardType_urln) {
- [dragPBoard setString:currentValue forType:currentKey];
- }
- else if (currentKey == NSHTMLPboardType) {
- [dragPBoard setString:(nsClipboard::WrapHtmlForSystemPasteboard(currentValue))
- forType:currentKey];
- }
- else if (currentKey == NSTIFFPboardType ||
- currentKey == kCustomTypesPboardType) {
- [dragPBoard setData:currentValue forType:currentKey];
- }
- else if (currentKey == NSFilesPromisePboardType ||
- currentKey == NSFilenamesPboardType) {
- [dragPBoard setPropertyList:currentValue forType:currentKey];
- }
- }
- }
-
- return NS_OK;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NSImage*
-nsDragService::ConstructDragImage(nsIDOMNode* aDOMNode,
- LayoutDeviceIntRect* aDragRect,
- nsIScriptableRegion* aRegion)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
-
- CGFloat scaleFactor = nsCocoaUtils::GetBackingScaleFactor(gLastDragView);
-
- RefPtr<SourceSurface> surface;
- nsPresContext* pc;
- nsresult rv = DrawDrag(aDOMNode, aRegion, mScreenPosition,
- aDragRect, &surface, &pc);
- if (pc && (!aDragRect->width || !aDragRect->height)) {
- // just use some suitable defaults
- int32_t size = nsCocoaUtils::CocoaPointsToDevPixels(20, scaleFactor);
- aDragRect->SetRect(pc->CSSPixelsToDevPixels(mScreenPosition.x),
- pc->CSSPixelsToDevPixels(mScreenPosition.y), size, size);
- }
-
- if (NS_FAILED(rv) || !surface)
- return nil;
-
- uint32_t width = aDragRect->width;
- uint32_t height = aDragRect->height;
-
- RefPtr<DataSourceSurface> dataSurface =
- Factory::CreateDataSourceSurface(IntSize(width, height),
- SurfaceFormat::B8G8R8A8);
- DataSourceSurface::MappedSurface map;
- if (!dataSurface->Map(DataSourceSurface::MapType::READ_WRITE, &map)) {
- return nil;
- }
-
- RefPtr<DrawTarget> dt =
- Factory::CreateDrawTargetForData(BackendType::CAIRO,
- map.mData,
- dataSurface->GetSize(),
- map.mStride,
- dataSurface->GetFormat());
- if (!dt) {
- dataSurface->Unmap();
- return nil;
- }
-
- dt->FillRect(gfx::Rect(0, 0, width, height),
- SurfacePattern(surface, ExtendMode::CLAMP),
- DrawOptions(1.0f, CompositionOp::OP_SOURCE));
-
- NSBitmapImageRep* imageRep =
- [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
- pixelsWide:width
- pixelsHigh:height
- bitsPerSample:8
- samplesPerPixel:4
- hasAlpha:YES
- isPlanar:NO
- colorSpaceName:NSDeviceRGBColorSpace
- bytesPerRow:width * 4
- bitsPerPixel:32];
-
- uint8_t* dest = [imageRep bitmapData];
- for (uint32_t i = 0; i < height; ++i) {
- uint8_t* src = map.mData + i * map.mStride;
- for (uint32_t j = 0; j < width; ++j) {
- // Reduce transparency overall by multipying by a factor. Remember, Alpha
- // is premultipled here. Also, Quartz likes RGBA, so do that translation as well.
-#ifdef IS_BIG_ENDIAN
- dest[0] = uint8_t(src[1] * DRAG_TRANSLUCENCY);
- dest[1] = uint8_t(src[2] * DRAG_TRANSLUCENCY);
- dest[2] = uint8_t(src[3] * DRAG_TRANSLUCENCY);
- dest[3] = uint8_t(src[0] * DRAG_TRANSLUCENCY);
-#else
- dest[0] = uint8_t(src[2] * DRAG_TRANSLUCENCY);
- dest[1] = uint8_t(src[1] * DRAG_TRANSLUCENCY);
- dest[2] = uint8_t(src[0] * DRAG_TRANSLUCENCY);
- dest[3] = uint8_t(src[3] * DRAG_TRANSLUCENCY);
-#endif
- src += 4;
- dest += 4;
- }
- }
- dataSurface->Unmap();
-
- NSImage* image =
- [[NSImage alloc] initWithSize:NSMakeSize(width / scaleFactor,
- height / scaleFactor)];
- [image addRepresentation:imageRep];
- [imageRep release];
-
- return [image autorelease];
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
-}
-
-bool
-nsDragService::IsValidType(NSString* availableType, bool allowFileURL)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
-
- // Prevent exposing fileURL for non-fileURL type.
- // We need URL provided by dropped webloc file, but don't need file's URL.
- // kUTTypeFileURL is returned by [NSPasteboard availableTypeFromArray:] for
- // kUTTypeURL, since it conforms to kUTTypeURL.
- if (!allowFileURL && [availableType isEqualToString:(id)kUTTypeFileURL]) {
- return false;
- }
-
- return true;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
-}
-
-NSString*
-nsDragService::GetStringForType(NSPasteboardItem* item, const NSString* type,
- bool allowFileURL)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
-
- NSString* availableType = [item availableTypeFromArray:[NSArray arrayWithObjects:(id)type, nil]];
- if (availableType && IsValidType(availableType, allowFileURL)) {
- return [item stringForType:(id)availableType];
- }
-
- return nil;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
-}
-
-NSString*
-nsDragService::GetTitleForURL(NSPasteboardItem* item)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
-
- NSString* name = GetStringForType(item, (const NSString*)kUTTypeURLName);
- if (name) {
- return name;
- }
-
- NSString* filePath = GetFilePath(item);
- if (filePath) {
- return [filePath lastPathComponent];
- }
-
- return nil;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
-}
-
-NSString*
-nsDragService::GetFilePath(NSPasteboardItem* item)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
-
- NSString* urlString = GetStringForType(item, (const NSString*)kUTTypeFileURL, true);
- if (urlString) {
- NSURL* url = [NSURL URLWithString:urlString];
- if (url) {
- return [url path];
- }
- }
-
- return nil;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
-}
-
-// We can only invoke NSView's 'dragImage:at:offset:event:pasteboard:source:slideBack:' from
-// within NSView's 'mouseDown:' or 'mouseDragged:'. Luckily 'mouseDragged' is always on the
-// stack when InvokeDragSession gets called.
-nsresult
-nsDragService::InvokeDragSessionImpl(nsIArray* aTransferableArray,
- nsIScriptableRegion* aDragRgn,
- uint32_t aActionType)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- mDataItems = aTransferableArray;
-
- // put data on the clipboard
- if (NS_FAILED(SetUpDragClipboard(aTransferableArray)))
- return NS_ERROR_FAILURE;
-
- CGFloat scaleFactor = nsCocoaUtils::GetBackingScaleFactor(gLastDragView);
-
- LayoutDeviceIntRect dragRect(0, 0, 20, 20);
- NSImage* image = ConstructDragImage(mSourceNode, &dragRect, aDragRgn);
- if (!image) {
- // if no image was returned, just draw a rectangle
- NSSize size;
- size.width = nsCocoaUtils::DevPixelsToCocoaPoints(dragRect.width, scaleFactor);
- size.height = nsCocoaUtils::DevPixelsToCocoaPoints(dragRect.height, scaleFactor);
- image = [[NSImage alloc] initWithSize:size];
- [image lockFocus];
- [[NSColor grayColor] set];
- NSBezierPath* path = [NSBezierPath bezierPath];
- [path setLineWidth:2.0];
- [path moveToPoint:NSMakePoint(0, 0)];
- [path lineToPoint:NSMakePoint(0, size.height)];
- [path lineToPoint:NSMakePoint(size.width, size.height)];
- [path lineToPoint:NSMakePoint(size.width, 0)];
- [path lineToPoint:NSMakePoint(0, 0)];
- [path stroke];
- [image unlockFocus];
- }
-
- LayoutDeviceIntPoint pt(dragRect.x, dragRect.YMost());
- NSPoint point = nsCocoaUtils::DevPixelsToCocoaPoints(pt, scaleFactor);
- point.y = nsCocoaUtils::FlippedScreenY(point.y);
-
- point = nsCocoaUtils::ConvertPointFromScreen([gLastDragView window], point);
- NSPoint localPoint = [gLastDragView convertPoint:point fromView:nil];
-
- // Save the transferables away in case a promised file callback is invoked.
- gDraggedTransferables = aTransferableArray;
-
- nsBaseDragService::StartDragSession();
- nsBaseDragService::OpenDragPopup();
-
- // We need to retain the view and the event during the drag in case either gets destroyed.
- mNativeDragView = [gLastDragView retain];
- mNativeDragEvent = [gLastDragMouseDownEvent retain];
-
- gUserCancelledDrag = false;
- [mNativeDragView dragImage:image
- at:localPoint
- offset:NSZeroSize
- event:mNativeDragEvent
- pasteboard:[NSPasteboard pasteboardWithName:NSDragPboard]
- source:mNativeDragView
- slideBack:YES];
- gUserCancelledDrag = false;
-
- if (mDoingDrag)
- nsBaseDragService::EndDragSession(false);
-
- return NS_OK;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP
-nsDragService::GetData(nsITransferable* aTransferable, uint32_t aItemIndex)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- if (!aTransferable)
- return NS_ERROR_FAILURE;
-
- // get flavor list that includes all acceptable flavors (including ones obtained through conversion)
- nsCOMPtr<nsIArray> flavorList;
- nsresult rv = aTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList));
- if (NS_FAILED(rv))
- return NS_ERROR_FAILURE;
-
- uint32_t acceptableFlavorCount;
- flavorList->GetLength(&acceptableFlavorCount);
-
- // if this drag originated within Mozilla we should just use the cached data from
- // when the drag started if possible
- if (mDataItems) {
- nsCOMPtr<nsITransferable> currentTransferable = do_QueryElementAt(mDataItems, aItemIndex);
- if (currentTransferable) {
- for (uint32_t i = 0; i < acceptableFlavorCount; i++) {
- nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryElementAt(flavorList, i);
- if (!currentFlavor)
- continue;
- nsXPIDLCString flavorStr;
- currentFlavor->ToString(getter_Copies(flavorStr));
-
- nsCOMPtr<nsISupports> dataSupports;
- uint32_t dataSize = 0;
- rv = currentTransferable->GetTransferData(flavorStr, getter_AddRefs(dataSupports), &dataSize);
- if (NS_SUCCEEDED(rv)) {
- aTransferable->SetTransferData(flavorStr, dataSupports, dataSize);
- return NS_OK; // maybe try to fill in more types? Is there a point?
- }
- }
- }
- }
-
- // now check the actual clipboard for data
- for (uint32_t i = 0; i < acceptableFlavorCount; i++) {
- nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryElementAt(flavorList, i);
- if (!currentFlavor)
- continue;
-
- nsXPIDLCString flavorStr;
- currentFlavor->ToString(getter_Copies(flavorStr));
-
- MOZ_LOG(sCocoaLog, LogLevel::Info, ("nsDragService::GetData: looking for clipboard data of type %s\n", flavorStr.get()));
-
- NSArray* droppedItems = [globalDragPboard pasteboardItems];
- if (!droppedItems) {
- continue;
- }
-
- uint32_t itemCount = [droppedItems count];
- if (aItemIndex >= itemCount) {
- continue;
- }
-
- NSPasteboardItem* item = [droppedItems objectAtIndex:aItemIndex];
- if (!item) {
- continue;
- }
-
- if (flavorStr.EqualsLiteral(kFileMime)) {
- NSString* filePath = GetFilePath(item);
- if (!filePath)
- continue;
-
- unsigned int stringLength = [filePath length];
- unsigned int dataLength = (stringLength + 1) * sizeof(char16_t); // in bytes
- char16_t* clipboardDataPtr = (char16_t*)malloc(dataLength);
- if (!clipboardDataPtr)
- return NS_ERROR_OUT_OF_MEMORY;
- [filePath getCharacters:reinterpret_cast<unichar*>(clipboardDataPtr)];
- clipboardDataPtr[stringLength] = 0; // null terminate
-
- nsCOMPtr<nsIFile> file;
- rv = NS_NewLocalFile(nsDependentString(clipboardDataPtr), true, getter_AddRefs(file));
- free(clipboardDataPtr);
- if (NS_FAILED(rv))
- continue;
-
- aTransferable->SetTransferData(flavorStr, file, dataLength);
-
- break;
- }
- else if (flavorStr.EqualsLiteral(kCustomTypesMime)) {
- NSString* availableType = [item availableTypeFromArray:[NSArray arrayWithObject:kCustomTypesPboardType]];
- if (!availableType || !IsValidType(availableType, false)) {
- continue;
- }
- NSData *pasteboardData = [item dataForType:availableType];
- if (!pasteboardData) {
- continue;
- }
-
- unsigned int dataLength = [pasteboardData length];
- void* clipboardDataPtr = malloc(dataLength);
- if (!clipboardDataPtr) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- [pasteboardData getBytes:clipboardDataPtr];
-
- nsCOMPtr<nsISupports> genericDataWrapper;
- nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr, clipboardDataPtr, dataLength,
- getter_AddRefs(genericDataWrapper));
-
- aTransferable->SetTransferData(flavorStr, genericDataWrapper, sizeof(nsIInputStream*));
- free(clipboardDataPtr);
- break;
- }
-
- NSString* pString = nil;
- if (flavorStr.EqualsLiteral(kUnicodeMime)) {
- pString = GetStringForType(item, (const NSString*)kUTTypeUTF8PlainText);
- } else if (flavorStr.EqualsLiteral(kHTMLMime)) {
- pString = GetStringForType(item, (const NSString*)kUTTypeHTML);
- } else if (flavorStr.EqualsLiteral(kURLMime)) {
- pString = GetStringForType(item, (const NSString*)kUTTypeURL);
- if (pString) {
- NSString* title = GetTitleForURL(item);
- if (!title) {
- title = pString;
- }
- pString = [NSString stringWithFormat:@"%@\n%@", pString, title];
- }
- } else if (flavorStr.EqualsLiteral(kURLDataMime)) {
- pString = GetStringForType(item, (const NSString*)kUTTypeURL);
- } else if (flavorStr.EqualsLiteral(kURLDescriptionMime)) {
- pString = GetTitleForURL(item);
- } else if (flavorStr.EqualsLiteral(kRTFMime)) {
- pString = GetStringForType(item, (const NSString*)kUTTypeRTF);
- }
- if (pString) {
- NSData* stringData;
- if (flavorStr.EqualsLiteral(kRTFMime)) {
- stringData = [pString dataUsingEncoding:NSASCIIStringEncoding];
- } else {
- stringData = [pString dataUsingEncoding:NSUnicodeStringEncoding];
- }
- unsigned int dataLength = [stringData length];
- void* clipboardDataPtr = malloc(dataLength);
- if (!clipboardDataPtr)
- return NS_ERROR_OUT_OF_MEMORY;
- [stringData getBytes:clipboardDataPtr];
-
- // The DOM only wants LF, so convert from MacOS line endings to DOM line endings.
- int32_t signedDataLength = dataLength;
- nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks(flavorStr, &clipboardDataPtr, &signedDataLength);
- dataLength = signedDataLength;
-
- // skip BOM (Byte Order Mark to distinguish little or big endian)
- char16_t* clipboardDataPtrNoBOM = (char16_t*)clipboardDataPtr;
- if ((dataLength > 2) &&
- ((clipboardDataPtrNoBOM[0] == 0xFEFF) ||
- (clipboardDataPtrNoBOM[0] == 0xFFFE))) {
- dataLength -= sizeof(char16_t);
- clipboardDataPtrNoBOM += 1;
- }
-
- nsCOMPtr<nsISupports> genericDataWrapper;
- nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr, clipboardDataPtrNoBOM, dataLength,
- getter_AddRefs(genericDataWrapper));
- aTransferable->SetTransferData(flavorStr, genericDataWrapper, dataLength);
- free(clipboardDataPtr);
- break;
- }
-
- // We have never supported this on Mac OS X, we should someday. Normally dragging images
- // in is accomplished with a file path drag instead of the image data itself.
- /*
- if (flavorStr.EqualsLiteral(kPNGImageMime) || flavorStr.EqualsLiteral(kJPEGImageMime) ||
- flavorStr.EqualsLiteral(kJPGImageMime) || flavorStr.EqualsLiteral(kGIFImageMime)) {
-
- }
- */
- }
- return NS_OK;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP
-nsDragService::IsDataFlavorSupported(const char *aDataFlavor, bool *_retval)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- *_retval = false;
-
- if (!globalDragPboard)
- return NS_ERROR_FAILURE;
-
- nsDependentCString dataFlavor(aDataFlavor);
-
- // first see if we have data for this in our cached transferable
- if (mDataItems) {
- uint32_t dataItemsCount;
- mDataItems->GetLength(&dataItemsCount);
- for (unsigned int i = 0; i < dataItemsCount; i++) {
- nsCOMPtr<nsITransferable> currentTransferable = do_QueryElementAt(mDataItems, i);
- if (!currentTransferable)
- continue;
-
- nsCOMPtr<nsIArray> flavorList;
- nsresult rv = currentTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList));
- if (NS_FAILED(rv))
- continue;
-
- uint32_t flavorCount;
- flavorList->GetLength(&flavorCount);
- for (uint32_t j = 0; j < flavorCount; j++) {
- nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryElementAt(flavorList, j);
- if (!currentFlavor)
- continue;
- nsXPIDLCString flavorStr;
- currentFlavor->ToString(getter_Copies(flavorStr));
- if (dataFlavor.Equals(flavorStr)) {
- *_retval = true;
- return NS_OK;
- }
- }
- }
- }
-
- const NSString* type = nil;
- bool allowFileURL = false;
- if (dataFlavor.EqualsLiteral(kFileMime)) {
- type = (const NSString*)kUTTypeFileURL;
- allowFileURL = true;
- } else if (dataFlavor.EqualsLiteral(kUnicodeMime)) {
- type = (const NSString*)kUTTypeUTF8PlainText;
- } else if (dataFlavor.EqualsLiteral(kHTMLMime)) {
- type = (const NSString*)kUTTypeHTML;
- } else if (dataFlavor.EqualsLiteral(kURLMime) ||
- dataFlavor.EqualsLiteral(kURLDataMime)) {
- type = (const NSString*)kUTTypeURL;
- } else if (dataFlavor.EqualsLiteral(kURLDescriptionMime)) {
- type = (const NSString*)kUTTypeURLName;
- } else if (dataFlavor.EqualsLiteral(kRTFMime)) {
- type = (const NSString*)kUTTypeRTF;
- } else if (dataFlavor.EqualsLiteral(kCustomTypesMime)) {
- type = (const NSString*)kCustomTypesPboardType;
- }
-
- NSString* availableType = [globalDragPboard availableTypeFromArray:[NSArray arrayWithObjects:(id)type, nil]];
- if (availableType && IsValidType(availableType, allowFileURL)) {
- *_retval = true;
- }
-
- return NS_OK;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP
-nsDragService::GetNumDropItems(uint32_t* aNumItems)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- *aNumItems = 0;
-
- // first check to see if we have a number of items cached
- if (mDataItems) {
- mDataItems->GetLength(aNumItems);
- return NS_OK;
- }
-
- NSArray* droppedItems = [globalDragPboard pasteboardItems];
- if (droppedItems) {
- *aNumItems = [droppedItems count];
- }
-
- return NS_OK;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP
-nsDragService::EndDragSession(bool aDoneDrag)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- if (mNativeDragView) {
- [mNativeDragView release];
- mNativeDragView = nil;
- }
- if (mNativeDragEvent) {
- [mNativeDragEvent release];
- mNativeDragEvent = nil;
- }
-
- mUserCancelled = gUserCancelledDrag;
-
- nsresult rv = nsBaseDragService::EndDragSession(aDoneDrag);
- mDataItems = nullptr;
- return rv;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
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<nsIFile>& outFiles);
- int16_t GetLocalFolder(const nsString& inTitle, nsIFile** outFile);
- int16_t PutLocalFile(const nsString& inTitle, const nsString& inDefaultName, nsIFile** outFile);
-
- void SetDialogTitle(const nsString& inTitle, id aDialog);
- NSString *PanelDefaultDirectory();
- NSView* GetAccessoryView();
-
- nsString mTitle;
- nsCOMArray<nsIFile> mFiles;
- nsString mDefault;
-
- nsTArray<nsString> mFilters;
- nsTArray<nsString> mTitles;
-
- int32_t mSelectedTypeIndex;
-};
-
-#endif // nsFilePicker_h_
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 <Cocoa/Cocoa.h>
-
-#include "nsFilePicker.h"
-#include "nsCOMPtr.h"
-#include "nsReadableUtils.h"
-#include "nsNetUtil.h"
-#include "nsIComponentManager.h"
-#include "nsIFile.h"
-#include "nsILocalFileMac.h"
-#include "nsIURL.h"
-#include "nsArrayEnumerator.h"
-#include "nsIStringBundle.h"
-#include "nsCocoaUtils.h"
-#include "mozilla/Preferences.h"
-
-// This must be included last:
-#include "nsObjCExceptions.h"
-
-using namespace mozilla;
-
-const float kAccessoryViewPadding = 5;
-const int kSaveTypeControlTag = 1;
-
-static bool gCallSecretHiddenFileAPI = false;
-const char kShowHiddenFilesPref[] = "filepicker.showHiddenFiles";
-
-/**
- * This class is an observer of NSPopUpButton selection change.
- */
-@interface NSPopUpButtonObserver : NSObject
-{
- NSPopUpButton* mPopUpButton;
- NSOpenPanel* mOpenPanel;
- nsFilePicker* mFilePicker;
-}
-- (void) setPopUpButton:(NSPopUpButton*)aPopUpButton;
-- (void) setOpenPanel:(NSOpenPanel*)aOpenPanel;
-- (void) setFilePicker:(nsFilePicker*)aFilePicker;
-- (void) menuChangedItem:(NSNotification*)aSender;
-@end
-
-NS_IMPL_ISUPPORTS(nsFilePicker, nsIFilePicker)
-
-// We never want to call the secret show hidden files API unless the pref
-// has been set. Once the pref has been set we always need to call it even
-// if it disappears so that we stop showing hidden files if a user deletes
-// the pref. If the secret API was used once and things worked out it should
-// continue working for subsequent calls so the user is at no more risk.
-static void SetShowHiddenFileState(NSSavePanel* panel)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- bool show = false;
- if (NS_SUCCEEDED(Preferences::GetBool(kShowHiddenFilesPref, &show))) {
- gCallSecretHiddenFileAPI = true;
- }
-
- if (gCallSecretHiddenFileAPI) {
- // invoke a method to get a Cocoa-internal nav view
- SEL navViewSelector = @selector(_navView);
- NSMethodSignature* navViewSignature = [panel methodSignatureForSelector:navViewSelector];
- if (!navViewSignature)
- return;
- NSInvocation* navViewInvocation = [NSInvocation invocationWithMethodSignature:navViewSignature];
- [navViewInvocation setSelector:navViewSelector];
- [navViewInvocation setTarget:panel];
- [navViewInvocation invoke];
-
- // get the returned nav view
- id navView = nil;
- [navViewInvocation getReturnValue:&navView];
-
- // invoke the secret show hidden file state method on the nav view
- SEL showHiddenFilesSelector = @selector(setShowsHiddenFiles:);
- NSMethodSignature* showHiddenFilesSignature = [navView methodSignatureForSelector:showHiddenFilesSelector];
- if (!showHiddenFilesSignature)
- return;
- NSInvocation* showHiddenFilesInvocation = [NSInvocation invocationWithMethodSignature:showHiddenFilesSignature];
- [showHiddenFilesInvocation setSelector:showHiddenFilesSelector];
- [showHiddenFilesInvocation setTarget:navView];
- [showHiddenFilesInvocation setArgument:&show atIndex:2];
- [showHiddenFilesInvocation invoke];
- }
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-nsFilePicker::nsFilePicker()
-: mSelectedTypeIndex(0)
-{
-}
-
-nsFilePicker::~nsFilePicker()
-{
-}
-
-void
-nsFilePicker::InitNative(nsIWidget *aParent, const nsAString& aTitle)
-{
- mTitle = aTitle;
-}
-
-NSView* nsFilePicker::GetAccessoryView()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
-
- NSView* accessoryView = [[[NSView alloc] initWithFrame:NSMakeRect(0, 0, 0, 0)] autorelease];
-
- // Set a label's default value.
- NSString* label = @"Format:";
-
- // Try to get the localized string.
- nsCOMPtr<nsIStringBundleService> sbs = do_GetService(NS_STRINGBUNDLE_CONTRACTID);
- nsCOMPtr<nsIStringBundle> bundle;
- nsresult rv = sbs->CreateBundle("chrome://global/locale/filepicker.properties", getter_AddRefs(bundle));
- if (NS_SUCCEEDED(rv)) {
- nsXPIDLString locaLabel;
- bundle->GetStringFromName(u"formatLabel", getter_Copies(locaLabel));
- if (locaLabel) {
- label = [NSString stringWithCharacters:reinterpret_cast<const unichar*>(locaLabel.get())
- length:locaLabel.Length()];
- }
- }
-
- // set up label text field
- NSTextField* textField = [[[NSTextField alloc] init] autorelease];
- [textField setEditable:NO];
- [textField setSelectable:NO];
- [textField setDrawsBackground:NO];
- [textField setBezeled:NO];
- [textField setBordered:NO];
- [textField setFont:[NSFont labelFontOfSize:13.0]];
- [textField setStringValue:label];
- [textField setTag:0];
- [textField sizeToFit];
-
- // set up popup button
- NSPopUpButton* popupButton = [[[NSPopUpButton alloc] initWithFrame:NSMakeRect(0, 0, 0, 0) pullsDown:NO] autorelease];
- uint32_t numMenuItems = mTitles.Length();
- for (uint32_t i = 0; i < numMenuItems; i++) {
- const nsString& currentTitle = mTitles[i];
- NSString *titleString;
- if (currentTitle.IsEmpty()) {
- const nsString& currentFilter = mFilters[i];
- titleString = [[NSString alloc] initWithCharacters:reinterpret_cast<const unichar*>(currentFilter.get())
- length:currentFilter.Length()];
- }
- else {
- titleString = [[NSString alloc] initWithCharacters:reinterpret_cast<const unichar*>(currentTitle.get())
- length:currentTitle.Length()];
- }
- [popupButton addItemWithTitle:titleString];
- [titleString release];
- }
- if (mSelectedTypeIndex >= 0 && (uint32_t)mSelectedTypeIndex < numMenuItems)
- [popupButton selectItemAtIndex:mSelectedTypeIndex];
- [popupButton setTag:kSaveTypeControlTag];
- [popupButton sizeToFit]; // we have to do sizeToFit to get the height calculated for us
- // This is just a default width that works well, doesn't truncate the vast majority of
- // things that might end up in the menu.
- [popupButton setFrameSize:NSMakeSize(180, [popupButton frame].size.height)];
-
- // position everything based on control sizes with kAccessoryViewPadding pix padding
- // on each side kAccessoryViewPadding pix horizontal padding between controls
- float greatestHeight = [textField frame].size.height;
- if ([popupButton frame].size.height > greatestHeight)
- greatestHeight = [popupButton frame].size.height;
- float totalViewHeight = greatestHeight + kAccessoryViewPadding * 2;
- float totalViewWidth = [textField frame].size.width + [popupButton frame].size.width + kAccessoryViewPadding * 3;
- [accessoryView setFrameSize:NSMakeSize(totalViewWidth, totalViewHeight)];
-
- float textFieldOriginY = ((greatestHeight - [textField frame].size.height) / 2 + 1) + kAccessoryViewPadding;
- [textField setFrameOrigin:NSMakePoint(kAccessoryViewPadding, textFieldOriginY)];
-
- float popupOriginX = [textField frame].size.width + kAccessoryViewPadding * 2;
- float popupOriginY = ((greatestHeight - [popupButton frame].size.height) / 2) + kAccessoryViewPadding;
- [popupButton setFrameOrigin:NSMakePoint(popupOriginX, popupOriginY)];
-
- [accessoryView addSubview:textField];
- [accessoryView addSubview:popupButton];
- return accessoryView;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
-}
-
-// Display the file dialog
-NS_IMETHODIMP nsFilePicker::Show(int16_t *retval)
-{
- NS_ENSURE_ARG_POINTER(retval);
-
- *retval = returnCancel;
-
- int16_t userClicksOK = returnCancel;
-
-// Random questions from DHH:
-//
-// Why do we pass mTitle, mDefault to the functions? Can GetLocalFile. PutLocalFile,
-// and GetLocalFolder get called someplace else? It generates a bunch of warnings
-// as it is right now.
-//
-// I think we could easily combine GetLocalFile and GetLocalFolder together, just
-// setting panel pick options based on mMode. I didn't do it here b/c I wanted to
-// make this look as much like Carbon nsFilePicker as possible.
-
- mFiles.Clear();
- nsCOMPtr<nsIFile> theFile;
-
- switch (mMode)
- {
- case modeOpen:
- userClicksOK = GetLocalFiles(mTitle, false, mFiles);
- break;
-
- case modeOpenMultiple:
- userClicksOK = GetLocalFiles(mTitle, true, mFiles);
- break;
-
- case modeSave:
- userClicksOK = PutLocalFile(mTitle, mDefault, getter_AddRefs(theFile));
- break;
-
- case modeGetFolder:
- userClicksOK = GetLocalFolder(mTitle, getter_AddRefs(theFile));
- break;
-
- default:
- NS_ERROR("Unknown file picker mode");
- break;
- }
-
- if (theFile)
- mFiles.AppendObject(theFile);
-
- *retval = userClicksOK;
- return NS_OK;
-}
-
-static
-void UpdatePanelFileTypes(NSOpenPanel* aPanel, NSArray* aFilters)
-{
- // If we show all file types, also "expose" bundles' contents.
- [aPanel setTreatsFilePackagesAsDirectories:!aFilters];
-
- [aPanel setAllowedFileTypes:aFilters];
-}
-
-@implementation NSPopUpButtonObserver
-- (void) setPopUpButton:(NSPopUpButton*)aPopUpButton
-{
- mPopUpButton = aPopUpButton;
-}
-
-- (void) setOpenPanel:(NSOpenPanel*)aOpenPanel
-{
- mOpenPanel = aOpenPanel;
-}
-
-- (void) setFilePicker:(nsFilePicker*)aFilePicker
-{
- mFilePicker = aFilePicker;
-}
-
-- (void) menuChangedItem:(NSNotification *)aSender
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
- int32_t selectedItem = [mPopUpButton indexOfSelectedItem];
- if (selectedItem < 0) {
- return;
- }
-
- mFilePicker->SetFilterIndex(selectedItem);
- UpdatePanelFileTypes(mOpenPanel, mFilePicker->GetFilterList());
-
- NS_OBJC_END_TRY_ABORT_BLOCK_RETURN();
-}
-@end
-
-// Use OpenPanel to do a GetFile. Returns |returnOK| if the user presses OK in the dialog.
-int16_t
-nsFilePicker::GetLocalFiles(const nsString& inTitle, bool inAllowMultiple, nsCOMArray<nsIFile>& outFiles)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
-
- int16_t retVal = (int16_t)returnCancel;
- NSOpenPanel *thePanel = [NSOpenPanel openPanel];
-
- SetShowHiddenFileState(thePanel);
-
- // Set the options for how the get file dialog will appear
- SetDialogTitle(inTitle, thePanel);
- [thePanel setAllowsMultipleSelection:inAllowMultiple];
- [thePanel setCanSelectHiddenExtension:YES];
- [thePanel setCanChooseDirectories:NO];
- [thePanel setCanChooseFiles:YES];
- [thePanel setResolvesAliases:YES]; //this is default - probably doesn't need to be set
-
- // Get filters
- // filters may be null, if we should allow all file types.
- NSArray *filters = GetFilterList();
-
- // set up default directory
- NSString *theDir = PanelDefaultDirectory();
-
- // if this is the "Choose application..." dialog, and no other start
- // dir has been set, then use the Applications folder.
- if (!theDir) {
- if (filters && [filters count] == 1 &&
- [(NSString *)[filters objectAtIndex:0] isEqualToString:@"app"])
- theDir = @"/Applications/";
- else
- theDir = @"";
- }
-
- if (theDir) {
- [thePanel setDirectoryURL:[NSURL fileURLWithPath:theDir isDirectory:YES]];
- }
-
- int result;
- nsCocoaUtils::PrepareForNativeAppModalDialog();
- if (mFilters.Length() > 1) {
- // [NSURL initWithString:] (below) throws an exception if URLString is nil.
-
- NSPopUpButtonObserver* observer = [[NSPopUpButtonObserver alloc] init];
-
- NSView* accessoryView = GetAccessoryView();
- [thePanel setAccessoryView:accessoryView];
-
- [observer setPopUpButton:[accessoryView viewWithTag:kSaveTypeControlTag]];
- [observer setOpenPanel:thePanel];
- [observer setFilePicker:this];
-
- [[NSNotificationCenter defaultCenter]
- addObserver:observer
- selector:@selector(menuChangedItem:)
- name:NSMenuWillSendActionNotification object:nil];
-
- UpdatePanelFileTypes(thePanel, filters);
- result = [thePanel runModal];
-
- [[NSNotificationCenter defaultCenter] removeObserver:observer];
- [observer release];
- } else {
- // If we show all file types, also "expose" bundles' contents.
- if (!filters) {
- [thePanel setTreatsFilePackagesAsDirectories:YES];
- }
- [thePanel setAllowedFileTypes:filters];
- result = [thePanel runModal];
- }
- nsCocoaUtils::CleanUpAfterNativeAppModalDialog();
-
- if (result == NSFileHandlingPanelCancelButton)
- return retVal;
-
- // Converts data from a NSArray of NSURL to the returned format.
- // We should be careful to not call [thePanel URLs] more than once given that
- // it creates a new array each time.
- // We are using Fast Enumeration, thus the NSURL array is created once then
- // iterated.
- for (NSURL* url in [thePanel URLs]) {
- if (!url) {
- continue;
- }
-
- nsCOMPtr<nsIFile> localFile;
- NS_NewLocalFile(EmptyString(), true, getter_AddRefs(localFile));
- nsCOMPtr<nsILocalFileMac> macLocalFile = do_QueryInterface(localFile);
- if (macLocalFile && NS_SUCCEEDED(macLocalFile->InitWithCFURL((CFURLRef)url))) {
- outFiles.AppendObject(localFile);
- }
- }
-
- if (outFiles.Count() > 0)
- retVal = returnOK;
-
- return retVal;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0);
-}
-
-// Use OpenPanel to do a GetFolder. Returns |returnOK| if the user presses OK in the dialog.
-int16_t
-nsFilePicker::GetLocalFolder(const nsString& inTitle, nsIFile** outFile)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
- NS_ASSERTION(outFile, "this protected member function expects a null initialized out pointer");
-
- int16_t retVal = (int16_t)returnCancel;
- NSOpenPanel *thePanel = [NSOpenPanel openPanel];
-
- SetShowHiddenFileState(thePanel);
-
- // Set the options for how the get file dialog will appear
- SetDialogTitle(inTitle, thePanel);
- [thePanel setAllowsMultipleSelection:NO]; //this is default -probably doesn't need to be set
- [thePanel setCanSelectHiddenExtension:YES];
- [thePanel setCanChooseDirectories:YES];
- [thePanel setCanChooseFiles:NO];
- [thePanel setResolvesAliases:YES]; //this is default - probably doesn't need to be set
- [thePanel setCanCreateDirectories:YES];
-
- // packages != folders
- [thePanel setTreatsFilePackagesAsDirectories:NO];
-
- // set up default directory
- NSString *theDir = PanelDefaultDirectory();
- if (theDir) {
- [thePanel setDirectoryURL:[NSURL fileURLWithPath:theDir isDirectory:YES]];
- }
- nsCocoaUtils::PrepareForNativeAppModalDialog();
- int result = [thePanel runModal];
- nsCocoaUtils::CleanUpAfterNativeAppModalDialog();
-
- if (result == NSFileHandlingPanelCancelButton)
- return retVal;
-
- // get the path for the folder (we allow just 1, so that's all we get)
- NSURL *theURL = [[thePanel URLs] objectAtIndex:0];
- if (theURL) {
- nsCOMPtr<nsIFile> localFile;
- NS_NewLocalFile(EmptyString(), true, getter_AddRefs(localFile));
- nsCOMPtr<nsILocalFileMac> macLocalFile = do_QueryInterface(localFile);
- if (macLocalFile && NS_SUCCEEDED(macLocalFile->InitWithCFURL((CFURLRef)theURL))) {
- *outFile = localFile;
- NS_ADDREF(*outFile);
- retVal = returnOK;
- }
- }
-
- return retVal;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0);
-}
-
-// Returns |returnOK| if the user presses OK in the dialog.
-int16_t
-nsFilePicker::PutLocalFile(const nsString& inTitle, const nsString& inDefaultName, nsIFile** outFile)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
- NS_ASSERTION(outFile, "this protected member function expects a null initialized out pointer");
-
- int16_t retVal = returnCancel;
- NSSavePanel *thePanel = [NSSavePanel savePanel];
-
- SetShowHiddenFileState(thePanel);
-
- SetDialogTitle(inTitle, thePanel);
-
- // set up accessory view for file format options
- NSView* accessoryView = GetAccessoryView();
- [thePanel setAccessoryView:accessoryView];
-
- // set up default file name
- NSString* defaultFilename = [NSString stringWithCharacters:(const unichar*)inDefaultName.get() length:inDefaultName.Length()];
-
- // set up allowed types; this prevents the extension from being selected
- // use the UTI for the file type to allow alternate extensions (e.g., jpg vs. jpeg)
- NSString* extension = defaultFilename.pathExtension;
- if (extension.length != 0) {
- CFStringRef type = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (CFStringRef)extension, NULL);
-
- if (type) {
- thePanel.allowedFileTypes = @[(NSString*)type];
- CFRelease(type);
- } else {
- // if there's no UTI for the file extension, use the extension itself.
- thePanel.allowedFileTypes = @[extension];
- }
- }
- // Allow users to change the extension.
- thePanel.allowsOtherFileTypes = YES;
-
- // set up default directory
- NSString *theDir = PanelDefaultDirectory();
- if (theDir) {
- [thePanel setDirectoryURL:[NSURL fileURLWithPath:theDir isDirectory:YES]];
- }
-
- // load the panel
- nsCocoaUtils::PrepareForNativeAppModalDialog();
- [thePanel setNameFieldStringValue:defaultFilename];
- int result = [thePanel runModal];
- nsCocoaUtils::CleanUpAfterNativeAppModalDialog();
- if (result == NSFileHandlingPanelCancelButton)
- return retVal;
-
- // get the save type
- NSPopUpButton* popupButton = [accessoryView viewWithTag:kSaveTypeControlTag];
- if (popupButton) {
- mSelectedTypeIndex = [popupButton indexOfSelectedItem];
- }
-
- NSURL* fileURL = [thePanel URL];
- if (fileURL) {
- nsCOMPtr<nsIFile> localFile;
- NS_NewLocalFile(EmptyString(), true, getter_AddRefs(localFile));
- nsCOMPtr<nsILocalFileMac> macLocalFile = do_QueryInterface(localFile);
- if (macLocalFile && NS_SUCCEEDED(macLocalFile->InitWithCFURL((CFURLRef)fileURL))) {
- *outFile = localFile;
- NS_ADDREF(*outFile);
- // We tell if we are replacing or not by just looking to see if the file exists.
- // The user could not have hit OK and not meant to replace the file.
- if ([[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]])
- retVal = returnReplace;
- else
- retVal = returnOK;
- }
- }
-
- return retVal;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0);
-}
-
-NSArray *
-nsFilePicker::GetFilterList()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
-
- if (!mFilters.Length()) {
- return nil;
- }
-
- if (mFilters.Length() <= (uint32_t)mSelectedTypeIndex) {
- NS_WARNING("An out of range index has been selected. Using the first index instead.");
- mSelectedTypeIndex = 0;
- }
-
- const nsString& filterWide = mFilters[mSelectedTypeIndex];
- if (!filterWide.Length()) {
- return nil;
- }
-
- if (filterWide.Equals(NS_LITERAL_STRING("*"))) {
- return nil;
- }
-
- // The extensions in filterWide are in the format "*.ext" but are expected
- // in the format "ext" by NSOpenPanel. So we need to filter some characters.
- NSMutableString* filterString = [[[NSMutableString alloc] initWithString:
- [NSString stringWithCharacters:reinterpret_cast<const unichar*>(filterWide.get())
- length:filterWide.Length()]] autorelease];
- NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:@". *"];
- NSRange range = [filterString rangeOfCharacterFromSet:set];
- while (range.length) {
- [filterString replaceCharactersInRange:range withString:@""];
- range = [filterString rangeOfCharacterFromSet:set];
- }
-
- return [[[NSArray alloc] initWithArray:
- [filterString componentsSeparatedByString:@";"]] autorelease];
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
-}
-
-// Sets the dialog title to whatever it should be. If it fails, eh,
-// the OS will provide a sensible default.
-void
-nsFilePicker::SetDialogTitle(const nsString& inTitle, id aPanel)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- [aPanel setTitle:[NSString stringWithCharacters:(const unichar*)inTitle.get() length:inTitle.Length()]];
-
- if (!mOkButtonLabel.IsEmpty()) {
- [aPanel setPrompt:[NSString stringWithCharacters:(const unichar*)mOkButtonLabel.get() length:mOkButtonLabel.Length()]];
- }
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-// Converts path from an nsIFile into a NSString path
-// If it fails, returns an empty string.
-NSString *
-nsFilePicker::PanelDefaultDirectory()
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
-
- NSString *directory = nil;
- if (mDisplayDirectory) {
- nsAutoString pathStr;
- mDisplayDirectory->GetPath(pathStr);
- directory = [[[NSString alloc] initWithCharacters:reinterpret_cast<const unichar*>(pathStr.get())
- length:pathStr.Length()] autorelease];
- }
- return directory;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
-}
-
-NS_IMETHODIMP nsFilePicker::GetFile(nsIFile **aFile)
-{
- NS_ENSURE_ARG_POINTER(aFile);
- *aFile = nullptr;
-
- // just return the first file
- if (mFiles.Count() > 0) {
- *aFile = mFiles.ObjectAt(0);
- NS_IF_ADDREF(*aFile);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP nsFilePicker::GetFileURL(nsIURI **aFileURL)
-{
- NS_ENSURE_ARG_POINTER(aFileURL);
- *aFileURL = nullptr;
-
- if (mFiles.Count() == 0)
- return NS_OK;
-
- return NS_NewFileURI(aFileURL, mFiles.ObjectAt(0));
-}
-
-NS_IMETHODIMP nsFilePicker::GetFiles(nsISimpleEnumerator **aFiles)
-{
- return NS_NewArrayEnumerator(aFiles, mFiles);
-}
-
-NS_IMETHODIMP nsFilePicker::SetDefaultString(const nsAString& aString)
-{
- mDefault = aString;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsFilePicker::GetDefaultString(nsAString& aString)
-{
- return NS_ERROR_FAILURE;
-}
-
-// The default extension to use for files
-NS_IMETHODIMP nsFilePicker::GetDefaultExtension(nsAString& aExtension)
-{
- aExtension.Truncate();
- return NS_OK;
-}
-
-NS_IMETHODIMP nsFilePicker::SetDefaultExtension(const nsAString& aExtension)
-{
- return NS_OK;
-}
-
-// Append an entry to the filters array
-NS_IMETHODIMP
-nsFilePicker::AppendFilter(const nsAString& aTitle, const nsAString& aFilter)
-{
- // "..apps" has to be translated with native executable extensions.
- if (aFilter.EqualsLiteral("..apps")) {
- mFilters.AppendElement(NS_LITERAL_STRING("*.app"));
- } else {
- mFilters.AppendElement(aFilter);
- }
- mTitles.AppendElement(aTitle);
-
- return NS_OK;
-}
-
-// Get the filter index - do we still need this?
-NS_IMETHODIMP nsFilePicker::GetFilterIndex(int32_t *aFilterIndex)
-{
- *aFilterIndex = mSelectedTypeIndex;
- return NS_OK;
-}
-
-// Set the filter index - do we still need this?
-NS_IMETHODIMP nsFilePicker::SetFilterIndex(int32_t aFilterIndex)
-{
- mSelectedTypeIndex = aFilterIndex;
- return NS_OK;
-}
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<nsIdleServiceX> GetInstance()
- {
- RefPtr<nsIdleService> idleService = nsIdleService::GetInstance();
- if (!idleService) {
- idleService = new nsIdleServiceX();
- }
-
- return idleService.forget().downcast<nsIdleServiceX>();
- }
-
-protected:
- nsIdleServiceX() { }
- virtual ~nsIdleServiceX() { }
- bool UsePollMode() override;
-};
-
-#endif // nsIdleServiceX_h_
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 <Foundation/Foundation.h>
-
-NS_IMPL_ISUPPORTS_INHERITED0(nsIdleServiceX, nsIdleService)
-
-bool
-nsIdleServiceX::PollIdleTime(uint32_t *aIdleTime)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
-
- kern_return_t rval;
- mach_port_t masterPort;
-
- rval = IOMasterPort(kIOMasterPortDefault, &masterPort);
- if (rval != KERN_SUCCESS)
- return false;
-
- io_iterator_t hidItr;
- rval = IOServiceGetMatchingServices(masterPort,
- IOServiceMatching("IOHIDSystem"),
- &hidItr);
-
- if (rval != KERN_SUCCESS)
- return false;
- NS_ASSERTION(hidItr, "Our iterator is null, but it ought not to be!");
-
- io_registry_entry_t entry = IOIteratorNext(hidItr);
- NS_ASSERTION(entry, "Our IO Registry Entry is null, but it shouldn't be!");
-
- IOObjectRelease(hidItr);
-
- NSMutableDictionary *hidProps;
- rval = IORegistryEntryCreateCFProperties(entry,
- (CFMutableDictionaryRef*)&hidProps,
- kCFAllocatorDefault, 0);
- if (rval != KERN_SUCCESS)
- return false;
- NS_ASSERTION(hidProps, "HIDProperties is null, but no error was returned.");
- [hidProps autorelease];
-
- id idleObj = [hidProps objectForKey:@"HIDIdleTime"];
- NS_ASSERTION([idleObj isKindOfClass: [NSData class]] ||
- [idleObj isKindOfClass: [NSNumber class]],
- "What we got for the idle object is not what we expect!");
-
- uint64_t time;
- if ([idleObj isKindOfClass: [NSData class]])
- [idleObj getBytes: &time];
- else
- time = [idleObj unsignedLongLongValue];
-
- IOObjectRelease(entry);
-
- // convert to ms from ns
- time /= 1000000;
- if (time > UINT32_MAX) // Overflow will occur
- return false;
-
- *aIdleTime = static_cast<uint32_t>(time);
-
- return true;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
-}
-
-bool
-nsIdleServiceX::UsePollMode()
-{
- return true;
-}
-
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<LookAndFeelInt> GetIntCacheImpl();
- virtual void SetIntCacheImpl(const nsTArray<LookAndFeelInt>& aLookAndFeelIntCache);
-
- virtual void RefreshImpl();
-
-protected:
- static bool SystemWantsOverlayScrollbars();
- static bool AllowOverlayScrollbarsOverlap();
-
-private:
- int32_t mUseOverlayScrollbars;
- bool mUseOverlayScrollbarsCached;
-
- int32_t mAllowOverlayScrollbarsOverlap;
- bool mAllowOverlayScrollbarsOverlapCached;
-};
-
-#endif // nsLookAndFeel_h_
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 <Cocoa/Cocoa.h>
-
-// This must be included last:
-#include "nsObjCExceptions.h"
-
-enum {
- mozNSScrollerStyleLegacy = 0,
- mozNSScrollerStyleOverlay = 1
-};
-typedef NSInteger mozNSScrollerStyle;
-
-@interface NSScroller(AvailableSinceLion)
-+ (mozNSScrollerStyle)preferredScrollerStyle;
-@end
-
-nsLookAndFeel::nsLookAndFeel()
- : nsXPLookAndFeel()
- , mUseOverlayScrollbars(-1)
- , mUseOverlayScrollbarsCached(false)
- , mAllowOverlayScrollbarsOverlap(-1)
- , mAllowOverlayScrollbarsOverlapCached(false)
-{
-}
-
-nsLookAndFeel::~nsLookAndFeel()
-{
-}
-
-static nscolor GetColorFromNSColor(NSColor* aColor)
-{
- NSColor* deviceColor = [aColor colorUsingColorSpaceName:NSDeviceRGBColorSpace];
- return NS_RGB((unsigned int)([deviceColor redComponent] * 255.0),
- (unsigned int)([deviceColor greenComponent] * 255.0),
- (unsigned int)([deviceColor blueComponent] * 255.0));
-}
-
-static nscolor GetColorFromNSColorWithAlpha(NSColor* aColor, float alpha)
-{
- NSColor* deviceColor = [aColor colorUsingColorSpaceName:NSDeviceRGBColorSpace];
- return NS_RGBA((unsigned int)([deviceColor redComponent] * 255.0),
- (unsigned int)([deviceColor greenComponent] * 255.0),
- (unsigned int)([deviceColor blueComponent] * 255.0),
- (unsigned int)(alpha * 255.0));
-}
-
-nsresult
-nsLookAndFeel::NativeGetColor(ColorID aID, nscolor &aColor)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- nsresult res = NS_OK;
-
- switch (aID) {
- case eColorID_WindowBackground:
- aColor = NS_RGB(0xff,0xff,0xff);
- break;
- case eColorID_WindowForeground:
- aColor = NS_RGB(0x00,0x00,0x00);
- break;
- case eColorID_WidgetBackground:
- aColor = NS_RGB(0xdd,0xdd,0xdd);
- break;
- case eColorID_WidgetForeground:
- aColor = NS_RGB(0x00,0x00,0x00);
- break;
- case eColorID_WidgetSelectBackground:
- aColor = NS_RGB(0x80,0x80,0x80);
- break;
- case eColorID_WidgetSelectForeground:
- aColor = NS_RGB(0x00,0x00,0x80);
- break;
- case eColorID_Widget3DHighlight:
- aColor = NS_RGB(0xa0,0xa0,0xa0);
- break;
- case eColorID_Widget3DShadow:
- aColor = NS_RGB(0x40,0x40,0x40);
- break;
- case eColorID_TextBackground:
- aColor = NS_RGB(0xff,0xff,0xff);
- break;
- case eColorID_TextForeground:
- aColor = NS_RGB(0x00,0x00,0x00);
- break;
- case eColorID_TextSelectBackground:
- aColor = GetColorFromNSColor([NSColor selectedTextBackgroundColor]);
- break;
- case eColorID_highlight: // CSS2 color
- aColor = GetColorFromNSColor([NSColor alternateSelectedControlColor]);
- break;
- case eColorID__moz_menuhover:
- aColor = GetColorFromNSColor([NSColor alternateSelectedControlColor]);
- break;
- case eColorID_TextSelectForeground:
- GetColor(eColorID_TextSelectBackground, aColor);
- if (aColor == 0x000000)
- aColor = NS_RGB(0xff,0xff,0xff);
- else
- aColor = NS_DONT_CHANGE_COLOR;
- break;
- case eColorID_highlighttext: // CSS2 color
- case eColorID__moz_menuhovertext:
- aColor = GetColorFromNSColor([NSColor alternateSelectedControlTextColor]);
- break;
- case eColorID_IMESelectedRawTextBackground:
- case eColorID_IMESelectedConvertedTextBackground:
- case eColorID_IMERawInputBackground:
- case eColorID_IMEConvertedTextBackground:
- aColor = NS_TRANSPARENT;
- break;
- case eColorID_IMESelectedRawTextForeground:
- case eColorID_IMESelectedConvertedTextForeground:
- case eColorID_IMERawInputForeground:
- case eColorID_IMEConvertedTextForeground:
- aColor = NS_SAME_AS_FOREGROUND_COLOR;
- break;
- case eColorID_IMERawInputUnderline:
- case eColorID_IMEConvertedTextUnderline:
- aColor = NS_40PERCENT_FOREGROUND_COLOR;
- break;
- case eColorID_IMESelectedRawTextUnderline:
- case eColorID_IMESelectedConvertedTextUnderline:
- aColor = NS_SAME_AS_FOREGROUND_COLOR;
- break;
- case eColorID_SpellCheckerUnderline:
- aColor = NS_RGB(0xff, 0, 0);
- break;
-
- //
- // css2 system colors http://www.w3.org/TR/REC-CSS2/ui.html#system-colors
- //
- // It's really hard to effectively map these to the Appearance Manager properly,
- // since they are modeled word for word after the win32 system colors and don't have any
- // real counterparts in the Mac world. I'm sure we'll be tweaking these for
- // years to come.
- //
- // Thanks to mpt26@student.canterbury.ac.nz for the hardcoded values that form the defaults
- // if querying the Appearance Manager fails ;)
- //
- case eColorID__moz_mac_buttonactivetext:
- case eColorID__moz_mac_defaultbuttontext:
- if (nsCocoaFeatures::OnYosemiteOrLater()) {
- aColor = NS_RGB(0xFF,0xFF,0xFF);
- break;
- }
- // Otherwise fall through and return the regular button text:
-
- case eColorID_buttontext:
- case eColorID__moz_buttonhovertext:
- aColor = GetColorFromNSColor([NSColor controlTextColor]);
- break;
- case eColorID_captiontext:
- case eColorID_menutext:
- case eColorID_infotext:
- case eColorID__moz_menubartext:
- aColor = GetColorFromNSColor([NSColor textColor]);
- break;
- case eColorID_windowtext:
- aColor = GetColorFromNSColor([NSColor windowFrameTextColor]);
- break;
- case eColorID_activecaption:
- aColor = GetColorFromNSColor([NSColor gridColor]);
- break;
- case eColorID_activeborder:
- aColor = GetColorFromNSColor([NSColor keyboardFocusIndicatorColor]);
- break;
- case eColorID_appworkspace:
- aColor = NS_RGB(0xFF,0xFF,0xFF);
- break;
- case eColorID_background:
- aColor = NS_RGB(0x63,0x63,0xCE);
- break;
- case eColorID_buttonface:
- case eColorID__moz_buttonhoverface:
- aColor = NS_RGB(0xF0,0xF0,0xF0);
- break;
- case eColorID_buttonhighlight:
- aColor = NS_RGB(0xFF,0xFF,0xFF);
- break;
- case eColorID_buttonshadow:
- aColor = NS_RGB(0xDC,0xDC,0xDC);
- break;
- case eColorID_graytext:
- aColor = GetColorFromNSColor([NSColor disabledControlTextColor]);
- break;
- case eColorID_inactiveborder:
- aColor = GetColorFromNSColor([NSColor controlBackgroundColor]);
- break;
- case eColorID_inactivecaption:
- aColor = GetColorFromNSColor([NSColor controlBackgroundColor]);
- break;
- case eColorID_inactivecaptiontext:
- aColor = NS_RGB(0x45,0x45,0x45);
- break;
- case eColorID_scrollbar:
- aColor = GetColorFromNSColor([NSColor scrollBarColor]);
- break;
- case eColorID_threeddarkshadow:
- aColor = NS_RGB(0xDC,0xDC,0xDC);
- break;
- case eColorID_threedshadow:
- aColor = NS_RGB(0xE0,0xE0,0xE0);
- break;
- case eColorID_threedface:
- aColor = NS_RGB(0xF0,0xF0,0xF0);
- break;
- case eColorID_threedhighlight:
- aColor = GetColorFromNSColor([NSColor highlightColor]);
- break;
- case eColorID_threedlightshadow:
- aColor = NS_RGB(0xDA,0xDA,0xDA);
- break;
- case eColorID_menu:
- aColor = GetColorFromNSColor([NSColor alternateSelectedControlTextColor]);
- break;
- case eColorID_infobackground:
- aColor = NS_RGB(0xFF,0xFF,0xC7);
- break;
- case eColorID_windowframe:
- aColor = GetColorFromNSColor([NSColor gridColor]);
- break;
- case eColorID_window:
- case eColorID__moz_field:
- case eColorID__moz_combobox:
- aColor = NS_RGB(0xff,0xff,0xff);
- break;
- case eColorID__moz_fieldtext:
- case eColorID__moz_comboboxtext:
- aColor = GetColorFromNSColor([NSColor controlTextColor]);
- break;
- case eColorID__moz_dialog:
- aColor = GetColorFromNSColor([NSColor controlHighlightColor]);
- break;
- case eColorID__moz_dialogtext:
- case eColorID__moz_cellhighlighttext:
- case eColorID__moz_html_cellhighlighttext:
- aColor = GetColorFromNSColor([NSColor controlTextColor]);
- break;
- case eColorID__moz_dragtargetzone:
- aColor = GetColorFromNSColor([NSColor selectedControlColor]);
- break;
- case eColorID__moz_mac_chrome_active:
- case eColorID__moz_mac_chrome_inactive: {
- int grey = NativeGreyColorAsInt(toolbarFillGrey, (aID == eColorID__moz_mac_chrome_active));
- aColor = NS_RGB(grey, grey, grey);
- }
- break;
- case eColorID__moz_mac_focusring:
- aColor = GetColorFromNSColorWithAlpha([NSColor keyboardFocusIndicatorColor], 0.48);
- break;
- case eColorID__moz_mac_menushadow:
- aColor = NS_RGB(0xA3,0xA3,0xA3);
- break;
- case eColorID__moz_mac_menutextdisable:
- aColor = NS_RGB(0x98,0x98,0x98);
- break;
- case eColorID__moz_mac_menutextselect:
- aColor = GetColorFromNSColor([NSColor selectedMenuItemTextColor]);
- break;
- case eColorID__moz_mac_disabledtoolbartext:
- aColor = GetColorFromNSColor([NSColor disabledControlTextColor]);
- break;
- case eColorID__moz_mac_menuselect:
- aColor = GetColorFromNSColor([NSColor alternateSelectedControlColor]);
- break;
- case eColorID__moz_buttondefault:
- aColor = NS_RGB(0xDC,0xDC,0xDC);
- break;
- case eColorID__moz_cellhighlight:
- case eColorID__moz_html_cellhighlight:
- case eColorID__moz_mac_secondaryhighlight:
- // For inactive list selection
- aColor = GetColorFromNSColor([NSColor secondarySelectedControlColor]);
- break;
- case eColorID__moz_eventreerow:
- // Background color of even list rows.
- aColor = GetColorFromNSColor([[NSColor controlAlternatingRowBackgroundColors] objectAtIndex:0]);
- break;
- case eColorID__moz_oddtreerow:
- // Background color of odd list rows.
- aColor = GetColorFromNSColor([[NSColor controlAlternatingRowBackgroundColors] objectAtIndex:1]);
- break;
- case eColorID__moz_nativehyperlinktext:
- // There appears to be no available system defined color. HARDCODING to the appropriate color.
- aColor = NS_RGB(0x14,0x4F,0xAE);
- break;
- default:
- NS_WARNING("Someone asked nsILookAndFeel for a color I don't know about");
- aColor = NS_RGB(0xff,0xff,0xff);
- res = NS_ERROR_FAILURE;
- break;
- }
-
- return res;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-nsresult
-nsLookAndFeel::GetIntImpl(IntID aID, int32_t &aResult)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
- nsresult res = nsXPLookAndFeel::GetIntImpl(aID, aResult);
- if (NS_SUCCEEDED(res))
- return res;
- res = NS_OK;
-
- switch (aID) {
- case eIntID_CaretBlinkTime:
- aResult = 567;
- break;
- case eIntID_CaretWidth:
- aResult = 1;
- break;
- case eIntID_ShowCaretDuringSelection:
- aResult = 0;
- break;
- case eIntID_SelectTextfieldsOnKeyFocus:
- // Select textfield content when focused by kbd
- // used by EventStateManager::sTextfieldSelectModel
- aResult = 1;
- break;
- case eIntID_SubmenuDelay:
- aResult = 200;
- break;
- case eIntID_TooltipDelay:
- aResult = 500;
- break;
- case eIntID_MenusCanOverlapOSBar:
- // xul popups are not allowed to overlap the menubar.
- aResult = 0;
- break;
- case eIntID_SkipNavigatingDisabledMenuItem:
- aResult = 1;
- break;
- case eIntID_DragThresholdX:
- case eIntID_DragThresholdY:
- aResult = 4;
- break;
- case eIntID_ScrollArrowStyle:
- aResult = eScrollArrow_None;
- break;
- case eIntID_ScrollSliderStyle:
- aResult = eScrollThumbStyle_Proportional;
- break;
- case eIntID_UseOverlayScrollbars:
- if (!mUseOverlayScrollbarsCached) {
- mUseOverlayScrollbars = SystemWantsOverlayScrollbars() ? 1 : 0;
- mUseOverlayScrollbarsCached = true;
- }
- aResult = mUseOverlayScrollbars;
- break;
- case eIntID_AllowOverlayScrollbarsOverlap:
- if (!mAllowOverlayScrollbarsOverlapCached) {
- mAllowOverlayScrollbarsOverlap = AllowOverlayScrollbarsOverlap() ? 1 : 0;
- mAllowOverlayScrollbarsOverlapCached = true;
- }
- aResult = mAllowOverlayScrollbarsOverlap;
- break;
- case eIntID_ScrollbarDisplayOnMouseMove:
- aResult = 0;
- break;
- case eIntID_ScrollbarFadeBeginDelay:
- aResult = 450;
- break;
- case eIntID_ScrollbarFadeDuration:
- aResult = 200;
- break;
- case eIntID_TreeOpenDelay:
- aResult = 1000;
- break;
- case eIntID_TreeCloseDelay:
- aResult = 1000;
- break;
- case eIntID_TreeLazyScrollDelay:
- aResult = 150;
- break;
- case eIntID_TreeScrollDelay:
- aResult = 100;
- break;
- case eIntID_TreeScrollLinesMax:
- aResult = 3;
- break;
- case eIntID_DWMCompositor:
- case eIntID_WindowsClassic:
- case eIntID_WindowsDefaultTheme:
- case eIntID_TouchEnabled:
- case eIntID_WindowsThemeIdentifier:
- case eIntID_OperatingSystemVersionIdentifier:
- aResult = 0;
- res = NS_ERROR_NOT_IMPLEMENTED;
- break;
- case eIntID_MacGraphiteTheme:
- aResult = [NSColor currentControlTint] == NSGraphiteControlTint;
- break;
- case eIntID_MacLionTheme:
- aResult = 1;
- break;
- case eIntID_MacYosemiteTheme:
- aResult = nsCocoaFeatures::OnYosemiteOrLater();
- break;
- case eIntID_AlertNotificationOrigin:
- aResult = NS_ALERT_TOP;
- break;
- case eIntID_TabFocusModel:
- aResult = [NSApp isFullKeyboardAccessEnabled] ?
- nsIContent::eTabFocus_any : nsIContent::eTabFocus_textControlsMask;
- break;
- case eIntID_ScrollToClick:
- {
- aResult = [[NSUserDefaults standardUserDefaults] boolForKey:@"AppleScrollerPagingBehavior"];
- }
- break;
- case eIntID_ChosenMenuItemsShouldBlink:
- aResult = 1;
- break;
- case eIntID_IMERawInputUnderlineStyle:
- case eIntID_IMEConvertedTextUnderlineStyle:
- case eIntID_IMESelectedRawTextUnderlineStyle:
- case eIntID_IMESelectedConvertedTextUnderline:
- aResult = NS_STYLE_TEXT_DECORATION_STYLE_SOLID;
- break;
- case eIntID_SpellCheckerUnderlineStyle:
- aResult = NS_STYLE_TEXT_DECORATION_STYLE_DOTTED;
- break;
- case eIntID_ScrollbarButtonAutoRepeatBehavior:
- aResult = 0;
- break;
- case eIntID_SwipeAnimationEnabled:
- aResult = 0;
- if ([NSEvent respondsToSelector:@selector(
- isSwipeTrackingFromScrollEventsEnabled)]) {
- aResult = [NSEvent isSwipeTrackingFromScrollEventsEnabled] ? 1 : 0;
- }
- break;
- case eIntID_ColorPickerAvailable:
- aResult = 1;
- break;
- case eIntID_ContextMenuOffsetVertical:
- aResult = -6;
- break;
- case eIntID_ContextMenuOffsetHorizontal:
- aResult = 1;
- break;
- default:
- aResult = 0;
- res = NS_ERROR_FAILURE;
- }
- return res;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-nsresult
-nsLookAndFeel::GetFloatImpl(FloatID aID, float &aResult)
-{
- nsresult res = nsXPLookAndFeel::GetFloatImpl(aID, aResult);
- if (NS_SUCCEEDED(res))
- return res;
- res = NS_OK;
-
- switch (aID) {
- case eFloatID_IMEUnderlineRelativeSize:
- aResult = 2.0f;
- break;
- case eFloatID_SpellCheckerUnderlineRelativeSize:
- aResult = 2.0f;
- break;
- default:
- aResult = -1.0;
- res = NS_ERROR_FAILURE;
- }
-
- return res;
-}
-
-bool nsLookAndFeel::UseOverlayScrollbars()
-{
- return GetInt(eIntID_UseOverlayScrollbars) != 0;
-}
-
-bool nsLookAndFeel::SystemWantsOverlayScrollbars()
-{
- return ([NSScroller respondsToSelector:@selector(preferredScrollerStyle)] &&
- [NSScroller preferredScrollerStyle] == mozNSScrollerStyleOverlay);
-}
-
-bool nsLookAndFeel::AllowOverlayScrollbarsOverlap()
-{
- return (UseOverlayScrollbars());
-}
-
-bool
-nsLookAndFeel::GetFontImpl(FontID aID, nsString &aFontName,
- gfxFontStyle &aFontStyle,
- float aDevPixPerCSSPixel)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
-
- // hack for now
- if (aID == eFont_Window || aID == eFont_Document) {
- aFontStyle.style = NS_FONT_STYLE_NORMAL;
- aFontStyle.weight = NS_FONT_WEIGHT_NORMAL;
- aFontStyle.stretch = NS_FONT_STRETCH_NORMAL;
- aFontStyle.size = 14 * aDevPixPerCSSPixel;
- aFontStyle.systemFont = true;
-
- aFontName.AssignLiteral("sans-serif");
- return true;
- }
-
- gfxPlatformMac::LookupSystemFont(aID, aFontName, aFontStyle,
- aDevPixPerCSSPixel);
-
- return true;
-
- NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
-}
-
-nsTArray<LookAndFeelInt>
-nsLookAndFeel::GetIntCacheImpl()
-{
- nsTArray<LookAndFeelInt> lookAndFeelIntCache =
- nsXPLookAndFeel::GetIntCacheImpl();
-
- LookAndFeelInt useOverlayScrollbars;
- useOverlayScrollbars.id = eIntID_UseOverlayScrollbars;
- useOverlayScrollbars.value = GetInt(eIntID_UseOverlayScrollbars);
- lookAndFeelIntCache.AppendElement(useOverlayScrollbars);
-
- LookAndFeelInt allowOverlayScrollbarsOverlap;
- allowOverlayScrollbarsOverlap.id = eIntID_AllowOverlayScrollbarsOverlap;
- allowOverlayScrollbarsOverlap.value = GetInt(eIntID_AllowOverlayScrollbarsOverlap);
- lookAndFeelIntCache.AppendElement(allowOverlayScrollbarsOverlap);
-
- return lookAndFeelIntCache;
-}
-
-void
-nsLookAndFeel::SetIntCacheImpl(const nsTArray<LookAndFeelInt>& aLookAndFeelIntCache)
-{
- for (auto entry : aLookAndFeelIntCache) {
- switch(entry.id) {
- case eIntID_UseOverlayScrollbars:
- mUseOverlayScrollbars = entry.value;
- mUseOverlayScrollbarsCached = true;
- break;
- case eIntID_AllowOverlayScrollbarsOverlap:
- mAllowOverlayScrollbarsOverlap = entry.value;
- mAllowOverlayScrollbarsOverlapCached = true;
- break;
- }
- }
-}
-
-void
-nsLookAndFeel::RefreshImpl()
-{
- // We should only clear the cache if we're in the main browser process.
- // Otherwise, we should wait for the parent to inform us of new values
- // to cache via LookAndFeel::SetIntCache.
- if (XRE_IsParentProcess()) {
- mUseOverlayScrollbarsCached = false;
- mAllowOverlayScrollbarsOverlapCached = false;
- }
-}
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 <Cocoa/Cocoa.h>
-#import "nsIWidget.h"
-
-/*! @class nsMacCursor
- @abstract Represents a native Mac cursor.
- @discussion <code>nsMacCursor</code> 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 <code>NSCursor</code>.
- @discussion Creates a cursor representing the given Cocoa built-in cursor.
- @param aCursor the <code>NSCursor</code> to use
- @param aType the corresponding <code>nsCursor</code> constant
- @result an autoreleased instance of <code>nsMacCursor</code> representing the given <code>NSCursor</code>
- */
-+ (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 <code>+[NSImage imageNamed:]</code> method.
- <p>The image must be compatible with any restrictions laid down by <code>NSCursor</code>. These vary
- by operating system version.</p>
- <p>The hotspot precisely determines the point where the user clicks when using the cursor.</p>
- @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 <code>nsCursor</code> constant
- @result an autoreleased instance of <code>nsMacCursor</code> 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 <code>NSCursor</code>
- @param aCursorFrames an array of <code>NSCursor</code>, representing the frames of an animated cursor, in the
- order they should be played.
- @param aType the corresponding <code>nsCursor</code> constant
- @result an autoreleased instance of <code>nsMacCursor</code> 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 <code>nsMacCursor</code> 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 <code>nsCursor</code> 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 <code>nsMacCursor</code> 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 <code>NSTimer</code> 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 <code>NSTimer</code> instance associated with this cursor.
- */
-- (void) destroyTimer;
-/*! @method destroyTimer
- @abstract Destroy any timer instance associated with this cursor.
- @discussion Invalidates and releases any <code>NSTimer</code> 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 <code>0</code> to <code>-[nsMacCursor numFrames] - 1</code>. 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 <code>nsMacCursor</code> that uses Cocoa <code>NSCursor</code> instances.
- @discussion Displays a static or animated cursor, using Cocoa <code>NSCursor</code> instances. These can be either
- built-in <code>NSCursor</code> instances, or custom <code>NSCursor</code>s created from images.
- When more than one <code>NSCursor</code> 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 <code>NSCursor</code>
- @param aCursorFrames an array of <code>NSCursor</code>, representing the frames of an animated cursor, in the
- order they should be played.
- @param aType the corresponding <code>nsCursor</code> constant
- @result an instance of <code>nsCocoaCursor</code> that will animate the given cursor frames
- */
-- (id) initWithFrames: (NSArray *) aCursorFrames type: (nsCursor) aType;
-
-/*! @method initWithCursor:
- @abstract Create a cursor by specifying a Cocoa <code>NSCursor</code>.
- @discussion Creates a cursor representing the given Cocoa built-in cursor.
- @param aCursor the <code>NSCursor</code> to use
- @param aType the corresponding <code>nsCursor</code> constant
- @result an instance of <code>nsCocoaCursor</code> representing the given <code>NSCursor</code>
-*/
-- (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 <code>+[NSImage imageNamed:]</code> method.
- <p>The image must be compatible with any restrictions laid down by <code>NSCursor</code>. These vary
- by operating system version.</p>
- <p>The hotspot precisely determines the point where the user clicks when using the cursor.</p>
- @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 <code>nsCursor</code> constant
- @result an instance of <code>nsCocoaCursor</code> 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<nsIFile> 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<nsIStandaloneNativeMenu> mDockMenu;
- nsString mBadgeText;
-
- NSImage *mAppIcon, *mProgressBackground;
-
- HIRect mProgressBounds;
- nsTaskbarProgressState mProgressState;
- double mProgressFraction;
- nsCOMPtr<nsITimer> mProgressTimer;
- RefPtr<nsNativeThemeCocoa> 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 <Cocoa/Cocoa.h>
-
-#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<nsIStandaloneNativeMenu> 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<const unichar*>(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<nsMacDockSupport*>(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 <Cocoa/Cocoa.h>
-
-#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<const unichar*>(((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<const unichar*>(((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<nsITrashAppCallback> callback = aCallback;
-
- NSString* tempString = [NSString stringWithCharacters:reinterpret_cast<const unichar*>(((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 <Cocoa/Cocoa.h>
-
-#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<nsIContent> mAboutItemContent;
- nsCOMPtr<nsIContent> mPrefItemContent;
- nsCOMPtr<nsIContent> 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<mozilla::UniquePtr<nsMenuX>> 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 <objc/objc-runtime.h>
-
-#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<nsMenuBarX> 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<nsCocoaWindow*>(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<nsIStringBundle> stringBundle;
-
- nsCOMPtr<nsIStringBundleService> 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<const unichar*>(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<nsMenuX*>(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<nsIDOMDocument> domDoc(do_QueryInterface(sLastGeckoMenuBarPainted->mContent->OwnerDoc()));
- if (!domDoc)
- return 0;
-
- NS_ConvertASCIItoUTF16 shortcutIDStr((const char *)shortcutID);
- nsCOMPtr<nsIDOMElement> shortcutElement;
- domDoc->GetElementById(shortcutIDStr, getter_AddRefs(shortcutElement));
- nsCOMPtr<nsIContent> 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<nsIDOMElement> menuItem;
- inDoc->GetElementById(inID, getter_AddRefs(menuItem));
- nsCOMPtr<nsIContent> 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<nsIDOMDocument> 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<nsIDocument> doc = inMenu->Content()->GetUncomposedDoc();
- if (!doc) {
- return nil;
- }
-
- nsCOMPtr<nsIDOMDocument> domdoc(do_QueryInterface(doc));
- if (!domdoc) {
- return nil;
- }
-
- // Get information from the gecko menu item
- nsAutoString label;
- nsAutoString modifiers;
- nsAutoString key;
- nsCOMPtr<nsIDOMElement> 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<nsIDOMElement> keyElement;
- domdoc->GetElementById(key, getter_AddRefs(keyElement));
- if (keyElement) {
- nsCOMPtr<nsIContent> 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<const unichar*>(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<const unichar*>(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:
-
- <menuitem id="menu_preferences"
- label="&preferencesCmdMac.label;"
- key="open_prefs_key"/>
-
- 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<nsMenuBarX*>(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<nsIAppStartup> 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<uint32_t>(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 <Foundation/Foundation.h>
-
-#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<nsIContent> 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 <Cocoa/Cocoa.h>
-
-#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<nsPtrHashKey<nsIContent>, nsChangeObserver *> mContentToObserverTable;
-
- // stores mapping of command IDs to menu objects
- nsDataHashtable<nsUint32HashKey, nsMenuItemX *> 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<nsIMutationObserver> 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<nsIMutationObserver> 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<nsIContent> 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<nsIMutationObserver> 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<nsIContent> 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 <Cocoa/Cocoa.h>
-
-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<nsIContent> mContent;
- RefPtr<imgRequestProxy> 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 <limits> to get the libstdc++ version. */
-#include <limits>
-#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<nsIURI> 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<nsIDOMCSSPrimitiveValue> 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<nsMenuItemX*>(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<nsIDOMCSSValue> cssValue;
- nsCOMPtr<nsICSSDeclaration> cssStyleDecl;
- nsCOMPtr<nsIDOMCSSPrimitiveValue> primitiveValue;
- uint16_t primitiveType;
- if (!hasImageAttr) {
- // If the content node has no "image" attribute, get the
- // "list-style-image" property from CSS.
- nsCOMPtr<nsIDocument> document = mContent->GetComposedDoc();
- if (!document)
- return NS_ERROR_FAILURE;
-
- nsCOMPtr<nsPIDOMWindowInner> window = document->GetInnerWindow();
- if (!window)
- return NS_ERROR_FAILURE;
-
- nsCOMPtr<Element> 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<nsIURI> 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<nsIDOMRect> 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<nsIDocument> document = mContent->OwnerDoc();
-
- nsCOMPtr<nsILoadGroup> loadGroup = document->GetDocumentLoadGroup();
- if (!loadGroup) return NS_ERROR_FAILURE;
-
- RefPtr<imgLoader> 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<imgIContainer> 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<imgIContainer> 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<SourceSurface> 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 <Cocoa/Cocoa.h>
-
-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<nsIContent> mCommandContent;
- // The icon object should never outlive its creating nsMenuItemX object.
- RefPtr<nsMenuItemIconX> 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<nsIDocument> parentDoc = mContent->OwnerDoc();
-
- // get interface for creating DOM events from content owner document
- nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(parentDoc);
- if (!domDoc) {
- NS_WARNING("Failed to QI parent nsIDocument to nsIDOMDocument");
- return NS_ERROR_FAILURE;
- }
-
- // create DOM event
- nsCOMPtr<nsIDOMEvent> 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<nsIContent> 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 <Cocoa/Cocoa.h>
-
-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<dom::Event> event =
- doc->CreateEvent(NS_LITERAL_STRING("xulcommandevent"), rv);
- nsCOMPtr<nsIDOMXULCommandEvent> 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<const unichar*>(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<nsCocoaWindow*>(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<nsMenuBarX*>(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<nsMenuX*>(aParent);
- else
- menuParent = static_cast<nsStandaloneNativeMenu*>(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<nsMenuX*>(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 <Cocoa/Cocoa.h>
-
-#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<nsMenuX> aMenu);
- void LoadMenuItem(nsIContent* inMenuItemContent);
- void LoadSubMenu(nsIContent* inMenuContent);
- GeckoNSMenu* CreateMenuWithGeckoString(nsString& menuTitle);
-
- nsTArray<mozilla::UniquePtr<nsMenuObjectX>> mMenuObjectsArray;
- nsString mLabel;
- uint32_t mVisibleItemsCount; // cache
- nsMenuObjectX* mParent; // [weak]
- nsMenuGroupOwnerX* mMenuGroupOwner; // [weak]
- // The icon object should never outlive its creating nsMenuX object.
- RefPtr<nsMenuItemIconX> 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 <dlfcn.h>
-
-#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<nsMenuX> 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<nsIContent> 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<nsIContent> 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<nsIContent> 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<nsIXPConnect> 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<nsMenuX>();
- 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<nsIContent> 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<nsIContent> 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<nsIAtom> 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<nsIAtom> 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<nsMenuX*>(mParent)->SetRebuild(true);
- }
- else if (parentType == eStandaloneNativeMenuObjectType) {
- static_cast<nsStandaloneNativeMenu*>(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<nsMenuBarX*>(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<nsMenuItemX*>(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<nsIWidget> 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 <Carbon/Carbon.h>
-#import <Cocoa/Cocoa.h>
-
-#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 <algorithm>
-
-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<HTMLMeterElement*>(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<ThemeMenuType>(kThemeMenuTypeInactive) :
- static_cast<ThemeMenuType>(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<ThemeMenuState>(kThemeMenuDisabled) :
- isSelected ?
- static_cast<ThemeMenuState>(kThemeMenuSelected) :
- static_cast<ThemeMenuState>(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 <Cocoa/Cocoa.h>
-
-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 <Cocoa/Cocoa.h>
-
-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 <NSPrintPanelAccessorizing>
-
-- (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 <Cocoa/Cocoa.h>
-#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<nsPrintSettingsX> settingsX(do_QueryObject(aSettings));
- if (!settingsX)
- return NS_ERROR_FAILURE;
-
- nsCOMPtr<nsIPrintSettingsService> 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<const UniChar*>(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<nsPrintSettingsX> 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<nsIStringBundleService> 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<nsPrintSettingsX> 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<nsPrintSettingsX> 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<nsPrintSettingsX> 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<nsPrintSettingsX> 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 <Cocoa/Cocoa.h>
-
-#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<nsPrintSettingsX*>(aPS);
- if (!printSettingsX)
- return NS_ERROR_UNEXPECTED;
- *this = *printSettingsX;
- return NS_OK;
-}
-
-PMPrintSettings
-nsPrintSettingsX::GetPMPrintSettings()
-{
- return static_cast<PMPrintSettings>([mPrintInfo PMPrintSettings]);
-}
-
-PMPrintSession
-nsPrintSettingsX::GetPMPrintSession()
-{
- return static_cast<PMPrintSession>([mPrintInfo PMPrintSession]);
-}
-
-PMPageFormat
-nsPrintSettingsX::GetPMPageFormat()
-{
- return static_cast<PMPageFormat>([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 <stdint.h>
-
-// 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 <unistd.h>
-#include <time.h>
-#include <asl.h>
-#include <dispatch/dispatch.h>
-#include <notify.h>
-#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 <Cocoa/Cocoa.h>
-
-#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 <Cocoa/Cocoa.h>
-
-#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<nsScreenCocoa> > 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<nsScreenCocoa> 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<NSWindow*>(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 <Cocoa/Cocoa.h>
-
-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<nsIURI> uri(do_QueryInterface(aURL));
- nsCOMPtr<nsIStreamLoader> 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<const unichar*>(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 <Cocoa/Cocoa.h>
-
-#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<nsIContent> 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<nsMenuX*>(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<const unichar*>(indexString.BeginReading())
- length:indexString.Length()];
- NSMenu * menu = static_cast<NSMenu *> (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<const unichar*>(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<nsMenuX*>(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<nsStandaloneNativeMenu> mMenu;
- NSStatusItem* mStatusItem;
- };
-
- nsClassHashtable<nsISupportsHashKey, StatusItem> 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 <Cocoa/Cocoa.h>
-
-#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<nsStandaloneNativeMenu> menu = new nsStandaloneNativeMenu();
- nsresult rv = menu->Init(aDOMElement);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- nsCOMPtr<nsISupports> 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<void**>(&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 <Carbon/Carbon.h>
-#import <Cocoa/Cocoa.h>
-#import <objc/Object.h>
-#import <IOKit/IOKitLib.h>
-
-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 <ctype.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include <mach/mach_port.h>
-#include <mach/mach_interface.h>
-#include <mach/mach_init.h>
-
-extern "C" {
-#include <mach-o/getsect.h>
-}
-#include <unistd.h>
-#include <dlfcn.h>
-
-#import <Cocoa/Cocoa.h>
-#import <IOKit/pwr_mgt/IOPMLib.h>
-#import <IOKit/IOMessage.h>
-
-#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<nsIObserverService> 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, &notifyPortRef, 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<nsIWidget> 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 <Cocoa/Cocoa.h>
-
-// 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 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>IBDocumentLocation</key>
- <string>159 127 356 240 0 0 1920 1178 </string>
- <key>IBEditorPositions</key>
- <dict>
- <key>29</key>
- <string>413 971 130 44 0 0 1920 1178 </string>
- </dict>
- <key>IBFramework Version</key>
- <string>443.0</string>
- <key>IBOpenObjects</key>
- <array>
- <integer>29</integer>
- </array>
- <key>IBSystem Version</key>
- <string>8F46</string>
-</dict>
-</plist>
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
--- a/widget/cocoa/resources/MainMenu.nib/keyedobjects.nib
+++ /dev/null
Binary files 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<GfxDriverInfo>&
-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<GfxDriverInfo>& 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<GfxDriverInfo>& aDriverInfo,
- OperatingSystem* aOS = nullptr);
- virtual const nsTArray<GfxDriverInfo>& 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 <Foundation/NSAutoreleasePool.h>
-#include <CoreFoundation/CFRunLoop.h>
-#include <UIKit/UIWindow.h>
-
-@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 <UIKit/UIApplication.h>
-#import <UIKit/UIScreen.h>
-#import <UIKit/UIWindow.h>
-#import <UIKit/UIViewController.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 "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 <UIApplicationDelegate> {
-}
-@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<nsAppShell*> (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 <UIKit/UIColor.h>
-#import <UIKit/UIInterface.h>
-
-#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<nsIScreen> 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 <UIKit/UIScreen.h>
-
-#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<Configuration>& 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<nsWindow*> mChildren;
- nsWindow* mParent;
- InputContext mInputContext;
-
- void OnSizeChanged(const mozilla::gfx::IntSize& aSize);
-
- static void DumpWindows();
- static void DumpWindows(const nsTArray<nsWindow*>& 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 <UIKit/UIEvent.h>
-#import <UIKit/UIGraphics.h>
-#import <UIKit/UIInterface.h>
-#import <UIKit/UIScreen.h>
-#import <UIKit/UITapGestureRecognizer.h>
-#import <UIKit/UITouch.h>
-#import <UIKit/UIView.h>
-#import <UIKit/UIViewController.h>
-#import <UIKit/UIWindow.h>
-#import <QuartzCore/QuartzCore.h>
-
-#include <algorithm>
-
-#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<int>(value);
- RefPtr<Touch> 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<gfxQuartzSurface> targetSurface;
-
- RefPtr<gfxContext> 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<gfx::DrawTarget> 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<nsIWidget::Configuration>& 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<int32_t>(mSizeMode)) {
- return;
- }
-
- mSizeMode = static_cast<nsSizeMode>(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<nsIWidget> 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;
-}