[prev in list] [next in list] [prev in thread] [next in thread] 

List:       freedesktop-compiz
Subject:    [compiz] KDesktop 3 transparency patch
From:       Dennis Kasprzyk <onestone () opencompositing ! org>
Date:       2007-06-06 15:05:54
Message-ID: 200706061705.54801.onestone () opencompositing ! org
[Download RAW message or body]

Hello,

this patch adds support for real transparency to kdesktop. It adds two new 
composite manager related features. To activate the features kdesktop has to 
be started with the "--bg-transparency" option.

The first one allows you to change the opacity of the background image. This 
works currently with the beryl transparent cube and will also work with 
compiz once the transparent cube gets applied. To activate the feature add 
the following to your kdesktoprc:
[Background Common]
BackgroundOpacity=90 (0 = fully transparent / 100 = opaque)

The second feature allows compiz (and later maybe other composite managers) to 
tell kdesktop not to paint the background image 
("_COMPIZ_WALLPAPER_SUPPORTED" x atom). In this case compiz is able to paint 
a viewport dependent background or to make it even animated. This feature 
looks for changes to the x atom, so that kdesktop will automatically switch 
back to normal background if kwin gets started or compiz stops to render the 
wallpaper.

This patch is against the current kde3 svn.

You can also find it with screenshots on 
http://www.kde-apps.org/content/show.php/KDesktop+transparency+support?content=59864

Regards
Dennis

["kdesktop-transparency.patch" (text/x-diff)]

Index: main.cc
===================================================================
--- main.cc	(Revision 671918)
+++ main.cc	(Arbeitskopie)
@@ -36,12 +36,24 @@
 #include "init.h"
 #include "krootwm.h"
 #include "kdesktopsettings.h"
+#include "kdesktopapp.h"
 
 #include <signal.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <stdlib.h>
 
+#if defined(Q_WS_X11) && defined(HAVE_XRENDER) && QT_VERSION >= 0x030300
+#define COMPOSITE
+#endif
+
+#ifdef COMPOSITE
+# include <X11/Xlib.h>
+# include <X11/extensions/Xrender.h>
+# include <fixx11h.h>
+# include <dlfcn.h>
+#endif
+
 static const char description[] =
         I18N_NOOP("The KDE desktop");
 
@@ -52,9 +64,15 @@
    { "x-root", I18N_NOOP("Use this if the desktop window appears as a real window"), \
0 },  { "noautostart", I18N_NOOP("Obsolete"), 0 },
    { "waitforkded", I18N_NOOP("Wait for kded to finish building database"), 0 },
+#ifdef COMPOSITE
+   { "bg-transparency",  I18N_NOOP("Enable background transparency"), 0 },
+#endif
    KCmdLineLastOption
 };
 
+bool argb_visual = false;
+KDesktopApp *myApp = NULL;
+
 // -----------------------------------------------------------------------------
 
 int kdesktop_screen_number = 0;
@@ -176,12 +194,72 @@
     r.setDCOPClient( cl );
     r.send( "suspendStartup", QCString( "kdesktop" ));
     delete cl;
-    KUniqueApplication app;
-    app.disableSessionManagement(); // Do SM, but don't restart.
 
-    KDesktopSettings::instance(kdesktop_name + "rc");
     KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
 
+#ifdef COMPOSITE
+
+    KCmdLineArgs *qtargs = KCmdLineArgs::parsedArgs("qt");
+
+    if ( args->isSet("bg-transparency")) {
+        char *display = 0;
+        if ( qtargs->isSet("display"))
+            display = qtargs->getOption( "display" ).data();
+
+        Display *dpy = XOpenDisplay( display );
+        if ( !dpy ) {
+            kdError() << "cannot connect to X server " << display << endl;
+            exit( 1 );
+        }
+
+        int screen = DefaultScreen( dpy );
+
+        Visual *visual = 0;
+        int event_base, error_base;
+
+        if ( XRenderQueryExtension( dpy, &event_base, &error_base ) ) {
+            int nvi;
+            XVisualInfo templ;
+            templ.screen  = screen;
+            templ.depth   = 32;
+            templ.c_class = TrueColor;
+            XVisualInfo *xvi = XGetVisualInfo( dpy, VisualScreenMask
+                    | VisualDepthMask | VisualClassMask, &templ, &nvi );
+
+            for ( int i = 0; i < nvi; i++ ) {
+                XRenderPictFormat *format =
+                        XRenderFindVisualFormat( dpy, xvi[i].visual );
+                if ( format->type == PictTypeDirect && format->direct.alphaMask ) {
+                    visual = xvi[i].visual;
+                    kdDebug() << "found visual with alpha support" << endl;
+                    argb_visual = true;
+                    break;
+                }
+            }
+        }
+        // The QApplication ctor used is normally intended for applications not \
using Qt +        // as the primary toolkit (e.g. Motif apps also using Qt), with \
some slightly +        // unpleasant side effects (e.g. #83974). This code checks if \
qt-copy patch #0078 +        // is applied, which allows turning this off.
+        bool* qt_no_foreign_hack =
+                static_cast< bool* >( dlsym( RTLD_DEFAULT, "qt_no_foreign_hack" ));
+        if( qt_no_foreign_hack )
+            *qt_no_foreign_hack = true;
+        // else argb_visual = false ... ? *shrug*
+        if( argb_visual )
+            myApp = new KDesktopApp( dpy, Qt::HANDLE( visual ), 0 );
+        else
+            XCloseDisplay( dpy );
+    }
+    if( myApp == NULL )
+        myApp = new KDesktopApp;
+#else
+    myApp = new KDesktopApp;
+#endif
+    myApp->disableSessionManagement(); // Do SM, but don't restart.
+
+    KDesktopSettings::instance(kdesktop_name + "rc");
+
     bool x_root_hack = args->isSet("x-root");
     bool wait_for_kded = args->isSet("waitforkded");
 
@@ -194,11 +272,11 @@
     testLocalInstallation();
 
     // Mark kdeskop as immutable if all of its config modules have been disabled
-    if (!app.config()->isImmutable() && 
+    if (!myApp->config()->isImmutable() &&
         kapp->authorizeControlModules(KRootWm::configModules()).isEmpty())
     {
-       app.config()->setReadOnly(true);
-       app.config()->reparseConfiguration();
+       myApp->config()->setReadOnly(true);
+       myApp->config()->reparseConfiguration();
     }
 
     // for the KDE-already-running check in startkde
@@ -209,7 +287,8 @@
 
     args->clear();
 
-    app.dcopClient()->setDefaultObject( "KDesktopIface" );
+    myApp->dcopClient()->setDefaultObject( "KDesktopIface" );
 
-    return app.exec();
+	
+    return myApp->exec();
 }
Index: kdesktopapp.h
===================================================================
--- kdesktopapp.h	(Revision 0)
+++ kdesktopapp.h	(Revision 0)
@@ -0,0 +1,67 @@
+/* This file is part of the KDE project
+   Copyright (C) 2007 Dennis Kasprzyk <onestone@opencompositing.org>
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public License
+   along with this library; see the file COPYING.LIB.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __kdesktopapp_h__
+#define __kdesktopapp_h__
+
+#include <config.h>
+#include <kuniqueapplication.h>
+
+#if defined(Q_WS_X11) && defined(HAVE_XRENDER) && QT_VERSION >= 0x030300
+#define COMPOSITE
+#endif
+
+#ifdef COMPOSITE
+# include <X11/Xlib.h>
+# include <X11/Xatom.h>
+# include <fixx11h.h>
+#endif
+
+class KDesktopApp : public KUniqueApplication
+{
+    Q_OBJECT
+    public:
+        KDesktopApp();
+        KDesktopApp(Display * dpy, Qt::HANDLE visual = 0,
+                    Qt::HANDLE colormap = 0);
+
+#ifdef COMPOSITE
+        bool x11EventFilter (XEvent *);
+
+        bool cmBackground ()
+        {
+            return m_bgSupported;
+        }
+#endif
+        
+    signals:
+        void cmBackgroundChanged(bool supported);
+
+#ifdef COMPOSITE
+    private:
+        void initCmBackground();
+        
+    private:
+
+        Atom m_cmBackground;
+        Bool m_bgSupported;
+#endif
+};
+
+#endif
Index: kdesktop.kcfg
===================================================================
--- kdesktop.kcfg	(Revision 671918)
+++ kdesktop.kcfg	(Arbeitskopie)
@@ -31,6 +31,11 @@
       <label>Background cache size</label>
       <whatsthis>Here you can enter how much memory KDE should use for caching the \
background(s). If you have different backgrounds for the different desktops caching \
can make switching desktops smoother at the expense of higher memory use.</whatsthis> \
</entry> +    <entry key="BackgroundOpacity" type="Int">
+      <default>100</default>
+      <label>Background Opacity</label>
+      <whatsthis>Here you can the opacity of the background (0-100). A composite \
manager can then render something behind it.</whatsthis> +    </entry>
   </group>
   <group name="General"> 
     <entry name="DesktopEnabled" key="Enabled" type="Bool">
Index: kdesktopapp.cpp
===================================================================
--- kdesktopapp.cpp	(Revision 0)
+++ kdesktopapp.cpp	(Revision 0)
@@ -0,0 +1,95 @@
+/* This file is part of the KDE project
+   Copyright (C) 2007 Dennis Kasprzyk <onestone@opencompositing.org>
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public License
+   along with this library; see the file COPYING.LIB.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+#include <kdesktopapp.h>
+
+KDesktopApp::KDesktopApp():
+KUniqueApplication()
+{
+#ifdef COMPOSITE
+    initCmBackground();
+#endif
+}
+
+KDesktopApp::KDesktopApp(Display * dpy, Qt::HANDLE visual, Qt::HANDLE colormap):
+KUniqueApplication(dpy, visual, colormap)
+{
+#ifdef COMPOSITE
+    initCmBackground();
+#endif
+}
+
+#ifdef COMPOSITE
+void KDesktopApp::initCmBackground()
+{
+    Atom type;
+    int format;
+    unsigned long num, rest;
+    unsigned char *data;
+
+    m_bgSupported = false;
+    m_cmBackground =
+            XInternAtom (qt_xdisplay(), "_COMPIZ_WALLPAPER_SUPPORTED", false);
+
+    XSelectInput (qt_xdisplay(), qt_xrootwin(), PropertyChangeMask);
+
+    if (XGetWindowProperty (qt_xdisplay(), qt_xrootwin(), m_cmBackground,
+                            0, 1, FALSE,  XA_CARDINAL, &type, &format, &num,
+                            &rest, &data) == Success && num)
+    {
+        if (type == XA_CARDINAL)
+            m_bgSupported = (*data == 1);
+        XFree (data);
+    }
+}
+
+bool KDesktopApp::x11EventFilter (XEvent * xevent)
+{
+    if (xevent->type == PropertyNotify &&
+        xevent->xproperty.window == qt_xrootwin() &&
+        xevent->xproperty.atom == m_cmBackground)
+    {
+        Atom type;
+        int format;
+        unsigned long num, rest;
+        unsigned char *data;
+    
+        Bool supported = false;
+        
+        if (XGetWindowProperty (qt_xdisplay(), qt_xrootwin(), m_cmBackground,
+                            0, 1, FALSE,  XA_CARDINAL, &type, &format, &num,
+                            &rest, &data) == Success && num)
+        {
+            if (type == XA_CARDINAL)
+                supported = (*data == 1);
+            XFree (data);
+        }
+
+        if (m_bgSupported != supported)
+        {
+            m_bgSupported = supported;
+            emit cmBackgroundChanged(supported);
+        }
+    }
+    return KUniqueApplication::x11EventFilter (xevent);
+}
+
+#endif
+
+#include "kdesktopapp.moc"
Index: bgmanager.cc
===================================================================
--- bgmanager.cc	(Revision 671918)
+++ bgmanager.cc	(Arbeitskopie)
@@ -14,6 +14,7 @@
 #include "bgdefaults.h"
 #include "kdesktopsettings.h"
 #include "bgsettings.h"
+#include "kdesktopapp.h"
 
 #include <assert.h>
 
@@ -38,6 +39,12 @@
 #define None 0L
 #endif
 
+#ifdef COMPOSITE
+# include <X11/Xlib.h>
+# include <X11/extensions/Xrender.h>
+# include <fixx11h.h>
+#endif
+
 #include "pixmapserver.h"
 
 template class QPtrVector<KBackgroundRenderer>;
@@ -47,6 +54,9 @@
 static Atom prop_root;
 static bool properties_inited = false;
 
+extern bool argb_visual;
+extern KDesktopApp *myApp;
+
 /**** KBackgroundManager ****/
 
 KBackgroundManager::KBackgroundManager(QWidget *desktop, KWinModule* kwinModule)
@@ -85,6 +95,13 @@
         m_Renderer[i]->enableTiling( true ); // optimize
     }
 
+#ifdef COMPOSITE
+    m_tPixmap = new KPixmap(kapp->desktop()->size());
+    m_tPixmap->fill(QColor(0, 0x0));
+    connect(myApp, SIGNAL(cmBackgroundChanged( bool )),
+            SLOT(slotCmBackgroundChanged( bool )));
+#endif
+
     configure();
 
     m_pTimer = new QTimer(this);
@@ -345,6 +362,43 @@
  */
 void KBackgroundManager::setPixmap(KPixmap *pm, int hash, int desk)
 {
+    KPixmap *ep = pm;
+
+#ifdef COMPOSITE
+    if (argb_visual && (KDesktopSettings::backgroundOpacity() < 100
+        || myApp->cmBackground()))
+    {
+        ep = m_tPixmap;
+        if (KDesktopSettings::backgroundOpacity() > 0 && pm
+            && !myApp->cmBackground())
+        {
+            XRenderPictFormat *format;
+            format = XRenderFindStandardFormat (qt_xdisplay(), PictStandardARGB32);
+
+            XRenderColor fillColor;
+
+            int color = KDesktopSettings::backgroundOpacity() * 0xffff / 100;
+            fillColor.red = color;
+            fillColor.green = color;
+            fillColor.blue = color;
+            fillColor.alpha = color;
+
+            Picture fill = XRenderCreateSolidFill (qt_xdisplay(), &fillColor);
+            Picture src = XRenderCreatePicture(qt_xdisplay(), pm->handle(),
+                                               format, 0, NULL);
+            Picture dst = XRenderCreatePicture(qt_xdisplay(), ep->handle(),
+                                               format, 0, NULL);
+
+            XRenderComposite (qt_xdisplay(), PictOpSrc, src, fill, dst, 0, 0, 0,
+                              0, 0, 0, pm->width(), pm->height());
+
+            XRenderFreePicture (qt_xdisplay(), fill);
+            XRenderFreePicture (qt_xdisplay(), src);
+            XRenderFreePicture (qt_xdisplay(), dst);
+        }
+    }
+#endif
+
     if (m_pDesktop)
     {
        QScrollView* sv = dynamic_cast<QScrollView*>( m_pDesktop );
@@ -352,7 +406,7 @@
          // Qt eats repaint events in this case :-((
          sv->viewport()->update();
        }
-       m_pDesktop->setErasePixmap(*pm);
+       m_pDesktop->setErasePixmap(*ep);
        m_pDesktop->repaint();
        static bool root_cleared = false;
        if( !root_cleared )
@@ -360,13 +414,13 @@
           root_cleared = true;
 	  QTimer::singleShot( 0, this, SLOT( clearRoot()));
           // but make the pixmap visible until m_pDesktop is visible
-          QApplication::desktop()->screen()->setErasePixmap(*pm);
+          QApplication::desktop()->screen()->setErasePixmap(*ep);
           QApplication::desktop()->screen()->erase();
        }
     }
     else
     {
-       QApplication::desktop()->screen()->setErasePixmap(*pm);
+       QApplication::desktop()->screen()->setErasePixmap(*ep);
        QApplication::desktop()->screen()->erase();
     }
 
@@ -756,6 +810,14 @@
         // make the renderer update its desktop size
         r->desktopResized();
     }
+
+#ifdef COMPOSITE
+    if (m_tPixmap)
+	delete m_tPixmap;
+    m_tPixmap = new KPixmap(kapp->desktop()->size());
+    m_tPixmap->fill(QColor(0, 0x0));
+#endif
+    
     m_Hash = 0;
     if( m_pDesktop )
         m_pDesktop->resize( kapp->desktop()->size());
@@ -808,4 +870,13 @@
   slotChangeDesktop(0);
 }
 
+#ifdef COMPOSITE
+void KBackgroundManager::slotCmBackgroundChanged( bool )
+{
+    m_tPixmap->fill(QColor(0, 0x0));
+    m_Hash = 0;
+    slotChangeDesktop(0);
+}
+#endif
+
 #include "bgmanager.moc"
Index: Makefile.am
===================================================================
--- Makefile.am	(Revision 671918)
+++ Makefile.am	(Arbeitskopie)
@@ -23,13 +23,15 @@
 	minicli.cpp KBackgroundIface.skel pixmapserver.cc kcustommenu.cc \
 	startupid.cpp minicli_ui.ui xautolock_diy.c xautolock_engine.c \
 	kshadowengine.cpp kshadowsettings.cpp \
-	kdesktopshadowsettings.cpp kfileividesktop.cpp
+	kdesktopshadowsettings.cpp kfileividesktop.cpp \
+	kdesktopapp.cpp
 
 include_HEADERS = KDesktopIface.h KScreensaverIface.h KBackgroundIface.h
 
 noinst_HEADERS = desktop.h bgmanager.h krootwm.h \
 	xautolock.h lockeng.h init.h minicli.h \
-	pixmapserver.h startupid.h xautolock_c.h
+	pixmapserver.h startupid.h xautolock_c.h \
+	kdesktopapp.h
 
 kcheckrunning_SOURCES = kcheckrunning.cpp
 kcheckrunning_LDFLAGS = $(all_libraries)
Index: bgmanager.h
===================================================================
--- bgmanager.h	(Revision 671918)
+++ bgmanager.h	(Arbeitskopie)
@@ -15,6 +15,10 @@
 
 #include <KBackgroundIface.h>
 
+#if defined(Q_WS_X11) && defined(HAVE_XRENDER) && QT_VERSION >= 0x030300
+#define COMPOSITE
+#endif
+
 class KConfig;
 class QTimer;
 class QPixmap;
@@ -83,6 +87,10 @@
     void desktopResized();
     void clearRoot();
     void saveImages();
+
+#ifdef COMPOSITE
+    void slotCmBackgroundChanged(bool);
+#endif
     
 private:
     void applyCommon(bool common);
@@ -114,6 +122,10 @@
     QWidget *m_pDesktop;
     QTimer *m_pTimer;
 
+#ifdef COMPOSITE
+	KPixmap *m_tPixmap;
+#endif
+	
     QPtrVector<KVirtualBGRenderer> m_Renderer;
     QPtrVector<KBackgroundCacheEntry> m_Cache;
 



_______________________________________________
compiz mailing list
compiz@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/compiz


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic