VirtualBox

Changeset 35791 in vbox


Ignore:
Timestamp:
Jan 31, 2011 3:36:13 PM (14 years ago)
Author:
vboxsync
Message:

FE/Qt: 5245: GUI support for complex host-key combinations: Better host-key snapshotting mechanism.

Location:
trunk/src/VBox/Frontends/VirtualBox/src/widgets
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIHotKeyEditor.cpp

    r35749 r35791  
    2828#include <QStylePainter>
    2929#include <QKeyEvent>
     30#include <QTimer>
    3031
    3132#ifdef Q_WS_WIN
     
    5657# include "VBoxUtils.h"
    5758# include <Carbon/Carbon.h>
    58 # include <QTimer>
    5959#endif /* Q_WS_MAC */
    6060
     
    203203
    204204#ifdef Q_WS_WIN
    205 int UIHotKey::distinguishModifierVKey(int wParam)
     205int UIHotKey::distinguishModifierVKey(int wParam, int lParam)
    206206{
    207207    int iKeyCode = wParam;
     
    209209    {
    210210        case VK_SHIFT:
    211             if (::GetKeyState(VK_LSHIFT) & 0x8000) iKeyCode = VK_LSHIFT;
    212             else if (::GetKeyState(VK_RSHIFT) & 0x8000) iKeyCode = VK_RSHIFT;
    213             break;
     211        {
     212            UINT uCurrentScanCode = (lParam & 0x01FF0000) >> 16;
     213            UINT uLeftScanCode = ::MapVirtualKey(iKeyCode, 0);
     214            if (uCurrentScanCode == uLeftScanCode)
     215                iKeyCode = VK_LSHIFT;
     216            else
     217                iKeyCode = VK_RSHIFT;
     218            break;
     219        }
    214220        case VK_CONTROL:
    215             if (::GetKeyState(VK_LCONTROL) & 0x8000) iKeyCode = VK_LCONTROL;
    216             else if (::GetKeyState(VK_RCONTROL) & 0x8000) iKeyCode = VK_RCONTROL;
    217             break;
     221        {
     222            UINT uCurrentScanCode = (lParam & 0x01FF0000) >> 16;
     223            UINT uLeftScanCode = ::MapVirtualKey(iKeyCode, 0);
     224            if (uCurrentScanCode == uLeftScanCode)
     225                iKeyCode = VK_LCONTROL;
     226            else
     227                iKeyCode = VK_RCONTROL;
     228            break;
     229        }
    218230        case VK_MENU:
    219             if (::GetKeyState(VK_LMENU) & 0x8000) iKeyCode = VK_LMENU;
    220             else if (::GetKeyState(VK_RMENU) & 0x8000) iKeyCode = VK_RMENU;
    221             break;
     231        {
     232            UINT uCurrentScanCode = (lParam & 0x01FF0000) >> 16;
     233            UINT uLeftScanCode = ::MapVirtualKey(iKeyCode, 0);
     234            if (uCurrentScanCode == uLeftScanCode)
     235                iKeyCode = VK_LMENU;
     236            else
     237                iKeyCode = VK_RMENU;
     238            break;
     239        }
    222240    }
    223241    return iKeyCode;
     
    283301UIHotKeyEditor::UIHotKeyEditor(QWidget *pParent)
    284302    : QLabel(pParent)
     303    , m_pReleaseTimer(0)
    285304    , m_fStartNewSequence(true)
    286305{
     
    298317    setPalette(p);
    299318
     319    /* Setup release-pending-keys timer: */
     320    m_pReleaseTimer = new QTimer(this);
     321    m_pReleaseTimer->setInterval(200);
     322    connect(m_pReleaseTimer, SIGNAL(timeout()), this, SLOT(sltReleasePendingKeys()));
     323
    300324#ifdef Q_WS_X11
    301325    /* Initialize the X keyboard subsystem: */
     
    307331    UICocoaApplication::instance()->registerForNativeEvents(RT_BIT_32(10) | RT_BIT_32(11) | RT_BIT_32(12) /* NSKeyDown  | NSKeyUp | | NSFlagsChanged */, UIHotKeyEditor::darwinEventHandlerProc, this);
    308332    ::DarwinGrabKeyboard(false /* just modifiers */);
    309 
    310     m_pRemoveTimer = new QTimer(this);
    311     m_pRemoveTimer->setInterval(200);
    312     connect(m_pRemoveTimer, SIGNAL(timeout()),
    313             this, SLOT(removePendingKeys()));
    314333#endif /* Q_WS_MAC */
    315334}
     
    382401        {
    383402            /* Get key-code: */
    384             int iKeyCode = UIHotKey::distinguishModifierVKey((int)pMsg->wParam);
     403            int iKeyCode = UIHotKey::distinguishModifierVKey((int)pMsg->wParam, (int)pMsg->lParam);
    385404
    386405            /* Check if symbol is valid else pass it to Qt: */
    387406            if (!UIHotKey::isValidKey(iKeyCode))
    388407                return false;
     408
     409            /* Stop the release-pending-keys timer: */
     410            m_pReleaseTimer->stop();
    389411
    390412            /* Key press: */
     
    394416                if (m_fStartNewSequence)
    395417                    m_shownKeys.clear();
    396 
     418                /* Make sure any keys pending for releasing are processed: */
     419                sltReleasePendingKeys();
    397420                /* Check maximum combo size: */
    398421                if (m_shownKeys.size() < UIHotKeyCombination::m_iMaxComboSize)
    399422                {
    400423                    /* Remember pressed symbol: */
    401                     m_pressedKeys << pMsg->wParam;
     424                    m_pressedKeys << iKeyCode;
    402425                    m_shownKeys.insert(iKeyCode, UIHotKey::toString(iKeyCode));
    403426
     
    409432            else if (pMsg->message == WM_KEYUP || pMsg->message == WM_SYSKEYUP)
    410433            {
    411                 /* Remove pressed symbol: */
    412                 m_pressedKeys.remove(pMsg->wParam);
    413 
    414                 /* If pressed keys map is empty => start new sequence: */
    415                 if (m_pressedKeys.isEmpty())
     434                /* Queue released symbol for processing: */
     435                m_releasedKeys << iKeyCode;
     436
     437                /* If all pressed keys are now pending for releasing we should stop further handling.
     438                 * Now we have the status the user want: */
     439                if (m_pressedKeys == m_releasedKeys)
     440                {
     441                    m_pressedKeys.clear();
     442                    m_releasedKeys.clear();
    416443                    m_fStartNewSequence = true;
     444                }
     445                else
     446                    m_pReleaseTimer->start();
    417447            }
    418448
     
    448478                return false;
    449479
     480            /* Stop the release-pending-keys timer: */
     481            m_pReleaseTimer->stop();
     482
    450483            /* Key press: */
    451484            if (pEvent->type == XKeyPress)
     
    454487                if (m_fStartNewSequence)
    455488                    m_shownKeys.clear();
    456 
     489                /* Make sure any keys pending for releasing are processed: */
     490                sltReleasePendingKeys();
    457491                /* Check maximum combo size: */
    458492                if (m_shownKeys.size() < UIHotKeyCombination::m_iMaxComboSize)
     
    469503            else if (pEvent->type == XKeyRelease)
    470504            {
    471                 /* Remove pressed symbol: */
    472                 m_pressedKeys.remove(iKeySym);
    473 
    474                 /* If pressed keys map is empty => start new sequence: */
    475                 if (m_pressedKeys.isEmpty())
     505                /* Queue released symbol for processing: */
     506                m_releasedKeys << iKeySym;
     507
     508                /* If all pressed keys are now pending for releasing we should stop further handling.
     509                 * Now we have the status the user want: */
     510                if (m_pressedKeys == m_releasedKeys)
     511                {
     512                    m_pressedKeys.clear();
     513                    m_releasedKeys.clear();
    476514                    m_fStartNewSequence = true;
     515                }
     516                else
     517                    m_pReleaseTimer->start();
    477518            }
    478519
     
    493534bool UIHotKeyEditor::darwinEventHandlerProc(const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser)
    494535{
    495     UIHotKeyEditor *edit = (UIHotKeyEditor*)pvUser;
     536    UIHotKeyEditor *pEditor = (UIHotKeyEditor*)pvUser;
    496537    EventRef inEvent = (EventRef)pvCarbonEvent;
    497538    UInt32 EventClass = ::GetEventClass(inEvent);
    498539    if (EventClass == kEventClassKeyboard)
    499         return edit->darwinKeyboardEvent(pvCocoaEvent, inEvent);
     540        return pEditor->darwinKeyboardEvent(pvCocoaEvent, inEvent);
    500541    return false;
    501542}
     
    533574                /* Stop the delete pending keys timer. */
    534575                m_pRemoveTimer->stop();
    535                 /* If modifierMask is empty, no key is pressed anymore. Stop
    536                  * all key handling and the deletion of keys. This is the
    537                  * status the user want. */
     576                /* If modifierMask is empty, no key is pressed anymore.
     577                 * Stop all key handling and the deletion of keys. This is the status the user want: */
    538578                if (!modifierMask)
    539579                    m_fStartNewSequence = true;
     
    541581                else if (!(changed & modifierMask))
    542582                {
    543                     /* Queue pressed symbol for removing: */
    544                     m_removeKeys.insert(iKeyCode);
    545                     m_pRemoveTimer->start();
     583                    /* Queue released symbol for processing: */
     584                    m_releasedKeys << iKeyCode;
     585                    m_pReleaseTimer->start();
    546586                }
    547587                /* Key press: */
     
    551591                    if (m_fStartNewSequence)
    552592                        m_shownKeys.clear();
    553                     /* Make sure any keys pending for removal are removed. */
    554                     removePendingKeys();
     593                    /* Make sure any keys pending for releasing are processed: */
     594                    sltReleasePendingKeys();
    555595                    /* Check maximum combo size: */
    556596                    if (m_shownKeys.size() < UIHotKeyCombination::m_iMaxComboSize)
     
    575615    return false;
    576616}
    577 
    578 void UIHotKeyEditor::removePendingKeys()
    579 {
    580     /* Stop the timer, we process all pending keys at once. */
    581     m_pRemoveTimer->stop();
    582     /* Something to do? */
    583     if (!m_removeKeys.isEmpty())
    584     {
    585         /* Remove every key. */
    586         foreach(int v, m_removeKeys)
    587         {
    588             m_pressedKeys.remove(v);
    589             m_shownKeys.remove(v);
    590         }
    591         m_removeKeys.clear();
    592         if (m_pressedKeys.isEmpty())
    593             m_fStartNewSequence = true;
    594     }
    595     /* Make sure the user see what happens. */
    596     updateText();
    597 }
    598 
    599617#endif /* Q_WS_MAC */
    600618
     
    648666}
    649667
     668void UIHotKeyEditor::sltReleasePendingKeys()
     669{
     670    /* Stop the timer, we process all pending keys at once: */
     671    m_pReleaseTimer->stop();
     672    /* Something to do? */
     673    if (!m_releasedKeys.isEmpty())
     674    {
     675        /* Remove every key: */
     676        QSetIterator<int> iterator(m_releasedKeys);
     677        while (iterator.hasNext())
     678        {
     679            int iKeyCode = iterator.next();
     680            m_pressedKeys.remove(iKeyCode);
     681            m_shownKeys.remove(iKeyCode);
     682        }
     683        m_releasedKeys.clear();
     684        if (m_pressedKeys.isEmpty())
     685            m_fStartNewSequence = true;
     686    }
     687    /* Make sure the user see what happens: */
     688    updateText();
     689}
     690
    650691void UIHotKeyEditor::updateText()
    651692{
  • trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIHotKeyEditor.h

    r35749 r35791  
    3232    bool isValidKey(int iKeyCode);
    3333#ifdef Q_WS_WIN
    34     int distinguishModifierVKey(int wParam);
     34    int distinguishModifierVKey(int wParam, int lParam);
    3535#endif /* Q_WS_WIN */
    3636#ifdef Q_WS_X11
     
    8181    void paintEvent(QPaintEvent *pEvent);
    8282
     83private slots:
     84
     85    void sltReleasePendingKeys();
     86
    8387private:
    8488
     
    8690
    8791    QSet<int> m_pressedKeys;
     92    QSet<int> m_releasedKeys;
    8893    QMap<int, QString> m_shownKeys;
    8994
     95    QTimer* m_pReleaseTimer;
    9096    bool m_fStartNewSequence;
    9197
    9298#ifdef RT_OS_DARWIN
    93     QSet<int> m_removeKeys;
    94     QTimer* m_pRemoveTimer;
    9599    /* The current modifier key mask. Used to figure out which modifier
    96100     * key was pressed when we get a kEventRawKeyModifiersChanged event. */
    97101    uint32_t m_uDarwinKeyModifiers;
    98 private slots:
    99     void removePendingKeys();
    100102#endif /* RT_OS_DARWIN */
    101103};
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