Skip to content

Commit

Permalink
QNX desktop support
Browse files Browse the repository at this point in the history
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 <[email protected]>
(cherry picked from commit 70b1db9)
Reviewed-by: Qt Cherry-pick Bot <[email protected]>
  • Loading branch information
felixlionardo-qnx authored and Qt Cherry-pick Bot committed Jan 25, 2025
1 parent 12f59b2 commit ef2200e
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 15 deletions.
4 changes: 4 additions & 0 deletions src/plugins/platforms/qnx/qqnxintegration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
3 changes: 2 additions & 1 deletion src/plugins/platforms/qnx/qqnxintegration.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ class QQnxIntegration : public QPlatformIntegration
FullScreenApplication = 0x1,
RootWindow = 0x2,
AlwaysFlushScreenContext = 0x4,
SurfacelessEGLContext = 0x8
SurfacelessEGLContext = 0x8,
Desktop = 0x10
};
Q_DECLARE_FLAGS(Options, Option)
explicit QQnxIntegration(const QStringList &paramList);
Expand Down
35 changes: 35 additions & 0 deletions src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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"
1 change: 1 addition & 0 deletions src/plugins/platforms/qnx/qqnxscreeneventhandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ private Q_SLOTS:
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 {
Expand Down
85 changes: 71 additions & 14 deletions src/plugins/platforms/qnx/qqnxwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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");

Expand Down Expand Up @@ -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:");
Expand Down
10 changes: 10 additions & 0 deletions src/plugins/platforms/qnx/qqnxwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ friend class QQnxScreen;
void windowPosted();
void handleActivationEvent();

void setWindowTitle(const QString &title);

protected:
virtual int pixelFormat() const = 0;
virtual void resetBuffers() = 0;
Expand All @@ -95,6 +97,7 @@ friend class QQnxScreen;
void setFocus(screen_window_t newFocusWindow);
bool showWithoutActivating() const;
bool focusable() const;
void notifyManager(const QString &msg);

void addContextPermission();
void removeContextPermission();
Expand All @@ -119,6 +122,13 @@ friend class QQnxScreen;

bool m_isTopLevel;
bool m_firstActivateHandled;
int m_desktopNotify;

enum {
DesktopNotifyTitle = 0x1,
DesktopNotifyPosition = 0x2,
DesktopNotifyVisible = 0x2
};
};

QT_END_NAMESPACE
Expand Down

0 comments on commit ef2200e

Please sign in to comment.