Blame SOURCES/kde-workspace-4.11-bz#921781-check-max-viewport-size.patch

652846
diff --git a/kwin/kcmkwin/kwincompositing/dbus.h b/kwin/kcmkwin/kwincompositing/dbus.h
652846
new file mode 100644
652846
index 0000000..05f5d23
652846
--- /dev/null
652846
+++ b/kwin/kcmkwin/kwincompositing/dbus.h
652846
@@ -0,0 +1,46 @@
652846
+/********************************************************************
652846
+ KWin - the KDE window manager
652846
+ This file is part of the KDE project.
652846
+
652846
+Copyright (C) 2012 Thomas Lübking <thomas.luebking@gmail.com>
652846
+
652846
+This program is free software; you can redistribute it and/or modify
652846
+it under the terms of the GNU General Public License as published by
652846
+the Free Software Foundation; either version 2 of the License, or
652846
+(at your option) any later version.
652846
+
652846
+This program is distributed in the hope that it will be useful,
652846
+but WITHOUT ANY WARRANTY; without even the implied warranty of
652846
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
652846
+GNU General Public License for more details.
652846
+
652846
+You should have received a copy of the GNU General Public License
652846
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
652846
+*********************************************************************/
652846
+
652846
+#ifndef MAIN_ADAPTOR_H
652846
+#define MAIN_ADAPTOR_H
652846
+
652846
+#include <QtDBus/QDBusAbstractAdaptor>
652846
+#include "main.h"
652846
+
652846
+namespace KWin
652846
+{
652846
+class MainAdaptor : public QDBusAbstractAdaptor
652846
+{
652846
+   Q_OBJECT
652846
+   Q_CLASSINFO("D-Bus Interface", "org.kde.kwinCompositingDialog")
652846
+
652846
+private:
652846
+    KWinCompositingConfig *m_config;
652846
+
652846
+public:
652846
+    MainAdaptor(KWinCompositingConfig *config) : QDBusAbstractAdaptor(config), m_config(config) { }
652846
+
652846
+public slots:
652846
+    Q_NOREPLY void warn(QString message, QString details, QString dontAgainKey) {
652846
+        m_config->warn(message, details, dontAgainKey);
652846
+    }
652846
+};
652846
+}
652846
+#endif
652846
\ No newline at end of file
652846
diff --git a/kwin/kcmkwin/kwincompositing/main.cpp b/kwin/kcmkwin/kwincompositing/main.cpp
652846
index 6e39479..e802b46 100644
652846
--- a/kwin/kcmkwin/kwincompositing/main.cpp
652846
+++ b/kwin/kcmkwin/kwincompositing/main.cpp
652846
@@ -19,6 +19,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
652846
 *********************************************************************/
652846
 
652846
 #include "main.h"
652846
+#include "dbus.h"
652846
 
652846
 #include "kwin_interface.h"
652846
 #include "kwinglobals.h"
652846
@@ -76,13 +77,17 @@ ConfirmDialog::ConfirmDialog() :
652846
 }
652846
 
652846
 
652846
-KWinCompositingConfig::KWinCompositingConfig(QWidget *parent, const QVariantList &)
652846
+KWinCompositingConfig::KWinCompositingConfig(QWidget *parent, const QVariantList &args)
652846
     : KCModule(KWinCompositingConfigFactory::componentData(), parent)
652846
     , mKWinConfig(KSharedConfig::openConfig("kwinrc"))
652846
     , m_showConfirmDialog(false)
652846
     , m_showDetailedErrors(new QAction(i18nc("Action to open a dialog showing detailed information why an effect could not be loaded",
652846
                                              "Details"), this))
652846
+    , m_dontShowAgain(new QAction(i18nc("Prevent warning from bein displayed again", "Don't show again!"), this))
652846
 {
652846
+    QDBusConnection::sessionBus().registerService("org.kde.kwinCompositingDialog");
652846
+    QDBusConnection::sessionBus().registerObject("/CompositorSettings", this);
652846
+    new MainAdaptor(this);
652846
     KGlobal::locale()->insertCatalog("kwin_effects");
652846
     ui.setupUi(this);
652846
     layout()->setMargin(0);
652846
@@ -90,9 +95,34 @@ KWinCompositingConfig::KWinCompositingConfig(QWidget *parent, const QVariantList
652846
     ui.tabWidget->setCurrentIndex(0);
652846
     ui.statusTitleWidget->hide();
652846
     ui.rearmGlSupport->hide();
652846
-    ui.messageBox->setVisible(false);
652846
-    ui.messageBox->addAction(m_showDetailedErrors);
652846
     ui.messageBox->setMessageType(KMessageWidget::Warning);
652846
+    ui.messageBox->addAction(m_dontShowAgain);
652846
+    foreach (QWidget *w, m_dontShowAgain->associatedWidgets())
652846
+        w->setVisible(false);
652846
+    ui.messageBox->addAction(m_showDetailedErrors);
652846
+
652846
+    bool showMessage = false;
652846
+    QString message, details, dontAgainKey;
652846
+    if (args.count() > 1) {
652846
+        for (int i = 0; i < args.count() - 1; ++i) {
652846
+            if (args.at(i).toString() == "warn") {
652846
+                showMessage = true;
652846
+                message = QString::fromLocal8Bit(QByteArray::fromBase64(args.at(i+1).toByteArray()));
652846
+            } else if (args.at(i).toString() == "details") {
652846
+                showMessage = true;
652846
+                details = QString::fromLocal8Bit(QByteArray::fromBase64(args.at(i+1).toByteArray()));
652846
+            } else if (args.at(i).toString() == "dontagain") {
652846
+                showMessage = true;
652846
+                dontAgainKey = args.at(i+1).toString();
652846
+            }
652846
+        }
652846
+    }
652846
+
652846
+    if (showMessage) {
652846
+        ui.messageBox->setVisible(showMessage); // first show, animation is broken on init
652846
+        warn(message, details, dontAgainKey);
652846
+    } else
652846
+        ui.messageBox->setVisible(false);
652846
     ui.ghns->setIcon(KIcon("get-hot-new-stuff"));
652846
 
652846
     // For future use
652846
@@ -133,6 +163,7 @@ KWinCompositingConfig::KWinCompositingConfig(QWidget *parent, const QVariantList
652846
     connect(ui.glShaders, SIGNAL(toggled(bool)), this, SLOT(changed()));
652846
     connect(ui.glColorCorrection, SIGNAL(toggled(bool)), this, SLOT(changed()));
652846
     connect(m_showDetailedErrors, SIGNAL(triggered(bool)), SLOT(showDetailedEffectLoadingInformation()));
652846
+    connect(m_dontShowAgain, SIGNAL(triggered(bool)), SLOT(blockFutureWarnings()));
652846
     connect(ui.ghns, SIGNAL(clicked(bool)), SLOT(slotGHNS()));
652846
 
652846
     // Open the temporary config file
652846
@@ -615,10 +646,15 @@ void KWinCompositingConfig::checkLoadedEffects()
652846
         }
652846
         if (!disabledEffects.isEmpty()) {
652846
             m_showDetailedErrors->setData(disabledEffects);
652846
+            foreach (QWidget *w, m_showDetailedErrors->associatedWidgets())
652846
+                w->setVisible(true);
652846
             ui.messageBox->setText(i18ncp("Error Message shown when a desktop effect could not be loaded",
652846
                                           "One desktop effect could not be loaded.",
652846
                                           "%1 desktop effects could not be loaded.", disabledEffects.count()));
652846
             ui.messageBox->animatedShow();
652846
+        } else {
652846
+            foreach (QWidget *w, m_showDetailedErrors->associatedWidgets())
652846
+                w->setVisible(false);
652846
         }
652846
     }
652846
 }
652846
@@ -653,7 +689,9 @@ void KWinCompositingConfig::showDetailedEffectLoadingInformation()
652846
     label->setOpenExternalLinks(true);
652846
     vboxLayout->addWidget(titleWidget);
652846
     vboxLayout->addWidget(label);
652846
-    if (compositingType != "none") {
652846
+    if (!m_externErrorDetails.isNull()) {
652846
+        label->setText(m_externErrorDetails);
652846
+    } else if (compositingType != "none") {
652846
         QString text;
652846
         if (disabledEffects.count() > 1) {
652846
             text = "
    ";
652846
@@ -716,6 +754,31 @@ void KWinCompositingConfig::showDetailedEffectLoadingInformation()
652846
     dialog->show();
652846
 }
652846
 
652846
+void KWinCompositingConfig::warn(QString message, QString details, QString dontAgainKey)
652846
+{
652846
+    ui.messageBox->setText(message);
652846
+    m_dontShowAgain->setData(dontAgainKey);
652846
+    foreach (QWidget *w, m_dontShowAgain->associatedWidgets())
652846
+        w->setVisible(!dontAgainKey.isEmpty());
652846
+    m_externErrorDetails = details.isNull() ? "" : details;
652846
+    foreach (QWidget *w, m_showDetailedErrors->associatedWidgets())
652846
+        w->setVisible(!m_externErrorDetails.isEmpty());
652846
+    ui.messageBox->animatedShow();
652846
+}
652846
+
652846
+void KWinCompositingConfig::blockFutureWarnings() {
652846
+    QString key;
652846
+    if (QAction *act = qobject_cast<QAction*>(sender()))
652846
+        key = act->data().toString();
652846
+    if (key.isEmpty())
652846
+        return;
652846
+    QStringList l = key.split(':', QString::SkipEmptyParts);
652846
+    KConfig cfg(l.count() > 1 ? l.at(0) : "kwin_dialogsrc");
652846
+    KConfigGroup(&cfg, "Notification Messages").writeEntry(l.last(), false);
652846
+    cfg.sync();
652846
+    ui.messageBox->animatedHide();
652846
+}
652846
+
652846
 void KWinCompositingConfig::configChanged(bool reinitCompositing)
652846
 {
652846
     // Send signal to kwin
652846
@@ -779,4 +842,5 @@ void KWinCompositingConfig::slotGHNS()
652846
 
652846
 } // namespace
652846
 
652846
+#include "dbus.moc"
652846
 #include "main.moc"
652846
diff --git a/kwin/kcmkwin/kwincompositing/main.h b/kwin/kcmkwin/kwincompositing/main.h
652846
index 35079c3..d806531 100644
652846
--- a/kwin/kcmkwin/kwincompositing/main.h
652846
+++ b/kwin/kcmkwin/kwincompositing/main.h
652846
@@ -74,6 +74,8 @@ public slots:
652846
     void configChanged(bool reinitCompositing);
652846
     void initEffectSelector();
652846
 
652846
+    void warn(QString message, QString details, QString dontAgainKey);
652846
+
652846
 private slots:
652846
     void confirmReInit() { showConfirmDialog(true); }
652846
     void rearmGlSupport();
652846
@@ -82,6 +84,7 @@ private slots:
652846
     void toggleEffectShortcutChanged(const QKeySequence &seq;;
652846
     void updateStatusUI(bool compositingIsPossible);
652846
     void showDetailedEffectLoadingInformation();
652846
+    void blockFutureWarnings();
652846
     void slotGHNS();
652846
 
652846
 private:
652846
@@ -97,6 +100,8 @@ private:
652846
     KActionCollection* m_actionCollection;
652846
     QString originalGraphicsSystem;
652846
     QAction *m_showDetailedErrors;
652846
+    QAction *m_dontShowAgain;
652846
+    QString m_externErrorDetails;
652846
 };
652846
 
652846
 } // namespace
652846
diff --git a/kwin/scene_opengl.cpp b/kwin/scene_opengl.cpp
652846
index 6cf62c6..7df85ce 100644
652846
--- a/kwin/scene_opengl.cpp
652846
+++ b/kwin/scene_opengl.cpp
652846
@@ -97,11 +97,18 @@ Sources and other compositing managers:
652846
 #include <X11/extensions/Xcomposite.h>
652846
 
652846
 #include <qpainter.h>
652846
+#include <QDBusConnection>
652846
+#include <QDBusConnectionInterface>
652846
+#include <QDBusInterface>
652846
 #include <QDesktopWidget>
652846
+#include <QStringList>
652846
 #include <QVector2D>
652846
 #include <QVector4D>
652846
 #include <QMatrix4x4>
652846
 
652846
+#include <KLocale>
652846
+#include <KProcess>
652846
+
652846
 namespace KWin
652846
 {
652846
 
652846
@@ -152,6 +159,8 @@ SceneOpenGL::SceneOpenGL(Workspace* ws, OpenGLBackend *backend)
652846
         init_ok = false;
652846
         return;
652846
     }
652846
+    if (!viewportLimitsMatched(QSize(displayWidth(), displayHeight())))
652846
+        return;
652846
 
652846
     // perform Scene specific checks
652846
     GLPlatform *glPlatform = GLPlatform::instance();
652846
@@ -434,8 +443,75 @@ SceneOpenGL::Texture *SceneOpenGL::createTexture(const QPixmap &pix, GLenum targ
652846
     return new Texture(m_backend, pix, target);
652846
 }
652846
 
652846
+bool SceneOpenGL::viewportLimitsMatched(const QSize &size) const {
652846
+    GLint limit[2];
652846
+    glGetIntegerv(GL_MAX_VIEWPORT_DIMS, limit);
652846
+    if (limit[0] < size.width() || limit[1] < size.height()) {
652846
+        QMetaObject::invokeMethod(Compositor::self(), "suspend",
652846
+                                  Qt::QueuedConnection);
652846
+        const QString message = i18n("

OpenGL desktop effects not possible

"
652846
+                                     "Your system cannot perform OpenGL Desktop Effects at the "
652846
+                                     "current resolution

"
652846
+                                     "You can try to select the XRender backend , but it "
652846
+                                     "might be very slow for this resolution as well.
"
652846
+                                     "Alternatively, lower the combined resolution of all screens "
652846
+                                     "to %1x%2 ", limit[0], limit[1]);
652846
+        const QString details = i18n("The demanded resolution exceeds the GL_MAX_VIEWPORT_DIMS "
652846
+                                     "limitation of your GPU and is therefore not compatible "
652846
+                                     "with the OpenGL compositor.
"
652846
+                                     "XRender does not know such limitation, but the performance "
652846
+                                     "will usually be impacted by the hardware limitations that"
652846
+                                     "restrict the OpenGL viewport size.");
652846
+        const int oldTimeout = QDBusConnection::sessionBus().interface()->timeout();
652846
+        QDBusConnection::sessionBus().interface()->setTimeout(500);
652846
+        if (QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.kwinCompositingDialog").value()) {
652846
+            QDBusInterface dialog( "org.kde.kwinCompositingDialog", "/CompositorSettings", "org.kde.kwinCompositingDialog" );
652846
+            dialog.asyncCall("warn", message, details, "");
652846
+        } else {
652846
+            const QString args = "warn " + message.toLocal8Bit().toBase64() + " details " + details.toLocal8Bit().toBase64();
652846
+            KProcess::startDetached("kcmshell4", QStringList() << "kwincompositing" << "--args" << args);
652846
+        }
652846
+        QDBusConnection::sessionBus().interface()->setTimeout(oldTimeout);
652846
+        return false;
652846
+    }
652846
+    glGetIntegerv(GL_MAX_TEXTURE_SIZE, limit);
652846
+    if (limit[0] < size.width() || limit[0] < size.height()) {
652846
+        KConfig cfg("kwin_dialogsrc");
652846
+
652846
+        if (!KConfigGroup(&cfg, "Notification Messages").readEntry("max_tex_warning", true))
652846
+            return true;
652846
+
652846
+        const QString message = i18n("

OpenGL desktop effects might be unusable

"
652846
+                                     "OpenGL Desktop Effects at the current resolution are supported "
652846
+                                     "but might be exceptionally slow.
"
652846
+                                     "Also large windows will turn entirely black.

"
652846
+                                     "Consider to suspend compositing, switch to the XRender backend "
652846
+                                     "or lower the resolution to %1x%1." , limit[0]);
652846
+        const QString details = i18n("The demanded resolution exceeds the GL_MAX_TEXTURE_SIZE "
652846
+                                     "limitation of your GPU, thus windows of that size cannot be "
652846
+                                     "assigned to textures and will be entirely black.
"
652846
+                                     "Also this limit will often be a performance level barrier despite "
652846
+                                     "below GL_MAX_VIEWPORT_DIMS, because the driver might fall back to "
652846
+                                     "software rendering in this case.");
652846
+        const int oldTimeout = QDBusConnection::sessionBus().interface()->timeout();
652846
+        QDBusConnection::sessionBus().interface()->setTimeout(500);
652846
+        if (QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.kwinCompositingDialog").value()) {
652846
+            QDBusInterface dialog( "org.kde.kwinCompositingDialog", "/CompositorSettings", "org.kde.kwinCompositingDialog" );
652846
+            dialog.asyncCall("warn", message, details, "kwin_dialogsrc:max_tex_warning");
652846
+        } else {
652846
+            const QString args = "warn " + message.toLocal8Bit().toBase64() + " details " +
652846
+                                 details.toLocal8Bit().toBase64() + " dontagain kwin_dialogsrc:max_tex_warning";
652846
+            KProcess::startDetached("kcmshell4", QStringList() << "kwincompositing" << "--args" << args);
652846
+        }
652846
+        QDBusConnection::sessionBus().interface()->setTimeout(oldTimeout);
652846
+    }
652846
+    return true;
652846
+}
652846
+
652846
 void SceneOpenGL::screenGeometryChanged(const QSize &size)
652846
 {
652846
+    if (!viewportLimitsMatched(size))
652846
+        return;
652846
     Scene::screenGeometryChanged(size);
652846
     glViewport(0,0, size.width(), size.height());
652846
     m_backend->screenGeometryChanged(size);
652846
diff --git a/kwin/scene_opengl.h b/kwin/scene_opengl.h
652846
index e6142c0..c10c611 100644
652846
--- a/kwin/scene_opengl.h
652846
+++ b/kwin/scene_opengl.h
652846
@@ -79,6 +79,8 @@ public Q_SLOTS:
652846
 protected:
652846
     bool init_ok;
652846
 private:
652846
+    bool viewportLimitsMatched(const QSize &size) const;
652846
+private:
652846
     QHash< Toplevel*, Window* > windows;
652846
     bool debug;
652846
     OpenGLBackend *m_backend;