VirtualBox

Changeset 35740 in vbox for trunk/src


Ignore:
Timestamp:
Jan 27, 2011 2:36:03 PM (14 years ago)
Author:
vboxsync
Message:

FE/Qt4-OSX: Prevent the mouse from leaving the window in capture mode.

Location:
trunk/src/VBox/Frontends/VirtualBox/src
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/platform/darwin/VBoxUtils-darwin-cocoa.mm

    r35424 r35740  
    332332
    333333    return size;
     334}
     335
     336bool darwinMouseMoveEvents(const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser)
     337{
     338    NSEvent *pEvent = (NSEvent*)pvCocoaEvent;
     339    NSEventType EvtType = [pEvent type];
     340    NSWindow *pWin = ::darwinToNativeWindow((QWidget*)pvUser);
     341    if (   pWin == [pEvent window]
     342        && (   EvtType == NSLeftMouseDown
     343            || EvtType == NSLeftMouseUp
     344            || EvtType == NSRightMouseDown
     345            || EvtType == NSRightMouseUp
     346            || EvtType == NSOtherMouseDown
     347            || EvtType == NSOtherMouseUp
     348            || EvtType == NSLeftMouseDragged
     349            || EvtType == NSRightMouseDragged
     350            || EvtType == NSOtherMouseDragged
     351            || EvtType == NSMouseMoved
     352            || EvtType == NSScrollWheel))
     353    {
     354        float x = [pEvent deltaX];
     355        float y = [pEvent deltaY];
     356        /* Get the buttons which where pressed when this event occurs. We have
     357           to use Carbon here, cause the Cocoa method [NSEvent pressedMouseButtons]
     358           is >= 10.6. */
     359        if (EvtType == NSScrollWheel)
     360        {
     361            /* In the scroll wheel case we have to do some magic, cause a
     362               normal scroll wheel on a mouse behaves different to a trackpad.
     363               The following is used within Qt. We use the same to get a
     364               similar behavior. */
     365            if ([pEvent respondsToSelector:@selector(deviceDeltaX:)])
     366                x = (float)(intptr_t)[pEvent performSelector:@selector(deviceDeltaX)] * 2;
     367            else
     368                x = qBound(-120, (int)(x * 10000), 120);
     369            if ([pEvent respondsToSelector:@selector(deviceDeltaY:)])
     370                y = (float)(intptr_t)[pEvent performSelector:@selector(deviceDeltaY)] * 2;
     371            else
     372                y = qBound(-120, (int)(y * 10000), 120);
     373        }
     374        uint32 buttonMask = 0;
     375        GetEventParameter((EventRef)pvCarbonEvent, kEventParamMouseChord, typeUInt32, 0,
     376                          sizeof(buttonMask), 0, &buttonMask);
     377        /* Produce a Qt event out of our info. */
     378        ::darwinSendDeltaEvents((QWidget*)pvUser, EvtType, [pEvent buttonNumber], buttonMask, x, y);
     379        return true;
     380    }
     381    return false;
    334382}
    335383
  • trunk/src/VBox/Frontends/VirtualBox/src/platform/darwin/VBoxUtils-darwin.cpp

    r35424 r35740  
    340340{
    341341    UICocoaApplication::instance()->unregisterForNativeEvents(RT_BIT_32(3) /* NSRightMouseDown */, ::darwinUnifiedToolbarEvents, pWindow);
     342}
     343
     344void darwinMouseGrab(QWidget *pWidget)
     345{
     346    CGAssociateMouseAndMouseCursorPosition(false);
     347    UICocoaApplication::instance()->registerForNativeEvents(RT_BIT_32(1)  | /* NSLeftMouseDown */
     348                                                            RT_BIT_32(2)  | /* NSLeftMouseUp */
     349                                                            RT_BIT_32(3)  | /* NSRightMouseDown */
     350                                                            RT_BIT_32(4)  | /* NSRightMouseUp */
     351                                                            RT_BIT_32(5)  | /* NSMouseMoved */
     352                                                            RT_BIT_32(6)  | /* NSLeftMouseDragged */
     353                                                            RT_BIT_32(7)  | /* NSRightMouseDragged */
     354                                                            RT_BIT_32(25) | /* NSOtherMouseDown */
     355                                                            RT_BIT_32(26) | /* NSOtherMouseUp */
     356                                                            RT_BIT_32(27) | /* NSOtherMouseDragged */
     357                                                            RT_BIT_32(22),  /* NSScrollWheel */
     358                                                            ::darwinMouseMoveEvents, pWidget);
     359}
     360
     361void darwinMouseRelease(QWidget *pWidget)
     362{
     363    UICocoaApplication::instance()->unregisterForNativeEvents(RT_BIT_32(1)  | /* NSLeftMouseDown */
     364                                                              RT_BIT_32(2)  | /* NSLeftMouseUp */
     365                                                              RT_BIT_32(3)  | /* NSRightMouseDown */
     366                                                              RT_BIT_32(4)  | /* NSRightMouseUp */
     367                                                              RT_BIT_32(5)  | /* NSMouseMoved */
     368                                                              RT_BIT_32(6)  | /* NSLeftMouseDragged */
     369                                                              RT_BIT_32(7)  | /* NSRightMouseDragged */
     370                                                              RT_BIT_32(25) | /* NSOtherMouseDown */
     371                                                              RT_BIT_32(26) | /* NSOtherMouseUp */
     372                                                              RT_BIT_32(27) | /* NSOtherMouseDragged */
     373                                                              RT_BIT_32(22),  /* NSScrollWheel */
     374                                                              ::darwinMouseMoveEvents, pWidget);
     375    CGAssociateMouseAndMouseCursorPosition(true);
     376}
     377
     378void darwinSendDeltaEvents(QWidget *pWidget, int type, int button, int buttons, int x, int y)
     379{
     380    QEvent::Type qtType = QEvent::None;
     381    Qt::MouseButtons qtButtons = Qt::NoButton;
     382    Qt::MouseButton qtButton = Qt::NoButton;
     383    Qt::MouseButton qtExtraButton = Qt::NoButton;
     384    Qt::Orientation qtOrientation = Qt::Horizontal;
     385    int wheelDelta = 0;
     386    /* Which button is used in the NSOtherMouse... cases? */
     387    if (button == 0)
     388        qtExtraButton = Qt::LeftButton;
     389    else if (button == 1)
     390        qtExtraButton = Qt::RightButton;
     391    else if (button == 2)
     392        qtExtraButton = Qt::MidButton;
     393    else if (button == 3)
     394        qtExtraButton = Qt::XButton1;
     395    else if (button == 4)
     396        qtExtraButton = Qt::XButton2;
     397    /* Map the NSEvent to a QEvent and define the Qt::Buttons when necessary. */
     398    switch(type)
     399    {
     400        case 1: /* NSLeftMouseDown */
     401        {
     402            qtType = QEvent::MouseButtonPress;
     403            qtButton = Qt::LeftButton;
     404            break;
     405        }
     406        case 2: /* NSLeftMouseUp */
     407        {
     408            qtType = QEvent::MouseButtonRelease;
     409            qtButton = Qt::LeftButton;
     410            break;
     411        }
     412        case 3: /* NSRightMouseDown */
     413        {
     414            qtType = QEvent::MouseButtonPress;
     415            qtButton = Qt::RightButton;
     416            break;
     417        }
     418        case 4: /* NSRightMouseUp */
     419        {
     420            qtType = QEvent::MouseButtonRelease;
     421            qtButton = Qt::RightButton;
     422            break;
     423        }
     424        case 5: /* NSMouseMoved */
     425        {
     426            qtType = QEvent::MouseMove;
     427            break;
     428        }
     429        case 6: /* NSLeftMouseDragged */
     430        {
     431            qtType = QEvent::MouseMove;
     432            qtButton = Qt::LeftButton;
     433            break;
     434        }
     435        case 7: /* NSRightMouseDragged */
     436        {
     437            qtType = QEvent::MouseMove;
     438            qtButton = Qt::RightButton;
     439            break;
     440        }
     441        case 22: /* NSScrollWheel */
     442        {
     443            qtType = QEvent::Wheel;
     444            if (y != 0)
     445            {
     446                wheelDelta = y;
     447                qtOrientation = Qt::Vertical;
     448            }
     449            else if (x != 0)
     450            {
     451                wheelDelta = x;
     452                qtOrientation = Qt::Horizontal;
     453            }
     454            x = y = 0;
     455            break;
     456        }
     457        case 25: /* NSOtherMouseDown */
     458        {
     459            qtType = QEvent::MouseButtonPress;
     460            qtButton = qtExtraButton;
     461            break;
     462        }
     463        case 26: /* NSOtherMouseUp */
     464        {
     465            qtType = QEvent::MouseButtonRelease;
     466            qtButton = qtExtraButton;
     467            break;
     468        }
     469        case 27: /* NSOtherMouseDragged */
     470        {
     471            qtType = QEvent::MouseMove;
     472            qtButton = qtExtraButton;
     473            break;
     474        }
     475        default: return;
     476    }
     477    /* Create a Qt::MouseButtons Mask. */
     478    if ((buttons & RT_BIT_32(0)) == RT_BIT_32(0))
     479        qtButtons |= Qt::LeftButton;
     480    if ((buttons & RT_BIT_32(1)) == RT_BIT_32(1))
     481        qtButtons |= Qt::RightButton;
     482    if ((buttons & RT_BIT_32(2)) == RT_BIT_32(2))
     483        qtButtons |= Qt::MidButton;
     484    if ((buttons & RT_BIT_32(3)) == RT_BIT_32(3))
     485        qtButtons |= Qt::XButton1;
     486    if ((buttons & RT_BIT_32(4)) == RT_BIT_32(4))
     487        qtButtons |= Qt::XButton2;
     488    /* Create a new mouse delta event and send it to the widget. */
     489    UIGrabMouseEvent *pEvent = new UIGrabMouseEvent(qtType, qtButton, qtButtons, x, y, wheelDelta, qtOrientation);
     490    qApp->sendEvent(pWidget, pEvent);
    342491}
    343492
  • trunk/src/VBox/Frontends/VirtualBox/src/platform/darwin/VBoxUtils-darwin.h

    r35424 r35740  
    8686
    8787bool darwinUnifiedToolbarEvents(const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser);
     88bool darwinMouseMoveEvents(const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser);
    8889void darwinCreateContextMenuEvent(void *pvWin, int x, int y);
    8990
     
    9192
    9293void darwinRetranslateAppMenu();
     94
     95void darwinSendDeltaEvents(QWidget *pWidget, int type, int button, int buttons, int x, int y);
    9396
    9497QString darwinResolveAlias(const QString &strFile);
     
    169172
    170173#ifndef __OBJC__
     174
     175#include <QEvent>
     176class UIGrabMouseEvent: public QEvent
     177{
     178public:
     179    enum { GrabMouseEvent = QEvent::User + 200 };
     180
     181    UIGrabMouseEvent(QEvent::Type type, Qt::MouseButton button, Qt::MouseButtons buttons, int x, int y, int wheelDelta, Qt::Orientation o)
     182      : QEvent((QEvent::Type)GrabMouseEvent)
     183      , m_type(type)
     184      , m_button(button)
     185      , m_buttons(buttons)
     186      , m_x(x)
     187      , m_y(y)
     188      , m_wheelDelta(wheelDelta)
     189      , m_orientation(o)
     190    {}
     191    QEvent::Type mouseEventType() const { return m_type; }
     192    Qt::MouseButton button() const { return m_button; }
     193    Qt::MouseButtons buttons() const { return m_buttons; }
     194    int xDelta() const { return m_x; }
     195    int yDelta() const { return m_y; }
     196    int wheelDelta() const { return m_wheelDelta; }
     197    Qt::Orientation orientation() const { return m_orientation; }
     198
     199private:
     200    /* Private members */
     201    QEvent::Type m_type;
     202    Qt::MouseButton m_button;
     203    Qt::MouseButtons m_buttons;
     204    int m_x;
     205    int m_y;
     206    int m_wheelDelta;
     207    Qt::Orientation m_orientation;
     208};
     209
    171210/********************************************************************************
    172211 *
     
    205244void darwinRegisterForUnifiedToolbarContextMenuEvents(QMainWindow *pWindow);
    206245void darwinUnregisterForUnifiedToolbarContextMenuEvents(QMainWindow *pWindow);
     246
     247void darwinMouseGrab(QWidget *pWidget);
     248void darwinMouseRelease(QWidget *pWidget);
    207249#endif /* !__OBJC__ */
    208250
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.cpp

    r35730 r35740  
    968968        /* Disable mouse and keyboard event compression/delaying to make sure we *really* get all of the events. */
    969969        ::CGSetLocalEventsSuppressionInterval(0.0);
    970         machineLogic()->mouseHandler()->setMouseCoalescingEnabled(false);
     970        ::darwinSetMouseCoalescingEnabled(false);
    971971
    972972        /* Register the event callback/hook and grab the keyboard. */
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.cpp

    r35509 r35740  
    174174        updateMouseCursorClipping();
    175175#elif defined (Q_WS_MAC)
    176         /* Move the mouse to the center of the visible area: */
    177         m_lastMousePos = visibleRectangle.center();
    178         QCursor::setPos(m_lastMousePos);
    179176        /* Grab all mouse events: */
    180         m_viewports[m_iMouseCaptureViewIndex]->grabMouse();
     177        ::darwinMouseGrab(m_viewports[m_iMouseCaptureViewIndex]);
    181178#else /* Q_WS_MAC */
    182179        /* Remember current mouse position: */
     
    212209        /* Update mouse clipping: */
    213210        updateMouseCursorClipping();
    214 #else /* Q_WS_WIN */
     211#elif defined(Q_WS_MAC)
     212        /* Releasing grabbed mouse from that view: */
     213        ::darwinMouseRelease(m_viewports[m_iMouseCaptureViewIndex]);
     214#else /* Q_WS_MAC */
    215215        /* Releasing grabbed mouse from that view: */
    216216        m_viewports[m_iMouseCaptureViewIndex]->releaseMouse();
    217 #endif /* !Q_WS_WIN */
     217#endif /* !Q_WS_MAC */
    218218        /* Reset mouse-capture index: */
    219219        m_iMouseCaptureViewIndex = -1;
     
    245245           (uisession()->isMouseIntegrated() ? 0 : UIMouseStateType_MouseAbsoluteDisabled);
    246246}
    247 
    248 #ifdef Q_WS_MAC
    249 void UIMouseHandler::setMouseCoalescingEnabled(bool fOn)
    250 {
    251     /* Enable mouse event compression if we leave the VM view.
    252      * This is necessary for having smooth resizing of the VM/other windows.
    253      * Disable mouse event compression if we enter the VM view.
    254      * So all mouse events are registered in the VM. */
    255     ::darwinSetMouseCoalescingEnabled(fOn);
    256 }
    257 #endif /* Q_WS_MAC */
    258247
    259248#ifdef Q_WS_X11
     
    513502            switch (pEvent->type())
    514503            {
     504#ifdef Q_WS_MAC
     505                case UIGrabMouseEvent::GrabMouseEvent:
     506                {
     507                    UIGrabMouseEvent *pDeltaEvent = static_cast<UIGrabMouseEvent*>(pEvent);
     508                    QPoint gl = m_lastMousePos;
     509                    QPoint p = QPoint(pDeltaEvent->xDelta() + gl.x(),
     510                                      pDeltaEvent->yDelta() + gl.y());
     511                    if (mouseEvent(pDeltaEvent->mouseEventType(), uScreenId,
     512                                   m_viewports[uScreenId]->mapFromGlobal(p), p,
     513                                   pDeltaEvent->buttons(),
     514                                   pDeltaEvent->wheelDelta(), pDeltaEvent->orientation()))
     515                        return true;
     516//
     517//                    QMouseEvent *pNewMouseEvent = new QMouseEvent(QEvent::MouseMove,
     518//                                                                  m_viewports[uScreenId]->mapFromGlobal(p), p,
     519//                                                                  Qt::NoButton,
     520//                                                                  Qt::NoButton,
     521//                                                                  Qt::NoModifier);
     522//
     523//
     524//                    /* Send that event to real destination: */
     525//                    QApplication::postEvent(m_viewports[uScreenId], pNewMouseEvent);
     526                    return false;
     527                    break;
     528                }
     529#endif /* Q_WS_MAC */
    515530                case QEvent::MouseMove:
    516531                case QEvent::MouseButtonRelease:
    517532                {
     533
     534                    printf("move event \n");
    518535                    /* Check if we should propagate this event to another window: */
    519536                    QWidget *pHoveredWidget = QApplication::widgetAt(QCursor::pos());
     
    599616                    /* Enable mouse event compression if we leave the VM view.
    600617                     * This is necessary for having smooth resizing of the VM/other windows: */
    601                     setMouseCoalescingEnabled(true);
     618                    ::darwinSetMouseCoalescingEnabled(true);
    602619                    break;
    603620                }
     
    609626                     * (this is when we have a valid event handler): */
    610627                    if (machineLogic()->keyboardHandler()->isKeyboardGrabbed())
    611                         setMouseCoalescingEnabled(false);
     628                        darwinSetMouseCoalescingEnabled(false);
    612629                    break;
    613630                }
     
    681698        ::UpdateWindow(m_viewports[uScreenId]->winId());
    682699#endif
    683 
    684700        CMouse mouse = session().GetConsole().GetMouse();
    685701        mouse.PutMouseEvent(globalPos.x() - m_lastMousePos.x(),
     
    687703                            iWheelVertical, iWheelHorizontal, iMouseButtonsState);
    688704
    689 #ifdef Q_WS_MAC
    690         /* Keep the mouse from leaving the widget.
    691          * This is a bit tricky to get right because if it escapes we won't necessarily
    692          * get mouse events any longer and can warp it back. So, we keep safety zone
    693          * of up to 300 pixels around the borders of the widget to prevent this from
    694          * happening. Also, the mouse is warped back to the center of the widget.
    695          * (Note, relativePos seems to be unreliable, it caused endless recursion here at one points...)
    696          * (Note, synergy and other remote clients might not like this cursor warping.) */
    697         QRect rect = m_viewports[uScreenId]->visibleRegion().boundingRect();
    698         QPoint pw = m_viewports[uScreenId]->mapToGlobal(m_viewports[uScreenId]->pos());
    699         rect.translate(pw.x(), pw.y());
    700 
    701         QRect dpRect = QApplication::desktop()->screenGeometry(m_viewports[uScreenId]);
    702         if (rect.intersects(dpRect))
    703             rect = rect.intersect(dpRect);
    704 
    705         int iWsafe = rect.width() / 6;
    706         rect.setWidth(rect.width() - iWsafe * 2);
    707         rect.setLeft(rect.left() + iWsafe);
    708 
    709         int iHsafe = rect.height() / 6;
    710         rect.setWidth(rect.height() - iHsafe * 2);
    711         rect.setTop(rect.top() + iHsafe);
    712 
    713         if (rect.contains(globalPos, true))
    714             m_lastMousePos = globalPos;
    715         else
    716         {
    717             m_lastMousePos = rect.center();
    718             QCursor::setPos(m_lastMousePos);
    719         }
    720 #else /* Q_WS_MAC */
    721 
     705#ifdef Q_WS_WIN
    722706        /* Bringing mouse to the opposite side to simulate the endless moving: */
    723707
    724 # ifdef Q_WS_WIN
    725708        /* Acquiring visible viewport rectangle in local coordinates: */
    726709        QRect viewportRectangle = m_viewports[uScreenId]->visibleRegion().boundingRect();
     
    755738        }
    756739        else
    757         {
    758740            m_lastMousePos = globalPos;
    759         }
    760 # else /* Q_WS_WIN */
     741#else /* Q_WS_WIN */
    761742        int iWe = QApplication::desktop()->width() - 1;
    762743        int iHe = QApplication::desktop()->height() - 1;
     
    774755        {
    775756            m_lastMousePos =  p;
     757            /* No need for cursor updating on the Mac, there is no one. */
     758# ifndef Q_WS_MAC
    776759            QCursor::setPos(m_lastMousePos);
     760# endif /* Q_WS_MAC */
    777761        }
    778762        else
    779         {
    780763            m_lastMousePos = globalPos;
    781         }
    782 # endif /* !Q_WS_WIN */
    783 #endif /* !Q_WS_MAC */
     764#endif /* !Q_WS_WIN */
    784765        return true; /* stop further event handling */
    785766    }
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.h

    r34471 r35740  
    6666    int mouseState() const;
    6767
    68 #ifdef Q_WS_MAC
    69     /* Enable mouse event compression if we leave the VM view.
    70      * This is necessary for having smooth resizing of the VM/other windows.
    71      * Disable mouse event compression if we enter the VM view.
    72      * So all mouse events are registered in the VM. */
    73     void setMouseCoalescingEnabled(bool fOn);
    74 #endif /* Q_WS_MAC */
    75 
    7668#ifdef Q_WS_X11
    7769    bool x11EventFilter(XEvent *pEvent, ulong uScreenId);
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette