Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqnxscreeneventthread.cpp
Go to the documentation of this file.
1// Copyright (C) 2017 QNX Software Systems. All rights reserved.
2// Copyright (C) 2011 - 2012 Research In Motion
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4// Qt-Security score:significant reason:default
5
6#include "qqnxglobal.h"
7
10
11#include <QtCore/QDebug>
12
13#include <errno.h>
14#include <unistd.h>
15
16#include <cctype>
17
18static const int c_screenCode = _PULSE_CODE_MINAVAIL + 0;
19static const int c_armCode = _PULSE_CODE_MINAVAIL + 1;
20static const int c_quitCode = _PULSE_CODE_MINAVAIL + 2;
21static const int c_postCode = _PULSE_CODE_MINAVAIL + 3;
22
23#if !defined(screen_register_event)
24int screen_register_event(screen_context_t, struct sigevent *event)
25{
26 return MsgRegisterEvent(event, -1);
27}
28
29int screen_unregister_event(struct sigevent *event)
30{
31 return MsgUnregisterEvent(event);
32}
33#endif
34
35QQnxScreenEventThread::QQnxScreenEventThread(screen_context_t context)
36 : QThread()
37 , m_screenContext(context)
38{
39 m_channelId = ChannelCreate(_NTO_CHF_DISCONNECT | _NTO_CHF_UNBLOCK | _NTO_CHF_PRIVATE);
40 if (m_channelId == -1) {
41 qFatal("QQnxScreenEventThread: Can't continue without a channel");
42 }
43
44 m_connectionId = ConnectAttach(0, 0, m_channelId, _NTO_SIDE_CHANNEL, 0);
45 if (m_connectionId == -1) {
46 ChannelDestroy(m_channelId);
47 qFatal("QQnxScreenEventThread: Can't continue without a channel connection");
48 }
49
50 SIGEV_PULSE_INIT(&m_screenEvent, m_connectionId, SIGEV_PULSE_PRIO_INHERIT, c_screenCode, 0);
51 if (screen_register_event(m_screenContext, &m_screenEvent) == -1) {
52 ConnectDetach(m_connectionId);
53 ChannelDestroy(m_channelId);
54 qFatal("QQnxScreenEventThread: Can't continue without a registered event");
55 }
56
57 screen_notify(m_screenContext, SCREEN_NOTIFY_EVENT, nullptr, &m_screenEvent);
58 qRegisterMetaType<screen_window_t>("screen_window_t");
59}
60
61QQnxScreenEventThread::~QQnxScreenEventThread()
62{
63 // block until thread terminates
64 shutdown();
65
66 screen_notify(m_screenContext, SCREEN_NOTIFY_EVENT, nullptr, nullptr);
67 screen_unregister_event(&m_screenEvent);
68 ConnectDetach(m_connectionId);
69 ChannelDestroy(m_channelId);
70}
71
72void QQnxScreenEventThread::run()
73{
74 qCDebug(lcQpaScreenEvents) << "Screen event thread started";
75
76 while (1) {
77 struct _pulse msg;
78 memset(&msg, 0, sizeof(msg));
79 int receiveId = MsgReceive(m_channelId, &msg, sizeof(msg), nullptr);
80 if (receiveId == 0 && msg.code == c_quitCode)
81 break;
82 else if (receiveId == 0)
83 handlePulse(msg);
84 else if (receiveId > 0)
85 qWarning() << "Unexpected message" << msg.code;
86 else
87 qWarning() << "MsgReceive error" << strerror(errno);
88 }
89
90 qCDebug(lcQpaScreenEvents) << "Screen event thread stopped";
91}
92
93void QQnxScreenEventThread::armEventsPending(int count)
94{
95 MsgSendPulse(m_connectionId, SIGEV_PULSE_PRIO_INHERIT, c_armCode, count);
96}
97
98bool QQnxScreenEventThread::registerUpdateNotification(screen_window_t window)
99{
100 struct sigevent evt;
101 SIGEV_PULSE_INIT(&evt, m_connectionId, SIGEV_PULSE_PRIO_INHERIT, c_postCode, 0);
102 evt.sigev_value.sival_ptr = window;
103 if (screen_register_event(m_screenContext, &evt) == -1) {
104 qWarning() << "QQnxScreenEventThread: Failed to register post event for window" << window;
105 return false;
106 }
107 int rc = screen_notify(m_screenContext, SCREEN_NOTIFY_UPDATE, window, &evt);
108 qCDebug(lcQpaScreenEvents) << "registerUpdateNotification window=" << window << "rc=" << rc;
109 if (rc != 0) {
110 qWarning() << "screen_notify(SCREEN_NOTIFY_UPDATE) failed for window=" << window << strerror(errno);
111 screen_unregister_event(&evt);
112 return false;
113 }
114 m_postEvents.insert(window, evt);
115 return true;
116}
117
118void QQnxScreenEventThread::unregisterUpdateNotification(screen_window_t window)
119{
120 int rc = screen_notify(m_screenContext, SCREEN_NOTIFY_UPDATE, window, nullptr);
121 qCDebug(lcQpaScreenEvents) << "unregisterUpdateNotification window=" << window << "rc=" << rc;
122 if (m_postEvents.contains(window)) {
123 screen_unregister_event(&m_postEvents[window]);
124 m_postEvents.remove(window);
125 }
126}
127
128void QQnxScreenEventThread::handlePostPulse(const struct _pulse &msg)
129{
130 screen_window_t window = static_cast<screen_window_t>(msg.value.sival_ptr);
131 Q_EMIT postEventReceived(window);
132}
133
134void QQnxScreenEventThread::handleScreenPulse(const struct _pulse &msg)
135{
136 Q_UNUSED(msg);
137
138 ++m_screenPulsesSinceLastArmPulse;
139 if (m_emitNeededOnNextScreenPulse) {
140 m_emitNeededOnNextScreenPulse = false;
141 Q_EMIT eventsPending();
142 }
143}
144
145void QQnxScreenEventThread::handleArmPulse(const struct _pulse &msg)
146{
147 if (msg.value.sival_int == 0 && m_screenPulsesSinceLastArmPulse == 0) {
148 m_emitNeededOnNextScreenPulse = true;
149 } else {
150 m_screenPulsesSinceLastArmPulse = 0;
151 m_emitNeededOnNextScreenPulse = false;
152 Q_EMIT eventsPending();
153 }
154}
155
156void QQnxScreenEventThread::handlePulse(const struct _pulse &msg)
157{
158 if (msg.code == c_screenCode)
159 handleScreenPulse(msg);
160 else if (msg.code == c_armCode)
161 handleArmPulse(msg);
162 else if (msg.code == c_postCode)
163 handlePostPulse(msg);
164 else
165 qWarning() << "Unexpected pulse" << msg.code;
166}
167
168void QQnxScreenEventThread::shutdown()
169{
170 MsgSendPulse(m_connectionId, SIGEV_PULSE_PRIO_INHERIT, c_quitCode, 0);
171
172 qCDebug(lcQpaScreenEvents) << "Screen event thread shutdown begin";
173
174 // block until thread terminates
175 wait();
176
177 qCDebug(lcQpaScreenEvents) << "Screen event thread shutdown end";
178}
int screen_register_event(screen_context_t, struct sigevent *event)
static const int c_quitCode
int screen_unregister_event(struct sigevent *event)
static const int c_armCode
static const int c_screenCode
static const int c_postCode