diff -Naur kdebase-3.5.8.orig/kdesktop/Makefile.am kdebase-3.5.8/kdesktop/Makefile.am --- kdebase-3.5.8.orig/kdesktop/Makefile.am 2006-05-22 20:12:51.000000000 +0200 +++ kdebase-3.5.8/kdesktop/Makefile.am 2007-11-21 06:49:07.000000000 +0100 @@ -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) diff -Naur kdebase-3.5.8.orig/kdesktop/bgmanager.cc kdebase-3.5.8/kdesktop/bgmanager.cc --- kdebase-3.5.8.orig/kdesktop/bgmanager.cc 2007-01-15 12:32:10.000000000 +0100 +++ kdebase-3.5.8/kdesktop/bgmanager.cc 2007-11-21 06:49:07.000000000 +0100 @@ -14,6 +14,7 @@ #include "bgdefaults.h" #include "kdesktopsettings.h" #include "bgsettings.h" +#include "kdesktopapp.h" #include @@ -38,6 +39,12 @@ #define None 0L #endif +#ifdef COMPOSITE +# include +# include +# include +#endif + #include "pixmapserver.h" template class QPtrVector; @@ -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( 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" diff -Naur kdebase-3.5.8.orig/kdesktop/bgmanager.h kdebase-3.5.8/kdesktop/bgmanager.h --- kdebase-3.5.8.orig/kdesktop/bgmanager.h 2006-10-01 19:32:02.000000000 +0200 +++ kdebase-3.5.8/kdesktop/bgmanager.h 2007-11-21 06:49:07.000000000 +0100 @@ -15,6 +15,10 @@ #include +#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 m_Renderer; QPtrVector m_Cache; diff -Naur kdebase-3.5.8.orig/kdesktop/kdesktop.kcfg kdebase-3.5.8/kdesktop/kdesktop.kcfg --- kdebase-3.5.8.orig/kdesktop/kdesktop.kcfg 2006-07-22 10:15:49.000000000 +0200 +++ kdebase-3.5.8/kdesktop/kdesktop.kcfg 2007-11-21 06:49:07.000000000 +0100 @@ -31,6 +31,11 @@ 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. + + 100 + + Here you can the opacity of the background (0-100). A composite manager can then render something behind it. + diff -Naur kdebase-3.5.8.orig/kdesktop/kdesktopapp.cpp kdebase-3.5.8/kdesktop/kdesktopapp.cpp --- kdebase-3.5.8.orig/kdesktop/kdesktopapp.cpp 1970-01-01 01:00:00.000000000 +0100 +++ kdebase-3.5.8/kdesktop/kdesktopapp.cpp 2007-11-21 06:49:07.000000000 +0100 @@ -0,0 +1,95 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Dennis Kasprzyk + + 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::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" diff -Naur kdebase-3.5.8.orig/kdesktop/kdesktopapp.h kdebase-3.5.8/kdesktop/kdesktopapp.h --- kdebase-3.5.8.orig/kdesktop/kdesktopapp.h 1970-01-01 01:00:00.000000000 +0100 +++ kdebase-3.5.8/kdesktop/kdesktopapp.h 2007-11-21 06:49:07.000000000 +0100 @@ -0,0 +1,67 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Dennis Kasprzyk + + 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 +#include + +#if defined(Q_WS_X11) && defined(HAVE_XRENDER) && QT_VERSION >= 0x030300 +#define COMPOSITE +#endif + +#ifdef COMPOSITE +# include +# include +# include +#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 diff -Naur kdebase-3.5.8.orig/kdesktop/main.cc kdebase-3.5.8/kdesktop/main.cc --- kdebase-3.5.8.orig/kdesktop/main.cc 2006-10-01 19:32:02.000000000 +0200 +++ kdebase-3.5.8/kdesktop/main.cc 2007-11-21 06:49:07.000000000 +0100 @@ -36,12 +36,24 @@ #include "init.h" #include "krootwm.h" #include "kdesktopsettings.h" +#include "kdesktopapp.h" #include #include #include #include +#if defined(Q_WS_X11) && defined(HAVE_XRENDER) && QT_VERSION >= 0x030300 +#define COMPOSITE +#endif + +#ifdef COMPOSITE +# include +# include +# include +# include +#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(); }