20#include <QGuiApplication>
23#include <sys/keycodes.h>
25using namespace std::chrono_literals;
29static int qtKey(
int virtualKey, QChar::Category category)
31 if (Q_UNLIKELY(category == QChar::Other_NotAssigned))
33 else if (category == QChar::Other_PrivateUse)
36 return QChar::toUpper(virtualKey);
41 if (Q_UNLIKELY(category == QChar::Other_NotAssigned)) {
43 }
else if (category == QChar::Other_PrivateUse) {
44 return keyStringForPrivateUseQnxKey(sym);
46 return QStringView{QChar::fromUcs4(sym)}.toString();
52 if (cap >= 0x20 && cap <= 0x0ff) {
53 if (modifiers & KEYMOD_CTRL)
54 return QChar((
int)(key & 0x3f));
63 screen_get_event_property_pv(event,
64 screen_traits<T>::propertyName,
65 reinterpret_cast<
void**>(&t));
66 screen_traits<T>::destroy(t);
72 int objectType = SCREEN_OBJECT_TYPE_CONTEXT;
73 screen_get_event_property_iv(event, SCREEN_PROPERTY_OBJECT_TYPE, &objectType);
75 case SCREEN_OBJECT_TYPE_CONTEXT:
76 finishCloseEvent<screen_context_t>(event);
78 case SCREEN_OBJECT_TYPE_DEVICE:
79 finishCloseEvent<screen_device_t>(event);
81 case SCREEN_OBJECT_TYPE_DISPLAY:
84 case SCREEN_OBJECT_TYPE_GROUP:
85 finishCloseEvent<screen_group_t>(event);
87 case SCREEN_OBJECT_TYPE_PIXMAP:
88 finishCloseEvent<screen_pixmap_t>(event);
90 case SCREEN_OBJECT_TYPE_SESSION:
91 finishCloseEvent<screen_session_t>(event);
94 case SCREEN_OBJECT_TYPE_STREAM:
95 finishCloseEvent<screen_stream_t>(event);
98 case SCREEN_OBJECT_TYPE_WINDOW:
99 finishCloseEvent<screen_window_t>(event);
106using namespace Qt::StringLiterals;
109 : m_qnxIntegration(integration)
110 , m_lastButtonState(Qt::NoButton)
111 , m_lastMouseWindow(0)
117 m_touchDevice =
new QPointingDevice(
118 "touchscreen"_L1, 1, QInputDevice::DeviceType::TouchScreen,
119 QPointingDevice::PointerType::Finger,
120 QPointingDevice::Capability::Position | QPointingDevice::Capability::Area
121 | QPointingDevice::Capability::Pressure
122 | QPointingDevice::Capability::NormalizedPosition,
123 MaximumTouchPoints, 8);
124 QWindowSystemInterface::registerInputDevice(m_touchDevice);
126 m_mouseDevice =
new QPointingDevice(
"mouse"_L1, 2, QInputDevice::DeviceType::Mouse,
127 QPointingDevice::PointerType::Generic,
128 QPointingDevice::Capability::Position, 1, 8);
129 QWindowSystemInterface::registerInputDevice(m_mouseDevice);
132 for (
int i = 0; i < MaximumTouchPoints; i++) {
135 m_touchPoints[i].id = i;
138 m_touchPoints[i].pressure = 1.0;
141 m_touchPoints[i].state = QEventPoint::State::Released;
147 m_eventFilters.append(filter);
152 m_eventFilters.removeOne(filter);
160 "Failed to query event type");
162 return handleEvent(event, qnxType);
168 case SCREEN_EVENT_MTOUCH_TOUCH:
169 case SCREEN_EVENT_MTOUCH_MOVE:
170 case SCREEN_EVENT_MTOUCH_RELEASE:
171 handleTouchEvent(event, qnxType);
174 case SCREEN_EVENT_KEYBOARD:
175 handleKeyboardEvent(event);
178 case SCREEN_EVENT_POINTER:
179 handlePointerEvent(event);
182 case SCREEN_EVENT_CREATE:
183 handleCreateEvent(event);
186 case SCREEN_EVENT_CLOSE:
187 handleCloseEvent(event);
190 case SCREEN_EVENT_DISPLAY:
191 handleDisplayEvent(event);
194 case SCREEN_EVENT_PROPERTY:
195 handlePropertyEvent(event);
198 case SCREEN_EVENT_MANAGER:
199 handleManagerEvent(event);
204 qCDebug(lcQpaScreenEvents) << Q_FUNC_INFO <<
"Unknown event" << qnxType;
215 if (!(flags & KEY_CAP_VALID))
219 if ((flags & KEY_SYM_VALID) && sym ==
static_cast<
int>(0xFFFFFFFF))
220 flags &= ~(KEY_SYM_VALID);
222 Qt::KeyboardModifiers qtMod = Qt::NoModifier;
223 if (modifiers & KEYMOD_SHIFT)
224 qtMod |= Qt::ShiftModifier;
225 if (modifiers & KEYMOD_CTRL)
226 qtMod |= Qt::ControlModifier;
227 if (modifiers & KEYMOD_ALT)
228 qtMod |= Qt::AltModifier;
229 if (isKeypadKey(cap))
230 qtMod |= Qt::KeypadModifier;
232 QEvent::Type type = (flags & KEY_DOWN) ? QEvent::KeyPress : QEvent::KeyRelease;
234 int virtualKey = (flags & KEY_SYM_VALID) ? sym : cap;
235 QChar::Category category = QChar::category(virtualKey);
236 int key = qtKey(virtualKey, category);
237 QString keyStr = (flags & KEY_SYM_VALID) ? keyString(sym, category) :
238 capKeyString(cap, modifiers, key);
240 QWindowSystemInterface::handleExtendedKeyEvent(QGuiApplication::focusWindow(), type, key, qtMod,
241 scan, virtualKey, modifiers, keyStr, flags & KEY_REPEAT);
242 qCDebug(lcQpaScreenEvents) <<
"Qt key t=" << type <<
", k=" << key <<
", s=" << keyStr;
247 m_eventThread = eventThread;
248 connect(m_eventThread, &QQnxScreenEventThread::eventsPending,
249 this, &QQnxScreenEventHandler::processEvents);
250 connect(m_eventThread, &QQnxScreenEventThread::postEventReceived,
251 this, &QQnxScreenEventHandler::processPostEvent);
259 screen_event_t event =
nullptr;
260 if (screen_create_event(&event) != 0)
265 if (screen_get_event(m_eventThread->context(), event, 0) != 0)
268 int type = SCREEN_EVENT_NONE;
269 screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &type);
270 if (type == SCREEN_EVENT_NONE)
275 QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance();
276 bool handled = dispatcher && dispatcher->filterNativeEvent(QByteArrayLiteral(
"screen_event_t"), event, &result);
280 if (type == SCREEN_EVENT_CLOSE)
281 finishCloseEvent(event);
284 m_eventThread->armEventsPending(count);
285 screen_destroy_event(event);
293 "Failed to query event flags");
298 "Failed to query event sym");
302 "Failed to query event modifieres");
306 "Failed to query event scan");
310 "Failed to query event cap");
315 Q_FOREACH (QQnxScreenEventFilter *filter, m_eventFilters) {
316 if (filter->handleKeyboardEvent(flags, sym, modifiers, scan, cap, sequenceId)) {
331 screen_window_t qnxWindow;
334 "Failed to query event window");
336 qnxWindow =
static_cast<screen_window_t>(handle);
340 Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_BUTTONS, &buttonState),
341 "Failed to query event button state");
346 screen_get_event_property_iv(event, SCREEN_PROPERTY_SOURCE_POSITION, windowPos),
347 "Failed to query event window position");
352 "Failed to query event position");
357 screen_get_event_property_iv(event, SCREEN_PROPERTY_MOUSE_WHEEL, &wheelDelta),
358 "Failed to query event wheel delta");
361 Q_SCREEN_CHECKERROR(screen_get_event_property_llv(event, SCREEN_PROPERTY_TIMESTAMP, ×tamp),
362 "Failed to get timestamp");
368 if (qnxWindow != m_lastMouseWindow) {
372 QWindowSystemInterface::handleLeaveEvent(wOld);
373 qCDebug(lcQpaScreenEvents) <<
"Qt leave, w=" << wOld;
377 QWindowSystemInterface::handleEnterEvent(w);
378 qCDebug(lcQpaScreenEvents) <<
"Qt enter, w=" << w;
382 m_lastMouseWindow = qnxWindow;
390 QPoint globalPoint(pos[0], pos[1]);
391 QPoint localPoint(windowPos[0], windowPos[1]);
397 Qt::MouseButtons buttons = Qt::NoButton;
398 if (buttonState & 0x01)
399 buttons |= Qt::LeftButton;
400 if (buttonState & 0x02)
401 buttons |= Qt::MiddleButton;
402 if (buttonState & 0x04)
403 buttons |= Qt::RightButton;
404 if (buttonState & 0x08)
405 buttons |= Qt::ExtraButton1;
406 if (buttonState & 0x10)
407 buttons |= Qt::ExtraButton2;
408 if (buttonState & 0x20)
409 buttons |= Qt::ExtraButton3;
410 if (buttonState & 0x40)
411 buttons |= Qt::ExtraButton4;
412 if (buttonState & 0x80)
413 buttons |= Qt::ExtraButton5;
417 if (m_lastGlobalMousePoint != globalPoint || m_lastLocalMousePoint != localPoint) {
418 QWindowSystemInterface::handleMouseEvent(w, timestamp, m_mouseDevice, localPoint,
419 globalPoint, buttons, Qt::NoButton,
421 qCDebug(lcQpaScreenEvents) <<
"Qt mouse move, w=" << w <<
", (" << localPoint.x() <<
","
422 << localPoint.y() <<
"), b=" <<
static_cast<
int>(buttons);
425 if (m_lastButtonState != buttons) {
426 static const auto supportedButtons = { Qt::LeftButton, Qt::MiddleButton,
427 Qt::RightButton, Qt::ExtraButton1,
428 Qt::ExtraButton2, Qt::ExtraButton3,
429 Qt::ExtraButton4, Qt::ExtraButton5 };
431 int releasedButtons = (m_lastButtonState ^ buttons) & ~buttons;
432 for (
auto button : supportedButtons) {
433 if (releasedButtons & button) {
434 QWindowSystemInterface::handleMouseEvent(w, timestamp, m_mouseDevice,
435 localPoint, globalPoint, buttons,
436 button, QEvent::MouseButtonRelease);
437 qCDebug(lcQpaScreenEvents) <<
"Qt mouse release, w=" << w <<
", (" << localPoint.x()
438 <<
"," << localPoint.y() <<
"), b=" << button;
442 if (m_lastButtonState != 0 && buttons == 0) {
446 int pressedButtons = (m_lastButtonState ^ buttons) & buttons;
447 for (
auto button : supportedButtons) {
448 if (pressedButtons & button) {
449 QWindowSystemInterface::handleMouseEvent(w, timestamp, m_mouseDevice,
450 localPoint, globalPoint, buttons,
451 button, QEvent::MouseButtonPress);
452 qCDebug(lcQpaScreenEvents) <<
"Qt mouse press, w=" << w <<
", (" << localPoint.x()
453 <<
"," << localPoint.y() <<
"), b=" << button;
461 QPoint angleDelta(0, wheelDelta);
462 QWindowSystemInterface::handleWheelEvent(w, timestamp, m_mouseDevice, localPoint,
463 globalPoint, QPoint(), angleDelta);
464 qCDebug(lcQpaScreenEvents) <<
"Qt wheel, w=" << w <<
", (" << localPoint.x() <<
","
465 << localPoint.y() <<
"), d=" <<
static_cast<
int>(wheelDelta);
469 m_lastGlobalMousePoint = globalPoint;
470 m_lastLocalMousePoint = localPoint;
471 m_lastButtonState = buttons;
479 "Failed to query event position");
481 QCursor::setPos(pos[0], pos[1]);
485 Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_SOURCE_POSITION, windowPos),
486 "Failed to query event window position");
490 Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_TOUCH_ID, &touchId),
491 "Failed to query event touch id");
496 "Failed to query event window");
501 "Failed to query event touch area");
505 screen_get_event_property_iv(event, SCREEN_PROPERTY_TOUCH_PRESSURE, &touchPressure),
506 "Failed to query event touch pressure");
508 screen_window_t qnxWindow =
static_cast<screen_window_t>(handle);
511 if (touchId < MaximumTouchPoints) {
517 if (qnxWindow != m_lastMouseWindow) {
521 QWindowSystemInterface::handleLeaveEvent(wOld);
522 qCDebug(lcQpaScreenEvents) <<
"Qt leave, w=" << wOld;
526 QWindowSystemInterface::handleEnterEvent(w);
527 qCDebug(lcQpaScreenEvents) <<
"Qt enter, w=" << w;
530 m_lastMouseWindow = qnxWindow;
533 if (qnxType == SCREEN_EVENT_MTOUCH_RELEASE)
537 QPlatformScreen *platformScreen = QPlatformScreen::platformScreenForWindow(w);
538 QSizeF screenSize = platformScreen->geometry().size();
541 m_touchPoints[touchId].normalPosition =
542 QPointF(
static_cast<qreal>(pos[0]) / screenSize.width(),
543 static_cast<qreal>(pos[1]) / screenSize.height());
545 m_touchPoints[touchId].area = QRectF(w->geometry().left() + windowPos[0] - (touchArea[0]>>1),
546 w->geometry().top() + windowPos[1] - (touchArea[1]>>1),
547 (touchArea[0]>>1), (touchArea[1]>>1));
548 QWindow *parent = w->parent();
550 m_touchPoints[touchId].area.translate(parent->geometry().topLeft());
551 parent = parent->parent();
557 m_touchPoints[touchId].pressure =
static_cast<qreal>(touchPressure)/200.0;
559 if (m_touchPoints[touchId].pressure > 1)
560 m_touchPoints[touchId].pressure = 1;
563 QEvent::Type type = QEvent::None;
565 case SCREEN_EVENT_MTOUCH_TOUCH:
566 m_touchPoints[touchId].state = QEventPoint::State::Pressed;
567 type = QEvent::TouchBegin;
569 case SCREEN_EVENT_MTOUCH_MOVE:
570 m_touchPoints[touchId].state = QEventPoint::State::Updated;
571 type = QEvent::TouchUpdate;
573 case SCREEN_EVENT_MTOUCH_RELEASE:
574 m_touchPoints[touchId].state = QEventPoint::State::Released;
575 type = QEvent::TouchEnd;
580 QList<QWindowSystemInterface::TouchPoint> pointList;
581 for (
int i = 0; i < MaximumTouchPoints; i++) {
584 pointList.append(m_touchPoints[i]);
585 }
else if (m_touchPoints[i].state != QEventPoint::State::Released) {
587 m_touchPoints[i].state = QEventPoint::State::Stationary;
588 pointList.append(m_touchPoints[i]);
593 QWindowSystemInterface::handleTouchEvent(w, m_touchDevice, pointList);
594 qCDebug(lcQpaScreenEvents) <<
"Qt touch, w =" << w
595 <<
", p=" << m_touchPoints[touchId].area.topLeft()
603 screen_window_t window = 0;
605 screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, (
void**)&window),
606 "Failed to query window property");
608 Q_EMIT windowClosed(window);
613 QWindowSystemInterface::handleCloseEvent(w);
618 screen_window_t window = 0;
619 int object_type = -1;
622 screen_get_event_property_iv(event, SCREEN_PROPERTY_OBJECT_TYPE, &object_type),
623 "Failed to query object type for create event");
625 switch (object_type) {
627 case SCREEN_OBJECT_TYPE_CONTEXT:
628 case SCREEN_OBJECT_TYPE_GROUP:
629 case SCREEN_OBJECT_TYPE_DISPLAY:
630 case SCREEN_OBJECT_TYPE_DEVICE:
631 case SCREEN_OBJECT_TYPE_PIXMAP:
632 case SCREEN_OBJECT_TYPE_SESSION:
633 case SCREEN_OBJECT_TYPE_STREAM:
635 case SCREEN_OBJECT_TYPE_WINDOW:
638 screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, (
void**)&window),
639 "Failed to query window property");
641 Q_EMIT newWindowCreated(window);
645 qCDebug(lcQpaScreenEvents) <<
"Ignore create event for object type: " << object_type;
652 screen_display_t nativeDisplay = 0;
653 if (screen_get_event_property_pv(event, SCREEN_PROPERTY_DISPLAY, (
void **)&nativeDisplay) != 0) {
654 qWarning(
"QQnx: failed to query display property, errno=%d", errno);
659 if (screen_get_event_property_iv(event, SCREEN_PROPERTY_ATTACHED, &isAttached) != 0) {
660 qWarning(
"QQnx: failed to query display attached property, errno=%d", errno);
664 qCDebug(lcQpaScreenEvents) <<
"display attachment is now:" << isAttached;
666 QQnxScreen *screen = m_qnxIntegration->screenForNative(nativeDisplay);
671 screen_get_display_property_iv(nativeDisplay, SCREEN_PROPERTY_SIZE, val);
672 if (val[0] == 0 && val[1] == 0)
675 qCDebug(lcQpaScreenEvents) <<
"Creating new QQnxScreen for newly attached display";
676 m_qnxIntegration->createDisplay(nativeDisplay,
false );
678 }
else if (!isAttached) {
688 qCDebug(lcQpaScreenEvents) <<
"Removing display";
699 screen_get_event_property_iv(event, SCREEN_PROPERTY_OBJECT_TYPE, &objectType),
700 "Failed to query object type property");
702 if (objectType != SCREEN_OBJECT_TYPE_WINDOW)
706 screen_window_t window = 0;
707 if (Q_UNLIKELY(screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, (
void**)&window) != 0))
708 qFatal(
"QQnx: failed to query window property, errno=%d", errno);
711 qCDebug(lcQpaScreenEvents) <<
"handlePositionEvent on NULL window";
717 if (Q_UNLIKELY(screen_get_event_property_iv(event, SCREEN_PROPERTY_NAME, &property) != 0))
718 qWarning(
"QQnx: failed to query window property, errno=%d", errno);
721 case SCREEN_PROPERTY_FOCUS:
722 handleKeyboardFocusPropertyEvent(window);
724 case SCREEN_PROPERTY_SIZE:
725 case SCREEN_PROPERTY_POSITION:
726 handleGeometryPropertyEvent(window);
730 qCDebug(lcQpaScreenEvents) <<
"Ignore property event for property: " << property;
739 qWarning(
"QQnx: failed to query keyboard focus property, errno=%d", errno);
743 m_focusLostTimer.stop();
745 if (focus && focusWindow != QGuiApplication::focusWindow())
746 QWindowSystemInterface::handleFocusWindowChanged(focusWindow, Qt::ActiveWindowFocusReason);
747 else if (!focus && focusWindow == QGuiApplication::focusWindow())
748 m_focusLostTimer.start(50ms,
this);
754 if (screen_get_window_property_iv(window, SCREEN_PROPERTY_POSITION, pos) != 0) {
755 qWarning(
"QQnx: failed to query window property, errno=%d", errno);
760 if (screen_get_window_property_iv(window, SCREEN_PROPERTY_SIZE, size) != 0) {
761 qWarning(
"QQnx: failed to query window property, errno=%d", errno);
765 QRect rect(pos[0], pos[1], size[0], size[1]);
771 if (qtWindow->handle() && qtWindow->handle()->geometry() != rect)
772 qtWindow->handle()->setGeometry(rect);
775 qCDebug(lcQpaScreenEvents) << qtWindow <<
"moved to" << rect;
780 if (event->id() == m_focusLostTimer.id()) {
781 m_focusLostTimer.stop();
784 QObject::timerEvent(event);
795 screen_get_event_property_iv(event, SCREEN_PROPERTY_SUBTYPE, &subtype),
796 "Failed to query object type property");
799 screen_window_t window = 0;
800 if (screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, (
void**)&window) != 0)
801 qFatal(
"QQnx: failed to query window property, errno=%d", errno);
804 case SCREEN_EVENT_CLOSE: {
806 closeWindow->close();
812 qCDebug(lcQpaScreenEvents) <<
"Ignore manager event for subtype: " << subtype;
825#include "moc_qqnxscreeneventhandler.cpp"
static QQnxIntegration * instance()
void removeDisplay(QQnxScreen *screen)
void removeScreenEventFilter(QQnxScreenEventFilter *filter)
void setScreenEventThread(QQnxScreenEventThread *eventThread)
void timerEvent(QTimerEvent *event) override
This event handler can be reimplemented in a subclass to receive timer events for the object.
bool handleEvent(screen_event_t event)
static void injectKeyboardEvent(int flags, int sym, int mod, int scan, int cap)
void addScreenEventFilter(QQnxScreenEventFilter *filter)
bool handleEvent(screen_event_t event, int qnxType)
bool isPrimaryScreen() const
The QQnxWindow is the base class of the various classes used as instances of QPlatformWindow in the Q...
void handleActivationEvent()
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")
#define Q_SCREEN_CHECKERROR(x, message)
QT_BEGIN_NAMESPACE int qtKeyForPrivateUseQnxKey(int key)
const int SCREEN_PROPERTY_SYM
const int SCREEN_PROPERTY_SCAN
const int SCREEN_PROPERTY_FOCUS
const int SCREEN_PROPERTY_MODIFIERS
#define _SCREEN_MAKE_VERSION(major, minor, patch)
static int qtKey(int virtualKey, QChar::Category category)
static QString keyString(int sym, QChar::Category category)
static void finishCloseEvent(screen_event_t event)
static QString capKeyString(int cap, int modifiers, int key)
static void finishCloseEvent(screen_event_t event)