QNX desktop support

Adds functionality to communicate with a desktop manager. This feature
is only enabled if "desktop" is added to the QT_QPA_PLATFORM environment
variable (e.g., "QT_QPA_PLATFORM=qnx:no-fullscreen:desktop").

Pick-to: 6.8
Change-Id: If98e0dda43692abce47f2d8f5f340bd7276ec901
Reviewed-by: James McDonnell <jmcdonnell@blackberry.com>
(cherry picked from commit 70b1db9c0e0a53ec7e47ba296a534d38559c702f)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Felix Lionardo 2025-01-16 15:52:26 -05:00 committed by Qt Cherry-pick Bot
parent 12f59b27e1
commit ef2200e327
6 changed files with 123 additions and 15 deletions

View File

@ -93,6 +93,10 @@ static inline QQnxIntegration::Options parseOptions(const QStringList &paramList
options |= QQnxIntegration::SurfacelessEGLContext;
}
if (paramList.contains("desktop"_L1)) {
options |= QQnxIntegration::Desktop;
}
return options;
}

View File

@ -54,7 +54,8 @@ public:
FullScreenApplication = 0x1,
RootWindow = 0x2,
AlwaysFlushScreenContext = 0x4,
SurfacelessEGLContext = 0x8
SurfacelessEGLContext = 0x8,
Desktop = 0x10
};
Q_DECLARE_FLAGS(Options, Option)
explicit QQnxIntegration(const QStringList &paramList);

View File

@ -192,6 +192,10 @@ bool QQnxScreenEventHandler::handleEvent(screen_event_t event, int qnxType)
handlePropertyEvent(event);
break;
case SCREEN_EVENT_MANAGER:
handleManagerEvent(event);
break;
default:
// event ignored
qCDebug(lcQpaScreenEvents) << Q_FUNC_INFO << "Unknown event" << qnxType;
@ -698,6 +702,11 @@ void QQnxScreenEventHandler::handlePropertyEvent(screen_event_t event)
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))
@ -768,4 +777,30 @@ void QQnxScreenEventHandler::timerEvent(QTimerEvent *event)
QT_END_NAMESPACE
void QQnxScreenEventHandler::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 ignored
qCDebug(lcQpaScreenEvents) << "Ignore manager event for subtype: " << subtype;
}
}
#include "moc_qqnxscreeneventhandler.cpp"

View File

@ -54,6 +54,7 @@ private:
void handlePropertyEvent(screen_event_t event);
void handleKeyboardFocusPropertyEvent(screen_window_t window);
void handleGeometryPropertyEvent(screen_window_t window);
void handleManagerEvent(screen_event_t event);
private:
enum {

View File

@ -119,7 +119,8 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, bool needRootW
m_exposed(true),
m_foreign(false),
m_windowState(Qt::WindowNoState),
m_firstActivateHandled(false)
m_firstActivateHandled(false),
m_desktopNotify(0)
{
qCDebug(lcQpaWindow) << "window =" << window << ", size =" << window->size();
@ -201,6 +202,26 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, bool needRootW
}
}
// QNX desktop integration.
if (QQnxIntegration::instance()->options() & QQnxIntegration::Desktop) {
// Determine if the window needs a frame.
switch (window->type()) {
case Qt::Popup:
case Qt::ToolTip:
m_desktopNotify = DesktopNotifyPosition | DesktopNotifyVisible;
break;
default:
m_desktopNotify = DesktopNotifyTitle | DesktopNotifyVisible;
break;
}
// Wait for the window manager to acknowledge the window's creation.
// The call returns immediately if there is no window manager.
screen_manage_window(m_window,
(m_desktopNotify & DesktopNotifyTitle) ? "Frame=Y" : "Frame=N");
}
int debug = 0;
if (Q_UNLIKELY(debug_fps())) {
debug |= SCREEN_DEBUG_GRAPH_FPS;
@ -308,12 +329,17 @@ void QQnxWindow::setGeometryHelper(const QRect &rect)
// Call base class method
QPlatformWindow::setGeometry(rect);
// Set window geometry equal to widget geometry
int val[2];
val[0] = rect.x();
val[1] = rect.y();
Q_SCREEN_CHECKERROR(screen_set_window_property_iv(m_window, SCREEN_PROPERTY_POSITION, val),
"Failed to set window position");
// Set window geometry equal to widget geometry
if (m_desktopNotify & DesktopNotifyPosition) {
notifyManager(QString::asprintf("Pos=%d,%d", rect.x(), rect.y()));
} else {
val[0] = rect.x();
val[1] = rect.y();
Q_SCREEN_CHECKERROR(screen_set_window_property_iv(m_window, SCREEN_PROPERTY_POSITION, val),
"Failed to set window position");
}
val[0] = rect.width();
val[1] = rect.height();
@ -373,8 +399,12 @@ void QQnxWindow::updateVisibility(bool parentVisible)
qCDebug(lcQpaWindow) << "parentVisible =" << parentVisible << "window =" << window();
// Set window visibility
int val = (m_visible && parentVisible) ? 1 : 0;
Q_SCREEN_CHECKERROR(screen_set_window_property_iv(m_window, SCREEN_PROPERTY_VISIBLE, &val),
"Failed to set window visibility");
if (m_desktopNotify & DesktopNotifyVisible) {
notifyManager(QString("Visible=") + (val ? "Y" : "N"));
} else {
Q_SCREEN_CHECKERROR(screen_set_window_property_iv(m_window, SCREEN_PROPERTY_VISIBLE, &val),
"Failed to set window visibility");
}
Q_FOREACH (QQnxWindow *childWindow, m_childWindows)
childWindow->updateVisibility(m_visible && parentVisible);
@ -421,16 +451,16 @@ void QQnxWindow::setBufferSize(const QSize &size)
screen_set_window_property_iv(m_window, SCREEN_PROPERTY_FORMAT, &format),
"Failed to set window format");
if (m_bufferSize.isValid()) {
// destroy buffers first, if resized
Q_SCREEN_CRITICALERROR(screen_destroy_window_buffers(m_window),
"Failed to destroy window buffers");
}
int val[2] = { nonEmptySize.width(), nonEmptySize.height() };
Q_SCREEN_CHECKERROR(screen_set_window_property_iv(m_window, SCREEN_PROPERTY_BUFFER_SIZE, val),
"Failed to set window buffer size");
if (m_bufferSize.isValid()) {
m_bufferSize = nonEmptySize;
resetBuffers();
return;
}
Q_SCREEN_CRITICALERROR(screen_create_window_buffers(m_window, MAX_BUFFER_COUNT),
"Failed to create window buffers");
@ -930,6 +960,33 @@ void QQnxWindow::addContextPermission()
grantString.data());
}
void QQnxWindow::setWindowTitle(const QString &title)
{
if (m_desktopNotify & DesktopNotifyTitle) {
QString titleStr = "Title=" + title;
notifyManager(titleStr);
}
}
void QQnxWindow::notifyManager(const QString &msg)
{
screen_event_t ev;
screen_create_event(&ev);
std::string str = msg.toStdString();
screen_set_event_property_iv(ev, SCREEN_PROPERTY_TYPE,
(const int[]){ SCREEN_EVENT_MANAGER });
screen_set_event_property_cv(ev, SCREEN_PROPERTY_USER_DATA, str.length(),
str.c_str());
screen_set_event_property_pv(ev, SCREEN_PROPERTY_WINDOW,
reinterpret_cast<void **>(&m_window));
screen_set_event_property_pv(ev, SCREEN_PROPERTY_CONTEXT,
reinterpret_cast<void **>(&m_screenContext));
Q_SCREEN_CHECKERROR(screen_inject_event(NULL, ev),
"Failed to send a message to the window manager");
}
void QQnxWindow::removeContextPermission()
{
QByteArray revokeString("context:");

View File

@ -75,6 +75,8 @@ public:
void windowPosted();
void handleActivationEvent();
void setWindowTitle(const QString &title);
protected:
virtual int pixelFormat() const = 0;
virtual void resetBuffers() = 0;
@ -95,6 +97,7 @@ private:
void setFocus(screen_window_t newFocusWindow);
bool showWithoutActivating() const;
bool focusable() const;
void notifyManager(const QString &msg);
void addContextPermission();
void removeContextPermission();
@ -119,6 +122,13 @@ private:
bool m_isTopLevel;
bool m_firstActivateHandled;
int m_desktopNotify;
enum {
DesktopNotifyTitle = 0x1,
DesktopNotifyPosition = 0x2,
DesktopNotifyVisible = 0x2
};
};
QT_END_NAMESPACE