From b0abae5b66b2775ba150070b70b639cd88cf62b3 Mon Sep 17 00:00:00 2001 From: tpearson Date: Mon, 19 Apr 2010 04:34:32 +0000 Subject: KDEDIR ordering repair Added true transparency support to kdesktop git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdebase@1116291 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- kdesktop/Makefile.am | 6 ++- kdesktop/bgmanager.cc | 77 +++++++++++++++++++++++++++++++++++++-- kdesktop/bgmanager.h | 12 ++++++ kdesktop/kdesktop.kcfg | 5 +++ kdesktop/kdesktopapp.cpp | 95 ++++++++++++++++++++++++++++++++++++++++++++++++ kdesktop/kdesktopapp.h | 67 ++++++++++++++++++++++++++++++++++ kdesktop/main.cc | 95 ++++++++++++++++++++++++++++++++++++++++++++---- startkde | 2 +- 8 files changed, 345 insertions(+), 14 deletions(-) create mode 100644 kdesktop/kdesktopapp.cpp create mode 100644 kdesktop/kdesktopapp.h diff --git a/kdesktop/Makefile.am b/kdesktop/Makefile.am index 0c1041f19..fecd9e9c4 100644 --- a/kdesktop/Makefile.am +++ b/kdesktop/Makefile.am @@ -23,13 +23,15 @@ kdesktop_la_SOURCES = main.cc krootwm.cc xautolock.cc kdiconview.cc desktop.cc \ 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 --git a/kdesktop/bgmanager.cc b/kdesktop/bgmanager.cc index 0beb49c93..7a9fe5fd5 100644 --- a/kdesktop/bgmanager.cc +++ b/kdesktop/bgmanager.cc @@ -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 @@ template class QMemArray; 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 @@ KBackgroundManager::KBackgroundManager(QWidget *desktop, KWinModule* kwinModule) 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); @@ -450,6 +467,43 @@ void KBackgroundManager::exportBackground(int pixmap, int desk) */ 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 ); @@ -457,7 +511,7 @@ void KBackgroundManager::setPixmap(KPixmap *pm, int hash, int desk) // 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 ) @@ -465,13 +519,13 @@ void KBackgroundManager::setPixmap(KPixmap *pm, int hash, int desk) root_cleared = true; QTimer::singleShot( 0, this, SLOT( clearRoot())); // but make the pixmap visible until m_pDesktop is visible - KApplication::desktop()->screen()->setErasePixmap(*pm); + KApplication::desktop()->screen()->setErasePixmap(*ep); KApplication::desktop()->screen()->erase(); } } else { - KApplication::desktop()->screen()->setErasePixmap(*pm); + KApplication::desktop()->screen()->setErasePixmap(*ep); KApplication::desktop()->screen()->erase(); } @@ -878,6 +932,14 @@ void KBackgroundManager::desktopResized() r->renderer(j)->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()->geometry().size()); @@ -934,4 +996,13 @@ void KBackgroundManager::setBackgroundEnabled( const bool enable ) slotChangeDesktop(0); } +#ifdef COMPOSITE +void KBackgroundManager::slotCmBackgroundChanged( bool ) +{ + m_tPixmap->fill(QColor(0, 0x0)); + m_Hash = 0; + slotChangeDesktop(0); +} +#endif + #include "bgmanager.moc" diff --git a/kdesktop/bgmanager.h b/kdesktop/bgmanager.h index 53787e501..455e3a3ad 100644 --- a/kdesktop/bgmanager.h +++ b/kdesktop/bgmanager.h @@ -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; @@ -84,6 +88,10 @@ private slots: void desktopResized(); void clearRoot(); void saveImages(); + +#ifdef COMPOSITE + void slotCmBackgroundChanged(bool); +#endif private: void applyCommon(bool common); @@ -116,6 +124,10 @@ private: QWidget *m_pDesktop; QTimer *m_pTimer; +#ifdef COMPOSITE + KPixmap *m_tPixmap; +#endif + QPtrVector m_Renderer; QPtrVector m_Cache; diff --git a/kdesktop/kdesktop.kcfg b/kdesktop/kdesktop.kcfg index b949efbea..739e40e16 100644 --- a/kdesktop/kdesktop.kcfg +++ b/kdesktop/kdesktop.kcfg @@ -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 --git a/kdesktop/kdesktopapp.cpp b/kdesktop/kdesktopapp.cpp new file mode 100644 index 000000000..f7324362c --- /dev/null +++ b/kdesktop/kdesktopapp.cpp @@ -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 --git a/kdesktop/kdesktopapp.h b/kdesktop/kdesktopapp.h new file mode 100644 index 000000000..22b47bda2 --- /dev/null +++ b/kdesktop/kdesktopapp.h @@ -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 --git a/kdesktop/main.cc b/kdesktop/main.cc index dd058c498..3a9c4911a 100644 --- a/kdesktop/main.cc +++ b/kdesktop/main.cc @@ -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 @@ static KCmdLineOptions options[] = { "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 @@ extern "C" KDE_EXPORT int kdemain( int argc, char **argv ) 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 @@ extern "C" KDE_EXPORT int kdemain( int argc, char **argv ) 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 @@ extern "C" KDE_EXPORT int kdemain( int argc, char **argv ) args->clear(); - app.dcopClient()->setDefaultObject( "KDesktopIface" ); + myApp->dcopClient()->setDefaultObject( "KDesktopIface" ); - return app.exec(); + + return myApp->exec(); } diff --git a/startkde b/startkde index 6c6c0a5b3..f0086d870 100644 --- a/startkde +++ b/startkde @@ -60,7 +60,7 @@ fi # The user's personal KDE directory is usually ~/.kde3, but this setting # may be overridden by setting KDEHOME. -export KDEHOME=$HOME/.kde3 && export PATH=/opt/kde3/bin:/opt/kde3/games:$PATH && export KDEDIRS=/usr/:/opt/kde3/ && export XDG_DATA_DIRS=/opt/kde3/share/:/usr/share/ && export XDG_CONFIG_DIRS=/opt/kde3/etc/xdg/:/etc/xdg/ && export MANPATH=/opt/kde3/share/man:$MANPATH && export DESKTOP_SESSION=kde3 +export KDEHOME=$HOME/.kde3 && export PATH=/opt/kde3/bin:/opt/kde3/games:$PATH && export KDEDIRS=/opt/kde3/:/usr/ && export XDG_DATA_DIRS=/opt/kde3/share/:/usr/share/ && export XDG_CONFIG_DIRS=/opt/kde3/etc/xdg/:/etc/xdg/ && export MANPATH=/opt/kde3/share/man:$MANPATH && export DESKTOP_SESSION=kde3 test -n "$KDEHOME" && kdehome=`echo "$KDEHOME"|sed "s,^~/,$HOME/,"` # see kstartupconfig source for usage -- cgit v1.2.3