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

macOS Mojave: security 'Accessibility Access' dialog (qcocoacursor.mm)

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P1: Critical
    • Resolution: Duplicate
    • Affects Version/s: 5.10.1, 5.11.0
    • Fix Version/s: 5.11.2
    • Labels:
      None
    • Platform/s:
      macOS
    • Commits:
      cd08753d3e2ac02663ba0ab588d7d926f7438475

      Description

      Any Qt application using drag and drop triggers the new 'Accessibility Access' security dialog on macOS Mojave. See attached screencast [^screencast.mov]

       

      Steps to reproduce:

      1. Download the attached application testDragDrop.app.zip [^testDragDrop.app.zip]. Source code is also attached [^testDragDrop_src.zip]
      2. Run the application on macOS Mojave
      3. Select any row and perform a drag operation

      Result: You see the 'Accessibility Access' security dialog asking the user to allow the application.

      Note: In order to see again the dialog, you can reset it by typing in the Terminal:

      sudo tccutil reset PostEvent
      

       

      macOS Mojave added a new security mechanism to prevent an application to control another application using CGEventPost without the user consent. When a CGEventPost event is posted, you will see a dialog asking you to allow the application in the Accessibility preferences in the System Preferences:

       

      You can find more information about this new mechanism in the session 702 from the WWDC 2018: https://developer.apple.com/videos/play/wwdc2018/702/

       

      When a drag occurs, QNSView creates a fake move event. This causes the new macOS security mechanism to be triggered. See in Src/qtbase/src/plugins/platforms/cocoa/qnsview.mm in the function:

      - (void)updateCursorFromDragResponse:(QPlatformDragQtResponse)response drag:(QCocoaDrag *)drag
      
      // Make sure the cursor is updated correctly if the mouse does not move and window is under cursor
      // by creating a fake move event
      if (m_updatingDrag)
      return;
      
      const QPoint mousePos(QCursor::pos());
      CGEventRef moveEvent(CGEventCreateMouseEvent(
      NULL, kCGEventMouseMoved,
      CGPointMake(mousePos.x(), mousePos.y()),
      kCGMouseButtonLeft // ignored
      ));
      CGEventPost(kCGHIDEventTap, moveEvent);
      CFRelease(moveEvent);
      

       

      Here is a backtrace where you see when the CGEventPost is sent:

      * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
      * frame #0: 0x00007fff7520fcc5 SkyLight`SLEventPost
      frame #1: 0x0000000104298584 libqcocoa.dylib`-[QNSView updateCursorFromDragResponse:drag:] + 580
      frame #2: 0x0000000104298868 libqcocoa.dylib`-[QNSView handleDrag:] + 600
      frame #3: 0x00007fff4c9cf61e AppKit`-[NSDragDestination _draggingEntered] + 54
      frame #4: 0x00007fff4c6dfa98 AppKit`NSCoreDragTrackingProc + 1007
      frame #5: 0x00007fff4d6b0b7a HIServices`DoTrackingMessage + 409
      frame #6: 0x00007fff4d6b0fc6 HIServices`DragInApplication + 244
      frame #7: 0x00007fff4d6afff0 HIServices`CoreDragStartDragging + 955
      frame #8: 0x00007fff4c6defa7 AppKit`-[NSCoreDragManager _dragUntilMouseUp:accepted:] + 1238
      frame #9: 0x00007fff4c6dc029 AppKit`-[NSCoreDragManager dragImage:fromWindow:at:offset:event:pasteboard:source:slideBack:] + 2992
      frame #10: 0x00007fff4c6db467 AppKit`-[NSWindow(NSDrag) dragImage:at:offset:event:pasteboard:source:slideBack:] + 132
      frame #11: 0x00000001042b3d36 libqcocoa.dylib`QCocoaDrag::drag(QDrag*) + 694
      frame #12: 0x00000001006c972d QtGui`QDragManager::drag(QDrag*) + 189
      frame #13: 0x00000001006c8cb8 QtGui`QDrag::exec(QFlags<Qt::DropAction>, Qt::DropAction) + 88
      frame #14: 0x000000010036d314 QtWidgets`QAbstractItemView::startDrag(QFlags<Qt::DropAction>) + 292
      frame #15: 0x0000000100363df5 QtWidgets`QAbstractItemView::mouseMoveEvent(QMouseEvent*) + 421
      frame #16: 0x00000001003d2e57 QtWidgets`QTreeView::mouseMoveEvent(QMouseEvent*) + 199
      frame #17: 0x0000000100137120 QtWidgets`QWidget::event(QEvent*) + 544
      frame #18: 0x00000001001e07cd QtWidgets`QFrame::event(QEvent*) + 45
      frame #19: 0x00000001001ea869 QtWidgets`QAbstractScrollArea::viewportEvent(QEvent*) + 57
      frame #20: 0x00000001003634fe QtWidgets`QAbstractItemView::viewportEvent(QEvent*) + 1502
      frame #21: 0x00000001003cf135 QtWidgets`QTreeView::viewportEvent(QEvent*) + 517
      frame #22: 0x00000001001eb524 QtWidgets`QAbstractScrollAreaFilter::eventFilter(QObject*, QEvent*) + 36
      frame #23: 0x0000000100d71322 QtCore`QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject*, QEvent*) + 210
      frame #24: 0x00000001000fcecd QtWidgets`QApplicationPrivate::notify_helper(QObject*, QEvent*) + 285
      frame #25: 0x00000001000ffc7d QtWidgets`QApplication::notify(QObject*, QEvent*) + 7165
      frame #26: 0x0000000100d7103f QtCore`QCoreApplication::notifyInternal2(QObject*, QEvent*) + 159
      frame #27: 0x00000001000fd810 QtWidgets`QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool) + 896
      frame #28: 0x0000000100157210 QtWidgets`QWidgetWindow::handleMouseEvent(QMouseEvent*) + 1744
      frame #29: 0x0000000100155f00 QtWidgets`QWidgetWindow::event(QEvent*) + 224
      frame #30: 0x00000001000fcee2 QtWidgets`QApplicationPrivate::notify_helper(QObject*, QEvent*) + 306
      frame #31: 0x00000001000fe1ff QtWidgets`QApplication::notify(QObject*, QEvent*) + 383
      frame #32: 0x0000000100d7103f QtCore`QCoreApplication::notifyInternal2(QObject*, QEvent*) + 159
      frame #33: 0x00000001006b37f9 QtGui`QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent*) + 3145
      frame #34: 0x00000001006994db QtGui`QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 155
      frame #35: 0x000000010429e2c1 libqcocoa.dylib`QCocoaEventDispatcherPrivate::postedEventsSourceCallback(void*) + 33
      frame #36: 0x00007fff4ef00fc0 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
      frame #37: 0x00007fff4ef9e472 CoreFoundation`__CFRunLoopDoSource0 + 108
      frame #38: 0x00007fff4eee811a CoreFoundation`__CFRunLoopDoSources0 + 195
      frame #39: 0x00007fff4eee76b7 CoreFoundation`__CFRunLoopRun + 1225
      frame #40: 0x00007fff4eee6fc7 CoreFoundation`CFRunLoopRunSpecific + 463
      frame #41: 0x00007fff4e1835fb HIToolbox`RunCurrentEventLoopInMode + 293
      frame #42: 0x00007fff4e18323e HIToolbox`ReceiveNextEventCommon + 371
      frame #43: 0x00007fff4e1830b2 HIToolbox`_BlockUntilNextEventMatchingListInModeWithFilter + 64
      frame #44: 0x00007fff4c48fa02 AppKit`_DPSNextEvent + 1000
      frame #45: 0x00007fff4cbd7586 AppKit`-[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 1356
      frame #46: 0x00007fff4c4850e5 AppKit`-[NSApplication run] + 699
      frame #47: 0x000000010429d0bd libqcocoa.dylib`QCocoaEventDispatcher::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 2397
      frame #48: 0x0000000100d6cb92 QtCore`QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) + 418
      frame #49: 0x0000000100d71752 QtCore`QCoreApplication::exec() + 402
      frame #50: 0x00000001000038af testDragDrop`main(argc=1, argv=0x00007ffeefbff9f8) at main.cpp:34
      frame #51: 0x00007fff7be09ee1 libdyld.dylib`start + 1
      frame #52: 0x00007fff7be09ee1 libdyld.dylib`start + 1
      

       

        Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

            Assignee:
            sorvig Morten Sørvig
            Reporter:
            nshaforostov Mykola Shaforostov
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved:

                Gerrit Reviews

                There are no open Gerrit changes