27b5108
qt-bugs@ issue : none
27b5108
bugs.kde.org number : none
27b5108
applied: no
27b5108
author: Lubos Lunak <l.lunak@kde.org>
27b5108
27b5108
Support for _NET_WM_SYNC_REQUEST - allows the WM to find out when the app
27b5108
finished one redraw - less flicker during resize and with compositing
27b5108
also when opening a window.
27b5108
27b5108
--- src/kernel/qwidget.h.sav	2007-06-22 14:14:05.000000000 +0200
27b5108
+++ src/kernel/qwidget.h	2007-06-23 11:53:39.000000000 +0200
27b5108
@@ -586,6 +586,14 @@ private:
27b5108
     void	 destroyInputContext();
27b5108
     void	 focusInputContext();
27b5108
     void	 checkChildrenDnd();
27b5108
+
27b5108
+#ifndef QT_NO_XSYNC
27b5108
+    void        createSyncCounter();
27b5108
+    void        destroySyncCounter();
27b5108
+    void        incrementSyncCounter();
27b5108
+    void        handleSyncRequest( void* ev );
27b5108
+#endif
27b5108
+
27b5108
 #elif defined(Q_WS_MAC)
27b5108
     uint    own_id : 1, macDropEnabled : 1;
27b5108
     EventHandlerRef window_event;
27b5108
@@ -962,8 +970,12 @@ struct Q_EXPORT QTLWExtra {
27b5108
     uint     uspos : 1;				// User defined position
27b5108
     uint     ussize : 1;			// User defined size
27b5108
 #if defined(QT_NO_IM_EXTENSIONS)
27b5108
     void    *xic;				// Input Context
27b5108
 #endif
27b5108
+#ifndef QT_NO_XSYNC
27b5108
+    ulong    syncCounter;
27b5108
+    uint     syncRequestValue[2];
27b5108
+#endif
27b5108
 #endif
27b5108
 #if defined(Q_WS_MAC)
27b5108
     WindowGroupRef group;
27b5108
--- src/kernel/qt_x11_p.h.sav	2007-02-23 14:01:18.000000000 +0100
27b5108
+++ src/kernel/qt_x11_p.h	2007-06-23 11:53:39.000000000 +0200
27b5108
@@ -174,6 +174,11 @@ extern "C" {
27b5108
 #endif // QT_NO_XRENDER
27b5108
 
27b5108
 
27b5108
+#ifndef QT_NO_XSYNC
27b5108
+#  include <X11/extensions/sync.h>
27b5108
+#endif // QT_NO_XSYNC
27b5108
+
27b5108
+
27b5108
 #ifndef QT_NO_XKB
27b5108
 #  include <X11/XKBlib.h>
27b5108
 #endif // QT_NO_XKB
27b5108
--- src/kernel/qwidget_x11.cpp.sav	2007-04-16 13:47:26.000000000 +0200
27b5108
+++ src/kernel/qwidget_x11.cpp	2007-06-23 19:48:44.000000000 +0200
27b5108
@@ -87,6 +87,12 @@ static QWidget *keyboardGrb = 0;
27b5108
 extern Time qt_x_time;
27b5108
 extern Time qt_x_user_time;
27b5108
 
27b5108
+#ifndef QT_NO_XSYNC
27b5108
+extern Atom qt_net_wm_sync_request_counter;
27b5108
+extern Atom qt_net_wm_sync_request;
27b5108
+extern bool qt_use_xsync;
27b5108
+#endif
27b5108
+
27b5108
 // defined in qfont_x11.cpp
27b5108
 extern bool qt_has_xft;
27b5108
 
27b5108
@@ -595,11 +601,14 @@ void QWidget::create( WId window, bool i
27b5108
 
27b5108
 	XResizeWindow( dpy, id, crect.width(), crect.height() );
27b5108
 	XStoreName( dpy, id, qAppName() );
27b5108
-	Atom protocols[4];
27b5108
+	Atom protocols[5];
27b5108
 	int n = 0;
27b5108
 	protocols[n++] = qt_wm_delete_window;	// support del window protocol
27b5108
 	protocols[n++] = qt_wm_take_focus;	// support take focus window protocol
27b5108
 	protocols[n++] = qt_net_wm_ping;	// support _NET_WM_PING protocol
27b5108
+#ifndef QT_NO_XSYNC
27b5108
+	protocols[n++] = qt_net_wm_sync_request;// support the _NET_WM_SYNC_REQUEST protocol
27b5108
+#endif
27b5108
 	if ( testWFlags( WStyle_ContextHelp ) )
27b5108
 	    protocols[n++] = qt_net_wm_context_help;
27b5108
 	XSetWMProtocols( dpy, id, protocols, n );
27b5108
@@ -625,6 +634,14 @@ void QWidget::create( WId window, bool i
27b5108
 	XChangeProperty(dpy, id, qt_net_wm_pid, XA_CARDINAL, 32, PropModeReplace,
27b5108
 			(unsigned char *) &curr_pid, 1);
27b5108
 
27b5108
+#ifndef QT_NO_XSYNC
27b5108
+        // set _NET_WM_SYNC_COUNTER
27b5108
+        createSyncCounter();
27b5108
+        long counterVal = topData()->syncCounter;
27b5108
+        XChangeProperty( dpy, id, qt_net_wm_sync_request_counter, XA_CARDINAL, 32, PropModeReplace,
27b5108
+                         (unsigned char*) &counterVal, 1);
27b5108
+#endif
27b5108
+
27b5108
 	// when we create a toplevel widget, the frame strut should be dirty
27b5108
 	fstrut_dirty = 1;
27b5108
 
27b5108
@@ -720,6 +737,9 @@ void QWidget::destroy( bool destroyWindo
27b5108
 	    if ( destroyWindow )
27b5108
 		qt_XDestroyWindow( this, x11Display(), winid );
27b5108
 	}
27b5108
+#ifndef QT_NO_XSYNC
27b5108
+        destroySyncCounter();
27b5108
+#endif
27b5108
 	setWinId( 0 );
27b5108
 
27b5108
 	extern void qPRCleanup( QWidget *widget ); // from qapplication_x11.cpp
27b5108
@@ -769,6 +789,10 @@ void QWidget::reparentSys( QWidget *pare
27b5108
         destroyInputContext();
27b5108
     }
27b5108
 
27b5108
+#ifndef QT_NO_XSYNC
27b5108
+    destroySyncCounter();
27b5108
+#endif
27b5108
+
27b5108
     if ( isTopLevel() || !parent ) // we are toplevel, or reparenting to toplevel
27b5108
         topData()->parentWinId = 0;
27b5108
 
27b5108
@@ -2456,8 +2480,13 @@ void QWidget::createTLSysExtra()
27b5108
 {
27b5108
 #if defined(QT_NO_IM_EXTENSIONS)
27b5108
     // created lazily
27b5108
     extra->topextra->xic = 0;
27b5108
 #endif
27b5108
+#ifndef QT_NO_XSYNC
27b5108
+    extra->topextra->syncCounter = 0;
27b5108
+    extra->topextra->syncRequestValue[0] = 0;
27b5108
+    extra->topextra->syncRequestValue[1] = 0;
27b5108
+#endif
27b5108
 }
27b5108
 
27b5108
 void QWidget::deleteTLSysExtra()
27b5108
@@ -2501,6 +2530,51 @@ void QWidget::checkChildrenDnd()
27b5108
     }
27b5108
 }
27b5108
 
27b5108
+
27b5108
+#ifndef QT_NO_XSYNC
27b5108
+// create a window's XSyncCounter
27b5108
+void QWidget::createSyncCounter()
27b5108
+{
27b5108
+    if( !qt_use_xsync || !isTopLevel() || topData()->syncCounter )
27b5108
+        return;
27b5108
+    XSyncValue zero;
27b5108
+    XSyncIntToValue( &zero, 0 );
27b5108
+    topData()->syncCounter = XSyncCreateCounter( x11Display(), zero );
27b5108
+}
27b5108
+
27b5108
+// destroy a window's XSyncCounter
27b5108
+void QWidget::destroySyncCounter()
27b5108
+{
27b5108
+    if( !qt_use_xsync || !extra || !extra->topextra
27b5108
+        || !extra->topextra->syncCounter )
27b5108
+        return;
27b5108
+    XSyncDestroyCounter( x11Display(), extra->topextra->syncCounter );
27b5108
+    extra->topextra->syncCounter = 0;
27b5108
+}
27b5108
+
27b5108
+// increment a window's XSyncCounter
27b5108
+void QWidget::incrementSyncCounter()
27b5108
+{
27b5108
+    if( qt_use_xsync && topData()->syncCounter &&
27b5108
+        !(topData()->syncRequestValue[0] == 0 &&
27b5108
+         topData()->syncRequestValue[1] == 0) ) {
27b5108
+        XSyncValue val;
27b5108
+        XSyncIntsToValue( &val, topData()->syncRequestValue[ 0 ], topData()->syncRequestValue[ 1 ] );
27b5108
+        XSyncSetCounter( x11Display(), topData()->syncCounter, val );
27b5108
+        topData()->syncRequestValue[0] = topData()->syncRequestValue[1] = 0;
27b5108
+    }
27b5108
+}
27b5108
+
27b5108
+// handle _NET_WM_SYNC_REQUEST
27b5108
+void QWidget::handleSyncRequest( void* ev )
27b5108
+{
27b5108
+    XEvent* xev = (XEvent*)ev;
27b5108
+    topData()->syncRequestValue[ 0 ] = xev->xclient.data.l[ 2 ];
27b5108
+    topData()->syncRequestValue[ 1 ] = xev->xclient.data.l[ 3 ];
27b5108
+}
27b5108
+#endif  // QT_NO_XSYNC
27b5108
+
27b5108
+
27b5108
 /*!
27b5108
     \property QWidget::acceptDrops
27b5108
     \brief whether drop events are enabled for this widget
27b5108
--- src/kernel/qapplication_x11.cpp.sav	2007-04-16 13:47:26.000000000 +0200
27b5108
+++ src/kernel/qapplication_x11.cpp	2007-06-23 19:49:15.000000000 +0200
27b5108
@@ -285,6 +285,11 @@ Atom		*qt_net_supported_list	= 0;
27b5108
 Window		*qt_net_virtual_root_list	= 0;
27b5108
 
27b5108
 
27b5108
+// X11 SYNC support
27b5108
+#ifndef QT_NO_XSYNC
27b5108
+Atom		qt_net_wm_sync_request_counter	= 0;
27b5108
+Atom		qt_net_wm_sync_request     	= 0;
27b5108
+#endif
27b5108
 
27b5108
 // client leader window
27b5108
 Window qt_x11_wm_client_leader = 0;
27b5108
@@ -309,6 +314,13 @@ static int xrandr_eventbase;
27b5108
 // Display
27b5108
 Q_EXPORT bool qt_use_xrender = FALSE;
27b5108
 
27b5108
+#ifndef QT_NO_XSYNC
27b5108
+// True if SYNC extension exists on the connected display
27b5108
+bool qt_use_xsync = FALSE;
27b5108
+static int xsync_eventbase;
27b5108
+static int xsync_errorbase;
27b5108
+#endif
27b5108
+
27b5108
 // modifier masks for alt/meta - detected when the application starts
27b5108
 static long qt_alt_mask = 0;
27b5108
 static long qt_meta_mask = 0;
27b5108
@@ -1938,6 +1950,11 @@ void qt_init_internal( int *argcptr, cha
27b5108
 	qt_x11_intern_atom( "UTF8_STRING", &qt_utf8_string );
27b5108
         qt_x11_intern_atom( "_SGI_DESKS_MANAGER", &qt_sgi_desks_manager );
27b5108
 
27b5108
+#ifndef QT_NO_XSYNC
27b5108
+	qt_x11_intern_atom( "_NET_WM_SYNC_REQUEST_COUNTER", &qt_net_wm_sync_request_counter );
27b5108
+	qt_x11_intern_atom( "_NET_WM_SYNC_REQUEST", &qt_net_wm_sync_request );
27b5108
+#endif
27b5108
+
27b5108
 	qt_xdnd_setup();
27b5108
 	qt_x11_motifdnd_init();
27b5108
 
27b5108
@@ -1974,6 +1991,15 @@ void qt_init_internal( int *argcptr, cha
27b5108
 	}
27b5108
 #endif // QT_NO_XRENDER
27b5108
 
27b5108
+#ifndef QT_NO_XSYNC
27b5108
+	// Try to initialize SYNC extension on the connected display
27b5108
+	int xsync_major, xsync_minor;
27b5108
+	if ( XSyncQueryExtension( appDpy, &xsync_eventbase, &xsync_errorbase ) && 
27b5108
+	     XSyncInitialize( appDpy, &xsync_major,  &xsync_minor ) ) {
27b5108
+	     qt_use_xsync = TRUE;
27b5108
+	}
27b5108
+#endif 
27b5108
+
27b5108
 #ifndef QT_NO_XKB
27b5108
 	// If XKB is detected, set the GrabsUseXKBState option so input method
27b5108
 	// compositions continue to work (ie. deadkeys)
27b5108
@@ -3141,6 +3167,10 @@ int QApplication::x11ClientMessage(QWidg
27b5108
 		    XSendEvent( event->xclient.display, event->xclient.window,
27b5108
 				False, SubstructureNotifyMask|SubstructureRedirectMask, event );
27b5108
 		}
27b5108
+#ifndef QT_NO_XSYNC
27b5108
+	    } else if (a == qt_net_wm_sync_request ) {
27b5108
+		    widget->handleSyncRequest( event );
27b5108
+#endif
27b5108
 	    }
27b5108
 	} else if ( event->xclient.message_type == qt_qt_scrolldone ) {
27b5108
 	    widget->translateScrollDoneEvent(event);
27b5108
@@ -5681,6 +5711,21 @@ bool QETWidget::translateScrollDoneEvent
27b5108
     return FALSE;
27b5108
 }
27b5108
 
27b5108
+#if defined(Q_C_CALLBACKS)
27b5108
+extern "C" {
27b5108
+#endif
27b5108
+#ifndef QT_NO_XSYNC
27b5108
+static Bool qt_net_wm_sync_request_scanner(Display*, XEvent* event, XPointer arg)
27b5108
+{
27b5108
+    return (event->type == ClientMessage && event->xclient.window == *(Window*)arg
27b5108
+        && event->xclient.message_type == qt_wm_protocols
27b5108
+        && event->xclient.data.l[ 0 ] == qt_net_wm_sync_request );
27b5108
+}
27b5108
+#endif
27b5108
+
27b5108
+#if defined(Q_C_CALLBACKS)
27b5108
+}
27b5108
+#endif
27b5108
 
27b5108
 //
27b5108
 // ConfigureNotify (window move and resize) event translation
27b5108
@@ -5712,6 +5757,7 @@ bool QETWidget::translateConfigEvent( co
27b5108
         if (! extra || extra->compress_events) {
27b5108
             // ConfigureNotify compression for faster opaque resizing
27b5108
             XEvent otherEvent;
27b5108
+            int compressed_configs = 0;
27b5108
             while ( XCheckTypedWindowEvent( x11Display(), winId(), ConfigureNotify,
27b5108
                                             &otherEvent ) ) {
27b5108
                 if ( qt_x11EventFilter( &otherEvent ) )
27b5108
@@ -5732,7 +5778,18 @@ bool QETWidget::translateConfigEvent( co
27b5108
                     newCPos.ry() = otherEvent.xconfigure.y +
27b5108
                                    otherEvent.xconfigure.border_width;
27b5108
                 }
27b5108
+                ++compressed_configs;
27b5108
+            }
27b5108
+#ifndef QT_NO_XSYNC
27b5108
+            // _NET_WM_SYNC_REQUEST compression 
27b5108
+            Window wid = winId();
27b5108
+            while ( compressed_configs &&
27b5108
+                    XCheckIfEvent( x11Display(), &otherEvent,
27b5108
+                    qt_net_wm_sync_request_scanner, (XPointer)&wid ) ) {
27b5108
+                handleSyncRequest( (void*)&otherEvent );
27b5108
+                --compressed_configs;
27b5108
             }
27b5108
+#endif
27b5108
         }
27b5108
 
27b5108
 	QRect cr ( geometry() );
27b5108
@@ -5786,6 +5843,8 @@ bool QETWidget::translateConfigEvent( co
27b5108
 	repaint( !testWFlags(WResizeNoErase) || transbg );
27b5108
     }
27b5108
 
27b5108
+    incrementSyncCounter();
27b5108
+
27b5108
     return TRUE;
27b5108
 }
27b5108