mozilla-bmo1360278.patch
changeset 1019 b0c883afdffa
parent 1018 0e45f8ad501c
child 1020 d2c159cb9bf2
equal deleted inserted replaced
1018:0e45f8ad501c 1019:b0c883afdffa
     1 
       
     2 # HG changeset patch
       
     3 # User Robin Grenet <robin.grenet@wanadoo.fr>
       
     4 # Date 1510835758 -3600
       
     5 # Node ID f540f9e801cb2e0be5259baea13dfce953ccb520
       
     6 # Parent  0abbf75bd0ecfa99ab4386f551a622983f5f27ea
       
     7 Bug 1360278 - Add preference to trigger context menu on mouse up for GTK+ and macOS, r=mstange,smaug
       
     8 
       
     9 MozReview-Commit-ID: Bg60bD8jIg6
       
    10 
       
    11 diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js
       
    12 --- a/modules/libpref/init/all.js
       
    13 +++ b/modules/libpref/init/all.js
       
    14 @@ -229,16 +229,20 @@ pref("dom.script_loader.bytecode_cache.e
       
    15  pref("dom.script_loader.bytecode_cache.strategy", 0);
       
    16  
       
    17  // Fastback caching - if this pref is negative, then we calculate the number
       
    18  // of content viewers to cache based on the amount of available memory.
       
    19  pref("browser.sessionhistory.max_total_viewers", -1);
       
    20  
       
    21  pref("ui.use_native_colors", true);
       
    22  pref("ui.click_hold_context_menus", false);
       
    23 +
       
    24 +// Pop up context menu on mouseup instead of mousedown, if that's the OS default.
       
    25 +// Note: ignored on Windows (context menus always use mouseup)
       
    26 +pref("ui.context_menus.after_mouseup", false);
       
    27  // Duration of timeout of incremental search in menus (ms).  0 means infinite.
       
    28  pref("ui.menu.incremental_search.timeout", 1000);
       
    29  // If true, all popups won't hide automatically on blur
       
    30  pref("ui.popup.disable_autohide", false);
       
    31  
       
    32  pref("browser.display.use_document_fonts",  1);  // 0 = never, 1 = quick, 2 = always
       
    33  // 0 = default: always, except in high contrast mode
       
    34  // 1 = always
       
    35 diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm
       
    36 --- a/widget/cocoa/nsChildView.mm
       
    37 +++ b/widget/cocoa/nsChildView.mm
       
    38 @@ -4695,18 +4695,20 @@ NSEvent* gLastDragMouseDownEvent = nil;
       
    39    [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
       
    40    geckoEvent.button = WidgetMouseEvent::eRightButton;
       
    41    geckoEvent.mClickCount = [theEvent clickCount];
       
    42  
       
    43    mGeckoChild->DispatchInputEvent(&geckoEvent);
       
    44    if (!mGeckoChild)
       
    45      return;
       
    46  
       
    47 -  // Let the superclass do the context menu stuff.
       
    48 -  [super rightMouseDown:theEvent];
       
    49 +  if (!nsBaseWidget::ShowContextMenuAfterMouseUp()) {
       
    50 +    // Let the superclass do the context menu stuff.
       
    51 +    [super rightMouseDown:theEvent];
       
    52 +  }
       
    53  
       
    54    NS_OBJC_END_TRY_ABORT_BLOCK;
       
    55  }
       
    56  
       
    57  - (void)rightMouseUp:(NSEvent *)theEvent
       
    58  {
       
    59    NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
       
    60  
       
    61 @@ -4719,16 +4721,33 @@ NSEvent* gLastDragMouseDownEvent = nil;
       
    62    WidgetMouseEvent geckoEvent(true, eMouseUp, mGeckoChild,
       
    63                                WidgetMouseEvent::eReal);
       
    64    [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
       
    65    geckoEvent.button = WidgetMouseEvent::eRightButton;
       
    66    geckoEvent.mClickCount = [theEvent clickCount];
       
    67  
       
    68    nsAutoRetainCocoaObject kungFuDeathGrip(self);
       
    69    mGeckoChild->DispatchInputEvent(&geckoEvent);
       
    70 +  if (!mGeckoChild)
       
    71 +    return;
       
    72 +
       
    73 +  if (nsBaseWidget::ShowContextMenuAfterMouseUp()) {
       
    74 +    // Let the superclass do the context menu stuff, but pretend it's rightMouseDown.
       
    75 +    NSEvent *dupeEvent = [NSEvent mouseEventWithType:NSRightMouseDown
       
    76 +                                            location:theEvent.locationInWindow
       
    77 +                                       modifierFlags:theEvent.modifierFlags
       
    78 +                                           timestamp:theEvent.timestamp
       
    79 +                                        windowNumber:theEvent.windowNumber
       
    80 +                                             context:theEvent.context
       
    81 +                                         eventNumber:theEvent.eventNumber
       
    82 +                                          clickCount:theEvent.clickCount
       
    83 +                                            pressure:theEvent.pressure];
       
    84 +
       
    85 +    [super rightMouseDown:dupeEvent];
       
    86 +  }
       
    87  
       
    88    NS_OBJC_END_TRY_ABORT_BLOCK;
       
    89  }
       
    90  
       
    91  - (void)rightMouseDragged:(NSEvent*)theEvent
       
    92  {
       
    93    if (!mGeckoChild)
       
    94      return;
       
    95 diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp
       
    96 --- a/widget/gtk/nsWindow.cpp
       
    97 +++ b/widget/gtk/nsWindow.cpp
       
    98 @@ -2733,16 +2733,29 @@ nsWindow::InitButtonEvent(WidgetMouseEve
       
    99  }
       
   100  
       
   101  static guint ButtonMaskFromGDKButton(guint button)
       
   102  {
       
   103      return GDK_BUTTON1_MASK << (button - 1);
       
   104  }
       
   105  
       
   106  void
       
   107 +nsWindow::DispatchContextMenuEventFromMouseEvent(uint16_t domButton,
       
   108 +                                                 GdkEventButton *aEvent)
       
   109 +{
       
   110 +    if (domButton == WidgetMouseEvent::eRightButton && MOZ_LIKELY(!mIsDestroyed)) {
       
   111 +        WidgetMouseEvent contextMenuEvent(true, eContextMenu, this,
       
   112 +                                          WidgetMouseEvent::eReal);
       
   113 +        InitButtonEvent(contextMenuEvent, aEvent);
       
   114 +        contextMenuEvent.pressure = mLastMotionPressure;
       
   115 +        DispatchInputEvent(&contextMenuEvent);
       
   116 +    }
       
   117 +}
       
   118 +
       
   119 +void
       
   120  nsWindow::OnButtonPressEvent(GdkEventButton *aEvent)
       
   121  {
       
   122      LOG(("Button %u press on %p\n", aEvent->button, (void *)this));
       
   123  
       
   124      // If you double click in GDK, it will actually generate a second
       
   125      // GDK_BUTTON_PRESS before sending the GDK_2BUTTON_PRESS, and this is
       
   126      // different than the DOM spec.  GDK puts this in the queue
       
   127      // programatically, so it's safe to assume that if there's a
       
   128 @@ -2801,23 +2814,18 @@ nsWindow::OnButtonPressEvent(GdkEventBut
       
   129      WidgetMouseEvent event(true, eMouseDown, this, WidgetMouseEvent::eReal);
       
   130      event.button = domButton;
       
   131      InitButtonEvent(event, aEvent);
       
   132      event.pressure = mLastMotionPressure;
       
   133  
       
   134      DispatchInputEvent(&event);
       
   135  
       
   136      // right menu click on linux should also pop up a context menu
       
   137 -    if (domButton == WidgetMouseEvent::eRightButton &&
       
   138 -        MOZ_LIKELY(!mIsDestroyed)) {
       
   139 -        WidgetMouseEvent contextMenuEvent(true, eContextMenu, this,
       
   140 -                                          WidgetMouseEvent::eReal);
       
   141 -        InitButtonEvent(contextMenuEvent, aEvent);
       
   142 -        contextMenuEvent.pressure = mLastMotionPressure;
       
   143 -        DispatchInputEvent(&contextMenuEvent);
       
   144 +    if (!nsBaseWidget::ShowContextMenuAfterMouseUp()) {
       
   145 +        DispatchContextMenuEventFromMouseEvent(domButton, aEvent);
       
   146      }
       
   147  }
       
   148  
       
   149  void
       
   150  nsWindow::OnButtonReleaseEvent(GdkEventButton *aEvent)
       
   151  {
       
   152      LOG(("Button %u release on %p\n", aEvent->button, (void *)this));
       
   153  
       
   154 @@ -2843,16 +2851,21 @@ nsWindow::OnButtonReleaseEvent(GdkEventB
       
   155      event.button = domButton;
       
   156      InitButtonEvent(event, aEvent);
       
   157      gdouble pressure = 0;
       
   158      gdk_event_get_axis ((GdkEvent*)aEvent, GDK_AXIS_PRESSURE, &pressure);
       
   159      event.pressure = pressure ? pressure : mLastMotionPressure;
       
   160  
       
   161      DispatchInputEvent(&event);
       
   162      mLastMotionPressure = pressure;
       
   163 +
       
   164 +    // right menu click on linux should also pop up a context menu
       
   165 +    if (nsBaseWidget::ShowContextMenuAfterMouseUp()) {
       
   166 +        DispatchContextMenuEventFromMouseEvent(domButton, aEvent);
       
   167 +    }
       
   168  }
       
   169  
       
   170  void
       
   171  nsWindow::OnContainerFocusInEvent(GdkEventFocus *aEvent)
       
   172  {
       
   173      LOGFOCUS(("OnContainerFocusInEvent [%p]\n", (void *)this));
       
   174  
       
   175      // Unset the urgency hint, if possible
       
   176 diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h
       
   177 --- a/widget/gtk/nsWindow.h
       
   178 +++ b/widget/gtk/nsWindow.h
       
   179 @@ -240,16 +240,18 @@ private:
       
   180      LayoutDeviceIntSize GetSafeWindowSize(LayoutDeviceIntSize aSize);
       
   181  
       
   182      void               EnsureGrabs  (void);
       
   183      void               GrabPointer  (guint32 aTime);
       
   184      void               ReleaseGrabs (void);
       
   185  
       
   186      void               UpdateClientOffset();
       
   187  
       
   188 +    void               DispatchContextMenuEventFromMouseEvent(uint16_t domButton,
       
   189 +                                                              GdkEventButton *aEvent);
       
   190  public:
       
   191      void               ThemeChanged(void);
       
   192      void               OnDPIChanged(void);
       
   193      void               OnCheckResize(void);
       
   194      void               OnCompositedChanged(void);
       
   195  
       
   196  #ifdef MOZ_X11
       
   197      Window             mOldFocusWindow;
       
   198 diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp
       
   199 --- a/widget/nsBaseWidget.cpp
       
   200 +++ b/widget/nsBaseWidget.cpp
       
   201 @@ -1213,16 +1213,32 @@ nsBaseWidget::DispatchEventToAPZOnly(moz
       
   202    if (mAPZC) {
       
   203      MOZ_ASSERT(APZThreadUtils::IsControllerThread());
       
   204      uint64_t inputBlockId = 0;
       
   205      ScrollableLayerGuid guid;
       
   206      mAPZC->ReceiveInputEvent(*aEvent, &guid, &inputBlockId);
       
   207    }
       
   208  }
       
   209  
       
   210 +// static
       
   211 +bool
       
   212 +nsBaseWidget::ShowContextMenuAfterMouseUp()
       
   213 +{
       
   214 +  static bool gContextMenuAfterMouseUp = false;
       
   215 +  static bool gContextMenuAfterMouseUpCached = false;
       
   216 +  if (!gContextMenuAfterMouseUpCached) {
       
   217 +    Preferences::AddBoolVarCache(&gContextMenuAfterMouseUp,
       
   218 +                                 "ui.context_menus.after_mouseup",
       
   219 +                                 false);
       
   220 +
       
   221 +    gContextMenuAfterMouseUpCached = true;
       
   222 +  }
       
   223 +  return gContextMenuAfterMouseUp;
       
   224 +}
       
   225 +
       
   226  nsIDocument*
       
   227  nsBaseWidget::GetDocument() const
       
   228  {
       
   229    if (mWidgetListener) {
       
   230      if (nsIPresShell* presShell = mWidgetListener->GetPresShell()) {
       
   231        return presShell->GetDocument();
       
   232      }
       
   233    }
       
   234 diff --git a/widget/nsBaseWidget.h b/widget/nsBaseWidget.h
       
   235 --- a/widget/nsBaseWidget.h
       
   236 +++ b/widget/nsBaseWidget.h
       
   237 @@ -412,16 +412,22 @@ public:
       
   238    void NotifyLiveResizeStopped();
       
   239  
       
   240  #if defined(MOZ_WIDGET_ANDROID)
       
   241    void RecvToolbarAnimatorMessageFromCompositor(int32_t) override {};
       
   242    void UpdateRootFrameMetrics(const ScreenPoint& aScrollOffset, const CSSToScreenScale& aZoom) override {};
       
   243    void RecvScreenPixels(mozilla::ipc::Shmem&& aMem, const ScreenIntSize& aSize) override {};
       
   244  #endif
       
   245  
       
   246 +  /**
       
   247 +   * Whether context menus should only appear on mouseup instead of mousedown,
       
   248 +   * on OSes where they normally appear on mousedown (macOS, *nix).
       
   249 +   */
       
   250 +  static bool ShowContextMenuAfterMouseUp();
       
   251 +
       
   252  protected:
       
   253    // These are methods for CompositorWidgetWrapper, and should only be
       
   254    // accessed from that class. Derived widgets can choose which methods to
       
   255    // implement, or none if supporting out-of-process compositing.
       
   256    virtual bool PreRender(mozilla::widget::WidgetRenderingContext* aContext) {
       
   257      return true;
       
   258    }
       
   259    virtual void PostRender(mozilla::widget::WidgetRenderingContext* aContext)
       
   260