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