17#include <QGuiApplication>
20#include <sys/keycodes.h>
22using namespace std::chrono_literals;
26static int qtKey(
int virtualKey, QChar::Category category)
28 if (Q_UNLIKELY(category == QChar::Other_NotAssigned))
30 else if (category == QChar::Other_PrivateUse)
33 return QChar::toUpper(virtualKey);
38 if (Q_UNLIKELY(category == QChar::Other_NotAssigned)) {
40 }
else if (category == QChar::Other_PrivateUse) {
41 return keyStringForPrivateUseQnxKey(sym);
43 return QStringView{QChar::fromUcs4(sym)}.toString();
49 if (cap >= 0x20 && cap <= 0x0ff) {
50 if (modifiers & KEYMOD_CTRL)
51 return QChar((
int)(key & 0x3f));
60 screen_get_event_property_pv(event,
61 screen_traits<T>::propertyName,
62 reinterpret_cast<
void**>(&t));
63 screen_traits<T>::destroy(t);
69 int objectType = SCREEN_OBJECT_TYPE_CONTEXT;
70 screen_get_event_property_iv(event, SCREEN_PROPERTY_OBJECT_TYPE, &objectType);
72 case SCREEN_OBJECT_TYPE_CONTEXT:
73 finishCloseEvent<screen_context_t>(event);
75 case SCREEN_OBJECT_TYPE_DEVICE:
76 finishCloseEvent<screen_device_t>(event);
78 case SCREEN_OBJECT_TYPE_DISPLAY:
81 case SCREEN_OBJECT_TYPE_GROUP:
82 finishCloseEvent<screen_group_t>(event);
84 case SCREEN_OBJECT_TYPE_PIXMAP:
85 finishCloseEvent<screen_pixmap_t>(event);
87 case SCREEN_OBJECT_TYPE_SESSION:
88 finishCloseEvent<screen_session_t>(event);
91 case SCREEN_OBJECT_TYPE_STREAM:
92 finishCloseEvent<screen_stream_t>(event);
95 case SCREEN_OBJECT_TYPE_WINDOW:
96 finishCloseEvent<screen_window_t>(event);
103using namespace Qt::StringLiterals;
106 : m_qnxIntegration(integration)
107 , m_lastButtonState(Qt::NoButton)
108 , m_lastMouseWindow(0)
114 m_touchDevice =
new QPointingDevice(
115 "touchscreen"_L1, 1, QInputDevice::DeviceType::TouchScreen,
116 QPointingDevice::PointerType::Finger,
117 QPointingDevice::Capability::Position | QPointingDevice::Capability::Area
118 | QPointingDevice::Capability::Pressure
119 | QPointingDevice::Capability::NormalizedPosition,
120 MaximumTouchPoints, 8);
121 QWindowSystemInterface::registerInputDevice(m_touchDevice);
123 m_mouseDevice =
new QPointingDevice(
"mouse"_L1, 2, QInputDevice::DeviceType::Mouse,
124 QPointingDevice::PointerType::Generic,
125 QPointingDevice::Capability::Position, 1, 8);
126 QWindowSystemInterface::registerInputDevice(m_mouseDevice);
129 for (
int i = 0; i < MaximumTouchPoints; i++) {
132 m_touchPoints[i].id = i;
135 m_touchPoints[i].pressure = 1.0;
138 m_touchPoints[i].state = QEventPoint::State::Released;
144 m_eventFilters.append(filter);
149 m_eventFilters.removeOne(filter);
157 "Failed to query event type");
159 return handleEvent(event, qnxType);
165 case SCREEN_EVENT_MTOUCH_TOUCH:
166 case SCREEN_EVENT_MTOUCH_MOVE:
167 case SCREEN_EVENT_MTOUCH_RELEASE:
168 handleTouchEvent(event, qnxType);
171 case SCREEN_EVENT_KEYBOARD:
172 handleKeyboardEvent(event);
175 case SCREEN_EVENT_POINTER:
176 handlePointerEvent(event);
179 case SCREEN_EVENT_CREATE:
180 handleCreateEvent(event);
183 case SCREEN_EVENT_CLOSE:
184 handleCloseEvent(event);
187 case SCREEN_EVENT_DISPLAY:
188 handleDisplayEvent(event);
191 case SCREEN_EVENT_PROPERTY:
192 handlePropertyEvent(event);
195 case SCREEN_EVENT_MANAGER:
196 handleManagerEvent(event);
201 qCDebug(lcQpaScreenEvents) << Q_FUNC_INFO <<
"Unknown event" << qnxType;
212 if (!(flags & KEY_CAP_VALID))
216 if ((flags & KEY_SYM_VALID) && sym ==
static_cast<
int>(0xFFFFFFFF))
217 flags &= ~(KEY_SYM_VALID);
219 Qt::KeyboardModifiers qtMod = Qt::NoModifier;
220 if (modifiers & KEYMOD_SHIFT)
221 qtMod |= Qt::ShiftModifier;
222 if (modifiers & KEYMOD_CTRL)
223 qtMod |= Qt::ControlModifier;
224 if (modifiers & KEYMOD_ALT)
225 qtMod |= Qt::AltModifier;
226 if (isKeypadKey(cap))
227 qtMod |= Qt::KeypadModifier;
229 QEvent::Type type = (flags & KEY_DOWN) ? QEvent::KeyPress : QEvent::KeyRelease;
231 int virtualKey = (flags & KEY_SYM_VALID) ? sym : cap;
232 QChar::Category category = QChar::category(virtualKey);
233 int key = qtKey(virtualKey, category);
234 QString keyStr = (flags & KEY_SYM_VALID) ? keyString(sym, category) :
235 capKeyString(cap, modifiers, key);
237 QWindowSystemInterface::handleExtendedKeyEvent(QGuiApplication::focusWindow(), type, key, qtMod,
238 scan, virtualKey, modifiers, keyStr, flags & KEY_REPEAT);
239 qCDebug(lcQpaScreenEvents) <<
"Qt key t=" << type <<
", k=" << key <<
", s=" << keyStr;
244 m_eventThread = eventThread;
245 connect(m_eventThread, &QQnxScreenEventThread::eventsPending,
246 this, &QQnxScreenEventHandler::processEvents);
254 screen_event_t event =
nullptr;
255 if (screen_create_event(&event) != 0)
260 if (screen_get_event(m_eventThread->context(), event, 0) != 0)
263 int type = SCREEN_EVENT_NONE;
264 screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &type);
265 if (type == SCREEN_EVENT_NONE)
270 QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance();
271 bool handled = dispatcher && dispatcher->filterNativeEvent(QByteArrayLiteral(
"screen_event_t"), event, &result);
275 if (type == SCREEN_EVENT_CLOSE)
276 finishCloseEvent(event);
280 screen_destroy_event(event);
288 "Failed to query event flags");
293 "Failed to query event sym");
296 Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_MODIFIERS, &modifiers),
297 "Failed to query event modifieres");
301 "Failed to query event scan");
305 "Failed to query event cap");
310 Q_FOREACH (QQnxScreenEventFilter *filter, m_eventFilters) {
311 if (filter->handleKeyboardEvent(flags, sym, modifiers, scan, cap, sequenceId)) {
318 injectKeyboardEvent(flags, sym, modifiers, scan, cap);
326 screen_window_t qnxWindow;
329 "Failed to query event window");
331 qnxWindow =
static_cast<screen_window_t>(handle);
335 Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_BUTTONS, &buttonState),
336 "Failed to query event button state");
341 screen_get_event_property_iv(event, SCREEN_PROPERTY_SOURCE_POSITION, windowPos),
342 "Failed to query event window position");
347 "Failed to query event position");
352 screen_get_event_property_iv(event, SCREEN_PROPERTY_MOUSE_WHEEL, &wheelDelta),
353 "Failed to query event wheel delta");
356 Q_SCREEN_CHECKERROR(screen_get_event_property_llv(event, SCREEN_PROPERTY_TIMESTAMP, ×tamp),
357 "Failed to get timestamp");
363 if (qnxWindow != m_lastMouseWindow) {
364 QWindow *wOld = QQnxIntegration::instance()->window(m_lastMouseWindow);
367 QWindowSystemInterface::handleLeaveEvent(wOld);
368 qCDebug(lcQpaScreenEvents) <<
"Qt leave, w=" << wOld;
372 QWindowSystemInterface::handleEnterEvent(w);
373 qCDebug(lcQpaScreenEvents) <<
"Qt enter, w=" << w;
377 m_lastMouseWindow = qnxWindow;
385 QPoint globalPoint(pos[0], pos[1]);
386 QPoint localPoint(windowPos[0], windowPos[1]);
392 Qt::MouseButtons buttons = Qt::NoButton;
393 if (buttonState & 0x01)
394 buttons |= Qt::LeftButton;
395 if (buttonState & 0x02)
396 buttons |= Qt::MiddleButton;
397 if (buttonState & 0x04)
398 buttons |= Qt::RightButton;
399 if (buttonState & 0x08)
400 buttons |= Qt::ExtraButton1;
401 if (buttonState & 0x10)
402 buttons |= Qt::ExtraButton2;
403 if (buttonState & 0x20)
404 buttons |= Qt::ExtraButton3;
405 if (buttonState & 0x40)
406 buttons |= Qt::ExtraButton4;
407 if (buttonState & 0x80)
408 buttons |= Qt::ExtraButton5;
412 if (m_lastGlobalMousePoint != globalPoint || m_lastLocalMousePoint != localPoint) {
413 QWindowSystemInterface::handleMouseEvent(w, timestamp, m_mouseDevice, localPoint,
414 globalPoint, buttons, Qt::NoButton,
416 qCDebug(lcQpaScreenEvents) <<
"Qt mouse move, w=" << w <<
", (" << localPoint.x() <<
","
417 << localPoint.y() <<
"), b=" <<
static_cast<
int>(buttons);
420 if (m_lastButtonState != buttons) {
421 static const auto supportedButtons = { Qt::LeftButton, Qt::MiddleButton,
422 Qt::RightButton, Qt::ExtraButton1,
423 Qt::ExtraButton2, Qt::ExtraButton3,
424 Qt::ExtraButton4, Qt::ExtraButton5 };
426 int releasedButtons = (m_lastButtonState ^ buttons) & ~buttons;
427 for (
auto button : supportedButtons) {
428 if (releasedButtons & button) {
429 QWindowSystemInterface::handleMouseEvent(w, timestamp, m_mouseDevice,
430 localPoint, globalPoint, buttons,
431 button, QEvent::MouseButtonRelease);
432 qCDebug(lcQpaScreenEvents) <<
"Qt mouse release, w=" << w <<
", (" << localPoint.x()
433 <<
"," << localPoint.y() <<
"), b=" << button;
437 if (m_lastButtonState != 0 && buttons == 0) {
441 int pressedButtons = (m_lastButtonState ^ buttons) & buttons;
442 for (
auto button : supportedButtons) {
443 if (pressedButtons & button) {
444 QWindowSystemInterface::handleMouseEvent(w, timestamp, m_mouseDevice,
445 localPoint, globalPoint, buttons,
446 button, QEvent::MouseButtonPress);
447 qCDebug(lcQpaScreenEvents) <<
"Qt mouse press, w=" << w <<
", (" << localPoint.x()
448 <<
"," << localPoint.y() <<
"), b=" << button;
456 QPoint angleDelta(0, wheelDelta);
457 QWindowSystemInterface::handleWheelEvent(w, timestamp, m_mouseDevice, localPoint,
458 globalPoint, QPoint(), angleDelta);
459 qCDebug(lcQpaScreenEvents) <<
"Qt wheel, w=" << w <<
", (" << localPoint.x() <<
","
460 << localPoint.y() <<
"), d=" <<
static_cast<
int>(wheelDelta);
464 m_lastGlobalMousePoint = globalPoint;
465 m_lastLocalMousePoint = localPoint;
466 m_lastButtonState = buttons;
474 "Failed to query event position");
476 QCursor::setPos(pos[0], pos[1]);
480 Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_SOURCE_POSITION, windowPos),
481 "Failed to query event window position");
485 Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_TOUCH_ID, &touchId),
486 "Failed to query event touch id");
491 "Failed to query event window");
496 "Failed to query event touch area");
500 screen_get_event_property_iv(event, SCREEN_PROPERTY_TOUCH_PRESSURE, &touchPressure),
501 "Failed to query event touch pressure");
503 screen_window_t qnxWindow =
static_cast<screen_window_t>(handle);
506 if (touchId < MaximumTouchPoints) {
512 if (qnxWindow != m_lastMouseWindow) {
513 QWindow *wOld = QQnxIntegration::instance()->window(m_lastMouseWindow);
516 QWindowSystemInterface::handleLeaveEvent(wOld);
517 qCDebug(lcQpaScreenEvents) <<
"Qt leave, w=" << wOld;
521 QWindowSystemInterface::handleEnterEvent(w);
522 qCDebug(lcQpaScreenEvents) <<
"Qt enter, w=" << w;
525 m_lastMouseWindow = qnxWindow;
528 if (qnxType == SCREEN_EVENT_MTOUCH_RELEASE)
532 QPlatformScreen *platformScreen = QPlatformScreen::platformScreenForWindow(w);
533 QSizeF screenSize = platformScreen->geometry().size();
536 m_touchPoints[touchId].normalPosition =
537 QPointF(
static_cast<qreal>(pos[0]) / screenSize.width(),
538 static_cast<qreal>(pos[1]) / screenSize.height());
540 m_touchPoints[touchId].area = QRectF(w->geometry().left() + windowPos[0] - (touchArea[0]>>1),
541 w->geometry().top() + windowPos[1] - (touchArea[1]>>1),
542 (touchArea[0]>>1), (touchArea[1]>>1));
543 QWindow *parent = w->parent();
545 m_touchPoints[touchId].area.translate(parent->geometry().topLeft());
546 parent = parent->parent();
552 m_touchPoints[touchId].pressure =
static_cast<qreal>(touchPressure)/200.0;
554 if (m_touchPoints[touchId].pressure > 1)
555 m_touchPoints[touchId].pressure = 1;
558 QEvent::Type type = QEvent::None;
560 case SCREEN_EVENT_MTOUCH_TOUCH:
561 m_touchPoints[touchId].state = QEventPoint::State::Pressed;
562 type = QEvent::TouchBegin;
564 case SCREEN_EVENT_MTOUCH_MOVE:
565 m_touchPoints[touchId].state = QEventPoint::State::Updated;
566 type = QEvent::TouchUpdate;
568 case SCREEN_EVENT_MTOUCH_RELEASE:
569 m_touchPoints[touchId].state = QEventPoint::State::Released;
570 type = QEvent::TouchEnd;
575 QList<QWindowSystemInterface::TouchPoint> pointList;
576 for (
int i = 0; i < MaximumTouchPoints; i++) {
579 pointList.append(m_touchPoints[i]);
580 }
else if (m_touchPoints[i].state != QEventPoint::State::Released) {
582 m_touchPoints[i].state = QEventPoint::State::Stationary;
583 pointList.append(m_touchPoints[i]);
588 QWindowSystemInterface::handleTouchEvent(w, m_touchDevice, pointList);
589 qCDebug(lcQpaScreenEvents) <<
"Qt touch, w =" << w
590 <<
", p=" << m_touchPoints[touchId].area.topLeft()
598 screen_window_t window = 0;
600 screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, (
void**)&window),
601 "Failed to query window property");
603 Q_EMIT windowClosed(window);
608 QWindowSystemInterface::handleCloseEvent(w);
613 screen_window_t window = 0;
614 int object_type = -1;
617 screen_get_event_property_iv(event, SCREEN_PROPERTY_OBJECT_TYPE, &object_type),
618 "Failed to query object type for create event");
620 switch (object_type) {
622 case SCREEN_OBJECT_TYPE_CONTEXT:
623 case SCREEN_OBJECT_TYPE_GROUP:
624 case SCREEN_OBJECT_TYPE_DISPLAY:
625 case SCREEN_OBJECT_TYPE_DEVICE:
626 case SCREEN_OBJECT_TYPE_PIXMAP:
627 case SCREEN_OBJECT_TYPE_SESSION:
628 case SCREEN_OBJECT_TYPE_STREAM:
630 case SCREEN_OBJECT_TYPE_WINDOW:
633 screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, (
void**)&window),
634 "Failed to query window property");
636 Q_EMIT newWindowCreated(window);
640 qCDebug(lcQpaScreenEvents) <<
"Ignore create event for object type: " << object_type;
647 screen_display_t nativeDisplay = 0;
648 if (screen_get_event_property_pv(event, SCREEN_PROPERTY_DISPLAY, (
void **)&nativeDisplay) != 0) {
649 qWarning(
"QQnx: failed to query display property, errno=%d", errno);
654 if (screen_get_event_property_iv(event, SCREEN_PROPERTY_ATTACHED, &isAttached) != 0) {
655 qWarning(
"QQnx: failed to query display attached property, errno=%d", errno);
659 qCDebug(lcQpaScreenEvents) <<
"display attachment is now:" << isAttached;
661 QQnxScreen *screen = m_qnxIntegration->screenForNative(nativeDisplay);
666 screen_get_display_property_iv(nativeDisplay, SCREEN_PROPERTY_SIZE, val);
667 if (val[0] == 0 && val[1] == 0)
670 qCDebug(lcQpaScreenEvents) <<
"Creating new QQnxScreen for newly attached display";
671 m_qnxIntegration->createDisplay(nativeDisplay,
false );
673 }
else if (!isAttached) {
683 qCDebug(lcQpaScreenEvents) <<
"Removing display";
694 screen_get_event_property_iv(event, SCREEN_PROPERTY_OBJECT_TYPE, &objectType),
695 "Failed to query object type property");
697 if (objectType != SCREEN_OBJECT_TYPE_WINDOW)
701 screen_window_t window = 0;
702 if (Q_UNLIKELY(screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, (
void**)&window) != 0))
703 qFatal(
"QQnx: failed to query window property, errno=%d", errno);
706 qCDebug(lcQpaScreenEvents) <<
"handlePositionEvent on NULL window";
712 if (Q_UNLIKELY(screen_get_event_property_iv(event, SCREEN_PROPERTY_NAME, &property) != 0))
713 qWarning(
"QQnx: failed to query window property, errno=%d", errno);
716 case SCREEN_PROPERTY_FOCUS:
717 handleKeyboardFocusPropertyEvent(window);
719 case SCREEN_PROPERTY_SIZE:
720 case SCREEN_PROPERTY_POSITION:
721 handleGeometryPropertyEvent(window);
725 qCDebug(lcQpaScreenEvents) <<
"Ignore property event for property: " << property;
734 qWarning(
"QQnx: failed to query keyboard focus property, errno=%d", errno);
738 m_focusLostTimer.stop();
740 if (focus && focusWindow != QGuiApplication::focusWindow())
741 QWindowSystemInterface::handleFocusWindowChanged(focusWindow, Qt::ActiveWindowFocusReason);
742 else if (!focus && focusWindow == QGuiApplication::focusWindow())
743 m_focusLostTimer.start(50ms,
this);
749 if (screen_get_window_property_iv(window, SCREEN_PROPERTY_POSITION, pos) != 0) {
750 qWarning(
"QQnx: failed to query window property, errno=%d", errno);
755 if (screen_get_window_property_iv(window, SCREEN_PROPERTY_SIZE, size) != 0) {
756 qWarning(
"QQnx: failed to query window property, errno=%d", errno);
760 QRect rect(pos[0], pos[1], size[0], size[1]);
763 qtWindow->setGeometry(rect);
764 QWindowSystemInterface::handleGeometryChange(qtWindow, rect);
767 qCDebug(lcQpaScreenEvents) << qtWindow <<
"moved to" << rect;
772 if (event->id() == m_focusLostTimer.id()) {
773 m_focusLostTimer.stop();
776 QObject::timerEvent(event);
787 screen_get_event_property_iv(event, SCREEN_PROPERTY_SUBTYPE, &subtype),
788 "Failed to query object type property");
791 screen_window_t window = 0;
792 if (screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, (
void**)&window) != 0)
793 qFatal(
"QQnx: failed to query window property, errno=%d", errno);
796 case SCREEN_EVENT_CLOSE: {
798 closeWindow->close();
804 qCDebug(lcQpaScreenEvents) <<
"Ignore manager event for subtype: " << subtype;
808#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)
void armEventsPending(int count)
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_FOCUS
#define _SCREEN_MAKE_VERSION(major, minor, patch)
Q_DECLARE_LOGGING_CATEGORY(lcQpaScreenEvents)
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)