diff --git a/kde355684.patch b/kde355684.patch index ff067dd..d0bc448 100644 --- a/kde355684.patch +++ b/kde355684.patch @@ -1,5 +1,22 @@ +From 41df1bdb8b478eb27fb424d201c075c76ec0ed5a Mon Sep 17 00:00:00 2001 +From: Benedikt Gollatz +Date: Sun, 13 Dec 2015 20:47:57 +0000 +Subject: [PATCH 1/1] Mitigate failed icon grabbing in xembed-sni-proxy + +If grabbed icons are blank, try to salvage the copied data as well as +possible while leaving setups where image grabbing works fine alone. + +Based on a patch by Rakyn Barker. + +BUG:355684 +REVIEW: 126336 +--- + xembed-sni-proxy/sniproxy.cpp | 143 ++++++++++++++++++++++++++++++++---------- + xembed-sni-proxy/sniproxy.h | 5 +- + 2 files changed, 114 insertions(+), 34 deletions(-) + diff --git a/xembed-sni-proxy/sniproxy.cpp b/xembed-sni-proxy/sniproxy.cpp -index ca2667f..0b7c072 100644 +index ca2667f18f01a1f99b52422d8474aaabad107b92..ae6eab72e41832c4105fcf3ecb0249969d2525f7 100644 --- a/xembed-sni-proxy/sniproxy.cpp +++ b/xembed-sni-proxy/sniproxy.cpp @@ -33,7 +33,7 @@ @@ -11,28 +28,115 @@ index ca2667f..0b7c072 100644 #include #include -@@ -191,6 +191,10 @@ +@@ -191,48 +191,51 @@ SNIProxy::~SNIProxy() void SNIProxy::update() { const QImage image = getImageNonComposite(); + if (image.isNull()) { -+ qCDebug(SNIPROXY) << "No xembed icon for" << m_windowId << Title(); -+ return; ++ qCDebug(SNIPROXY) << "No xembed icon for" << m_windowId << Title(); ++ return; + } int w = image.width(); int h = image.height(); -@@ -240,11 +244,70 @@ + ++ m_pixmap = QPixmap::fromImage(image); ++ if (w != s_embedSize || h != s_embedSize) { ++ qCDebug(SNIPROXY) << "Scaling pixmap of window" << m_windowId << Title() << "from w*h" << w << h; ++ m_pixmap = m_pixmap.scaled(s_embedSize, s_embedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); ++ } ++ emit NewIcon(); ++ emit NewToolTip(); ++} ++ ++void sni_cleanup_xcb_image(void *data) { ++ xcb_image_destroy(static_cast(data)); ++} ++ ++bool SNIProxy::isTransparentImage(const QImage& image) const ++{ ++ int w = image.width(); ++ int h = image.height(); ++ + // check for the center and sub-center pixels first and avoid full image scan +- bool isTransparentImage = qAlpha(image.pixel(w >> 1, h >> 1)) + qAlpha(image.pixel(w >> 2, h >> 2)) == 0; ++ if (! (qAlpha(image.pixel(w >> 1, h >> 1)) + qAlpha(image.pixel(w >> 2, h >> 2)) == 0)) ++ return false; + + // skip scan altogether if sub-center pixel found to be opaque + // and break out from the outer loop too on full scan +- for (int x = 0; x < w && isTransparentImage; ++x) { +- for (int y = 0; y < h; ++y) { +- if (qAlpha(image.pixel(x, y))) { +- // Found an opaque pixel. +- isTransparentImage = false; +- break; +- } +- } ++ for (int x = 0; x < w; ++x) { ++ for (int y = 0; y < h; ++y) { ++ if (qAlpha(image.pixel(x, y))) { ++ // Found an opaque pixel. ++ return false; ++ } ++ } + } + +- // Update icon only if it is at least partially opaque. +- // This is just a workaround for X11 bug: xembed icon may suddenly +- // become transparent for a one or few frames. Reproducible at least +- // with WINE applications. +- if (!isTransparentImage) { +- m_pixmap = QPixmap::fromImage(image); +- if (w != s_embedSize || h != s_embedSize) { +- qCDebug(SNIPROXY) << "Scaling pixmap of window" << m_windowId << Title() << "from w*h" << w << h; +- m_pixmap = m_pixmap.scaled(s_embedSize, s_embedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); +- } +- emit NewIcon(); +- emit NewToolTip(); +- } +- else { +- qCDebug(SNIPROXY) << "Skip transparent xembed icon for" << m_windowId << Title(); +- } ++ return true; + } + +-void sni_cleanup_xcb_image(void *data) { +- xcb_image_destroy(static_cast(data)); +-} +- +-QImage SNIProxy::getImageNonComposite() ++QImage SNIProxy::getImageNonComposite() const + { + auto c = QX11Info::connection(); + auto cookie = xcb_get_geometry(c, m_windowId); +@@ -240,9 +243,83 @@ QImage SNIProxy::getImageNonComposite() xcb_image_t *image = xcb_image_get(c, m_windowId, 0, 0, geom->width, geom->height, 0xFFFFFF, XCB_IMAGE_FORMAT_Z_PIXMAP); - QImage qimage(image->data, image->width, image->height, image->stride, QImage::Format_ARGB32, sni_cleanup_xcb_image, image); -+ QImage qimage(convertFromNative(image)); - - return qimage; - } - -+QImage SNIProxy::convertFromNative(xcb_image_t *xcbImage) ++ // Don't hook up cleanup yet, we may use a different QImage after all ++ QImage naiveConversion = QImage(image->data, image->width, image->height, QImage::Format_ARGB32); ++ ++ if (isTransparentImage(naiveConversion)) { ++ QImage elaborateConversion = QImage(convertFromNative(image)); ++ ++ // Update icon only if it is at least partially opaque. ++ // This is just a workaround for X11 bug: xembed icon may suddenly ++ // become transparent for a one or few frames. Reproducible at least ++ // with WINE applications. ++ if (isTransparentImage(elaborateConversion)) { ++ qCDebug(SNIPROXY) << "Skip transparent xembed icon for" << m_windowId << Title(); ++ return QImage(); ++ } else ++ return elaborateConversion; ++ } else { ++ // Now we are sure we can eventually delete the xcb_image_t with this version ++ return QImage(image->data, image->width, image->height, image->stride, QImage::Format_ARGB32, sni_cleanup_xcb_image, image); ++ } ++} ++ ++QImage SNIProxy::convertFromNative(xcb_image_t *xcbImage) const +{ + QImage::Format format = QImage::Format_Invalid; + @@ -65,7 +169,6 @@ index ca2667f..0b7c072 100644 + return QImage(); // we don't know + } + -+ //QImage image(xcbImage->data, xcbImage->width, xcbImage->height, format); + QImage image(xcbImage->data, xcbImage->width, xcbImage->height, xcbImage->stride, format, sni_cleanup_xcb_image, xcbImage); + + if (image.isNull()) { @@ -87,15 +190,14 @@ index ca2667f..0b7c072 100644 + image.setColor(0, QColor(Qt::white).rgb()); + image.setColor(1, QColor(Qt::black).rgb()); + } -+ -+ return image; -+} -+ - //____________properties__________ - QString SNIProxy::Category() const +- return qimage; ++ return image; + } + + //____________properties__________ diff --git a/xembed-sni-proxy/sniproxy.h b/xembed-sni-proxy/sniproxy.h -index 29aa56e..89746a7 100644 +index 29aa56e381b034513d4683f047e1556679b57910..6ab5b7d6988b3e975ac562f7b591c2d9307574f0 100644 --- a/xembed-sni-proxy/sniproxy.h +++ b/xembed-sni-proxy/sniproxy.h @@ -28,6 +28,7 @@ @@ -106,11 +208,17 @@ index 29aa56e..89746a7 100644 #include "snidbus.h" -@@ -141,6 +142,7 @@ +@@ -140,7 +141,9 @@ Q_SIGNALS: + private: void sendClick(uint8_t mouseButton, int x, int y); - QImage getImageNonComposite(); -+ QImage convertFromNative(xcb_image_t *xcbImage); +- QImage getImageNonComposite(); ++ QImage getImageNonComposite() const; ++ bool isTransparentImage(const QImage &image) const; ++ QImage convertFromNative(xcb_image_t *xcbImage) const; QDBusConnection m_dbus; xcb_window_t m_windowId; +-- +2.6.2 +