Blame SOURCES/0080-net-wm-sync-request-2.patch

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