Browse Source

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-ecb5cbfe19
tpearson 7 years ago
parent
commit
47ee068d2c
5 changed files with 316 additions and 7 deletions
  1. 6
    0
      CMakeLists.txt
  2. 3
    0
      config.h.cmake
  3. 9
    1
      kdecore/CMakeLists.txt
  4. 211
    4
      kdecore/kapplication.cpp
  5. 87
    2
      kdecore/kapplication.h

+ 6
- 0
CMakeLists.txt View File

@@ -548,6 +548,12 @@ if( XRENDER_FOUND )
548 548
   set( HAVE_XRENDER 1 )
549 549
 endif( XRENDER_FOUND )
550 550
 
551
+##### check for xcomposite #########################
552
+
553
+pkg_search_module( XCOMPOSITE xcomposite )
554
+if( XCOMPOSITE_FOUND )
555
+  set( HAVE_XCOMPOSITE 1 )
556
+endif( XCOMPOSITE_FOUND )
551 557
 
552 558
 ##### check for libxml-2.0 ######################
553 559
 

+ 3
- 0
config.h.cmake View File

@@ -665,6 +665,9 @@
665 665
 /* Defined if your system has XRender support */
666 666
 #cmakedefine HAVE_XRENDER 1
667 667
 
668
+/* Defined if your system has XComposite support */
669
+#cmakedefine HAVE_XCOMPOSITE 1
670
+
668 671
 /* Define to 1 if you have the `_getpty' function. */
669 672
 #cmakedefine HAVE__GETPTY 1
670 673
 

+ 9
- 1
kdecore/CMakeLists.txt View File

@@ -129,7 +129,7 @@ tde_add_library( ${target} SHARED AUTOMOC
129 129
   SOURCES ${${target}_SRCS}
130 130
   VERSION 4.2.0
131 131
   EMBED kdecorenetwork-static
132
-  LINK ltdlc-static ${KDESVGICONS} DCOP-shared kdefx-shared ${ZLIB_LIBRARIES} ${LIBIDN_LIBRARIES} ICE SM
132
+  LINK ltdlc-static ${KDESVGICONS} DCOP-shared kdefx-shared ${ZLIB_LIBRARIES} ${LIBIDN_LIBRARIES} ${XCOMPOSITE_LIBRARIES} ICE SM
133 133
   DEPENDENCIES dcopidl dcopidl2cpp
134 134
   DESTINATION ${LIB_INSTALL_DIR}
135 135
 )
@@ -199,3 +199,11 @@ tde_add_executable(kgrantpty SETUID
199 199
   SOURCES kgrantpty.c
200 200
   DESTINATION ${BIN_INSTALL_DIR}
201 201
 )
202
+
203
+##### kdetcompmgr #################################
204
+
205
+tde_add_executable( kdetcompmgr
206
+  SOURCES kdetcompmgr.cpp
207
+  LINK kdecore-shared
208
+  DESTINATION ${BIN_INSTALL_DIR}
209
+)

+ 211
- 4
kdecore/kapplication.cpp View File

@@ -125,6 +125,11 @@
125 125
 
126 126
 #ifdef Q_WS_X11
127 127
 #include <X11/Xlib.h>
128
+#ifdef COMPOSITE
129
+#include <X11/extensions/Xrender.h>
130
+#include <X11/extensions/Xcomposite.h>
131
+#include <dlfcn.h>
132
+#endif
128 133
 #include <X11/Xutil.h>
129 134
 #include <X11/Xatom.h>
130 135
 #include <X11/SM/SMlib.h>
@@ -175,6 +180,18 @@ static Atom atom_NetSupported;
175 180
 static Atom kde_xdnd_drop;
176 181
 #endif
177 182
 
183
+#ifdef Q_WS_X11
184
+static int composite_event, composite_error, composite_opcode;
185
+static bool x11_composite_error_generated;
186
+static int x11_error(Display *dpy, XErrorEvent *ev) {
187
+	if (ev->request_code == composite_opcode && ev->minor_code == X_CompositeRedirectSubwindows)
188
+	{
189
+		x11_composite_error_generated = true;
190
+		return 0;
191
+	}
192
+}
193
+#endif
194
+
178 195
 // duplicated from patched Qt, so that there won't be unresolved symbols if Qt gets
179 196
 // replaced by unpatched one
180 197
 KDECORE_EXPORT bool qt_qclipboard_bailout_hack = false;
@@ -602,6 +619,7 @@ KApplication::KApplication( int& argc, char** argv, const TQCString& rAppName,
602 619
   TQApplication( argc, argv, GUIenabled ), KInstance(rAppName),
603 620
 #ifdef Q_WS_X11
604 621
   display(0L),
622
+  argb_visual(false),
605 623
 #endif
606 624
   d (new KApplicationPrivate())
607 625
 {
@@ -622,11 +640,11 @@ KApplication::KApplication( int& argc, char** argv, const TQCString& rAppName,
622 640
 }
623 641
 
624 642
 KApplication::KApplication( bool allowStyles, bool GUIenabled ) :
625
-  TQApplication( *KCmdLineArgs::qt_argc(), *KCmdLineArgs::qt_argv(),
626
-                TRUE ),	// Qt4 requires that there always be a GUI
643
+  TQApplication( *KCmdLineArgs::qt_argc(), *KCmdLineArgs::qt_argv(), TRUE ),	// Qt4 requires that there always be a GUI
627 644
   KInstance( KCmdLineArgs::about),
628 645
 #ifdef Q_WS_X11
629 646
   display(0L),
647
+  argb_visual(false),
630 648
 #endif
631 649
   d (new KApplicationPrivate)
632 650
 {
@@ -648,9 +666,11 @@ KApplication::KApplication( bool allowStyles, bool GUIenabled ) :
648 666
 KApplication::KApplication( Display *dpy, Qt::HANDLE visual, Qt::HANDLE colormap,
649 667
 		            bool allowStyles ) :
650 668
   TQApplication( dpy, *KCmdLineArgs::qt_argc(), *KCmdLineArgs::qt_argv(),
651
-                visual, colormap ),
669
+                visual?visual:getX11RGBAVisual(dpy), colormap?colormap:getX11RGBAColormap(dpy) ),
652 670
   KInstance( KCmdLineArgs::about), display(0L), d (new KApplicationPrivate)
653 671
 {
672
+    if ((visual) && (colormap))
673
+        getX11RGBAInformation(dpy);
654 674
     aIconPixmap.pm.icon = 0L;
655 675
     aIconPixmap.pm.miniIcon = 0L;
656 676
     read_app_startup_id();
@@ -665,9 +685,11 @@ KApplication::KApplication( Display *dpy, Qt::HANDLE visual, Qt::HANDLE colormap
665 685
 KApplication::KApplication( Display *dpy, Qt::HANDLE visual, Qt::HANDLE colormap,
666 686
 		            bool allowStyles, KInstance * _instance ) :
667 687
   TQApplication( dpy, *KCmdLineArgs::qt_argc(), *KCmdLineArgs::qt_argv(),
668
-                visual, colormap ),
688
+                visual?visual:getX11RGBAVisual(dpy), colormap?colormap:getX11RGBAColormap(dpy) ),
669 689
   KInstance( _instance ), display(0L), d (new KApplicationPrivate)
670 690
 {
691
+    if ((visual) && (colormap))
692
+        getX11RGBAInformation(dpy);
671 693
     aIconPixmap.pm.icon = 0L;
672 694
     aIconPixmap.pm.miniIcon = 0L;
673 695
     read_app_startup_id();
@@ -684,6 +706,7 @@ KApplication::KApplication( bool allowStyles, bool GUIenabled, KInstance* _insta
684 706
   TQApplication( *KCmdLineArgs::qt_argc(), *KCmdLineArgs::qt_argv(),
685 707
                 GUIenabled ),
686 708
   KInstance( _instance ),
709
+  argb_visual(false),
687 710
 #ifdef Q_WS_X11
688 711
   display(0L),
689 712
 #endif
@@ -708,6 +731,7 @@ KApplication::KApplication(Display *display, int& argc, char** argv, const TQCSt
708 731
                            bool allowStyles, bool GUIenabled ) :
709 732
   TQApplication( display ), KInstance(rAppName),
710 733
   display(0L),
734
+  argb_visual(false),
711 735
   d (new KApplicationPrivate())
712 736
 {
713 737
     aIconPixmap.pm.icon = 0L;
@@ -1718,7 +1742,190 @@ public:
1718 1742
 };
1719 1743
 #endif
1720 1744
 
1745
+#if defined(Q_WS_X11) && defined(COMPOSITE)
1746
+bool KApplication::isCompositionManagerAvailable() {
1747
+	KConfigGroup pConfig (KGlobal::config(), "General");
1748
+	return pConfig.readBoolEntry("compositingManagerAvailable", false);
1749
+
1750
+return false;
1751
+}
1752
+
1753
+bool KApplication::detectCompositionManagerAvailable(bool force_available) {
1754
+	bool compositing_manager_available;
1755
+	if (force_available) {
1756
+		compositing_manager_available = true;
1757
+	}
1758
+	else {
1759
+		// See if compositing has been enabled
1760
+		KCmdLineArgs *qtargs = KCmdLineArgs::parsedArgs("qt");
1761
+		char *displayname = 0;
1762
+		if ( qtargs->isSet("display"))
1763
+			displayname = qtargs->getOption( "display" ).data();
1764
+			
1765
+		Display *dpy = XOpenDisplay( displayname );
1766
+	
1767
+		x11_composite_error_generated = false;
1768
+		compositing_manager_available = false;
1769
+		XSetErrorHandler(x11_error);
1770
+		if (!XQueryExtension (dpy, COMPOSITE_NAME, &composite_opcode, &composite_event, &composite_error)) {
1771
+			XSetErrorHandler(NULL);
1772
+			compositing_manager_available = false;
1773
+		}
1774
+		else {
1775
+			Window root_window = XDefaultRootWindow(dpy);
1776
+			XCompositeRedirectSubwindows(dpy, root_window, CompositeRedirectManual);
1777
+			XSync(dpy, false);
1778
+			if (x11_composite_error_generated == true) {
1779
+				compositing_manager_available = true;
1780
+			}
1781
+			else {
1782
+				XCompositeUnredirectSubwindows(dpy, root_window, CompositeRedirectManual);
1783
+				compositing_manager_available = false;
1784
+			}
1785
+			XSetErrorHandler(NULL);
1786
+			XCloseDisplay(dpy);
1787
+		}
1788
+	}
1789
+	
1790
+	KConfigGroup pConfig (KGlobal::config(), "General");
1791
+	bool cmanager_enabled = pConfig.readBoolEntry("compositingManagerAvailable", false);
1792
+	if (cmanager_enabled != compositing_manager_available) {
1793
+		pConfig.writeEntry("compositingManagerAvailable", compositing_manager_available, true, true);
1794
+	}
1795
+	pConfig.sync();
1796
+
1797
+	return compositing_manager_available;
1798
+}
1799
+
1800
+Display* KApplication::openX11RGBADisplay() {
1801
+	KCmdLineArgs *qtargs = KCmdLineArgs::parsedArgs("qt");
1802
+	char *displayname = 0;
1803
+	if ( qtargs->isSet("display"))
1804
+		displayname = qtargs->getOption( "display" ).data();
1805
+		
1806
+	Display *dpy = XOpenDisplay( displayname );
1807
+	return dpy;
1808
+}
1809
+
1810
+Qt::HANDLE KApplication::getX11RGBAVisual(Display *dpy) {
1811
+	getX11RGBAInformation(dpy);
1812
+	return argb_x11_visual;
1813
+}
1814
+
1815
+Qt::HANDLE KApplication::getX11RGBAColormap(Display *dpy) {
1816
+	getX11RGBAInformation(dpy);
1817
+	return argb_x11_colormap;
1818
+}
1819
+
1820
+bool KApplication::isX11CompositionAvailable() {
1821
+	return argb_visual & isCompositionManagerAvailable();
1822
+}
1823
+
1824
+void KApplication::getX11RGBAInformation(Display *dpy) {
1825
+	if ( !dpy ) {
1826
+		argb_visual = false;
1827
+		return;
1828
+	}
1829
+	
1830
+	int screen = DefaultScreen( dpy );
1831
+	Colormap colormap = 0;
1832
+	Visual *visual = 0;
1833
+	int event_base, error_base;
1834
+	
1835
+	if ( XRenderQueryExtension( dpy, &event_base, &error_base ) ) {
1836
+		int nvi;
1837
+		XVisualInfo templ;
1838
+		templ.screen  = screen;
1839
+		templ.depth   = 32;
1840
+		templ.c_class = TrueColor;
1841
+		XVisualInfo *xvi = XGetVisualInfo( dpy, VisualScreenMask | VisualDepthMask
1842
+				| VisualClassMask, &templ, &nvi );
1843
+		
1844
+		for ( int i = 0; i < nvi; i++ ) {
1845
+			XRenderPictFormat *format = XRenderFindVisualFormat( dpy, xvi[i].visual );
1846
+			if ( format->type == PictTypeDirect && format->direct.alphaMask ) {
1847
+				visual = xvi[i].visual;
1848
+				colormap = XCreateColormap( dpy, RootWindow( dpy, screen ), visual, AllocNone );
1849
+				kdDebug() << "found visual with alpha support" << endl;
1850
+				argb_visual = true;
1851
+				break;
1852
+			}
1853
+		}
1854
+	}
1855
+	
1856
+	if( argb_visual ) {
1857
+		argb_x11_visual = Qt::HANDLE( visual );
1858
+		argb_x11_colormap = Qt::HANDLE( colormap );
1859
+		argb_visual = true;
1860
+		return;
1861
+	}
1862
+	argb_visual = false;
1863
+	return;
1864
+}
1865
+
1866
+KApplication KApplication::KARGBApplicationObject( bool allowStyles ) {
1867
+	KCmdLineArgs *qtargs = KCmdLineArgs::parsedArgs("qt");
1868
+	bool argb_visual_available = false;
1869
+	char *display = 0;
1870
+	if ( qtargs->isSet("display"))
1871
+		display = qtargs->getOption( "display" ).data();
1872
+	
1873
+	Display *dpy = XOpenDisplay( display );
1874
+	if ( !dpy ) {
1875
+		kdError() << "cannot connect to X server " << display << endl;
1876
+		exit( 1 );
1877
+	}
1878
+	
1879
+	int screen = DefaultScreen( dpy );
1880
+	Colormap colormap = 0;
1881
+	Visual *visual = 0;
1882
+	int event_base, error_base;
1883
+	
1884
+	if ( XRenderQueryExtension( dpy, &event_base, &error_base ) ) {
1885
+		int nvi;
1886
+		XVisualInfo templ;
1887
+		templ.screen  = screen;
1888
+		templ.depth   = 32;
1889
+		templ.c_class = TrueColor;
1890
+		XVisualInfo *xvi = XGetVisualInfo( dpy, VisualScreenMask | VisualDepthMask
1891
+				| VisualClassMask, &templ, &nvi );
1892
+		
1893
+		for ( int i = 0; i < nvi; i++ ) {
1894
+			XRenderPictFormat *format = XRenderFindVisualFormat( dpy, xvi[i].visual );
1895
+			if ( format->type == PictTypeDirect && format->direct.alphaMask ) {
1896
+				visual = xvi[i].visual;
1897
+				colormap = XCreateColormap( dpy, RootWindow( dpy, screen ), visual, AllocNone );
1898
+				kdDebug() << "found visual with alpha support" << endl;
1899
+				argb_visual_available = true;
1900
+				break;
1901
+			}
1902
+		}
1903
+	}
1904
+	
1905
+	if( argb_visual_available ) {
1906
+		return KApplication( dpy, Qt::HANDLE( visual ), Qt::HANDLE( colormap ), allowStyles );
1907
+	}
1908
+	else {
1909
+		return KApplication(allowStyles, true);
1910
+	}
1911
+}
1912
+#else
1913
+Qt::HANDLE KApplication::getX11RGBAVisual(char *display) {
1914
+	return 0;
1915
+}
1916
+
1917
+Qt::HANDLE KApplication::getX11RGBAColormap(char *display) {
1918
+	return 0;
1919
+}
1721 1920
 
1921
+bool KApplication::isX11CompositionAvailable() {
1922
+	return false;
1923
+}
1924
+
1925
+KApplication KApplication::KARGBApplication( bool allowStyles ) {
1926
+	return KApplication::KApplication(allowStyles, true);
1927
+}
1928
+#endif
1722 1929
 
1723 1930
 static bool kapp_block_user_input = false;
1724 1931
 

+ 87
- 2
kdecore/kapplication.h View File

@@ -48,6 +48,8 @@ class KSessionManaged;
48 48
 class KStyle;
49 49
 class KURL;
50 50
 
51
+#define COMPOSITE	// [FIXME] Autodetect composition support
52
+
51 53
 #define kapp KApplication::kApplication()
52 54
 
53 55
 class KApplicationPrivate;
@@ -113,6 +115,10 @@ public:
113 115
    * This constructor takes aboutData and command line
114 116
    *  arguments from KCmdLineArgs.
115 117
    *
118
+   *  If ARGB (transparent) widgets are to be used in your application,
119
+   *  please use KARGBApplication(new object name) or
120
+   *  KARGBApplication(new object name, allow_styles) instead of KApplication(...).
121
+   *
116 122
    * @param allowStyles Set to false to disable the loading on plugin based
117 123
    * styles. This is only useful to applications that do not display a GUI
118 124
    * normally. If you do create an application with @p allowStyles set to false
@@ -860,15 +866,88 @@ public:
860 866
    */
861 867
   TQString checkRecoverFile( const TQString& pFilename, bool& bRecover ) const;
862 868
 
863
-#ifdef Q_WS_X11
869
+#if defined(Q_WS_X11) && defined(COMPOSITE)
864 870
   /**
871
+   * @internal
865 872
    * Get the X11 display
866 873
    * @return the X11 Display
867 874
    */
868
-  Display *getDisplay() { return display; }
875
+   Display *getDisplay() { return display; }
876
+
877
+  /**
878
+   * @internal
879
+   * Gets X11 composition information
880
+   */
881
+   void getX11RGBAInformation(Display *dpy);
882
+
883
+  /**
884
+   * Gets the availability of a composition manager such as kompmgr
885
+   * Note that at least one application must have called detectCompositionManagerAvailable
886
+   * while the current X display was active in order for this method to return valid results.
887
+   * @see detectCompositionManagerAvailable()
888
+   * @return whether the composition manager is enabled
889
+   */
890
+   static bool isCompositionManagerAvailable();
891
+
892
+  /**
893
+   * Detects the availability of a composition manager such as kompmgr
894
+   * Note that calling this method will probably cause the screen to flicker.
895
+   * @see isCompositionManagerAvailable()
896
+   * @param force_available If set, force TDE to assume a composition manager is available
897
+   * @return whether the composition manager is enabled
898
+   */
899
+   bool detectCompositionManagerAvailable(bool force_available=false);
900
+
901
+  /**
902
+   * @internal
903
+   * Opens an X11 display and returns the handle to it
904
+   * @return the X11 display handle
905
+   */
906
+   Display *openX11RGBADisplay();
869 907
 #endif
870 908
 
871 909
   /**
910
+   * @internal
911
+   * Creates a default KApplication with transparency support
912
+   * (if available)
913
+   */
914
+   static KApplication KARGBApplicationObject( bool allowStyles=true );
915
+
916
+   #define KARGBApplication(objectname, ...) const KApplication &__kapplication_internal_app = KApplication::KARGBApplicationObject(__VA_ARGS__); KApplication &objectname = const_cast<KApplication&>(__kapplication_internal_app);
917
+
918
+  /**
919
+   * Returns the X11 display visual
920
+   *
921
+   * @return A pointer to the X11 display visual
922
+   */
923
+   Qt::HANDLE getX11RGBAVisual(Display *dpy);
924
+
925
+  /**
926
+   * Returns the X11 display colormap
927
+   *
928
+   * @return An X11 display colormap object
929
+   */
930
+   Qt::HANDLE getX11RGBAColormap(Display *dpy);
931
+
932
+  /**
933
+   * Returns whether or not X11 composition is available
934
+   * 
935
+   * You must first call getX11RGBAInformation()
936
+   * 
937
+   * Note that getX11RGBAInformation() has already
938
+   * been called if you used the default KApplication
939
+   * constructor.
940
+   *
941
+   * Additionally, at least one application must have called
942
+   * detectCompositionManagerAvailable while the current X 
943
+   * display was active in order for this method to return
944
+   * valid results.
945
+   *
946
+   * @return true if composition is available
947
+   */
948
+   bool isX11CompositionAvailable();
949
+
950
+  /**
872 951
    * Enables style plugins.
873 952
    *
874 953
    * This is useful only to applications that normally
@@ -1201,6 +1280,12 @@ private:
1201 1280
   void dcopClientPostInit();
1202 1281
   void initUrlActionRestrictions();
1203 1282
 
1283
+  bool argb_visual;
1284
+#if defined(Q_WS_X11) && defined(COMPOSITE)
1285
+  Qt::HANDLE argb_x11_visual;
1286
+  Qt::HANDLE argb_x11_colormap;
1287
+#endif
1288
+
1204 1289
 public:
1205 1290
   /**
1206 1291
    * @internal

Loading…
Cancel
Save