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
qqnxscreeneventhandler.cpp
Go to the documentation of this file.
1// Copyright (C) 2013 BlackBerry Limited. All rights reserved.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
6
7#include "qqnxglobal.h"
8
13#include "qqnxscreen.h"
16
17#include "qqnxwindow.h"
18
19#include <QDebug>
20#include <QGuiApplication>
21
22#include <errno.h>
23#include <sys/keycodes.h>
24
25using namespace std::chrono_literals;
26
27Q_LOGGING_CATEGORY(lcQpaScreenEvents, "qt.qpa.screen.events");
28
29static int qtKey(int virtualKey, QChar::Category category)
30{
31 if (Q_UNLIKELY(category == QChar::Other_NotAssigned))
32 return virtualKey;
33 else if (category == QChar::Other_PrivateUse)
34 return qtKeyForPrivateUseQnxKey(virtualKey);
35 else
36 return QChar::toUpper(virtualKey);
37}
38
39static QString keyString(int sym, QChar::Category category)
40{
41 if (Q_UNLIKELY(category == QChar::Other_NotAssigned)) {
42 return QString();
43 } else if (category == QChar::Other_PrivateUse) {
44 return keyStringForPrivateUseQnxKey(sym);
45 } else {
46 return QStringView{QChar::fromUcs4(sym)}.toString();
47 }
48}
49
50static QString capKeyString(int cap, int modifiers, int key)
51{
52 if (cap >= 0x20 && cap <= 0x0ff) {
53 if (modifiers & KEYMOD_CTRL)
54 return QChar((int)(key & 0x3f));
55 }
56 return QString();
57}
58
59template <typename T>
60static void finishCloseEvent(screen_event_t event)
61{
62 T t;
63 screen_get_event_property_pv(event,
64 screen_traits<T>::propertyName,
65 reinterpret_cast<void**>(&t));
66 screen_traits<T>::destroy(t);
67}
68
69static void finishCloseEvent(screen_event_t event)
70{
71 // Let libscreen know that we're finished with anything that may have been acquired.
72 int objectType = SCREEN_OBJECT_TYPE_CONTEXT;
73 screen_get_event_property_iv(event, SCREEN_PROPERTY_OBJECT_TYPE, &objectType);
74 switch (objectType) {
75 case SCREEN_OBJECT_TYPE_CONTEXT:
76 finishCloseEvent<screen_context_t>(event);
77 break;
78 case SCREEN_OBJECT_TYPE_DEVICE:
79 finishCloseEvent<screen_device_t>(event);
80 break;
81 case SCREEN_OBJECT_TYPE_DISPLAY:
82 // no screen_destroy_display
83 break;
84 case SCREEN_OBJECT_TYPE_GROUP:
85 finishCloseEvent<screen_group_t>(event);
86 break;
87 case SCREEN_OBJECT_TYPE_PIXMAP:
88 finishCloseEvent<screen_pixmap_t>(event);
89 break;
90 case SCREEN_OBJECT_TYPE_SESSION:
91 finishCloseEvent<screen_session_t>(event);
92 break;
94 case SCREEN_OBJECT_TYPE_STREAM:
95 finishCloseEvent<screen_stream_t>(event);
96 break;
97#endif
98 case SCREEN_OBJECT_TYPE_WINDOW:
99 finishCloseEvent<screen_window_t>(event);
100 break;
101 }
102}
103
104QT_BEGIN_NAMESPACE
105
106using namespace Qt::StringLiterals;
107
108QQnxScreenEventHandler::QQnxScreenEventHandler(QQnxIntegration *integration)
109 : m_qnxIntegration(integration)
110 , m_lastButtonState(Qt::NoButton)
111 , m_lastMouseWindow(0)
112 , m_touchDevice(0)
113 , m_mouseDevice(0)
114 , m_eventThread(0)
115{
116 // Create a touch device
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);
125
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);
130
131 // initialize array of touch points
132 for (int i = 0; i < MaximumTouchPoints; i++) {
133
134 // map array index to id
135 m_touchPoints[i].id = i;
136
137 // pressure is not supported - use default
138 m_touchPoints[i].pressure = 1.0;
139
140 // nothing touching
141 m_touchPoints[i].state = QEventPoint::State::Released;
142 }
143}
144
146{
147 m_eventFilters.append(filter);
148}
149
151{
152 m_eventFilters.removeOne(filter);
153}
154
155bool QQnxScreenEventHandler::handleEvent(screen_event_t event)
156{
157 // get the event type
158 int qnxType;
159 Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &qnxType),
160 "Failed to query event type");
161
162 return handleEvent(event, qnxType);
163}
164
165bool QQnxScreenEventHandler::handleEvent(screen_event_t event, int qnxType)
166{
167 switch (qnxType) {
168 case SCREEN_EVENT_MTOUCH_TOUCH:
169 case SCREEN_EVENT_MTOUCH_MOVE:
170 case SCREEN_EVENT_MTOUCH_RELEASE:
171 handleTouchEvent(event, qnxType);
172 break;
173
174 case SCREEN_EVENT_KEYBOARD:
175 handleKeyboardEvent(event);
176 break;
177
178 case SCREEN_EVENT_POINTER:
179 handlePointerEvent(event);
180 break;
181
182 case SCREEN_EVENT_CREATE:
183 handleCreateEvent(event);
184 break;
185
186 case SCREEN_EVENT_CLOSE:
187 handleCloseEvent(event);
188 break;
189
190 case SCREEN_EVENT_DISPLAY:
191 handleDisplayEvent(event);
192 break;
193
194 case SCREEN_EVENT_PROPERTY:
195 handlePropertyEvent(event);
196 break;
197
198 case SCREEN_EVENT_MANAGER:
199 handleManagerEvent(event);
200 break;
201
202 default:
203 // event ignored
204 qCDebug(lcQpaScreenEvents) << Q_FUNC_INFO << "Unknown event" << qnxType;
205 return false;
206 }
207
208 return true;
209}
210
211void QQnxScreenEventHandler::injectKeyboardEvent(int flags, int sym, int modifiers, int scan, int cap)
212{
213 Q_UNUSED(scan);
214
215 if (!(flags & KEY_CAP_VALID))
216 return;
217
218 // Correct erroneous information.
219 if ((flags & KEY_SYM_VALID) && sym == static_cast<int>(0xFFFFFFFF))
220 flags &= ~(KEY_SYM_VALID);
221
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;
231
232 QEvent::Type type = (flags & KEY_DOWN) ? QEvent::KeyPress : QEvent::KeyRelease;
233
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);
239
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;
243}
244
245void QQnxScreenEventHandler::setScreenEventThread(QQnxScreenEventThread *eventThread)
246{
247 m_eventThread = eventThread;
248 connect(m_eventThread, &QQnxScreenEventThread::eventsPending,
249 this, &QQnxScreenEventHandler::processEvents);
250 connect(m_eventThread, &QQnxScreenEventThread::postEventReceived,
251 this, &QQnxScreenEventHandler::processPostEvent);
252}
253
254void QQnxScreenEventHandler::processEvents()
255{
256 if (!m_eventThread)
257 return;
258
259 screen_event_t event = nullptr;
260 if (screen_create_event(&event) != 0)
261 return;
262
263 int count = 0;
264 for (;;) {
265 if (screen_get_event(m_eventThread->context(), event, 0) != 0)
266 break;
267
268 int type = SCREEN_EVENT_NONE;
269 screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &type);
270 if (type == SCREEN_EVENT_NONE)
271 break;
272
273 ++count;
274 qintptr result = 0;
275 QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance();
276 bool handled = dispatcher && dispatcher->filterNativeEvent(QByteArrayLiteral("screen_event_t"), event, &result);
277 if (!handled)
278 handleEvent(event);
279
280 if (type == SCREEN_EVENT_CLOSE)
281 finishCloseEvent(event);
282 }
283
284 m_eventThread->armEventsPending(count);
285 screen_destroy_event(event);
286}
287
288void QQnxScreenEventHandler::handleKeyboardEvent(screen_event_t event)
289{
290 // get flags of key event
291 int flags;
292 Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_FLAGS, &flags),
293 "Failed to query event flags");
294
295 // get key code
296 int sym;
297 Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_SYM, &sym),
298 "Failed to query event sym");
299
300 int modifiers;
301 Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_MODIFIERS, &modifiers),
302 "Failed to query event modifieres");
303
304 int scan;
305 Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_SCAN, &scan),
306 "Failed to query event scan");
307
308 int cap;
309 Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_CAP, &cap),
310 "Failed to query event cap");
311
312 int sequenceId = 0;
313 bool inject = true;
314
315 Q_FOREACH (QQnxScreenEventFilter *filter, m_eventFilters) {
316 if (filter->handleKeyboardEvent(flags, sym, modifiers, scan, cap, sequenceId)) {
317 inject = false;
318 break;
319 }
320 }
321
322 if (inject)
323 injectKeyboardEvent(flags, sym, modifiers, scan, cap);
324}
325
326void QQnxScreenEventHandler::handlePointerEvent(screen_event_t event)
327{
328 errno = 0;
329
330 // Query the window that was clicked
331 screen_window_t qnxWindow;
332 void *handle;
333 Q_SCREEN_CHECKERROR(screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, &handle),
334 "Failed to query event window");
335
336 qnxWindow = static_cast<screen_window_t>(handle);
337
338 // Query the button states
339 int buttonState = 0;
340 Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_BUTTONS, &buttonState),
341 "Failed to query event button state");
342
343 // Query the window position
344 int windowPos[2];
346 screen_get_event_property_iv(event, SCREEN_PROPERTY_SOURCE_POSITION, windowPos),
347 "Failed to query event window position");
348
349 // Query the screen position
350 int pos[2];
351 Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_POSITION, pos),
352 "Failed to query event position");
353
354 // Query the wheel delta
355 int wheelDelta = 0;
357 screen_get_event_property_iv(event, SCREEN_PROPERTY_MOUSE_WHEEL, &wheelDelta),
358 "Failed to query event wheel delta");
359
360 long long timestamp;
361 Q_SCREEN_CHECKERROR(screen_get_event_property_llv(event, SCREEN_PROPERTY_TIMESTAMP, &timestamp),
362 "Failed to get timestamp");
363
364 // Map window handle to top-level QWindow
365 QWindow *w = QQnxIntegration::instance()->window(qnxWindow);
366
367 // Generate enter and leave events as needed.
368 if (qnxWindow != m_lastMouseWindow) {
369 QWindow *wOld = QQnxIntegration::instance()->window(m_lastMouseWindow);
370
371 if (wOld) {
372 QWindowSystemInterface::handleLeaveEvent(wOld);
373 qCDebug(lcQpaScreenEvents) << "Qt leave, w=" << wOld;
374 }
375
376 if (w) {
377 QWindowSystemInterface::handleEnterEvent(w);
378 qCDebug(lcQpaScreenEvents) << "Qt enter, w=" << w;
379 }
380 }
381
382 m_lastMouseWindow = qnxWindow;
383
384 // Apply scaling to wheel delta and invert value for Qt. We'll probably want to scale
385 // this via a system preference at some point. But for now this is a sane value and makes
386 // the wheel usable.
387 wheelDelta *= -10;
388
389 // convert point to local coordinates
390 QPoint globalPoint(pos[0], pos[1]);
391 QPoint localPoint(windowPos[0], windowPos[1]);
392
393 // Convert buttons.
394 // Some QNX header files invert 'Right Button versus "Left Button' ('Right' == 0x01). But they also offer a 'Button Swap' bit,
395 // so we may receive events as shown. (If this is wrong, the fix is easy.)
396 // QNX Button mask is 8 buttons wide, with a maximum value of x080.
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; // AKA 'Qt::BackButton'
406 if (buttonState & 0x10)
407 buttons |= Qt::ExtraButton2; // AKA 'Qt::ForwardButton'
408 if (buttonState & 0x20)
409 buttons |= Qt::ExtraButton3;
410 if (buttonState & 0x40)
411 buttons |= Qt::ExtraButton4;
412 if (buttonState & 0x80)
413 buttons |= Qt::ExtraButton5;
414
415 if (w) {
416 // Inject mouse event into Qt only if something has changed.
417 if (m_lastGlobalMousePoint != globalPoint || m_lastLocalMousePoint != localPoint) {
418 QWindowSystemInterface::handleMouseEvent(w, timestamp, m_mouseDevice, localPoint,
419 globalPoint, buttons, Qt::NoButton,
420 QEvent::MouseMove);
421 qCDebug(lcQpaScreenEvents) << "Qt mouse move, w=" << w << ", (" << localPoint.x() << ","
422 << localPoint.y() << "), b=" << static_cast<int>(buttons);
423 }
424
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 };
430
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;
439 }
440 }
441
442 if (m_lastButtonState != 0 && buttons == 0) {
443 (static_cast<QQnxWindow *>(w->handle()))->handleActivationEvent();
444 }
445
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;
454 }
455 }
456 }
457
458 if (wheelDelta) {
459 // Screen only supports a single wheel, so we will assume Vertical orientation for
460 // now since that is pretty much standard.
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);
466 }
467 }
468
469 m_lastGlobalMousePoint = globalPoint;
470 m_lastLocalMousePoint = localPoint;
471 m_lastButtonState = buttons;
472}
473
474void QQnxScreenEventHandler::handleTouchEvent(screen_event_t event, int qnxType)
475{
476 // get display coordinates of touch
477 int pos[2];
478 Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_POSITION, pos),
479 "Failed to query event position");
480
481 QCursor::setPos(pos[0], pos[1]);
482
483 // get window coordinates of touch
484 int windowPos[2];
485 Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_SOURCE_POSITION, windowPos),
486 "Failed to query event window position");
487
488 // determine which finger touched
489 int touchId;
490 Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_TOUCH_ID, &touchId),
491 "Failed to query event touch id");
492
493 // determine which window was touched
494 void *handle;
495 Q_SCREEN_CHECKERROR(screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, &handle),
496 "Failed to query event window");
497
498 errno = 0;
499 int touchArea[2];
500 Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_SIZE, touchArea),
501 "Failed to query event touch area");
502
503 int touchPressure;
505 screen_get_event_property_iv(event, SCREEN_PROPERTY_TOUCH_PRESSURE, &touchPressure),
506 "Failed to query event touch pressure");
507
508 screen_window_t qnxWindow = static_cast<screen_window_t>(handle);
509
510 // check if finger is valid
511 if (touchId < MaximumTouchPoints) {
512
513 // Map window handle to top-level QWindow
514 QWindow *w = QQnxIntegration::instance()->window(qnxWindow);
515
516 // Generate enter and leave events as needed.
517 if (qnxWindow != m_lastMouseWindow) {
518 QWindow *wOld = QQnxIntegration::instance()->window(m_lastMouseWindow);
519
520 if (wOld) {
521 QWindowSystemInterface::handleLeaveEvent(wOld);
522 qCDebug(lcQpaScreenEvents) << "Qt leave, w=" << wOld;
523 }
524
525 if (w) {
526 QWindowSystemInterface::handleEnterEvent(w);
527 qCDebug(lcQpaScreenEvents) << "Qt enter, w=" << w;
528 }
529 }
530 m_lastMouseWindow = qnxWindow;
531
532 if (w) {
533 if (qnxType == SCREEN_EVENT_MTOUCH_RELEASE)
534 (static_cast<QQnxWindow *>(w->handle()))->handleActivationEvent();
535
536 // get size of screen which contains window
537 QPlatformScreen *platformScreen = QPlatformScreen::platformScreenForWindow(w);
538 QSizeF screenSize = platformScreen->geometry().size();
539
540 // update cached position of current touch point
541 m_touchPoints[touchId].normalPosition =
542 QPointF(static_cast<qreal>(pos[0]) / screenSize.width(),
543 static_cast<qreal>(pos[1]) / screenSize.height());
544
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();
549 while (parent) {
550 m_touchPoints[touchId].area.translate(parent->geometry().topLeft());
551 parent = parent->parent();
552 }
553
554 //Qt expects the pressure between 0 and 1. There is however no definite upper limit for
555 //the integer value of touch event pressure. The 200 was determined by experiment, it
556 //usually does not get higher than that.
557 m_touchPoints[touchId].pressure = static_cast<qreal>(touchPressure)/200.0;
558 // Can happen, because there is no upper limit for pressure
559 if (m_touchPoints[touchId].pressure > 1)
560 m_touchPoints[touchId].pressure = 1;
561
562 // determine event type and update state of current touch point
563 QEvent::Type type = QEvent::None;
564 switch (qnxType) {
565 case SCREEN_EVENT_MTOUCH_TOUCH:
566 m_touchPoints[touchId].state = QEventPoint::State::Pressed;
567 type = QEvent::TouchBegin;
568 break;
569 case SCREEN_EVENT_MTOUCH_MOVE:
570 m_touchPoints[touchId].state = QEventPoint::State::Updated;
571 type = QEvent::TouchUpdate;
572 break;
573 case SCREEN_EVENT_MTOUCH_RELEASE:
574 m_touchPoints[touchId].state = QEventPoint::State::Released;
575 type = QEvent::TouchEnd;
576 break;
577 }
578
579 // build list of active touch points
580 QList<QWindowSystemInterface::TouchPoint> pointList;
581 for (int i = 0; i < MaximumTouchPoints; i++) {
582 if (i == touchId) {
583 // current touch point is always active
584 pointList.append(m_touchPoints[i]);
585 } else if (m_touchPoints[i].state != QEventPoint::State::Released) {
586 // finger is down but did not move
587 m_touchPoints[i].state = QEventPoint::State::Stationary;
588 pointList.append(m_touchPoints[i]);
589 }
590 }
591
592 // inject event into Qt
593 QWindowSystemInterface::handleTouchEvent(w, m_touchDevice, pointList);
594 qCDebug(lcQpaScreenEvents) << "Qt touch, w =" << w
595 << ", p=" << m_touchPoints[touchId].area.topLeft()
596 << ", t=" << type;
597 }
598 }
599}
600
601void QQnxScreenEventHandler::handleCloseEvent(screen_event_t event)
602{
603 screen_window_t window = 0;
605 screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, (void**)&window),
606 "Failed to query window property");
607
608 Q_EMIT windowClosed(window);
609
610 // Map window handle to top-level QWindow
611 QWindow *w = QQnxIntegration::instance()->window(window);
612 if (w != 0)
613 QWindowSystemInterface::handleCloseEvent(w);
614}
615
616void QQnxScreenEventHandler::handleCreateEvent(screen_event_t event)
617{
618 screen_window_t window = 0;
619 int object_type = -1;
620
622 screen_get_event_property_iv(event, SCREEN_PROPERTY_OBJECT_TYPE, &object_type),
623 "Failed to query object type for create event");
624
625 switch (object_type) {
626 // Other object types than window produces an unnessary warning, thus ignore
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:
634 break;
635 case SCREEN_OBJECT_TYPE_WINDOW:
636 {
638 screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, (void**)&window),
639 "Failed to query window property");
640
641 Q_EMIT newWindowCreated(window);
642 break;
643 }
644 default:
645 qCDebug(lcQpaScreenEvents) << "Ignore create event for object type: " << object_type;
646 break;
647 }
648}
649
650void QQnxScreenEventHandler::handleDisplayEvent(screen_event_t event)
651{
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);
655 return;
656 }
657
658 int isAttached = 0;
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);
661 return;
662 }
663
664 qCDebug(lcQpaScreenEvents) << "display attachment is now:" << isAttached;
665
666 QQnxScreen *screen = m_qnxIntegration->screenForNative(nativeDisplay);
667
668 if (!screen) {
669 if (isAttached) {
670 int val[2];
671 screen_get_display_property_iv(nativeDisplay, SCREEN_PROPERTY_SIZE, val);
672 if (val[0] == 0 && val[1] == 0) //If screen size is invalid, wait for the next event
673 return;
674
675 qCDebug(lcQpaScreenEvents) << "Creating new QQnxScreen for newly attached display";
676 m_qnxIntegration->createDisplay(nativeDisplay, false /* not primary, we assume */);
677 }
678 } else if (!isAttached) {
679 // We never remove the primary display, the qpa plugin doesn't support that and it crashes.
680 // To support it, this would be needed:
681 // - Adjust all qnx qpa code which uses screens
682 // - Make QWidgetRepaintManager not dereference a null paint device
683 // - Create platform resources ( QQnxWindow ) for all QWindow because they would be deleted
684 // when you delete the screen
685
686 if (!screen->isPrimaryScreen()) {
687 // libscreen display is deactivated, let's remove the QQnxScreen / QScreen
688 qCDebug(lcQpaScreenEvents) << "Removing display";
689 m_qnxIntegration->removeDisplay(screen);
690 }
691 }
692}
693
694void QQnxScreenEventHandler::handlePropertyEvent(screen_event_t event)
695{
696 errno = 0;
697 int objectType;
699 screen_get_event_property_iv(event, SCREEN_PROPERTY_OBJECT_TYPE, &objectType),
700 "Failed to query object type property");
701
702 if (objectType != SCREEN_OBJECT_TYPE_WINDOW)
703 return;
704
705 errno = 0;
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);
709
710 if (window == 0) {
711 qCDebug(lcQpaScreenEvents) << "handlePositionEvent on NULL window";
712 return;
713 }
714
715 errno = 0;
716 int property;
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);
719
720 switch (property) {
721 case SCREEN_PROPERTY_FOCUS:
722 handleKeyboardFocusPropertyEvent(window);
723 break;
724 case SCREEN_PROPERTY_SIZE:
725 case SCREEN_PROPERTY_POSITION:
726 handleGeometryPropertyEvent(window);
727 break;
728 default:
729 // event ignored
730 qCDebug(lcQpaScreenEvents) << "Ignore property event for property: " << property;
731 }
732}
733
734void QQnxScreenEventHandler::handleKeyboardFocusPropertyEvent(screen_window_t window)
735{
736 errno = 0;
737 int focus = 0;
738 if (Q_UNLIKELY(window && screen_get_window_property_iv(window, SCREEN_PROPERTY_FOCUS, &focus) != 0))
739 qWarning("QQnx: failed to query keyboard focus property, errno=%d", errno);
740
741 QWindow *focusWindow = QQnxIntegration::instance()->window(window);
742
743 m_focusLostTimer.stop();
744
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);
749}
750
751void QQnxScreenEventHandler::handleGeometryPropertyEvent(screen_window_t window)
752{
753 int pos[2];
754 if (screen_get_window_property_iv(window, SCREEN_PROPERTY_POSITION, pos) != 0) {
755 qWarning("QQnx: failed to query window property, errno=%d", errno);
756 return;
757 }
758
759 int size[2];
760 if (screen_get_window_property_iv(window, SCREEN_PROPERTY_SIZE, size) != 0) {
761 qWarning("QQnx: failed to query window property, errno=%d", errno);
762 return;
763 }
764
765 QRect rect(pos[0], pos[1], size[0], size[1]);
766 QWindow *qtWindow = QQnxIntegration::instance()->window(window);
767 if (qtWindow) {
768 // Only update if the geometry actually changed to avoid duplicate events.
769 // QQnxWindow::setGeometry() already calls handleGeometryChange() internally,
770 // so we must not call it again here.
771 if (qtWindow->handle() && qtWindow->handle()->geometry() != rect)
772 qtWindow->handle()->setGeometry(rect);
773 }
774
775 qCDebug(lcQpaScreenEvents) << qtWindow << "moved to" << rect;
776}
777
778void QQnxScreenEventHandler::timerEvent(QTimerEvent *event)
779{
780 if (event->id() == m_focusLostTimer.id()) {
781 m_focusLostTimer.stop();
782 event->accept();
783 } else {
784 QObject::timerEvent(event);
785 }
786}
787
788QT_END_NAMESPACE
789
790void QQnxScreenEventHandler::handleManagerEvent(screen_event_t event)
791{
792 errno = 0;
793 int subtype;
795 screen_get_event_property_iv(event, SCREEN_PROPERTY_SUBTYPE, &subtype),
796 "Failed to query object type property");
797
798 errno = 0;
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);
802
803 switch (subtype) {
804 case SCREEN_EVENT_CLOSE: {
805 QWindow *closeWindow = QQnxIntegration::instance()->window(window);
806 closeWindow->close();
807 break;
808 }
809
810 default:
811 // event ignored
812 qCDebug(lcQpaScreenEvents) << "Ignore manager event for subtype: " << subtype;
813 }
814}
815
816void QQnxScreenEventHandler::processPostEvent(screen_window_t qnxWindow)
817{
818 QWindow *w = QQnxIntegration::instance()->window(qnxWindow);
819 if (!w)
820 return;
821 if (QQnxWindow *platformWindow = static_cast<QQnxWindow *>(w->handle()))
822 platformWindow->handlePostEvent();
823}
824
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
Definition qqnxscreen.h:60
The QQnxWindow is the base class of the various classes used as instances of QPlatformWindow in the Q...
Definition qqnxwindow.h:32
void handlePostEvent()
void handleActivationEvent()
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")
#define Q_SCREEN_CHECKERROR(x, message)
Definition qqnxglobal.h:17
QT_BEGIN_NAMESPACE int qtKeyForPrivateUseQnxKey(int key)
const int SCREEN_PROPERTY_SYM
Definition qqnxscreen.h:29
#define _SCREEN_VERSION
Definition qqnxscreen.h:19
const int SCREEN_PROPERTY_SCAN
Definition qqnxscreen.h:28
const int SCREEN_PROPERTY_FOCUS
Definition qqnxscreen.h:26
const int SCREEN_PROPERTY_MODIFIERS
Definition qqnxscreen.h:27
#define _SCREEN_MAKE_VERSION(major, minor, patch)
Definition qqnxscreen.h:18
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)