diff -r 85bd01789b6f -r 0c59a30173da mozilla-bmo1360278.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mozilla-bmo1360278.patch Sat Dec 16 13:35:25 2017 +0100 @@ -0,0 +1,260 @@ + +# HG changeset patch +# User Robin Grenet +# Date 1510835758 -3600 +# Node ID f540f9e801cb2e0be5259baea13dfce953ccb520 +# Parent 0abbf75bd0ecfa99ab4386f551a622983f5f27ea +Bug 1360278 - Add preference to trigger context menu on mouse up for GTK+ and macOS, r=mstange,smaug + +MozReview-Commit-ID: Bg60bD8jIg6 + +diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js +--- a/modules/libpref/init/all.js ++++ b/modules/libpref/init/all.js +@@ -229,16 +229,20 @@ pref("dom.script_loader.bytecode_cache.e + pref("dom.script_loader.bytecode_cache.strategy", 0); + + // Fastback caching - if this pref is negative, then we calculate the number + // of content viewers to cache based on the amount of available memory. + pref("browser.sessionhistory.max_total_viewers", -1); + + pref("ui.use_native_colors", true); + pref("ui.click_hold_context_menus", false); ++ ++// Pop up context menu on mouseup instead of mousedown, if that's the OS default. ++// Note: ignored on Windows (context menus always use mouseup) ++pref("ui.context_menus.after_mouseup", false); + // Duration of timeout of incremental search in menus (ms). 0 means infinite. + pref("ui.menu.incremental_search.timeout", 1000); + // If true, all popups won't hide automatically on blur + pref("ui.popup.disable_autohide", false); + + pref("browser.display.use_document_fonts", 1); // 0 = never, 1 = quick, 2 = always + // 0 = default: always, except in high contrast mode + // 1 = always +diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm +--- a/widget/cocoa/nsChildView.mm ++++ b/widget/cocoa/nsChildView.mm +@@ -4695,18 +4695,20 @@ NSEvent* gLastDragMouseDownEvent = nil; + [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]; ++ if (!nsBaseWidget::ShowContextMenuAfterMouseUp()) { ++ // 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; + +@@ -4719,16 +4721,33 @@ NSEvent* gLastDragMouseDownEvent = nil; + 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); ++ if (!mGeckoChild) ++ return; ++ ++ if (nsBaseWidget::ShowContextMenuAfterMouseUp()) { ++ // Let the superclass do the context menu stuff, but pretend it's rightMouseDown. ++ NSEvent *dupeEvent = [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]; ++ ++ [super rightMouseDown:dupeEvent]; ++ } + + NS_OBJC_END_TRY_ABORT_BLOCK; + } + + - (void)rightMouseDragged:(NSEvent*)theEvent + { + if (!mGeckoChild) + return; +diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp +--- a/widget/gtk/nsWindow.cpp ++++ b/widget/gtk/nsWindow.cpp +@@ -2733,16 +2733,29 @@ nsWindow::InitButtonEvent(WidgetMouseEve + } + + static guint ButtonMaskFromGDKButton(guint button) + { + return GDK_BUTTON1_MASK << (button - 1); + } + + void ++nsWindow::DispatchContextMenuEventFromMouseEvent(uint16_t domButton, ++ GdkEventButton *aEvent) ++{ ++ if (domButton == WidgetMouseEvent::eRightButton && MOZ_LIKELY(!mIsDestroyed)) { ++ WidgetMouseEvent contextMenuEvent(true, eContextMenu, this, ++ WidgetMouseEvent::eReal); ++ InitButtonEvent(contextMenuEvent, aEvent); ++ contextMenuEvent.pressure = mLastMotionPressure; ++ DispatchInputEvent(&contextMenuEvent); ++ } ++} ++ ++void + nsWindow::OnButtonPressEvent(GdkEventButton *aEvent) + { + LOG(("Button %u press on %p\n", aEvent->button, (void *)this)); + + // If you double click in GDK, it will actually generate a second + // GDK_BUTTON_PRESS before sending the GDK_2BUTTON_PRESS, and this is + // different than the DOM spec. GDK puts this in the queue + // programatically, so it's safe to assume that if there's a +@@ -2801,23 +2814,18 @@ nsWindow::OnButtonPressEvent(GdkEventBut + WidgetMouseEvent event(true, eMouseDown, this, WidgetMouseEvent::eReal); + event.button = domButton; + InitButtonEvent(event, aEvent); + event.pressure = mLastMotionPressure; + + DispatchInputEvent(&event); + + // right menu click on linux should also pop up a context menu +- if (domButton == WidgetMouseEvent::eRightButton && +- MOZ_LIKELY(!mIsDestroyed)) { +- WidgetMouseEvent contextMenuEvent(true, eContextMenu, this, +- WidgetMouseEvent::eReal); +- InitButtonEvent(contextMenuEvent, aEvent); +- contextMenuEvent.pressure = mLastMotionPressure; +- DispatchInputEvent(&contextMenuEvent); ++ if (!nsBaseWidget::ShowContextMenuAfterMouseUp()) { ++ DispatchContextMenuEventFromMouseEvent(domButton, aEvent); + } + } + + void + nsWindow::OnButtonReleaseEvent(GdkEventButton *aEvent) + { + LOG(("Button %u release on %p\n", aEvent->button, (void *)this)); + +@@ -2843,16 +2851,21 @@ nsWindow::OnButtonReleaseEvent(GdkEventB + event.button = domButton; + InitButtonEvent(event, aEvent); + gdouble pressure = 0; + gdk_event_get_axis ((GdkEvent*)aEvent, GDK_AXIS_PRESSURE, &pressure); + event.pressure = pressure ? pressure : mLastMotionPressure; + + DispatchInputEvent(&event); + mLastMotionPressure = pressure; ++ ++ // right menu click on linux should also pop up a context menu ++ if (nsBaseWidget::ShowContextMenuAfterMouseUp()) { ++ DispatchContextMenuEventFromMouseEvent(domButton, aEvent); ++ } + } + + void + nsWindow::OnContainerFocusInEvent(GdkEventFocus *aEvent) + { + LOGFOCUS(("OnContainerFocusInEvent [%p]\n", (void *)this)); + + // Unset the urgency hint, if possible +diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h +--- a/widget/gtk/nsWindow.h ++++ b/widget/gtk/nsWindow.h +@@ -240,16 +240,18 @@ private: + LayoutDeviceIntSize GetSafeWindowSize(LayoutDeviceIntSize aSize); + + void EnsureGrabs (void); + void GrabPointer (guint32 aTime); + void ReleaseGrabs (void); + + void UpdateClientOffset(); + ++ void DispatchContextMenuEventFromMouseEvent(uint16_t domButton, ++ GdkEventButton *aEvent); + public: + void ThemeChanged(void); + void OnDPIChanged(void); + void OnCheckResize(void); + void OnCompositedChanged(void); + + #ifdef MOZ_X11 + Window mOldFocusWindow; +diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp +--- a/widget/nsBaseWidget.cpp ++++ b/widget/nsBaseWidget.cpp +@@ -1213,16 +1213,32 @@ nsBaseWidget::DispatchEventToAPZOnly(moz + if (mAPZC) { + MOZ_ASSERT(APZThreadUtils::IsControllerThread()); + uint64_t inputBlockId = 0; + ScrollableLayerGuid guid; + mAPZC->ReceiveInputEvent(*aEvent, &guid, &inputBlockId); + } + } + ++// static ++bool ++nsBaseWidget::ShowContextMenuAfterMouseUp() ++{ ++ static bool gContextMenuAfterMouseUp = false; ++ static bool gContextMenuAfterMouseUpCached = false; ++ if (!gContextMenuAfterMouseUpCached) { ++ Preferences::AddBoolVarCache(&gContextMenuAfterMouseUp, ++ "ui.context_menus.after_mouseup", ++ false); ++ ++ gContextMenuAfterMouseUpCached = true; ++ } ++ return gContextMenuAfterMouseUp; ++} ++ + nsIDocument* + nsBaseWidget::GetDocument() const + { + if (mWidgetListener) { + if (nsIPresShell* presShell = mWidgetListener->GetPresShell()) { + return presShell->GetDocument(); + } + } +diff --git a/widget/nsBaseWidget.h b/widget/nsBaseWidget.h +--- a/widget/nsBaseWidget.h ++++ b/widget/nsBaseWidget.h +@@ -412,16 +412,22 @@ public: + void NotifyLiveResizeStopped(); + + #if defined(MOZ_WIDGET_ANDROID) + void RecvToolbarAnimatorMessageFromCompositor(int32_t) override {}; + void UpdateRootFrameMetrics(const ScreenPoint& aScrollOffset, const CSSToScreenScale& aZoom) override {}; + void RecvScreenPixels(mozilla::ipc::Shmem&& aMem, const ScreenIntSize& aSize) override {}; + #endif + ++ /** ++ * Whether context menus should only appear on mouseup instead of mousedown, ++ * on OSes where they normally appear on mousedown (macOS, *nix). ++ */ ++ static bool ShowContextMenuAfterMouseUp(); ++ + protected: + // These are methods for CompositorWidgetWrapper, and should only be + // accessed from that class. Derived widgets can choose which methods to + // implement, or none if supporting out-of-process compositing. + virtual bool PreRender(mozilla::widget::WidgetRenderingContext* aContext) { + return true; + } + virtual void PostRender(mozilla::widget::WidgetRenderingContext* aContext) +