diff options
author | Uli Schlachter <psychon@znc.in> | 2014-12-04 17:57:02 +0100 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@digia.com> | 2014-12-09 16:01:59 +0100 |
commit | 2203d9d93e24e00d6e9bc9bda0e65a0c7f9923cc (patch) | |
tree | 67cf443dc490d58a66c63cc2494fd96f9424d4a2 /src/widgets/util | |
parent | 459e22a9dfd7105918528def302604a6c0628115 (diff) |
xcb: Fix transparent tray backgrounds with 24bpp tray visuals
Commit 0eefa785a0d8 ported Qt4's method of indirectly drawing the tray
icon's background to Qt5. This commit makes it work a bit better.
When drawing the tray's background, we use a ClearArea request to make
the X11 server fill the tray icon with its background. Then we grab that
background from the server and paint the icon on top of it. So this is
pretty much pseudo-transparency at work. One small ingredient that was
missing before is the BackgroundPixmap of the tray icon. If this
attribute is set to ParentRelative, then our tray icon inherits the
background of its parent window. That way the ClearArea will actually
produce the expected background.
Task-number: QTBUG-35832
Change-Id: I63fc4609064d8f858ca9e5cc290409a298b918b7
Reviewed-by: Jørgen Lind <jorgen.lind@theqtcompany.com>
Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
Diffstat (limited to 'src/widgets/util')
-rw-r--r-- | src/widgets/util/qsystemtrayicon_x11.cpp | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/src/widgets/util/qsystemtrayicon_x11.cpp b/src/widgets/util/qsystemtrayicon_x11.cpp index eee100d279..ba80734876 100644 --- a/src/widgets/util/qsystemtrayicon_x11.cpp +++ b/src/widgets/util/qsystemtrayicon_x11.cpp @@ -107,13 +107,29 @@ QSystemTrayIconSys::QSystemTrayIconSys(QSystemTrayIcon *qIn) // If we have a visual that has an alpha channel, we can paint this widget with a transparent // background and it will work. // However, if there's no alpha channel visual, in order for transparent tray icons to work, - // we do not have a transparent background on the widget, but call xcb_clear_region before - // painting the icon + // we do not have a transparent background on the widget, but set the BackPixmap property of our + // window to ParentRelative (so that it inherits the background of its X11 parent window), call + // xcb_clear_region before painting (so that the inherited background is visible) and then grab + // the just-drawn background from the X11 server. bool hasAlphaChannel = false; QMetaObject::invokeMethod(QGuiApplication::platformNativeInterface(), "systrayVisualHasAlphaChannel", Qt::DirectConnection, Q_RETURN_ARG(bool, hasAlphaChannel)); setAttribute(Qt::WA_TranslucentBackground, hasAlphaChannel); + if (!hasAlphaChannel) { + createWinId(); + QMetaObject::invokeMethod(QGuiApplication::platformNativeInterface(), + "setParentRelativeBackPixmap", Qt::DirectConnection, + Q_ARG(const QWindow *, windowHandle()) + ); + + // XXX: This is actually required, but breaks things ("QWidget::paintEngine: Should no + // longer be called"). Why is this needed? When the widget is drawn, we use tricks to grab + // the tray icon's background from the server. If the tray icon isn't visible (because + // another window is on top of it), the trick fails and instead uses the content of that + // other window as the background. + // setAttribute(Qt::WA_PaintOnScreen); + } addToTray(); } @@ -214,11 +230,18 @@ void QSystemTrayIconSys::paintEvent(QPaintEvent *) painter.setCompositionMode(QPainter::CompositionMode_Source); painter.fillRect(rect, Qt::transparent); } else { + // Without Qt::WA_TranslucentBackground, we use a ParentRelative BackPixmap and jump through + // some hops to draw this background below our icon. This clears the whole tray icon to its + // background color and thus causes flickering (you can see that the icon is being + // repainted). However, we can't really do much about this. QMetaObject::invokeMethod(QGuiApplication::platformNativeInterface(), "clearRegion", Qt::DirectConnection, Q_ARG(const QWindow *, windowHandle()), Q_ARG(const QRect&, rect) ); + painter.drawPixmap(QPoint(0, 0), + QGuiApplication::primaryScreen()->grabWindow(winId(), + 0, 0, rect.size().width(), rect.size().height())); } painter.setCompositionMode(QPainter::CompositionMode_SourceOver); q->icon().paint(&painter, rect); |