Capturing alt-tab event



  • I want to capture alt-tab event, so that my program will not be switched to other programs, as long as my program is under focus.

    to do this, I need to capture the alt-tab event. I'm using nativeEventFilter, but I don't know which native event I need to capture (I'm working on windows, but eventually I need to support linux and mac also).

    I tried WM_KEYUP and WM_SYSKEYUP. they won't work.

    is there a ALT_TAB event I can capture? or is there any other tricks I can play?

    I know that virtual box supports this and its ui seems to be in Qt.



  • so far haven't found how to achieve this on windows.
    this link suggests unregistering the default windows hotkey, but this method won't work on win7 and win8
    http://www.codeguru.com/cpp/misc/misc/keyboard/article.php/c433/Disabling-the-AltTab-key-combination.htm

    this method looks promising, but requires more code change in the client:
    http://stackoverflow.com/questions/11352343/how-can-i-disable-specific-windows-hotkeys-from-inside-a-software-using-c



  • method mentioned here should work for windows.
    http://www.windowsnetworking.com/kbase/WindowsTips/WindowsNT/AdminTips/Miscellaneous/DisableAltTab.html

    but I don't know how to do this on mac and linux. need to dig more.



  • I have successfully captured cmd+tab on mac by using Quartz event service, but there are two serious problems.

    http://brianlipkowitz.tumblr.com/post/4881199383/quartz-event-taps

    first, the user must run with root privilege. for users without CS background, this could be a bit difficult.

    second, the method monitors the key events sent to the entire system. the implementation has to be careful in order to not to break other apps.



  • ok, I installed virtualbox, and found out that it doesn't seem to require root user to capture alt-tab.

    after digging the source code, it seems that they achieved this by disabling default hotkeys.

    I need to experiment this myself.

    @
    /**

    • Disables or enabled global hot keys.

    • @param fDisable Pass 'true' to disable the hot keys, pass 'false' to re-enable them.
      */
      void DarwinDisableGlobalHotKeys(bool fDisable)
      {
      static unsigned s_cComplaints = 0;

      /*

      • Lazy connect to the core graphics service.
        */
        if (!g_fConnectedToCGS)
        {
        g_CGSConnection = _CGSDefaultConnection();
        g_fConnectedToCGS = true;
        }

      /*

      • Get the current mode.
        */
        CGSGlobalHotKeyOperatingMode enmMode = kCGSGlobalHotKeyInvalid;
        CGSGetGlobalHotKeyOperatingMode(g_CGSConnection, &enmMode);
        if ( enmMode != kCGSGlobalHotKeyEnable
        && enmMode != kCGSGlobalHotKeyDisable
        && enmMode != kCGSGlobalHotKeyDisableExceptUniversalAccess)
        {
        AssertMsgFailed(("%d\n", enmMode));
        if (s_cComplaints++ < 32)
        LogRel(("DarwinDisableGlobalHotKeys: Unexpected enmMode=%d\n", enmMode));
        return;
        }

      /*

      • Calc the new mode.
        */
        if (fDisable)
        {
        if (enmMode != kCGSGlobalHotKeyEnable)
        return;
        enmMode = kCGSGlobalHotKeyDisableExceptUniversalAccess;
        }
        else
        {
        if (enmMode != kCGSGlobalHotKeyDisableExceptUniversalAccess)
        return;
        enmMode = kCGSGlobalHotKeyEnable;
        }

      /*

      • Try set it and check the actual result.
        /
        CGSSetGlobalHotKeyOperatingMode(g_CGSConnection, enmMode);
        CGSGlobalHotKeyOperatingMode enmNewMode = kCGSGlobalHotKeyInvalid;
        CGSGetGlobalHotKeyOperatingMode(g_CGSConnection, &enmNewMode);
        if (enmNewMode != enmMode)
        {
        /
        If the screensaver kicks in we should ignore failure here. */
        AssertMsg(enmMode == kCGSGlobalHotKeyEnable, ("enmNewMode=%d enmMode=%d\n", enmNewMode, enmMode));
        if (s_cComplaints++ < 32)
        LogRel(("DarwinDisableGlobalHotKeys: Failed to change mode; enmNewMode=%d enmMode=%d\n", enmNewMode, enmMode));
        }
        }
        @


  • I verified that the above code could work, but it uses undocumented apis from the coregraphics framework:

    it turned out that they disabled the system default hotkeys by using undocumented hidden apis from the coregraphics framework.

    extern "C" {
    CGSConnection _CGSDefaultConnection(void);
    CGError CGSGetGlobalHotKeyOperatingMode(CGSConnection Connection, CGSGlobalHotKeyOperatingMode *enmMode);
    CGError CGSSetGlobalHotKeyOperatingMode(CGSConnection Connection, CGSGlobalHotKeyOperatingMode enmMode);
    }



  • just tested virtual box's solution for linux:

    XGrabKey(QX11Info::display(), AnyKey, AnyModifier, w.winId(), False, GrabModeAsync, GrabModeAsync);
    

    works like a charm


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.