summaryrefslogtreecommitdiff
path: root/layout
diff options
context:
space:
mode:
authorMoonchild <moonchild@palemoon.org>2022-04-29 07:20:46 +0000
committerMoonchild <moonchild@palemoon.org>2022-04-29 07:20:46 +0000
commitbc2841f9f916b2a6aade0cd6dae4a2e4407352b6 (patch)
treee8314f3d55f136a6db6bb9e2a035ae68a04dc3e9 /layout
parent33523f5d5ed0c3b8000aae21a50a56c238422db3 (diff)
parentd78e03d528ba9e7395160a23bce23726067600dd (diff)
downloaduxp-bc2841f9f916b2a6aade0cd6dae4a2e4407352b6.tar.gz
Merge pull request 'Restore Mac OS X code and buildability' (#1886) from dbsoft/UXP:1829 into master
Reviewed-on: https://repo.palemoon.org/MoonchildProductions/UXP/pulls/1886
Diffstat (limited to 'layout')
-rw-r--r--layout/base/nsCSSFrameConstructor.cpp32
-rw-r--r--layout/base/nsCSSFrameConstructor.h4
-rw-r--r--layout/base/nsPresContext.cpp14
-rw-r--r--layout/base/nsPresShell.cpp2
-rw-r--r--layout/build/moz.build4
-rw-r--r--layout/forms/nsListControlFrame.cpp14
-rw-r--r--layout/generic/nsFrame.cpp10
-rw-r--r--layout/generic/nsPluginFrame.cpp127
-rw-r--r--layout/generic/nsSelection.cpp18
-rw-r--r--layout/printing/nsPrintEngine.cpp5
-rw-r--r--layout/reftests/reftest.list3
-rw-r--r--layout/style/nsComputedDOMStyle.cpp9
-rw-r--r--layout/style/res/forms.css6
-rw-r--r--layout/xul/nsButtonBoxFrame.cpp3
-rw-r--r--layout/xul/nsMenuBarListener.cpp12
-rw-r--r--layout/xul/nsMenuFrame.cpp16
-rw-r--r--layout/xul/nsMenuPopupFrame.cpp11
-rw-r--r--layout/xul/nsRepeatService.h4
-rw-r--r--layout/xul/nsSliderFrame.cpp12
-rw-r--r--layout/xul/nsXULPopupManager.cpp28
-rw-r--r--layout/xul/tree/nsTreeBodyFrame.cpp53
21 files changed, 376 insertions, 11 deletions
diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp
index 5b514a330b..8b91e38e8f 100644
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -55,6 +55,9 @@
#include "nsXBLBinding.h"
#include "nsContentUtils.h"
#include "nsIScriptError.h"
+#ifdef XP_MACOSX
+#include "nsIDocShell.h"
+#endif
#include "ChildIterator.h"
#include "nsError.h"
#include "nsLayoutUtils.h"
@@ -4298,7 +4301,11 @@ nsCSSFrameConstructor::FindXULTagData(Element* aElement,
SIMPLE_XUL_CREATE(menu, NS_NewMenuFrame),
SIMPLE_XUL_CREATE(menubutton, NS_NewMenuFrame),
SIMPLE_XUL_CREATE(menuitem, NS_NewMenuItemFrame),
+#ifdef XP_MACOSX
+ SIMPLE_TAG_CHAIN(menubar, nsCSSFrameConstructor::FindXULMenubarData),
+#else
SIMPLE_XUL_CREATE(menubar, NS_NewMenuBarFrame),
+#endif /* XP_MACOSX */
SIMPLE_TAG_CHAIN(popupgroup, nsCSSFrameConstructor::FindPopupGroupData),
SIMPLE_XUL_CREATE(iframe, NS_NewSubDocumentFrame),
SIMPLE_XUL_CREATE(editor, NS_NewSubDocumentFrame),
@@ -4371,6 +4378,31 @@ nsCSSFrameConstructor::FindXULDescriptionData(Element* aElement,
return &sDescriptionData;
}
+#ifdef XP_MACOSX
+/* static */
+const nsCSSFrameConstructor::FrameConstructionData*
+nsCSSFrameConstructor::FindXULMenubarData(Element* aElement,
+ nsStyleContext* aStyleContext)
+{
+ nsCOMPtr<nsIDocShell> treeItem =
+ aStyleContext->PresContext()->GetDocShell();
+ if (treeItem && nsIDocShellTreeItem::typeChrome == treeItem->ItemType()) {
+ nsCOMPtr<nsIDocShellTreeItem> parent;
+ treeItem->GetParent(getter_AddRefs(parent));
+ if (!parent) {
+ // This is the root. Suppress the menubar, since on Mac
+ // window menus are not attached to the window.
+ static const FrameConstructionData sSuppressData = SUPPRESS_FCDATA();
+ return &sSuppressData;
+ }
+ }
+
+ static const FrameConstructionData sMenubarData =
+ SIMPLE_XUL_FCDATA(NS_NewMenuBarFrame);
+ return &sMenubarData;
+}
+#endif /* XP_MACOSX */
+
/* static */
const nsCSSFrameConstructor::FrameConstructionData*
nsCSSFrameConstructor::FindXULListBoxBodyData(Element* aElement,
diff --git a/layout/base/nsCSSFrameConstructor.h b/layout/base/nsCSSFrameConstructor.h
index 738ac82eca..c4f94ceccd 100644
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -1468,6 +1468,10 @@ private:
FindXULLabelData(Element* aElement, nsStyleContext* aStyleContext);
static const FrameConstructionData*
FindXULDescriptionData(Element* aElement, nsStyleContext* aStyleContext);
+#ifdef XP_MACOSX
+ static const FrameConstructionData*
+ FindXULMenubarData(Element* aElement, nsStyleContext* aStyleContext);
+#endif /* XP_MACOSX */
static const FrameConstructionData*
FindXULListBoxBodyData(Element* aElement, nsStyleContext* aStyleContext);
static const FrameConstructionData*
diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp
index 8f3de7f78d..f7be42b5ff 100644
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -2895,9 +2895,15 @@ nsRootPresContext::ComputePluginGeometryUpdates(nsIFrame* aFrame,
aList->ComputeVisibilityForRoot(aBuilder, &region);
}
+#ifdef XP_MACOSX
+ // We control painting of Mac plugins, so just apply geometry updates now.
+ // This is not happening during a paint event.
+ ApplyPluginGeometryUpdates();
+#else
if (XRE_IsParentProcess()) {
InitApplyPluginGeometryTimer();
}
+#endif
}
static void
@@ -2933,6 +2939,8 @@ nsRootPresContext::CancelApplyPluginGeometryTimer()
}
}
+#ifndef XP_MACOSX
+
static bool
HasOverlap(const LayoutDeviceIntPoint& aOffset1,
const nsTArray<LayoutDeviceIntRect>& aClipRects1,
@@ -3017,6 +3025,8 @@ PluginGetGeometryUpdate(nsTHashtable<nsRefPtrHashKey<nsIContent>>& aPlugins,
}
}
+#endif // #ifndef XP_MACOSX
+
static void
PluginDidSetGeometry(nsTHashtable<nsRefPtrHashKey<nsIContent>>& aPlugins)
{
@@ -3033,6 +3043,7 @@ PluginDidSetGeometry(nsTHashtable<nsRefPtrHashKey<nsIContent>>& aPlugins)
void
nsRootPresContext::ApplyPluginGeometryUpdates()
{
+#ifndef XP_MACOSX
CancelApplyPluginGeometryTimer();
nsTArray<nsIWidget::Configuration> configurations;
@@ -3044,6 +3055,7 @@ nsRootPresContext::ApplyPluginGeometryUpdates()
SortConfigurations(&configurations);
widget->ConfigureChildren(configurations);
}
+#endif // #ifndef XP_MACOSX
PluginDidSetGeometry(mRegisteredPlugins);
}
@@ -3051,6 +3063,7 @@ nsRootPresContext::ApplyPluginGeometryUpdates()
void
nsRootPresContext::CollectPluginGeometryUpdates(LayerManager* aLayerManager)
{
+#ifndef XP_MACOSX
// Collect and pass plugin widget configurations down to the compositor
// for transmission to the chrome process.
NS_ASSERTION(aLayerManager, "layer manager is invalid!");
@@ -3073,6 +3086,7 @@ nsRootPresContext::CollectPluginGeometryUpdates(LayerManager* aLayerManager)
clm->StorePluginWidgetConfigurations(configurations);
}
PluginDidSetGeometry(mRegisteredPlugins);
+#endif // #ifndef XP_MACOSX
}
static void
diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp
index eeb059f278..23876cc112 100644
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -8724,7 +8724,9 @@ PresShell::WillPaintWindow()
return;
}
+#ifndef XP_MACOSX
rootPresContext->ApplyPluginGeometryUpdates();
+#endif
}
void
diff --git a/layout/build/moz.build b/layout/build/moz.build
index 3e76edc491..d7996af8d9 100644
--- a/layout/build/moz.build
+++ b/layout/build/moz.build
@@ -63,6 +63,10 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
LOCAL_INCLUDES += [
'/dom/system/windows',
]
+elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
+ LOCAL_INCLUDES += [
+ '/dom/system/mac',
+ ]
elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
LOCAL_INCLUDES += [
'/widget/gtk',
diff --git a/layout/forms/nsListControlFrame.cpp b/layout/forms/nsListControlFrame.cpp
index 50e05776ef..5e157b7842 100644
--- a/layout/forms/nsListControlFrame.cpp
+++ b/layout/forms/nsListControlFrame.cpp
@@ -834,7 +834,11 @@ nsListControlFrame::HandleListSelection(nsIDOMEvent* aEvent,
nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aEvent);
bool isShift;
bool isControl;
+#ifdef XP_MACOSX
+ mouseEvent->GetMetaKey(&isControl);
+#else
mouseEvent->GetCtrlKey(&isControl);
+#endif
mouseEvent->GetShiftKey(&isShift);
return PerformSelection(aClickedIndex, isShift, isControl); // might destroy us
}
@@ -1904,7 +1908,11 @@ nsListControlFrame::DragMove(nsIDOMEvent* aMouseEvent)
nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aMouseEvent);
NS_ASSERTION(mouseEvent, "aMouseEvent is not an nsIDOMMouseEvent!");
bool isControl;
+#ifdef XP_MACOSX
+ mouseEvent->GetMetaKey(&isControl);
+#else
mouseEvent->GetCtrlKey(&isControl);
+#endif
nsWeakFrame weakFrame(this);
// Turn SHIFT on when you are dragging, unless control is on.
bool wasChanged = PerformSelection(selectedIndex,
@@ -2112,8 +2120,14 @@ nsListControlFrame::KeyDown(nsIDOMEvent* aKeyEvent)
bool dropDownMenuOnUpDown;
bool dropDownMenuOnSpace;
+#ifdef XP_MACOSX
+ dropDownMenuOnUpDown = IsInDropDownMode() && !mComboboxFrame->IsDroppedDown();
+ dropDownMenuOnSpace = !keyEvent->IsAlt() && !keyEvent->IsControl() &&
+ !keyEvent->IsMeta();
+#else
dropDownMenuOnUpDown = keyEvent->IsAlt();
dropDownMenuOnSpace = IsInDropDownMode() && !mComboboxFrame->IsDroppedDown();
+#endif
bool withinIncrementalSearchTime =
keyEvent->mTime - gLastKeyTime <= INCREMENTAL_SEARCH_KEYPRESS_TIME;
if ((dropDownMenuOnUpDown &&
diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp
index af3d2f9457..7e819ddf3b 100644
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -3055,7 +3055,11 @@ nsFrame::GetDataForTableSelection(const nsFrameSelection* aFrameSelection,
{
// In Browser, special 'table selection' key must be pressed for table selection
// or when just Shift is pressed and we're already in table/cell selection mode
+#ifdef XP_MACOSX
+ doTableSelection = aMouseEvent->IsMeta() || (aMouseEvent->IsShift() && selectingTableCells);
+#else
doTableSelection = aMouseEvent->IsControl() || (aMouseEvent->IsShift() && selectingTableCells);
+#endif
}
if (!doTableSelection)
return NS_OK;
@@ -3324,7 +3328,13 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
if (!frameselection || frameselection->GetDisplaySelection() == nsISelectionController::SELECTION_OFF)
return NS_OK;//nothing to do we cannot affect selection from here
+#ifdef XP_MACOSX
+ if (mouseEvent->IsControl())
+ return NS_OK;//short circuit. hard coded for mac due to time restraints.
+ bool control = mouseEvent->IsMeta();
+#else
bool control = mouseEvent->IsControl();
+#endif
RefPtr<nsFrameSelection> fc = const_cast<nsFrameSelection*>(frameselection);
if (mouseEvent->mClickCount > 1) {
diff --git a/layout/generic/nsPluginFrame.cpp b/layout/generic/nsPluginFrame.cpp
index ea42d9bd37..eee3f46b8b 100644
--- a/layout/generic/nsPluginFrame.cpp
+++ b/layout/generic/nsPluginFrame.cpp
@@ -69,6 +69,11 @@
#endif /* MOZ_LOGGING */
#include "mozilla/Logging.h"
+#ifdef XP_MACOSX
+#include "gfxQuartzNativeDrawing.h"
+#include "mozilla/gfx/QuartzSupport.h"
+#endif
+
#ifdef MOZ_X11
#include "mozilla/X11Util.h"
using mozilla::DefaultXDisplay;
@@ -313,6 +318,15 @@ nsPluginFrame::PrepForDrawing(nsIWidget *aWidget)
mInnerView->AttachWidgetEventHandler(mWidget);
+#ifdef XP_MACOSX
+ // On Mac, we need to invalidate ourselves since even windowed
+ // plugins are painted through Thebes and we need to ensure
+ // the PaintedLayer containing the plugin is updated.
+ if (parentWidget == GetNearestWidget()) {
+ InvalidateFrame();
+ }
+#endif
+
RegisterPluginForGeometryUpdates();
// Here we set the background color for this widget because some plugins will use
@@ -551,12 +565,27 @@ nsPluginFrame::FixupWindow(const nsSize& aSize)
nsIntPoint origin = GetWindowOriginInPixels(windowless);
// window must be in "display pixels"
+#if defined(XP_MACOSX)
+ // window must be in "display pixels"
+ double scaleFactor = 1.0;
+ if (NS_FAILED(mInstanceOwner->GetContentsScaleFactor(&scaleFactor))) {
+ scaleFactor = 1.0;
+ }
+ int intScaleFactor = ceil(scaleFactor);
+ window->x = origin.x / intScaleFactor;
+ window->y = origin.y / intScaleFactor;
+ window->width = presContext->AppUnitsToDevPixels(aSize.width) / intScaleFactor;
+ window->height = presContext->AppUnitsToDevPixels(aSize.height) / intScaleFactor;
+#else
window->x = origin.x;
window->y = origin.y;
window->width = presContext->AppUnitsToDevPixels(aSize.width);
window->height = presContext->AppUnitsToDevPixels(aSize.height);
+#endif
+#ifndef XP_MACOSX
mInstanceOwner->UpdateWindowPositionAndClipRect(false);
+#endif
NotifyPluginReflowObservers();
}
@@ -587,6 +616,13 @@ nsPluginFrame::CallSetWindow(bool aCheckIsHidden)
RefPtr<nsPluginInstanceOwner> instanceOwnerRef(mInstanceOwner);
// refresh the plugin port as well
+#ifdef XP_MACOSX
+ mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintEnable);
+ // Bail now if our frame has been destroyed.
+ if (!instanceOwnerRef->GetFrame()) {
+ return NS_ERROR_FAILURE;
+ }
+#endif
window->window = mInstanceOwner->GetPluginPort();
// Adjust plugin dimensions according to pixel snap results
@@ -606,11 +642,24 @@ nsPluginFrame::CallSetWindow(bool aCheckIsHidden)
intBounds.x += intOffset.x;
intBounds.y += intOffset.y;
+#if defined(XP_MACOSX)
+ // window must be in "display pixels"
+ double scaleFactor = 1.0;
+ if (NS_FAILED(instanceOwnerRef->GetContentsScaleFactor(&scaleFactor))) {
+ scaleFactor = 1.0;
+ }
+
+ size_t intScaleFactor = ceil(scaleFactor);
+ window->x = intBounds.x / intScaleFactor;
+ window->y = intBounds.y / intScaleFactor;
+ window->width = intBounds.width / intScaleFactor;
+ window->height = intBounds.height / intScaleFactor;
+#else
window->x = intBounds.x;
window->y = intBounds.y;
window->width = intBounds.width;
window->height = intBounds.height;
-
+#endif
// BE CAREFUL: By the time we get here the PluginFrame is sometimes destroyed
// and poisoned. If we reference local fields (implicit this deref),
// we will crash.
@@ -1012,6 +1061,11 @@ nsPluginFrame::NotifyPluginReflowObservers()
void
nsPluginFrame::DidSetWidgetGeometry()
{
+#if defined(XP_MACOSX)
+ if (mInstanceOwner && !IsHidden()) {
+ mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintEnable);
+ }
+#else
if (!mWidget && mInstanceOwner) {
// UpdateWindowVisibility will notify the plugin of position changes
// by updating the NPWindow and calling NPP_SetWindow/AsyncSetWindow.
@@ -1022,20 +1076,29 @@ nsPluginFrame::DidSetWidgetGeometry()
nsLayoutUtils::IsPopup(nsLayoutUtils::GetDisplayRootFrame(this)) ||
!mNextConfigurationBounds.IsEmpty());
}
+#endif
}
bool
nsPluginFrame::IsOpaque() const
{
+#if defined(XP_MACOSX)
+ return false;
+#else
+
if (mInstanceOwner && mInstanceOwner->UseAsyncRendering()) {
return false;
}
return !IsTransparentMode();
+#endif
}
bool
nsPluginFrame::IsTransparentMode() const
{
+#if defined(XP_MACOSX)
+ return false;
+#else
if (!mInstanceOwner)
return false;
@@ -1057,6 +1120,7 @@ nsPluginFrame::IsTransparentMode() const
bool transparent = false;
pi->IsTransparent(&transparent);
return transparent;
+#endif
}
void
@@ -1077,20 +1141,27 @@ nsPluginFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
DO_GLOBAL_REFLOW_COUNT_DSP("nsPluginFrame");
+#ifndef XP_MACOSX
if (mWidget && aBuilder->IsInTransform()) {
// Windowed plugins should not be rendered inside a transform.
return;
}
+#endif
if (aBuilder->IsForPainting() && mInstanceOwner) {
// Update plugin frame for both content scaling and full zoom changes.
mInstanceOwner->ResolutionMayHaveChanged();
+#ifdef XP_MACOSX
+ mInstanceOwner->WindowFocusMayHaveChanged();
+#endif
if (mInstanceOwner->UseAsyncRendering()) {
NPWindow* window = nullptr;
mInstanceOwner->GetWindow(window);
bool isVisible = window && window->width > 0 && window->height > 0;
if (isVisible && aBuilder->ShouldSyncDecodeImages()) {
+#ifndef XP_MACOSX
mInstanceOwner->UpdateWindowVisibility(true);
+#endif
}
mInstanceOwner->NotifyPaintWaiter(aBuilder);
@@ -1167,8 +1238,8 @@ nsPluginFrame::PrintPlugin(nsRenderingContext& aRenderingContext,
window.clipRect.left = 0; window.clipRect.right = 0;
// platform specific printing code
-#if defined(XP_UNIX)
- // Doesn't work in a thebes world.
+#if defined(XP_UNIX) || defined(XP_MACOSX)
+ // Doesn't work in a thebes world, or on OS X.
(void)window;
(void)npprint;
#elif defined(XP_WIN)
@@ -1306,7 +1377,20 @@ nsPluginFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
if (window->width <= 0 || window->height <= 0)
return nullptr;
- IntSize size(window->width, window->height);
+#if defined(XP_MACOSX)
+ // window is in "display pixels", but size needs to be in device pixels
+ // window must be in "display pixels"
+ double scaleFactor = 1.0;
+ if (NS_FAILED(mInstanceOwner->GetContentsScaleFactor(&scaleFactor))) {
+ scaleFactor = 1.0;
+ }
+
+ size_t intScaleFactor = ceil(scaleFactor);
+#else
+ size_t intScaleFactor = 1;
+#endif
+
+ IntSize size(window->width * intScaleFactor, window->height * intScaleFactor);
nsRect area = GetContentRectRelativeToSelf() + aItem->ToReferenceFrame();
gfxRect r = nsLayoutUtils::RectToGfxRect(area, PresContext()->AppUnitsPerDevPixel());
@@ -1336,6 +1420,11 @@ nsPluginFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
NS_ASSERTION(layer->GetType() == Layer::TYPE_IMAGE, "Bad layer type");
ImageLayer* imglayer = static_cast<ImageLayer*>(layer.get());
+#ifdef XP_MACOSX
+ if (!mInstanceOwner->UseAsyncRendering()) {
+ mInstanceOwner->DoCocoaEventDrawRect(r, nullptr);
+ }
+#endif
imglayer->SetScaleToSize(size, ScaleMode::STRETCH);
imglayer->SetContainer(container);
@@ -1456,11 +1545,37 @@ nsPluginFrame::HandleEvent(nsPresContext* aPresContext,
return rv;
#endif
+#ifdef XP_MACOSX
+ // we want to process some native mouse events in the cocoa event model
+ if ((anEvent->mMessage == eMouseEnterIntoWidget ||
+ anEvent->mMessage == eWheel) &&
+ mInstanceOwner->GetEventModel() == NPEventModelCocoa) {
+ *anEventStatus = mInstanceOwner->ProcessEvent(*anEvent);
+ // Due to plugin code reentering Gecko, this frame may be dead at this
+ // point.
+ return rv;
+ }
+
+ // These two calls to nsIPresShell::SetCapturingContext() (on mouse-down
+ // and mouse-up) are needed to make the routing of mouse events while
+ // dragging conform to standard OS X practice, and to the Cocoa NPAPI spec.
+ // See bug 525078 and bug 909678.
+ if (anEvent->mMessage == eMouseDown) {
+ nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED);
+ }
+#endif
+
rv = nsFrame::HandleEvent(aPresContext, anEvent, anEventStatus);
// We need to be careful from this point because the call to
// nsFrame::HandleEvent() might have killed us.
+#ifdef XP_MACOSX
+ if (anEvent->mMessage == eMouseUp) {
+ nsIPresShell::SetCapturingContent(nullptr, 0);
+ }
+#endif
+
return rv;
}
@@ -1636,7 +1751,11 @@ NS_NewObjectFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
bool
nsPluginFrame::IsPaintedByGecko() const
{
+#ifdef XP_MACOSX
+ return true;
+#else
return !mWidget;
+#endif
}
NS_IMPL_FRAMEARENA_HELPERS(nsPluginFrame)
diff --git a/layout/generic/nsSelection.cpp b/layout/generic/nsSelection.cpp
index 301d799525..f8a231b00c 100644
--- a/layout/generic/nsSelection.cpp
+++ b/layout/generic/nsSelection.cpp
@@ -551,6 +551,10 @@ nsFrameSelection::nsFrameSelection()
mSelectedCellIndex = 0;
nsAutoCopyListener *autoCopy = nullptr;
+ // On macOS, cache the current selection to send to osx service menu.
+#ifdef XP_MACOSX
+ autoCopy = nsAutoCopyListener::GetInstance(nsIClipboard::kSelectionCache);
+#endif
// Check to see if the autocopy pref is enabled
// and add the autocopy listener if it is
@@ -1973,6 +1977,16 @@ nsFrameSelection::RepaintSelection(SelectionType aSelectionType)
return NS_ERROR_NULL_POINTER;
NS_ENSURE_STATE(mShell);
+// On macOS, update the selection cache to the new active selection
+// aka the current selection.
+#ifdef XP_MACOSX
+ nsFocusManager* fm = nsFocusManager::GetFocusManager();
+ // Check an active window exists otherwise there cannot be a current selection
+ // and that it's a normal selection.
+ if (fm->GetActiveWindow() && aSelectionType == SelectionType::eNormal) {
+ UpdateSelectionCacheOnRepaintSelection(mDomSelections[index]);
+ }
+#endif
return mDomSelections[index]->Repaint(mShell->GetPresContext());
}
@@ -2696,7 +2710,11 @@ printf("aTarget == %d\n", aTarget);
// Any other mouseup actions require that Ctrl or Cmd key is pressed
// else stop table selection mode
bool doMouseUpAction = false;
+#ifdef XP_MACOSX
+ doMouseUpAction = aMouseEvent->IsMeta();
+#else
doMouseUpAction = aMouseEvent->IsControl();
+#endif
if (!doMouseUpAction)
{
#ifdef DEBUG_TABLE_SELECTION
diff --git a/layout/printing/nsPrintEngine.cpp b/layout/printing/nsPrintEngine.cpp
index 23edeb1fe0..d232b669bb 100644
--- a/layout/printing/nsPrintEngine.cpp
+++ b/layout/printing/nsPrintEngine.cpp
@@ -1004,6 +1004,10 @@ nsPrintEngine::GetCurrentPrintSettings(nsIPrintSettings * *aCurrentPrintSettings
nsresult
nsPrintEngine::CheckForPrinters(nsIPrintSettings* aPrintSettings)
{
+#if defined(XP_MACOSX)
+ // Mac doesn't support retrieving a printer list.
+ return NS_OK;
+#else
NS_ENSURE_ARG_POINTER(aPrintSettings);
// See if aPrintSettings already has a printer
@@ -1023,6 +1027,7 @@ nsPrintEngine::CheckForPrinters(nsIPrintSettings* aPrintSettings)
rv = aPrintSettings->SetPrinterName(printerName.get());
}
return rv;
+#endif
}
//----------------------------------------------------------------------
diff --git a/layout/reftests/reftest.list b/layout/reftests/reftest.list
index 15840f38e5..90320cba30 100644
--- a/layout/reftests/reftest.list
+++ b/layout/reftests/reftest.list
@@ -347,6 +347,9 @@ include text-svgglyphs/reftest.list
# text-transform/
include text-transform/reftest.list
+# theme (osx)
+include ../../toolkit/themes/osx/reftests/reftest.list
+
include ../../toolkit/content/tests/reftests/reftest.list
# -moz-transform/
diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp
index b3c4ccc148..65f42805de 100644
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -6647,7 +6647,14 @@ nsComputedDOMStyle::DoGetAnimationIterationCount()
RefPtr<nsROCSSPrimitiveValue> iterationCount = new nsROCSSPrimitiveValue;
float f = animation->GetIterationCount();
- float inf = NS_IEEEPositiveInfinity();
+ /* Need a nasty hack here to work around an optimizer bug in gcc
+ 4.2 on Mac, which somehow gets confused when directly comparing
+ a float to the return value of NS_IEEEPositiveInfinity when
+ building 32-bit builds. */
+#ifdef XP_MACOSX
+ volatile
+#endif
+ float inf = NS_IEEEPositiveInfinity();
if (f == inf) {
iterationCount->SetIdent(eCSSKeyword_infinite);
} else {
diff --git a/layout/style/res/forms.css b/layout/style/res/forms.css
index 281b75d769..db75151d48 100644
--- a/layout/style/res/forms.css
+++ b/layout/style/res/forms.css
@@ -593,11 +593,15 @@ input[type="checkbox"]:disabled:hover:active {
cursor: inherit;
}
+% On Mac, the native theme takes care of this.
+% See nsNativeThemeCocoa::ThemeDrawsFocusForWidget.
+%ifndef XP_MACOSX
input[type="checkbox"]:-moz-focusring,
input[type="radio"]:-moz-focusring {
/* Don't specify the outline-color, we should always use initial value. */
outline: 1px dotted;
}
+%endif
input[type="checkbox"]:hover:active,
input[type="radio"]:hover:active {
@@ -719,10 +723,12 @@ input[type="color"]:-moz-system-metric(color-picker-available):active:hover,
input[type="reset"]:active:hover,
input[type="button"]:active:hover,
input[type="submit"]:active:hover {
+%ifndef XP_MACOSX
padding-block-start: 0px;
padding-inline-end: 5px;
padding-block-end: 0px;
padding-inline-start: 7px;
+%endif
border-style: inset;
background-color: ButtonFace;
}
diff --git a/layout/xul/nsButtonBoxFrame.cpp b/layout/xul/nsButtonBoxFrame.cpp
index 3e0529e600..ba0b7fb2ab 100644
--- a/layout/xul/nsButtonBoxFrame.cpp
+++ b/layout/xul/nsButtonBoxFrame.cpp
@@ -126,6 +126,8 @@ nsButtonBoxFrame::HandleEvent(nsPresContext* aPresContext,
break;
}
+// On mac, Return fires the default button, not the focused one.
+#ifndef XP_MACOSX
case eKeyPress: {
WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
if (!keyEvent) {
@@ -140,6 +142,7 @@ nsButtonBoxFrame::HandleEvent(nsPresContext* aPresContext,
}
break;
}
+#endif
case eKeyUp: {
WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
diff --git a/layout/xul/nsMenuBarListener.cpp b/layout/xul/nsMenuBarListener.cpp
index 70955c4301..23df81937a 100644
--- a/layout/xul/nsMenuBarListener.cpp
+++ b/layout/xul/nsMenuBarListener.cpp
@@ -76,9 +76,15 @@ void nsMenuBarListener::InitAccessKey()
if (mAccessKey >= 0)
return;
- // Compiled-in defaults, in case we can't get LookAndFeel...
+ // Compiled-in defaults, in case we can't get LookAndFeel --
+ // mac doesn't have menu shortcuts, other platforms use alt.
+#ifdef XP_MACOSX
+ mAccessKey = 0;
+ mAccessKeyMask = 0;
+#else
mAccessKey = nsIDOMKeyEvent::DOM_VK_ALT;
mAccessKeyMask = MODIFIER_ALT;
+#endif
// Get the menu access key value from prefs, overriding the default:
mAccessKey = Preferences::GetInt("ui.key.menuAccessKey", mAccessKey);
@@ -248,7 +254,8 @@ nsMenuBarListener::KeyPress(nsIDOMEvent* aKeyEvent)
aKeyEvent->PreventDefault();
}
}
- // Also need to handle F10 specially.
+#ifndef XP_MACOSX
+ // Also need to handle F10 specially on Non-Mac platform.
else if (nativeKeyEvent->mMessage == eKeyPress && keyCode == NS_VK_F10) {
if ((GetModifiersForAccessKey(keyEvent) & ~MODIFIER_CONTROL) == 0) {
// The F10 key just went down by itself or with ctrl pressed.
@@ -266,6 +273,7 @@ nsMenuBarListener::KeyPress(nsIDOMEvent* aKeyEvent)
}
}
}
+#endif // !XP_MACOSX
}
return NS_OK;
diff --git a/layout/xul/nsMenuFrame.cpp b/layout/xul/nsMenuFrame.cpp
index 30cab242ea..933cc43cf3 100644
--- a/layout/xul/nsMenuFrame.cpp
+++ b/layout/xul/nsMenuFrame.cpp
@@ -404,12 +404,26 @@ nsMenuFrame::HandleEvent(nsPresContext* aPresContext,
if (aEvent->mMessage == eKeyPress && !IsDisabled()) {
WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
uint32_t keyCode = keyEvent->mKeyCode;
- // Toggle menulist on unmodified F4 or Alt arrow
+#ifdef XP_MACOSX
+ // On mac, open menulist on either up/down arrow or space (w/o Cmd pressed)
+ if (!IsOpen() && ((keyEvent->mCharCode == ' ' && !keyEvent->IsMeta()) ||
+ (keyCode == NS_VK_UP || keyCode == NS_VK_DOWN))) {
+
+ // When pressing space, don't open the menu if performing an incremental search.
+ if (keyEvent->mCharCode != ' ' ||
+ !nsMenuPopupFrame::IsWithinIncrementalTime(keyEvent->mTime)) {
+ *aEventStatus = nsEventStatus_eConsumeNoDefault;
+ OpenMenu(false);
+ }
+ }
+#else
+ // On other platforms, toggle menulist on unmodified F4 or Alt arrow
if ((keyCode == NS_VK_F4 && !keyEvent->IsAlt()) ||
((keyCode == NS_VK_UP || keyCode == NS_VK_DOWN) && keyEvent->IsAlt())) {
*aEventStatus = nsEventStatus_eConsumeNoDefault;
ToggleMenuState();
}
+#endif
}
else if (aEvent->mMessage == eMouseDown &&
aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton &&
diff --git a/layout/xul/nsMenuPopupFrame.cpp b/layout/xul/nsMenuPopupFrame.cpp
index 1d47652dcb..378d719d44 100644
--- a/layout/xul/nsMenuPopupFrame.cpp
+++ b/layout/xul/nsMenuPopupFrame.cpp
@@ -1502,8 +1502,17 @@ nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame, bool aIsMove, bool aS
screenPoint.MoveBy(margin.left + offsetForContextMenu.x,
margin.top + offsetForContextMenu.y);
- // Screen positioned popups can be flipped vertically but never horizontally
+#ifdef XP_MACOSX
+ // OSX tooltips follow standard flip rule but other popups flip horizontally not vertically
+ if (mPopupType == ePopupTypeTooltip) {
+ vFlip = FlipStyle_Outside;
+ } else {
+ hFlip = FlipStyle_Outside;
+ }
+#else
+ // Other OS screen positioned popups can be flipped vertically but never horizontally
vFlip = FlipStyle_Outside;
+#endif // #ifdef XP_MACOSX
}
// If a panel is being moved or has flip="none", don't constrain or flip it. But always do this for
diff --git a/layout/xul/nsRepeatService.h b/layout/xul/nsRepeatService.h
index c731f8cf59..81321a4729 100644
--- a/layout/xul/nsRepeatService.h
+++ b/layout/xul/nsRepeatService.h
@@ -14,7 +14,11 @@
#define INITAL_REPEAT_DELAY 250
+#ifdef XP_MACOSX
+#define REPEAT_DELAY 25
+#else
#define REPEAT_DELAY 50
+#endif
class nsITimer;
diff --git a/layout/xul/nsSliderFrame.cpp b/layout/xul/nsSliderFrame.cpp
index b98ac4a03f..812c233fc1 100644
--- a/layout/xul/nsSliderFrame.cpp
+++ b/layout/xul/nsSliderFrame.cpp
@@ -664,7 +664,11 @@ nsSliderFrame::GetScrollToClick()
return false;
}
+#ifdef XP_MACOSX
+ return true;
+#else
return false;
+#endif
}
nsIFrame*
@@ -1174,8 +1178,8 @@ nsSliderFrame::ShouldScrollToClickForEvent(WidgetGUIEvent* aEvent)
return false;
}
-#if defined(MOZ_WIDGET_GTK)
- // On Linux, clicking the scrollbar thumb should never scroll to click.
+#if defined(XP_MACOSX) || defined(MOZ_WIDGET_GTK)
+ // On Mac and Linux, clicking the scrollbar thumb should never scroll to click.
if (IsEventOverThumb(aEvent)) {
return false;
}
@@ -1183,7 +1187,11 @@ nsSliderFrame::ShouldScrollToClickForEvent(WidgetGUIEvent* aEvent)
WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
if (mouseEvent->button == WidgetMouseEvent::eLeftButton) {
+#ifdef XP_MACOSX
+ bool invertPref = mouseEvent->IsAlt();
+#else
bool invertPref = mouseEvent->IsShift();
+#endif
return GetScrollToClick() != invertPref;
}
diff --git a/layout/xul/nsXULPopupManager.cpp b/layout/xul/nsXULPopupManager.cpp
index 5fc533e1b9..6e8cc3dda1 100644
--- a/layout/xul/nsXULPopupManager.cpp
+++ b/layout/xul/nsXULPopupManager.cpp
@@ -712,6 +712,21 @@ nsXULPopupManager::ShowMenu(nsIContent *aMenu,
nsAutoString position;
+#ifdef XP_MACOSX
+ nsCOMPtr<nsIDOMXULMenuListElement> menulist = do_QueryInterface(aMenu);
+ bool isNonEditableMenulist = false;
+ if (menulist) {
+ bool editable;
+ menulist->GetEditable(&editable);
+ isNonEditableMenulist = !editable;
+ }
+
+ if (isNonEditableMenulist) {
+ position.AssignLiteral("selection");
+ }
+ else
+#endif
+
if (onMenuBar || !onmenu)
position.AssignLiteral("after_start");
else
@@ -1799,6 +1814,15 @@ nsXULPopupManager::MayShowPopup(nsMenuPopupFrame* aPopup)
return false;
}
+#ifdef XP_MACOSX
+ if (rootWin) {
+ auto globalWin = nsGlobalWindow::Cast(rootWin.get());
+ if (globalWin->IsInModalState()) {
+ return false;
+ }
+ }
+#endif
+
// cannot open a popup that is a submenu of a menupopup that isn't open.
nsMenuFrame* menuFrame = do_QueryFrame(aPopup->GetParent());
if (menuFrame) {
@@ -2304,6 +2328,7 @@ nsXULPopupManager::HandleKeyboardEventWithKeyCode(
switch (keyCode) {
case nsIDOMKeyEvent::DOM_VK_UP:
case nsIDOMKeyEvent::DOM_VK_DOWN:
+#ifndef XP_MACOSX
// roll up the popup when alt+up/down are pressed within a menulist.
bool alt;
aKeyEvent->GetAltKey(&alt);
@@ -2312,6 +2337,7 @@ nsXULPopupManager::HandleKeyboardEventWithKeyCode(
break;
}
MOZ_FALLTHROUGH;
+#endif
case nsIDOMKeyEvent::DOM_VK_LEFT:
case nsIDOMKeyEvent::DOM_VK_RIGHT:
@@ -2340,7 +2366,9 @@ nsXULPopupManager::HandleKeyboardEventWithKeyCode(
break;
case nsIDOMKeyEvent::DOM_VK_TAB:
+#ifndef XP_MACOSX
case nsIDOMKeyEvent::DOM_VK_F10:
+#endif
if (aTopVisibleMenuItem &&
!aTopVisibleMenuItem->Frame()->GetContent()->AttrValueIs(kNameSpaceID_None,
nsGkAtoms::activateontab, nsGkAtoms::_true, eCaseMatters)) {
diff --git a/layout/xul/tree/nsTreeBodyFrame.cpp b/layout/xul/tree/nsTreeBodyFrame.cpp
index 262884c9a8..ec054a234e 100644
--- a/layout/xul/tree/nsTreeBodyFrame.cpp
+++ b/layout/xul/tree/nsTreeBodyFrame.cpp
@@ -2613,7 +2613,9 @@ nsTreeBodyFrame::HandleEvent(nsPresContext* aPresContext,
// Save last values, we will need them.
int32_t lastDropRow = mSlots->mDropRow;
int16_t lastDropOrient = mSlots->mDropOrient;
+#ifndef XP_MACOSX
int16_t lastScrollLines = mSlots->mScrollLines;
+#endif
// Find out the current drag action
uint32_t lastDragAction = mSlots->mDragAction;
@@ -2631,6 +2633,9 @@ nsTreeBodyFrame::HandleEvent(nsPresContext* aPresContext,
mSlots->mDropAllowed = false;
InvalidateDropFeedback(lastDropRow, lastDropOrient);
}
+#ifdef XP_MACOSX
+ ScrollByLines(mSlots->mScrollLines);
+#else
if (!lastScrollLines) {
// Cancel any previously initialized timer.
if (mSlots->mTimer) {
@@ -2643,6 +2648,7 @@ nsTreeBodyFrame::HandleEvent(nsPresContext* aPresContext,
LazyScrollCallback, nsITimer::TYPE_ONE_SHOT,
getter_AddRefs(mSlots->mTimer));
}
+#endif
// Bail out to prevent spring loaded timer and feedback line settings.
return NS_OK;
}
@@ -2836,6 +2842,53 @@ nsTreeBodyFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
if (!mView || !GetContent ()->GetComposedDoc()->GetWindow())
return;
+#ifdef XP_MACOSX
+ nsIContent* baseElement = GetBaseElement();
+ nsIFrame* treeFrame =
+ baseElement ? baseElement->GetPrimaryFrame() : nullptr;
+ nsCOMPtr<nsITreeSelection> selection;
+ mView->GetSelection(getter_AddRefs(selection));
+ nsITheme* theme = PresContext()->GetTheme();
+ // On Mac, we support native theming of selected rows. On 10.10 and higher,
+ // this means applying vibrancy which require us to register the theme
+ // geometrics for the row. In order to make the vibrancy effect to work
+ // properly, we also need the tree to be themed as a source list.
+ if (selection && treeFrame && theme &&
+ treeFrame->StyleDisplay()->mAppearance == NS_THEME_MAC_SOURCE_LIST) {
+ // Loop through our onscreen rows. If the row is selected and a
+ // -moz-appearance is provided, RegisterThemeGeometry might be necessary.
+ const auto end = std::min(mRowCount, LastVisibleRow() + 1);
+ for (auto i = FirstVisibleRow(); i < end; i++) {
+ bool isSelected;
+ selection->IsSelected(i, &isSelected);
+ if (isSelected) {
+ PrefillPropertyArray(i, nullptr);
+ nsAutoString properties;
+ mView->GetRowProperties(i, properties);
+ nsTreeUtils::TokenizeProperties(properties, mScratchArray);
+ nsStyleContext* rowContext =
+ GetPseudoStyleContext(nsCSSAnonBoxes::moztreerow);
+ auto appearance = rowContext->StyleDisplay()->mAppearance;
+ if (appearance) {
+ if (theme->ThemeSupportsWidget(PresContext(), this, appearance)) {
+ nsITheme::ThemeGeometryType type =
+ theme->ThemeGeometryTypeForWidget(this, appearance);
+ if (type != nsITheme::eThemeGeometryTypeUnknown) {
+ nsRect rowRect(mInnerBox.x, mInnerBox.y + mRowHeight *
+ (i - FirstVisibleRow()), mInnerBox.width,
+ mRowHeight);
+ aBuilder->RegisterThemeGeometry(type,
+ LayoutDeviceIntRect::FromUnknownRect(
+ (rowRect + aBuilder->ToReferenceFrame(this)).ToNearestPixels(
+ PresContext()->AppUnitsPerDevPixel())));
+ }
+ }
+ }
+ }
+ }
+ }
+#endif
+
aLists.Content()->AppendNewToTop(new (aBuilder)
nsDisplayTreeBody(aBuilder, this));
}