This commit is contained in:
parent
a6cb2d2bbf
commit
6ff7e438c5
152
kde355684.patch
152
kde355684.patch
@ -1,5 +1,22 @@
|
||||
From 41df1bdb8b478eb27fb424d201c075c76ec0ed5a Mon Sep 17 00:00:00 2001
|
||||
From: Benedikt Gollatz <benedikt@gollatz.net>
|
||||
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 <KWindowSystem>
|
||||
#include <netwm.h>
|
||||
@@ -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<xcb_image_t*>(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<xcb_image_t*>(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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user