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
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 <[EMAIL PROTECTED]> + + 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 <[EMAIL PROTECTED]> + + 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