diff options
author | Leo Franchi <lfranchi@dropbox.com> | 2014-07-01 17:36:15 +0200 |
---|---|---|
committer | Leonardo Franchi <lfranchi@dropbox.com> | 2014-07-04 15:32:45 +0200 |
commit | 0eefa785a0d8bfe96403f9c13e80544cf8bb8eb3 (patch) | |
tree | 738be91ded23632a42cea8af102978fa60e1a06e /src/plugins/platforms/xcb/qxcbnativeinterface.cpp | |
parent | 6577ac381e73b2ce3d57d2e8a39edb424ce9a52d (diff) |
Support transparency in qt5 system tray icons, regardless of tray visual
This ports the Qt4 method of supporting the system tray
window visual that has an alpha channel as well as ones
that do not. We detect whether or not we have a 32-bit
format and either use a Qt::transparent background, or
call xcb_clear_region before painting the icon.
[ChangeLog][Linux/XCB] Fix transparency of tray icons in cases where
there is no alpha channel or system tray visual.
Task-number: QTBUG-35832
Change-Id: I43d500c39846d2916dd39f8c47c8d85e59b49cae
Reviewed-by: Uli Schlachter <psychon@znc.in>
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@digia.com>
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbnativeinterface.cpp')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbnativeinterface.cpp | 80 |
1 files changed, 79 insertions, 1 deletions
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp index 625a804c0c..490064a94d 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp @@ -93,7 +93,9 @@ static int resourceType(const QByteArray &key) } QXcbNativeInterface::QXcbNativeInterface() : - m_genericEventFilterType(QByteArrayLiteral("xcb_generic_event_t")) + m_genericEventFilterType(QByteArrayLiteral("xcb_generic_event_t")), + m_sysTraySelectionAtom(XCB_ATOM_NONE), + m_systrayVisualId(XCB_NONE) { } @@ -135,6 +137,82 @@ QRect QXcbNativeInterface::systemTrayWindowGlobalGeometry(const QWindow *window) return QRect(); } +xcb_window_t QXcbNativeInterface::locateSystemTray(xcb_connection_t *conn, const QXcbScreen *screen) +{ + if (m_sysTraySelectionAtom == XCB_ATOM_NONE) { + const QByteArray net_sys_tray = QString::fromLatin1("_NET_SYSTEM_TRAY_S%1").arg(screen->screenNumber()).toLatin1(); + xcb_intern_atom_cookie_t intern_c = + xcb_intern_atom_unchecked(conn, true, net_sys_tray.length(), net_sys_tray); + + xcb_intern_atom_reply_t *intern_r = xcb_intern_atom_reply(conn, intern_c, 0); + + if (!intern_r) + return XCB_WINDOW_NONE; + + m_sysTraySelectionAtom = intern_r->atom; + free(intern_r); + } + + xcb_get_selection_owner_cookie_t sel_owner_c = xcb_get_selection_owner_unchecked(conn, m_sysTraySelectionAtom); + xcb_get_selection_owner_reply_t *sel_owner_r = xcb_get_selection_owner_reply(conn, sel_owner_c, 0); + + if (!sel_owner_r) + return XCB_WINDOW_NONE; + + xcb_window_t selection_window = sel_owner_r->owner; + free(sel_owner_r); + + return selection_window; +} + +bool QXcbNativeInterface::systrayVisualHasAlphaChannel() { + const QXcbScreen *screen = static_cast<QXcbScreen *>(QGuiApplication::primaryScreen()->handle()); + + if (m_systrayVisualId == XCB_NONE) { + xcb_connection_t *xcb_conn = screen->xcb_connection(); + xcb_atom_t tray_atom = screen->atom(QXcbAtom::_NET_SYSTEM_TRAY_VISUAL); + + xcb_window_t systray_window = locateSystemTray(xcb_conn, screen); + if (systray_window == XCB_WINDOW_NONE) + return false; + + // Get the xcb property for the _NET_SYSTEM_TRAY_VISUAL atom + xcb_get_property_cookie_t systray_atom_cookie; + xcb_get_property_reply_t *systray_atom_reply; + + systray_atom_cookie = xcb_get_property_unchecked(xcb_conn, false, systray_window, + tray_atom, XCB_ATOM_VISUALID, 0, 1); + systray_atom_reply = xcb_get_property_reply(xcb_conn, systray_atom_cookie, 0); + + if (!systray_atom_reply) + return false; + + if (systray_atom_reply->value_len > 0 && xcb_get_property_value_length(systray_atom_reply) > 0) { + xcb_visualid_t * vids = (uint32_t *)xcb_get_property_value(systray_atom_reply); + m_systrayVisualId = vids[0]; + } + + free(systray_atom_reply); + } + + if (m_systrayVisualId != XCB_NONE) { + quint8 depth = screen->depthOfVisual(m_systrayVisualId); + return depth == 32; + } else { + return false; + } +} + +void QXcbNativeInterface::clearRegion(const QWindow *qwindow, const QRect& rect) +{ + if (const QPlatformWindow *platformWindow = qwindow->handle()) { + const QXcbWindow *qxwindow = static_cast<const QXcbWindow *>(platformWindow); + xcb_connection_t *xcb_conn = qxwindow->xcb_connection(); + + xcb_clear_area(xcb_conn, false, qxwindow->xcb_window(), rect.x(), rect.y(), rect.width(), rect.height()); + } +} + void *QXcbNativeInterface::nativeResourceForIntegration(const QByteArray &resourceString) { void *result = 0; |