diff options
Diffstat (limited to 'src/plugins/platforms/qnx')
-rw-r--r-- | src/plugins/platforms/qnx/qqnxintegration.cpp | 3 | ||||
-rw-r--r-- | src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp | 31 | ||||
-rw-r--r-- | src/plugins/platforms/qnx/qqnxscreeneventhandler.h | 2 | ||||
-rw-r--r-- | src/plugins/platforms/qnx/qqnxscreeneventthread.cpp | 156 | ||||
-rw-r--r-- | src/plugins/platforms/qnx/qqnxscreeneventthread.h | 26 |
5 files changed, 103 insertions, 115 deletions
diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp index bffe7ee34b..fa8746c684 100644 --- a/src/plugins/platforms/qnx/qqnxintegration.cpp +++ b/src/plugins/platforms/qnx/qqnxintegration.cpp @@ -164,7 +164,8 @@ QQnxIntegration::QQnxIntegration(const QStringList ¶mList) #endif // Create/start event thread - m_screenEventThread = new QQnxScreenEventThread(ms_screenContext, m_screenEventHandler); + m_screenEventThread = new QQnxScreenEventThread(ms_screenContext); + m_screenEventHandler->setScreenEventThread(m_screenEventThread); m_screenEventThread->start(); #if QT_CONFIG(qqnx_pps) diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp index f211883e4f..c6b5bd7396 100644 --- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp +++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp @@ -197,36 +197,39 @@ void QQnxScreenEventHandler::injectKeyboardEvent(int flags, int sym, int modifie void QQnxScreenEventHandler::setScreenEventThread(QQnxScreenEventThread *eventThread) { m_eventThread = eventThread; + connect(m_eventThread, &QQnxScreenEventThread::eventsPending, + this, &QQnxScreenEventHandler::processEvents); } -void QQnxScreenEventHandler::processEventsFromScreenThread() +void QQnxScreenEventHandler::processEvents() { if (!m_eventThread) return; - QQnxScreenEventArray *events = m_eventThread->lock(); + screen_event_t event = nullptr; + if (screen_create_event(&event) != 0) + return; - for (int i = 0; i < events->size(); ++i) { - screen_event_t event = events->at(i); - if (!event) - continue; - (*events)[i] = 0; + int count = 0; + for (;;) { + if (screen_get_event(m_eventThread->context(), event, 0) != 0) + break; - m_eventThread->unlock(); + int type = SCREEN_EVENT_NONE; + screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &type); + if (type == SCREEN_EVENT_NONE) + break; + ++count; long result = 0; QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance(); bool handled = dispatcher && dispatcher->filterNativeEvent(QByteArrayLiteral("screen_event_t"), event, &result); if (!handled) handleEvent(event); - screen_destroy_event(event); - - m_eventThread->lock(); } - events->clear(); - - m_eventThread->unlock(); + m_eventThread->armEventsPending(count); + screen_destroy_event(event); } void QQnxScreenEventHandler::handleKeyboardEvent(screen_event_t event) diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.h b/src/plugins/platforms/qnx/qqnxscreeneventhandler.h index 40697b7a09..b35967610e 100644 --- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.h +++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.h @@ -74,7 +74,7 @@ protected: void timerEvent(QTimerEvent *event) override; private Q_SLOTS: - void processEventsFromScreenThread(); + void processEvents(); private: void handleKeyboardEvent(screen_event_t event); diff --git a/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp b/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp index c56d9a8da4..1b5f3b4954 100644 --- a/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp +++ b/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp @@ -1,5 +1,6 @@ /*************************************************************************** ** +** Copyright (C) 2017 QNX Software Systems. All rights reserved. ** Copyright (C) 2011 - 2012 Research In Motion ** Contact: https://www.qt.io/licensing/ ** @@ -55,116 +56,101 @@ #define qScreenEventThreadDebug QT_NO_QDEBUG_MACRO #endif -QQnxScreenEventThread::QQnxScreenEventThread(screen_context_t context, QQnxScreenEventHandler *screenEventHandler) - : QThread(), - m_screenContext(context), - m_screenEventHandler(screenEventHandler), - m_quit(false) +static const int c_screenCode = _PULSE_CODE_MINAVAIL + 0; +static const int c_armCode = _PULSE_CODE_MINAVAIL + 1; +static const int c_quitCode = _PULSE_CODE_MINAVAIL + 2; + +QQnxScreenEventThread::QQnxScreenEventThread(screen_context_t context) + : QThread() + , m_screenContext(context) { - screenEventHandler->setScreenEventThread(this); - connect(this, SIGNAL(eventPending()), screenEventHandler, SLOT(processEventsFromScreenThread()), Qt::QueuedConnection); - connect(this, SIGNAL(finished()), screenEventHandler, SLOT(processEventsFromScreenThread()), Qt::QueuedConnection); + m_channelId = ChannelCreate(_NTO_CHF_DISCONNECT | _NTO_CHF_UNBLOCK | _NTO_CHF_PRIVATE); + if (m_channelId == -1) { + qFatal("QQnxScreenEventThread: Can't continue without a channel"); + } + + m_connectionId = ConnectAttach(0, 0, m_channelId, _NTO_SIDE_CHANNEL, 0); + if (m_connectionId == -1) { + ChannelDestroy(m_channelId); + qFatal("QQnxScreenEventThread: Can't continue without a channel connection"); + } + + struct sigevent screenEvent; + SIGEV_PULSE_INIT(&screenEvent, m_connectionId, SIGEV_PULSE_PRIO_INHERIT, c_screenCode, 0); + + screen_notify(m_screenContext, SCREEN_NOTIFY_EVENT, nullptr, &screenEvent); } QQnxScreenEventThread::~QQnxScreenEventThread() { // block until thread terminates shutdown(); -} -void QQnxScreenEventThread::injectKeyboardEvent(int flags, int sym, int mod, int scan, int cap) -{ - QQnxScreenEventHandler::injectKeyboardEvent(flags, sym, mod, scan, cap); -} - -QQnxScreenEventArray *QQnxScreenEventThread::lock() -{ - m_mutex.lock(); - return &m_events; -} - -void QQnxScreenEventThread::unlock() -{ - m_mutex.unlock(); + ConnectDetach(m_connectionId); + ChannelDestroy(m_channelId); } void QQnxScreenEventThread::run() { qScreenEventThreadDebug("screen event thread started"); - int errorCounter = 0; - // loop indefinitely - while (!m_quit) { - screen_event_t event; - - // create screen event - Q_SCREEN_CHECKERROR(screen_create_event(&event), "Failed to create screen event"); - - // block until screen event is available - const int error = screen_get_event(m_screenContext, event, -1); - Q_SCREEN_CRITICALERROR(error, "Failed to get screen event"); - // Only allow 50 consecutive errors before we exit the thread - if (error) { - errorCounter++; - if (errorCounter > 50) - m_quit = true; - - screen_destroy_event(event); - continue; - } else { - errorCounter = 0; - } - - // process received event - // get the event type - int qnxType; - Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &qnxType), - "Failed to query screen event type"); - - if (qnxType == SCREEN_EVENT_USER) { - // treat all user events as shutdown requests - qScreenEventThreadDebug("QNX user screen event"); - m_quit = true; - } else { - m_mutex.lock(); - m_events << event; - m_mutex.unlock(); - emit eventPending(); - } + while (1) { + struct _pulse msg; + memset(&msg, 0, sizeof(msg)); + int receiveId = MsgReceive(m_channelId, &msg, sizeof(msg), nullptr); + if (receiveId == 0 && msg.code == c_quitCode) + break; + else if (receiveId == 0) + handlePulse(msg); + else if (receiveId > 0) + qWarning() << "Unexpected message" << msg.code; + else + qWarning() << "MsgReceive error" << strerror(errno); } qScreenEventThreadDebug("screen event thread stopped"); - - // cleanup - m_mutex.lock(); - Q_FOREACH (screen_event_t event, m_events) { - screen_destroy_event(event); - } - m_events.clear(); - m_mutex.unlock(); } -void QQnxScreenEventThread::shutdown() +void QQnxScreenEventThread::armEventsPending(int count) { - screen_event_t event; + MsgSendPulse(m_connectionId, SIGEV_PULSE_PRIO_INHERIT, c_armCode, count); +} - // create screen event - Q_SCREEN_CHECKERROR(screen_create_event(&event), - "Failed to create screen event"); +void QQnxScreenEventThread::handleScreenPulse(const struct _pulse &msg) +{ + Q_UNUSED(msg); - // set the event type as user - int type = SCREEN_EVENT_USER; - Q_SCREEN_CHECKERROR(screen_set_event_property_iv(event, SCREEN_PROPERTY_TYPE, &type), - "Failed to set screen type"); + ++m_screenPulsesSinceLastArmPulse; + if (m_emitNeededOnNextScreenPulse) { + m_emitNeededOnNextScreenPulse = false; + Q_EMIT eventsPending(); + } +} - // NOTE: ignore SCREEN_PROPERTY_USER_DATA; treat all user events as shutdown events +void QQnxScreenEventThread::handleArmPulse(const struct _pulse &msg) +{ + if (msg.value.sival_int == 0 && m_screenPulsesSinceLastArmPulse == 0) { + m_emitNeededOnNextScreenPulse = true; + } else { + m_screenPulsesSinceLastArmPulse = 0; + m_emitNeededOnNextScreenPulse = false; + Q_EMIT eventsPending(); + } +} - // post event to event loop so it will wake up and die - Q_SCREEN_CHECKERROR(screen_send_event(m_screenContext, event, getpid()), - "Failed to set screen event type"); +void QQnxScreenEventThread::handlePulse(const struct _pulse &msg) +{ + if (msg.code == c_screenCode) + handleScreenPulse(msg); + else if (msg.code == c_armCode) + handleArmPulse(msg); + else + qWarning() << "Unexpected pulse" << msg.code; +} - // cleanup - screen_destroy_event(event); +void QQnxScreenEventThread::shutdown() +{ + MsgSendPulse(m_connectionId, SIGEV_PULSE_PRIO_INHERIT, c_quitCode, 0); qScreenEventThreadDebug("screen event thread shutdown begin"); diff --git a/src/plugins/platforms/qnx/qqnxscreeneventthread.h b/src/plugins/platforms/qnx/qqnxscreeneventthread.h index 140f53aa50..3c8d197545 100644 --- a/src/plugins/platforms/qnx/qqnxscreeneventthread.h +++ b/src/plugins/platforms/qnx/qqnxscreeneventthread.h @@ -1,5 +1,6 @@ /*************************************************************************** ** +** Copyright (C) 2017 QNX Software Systems. All rights reserved. ** Copyright (C) 2011 - 2012 Research In Motion ** Contact: https://www.qt.io/licensing/ ** @@ -47,37 +48,34 @@ QT_BEGIN_NAMESPACE -class QQnxScreenEventHandler; - -typedef QVarLengthArray<screen_event_t, 64> QQnxScreenEventArray; - class QQnxScreenEventThread : public QThread { Q_OBJECT public: - QQnxScreenEventThread(screen_context_t context, QQnxScreenEventHandler *screenEventHandler); + QQnxScreenEventThread(screen_context_t context); ~QQnxScreenEventThread(); - static void injectKeyboardEvent(int flags, int sym, int mod, int scan, int cap); - - QQnxScreenEventArray *lock(); - void unlock(); + screen_context_t context() const { return m_screenContext; } + void armEventsPending(int count); protected: void run() override; Q_SIGNALS: - void eventPending(); + void eventsPending(); private: + void handleScreenPulse(const struct _pulse &msg); + void handleArmPulse(const struct _pulse &msg); + void handlePulse(const struct _pulse &msg); void shutdown(); + int m_channelId; + int m_connectionId; screen_context_t m_screenContext; - QMutex m_mutex; - QQnxScreenEventArray m_events; - QQnxScreenEventHandler *m_screenEventHandler; - bool m_quit; + bool m_emitNeededOnNextScreenPulse = true; + int m_screenPulsesSinceLastArmPulse = 0; }; QT_END_NAMESPACE |