XCB: Set WM_CLASS.

Set the instance name and class name of the application windows.

Task-number: QTBUG-29396

Change-Id: Ia1fb492ab169108c3779deb8964bb731b322dd89
Reviewed-by: Uli Schlachter <psychon@znc.in>
Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
This commit is contained in:
Friedemann Kleint 2013-07-17 14:39:42 +02:00 committed by The Qt Project
parent 07bc530250
commit 81addcc1ed
5 changed files with 57 additions and 0 deletions

View File

@ -1232,6 +1232,7 @@ static const char * xcb_atomnames = {
// ICCCM window state
"WM_STATE\0"
"WM_CHANGE_STATE\0"
"WM_CLASS\0"
// Session management
"WM_CLIENT_LEADER\0"

View File

@ -102,6 +102,7 @@ namespace QXcbAtom {
// ICCCM window state
WM_STATE,
WM_CHANGE_STATE,
WM_CLASS,
// Session management
WM_CLIENT_LEADER,

View File

@ -369,4 +369,48 @@ QVariant QXcbIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
return QPlatformIntegration::styleHint(hint);
}
static QString argv0BaseName()
{
QString result;
const QStringList arguments = QCoreApplication::arguments();
if (!arguments.isEmpty() && !arguments.front().isEmpty()) {
result = arguments.front();
const int lastSlashPos = result.lastIndexOf(QLatin1Char('/'));
if (lastSlashPos != -1)
result.remove(0, lastSlashPos + 1);
}
return result;
}
static const char resourceNameVar[] = "RESOURCE_NAME";
QByteArray QXcbIntegration::wmClass() const
{
if (m_wmClass.isEmpty()) {
// Instance name according to ICCCM 4.1.2.5
QString name;
if (name.isEmpty() && qEnvironmentVariableIsSet(resourceNameVar))
name = QString::fromLocal8Bit(qgetenv(resourceNameVar));
if (name.isEmpty())
name = argv0BaseName();
// Note: QCoreApplication::applicationName() cannot be called from the QGuiApplication constructor,
// hence this delayed initialization.
QString className = QCoreApplication::applicationName();
if (className.isEmpty()) {
className = argv0BaseName();
if (!className.isEmpty() && className.at(0).isLower())
className[0] = className.at(0).toUpper();
}
if (!name.isEmpty() && !className.isEmpty()) {
m_wmClass = name.toLocal8Bit();
m_wmClass.append('\0');
m_wmClass.append(className.toLocal8Bit());
m_wmClass.append('\0');
}
}
return m_wmClass;
}
QT_END_NAMESPACE

View File

@ -99,6 +99,8 @@ public:
QXcbConnection *defaultConnection() const { return m_connections.first(); }
QByteArray wmClass() const;
private:
QList<QXcbConnection *> m_connections;
@ -115,6 +117,8 @@ private:
QScopedPointer<QPlatformServices> m_services;
friend class QXcbConnection; // access QPlatformIntegration::screenAdded()
mutable QByteArray m_wmClass;
};
QT_END_NAMESPACE

View File

@ -379,6 +379,13 @@ void QXcbWindow::create()
m_syncValue.hi = 0;
m_syncValue.lo = 0;
const QByteArray wmClass = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration())->wmClass();
if (!wmClass.isEmpty()) {
Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE,
m_window, atom(QXcbAtom::WM_CLASS),
XCB_ATOM_STRING, 8, wmClass.size(), wmClass.constData()));
}
if (m_usingSyncProtocol) {
m_syncCounter = xcb_generate_id(xcb_connection());
Q_XCB_CALL(xcb_sync_create_counter(xcb_connection(), m_syncCounter, m_syncValue));