Search code examples
pyqt6qwebengineviewqwebenginepage

Clicking links with the middle mouse button in Python3/Qt6


I used a Python3 script under GTK, where I clicked on a link with the left mouse button to open it in the same window and on a middle mouse button to open it in a separate window.

I am now in the process of migrating this script from GTK to Qt6.

The problem is that I cannot intercept the middle mouse button in conjunction with a clicked link:

My browser window is based on QWebEngineView, I can intercept mouse button clicks with an event filter (eventFilter()), and I can intercept clicked links within the acceptNavigationRequest() function of a QWebEnginePage.

The URL of the clicked link is only available in acceptNavigationRequest(), but this function is only called by Qt6 when I use the left mouse button, not, as desired, the middle mouse button (neither does control + left mouse button work).

How can I let a middle mouse button click be recognized in a navigation request?


Debian 11.6 Bullseye, Python 3.9.2, PyQt6-Qt6 6.4.1


Solution

  • With the help of @musicamante (note the comments in the original post), I solved my problem this way:

    g_mouse_button = '--'
    
    class MyWebEngineView(QWebEngineView):
    
      def __init__(self):
        ...
    
    class MyEventFilter(QObject):
    
      def eventFilter(self, obj, event):
        global g_mouse_button
        ...
        if event.button() == Qt.MouseButton.MiddleButton:
          g_mouse_button = 'middle'
         ...
        ...
    
    class MyWebEnginePage(QWebEnginePage):
    
      def acceptNavigationRequest(self, url, ttype, isMainFrame):
        global g_mouse_button
    
        if  ttype           == QWebEnginePage.NavigationType.NavigationTypeLinkClicked and \
            g_mouse_button  == 'middle':
          <open link in new window>
          g_mouse_button = '--'
          return False # ignore
    
        return True # process
    
      def createWindow(self, window_type):
    
        return self
    
    if __name__ == "__main__":
      ...
      event_filter = MyEventFilter()
      g_app.installEventFilter(event_filter)
      ...