diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2011-08-10 23:38:28 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2011-08-10 23:38:28 +0000 |
commit | 47ee068d2c202c4006d5a916fb2cfa4d4071230d (patch) | |
tree | ca18f62ea3a5300b4e94f757208abf47fecad42f | |
parent | db9d51186b28bc2252032458b433ba5f8d1972bc (diff) | |
download | tdelibs-47ee068d2c202c4006d5a916fb2cfa4d4071230d.tar.gz tdelibs-47ee068d2c202c4006d5a916fb2cfa4d4071230d.zip |
Add composition manager detection and support to Trinity
This adds the methods required to make transparent widgets via alpha blending a reality
An additional widget class may be coming shortly
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdelibs@1246265 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
-rw-r--r-- | CMakeLists.txt | 6 | ||||
-rw-r--r-- | config.h.cmake | 3 | ||||
-rw-r--r-- | kdecore/CMakeLists.txt | 10 | ||||
-rw-r--r-- | kdecore/kapplication.cpp | 215 | ||||
-rw-r--r-- | kdecore/kapplication.h | 89 |
5 files changed, 316 insertions, 7 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 3fd7da01c..941411514 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -548,6 +548,12 @@ if( XRENDER_FOUND ) set( HAVE_XRENDER 1 ) endif( XRENDER_FOUND ) +##### check for xcomposite ######################### + +pkg_search_module( XCOMPOSITE xcomposite ) +if( XCOMPOSITE_FOUND ) + set( HAVE_XCOMPOSITE 1 ) +endif( XCOMPOSITE_FOUND ) ##### check for libxml-2.0 ###################### diff --git a/config.h.cmake b/config.h.cmake index 719e324df..99562b3a6 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -665,6 +665,9 @@ /* Defined if your system has XRender support */ #cmakedefine HAVE_XRENDER 1 +/* Defined if your system has XComposite support */ +#cmakedefine HAVE_XCOMPOSITE 1 + /* Define to 1 if you have the `_getpty' function. */ #cmakedefine HAVE__GETPTY 1 diff --git a/kdecore/CMakeLists.txt b/kdecore/CMakeLists.txt index 3e37ed20c..efe2c8f3c 100644 --- a/kdecore/CMakeLists.txt +++ b/kdecore/CMakeLists.txt @@ -129,7 +129,7 @@ tde_add_library( ${target} SHARED AUTOMOC SOURCES ${${target}_SRCS} VERSION 4.2.0 EMBED kdecorenetwork-static - LINK ltdlc-static ${KDESVGICONS} DCOP-shared kdefx-shared ${ZLIB_LIBRARIES} ${LIBIDN_LIBRARIES} ICE SM + LINK ltdlc-static ${KDESVGICONS} DCOP-shared kdefx-shared ${ZLIB_LIBRARIES} ${LIBIDN_LIBRARIES} ${XCOMPOSITE_LIBRARIES} ICE SM DEPENDENCIES dcopidl dcopidl2cpp DESTINATION ${LIB_INSTALL_DIR} ) @@ -199,3 +199,11 @@ tde_add_executable(kgrantpty SETUID SOURCES kgrantpty.c DESTINATION ${BIN_INSTALL_DIR} ) + +##### kdetcompmgr ################################# + +tde_add_executable( kdetcompmgr + SOURCES kdetcompmgr.cpp + LINK kdecore-shared + DESTINATION ${BIN_INSTALL_DIR} +) diff --git a/kdecore/kapplication.cpp b/kdecore/kapplication.cpp index 292105835..7986079f4 100644 --- a/kdecore/kapplication.cpp +++ b/kdecore/kapplication.cpp @@ -125,6 +125,11 @@ #ifdef Q_WS_X11 #include <X11/Xlib.h> +#ifdef COMPOSITE +#include <X11/extensions/Xrender.h> +#include <X11/extensions/Xcomposite.h> +#include <dlfcn.h> +#endif #include <X11/Xutil.h> #include <X11/Xatom.h> #include <X11/SM/SMlib.h> @@ -175,6 +180,18 @@ static Atom atom_NetSupported; static Atom kde_xdnd_drop; #endif +#ifdef Q_WS_X11 +static int composite_event, composite_error, composite_opcode; +static bool x11_composite_error_generated; +static int x11_error(Display *dpy, XErrorEvent *ev) { + if (ev->request_code == composite_opcode && ev->minor_code == X_CompositeRedirectSubwindows) + { + x11_composite_error_generated = true; + return 0; + } +} +#endif + // duplicated from patched Qt, so that there won't be unresolved symbols if Qt gets // replaced by unpatched one KDECORE_EXPORT bool qt_qclipboard_bailout_hack = false; @@ -602,6 +619,7 @@ KApplication::KApplication( int& argc, char** argv, const TQCString& rAppName, TQApplication( argc, argv, GUIenabled ), KInstance(rAppName), #ifdef Q_WS_X11 display(0L), + argb_visual(false), #endif d (new KApplicationPrivate()) { @@ -622,11 +640,11 @@ KApplication::KApplication( int& argc, char** argv, const TQCString& rAppName, } KApplication::KApplication( bool allowStyles, bool GUIenabled ) : - TQApplication( *KCmdLineArgs::qt_argc(), *KCmdLineArgs::qt_argv(), - TRUE ), // Qt4 requires that there always be a GUI + TQApplication( *KCmdLineArgs::qt_argc(), *KCmdLineArgs::qt_argv(), TRUE ), // Qt4 requires that there always be a GUI KInstance( KCmdLineArgs::about), #ifdef Q_WS_X11 display(0L), + argb_visual(false), #endif d (new KApplicationPrivate) { @@ -648,9 +666,11 @@ KApplication::KApplication( bool allowStyles, bool GUIenabled ) : KApplication::KApplication( Display *dpy, Qt::HANDLE visual, Qt::HANDLE colormap, bool allowStyles ) : TQApplication( dpy, *KCmdLineArgs::qt_argc(), *KCmdLineArgs::qt_argv(), - visual, colormap ), + visual?visual:getX11RGBAVisual(dpy), colormap?colormap:getX11RGBAColormap(dpy) ), KInstance( KCmdLineArgs::about), display(0L), d (new KApplicationPrivate) { + if ((visual) && (colormap)) + getX11RGBAInformation(dpy); aIconPixmap.pm.icon = 0L; aIconPixmap.pm.miniIcon = 0L; read_app_startup_id(); @@ -665,9 +685,11 @@ KApplication::KApplication( Display *dpy, Qt::HANDLE visual, Qt::HANDLE colormap KApplication::KApplication( Display *dpy, Qt::HANDLE visual, Qt::HANDLE colormap, bool allowStyles, KInstance * _instance ) : TQApplication( dpy, *KCmdLineArgs::qt_argc(), *KCmdLineArgs::qt_argv(), - visual, colormap ), + visual?visual:getX11RGBAVisual(dpy), colormap?colormap:getX11RGBAColormap(dpy) ), KInstance( _instance ), display(0L), d (new KApplicationPrivate) { + if ((visual) && (colormap)) + getX11RGBAInformation(dpy); aIconPixmap.pm.icon = 0L; aIconPixmap.pm.miniIcon = 0L; read_app_startup_id(); @@ -684,6 +706,7 @@ KApplication::KApplication( bool allowStyles, bool GUIenabled, KInstance* _insta TQApplication( *KCmdLineArgs::qt_argc(), *KCmdLineArgs::qt_argv(), GUIenabled ), KInstance( _instance ), + argb_visual(false), #ifdef Q_WS_X11 display(0L), #endif @@ -708,6 +731,7 @@ KApplication::KApplication(Display *display, int& argc, char** argv, const TQCSt bool allowStyles, bool GUIenabled ) : TQApplication( display ), KInstance(rAppName), display(0L), + argb_visual(false), d (new KApplicationPrivate()) { aIconPixmap.pm.icon = 0L; @@ -1718,7 +1742,190 @@ public: }; #endif +#if defined(Q_WS_X11) && defined(COMPOSITE) +bool KApplication::isCompositionManagerAvailable() { + KConfigGroup pConfig (KGlobal::config(), "General"); + return pConfig.readBoolEntry("compositingManagerAvailable", false); + +return false; +} + +bool KApplication::detectCompositionManagerAvailable(bool force_available) { + bool compositing_manager_available; + if (force_available) { + compositing_manager_available = true; + } + else { + // See if compositing has been enabled + KCmdLineArgs *qtargs = KCmdLineArgs::parsedArgs("qt"); + char *displayname = 0; + if ( qtargs->isSet("display")) + displayname = qtargs->getOption( "display" ).data(); + + Display *dpy = XOpenDisplay( displayname ); + + x11_composite_error_generated = false; + compositing_manager_available = false; + XSetErrorHandler(x11_error); + if (!XQueryExtension (dpy, COMPOSITE_NAME, &composite_opcode, &composite_event, &composite_error)) { + XSetErrorHandler(NULL); + compositing_manager_available = false; + } + else { + Window root_window = XDefaultRootWindow(dpy); + XCompositeRedirectSubwindows(dpy, root_window, CompositeRedirectManual); + XSync(dpy, false); + if (x11_composite_error_generated == true) { + compositing_manager_available = true; + } + else { + XCompositeUnredirectSubwindows(dpy, root_window, CompositeRedirectManual); + compositing_manager_available = false; + } + XSetErrorHandler(NULL); + XCloseDisplay(dpy); + } + } + + KConfigGroup pConfig (KGlobal::config(), "General"); + bool cmanager_enabled = pConfig.readBoolEntry("compositingManagerAvailable", false); + if (cmanager_enabled != compositing_manager_available) { + pConfig.writeEntry("compositingManagerAvailable", compositing_manager_available, true, true); + } + pConfig.sync(); + + return compositing_manager_available; +} + +Display* KApplication::openX11RGBADisplay() { + KCmdLineArgs *qtargs = KCmdLineArgs::parsedArgs("qt"); + char *displayname = 0; + if ( qtargs->isSet("display")) + displayname = qtargs->getOption( "display" ).data(); + + Display *dpy = XOpenDisplay( displayname ); + return dpy; +} + +Qt::HANDLE KApplication::getX11RGBAVisual(Display *dpy) { + getX11RGBAInformation(dpy); + return argb_x11_visual; +} + +Qt::HANDLE KApplication::getX11RGBAColormap(Display *dpy) { + getX11RGBAInformation(dpy); + return argb_x11_colormap; +} + +bool KApplication::isX11CompositionAvailable() { + return argb_visual & isCompositionManagerAvailable(); +} + +void KApplication::getX11RGBAInformation(Display *dpy) { + if ( !dpy ) { + argb_visual = false; + return; + } + + int screen = DefaultScreen( dpy ); + Colormap colormap = 0; + 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; + colormap = XCreateColormap( dpy, RootWindow( dpy, screen ), visual, AllocNone ); + kdDebug() << "found visual with alpha support" << endl; + argb_visual = true; + break; + } + } + } + + if( argb_visual ) { + argb_x11_visual = Qt::HANDLE( visual ); + argb_x11_colormap = Qt::HANDLE( colormap ); + argb_visual = true; + return; + } + argb_visual = false; + return; +} + +KApplication KApplication::KARGBApplicationObject( bool allowStyles ) { + KCmdLineArgs *qtargs = KCmdLineArgs::parsedArgs("qt"); + bool argb_visual_available = false; + 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 ); + Colormap colormap = 0; + 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; + colormap = XCreateColormap( dpy, RootWindow( dpy, screen ), visual, AllocNone ); + kdDebug() << "found visual with alpha support" << endl; + argb_visual_available = true; + break; + } + } + } + + if( argb_visual_available ) { + return KApplication( dpy, Qt::HANDLE( visual ), Qt::HANDLE( colormap ), allowStyles ); + } + else { + return KApplication(allowStyles, true); + } +} +#else +Qt::HANDLE KApplication::getX11RGBAVisual(char *display) { + return 0; +} + +Qt::HANDLE KApplication::getX11RGBAColormap(char *display) { + return 0; +} +bool KApplication::isX11CompositionAvailable() { + return false; +} + +KApplication KApplication::KARGBApplication( bool allowStyles ) { + return KApplication::KApplication(allowStyles, true); +} +#endif static bool kapp_block_user_input = false; diff --git a/kdecore/kapplication.h b/kdecore/kapplication.h index 93820b68d..00a6429da 100644 --- a/kdecore/kapplication.h +++ b/kdecore/kapplication.h @@ -48,6 +48,8 @@ class KSessionManaged; class KStyle; class KURL; +#define COMPOSITE // [FIXME] Autodetect composition support + #define kapp KApplication::kApplication() class KApplicationPrivate; @@ -113,6 +115,10 @@ public: * This constructor takes aboutData and command line * arguments from KCmdLineArgs. * + * If ARGB (transparent) widgets are to be used in your application, + * please use KARGBApplication(new object name) or + * KARGBApplication(new object name, allow_styles) instead of KApplication(...). + * * @param allowStyles Set to false to disable the loading on plugin based * styles. This is only useful to applications that do not display a GUI * normally. If you do create an application with @p allowStyles set to false @@ -860,15 +866,88 @@ public: */ TQString checkRecoverFile( const TQString& pFilename, bool& bRecover ) const; -#ifdef Q_WS_X11 +#if defined(Q_WS_X11) && defined(COMPOSITE) /** + * @internal * Get the X11 display * @return the X11 Display */ - Display *getDisplay() { return display; } + Display *getDisplay() { return display; } + + /** + * @internal + * Gets X11 composition information + */ + void getX11RGBAInformation(Display *dpy); + + /** + * Gets the availability of a composition manager such as kompmgr + * Note that at least one application must have called detectCompositionManagerAvailable + * while the current X display was active in order for this method to return valid results. + * @see detectCompositionManagerAvailable() + * @return whether the composition manager is enabled + */ + static bool isCompositionManagerAvailable(); + + /** + * Detects the availability of a composition manager such as kompmgr + * Note that calling this method will probably cause the screen to flicker. + * @see isCompositionManagerAvailable() + * @param force_available If set, force TDE to assume a composition manager is available + * @return whether the composition manager is enabled + */ + bool detectCompositionManagerAvailable(bool force_available=false); + + /** + * @internal + * Opens an X11 display and returns the handle to it + * @return the X11 display handle + */ + Display *openX11RGBADisplay(); #endif /** + * @internal + * Creates a default KApplication with transparency support + * (if available) + */ + static KApplication KARGBApplicationObject( bool allowStyles=true ); + + #define KARGBApplication(objectname, ...) const KApplication &__kapplication_internal_app = KApplication::KARGBApplicationObject(__VA_ARGS__); KApplication &objectname = const_cast<KApplication&>(__kapplication_internal_app); + + /** + * Returns the X11 display visual + * + * @return A pointer to the X11 display visual + */ + Qt::HANDLE getX11RGBAVisual(Display *dpy); + + /** + * Returns the X11 display colormap + * + * @return An X11 display colormap object + */ + Qt::HANDLE getX11RGBAColormap(Display *dpy); + + /** + * Returns whether or not X11 composition is available + * + * You must first call getX11RGBAInformation() + * + * Note that getX11RGBAInformation() has already + * been called if you used the default KApplication + * constructor. + * + * Additionally, at least one application must have called + * detectCompositionManagerAvailable while the current X + * display was active in order for this method to return + * valid results. + * + * @return true if composition is available + */ + bool isX11CompositionAvailable(); + + /** * Enables style plugins. * * This is useful only to applications that normally @@ -1201,6 +1280,12 @@ private: void dcopClientPostInit(); void initUrlActionRestrictions(); + bool argb_visual; +#if defined(Q_WS_X11) && defined(COMPOSITE) + Qt::HANDLE argb_x11_visual; + Qt::HANDLE argb_x11_colormap; +#endif + public: /** * @internal |