parent
3805715ef4
commit
52c068f0bb
@ -1,34 +0,0 @@
|
|||||||
From 2b59ccd531dcdb7d86577cee1d987f95a9db9bf0 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Martin Klapetek <mklapetek@kde.org>
|
|
||||||
Date: Wed, 9 Dec 2015 13:29:24 -0500
|
|
||||||
Subject: [PATCH 01/10] [notifications] Check if the popup is visible before
|
|
||||||
updating its geometry
|
|
||||||
|
|
||||||
This slot gets triggered also on popup hiding, which is unwanted.
|
|
||||||
Should also prevent a crash when unloading notifications applet while
|
|
||||||
there is an active popup on screen.
|
|
||||||
|
|
||||||
BUG: 356402
|
|
||||||
FIXED-IN: 5.5.1
|
|
||||||
---
|
|
||||||
applets/notifications/plugin/notificationshelper.cpp | 4 ++--
|
|
||||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/applets/notifications/plugin/notificationshelper.cpp b/applets/notifications/plugin/notificationshelper.cpp
|
|
||||||
index ab002d9..208dcc5 100644
|
|
||||||
--- a/applets/notifications/plugin/notificationshelper.cpp
|
|
||||||
+++ b/applets/notifications/plugin/notificationshelper.cpp
|
|
||||||
@@ -130,8 +130,8 @@ void NotificationsHelper::addNotificationPopup(QObject *win)
|
|
||||||
|
|
||||||
void NotificationsHelper::onPopupShown()
|
|
||||||
{
|
|
||||||
- QObject *popup = sender();
|
|
||||||
- if (!popup) {
|
|
||||||
+ QWindow *popup = qobject_cast<QWindow*>(sender());
|
|
||||||
+ if (!popup || !popup->isVisible()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
2.5.0
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
|||||||
From 5c5bbc3f8c4297cfd6862072aa33a45d947fa41b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Martin Klapetek <mklapetek@kde.org>
|
|
||||||
Date: Wed, 9 Dec 2015 14:07:07 -0500
|
|
||||||
Subject: [PATCH 02/10] [notifications] Move reading globalConfig() from ctor
|
|
||||||
to init()
|
|
||||||
|
|
||||||
The globalConfig() in ctor returns a non-(yet-)existing KConfigGroup
|
|
||||||
which makes it always return the default value. So the config access
|
|
||||||
must be delayed for init().
|
|
||||||
|
|
||||||
Custom notification position is now correctly remembered.
|
|
||||||
|
|
||||||
BUG: 356419
|
|
||||||
FIXED-IN: 5.5.1
|
|
||||||
---
|
|
||||||
applets/notifications/lib/notificationsapplet.cpp | 10 +++++++---
|
|
||||||
applets/notifications/lib/notificationsapplet.h | 1 +
|
|
||||||
2 files changed, 8 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/applets/notifications/lib/notificationsapplet.cpp b/applets/notifications/lib/notificationsapplet.cpp
|
|
||||||
index fdfb657..33184c4 100644
|
|
||||||
--- a/applets/notifications/lib/notificationsapplet.cpp
|
|
||||||
+++ b/applets/notifications/lib/notificationsapplet.cpp
|
|
||||||
@@ -28,16 +28,20 @@
|
|
||||||
NotificationsApplet::NotificationsApplet(QObject *parent, const QVariantList &data)
|
|
||||||
: Plasma::Applet(parent, data)
|
|
||||||
{
|
|
||||||
- KConfigGroup globalGroup = globalConfig();
|
|
||||||
- m_popupPosition = (NotificationsHelper::PositionOnScreen)globalGroup.readEntry("popupPosition", 0); //0 is default
|
|
||||||
-
|
|
||||||
connect(this, &Plasma::Applet::locationChanged,
|
|
||||||
this, &NotificationsApplet::onAppletLocationChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
NotificationsApplet::~NotificationsApplet()
|
|
||||||
{
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void NotificationsApplet::init()
|
|
||||||
+{
|
|
||||||
+ KConfigGroup globalGroup = globalConfig();
|
|
||||||
+ m_popupPosition = (NotificationsHelper::PositionOnScreen)globalGroup.readEntry("popupPosition", 0); //0 is default
|
|
||||||
|
|
||||||
+ Plasma::Applet::init();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotificationsApplet::onAppletLocationChanged(Plasma::Types::Location location)
|
|
||||||
diff --git a/applets/notifications/lib/notificationsapplet.h b/applets/notifications/lib/notificationsapplet.h
|
|
||||||
index bad3071..5b262f1 100644
|
|
||||||
--- a/applets/notifications/lib/notificationsapplet.h
|
|
||||||
+++ b/applets/notifications/lib/notificationsapplet.h
|
|
||||||
@@ -38,6 +38,7 @@ public:
|
|
||||||
Q_INVOKABLE uint screenPosition() const;
|
|
||||||
|
|
||||||
public Q_SLOTS:
|
|
||||||
+ void init() Q_DECL_OVERRIDE;
|
|
||||||
void onScreenPositionChanged(uint position);
|
|
||||||
void onAppletLocationChanged(Plasma::Types::Location location);
|
|
||||||
|
|
||||||
--
|
|
||||||
2.5.0
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
|||||||
From 6381dbd9b7a0f33dd024a98ef18a5143ba929b0e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Imran Tatriev <itatriev@gmail.com>
|
|
||||||
Date: Thu, 10 Dec 2015 15:35:35 +0000
|
|
||||||
Subject: [PATCH 03/10] Make "comment" section of the timezones configuration
|
|
||||||
searchable
|
|
||||||
|
|
||||||
BUG: 354238
|
|
||||||
REVIEW: 126302
|
|
||||||
FIXED-IN: 5.5.1
|
|
||||||
---
|
|
||||||
applets/digital-clock/plugin/timezonemodel.cpp | 4 +++-
|
|
||||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/applets/digital-clock/plugin/timezonemodel.cpp b/applets/digital-clock/plugin/timezonemodel.cpp
|
|
||||||
index 5d23505..2fe7b16 100644
|
|
||||||
--- a/applets/digital-clock/plugin/timezonemodel.cpp
|
|
||||||
+++ b/applets/digital-clock/plugin/timezonemodel.cpp
|
|
||||||
@@ -40,8 +40,10 @@ bool TimeZoneFilterProxy::filterAcceptsRow(int source_row, const QModelIndex &so
|
|
||||||
|
|
||||||
const QString city = sourceModel()->index(source_row, 0, source_parent).data(TimeZoneModel::CityRole).toString();
|
|
||||||
const QString region = sourceModel()->index(source_row, 0, source_parent).data(TimeZoneModel::RegionRole).toString();
|
|
||||||
+ const QString comment = sourceModel()->index(source_row, 0, source_parent).data(TimeZoneModel::CommentRole).toString();
|
|
||||||
|
|
||||||
- if (m_stringMatcher.indexIn(city) != -1 || m_stringMatcher.indexIn(region) != -1) {
|
|
||||||
+ if (m_stringMatcher.indexIn(city) != -1 || m_stringMatcher.indexIn(region) != -1 ||
|
|
||||||
+ m_stringMatcher.indexIn(comment) != -1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
2.5.0
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
|||||||
From 5d56df0d53851a8cd61344d356bcb552220dd3ed Mon Sep 17 00:00:00 2001
|
|
||||||
From: Martin Klapetek <mklapetek@kde.org>
|
|
||||||
Date: Thu, 10 Dec 2015 16:29:43 -0500
|
|
||||||
Subject: [PATCH 04/10] [notifications] Fix default notification position
|
|
||||||
setting
|
|
||||||
|
|
||||||
It can happen that the onAppletLocationChanged() slot gets called before
|
|
||||||
init(), making init() reset the calculated position from the slot.
|
|
||||||
|
|
||||||
CCBUG: 356461
|
|
||||||
---
|
|
||||||
applets/notifications/lib/notificationsapplet.cpp | 7 +++++--
|
|
||||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/applets/notifications/lib/notificationsapplet.cpp b/applets/notifications/lib/notificationsapplet.cpp
|
|
||||||
index 33184c4..891cdb0 100644
|
|
||||||
--- a/applets/notifications/lib/notificationsapplet.cpp
|
|
||||||
+++ b/applets/notifications/lib/notificationsapplet.cpp
|
|
||||||
@@ -28,8 +28,6 @@
|
|
||||||
NotificationsApplet::NotificationsApplet(QObject *parent, const QVariantList &data)
|
|
||||||
: Plasma::Applet(parent, data)
|
|
||||||
{
|
|
||||||
- connect(this, &Plasma::Applet::locationChanged,
|
|
||||||
- this, &NotificationsApplet::onAppletLocationChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
NotificationsApplet::~NotificationsApplet()
|
|
||||||
@@ -41,7 +39,12 @@ void NotificationsApplet::init()
|
|
||||||
KConfigGroup globalGroup = globalConfig();
|
|
||||||
m_popupPosition = (NotificationsHelper::PositionOnScreen)globalGroup.readEntry("popupPosition", 0); //0 is default
|
|
||||||
|
|
||||||
+ connect(this, &Plasma::Applet::locationChanged,
|
|
||||||
+ this, &NotificationsApplet::onAppletLocationChanged);
|
|
||||||
+
|
|
||||||
Plasma::Applet::init();
|
|
||||||
+
|
|
||||||
+ onAppletLocationChanged(location());
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotificationsApplet::onAppletLocationChanged(Plasma::Types::Location location)
|
|
||||||
--
|
|
||||||
2.5.0
|
|
||||||
|
|
@ -1,122 +0,0 @@
|
|||||||
From 1dc7f11692a4096b9815ae24f7be9cec10f8f7a5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Edmundson <kde@davidedmundson.co.uk>
|
|
||||||
Date: Sun, 6 Dec 2015 19:47:12 +0000
|
|
||||||
Subject: [PATCH 06/10] Move shutdown scripts into ksmserver cleanup
|
|
||||||
|
|
||||||
Shutdown scripts are done by startkde after ksmserver quits. Which never
|
|
||||||
happens because we've told systemd to shutdown.
|
|
||||||
|
|
||||||
Old systems worked because they used to communicate with the display
|
|
||||||
manager which then closed us before shutting down, this is no longer the
|
|
||||||
case.
|
|
||||||
|
|
||||||
This moves handling the shutdown scripts into ksmserver (which already
|
|
||||||
handles startup scripts) and runs them before asking logind to shutdown.
|
|
||||||
|
|
||||||
BUG: 356190
|
|
||||||
REVIEW: 126268
|
|
||||||
---
|
|
||||||
ksmserver/server.cpp | 27 +++++++++++++++++++++++++++
|
|
||||||
ksmserver/server.h | 2 ++
|
|
||||||
startkde/startkde.cmake | 9 ---------
|
|
||||||
startkde/startplasma.cmake | 9 ---------
|
|
||||||
4 files changed, 29 insertions(+), 18 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/ksmserver/server.cpp b/ksmserver/server.cpp
|
|
||||||
index 9477e54..6a05ff2 100644
|
|
||||||
--- a/ksmserver/server.cpp
|
|
||||||
+++ b/ksmserver/server.cpp
|
|
||||||
@@ -757,6 +757,8 @@ void KSMServer::cleanUp()
|
|
||||||
signal(SIGTERM, SIG_DFL);
|
|
||||||
signal(SIGINT, SIG_DFL);
|
|
||||||
|
|
||||||
+ runShutdownScripts();
|
|
||||||
+
|
|
||||||
KDisplayManager().shutdown( shutdownType, shutdownMode, bootOption );
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1093,3 +1095,28 @@ void KSMServer::openSwitchUserDialog()
|
|
||||||
QScopedPointer<KSMSwitchUserDialog> dlg(new KSMSwitchUserDialog(&dm));
|
|
||||||
dlg->exec();
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+void KSMServer::runShutdownScripts()
|
|
||||||
+{
|
|
||||||
+ const QStringList shutdownFolders = QStandardPaths::locateAll(QStandardPaths::GenericConfigLocation, QStringLiteral("plasma-workspace/shutdown"), QStandardPaths::LocateDirectory);
|
|
||||||
+ foreach (const QString &shutDownFolder, shutdownFolders) {
|
|
||||||
+ QDir dir(shutDownFolder);
|
|
||||||
+ if (!dir.exists()) {
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ const QStringList entries = dir.entryList(QDir::Files);
|
|
||||||
+ foreach (const QString &file, entries) {
|
|
||||||
+ // Don't execute backup files
|
|
||||||
+ if (!file.endsWith(QLatin1Char('~')) && !file.endsWith(QStringLiteral(".bak")) &&
|
|
||||||
+ (file[0] != QLatin1Char('%') || !file.endsWith(QLatin1Char('%'))) &&
|
|
||||||
+ (file[0] != QLatin1Char('#') || !file.endsWith(QLatin1Char('#'))))
|
|
||||||
+ {
|
|
||||||
+ const QString fullPath = dir.absolutePath() + QLatin1Char('/') + file;
|
|
||||||
+
|
|
||||||
+ qCDebug(KSMSERVER) << "running shutdown script" << fullPath;
|
|
||||||
+ QProcess::execute(fullPath);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
diff --git a/ksmserver/server.h b/ksmserver/server.h
|
|
||||||
index 1a2f081..d026ecd 100644
|
|
||||||
--- a/ksmserver/server.h
|
|
||||||
+++ b/ksmserver/server.h
|
|
||||||
@@ -202,6 +202,8 @@ private:
|
|
||||||
void resumeStartupInternal();
|
|
||||||
void setupShortcuts();
|
|
||||||
|
|
||||||
+ void runShutdownScripts();
|
|
||||||
+
|
|
||||||
// public dcop interface
|
|
||||||
|
|
||||||
public Q_SLOTS: //public dcop interface
|
|
||||||
diff --git a/startkde/startkde.cmake b/startkde/startkde.cmake
|
|
||||||
index 37ab5cd..9e52fee 100644
|
|
||||||
--- a/startkde/startkde.cmake
|
|
||||||
+++ b/startkde/startkde.cmake
|
|
||||||
@@ -412,15 +412,6 @@ test -n "$ksplash_pid" && kill "$ksplash_pid" 2>/dev/null
|
|
||||||
# Clean up
|
|
||||||
kdeinit5_shutdown
|
|
||||||
|
|
||||||
-echo 'startkde: Running shutdown scripts...' 1>&2
|
|
||||||
-
|
|
||||||
-# Run scripts found in <config locations>/plasma-workspace/shutdown
|
|
||||||
-for prefix in `echo "$scriptpath"`; do
|
|
||||||
- for file in `ls "$prefix"/shutdown 2> /dev/null | egrep -v '(~|\.bak)$'`; do
|
|
||||||
- test -x "$prefix/shutdown/$file" && "$prefix/shutdown/$file"
|
|
||||||
- done
|
|
||||||
-done
|
|
||||||
-
|
|
||||||
unset KDE_FULL_SESSION
|
|
||||||
xprop -root -remove KDE_FULL_SESSION
|
|
||||||
unset KDE_SESSION_VERSION
|
|
||||||
diff --git a/startkde/startplasma.cmake b/startkde/startplasma.cmake
|
|
||||||
index 8360a63..8928cf6 100644
|
|
||||||
--- a/startkde/startplasma.cmake
|
|
||||||
+++ b/startkde/startplasma.cmake
|
|
||||||
@@ -175,15 +175,6 @@ test -n "$ksplash_pid" && kill "$ksplash_pid" 2>/dev/null
|
|
||||||
# Clean up
|
|
||||||
kdeinit5_shutdown
|
|
||||||
|
|
||||||
-echo 'startplasma: Running shutdown scripts...' 1>&2
|
|
||||||
-
|
|
||||||
-# Run scripts found in <config locations>/plasma-workspace/shutdown
|
|
||||||
-for prefix in `echo "$scriptpath"`; do
|
|
||||||
- for file in `ls "$prefix"/shutdown 2> /dev/null | egrep -v '(~|\.bak)$'`; do
|
|
||||||
- test -x "$prefix/shutdown/$file" && "$prefix/shutdown/$file"
|
|
||||||
- done
|
|
||||||
-done
|
|
||||||
-
|
|
||||||
unset KDE_FULL_SESSION
|
|
||||||
xprop -root -remove KDE_FULL_SESSION
|
|
||||||
unset KDE_SESSION_VERSION
|
|
||||||
--
|
|
||||||
2.5.0
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
|||||||
From b5ebbb01b20509571eb8dab03ed7b49891d9bad4 Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Edmundson <david@davidedmundson.co.uk>
|
|
||||||
Date: Sun, 13 Dec 2015 16:30:25 +0000
|
|
||||||
Subject: [PATCH 07/10] If the user runs failsafe mode, use software rendering
|
|
||||||
in QtQuick
|
|
||||||
|
|
||||||
Graphics seem more likely than anything else to be broken, if the user
|
|
||||||
explicitly selects failsafe mode from the DM we should follow the same
|
|
||||||
rationale as kwin and not trust the user's drivers.
|
|
||||||
|
|
||||||
REVIEW: 126205
|
|
||||||
---
|
|
||||||
startkde/startkde.cmake | 3 ++-
|
|
||||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/startkde/startkde.cmake b/startkde/startkde.cmake
|
|
||||||
index 9e52fee..12c921e 100644
|
|
||||||
--- a/startkde/startkde.cmake
|
|
||||||
+++ b/startkde/startkde.cmake
|
|
||||||
@@ -6,7 +6,8 @@
|
|
||||||
if test "x$1" = x--failsafe; then
|
|
||||||
KDE_FAILSAFE=1 # General failsafe flag
|
|
||||||
KWIN_COMPOSE=N # Disable KWin's compositing
|
|
||||||
- export KWIN_COMPOSE KDE_FAILSAFE
|
|
||||||
+ QT_XCB_FORCE_SOFTWARE_OPENGL=1
|
|
||||||
+ export KWIN_COMPOSE KDE_FAILSAFE QT_XCB_FORCE_SOFTWARE_OPENGL
|
|
||||||
fi
|
|
||||||
|
|
||||||
# When the X server dies we get a HUP signal from xinit. We must ignore it
|
|
||||||
--
|
|
||||||
2.5.0
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
|||||||
From 9b2396770dd103c6b549763a7f13a896e6af19d8 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Kai Uwe Broulik <kde@privat.broulik.de>
|
|
||||||
Date: Sun, 13 Dec 2015 20:32:45 +0100
|
|
||||||
Subject: [PATCH 08/10] [Clipboard Plasmoid] Fix import to use StandardKey
|
|
||||||
|
|
||||||
StandardKey is only available since Qt 5.4
|
|
||||||
|
|
||||||
REVIEW: 126294
|
|
||||||
---
|
|
||||||
applets/clipboard/contents/ui/ClipboardPage.qml | 3 ++-
|
|
||||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/applets/clipboard/contents/ui/ClipboardPage.qml b/applets/clipboard/contents/ui/ClipboardPage.qml
|
|
||||||
index a8b1b85..5a82730 100644
|
|
||||||
--- a/applets/clipboard/contents/ui/ClipboardPage.qml
|
|
||||||
+++ b/applets/clipboard/contents/ui/ClipboardPage.qml
|
|
||||||
@@ -17,8 +17,9 @@ GNU General Public License for more details.
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*********************************************************************/
|
|
||||||
-import QtQuick 2.0
|
|
||||||
+import QtQuick 2.4
|
|
||||||
import QtQuick.Layouts 1.1
|
|
||||||
+
|
|
||||||
import org.kde.plasma.plasmoid 2.0
|
|
||||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
|
||||||
import org.kde.plasma.components 2.0 as PlasmaComponents
|
|
||||||
--
|
|
||||||
2.5.0
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
|||||||
From 46310dcb50bed485550510ed5f70a623041d84ab Mon Sep 17 00:00:00 2001
|
|
||||||
From: Kai Uwe Broulik <kde@privat.broulik.de>
|
|
||||||
Date: Sun, 13 Dec 2015 20:34:04 +0100
|
|
||||||
Subject: [PATCH 09/10] [System Tray] Explicitly forward key events to expanded
|
|
||||||
task
|
|
||||||
|
|
||||||
Somehow key events no longer end up in the expanded task, this could be related
|
|
||||||
to the fact that we now have a proper ScrollView instead of a plain ListView/Flickable.
|
|
||||||
|
|
||||||
REVIEW: 126293
|
|
||||||
---
|
|
||||||
applets/systemtray/package/contents/ui/ExpandedRepresentation.qml | 4 +++-
|
|
||||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/applets/systemtray/package/contents/ui/ExpandedRepresentation.qml b/applets/systemtray/package/contents/ui/ExpandedRepresentation.qml
|
|
||||||
index a53be6c..7f13458 100644
|
|
||||||
--- a/applets/systemtray/package/contents/ui/ExpandedRepresentation.qml
|
|
||||||
+++ b/applets/systemtray/package/contents/ui/ExpandedRepresentation.qml
|
|
||||||
@@ -28,6 +28,8 @@ KQuickControlsAddons.MouseEventListener {
|
|
||||||
|
|
||||||
acceptedButtons: Qt.RightButton
|
|
||||||
|
|
||||||
+ Keys.forwardTo: root.expandedTask ? [root.expandedTask.taskItemExpanded] : [hiddenView]
|
|
||||||
+
|
|
||||||
Component.onCompleted: {
|
|
||||||
if (root.expandedTask) {
|
|
||||||
root.expandedTask.taskItemExpanded.parent = expandedItemContainer;
|
|
||||||
@@ -109,7 +111,7 @@ KQuickControlsAddons.MouseEventListener {
|
|
||||||
}
|
|
||||||
|
|
||||||
ListView {
|
|
||||||
- clip: true
|
|
||||||
+ id: list
|
|
||||||
anchors.fill: parent
|
|
||||||
spacing: units.smallSpacing
|
|
||||||
|
|
||||||
--
|
|
||||||
2.5.0
|
|
||||||
|
|
@ -1,224 +0,0 @@
|
|||||||
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 10/10] 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..ae6eab7 100644
|
|
||||||
--- a/xembed-sni-proxy/sniproxy.cpp
|
|
||||||
+++ b/xembed-sni-proxy/sniproxy.cpp
|
|
||||||
@@ -33,7 +33,7 @@
|
|
||||||
#include <QGuiApplication>
|
|
||||||
#include <QTimer>
|
|
||||||
|
|
||||||
-#include <QPainter>
|
|
||||||
+#include <QBitmap>
|
|
||||||
|
|
||||||
#include <KWindowSystem>
|
|
||||||
#include <netwm.h>
|
|
||||||
@@ -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;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
int w = image.width();
|
|
||||||
int h = image.height();
|
|
||||||
|
|
||||||
+ 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);
|
|
||||||
+ // 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;
|
|
||||||
+
|
|
||||||
+ switch (xcbImage->depth) {
|
|
||||||
+ case 1:
|
|
||||||
+ format = QImage::Format_MonoLSB;
|
|
||||||
+ break;
|
|
||||||
+ case 16:
|
|
||||||
+ format = QImage::Format_RGB16;
|
|
||||||
+ break;
|
|
||||||
+ case 24:
|
|
||||||
+ format = QImage::Format_RGB32;
|
|
||||||
+ break;
|
|
||||||
+ case 30: {
|
|
||||||
+ // Qt doesn't have a matching image format. We need to convert manually
|
|
||||||
+ quint32 *pixels = reinterpret_cast<quint32 *>(xcbImage->data);
|
|
||||||
+ for (uint i = 0; i < (xcbImage->size / 4); i++) {
|
|
||||||
+ int r = (pixels[i] >> 22) & 0xff;
|
|
||||||
+ int g = (pixels[i] >> 12) & 0xff;
|
|
||||||
+ int b = (pixels[i] >> 2) & 0xff;
|
|
||||||
+
|
|
||||||
+ pixels[i] = qRgba(r, g, b, 0xff);
|
|
||||||
+ }
|
|
||||||
+ // fall through, Qt format is still Format_ARGB32_Premultiplied
|
|
||||||
+ }
|
|
||||||
+ case 32:
|
|
||||||
+ format = QImage::Format_ARGB32_Premultiplied;
|
|
||||||
+ break;
|
|
||||||
+ default:
|
|
||||||
+ return QImage(); // we don't know
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ QImage image(xcbImage->data, xcbImage->width, xcbImage->height, xcbImage->stride, format, sni_cleanup_xcb_image, xcbImage);
|
|
||||||
+
|
|
||||||
+ if (image.isNull()) {
|
|
||||||
+ return QImage();
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (format == QImage::Format_RGB32 && xcbImage->bpp == 32)
|
|
||||||
+ {
|
|
||||||
+ QImage m = image.createHeuristicMask();
|
|
||||||
+ QBitmap mask(QPixmap::fromImage(m));
|
|
||||||
+ QPixmap p = QPixmap::fromImage(image);
|
|
||||||
+ p.setMask(mask);
|
|
||||||
+ image = p.toImage();
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ // work around an abort in QImage::color
|
|
||||||
+ if (image.format() == QImage::Format_MonoLSB) {
|
|
||||||
+ image.setColorCount(2);
|
|
||||||
+ image.setColor(0, QColor(Qt::white).rgb());
|
|
||||||
+ image.setColor(1, QColor(Qt::black).rgb());
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- return qimage;
|
|
||||||
+ return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
//____________properties__________
|
|
||||||
diff --git a/xembed-sni-proxy/sniproxy.h b/xembed-sni-proxy/sniproxy.h
|
|
||||||
index 29aa56e..6ab5b7d 100644
|
|
||||||
--- a/xembed-sni-proxy/sniproxy.h
|
|
||||||
+++ b/xembed-sni-proxy/sniproxy.h
|
|
||||||
@@ -28,6 +28,7 @@
|
|
||||||
#include <QPixmap>
|
|
||||||
|
|
||||||
#include <xcb/xcb.h>
|
|
||||||
+#include <xcb/xcb_image.h>
|
|
||||||
|
|
||||||
#include "snidbus.h"
|
|
||||||
|
|
||||||
@@ -140,7 +141,9 @@ Q_SIGNALS:
|
|
||||||
|
|
||||||
private:
|
|
||||||
void sendClick(uint8_t mouseButton, int x, int y);
|
|
||||||
- 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.5.0
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
|||||||
diff --git a/shell/panelview.cpp b/shell/panelview.cpp
|
|
||||||
index 063343d..893def0 100644
|
|
||||||
--- a/shell/panelview.cpp
|
|
||||||
+++ b/shell/panelview.cpp
|
|
||||||
@@ -748,7 +748,6 @@ bool PanelView::event(QEvent *e)
|
|
||||||
* on the mouse edge, forward the click in the containment boundaries
|
|
||||||
*/
|
|
||||||
switch (e->type()) {
|
|
||||||
- case QEvent::Enter:
|
|
||||||
case QEvent::MouseMove:
|
|
||||||
case QEvent::MouseButtonPress:
|
|
||||||
case QEvent::MouseButtonRelease: {
|
|
||||||
@@ -756,7 +755,7 @@ bool PanelView::event(QEvent *e)
|
|
||||||
|
|
||||||
//first, don't mess with position if the cursor is actually outside the view:
|
|
||||||
//somebody is doing a click and drag that must not break when the cursor i outside
|
|
||||||
- if (geometry().contains(me->screenPos().toPoint())) {
|
|
||||||
+ if (geometry().contains(QCursor::pos())) {
|
|
||||||
if (!containmentContainsPosition(me->windowPos())) {
|
|
||||||
auto me2 = new QMouseEvent(me->type(),
|
|
||||||
positionAdjustedForContainment(me->windowPos()),
|
|
||||||
@@ -767,25 +766,19 @@ bool PanelView::event(QEvent *e)
|
|
||||||
QCoreApplication::postEvent(this, me2);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
- }
|
|
||||||
- break;
|
|
||||||
- }
|
|
||||||
- case QEvent::Leave: {
|
|
||||||
- QMouseEvent *me = static_cast<QMouseEvent *>(e);
|
|
||||||
- // don't forget to trigger QEvent::Leave if current mouse position is outside the panel
|
|
||||||
- if (!geometry().contains(me->screenPos().toPoint())) {
|
|
||||||
- auto me2 = new QMouseEvent(QEvent::Leave,
|
|
||||||
- positionAdjustedForContainment(me->windowPos()),
|
|
||||||
- positionAdjustedForContainment(me->windowPos()),
|
|
||||||
- positionAdjustedForContainment(me->windowPos()) + position(),
|
|
||||||
- me->button(), me->buttons(), me->modifiers());
|
|
||||||
-
|
|
||||||
- QCoreApplication::postEvent(this, me2);
|
|
||||||
+ } else {
|
|
||||||
+ // discard event if current mouse position is outside the panel
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ case QEvent::Enter:
|
|
||||||
+ case QEvent::Leave:
|
|
||||||
+ // QtQuick < 5.6 issue:
|
|
||||||
+ // QEvent::Leave is triggered on MouseButtonPress Qt::LeftButton
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
case QEvent::Wheel: {
|
|
||||||
QWheelEvent *we = static_cast<QWheelEvent *>(e);
|
|
Loading…
Reference in new issue