How to notify style change to apps ?
-
Hi all,
When using KDE system settings, changing the style magically makes its way to all open applications so they load the new style.
I made a custom QStyle which has its own config tool. I'd like to reproduce the notification when I press "Apply" button so that apps using my style will reload the config.
How can I notify open apps for style (or config) changes ? -
Yes watching the config file is something that I intended to use as a fallback. Do the X server or Wayland support a "style change" message ?
I found some time ago this code (that does not work):
#if HAVE_X11 void ThemeManagerUI::notifyConfigurationChange() { using namespace QNativeInterface; QX11Application *native = qApp->nativeInterface<QX11Application>(); qDebug() << "FIXME notifyConfigurationChange()"; QByteArray stamp; QDataStream s(&stamp, QIODevice::WriteOnly); s << QDateTime::currentDateTime(); QByteArray settings_atom_name("_QT_SETTINGS_TIMESTAMP_"); settings_atom_name += XDisplayString(native->display()); xcb_connection_t *xcb_conn = native->connection(); xcb_intern_atom_cookie_t cookie = xcb_intern_atom(xcb_conn, false, settings_atom_name.size(), settings_atom_name.constData()); xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(xcb_conn, cookie, 0); xcb_atom_t atom = reply->atom; free(reply); xcb_change_property(xcb_conn, XCB_PROP_MODE_REPLACE, qApp->topLevelWindows().first()->winId(), atom, XCB_ATOM_ATOM, 8, stamp.size(), (const void *)stamp.constData()); //XChangeProperty(QX11Info::display(), QX11Info::appRootWindow(0), //ATOM(_QT_SETTINGS_TIMESTAMP), ATOM(_QT_SETTINGS_TIMESTAMP), 8, //PropModeReplace, (unsigned char *)stamp.data(), stamp.size()); } #endif
I don't know the purpose of this QT_SETTINGS_TIMESTAMP. Maybe there is a similar one for style change.
-
KDE does it through its QPA platform theme that it injects into all Qt applications running under it that use the same Qt installation as itself. It listens over D-Bus for settings changes.
While you probably can't use the same mechanism for your needs, you can do something similar within your style implementation. For example, if the configuration tool writes out a settings file, you can use
QFileSystemWatcher
to monitor for changes to that file and re-load it. Or also use D-Bus, or any of the myriad of other IPC mechanisms available - all based on what makes sense for your design. -
Yes watching the config file is something that I intended to use as a fallback. Do the X server or Wayland support a "style change" message ?
I found some time ago this code (that does not work):
#if HAVE_X11 void ThemeManagerUI::notifyConfigurationChange() { using namespace QNativeInterface; QX11Application *native = qApp->nativeInterface<QX11Application>(); qDebug() << "FIXME notifyConfigurationChange()"; QByteArray stamp; QDataStream s(&stamp, QIODevice::WriteOnly); s << QDateTime::currentDateTime(); QByteArray settings_atom_name("_QT_SETTINGS_TIMESTAMP_"); settings_atom_name += XDisplayString(native->display()); xcb_connection_t *xcb_conn = native->connection(); xcb_intern_atom_cookie_t cookie = xcb_intern_atom(xcb_conn, false, settings_atom_name.size(), settings_atom_name.constData()); xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(xcb_conn, cookie, 0); xcb_atom_t atom = reply->atom; free(reply); xcb_change_property(xcb_conn, XCB_PROP_MODE_REPLACE, qApp->topLevelWindows().first()->winId(), atom, XCB_ATOM_ATOM, 8, stamp.size(), (const void *)stamp.constData()); //XChangeProperty(QX11Info::display(), QX11Info::appRootWindow(0), //ATOM(_QT_SETTINGS_TIMESTAMP), ATOM(_QT_SETTINGS_TIMESTAMP), 8, //PropModeReplace, (unsigned char *)stamp.data(), stamp.size()); } #endif
I don't know the purpose of this QT_SETTINGS_TIMESTAMP. Maybe there is a similar one for style change.
-
Yes watching the config file is something that I intended to use as a fallback. Do the X server or Wayland support a "style change" message ?
I found some time ago this code (that does not work):
#if HAVE_X11 void ThemeManagerUI::notifyConfigurationChange() { using namespace QNativeInterface; QX11Application *native = qApp->nativeInterface<QX11Application>(); qDebug() << "FIXME notifyConfigurationChange()"; QByteArray stamp; QDataStream s(&stamp, QIODevice::WriteOnly); s << QDateTime::currentDateTime(); QByteArray settings_atom_name("_QT_SETTINGS_TIMESTAMP_"); settings_atom_name += XDisplayString(native->display()); xcb_connection_t *xcb_conn = native->connection(); xcb_intern_atom_cookie_t cookie = xcb_intern_atom(xcb_conn, false, settings_atom_name.size(), settings_atom_name.constData()); xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(xcb_conn, cookie, 0); xcb_atom_t atom = reply->atom; free(reply); xcb_change_property(xcb_conn, XCB_PROP_MODE_REPLACE, qApp->topLevelWindows().first()->winId(), atom, XCB_ATOM_ATOM, 8, stamp.size(), (const void *)stamp.constData()); //XChangeProperty(QX11Info::display(), QX11Info::appRootWindow(0), //ATOM(_QT_SETTINGS_TIMESTAMP), ATOM(_QT_SETTINGS_TIMESTAMP), 8, //PropModeReplace, (unsigned char *)stamp.data(), stamp.size()); } #endif
I don't know the purpose of this QT_SETTINGS_TIMESTAMP. Maybe there is a similar one for style change.
@dextermagnific said in How to notify style change to apps ?:
Do the X server or Wayland support a "style change" message
No, neither knows anything about theming, styles or anything of the sort. The closest thing you have for a generic way is the XDG Settings Portal, and it only conveys changes of light/dark mode and high contrast mode.
In X11 there used to be a generic Xsettings protocol, which the code you posted seems to be related to. I don't see how that helps you - applications have to listen and respond to it anyway; and it is X11 specific. If you want a push based approach rather than pull based you can create your own D-Bus interface. If you are worried that watching the configuration file is inefficient, don't be -
inotify
isn't polling. -
Thank you I'll go the inotify way. I just need to check that "commits" to the settings file are atomic so I won't be reading garbage (I read somewhere that QSettings handles well that).
-