Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-68105

Refactor context menu event handling

    XMLWordPrintable

Details

    Description

      Problem

      In my quest to fix QTBUG-67331 (see https://codereview.qt-project.org/#/c/228011/, which is essentially copying the logic from qwidgetwindow to qquickwindow), a discussion arose surrounding the fact that qwidgetwindow.cpp currently "hard-codes" context menu events, and that this would be better done in the platform plugins rather than duplicating the logic further.

      Solution

      1. Make platform plugins responsible for generating QContextMenuEvents, as they know how they want them to be triggered (e.g. keyboard, mouse (and then press vs release), etc.)
      2. Move any remaining context menu handling stuff in qwidgetwindow to Qt GUI so that Qt Quick items can also be sent these events.

      Relevant info

      Windows

      Patch that added back support for keyboard-based context menu events, presumably after QPA was introduced:

      Add ContextMenu event to QWindowSystemInterface
      
      Context menu key wasn't working, as QPA had no handling for it.
      Added ContextMenu event to QWindowSystemInterface and proper handling
      to QGuiApplication and QWidgetWindow.
      
      Also provide Windows implementation.
      
      Task-number: QTBUG-27648
      Change-Id: I7ce71ec4b5cdcc7be758e67f9faf6d863f7b19be
      

      Windows sends WM_CONTEXTMENU when the menu button on a keyboard is pressed, or the title bar is right clicked. It should send the event when the client area of the window is clicked too, but currently it looks like Qt ignores this:

      DefWindowProc generates the WM_CONTEXTMENU message when it processes the WM_RBUTTONUP or WM_NCRBUTTONUP message or when the user types SHIFT+F10. The WM_CONTEXTMENU message is also generated when the user presses and releases the VK_APPS key.

      https://msdn.microsoft.com/en-us/library/windows/desktop/ms646243(v=vs.85).aspx says this about WM_RBUTTONUP:

      Posted when the user releases the right mouse button while the cursor is in the client area of a window. If the mouse is not captured, the message is posted to the window beneath the cursor. Otherwise, the message is posted to the window that has captured the mouse.

      A window receives this message through its WindowProc function.

      As a quick test, if we return false at the top of QWindowsMouseHandler::translateMouseEvent(), we get the WM_CONTEXTMENU event. This means that:

      <frkleint> micurtis: [...] we need to return false for WM_RBUTTONUP if Qt does not handle it so WM_CONTEXTMENU will be send
      <micurtis> frkleint: ok, that makes sense
      <frkleint> micurtis: But, as with KDB shortcuts. this is not possible to find out given the gazillions of event queues in Qt
      <micurtis> frkleint: oh...
      <frkleint> yep, same problem with KDB shortcuts...

      So #1 might not be possible. In that case we need to settle with #2. We need to check why the keyboard event path works but the mouse one doesn't.

      QPA logging categories (qt.qpa.events is probably the most useful one in this case):

      Q_LOGGING_CATEGORY(lcQpaWindows, "qt.qpa.windows")
      Q_LOGGING_CATEGORY(lcQpaBackingStore, "qt.qpa.backingstore")
      Q_LOGGING_CATEGORY(lcQpaEvents, "qt.qpa.events")
      Q_LOGGING_CATEGORY(lcQpaGl, "qt.qpa.gl")
      Q_LOGGING_CATEGORY(lcQpaMime, "qt.qpa.mime")
      Q_LOGGING_CATEGORY(lcQpaInputMethods, "qt.qpa.input.methods")
      Q_LOGGING_CATEGORY(lcQpaDialogs, "qt.qpa.dialogs")
      Q_LOGGING_CATEGORY(lcQpaMenus, "qt.qpa.menus")
      Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
      Q_LOGGING_CATEGORY(lcQpaAccessibility, "qt.qpa.accessibility")
      Q_LOGGING_CATEGORY(lcQpaUiAutomation, "qt.qpa.uiautomation")
      Q_LOGGING_CATEGORY(lcQpaTrayIcon, "qt.qpa.trayicon")
      

      To get verbose debug output, use QT_QPA_VERBOSE:

          // Verbose flag set by environment variable QT_QPA_VERBOSE
          static int verbose;
      

      Linux

      Patch that added back support for keyboard-based context menu events, presumably after QPA was introduced:

      Send QContexMenuEvent when Context Menu key is pressed.
      
      Bring back code from keymapper_x11.cpp.
      
      Task-number: QTBUG-27648
      Change-Id: I2a189a0537bcd2ae0eb093576c84814b2f09933b
      

      macOS

      Some info about context menu events on macOS:

      Mac HIG https://developer.apple.com/library/mac/documentation/userexperience/conceptual/applehiguidelines/Menus/Menus.html discusses context menus. The 'Context Menu key' is a property of keyboards. Most keyboards used on Macs do not have said key. Said key is usually found only on PC's running MS Windows. See http://en.wikipedia.org/wiki/Menu_key. OSX does support mouse with many buttons, and RMB usually shows context menu. According to the HIG, on OSX with a one-button mouse, the combination of 'Ctl' key (not the Command key) and mouse button should invoke a context menu.

      Attachments

        Issue Links

          Activity

            People

              qt.team.quick.subscriptions Qt Quick and Widgets Team
              mitch_curtis Mitch Curtis
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: