如何使用Qt和X11事件识别KeyPress事件?

时间:2011-05-04 12:21:17

标签: qt cross-platform x11 keypress

我正在一个需要识别物理键位置,Control,Shift和Winkey的项目中工作。我需要知道键盘中每个左侧或右侧的位置。

为此,我需要使用Qt处理X11events和WinEvents。我在Windows中做得很好,忘记了Alt Gr的可怕部分,我无法处理。在Linux中,我试图做同样的事情:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#if WIN32
#include <windows.h>
#else
#include <X11/XKBlib.h>
#ifdef KeyPress
const int XKeyPress = KeyPress;
#undef KeyPress
#endif    
#endif

#include "main.h"
#include <QFile>
#include <QDebug>
#include <QX11Info>


#if WIN32
bool MainWindow::winEvent( MSG* msg, long* result )
{  
    if(msg->message == WM_KEYDOWN || msg->message == WM_HOTKEY)
    {   
        SHORT state;
        switch(msg->wParam)
        {

        case VK_CONTROL:  
            // the Alt Gr is handled using Ctrl+Alt+Shift (I Guess)
            state = GetKeyState(VK_SHIFT);
            if(state == TRUE)
                keyPressEvent(msg->wParam, "Key_AltGr");
            else{
                state = GetKeyState(VK_LCONTROL);
                if(state & VK_LCONTROL)
                    keyPressEvent(msg->wParam, "Key_ControlL");
                else
                    keyPressEvent(msg->wParam, "Key_ControlR");
            }
            break;            
        case VK_SHIFT:
            state = GetKeyState(VK_LSHIFT);
            if(state & VK_LSHIFT)
                keyPressEvent(msg->wParam, "Key_ShiftL");
            else
                keyPressEvent(msg->wParam, "Key_ShiftR");
            break;            
        case VK_MENU:// alt
            state = GetKeyState(VK_SHIFT);
            if(state == TRUE)
                keyPressEvent(msg->wParam, "Key_AltGr");
            break;

        case VK_SNAPSHOT:
            keyPressEvent(msg->wParam, "Key_Print");
            break;

        default:
            return false;  
        }

        return true;        
    } 
    return false;
}
#else
bool MainWindow::x11Event(XEvent *xe)
{   
    switch(xe->type)
    {
    case XKeyPress:
        switch (xe->xkey.keycode)
        {
        case 37://Control_L
            keyPressEvent(xe->xkey.keycode, "Key_ControlL");
            break;
        case 105://Control_R
            keyPressEvent(xe->xkey.keycode, "Key_ControlR");
            break;
        case 50://Shift_L
            keyPressEvent(xe->xkey.keycode, "Key_ShiftL");
            break;
        case 62://Shift_R
            keyPressEvent(xe->xkey.keycode, "Key_ShiftR");
            break;
        case 133://Super_L
            keyPressEvent(xe->xkey.keycode, "Key_SuperL");
            break;
        case 134://Super_R
            keyPressEvent(xe->xkey.keycode, "Key_SuperR");
            break;
        default:
            return false;
        }
        return true;
        break;
    }
    return false;
}
#endif

方法x11Event案例XKeyPress(在调试模式下,它是2)永远不会满足,但是如果你看:

grep KeyPress  /usr/include/X11/X.h 
#define KeyPressMask            (1L<<0)  
#define KeyPress        2

常量是正确的,但类型永远不会相等2.如果我将常量XKeyPress更改为28,看起来像

maiko@cits-d530:release$ grep 28  /usr/include/X11/X.h 
#define PropertyNotify      28
#define FirstExtensionError 128

效果很好。

THX

1 个答案:

答案 0 :(得分:1)

我不知道为什么它不起作用。在KeyPress之后没有调用x11events,只有当我移动鼠标时才调用它,然后触发所有尚未触发的事件。为此,我收到了相同类型的所有事件,我无法比较每个事件的类型,因为它是垃圾。

要解决这个问题,我在main.cow中实现了QAbstractEventDispatcher,它是mainwindow.cpp的所有者(来自我的KeyPress事件的接收者) 的的main.cpp

 QAbstractEventDispatcher *evInstance = QAbstractEventDispatcher::instance(0);
    evInstance->setEventFilter((QAbstractEventDispatcher::EventFilter) MainWindow::customEventFilter);

    MainWindow *w = new MainWindow(program.getLayoutFile(), program.getUnicode());
    w->show();
    a.exec();

但是方法customEventFilter需要是静态的。我更改了所有代码,但是工作正常,customEventFilter可以在linux或windows上接收所有系统范围的事件。

再见。