diff options
Diffstat (limited to 'src/platformsupport/input')
9 files changed, 211 insertions, 21 deletions
diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp index 0841544208..9c44283b0e 100644 --- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp +++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp @@ -93,13 +93,15 @@ QEvdevKeyboardHandler::~QEvdevKeyboardHandler() qt_safe_close(m_fd); } -QEvdevKeyboardHandler *QEvdevKeyboardHandler::create(const QString &device, const QString &specification) +QEvdevKeyboardHandler *QEvdevKeyboardHandler::create(const QString &device, + const QString &specification, + const QString &defaultKeymapFile) { #ifdef QT_QPA_KEYMAP_DEBUG qWarning() << "Try to create keyboard handler for" << device << specification; #endif - QString keymapFile; + QString keymapFile = defaultKeymapFile; int repeatDelay = 400; int repeatRate = 80; bool disableZap = false; @@ -406,6 +408,53 @@ QEvdevKeyboardHandler::KeycodeAction QEvdevKeyboardHandler::processKeycode(quint #ifdef QT_QPA_KEYMAP_DEBUG qWarning("Processing: uni=%04x, qt=%08x, qtmod=%08x", unicode, qtcode & ~modmask, (qtcode & modmask)); #endif + //If NumLockOff and keypad key pressed remap event sent + if (!m_locks[1] && + (qtcode & Qt::KeypadModifier) && + keycode >= 71 && + keycode <= 83 && + keycode != 74 && + keycode != 78) { + + unicode = 0xffff; + int oldMask = (qtcode & modmask); + switch (keycode) { + case 71: //7 --> Home + qtcode = Qt::Key_Home; + break; + case 72: //8 --> Up + qtcode = Qt::Key_Up; + break; + case 73: //9 --> PgUp + qtcode = Qt::Key_PageUp; + break; + case 75: //4 --> Left + qtcode = Qt::Key_Left; + break; + case 76: //5 --> Clear + qtcode = Qt::Key_Clear; + break; + case 77: //6 --> right + qtcode = Qt::Key_Right; + break; + case 79: //1 --> End + qtcode = Qt::Key_End; + break; + case 80: //2 --> Down + qtcode = Qt::Key_Down; + break; + case 81: //3 --> PgDn + qtcode = Qt::Key_PageDown; + break; + case 82: //0 --> Ins + qtcode = Qt::Key_Insert; + break; + case 83: //, --> Del + qtcode = Qt::Key_Delete; + break; + } + qtcode ^= oldMask; + } // send the result to the server processKeyEvent(keycode, unicode, qtcode & ~modmask, Qt::KeyboardModifiers(qtcode & modmask), pressed, autorepeat); @@ -435,6 +484,29 @@ void QEvdevKeyboardHandler::unloadKeymap() memset(m_locks, 0, sizeof(m_locks)); m_composing = 0; m_dead_unicode = 0xffff; + + //Set locks according to keyboard leds + quint16 ledbits[1]; + memset(ledbits, 0, sizeof(ledbits)); + if (::ioctl(m_fd, EVIOCGLED(sizeof(ledbits)), ledbits) < 0) { + qWarning("Failed to query led states. Settings numlock & capslock off"); + switchLed(LED_NUML,false); + switchLed(LED_CAPSL, false); + switchLed(LED_SCROLLL,false); + } else { + //Capslock + if ((ledbits[0]&0x02) > 0) + m_locks[0] = 1; + //Numlock + if ((ledbits[0]&0x01) > 0) + m_locks[1] = 1; + //Scrollock + if ((ledbits[0]&0x04) > 0) + m_locks[2] = 1; +#ifdef QT_QPA_KEYMAP_DEBUG + qWarning("numlock=%d , capslock=%d, scrolllock=%d",m_locks[1],m_locks[0],m_locks[2]); +#endif + } } bool QEvdevKeyboardHandler::loadKeymap(const QString &file) diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h index 81bc2f6154..06b7818135 100644 --- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h +++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h @@ -156,7 +156,9 @@ public: SwitchConsoleMask = 0x0000007f }; - static QEvdevKeyboardHandler *create(const QString &device, const QString &specification); + static QEvdevKeyboardHandler *create(const QString &device, + const QString &specification, + const QString &defaultKeymapFile = QString()); static Qt::KeyboardModifiers toQtModifiers(quint8 mod) { @@ -172,13 +174,14 @@ public: return qtmod; } + bool loadKeymap(const QString &file); + void unloadKeymap(); + private slots: void readKeycode(); KeycodeAction processKeycode(quint16 keycode, bool pressed, bool autorepeat); private: - void unloadKeymap(); - bool loadKeymap(const QString &file); void processKeyEvent(int nativecode, int unicode, int qtcode, Qt::KeyboardModifiers modifiers, bool isPress, bool autoRepeat); void switchLed(int, bool); diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp index 4932087c5f..4ceaf98055 100644 --- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp +++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp @@ -113,7 +113,7 @@ void QEvdevKeyboardManager::addKeyboard(const QString &deviceNode) #endif QEvdevKeyboardHandler *keyboard; - keyboard = QEvdevKeyboardHandler::create(deviceNode, m_spec); + keyboard = QEvdevKeyboardHandler::create(deviceNode, m_spec, m_defaultKeymapFile); if (keyboard) m_keyboards.insert(deviceNode, keyboard); else @@ -132,4 +132,28 @@ void QEvdevKeyboardManager::removeKeyboard(const QString &deviceNode) } } +void QEvdevKeyboardManager::loadKeymap(const QString &file) +{ + m_defaultKeymapFile = file; + + if (file.isEmpty()) { + // Restore the default, which is either the built-in keymap or + // the one given in the plugin spec. + QString keymapFromSpec; + foreach (const QString &arg, m_spec.split(QLatin1Char(':'))) { + if (arg.startsWith(QLatin1String("keymap="))) + keymapFromSpec = arg.mid(7); + } + foreach (QEvdevKeyboardHandler *handler, m_keyboards) { + if (keymapFromSpec.isEmpty()) + handler->unloadKeymap(); + else + handler->loadKeymap(keymapFromSpec); + } + } else { + foreach (QEvdevKeyboardHandler *handler, m_keyboards) + handler->loadKeymap(file); + } +} + QT_END_NAMESPACE diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager_p.h b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager_p.h index 0b1ccc23ab..c59de3ca09 100644 --- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager_p.h +++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager_p.h @@ -70,6 +70,8 @@ public: QEvdevKeyboardManager(const QString &key, const QString &specification, QObject *parent = 0); ~QEvdevKeyboardManager(); + void loadKeymap(const QString &file); + private slots: void addKeyboard(const QString &deviceNode = QString()); void removeKeyboard(const QString &deviceNode); @@ -78,6 +80,7 @@ private: QString m_spec; QHash<QString,QEvdevKeyboardHandler*> m_keyboards; QDeviceDiscovery *m_deviceDiscovery; + QString m_defaultKeymapFile; }; QT_END_NAMESPACE diff --git a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp index 92f807095f..611a7f9d6d 100644 --- a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp +++ b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp @@ -60,6 +60,8 @@ //#define QT_QPA_MOUSE_HANDLER_DEBUG +#define TEST_BIT(array, bit) (array[bit/8] & (1<<(bit%8))) + QT_BEGIN_NAMESPACE QEvdevMouseHandler *QEvdevMouseHandler::create(const QString &device, const QString &specification) @@ -71,6 +73,7 @@ QEvdevMouseHandler *QEvdevMouseHandler::create(const QString &device, const QStr bool compression = true; int jitterLimit = 0; int grab = 0; + bool abs = false; QStringList args = specification.split(QLatin1Char(':')); foreach (const QString &arg, args) { @@ -80,27 +83,37 @@ QEvdevMouseHandler *QEvdevMouseHandler::create(const QString &device, const QStr jitterLimit = arg.mid(9).toInt(); else if (arg.startsWith(QLatin1String("grab="))) grab = arg.mid(5).toInt(); + else if (arg == QLatin1String("abs")) + abs = true; } int fd; fd = qt_safe_open(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0); if (fd >= 0) { ::ioctl(fd, EVIOCGRAB, grab); - return new QEvdevMouseHandler(device, fd, compression, jitterLimit); + return new QEvdevMouseHandler(device, fd, abs, compression, jitterLimit); } else { qWarning("Cannot open mouse input device '%s': %s", qPrintable(device), strerror(errno)); return 0; } } -QEvdevMouseHandler::QEvdevMouseHandler(const QString &device, int fd, bool compression, int jitterLimit) +QEvdevMouseHandler::QEvdevMouseHandler(const QString &device, int fd, bool abs, bool compression, int jitterLimit) : m_device(device), m_fd(fd), m_notify(0), m_x(0), m_y(0), m_prevx(0), m_prevy(0), - m_compression(compression), m_buttons(0), m_prevInvalid(true) + m_abs(abs), m_compression(compression), m_buttons(0), m_prevInvalid(true) { setObjectName(QLatin1String("Evdev Mouse Handler")); m_jitterLimitSquared = jitterLimit * jitterLimit; + // Some touch screens present as mice with absolute coordinates. + // These can not be differentiated from touchpads, so supplying abs to QT_QPA_EVDEV_MOUSE_PARAMETERS + // will force qevdevmousehandler to treat the coordinates as absolute, scaled to the hardware maximums. + // Turning this on will not affect mice as these do not report in absolute coordinates + // but will make touchpads act like touch screens + if (m_abs) + m_abs = getHardwareMaximum(); + // socket notifier for events on the mouse device QSocketNotifier *notifier; notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); @@ -113,16 +126,66 @@ QEvdevMouseHandler::~QEvdevMouseHandler() qt_safe_close(m_fd); } +// Ask touch screen hardware for information on coordinate maximums +// If any ioctls fail, revert to non abs mode +bool QEvdevMouseHandler::getHardwareMaximum() +{ + unsigned char absFeatures[(ABS_MAX / 8) + 1]; + memset(absFeatures, '\0', sizeof (absFeatures)); + + // test if ABS_X, ABS_Y are available + if (ioctl(m_fd, EVIOCGBIT(EV_ABS, sizeof (absFeatures)), absFeatures) == -1) + return false; + + if ((!TEST_BIT(absFeatures, ABS_X)) || (!TEST_BIT(absFeatures, ABS_Y))) + return false; + + // ask hardware for minimum and maximum values + struct input_absinfo absInfo; + if (ioctl(m_fd, EVIOCGABS(ABS_X), &absInfo) == -1) + return false; + + m_hardwareWidth = absInfo.maximum - absInfo.minimum; + + if (ioctl(m_fd, EVIOCGABS(ABS_Y), &absInfo) == -1) + return false; + + m_hardwareHeight = absInfo.maximum - absInfo.minimum; + + QRect g = QGuiApplication::primaryScreen()->virtualGeometry(); + m_hardwareScalerX = static_cast<qreal>(m_hardwareWidth) / (g.right() - g.left()); + m_hardwareScalerY = static_cast<qreal>(m_hardwareHeight) / (g.bottom() - g.top()); + +#ifdef QT_QPA_MOUSE_HANDLER_DEBUG + qDebug() << "Absolute pointing device"; + qDebug() << "hardware max x" << m_hardwareWidth; + qDebug() << "hardware max y" << m_hardwareHeight; + qDebug() << "hardware scalers x" << m_hardwareScalerX << "y" << m_hardwareScalerY; +#endif + + return true; +} + void QEvdevMouseHandler::sendMouseEvent() { - int x = m_x - m_prevx; - int y = m_y - m_prevy; + int x; + int y; + + if (!m_abs) { + x = m_x - m_prevx; + y = m_y - m_prevy; + } + else { + x = m_x / m_hardwareScalerX; + y = m_y / m_hardwareScalerY; + } + if (m_prevInvalid) { x = y = 0; m_prevInvalid = false; } - emit handleMouseEvent(x, y, m_buttons); + emit handleMouseEvent(x, y, m_abs, m_buttons); m_prevx = m_x; m_prevy = m_y; diff --git a/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h b/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h index 5d8a536ee1..ee284bd7ed 100644 --- a/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h +++ b/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h @@ -68,26 +68,32 @@ public: ~QEvdevMouseHandler(); signals: - void handleMouseEvent(int x, int y, Qt::MouseButtons buttons); + void handleMouseEvent(int x, int y, bool abs, Qt::MouseButtons buttons); void handleWheelEvent(int delta, Qt::Orientation orientation); private slots: void readMouseData(); private: - QEvdevMouseHandler(const QString &device, int fd, bool compression, int jitterLimit); + QEvdevMouseHandler(const QString &device, int fd, bool abs, bool compression, int jitterLimit); void sendMouseEvent(); + bool getHardwareMaximum(); QString m_device; int m_fd; QSocketNotifier *m_notify; int m_x, m_y; int m_prevx, m_prevy; + bool m_abs; bool m_compression; Qt::MouseButtons m_buttons; int m_jitterLimitSquared; bool m_prevInvalid; + int m_hardwareWidth; + int m_hardwareHeight; + qreal m_hardwareScalerY; + qreal m_hardwareScalerX; }; QT_END_NAMESPACE diff --git a/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp b/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp index 6c430091c1..87f3a4c9a0 100644 --- a/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp +++ b/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp @@ -111,11 +111,16 @@ QEvdevMouseManager::~QEvdevMouseManager() m_mice.clear(); } -void QEvdevMouseManager::handleMouseEvent(int x, int y, Qt::MouseButtons buttons) +void QEvdevMouseManager::handleMouseEvent(int x, int y, bool abs, Qt::MouseButtons buttons) { // update current absolute coordinates - m_x += x; - m_y += y; + if (!abs) { + m_x += x; + m_y += y; + } else { + m_x = x; + m_y = y; + } // clamp to screen geometry QRect g = QGuiApplication::primaryScreen()->virtualGeometry(); @@ -130,7 +135,9 @@ void QEvdevMouseManager::handleMouseEvent(int x, int y, Qt::MouseButtons buttons m_y = g.bottom() - m_yoffset; QPoint pos(m_x + m_xoffset, m_y + m_yoffset); - QWindowSystemInterface::handleMouseEvent(0, pos, pos, buttons); + // Cannot track the keyboard modifiers ourselves here. Instead, report the + // modifiers from the last key event that has been seen by QGuiApplication. + QWindowSystemInterface::handleMouseEvent(0, pos, pos, buttons, QGuiApplication::keyboardModifiers()); #ifdef QT_QPA_MOUSEMANAGER_DEBUG qDebug("mouse event %d %d %d", pos.x(), pos.y(), int(buttons)); @@ -140,7 +147,7 @@ void QEvdevMouseManager::handleMouseEvent(int x, int y, Qt::MouseButtons buttons void QEvdevMouseManager::handleWheelEvent(int delta, Qt::Orientation orientation) { QPoint pos(m_x + m_xoffset, m_y + m_yoffset); - QWindowSystemInterface::handleWheelEvent(0, pos, pos, delta, orientation); + QWindowSystemInterface::handleWheelEvent(0, pos, pos, delta, orientation, QGuiApplication::keyboardModifiers()); #ifdef QT_QPA_MOUSEMANAGER_DEBUG qDebug("mouse wheel event %dx%d %d %d", pos.x(), pos.y(), delta, int(orientation)); @@ -156,7 +163,7 @@ void QEvdevMouseManager::addMouse(const QString &deviceNode) QEvdevMouseHandler *handler; handler = QEvdevMouseHandler::create(deviceNode, m_spec); if (handler) { - connect(handler, SIGNAL(handleMouseEvent(int,int,Qt::MouseButtons)), this, SLOT(handleMouseEvent(int,int,Qt::MouseButtons))); + connect(handler, SIGNAL(handleMouseEvent(int,int,bool,Qt::MouseButtons)), this, SLOT(handleMouseEvent(int,int,bool,Qt::MouseButtons))); connect(handler, SIGNAL(handleWheelEvent(int,Qt::Orientation)), this, SLOT(handleWheelEvent(int,Qt::Orientation))); m_mice.insert(deviceNode, handler); } else { diff --git a/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h b/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h index 662b216b11..83d8b314aa 100644 --- a/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h +++ b/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h @@ -73,7 +73,7 @@ public: QDeviceDiscovery *deviceDiscovery() { return m_deviceDiscovery; } public slots: - void handleMouseEvent(int x, int y, Qt::MouseButtons buttons); + void handleMouseEvent(int x, int y, bool abs, Qt::MouseButtons buttons); void handleWheelEvent(int delta, Qt::Orientation orientation); private slots: diff --git a/src/platformsupport/input/evdevtouch/qevdevtouch.cpp b/src/platformsupport/input/evdevtouch/qevdevtouch.cpp index 563edf4fd7..6ed4abaeee 100644 --- a/src/platformsupport/input/evdevtouch/qevdevtouch.cpp +++ b/src/platformsupport/input/evdevtouch/qevdevtouch.cpp @@ -184,6 +184,8 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &specification, QString dev; int rotationAngle = 0; + bool invertx = false; + bool inverty = false; for (int i = 0; i < args.count(); ++i) { if (args.at(i).startsWith(QLatin1String("/dev/")) && dev.isEmpty()) { dev = args.at(i); @@ -201,6 +203,10 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &specification, break; } } + } else if (args.at(i) == QLatin1String("invertx")) { + invertx = true; + } else if (args.at(i) == QLatin1String("inverty")) { + inverty = true; } } @@ -326,6 +332,12 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &specification, if (rotationAngle) d->m_rotate = QTransform::fromTranslate(0.5, 0.5).rotate(rotationAngle).translate(-0.5, -0.5); + if (invertx) + d->m_rotate *= QTransform::fromTranslate(0.5, 0.5).scale(-1.0, 1.0).translate(-0.5, -0.5); + + if (inverty) + d->m_rotate *= QTransform::fromTranslate(0.5, 0.5).scale(1.0, -1.0).translate(-0.5, -0.5); + d->registerDevice(); } |