123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808 | // Copyright (C) 2013 BlackBerry Limited. All rights reserved.// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only#undef QT_NO_FOREACH// this file contains unported legacy Q_FOREACH uses#include"qqnxglobal.h"#include"qqnxscreeneventhandler.h"#include"qqnxscreeneventthread.h"#include"qqnxintegration.h"#include"qqnxkeytranslator.h"#include"qqnxscreen.h"#include"qqnxscreeneventfilter.h"#include"qqnxscreentraits.h"#include <QDebug>#include <QGuiApplication>#include <errno.h>#include <sys/keycodes.h>using namespacestd::chrono_literals;Q_LOGGING_CATEGORY(lcQpaScreenEvents,"qt.qpa.screen.events");static intqtKey(int virtualKey,QChar::Category category){if(Q_UNLIKELY(category ==QChar::Other_NotAssigned))return virtualKey;else if(category ==QChar::Other_PrivateUse)returnqtKeyForPrivateUseQnxKey(virtualKey);elsereturnQChar::toUpper(virtualKey);}static QString keyString(int sym,QChar::Category category){if(Q_UNLIKELY(category ==QChar::Other_NotAssigned)) {returnQString();}else if(category ==QChar::Other_PrivateUse) {returnkeyStringForPrivateUseQnxKey(sym);}else{return QStringView{QChar::fromUcs4(sym)}.toString();}}static QString capKeyString(int cap,int modifiers,int key){if(cap >=0x20&& cap <=0x0ff) {if(modifiers & KEYMOD_CTRL)returnQChar((int)(key &0x3f));}returnQString();}template<typename T>static voidfinishCloseEvent(screen_event_t event){ T t;screen_get_event_property_pv(event, screen_traits<T>::propertyName,reinterpret_cast<void**>(&t)); screen_traits<T>::destroy(t);}static voidfinishCloseEvent(screen_event_t event){// Let libscreen know that we're finished with anything that may have been acquired.int objectType = SCREEN_OBJECT_TYPE_CONTEXT;screen_get_event_property_iv(event, SCREEN_PROPERTY_OBJECT_TYPE, &objectType);switch(objectType) {case SCREEN_OBJECT_TYPE_CONTEXT: finishCloseEvent<screen_context_t>(event);break;case SCREEN_OBJECT_TYPE_DEVICE: finishCloseEvent<screen_device_t>(event);break;case SCREEN_OBJECT_TYPE_DISPLAY:// no screen_destroy_displaybreak;case SCREEN_OBJECT_TYPE_GROUP: finishCloseEvent<screen_group_t>(event);break;case SCREEN_OBJECT_TYPE_PIXMAP: finishCloseEvent<screen_pixmap_t>(event);break;case SCREEN_OBJECT_TYPE_SESSION: finishCloseEvent<screen_session_t>(event);break;#if _SCREEN_VERSION >= _SCREEN_MAKE_VERSION(2, 0, 0)case SCREEN_OBJECT_TYPE_STREAM: finishCloseEvent<screen_stream_t>(event);break;#endifcase SCREEN_OBJECT_TYPE_WINDOW: finishCloseEvent<screen_window_t>(event);break;}} QT_BEGIN_NAMESPACE using namespaceQt::StringLiterals;QQnxScreenEventHandler::QQnxScreenEventHandler(QQnxIntegration *integration):m_qnxIntegration(integration),m_lastButtonState(Qt::NoButton),m_lastMouseWindow(0),m_touchDevice(0),m_mouseDevice(0),m_eventThread(0){// Create a touch device m_touchDevice =newQPointingDevice("touchscreen"_L1,1,QInputDevice::DeviceType::TouchScreen,QPointingDevice::PointerType::Finger,QPointingDevice::Capability::Position |QPointingDevice::Capability::Area |QPointingDevice::Capability::Pressure |QPointingDevice::Capability::NormalizedPosition, MaximumTouchPoints,8);QWindowSystemInterface::registerInputDevice(m_touchDevice); m_mouseDevice =newQPointingDevice("mouse"_L1,2,QInputDevice::DeviceType::Mouse,QPointingDevice::PointerType::Generic,QPointingDevice::Capability::Position,1,8);QWindowSystemInterface::registerInputDevice(m_mouseDevice);// initialize array of touch pointsfor(int i =0; i < MaximumTouchPoints; i++) {// map array index to id m_touchPoints[i].id = i;// pressure is not supported - use default m_touchPoints[i].pressure =1.0;// nothing touching m_touchPoints[i].state =QEventPoint::State::Released;}}voidQQnxScreenEventHandler::addScreenEventFilter(QQnxScreenEventFilter *filter){ m_eventFilters.append(filter);}voidQQnxScreenEventHandler::removeScreenEventFilter(QQnxScreenEventFilter *filter){ m_eventFilters.removeOne(filter);}boolQQnxScreenEventHandler::handleEvent(screen_event_t event){// get the event typeint qnxType;Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &qnxType),"Failed to query event type");returnhandleEvent(event, qnxType);}boolQQnxScreenEventHandler::handleEvent(screen_event_t event,int qnxType){switch(qnxType) {case SCREEN_EVENT_MTOUCH_TOUCH:case SCREEN_EVENT_MTOUCH_MOVE:case SCREEN_EVENT_MTOUCH_RELEASE:handleTouchEvent(event, qnxType);break;case SCREEN_EVENT_KEYBOARD:handleKeyboardEvent(event);break;case SCREEN_EVENT_POINTER:handlePointerEvent(event);break;case SCREEN_EVENT_CREATE:handleCreateEvent(event);break;case SCREEN_EVENT_CLOSE:handleCloseEvent(event);break;case SCREEN_EVENT_DISPLAY:handleDisplayEvent(event);break;case SCREEN_EVENT_PROPERTY:handlePropertyEvent(event);break;case SCREEN_EVENT_MANAGER:handleManagerEvent(event);break;default:// event ignoredqCDebug(lcQpaScreenEvents) << Q_FUNC_INFO <<"Unknown event"<< qnxType;return false;}return true;}voidQQnxScreenEventHandler::injectKeyboardEvent(int flags,int sym,int modifiers,int scan,int cap){Q_UNUSED(scan);if(!(flags & KEY_CAP_VALID))return;// Correct erroneous information.if((flags & KEY_SYM_VALID) && sym ==static_cast<int>(0xFFFFFFFF)) flags &= ~(KEY_SYM_VALID);Qt::KeyboardModifiers qtMod =Qt::NoModifier;if(modifiers & KEYMOD_SHIFT) qtMod |=Qt::ShiftModifier;if(modifiers & KEYMOD_CTRL) qtMod |=Qt::ControlModifier;if(modifiers & KEYMOD_ALT) qtMod |=Qt::AltModifier;if(isKeypadKey(cap)) qtMod |=Qt::KeypadModifier;QEvent::Type type = (flags & KEY_DOWN) ?QEvent::KeyPress :QEvent::KeyRelease;int virtualKey = (flags & KEY_SYM_VALID) ? sym : cap;QChar::Category category =QChar::category(virtualKey);int key =qtKey(virtualKey, category); QString keyStr = (flags & KEY_SYM_VALID) ?keyString(sym, category) :capKeyString(cap, modifiers, key);QWindowSystemInterface::handleExtendedKeyEvent(QGuiApplication::focusWindow(), type, key, qtMod, scan, virtualKey, modifiers, keyStr, flags & KEY_REPEAT);qCDebug(lcQpaScreenEvents) <<"Qt key t="<< type <<", k="<< key <<", s="<< keyStr;}voidQQnxScreenEventHandler::setScreenEventThread(QQnxScreenEventThread *eventThread){ m_eventThread = eventThread;connect(m_eventThread, &QQnxScreenEventThread::eventsPending,this, &QQnxScreenEventHandler::processEvents);}voidQQnxScreenEventHandler::processEvents(){if(!m_eventThread)return; screen_event_t event =nullptr;if(screen_create_event(&event) !=0)return;int count =0;for(;;) {if(screen_get_event(m_eventThread->context(), event,0) !=0)break;int type = SCREEN_EVENT_NONE;screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &type);if(type == SCREEN_EVENT_NONE)break;++count; qintptr result =0; QAbstractEventDispatcher* dispatcher =QAbstractEventDispatcher::instance();bool handled = dispatcher && dispatcher->filterNativeEvent(QByteArrayLiteral("screen_event_t"), event, &result);if(!handled)handleEvent(event);if(type == SCREEN_EVENT_CLOSE)finishCloseEvent(event);} m_eventThread->armEventsPending(count);screen_destroy_event(event);}voidQQnxScreenEventHandler::handleKeyboardEvent(screen_event_t event){// get flags of key eventint flags;Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_FLAGS, &flags),"Failed to query event flags");// get key codeint sym;Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_SYM, &sym),"Failed to query event sym");int modifiers;Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_MODIFIERS, &modifiers),"Failed to query event modifieres");int scan;Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_SCAN, &scan),"Failed to query event scan");int cap;Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_CAP, &cap),"Failed to query event cap");int sequenceId =0;bool inject =true;Q_FOREACH(QQnxScreenEventFilter *filter, m_eventFilters) {if(filter->handleKeyboardEvent(flags, sym, modifiers, scan, cap, sequenceId)) { inject =false;break;}}if(inject)injectKeyboardEvent(flags, sym, modifiers, scan, cap);}voidQQnxScreenEventHandler::handlePointerEvent(screen_event_t event){ errno =0;// Query the window that was clicked screen_window_t qnxWindow;void*handle;Q_SCREEN_CHECKERROR(screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, &handle),"Failed to query event window"); qnxWindow =static_cast<screen_window_t>(handle);// Query the button statesint buttonState =0;Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_BUTTONS, &buttonState),"Failed to query event button state");// Query the window positionint windowPos[2];Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_SOURCE_POSITION, windowPos),"Failed to query event window position");// Query the screen positionint pos[2];Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_POSITION, pos),"Failed to query event position");// Query the wheel deltaint wheelDelta =0;Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_MOUSE_WHEEL, &wheelDelta),"Failed to query event wheel delta");long long timestamp;Q_SCREEN_CHECKERROR(screen_get_event_property_llv(event, SCREEN_PROPERTY_TIMESTAMP, ×tamp),"Failed to get timestamp");// Map window handle to top-level QWindow QWindow *w =QQnxIntegration::instance()->window(qnxWindow);// Generate enter and leave events as needed.if(qnxWindow != m_lastMouseWindow) { QWindow *wOld =QQnxIntegration::instance()->window(m_lastMouseWindow);if(wOld) {QWindowSystemInterface::handleLeaveEvent(wOld);qCDebug(lcQpaScreenEvents) <<"Qt leave, w="<< wOld;}if(w) {QWindowSystemInterface::handleEnterEvent(w);qCDebug(lcQpaScreenEvents) <<"Qt enter, w="<< w;}} m_lastMouseWindow = qnxWindow;// Apply scaling to wheel delta and invert value for Qt. We'll probably want to scale// this via a system preference at some point. But for now this is a sane value and makes// the wheel usable. wheelDelta *= -10;// convert point to local coordinates QPoint globalPoint(pos[0], pos[1]); QPoint localPoint(windowPos[0], windowPos[1]);// Convert buttons.// Some QNX header files invert 'Right Button versus "Left Button' ('Right' == 0x01). But they also offer a 'Button Swap' bit,// so we may receive events as shown. (If this is wrong, the fix is easy.)// QNX Button mask is 8 buttons wide, with a maximum value of x080.Qt::MouseButtons buttons =Qt::NoButton;if(buttonState &0x01) buttons |=Qt::LeftButton;if(buttonState &0x02) buttons |=Qt::MiddleButton;if(buttonState &0x04) buttons |=Qt::RightButton;if(buttonState &0x08) buttons |=Qt::ExtraButton1;// AKA 'Qt::BackButton'if(buttonState &0x10) buttons |=Qt::ExtraButton2;// AKA 'Qt::ForwardButton'if(buttonState &0x20) buttons |=Qt::ExtraButton3;if(buttonState &0x40) buttons |=Qt::ExtraButton4;if(buttonState &0x80) buttons |=Qt::ExtraButton5;if(w) {// Inject mouse event into Qt only if something has changed.if(m_lastGlobalMousePoint != globalPoint || m_lastLocalMousePoint != localPoint) {QWindowSystemInterface::handleMouseEvent(w, timestamp, m_mouseDevice, localPoint, globalPoint, buttons,Qt::NoButton,QEvent::MouseMove);qCDebug(lcQpaScreenEvents) <<"Qt mouse move, w="<< w <<", ("<< localPoint.x() <<","<< localPoint.y() <<"), b="<<static_cast<int>(buttons);}if(m_lastButtonState != buttons) {static constauto supportedButtons = {Qt::LeftButton,Qt::MiddleButton,Qt::RightButton,Qt::ExtraButton1,Qt::ExtraButton2,Qt::ExtraButton3,Qt::ExtraButton4,Qt::ExtraButton5 };int releasedButtons = (m_lastButtonState ^ buttons) & ~buttons;for(auto button : supportedButtons) {if(releasedButtons & button) {QWindowSystemInterface::handleMouseEvent(w, timestamp, m_mouseDevice, localPoint, globalPoint, buttons, button,QEvent::MouseButtonRelease);qCDebug(lcQpaScreenEvents) <<"Qt mouse release, w="<< w <<", ("<< localPoint.x()<<","<< localPoint.y() <<"), b="<< button;}}if(m_lastButtonState !=0&& buttons ==0) {(static_cast<QQnxWindow *>(w->handle()))->handleActivationEvent();}int pressedButtons = (m_lastButtonState ^ buttons) & buttons;for(auto button : supportedButtons) {if(pressedButtons & button) {QWindowSystemInterface::handleMouseEvent(w, timestamp, m_mouseDevice, localPoint, globalPoint, buttons, button,QEvent::MouseButtonPress);qCDebug(lcQpaScreenEvents) <<"Qt mouse press, w="<< w <<", ("<< localPoint.x()<<","<< localPoint.y() <<"), b="<< button;}}}if(wheelDelta) {// Screen only supports a single wheel, so we will assume Vertical orientation for// now since that is pretty much standard. QPoint angleDelta(0, wheelDelta);QWindowSystemInterface::handleWheelEvent(w, timestamp, m_mouseDevice, localPoint, globalPoint,QPoint(), angleDelta);qCDebug(lcQpaScreenEvents) <<"Qt wheel, w="<< w <<", ("<< localPoint.x() <<","<< localPoint.y() <<"), d="<<static_cast<int>(wheelDelta);}} m_lastGlobalMousePoint = globalPoint; m_lastLocalMousePoint = localPoint; m_lastButtonState = buttons;}voidQQnxScreenEventHandler::handleTouchEvent(screen_event_t event,int qnxType){// get display coordinates of touchint pos[2];Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_POSITION, pos),"Failed to query event position");QCursor::setPos(pos[0], pos[1]);// get window coordinates of touchint windowPos[2];Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_SOURCE_POSITION, windowPos),"Failed to query event window position");// determine which finger touchedint touchId;Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_TOUCH_ID, &touchId),"Failed to query event touch id");// determine which window was touchedvoid*handle;Q_SCREEN_CHECKERROR(screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, &handle),"Failed to query event window"); errno =0;int touchArea[2];Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_SIZE, touchArea),"Failed to query event touch area");int touchPressure;Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_TOUCH_PRESSURE, &touchPressure),"Failed to query event touch pressure"); screen_window_t qnxWindow =static_cast<screen_window_t>(handle);// check if finger is validif(touchId < MaximumTouchPoints) {// Map window handle to top-level QWindow QWindow *w =QQnxIntegration::instance()->window(qnxWindow);// Generate enter and leave events as needed.if(qnxWindow != m_lastMouseWindow) { QWindow *wOld =QQnxIntegration::instance()->window(m_lastMouseWindow);if(wOld) {QWindowSystemInterface::handleLeaveEvent(wOld);qCDebug(lcQpaScreenEvents) <<"Qt leave, w="<< wOld;}if(w) {QWindowSystemInterface::handleEnterEvent(w);qCDebug(lcQpaScreenEvents) <<"Qt enter, w="<< w;}} m_lastMouseWindow = qnxWindow;if(w) {if(qnxType == SCREEN_EVENT_MTOUCH_RELEASE)(static_cast<QQnxWindow *>(w->handle()))->handleActivationEvent();// get size of screen which contains window QPlatformScreen *platformScreen =QPlatformScreen::platformScreenForWindow(w); QSizeF screenSize = platformScreen->geometry().size();// update cached position of current touch point m_touchPoints[touchId].normalPosition =QPointF(static_cast<qreal>(pos[0]) / screenSize.width(),static_cast<qreal>(pos[1]) / screenSize.height()); m_touchPoints[touchId].area =QRectF(w->geometry().left() + windowPos[0] - (touchArea[0]>>1), w->geometry().top() + windowPos[1] - (touchArea[1]>>1),(touchArea[0]>>1), (touchArea[1]>>1)); QWindow *parent = w->parent();while(parent) { m_touchPoints[touchId].area.translate(parent->geometry().topLeft()); parent = parent->parent();}//Qt expects the pressure between 0 and 1. There is however no definite upper limit for//the integer value of touch event pressure. The 200 was determined by experiment, it//usually does not get higher than that. m_touchPoints[touchId].pressure =static_cast<qreal>(touchPressure)/200.0;// Can happen, because there is no upper limit for pressureif(m_touchPoints[touchId].pressure >1) m_touchPoints[touchId].pressure =1;// determine event type and update state of current touch pointQEvent::Type type =QEvent::None;switch(qnxType) {case SCREEN_EVENT_MTOUCH_TOUCH: m_touchPoints[touchId].state =QEventPoint::State::Pressed; type =QEvent::TouchBegin;break;case SCREEN_EVENT_MTOUCH_MOVE: m_touchPoints[touchId].state =QEventPoint::State::Updated; type =QEvent::TouchUpdate;break;case SCREEN_EVENT_MTOUCH_RELEASE: m_touchPoints[touchId].state =QEventPoint::State::Released; type =QEvent::TouchEnd;break;}// build list of active touch points QList<QWindowSystemInterface::TouchPoint> pointList;for(int i =0; i < MaximumTouchPoints; i++) {if(i == touchId) {// current touch point is always active pointList.append(m_touchPoints[i]);}else if(m_touchPoints[i].state !=QEventPoint::State::Released) {// finger is down but did not move m_touchPoints[i].state =QEventPoint::State::Stationary; pointList.append(m_touchPoints[i]);}}// inject event into QtQWindowSystemInterface::handleTouchEvent(w, m_touchDevice, pointList);qCDebug(lcQpaScreenEvents) <<"Qt touch, w ="<< w <<", p="<< m_touchPoints[touchId].area.topLeft()<<", t="<< type;}}}voidQQnxScreenEventHandler::handleCloseEvent(screen_event_t event){ screen_window_t window =0;Q_SCREEN_CHECKERROR(screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, (void**)&window),"Failed to query window property"); Q_EMIT windowClosed(window);// Map window handle to top-level QWindow QWindow *w =QQnxIntegration::instance()->window(window);if(w !=0)QWindowSystemInterface::handleCloseEvent(w);}voidQQnxScreenEventHandler::handleCreateEvent(screen_event_t event){ screen_window_t window =0;int object_type = -1;Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_OBJECT_TYPE, &object_type),"Failed to query object type for create event");switch(object_type) {// Other object types than window produces an unnessary warning, thus ignore case SCREEN_OBJECT_TYPE_CONTEXT:case SCREEN_OBJECT_TYPE_GROUP:case SCREEN_OBJECT_TYPE_DISPLAY:case SCREEN_OBJECT_TYPE_DEVICE:case SCREEN_OBJECT_TYPE_PIXMAP:case SCREEN_OBJECT_TYPE_SESSION:case SCREEN_OBJECT_TYPE_STREAM:break;case SCREEN_OBJECT_TYPE_WINDOW:{Q_SCREEN_CHECKERROR(screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, (void**)&window),"Failed to query window property"); Q_EMIT newWindowCreated(window);break;}default:qCDebug(lcQpaScreenEvents) <<"Ignore create event for object type: "<< object_type;break;}}voidQQnxScreenEventHandler::handleDisplayEvent(screen_event_t event){ screen_display_t nativeDisplay =0;if(screen_get_event_property_pv(event, SCREEN_PROPERTY_DISPLAY, (void**)&nativeDisplay) !=0) {qWarning("QQnx: failed to query display property, errno=%d", errno);return;}int isAttached =0;if(screen_get_event_property_iv(event, SCREEN_PROPERTY_ATTACHED, &isAttached) !=0) {qWarning("QQnx: failed to query display attached property, errno=%d", errno);return;}qCDebug(lcQpaScreenEvents) <<"display attachment is now:"<< isAttached; QQnxScreen *screen = m_qnxIntegration->screenForNative(nativeDisplay);if(!screen) {if(isAttached) {int val[2];screen_get_display_property_iv(nativeDisplay, SCREEN_PROPERTY_SIZE, val);if(val[0] ==0&& val[1] ==0)//If screen size is invalid, wait for the next eventreturn;qCDebug(lcQpaScreenEvents) <<"Creating new QQnxScreen for newly attached display"; m_qnxIntegration->createDisplay(nativeDisplay,false/* not primary, we assume */);}}else if(!isAttached) {// We never remove the primary display, the qpa plugin doesn't support that and it crashes.// To support it, this would be needed:// - Adjust all qnx qpa code which uses screens// - Make QWidgetRepaintManager not dereference a null paint device// - Create platform resources ( QQnxWindow ) for all QWindow because they would be deleted// when you delete the screenif(!screen->isPrimaryScreen()) {// libscreen display is deactivated, let's remove the QQnxScreen / QScreenqCDebug(lcQpaScreenEvents) <<"Removing display"; m_qnxIntegration->removeDisplay(screen);}}}voidQQnxScreenEventHandler::handlePropertyEvent(screen_event_t event){ errno =0;int objectType;Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_OBJECT_TYPE, &objectType),"Failed to query object type property");if(objectType != SCREEN_OBJECT_TYPE_WINDOW)return; errno =0; screen_window_t window =0;if(Q_UNLIKELY(screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, (void**)&window) !=0))qFatal("QQnx: failed to query window property, errno=%d", errno);if(window ==0) {qCDebug(lcQpaScreenEvents) <<"handlePositionEvent on NULL window";return;} errno =0;int property;if(Q_UNLIKELY(screen_get_event_property_iv(event, SCREEN_PROPERTY_NAME, &property) !=0))qWarning("QQnx: failed to query window property, errno=%d", errno);switch(property) {case SCREEN_PROPERTY_FOCUS:handleKeyboardFocusPropertyEvent(window);break;case SCREEN_PROPERTY_SIZE:case SCREEN_PROPERTY_POSITION:handleGeometryPropertyEvent(window);break;default:// event ignoredqCDebug(lcQpaScreenEvents) <<"Ignore property event for property: "<< property;}}voidQQnxScreenEventHandler::handleKeyboardFocusPropertyEvent(screen_window_t window){ errno =0;int focus =0;if(Q_UNLIKELY(window &&screen_get_window_property_iv(window, SCREEN_PROPERTY_FOCUS, &focus) !=0))qWarning("QQnx: failed to query keyboard focus property, errno=%d", errno); QWindow *focusWindow =QQnxIntegration::instance()->window(window); m_focusLostTimer.stop();if(focus && focusWindow !=QGuiApplication::focusWindow())QWindowSystemInterface::handleFocusWindowChanged(focusWindow,Qt::ActiveWindowFocusReason);else if(!focus && focusWindow ==QGuiApplication::focusWindow()) m_focusLostTimer.start(50ms,this);}voidQQnxScreenEventHandler::handleGeometryPropertyEvent(screen_window_t window){int pos[2];if(screen_get_window_property_iv(window, SCREEN_PROPERTY_POSITION, pos) !=0) {qWarning("QQnx: failed to query window property, errno=%d", errno);return;}int size[2];if(screen_get_window_property_iv(window, SCREEN_PROPERTY_SIZE, size) !=0) {qWarning("QQnx: failed to query window property, errno=%d", errno);return;} QRect rect(pos[0], pos[1], size[0], size[1]); QWindow *qtWindow =QQnxIntegration::instance()->window(window);if(qtWindow) { qtWindow->setGeometry(rect);QWindowSystemInterface::handleGeometryChange(qtWindow, rect);}qCDebug(lcQpaScreenEvents) << qtWindow <<"moved to"<< rect;}voidQQnxScreenEventHandler::timerEvent(QTimerEvent *event){if(event->id() == m_focusLostTimer.id()) { m_focusLostTimer.stop(); event->accept();}else{QObject::timerEvent(event);}} QT_END_NAMESPACE voidQQnxScreenEventHandler::handleManagerEvent(screen_event_t event){ errno =0;int subtype;Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_SUBTYPE, &subtype),"Failed to query object type property"); errno =0; screen_window_t window =0;if(screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, (void**)&window) !=0)qFatal("QQnx: failed to query window property, errno=%d", errno);switch(subtype) {case SCREEN_EVENT_CLOSE: { QWindow *closeWindow =QQnxIntegration::instance()->window(window); closeWindow->close();break;}default:// event ignoredqCDebug(lcQpaScreenEvents) <<"Ignore manager event for subtype: "<< subtype;}}#include"moc_qqnxscreeneventhandler.cpp"
|