aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Gabriel <mike.gabriel@das-netzwerkteam.de>2015-02-13 14:14:26 +0100
committerMike Gabriel <mike.gabriel@das-netzwerkteam.de>2015-02-13 14:18:50 +0100
commit1e5ee575d4912665dd2356681f0827d5229fa1f5 (patch)
tree31db7768b2686507a5f9ea2ffa03d9c62ccf78c9
parent1fd8551f1632efbc2655c9293087bba08cf2f0c9 (diff)
downloadnx-libs-1e5ee575d4912665dd2356681f0827d5229fa1f5.tar.gz
nx-libs-1e5ee575d4912665dd2356681f0827d5229fa1f5.tar.bz2
nx-libs-1e5ee575d4912665dd2356681f0827d5229fa1f5.zip
nx-X11 vs. X.Org 6.9 patches for further studying / documentation
NoMachine kept all original X.Org 6.9 files in the nx-X11 source tree. These files have been removed in Feb 2015 during a major code cleanup. For later studying we provide all diffs of the changes that NoMachine employed on the original X.Org X11 code tree in the doc/nx-X11_vs_XOrg69_patches folder.
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/AuRead.c.NX.patch62
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/CHANGELOG.NX.patch1088
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/ChkIfEv.c.NX.patch59
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/ConnDis.c.NX.patch319
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/Glyph.c.NX.patch547
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/IfEvent.c.NX.patch13
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/Imakefile.NX.patch11
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/MaskEvent.c.NX.patch13
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/NXdamage.c.NX.patch138
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/NXdispatch.c.NX.patch1036
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/NXdixfonts.c.NX.patch892
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/NXevents.c.NX.patch648
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/NXextension.c.NX.patch70
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/NXglxext.c.NX.patch118
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/NXglyph.c.NX.patch160
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/NXglyphcurs.c.NX.patch121
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/NXglyphstr.h.NX.patch59
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/NXmiexpose.c.NX.patch116
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/NXmiglyph.c.NX.patch156
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/NXmitrap.c.NX.patch65
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/NXmiwindow.c.NX.patch53
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/NXpicture.c.NX.patch615
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/NXpicturestr.h.NX.patch42
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/NXproperty.c.NX.patch358
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/NXrender.c.NX.patch948
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/NXresource.c.NX.patch426
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/NXshm.c.NX.patch373
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/NXwindow.c.NX.patch561
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/NXxvdisp.c.NX.patch266
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/NextEvent.c.NX.patch42
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/OpenDis.c.NX.patch96
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/PeekIfEv.c.NX.patch14
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/Pending.c.NX.patch30
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/WSDrawBuffer.h.NX.patch0
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/WaitFor.c.NX.patch271
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/XKBMAlloc.c.NX.patch84
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/XKBsrv.h.NX.patch14
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/Xlib.h.NX.patch30
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/XlibAsync.c.NX.patch41
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/XlibInt.c.NX.patch1165
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/Xlibint.h.NX.patch59
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/Xpoll.h.in.NX.patch67
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/Xrender.h.NX.patch39
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/Xtranssock.c.NX.patch1133
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/auth.c.NX.patch271
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/charproc.c.NX.patch40
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/cmsProp.c.NX.patch14
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/connection.c.NX.patch48
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/context.c.NX.patch103
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/cross.def.NX.patch33
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/cursor.c.NX.patch12
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/ddxKillSrv.c.NX.patch21
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/ddxLoad.c.NX.patch443
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/dixfonts.c.NX.patch86
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/dixstruct.h.NX.patch12
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/encparse.c.NX.patch22
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/fbtrap.c.NX.patch12
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/glcontextmodes.c.NX.patch10
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/host.def.NX.patch1023
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/iPAQH3600.cf.NX.patch112
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/log.c.NX.patch136
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/main.c.NX.patch42
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/oscolor.c.NX.patch214
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/panoramiXproto.h.NX.patch195
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/pixmap.c.NX.patch18
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/randr.NX.patch2704
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/randr.c.NX.patch72
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/randr.h.NX.patch144
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/randrproto.h.NX.patch658
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/registry.h.NX.patch67
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/render2.c.NX.patch11
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/render2swap.c.NX.patch11
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/renderedge.c.NX.patch10
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/rrcrtc.c.NX.patch48
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/rrdispatch.c.NX.patch15
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/rrmode.c.NX.patch39
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/rrscreen.c.NX.patch107
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/rrxinerama.c.NX.patch72
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/security.c.NX.patch315
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/select.c.NX.patch13
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/sun.cf.NX.patch50
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/sunLib.tmpl.NX.patch122
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/svr4.cf.NX.patch24
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/utils.c.NX.patch250
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/xdmcp.c.NX.patch59
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/xf86glx.c.NX.patch70
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/xkbDflts.h.NX.patch24
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/xprintf.c.NX.patch75
88 files changed, 20245 insertions, 0 deletions
diff --git a/doc/nx-X11_vs_XOrg69_patches/AuRead.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/AuRead.c.NX.patch
new file mode 100644
index 000000000..940a3fee4
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/AuRead.c.NX.patch
@@ -0,0 +1,62 @@
+--- ./nx-X11/lib/Xau/AuRead.c.X.original 2015-02-13 14:03:44.624443872 +0100
++++ ./nx-X11/lib/Xau/AuRead.c 2015-02-10 19:13:12.488735202 +0100
+@@ -32,14 +32,29 @@
+ #endif
+ #include <X11/Xauth.h>
+ #include <stdlib.h>
++#include <errno.h>
+
+ static int
+ read_short (unsigned short *shortp, FILE *file)
+ {
+ unsigned char file_short[2];
+
+- if (fread ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
+- return 0;
++ /*
++ * Added a check on EINTR to prevent the fread() call to be
++ * interrupted by any signal not blocked by OsBlockSignals().
++ */
++
++ for (;;) {
++ if (fread ((char *) file_short, (int) sizeof (file_short), 1, file) != 1) {
++ if (errno == EINTR && ferror (file)) {
++ perror ("Reading from auth file");
++ clearerr (file);
++ continue;
++ }
++ return 0;
++ }
++ break;
++ }
+ *shortp = file_short[0] * 256 + file_short[1];
+ return 1;
+ }
+@@ -58,11 +73,22 @@
+ data = malloc ((unsigned) len);
+ if (!data)
+ return 0;
+- if (fread (data, (int) sizeof (char), (int) len, file) != len) {
+- bzero (data, len);
+- free (data);
+- return 0;
+- }
++ for (;;)
++ {
++ if (fread (data, (int) sizeof (char), (int) len, file) != len)
++ {
++ if (errno == EINTR && ferror (file))
++ {
++ perror ("Reading from auth file");
++ clearerr (file);
++ continue;
++ }
++ bzero (data, len);
++ free (data);
++ return 0;
++ }
++ break;
++ }
+ }
+ *stringp = data;
+ *countp = len;
diff --git a/doc/nx-X11_vs_XOrg69_patches/CHANGELOG.NX.patch b/doc/nx-X11_vs_XOrg69_patches/CHANGELOG.NX.patch
new file mode 100644
index 000000000..085401dd9
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/CHANGELOG.NX.patch
@@ -0,0 +1,1088 @@
+--- ./nx-X11/CHANGELOG.X.original 2015-02-13 14:03:44.392448449 +0100
++++ ./nx-X11/CHANGELOG 2015-02-10 19:13:14.668653602 +0100
+@@ -0,0 +1,1085 @@
++ChangeLog:
++
++nx-X11-3.5.0-2
++
++- Fixed TR0202420. XKB utility functions wrote out of bounds.
++
++- Upgraded RandR server extension to version 1.2.
++
++nx-X11-3.5.0-1
++
++- Opened the 3.5.0 branch based on nx-X11-3.4.0-4.
++
++- Updated copyright to year 2011.
++
++nx-X11-3.4.0-4
++
++- Fixed TR06H02359. Removed compiler warnings.
++
++nx-X11-3.4.0-3
++
++- Updated copyright to year 2010.
++
++nx-X11-3.4.0-2
++
++- Fixed TR04G02208. Added a path to rgb file.
++
++nx-X11-3.4.0-1
++
++- Opened the 3.4.0 branch based on nx-X11-3.3.0-7.
++
++- Updated copyright to year 2009.
++
++nx-X11-3.3.0-7
++
++- Fixed TR08G02257. The maximum client condition was reached because
++ available fd exhausted. This bug was caused by a function in font
++ library not closing the file before a return on error breaking the
++ flow of normal execution.
++
++- Fixed TR06G02225. The implementation of Xvprintf() has been reviewed
++ to work on more platforms. Previous implementation caused a failure
++ in the build of keyboard map on some platform like Solaris 8 and 9.
++
++nx-X11-3.3.0-6
++
++- Fixed TR03G02198. Reimplemented Xvprintf() in Xserver/os to handle
++ the case in which vsnprintf returned -1.
++
++- Returning from _XSeqSyncFunction() and _XReply() if an I/O error is
++ detected.
++
++nx-X11-3.3.0-5
++
++- Fixed TR01G02163. Signals need to be blocked before the call to
++ fork() in the Popen() utility.
++
++- Fixed TR01G02164. Trapezoid data need to be validated before use.
++ This issue was the same of CVE-2007-2437.
++
++nx-X11-3.3.0-4
++
++- Enabled the code resetting the Xlib buffer if an IO error occured.
++
++nx-X11-3.3.0-3
++
++- Fixed the search path for the XKB base directory.
++
++nx-X11-3.3.0-2
++
++- Fixed TR10F02116. The X11 agent could enter an indefinite wait state
++ if connection to X display is broken and libX11 output buffer is not
++ empty.
++
++nx-X11-3.3.0-1
++
++- Opened the 3.3.0 branch based on nx-X11-3.2.0-2.
++
++nx-X11-3.2.0-2
++
++- Imported patch fixing issues from X.Org security advisory, June
++ 11th, 2008: Multiple vulnerabilities in X server extensions. CVE
++ IDs: CVE-2008-1377, CVE-2008-1379, CVE-2008-2360, CVE-2008-2361,
++ CVE-2008-2362.
++
++nx-X11-3.2.0-1
++
++- Opened the 3.2.0 branch based on nx-X11-3.1.0-6.
++
++nx-X11-3.1.0-6
++
++- Modified Xserver Imakefile to link the Xfixes library.
++
++nx-X11-3.1.0-5
++
++- Disabled the terminate action, just in case the TerminateServer
++ symbol is binded to a non default key sequence.
++
++nx-X11-3.1.0-4
++
++- Imported patch fixing issues from X.Org security advisory, January
++ 17th, 2008: Multiple vulnerabilities in the X server. CVE IDs:
++ CVE-2007-5760 CVE-2007-5958 CVE-2007-6427 CVE-2007-6428
++ CVE-2007-6429 CVE-2008-0006.
++
++nx-X11-3.1.0-3
++
++- Moved a variable definition placed in _mesa_make_current().
++
++nx-X11-3.1.0-2
++
++- Fixed TR10E01924. A crash could occur in _mesa_make_current().
++
++- Initialized after_ret variable in _XcmsGetProperty().
++
++nx-X11-3.1.0-1
++
++- Opened the 3.1.0 branch based on nx-X11-3.0.0-37.
++
++nx-X11-3.0.0-37
++
++- Changed the Xserver Imakefile to link against Xcomposite on the
++ Cygwin platform too.
++
++nx-X11-3.0.0-36
++
++- Fixed TR07E01806. Modified host.def to build GLX code with symbol
++ __GLX_ALIGN64 defined on Solaris platform.
++
++nx-X11-3.0.0-35
++
++- Flush explicitly the NX link before entering the select() in the
++ WaitForReadable() and WaitForWritable() routines.
++
++nx-X11-3.0.0-34
++
++- Changed the agent Imakefile to link to the Xcomposite library.
++
++nx-X11-3.0.0-33
++
++- Fix the NX_TRANS_WAKEUP stuff in WaitForSomething() to not over-
++ ride a valid timeout.
++
++- Check if the requesting client is gone in the XFixes functions
++ sending the cursor events.
++
++nx-X11-3.0.0-32
++
++- Define DDXOSVERRORF and DDXOSFATALERROR symbols on Sun.
++
++- Changed the copyright attribution from Medialogic to NoMachine.
++
++nx-X11-3.0.0-31
++
++- Make SmartScheduleStopTimer() visible outside Xserver/os/utils.c
++ so that it can be called by the agent. Export the declaration in
++ dixstruct.h.
++
++nx-X11-3.0.0-30
++
++- The OsVendorVErrorFFatal flag is set to 1 if the function pointed
++ by OsVendorVErrorFProc is called due to a fatal error.
++
++- Give the possibility to the agent to redirect the standard error
++ during a Popen() or a System() by setting the OsVendorStartRedir-
++ ectErrorFProc and OsVendorEndRedirectErrorFProc function pointers.
++
++nx-X11-3.0.0-29
++
++- Changed the default message printed on a fatal server error. The
++ new message is:
++
++ Error: Aborting session with 'Error text...'.
++
++- Hacked LogVWrite() to force all fatal error messages to have an
++ uppercase initial. Also remove the trailing newline and the full-
++ stop, if present.
++
++nx-X11-3.0.0-28
++
++- Corrected the typos in the ChangeLog.
++
++nx-X11-3.0.0-27
++
++- Fixed the cleanup of the X_RenderCompositeText16 padding bytes.
++
++- More code cleanup in the NX changes to the Xrender library.
++
++- Changed host.def to build the freetype and fontconfig libraries
++ if the agent server is also built. Freetype is built as a shared
++ library: this avoids the link error on 64 bit platforms.
++
++nx-X11-3.0.0-26
++
++- Applied the following security patches, from the X.Org security
++ advisory, April 3rd, 2007 "Multiple vulnerability in X server,
++ libXfont and libX11":
++
++ xorg-xserver-1.2.0-xcmisc.diff
++ xorg-libXfont-1.2.7-bdf-fontdir.diff
++ xorg-libX11-1.1.1-xinitimage.diff
++
++nx-X11-3.0.0-25
++
++- Added the missing *.X.original file for ChkIfEv.c and Xlib.h.
++
++nx-X11-3.0.0-24
++
++- Changed Xrender to clean up the padding bytes in XRenderComposite-
++ Text functions.
++
++- Added function XRenderCleanGlyphs() cleaning the padding bytes in
++ the data section of RenderAddGlyphs requests.
++
++nx-X11-3.0.0-23
++
++- Removed the additional parameter from the call to NXTransFlush()
++ in _XReply().
++
++- Call NXTransExit() on AbortServer() (called by FatalError()) to
++ give the proxy a chance to shut down the NX transport.
++
++nx-X11-3.0.0-22
++
++- Moved the replacement of XCheckIfEvent() ChkIfEv.c with the name
++ XCheckIfEventNoFlush().
++
++nx-X11-3.0.0-21
++
++- Set BUFSIZE to 8192 bytes. While the output buffer size can be
++ configured by setting the XLIBBUFFERSIZE in the environment (see
++ OpenDis.c), this constant is still used when reading from the
++ socket.
++
++nx-X11-3.0.0-20
++
++- If set, the handler pointed by _NXDisplayWriteFunction is called
++ after that more data is written to the display connection.
++
++nx-X11-3.0.0-19
++
++- Added a RejectWellKnownSockets() stub to make possible to compile
++ the agent when the NX transport is disabled.
++
++- Added more useful logs to _XWaitForWritable().
++
++nx-X11-3.0.0-18
++
++- Changed Imakefile of X11 and Xserver in order to build nxcompshad
++ just before the NX agent server.
++
++- Changed Imakefile in Xserver to add NXdamage.o to NXAGENTOBJS.
++
++nx-X11-3.0.0-17
++
++- Changed host.def in order to build Xdamage and Xrandr libraries.
++
++- Changed host.def in order not to build NXWin.
++
++nx-X11-3.0.0-16
++
++- Changed host.def in order to build Xtst as a shared library.
++
++nx-X11-3.0.0-15
++
++- Changes to comply with nxcompshad library.
++
++- Changed configuration to statically build Xtst library.
++
++- Restored parser directory under Xserver/hw/xfree86.
++
++nx-X11-3.0.0-14
++
++- Changed the LICENSE file to state that the software is only made
++ available under the version 2 of the GPL.
++
++- Added file COPYING.
++
++- In nx-X11/programs and nx-X11/programs/Xserver/hw/xfree86, removed
++ files and directories not needed to build servers.
++
++nx-X11-3.0.0-13
++
++- Changes aimed to link servers with static versions of Xdmcp and Xau
++ libraries.
++
++nx-X11-3.0.0-12
++
++- Added references to implented FR in the ChangeLog.
++
++- Removed nx-X11/fonts and nx-X11/doc directories. They are not needed
++ for building the NX components.
++
++nx-X11-3.0.0-11
++
++- Updated the copyright notices to year 2007.
++
++nx-X11-3.0.0-10
++
++- Applied the following security patches:
++
++ x11r6.9.0-cidfonts.diff
++ x11r6.9.0-dbe-render.diff
++ x11r6.9.0-geteuid.diff
++ x11r6.9.0-mitri.diff
++ x11r6.9.0-setuid.diff
++
++nx-X11-3.0.0-9
++
++- Merged the NX changes to X11 with the X11R6.9.0 version of X.org.
++
++nx-X11-3.0.0-8
++
++- Changes to build Xshadow library when building X11.
++
++- Changes to Xserver Imakefile to link Xshadow library.
++
++- Changes to host.def in order to build on old distributions.
++
++nx-X11-3.0.0-7
++
++- Imported changes up to nx-X11-2.1.0-2
++
++- Fixed TR08D01485. Updated rgb file paths validation in order to
++ support Ubuntu distribution.
++
++- Added Xtst to libraries to be linked by nxagent.
++
++- Changed Xpm Imakefile to build a shared library on Solaris.
++
++- Fixed build error on Solaris in xtrans.
++
++- Changed host.def not to build Xnest server.
++
++- Changed Xserver Imakefile to link nxaccess library.
++
++nx-X11-3.0.0-6
++
++- Added the path of nxaccess library to the server link command.
++
++nx-X11-3.0.0-5
++
++- Implemented FR10C01079 and FR10C01080. The merge of NX changes to
++ the X.org code is complete.
++
++- Merged changes in config/cf. The NX-*.def files have been dismissed.
++ Main platform dependent configurations have been moved to host.def.
++
++- Removed *.reference files from config/cf.
++
++- Fixed compilation for Cygwin platform.
++
++nx-X11-3.0.0-4
++
++- Imported all changes up to nx-X11-2.0.0-32.
++
++- Cleaned up lib/zlib directory.
++
++- Added missing file programs/Xserver/os/utils.c.NX.original.
++
++- Updated the copyright notice to year 2006.
++
++- The pointer to the display buffer is reset after an I/O error.
++ This prevents leaving the buffer in an inconsistent state if the
++ error occurs inside _XFlush().
++
++- Removed the modifications to the Xrender library. The cleanup of
++ the padding bytes is now performed by the NX transport.
++
++- NX uses the updated ZLIB from its build tree, so Imake.tmpl will
++ now assume that the platform as ZLIB unless otherwise stated.
++
++- The path of the SecurityPolicy file is searched and validated at
++ runtime.
++
++- Added the _X11TransSocketProxyConnInfo() function to Xtranssock.c
++ It returns the pointer to the XtransConnInfo private, if it is a
++ valid _NXProxyConnInfo structure.
++
++- The above function is used by OpenDis.c to detect if the NX trans-
++ port was requested on the display and avoid spurious error messa-
++ ges in the case of a connection failure.
++
++- Added NXmiwindow.o to the NXAGENTOBJS in the Xserver's Imakefile
++ and imported NXmiwindow.c in nxagent. This allows us to check the
++ pointer to the pOldClip region in miSetShape() before going on
++ freeing it.
++
++- The path of the XKB base directory and of the xkbcomp comand is
++ validated at runtime.
++
++- Also added a check to verify the validity of the rgb file path.
++
++- Added NXresource.o to NXAGENTOBJS in the Imakefile of nxagent. We
++ need this to a assign a resource to the pixmaps and other server
++ objects which need to be enumerated at reconnection. Some objects,
++ being created by the X server and not by the clients, don't pass
++ through the resource assignment process operated by the dix. To
++ ensure that all objects get a resource, we add a resource at the
++ time the object is created and temporarily assign the resource to
++ the server client. If the dix later assigns the resource to a va-
++ lid client, the resource is removed from the server client's list.
++
++- The display block handler registered by the client is called in
++ WaitForReadable() and WaitForWritable() before every select(),
++ not only upon entering the function. The reason is that more
++ data can be possibly produced for the NX link by the proxy it-
++ self and, when setting the flush policy to deferred, the client
++ may not have the chance of flushing the NX link.
++
++- Fixed a bug in XkbUseExtension() that caused Xlib to query the
++ presence of the XKEYBOARD extension multiple times. This partial-
++ ly implents the FR01D01275. The complete implementation required
++ modifications to the X11 agent, implemented in nxagent-2.0.0-33.
++
++- Updated to comply with the new NXTransFlush() interface.
++
++- Both nxwin and nxagent now read the X authority file by using an
++ fopen() instead of the system command 'cat'.
++
++- Removed NXmiwindow.o from the NXAGENTOBJ list. The agent will now
++ use the original miwindow.c.
++
++- Added some additional logs in Xtranssock.c to follow the creation
++ and removal of the X server's Unix listener.
++
++- Avoided the sleep of 5 seconds forced by Xtransutil.c if the dir-
++ ectory where the Unix listener is created is not owned by root.
++ This sleep is not executed on Cygwin (where the X socket can be
++ hardly owned by root) but may delay the startup of the agent if
++ the user chose a different NX_TEMP directory. Furthermore, it is
++ unclear what real benefits such sleeps are intended to bring to
++ the security of the X server. This can be controlled by defining
++ the NX_TRANS_SLEEP directive in Xserver/os/Imakefile.
++
++- Added NXmiexpose.o to the NXAGENTOBJ.
++
++- Ensured that _X11TransSocketCloseConnInfo() now initiates the NX
++ shutdown by calling NXTransClose().
++
++- Corrected a misplaced #else that made SocketUNIXConnect() skip a
++ block if the connection was not to the NX transport.
++
++- Updated to comply with the new NX function prototypes introduced
++ in nxcomp-2.0.0-31.
++
++- Moved the most important Xtranssock.c modifications into separate
++ functions.
++
++- Ensured that the modifications enabling the internal connections
++ to the proxy are compiled only when the TRANS_CLIENT directive is
++ defined.
++
++- Solved a bug that prevented the X11 socket to be deleted at the X
++ server shutdown. This needs further tests.
++
++- Added nxcompext to the link of nxagent, now that the dependency
++ of libX11 from nxcompext is removed.
++
++- Improved the Xtranssock routines to never loop through the array
++ of connection info.
++
++- Added a congestion flag to the connection info structure and a
++ function querying the transport and reporting if a change in the
++ congestion state has occurred. The code is currently not enabled,
++ because instead of polling the transport, we let the proxy notify
++ the changes in congestion state by using the callback. The code
++ can be used in future to extend the library, for example, by add-
++ ing some counters tracking the bandwidth usage of the socket con-
++ nection, so that we can make the congestion notifications work
++ even with a plain X11 connection.
++
++- Profiled the routines in XlibInt.c to reduce the number of calls
++ to the error predicate function provided by the client.
++
++- Fixed the nxcompext build problem that caused make World to fail.
++
++- Added a 'CONF' target to the X11 and Xext Imakefiles so that the
++ configure script is not run if the config.status exists.
++
++- Added the _NXDisplayBlockHandler hook. The function is called by
++ Xlib before blocking. The parameter says if Xlib is going to wait
++ for more input or because it needs to write to the display socket.
++ The client can use the hook to perform any internal operation that
++ may require some time to complete. The user, though, should not
++ try to read or write to the display inside the callback routine.
++
++- Removed the outdated NX_TRANS_PROCESS, NX_TRANS_THREAD and NX_TR-
++ ANS_INCLUDE defines.
++
++- Reverted the lib/Xext Imakefile to the original XF86 version and
++ moved the build of the nxcompext library among the libX11 depend-
++ encies.
++
++- Corrected the lib/X11 Imakefile so that a new build of nxcomp and
++ nxcompext is not attempted if the libraries are up-to-date.
++
++- Removed the unused display buffer and image cleanup functions.
++
++- Reverted the PutImage.c file to the original XF86 version.
++
++- Added the _NXDisplayErrorPredicate function in XlibInt.c. It is
++ actually a pointer to a function called whenever Xlib is going to
++ perform a network operation. If the function returns true, the
++ call will be aborted and Xlib will return the control to the ap-
++ plication. It is up to the application to set the XlibDisplayIO-
++ Error flag after the _NXDisplayErrorPredicate returns true. The
++ function can be used to activate additional checks, besides the
++ normal failures detected by Xlib on the display socket. For exam-
++ ple, the application can set the funciton to verify if an inter-
++ rupt was received or if any other event occurred mandating the
++ end of the session.
++
++- Modified XIfEvent(), XMaskEvent() and XPeekIfEvent() to check the
++ _NXDisplayErrorPredicate function and return immediately if the
++ function returns true.
++
++- Modified _XWaitForReadable() to never enter the loop if the dis-
++ play is broken.
++
++- Corrected a make problem on Windows that caused the nxcomp and
++ nxcompext libraries to be referred with the wrong name, with the
++ result that a new configure and make was attempted at each build
++ attempt.
++
++- Merged all the changes to os, Xext, xkb, dix.
++
++- Changed host.def to build only the agent server.
++
++- Merged the changes to Xtranssock.c
++
++nx-X11-3.0.0-3
++
++- Merged the changes to lib/X11. Restored original PutImage.c and
++ ClDisplay.c files.
++
++nx-X11-3.0.0-2
++
++- Created a directory named 'reference' to keep files that are chan-
++ ged during the development of nx-X11 since the 1.5.0-16 to 2.0.0-32
++ version. These files will be removed as long as the differences are
++ merged to the 3.0.0 version. When all differences are merged, this
++ directory will be removed.
++
++nx-X11-3.0.0-1
++
++- Opened the 3.0.0 branch based on the nx-X11-2.0.0-9. The 3.0.0
++ branch will now support the migration toward the X.org tree. Due
++ to time concerns, the 2.0.0 branch is going to be based on the
++ same nx-X11 as the 1.5.0.
++
++nx-X11-2.0.0-9
++
++- Modified the agent link arguments to explicitly include the NX
++ libraries.
++
++- Disabled the Xinerama extension to avoid further clashes with
++ the redefinition of GC in Xlib.
++
++- Added os/libos.a at the end of the agent link.
++
++nx-X11-2.0.0-8
++
++- Moved the declarations of _NXEnable* and related structures from
++ Xlibint.h to NXlibint.h.
++
++- Added provision for building the agent. This can be controlled by
++ setting NXAgentServer to YES in host.def.
++
++- Setting the NXUpgradeAgentServer variable to YES in the host.def
++ file will make the agent assume that it is being built in the new
++ environment. This variable is normally unset when building in the
++ 1.5.0 tree.
++
++nx-X11-2.0.0-7
++
++- Fixed a problem on AMD64 due to the size of the area pointed by
++ the argument of _X11TransBytesReadable(). BytesReadable_t is long,
++ at least on Linux, while the ioctl() requires a pointer to an int.
++ The original _X11TransBytesReadable() function simply calls the
++ ioctl() by passing the pointer that is provided. NXTransReadable(),
++ instead, was correctly returning the value assuming a pointer to
++ a long, but this crashes some applications, among them xterm. Now
++ NXTransReadable() follows the same schema of the ioctl() call and
++ stores the result assuming a pointer to an int.
++
++- Removed the outdated NX_TRANS_PROCESS and NX_TRANS_THREAD code.
++
++nx-X11-2.0.0-6
++
++- Made xterm work with the NX transport. This required small changes
++ to the Xt toolkit's and the xterm's files to let them use the NX
++ aware select(). This is useful to test the NX transport until the
++ nxagent server is integrated.
++
++- When the transport is gone _X11TransSocketBytesReadable() returns
++ EPIPE. This makes the client become aware of the closure of the
++ connection.
++
++- Added a call to NXTransDestroy() in XCloseDisplay().
++
++- The exit() function in XlibInt.c causes a call to NXTransExit().
++
++- Merged changes to dix/pixmap.c, xkb/xkbDflts.h, mi/Imakefile.
++
++- Removed unneeded changes and files containing patches already in
++ the latest X.org distribution: dix/dispatch.c, fb/fbcompose.c, fb/
++ fbgc.c, xkb/ddxList.c, font/fontfile/dirfile.c, font/fontfile/
++ encparse.c, font/fontfile/fontfile.c, font/FreeType/fttools.c,
++ Xrender/FillRect.c, Xrender/Picture.c.
++
++nx-X11-2.0.0-5
++
++- Changes to the lib/X11/Imakefile to cleanly build the tree. This
++ is obtained by creating a link to the Xcomp library in exports/lib
++ without having to modify the programs' Imakefiles.
++
++- Finished merging the NX changes in the lib/X11 files.
++
++- Merged the CHANGELOG with the one from the 1.5.0 tree.
++
++nx-X11-2.0.0-4
++
++- Merged the NX changes in most Xtrans and lib/X11 files.
++
++nx-X11-2.0.0-3
++
++- Temporarily disabled the use of the MMX extensions in the Xserver's
++ fb code to successfully compile with GCC 4.
++
++nx-X11-2.0.0-2
++
++- Imported the *.NX.reference and *.XF86.reference files that will
++ be needed for the merge. These files are the *.original from the
++ 1.5.0 tree. They will be removed as long as the merge advances.
++
++nx-X11-2.0.0-1
++
++- Created the 2.0.0 branch based on X.org the 6.8.99.16 snapshot.
++
++nx-X11-1.5.0-16
++
++- Added the missing *.XF86.original and *.NX.original files.
++
++nx-X11-1.5.0-15
++
++- Made the nxagent server use select() instead of poll() on Solaris
++ so that it can leverage the new NX transport.
++
++- Moved the NXTransFlush() call to _XReply().
++
++nx-X11-1.5.0-14
++
++- Added the 'synchronous' parameter in the _XWaitForReadable() call
++ to NXTransFlush().
++
++nx-X11-1.5.0-13
++
++- Removed the log entry in XlibInt.c on calling the NXTransFlush().
++
++nx-X11-1.5.0-12
++
++- Changed XlibInt.c and utils.c to call NXTransExit().
++
++nx-X11-1.5.0-11
++
++- Changed XlibInt.c to comply with the new NXTransFlush() interfa-
++ ce introduced in nxcomp-1.5.0-42.
++
++- Cosmetic changes to messages printed for debug.
++
++nx-X11-1.5.0-10
++
++- Ensured that all calls to _XIOError() are followed by a return.
++
++- Put exiting the client program in the case of an I/O error under
++ the control of the _NXContinueOnDisplayError flag. If set, the
++ I/O error routine will simply return, leaving to the application
++ the responsibility of checking the state of the XlibDisplayIOEr-
++ ror flag.
++
++- Added some checks whenever a read or write is performed on the X
++ connection, so that we can exit the I/O loop if the X channel is
++ gone. It is likely that more work will be needed when trying to
++ support XTHREADS enabled connections. This should not be a pro-
++ blem for now, as the default is still to quit the application un-
++ less the _NXContinueOnDisplayError flag is explicitly set.
++
++nx-X11-1.5.0-9
++
++- Removed the references to the cygipc library in NXWin. Now use the
++ cygserver daemon to provide the MIT-SHM extension.
++
++- Fixed an error in the UseCygIPC definition.
++
++- Changed the cygwin.cf file to avoid redefinition of the BuildGlxExt,
++ XWinServer and BuildGlxExt symbols.
++
++nx-X11-1.5.0-8
++
++- Added provision for deferred writes in the NX transport. When en-
++ tering _XWaitForReadable() we must ensure that data is flushed to
++ the proxy link.
++
++- Added the UseCygIPC define to NX-Cygwin.def.
++
++- Updated the NoMachine copyright notice on the modified files.
++
++nx-X11-1.5.0-7
++
++- Added the GLX extension in NX-Sun.def.
++
++- Added some more logs in WaitFor.c.
++
++nx-X11-1.5.0-6
++
++- Modified Xlibint.h and XlibInt.c to remove the _NXFlushSize para-
++ meter. New agents run the NX transport in-process, so we don't get
++ any benefit from increasing the display buffer size.
++
++- Modified NX-Darwin.def to not build the NXDarwin server. Since the
++ 1.4.0 version the NXDarwin server is unsupported and the NX client
++ for the Mac requires that the Apple X server is installed.
++
++- Changed NX-Linux.def to avoid the warning due to "SharedLibGLw"
++ being not defined.
++
++nx-X11-1.5.0-5
++
++- Modified the Xserver Imakefile to link nxagent with FbPostFbLibs
++ and avoid including mfb/libmfb.a.
++
++- Added the GLX extension in NX-Linux.def. This provides unaccelera-
++ ted support in nxagent, with GLX operations translated into core X
++ protocol primitives.
++
++- Fixed x-X11/programs/Xserver/GL/dri/Imakefile to look in ../../hw/
++ /xfree86/os-support/bus for includes.
++
++nx-X11-1.5.0-4
++
++- Avoid calling NXTransSelect() if the transport is gone, so that we
++ don't have to wait until the timeout.
++
++- Added the "-fno-strict-aliasing" option to linux.cf when compiling
++ with a GCC version >= 4. In the words of Stefan Dirsch: "The opt-
++ ion, which is default since gcc 3.1, can result in wrong code when
++ the gcc warnings related to it are ignored. And as there are seve-
++ ral warnings in X11 related to it, it has been disabled for X11
++ from the beginning. This didn't change for gcc4, so it still needs
++ to be used."
++
++- Added more logs in XlibInt.c and utils.c. A warning is printed if
++ the SmartScheduler is initialized.
++
++nx-X11-1.5.0-3
++
++- Started integration of nxcomp with the X libraries. The Xtrans
++ code creates an internal connection to the nxcomp library instead
++ of a child proxy process.
++
++- Changed Xpoll.h and XlibInt.c to replace the standard Select
++ with a version giving NX a chance to check its own descriptors.
++
++- Implemented the NXTransReadVector() and the NXTransWriteVector()
++ functions to replace READV() and WRITEV().
++
++- Implemented memory-to-memory communication with the NX proxy by
++ making use of the NXTransAgent() interface.
++
++nx-X11-1.5.0-2
++
++- We think that the way LoadAuthorization() is working is wrong.
++ It doesn't reset the list of stored authorizations before reading
++ the new cookies. Our take is that if a new auth file is to be
++ read, the only cookies that are to be accepted are those that are
++ in the new file, not those in the file -plus- those that have
++ been in the file in the past. Furthermore, if the list can't be
++ read or it is empty, it should assume that it ignores which co-
++ okies are valid and thus it should disable any access. Your mile-
++ age can vary. A less draconian approach could be to leave the old
++ cookies if the file can't be read and remove them only if the
++ file is empty.
++
++ Adding the cookies without removing the old values for the same
++ protocol has an important implication. If an user shares the co-
++ okie with somebody and later wants to revoke the access to the
++ display, changing the cookie will not work. This is especially
++ important with NX. For security reasons, after reconnecting the
++ session to a different display, it is advisable to generate a
++ new set of cookies, but doing that it is useless with the current
++ code, as the old cookies are going to be still accepted. On the
++ same topic, consider that once an user has got access to the X
++ server, he/she can freely enable host authentication from any
++ host, so the safe behaviour should be to reset the host based
++ authenthication at least at reconnection, and keep as valid only
++ the cookies that are actually in the file. This behaviour would
++ surely break many applications, among them a SSH connection run
++ inside a NX session, as ssh -X reads the cookie for the display
++ only at session startup and does not read the cookies again
++ when the auth file is changed.
++
++ Another bug (or feature, depending on how you want to consider
++ it) is that if the authority file contains entries for different
++ displays (as it is the norm when the authority file is the default
++ .Xauthority in the user's home), the X server will match -any- of
++ the cookies, even cookies that are not for its own display. This
++ means that you have to be careful when passing an authority file
++ to nxagent and maybe keep separate files for letting nxagent find
++ the cookie to be used to connect to the remote display and for
++ letting it find what cookies to accept. If the file is the same,
++ clients will be able to connect to nxagent with both the cookies.
++ This bug obviously affects any X server, also the real X server
++ running on the workstation, so it is common to see nxagent being
++ able to connect to the X server even if no cookie matches the
++ real display.
++
++- Added a check in lib/Xau/AuRead.c to prevent the fread() call to
++ be interrupted by SIGCHLD while reading the auth file. Due to the
++ way the old code worked, this could lead to the server enabling
++ local host access to the display. This problem had been identified
++ in the past. We just found that all the code dealing with reading
++ the auth file was affected. The code calls sigprocmask() to block
++ the signal (though it leaves some other calls unprotected) but the
++ SIGCHLD was not included in the set.
++
++- Added SIGCHLD to the set of signals that are blocked when reading
++ the authorization file.
++
++- As I was at it, I changed the path to the SecurityPolicy file. A
++ few Linux ditributors ship the file in $LIBDIR/xserver, a few only
++ in /etc/X11/xserver, most others in both places. It seems that
++ those who ship in $LIBDIR/xserver do also in /etc/X11 but the op-
++ posite is not true, so I switched to /etc/X11.
++
++nx-X11-1.5.0-1
++
++- Opened the 1.5.0 branch.
++
++nx-X11-1.4.1-2
++
++- Set parameter UseCygIPC on cygwin conf file in order to force the
++ build of MIT-SHM estension.
++
++- Removed some spurius object file.
++
++nx-X11-1.4.1-1
++
++- Opened the 1.4.1 branch.
++
++nx-X11-1.4.0-8
++
++- Changed DefaultFontPath and DefaultRGBDatabase in
++ NX-Cygwin.def.
++
++nx-X11-1.4.0-7
++
++- Imported dispatch in nxdarwin package, in order to let
++ nxdarwin being able to detect new client connection.
++
++- Changed the Xpm Imakefile to make also .a static library
++ on Solaris. To link nxviewer and nxdestkop staticaly.
++
++nx-X11-1.4.0-6
++
++- XInput extension enabled on MacOSX.
++
++- Added some missing backup files of the original XFree86
++ package.
++
++nx-X11-1.4.0-5
++
++- Changed the mi Imakefile in order to let xfree86 servers use
++ the normal mi extension initialization for the XInput exten-
++ sion.
++
++- XInput extension enabled on Solaris.
++
++nx-X11-1.4.0-4
++
++- Removed the RejectWellKnownSocket for the cygwin and
++ MacOSX environments that doesn't use the Xtransport library.
++
++nx-X11-1.4.0-3
++
++- Changed the implementation of the reject method in the
++ Xtransport library, now close any new incoming connection
++ immediately without reading or writing to it.
++
++nx-X11-1.4.0-2
++
++- Implemented a reject method in the Xtransport library,
++ this function accept and close every connection attempt,
++ on the specified listening socket.
++
++- Added the new function RejectWellKnownSocket to the os
++ connection code.
++ This function use the new transport reject function on
++ all listening socket.
++
++nx-X11-1.4.0-1
++
++- Opened the 1.4.0 branch.
++
++- Removed forgotten nxagent-1.3.2-20 directory.
++
++nx-X11-1.3.2-9
++
++- Prevents NX Darwin server going through the reset. On Darwin
++ we found that the it is not possible to get the correct key-
++ board layout unless it is set on the local machine, before
++ the NX session is started, by using xmodmap. As we set the
++ keyboard locally, we must prevent the X server to reset, or
++ we would loose any local configuration.
++
++nx-X11-1.3.2-8
++
++- Removed action associated to keysym XK_Terminate_Server. This
++ could cause agent to be terminated when pressing shift + back-
++ space if using the default US keyboard mapping.
++
++- Disabled the remaining debug logs in lib/X11/PutImage.c
++
++nx-X11-1.3.2-7
++
++- Fixed the wrong programs/Xserver/Imakefile in 1.3.2-6 package.
++
++nx-X11-1.3.2-6
++
++- Changed the define from NX_CLEAN_IN_PLACE to NX_CLEAN_INPLACE.
++ Definition of symbol is now placed in the Imakefile.
++
++- The new _NXEnableCleanInplace Xlib variable does control which
++ algorithm is used to clean the images. Setting NX_IMAGEINPLACE
++ in the environment will activate the in-place cleanup.
++
++- The default value of _NXEnableCleanInplace is -1. Leaving it to
++ a value <= 0 disables use of CleanInplace.
++
++nx-X11-1.3.2-5
++
++- Patch in config/cf/sun.cf. Fix for libfontconfig compilation
++ during gmake Everything on Solaris.
++
++- Patch in lib/X11/Imakefile. Fix for nxcomp compilation during
++ gmake World on Solaris.
++
++nx-X11-1.3.2-4
++
++- Image cleanup is now performed by using NXCleanInPlaceImage from
++ nxcompext. This function saves a buffer copy by cleaning the
++ padding bytes in the same buffer provided by the caller. Note that
++ to prevent memory violations in the case the image was allocated
++ in a static buffer, the function will temporarily redefine the
++ SIGSEGV handler. The former handler is restored before returning
++ to the caller. This can potentially affect some multithreaded
++ clients. Is to be decided if the function is safe enough to be
++ included in the production release.
++
++nx-X11-1.3.2-3
++
++- More debug logs in programs/Xserver/xkb/ddxLoad.c.
++
++nx-X11-1.3.2-2
++
++- Added NXmiwindow.o to NXAGENTOBJS in programs/Xserver/Imakefile.
++ File was not linked into the resulting nxagent. This solves the
++ problem of missing repaints in CDE and other Xt applications.
++
++nx-X11-1.3.2-1
++
++- Added some debug logs in programs/Xserver/xkb/ddxLoad.c. Function
++ XkbDDXCompileKeymapByNames is called by OpenOffice to read the
++ keyboard configuration whenever a drop-down menu is accessed. It
++ seem to always fail with the following error:
++
++ The XKEYBOARD keymap compiler (xkbcomp) reports:
++ > Error: Can't find file "unknown" for geometry include
++ > Exiting
++ > Abandoning geometry file "default"
++
++- Opened the 1.3.2 development branch.
++
++nx-X11-1.3.1-12
++
++- Fixed a problem in xkb/ddxLoad.c on Solaris where Pclose was
++ always returning an error code despite the fact that command
++ was executed properly.
++
++nx-X11-1.3.1-11
++
++- Changed default GCC flags from '-O2 -fno-strength-reduce' to
++ -O3. No platform where NX is targeted is currently using a
++ GCC 2.x affected by the -fno-strength-reduce bug. Note also
++ that nxcomp is already compiled with -O3 since 1.1.1, so it
++ can be considered safe.
++
++nx-X11-1.3.1-10
++
++- Imported an updated fbcompose.c file from XFree86-4.3.99.902.
++ This fixes "uninitialized value" problems reported by Valgrind.
++
++- Fixed further buffer overflows by updating the following file
++ with recent versions coming from the XFree86-4.3.99.902 tree.
++
++ nx-X11/lib/font/fontfile/dirfile.c
++ nx-X11/lib/font/fontfile/encparse.c
++ nx-X11/lib/font/fontfile/fontfile.c
++
++- Fixed a possible buffer overflow in lib/font/FreeType/fttools.c.
++ Verified that the change is already in the XFree86 4.4.0 CVS.
++
++nx-X11-1.3.1-9
++
++- Fixed Xserver/Imakefile which was still referencing NXpixmap.o.
++
++nx-X11-1.3.1-8
++
++- Imported an updated fbgc.c from XFree86-4.3.99.902. This fixes
++ some minor problems reported by Valgrind.
++
++- A major problem was reported by Valgrind about reading after
++ the block allocated in fbCreatePixmap from AllocatePixmap. The
++ file pixmap.c has been modified so that 4 bytes are added to
++ the pixmap buffer at any new allocation. This quick hack should
++ solve the problem for both nxagent and the NXWin server. Further
++ investigation is planned for the next release.
++
++- Fixed Xtranssock.c to compile on Solaris where struct sigaction
++ doesn't have the sa_restorer member.
++
++nx-X11-1.3.1-5
++
++- Renamed the NX-sun.def configuration file to NX-Sun.def.
++
++- Renamed the non-standard NX_iPAQ_XServer and NX_Zaurus_XServer
++ symbols to NXiPAQXServer and NXZaurusXServer.
++
++- Added the missing sun.cf.XF86.original file in config/cf.
++
++- Added the missing empty file host.def.XF86.original in the
++ same directory.
++
++- Added initialization of sa.sa_mask when setting sigaction()
++ for SIGCHLD. The problem was reported by Valgrind running
++ nxagent.
++
++- Removed an unused block of code from WaitFor.c. The code had
++ been commented out in previous versions.
++
++- Removed the non-standard colon at the end of version in this
++ CHANGELOG.
++
++- Removed the spurious spaces in this CHANGELOG.
++
++nx-X11-1.3.1-4
++
++- Added a little workaround to the top Imakefile intended to
++ hide the makedepend warnings about non portable whitespaces
++ in sources.
++
++nx-X11-1.3.1-3
++
++- Fixed compilation problem with nxagent-1.3.1-13.
++
++nx-X11-1.3.1-2
++
++- Changes in NX-sun.def configuration file for Solaris to allow
++ compilation of the XKB extension.
++
++nx-X11-1.3.1-1
++
++- Opened the 1.3.1 development branch.
++
++nx-X11-1.3.0-6
++
++- Original output buffer size in stock XFree86 is 2048. We try
++ to reduce context switches and help stream compression by
++ increasing the maximum size of the buffer 8192. _NXFlushSize
++ determines when the display buffer is actually flushed. It is
++ set by default to 4096 but agents should set it to 0 if they
++ want to disable early flush.
++
++- Added the _NXLostSequenceFunction function pointer to let NX
++ agents suppress the error message and modify the default Xlib
++ behaviour when out-of-order sequence numbers are received.
diff --git a/doc/nx-X11_vs_XOrg69_patches/ChkIfEv.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/ChkIfEv.c.NX.patch
new file mode 100644
index 000000000..333838d51
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/ChkIfEv.c.NX.patch
@@ -0,0 +1,59 @@
+--- ./nx-X11/lib/X11/ChkIfEv.c.X.original 2015-02-13 14:03:44.620443950 +0100
++++ ./nx-X11/lib/X11/ChkIfEv.c 2015-02-10 19:13:13.120711494 +0100
+@@ -83,3 +83,56 @@
+ UnlockDisplay(dpy);
+ return False;
+ }
++
++#ifdef NX_TRANS_SOCKET
++
++/*
++ * This is just like XCheckIfEvent() but doesn't
++ * flush the output buffer if it can't read new
++ * events.
++ */
++
++Bool XCheckIfEventNoFlush (dpy, event, predicate, arg)
++ register Display *dpy;
++ Bool (*predicate)(
++ Display* /* display */,
++ XEvent* /* event */,
++ char* /* arg */
++ ); /* function to call */
++ register XEvent *event; /* XEvent to be filled in. */
++ char *arg;
++{
++ register _XQEvent *prev, *qelt;
++ unsigned long qe_serial = 0;
++ int n; /* time through count */
++
++ LockDisplay(dpy);
++ prev = NULL;
++ for (n = 2; --n >= 0;) {
++ for (qelt = prev ? prev->next : dpy->head;
++ qelt;
++ prev = qelt, qelt = qelt->next) {
++ if(qelt->qserial_num > qe_serial
++ && (*predicate)(dpy, &qelt->event, arg)) {
++ *event = qelt->event;
++ _XDeq(dpy, prev, qelt);
++ UnlockDisplay(dpy);
++ return True;
++ }
++ }
++ if (prev)
++ qe_serial = prev->qserial_num;
++ switch (n) {
++ case 1:
++ _XEventsQueued(dpy, QueuedAfterReading);
++ break;
++ }
++ if (prev && prev->qserial_num != qe_serial)
++ /* another thread has snatched this event */
++ prev = NULL;
++ }
++ UnlockDisplay(dpy);
++ return False;
++}
++
++#endif
diff --git a/doc/nx-X11_vs_XOrg69_patches/ConnDis.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/ConnDis.c.NX.patch
new file mode 100644
index 000000000..17f054970
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/ConnDis.c.NX.patch
@@ -0,0 +1,319 @@
+--- ./nx-X11/lib/X11/ConnDis.c.X.original 2015-02-13 14:03:44.620443950 +0100
++++ ./nx-X11/lib/X11/ConnDis.c 2015-02-10 19:13:13.008715687 +0100
+@@ -25,6 +25,24 @@
+ in this Software without prior written authorization from The Open Group.
+
+ */
++
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NX-X11, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /* $XFree86: xc/lib/X11/ConnDis.c,v 3.28 2003/12/02 23:33:17 herrb Exp $ */
+
+ /*
+@@ -162,6 +180,39 @@
+ saddrlen = 0; /* set so that we can clear later */
+ saddr = NULL;
+
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
++ fprintf(stderr, "_X11TransConnectDisplay: Called with display_name [%s].\n", display_name);
++#endif
++
++#ifdef NX_TRANS_SOCKET
++
++ /*
++ * Check if user selected the "nx"
++ * protocol or an "nx" hostname.
++ */
++
++ if (!strncasecmp(p, "nx/", 3) || !strcasecmp(p, "nx") ||
++ !strncasecmp(p, "nx:", 3) || !strncasecmp(p, "nx,", 3))
++ {
++ if (*(display_name + 2) == '/')
++ {
++ p += 3;
++ }
++
++ pprotocol = copystring ("nx", 2);
++
++ if (!pprotocol) goto bad;
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_X11TransConnectDisplay: Forced protocol to [%s].\n", pprotocol);
++#endif
++
++ }
++ else
++ {
++
++#endif
++
+ /*
+ * Step 0, find the protocol. This is delimited by the optional
+ * slash ('/').
+@@ -176,6 +227,60 @@
+ } else
+ p = display_name; /* reset the pointer in
+ case no protocol was given */
++#ifdef NX_TRANS_SOCKET
++
++ } /* End of step 0. */
++
++ /*
++ * Check if user specified the "nx" protocol or
++ * hostname is "nx" or in the form "nx,...".
++ */
++
++ if (pprotocol && !strcasecmp(pprotocol, "nx"))
++ {
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_X11TransConnectDisplay: Checking hostname [%s].\n", p);
++#endif
++
++ /*
++ * Options can include a "display=" tuple so
++ * need to scan right to left.
++ */
++
++ lastp = p;
++ lastc = NULL;
++
++ for (; *p; p++)
++ if (*p == ':')
++ lastc = p;
++
++ /*
++ * Don't complain if no screen was provided.
++ */
++
++ if (lastc)
++ {
++ phostname = copystring (lastp, lastc - lastp);
++
++ p = lastc;
++ }
++ else
++ {
++ phostname = copystring (lastp, strlen(lastp));
++ }
++
++ if (!phostname) goto bad;
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_X11TransConnectDisplay: Forced hostname [%s].\n", phostname);
++#endif
++
++ }
++ else
++ {
++
++#endif
+
+ /*
+ * Step 1, find the hostname. This is delimited by either one colon,
+@@ -240,6 +345,20 @@
+ }
+ #endif
+
++#ifdef NX_TRANS_SOCKET
++
++ } /* End of step 1. */
++
++ /*
++ * Check if no display was specified. In this case
++ * search the "port=n" option in NX host string.
++ */
++
++ if (*p)
++ {
++
++#endif
++
+
+ /*
+ * Step 2, find the display number. This field is required and is
+@@ -254,6 +373,66 @@
+ goto bad;
+ idisplay = atoi (pdpynum);
+
++#ifdef NX_TRANS_SOCKET
++
++ }
++ else
++ {
++ char *host = NULL;
++ char *name = NULL;
++ char *value = NULL;
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_X11TransConnectDisplay: Searching port in port [%s].\n", phostname);
++#endif
++
++ if (!strncasecmp(phostname, "nx,", 3))
++ {
++ host = copystring(phostname + 3, strlen(phostname) - 3);
++ }
++
++ if (!host) goto bad;
++
++ idisplay = -1;
++
++ name = strtok(host, "=");
++
++ while (name)
++ {
++ value = strtok(NULL, ",");
++
++ if (value == NULL || strstr(value, "=") != NULL ||
++ strstr(name, ",") != NULL || strlen(value) >= 128)
++ {
++ Xfree(host);
++
++ goto bad;
++ }
++ else if (strcasecmp(name, "port") == 0)
++ {
++ idisplay = atoi(value);
++
++ pdpynum = copystring(value, strlen(value));
++
++ if (!pdpynum) goto bad;
++
++ break;
++ }
++
++ name = strtok(NULL, "=");
++ }
++
++ Xfree(host);
++
++ if (idisplay == -1)
++ {
++ goto bad;
++ }
++
++ } /* End of step 2. */
++
++#endif
++
+
+ /*
+ * Step 3, find the screen number. This field is optional. It is
+@@ -286,6 +465,27 @@
+ * is "unix", then choose BSD UNIX domain sockets (if configured).
+ */
+
++#ifdef NX_TRANS_SOCKET
++
++ /*
++ * If user selected the "nx" protocol
++ * force "local" transport.
++ */
++
++ if (pprotocol && !strcasecmp(pprotocol, "nx"))
++ {
++ pprotocol = copystring ("local", 5);
++
++ if (!pprotocol) goto bad;
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_X11TransConnectDisplay: Converted protocol to [%s].\n", pprotocol);
++#endif
++
++ }
++
++#endif
++
+ #if defined(TCPCONN) || defined(UNIXCONN) || defined(LOCALCONN) || defined(MNX_TCPCONN) || defined(OS2PIPECONN)
+ if (!pprotocol) {
+ if (!phostname) {
+@@ -358,14 +558,26 @@
+ * being a server listening at all, which is why we have to not retry
+ * too many times).
+ */
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
++ fprintf(stderr, "_X11TransConnectDisplay: Entering connection loop.\n");
++#endif
+ for(retry=X_CONNECTION_RETRIES; retry>=0; retry-- )
+ {
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
++ fprintf(stderr, "_X11TransConnectDisplay: Going to call _X11TransOpenCOTSClient(address) with address [%s].\n", address);
++#endif
+ if ( (trans_conn = _X11TransOpenCOTSClient(address)) == NULL )
+ {
+ break;
+ }
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
++ fprintf(stderr, "_X11TransConnectDisplay: Going to call _X11TransConnect(trans_conn,address).\n");
++#endif
+ if ((connect_stat = _X11TransConnect(trans_conn,address)) < 0 )
+ {
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
++ fprintf(stderr, "_X11TransConnectDisplay: Going to call _X11TransClose(trans_conn).\n");
++#endif
+ _X11TransClose(trans_conn);
+ trans_conn = NULL;
+
+@@ -378,6 +590,9 @@
+ break;
+ }
+
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
++ fprintf(stderr, "_X11TransConnectDisplay: Going to call _X11TransGetPeerAddr(trans_conn, &family, &saddrlen, &saddr).\n");
++#endif
+ _X11TransGetPeerAddr(trans_conn, &family, &saddrlen, &saddr);
+
+ /*
+@@ -386,6 +601,9 @@
+ * X protocol (ie FamilyInternet).
+ */
+
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
++ fprintf(stderr, "_X11TransConnectDisplay: Going to call _X11TransConvertAddress(&family, &saddrlen, &saddr).\n");
++#endif
+ if( _X11TransConvertAddress(&family, &saddrlen, &saddr) < 0 )
+ {
+ _X11TransClose(trans_conn);
+@@ -402,6 +620,9 @@
+ break;
+ }
+
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
++ fprintf(stderr, "_X11TransConnectDisplay: Out of connection loop.\n");
++#endif
+ if (address != addrbuf) Xfree (address);
+ address = addrbuf;
+
+@@ -570,6 +791,17 @@
+
+ if (len != 0)
+ return -1;
++#ifdef NX_TRANS_SOCKET
++ if (_NXDisplayWriteFunction != NULL) {
++ (*_NXDisplayWriteFunction)(dpy, len);
++ }
++#ifdef NX_TRANS_CHANGE
++ if (_NXDisplayCongestionFunction != NULL &&
++ _X11TransSocketCongestionChange(dpy->trans_conn, &congestion) == 1) {
++ (*_NXDisplayCongestionFunction)(dpy, congestion);
++ }
++#endif
++#endif
+
+ #ifdef K5AUTH
+ if (auth_length == 14 &&
diff --git a/doc/nx-X11_vs_XOrg69_patches/Glyph.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/Glyph.c.NX.patch
new file mode 100644
index 000000000..6dd036e2c
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/Glyph.c.NX.patch
@@ -0,0 +1,547 @@
+--- ./nx-X11/lib/Xrender/Glyph.c.X.original 2015-02-13 14:03:44.652443320 +0100
++++ ./nx-X11/lib/Xrender/Glyph.c 2015-02-10 19:13:12.580731749 +0100
+@@ -27,6 +27,26 @@
+ #endif
+ #include "Xrenderint.h"
+
++/*
++ * NX_RENDER_CLEANUP enables cleaning of padding bytes
++ */
++
++#define NX_RENDER_CLEANUP
++
++#define PANIC
++#define WARNING
++#undef TEST
++#undef DEBUG
++#undef DUMP
++
++#ifdef NX_RENDER_CLEANUP
++
++#include <stdio.h>
++
++#define ROUNDUP(nbits, pad) ((((nbits) + ((pad)-1)) / (pad)) * ((pad)>>3))
++
++#endif /* NX_RENDER_CLEANUP */
++
+ GlyphSet
+ XRenderCreateGlyphSet (Display *dpy, _Xconst XRenderPictFormat *format)
+ {
+@@ -81,6 +101,248 @@
+ SyncHandle();
+ }
+
++#ifdef NX_RENDER_CLEANUP
++
++void
++XRenderCleanGlyphs(xGlyphInfo *gi,
++ int nglyphs,
++ CARD8 *images,
++ int depth,
++ Display *dpy)
++{
++
++ int widthInBits;
++ int bytesPerLine;
++ int bytesToClean;
++ int bitsToClean;
++ int widthInBytes;
++ int height = gi -> height;
++ register int i;
++ int j;
++
++ #ifdef DEBUG
++ fprintf(stderr, "nxagentCleanGlyphs: Found a Glyph with Depth %d, width %d, pad %d.\n",
++ depth, gi -> width, dpy -> bitmap_pad);
++ #endif
++
++ while (nglyphs > 0)
++ {
++ if (depth == 24)
++ {
++ widthInBits = gi -> width * 32;
++
++ bytesPerLine = ROUNDUP(widthInBits, dpy -> bitmap_pad);
++
++ bytesToClean = bytesPerLine * height;
++
++ #ifdef DUBUG
++ fprintf(stderr, "nxagentCleanGlyphs: Found glyph with depth 24, bytes to clean is %d"
++ "width in bits is %d bytes per line [%d] height [%d].\n", bytesToClean,
++ widthInBits, bytesPerLine, height);
++ #endif
++
++ if (dpy -> byte_order == LSBFirst)
++ {
++ for (i = 3; i < bytesToClean; i += 4)
++ {
++ images[i] = 0x00;
++ }
++ }
++ else
++ {
++ for (i = 0; i < bytesToClean; i += 4)
++ {
++ images[i] = 0x00;
++ }
++ }
++
++ #ifdef DUMP
++ fprintf(stderr, "nxagentCleanGlyphs: depth %d, bytesToClean %d, scanline: ", depth, bytesToClean);
++ for (i = 0; i < bytesPerLine; i++)
++ {
++ fprintf(stderr, "[%d]", images[i]);
++ }
++ fprintf(stderr,"\n");
++ #endif
++
++ images += bytesToClean;
++
++ gi++;
++
++ nglyphs--;
++ }
++ else if (depth == 1)
++ {
++ widthInBits = gi -> width;
++
++ bytesPerLine = ROUNDUP(widthInBits, dpy -> bitmap_pad);
++
++ bitsToClean = (bytesPerLine << 3) - (gi -> width);
++
++ #ifdef DEBUG
++ fprintf(stderr, "nxagentCleanGlyphs: Found glyph with depth 1, width [%d], height [%d], bitsToClean [%d],"
++ " bytesPerLine [%d].\n", gi -> width, height, bitsToClean, bytesPerLine);
++ #endif
++
++ bytesToClean = bitsToClean >> 3;
++
++ bitsToClean &= 7;
++
++ #ifdef DEBUG
++ fprintf(stderr, "nxagentCleanGlyphs: bitsToClean &=7 is %d, bytesToCLean is %d."
++ " byte_order is %d, bitmap_bit_order is %d.\n", bitsToClean, bytesToClean,
++ dpy -> byte_order, dpy -> bitmap_bit_order);
++ #endif
++
++ for (i = 1; i <= height; i++)
++ {
++ if (dpy -> byte_order == dpy -> bitmap_bit_order)
++ {
++ for (j = 1; j <= bytesToClean; j++)
++ {
++ images[i * bytesPerLine - j] = 0x00;
++
++ #ifdef DEBUG
++ fprintf(stderr, "nxagentCleanGlyphs: byte_order = bitmap_bit_orde, cleaning %d, i=%d, j=%d.\n"
++ , (i * bytesPerLine - j), i, j);
++ #endif
++
++ }
++ }
++ else
++ {
++ for (j = bytesToClean; j >= 1; j--)
++ {
++ images[i * bytesPerLine - j] = 0x00;
++
++ #ifdef DEBUG
++ fprintf(stderr, "nxagentCleanGlyphs: byte_order %d, bitmap_bit_order %d, cleaning %d, i=%d, j=%d.\n"
++ , dpy -> byte_order, dpy -> bitmap_bit_order, (i * bytesPerLine - j), i, j);
++ #endif
++
++ }
++ }
++
++ if (dpy -> bitmap_bit_order == MSBFirst)
++ {
++ images[i * bytesPerLine - j] &= 0xff << bitsToClean;
++
++ #ifdef DEBUG
++ fprintf(stderr, "nxagentCleanGlyphs: byte_order MSBFirst, cleaning %d, i=%d, j=%d.\n"
++ , (i * bytesPerLine - j), i, j);
++ #endif
++ }
++ else
++ {
++ images[i * bytesPerLine - j] &= 0xff >> bitsToClean;
++
++ #ifdef DEBUG
++ fprintf(stderr, "nxagentCleanGlyphs: byte_order LSBFirst, cleaning %d, i=%d, j=%d.\n"
++ , (i * bytesPerLine - j), i, j);
++ #endif
++ }
++ }
++
++ #ifdef DUMP
++ fprintf(stderr, "nxagentCleanGlyphs: depth %d, bytesToClean %d, scanline: ", depth, bytesToClean);
++ for (i = 0; i < bytesPerLine; i++)
++ {
++ fprintf(stderr, "[%d]", images[i]);
++ }
++ fprintf(stderr,"\n");
++ #endif
++
++ images += bytesPerLine * height;
++
++ gi++;
++
++ nglyphs--;
++ }
++ else if ((depth == 8) || (depth == 16) )
++ {
++ widthInBits = gi -> width * depth;
++
++ bytesPerLine = ROUNDUP(widthInBits, dpy -> bitmap_pad);
++
++ widthInBytes = (widthInBits >> 3);
++
++ bytesToClean = bytesPerLine - widthInBytes;
++
++ #ifdef DEBUG
++ fprintf(stderr, "nxagentCleanGlyphs: nglyphs is %d, width of glyph in bits is %d, in bytes is %d.\n",
++ nglyphs, widthInBits, widthInBytes);
++
++ fprintf(stderr, "nxagentCleanGlyphs: bytesPerLine is %d bytes, there are %d scanlines.\n", bytesPerLine, height);
++
++ fprintf(stderr, "nxagentCleanGlyphs: Bytes to clean for each scanline are %d.\n", bytesToClean);
++ #endif
++
++ if (bytesToClean > 0)
++ {
++ while (height > 0)
++ {
++ i = bytesToClean;
++
++ while (i > 0)
++ {
++ *(images + (bytesPerLine - i)) = 0;
++
++ #ifdef DEBUG
++ fprintf(stderr, "nxagentCleanGlyphs: cleaned a byte.\n");
++ #endif
++
++ i--;
++ }
++
++ #ifdef DUMP
++ fprintf(stderr, "nxagentCleanGlyphs: depth %d, bytesToClean %d, scanline: ", depth, bytesToClean);
++ for (i = 0; i < bytesPerLine; i++)
++ {
++ fprintf(stderr, "[%d]", images[i]);
++ }
++ fprintf(stderr,"\n");
++ #endif
++
++ images += bytesPerLine;
++
++ height--;
++ }
++ }
++
++ gi++;
++
++ nglyphs--;
++
++ #ifdef DEBUG
++ fprintf(stderr, "nxagentCleanGlyphs: Breaking Out.\n");
++ #endif
++ }
++ else if (depth == 32)
++ {
++ #ifdef DEBUG
++ fprintf(stderr, "nxagentCleanGlyphs: Found glyph with depth 32.\n");
++ #endif
++
++ gi++;
++
++ nglyphs--;
++ }
++ else
++ {
++ #ifdef WARNING
++ fprintf(stderr, "nxagentCleanGlyphs: Unrecognized glyph, depth is not 8/16/24/32, it appears to be %d.\n",
++ depth);
++ #endif
++
++ gi++;
++
++ nglyphs--;
++ }
++ }
++}
++
++#endif /* #ifdef NX_RENDER_CLEANUP */
++
+ void
+ XRenderAddGlyphs (Display *dpy,
+ GlyphSet glyphset,
+@@ -404,6 +666,14 @@
+ _Xconst char *chars;
+ int nchars;
+
++ #ifdef NX_RENDER_CLEANUP
++
++ char tmpChar[4];
++ int bytes_to_clean;
++ int bytes_to_write;
++
++ #endif /* NX_RENDER_CLEANUP */
++
+ if (!nelt)
+ return;
+
+@@ -464,6 +734,14 @@
+ {
+ glyphset = elts[i].glyphset;
+ BufAlloc (xGlyphElt *, elt, SIZEOF (xGlyphElt));
++
++ #ifdef NX_RENDER_CLEANUP
++
++ elt->pad1 = 0;
++ elt->pad2 = 0;
++
++ #endif /* NX_RENDER_CLEANUP */
++
+ elt->len = 0xff;
+ elt->deltax = 0;
+ elt->deltay = 0;
+@@ -478,11 +756,88 @@
+ int this_chars = nchars > MAX_8 ? MAX_8 : nchars;
+
+ BufAlloc (xGlyphElt *, elt, SIZEOF(xGlyphElt))
++
++ #ifdef NX_RENDER_CLEANUP
++
++ elt->pad1 = 0;
++ elt->pad2 = 0;
++
++ #endif /* NX_RENDER_CLEANUP */
++
+ elt->len = this_chars;
+ elt->deltax = xDst;
+ elt->deltay = yDst;
+ xDst = 0;
+ yDst = 0;
++
++ #ifdef NX_RENDER_CLEANUP
++
++ bytes_to_write = this_chars & ~3;
++
++ bytes_to_clean = ((this_chars + 3) & ~3) - this_chars;
++
++ #ifdef DEBUG
++ fprintf(stderr, "XRenderCompositeText8: bytes_to_write %d, bytes_to_clean are %d,"
++ " this_chars %d.\n", bytes_to_write, bytes_to_clean, this_chars);
++ #endif
++
++ if (bytes_to_clean > 0)
++ {
++ if (bytes_to_write > 0)
++ {
++ #ifdef DEBUG
++ fprintf(stderr, "XRenderCompositeText8: found %d clean bytes, bytes_to_clean are %d,"
++ " this_chars %d.\n", bytes_to_write, bytes_to_clean, this_chars);
++ #endif
++
++ Data (dpy, chars, bytes_to_write);
++ chars += bytes_to_write;
++ }
++
++ bytes_to_write = this_chars % 4;
++ memcpy (tmpChar, chars, bytes_to_write);
++ chars += bytes_to_write;
++
++ #ifdef DEBUG
++ fprintf(stderr, "XRenderCompositeText8: last 32 bit, bytes_to_write are %d,"
++ " bytes_to_clean are %d, this_chars are %d.\n", bytes_to_write, bytes_to_clean, this_chars);
++ #endif
++
++ #ifdef DUMP
++ fprintf(stderr, "XRenderCompositeText8: bytes_to_clean %d, ", bytes_to_clean);
++ #endif
++
++ while (bytes_to_clean > 0)
++ {
++ tmpChar[4 - bytes_to_clean] = 0;
++ bytes_to_clean--;
++
++ #ifdef DEBUG
++ fprintf(stderr, "XRenderCompositeText8: Cleaned %d byte.\n", 4 - bytes_to_clean);
++ #endif
++ }
++
++ Data (dpy, tmpChar, 4);
++ nchars -= this_chars;
++
++ #ifdef DUMP
++ fprintf(stderr, "Data: ");
++ for (i = 0; i < 4; i++)
++ {
++ fprintf(stderr, "[%d]", tmpChar[i]);
++ }
++ fprintf(stderr,"\n");
++ #endif
++
++ #ifdef DEBUG
++ fprintf(stderr, "XRenderCompositeText8: nchars now is %d.\n", nchars);
++ #endif
++
++ continue;
++ }
++
++ #endif /* NX_RENDER_CLEANUP */
++
+ Data (dpy, chars, this_chars);
+ nchars -= this_chars;
+ chars += this_chars;
+@@ -517,6 +872,14 @@
+ _Xconst unsigned short *chars;
+ int nchars;
+
++ #ifdef NX_RENDER_CLEANUP
++
++ int bytes_to_write;
++ int bytes_to_clean;
++ char tmpChar[4];
++
++ #endif /* NX_RENDER_CLEANUP */
++
+ if (!nelt)
+ return;
+
+@@ -574,6 +937,14 @@
+ {
+ glyphset = elts[i].glyphset;
+ BufAlloc (xGlyphElt *, elt, SIZEOF (xGlyphElt));
++
++ #ifdef NX_RENDER_CLEANUP
++
++ elt->pad1 = 0;
++ elt->pad2 = 0;
++
++ #endif /* NX_RENDER_CLEANUP */
++
+ elt->len = 0xff;
+ elt->deltax = 0;
+ elt->deltay = 0;
+@@ -587,13 +958,77 @@
+ {
+ int this_chars = nchars > MAX_16 ? MAX_16 : nchars;
+ int this_bytes = this_chars * 2;
+-
++
+ BufAlloc (xGlyphElt *, elt, SIZEOF(xGlyphElt))
++
++ #ifdef NX_RENDER_CLEANUP
++
++ elt->pad1 = 0;
++ elt->pad2 = 0;
++
++ #endif /* NX_RENDER_CLEANUP */
++
+ elt->len = this_chars;
+ elt->deltax = xDst;
+ elt->deltay = yDst;
+ xDst = 0;
+ yDst = 0;
++
++ #ifdef NX_RENDER_CLEANUP
++
++ bytes_to_write = this_bytes & ~3;
++ bytes_to_clean = ((this_bytes + 3) & ~3) - this_bytes;
++
++ #ifdef DEBUG
++ fprintf(stderr, "XRenderCompositeText16: this_chars %d, this_bytes %d.\n"
++ "bytes_to_write %d, bytes_to_clean are %d.\n", this_chars, this_bytes,
++ bytes_to_write, bytes_to_clean);
++ #endif
++
++ if (bytes_to_clean > 0)
++ {
++ if (bytes_to_write > 0)
++ {
++ Data16 (dpy, chars, bytes_to_write);
++
++ /*
++ * Cast chars to avoid errors with pointer arithmetic.
++ */
++
++ chars = (unsigned short *) ((char *) chars + bytes_to_write);
++ }
++
++ bytes_to_write = this_bytes % 4;
++ memcpy (tmpChar, (char *) chars, bytes_to_write);
++ chars = (unsigned short *) ((char *) chars + bytes_to_write);
++
++ #ifdef DEBUG
++ fprintf(stderr, "XRenderCompositeText16: last 32 bit, bytes_to_write are %d,"
++ " bytes_to_clean are %d.\n", bytes_to_write, bytes_to_clean);
++ #endif
++
++ while (bytes_to_clean > 0)
++ {
++ tmpChar[4 - bytes_to_clean] = 0;
++ bytes_to_clean--;
++
++ #ifdef DEBUG
++ fprintf(stderr, "XRenderCompositeText16: Cleaned %d byte.\n", 4 - bytes_to_clean);
++ #endif
++ }
++
++ Data16 (dpy, tmpChar, 4);
++ nchars -= this_chars;
++
++ #ifdef DEBUG
++ fprintf(stderr, "XRenderCompositeText16: nchars now is %d.\n", nchars);
++ #endif
++
++ continue;
++ }
++
++ #endif /* NX_RENDER_CLEANUP */
++
+ Data16 (dpy, chars, this_bytes);
+ nchars -= this_chars;
+ chars += this_chars;
+@@ -681,6 +1116,14 @@
+ {
+ glyphset = elts[i].glyphset;
+ BufAlloc (xGlyphElt *, elt, SIZEOF (xGlyphElt));
++
++ #ifdef NX_RENDER_CLEANUP
++
++ elt->pad1 = 0;
++ elt->pad2 = 0;
++
++ #endif /* NX_RENDER_CLEANUP */
++
+ elt->len = 0xff;
+ elt->deltax = 0;
+ elt->deltay = 0;
+@@ -695,11 +1138,25 @@
+ int this_chars = nchars > MAX_32 ? MAX_32 : nchars;
+ int this_bytes = this_chars * 4;
+ BufAlloc (xGlyphElt *, elt, SIZEOF(xGlyphElt))
++
++ #ifdef NX_RENDER_CLEANUP
++
++ elt->pad1 = 0;
++ elt->pad2 = 0;
++
++ #endif /* NX_RENDER_CLEANUP */
++
+ elt->len = this_chars;
+ elt->deltax = xDst;
+ elt->deltay = yDst;
+ xDst = 0;
+ yDst = 0;
++
++ #ifdef TEST
++ fprintf(stderr, "XRenderCompositeText32: this_chars %d, this_bytes %d.\n",
++ this_chars, this_bytes);
++ #endif
++
+ DataInt32 (dpy, chars, this_bytes);
+ nchars -= this_chars;
+ chars += this_chars;
diff --git a/doc/nx-X11_vs_XOrg69_patches/IfEvent.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/IfEvent.c.NX.patch
new file mode 100644
index 000000000..fb5e164a3
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/IfEvent.c.NX.patch
@@ -0,0 +1,13 @@
+--- ./nx-X11/lib/X11/IfEvent.c.X.original 2015-02-13 14:03:44.620443950 +0100
++++ ./nx-X11/lib/X11/IfEvent.c 2015-02-10 19:13:12.796723642 +0100
+@@ -71,5 +71,10 @@
+ if (prev && prev->qserial_num != qe_serial)
+ /* another thread has snatched this event */
+ prev = NULL;
++#ifdef NX_TRANS_SOCKET
++ if (_XGetIOError(dpy)) {
++ return 0;
++ }
++#endif
+ }
+ }
diff --git a/doc/nx-X11_vs_XOrg69_patches/Imakefile.NX.patch b/doc/nx-X11_vs_XOrg69_patches/Imakefile.NX.patch
new file mode 100644
index 000000000..7f3db6c8b
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/Imakefile.NX.patch
@@ -0,0 +1,11 @@
+--- ./nx-X11/programs/Xserver/GL/mesa/X/Imakefile.X.original 2015-02-13 14:03:44.680442769 +0100
++++ ./nx-X11/programs/Xserver/GL/mesa/X/Imakefile 2015-02-10 19:13:14.340665851 +0100
+@@ -57,7 +57,7 @@
+ -I$(XF86OSSRC) \
+ -I$(DRMSRCDIR)/shared-core
+
+- DEFINES = $(GLX_DEFINES) $(GLXSRV_DEFINES) /*-DUSE_X86_ASM*/ /*-DUSE_SPARC_ASM*/
++ DEFINES = $(GLX_DEFINES) $(GLXSRV_DEFINES) -DNXAGENT_SERVER /*-DUSE_X86_ASM*/ /*-DUSE_SPARC_ASM*/
+
+ #ifdef IHaveModules
+ ModuleObjectRule()
diff --git a/doc/nx-X11_vs_XOrg69_patches/MaskEvent.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/MaskEvent.c.NX.patch
new file mode 100644
index 000000000..6620d4baa
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/MaskEvent.c.NX.patch
@@ -0,0 +1,13 @@
+--- ./nx-X11/lib/X11/MaskEvent.c.X.original 2015-02-13 14:03:44.620443950 +0100
++++ ./nx-X11/lib/X11/MaskEvent.c 2015-02-10 19:13:12.944718089 +0100
+@@ -75,5 +75,10 @@
+ if (prev && prev->qserial_num != qe_serial)
+ /* another thread has snatched this event */
+ prev = NULL;
++#ifdef NX_TRANS_SOCKET
++ if (_XGetIOError(dpy)) {
++ return 0;
++ }
++#endif
+ }
+ }
diff --git a/doc/nx-X11_vs_XOrg69_patches/NXdamage.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/NXdamage.c.NX.patch
new file mode 100644
index 000000000..06d91218f
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/NXdamage.c.NX.patch
@@ -0,0 +1,138 @@
+--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXdamage.c.X.original 2015-02-13 14:03:44.740441589 +0100
++++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXdamage.c 2015-02-10 19:13:13.828684988 +0100
+@@ -1,3 +1,20 @@
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NXAGENT, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /*
+ * $Id: damage.c,v 1.19 2005/10/06 21:55:41 anholt Exp $
+ *
+@@ -1358,17 +1375,24 @@
+ if (n != 0) {
+ damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, n,
+ charinfo, imageblt, pGC->subWindowMode);
++
++#ifndef NXAGENT_SERVER
++
+ if (imageblt)
+ (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, n, charinfo,
+ FONTGLYPHS(pGC->font));
+ else
+ (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, n, charinfo,
+ FONTGLYPHS(pGC->font));
++#endif
++
+ }
+ DEALLOCATE_LOCAL(charinfo);
+ return x + w;
+ }
+
++#ifndef NXAGENT_SERVER
++
+ static int
+ damagePolyText8(DrawablePtr pDrawable,
+ GCPtr pGC,
+@@ -1445,6 +1469,89 @@
+ DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
+ }
+
++#else /* #ifndef NXAGENT_SERVER */
++
++static int
++damagePolyText8(DrawablePtr pDrawable,
++ GCPtr pGC,
++ int x,
++ int y,
++ int count,
++ char *chars)
++{
++ DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
++
++ if (checkGCDamage (pDrawable, pGC))
++ damageText (pDrawable, pGC, x, y, (unsigned long) count, chars,
++ Linear8Bit, TT_POLY8);
++
++ x = (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars);
++
++ DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
++ return x;
++}
++
++static int
++damagePolyText16(DrawablePtr pDrawable,
++ GCPtr pGC,
++ int x,
++ int y,
++ int count,
++ unsigned short *chars)
++{
++ DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
++
++ if (checkGCDamage (pDrawable, pGC))
++ damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars,
++ FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit,
++ TT_POLY16);
++
++ x = (*pGC->ops->PolyText16)(pDrawable, pGC, x, y, count, chars);
++
++ DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
++ return x;
++}
++
++static void
++damageImageText8(DrawablePtr pDrawable,
++ GCPtr pGC,
++ int x,
++ int y,
++ int count,
++ char *chars)
++{
++ DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
++
++ if (checkGCDamage (pDrawable, pGC))
++ damageText (pDrawable, pGC, x, y, (unsigned long) count, chars,
++ Linear8Bit, TT_IMAGE8);
++
++ (*pGC->ops->ImageText8)(pDrawable, pGC, x, y, count, chars);
++
++ DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
++}
++
++static void
++damageImageText16(DrawablePtr pDrawable,
++ GCPtr pGC,
++ int x,
++ int y,
++ int count,
++ unsigned short *chars)
++{
++ DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
++
++ if (checkGCDamage (pDrawable, pGC))
++ damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars,
++ FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit,
++ TT_IMAGE16);
++
++ (*pGC->ops->ImageText16)(pDrawable, pGC, x, y, count, chars);
++
++ DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
++}
++
++#endif /* #ifndef NXAGENT_SERVER */
+
+ static void
+ damageImageGlyphBlt(DrawablePtr pDrawable,
diff --git a/doc/nx-X11_vs_XOrg69_patches/NXdispatch.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/NXdispatch.c.NX.patch
new file mode 100644
index 000000000..d9e35f7ae
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/NXdispatch.c.NX.patch
@@ -0,0 +1,1036 @@
+--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXdispatch.c.X.original 2015-02-13 14:03:44.740441589 +0100
++++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXdispatch.c 2015-02-13 14:03:44.740441589 +0100
+@@ -1,3 +1,20 @@
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NXAGENT, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /* $XdotOrg: xc/programs/Xserver/dix/dispatch.c,v 1.13 2005/09/13 01:33:19 daniels Exp $ */
+ /* $Xorg: dispatch.c,v 1.5 2001/02/09 02:04:40 xorgcvs Exp $ */
+ /************************************************************
+@@ -87,6 +104,15 @@
+ int ProcInitialConnection();
+ #endif
+
++#ifdef __sun
++#define False 0
++#define True 1
++#endif
++
++#define GC XlibGC
++#include <X11/Xlib.h>
++#undef GC
++
+ #include "windowstr.h"
+ #include <X11/fonts/fontstruct.h>
+ #include "dixfontstr.h"
+@@ -100,7 +126,7 @@
+ #include "servermd.h"
+ #include "extnsionst.h"
+ #include "dixfont.h"
+-#include "dispatch.h"
++#include "../../dix/dispatch.h"
+ #include "swaprep.h"
+ #include "swapreq.h"
+ #ifdef PANORAMIX
+@@ -119,8 +145,69 @@
+ #include "inputstr.h"
+ #include <X11/extensions/XKBsrv.h>
+ #endif
++
++#include "Atoms.h"
++#include "Splash.h"
++#include "Client.h"
++#include "Clipboard.h"
++#include "Reconnect.h"
++#include "Millis.h"
++#include "Font.h"
++#include "Shadow.h"
++#include "Handlers.h"
++#include "Keyboard.h"
++
++const int nxagentMaxFontNames = 10000;
++
++char dispatchExceptionAtReset = DE_RESET;
++
++/*
++ * This allows the agent to exit if no
++ * client is connected within a timeout.
++ */
++
++int nxagentClients = 0;
++
++void nxagentWaitDisplay(void);
++
++void nxagentListRemoteFonts(const char *, int);
++
++unsigned int nxagentWMtimeout = 0;
++Bool nxagentWMPassed = 0;
++
++/*
++ * Timeouts based on screen saver time.
++ */
++
++int nxagentAutoDisconnectTimeout = 0;
++
+ #ifdef LBX
+-#include "lbxserve.h"
++#include "../../lbx/lbxserve.h"
++#endif
++
++#include "Xatom.h"
++
++/*
++ * Set here the required log level.
++ */
++
++#define PANIC
++#define WARNING
++#undef TEST
++#undef WATCH
++
++/*
++ * Log begin and end of the important handlers.
++ */
++
++#undef BLOCKS
++
++#ifdef WATCH
++#include "unistd.h"
++#endif
++
++#ifdef TEST
++#include "Literals.h"
+ #endif
+
+ #define mskcnt ((MAXCLIENTS + 31) / 32)
+@@ -138,6 +225,28 @@
+ int NumCurrentSelections;
+ CallbackListPtr SelectionCallback = NULL;
+
++#ifdef VIEWPORT_FRAME
++
++extern WindowPtr nxagentViewportFrameLeft;
++extern WindowPtr nxagentViewportFrameRight;
++extern WindowPtr nxagentViewportFrameAbove;
++extern WindowPtr nxagentViewportFrameBelow;
++
++#define IsViewportFrame(pWin) ((pWin) == nxagentViewportFrameLeft || \
++ (pWin) == nxagentViewportFrameRight || \
++ (pWin) == nxagentViewportFrameAbove || \
++ (pWin) == nxagentViewportFrameBelow)
++
++#else
++
++#define IsViewportFrame(pWin) (0)
++
++#endif /* #ifdef VIEWPORT_FRAME */
++
++extern int nxagentMaxAllowedResets;
++
++extern int nxagentFindClientResource(int, RESTYPE, pointer);
++
+ static ClientPtr grabClient;
+ #define GrabNone 0
+ #define GrabActive 1
+@@ -222,6 +331,30 @@
+ xfree(CurrentSelections);
+ CurrentSelections = (Selection *)NULL;
+ NumCurrentSelections = 0;
++
++#ifdef NXAGENT_CLIPBOARD
++ {
++ Selection *newsels;
++ newsels = (Selection *)xalloc(2 * sizeof(Selection));
++ if (!newsels)
++ return;
++ NumCurrentSelections += 2;
++ CurrentSelections = newsels;
++
++ CurrentSelections[0].selection = XA_PRIMARY;
++ CurrentSelections[0].lastTimeChanged = ClientTimeToServerTime(0);
++ CurrentSelections[0].window = WindowTable[0]->drawable.id;
++ CurrentSelections[0].pWin = NULL;
++ CurrentSelections[0].client = NullClient;
++
++ CurrentSelections[1].selection = MakeAtom("CLIPBOARD", 9, 1);
++ CurrentSelections[1].lastTimeChanged = ClientTimeToServerTime(0);
++ CurrentSelections[1].window = WindowTable[0]->drawable.id;
++ CurrentSelections[1].pWin = NULL;
++ CurrentSelections[1].client = NullClient;
++ }
++#endif
++
+ }
+
+ void
+@@ -369,14 +502,72 @@
+ long start_tick;
+ #endif
+
++ unsigned long currentDispatch = 0;
++
+ nextFreeClientID = 1;
+ InitSelections();
+ nClients = 0;
+
++ /*
++ * The agent initialization was successfully
++ * completed. We can now handle our clients.
++ */
++
++ #ifdef XKB
++
++ nxagentInitXkbWrapper();
++
++ nxagentTuneXkbWrapper();
++
++ #endif
++
++ #ifdef NXAGENT_ONSTART
++
++ /*
++ * Set NX_WM property (used by NX client to identify
++ * the agent's window) three seconds since the first
++ * client connects.
++ */
++
++ nxagentWMtimeout = GetTimeInMillis() + 3000;
++
++ #endif
++
+ clientReady = (int *) ALLOCATE_LOCAL(sizeof(int) * MaxClients);
+ if (!clientReady)
+ return;
+
++ #ifdef WATCH
++
++ fprintf(stderr, "Dispatch: Watchpoint 12.\n");
++
++/*
++Reply Total Cached Bits In Bits Out Bits/Reply Ratio
++------- ----- ------ ------- -------- ---------- -----
++#3 1 352 bits (0 KB) -> 236 bits (0 KB) -> 352/1 -> 236/1 = 1.492:1
++#14 1 256 bits (0 KB) -> 101 bits (0 KB) -> 256/1 -> 101/1 = 2.535:1
++#16 1 256 bits (0 KB) -> 26 bits (0 KB) -> 256/1 -> 26/1 = 9.846:1
++#20 2 2 12256 bits (1 KB) -> 56 bits (0 KB) -> 6128/1 -> 28/1 = 218.857:1
++#43 1 256 bits (0 KB) -> 45 bits (0 KB) -> 256/1 -> 45/1 = 5.689:1
++#47 2 2 42304 bits (5 KB) -> 49 bits (0 KB) -> 21152/1 -> 24/1 = 863.347:1
++#98 1 256 bits (0 KB) -> 34 bits (0 KB) -> 256/1 -> 34/1 = 7.529:1
++*/
++
++ sleep(30);
++
++ #endif
++
++ #ifdef TEST
++ fprintf(stderr, "Dispatch: Value of dispatchException is [%x].\n",
++ dispatchException);
++
++ fprintf(stderr, "Dispatch: Value of dispatchExceptionAtReset is [%x].\n",
++ dispatchExceptionAtReset);
++ #endif
++
++ if (!(dispatchException & DE_TERMINATE))
++ dispatchException = 0;
++
+ while (!dispatchException)
+ {
+ if (*icheck[0] != *icheck[1])
+@@ -385,8 +576,75 @@
+ FlushIfCriticalOutputPending();
+ }
+
++ /*
++ * Ensure we remove the splash after the timeout.
++ * Initializing clientReady[0] to -1 will tell
++ * WaitForSomething() to yield control after the
++ * timeout set in clientReady[1].
++ */
++
++ clientReady[0] = 0;
++
++ if (nxagentSplashWindow != None || (nxagentOption(Xdmcp) == 1 && nxagentXdmcpUp == 0))
++ {
++ #ifdef TEST
++ fprintf(stderr, "******Dispatch: Requesting a timeout of [%d] Ms.\n",
++ NXAGENT_WAKEUP);
++ #endif
++
++ clientReady[0] = -1;
++ clientReady[1] = NXAGENT_WAKEUP;
++ }
++
++ if (serverGeneration > nxagentMaxAllowedResets &&
++ nxagentSessionState == SESSION_STARTING &&
++ (nxagentOption(Xdmcp) == 0 || nxagentXdmcpUp == 1))
++ {
++ #ifdef NX_DEBUG_INPUT
++ fprintf(stderr, "Session: Session started at '%s' timestamp [%lu].\n",
++ GetTimeAsString(), GetTimeInMillis());
++ #else
++ fprintf(stderr, "Session: Session started at '%s'.\n",
++ GetTimeAsString());
++ #endif
++
++ nxagentSessionState = SESSION_UP;
++ }
++
++ #ifdef BLOCKS
++ fprintf(stderr, "[End dispatch]\n");
++ #endif
++
+ nready = WaitForSomething(clientReady);
+
++ #ifdef BLOCKS
++ fprintf(stderr, "[Begin dispatch]\n");
++ #endif
++
++ #ifdef TEST
++ fprintf(stderr, "******Dispatch: Running with [%d] clients ready.\n",
++ nready);
++ #endif
++
++ #ifdef NXAGENT_ONSTART
++
++ currentDispatch = GetTimeInMillis();
++
++ /*
++ * If the timeout is expired set the
++ * selection informing the NX client
++ * that the agent is ready.
++ */
++
++ if (!nxagentWMPassed && (nxagentWMtimeout < currentDispatch))
++ {
++ nxagentRemoveSplashWindow(NULL);
++ }
++
++ nxagentClients = nClients;
++
++ #endif
++
+ #ifdef SMART_SCHEDULE
+ if (nready && !SmartScheduleDisable)
+ {
+@@ -438,6 +696,11 @@
+ #endif
+ /* now, finally, deal with client requests */
+
++ #ifdef TEST
++ fprintf(stderr, "******Dispatch: Reading request from client [%d].\n",
++ client->index);
++ #endif
++
+ result = ReadRequestFromClient(client);
+ if (result <= 0)
+ {
+@@ -445,6 +708,29 @@
+ CloseDownClient(client);
+ break;
+ }
++#ifdef NXAGENT_SERVER
++
++ #ifdef TEST
++
++ else
++ {
++
++ if (MAJOROP > 127)
++ {
++ fprintf(stderr, "******Dispatch: Read [Extension] request OPCODE#%d MINOR#%d "
++ "size [%d] client [%d].\n", MAJOROP, *((char *) client->requestBuffer + 1),
++ client->req_len << 2, client->index);
++ }
++ else
++ {
++ fprintf(stderr, "******Dispatch: Read [%s] request OPCODE#%d size [%d] client [%d].\n",
++ nxagentRequestLiteral[MAJOROP], MAJOROP, client->req_len << 2,
++ client->index);
++ }
++ }
++
++ #endif
++#endif
+
+ client->sequence++;
+ #ifdef DEBUG
+@@ -456,8 +742,40 @@
+ if (result > (maxBigRequestSize << 2))
+ result = BadLength;
+ else
++#ifdef NXAGENT_SERVER
++ {
++ result = (* client->requestVector[MAJOROP])(client);
++
++ #ifdef TEST
++
++ if (MAJOROP > 127)
++ {
++ fprintf(stderr, "******Dispatch: Handled [Extension] request OPCODE#%d MINOR#%d "
++ "size [%d] client [%d] result [%d].\n", MAJOROP,
++ *((char *) client->requestBuffer + 1), client->req_len << 2,
++ client->index, result);
++ }
++ else
++ {
++ fprintf(stderr, "******Dispatch: Handled [%s] request OPCODE#%d size [%d] client [%d] "
++ "result [%d].\n", nxagentRequestLiteral[MAJOROP], MAJOROP,
++ client->req_len << 2, client->index, result);
++ }
++
++ #endif
++
++ /*
++ * Can set isItTimeToYield to force
++ * the dispatcher to pay attention
++ * to another client.
++ */
++
++ nxagentDispatchHandler(client, client->req_len << 2, 0);
++ }
++#else
+ result = (* client->requestVector[MAJOROP])(client);
+-
++#endif
++
+ if (result != Success)
+ {
+ if (client->noClientException != Success)
+@@ -485,6 +803,37 @@
+ #if defined(DDXBEFORERESET)
+ ddxBeforeReset ();
+ #endif
++ if ((dispatchException & DE_RESET) &&
++ (serverGeneration > nxagentMaxAllowedResets))
++ {
++ dispatchException &= ~DE_RESET;
++ dispatchException |= DE_TERMINATE;
++
++ fprintf(stderr, "Info: Reached threshold of maximum allowed resets.\n");
++ }
++
++ nxagentResetAtomMap();
++
++ if (serverGeneration > nxagentMaxAllowedResets)
++ {
++ /*
++ * The session is terminating. Force an I/O
++ * error on the display and wait until the
++ * NX transport is gone.
++ */
++
++ fprintf(stderr, "Session: Terminating session at '%s'.\n", GetTimeAsString());
++
++ nxagentWaitDisplay();
++
++ fprintf(stderr, "Session: Session terminated at '%s'.\n", GetTimeAsString());
++ }
++
++ if (nxagentOption(Shadow) == 1)
++ {
++ NXShadowDestroy();
++ }
++
+ KillAllClients();
+ DEALLOCATE_LOCAL(clientReady);
+ dispatchException &= ~DE_RESET;
+@@ -656,6 +1005,12 @@
+ SecurityWriteAccess);
+ if (!pWin)
+ return(BadWindow);
++
++ if (!nxagentWMPassed)
++ {
++ nxagentRemoveSplashWindow(pWin);
++ }
++
+ pParent = (WindowPtr)SecurityLookupWindow(stuff->parent, client,
+ SecurityWriteAccess);
+ if (!pParent)
+@@ -724,6 +1079,7 @@
+ return(BadWindow);
+ UnmapWindow(pWin, FALSE);
+ /* update cache to say it is mapped */
++
+ return(client->noClientException);
+ }
+
+@@ -760,6 +1116,7 @@
+ return BadLength;
+ result = ConfigureWindow(pWin, (Mask)stuff->mask, (XID *) &stuff[1],
+ client);
++
+ if (client->noClientException != Success)
+ return(client->noClientException);
+ else
+@@ -865,7 +1222,12 @@
+ reply.parent = (Window)None;
+ pHead = RealChildHead(pWin);
+ for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib)
++ {
++ if (!IsViewportFrame(pChild))
++ {
+ numChildren++;
++ }
++ }
+ if (numChildren)
+ {
+ int curChild = 0;
+@@ -874,7 +1236,12 @@
+ if (!childIDs)
+ return BadAlloc;
+ for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib)
++ {
++ if (!IsViewportFrame(pChild))
++ {
+ childIDs[curChild++] = pChild->drawable.id;
++ }
++ }
+ }
+
+ reply.nChildren = numChildren;
+@@ -1038,6 +1405,16 @@
+ info.kind= SelectionSetOwner;
+ CallCallbacks(&SelectionCallback, &info);
+ }
++
++#ifdef NXAGENT_CLIPBOARD
++ if ((CurrentSelections[i].pWin != NULL) &&
++ (nxagentOption(Clipboard) != ClipboardNone) &&
++ ((CurrentSelections[i].selection == XA_PRIMARY) ||
++ (CurrentSelections[i].selection == MakeAtom("CLIPBOARD", 9, 0))))
++ {
++ nxagentSetSelectionOwner(&CurrentSelections[i]);
++ }
++#endif
+ return (client->noClientException);
+ }
+ else
+@@ -1092,6 +1469,27 @@
+ if (!pWin)
+ return(BadWindow);
+
++#ifdef NXAGENT_CLIPBOARD
++ if (((stuff->selection == XA_PRIMARY) ||
++ (stuff->selection == MakeAtom("CLIPBOARD", 9, 0))) &&
++ nxagentOption(Clipboard) != ClipboardNone)
++ {
++ int i = 0;
++
++ while ((i < NumCurrentSelections) &&
++ CurrentSelections[i].selection != stuff->selection) i++;
++
++ if ((i < NumCurrentSelections) && (CurrentSelections[i].window != None))
++ {
++ if (nxagentConvertSelection(client, pWin, stuff->selection, stuff->requestor,
++ stuff->property, stuff->target, stuff->time))
++ {
++ return (client->noClientException);
++ }
++ }
++ }
++#endif
++
+ paramsOkay = (ValidAtom(stuff->selection) && ValidAtom(stuff->target));
+ if (stuff->property != None)
+ paramsOkay &= ValidAtom(stuff->property);
+@@ -1103,7 +1501,7 @@
+ while ((i < NumCurrentSelections) &&
+ CurrentSelections[i].selection != stuff->selection) i++;
+ if ((i < NumCurrentSelections) &&
+- (CurrentSelections[i].window != None)
++ (CurrentSelections[i].window != None) && (CurrentSelections[i].client != NullClient)
+ #ifdef XCSECURITY
+ && (!client->CheckAccess ||
+ (* client->CheckAccess)(client, CurrentSelections[i].window,
+@@ -1286,11 +1684,26 @@
+ ProcOpenFont(register ClientPtr client)
+ {
+ int err;
++ char fontReq[256];
+ REQUEST(xOpenFontReq);
+
+ REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes);
+ client->errorValue = stuff->fid;
+ LEGAL_NEW_RESOURCE(stuff->fid, client);
++
++ memcpy(fontReq,(char *)&stuff[1],(stuff->nbytes<256)?stuff->nbytes:255);
++ fontReq[stuff->nbytes]=0;
++ if (strchr(fontReq,'*') || strchr(fontReq,'?'))
++ {
++ extern int nxOpenFont(ClientPtr, XID, Mask, unsigned, char*);
++#ifdef NXAGENT_FONTMATCH_DEBUG
++ fprintf(stderr, "Dispatch: ProcOpenFont try to find a common font with font pattern=%s\n",fontReq);
++#endif
++ nxagentListRemoteFonts(fontReq, nxagentMaxFontNames);
++ err = nxOpenFont(client, stuff->fid, (Mask) 0,
++ stuff->nbytes, (char *)&stuff[1]);
++ }
++ else
+ err = OpenFont(client, stuff->fid, (Mask) 0,
+ stuff->nbytes, (char *)&stuff[1]);
+ if (err == Success)
+@@ -1310,8 +1723,43 @@
+ REQUEST_SIZE_MATCH(xResourceReq);
+ pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT,
+ SecurityDestroyAccess);
+- if ( pFont != (FontPtr)NULL) /* id was valid */
++ if (pFont != (FontPtr)NULL)
+ {
++ #ifdef NXAGENT_SERVER
++
++ /*
++ * When a client closes a font the resource
++ * should not be lost if the reference counter
++ * is not 0, otherwise the server will not be
++ * able to find this font looping through the
++ * resources.
++ */
++
++ if (pFont -> refcnt > 0)
++ {
++ if (nxagentFindClientResource(serverClient -> index, RT_NX_FONT, pFont) == 0)
++ {
++ #ifdef TEST
++ fprintf(stderr, "ProcCloseFont: Switching resource for font at [%p].\n",
++ (void *) pFont);
++ #endif
++
++ nxagentFontPriv(pFont) -> mirrorID = FakeClientID(serverClient -> index);
++
++ AddResource(nxagentFontPriv(pFont) -> mirrorID, RT_NX_FONT, pFont);
++
++ }
++ #ifdef TEST
++ else
++ {
++ fprintf(stderr, "ProcCloseFont: Found duplicated font at [%p], "
++ "resource switching skipped.\n", (void *) pFont);
++ }
++ #endif
++ }
++
++ #endif
++
+ FreeResource(stuff->id, RT_NONE);
+ return(client->noClientException);
+ }
+@@ -1332,6 +1780,8 @@
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ client->errorValue = stuff->id; /* EITHER font or gc */
++
++ pFont = NULL;
+ pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT,
+ SecurityReadAccess);
+ if (!pFont)
+@@ -1347,6 +1797,33 @@
+ pFont = pGC->font;
+ }
+
++/* test
++{
++ Atom name_atom, value_atom;
++ int nprops;
++ FontPropPtr props;
++ int i;
++ char *name;
++
++ name_atom = MakeAtom("FONT", 4, True);
++ value_atom = 0L;
++
++ nprops = pFont->info.nprops;
++ props = pFont->info.props;
++
++ for (i = 0; i < nprops; i++)
++ if (props[i].name == name_atom) {
++ value_atom = props[i].value;
++ break;
++ }
++
++ if (!value_atom) return (BadFont);
++
++ name = (char *)NameForAtom(value_atom);
++ fprintf(stderr, "QueryFont: font name [%s]\n",name);
++}
++ end test */
++
+ {
+ xCharInfo *pmax = FONTINKMAX(pFont);
+ xCharInfo *pmin = FONTINKMIN(pFont);
+@@ -1364,6 +1841,7 @@
+ rlength = sizeof(xQueryFontReply) +
+ FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) +
+ nprotoxcistructs * sizeof(xCharInfo);
++ reply = NULL;
+ reply = (xQueryFontReply *)ALLOCATE_LOCAL(rlength);
+ if(!reply)
+ {
+@@ -1434,10 +1912,18 @@
+ int
+ ProcListFonts(register ClientPtr client)
+ {
++ char tmp[256];
++
+ REQUEST(xListFontsReq);
+
+ REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes);
++ memcpy(tmp,(unsigned char *) &stuff[1],(stuff->nbytes<256)?stuff->nbytes:255);
++ tmp[stuff->nbytes]=0;
+
++#ifdef NXAGENT_FONTMATCH_DEBUG
++ fprintf(stderr, "Dispatch: ListFont request with pattern %s max_names=%d\n",tmp,stuff->maxNames);
++#endif
++ nxagentListRemoteFonts(tmp, stuff -> maxNames < nxagentMaxFontNames ? nxagentMaxFontNames : stuff->maxNames);
+ return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes,
+ stuff->maxNames);
+ }
+@@ -1445,10 +1931,18 @@
+ int
+ ProcListFontsWithInfo(register ClientPtr client)
+ {
++ char tmp[256];
+ REQUEST(xListFontsWithInfoReq);
+
+ REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes);
+
++ memcpy(tmp,(unsigned char *) &stuff[1],(stuff->nbytes<256)?stuff->nbytes:255);
++ tmp[stuff->nbytes]=0;
++#ifdef NXAGENT_FONTMATCH_DEBUG
++ fprintf(stderr, "Dispatch: ListFont with info request with pattern %s max_names=%d\n",tmp,stuff->maxNames);
++#endif
++ nxagentListRemoteFonts(tmp, stuff -> maxNames < nxagentMaxFontNames ? nxagentMaxFontNames :stuff->maxNames);
++
+ return StartListFontsWithInfo(client, stuff->nbytes,
+ (unsigned char *) &stuff[1], stuff->maxNames);
+ }
+@@ -1535,6 +2029,40 @@
+ SecurityDestroyAccess);
+ if (pMap)
+ {
++ #ifdef NXAGENT_SERVER
++
++ /*
++ * When a client releases a pixmap the resource
++ * should not be lost if the reference counter
++ * is not 0, otherwise the server will not be
++ * able to find this pixmap looping through the
++ * resources.
++ */
++
++ if (pMap -> refcnt > 0)
++ {
++ if (nxagentFindClientResource(serverClient -> index, RT_NX_PIXMAP, pMap) == 0)
++ {
++ #ifdef TEST
++ fprintf(stderr, "ProcFreePixmap: Switching resource for pixmap at [%p].\n",
++ (void *) pMap);
++ #endif
++
++ nxagentPixmapPriv(pMap) -> mid = FakeClientID(serverClient -> index);
++
++ AddResource(nxagentPixmapPriv(pMap) -> mid, RT_NX_PIXMAP, pMap);
++ }
++ #ifdef TEST
++ else
++ {
++ fprintf(stderr, "ProcFreePixmap: Found duplicated pixmap at [%p], "
++ "resource switching skipped.\n", (void *) pMap);
++ }
++ #endif
++ }
++
++ #endif
++
+ FreeResource(stuff->id, RT_NONE);
+ return(client->noClientException);
+ }
+@@ -1819,8 +2347,10 @@
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client);
+ npoint = ((client->req_len << 2) - sizeof(xPolyPointReq)) >> 2;
+ if (npoint)
++ {
+ (*pGC->ops->PolyPoint)(pDraw, pGC, stuff->coordMode, npoint,
+ (xPoint *) &stuff[1]);
++ }
+ return (client->noClientException);
+ }
+
+@@ -1842,8 +2372,10 @@
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client);
+ npoint = ((client->req_len << 2) - sizeof(xPolyLineReq)) >> 2;
+ if (npoint > 1)
++ {
+ (*pGC->ops->Polylines)(pDraw, pGC, stuff->coordMode, npoint,
+ (DDXPointPtr) &stuff[1]);
++ }
+ return(client->noClientException);
+ }
+
+@@ -1862,7 +2394,9 @@
+ return(BadLength);
+ nsegs >>= 3;
+ if (nsegs)
++ {
+ (*pGC->ops->PolySegment)(pDraw, pGC, nsegs, (xSegment *) &stuff[1]);
++ }
+ return (client->noClientException);
+ }
+
+@@ -1881,8 +2415,10 @@
+ return(BadLength);
+ nrects >>= 3;
+ if (nrects)
++ {
+ (*pGC->ops->PolyRectangle)(pDraw, pGC,
+ nrects, (xRectangle *) &stuff[1]);
++ }
+ return(client->noClientException);
+ }
+
+@@ -1901,7 +2437,9 @@
+ return(BadLength);
+ narcs /= sizeof(xArc);
+ if (narcs)
++ {
+ (*pGC->ops->PolyArc)(pDraw, pGC, narcs, (xArc *) &stuff[1]);
++ }
+ return (client->noClientException);
+ }
+
+@@ -1930,9 +2468,11 @@
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client);
+ things = ((client->req_len << 2) - sizeof(xFillPolyReq)) >> 2;
+ if (things)
++ {
+ (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape,
+ stuff->coordMode, things,
+ (DDXPointPtr) &stuff[1]);
++ }
+ return(client->noClientException);
+ }
+
+@@ -1952,8 +2492,10 @@
+ things >>= 3;
+
+ if (things)
++ {
+ (*pGC->ops->PolyFillRect) (pDraw, pGC, things,
+ (xRectangle *) &stuff[1]);
++ }
+ return (client->noClientException);
+ }
+
+@@ -1972,7 +2514,9 @@
+ return(BadLength);
+ narcs /= sizeof(xArc);
+ if (narcs)
++ {
+ (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]);
++ }
+ return (client->noClientException);
+ }
+
+@@ -3127,7 +3671,14 @@
+ stuff->backRed, stuff->backGreen, stuff->backBlue);
+
+ if (pCursor && AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor))
++ {
++ #ifdef TEST
++ fprintf(stderr, "ProcCreateCursor: Created cursor at [%p].\n", (void *) pCursor);
++ #endif
++
+ return (client->noClientException);
++ }
++
+ return BadAlloc;
+ }
+
+@@ -3243,25 +3794,68 @@
+ return BadValue;
+ }
+
+- if (blankingOption == DefaultBlanking)
++ /*
++ * The NX agent uses the screen saver procedure
++ * to monitor the user activities and launch its
++ * handlers (like timeout feature), so we can't
++ * always allow the clients to change our values.
++ */
++
++ #ifdef TEST
++ fprintf(stderr, "ProcSetScreenSaver: Called with timeout [%d] interval [%d] Blanking [%d] Exposure [%d].\n",
++ stuff -> timeout, stuff -> interval, blankingOption, exposureOption);
++ #endif
++
++ if (nxagentOption(Timeout) == 0)
++ {
++ if (blankingOption == DefaultBlanking)
++ {
+ ScreenSaverBlanking = defaultScreenSaverBlanking;
+- else
++ }
++ else
++ {
+ ScreenSaverBlanking = blankingOption;
+- if (exposureOption == DefaultExposures)
++ }
++
++ if (exposureOption == DefaultExposures)
++ {
+ ScreenSaverAllowExposures = defaultScreenSaverAllowExposures;
+- else
+- ScreenSaverAllowExposures = exposureOption;
++ }
++ else
++ {
++ ScreenSaverAllowExposures = exposureOption;
++ }
++
++ if (stuff->timeout >= 0)
++ {
++ ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND;
++ }
++ else
++ {
++ ScreenSaverTime = defaultScreenSaverTime;
++ }
++
++ if (stuff->interval >= 0)
++ {
++ ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND;
++ }
++ else
++ {
++ ScreenSaverInterval = defaultScreenSaverInterval;
++ }
++
++ SetScreenSaverTimer();
++ }
++ #ifdef TEST
+
+- if (stuff->timeout >= 0)
+- ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND;
+- else
+- ScreenSaverTime = defaultScreenSaverTime;
+- if (stuff->interval >= 0)
+- ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND;
+ else
+- ScreenSaverInterval = defaultScreenSaverInterval;
++ {
++ fprintf(stderr, "ProcSetScreenSaver: Keeping auto-disconnect timeout set to [%d] seconds.\n",
++ nxagentOption(Timeout));
++ }
++
++ #endif
+
+- SetScreenSaverTimer();
+ return (client->noClientException);
+ }
+
+@@ -3481,7 +4075,30 @@
+ client->errorValue = stuff->mode;
+ return BadValue;
+ }
+- SaveScreens(SCREEN_SAVER_FORCER, (int)stuff->mode);
++
++ /*
++ * The NX agent uses the screen saver procedure
++ * to monitor the user activities and launch its
++ * handlers (like timeout feature), so we can't
++ * always allow the clients to force the screen
++ * saver handler execution.
++ */
++
++ if (nxagentOption(Timeout) == 0)
++ {
++ SaveScreens(SCREEN_SAVER_FORCER, (int)stuff->mode);
++ }
++
++ #ifdef TEST
++
++ else
++ {
++ fprintf(stderr, "ProcForceScreenSaver: Ignoring the client request with mode [%d].\n",
++ stuff -> mode);
++ }
++
++ #endif
++
+ return client->noClientException;
+ }
+
+@@ -3525,14 +4142,34 @@
+ * then killed again, the client is really destroyed.
+ *********************/
+
+-char dispatchExceptionAtReset = DE_RESET;
+-
+ void
+ CloseDownClient(register ClientPtr client)
+ {
+ Bool really_close_down = client->clientGone ||
+ client->closeDownMode == DestroyAll;
+
++ /*
++ * There must be a better way to hook a
++ * call-back function to be called any
++ * time a client is going to be closed.
++ */
++
++ nxagentClearClipboard(client, NULL);
++
++ /*
++ * Need to reset the karma counter and
++ * get rid of the pending sync replies.
++ */
++
++ nxagentWakeupByReset(client);
++
++ /*
++ * Check if the client
++ * is a shadow nxagent.
++ */
++
++ nxagentCheckIfShadowAgent(client);
++
+ if (!client->clientGone)
+ {
+ /* ungrab server if grabbing client dies */
+@@ -3673,7 +4310,7 @@
+ client->numSaved = 0;
+ client->saveSet = (SaveSetElt *)NULL;
+ client->noClientException = Success;
+-#ifdef DEBUG
++#ifdef LOG_DEBUG
+ client->requestLogIndex = 0;
+ #endif
+ client->requestVector = InitialVector;
+@@ -3746,6 +4383,13 @@
+ else
+ ppriv->ptr = (pointer)NULL;
+ }
++
++ /*
++ * Initialize the private members.
++ */
++
++ nxagentInitClientPrivates(client);
++
+ return 1;
+ }
+
diff --git a/doc/nx-X11_vs_XOrg69_patches/NXdixfonts.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/NXdixfonts.c.NX.patch
new file mode 100644
index 000000000..f491948f0
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/NXdixfonts.c.NX.patch
@@ -0,0 +1,892 @@
+--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXdixfonts.c.X.original 2015-02-13 14:03:44.744441510 +0100
++++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXdixfonts.c 2015-02-13 14:03:44.744441510 +0100
+@@ -1,3 +1,20 @@
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NXAGENT, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /* $XdotOrg: xc/programs/Xserver/dix/dixfonts.c,v 1.8 2005/07/03 08:53:38 daniels Exp $ */
+ /* $XFree86: xc/programs/Xserver/dix/dixfonts.c,v 3.28 2003/11/08 02:02:03 dawes Exp $ */
+ /************************************************************************
+@@ -68,12 +85,84 @@
+ #include "dixfontstr.h"
+ #include "closestr.h"
+
++/*
++#define NXAGENT_DEBUG
++*/
++
+ #ifdef DEBUG
+ #include <stdio.h>
+ #endif
+
++#include "Agent.h"
++#include "Font.h"
++
++#ifndef NX_TRANS_SOCKET
++
++#define NX_TRANS_SOCKET
++
++#endif
++
++#ifdef NX_TRANS_SOCKET
++
++char _NXFontPath[1024];
++
++/*
++ * Override the default font path and make
++ * it configurable at run time, based on
++ * the NX_FONT environment.
++ */
++
++static const char *_NXGetFontPath(const char *path)
++{
++ const char *fontEnv;
++
++ /*
++ * Check the environment only once.
++ */
++
++ if (*_NXFontPath != '\0')
++ {
++ return _NXFontPath;
++ }
++
++ fontEnv = getenv("NX_FONT");
++
++ if (fontEnv != NULL && *fontEnv != '\0')
++ {
++ if (strlen(fontEnv) + 1 > 1024)
++ {
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_NXGetFontPath: WARNING! Maximum length of font path exceeded.\n");
++#endif
++ goto _NXGetFontPathError;
++ }
++
++ strcpy(_NXFontPath, fontEnv);
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_NXGetFontPath: Using NX font path [%s].\n", _NXFontPath);
++#endif
++
++ return _NXFontPath;
++ }
++
++_NXGetFontPathError:
++
++ strncpy(_NXFontPath, path, 1023);
++ _NXFontPath[1023] = '\0';
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_NXGetFontPath: Using default font path [%s].\n", _NXFontPath);
++#endif
++
++ return _NXFontPath;
++}
++
++#endif
++
+ #ifdef PANORAMIX
+-#include "panoramiX.h"
++#include "../../Xext/panoramiX.h"
++#include "../../Xext/panoramiXsrv.h"
+ #endif
+
+ #ifdef LBX
+@@ -245,6 +334,9 @@
+ *newname;
+ int newlen;
+ int aliascount = 20;
++ char nxagentOrigFontName[256];
++ int nxagentOrigFontNameLen;
++
+ /*
+ * Decide at runtime what FontFormat to use.
+ */
+@@ -276,6 +368,13 @@
+
+ BitmapFormatScanlineUnit8;
+
++
++ nxagentOrigFontNameLen = (c -> origFontNameLen < 256) ? c -> origFontNameLen : 255;
++
++ memcpy(nxagentOrigFontName, c -> origFontName, nxagentOrigFontNameLen);
++
++ nxagentOrigFontName[nxagentOrigFontNameLen] = 0;
++
+ if (client->clientGone)
+ {
+ if (c->current_fpe < c->num_fpes)
+@@ -324,6 +423,9 @@
+ if (!c->slept) {
+ c->slept = TRUE;
+ ClientSleep(client, (ClientSleepProcPtr)doOpenFont, (pointer) c);
++#ifdef NXAGENT_DEBUG
++ fprintf(stderr, " NXdixfonts: doOpenFont: client [%lx] sleeping.\n", client);
++#endif
+ }
+ return TRUE;
+ }
+@@ -352,10 +454,15 @@
+ pScr = screenInfo.screens[i];
+ if (pScr->RealizeFont)
+ {
+- if (!(*pScr->RealizeFont) (pScr, pfont))
++
++ /* NXAGENT uses useless screen pointer to pass the original font name
++ * to realizeFont, could be a source of problems in the future.
++ */
++
++ if (!(*pScr->RealizeFont) ((ScreenPtr)nxagentOrigFontName, pfont))
+ {
+ CloseFont (pfont, (Font) 0);
+- err = AllocError;
++ err=BadFontName;
+ goto bail;
+ }
+ }
+@@ -365,8 +472,19 @@
+ err = AllocError;
+ goto bail;
+ }
++ if( nxagentFontPriv(pfont) -> mirrorID == 0 )
++ {
++ extern RESTYPE RT_NX_FONT;
++
++ nxagentFontPriv(pfont) -> mirrorID = FakeClientID(0);
++ if (!AddResource(nxagentFontPriv(pfont) -> mirrorID, RT_NX_FONT, (pointer) pfont)) {
++ FreeResource(c->fontid, RT_NONE);
++ err = AllocError;
++ goto bail;
++ }
++ }
+ if (patternCache && pfont != c->non_cachable_font)
+- CacheFontPattern(patternCache, c->origFontName, c->origFontNameLen,
++ CacheFontPattern(patternCache, nxagentOrigFontName, nxagentOrigFontNameLen,
+ pfont);
+ bail:
+ if (err != Successful && c->client != serverClient) {
+@@ -374,7 +492,12 @@
+ c->fontid, FontToXError(err));
+ }
+ if (c->slept)
++ {
+ ClientWakeup(c->client);
++#ifdef NXAGENT_DEBUG
++ fprintf(stderr, " NXdixfonts: doOpenFont: client [%lx] wakeup.\n", client);
++#endif
++ }
+ for (i = 0; i < c->num_fpes; i++) {
+ FreeFPE(c->fpe_list[i]);
+ }
+@@ -502,7 +625,10 @@
+ LbxFreeFontTag(pfont);
+ #endif
+ #ifdef XF86BIGFONT
+- XF86BigfontFreeFontShm(pfont);
++ {
++ extern void XF86BigfontFreeFontShm(FontPtr);
++ XF86BigfontFreeFontShm(pfont);
++ }
+ #endif
+ fpe = pfont->fpe;
+ (*fpe_functions[fpe->type].close_font) (fpe, pfont);
+@@ -631,6 +757,9 @@
+ ClientSleep(client,
+ (ClientSleepProcPtr)doListFontsAndAliases,
+ (pointer) c);
++#ifdef NXAGENT_DEBUG
++ fprintf(stderr, " NXdixfonts: doListFont (1): client [%lx] sleeping.\n", client);
++#endif
+ }
+ return TRUE;
+ }
+@@ -677,6 +806,12 @@
+ (ClientSleepProcPtr)doListFontsAndAliases,
+ (pointer) c);
+ c->slept = TRUE;
++#ifdef NXAGENT_DEBUG
++ fprintf(stderr, " NXdixfonts: doListFont (2): client [%lx] sleeping.\n", client);
++#endif
++#ifdef NXAGENT_DEBUG
++ fprintf(stderr, " NXdixfonts: doListFont (3): client [%lx] sleeping.\n", client);
++#endif
+ }
+ return TRUE;
+ }
+@@ -813,6 +948,24 @@
+ reply.nFonts--;
+ else
+ {
++ {
++ /* dirty hack: don't list to client fonts not existing on the remote side */
++ char tmp[256];
++
++ memcpy(tmp, names->names[i], names->length[i]);
++ tmp[ names->length[i] ] = 0;
++
++ if (nxagentFontLookUp(tmp) == 0)
++ {
++#ifdef NXAGENT_FONTMATCH_DEBUG
++ fprintf(stderr, "doListFontsAndAliases:\n");
++ fprintf(stderr, " removing font: %s \n", tmp);
++#endif
++ reply.nFonts--;
++ stringLens -= names->length[i];
++ continue;
++ }
++ }
+ *bufptr++ = names->length[i];
+ memmove( bufptr, names->names[i], names->length[i]);
+ bufptr += names->length[i];
+@@ -827,7 +980,12 @@
+
+ bail:
+ if (c->slept)
++ {
+ ClientWakeup(client);
++#ifdef NXAGENT_DEBUG
++ fprintf(stderr, " NXdixfonts: doListFont: client [%lx] wakeup.\n", client);
++#endif
++ }
+ for (i = 0; i < c->num_fpes; i++)
+ FreeFPE(c->fpe_list[i]);
+ xfree(c->fpe_list);
+@@ -862,7 +1020,7 @@
+ xfree(c);
+ return BadAlloc;
+ }
+- c->names = MakeFontNamesRecord(max_names < 100 ? max_names : 100);
++ c->names = MakeFontNamesRecord(max_names < nxagentMaxFontNames ? max_names : nxagentMaxFontNames);
+ if (!c->names)
+ {
+ xfree(c->fpe_list);
+@@ -933,6 +1091,9 @@
+ {
+ ClientSleep(client, (ClientSleepProcPtr)doListFontsWithInfo, c);
+ c->slept = TRUE;
++#ifdef NXAGENT_DEBUG
++ fprintf(stderr, " NXdixfonts: doListFontWinfo (1): client [%lx] sleeping.\n", client);
++#endif
+ }
+ return TRUE;
+ }
+@@ -954,6 +1115,9 @@
+ (ClientSleepProcPtr)doListFontsWithInfo,
+ c);
+ c->slept = TRUE;
++#ifdef NXAGENT_DEBUG
++ fprintf(stderr, " NXdixfonts: doListFontWinfo (2): client [%lx] sleeping.\n", client);
++#endif
+ }
+ return TRUE;
+ }
+@@ -1035,6 +1199,23 @@
+ }
+ else if (err == Successful)
+ {
++
++ if (c->haveSaved)
++ {
++ numFonts = c->savedNumFonts;
++ name = c->savedName;
++ namelen = strlen(name);
++ }
++
++ if (nxagentFontLookUp(name) == 0)
++ {
++#ifdef NXAGENT_FONTMATCH_DEBUG
++ fprintf(stderr, "doListFontsAndAliases (with info):\n");
++ fprintf(stderr, " removing font: %s \n", name);
++#endif
++ continue;
++ }
++
+ length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp);
+ reply = c->reply;
+ if (c->length < length)
+@@ -1048,12 +1229,6 @@
+ c->reply = reply;
+ c->length = length;
+ }
+- if (c->haveSaved)
+- {
+- numFonts = c->savedNumFonts;
+- name = c->savedName;
+- namelen = strlen(name);
+- }
+ reply->type = X_Reply;
+ reply->length = (sizeof *reply - sizeof(xGenericReply) +
+ pFontInfo->nprops * sizeof(xFontProp) +
+@@ -1100,7 +1275,12 @@
+ WriteSwappedDataToClient(client, length, &finalReply);
+ bail:
+ if (c->slept)
++ {
+ ClientWakeup(client);
++#ifdef NXAGENT_DEBUG
++ fprintf(stderr, " NXdixfonts: doListFontWinfo: client [%lx] wakeup.\n", client);
++#endif
++ }
+ for (i = 0; i < c->num_fpes; i++)
+ FreeFPE(c->fpe_list[i]);
+ xfree(c->reply);
+@@ -1347,6 +1527,11 @@
+ err = BadAlloc;
+ goto bail;
+ }
++
++ pGC->tileIsPixel = TRUE;
++ pGC->tile.pixel = 0;
++ pGC->stipple = NullPixmap;
++
+ if ((err = CopyGC(c->pGC, pGC, GCFunction |
+ GCPlaneMask | GCForeground |
+ GCBackground | GCFillStyle |
+@@ -1371,6 +1556,9 @@
+ ClientSleep(client,
+ (ClientSleepProcPtr)doPolyText,
+ (pointer) c);
++#ifdef NXAGENT_DEBUG
++ fprintf(stderr, " NXdixfonts: doPolyText (1): client [%lx] sleeping.\n", client);
++#endif
+
+ /* Set up to perform steps 3 and 4 */
+ client_state = START_SLEEP;
+@@ -1419,6 +1607,9 @@
+ if (c->slept)
+ {
+ ClientWakeup(c->client);
++#ifdef NXAGENT_DEBUG
++ fprintf(stderr, " NXdixfonts: doPolytext: client [%lx] wakeup.\n", client);
++#endif
+ ChangeGC(c->pGC, clearGCmask, clearGC);
+
+ /* Unreference the font from the scratch GC */
+@@ -1535,6 +1726,11 @@
+ err = BadAlloc;
+ goto bail;
+ }
++
++ pGC->tileIsPixel = TRUE;
++ pGC->tile.pixel = 0;
++ pGC->stipple = NullPixmap;
++
+ if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask |
+ GCForeground | GCBackground | GCFillStyle |
+ GCTile | GCStipple | GCTileStipXOrigin |
+@@ -1553,6 +1749,10 @@
+
+ c->slept = TRUE;
+ ClientSleep(client, (ClientSleepProcPtr)doImageText, (pointer) c);
++#ifdef NXAGENT_DEBUG
++ fprintf(stderr, " NXdixfonts: doImageText (1): client [%lx] sleeping.\n", client);
++#endif
++
+ }
+ return TRUE;
+ }
+@@ -1575,6 +1775,9 @@
+ if (c->slept)
+ {
+ ClientWakeup(c->client);
++#ifdef NXAGENT_DEBUG
++ fprintf(stderr, " NXdixfonts: doImageText: client [%lx] wakeup.\n", client);
++#endif
+ ChangeGC(c->pGC, clearGCmask, clearGC);
+
+ /* Unreference the font from the scratch GC */
+@@ -1751,11 +1954,13 @@
+ err = (*fpe_functions[fpe->type].init_fpe) (fpe);
+ if (err != Successful)
+ {
++ #ifndef NXAGENT_SERVER
+ if (persist)
+ {
+ ErrorF("Could not init font path element %s, removing from list!\n",
+ fpe->name);
+ }
++ #endif
+ xfree (fpe->name);
+ xfree (fpe);
+ }
+@@ -1817,11 +2022,19 @@
+ bad;
+
+ /* get enough for string, plus values -- use up commas */
++#ifdef NX_TRANS_SOCKET
++ len = strlen(_NXGetFontPath(path)) + 1;
++#else
+ len = strlen(path) + 1;
++#endif
+ nump = cp = newpath = (unsigned char *) ALLOCATE_LOCAL(len);
+ if (!newpath)
+ return BadAlloc;
++#ifdef NX_TRANS_SOCKET
++ pp = (unsigned char *) _NXGetFontPath(path);
++#else
+ pp = (unsigned char *) path;
++#endif
+ cp++;
+ while (*pp) {
+ if (*pp == ',') {
+@@ -2148,3 +2361,445 @@
+ }
+
+ #endif
++
++
++typedef struct
++{
++ LFclosurePtr c;
++ OFclosurePtr oc;
++} nxFs,*nxFsPtr;
++
++static Bool
++#if NeedFunctionPrototypes
++nxdoListFontsAndAliases(ClientPtr client, nxFsPtr fss)
++#else
++nxdoListFontsAndAliases(client, fss)
++ ClientPtr client;
++ nxFsPtr fss;
++#endif
++{
++ LFclosurePtr c=fss->c;
++ OFclosurePtr oc=fss->oc;
++ FontPathElementPtr fpe;
++ int err = Successful;
++ char *name, *resolved=NULL;
++ int namelen, resolvedlen;
++ int i;
++ int aliascount = 0;
++ char tmp[256];
++ tmp[0]=0;
++ if (client->clientGone)
++ {
++ if (c->current.current_fpe < c->num_fpes)
++ {
++ fpe = c->fpe_list[c->current.current_fpe];
++ (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
++ }
++ err = Successful;
++ goto bail;
++ }
++
++ if (!c->current.patlen)
++ goto finish;
++
++ while (c->current.current_fpe < c->num_fpes) {
++ fpe = c->fpe_list[c->current.current_fpe];
++ err = Successful;
++
++ if (!fpe_functions[fpe->type].start_list_fonts_and_aliases)
++ {
++ /* This FPE doesn't support/require list_fonts_and_aliases */
++
++ err = (*fpe_functions[fpe->type].list_fonts)
++ ((pointer) c->client, fpe, c->current.pattern,
++ c->current.patlen, c->current.max_names - c->names->nnames,
++ c->names);
++
++ if (err == Suspended) {
++ if (!c->slept) {
++ c->slept = TRUE;
++ ClientSleep(client,
++ (ClientSleepProcPtr)nxdoListFontsAndAliases,
++ (pointer) fss);
++#ifdef NXAGENT_DEBUG
++ fprintf(stderr, " NXdixfonts: nxdoListFont (1): client [%lx] sleeping.\n", client);
++#endif
++ }
++ return TRUE;
++ }
++
++ err = BadFontName;
++ }
++ else
++ {
++ /* Start of list_fonts_and_aliases functionality. Modeled
++ after list_fonts_with_info in that it resolves aliases,
++ except that the information collected from FPEs is just
++ names, not font info. Each list_next_font_or_alias()
++ returns either a name into name/namelen or an alias into
++ name/namelen and its target name into resolved/resolvedlen.
++ The code at this level then resolves the alias by polling
++ the FPEs. */
++
++ if (!c->current.list_started) {
++ err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases)
++ ((pointer) c->client, fpe, c->current.pattern,
++ c->current.patlen, c->current.max_names - c->names->nnames,
++ &c->current.private);
++ if (err == Suspended) {
++ if (!c->slept) {
++ ClientSleep(client,
++ (ClientSleepProcPtr)nxdoListFontsAndAliases,
++ (pointer) fss);
++ c->slept = TRUE;
++#ifdef NXAGENT_DEBUG
++ fprintf(stderr, " NXdixfonts: nxdoListFont (2): client [%lx] sleeping.\n", client);
++#endif
++ }
++ return TRUE;
++ }
++ if (err == Successful)
++ c->current.list_started = TRUE;
++ }
++ if (err == Successful) {
++ char *tmpname;
++ name = 0;
++ err = (*fpe_functions[fpe->type].list_next_font_or_alias)
++ ((pointer) c->client, fpe, &name, &namelen, &tmpname,
++ &resolvedlen, c->current.private);
++ if (err == Suspended) {
++ if (!c->slept) {
++ ClientSleep(client,
++ (ClientSleepProcPtr)nxdoListFontsAndAliases,
++ (pointer) fss);
++ c->slept = TRUE;
++#ifdef NXAGENT_DEBUG
++ fprintf(stderr, " NXdixfonts: nxdoListFont (3): client [%lx] sleeping.\n", client);
++#endif
++ }
++ return TRUE;
++ }
++ if (err == FontNameAlias) {
++ if (resolved) xfree(resolved);
++ resolved = (char *) xalloc(resolvedlen + 1);
++ if (resolved)
++ {
++ memmove(resolved, tmpname, resolvedlen);
++ resolved[resolvedlen] = '\0';
++ }
++ }
++ }
++
++ if (err == Successful)
++ {
++ if (c->haveSaved)
++ {
++ if (c->savedName)
++ {
++ memcpy(tmp,c->savedName,c->savedNameLen>255?255:c->savedNameLen);
++ tmp[c->savedNameLen>255?256:c->savedNameLen]=0;
++ if (nxagentFontLookUp(tmp))
++ break;
++ else tmp[0]=0;
++ }
++ }
++ else
++ {
++ memcpy(tmp,name,namelen>255?255:namelen);
++ tmp[namelen>255?256:namelen]=0;
++ if (nxagentFontLookUp(tmp))
++ break;
++ else tmp[0]=0;
++ }
++ }
++
++ /*
++ * When we get an alias back, save our state and reset back to
++ * the start of the FPE looking for the specified name. As
++ * soon as a real font is found for the alias, pop back to the
++ * old state
++ */
++ else if (err == FontNameAlias) {
++ char tmp_pattern[XLFDMAXFONTNAMELEN];
++ /*
++ * when an alias recurses, we need to give
++ * the last FPE a chance to clean up; so we call
++ * it again, and assume that the error returned
++ * is BadFontName, indicating the alias resolution
++ * is complete.
++ */
++ memmove(tmp_pattern, resolved, resolvedlen);
++ if (c->haveSaved)
++ {
++ char *tmpname;
++ int tmpnamelen;
++
++ tmpname = 0;
++ (void) (*fpe_functions[fpe->type].list_next_font_or_alias)
++ ((pointer) c->client, fpe, &tmpname, &tmpnamelen,
++ &tmpname, &tmpnamelen, c->current.private);
++ if (--aliascount <= 0)
++ {
++ err = BadFontName;
++ goto ContBadFontName;
++ }
++ }
++ else
++ {
++ c->saved = c->current;
++ c->haveSaved = TRUE;
++ if (c->savedName)
++ xfree(c->savedName);
++ c->savedName = (char *)xalloc(namelen + 1);
++ if (c->savedName)
++ {
++ memmove(c->savedName, name, namelen);
++ c->savedName[namelen] = '\0';
++ }
++ c->savedNameLen = namelen;
++ aliascount = 20;
++ }
++ memmove(c->current.pattern, tmp_pattern, resolvedlen);
++ c->current.patlen = resolvedlen;
++ c->current.max_names = c->names->nnames + 1;
++ c->current.current_fpe = -1;
++ c->current.private = 0;
++ err = BadFontName;
++ }
++ }
++ /*
++ * At the end of this FPE, step to the next. If we've finished
++ * processing an alias, pop state back. If we've collected enough
++ * font names, quit.
++ */
++ if (err == BadFontName) {
++ ContBadFontName: ;
++ c->current.list_started = FALSE;
++ c->current.current_fpe++;
++ err = Successful;
++ if (c->haveSaved)
++ {
++ if (c->names->nnames == c->current.max_names ||
++ c->current.current_fpe == c->num_fpes) {
++ c->haveSaved = FALSE;
++ c->current = c->saved;
++ /* Give the saved namelist a chance to clean itself up */
++ continue;
++ }
++ }
++ if (c->names->nnames == c->current.max_names)
++ break;
++ }
++ }
++
++ /*
++ * send the reply
++ */
++bail:
++finish:
++ if (strlen(tmp))
++ {
++#ifdef NXAGENT_FONTMATCH_DEBUG
++ fprintf(stderr, "nxListFont changed (0) font to %s\n",tmp);
++#endif
++ memcpy(oc->fontname, tmp, strlen(tmp));
++ oc->fnamelen = strlen(tmp);
++
++ oc->origFontName = oc->fontname;
++ oc->origFontNameLen = oc->fnamelen;
++
++ }
++ else
++ {
++ for (i = 0; i < c->names->nnames; i++)
++ {
++ if (c->names->length[i] > 255)
++ continue;
++ else
++ {
++ memcpy(tmp, c->names->names[i], c->names->length[i]);
++ tmp[ c->names->length[i] ] = 0;
++ if (nxagentFontLookUp(tmp) == 0)
++ continue;
++ memcpy(oc->fontname, tmp, strlen(tmp));
++ oc->fnamelen = strlen(tmp);
++
++ oc->origFontName = oc->fontname;
++ oc->origFontNameLen = oc->fnamelen;
++
++#ifdef NXAGENT_FONTMATCH_DEBUG
++ fprintf(stderr, "nxListFont changed (1) font to %s\n",tmp);
++#endif
++ break;
++ }
++ }
++ }
++
++ if (c->slept)
++ {
++ ClientWakeup(client);
++#ifdef NXAGENT_DEBUG
++ fprintf(stderr, " NXdixfonts: nxdoListFont: client [%lx] wakeup.\n", client);
++#endif
++ }
++ for (i = 0; i < c->num_fpes; i++)
++ FreeFPE(c->fpe_list[i]);
++ xfree(c->fpe_list);
++ if (c->savedName) xfree(c->savedName);
++ FreeFontNames(c->names);
++ xfree(c);
++ xfree(fss);
++ if (resolved) xfree(resolved);
++
++ return doOpenFont(client, oc);
++}
++
++int
++nxOpenFont(client, fid, flags, lenfname, pfontname)
++ ClientPtr client;
++ XID fid;
++ Mask flags;
++ unsigned lenfname;
++ char *pfontname;
++{
++ nxFsPtr fss;
++ LFclosurePtr c;
++ OFclosurePtr oc;
++ int i;
++ FontPtr cached = (FontPtr)0;
++
++#ifdef FONTDEBUG
++ char *f;
++ f = (char *)xalloc(lenfname + 1);
++ memmove(f, pfontname, lenfname);
++ f[lenfname] = '\0';
++ ErrorF("OpenFont: fontname is \"%s\"\n", f);
++ xfree(f);
++#endif
++ if (!lenfname || lenfname > XLFDMAXFONTNAMELEN)
++ return BadName;
++ if (patternCache)
++ {
++
++ /*
++ ** Check name cache. If we find a cached version of this font that
++ ** is cachable, immediately satisfy the request with it. If we find
++ ** a cached version of this font that is non-cachable, we do not
++ ** satisfy the request with it. Instead, we pass the FontPtr to the
++ ** FPE's open_font code (the fontfile FPE in turn passes the
++ ** information to the rasterizer; the fserve FPE ignores it).
++ **
++ ** Presumably, the font is marked non-cachable because the FPE has
++ ** put some licensing restrictions on it. If the FPE, using
++ ** whatever logic it relies on, determines that it is willing to
++ ** share this existing font with the client, then it has the option
++ ** to return the FontPtr we passed it as the newly-opened font.
++ ** This allows the FPE to exercise its licensing logic without
++ ** having to create another instance of a font that already exists.
++ */
++
++ cached = FindCachedFontPattern(patternCache, pfontname, lenfname);
++ if (cached && cached->info.cachable)
++ {
++ if (!AddResource(fid, RT_FONT, (pointer) cached))
++ return BadAlloc;
++ cached->refcnt++;
++ return Success;
++ }
++ }
++ if (!(fss = (nxFsPtr) xalloc(sizeof(nxFs))))
++ return BadAlloc;
++
++ if (!(c = (LFclosurePtr) xalloc(sizeof *c)))
++ {
++ xfree(fss);
++ return BadAlloc;
++ }
++ c->fpe_list = (FontPathElementPtr *)
++ xalloc(sizeof(FontPathElementPtr) * num_fpes);
++ if (!c->fpe_list) {
++ xfree(c);
++ xfree(fss);
++ return BadAlloc;
++ }
++ c->names = MakeFontNamesRecord(100);
++ if (!c->names)
++ {
++ xfree(c->fpe_list);
++ xfree(c);
++ xfree(fss);
++ return BadAlloc;
++ }
++ memmove( c->current.pattern, pfontname, lenfname);
++ for (i = 0; i < num_fpes; i++) {
++ c->fpe_list[i] = font_path_elements[i];
++ UseFPE(c->fpe_list[i]);
++ }
++ c->client = client;
++ c->num_fpes = num_fpes;
++ c->current.patlen = lenfname;
++ c->current.current_fpe = 0;
++ c->current.max_names = nxagentMaxFontNames;
++ c->current.list_started = FALSE;
++ c->current.private = 0;
++ c->haveSaved = FALSE;
++ c->slept = FALSE;
++ c->savedName = 0;
++
++ oc = (OFclosurePtr) xalloc(sizeof(OFclosureRec));
++ if (!oc)
++ {
++ for (i = 0; i < c->num_fpes; i++)
++ FreeFPE(c->fpe_list[i]);
++ xfree(c->fpe_list);
++ xfree(c);
++ xfree(fss);
++ return BadAlloc;
++ }
++ oc->fontname = (char *) xalloc(256);/* I don't want to deal with future reallocs errors */
++ oc->origFontName = pfontname;
++ oc->origFontNameLen = lenfname;
++ if (!oc->fontname) {
++ for (i = 0; i < c->num_fpes; i++)
++ FreeFPE(c->fpe_list[i]);
++ xfree(c->fpe_list);
++ xfree(c);
++ xfree(oc);
++ xfree(fss);
++ return BadAlloc;
++ }
++ /*
++ * copy the current FPE list, so that if it gets changed by another client
++ * while we're blocking, the request still appears atomic
++ */
++ oc->fpe_list = (FontPathElementPtr *)
++ xalloc(sizeof(FontPathElementPtr) * num_fpes);
++ if (!oc->fpe_list) {
++ xfree(oc->fontname);
++ xfree(oc);
++ for (i = 0; i < c->num_fpes; i++)
++ FreeFPE(c->fpe_list[i]);
++ xfree(c->fpe_list);
++ xfree(c);
++ xfree(fss);
++ return BadAlloc;
++ }
++ memmove(oc->fontname, pfontname, lenfname);
++ for (i = 0; i < num_fpes; i++) {
++ oc->fpe_list[i] = font_path_elements[i];
++ UseFPE(oc->fpe_list[i]);
++ }
++ oc->client = client;
++ oc->fontid = fid;
++ oc->current_fpe = 0;
++ oc->num_fpes = num_fpes;
++ oc->fnamelen = lenfname;
++ oc->slept = FALSE;
++ oc->flags = flags;
++ oc->non_cachable_font = cached;
++ fss->c=c;
++ fss->oc=oc;
++ nxdoListFontsAndAliases(client, fss);
++ return Success;
++}
++
diff --git a/doc/nx-X11_vs_XOrg69_patches/NXevents.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/NXevents.c.NX.patch
new file mode 100644
index 000000000..f2f9e37ee
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/NXevents.c.NX.patch
@@ -0,0 +1,648 @@
+--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXevents.c.X.original 2015-02-13 14:03:44.744441510 +0100
++++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXevents.c 2015-02-10 19:13:13.788686485 +0100
+@@ -1,3 +1,20 @@
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NXAGENT, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /* $XdotOrg: xc/programs/Xserver/dix/events.c,v 1.17 2005/08/25 22:11:04 anholt Exp $ */
+ /* $XFree86: xc/programs/Xserver/dix/events.c,v 3.51 2004/01/12 17:04:52 tsi Exp $ */
+ /************************************************************
+@@ -116,6 +133,7 @@
+ #endif
+
+ #include <X11/X.h>
++#include "Xlib.h"
+ #include "misc.h"
+ #include "resource.h"
+ #define NEED_EVENTS
+@@ -163,7 +181,22 @@
+
+ #include "dixevents.h"
+ #include "dixgrabs.h"
+-#include "dispatch.h"
++#include "../../dix/dispatch.h"
++
++#include "NXlib.h"
++
++#include "Events.h"
++#include "Windows.h"
++#include "Args.h"
++
++#ifdef NX_DEBUG_INPUT
++extern int nxagentDebugInput;
++extern int nxagentDebugInputDevices;
++#endif
++
++extern Display *nxagentDisplay;
++
++extern WindowPtr nxagentLastEnteredWindow;
+
+ #define EXTENSION_EVENT_BASE 64
+
+@@ -1322,6 +1355,51 @@
+ mouse->fromPassiveGrab = autoGrab;
+ PostNewCursor();
+ CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
++
++ #ifdef NXAGENT_SERVER
++
++ /*
++ * If grab is synchronous, events are delivered to clients only if they send
++ * an AllowEvent request. If mode field in AllowEvent request is SyncPointer, the
++ * delivered event is saved in a queue and replayed later, when grab is released.
++ * We should export sync grab to X as async in order to avoid events to be
++ * queued twice, in the agent and in the X server. This solution have a drawback:
++ * replayed events are not delivered to that application that are not clients of
++ * the agent.
++ * A different solution could be to make the grab asynchronous in the agent and
++ * to export it as synchronous. But this seems to be less safe.
++ *
++ * To make internal grab asynchronous, change previous line as follows.
++ *
++ * if (nxagentOption(Rootless))
++ * {
++ * CheckGrabForSyncs(mouse, GrabModeAsync, (Bool)grab->keyboardMode);
++ * }
++ * else
++ * {
++ * CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
++ * }
++ */
++
++ if (nxagentOption(Rootless) == 1)
++ {
++ /*
++ * FIXME: We should use the correct value
++ * for the cursor. Temporarily we set it
++ * to None.
++ */
++
++ int resource = nxagentWaitForResource(NXGetCollectGrabPointerResource,
++ nxagentCollectGrabPointerPredicate);
++
++ NXCollectGrabPointer(nxagentDisplay, resource, nxagentWindow(grab -> window),
++ 1, grab -> eventMask & PointerGrabMask,
++ GrabModeAsync, GrabModeAsync, (grab -> confineTo) ?
++ nxagentWindow(grab -> confineTo) : None,
++ None, CurrentTime);
++ }
++
++ #endif
+ }
+
+ void
+@@ -1346,6 +1424,22 @@
+ if (grab->cursor)
+ FreeCursor(grab->cursor, (Cursor)0);
+ ComputeFreezes();
++
++ #ifdef NXAGENT_SERVER
++
++ if (nxagentOption(Rootless) == 1)
++ {
++ XUngrabPointer(nxagentDisplay, CurrentTime);
++
++ if (sprite.win == ROOT)
++ {
++ mouse -> button -> state &=
++ ~(Button1Mask | Button2Mask | Button3Mask |
++ Button4Mask | Button5Mask);
++ }
++ }
++
++ #endif
+ }
+
+ void
+@@ -1546,6 +1640,17 @@
+ client->errorValue = stuff->mode;
+ return BadValue;
+ }
++
++ /*
++ * This is not necessary if we export grab to X as asynchronous.
++ *
++ * if (nxagentOption(Rootless) && stuff -> mode != ReplayKeyboard &&
++ * stuff -> mode != SyncKeyboard && stuff -> mode != AsyncKeyboard)
++ * {
++ * XAllowEvents(nxagentDisplay, stuff -> mode, CurrentTime);
++ * }
++ */
++
+ return Success;
+ }
+
+@@ -1582,11 +1687,28 @@
+ int i;
+ int type;
+
+-#ifdef DEBUG
++#ifdef NX_DEBUG_INPUT
++ if (grab && nxagentDebugInput && grab->window)
++ {
++ fprintf(stderr, "TryClientEvents: Grab window is [0x%x].\n",
++ (unsigned int)grab->window->drawable.id);
++ if (!SameClient(grab, client))
++ fprintf(stderr, "TryClientEvents: Events are going to be "
++ "discarded.\n");
++ }
++#endif
++#if defined(DEBUG) || defined(NX_DEBUG_INPUT)
++#ifdef NX_DEBUG_INPUT
++ if (nxagentDebugInput == 1)
++ fprintf(stderr, "Event([%d, %d], mask=0x%x), client=%d",
++ pEvents->u.u.type, pEvents->u.u.detail, (unsigned int)mask,
++ client->index);
++#else
+ if (debug_events) ErrorF(
+ "Event([%d, %d], mask=0x%x), client=%d",
+ pEvents->u.u.type, pEvents->u.u.detail, mask, client->index);
+ #endif
++#endif
+ if ((client) && (client != serverClient) && (!client->clientGone) &&
+ ((filter == CantBeFiltered) || (mask & filter)))
+ {
+@@ -1600,10 +1722,17 @@
+ if (WID(inputInfo.pointer->valuator->motionHintWindow) ==
+ pEvents->u.keyButtonPointer.event)
+ {
+-#ifdef DEBUG
++#if defined(DEBUG) || defined(NX_DEBUG_INPUT)
++#ifdef NX_DEBUG_INPUT
++ if (nxagentDebugInput == 1)
++ {
++ fprintf(stderr,"\nmotionHintWindow == keyButtonPointer.event\n");
++ }
++#else
+ if (debug_events) ErrorF("\n");
+ fprintf(stderr,"motionHintWindow == keyButtonPointer.event\n");
+ #endif
++#endif
+ return 1; /* don't send, but pretend we did */
+ }
+ pEvents->u.u.detail = NotifyHint;
+@@ -1640,16 +1769,26 @@
+ }
+
+ WriteEventsToClient(client, count, pEvents);
+-#ifdef DEBUG
++#if defined(DEBUG) || defined(NX_DEBUG_INPUT)
++#ifdef NX_DEBUG_INPUT
++ if (nxagentDebugInput == 1)
++ fprintf(stderr, " delivered\n");
++#else
+ if (debug_events) ErrorF( " delivered\n");
+ #endif
++#endif
+ return 1;
+ }
+ else
+ {
+-#ifdef DEBUG
++#if defined(DEBUG) || defined(NX_DEBUG_INPUT)
++#ifdef NX_DEBUG_INPUT
++ if (nxagentDebugInput == 1)
++ fprintf(stderr, "\n");
++#else
+ if (debug_events) ErrorF("\n");
+ #endif
++#endif
+ return 0;
+ }
+ }
+@@ -1727,6 +1866,12 @@
+ tempGrab.pointerMode = GrabModeAsync;
+ tempGrab.confineTo = NullWindow;
+ tempGrab.cursor = NullCursor;
++ #ifdef NX_DEBUG_INPUT
++ if (nxagentDebugInputDevices == 1)
++ {
++ fprintf(stderr, "DeliverEventsToWindow: Activating passive grab on pointer.\n");
++ }
++ #endif
+ (*inputInfo.pointer->ActivateGrab)(inputInfo.pointer, &tempGrab,
+ currentTime, TRUE);
+ }
+@@ -1999,7 +2144,26 @@
+ BoxRec box;
+
+ spriteTraceGood = 1; /* root window still there */
+- pWin = ROOT->firstChild;
++
++ if (nxagentOption(Rootless))
++ {
++ if (nxagentLastEnteredWindow == NULL)
++ {
++ return ROOT;
++ }
++
++ pWin = ROOT->lastChild;
++
++ while (pWin && pWin != ROOT->firstChild && pWin != nxagentLastEnteredWindow)
++ {
++ pWin = pWin->prevSib;
++ }
++ }
++ else
++ {
++ pWin = ROOT->firstChild;
++ }
++
+ while (pWin)
+ {
+ if ((pWin->mapped) &&
+@@ -2090,13 +2254,22 @@
+ ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y);
+ #endif
+ sprite.hotPhys = sprite.hot;
+- if ((sprite.hotPhys.x != XE_KBPTR.rootX) ||
+- (sprite.hotPhys.y != XE_KBPTR.rootY))
+- {
+- (*sprite.hotPhys.pScreen->SetCursorPosition)(
+- sprite.hotPhys.pScreen,
+- sprite.hotPhys.x, sprite.hotPhys.y, FALSE);
+- }
++
++ /*
++ * This code force cursor position to be inside the
++ * root window of the agent. We can't view a reason
++ * to do this and it interacts in an undesirable way
++ * with toggling fullscreen.
++ *
++ * if ((sprite.hotPhys.x != XE_KBPTR.rootX) ||
++ * (sprite.hotPhys.y != XE_KBPTR.rootY))
++ * {
++ * (*sprite.hotPhys.pScreen->SetCursorPosition)(
++ * sprite.hotPhys.pScreen,
++ * sprite.hotPhys.x, sprite.hotPhys.y, FALSE);
++ * }
++ */
++
+ XE_KBPTR.rootX = sprite.hot.x;
+ XE_KBPTR.rootY = sprite.hot.y;
+ }
+@@ -2176,6 +2349,10 @@
+ DefineInitialRootWindow(register WindowPtr win)
+ {
+ register ScreenPtr pScreen = win->drawable.pScreen;
++ #ifdef VIEWPORT_FRAME
++ extern void nxagentInitViewportFrame(ScreenPtr, WindowPtr);
++ #endif
++ extern int nxagentShadowInit(ScreenPtr, WindowPtr);
+
+ sprite.hotPhys.pScreen = pScreen;
+ sprite.hotPhys.x = pScreen->width / 2;
+@@ -2215,6 +2392,18 @@
+ REGION_NULL(pScreen, &sprite.Reg2);
+ }
+ #endif
++
++ #ifdef VIEWPORT_FRAME
++ nxagentInitViewportFrame(pScreen, win);
++ #endif
++
++ if (nxagentOption(Shadow))
++ {
++ if (nxagentShadowInit(pScreen, win) == -1)
++ {
++ FatalError("Failed to connect to display '%s'", nxagentShadowDisplayName);
++ }
++ }
+ }
+
+ /*
+@@ -2553,6 +2742,13 @@
+ tempGrab.modifiersDetail.exact&(~0x1f00);
+ }
+ #endif
++ #ifdef NX_DEBUG_INPUT
++ if (nxagentDebugInputDevices == 1)
++ {
++ fprintf(stderr, "CheckPassiveGrabsOnWindow: Activating passive grab on %s.\n",
++ device == inputInfo.keyboard ? "keyboard" : "pointer");
++ }
++ #endif
+ (*device->ActivateGrab)(device, grab, currentTime, TRUE);
+
+ FixUpEventFromWindow(xE, grab->window, None, TRUE);
+@@ -2911,7 +3107,17 @@
+ else
+ DeliverFocusedEvent(keybd, xE, sprite.win, count);
+ if (deactivateGrab)
++ #ifdef NX_DEBUG_INPUT
++ {
++ if (nxagentDebugInputDevices == 1)
++ {
++ fprintf(stderr, "ProcessKeyboardEvent: Deactivating grab on keyboard.\n");
++ }
++ #endif
+ (*keybd->DeactivateGrab)(keybd);
++ #ifdef NX_DEBUG_INPUT
++ }
++ #endif
+ }
+
+ #ifdef XKB
+@@ -2961,7 +3167,9 @@
+ Bool deactivateGrab = FALSE;
+ register ButtonClassPtr butc = mouse->button;
+ #ifdef XKB
+- XkbSrvInfoPtr xkbi= inputInfo.keyboard->key->xkbInfo;
++ XkbSrvInfoPtr xkbi;
++
++ xkbi = inputInfo.keyboard->key->xkbInfo;
+ #endif
+ #ifdef XEVIE
+ if(xevieFlag && clients[xevieClientIndex] && !xeviegrabState &&
+@@ -2970,6 +3178,12 @@
+ xevieEventSent = 0;
+ else {
+ xeviemouse = mouse;
++ #ifdef NX_DEBUG_INPUT
++ if (nxagentDebugInput == 1)
++ {
++ fprintf(stderr, "ProcessPointerEvent: Going to send XEVIE event.\n");
++ }
++ #endif
+ WriteToClient(clients[xevieClientIndex], sizeof(xEvent), (char *)xE);
+ return;
+ }
+@@ -3024,14 +3238,38 @@
+ #if !defined(XFree86Server) || !defined(XINPUT)
+ xE->u.u.detail = butc->map[key];
+ #endif
++ #ifdef NX_DEBUG_INPUT
++ if (xE->u.u.detail == 0)
++ {
++ if (nxagentDebugInput == 1)
++ {
++ fprintf(stderr, "ProcessPointerEvent: WARNING! detail == 0"
++ " for ButtonPress.\n");
++ }
++ return;
++ }
++ #else
+ if (xE->u.u.detail == 0)
+ return;
++ #endif
+ if (xE->u.u.detail <= 5)
+ butc->state |= (Button1Mask >> 1) << xE->u.u.detail;
+ filters[MotionNotify] = Motion_Filter(butc);
+ if (!grab)
++ #ifdef NX_DEBUG_INPUT
++ if (CheckDeviceGrabs(mouse, xE, 0, count))
++ {
++ if (nxagentDebugInput == 1)
++ {
++ fprintf(stderr, "ProcessPointerEvent: CheckDeviceGrabs"
++ " returned True for ButtonPress.\n");
++ }
++ return;
++ }
++ #else
+ if (CheckDeviceGrabs(mouse, xE, 0, count))
+ return;
++ #endif
+ break;
+ case ButtonRelease:
+ mouse->valuator->motionHintWindow = NullWindow;
+@@ -3043,8 +3281,20 @@
+ #if !defined(XFree86Server) || !defined(XINPUT)
+ xE->u.u.detail = butc->map[key];
+ #endif
++ #ifdef NX_DEBUG_INPUT
+ if (xE->u.u.detail == 0)
++ {
++ if (nxagentDebugInput == 1)
++ {
++ fprintf(stderr, "ProcessPointerEvent: WARNING! detail == 0"
++ " for ButtonRelease.\n");
++ }
+ return;
++ }
++ #else
++ if (xE->u.u.detail == 0)
++ return;
++ #endif
+ if (xE->u.u.detail <= 5)
+ butc->state &= ~((Button1Mask >> 1) << xE->u.u.detail);
+ filters[MotionNotify] = Motion_Filter(butc);
+@@ -3055,6 +3305,36 @@
+ FatalError("bogus pointer event from ddx");
+ }
+ }
++ #ifdef NX_DEBUG_INPUT
++ else if (!CheckMotion(xE))
++ {
++ if (nxagentDebugInput == 1)
++ {
++ fprintf(stderr, "ProcessPointerEvent: CheckMotion returned False"
++ " for MotionNotify.\n");
++ }
++ return;
++ }
++ if (grab)
++ {
++ if (nxagentDebugInput == 1)
++ {
++ fprintf(stderr, "ProcessPointerEvent: Going to deliver grabbed "
++ "events (count = %d).\n", count);
++ }
++ DeliverGrabbedEvent(xE, mouse, deactivateGrab, count);
++ }
++ else
++ {
++ if (nxagentDebugInput == 1)
++ {
++ fprintf(stderr, "ProcessPointerEvent: Going to deliver device "
++ "events (count = %d).\n", count);
++ }
++ DeliverDeviceEvents(sprite.win, xE, NullGrab, NullWindow,
++ mouse, count);
++ }
++ #else
+ else if (!CheckMotion(xE))
+ return;
+ if (grab)
+@@ -3062,8 +3342,19 @@
+ else
+ DeliverDeviceEvents(sprite.win, xE, NullGrab, NullWindow,
+ mouse, count);
++ #endif
+ if (deactivateGrab)
++ #ifdef NX_DEBUG_INPUT
++ {
++ if (nxagentDebugInputDevices == 1)
++ {
++ fprintf(stderr, "ProcessPointerEvent: Deactivating grab on pointer.\n");
++ }
++ #endif
+ (*mouse->DeactivateGrab)(mouse);
++ #ifdef NX_DEBUG_INPUT
++ }
++ #endif
+ }
+
+ #define AtMostOneClient \
+@@ -3784,6 +4075,12 @@
+ pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess);
+ if (!pWin)
+ return BadWindow;
++ #ifdef NX_DEBUG_INPUT
++ if (nxagentDebugInputDevices == 1)
++ {
++ fprintf(stderr, "ProcGrabPointer: pWin [%p] client [%d].\n", pWin, client -> index);
++ }
++ #endif
+ if (stuff->confineTo == None)
+ confineTo = NullWindow;
+ else
+@@ -3843,6 +4140,12 @@
+ tempGrab.keyboardMode = stuff->keyboardMode;
+ tempGrab.pointerMode = stuff->pointerMode;
+ tempGrab.device = device;
++ #ifdef NX_DEBUG_INPUT
++ if (nxagentDebugInputDevices == 1)
++ {
++ fprintf(stderr, "ProcGrabPointer: Activating active grab on pointer.\n");
++ }
++ #endif
+ (*device->ActivateGrab)(device, &tempGrab, time, FALSE);
+ if (oldCursor)
+ FreeCursor (oldCursor, (Cursor)0);
+@@ -3906,6 +4209,12 @@
+ TimeStamp time;
+ REQUEST(xResourceReq);
+
++ #ifdef NX_DEBUG_INPUT
++ if (nxagentDebugInputDevices == 1)
++ {
++ fprintf(stderr, "ProcUngrabPointer: client [%d].\n", client -> index);
++ }
++ #endif
+ REQUEST_SIZE_MATCH(xResourceReq);
+ UpdateCurrentTime();
+ grab = device->grab;
+@@ -3913,7 +4222,25 @@
+ if ((CompareTimeStamps(time, currentTime) != LATER) &&
+ (CompareTimeStamps(time, device->grabTime) != EARLIER) &&
+ (grab) && SameClient(grab, client))
++ #ifdef NX_DEBUG_INPUT
++ {
++ if (nxagentDebugInputDevices == 1)
++ {
++ fprintf(stderr, "ProcUngrabPointer: Deactivating grab on pointer.\n");
++ }
++ #endif
+ (*device->DeactivateGrab)(device);
++ #ifdef NX_DEBUG_INPUT
++ }
++ else
++ {
++ if (nxagentDebugInputDevices == 1)
++ {
++ fprintf(stderr, "ProcUngrabPointer: current time [%lu] request time [%lu] grab time [%lu].\n",
++ currentTime.milliseconds, time.milliseconds, device->grabTime.milliseconds);
++ }
++ }
++ #endif
+ return Success;
+ }
+
+@@ -3968,6 +4295,12 @@
+ tempGrab.pointerMode = other_mode;
+ tempGrab.eventMask = mask;
+ tempGrab.device = dev;
++ #ifdef NX_DEBUG_INPUT
++ if (nxagentDebugInputDevices == 1)
++ {
++ fprintf(stderr, "GrabDevice: Activating active grab on keyboard.\n");
++ }
++ #endif
+ (*dev->ActivateGrab)(dev, &tempGrab, time, FALSE);
+ *status = GrabSuccess;
+ }
+@@ -3981,6 +4314,12 @@
+ REQUEST(xGrabKeyboardReq);
+ int result;
+
++ #ifdef NX_DEBUG_INPUT
++ if (nxagentDebugInputDevices == 1)
++ {
++ fprintf(stderr, "ProcGrabKeyboard: client [%d].\n", client -> index);
++ }
++ #endif
+ REQUEST_SIZE_MATCH(xGrabKeyboardReq);
+ #ifdef XCSECURITY
+ if (!SecurityCheckDeviceAccess(client, inputInfo.keyboard, TRUE))
+@@ -4011,6 +4350,12 @@
+ TimeStamp time;
+ REQUEST(xResourceReq);
+
++ #ifdef NX_DEBUG_INPUT
++ if (nxagentDebugInputDevices == 1)
++ {
++ fprintf(stderr, "ProcUngrabKeyboard: client [%d].\n", client -> index);
++ }
++ #endif
+ REQUEST_SIZE_MATCH(xResourceReq);
+ UpdateCurrentTime();
+ grab = device->grab;
+@@ -4018,7 +4363,25 @@
+ if ((CompareTimeStamps(time, currentTime) != LATER) &&
+ (CompareTimeStamps(time, device->grabTime) != EARLIER) &&
+ (grab) && SameClient(grab, client))
++ #ifdef NX_DEBUG_INPUT
++ {
++ if (nxagentDebugInputDevices == 1)
++ {
++ fprintf(stderr, "ProcUngrabKeyboard: Deactivating grab on keyboard.\n");
++ }
++ #endif
+ (*device->DeactivateGrab)(device);
++ #ifdef NX_DEBUG_INPUT
++ }
++ else
++ {
++ if (nxagentDebugInputDevices == 1)
++ {
++ fprintf(stderr, "ProcUngrabKeyboard: current time [%lu] request time [%lu] grab time [%lu].\n",
++ currentTime.milliseconds, time.milliseconds, device->grabTime.milliseconds);
++ }
++ }
++ #endif
+ return Success;
+ }
+
+@@ -4152,6 +4515,17 @@
+ /* The client's event type must be a core event type or one defined by an
+ extension. */
+
++
++#ifdef NXAGENT_CLIPBOARD
++
++ if (stuff -> event.u.u.type == SelectionNotify)
++ {
++ extern int nxagentSendNotify(xEvent*);
++ if (nxagentSendNotify(&stuff->event) == 1)
++ return Success;
++ }
++#endif
++
+ if ( ! ((stuff->event.u.u.type > X_Reply &&
+ stuff->event.u.u.type < LASTEvent) ||
+ (stuff->event.u.u.type >= EXTENSION_EVENT_BASE &&
diff --git a/doc/nx-X11_vs_XOrg69_patches/NXextension.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/NXextension.c.NX.patch
new file mode 100644
index 000000000..84c5b130a
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/NXextension.c.NX.patch
@@ -0,0 +1,70 @@
+--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXextension.c.X.original 2015-02-13 14:03:44.744441510 +0100
++++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXextension.c 2015-02-10 19:13:13.804685886 +0100
+@@ -1,3 +1,20 @@
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NXAGENT, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /* $XFree86: xc/programs/Xserver/dix/extension.c,v 3.11 2001/12/14 19:59:31 dawes Exp $ */
+ /***********************************************************
+
+@@ -60,7 +77,7 @@
+ #include "extnsionst.h"
+ #include "gcstruct.h"
+ #include "scrnintstr.h"
+-#include "dispatch.h"
++#include "../../dix/dispatch.h"
+ #ifdef XCSECURITY
+ #define _SECURITY_SERVER
+ #include <X11/extensions/security.h>
+@@ -69,6 +86,8 @@
+ #include "lbxserve.h"
+ #endif
+
++#include "Trap.h"
++
+ #define EXTENSION_BASE 128
+ #define EXTENSION_EVENT_BASE 64
+ #define LAST_EVENT 128
+@@ -324,6 +343,13 @@
+ {
+ i = FindExtension((char *)&stuff[1], stuff->nbytes);
+ if (i < 0
++
++ /*
++ * Hide RENDER if our implementation
++ * is faulty.
++ */
++
++ || (nxagentRenderTrap && strcmp(extensions[i]->name, "RENDER") == 0)
+ #ifdef XCSECURITY
+ /* don't show insecure extensions to untrusted clients */
+ || (client->trustLevel == XSecurityClientUntrusted &&
+@@ -370,6 +396,14 @@
+ !extensions[i]->secure)
+ continue;
+ #endif
++ /*
++ * Hide RENDER if our implementation
++ * is faulty.
++ */
++
++ if (nxagentRenderTrap && strcmp(extensions[i]->name, "RENDER") == 0)
++ continue;
++
+ total_length += strlen(extensions[i]->name) + 1;
+ reply.nExtensions += 1 + extensions[i]->num_aliases;
+ for (j = extensions[i]->num_aliases; --j >= 0;)
diff --git a/doc/nx-X11_vs_XOrg69_patches/NXglxext.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/NXglxext.c.NX.patch
new file mode 100644
index 000000000..a8dbfe0fd
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/NXglxext.c.NX.patch
@@ -0,0 +1,118 @@
+--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXglxext.c.X.original 2015-02-13 14:03:44.744441510 +0100
++++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXglxext.c 2015-02-10 19:13:13.808685737 +0100
+@@ -1,3 +1,20 @@
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NXAGENT, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /* $XFree86: xc/programs/Xserver/GL/glx/glxext.c,v 1.9 2003/09/28 20:15:43 alanh Exp $
+ ** The contents of this file are subject to the GLX Public License Version 1.0
+ ** (the "License"). You may not use this file except in compliance with the
+@@ -33,6 +50,12 @@
+ #include "glxext.h"
+ #include "micmap.h"
+
++#include "Trap.h"
++
++#define PANIC
++#define WARNING
++#undef TEST
++#undef DEBUG
+
+ void GlxWrapInitVisuals(miInitVisualsProcPtr *);
+ void GlxSetVisualConfigs(int nconfigs,
+@@ -395,6 +418,8 @@
+ */
+ static int __glXDispatch(ClientPtr client)
+ {
++ int result;
++
+ REQUEST(xGLXSingleReq);
+ CARD8 opcode;
+ int (*proc)(__GLXclientState *cl, GLbyte *pc);
+@@ -444,11 +469,35 @@
+ ** Use the opcode to index into the procedure table.
+ */
+ proc = __glXSingleTable[opcode];
+- return (*proc)(cl, (GLbyte *) stuff);
++
++ /*
++ * Report upstream that we are
++ * dispatching a GLX operation.
++ */
++
++ nxagentGlxTrap = 1;
++
++ #ifdef TEST
++ fprintf(stderr, "__glXDispatch: Going to dispatch GLX operation [%d] for client [%d].\n",
++ opcode, client -> index);
++ #endif
++
++ result = (*proc)(cl, (GLbyte *) stuff);
++
++ nxagentGlxTrap = 0;
++
++ #ifdef TEST
++ fprintf(stderr, "__glXDispatch: Dispatched GLX operation [%d] for client [%d].\n",
++ opcode, client -> index);
++ #endif
++
++ return result;
+ }
+
+ static int __glXSwapDispatch(ClientPtr client)
+ {
++ int result;
++
+ REQUEST(xGLXSingleReq);
+ CARD8 opcode;
+ int (*proc)(__GLXclientState *cl, GLbyte *pc);
+@@ -490,7 +539,29 @@
+ ** Use the opcode to index into the procedure table.
+ */
+ proc = __glXSwapSingleTable[opcode];
+- return (*proc)(cl, (GLbyte *) stuff);
++
++ /*
++ * Report upstream that we are
++ * dispatching a GLX operation.
++ */
++
++ nxagentGlxTrap = 1;
++
++ #ifdef TEST
++ fprintf(stderr, "__glXDispatch: Going to dispatch GLX operation [%d] for client [%d].\n",
++ opcode, client -> index);
++ #endif
++
++ result = (*proc)(cl, (GLbyte *) stuff);
++
++ nxagentGlxTrap = 0;
++
++ #ifdef TEST
++ fprintf(stderr, "__glXDispatch: Dispatched GLX operation [%d] for client [%d].\n",
++ opcode, client -> index);
++ #endif
++
++ return result;
+ }
+
+ int __glXNoSuchSingleOpcode(__GLXclientState *cl, GLbyte *pc)
+@@ -502,4 +573,3 @@
+ {
+ return;
+ }
+-
diff --git a/doc/nx-X11_vs_XOrg69_patches/NXglyph.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/NXglyph.c.NX.patch
new file mode 100644
index 000000000..8ac8e4662
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/NXglyph.c.NX.patch
@@ -0,0 +1,160 @@
+--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXglyph.c.X.original 2015-02-13 14:03:44.744441510 +0100
++++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXglyph.c 2015-02-10 19:13:13.824685138 +0100
+@@ -1,3 +1,20 @@
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NXAGENT, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /*
+ * $XFree86: xc/programs/Xserver/render/glyph.c,v 1.5 2001/01/30 07:01:22 keithp Exp $
+ *
+@@ -40,9 +57,25 @@
+ #include "dixstruct.h"
+ #include "gcstruct.h"
+ #include "servermd.h"
++
++#ifdef NXAGENT_SERVER
++
++#include "NXpicturestr.h"
++#include "NXglyphstr.h"
++#include "Render.h"
++
++#define PANIC
++#define WARNING
++#undef DEBUG
++#undef TEST
++
++#else
++
+ #include "picturestr.h"
+ #include "glyphstr.h"
+
++#endif
++
+ #if HAVE_STDINT_H
+ #include <stdint.h>
+ #elif !defined(UINT32_MAX)
+@@ -293,7 +326,7 @@
+ gr->signature = hash;
+ globalGlyphs[glyphSet->fdepth].tableEntries++;
+ }
+-
++
+ /* Insert/replace glyphset value */
+ gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0);
+ ++glyph->refcnt;
+@@ -303,6 +336,13 @@
+ glyphSet->hash.tableEntries++;
+ gr->glyph = glyph;
+ gr->signature = id;
++
++ #ifdef NXAGENT_SERVER
++
++ gr -> corruptedGlyph = 1;
++
++ #endif
++
+ CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom");
+ }
+
+@@ -324,6 +364,36 @@
+ return FALSE;
+ }
+
++#ifdef NXAGENT_SERVER
++
++GlyphPtr FindGlyph (GlyphSetPtr glyphSet, Glyph id)
++{
++ GlyphRefPtr gr;
++ GlyphPtr glyph;
++
++ gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0);
++ glyph = gr -> glyph;
++
++ if (glyph == DeletedGlyph)
++ {
++ glyph = 0;
++ }
++ else if (gr -> corruptedGlyph == 1)
++ {
++ #ifdef DEBUG
++ fprintf(stderr, "FindGlyphRef: Going to synchronize the glyph [%p] for glyphset [%p].\n",
++ (void *) glyph, (void *) glyphSet);
++ #endif
++
++ nxagentAddGlyphs(glyphSet, &id, &(glyph -> info), 1,
++ (CARD8*)(glyph + 1), glyph -> size - sizeof(xGlyphInfo));
++ }
++
++ return glyph;
++}
++
++#else
++
+ GlyphPtr
+ FindGlyph (GlyphSetPtr glyphSet, Glyph id)
+ {
+@@ -335,6 +405,8 @@
+ return glyph;
+ }
+
++#endif
++
+ GlyphPtr
+ AllocateGlyph (xGlyphInfo *gi, int fdepth)
+ {
+@@ -379,6 +451,12 @@
+ int oldSize;
+ CARD32 s;
+
++ #ifdef NXAGENT_SERVER
++
++ CARD32 c;
++
++ #endif
++
+ tableEntries = hash->tableEntries + change;
+ hashSet = FindGlyphHashSet (tableEntries);
+ if (hashSet == hash->hashSet)
+@@ -396,9 +474,23 @@
+ if (glyph && glyph != DeletedGlyph)
+ {
+ s = hash->table[i].signature;
++
++ #ifdef NXAGENT_SERVER
++
++ c = hash->table[i].corruptedGlyph;
++
++ #endif
++
+ gr = FindGlyphRef (&newHash, s, global, glyph);
+ gr->signature = s;
+ gr->glyph = glyph;
++
++ #ifdef NXAGENT_SERVER
++
++ gr -> corruptedGlyph = c;
++
++ #endif
++
+ ++newHash.tableEntries;
+ }
+ }
+@@ -486,3 +578,4 @@
+ }
+ return Success;
+ }
++
diff --git a/doc/nx-X11_vs_XOrg69_patches/NXglyphcurs.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/NXglyphcurs.c.NX.patch
new file mode 100644
index 000000000..c8d302c97
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/NXglyphcurs.c.NX.patch
@@ -0,0 +1,121 @@
+--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXglyphcurs.c.X.original 2015-02-13 14:03:44.744441510 +0100
++++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXglyphcurs.c 2015-02-10 19:13:13.808685737 +0100
+@@ -1,3 +1,20 @@
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NXAGENT, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /************************************************************************
+
+ Copyright 1987, 1998 The Open Group
+@@ -62,6 +79,12 @@
+ #include "opaque.h"
+ #include "servermd.h"
+
++#include "../../fb/fb.h"
++#include "Pixmaps.h"
++
++#ifndef True
++#define True 1
++#endif
+
+ /*
+ get the bits out of the font in a portable way. to avoid
+@@ -98,44 +121,68 @@
+ /* zeroing the (pad) bits seems to help some ddx cursor handling */
+ bzero(pbits, nby);
+
+- ppix = (PixmapPtr)(*pScreen->CreatePixmap)(pScreen, cm->width,
+- cm->height, 1);
++ ppix = fbCreatePixmap(pScreen, cm->width, cm->height, 1);
+ pGC = GetScratchGC(1, pScreen);
+ if (!ppix || !pGC)
+ {
+ if (ppix)
+- (*pScreen->DestroyPixmap)(ppix);
++ fbDestroyPixmap(ppix);
+ if (pGC)
+ FreeScratchGC(pGC);
+ xfree(pbits);
+ return BadAlloc;
+ }
+
++ #ifdef TEST
++ fprintf(stderr, "ServerBitsFromGlyph: Created virtual pixmap at [%p] with width [%d] height [%d] depth [%d].\n",
++ (void *) ppix, cm->width, cm->height, 1);
++ #endif
++
++ nxagentPixmapPriv(ppix) -> id = 0;
++ nxagentPixmapPriv(ppix) -> mid = 0;
++ nxagentPixmapPriv(ppix) -> isVirtual = True;
++ nxagentPixmapPriv(ppix) -> pRealPixmap = NULL;
++ nxagentPixmapPriv(ppix) -> pVirtualPixmap = NULL;
++
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = cm->width;
+ rect.height = cm->height;
+
+- /* fill the pixmap with 0 */
+- gcval[0].val = GXcopy;
+- gcval[1].val = 0;
+- gcval[2].ptr = (pointer)pfont;
+- dixChangeGC(NullClient, pGC, GCFunction | GCForeground | GCFont,
+- NULL, gcval);
++ pGC->stateChanges |= GCFunction | GCForeground | GCFont;
++ pGC->alu = GXcopy;
++
++ pGC->fgPixel = 0;
++
++ pfont->refcnt++;
++
++ if (pGC->font)
++ CloseFont(pGC->font, (Font)0);
++
++ pGC->font = pfont;
++
+ ValidateGC((DrawablePtr)ppix, pGC);
+- (*pGC->ops->PolyFillRect)((DrawablePtr)ppix, pGC, 1, &rect);
++ fbPolyFillRect((DrawablePtr)ppix, pGC, 1, &rect);
+
+ /* draw the glyph */
+ gcval[0].val = 1;
+- dixChangeGC(NullClient, pGC, GCForeground, NULL, gcval);
++ pGC->fgPixel = 1;
++
++ pGC->stateChanges |= GCForeground;
++
+ ValidateGC((DrawablePtr)ppix, pGC);
+- (*pGC->ops->PolyText16)((DrawablePtr)ppix, pGC, cm->xhot, cm->yhot,
+- 1, (unsigned short *)char2b);
+- (*pScreen->GetImage)((DrawablePtr)ppix, 0, 0, cm->width, cm->height,
+- XYPixmap, 1, pbits);
++ miPolyText16((DrawablePtr)ppix, pGC, (int)cm->xhot, (int)cm->yhot, (int)1, (unsigned short*)char2b);
++ fbGetImage((DrawablePtr)ppix, 0, 0, cm->width, cm->height,
++ XYPixmap, 1, pbits);
+ *ppbits = (unsigned char *)pbits;
+ FreeScratchGC(pGC);
+- (*pScreen->DestroyPixmap)(ppix);
++ fbDestroyPixmap(ppix);
++
++ #ifdef TEST
++ fprintf(stderr, "ServerBitsFromGlyph: Destroyed virtual pixmap at [%p].\n",
++ (void *) ppix);
++ #endif
++
+ return Success;
+ }
+
diff --git a/doc/nx-X11_vs_XOrg69_patches/NXglyphstr.h.NX.patch b/doc/nx-X11_vs_XOrg69_patches/NXglyphstr.h.NX.patch
new file mode 100644
index 000000000..76f0a1625
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/NXglyphstr.h.NX.patch
@@ -0,0 +1,59 @@
+--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXglyphstr.h.X.original 2015-02-13 14:03:44.744441510 +0100
++++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXglyphstr.h 2015-02-10 19:13:13.780686785 +0100
+@@ -1,3 +1,20 @@
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NXAGENT, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /*
+ * $XFree86: xc/programs/Xserver/render/glyphstr.h,v 1.3 2000/11/20 07:13:13 keithp Exp $
+ *
+@@ -23,11 +40,18 @@
+ * Author: Keith Packard, SuSE, Inc.
+ */
+
++/*
++ * This must keep the same symbol as the original glyphstr.h
++ * or symbols will be redefined. The code here adds a field
++ * to _GlyphSet. This should be done by defining a new type
++ * and casting when appropriate.
++ */
++
+ #ifndef _GLYPHSTR_H_
+ #define _GLYPHSTR_H_
+
+ #include <X11/extensions/renderproto.h>
+-#include "picture.h"
++#include "../../render/picture.h"
+ #include "screenint.h"
+
+ #define GlyphFormat1 0
+@@ -47,6 +71,7 @@
+ typedef struct _GlyphRef {
+ CARD32 signature;
+ GlyphPtr glyph;
++ CARD16 corruptedGlyph;
+ } GlyphRefRec, *GlyphRefPtr;
+
+ #define DeletedGlyph ((GlyphPtr) 1)
+@@ -70,6 +95,7 @@
+ GlyphHashRec hash;
+ int maxPrivate;
+ pointer *devPrivates;
++ CARD32 remoteID;
+ } GlyphSetRec, *GlyphSetPtr;
+
+ #define GlyphSetGetPrivate(pGlyphSet,n) \
diff --git a/doc/nx-X11_vs_XOrg69_patches/NXmiexpose.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/NXmiexpose.c.NX.patch
new file mode 100644
index 000000000..829a95df4
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/NXmiexpose.c.NX.patch
@@ -0,0 +1,116 @@
+--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXmiexpose.c.X.original 2015-02-13 14:03:44.744441510 +0100
++++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXmiexpose.c 2015-02-10 19:13:13.768687235 +0100
+@@ -1,3 +1,20 @@
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NXAGENT, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /* $XdotOrg: xc/programs/Xserver/mi/miexpose.c,v 1.6 2005/07/03 08:53:51 daniels Exp $ */
+ /* $XFree86: xc/programs/Xserver/mi/miexpose.c,v 3.9tsi Exp $ */
+ /***********************************************************
+@@ -109,6 +126,12 @@
+ the region package can call this.
+ */
+
++#ifdef NXAGENT_SERVER
++
++#include "Windows.h"
++
++#endif
++
+ #ifndef RECTLIMIT
+ #define RECTLIMIT 25 /* pick a number, any number > 8 */
+ #endif
+@@ -158,6 +181,20 @@
+ BoxRec expBox;
+ Bool extents;
+
++#ifdef NXAGENT_SERVER
++
++ /*
++ * Set the elements reported by the compiler
++ * as uninitialized.
++ */
++
++ expBox.x1 = 0;
++ expBox.y1 = 0;
++ expBox.x2 = 0;
++ expBox.y2 = 0;
++
++#endif
++
+ /* This prevents warning about pscr not being used. */
+ pGC->pScreen = pscr = pGC->pScreen;
+
+@@ -498,6 +535,11 @@
+ WindowPtr pWin;
+ register RegionPtr prgn, other_exposed;
+ {
++#ifdef NXAGENT_SERVER
++
++ int total;
++
++#endif
+ RegionPtr exposures = prgn;
+ if (pWin->backStorage && prgn)
+ /*
+@@ -533,7 +575,20 @@
+ }
+ exposures = other_exposed;
+ }
++#ifdef NXAGENT_SERVER
++
++ /*
++ * If the number of rectangles is greater
++ * than 4, let the function decide.
++ */
++
++ total = REGION_NUM_RECTS(exposures);
++
++ if (clientInterested && exposures && (total > RECTLIMIT ||
++ (total > 4 && nxagentExtentsPredicate(total) == 1)))
++#else
+ if (clientInterested && exposures && (REGION_NUM_RECTS(exposures) > RECTLIMIT))
++#endif
+ {
+ /*
+ * If we have LOTS of rectangles, we decide to take the extents
+@@ -666,6 +721,25 @@
+ register xRectangle *prect;
+ int numRects;
+
++#ifdef NXAGENT_SERVER
++
++ /*
++ * Set the elements reported by the compiler
++ * as uninitialized.
++ */
++
++ prgnWin.extents.x1 = 0;
++ prgnWin.extents.y1 = 0;
++ prgnWin.extents.x2 = 0;
++ prgnWin.extents.y2 = 0;
++
++ prgnWin.data = NULL;
++
++ oldCorner.x = 0;
++ oldCorner.y = 0;
++
++#endif
++
+ gcmask = 0;
+
+ if (what == PW_BACKGROUND)
diff --git a/doc/nx-X11_vs_XOrg69_patches/NXmiglyph.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/NXmiglyph.c.NX.patch
new file mode 100644
index 000000000..37b68d613
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/NXmiglyph.c.NX.patch
@@ -0,0 +1,156 @@
+--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXmiglyph.c.X.original 2015-02-13 14:03:44.744441510 +0100
++++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXmiglyph.c 2015-02-10 19:13:13.804685886 +0100
+@@ -1,3 +1,20 @@
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NXAGENT, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /*
+ * $XFree86: xc/programs/Xserver/render/miglyph.c,v 1.4 2000/11/20 07:13:13 keithp Exp $
+ *
+@@ -35,6 +52,12 @@
+ #include "picturestr.h"
+ #include "mipict.h"
+
++#ifdef NXAGENT_SERVER
++
++#include "Render.h"
++
++#endif
++
+ void
+ miGlyphExtents (int nlist,
+ GlyphListPtr list,
+@@ -45,7 +68,7 @@
+ int n;
+ GlyphPtr glyph;
+ int x, y;
+-
++
+ x = 0;
+ y = 0;
+ extents->x1 = MAXSHORT;
+@@ -113,25 +136,58 @@
+ int error;
+ BoxRec extents;
+ CARD32 component_alpha;
+-
++
++ #ifdef NXAGENT_SERVER
++
++ /*
++ * Get rid of the warning.
++ */
++
++ extents.x1 = 0;
++ extents.y1 = 0;
++
++ #endif
++
+ if (maskFormat)
+ {
+ GCPtr pGC;
+ xRectangle rect;
+-
+- miGlyphExtents (nlist, list, glyphs, &extents);
+-
++
++ #ifdef NXAGENT_SERVER
++
++ if (nxagentGlyphsExtents != NullBox)
++ {
++ memcpy(&extents, nxagentGlyphsExtents, sizeof(BoxRec));
++ }
++ else
++ {
++ nxagentGlyphsExtents = (BoxPtr) xalloc(sizeof(BoxRec));
++
++ miGlyphExtents (nlist, list, glyphs, &extents);
++
++ memcpy(nxagentGlyphsExtents, &extents, sizeof(BoxRec));
++ }
++
++ #else
++
++ miGlyphExtents (nlist, list, glyphs, &extents);
++
++ #endif
++
+ if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
+ return;
+ width = extents.x2 - extents.x1;
+ height = extents.y2 - extents.y1;
+ pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, maskFormat->depth);
++
+ if (!pMaskPixmap)
+ return;
++
+ component_alpha = NeedsComponent(maskFormat->format);
+ pMask = CreatePicture (0, &pMaskPixmap->drawable,
+ maskFormat, CPComponentAlpha, &component_alpha,
+ serverClient, &error);
++
+ if (!pMask)
+ {
+ (*pScreen->DestroyPixmap) (pMaskPixmap);
+@@ -160,6 +216,7 @@
+ x += list->xOff;
+ y += list->yOff;
+ n = list->len;
++
+ while (n--)
+ {
+ glyph = *glyphs++;
+@@ -184,6 +241,21 @@
+ (*pScreen->ModifyPixmapHeader) (pPixmap,
+ glyph->info.width, glyph->info.height,
+ 0, 0, -1, (pointer) (glyph + 1));
++
++ #ifdef NXAGENT_SERVER
++
++ /*
++ * The following line fixes a problem with glyphs that appeared
++ * as clipped. It was a side effect due the validate function
++ * "ValidatePicture" that makes a check on the Drawable serial
++ * number instead of the picture serial number, failing thus
++ * the clip mask update.
++ */
++
++ pPicture->pDrawable->serialNumber = NEXT_SERIAL_NUMBER;
++
++ #endif
++
+ pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ if (maskFormat)
+ {
+@@ -215,6 +287,7 @@
+ x += glyph->info.xOff;
+ y += glyph->info.yOff;
+ }
++
+ list++;
+ if (pPicture)
+ {
+@@ -237,7 +310,9 @@
+ 0, 0,
+ x, y,
+ width, height);
++
+ FreePicture ((pointer) pMask, (XID) 0);
+ (*pScreen->DestroyPixmap) (pMaskPixmap);
+ }
++
+ }
diff --git a/doc/nx-X11_vs_XOrg69_patches/NXmitrap.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/NXmitrap.c.NX.patch
new file mode 100644
index 000000000..220b26a49
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/NXmitrap.c.NX.patch
@@ -0,0 +1,65 @@
+--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXmitrap.c.X.original 2015-02-13 14:03:44.744441510 +0100
++++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXmitrap.c 2015-02-10 19:13:13.820685287 +0100
+@@ -1,3 +1,20 @@
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NXAGENT, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /*
+ * $XFree86: xc/programs/Xserver/render/mitrap.c,v 1.8 2002/09/03 19:28:28 keithp Exp $
+ *
+@@ -35,6 +52,12 @@
+ #include "picturestr.h"
+ #include "mipict.h"
+
++#ifdef NXAGENT_SERVER
++
++#include "Render.h"
++
++#endif
++
+ PicturePtr
+ miCreateAlphaPicture (ScreenPtr pScreen,
+ PicturePtr pDst,
+@@ -159,7 +182,27 @@
+ xDst = traps[0].left.p1.x >> 16;
+ yDst = traps[0].left.p1.y >> 16;
+
+- miTrapezoidBounds (ntrap, traps, &bounds);
++ #ifdef NXAGENT_SERVER
++
++ if (nxagentTrapezoidExtents != NullBox)
++ {
++ memcpy(&bounds, nxagentTrapezoidExtents, sizeof(BoxRec));
++ }
++ else
++ {
++ nxagentTrapezoidExtents = (BoxPtr) xalloc(sizeof(BoxRec));
++
++ miTrapezoidBounds (ntrap, traps, &bounds);
++
++ memcpy(nxagentTrapezoidExtents, &bounds, sizeof(BoxRec));
++ }
++
++ #else
++
++ miTrapezoidBounds (ntrap, traps, &bounds);
++
++ #endif
++
+ if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
+ return;
+ pPicture = miCreateAlphaPicture (pScreen, pDst, maskFormat,
diff --git a/doc/nx-X11_vs_XOrg69_patches/NXmiwindow.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/NXmiwindow.c.NX.patch
new file mode 100644
index 000000000..7d6be7b0c
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/NXmiwindow.c.NX.patch
@@ -0,0 +1,53 @@
+--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXmiwindow.c.X.original 2015-02-13 14:03:44.744441510 +0100
++++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXmiwindow.c 2015-02-10 19:13:13.776686935 +0100
+@@ -1,3 +1,20 @@
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NXAGENT, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /* $XFree86: xc/programs/Xserver/mi/miwindow.c,v 1.9tsi Exp $ */
+ /***********************************************************
+
+@@ -1048,8 +1065,29 @@
+ bsExposed = (*pScreen->TranslateBackingStore)
+ (pWin, 0, 0, pOldClip,
+ pWin->drawable.x, pWin->drawable.y);
++#ifdef NXAGENT_SERVER
++
++ /*
++ * We got a few, rare, segfaults here after having
++ * started using the backing store. It may be a
++ * different bug but miChangeSaveUnder() calls mi-
++ * CheckSubSaveUnder() that, in turn, can change
++ * the backing store attribute of the window. This
++ * means that we may try to destroy the region
++ * even if it was not created at the beginning of
++ * this function as, at the time, the backing store
++ * was off. miCheckSubSaveUnder() appear to get a
++ * pointer to the parent, so maybe doesn't change
++ * the attribute of the window itself. This is to
++ * be better investigated.
++ */
++
++ if (WasViewable && pOldClip)
++ REGION_DESTROY(pScreen, pOldClip);
++#else
+ if (WasViewable)
+ REGION_DESTROY(pScreen, pOldClip);
++#endif
+ if (bsExposed)
+ {
+ RegionPtr valExposed = NullRegion;
diff --git a/doc/nx-X11_vs_XOrg69_patches/NXpicture.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/NXpicture.c.NX.patch
new file mode 100644
index 000000000..9713e4495
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/NXpicture.c.NX.patch
@@ -0,0 +1,615 @@
+--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXpicture.c.X.original 2015-02-13 14:03:44.744441510 +0100
++++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXpicture.c 2015-02-13 14:03:44.744441510 +0100
+@@ -1,3 +1,20 @@
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NXAGENT, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /*
+ * $XFree86: xc/programs/Xserver/render/picture.c,v 1.29 2002/11/23 02:38:15 keithp Exp $
+ *
+@@ -40,7 +57,21 @@
+ #include "dixstruct.h"
+ #include "gcstruct.h"
+ #include "servermd.h"
+-#include "picturestr.h"
++#include "NXpicturestr.h"
++
++#include "Screen.h"
++#include "Pixmaps.h"
++#include "Drawable.h"
++#include "Render.h"
++
++#define PANIC
++#define WARNING
++#undef TEST
++#undef DEBUG
++
++void *nxagentVisualFromID(ScreenPtr pScreen, VisualID visual);
++
++void *nxagentMatchingFormats(PictFormatPtr pForm);
+
+ int PictureScreenPrivateIndex = -1;
+ int PictureWindowPrivateIndex;
+@@ -50,6 +81,13 @@
+ RESTYPE GlyphSetType;
+ int PictureCmapPolicy = PictureCmapPolicyDefault;
+
++typedef struct _formatInit {
++ CARD32 format;
++ CARD8 depth;
++} FormatInitRec, *FormatInitPtr;
++
++void nxagentPictureCreateDefaultFormats(ScreenPtr pScreen, FormatInitRec *formats, int *nformats);
++
+ /* Picture Private machinery */
+
+ static int picturePrivateCount;
+@@ -189,11 +227,6 @@
+ return 0;
+ }
+
+-typedef struct _formatInit {
+- CARD32 format;
+- CARD8 depth;
+-} FormatInitRec, *FormatInitPtr;
+-
+ static int
+ addFormat (FormatInitRec formats[256],
+ int nformat,
+@@ -207,6 +240,11 @@
+ return nformat;
+ formats[nformat].format = format;
+ formats[nformat].depth = depth;
++
++ #ifdef DEBUG
++ fprintf(stderr, "addFormat: Added format [%lu] depth [%d].\n", format, depth);
++ #endif
++
+ return ++nformat;
+ }
+
+@@ -215,10 +253,13 @@
+ PictFormatPtr
+ PictureCreateDefaultFormats (ScreenPtr pScreen, int *nformatp)
+ {
+- int nformats, f;
++ int nformats, f;
+ PictFormatPtr pFormats;
+ FormatInitRec formats[1024];
+ CARD32 format;
++
++#ifndef NXAGENT_SERVER
++
+ CARD8 depth;
+ VisualPtr pVisual;
+ int v;
+@@ -228,7 +269,16 @@
+ int d;
+ DepthPtr pDepth;
+
++#endif
++
+ nformats = 0;
++
++#ifdef NXAGENT_SERVER
++
++ nxagentPictureCreateDefaultFormats(pScreen, formats, &nformats);
++
++#else
++
+ /* formats required by protocol */
+ formats[nformats].format = PICT_a1;
+ formats[nformats].depth = 1;
+@@ -254,6 +304,7 @@
+ if (!depth)
+ continue;
+ bpp = BitsPerPixel (depth);
++
+ switch (pVisual->class) {
+ case DirectColor:
+ case TrueColor:
+@@ -296,6 +347,7 @@
+ break;
+ }
+ }
++
+ /*
+ * Walk supported depths and add useful Direct formats
+ */
+@@ -304,16 +356,18 @@
+ pDepth = &pScreen->allowedDepths[d];
+ bpp = BitsPerPixel (pDepth->depth);
+ format = 0;
++
+ switch (bpp) {
+ case 16:
+ /* depth 12 formats */
+- if (pDepth->depth >= 12)
+- {
+- nformats = addFormat (formats, nformats,
+- PICT_x4r4g4b4, pDepth->depth);
+- nformats = addFormat (formats, nformats,
+- PICT_x4b4g4r4, pDepth->depth);
+- }
++ if (pDepth->depth >= 12)
++ {
++ nformats = addFormat (formats, nformats,
++ PICT_x4r4g4b4, pDepth->depth);
++ nformats = addFormat (formats, nformats,
++ PICT_x4b4g4r4, pDepth->depth);
++ }
++
+ /* depth 15 formats */
+ if (pDepth->depth >= 15)
+ {
+@@ -325,18 +379,18 @@
+ /* depth 16 formats */
+ if (pDepth->depth >= 16)
+ {
+- nformats = addFormat (formats, nformats,
+- PICT_a1r5g5b5, pDepth->depth);
+- nformats = addFormat (formats, nformats,
+- PICT_a1b5g5r5, pDepth->depth);
++ nformats = addFormat (formats, nformats,
++ PICT_a1r5g5b5, pDepth->depth);
++ nformats = addFormat (formats, nformats,
++ PICT_a1b5g5r5, pDepth->depth);
+ nformats = addFormat (formats, nformats,
+ PICT_r5g6b5, pDepth->depth);
+ nformats = addFormat (formats, nformats,
+ PICT_b5g6r5, pDepth->depth);
+ nformats = addFormat (formats, nformats,
+ PICT_a4r4g4b4, pDepth->depth);
+- nformats = addFormat (formats, nformats,
+- PICT_a4b4g4r4, pDepth->depth);
++ nformats = addFormat (formats, nformats,
++ PICT_a4b4g4r4, pDepth->depth);
+ }
+ break;
+ case 24:
+@@ -359,7 +413,8 @@
+ break;
+ }
+ }
+-
++
++#endif
+
+ pFormats = (PictFormatPtr) xalloc (nformats * sizeof (PictFormatRec));
+ if (!pFormats)
+@@ -368,9 +423,9 @@
+ for (f = 0; f < nformats; f++)
+ {
+ pFormats[f].id = FakeClientID (0);
+- pFormats[f].depth = formats[f].depth;
+- format = formats[f].format;
+- pFormats[f].format = format;
++ pFormats[f].depth = formats[f].depth;
++ format = formats[f].format;
++ pFormats[f].format = format;
+ switch (PICT_FORMAT_TYPE(format)) {
+ case PICT_TYPE_ARGB:
+ pFormats[f].type = PictTypeDirect;
+@@ -427,6 +482,29 @@
+ pFormats[f].index.vid = pScreen->visuals[PICT_FORMAT_VIS(format)].vid;
+ break;
+ }
++
++#ifdef NXAGENT_SERVER
++ if (nxagentMatchingFormats(&pFormats[f]) != NULL)
++ {
++ #ifdef DEBUG
++ fprintf(stderr, "PictureCreateDefaultFormats: Format with type [%d] depth [%d] rgb [%d,%d,%d] "
++ "mask rgb [%d,%d,%d] alpha [%d] alpha mask [%d] matches.\n",
++ pFormats[f].type, pFormats[f].depth, pFormats[f].direct.red, pFormats[f].direct.green,
++ pFormats[f].direct.blue, pFormats[f].direct.redMask, pFormats[f].direct.greenMask,
++ pFormats[f].direct.blueMask, pFormats[f].direct.alpha, pFormats[f].direct.alphaMask);
++ #endif
++ }
++ else
++ {
++ #ifdef DEBUG
++ fprintf(stderr, "PictureCreateDefaultFormats: Format with type [%d] depth [%d] rgb [%d,%d,%d] "
++ "mask rgb [%d,%d,%d] alpha [%d] alpha mask [%d] doesn't match.\n",
++ pFormats[f].type, pFormats[f].depth, pFormats[f].direct.red, pFormats[f].direct.green,
++ pFormats[f].direct.blue, pFormats[f].direct.redMask, pFormats[f].direct.greenMask,
++ pFormats[f].direct.blueMask, pFormats[f].direct.alpha, pFormats[f].direct.alphaMask);
++ #endif
++ }
++#endif
+ }
+ *nformatp = nformats;
+ return pFormats;
+@@ -795,9 +873,20 @@
+ else
+ ppriv->ptr = (pointer)NULL;
+ }
++
++ nxagentPicturePriv(pPicture) -> picture = 0;
++
+ return pPicture;
+ }
+
++/*
++ * Let picture always point to the virtual pixmap.
++ * For sure this is not the best way to deal with
++ * the virtual frame-buffer.
++ */
++
++#define NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL
++
+ PicturePtr
+ CreatePicture (Picture pid,
+ DrawablePtr pDrawable,
+@@ -823,6 +912,12 @@
+ pPicture->format = pFormat->format | (pDrawable->bitsPerPixel << 24);
+ if (pDrawable->type == DRAWABLE_PIXMAP)
+ {
++ #ifdef NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL
++
++ pPicture->pDrawable = nxagentVirtualDrawable(pDrawable);
++
++ #endif
++
+ ++((PixmapPtr)pDrawable)->refcnt;
+ pPicture->pNext = 0;
+ }
+@@ -972,7 +1067,49 @@
+ static PicturePtr createSourcePicture(void)
+ {
+ PicturePtr pPicture;
+- pPicture = (PicturePtr) xalloc(sizeof(PictureRec));
++
++ extern int nxagentPicturePrivateIndex;
++
++ unsigned int totalPictureSize;
++
++ DevUnion *ppriv;
++
++ char *privPictureRecAddr;
++
++ int i;
++
++ /*
++ * Compute size of entire PictureRect, plus privates.
++ */
++
++ totalPictureSize = sizeof(PictureRec) +
++ picturePrivateCount * sizeof(DevUnion) +
++ sizeof(nxagentPrivPictureRec);
++
++ pPicture = (PicturePtr) xalloc(totalPictureSize);
++
++ if (pPicture != NULL)
++ {
++ ppriv = (DevUnion *) (pPicture + 1);
++
++ for (i = 0; i < picturePrivateCount; ++i)
++ {
++ /*
++ * Other privates are inaccessible.
++ */
++
++ ppriv[i].ptr = NULL;
++ }
++
++ privPictureRecAddr = (char *) &ppriv[picturePrivateCount];
++
++ ppriv[nxagentPicturePrivateIndex].ptr = (pointer) privPictureRecAddr;
++
++ pPicture -> devPrivates = ppriv;
++
++ nxagentPicturePriv(pPicture) -> picture = 0;
++ }
++
+ pPicture->pDrawable = 0;
+ pPicture->pFormat = 0;
+ pPicture->pNext = 0;
+@@ -1294,6 +1431,12 @@
+ pPixmap->refcnt++;
+ }
+ }
++
++ #ifdef DEBUG
++ fprintf(stderr, "ChangePicture: Going to call ChangePictureClip with clipType [%d] pPixmap [%p].\n",
++ clipType, (void *) pPixmap);
++ #endif
++
+ error = (*ps->ChangePictureClip)(pPicture, clipType,
+ (pointer)pPixmap, 0);
+ break;
+@@ -1600,6 +1743,10 @@
+
+ if (--pPicture->refcnt == 0)
+ {
++#ifdef NXAGENT_SERVER
++ nxagentDestroyPicture(pPicture);
++#endif
++
+ if (pPicture->transform)
+ xfree (pPicture->transform);
+ if (!pPicture->pDrawable) {
+@@ -1698,6 +1845,13 @@
+
+ ValidatePicture (pSrc);
+ ValidatePicture (pDst);
++
++ #ifdef TEST
++ fprintf(stderr, "CompositeGlyphs: Going to composite glyphs with "
++ "source at [%p] and destination at [%p].\n",
++ (void *) pSrc, (void *) pDst);
++ #endif
++
+ (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, lists, glyphs);
+ }
+
+@@ -1862,3 +2016,255 @@
+ vector->vector[2] = xFixed1;
+ return TRUE;
+ }
++
++#ifndef True
++# define True 1
++#endif
++
++#ifndef False
++# define False 0
++#endif
++
++void nxagentReconnectPictFormat(void*, XID, void*);
++
++Bool nxagentReconnectAllPictFormat(void *p)
++{
++ PictFormatPtr formats_old, formats;
++ int nformats, nformats_old;
++ VisualPtr pVisual;
++ Bool success = True;
++ Bool matched;
++ int i, n;
++ CARD32 type, a, r, g, b;
++
++ #if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_PICTFORMAT_DEBUG)
++ fprintf(stderr, "nxagentReconnectAllPictFormat\n");
++ #endif
++
++ formats_old = GetPictureScreen(nxagentDefaultScreen) -> formats;
++ nformats_old = GetPictureScreen(nxagentDefaultScreen) -> nformats;
++
++ /*
++ * TODO: We could copy PictureCreateDefaultFormats,
++ * in order not to waste ID with FakeClientID().
++ */
++ formats = PictureCreateDefaultFormats (nxagentDefaultScreen, &nformats);
++
++ if (!formats)
++ return False;
++
++ for (n = 0; n < nformats; n++)
++ {
++ if (formats[n].type == PictTypeIndexed)
++ {
++ pVisual = nxagentVisualFromID(nxagentDefaultScreen, formats[n].index.vid);
++
++ if ((pVisual->class | DynamicClass) == PseudoColor)
++ type = PICT_TYPE_COLOR;
++ else
++ type = PICT_TYPE_GRAY;
++ a = r = g = b = 0;
++ }
++ else
++ {
++ if ((formats[n].direct.redMask|
++ formats[n].direct.blueMask|
++ formats[n].direct.greenMask) == 0)
++ type = PICT_TYPE_A;
++ else if (formats[n].direct.red > formats[n].direct.blue)
++ type = PICT_TYPE_ARGB;
++ else
++ type = PICT_TYPE_ABGR;
++ a = Ones (formats[n].direct.alphaMask);
++ r = Ones (formats[n].direct.redMask);
++ g = Ones (formats[n].direct.greenMask);
++ b = Ones (formats[n].direct.blueMask);
++ }
++ formats[n].format = PICT_FORMAT(0,type,a,r,g,b);
++ }
++
++ for (n = 0; n < nformats_old; n++)
++ {
++ for (i = 0, matched = False; (!matched) && (i < nformats); i++)
++ {
++ if (formats_old[n].format == formats[i].format &&
++ formats_old[n].type == formats[i].type &&
++ formats_old[n].direct.red == formats[i].direct.red &&
++ formats_old[n].direct.green == formats[i].direct.green &&
++ formats_old[n].direct.blue == formats[i].direct.blue &&
++ formats_old[n].direct.redMask == formats[i].direct.redMask &&
++ formats_old[n].direct.greenMask == formats[i].direct.greenMask &&
++ formats_old[n].direct.blueMask == formats[i].direct.blueMask &&
++ formats_old[n].direct.alpha == formats[i].direct.alpha &&
++ formats_old[n].direct.alphaMask == formats[i].direct.alphaMask)
++ {
++ /*
++ * Regard depth 16 and 15 as were the same, if all other values match.
++ */
++
++ if ((formats_old[n].depth == formats[i].depth) ||
++ ((formats_old[n].depth == 15 || formats_old[n].depth == 16) &&
++ (formats[i].depth == 15 || formats[i].depth == 16)))
++ {
++ matched = True;
++ }
++ }
++ }
++
++ if (!matched)
++ {
++ return False;
++ }
++ }
++
++ xfree(formats);
++
++ /* TODO: Perhaps do i have to do PictureFinishInit ?. */
++ /* TODO: We have to check for new Render protocol version. */
++
++ for (i = 0; (i < MAXCLIENTS) && (success); i++)
++ {
++ if (clients[i])
++ {
++ FindClientResourcesByType(clients[i], PictFormatType, nxagentReconnectPictFormat, &success);
++ }
++ }
++
++ return success;
++}
++
++/*
++ * It seem we don't have nothing
++ * to do for reconnect PictureFormat.
++ */
++
++void nxagentReconnectPictFormat(void *p0, XID x1, void *p2)
++{
++ PictFormatPtr pFormat;
++ Bool *pBool;
++
++ pFormat = (PictFormatPtr)p0;
++ pBool = (Bool*)p2;
++
++ #if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_PICTFORMAT_DEBUG)
++ fprintf(stderr, "nxagentReconnectPictFormat.\n");
++ #endif
++}
++
++/*
++ * The set of picture formats may change considerably
++ * between different X servers. This poses a problem
++ * while migrating NX sessions, because a requisite to
++ * successfully reconnect the session is that all pic-
++ * ture formats have to be available on the new X server.
++ * To reduce such problems, we use a limited set of
++ * pictures available on the most X servers.
++ */
++
++void nxagentPictureCreateDefaultFormats(ScreenPtr pScreen, FormatInitRec *formats, int *nformats)
++{
++ DepthPtr pDepth;
++ VisualPtr pVisual;
++
++ CARD32 format;
++ CARD8 depth;
++
++ int r, g, b;
++ int bpp;
++ int d;
++ int v;
++
++
++ formats[*nformats].format = PICT_a1;
++ formats[*nformats].depth = 1;
++ *nformats += 1;
++ formats[*nformats].format = PICT_a4;
++ formats[*nformats].depth = 4;
++ *nformats += 1;
++ formats[*nformats].format = PICT_a8;
++ formats[*nformats].depth = 8;
++ *nformats += 1;
++ formats[*nformats].format = PICT_a8r8g8b8;
++ formats[*nformats].depth = 32;
++ *nformats += 1;
++
++ /*
++ * This format should be required by the
++ * protocol, but it's not used by Xgl.
++ *
++ * formats[*nformats].format = PICT_x8r8g8b8;
++ * formats[*nformats].depth = 32;
++ * *nformats += 1;
++ */
++
++ /* now look through the depths and visuals adding other formats */
++ for (v = 0; v < pScreen->numVisuals; v++)
++ {
++ pVisual = &pScreen->visuals[v];
++ depth = visualDepth (pScreen, pVisual);
++ if (!depth)
++ continue;
++
++ bpp = BitsPerPixel (depth);
++
++ switch (pVisual->class)
++ {
++ case DirectColor:
++ case TrueColor:
++ r = Ones (pVisual->redMask);
++ g = Ones (pVisual->greenMask);
++ b = Ones (pVisual->blueMask);
++
++ if (pVisual->offsetBlue == 0 &&
++ pVisual->offsetGreen == b &&
++ pVisual->offsetRed == b + g)
++ {
++ format = PICT_FORMAT(bpp, PICT_TYPE_ARGB, 0, r, g, b);
++ *nformats = addFormat (formats, *nformats, format, depth);
++ }
++ break;
++ case StaticColor:
++ case PseudoColor:
++ case StaticGray:
++ case GrayScale:
++ break;
++ }
++ }
++
++ for (d = 0; d < pScreen -> numDepths; d++)
++ {
++ pDepth = &pScreen -> allowedDepths[d];
++ bpp = BitsPerPixel(pDepth -> depth);
++
++ switch (bpp) {
++ case 16:
++ if (pDepth->depth == 15)
++ {
++ *nformats = addFormat (formats, *nformats,
++ PICT_x1r5g5b5, pDepth->depth);
++ }
++
++ if (pDepth->depth == 16)
++ {
++ *nformats = addFormat (formats, *nformats,
++ PICT_r5g6b5, pDepth->depth);
++ }
++ break;
++ case 24:
++ if (pDepth->depth == 24)
++ {
++ *nformats = addFormat (formats, *nformats,
++ PICT_r8g8b8, pDepth->depth);
++ }
++ break;
++ case 32:
++ if (pDepth->depth == 24)
++ {
++ *nformats = addFormat (formats, *nformats,
++ PICT_x8r8g8b8, pDepth->depth);
++ }
++ break;
++ }
++ }
++}
++
diff --git a/doc/nx-X11_vs_XOrg69_patches/NXpicturestr.h.NX.patch b/doc/nx-X11_vs_XOrg69_patches/NXpicturestr.h.NX.patch
new file mode 100644
index 000000000..9150cfae8
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/NXpicturestr.h.NX.patch
@@ -0,0 +1,42 @@
+--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXpicturestr.h.X.original 2015-02-13 14:03:44.744441510 +0100
++++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXpicturestr.h 2015-02-13 14:03:44.744441510 +0100
+@@ -1,3 +1,20 @@
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NXAGENT, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /*
+ * $Id: picturestr.h,v 1.15 2005/12/09 18:35:21 ajax Exp $
+ *
+@@ -23,10 +40,17 @@
+ * Author: Keith Packard, SuSE, Inc.
+ */
+
++/*
++ * This must keep the same symbol as the original
++ * picturestr.h or symbols will be redefined. We
++ * should define a new types and cast when appro-
++ * priate.
++ */
++
+ #ifndef _PICTURESTR_H_
+ #define _PICTURESTR_H_
+
+-#include "glyphstr.h"
++#include "NXglyphstr.h"
+ #include "scrnintstr.h"
+ #include "resource.h"
+
diff --git a/doc/nx-X11_vs_XOrg69_patches/NXproperty.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/NXproperty.c.NX.patch
new file mode 100644
index 000000000..7327501ac
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/NXproperty.c.NX.patch
@@ -0,0 +1,358 @@
+--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXproperty.c.X.original 2015-02-13 14:03:44.744441510 +0100
++++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXproperty.c 2015-02-10 19:13:13.772687085 +0100
+@@ -1,3 +1,20 @@
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NXAGENT, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /* $XFree86: xc/programs/Xserver/dix/property.c,v 3.12 2002/02/19 11:09:22 alanh Exp $ */
+ /***********************************************************
+
+@@ -58,7 +75,7 @@
+ #include "windowstr.h"
+ #include "propertyst.h"
+ #include "dixstruct.h"
+-#include "dispatch.h"
++#include "../../dix/dispatch.h"
+ #include "swaprep.h"
+ #ifdef XCSECURITY
+ #define _SECURITY_SERVER
+@@ -69,6 +86,11 @@
+ #include "lbxtags.h"
+ #endif
+
++#include "Options.h"
++#include "Rootless.h"
++#include "Client.h"
++#include "Windows.h"
++
+ #if defined(LBX) || defined(LBX_COMPAT)
+ #if 0 /* no header in X11 environment, not used in X11 environment */
+ int fWriteToClient(ClientPtr client, int len, char *buf)
+@@ -78,6 +100,17 @@
+ #endif
+ #endif
+
++extern Atom clientCutProperty;
++
++#ifdef NXAGENT_SERVER
++typedef struct
++{
++ CARD32 state;
++ Window icon;
++}
++nxagentWMStateRec;
++#endif
++
+ /*****************************************************************
+ * Property Stuff
+ *
+@@ -234,6 +267,15 @@
+ totalSize = len * sizeInBytes;
+ REQUEST_FIXED_SIZE(xChangePropertyReq, totalSize);
+
++#ifdef NXAGENT_CLIPBOARD
++ {
++ extern WindowPtr nxagentGetClipboardWindow(Atom, WindowPtr);
++
++ pWin = nxagentGetClipboardWindow(stuff->property, NULL);
++ }
++
++ if (pWin == NULL)
++#endif
+ pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
+ SecurityWriteAccess);
+ if (!pWin)
+@@ -261,6 +303,18 @@
+ }
+ #endif
+
++#ifdef NXAGENT_ARTSD
++ {
++ /* Do not process MCOPGLOBALS property changes,
++ they are already set reflecting the server side settings.
++ Just return success.
++ */
++ extern Atom mcop_local_atom;
++ if (stuff->property == mcop_local_atom)
++ return client->noClientException;
++ }
++#endif
++
+ #ifdef LBX
+ err = LbxChangeWindowProperty(client, pWin, stuff->property, stuff->type,
+ (int)format, (int)mode, len, TRUE, (pointer)&stuff[1], TRUE, NULL);
+@@ -271,7 +325,23 @@
+ if (err != Success)
+ return err;
+ else
+- return client->noClientException;
++ {
++ if (nxagentOption(Rootless) == 1)
++ {
++ nxagentExportProperty(pWin, stuff->property, stuff->type, (int) format,
++ (int) mode, len, (pointer) &stuff[1]);
++ }
++
++ nxagentGuessClientHint(client, stuff->property, (char *) &stuff[1]);
++
++ nxagentGuessShadowHint(client, stuff->property);
++
++ #ifdef NX_DEBUG_INPUT
++ nxagentGuessDumpInputInfo(client, stuff->property, (char *) &stuff[1]);
++ #endif
++
++ return client->noClientException;
++ }
+ }
+
+ int
+@@ -289,10 +359,23 @@
+ int sizeInBytes;
+ int totalSize;
+ pointer data;
++ int copySize;
+
+ sizeInBytes = format>>3;
+ totalSize = len * sizeInBytes;
+
++ copySize = nxagentOption(CopyBufferSize);
++
++ if (copySize != COPY_UNLIMITED && property == clientCutProperty)
++ {
++ if (totalSize > copySize)
++ {
++ totalSize = copySize;
++ totalSize = totalSize - (totalSize % sizeInBytes);
++ len = totalSize / sizeInBytes;
++ }
++ }
++
+ /* first see if property already exists */
+
+ pProp = wUserProps (pWin);
+@@ -491,6 +574,11 @@
+ int
+ ProcGetProperty(ClientPtr client)
+ {
++ #ifdef NXAGENT_SERVER
++ nxagentWMStateRec wmState;
++ nxagentWMStateRec *wmsP = &wmState;
++ #endif
++
+ PropertyPtr pProp, prevProp;
+ unsigned long n, len, ind;
+ WindowPtr pWin;
+@@ -498,6 +586,7 @@
+ REQUEST(xGetPropertyReq);
+
+ REQUEST_SIZE_MATCH(xGetPropertyReq);
++
+ if (stuff->delete)
+ UpdateCurrentTime();
+ pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
+@@ -533,6 +622,59 @@
+
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
++
++ #ifdef NXAGENT_SERVER
++
++ /*
++ * Creating a reply for WM_STATE property if it doesn't exist.
++ * This is intended to allow drag & drop work in JAva 1.6 when
++ * the agent is connected to NXWin in multiwindow mode.
++ */
++
++ if (nxagentOption(Rootless) &&
++ nxagentWindowTopLevel(pWin) &&
++ (!pProp) &&
++ strcmp(NameForAtom(stuff->property), "WM_STATE") == 0)
++ {
++ wmState.state = 1;
++ wmState.icon = None;
++
++ if (ChangeWindowProperty(pWin, stuff->property, stuff->property, 32, 0, 2, &wmState, 1) == Success)
++ {
++ nxagentExportProperty(pWin, stuff->property, stuff->property, 32, 0, 2, &wmState);
++ }
++
++ n = 8;
++ ind = stuff->longOffset << 2;
++
++ if (n < ind)
++ {
++ client->errorValue = stuff->longOffset;
++ return BadValue;
++ }
++
++ len = min(n - ind, 4 * stuff->longLength);
++
++ reply.bytesAfter = n - (ind + len);
++ reply.length = (len + 3) >> 2;
++
++ reply.format = 32;
++ reply.nItems = len / 4;
++ reply.propertyType = stuff->property;
++
++ WriteReplyToClient(client, sizeof(xGenericReply), &reply);
++
++ if (len)
++ {
++ client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write;
++
++ WriteSwappedDataToClient(client, len, (char *)wmsP + ind);
++ }
++
++ return(client->noClientException);
++ }
++ #endif
++
+ if (!pProp)
+ return NullPropertyReply(client, None, 0, &reply);
+
+@@ -643,6 +785,126 @@
+ return(client->noClientException);
+ }
+
++#ifdef NXAGENT_CLIPBOARD
++/* GetWindowProperty clipboard use only */
++int
++GetWindowProperty(pWin, property, longOffset, longLength, delete,
++ type, actualType, format, nItems, bytesAfter, propData )
++ WindowPtr pWin;
++ Atom property;
++ long longOffset;
++ long longLength;
++ Bool delete;
++ Atom type;
++ Atom *actualType;
++ int *format;
++ unsigned long *nItems;
++ unsigned long *bytesAfter;
++ unsigned char **propData;
++{
++ PropertyPtr pProp, prevProp;
++ unsigned long n, len, ind;
++
++ if (!pWin)
++ return BadWindow;
++
++
++ if (!ValidAtom(property))
++ {
++ return(BadAtom);
++ }
++ if ((type != AnyPropertyType) && !ValidAtom(type))
++ {
++ return(BadAtom);
++ }
++
++ pProp = wUserProps (pWin);
++ prevProp = (PropertyPtr)NULL;
++
++ while (pProp)
++ {
++ if (pProp->propertyName == property)
++ break;
++ prevProp = pProp;
++ pProp = pProp->next;
++ }
++
++
++ if (!pProp)
++ return (BadAtom);
++
++ /* If the request type and actual type don't match. Return the
++ property information, but not the data. */
++
++ if (((type != pProp->type) &&
++ (type != AnyPropertyType))
++ )
++ {
++ *bytesAfter = pProp->size;
++ *format = pProp->format;
++ *nItems = 0;
++ *actualType = pProp->type;
++ return(Success);
++ }
++
++/*
++ * Return type, format, value to client
++ */
++ n = (pProp->format/8) * pProp->size; /* size (bytes) of prop */
++ ind = longOffset << 2;
++
++ /* If longOffset is invalid such that it causes "len" to
++ be negative, it's a value error. */
++
++ if (n < ind)
++ {
++ return BadValue;
++ }
++
++ len = min(n - ind, 4 * longLength);
++
++ *bytesAfter = n - (ind + len);
++ *format = pProp->format;
++ *nItems = len / (pProp->format / 8 );
++ *actualType = pProp->type;
++
++ if (delete && (*bytesAfter == 0))
++ { /* send the event */
++ xEvent event;
++
++ event.u.u.type = PropertyNotify;
++ event.u.property.window = pWin->drawable.id;
++ event.u.property.state = PropertyDelete;
++ event.u.property.atom = pProp->propertyName;
++ event.u.property.time = currentTime.milliseconds;
++ DeliverEvents(pWin, &event, 1, (WindowPtr)NULL);
++ }
++
++ if (len)
++ {
++ *propData = (unsigned char *)(pProp->data) + ind;
++ }
++
++ if (delete && (*bytesAfter == 0))
++ { /* delete the Property */
++#ifdef LBX
++ if (pProp->tag_id)
++ TagDeleteTag(pProp->tag_id);
++#endif
++ if (prevProp == (PropertyPtr)NULL) /* takes care of head */
++ {
++ if (!(pWin->optional->userProps = pProp->next))
++ CheckWindowOptionalNeed (pWin);
++ }
++ else
++ prevProp->next = pProp->next;
++ xfree(pProp->data);
++ xfree(pProp);
++ }
++ return(Success);
++}
++#endif
++
+ int
+ ProcListProperties(ClientPtr client)
+ {
+@@ -727,3 +989,4 @@
+ else
+ return(result);
+ }
++
diff --git a/doc/nx-X11_vs_XOrg69_patches/NXrender.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/NXrender.c.NX.patch
new file mode 100644
index 000000000..62c9e339f
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/NXrender.c.NX.patch
@@ -0,0 +1,948 @@
+--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXrender.c.X.original 2015-02-13 14:03:44.748441432 +0100
++++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXrender.c 2015-02-10 19:13:13.800686036 +0100
+@@ -24,6 +24,23 @@
+ * Author: Keith Packard, SuSE, Inc.
+ */
+
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NXAGENT, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ #define NEED_REPLIES
+ #define NEED_EVENTS
+ #ifdef HAVE_DIX_CONFIG_H
+@@ -44,8 +61,6 @@
+ #include "servermd.h"
+ #include <X11/extensions/render.h>
+ #include <X11/extensions/renderproto.h>
+-#include "picturestr.h"
+-#include "glyphstr.h"
+ #include <X11/Xfuncproto.h>
+ #include "cursorstr.h"
+ #ifdef EXTMODULE
+@@ -56,6 +71,95 @@
+ #define UINT32_MAX 0xffffffffU
+ #endif
+
++#include "NXpicturestr.h"
++#include "NXglyphstr.h"
++
++#include "Trap.h"
++
++#include "Render.h"
++#include "Pixmaps.h"
++#include "Options.h"
++#include "Screen.h"
++#include "Cursor.h"
++
++/*
++ * Set here the required log level.
++ */
++
++#define PANIC
++#define WARNING
++#undef TEST
++#undef DEBUG
++
++#ifdef TEST
++#include "Literals.h"
++#endif
++
++/*
++ * From NXmiglyph.c.
++ */
++
++void miGlyphExtents(int nlist, GlyphListPtr list,
++ GlyphPtr *glyphs, BoxPtr extents);
++
++/*
++ * From NXmitrap.c.
++ */
++
++void miTrapezoidBounds (int ntrap, xTrapezoid *traps, BoxPtr box);
++
++/*
++ * Functions from Render.c.
++ */
++
++int nxagentCursorSaveRenderInfo(ScreenPtr, CursorPtr);
++void nxagentCursorPostSaveRenderInfo(CursorPtr, ScreenPtr, PicturePtr, int, int);
++int nxagentRenderRealizeCursor(ScreenPtr, CursorPtr);
++int nxagentCreatePicture(PicturePtr, Mask);
++void nxagentChangePicture(PicturePtr, Mask);
++int nxagentChangePictureClip(PicturePtr, int, int, xRectangle *, int, int);
++void nxagentComposite(CARD8, PicturePtr, PicturePtr, PicturePtr, INT16, INT16,
++ INT16, INT16, INT16, INT16, CARD16, CARD16);
++void nxagentCompositeRects(CARD8, PicturePtr, xRenderColor *, int, xRectangle *);
++void nxagentCreateGlyphSet(GlyphSetPtr glyphSet);
++void nxagentReferenceGlyphSet(GlyphSetPtr glyphSet);
++void nxagentFreeGlyphs(GlyphSetPtr glyphSet, CARD32 *gids, int nglyph);
++void nxagentFreeGlyphSet(GlyphSetPtr glyphSet);
++void nxagentSetPictureTransform(PicturePtr pPicture, pointer transform);
++void nxagentSetPictureFilter(PicturePtr pPicture, char *filter, int name_size,
++ pointer params, int nparams);
++void nxagentTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictFormatPtr maskFormat,
++ INT16 xSrc, INT16 ySrc, int ntrap, xTrapezoid *traps);
++
++void nxagentRenderCreateSolidFill(PicturePtr pPicture, xRenderColor *color);
++
++void nxagentRenderCreateLinearGradient(PicturePtr pPicture, xPointFixed *p1,
++ xPointFixed *p2, int nStops,
++ xFixed *stops,
++ xRenderColor *colors);
++
++void nxagentRenderCreateRadialGradient(PicturePtr pPicture, xPointFixed *inner,
++ xPointFixed *outer,
++ xFixed innerRadius,
++ xFixed outerRadius,
++ int nStops,
++ xFixed *stops,
++ xRenderColor *colors);
++
++void nxagentRenderCreateConicalGradient(PicturePtr pPicture,
++ xPointFixed *center,
++ xFixed angle, int nStops,
++ xFixed *stops,
++ xRenderColor *colors);
++
++
++/*
++ * The void pointer is actually a XGlyphElt8.
++ */
++
++void nxagentGlyphs(CARD8, PicturePtr, PicturePtr, PictFormatPtr,
++ INT16, INT16, int, void *, int, GlyphPtr *);
++
+ static int ProcRenderQueryVersion (ClientPtr pClient);
+ static int ProcRenderQueryPictFormats (ClientPtr pClient);
+ static int ProcRenderQueryPictIndexValues (ClientPtr pClient);
+@@ -290,8 +394,8 @@
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+- rep.majorVersion = RENDER_MAJOR;
+- rep.minorVersion = RENDER_MINOR;
++ rep.majorVersion = nxagentRenderVersionMajor;
++ rep.minorVersion = nxagentRenderVersionMinor;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+@@ -363,6 +467,8 @@
+ int n;
+ int numScreens;
+ int numSubpixel;
++
++ extern int nxagentAlphaEnabled;
+ /* REQUEST(xRenderQueryPictFormatsReq); */
+
+ REQUEST_SIZE_MATCH(xRenderQueryPictFormatsReq);
+@@ -439,7 +545,7 @@
+ pictForm->direct.greenMask = pFormat->direct.greenMask;
+ pictForm->direct.blue = pFormat->direct.blue;
+ pictForm->direct.blueMask = pFormat->direct.blueMask;
+- pictForm->direct.alpha = pFormat->direct.alpha;
++ pictForm->direct.alpha = nxagentAlphaEnabled ? pFormat->direct.alpha : 0;
+ pictForm->direct.alphaMask = pFormat->direct.alphaMask;
+ if (pFormat->type == PictTypeIndexed && pFormat->index.pColormap)
+ pictForm->colormap = pFormat->index.pColormap->mid;
+@@ -656,6 +762,8 @@
+ &error);
+ if (!pPicture)
+ return error;
++ nxagentCreatePicture(pPicture, stuff -> mask);
++
+ if (!AddResource (stuff->pid, PictureType, (pointer)pPicture))
+ return BadAlloc;
+ return Success;
+@@ -667,6 +775,7 @@
+ PicturePtr pPicture;
+ REQUEST(xRenderChangePictureReq);
+ int len;
++ int error;
+
+ REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq);
+ VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess,
+@@ -676,8 +785,12 @@
+ if (Ones(stuff->mask) != len)
+ return BadLength;
+
+- return ChangePicture (pPicture, stuff->mask, (XID *) (stuff + 1),
++ error = ChangePicture (pPicture, stuff->mask, (XID *) (stuff + 1),
+ (DevUnion *) 0, client);
++
++ nxagentChangePicture(pPicture, stuff->mask);
++
++ return error;
+ }
+
+ static int
+@@ -694,13 +807,26 @@
+ if (!pPicture->pDrawable)
+ return BadDrawable;
+
+- nr = (client->req_len << 2) - sizeof(xRenderChangePictureReq);
++ /*
++ * The original code used sizeof(xRenderChangePictureReq).
++ * This was harmless, as both structures have the same size.
++ *
++ * nr = (client->req_len << 2) - sizeof(xRenderChangePictureReq);
++ */
++ nr = (client->req_len << 2) - sizeof(xRenderSetPictureClipRectanglesReq);
+ if (nr & 4)
+ return BadLength;
+ nr >>= 3;
+ result = SetPictureClipRects (pPicture,
+ stuff->xOrigin, stuff->yOrigin,
+ nr, (xRectangle *) &stuff[1]);
++ nxagentChangePictureClip (pPicture,
++ CT_NONE,
++ nr,
++ (xRectangle *) &stuff[1],
++ (int)stuff -> xOrigin,
++ (int)stuff -> yOrigin);
++
+ if (client->noClientException != Success)
+ return(client->noClientException);
+ else
+@@ -717,6 +843,7 @@
+
+ VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityDestroyAccess,
+ RenderErrBase + BadPicture);
++
+ FreeResource (stuff->picture, RT_NONE);
+ return(client->noClientException);
+ }
+@@ -733,6 +860,71 @@
+ return FALSE;
+ }
+
++/*
++ * Check if both pictures have drawables which are
++ * virtual pixmaps. See the corresponding define
++ * in NXpicture.c
++ */
++
++#define NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL
++
++#ifdef NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL
++
++#define nxagentCompositePredicate(pSrc, pDst) TRUE
++
++#else
++
++/*
++ * This is still under development. The final
++ * goal is to let pictures point to the real
++ * pixmaps instead of pointing to virtuals.
++ */
++
++int nxagentCompositePredicate(PicturePtr pSrc, PicturePtr pDst)
++{
++ PixmapPtr pPixmap1;
++ PixmapPtr pPixmap2;
++
++ pPixmap1 = (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP ?
++ ((PixmapPtr) pSrc -> pDrawable) : NULL);
++
++ pPixmap2 = (pDst -> pDrawable -> type == DRAWABLE_PIXMAP ?
++ ((PixmapPtr) pDst -> pDrawable) : NULL);
++
++ if (pPixmap1 == NULL || pPixmap2 == NULL)
++ {
++ #ifdef TEST
++ fprintf(stderr, "nxagentCompositePredicate: Case 0.\n");
++ #endif
++
++ return FALSE;
++ }
++ else
++ {
++ #ifdef TEST
++ fprintf(stderr, "nxagentCompositePredicate: Case 1.\n");
++ #endif
++
++ if (nxagentPixmapIsVirtual(pPixmap1) == 1 &&
++ nxagentPixmapIsVirtual(pPixmap2) == 1)
++ {
++ #ifdef TEST
++ fprintf(stderr, "nxagentCompositePredicate: Case 2.\n");
++ #endif
++
++ return TRUE;
++ }
++ }
++
++ #ifdef TEST
++ fprintf(stderr, "nxagentCompositePredicate: Case 3.\n");
++ #endif
++
++ return FALSE;
++}
++
++#endif
++
+ static int
+ ProcRenderComposite (ClientPtr client)
+ {
+@@ -753,9 +945,32 @@
+ RenderErrBase + BadPicture);
+ VERIFY_ALPHA (pMask, stuff->mask, client, SecurityReadAccess,
+ RenderErrBase + BadPicture);
++/*
++FIXME: Imported change from newest version of Xorg. Changed pSrc to pDst.
++
+ if ((pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) ||
+ (pMask && pMask->pDrawable && pSrc->pDrawable->pScreen != pMask->pDrawable->pScreen))
+ return BadMatch;
++*/
++ if ((pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) ||
++ (pMask && pMask->pDrawable && pDst->pDrawable->pScreen != pMask->pDrawable->pScreen))
++ return BadMatch;
++
++ ValidatePicture (pSrc);
++ if (pMask)
++ ValidatePicture (pMask);
++ ValidatePicture (pDst);
++
++ #ifdef NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL
++
++ if (nxagentCompositePredicate(pSrc, pDst))
++ {
++ #ifdef TEST
++ fprintf(stderr, "ProcRenderComposite: Going to composite with "
++ "source at [%p] mask at [%p] and destination at [%p].\n",
++ (void *) pSrc, (void *) pMask, (void *) pDst);
++ #endif
++
+ CompositePicture (stuff->op,
+ pSrc,
+ pMask,
+@@ -768,6 +983,78 @@
+ stuff->yDst,
+ stuff->width,
+ stuff->height);
++ }
++
++ #else
++
++ if (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP &&
++ pDst -> pDrawable -> type == DRAWABLE_PIXMAP &&
++ (!pMask || pMask -> pDrawable -> type == DRAWABLE_PIXMAP))
++ {
++ PixmapPtr pVirtualPixmapSrc;
++ PixmapPtr pVirtualPixmapDst;
++ PixmapPtr pVirtualPixmapMask;
++
++ PicturePtr pVirtualPictureSrc;
++ PicturePtr pVirtualPictureDst;
++ PicturePtr pVirtualPictureMask;
++
++ pVirtualPixmapSrc = (PixmapPtr) pSrc -> pDrawable;
++ pVirtualPictureSrc = nxagentPixmapPriv(pVirtualPixmapSrc) -> pPicture;
++
++ pVirtualPixmapDst = (PixmapPtr) pDst -> pDrawable;
++ pVirtualPictureDst = nxagentPixmapPriv(pVirtualPixmapDst) -> pPicture;
++
++ if (pMask)
++ {
++ pVirtualPixmapMask = (PixmapPtr) pMask -> pDrawable;
++ pVirtualPictureMask = nxagentPixmapPriv(pVirtualPixmapMask) -> pPicture;
++ }
++ else
++ {
++ pVirtualPixmapMask = NULL;
++ pVirtualPictureMask = NULL;
++ }
++
++ if (pVirtualPictureSrc && pVirtualPictureDst)
++ {
++ #ifdef TEST
++ fprintf(stderr, "ProcRenderComposite: Going to composite with "
++ "source at [%p] mask at [%p] and destination at [%p].\n",
++ (void *) pVirtualPixmapSrc, (void *) pVirtualPixmapMask,
++ (void *) pVirtualPixmapDst);
++ #endif
++
++ CompositePicture (stuff->op,
++ pVirtualPictureSrc,
++ pVirtualPictureMask,
++ pVirtualPictureDst,
++ stuff->xSrc,
++ stuff->ySrc,
++ stuff->xMask,
++ stuff->yMask,
++ stuff->xDst,
++ stuff->yDst,
++ stuff->width,
++ stuff->height);
++ }
++ }
++
++ #endif
++
++ nxagentComposite (stuff -> op,
++ pSrc,
++ pMask,
++ pDst,
++ stuff -> xSrc,
++ stuff -> ySrc,
++ stuff -> xMask,
++ stuff -> yMask,
++ stuff -> xDst,
++ stuff -> yDst,
++ stuff -> width,
++ stuff -> height);
++
+ return Success;
+ }
+
+@@ -818,9 +1105,33 @@
+ return BadLength;
+ ntraps /= sizeof (xTrapezoid);
+ if (ntraps)
++ {
++ if (pFormat != NULL)
++ {
++ nxagentTrapezoidExtents = (BoxPtr) xalloc(sizeof(BoxRec));
++
++ miTrapezoidBounds (ntraps, (xTrapezoid *) &stuff[1], nxagentTrapezoidExtents);
++ }
++
++ if (nxagentCompositePredicate(pSrc, pDst) == 1)
++ {
+ CompositeTrapezoids (stuff->op, pSrc, pDst, pFormat,
+ stuff->xSrc, stuff->ySrc,
+ ntraps, (xTrapezoid *) &stuff[1]);
++ }
++
++ nxagentTrapezoids (stuff->op, pSrc, pDst, pFormat,
++ stuff->xSrc, stuff->ySrc,
++ ntraps, (xTrapezoid *) &stuff[1]);
++
++ if (nxagentTrapezoidExtents != NullBox)
++ {
++ xfree(nxagentTrapezoidExtents);
++
++ nxagentTrapezoidExtents = NullBox;
++ }
++ }
++
+ return client->noClientException;
+ }
+
+@@ -1029,6 +1340,9 @@
+ return BadAlloc;
+ if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet))
+ return BadAlloc;
++
++ nxagentCreateGlyphSet(glyphSet);
++
+ return Success;
+ }
+
+@@ -1052,6 +1366,9 @@
+ return RenderErrBase + BadGlyphSet;
+ }
+ glyphSet->refcnt++;
++
++ nxagentReferenceGlyphSet(glyphSet);
++
+ if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet))
+ return BadAlloc;
+ return client->noClientException;
+@@ -1076,6 +1393,9 @@
+ client->errorValue = stuff->glyphset;
+ return RenderErrBase + BadGlyphSet;
+ }
++
++ nxagentFreeGlyphSet(glyphSet);
++
+ FreeResource (stuff->glyphset, RT_NONE);
+ return client->noClientException;
+ }
+@@ -1092,7 +1412,7 @@
+ REQUEST(xRenderAddGlyphsReq);
+ GlyphNewRec glyphsLocal[NLOCALGLYPH];
+ GlyphNewPtr glyphsBase, glyphs;
+- GlyphPtr glyph;
++ GlyphPtr glyph = NULL;
+ int remain, nglyphs;
+ CARD32 *gids;
+ xGlyphInfo *gi;
+@@ -1100,6 +1420,8 @@
+ int size;
+ int err = BadAlloc;
+
++ int totSizeImages;
++
+ REQUEST_AT_LEAST_SIZE(xRenderAddGlyphsReq);
+ glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client,
+ stuff->glyphset,
+@@ -1128,10 +1450,12 @@
+
+ glyphs = glyphsBase;
+
++ totSizeImages = 0;
+ gids = (CARD32 *) (stuff + 1);
+ gi = (xGlyphInfo *) (gids + nglyphs);
+ bits = (CARD8 *) (gi + nglyphs);
+ remain -= (sizeof (CARD32) + sizeof (xGlyphInfo)) * nglyphs;
++
+ while (remain >= 0 && nglyphs)
+ {
+ glyph = AllocateGlyph (gi, glyphSet->fdepth);
+@@ -1152,12 +1476,14 @@
+ if (size & 3)
+ size += 4 - (size & 3);
+ bits += size;
++ totSizeImages += size;
+ remain -= size;
+ gi++;
+ gids++;
+ glyphs++;
+ nglyphs--;
+ }
++
+ if (nglyphs || remain)
+ {
+ err = BadLength;
+@@ -1216,6 +1542,9 @@
+ }
+ nglyph = ((client->req_len << 2) - sizeof (xRenderFreeGlyphsReq)) >> 2;
+ gids = (CARD32 *) (stuff + 1);
++
++ nxagentFreeGlyphs(glyphSet, gids, nglyph);
++
+ while (nglyph-- > 0)
+ {
+ glyph = *gids++;
+@@ -1228,6 +1557,14 @@
+ return client->noClientException;
+ }
+
++typedef struct XGlyphElt8{
++ GlyphSet glyphset;
++ _Xconst char *chars;
++ int nchars;
++ int xOff;
++ int yOff;
++} XGlyphElt8;
++
+ static int
+ ProcRenderCompositeGlyphs (ClientPtr client)
+ {
+@@ -1248,6 +1585,8 @@
+ int size;
+ int n;
+
++ XGlyphElt8 *elements, *elementsBase;
++
+ REQUEST(xRenderCompositeGlyphsReq);
+
+ REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq);
+@@ -1335,9 +1674,15 @@
+ if (!listsBase)
+ return BadAlloc;
+ }
++
++ elementsBase = xalloc(nlist * sizeof(XGlyphElt8));
++ if (!elementsBase)
++ return BadAlloc;
++
+ buffer = (CARD8 *) (stuff + 1);
+ glyphs = glyphsBase;
+ lists = listsBase;
++ elements = elementsBase;
+ while (buffer + sizeof (xGlyphElt) < end)
+ {
+ elt = (xGlyphElt *) buffer;
+@@ -1345,6 +1690,11 @@
+
+ if (elt->len == 0xff)
+ {
++ #ifdef DEBUG
++ fprintf(stderr, "ProcRenderCompositeGlyphs: Glyphset change with base size [%d].\n",
++ size);
++ #endif
++
+ if (buffer + sizeof (GlyphSet) < end)
+ {
+ memcpy(&gs, buffer, sizeof(GlyphSet));
+@@ -1370,6 +1720,22 @@
+ lists->yOff = elt->deltay;
+ lists->format = glyphSet->format;
+ lists->len = 0;
++
++ if (glyphSet -> remoteID == 0)
++ {
++ #ifdef TEST
++ fprintf(stderr, "ProcRenderCompositeGlyphs: Going to reconnect glyphset at [%p].\n",
++ (void *) glyphSet);
++ #endif
++
++ nxagentReconnectGlyphSet(glyphSet, (XID) 0, (void*) NULL);
++ }
++
++ elements -> glyphset = glyphSet -> remoteID;
++ elements -> chars = (char *) buffer;
++ elements -> nchars = elt->len;
++ elements -> xOff = elt->deltax;
++ elements -> yOff = elt->deltay;
+ n = elt->len;
+ while (n--)
+ {
+@@ -1396,26 +1762,65 @@
+ if (space & 3)
+ buffer += 4 - (space & 3);
+ lists++;
++ elements++;
+ }
+ }
+ if (buffer > end)
+ return BadLength;
+
+- CompositeGlyphs (stuff->op,
+- pSrc,
+- pDst,
+- pFormat,
+- stuff->xSrc,
+- stuff->ySrc,
+- nlist,
+- listsBase,
+- glyphsBase);
++ /*
++ * We need to know the glyphs extents to synchronize
++ * the drawables involved in the composite text ope-
++ * ration. Also we need to synchronize only the back-
++ * ground of the text we are going to render, so the
++ * operations on the framebuffer must be executed
++ * after the X requests.
++ */
++
++ nxagentGlyphsExtents = (BoxPtr) xalloc(sizeof(BoxRec));
++
++ miGlyphExtents(nlist, listsBase, glyphsBase, nxagentGlyphsExtents);
++
++ nxagentGlyphs(stuff -> op,
++ pSrc,
++ pDst,
++ pFormat,
++ stuff -> xSrc,
++ stuff -> ySrc,
++ nlist,
++ elementsBase,
++ size,
++ glyphsBase);
++
++ if (nxagentCompositePredicate(pSrc, pDst) == 1)
++ {
++ #ifdef TEST
++ fprintf(stderr, "ProcRenderCompositeGlyphs: Going to composite glyphs with "
++ "source at [%p] and destination at [%p].\n",
++ (void *) pSrc, (void *) pDst);
++ #endif
++
++ CompositeGlyphs(stuff -> op,
++ pSrc,
++ pDst,
++ pFormat,
++ stuff -> xSrc,
++ stuff -> ySrc,
++ nlist,
++ listsBase,
++ glyphsBase);
++ }
++
++ xfree(nxagentGlyphsExtents);
++ nxagentGlyphsExtents = NullBox;
+
+ if (glyphsBase != glyphsLocal)
+ DEALLOCATE_LOCAL (glyphsBase);
+ if (listsBase != listsLocal)
+ DEALLOCATE_LOCAL (listsBase);
+
++ xfree(elementsBase);
++
+ return client->noClientException;
+ }
+
+@@ -1447,6 +1852,13 @@
+ &stuff->color,
+ things,
+ (xRectangle *) &stuff[1]);
++
++ ValidatePicture (pDst);
++ nxagentCompositeRects(stuff -> op,
++ pDst,
++ &stuff -> color,
++ things,
++ (xRectangle *) &stuff[1]);
+
+ return client->noClientException;
+ }
+@@ -1495,6 +1907,8 @@
+ CARD32 twocolor[3];
+ int ncolor;
+
++ RealizeCursorProcPtr saveRealizeCursor;
++
+ REQUEST_SIZE_MATCH (xRenderCreateCursorReq);
+ LEGAL_NEW_RESOURCE(stuff->cid, client);
+
+@@ -1662,6 +2076,20 @@
+ cm.height = height;
+ cm.xhot = stuff->x;
+ cm.yhot = stuff->y;
++
++ /*
++ * This cursor uses RENDER, so we make sure
++ * that it is allocated in a way that allows
++ * the mi and dix layers to handle it but we
++ * later create it on the server by mirror-
++ * ing the RENDER operation we got from the
++ * client.
++ */
++
++ saveRealizeCursor = pScreen -> RealizeCursor;
++
++ pScreen -> RealizeCursor = nxagentCursorSaveRenderInfo;
++
+ pCursor = AllocCursorARGB (srcbits, mskbits, argbbits, &cm,
+ GetColor(twocolor[0], 16),
+ GetColor(twocolor[0], 8),
+@@ -1669,7 +2097,27 @@
+ GetColor(twocolor[1], 16),
+ GetColor(twocolor[1], 8),
+ GetColor(twocolor[1], 0));
+- if (pCursor && AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor))
++
++ pScreen -> RealizeCursor = saveRealizeCursor;
++
++ /*
++ * Store into the private data members the
++ * information needed to recreate it at
++ * reconnection. This is done in two steps
++ * as in the first step we don't have the
++ * picture info.
++ */
++
++ if (pCursor == NULL)
++ {
++ return BadAlloc;
++ }
++
++ nxagentCursorPostSaveRenderInfo(pCursor, pScreen, pSrc, stuff -> x, stuff -> y);
++
++ nxagentRenderRealizeCursor(pScreen, pCursor);
++
++ if (AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor))
+ return (client->noClientException);
+ return BadAlloc;
+ }
+@@ -1685,6 +2133,9 @@
+ VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess,
+ RenderErrBase + BadPicture);
+ result = SetPictureTransform (pPicture, (PictTransform *) &stuff->transform);
++
++ nxagentSetPictureTransform(pPicture, &stuff->transform);
++
+ if (client->noClientException != Success)
+ return(client->noClientException);
+ else
+@@ -1785,7 +2236,7 @@
+ {
+ register int n;
+
+- for (i = 0; i < reply->numAliases; i++)
++ for (i = 0; i < (int)reply->numAliases; i++)
+ {
+ swaps (&aliases[i], n);
+ }
+@@ -1817,6 +2268,9 @@
+ params = (xFixed *) (name + ((stuff->nbytes + 3) & ~3));
+ nparams = ((xFixed *) stuff + client->req_len) - params;
+ result = SetPictureFilter (pPicture, name, stuff->nbytes, params, nparams);
++
++ nxagentSetPictureFilter(pPicture, name, stuff->nbytes, params, nparams);
++
+ return result;
+ }
+
+@@ -1859,7 +2313,14 @@
+ xfree (cursors);
+ if (ret != Success)
+ return ret;
+-
++
++ nxagentAnimCursorBits = pCursor -> bits;
++
++ for (i = 0; i < MAXSCREENS; i++)
++ {
++ pCursor -> devPriv[i] = NULL;
++ }
++
+ if (AddResource (stuff->cid, RT_CURSOR, (pointer)pCursor))
+ return client->noClientException;
+ return BadAlloc;
+@@ -1901,6 +2362,11 @@
+ pPicture = CreateSolidPicture(stuff->pid, &stuff->color, &error);
+ if (!pPicture)
+ return error;
++ /* AGENT SERVER */
++
++ nxagentRenderCreateSolidFill(pPicture, &stuff -> color);
++
++ /* AGENT SERVER */
+ if (!AddResource (stuff->pid, PictureType, (pointer)pPicture))
+ return BadAlloc;
+ return Success;
+@@ -1932,6 +2398,12 @@
+ stuff->nStops, stops, colors, &error);
+ if (!pPicture)
+ return error;
++ /* AGENT SERVER */
++
++ nxagentRenderCreateLinearGradient(pPicture, &stuff->p1, &stuff->p2,
++ stuff->nStops, stops, colors);
++
++ /* AGENT SERVER */
+ if (!AddResource (stuff->pid, PictureType, (pointer)pPicture))
+ return BadAlloc;
+ return Success;
+@@ -1962,6 +2434,14 @@
+ stuff->nStops, stops, colors, &error);
+ if (!pPicture)
+ return error;
++ /* AGENT SERVER */
++
++ nxagentRenderCreateRadialGradient(pPicture, &stuff->inner, &stuff->outer,
++ stuff->inner_radius,
++ stuff->outer_radius,
++ stuff->nStops, stops, colors);
++
++ /* AGENT SERVER */
+ if (!AddResource (stuff->pid, PictureType, (pointer)pPicture))
+ return BadAlloc;
+ return Success;
+@@ -1991,6 +2471,13 @@
+ stuff->nStops, stops, colors, &error);
+ if (!pPicture)
+ return error;
++ /* AGENT SERVER */
++
++ nxagentRenderCreateConicalGradient(pPicture, &stuff->center,
++ stuff->angle, stuff->nStops, stops,
++ colors);
++
++ /* AGENT SERVER */
+ if (!AddResource (stuff->pid, PictureType, (pointer)pPicture))
+ return BadAlloc;
+ return Success;
+@@ -2000,10 +2487,41 @@
+ static int
+ ProcRenderDispatch (ClientPtr client)
+ {
++ int result;
++
+ REQUEST(xReq);
++
++ /*
++ * Let the client fail if we are
++ * hiding the RENDER extension.
++ */
+
++ if (nxagentRenderTrap)
++ {
++ return BadRequest;
++ }
++
+ if (stuff->data < RenderNumberRequests)
+- return (*ProcRenderVector[stuff->data]) (client);
++ {
++ #ifdef TEST
++ fprintf(stderr, "ProcRenderDispatch: Request [%s] OPCODE#%d.\n",
++ nxagentRenderRequestLiteral[stuff->data], stuff->data);
++ #endif
++
++ /*
++ * Set the nxagentGCTrap flag while
++ * dispatching a render operation to
++ * avoid reentrancy in GCOps.c.
++ */
++
++ nxagentGCTrap = 1;
++
++ result = (*ProcRenderVector[stuff->data]) (client);
++
++ nxagentGCTrap = 0;
++
++ return result;
++ }
+ else
+ return BadRequest;
+ }
+@@ -2253,7 +2771,7 @@
+ SProcRenderAddGlyphs (ClientPtr client)
+ {
+ register int n;
+- register int i;
++ register unsigned int i;
+ CARD32 *gids;
+ void *end;
+ xGlyphInfo *gi;
+@@ -2595,10 +3113,36 @@
+ static int
+ SProcRenderDispatch (ClientPtr client)
+ {
++ int result;
++
+ REQUEST(xReq);
+
++ /*
++ * Let the client fail if we are
++ * hiding the RENDER extension.
++ */
++
++ if (nxagentRenderTrap)
++ {
++ return BadRequest;
++ }
++
+ if (stuff->data < RenderNumberRequests)
+- return (*SProcRenderVector[stuff->data]) (client);
++ {
++ /*
++ * Set the nxagentGCTrap flag while
++ * dispatching a render operation to
++ * avoid reentrancy in GCOps.c.
++ */
++
++ nxagentGCTrap = 1;
++
++ result = (*SProcRenderVector[stuff->data]) (client);
++
++ nxagentGCTrap = 0;
++
++ return result;
++ }
+ else
+ return BadRequest;
+ }
+@@ -3314,3 +3858,4 @@
+ }
+
+ #endif /* PANORAMIX */
++
diff --git a/doc/nx-X11_vs_XOrg69_patches/NXresource.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/NXresource.c.NX.patch
new file mode 100644
index 000000000..3c7f45e46
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/NXresource.c.NX.patch
@@ -0,0 +1,426 @@
+--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXresource.c.X.original 2015-02-13 14:03:44.748441432 +0100
++++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXresource.c 2015-02-10 19:13:13.820685287 +0100
+@@ -1,3 +1,20 @@
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NXAGENT, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /************************************************************
+
+ Copyright 1987, 1998 The Open Group
+@@ -125,6 +142,20 @@
+ #endif
+ #include <assert.h>
+
++#ifdef NXAGENT_SERVER
++
++#include "Agent.h"
++#include "Font.h"
++#include "Pixmaps.h"
++#include "GCs.h"
++
++#define PANIC
++#define WARNING
++#undef TEST
++#undef DEBUG
++
++#endif
++
+ static void RebuildTable(
+ int /*client*/
+ );
+@@ -170,6 +201,10 @@
+
+ #endif
+
++#ifdef NXAGENT_SERVER
++static int nxagentResChangedFlag = 0;
++#endif
++
+ RESTYPE
+ CreateNewResourceType(DeleteType deleteFunc)
+ {
+@@ -422,13 +457,107 @@
+ return id;
+ }
+
++#ifdef NXAGENT_SERVER
++
++int nxagentFindClientResource(int client, RESTYPE type, pointer value)
++{
++ ResourcePtr pResource;
++ ResourcePtr *resources;
++
++ int i;
++
++ for (i = 0; i < clientTable[client].buckets; i++)
++ {
++ resources = clientTable[client].resources;
++
++ for (pResource = resources[i]; pResource; pResource = pResource -> next)
++ {
++ if (pResource -> type == type && pResource -> value == value)
++ {
++ #ifdef TEST
++ fprintf(stderr, "nxagentFindClientResource: Found resource [%p] type [%lu] "
++ "for client [%d].\n", (void *) value,
++ pResource -> type, client);
++ #endif
++
++ return 1;
++ }
++ }
++ }
++
++ return 0;
++}
++
++int nxagentSwitchResourceType(int client, RESTYPE type, pointer value)
++{
++ ResourcePtr pResource;
++ ResourcePtr *resources;
++
++ RESTYPE internalType = 0;
++
++ int i;
++
++ if (type == RT_PIXMAP)
++ {
++ internalType = RT_NX_PIXMAP;
++ }
++ else if (type == RT_GC)
++ {
++ internalType = RT_NX_GC;
++ }
++ else if (type == RT_FONT)
++ {
++ internalType = RT_NX_FONT;
++ }
++ else
++ {
++ return 0;
++ }
++
++ if (client == serverClient -> index)
++ {
++ #ifdef TEST
++ fprintf(stderr, "nxagentSwitchResourceType: Requesting client is [%d]. Skipping the resource switch.\n",
++ client);
++ #endif
++
++ return 0;
++ }
++
++ for (i = 0; i < clientTable[serverClient -> index].buckets; i++)
++ {
++ resources = clientTable[serverClient -> index].resources;
++
++ for (pResource = resources[i]; pResource; pResource = pResource -> next)
++ {
++ if (pResource -> type == internalType &&
++ pResource -> value == value)
++ {
++ #ifdef TEST
++ fprintf(stderr, "nxagentSwitchResourceType: Changing resource [%p] type from [%lu] to "
++ "[%lu] for server client [%d].\n", (void *) value,
++ (unsigned long) pResource -> type, (unsigned long) type, serverClient -> index);
++ #endif
++
++ FreeResource(pResource -> id, RT_NONE);
++
++ return 1;
++ }
++ }
++ }
++
++ return 0;
++}
++
++#endif
++
+ Bool
+ AddResource(XID id, RESTYPE type, pointer value)
+ {
+ int client;
+ register ClientResourceRec *rrec;
+ register ResourcePtr res, *head;
+-
++
+ client = CLIENT_ID(id);
+ rrec = &clientTable[client];
+ if (!rrec->buckets)
+@@ -437,6 +566,18 @@
+ (unsigned long)id, type, (unsigned long)value, client);
+ FatalError("client not in use\n");
+ }
++
++#ifdef NXAGENT_SERVER
++
++ nxagentSwitchResourceType(client, type, value);
++
++ #ifdef TEST
++ fprintf(stderr, "AddResource: Adding resource for client [%d] type [%lu] value [%p] id [%lu].\n",
++ client, (unsigned long) type, (void *) value, (unsigned long) id);
++ #endif
++
++#endif
++
+ if ((rrec->elements >= 4*rrec->buckets) &&
+ (rrec->hashsize < MAXHASHSIZE))
+ RebuildTable(client);
+@@ -453,6 +594,9 @@
+ res->value = value;
+ *head = res;
+ rrec->elements++;
++ #ifdef NXAGENT_SERVER
++ nxagentResChangedFlag = 1;
++ #endif
+ if (!(id & SERVER_BIT) && (id >= rrec->expectID))
+ rrec->expectID = id + 1;
+ return TRUE;
+@@ -517,6 +661,14 @@
+ int elements;
+ Bool gotOne = FALSE;
+
++#ifdef NXAGENT_SERVER
++
++ #ifdef TEST
++ fprintf(stderr, "FreeResource: Freeing resource id [%lu].\n", (unsigned long) id);
++ #endif
++
++#endif
++
+ if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets)
+ {
+ head = &clientTable[cid].resources[Hash(cid, id)];
+@@ -530,6 +682,9 @@
+ RESTYPE rtype = res->type;
+ *prev = res->next;
+ elements = --*eltptr;
++ #ifdef NXAGENT_SERVER
++ nxagentResChangedFlag = 1;
++ #endif
+ if (rtype & RC_CACHED)
+ FlushClientCaches(res->id);
+ if (rtype != skipDeleteFuncType)
+@@ -570,6 +725,9 @@
+ if (res->id == id && res->type == type)
+ {
+ *prev = res->next;
++ #ifdef NXAGENT_SERVER
++ nxagentResChangedFlag = 1;
++ #endif
+ if (type & RC_CACHED)
+ FlushClientCaches(res->id);
+ if (!skipFree)
+@@ -634,10 +792,28 @@
+ int i, elements;
+ register int *eltptr;
+
++ #ifdef NXAGENT_SERVER
++ register ResourcePtr **resptr;
++ #endif
++
+ if (!client)
+ client = serverClient;
+
++/*
++ * If func triggers a resource table
++ * rebuild then restart the loop.
++ */
++
++#ifdef NXAGENT_SERVER
++RestartLoop:
++#endif
++
+ resources = clientTable[client->index].resources;
++
++ #ifdef NXAGENT_SERVER
++ resptr = &clientTable[client->index].resources;
++ #endif
++
+ eltptr = &clientTable[client->index].elements;
+ for (i = 0; i < clientTable[client->index].buckets; i++)
+ {
+@@ -646,8 +822,44 @@
+ next = this->next;
+ if (!type || this->type == type) {
+ elements = *eltptr;
++
++ /*
++ * FIXME:
++ * It is not safe to let a function change the resource
++ * table we are reading!
++ */
++
++ #ifdef NXAGENT_SERVER
++ nxagentResChangedFlag = 0;
++ #endif
+ (*func)(this->value, this->id, cdata);
++
++ /*
++ * Avoid that a call to RebuildTable() could invalidate the
++ * pointer. This is safe enough, because in RebuildTable()
++ * the new pointer is allocated just before the old one is
++ * freed, so it can't point to the same address.
++ */
++
++ #ifdef NXAGENT_SERVER
++ if (*resptr != resources)
++ goto RestartLoop;
++ #endif
++
++ /*
++ * It's not enough to check if the number of elements has
++ * changed, beacause it could happen that the number of
++ * resources that have been added matches the number of
++ * the freed ones.
++ * 'nxagentResChangedFlag' is set if a resource has been
++ * added or freed.
++ */
++
++ #ifdef NXAGENT_SERVER
++ if (*eltptr != elements || nxagentResChangedFlag)
++ #else
+ if (*eltptr != elements)
++ #endif
+ next = resources[i]; /* start over */
+ }
+ }
+@@ -665,10 +877,28 @@
+ int i, elements;
+ register int *eltptr;
+
++ #ifdef NXAGENT_SERVER
++ register ResourcePtr **resptr;
++ #endif
++
+ if (!client)
+ client = serverClient;
+
++/*
++ * If func triggers a resource table
++ * rebuild then restart the loop.
++ */
++
++#ifdef NXAGENT_SERVER
++RestartLoop:
++#endif
++
+ resources = clientTable[client->index].resources;
++
++ #ifdef NXAGENT_SERVER
++ resptr = &clientTable[client->index].resources;
++ #endif
++
+ eltptr = &clientTable[client->index].elements;
+ for (i = 0; i < clientTable[client->index].buckets; i++)
+ {
+@@ -676,8 +906,44 @@
+ {
+ next = this->next;
+ elements = *eltptr;
++
++ /*
++ * FIXME:
++ * It is not safe to let a function change the resource
++ * table we are reading!
++ */
++
++ #ifdef NXAGENT_SERVER
++ nxagentResChangedFlag = 0;
++ #endif
+ (*func)(this->value, this->id, this->type, cdata);
++
++ /*
++ * Avoid that a call to RebuildTable() could invalidate the
++ * pointer. This is safe enough, because in RebuildTable()
++ * the new pointer is allocated just before the old one is
++ * freed, so it can't point to the same address.
++ */
++
++ #ifdef NXAGENT_SERVER
++ if (*resptr != resources)
++ goto RestartLoop;
++ #endif
++
++ /*
++ * It's not enough to check if the number of elements has
++ * changed, beacause it could happen that the number of
++ * resources that have been added matches the number of
++ * the freed ones.
++ * 'nxagentResChangedFlag' is set if a resource has been
++ * added or freed.
++ */
++
++ #ifdef NXAGENT_SERVER
++ if (*eltptr != elements || nxagentResChangedFlag)
++ #else
+ if (*eltptr != elements)
++ #endif
+ next = resources[i]; /* start over */
+ }
+ }
+@@ -695,15 +961,44 @@
+ ResourcePtr this;
+ int i;
+
++ #ifdef NXAGENT_SERVER
++ ResourcePtr **resptr;
++ Bool res;
++ #endif
++
+ if (!client)
+ client = serverClient;
+
++/*
++ * If func triggers a resource table
++ * rebuild then restart the loop.
++ */
++
++#ifdef NXAGENT_SERVER
++RestartLoop:
++#endif
++
+ resources = clientTable[client->index].resources;
++
++ #ifdef NXAGENT_SERVER
++ resptr = &clientTable[client->index].resources;
++ #endif
++
+ for (i = 0; i < clientTable[client->index].buckets; i++) {
+ for (this = resources[i]; this; this = this->next) {
+ if (!type || this->type == type) {
++ #ifdef NXAGENT_SERVER
++ res = (*func)(this->value, this->id, cdata);
++
++ if (*resptr != resources)
++ goto RestartLoop;
++
++ if (res)
++ return this->value;
++ #else
+ if((*func)(this->value, this->id, cdata))
+ return this->value;
++ #endif
+ }
+ }
+ }
+@@ -952,3 +1247,4 @@
+ }
+
+ #endif /* XCSECURITY */
++
diff --git a/doc/nx-X11_vs_XOrg69_patches/NXshm.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/NXshm.c.NX.patch
new file mode 100644
index 000000000..ecc5d490c
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/NXshm.c.NX.patch
@@ -0,0 +1,373 @@
+--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXshm.c.X.original 2015-02-13 14:03:44.748441432 +0100
++++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXshm.c 2015-02-10 19:13:13.812685587 +0100
+@@ -1,3 +1,20 @@
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NXAGENT, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /* $XFree86: xc/programs/Xserver/Xext/shm.c,v 3.41 2003/12/17 23:28:56 alanh Exp $ */
+ /************************************************************
+
+@@ -73,6 +90,31 @@
+
+ #include "modinit.h"
+
++#include "Trap.h"
++#include "Agent.h"
++#include "Drawable.h"
++#include "Pixmaps.h"
++
++/*
++ * Set here the required log level.
++ */
++
++#define PANIC
++#define WARNING
++#undef TEST
++#undef DEBUG
++
++#ifdef TEST
++#include "Literals.h"
++#endif
++
++extern void fbGetImage(DrawablePtr pDrw, int x, int y, int w, int h,
++ unsigned int format, unsigned long planeMask, char *d);
++
++extern void fbPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth,
++ int x, int y, int w, int h, int leftPad, int format,
++ char *pImage);
++
+ typedef struct _ShmDesc {
+ struct _ShmDesc *next;
+ int shmid;
+@@ -216,15 +258,25 @@
+ }
+ #endif
+
++ if (nxagentOption(SharedMemory) == False)
++ {
++ return;
++ }
++
+ sharedPixmaps = xFalse;
+ pixmapFormat = 0;
+ {
+- sharedPixmaps = xTrue;
++ sharedPixmaps = nxagentOption(SharedPixmaps);
+ pixmapFormat = shmPixFormat[0];
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ if (!shmFuncs[i])
++ {
++ #ifdef TEST
++ fprintf(stderr, "ShmExtensionInit: Registering shmFuncs as miFuncs.\n");
++ #endif
+ shmFuncs[i] = &miFuncs;
++ }
+ if (!shmFuncs[i]->CreatePixmap)
+ sharedPixmaps = xFalse;
+ if (shmPixFormat[i] && (shmPixFormat[i] != pixmapFormat))
+@@ -335,6 +387,9 @@
+ ShmRegisterFbFuncs(pScreen)
+ ScreenPtr pScreen;
+ {
++ #ifdef TEST
++ fprintf(stderr, "ShmRegisterFbFuncs: Registering shmFuncs as fbFuncs.\n");
++ #endif
+ shmFuncs[pScreen->myNum] = &fbFuncs;
+ }
+
+@@ -512,12 +567,17 @@
+ PixmapPtr pmap;
+ GCPtr putGC;
+
++ nxagentShmTrap = 0;
+ putGC = GetScratchGC(depth, dst->pScreen);
+ if (!putGC)
++ {
++ nxagentShmTrap = 1;
+ return;
++ }
+ pmap = (*dst->pScreen->CreatePixmap)(dst->pScreen, sw, sh, depth);
+ if (!pmap)
+ {
++ nxagentShmTrap = 1;
+ FreeScratchGC(putGC);
+ return;
+ }
+@@ -532,6 +592,7 @@
+ (void)(*pGC->ops->CopyArea)((DrawablePtr)pmap, dst, pGC, 0, 0, sw, sh,
+ dx, dy);
+ (*pmap->drawable.pScreen->DestroyPixmap)(pmap);
++ nxagentShmTrap = 1;
+ }
+
+ static void
+@@ -542,6 +603,15 @@
+ unsigned int format;
+ char *data;
+ {
++ int length;
++ char *newdata;
++ extern int nxagentImageLength(int, int, int, int, int);
++
++ #ifdef TEST
++ fprintf(stderr, "fbShmPutImage: Called with drawable at [%p] GC at [%p] data at [%p].\n",
++ (void *) dst, (void *) pGC, (void *) data);
++ #endif
++
+ if ((format == ZPixmap) || (depth == 1))
+ {
+ PixmapPtr pPixmap;
+@@ -556,11 +626,45 @@
+ else
+ (void)(*pGC->ops->CopyArea)((DrawablePtr)pPixmap, dst, pGC,
+ sx, sy, sw, sh, dx, dy);
++
++ /*
++ * We updated the internal framebuffer,
++ * now we want to go on the real X.
++ */
++
++ #ifdef TEST
++ fprintf(stderr, "fbShmPutImage: Realizing the PutImage with depth [%d] "
++ " format [%d] w [%d] h [%d] sx [%d] sy [%d] sw [%d] "
++ " sh [%d] dx [%d].\n", depth, format, w, h,
++ sx, sy, sw, sh, dx);
++ #endif
++
++ length = nxagentImageLength(sw, sh, format, 0, depth);
++
++ if ((newdata = xalloc(length)) != NULL)
++ {
++ fbGetImage((DrawablePtr) pPixmap, sx, sy, sw, sh, format, AllPlanes, newdata);
++ (*pGC->ops->PutImage)(dst, pGC, depth, dx, dy, sw, sh, 0, format, newdata);
++
++ xfree(newdata);
++ }
++ else
++ {
++ #ifdef WARNING
++ fprintf(stderr, "fbShmPutImage: WARNING! Data allocation failed.\n");
++ #endif
++ }
++
+ FreeScratchPixmapHeader(pPixmap);
+ }
+ else
++ {
++ #ifdef TEST
++ fprintf(stderr, "fbShmPutImage: Calling miShmPutImage().\n");
++ #endif
+ miShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy,
+ data);
++ }
+ }
+
+
+@@ -895,26 +999,22 @@
+ return BadValue;
+ }
+
+- if ((((stuff->format == ZPixmap) && (stuff->srcX == 0)) ||
+- ((stuff->format != ZPixmap) &&
+- (stuff->srcX < screenInfo.bitmapScanlinePad) &&
+- ((stuff->format == XYBitmap) ||
+- ((stuff->srcY == 0) &&
+- (stuff->srcHeight == stuff->totalHeight))))) &&
+- ((stuff->srcX + stuff->srcWidth) == stuff->totalWidth))
+- (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth,
+- stuff->dstX, stuff->dstY,
+- stuff->totalWidth, stuff->srcHeight,
+- stuff->srcX, stuff->format,
+- shmdesc->addr + stuff->offset +
+- (stuff->srcY * length));
+- else
+- (*shmFuncs[pDraw->pScreen->myNum]->PutImage)(
+- pDraw, pGC, stuff->depth, stuff->format,
+- stuff->totalWidth, stuff->totalHeight,
+- stuff->srcX, stuff->srcY,
+- stuff->srcWidth, stuff->srcHeight,
+- stuff->dstX, stuff->dstY,
++ #ifdef TEST
++ fprintf(stderr, "ProcShmPutImage: Format [%d] srcX [%d] srcY [%d], "
++ "totalWidth [%d] totalHeight [%d]\n", stuff->format, stuff->srcX,
++ stuff->srcY, stuff->totalWidth, stuff->totalHeight);
++ #endif
++
++ #ifdef TEST
++ fprintf(stderr, "ProcShmPutImage: Calling (*shmFuncs[pDraw->pScreen->myNum]->PutImage)().\n");
++ #endif
++
++ (*shmFuncs[pDraw->pScreen->myNum]->PutImage)(
++ pDraw, pGC, stuff->depth, stuff->format,
++ stuff->totalWidth, stuff->totalHeight,
++ stuff->srcX, stuff->srcY,
++ stuff->srcWidth, stuff->srcHeight,
++ stuff->dstX, stuff->dstY,
+ shmdesc->addr + stuff->offset);
+
+ if (stuff->sendEvent)
+@@ -1056,15 +1156,37 @@
+ {
+ register PixmapPtr pPixmap;
+
+- pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth);
++ nxagentShmPixmapTrap = 1;
++
++ pPixmap = (*pScreen->CreatePixmap)(pScreen, width, height, depth);
++
+ if (!pPixmap)
+- return NullPixmap;
++ {
++ nxagentShmPixmapTrap = 0;
++
++ return NullPixmap;
++ }
++
++ #ifdef TEST
++ fprintf(stderr,"fbShmCreatePixmap: Width [%d] Height [%d] Depth [%d]\n", width, height, depth);
++ #endif
+
+ if (!(*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth,
+- BitsPerPixel(depth), PixmapBytePad(width, depth), (pointer)addr)) {
+- (*pScreen->DestroyPixmap)(pPixmap);
+- return NullPixmap;
++ BitsPerPixel(depth), PixmapBytePad(width, depth), (pointer)addr))
++ {
++ #ifdef WARNING
++ fprintf(stderr,"fbShmCreatePixmap: Return Null Pixmap.\n");
++ #endif
++
++ (*pScreen->DestroyPixmap)(pPixmap);
++
++ nxagentShmPixmapTrap = 0;
++
++ return NullPixmap;
+ }
++
++ nxagentShmPixmapTrap = 0;
++
+ return pPixmap;
+ }
+
+@@ -1146,6 +1268,18 @@
+ register ClientPtr client;
+ {
+ REQUEST(xReq);
++
++ #ifdef TEST
++ fprintf(stderr, "ProcShmDispatch: Going to execute operation [%d] for client [%d].\n",
++ stuff -> data, client -> index);
++
++ if (stuff->data <= X_ShmCreatePixmap)
++ {
++ fprintf(stderr, "ProcShmDispatch: Request [%s] OPCODE#%d.\n",
++ nxagentShmRequestLiteral[stuff->data], stuff->data);
++ }
++ #endif
++
+ switch (stuff->data)
+ {
+ case X_ShmQueryVersion:
+@@ -1155,11 +1289,38 @@
+ case X_ShmDetach:
+ return ProcShmDetach(client);
+ case X_ShmPutImage:
++ {
++ int result;
++
++ #ifdef TEST
++ fprintf(stderr, "ProcShmDispatch: Going to execute ProcShmPutImage() for client [%d].\n",
++ client -> index);
++ #endif
++
++ nxagentShmTrap = 1;
++
+ #ifdef PANORAMIX
+ if ( !noPanoramiXExtension )
+- return ProcPanoramiXShmPutImage(client);
++ {
++ result = ProcPanoramiXShmPutImage(client);
++
++ nxagentShmTrap = 0;
++
++ return result;
++ }
+ #endif
+- return ProcShmPutImage(client);
++
++ result = ProcShmPutImage(client);
++
++ nxagentShmTrap = 0;
++
++ #ifdef TEST
++ fprintf(stderr, "ProcShmDispatch: Returning from ProcShmPutImage() for client [%d].\n",
++ client -> index);
++ #endif
++
++ return result;
++ }
+ case X_ShmGetImage:
+ #ifdef PANORAMIX
+ if ( !noPanoramiXExtension )
+@@ -1290,6 +1451,12 @@
+ register ClientPtr client;
+ {
+ REQUEST(xReq);
++
++ #ifdef TEST
++ fprintf(stderr, "SProcShmDispatch: Going to execute operation [%d] for client [%d].\n",
++ stuff -> data, client -> index);
++ #endif
++
+ switch (stuff->data)
+ {
+ case X_ShmQueryVersion:
+@@ -1299,7 +1466,27 @@
+ case X_ShmDetach:
+ return SProcShmDetach(client);
+ case X_ShmPutImage:
+- return SProcShmPutImage(client);
++ {
++ int result;
++
++ #ifdef TEST
++ fprintf(stderr, "SProcShmDispatch: Going to execute SProcShmPutImage() for client [%d].\n",
++ client -> index);
++ #endif
++
++ nxagentShmTrap = 1;
++
++ result = SProcShmPutImage(client);
++
++ nxagentShmTrap = 0;
++
++ #ifdef TEST
++ fprintf(stderr, "SProcShmDispatch: Returning from SProcShmPutImage() for client [%d].\n",
++ client -> index);
++ #endif
++
++ return result;
++ }
+ case X_ShmGetImage:
+ return SProcShmGetImage(client);
+ case X_ShmCreatePixmap:
+@@ -1308,3 +1495,4 @@
+ return BadRequest;
+ }
+ }
++
diff --git a/doc/nx-X11_vs_XOrg69_patches/NXwindow.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/NXwindow.c.NX.patch
new file mode 100644
index 000000000..667dadc42
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/NXwindow.c.NX.patch
@@ -0,0 +1,561 @@
+--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXwindow.c.X.original 2015-02-13 14:03:44.748441432 +0100
++++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXwindow.c 2015-02-10 19:13:13.780686785 +0100
+@@ -1,3 +1,20 @@
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NXAGENT, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /* $XdotOrg: xc/programs/Xserver/dix/window.c,v 1.12 2005/07/03 08:53:38 daniels Exp $ */
+ /* $Xorg: window.c,v 1.4 2001/02/09 02:04:41 xorgcvs Exp $ */
+ /*
+@@ -97,9 +114,10 @@
+ #include "dixstruct.h"
+ #include "gcstruct.h"
+ #include "servermd.h"
++#include "selection.h"
+ #ifdef PANORAMIX
+-#include "panoramiX.h"
+-#include "panoramiXsrv.h"
++#include "../../Xext/panoramiX.h"
++#include "../../Xext/panoramiXsrv.h"
+ #endif
+ #include "dixevents.h"
+ #include "globals.h"
+@@ -112,6 +130,19 @@
+ #include <X11/extensions/security.h>
+ #endif
+
++#include "Screen.h"
++#include "Options.h"
++#include "Atoms.h"
++#include "Clipboard.h"
++#include "Splash.h"
++#include "Rootless.h"
++#include "Composite.h"
++#include "Drawable.h"
++#include "Colormap.h"
++
++extern Bool nxagentWMIsRunning;
++extern Bool nxagentScreenTrap;
++
+ /******
+ * Window stuff for server
+ *
+@@ -160,10 +191,25 @@
+ #define SubStrSend(pWin,pParent) (StrSend(pWin) || SubSend(pParent))
+
+
++/*
++ * Set here the required log level.
++ */
++
++#define PANIC
++#define WARNING
++#undef TEST
++#undef DEBUG
++
+ int numSaveUndersViewable = 0;
+ int deltaSaveUndersViewable = 0;
+
+-#ifdef DEBUG
++WindowPtr nxagentRootTileWindow;
++
++/*
++ * This block used the DEBUG symbol.
++ */
++
++#ifdef WINDOW_TREE_DEBUG
+ /******
+ * PrintWindowTree
+ * For debugging only
+@@ -289,6 +335,31 @@
+ #endif
+ }
+
++#ifdef NXAGENT_SERVER
++
++void nxagentClearSplash(WindowPtr pW)
++{
++ int w, h;
++ ScreenPtr pScreen;
++
++ w = pW->drawable.width;
++ h = pW->drawable.height;
++
++ pScreen = pW->drawable.pScreen;
++
++ if (pW->backgroundState == BackgroundPixmap)
++ {
++ (*pScreen->DestroyPixmap)(pW->background.pixmap);
++ }
++
++ pW->backgroundState = BackgroundPixel;
++ pW->background.pixel = nxagentLogoBlack;
++
++ (*pScreen->ChangeWindowAttributes)(pW, CWBackPixmap|CWBackPixel);
++}
++
++#endif /* NXAGENT_SERVER */
++
+ static void
+ MakeRootTile(WindowPtr pWin)
+ {
+@@ -333,6 +404,9 @@
+
+ FreeScratchGC(pGC);
+
++#ifdef NXAGENT_SERVER
++ nxagentRootTileWindow = pWin;
++#endif /* NXAGENT_SERVER */
+ }
+
+ WindowPtr
+@@ -458,9 +532,16 @@
+ return FALSE;
+
+ if (disableBackingStore)
+- pScreen->backingStoreSupport = NotUseful;
++ {
++ pScreen -> backingStoreSupport = NotUseful;
++ }
++
+ if (enableBackingStore)
+- pScreen->backingStoreSupport = Always;
++ {
++ pScreen -> backingStoreSupport = Always;
++ }
++
++ pScreen->saveUnderSupport = False;
+
+ #ifdef DO_SAVE_UNDERS
+ if ((pScreen->backingStoreSupport != NotUseful) &&
+@@ -480,6 +561,107 @@
+ return TRUE;
+ }
+
++#ifdef NXAGENT_SERVER
++
++void
++InitRootWindow(WindowPtr pWin)
++{
++ ScreenPtr pScreen;
++
++ #ifdef TEST
++ fprintf(stderr, "InitRootWindow: Called for window at [%p][%ld] with parent [%p].\n",
++ (void *) pWin, nxagentWindowPriv(pWin)->window, (void *) pWin -> parent);
++ #endif
++
++ if (nxagentOption(Rootless))
++ {
++ #ifdef TEST
++ fprintf(stderr, "InitRootWindow: Assigned agent root to window at [%p][%ld] with parent [%p].\n",
++ (void *) pWin, nxagentWindowPriv(pWin)->window, (void *) pWin -> parent);
++ #endif
++
++ nxagentRootlessWindow = pWin;
++ }
++
++ pScreen = pWin->drawable.pScreen;
++
++ /*
++ * A root window is created for each screen by main
++ * and the pointer is saved in WindowTable as in the
++ * following snippet:
++ *
++ * for (i = 0; i < screenInfo.numScreens; i++)
++ * InitRootWindow(WindowTable[i]);
++ *
++ * Our root window on the real display was already
++ * created at the time the screen was opened, so it
++ * is unclear how this window (or the other window,
++ * if you prefer) fits in the big picture.
++ */
++
++ #ifdef TEST
++ fprintf(stderr, "InitRootWindow: Going to create window as root at [%p][%ld] with parent [%p].\n",
++ (void *) pWin, nxagentWindowPriv(pWin)->window, (void *) pWin -> parent);
++ #endif
++
++ if (!(*pScreen->CreateWindow)(pWin))
++ return; /* XXX */
++
++ #ifdef TEST
++ fprintf(stderr, "InitRootWindow: Created window as root at [%p][%ld] with parent [%p].\n",
++ (void *) pWin, nxagentWindowPriv(pWin)->window, (void *) pWin -> parent);
++ #endif
++
++ (*pScreen->PositionWindow)(pWin, 0, 0);
++
++ pWin->cursorIsNone = FALSE;
++ pWin->optional->cursor = rootCursor;
++ rootCursor->refcnt++;
++ pWin->backingStore = defaultBackingStore;
++ pWin->forcedBS = (defaultBackingStore != NotUseful);
++
++ #ifdef NXAGENT_SPLASH
++ /* We SHOULD check for an error value here XXX */
++ pWin -> background.pixel = pScreen -> blackPixel;
++ (*pScreen->ChangeWindowAttributes)(pWin,
++ CWBackPixel|CWBorderPixel|CWCursor|CWBackingStore);
++ #else
++ (*pScreen->ChangeWindowAttributes)(pWin,
++ CWBackPixmap|CWBorderPixel|CWCursor|CWBackingStore);
++ #endif
++
++ MakeRootTile(pWin);
++
++ /*
++ * Map both the root and the default agent window.
++ */
++
++ #ifdef TEST
++ fprintf(stderr, "InitRootWindow: Mapping default windows.\n");
++ #endif
++
++ nxagentInitAtoms(pWin);
++
++ nxagentInitClipboard(pWin);
++
++ nxagentMapDefaultWindows();
++
++ nxagentRedirectDefaultWindows();
++
++ #ifdef NXAGENT_ARTSD
++ {
++ char artsd_port[10];
++ int nPort;
++ extern void nxagentPropagateArtsdProperties(ScreenPtr pScreen, char *port);
++ nPort = atoi(display) + 7000;
++ sprintf(artsd_port,"%d", nPort);
++ nxagentPropagateArtsdProperties(pScreen, artsd_port);
++ }
++ #endif
++}
++
++#else /* NXAGENT_SERVER */
++
+ void
+ InitRootWindow(WindowPtr pWin)
+ {
+@@ -502,6 +684,8 @@
+ MapWindow(pWin, serverClient);
+ }
+
++#endif /* NXAGENT_SERVER */
++
+ /* Set the region to the intersection of the rectangle and the
+ * window's winSize. The window is typically the parent of the
+ * window from which the region came.
+@@ -512,7 +696,9 @@
+ register int x, register int y,
+ register int w, register int h)
+ {
++#ifndef NXAGENT_SERVER
+ ScreenPtr pScreen = pWin->drawable.pScreen;
++#endif /* NXAGENT_SERVER */
+ BoxRec box;
+
+ box = *(REGION_EXTENTS(pScreen, &pWin->winSize));
+@@ -907,6 +1093,14 @@
+ if (pWin->prevSib)
+ pWin->prevSib->nextSib = pWin->nextSib;
+ }
++
++ if (pWin -> optional &&
++ pWin -> optional -> colormap &&
++ pWin -> parent)
++ {
++ nxagentSetInstalledColormapWindows(pWin -> drawable.pScreen);
++ }
++
+ xfree(pWin);
+ return Success;
+ }
+@@ -1147,6 +1341,12 @@
+ goto PatchUp;
+ }
+ pWin->backingStore = val;
++
++ #ifdef TEST
++ fprintf(stderr, "ChangeWindowAttributes: Changed backing store value to %d for window at %p.\n",
++ val, (void*)pWin);
++ #endif
++
+ pWin->forcedBS = FALSE;
+ break;
+ case CWBackingPlanes:
+@@ -1227,6 +1427,22 @@
+ #endif /* DO_SAVE_UNDERS */
+ break;
+ case CWEventMask:
++ /*
++ * TODO: Some applications like java bean shell
++ * don' t work if they cannot monitor the root
++ * window for Structure Redirect events. However
++ * this doesn't seem to be the best solution, since
++ * also an X server with a window manager running,
++ * doesn't allow to monitor for those events, but
++ * the java bean shell works flawlessy on this
++ * server.
++ *
++ * if (nxagentCheckIllegalRootMonitoring(pWin, (Mask)*pVlist))
++ * {
++ * return BadAccess;
++ * }
++ */
++
+ result = EventSelectForWindow(pWin, client, (Mask )*pVlist);
+ if (result)
+ {
+@@ -1611,8 +1827,9 @@
+ pRgn = REGION_CREATE(pWin->drawable.pScreen, &box, 1);
+ #ifdef SHAPE
+ if (wBoundingShape (pWin) || wClipShape (pWin)) {
++#ifndef NXAGENT_SERVER
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+-
++#endif /* NXAGENT_SERVER */
+ REGION_TRANSLATE(pScreen, pRgn, - pWin->drawable.x,
+ - pWin->drawable.y);
+ if (wBoundingShape (pWin))
+@@ -1647,8 +1864,9 @@
+ (int)pWin->drawable.height);
+ #ifdef SHAPE
+ if (wBoundingShape (pWin) || wClipShape (pWin)) {
++#ifndef NXAGENT_SERVER
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+-
++#endif /* NXAGENT_SERVER */
+ REGION_TRANSLATE(pScreen, &pWin->winSize, - pWin->drawable.x,
+ - pWin->drawable.y);
+ if (wBoundingShape (pWin))
+@@ -1689,8 +1907,9 @@
+ (int)(pWin->drawable.height + (bw<<1)));
+ #ifdef SHAPE
+ if (wBoundingShape (pWin)) {
++#ifndef NXAGENT_SERVER
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+-
++#endif /* NXAGENT_SERVER */
+ REGION_TRANSLATE(pScreen, &pWin->borderSize, - pWin->drawable.x,
+ - pWin->drawable.y);
+ REGION_INTERSECT(pScreen, &pWin->borderSize, &pWin->borderSize,
+@@ -1800,7 +2019,19 @@
+ pSib->drawable.y = pWin->drawable.y + pSib->origin.y;
+ SetWinSize (pSib);
+ SetBorderSize (pSib);
+- (*pScreen->PositionWindow)(pSib, pSib->drawable.x, pSib->drawable.y);
++
++ /*
++ * Don't force X to move children. It will position them
++ * according with gravity.
++ *
++ * (*pScreen->PositionWindow)(pSib, pSib->drawable.x, pSib->drawable.y);
++ */
++
++ /*
++ * Update pSib privates, as this window is moved by X.
++ */
++
++ nxagentAddConfiguredWindow(pSib, CW_Update);
+
+ if ( (pChild = pSib->firstChild) )
+ {
+@@ -1812,8 +2043,10 @@
+ pChild->origin.y;
+ SetWinSize (pChild);
+ SetBorderSize (pChild);
+- (*pScreen->PositionWindow)(pChild,
+- pChild->drawable.x, pChild->drawable.y);
++
++ (*pScreen->PositionWindow)(pChild, pChild->drawable.x,
++ pChild->drawable.y);
++
+ if (pChild->firstChild)
+ {
+ pChild = pChild->firstChild;
+@@ -1900,8 +2133,9 @@
+ BoxPtr pBox)
+ {
+ RegionPtr pRgn;
++#ifndef NXAGENT_SERVER
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+-
++#endif /* NXAGENT_SERVER */
+ pRgn = REGION_CREATE(pScreen, pBox, 1);
+ if (wBoundingShape (pWin)) {
+ REGION_TRANSLATE(pScreen, pRgn, -pWin->origin.x,
+@@ -2286,6 +2520,28 @@
+ /* Figure out if the window should be moved. Doesnt
+ make the changes to the window if event sent */
+
++ #ifdef TEST
++ if (nxagentWindowTopLevel(pWin))
++ {
++
++ fprintf(stderr, "ConfigureWindow: pWin [%p] mask [%lu] client [%p]\n",
++ pWin, mask, client);
++
++ fprintf(stderr, "ConfigureWindow: x [%d] y [%d] w [%d] h [%d] CWStackMode [%d] "
++ "smode [%d] pSib [%p]\n",
++ x, y, w, h, (mask & CWStackMode) ? 1 : 0, smode, pSib);
++ }
++ #endif
++
++ if (nxagentOption(Rootless) && nxagentWindowTopLevel(pWin) &&
++ pWin -> overrideRedirect == 0 &&
++ nxagentScreenTrap == 0)
++ {
++ nxagentConfigureRootlessWindow(pWin, x, y, w, h, bw, pSib, smode, mask);
++
++ return Success;
++ }
++
+ if (mask & CWStackMode)
+ pSib = WhereDoIGoInTheStack(pWin, pSib, pParent->drawable.x + x,
+ pParent->drawable.y + y,
+@@ -2443,6 +2699,9 @@
+
+ if (action != RESTACK_WIN)
+ CheckCursorConfinement(pWin);
++
++ nxagentFlushConfigureWindow();
++
+ return(Success);
+ #undef RESTACK_WIN
+ #undef MOVE_WIN
+@@ -2468,6 +2727,20 @@
+ xEvent event;
+ BoxRec box;
+
++ #ifdef TEST
++ fprintf(stderr, "CirculateWindow: pParent [%p] direction [%d] client [%p]\n",
++ pParent, direction, client);
++ #endif
++
++ /*
++ * if (nxagentOption(Rootless) && nxagentWMIsRunning &&
++ * nxagentWindowTopLevel(pWin) && pWin -> overrideRedirect == 0)
++ * {
++ * nxagentCirculateRootlessWindows(direction);
++ * return Success;
++ * }
++ */
++
+ pHead = RealChildHead(pParent);
+ pFirst = pHead ? pHead->nextSib : pParent->firstChild;
+ if (direction == RaiseLowest)
+@@ -2582,6 +2855,12 @@
+ /* insert at begining of pParent */
+ pWin->parent = pParent;
+ pPrev = RealChildHead(pParent);
++
++ if (pWin->parent == WindowTable[0])
++ {
++ nxagentSetTopLevelEventMask(pWin);
++ }
++
+ if (pPrev)
+ {
+ pWin->nextSib = pPrev->nextSib;
+@@ -2614,7 +2893,9 @@
+
+ if (pScreen->ReparentWindow)
+ (*pScreen->ReparentWindow)(pWin, pPriorParent);
++
+ (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y);
++
+ ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
+
+ CheckWindowOptionalNeed(pWin);
+@@ -2677,6 +2958,13 @@
+ #endif
+ WindowPtr pLayerWin;
+
++ #ifdef TEST
++ if (nxagentWindowTopLevel(pWin))
++ {
++ fprintf(stderr, "MapWindow: pWin [%p] client [%p]\n", pWin, client);
++ }
++ #endif
++
+ if (pWin->mapped)
+ return(Success);
+
+@@ -2782,6 +3070,8 @@
+ REGION_UNINIT(pScreen, &temp);
+ }
+
++ nxagentFlushConfigureWindow();
++
+ return(Success);
+ }
+
+@@ -2981,6 +3271,14 @@
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ WindowPtr pLayerWin = pWin;
+
++ #ifdef TEST
++ if (nxagentWindowTopLevel(pWin))
++ {
++ fprintf(stderr, "UnmapWindow: pWin [%p] fromConfigure [%d]\n", pWin,
++ fromConfigure);
++ }
++ #endif
++
+ if ((!pWin->mapped) || (!(pParent = pWin->parent)))
+ return(Success);
+ if (SubStrSend(pWin, pParent))
+@@ -3324,9 +3622,19 @@
+ (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], on);
+ if (savedScreenInfo[i].ExternalScreenSaver)
+ {
+- if ((*savedScreenInfo[i].ExternalScreenSaver)
+- (screenInfo.screens[i], type, on == SCREEN_SAVER_FORCER))
+- continue;
++ if (nxagentOption(Timeout) != 0)
++ {
++ #ifdef TEST
++ fprintf(stderr, "SaveScreens: An external screen-saver handler is installed. "
++ "Ignoring it to let the auto-disconnect feature work.\n");
++ #endif
++ }
++ else
++ {
++ if ((*savedScreenInfo[i].ExternalScreenSaver)
++ (screenInfo.screens[i], type, on == SCREEN_SAVER_FORCER))
++ continue;
++ }
+ }
+ if (type == screenIsSaved)
+ continue;
+@@ -3669,6 +3977,11 @@
+ }
+ else
+ pWin->cursorIsNone = TRUE;
++/* FIXME
++ There is an error when disposing ClientResources on Agent exit
++ this xfree is not valid in some window at exit
++*/
++
+ xfree (pWin->optional);
+ pWin->optional = NULL;
+ }
+@@ -3851,3 +4164,4 @@
+ }
+
+ #endif
++
diff --git a/doc/nx-X11_vs_XOrg69_patches/NXxvdisp.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/NXxvdisp.c.NX.patch
new file mode 100644
index 000000000..d8c20669d
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/NXxvdisp.c.NX.patch
@@ -0,0 +1,266 @@
+--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXxvdisp.c.X.original 2015-02-13 14:03:44.748441432 +0100
++++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXxvdisp.c 2015-02-13 14:03:44.748441432 +0100
+@@ -1,3 +1,20 @@
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NXAGENT, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /* $XdotOrg: xc/programs/Xserver/Xext/xvdisp.c,v 1.6 2005/07/03 08:53:36 daniels Exp $ */
+ /***********************************************************
+ Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts,
+@@ -71,6 +88,11 @@
+ #include <X11/extensions/shmstr.h>
+ #endif
+
++#include "Trap.h"
++
++#undef TEST
++#undef DEBUG
++
+ #ifdef EXTMODULE
+ #include "xf86_ansic.h"
+ #endif
+@@ -227,129 +249,175 @@
+ int
+ ProcXvDispatch(ClientPtr client)
+ {
++ int result;
++
+ REQUEST(xReq);
+
+ UpdateCurrentTime();
+
++ /*
++ * Report upstream that we are
++ * dispatching a XVideo operation.
++ */
++
++ nxagentXvTrap = 1;
++
++ #ifdef TEST
++ fprintf(stderr, "ProcXvDispatch: Going to dispatch XVideo operation [%d] for client [%d].\n",
++ stuff->data, client -> index);
++ #endif
++
+ switch (stuff->data)
+ {
+- case xv_QueryExtension: return(ProcXvQueryExtension(client));
+- case xv_QueryAdaptors: return(ProcXvQueryAdaptors(client));
+- case xv_QueryEncodings: return(ProcXvQueryEncodings(client));
++ case xv_QueryExtension: result = (ProcXvQueryExtension(client)); break;
++ case xv_QueryAdaptors: result = (ProcXvQueryAdaptors(client)); break;
++ case xv_QueryEncodings: result = (ProcXvQueryEncodings(client)); break;
+ case xv_PutVideo:
+ #ifdef PANORAMIX
+ if(!noPanoramiXExtension)
+- return(XineramaXvPutVideo(client));
++ result = (XineramaXvPutVideo(client)); break;
+ else
+ #endif
+- return(ProcXvPutVideo(client));
++ result = (ProcXvPutVideo(client)); break;
+ case xv_PutStill:
+ #ifdef PANORAMIX
+ if(!noPanoramiXExtension)
+- return(XineramaXvPutStill(client));
++ result = (XineramaXvPutStill(client)); break
+ else
+ #endif
+- return(ProcXvPutStill(client));
+- case xv_GetVideo: return(ProcXvGetVideo(client));
+- case xv_GetStill: return(ProcXvGetStill(client));
+- case xv_GrabPort: return(ProcXvGrabPort(client));
+- case xv_UngrabPort: return(ProcXvUngrabPort(client));
+- case xv_SelectVideoNotify: return(ProcXvSelectVideoNotify(client));
+- case xv_SelectPortNotify: return(ProcXvSelectPortNotify(client));
++ result = (ProcXvPutStill(client)); break;
++ case xv_GetVideo: result = (ProcXvGetVideo(client)); break;
++ case xv_GetStill: result = (ProcXvGetStill(client)); break;
++ case xv_GrabPort: result = (ProcXvGrabPort(client)); break;
++ case xv_UngrabPort: result = (ProcXvUngrabPort(client)); break;
++ case xv_SelectVideoNotify: result = (ProcXvSelectVideoNotify(client)); break;
++ case xv_SelectPortNotify: result = (ProcXvSelectPortNotify(client)); break;
+ case xv_StopVideo:
+ #ifdef PANORAMIX
+ if(!noPanoramiXExtension)
+- return(XineramaXvStopVideo(client));
++ result = (XineramaXvStopVideo(client)); break;
+ else
+ #endif
+- return(ProcXvStopVideo(client));
++ result = (ProcXvStopVideo(client)); break;
+ case xv_SetPortAttribute:
+ #ifdef PANORAMIX
+ if(!noPanoramiXExtension)
+- return(XineramaXvSetPortAttribute(client));
++ result = (XineramaXvSetPortAttribute(client)); break;
+ else
+ #endif
+- return(ProcXvSetPortAttribute(client));
+- case xv_GetPortAttribute: return(ProcXvGetPortAttribute(client));
+- case xv_QueryBestSize: return(ProcXvQueryBestSize(client));
+- case xv_QueryPortAttributes: return(ProcXvQueryPortAttributes(client));
++ result = (ProcXvSetPortAttribute(client)); break;
++ case xv_GetPortAttribute: result = (ProcXvGetPortAttribute(client)); break;
++ case xv_QueryBestSize: result = (ProcXvQueryBestSize(client)); break;
++ case xv_QueryPortAttributes: result = (ProcXvQueryPortAttributes(client)); break;
+ case xv_PutImage:
+ #ifdef PANORAMIX
+ if(!noPanoramiXExtension)
+- return(XineramaXvPutImage(client));
++ result = (XineramaXvPutImage(client)); break;
+ else
+ #endif
+- return(ProcXvPutImage(client));
++ result = (ProcXvPutImage(client)); break;
+ #ifdef MITSHM
+ case xv_ShmPutImage:
+ #ifdef PANORAMIX
+ if(!noPanoramiXExtension)
+- return(XineramaXvShmPutImage(client));
++ result = (XineramaXvShmPutImage(client)); break;
+ else
+ #endif
+- return(ProcXvShmPutImage(client));
++ result = (ProcXvShmPutImage(client)); break;
+ #endif
+- case xv_QueryImageAttributes: return(ProcXvQueryImageAttributes(client));
+- case xv_ListImageFormats: return(ProcXvListImageFormats(client));
++ case xv_QueryImageAttributes: result = (ProcXvQueryImageAttributes(client)); break;
++ case xv_ListImageFormats: result = (ProcXvListImageFormats(client)); break;
+ default:
+ if (stuff->data < xvNumRequests)
+ {
+ SendErrorToClient(client, XvReqCode, stuff->data, 0,
+ BadImplementation);
+- return(BadImplementation);
++ result = (BadImplementation); break;
+ }
+ else
+ {
+ SendErrorToClient(client, XvReqCode, stuff->data, 0, BadRequest);
+- return(BadRequest);
++ result = (BadRequest); break;
+ }
+ }
++
++ nxagentXvTrap = 0;
++
++ #ifdef TEST
++ fprintf(stderr, "ProcXvDispatch: Dispatched XVideo operation [%d] for client [%d].\n",
++ stuff->data, client -> index);
++ #endif
++
++ return result;
+ }
+
+ int
+ SProcXvDispatch(ClientPtr client)
+ {
++ int result;
++
+ REQUEST(xReq);
+
+ UpdateCurrentTime();
+
++ /*
++ * Report upstream that we are
++ * dispatching a XVideo operation.
++ */
++
++ nxagentXvTrap = 1;
++
++ #ifdef TEST
++ fprintf(stderr, "SProcXvDispatch: Going to dispatch XVideo operation [%d] for client [%d].\n",
++ stuff->data, client -> index);
++ #endif
++
+ switch (stuff->data)
+ {
+- case xv_QueryExtension: return(SProcXvQueryExtension(client));
+- case xv_QueryAdaptors: return(SProcXvQueryAdaptors(client));
+- case xv_QueryEncodings: return(SProcXvQueryEncodings(client));
+- case xv_PutVideo: return(SProcXvPutVideo(client));
+- case xv_PutStill: return(SProcXvPutStill(client));
+- case xv_GetVideo: return(SProcXvGetVideo(client));
+- case xv_GetStill: return(SProcXvGetStill(client));
+- case xv_GrabPort: return(SProcXvGrabPort(client));
+- case xv_UngrabPort: return(SProcXvUngrabPort(client));
+- case xv_SelectVideoNotify: return(SProcXvSelectVideoNotify(client));
+- case xv_SelectPortNotify: return(SProcXvSelectPortNotify(client));
+- case xv_StopVideo: return(SProcXvStopVideo(client));
+- case xv_SetPortAttribute: return(SProcXvSetPortAttribute(client));
+- case xv_GetPortAttribute: return(SProcXvGetPortAttribute(client));
+- case xv_QueryBestSize: return(SProcXvQueryBestSize(client));
+- case xv_QueryPortAttributes: return(SProcXvQueryPortAttributes(client));
+- case xv_PutImage: return(SProcXvPutImage(client));
++ case xv_QueryExtension: result = (SProcXvQueryExtension(client)); break;
++ case xv_QueryAdaptors: result = (SProcXvQueryAdaptors(client)); break;
++ case xv_QueryEncodings: result = (SProcXvQueryEncodings(client)); break;
++ case xv_PutVideo: result = (SProcXvPutVideo(client)); break;
++ case xv_PutStill: result = (SProcXvPutStill(client)); break;
++ case xv_GetVideo: result = (SProcXvGetVideo(client)); break;
++ case xv_GetStill: result = (SProcXvGetStill(client)); break;
++ case xv_GrabPort: result = (SProcXvGrabPort(client)); break;
++ case xv_UngrabPort: result = (SProcXvUngrabPort(client)); break;
++ case xv_SelectVideoNotify: result = (SProcXvSelectVideoNotify(client)); break;
++ case xv_SelectPortNotify: result = (SProcXvSelectPortNotify(client)); break;
++ case xv_StopVideo: result = (SProcXvStopVideo(client)); break;
++ case xv_SetPortAttribute: result = (SProcXvSetPortAttribute(client)); break;
++ case xv_GetPortAttribute: result = (SProcXvGetPortAttribute(client)); break;
++ case xv_QueryBestSize: result = (SProcXvQueryBestSize(client)); break;
++ case xv_QueryPortAttributes: result = (SProcXvQueryPortAttributes(client)); break;
++ case xv_PutImage: result = (SProcXvPutImage(client)); break;
+ #ifdef MITSHM
+- case xv_ShmPutImage: return(SProcXvShmPutImage(client));
++ case xv_ShmPutImage: result = (SProcXvShmPutImage(client)); break;
+ #endif
+- case xv_QueryImageAttributes: return(SProcXvQueryImageAttributes(client));
+- case xv_ListImageFormats: return(SProcXvListImageFormats(client));
++ case xv_QueryImageAttributes: result = (SProcXvQueryImageAttributes(client)); break;
++ case xv_ListImageFormats: result = (SProcXvListImageFormats(client)); break;
+ default:
+ if (stuff->data < xvNumRequests)
+ {
+ SendErrorToClient(client, XvReqCode, stuff->data, 0,
+ BadImplementation);
+- return(BadImplementation);
++ result = (BadImplementation); break;
+ }
+ else
+ {
+ SendErrorToClient(client, XvReqCode, stuff->data, 0, BadRequest);
+- return(BadRequest);
++ result = (BadRequest); break;
+ }
+ }
++
++ nxagentXvTrap = 0;
++
++ #ifdef TEST
++ fprintf(stderr, "ProcXvDispatch: Dispatched XVideo operation [%d] for client [%d].\n",
++ stuff->data, client -> index);
++ #endif
++
++ return result;
+ }
+
+ static int
+@@ -2215,3 +2283,4 @@
+ }
+
+ #endif
++
diff --git a/doc/nx-X11_vs_XOrg69_patches/NextEvent.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/NextEvent.c.NX.patch
new file mode 100644
index 000000000..6ddefa10c
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/NextEvent.c.NX.patch
@@ -0,0 +1,42 @@
+--- ./nx-X11/lib/Xt/NextEvent.c.X.original 2015-02-13 14:03:44.656443242 +0100
++++ ./nx-X11/lib/Xt/NextEvent.c 2015-02-13 14:03:44.656443242 +0100
+@@ -58,6 +58,24 @@
+ in this Software without prior written authorization from The Open Group.
+
+ */
++
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NX-X11, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /* $XFree86: xc/lib/Xt/NextEvent.c,v 3.26 2002/06/04 21:55:42 dawes Exp $ */
+
+ #ifdef HAVE_CONFIG_H
+@@ -345,6 +363,14 @@
+ wait_fds_ptr_t wf)
+ {
+ #ifndef USE_POLL
++
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
++
++ fprintf(stderr, "Xt::IoWait: Select called with [%d][%p][%p][%p][%p].\n",
++ wf->nfds, (void *) &wf->rmask, (void *) &wf->wmask, (void *) &wf->emask,
++ (void *) wt->wait_time_ptr);
++#endif
++
+ return Select (wf->nfds, &wf->rmask, &wf->wmask, &wf->emask,
+ wt->wait_time_ptr);
+ #else
diff --git a/doc/nx-X11_vs_XOrg69_patches/OpenDis.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/OpenDis.c.NX.patch
new file mode 100644
index 000000000..897fe2598
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/OpenDis.c.NX.patch
@@ -0,0 +1,96 @@
+--- ./nx-X11/lib/X11/OpenDis.c.X.original 2015-02-13 14:03:44.620443950 +0100
++++ ./nx-X11/lib/X11/OpenDis.c 2015-02-10 19:13:12.748725444 +0100
+@@ -24,6 +24,24 @@
+ in this Software without prior written authorization from The Open Group.
+
+ */
++
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NX-X11, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /* $XFree86: xc/lib/X11/OpenDis.c,v 3.16 2003/07/04 16:24:23 eich Exp $ */
+
+ #define NEED_REPLIES
+@@ -43,6 +61,10 @@
+ #include "XKBlib.h"
+ #endif /* XKB */
+
++#ifdef NX_TRANS_SOCKET
++extern void *_X11TransSocketProxyConnInfo(XtransConnInfo);
++#endif
++
+ #ifdef X_NOT_POSIX
+ #define Size_t unsigned int
+ #else
+@@ -117,6 +139,9 @@
+ bzero((char *) &client, sizeof(client));
+ bzero((char *) &prefix, sizeof(prefix));
+
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
++ fprintf(stderr, "\nXOpenDisplay: Called with display [%s].\n", display);
++#endif
+ /*
+ * If the display specifier string supplied as an argument to this
+ * routine is NULL or a pointer to NULL, read the DISPLAY variable.
+@@ -162,6 +187,9 @@
+
+ dpy->fd = _X11TransGetConnectionNumber (dpy->trans_conn);
+
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
++ fprintf(stderr, "\nXOpenDisplay: Connected display with dpy->fd = [%d].\n", dpy->fd);
++#endif
+ /* Initialize as much of the display structure as we can.
+ * Initialize pointers to NULL so that XFreeDisplayStructure will
+ * work if we run out of memory before we finish initializing.
+@@ -258,6 +286,10 @@
+ conn_buf_size = 1024 * strtol(xlib_buffer_size, NULL, 10);
+ if (conn_buf_size < XLIBMINBUFSIZE)
+ conn_buf_size = XLIBMINBUFSIZE;
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
++ fprintf (stderr, "Xlib: Running with XLIBBUFFERSIZE [%d] XLIBMINBUFSIZE [%d] "
++ "buffer size [%ld].\n", XLIBDEFAULTBUFSIZE, XLIBMINBUFSIZE, conn_buf_size);
++#endif
+
+ if ((dpy->bufptr = dpy->buffer = Xcalloc(1, conn_buf_size)) == NULL) {
+ OutOfMemory (dpy, setup);
+@@ -324,9 +356,16 @@
+
+ if (prefix.majorVersion != X_PROTOCOL) {
+ /* XXX - printing messages marks a bad programming interface */
++#ifdef NX_TRANS_SOCKET
++ if (_X11TransSocketProxyConnInfo(dpy->trans_conn) == NULL) {
++ fprintf (stderr, "Xlib: client uses different protocol version (%d) "
++ "than server (%d)!\r\n", X_PROTOCOL, prefix.majorVersion);
++ }
++#else
+ fprintf (stderr,
+ "Xlib: client uses different protocol version (%d) than server (%d)!\r\n",
+ X_PROTOCOL, prefix.majorVersion);
++#endif
+ _XDisconnectDisplay (dpy->trans_conn);
+ Xfree ((char *)dpy);
+ return(NULL);
+@@ -698,6 +737,9 @@
+ /*
+ * and return successfully
+ */
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
++ fprintf(stderr, "XOpenDisplay: Returning display at [%p].\n", dpy);
++#endif
+ return(dpy);
+ }
+
diff --git a/doc/nx-X11_vs_XOrg69_patches/PeekIfEv.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/PeekIfEv.c.NX.patch
new file mode 100644
index 000000000..7d87f13b1
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/PeekIfEv.c.NX.patch
@@ -0,0 +1,14 @@
+--- ./nx-X11/lib/X11/PeekIfEv.c.X.original 2015-02-13 14:03:44.620443950 +0100
++++ ./nx-X11/lib/X11/PeekIfEv.c 2015-02-10 19:13:12.952717788 +0100
+@@ -71,6 +71,11 @@
+ if (prev && prev->qserial_num != qe_serial)
+ /* another thread has snatched this event */
+ prev = NULL;
++#ifdef NX_TRANS_SOCKET
++ if (_XGetIOError(dpy)) {
++ return 0;
++ }
++#endif
+ }
+ }
+
diff --git a/doc/nx-X11_vs_XOrg69_patches/Pending.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/Pending.c.NX.patch
new file mode 100644
index 000000000..027ad7951
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/Pending.c.NX.patch
@@ -0,0 +1,30 @@
+--- ./nx-X11/lib/X11/Pending.c.X.original 2015-02-13 14:03:44.620443950 +0100
++++ ./nx-X11/lib/X11/Pending.c 2015-02-10 19:13:12.880720490 +0100
+@@ -25,6 +25,8 @@
+
+ */
+
++#include <stdio.h>
++
+ #ifdef HAVE_CONFIG_H
+ #include <config.h>
+ #endif
+@@ -37,11 +39,18 @@
+ int mode;
+ {
+ int ret_val;
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
++ fprintf(stderr, "\nXEventsQueued: Called with a display at [%p].\n", dpy);
++#endif
++
+ LockDisplay(dpy);
+ if (dpy->qlen || (mode == QueuedAlready))
+ ret_val = dpy->qlen;
+ else
+ ret_val = _XEventsQueued (dpy, mode);
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
++ fprintf(stderr, "\nXEventsQueued: Going to unlock the display at [%p].\n", dpy);
++#endif
+ UnlockDisplay(dpy);
+ return ret_val;
+ }
diff --git a/doc/nx-X11_vs_XOrg69_patches/WSDrawBuffer.h.NX.patch b/doc/nx-X11_vs_XOrg69_patches/WSDrawBuffer.h.NX.patch
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/WSDrawBuffer.h.NX.patch
diff --git a/doc/nx-X11_vs_XOrg69_patches/WaitFor.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/WaitFor.c.NX.patch
new file mode 100644
index 000000000..3850a2b26
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/WaitFor.c.NX.patch
@@ -0,0 +1,271 @@
+--- ./nx-X11/programs/Xserver/os/WaitFor.c.X.original 2015-02-13 14:03:44.788440645 +0100
++++ ./nx-X11/programs/Xserver/os/WaitFor.c 2015-02-10 19:13:13.464698616 +0100
+@@ -48,6 +48,23 @@
+
+ /* $Xorg: WaitFor.c,v 1.4 2001/02/09 02:05:22 xorgcvs Exp $ */
+
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NX-X11, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /*****************************************************************
+ * OS Dependent input routines:
+ *
+@@ -80,6 +97,12 @@
+ #include "dpmsproc.h"
+ #endif
+
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_WAKEUP)
++
++static unsigned long startTimeInMillis;
++
++#endif
++
+ #ifdef WIN32
+ /* Error codes from windows sockets differ from fileio error codes */
+ #undef EINTR
+@@ -169,8 +192,18 @@
+ Bool someReady = FALSE;
+ #endif
+
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "WaitForSomething: Got called.\n");
++#endif
++
+ FD_ZERO(&clientsReadable);
+
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_WAKEUP)
++
++ startTimeInMillis = GetTimeInMillis();
++
++#endif
++
+ /* We need a while loop here to handle
+ crashed connections and the screen saver timeout */
+ while (1)
+@@ -231,18 +264,127 @@
+ XTestComputeWaitTime (&waittime);
+ }
+ #endif /* XTESTEXT1 */
++
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_WAKEUP)
++
++ /*
++ * If caller has marked the first element of pClientsReady[],
++ * bail out of select after a short timeout. We need this to
++ * let the NX agent remove the splash screen when the timeout
++ * is expired. A better option would be to use the existing
++ * screen-saver timeout but it can be modified by clients, so
++ * we would need a special handling. This hack is trivial and
++ * keeps WaitForSomething() backward compatible with the exis-
++ * ting servers.
++ */
++
++ if (pClientsReady[0] == -1)
++ {
++ unsigned long timeoutInMillis;
++
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_WAKEUP) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "WaitForSomething: pClientsReady[0] is [%d], pClientsReady[1] is [%d].\n",
++ pClientsReady[0], pClientsReady[1]);
++#endif
++
++ timeoutInMillis = GetTimeInMillis();
++
++ if (timeoutInMillis - startTimeInMillis >= NX_TRANS_WAKEUP)
++ {
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_WAKEUP) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "WaitForSomething: Returning 0 because of wakeup timeout.\n");
++#endif
++ return 0;
++ }
++
++ timeoutInMillis = NX_TRANS_WAKEUP - (timeoutInMillis - startTimeInMillis);
++
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_WAKEUP) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "WaitForSomething: Milliseconds to next wakeup are %ld.\n",
++ timeoutInMillis);
++#endif
++ if (wt == NULL || (wt -> tv_sec * MILLI_PER_SECOND +
++ wt -> tv_usec / MILLI_PER_SECOND) > timeoutInMillis)
++ {
++ if ((waittime.tv_sec * MILLI_PER_SECOND +
++ waittime.tv_usec / MILLI_PER_SECOND) > timeoutInMillis)
++ {
++ waittime.tv_sec = timeoutInMillis / MILLI_PER_SECOND;
++ waittime.tv_usec = (timeoutInMillis * MILLI_PER_SECOND) %
++ (MILLI_PER_SECOND * 1000);
++ wt = &waittime;
++ }
++
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_WAKEUP) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "WaitForSomething: Next wakeup timeout set to %ld milliseconds.\n",
++ (waittime.tv_sec * MILLI_PER_SECOND) +
++ (waittime.tv_usec / MILLI_PER_SECOND));
++#endif
++ }
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_WAKEUP) && defined(NX_TRANS_DEBUG)
++ else
++ {
++ fprintf(stderr, "WaitForSomething: Using existing timeout of %ld milliseconds.\n",
++ (waittime.tv_sec * MILLI_PER_SECOND) +
++ (waittime.tv_usec / MILLI_PER_SECOND));
++ }
++#endif
++ }
++#endif
++
+ /* keep this check close to select() call to minimize race */
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+ if (dispatchException)
++ {
+ i = -1;
++
++ fprintf(stderr, "WaitForSomething: Value of dispatchException is true. Set i = -1.\n");
++ }
++#else
++ if (dispatchException)
++ i = -1;
++#endif
+ else if (AnyClientsWriteBlocked)
+ {
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ if (wt == NULL)
++ {
++ fprintf(stderr, "WaitForSomething: Executing select with LastSelectMask and "
++ "clientsWritable and null timeout.\n");
++ }
++ else
++ {
++ fprintf(stderr, "WaitForSomething: Executing select with LastSelectMask, "
++ "clientsWritable, %ld secs and %ld usecs.\n",
++ wt -> tv_sec, wt -> tv_usec);
++ }
++#endif
+ XFD_COPYSET(&ClientsWriteBlocked, &clientsWritable);
+ i = Select (MaxClients, &LastSelectMask, &clientsWritable, NULL, wt);
+ }
+ else
+ {
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ if (wt == NULL)
++ {
++ fprintf(stderr, "WaitForSomething: Executing select with LastSelectMask and null timeout.\n");
++ }
++ else
++ {
++ fprintf(stderr, "WaitForSomething: Executing select with LastSelectMask, %ld secs and %ld usecs.\n",
++ wt -> tv_sec, wt -> tv_usec);
++ }
++#endif
+ i = Select (MaxClients, &LastSelectMask, NULL, NULL, wt);
+ }
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "WaitForSomething: Bailed out with i = [%d] and errno = [%d].\n", i, errno);
++
++ if (i < 0)
++ {
++ fprintf(stderr, "WaitForSomething: Error is [%s].\n", strerror(errno));
++ }
++#endif
+ selecterr = GetErrno();
+ WakeupHandler(i, (pointer)&LastSelectMask);
+ #ifdef XTESTEXT1
+@@ -261,15 +403,31 @@
+ #endif
+ if (i <= 0) /* An error or timeout occurred */
+ {
+- if (dispatchException)
+- return 0;
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ if (dispatchException)
++ {
++ fprintf(stderr, "WaitForSomething: Returning 0 because of (dispatchException).\n");
++ return 0;
++ }
++#else
++ if (dispatchException)
++ return 0;
++#endif
+ if (i < 0)
+ {
+ if (selecterr == EBADF) /* Some client disconnected */
+ {
+ CheckConnections ();
+- if (! XFD_ANYSET (&AllClients))
+- return 0;
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ if (! XFD_ANYSET (&AllClients))
++ {
++ fprintf(stderr, "WaitForSomething: Returning 0 because of (! XFD_ANYSET (&AllClients)).\n");
++ return 0;
++ }
++#else
++ if (! XFD_ANYSET (&AllClients))
++ return 0;
++#endif
+ }
+ else if (selecterr == EINVAL)
+ {
+@@ -293,8 +451,18 @@
+ break;
+ }
+ #endif
++#if defined(NX_TRANS_SOCKET)
++ if (*checkForInput[0] != *checkForInput[1])
++ {
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "WaitForSomething: Returning 0 because of (*checkForInput[0] != *checkForInput[1]).\n");
++#endif
++ return 0;
++ }
++#else
+ if (*checkForInput[0] != *checkForInput[1])
+ return 0;
++#endif
+
+ if (timers)
+ {
+@@ -358,9 +526,19 @@
+ /* Windows keyboard and mouse events are added to the input queue
+ in Block- and WakupHandlers. There is no device to check if
+ data is ready. So check here if new input is available */
++#if defined(NX_TRANS_SOCKET)
++ if (*checkForInput[0] != *checkForInput[1])
++ {
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "WaitForSomething: Returning 0 because of (*checkForInput[0] != *checkForInput[1]).\n");
++#endif
++ return 0;
++ }
++#else
+ if (*checkForInput[0] != *checkForInput[1])
+ return 0;
+ #endif
++#endif
+ }
+ }
+
+@@ -429,6 +607,9 @@
+ #endif
+ }
+ }
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "WaitForSomething: Returning nready.\n");
++#endif
+ return nready;
+ }
+
diff --git a/doc/nx-X11_vs_XOrg69_patches/XKBMAlloc.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/XKBMAlloc.c.NX.patch
new file mode 100644
index 000000000..de5574c32
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/XKBMAlloc.c.NX.patch
@@ -0,0 +1,84 @@
+--- ./nx-X11/lib/X11/XKBMAlloc.c.X.original 2015-02-13 14:03:44.620443950 +0100
++++ ./nx-X11/lib/X11/XKBMAlloc.c 2015-02-10 19:13:12.836722141 +0100
+@@ -738,8 +738,13 @@
+ _XkbFree(prev_key_sym_map);
+ return BadAlloc;
+ }
++#ifdef NXAGENT_SERVER
++ bzero((char *)&xkb->map->key_sym_map[xkb->max_key_code+1],
++ tmp*sizeof(XkbSymMapRec));
++#else
+ bzero((char *)&xkb->map->key_sym_map[xkb->max_key_code],
+ tmp*sizeof(XkbSymMapRec));
++#endif
+ if (changes) {
+ changes->map.changed= _ExtendRange(changes->map.changed,
+ XkbKeySymsMask,maxKC,
+@@ -756,7 +761,11 @@
+ _XkbFree(prev_modmap);
+ return BadAlloc;
+ }
++#ifdef NXAGENT_SERVER
++ bzero((char *)&xkb->map->modmap[xkb->max_key_code+1],tmp);
++#else
+ bzero((char *)&xkb->map->modmap[xkb->max_key_code],tmp);
++#endif
+ if (changes) {
+ changes->map.changed= _ExtendRange(changes->map.changed,
+ XkbModifierMapMask,maxKC,
+@@ -775,8 +784,13 @@
+ _XkbFree(prev_behaviors);
+ return BadAlloc;
+ }
++#ifdef NXAGENT_SERVER
++ bzero((char *)&xkb->server->behaviors[xkb->max_key_code+1],
++ tmp*sizeof(XkbBehavior));
++#else
+ bzero((char *)&xkb->server->behaviors[xkb->max_key_code],
+ tmp*sizeof(XkbBehavior));
++#endif
+ if (changes) {
+ changes->map.changed= _ExtendRange(changes->map.changed,
+ XkbKeyBehaviorsMask,maxKC,
+@@ -793,8 +807,13 @@
+ _XkbFree(prev_key_acts);
+ return BadAlloc;
+ }
++#ifdef NXAGENT_SERVER
++ bzero((char *)&xkb->server->key_acts[xkb->max_key_code+1],
++ tmp*sizeof(unsigned short));
++#else
+ bzero((char *)&xkb->server->key_acts[xkb->max_key_code],
+ tmp*sizeof(unsigned short));
++#endif
+ if (changes) {
+ changes->map.changed= _ExtendRange(changes->map.changed,
+ XkbKeyActionsMask,maxKC,
+@@ -811,8 +830,13 @@
+ _XkbFree(prev_vmodmap);
+ return BadAlloc;
+ }
++#ifdef NXAGENT_SERVER
++ bzero((char *)&xkb->server->vmodmap[xkb->max_key_code+1],
++ tmp*sizeof(unsigned short));
++#else
+ bzero((char *)&xkb->server->vmodmap[xkb->max_key_code],
+ tmp*sizeof(unsigned short));
++#endif
+ if (changes) {
+ changes->map.changed= _ExtendRange(changes->map.changed,
+ XkbVirtualModMapMask,maxKC,
+@@ -830,8 +854,13 @@
+ _XkbFree(prev_keys);
+ return BadAlloc;
+ }
++#ifdef NXAGENT_SERVER
++ bzero((char *)&xkb->names->keys[xkb->max_key_code+1],
++ tmp*sizeof(XkbKeyNameRec));
++#else
+ bzero((char *)&xkb->names->keys[xkb->max_key_code],
+ tmp*sizeof(XkbKeyNameRec));
++#endif
+ if (changes) {
+ changes->names.changed= _ExtendRange(changes->names.changed,
+ XkbKeyNamesMask,maxKC,
diff --git a/doc/nx-X11_vs_XOrg69_patches/XKBsrv.h.NX.patch b/doc/nx-X11_vs_XOrg69_patches/XKBsrv.h.NX.patch
new file mode 100644
index 000000000..f85303bb2
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/XKBsrv.h.NX.patch
@@ -0,0 +1,14 @@
+--- ./nx-X11/include/extensions/XKBsrv.h.X.original 2015-02-13 14:03:44.612444107 +0100
++++ ./nx-X11/include/extensions/XKBsrv.h 2015-02-10 19:13:14.644654498 +0100
+@@ -73,6 +73,11 @@
+ #include <X11/extensions/XKBproto.h>
+ #include "inputstr.h"
+
++#ifdef NXAGENT_SERVER
++extern char *_NXGetXkbBasePath(const char *path);
++extern char *_NXGetXkbCompPath(const char *path);
++#endif
++
+ typedef struct _XkbInterest {
+ DeviceIntPtr dev;
+ ClientPtr client;
diff --git a/doc/nx-X11_vs_XOrg69_patches/Xlib.h.NX.patch b/doc/nx-X11_vs_XOrg69_patches/Xlib.h.NX.patch
new file mode 100644
index 000000000..794ccf09a
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/Xlib.h.NX.patch
@@ -0,0 +1,30 @@
+--- ./nx-X11/lib/X11/Xlib.h.X.original 2015-02-13 14:03:44.624443872 +0100
++++ ./nx-X11/lib/X11/Xlib.h 2015-02-10 19:13:12.720726495 +0100
+@@ -2102,6 +2102,27 @@
+ XPointer /* arg */
+ );
+
++#ifdef NX_TRANS_SOCKET
++
++/*
++ * This is just like XCheckIfEvent() but doesn't
++ * flush the output buffer if it can't read new
++ * events.
++ */
++
++extern Bool XCheckIfEventNoFlush(
++ Display* /* display */,
++ XEvent* /* event_return */,
++ Bool (*) (
++ Display* /* display */,
++ XEvent* /* event */,
++ XPointer /* arg */
++ ) /* predicate */,
++ XPointer /* arg */
++);
++
++#endif
++
+ extern Bool XCheckMaskEvent(
+ Display* /* display */,
+ long /* event_mask */,
diff --git a/doc/nx-X11_vs_XOrg69_patches/XlibAsync.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/XlibAsync.c.NX.patch
new file mode 100644
index 000000000..82494f70a
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/XlibAsync.c.NX.patch
@@ -0,0 +1,41 @@
+--- ./nx-X11/lib/X11/XlibAsync.c.X.original 2015-02-13 14:03:44.624443872 +0100
++++ ./nx-X11/lib/X11/XlibAsync.c 2015-02-10 19:13:13.064713591 +0100
+@@ -27,6 +27,23 @@
+
+ */
+
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NX-X11, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ #define NEED_REPLIES
+ #ifdef HAVE_CONFIG_H
+ #include <config.h>
+@@ -122,6 +139,14 @@
+ */
+ if ((rep->generic.length << 2) > len)
+ _XEatData (dpy, (rep->generic.length << 2) - len);
++#ifdef NX_TRANS_SOCKET
++
++ /*
++ * The original code has provision
++ * for returning already.
++ */
++
++#endif
+ _XIOError (dpy);
+ return (char *)rep;
+ }
diff --git a/doc/nx-X11_vs_XOrg69_patches/XlibInt.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/XlibInt.c.NX.patch
new file mode 100644
index 000000000..b76e169ee
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/XlibInt.c.NX.patch
@@ -0,0 +1,1165 @@
+--- ./nx-X11/lib/X11/XlibInt.c.X.original 2015-02-13 14:03:44.624443872 +0100
++++ ./nx-X11/lib/X11/XlibInt.c 2015-02-10 19:13:12.800723493 +0100
+@@ -26,6 +26,24 @@
+ from The Open Group.
+
+ */
++
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NX-X11, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /* $XFree86: xc/lib/X11/XlibInt.c,v 3.38 2003/10/30 21:55:05 alanh Exp $ */
+
+ /*
+@@ -100,6 +118,34 @@
+
+ #endif /* XTHREADS else */
+
++#include "NX.h"
++
++#ifdef NX_TRANS_SOCKET
++
++#include "NX.h"
++#include "NXvars.h"
++
++static struct timeval retry;
++
++/*
++ * From Xtranssock.c. Presently the congestion state
++ * is reported by the proxy to the application, by
++ * invoking the callback directly. The function will
++ * be possibly used in the future, to be able to track
++ * the bandwidth usage even when the NX transport is
++ * not running. Note that in this sample implementation
++ * the congestion state is checked very often and can
++ * be surely optimized.
++ */
++
++#ifdef NX_TRANS_CHANGE
++
++extern int _X11TransSocketCongestionChange(XtransConnInfo, int *);
++
++#endif
++
++#endif /* #ifdef NX_TRANS_SOCKET */
++
+ /* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX
+ * systems are broken and return EWOULDBLOCK when they should return EAGAIN
+ */
+@@ -219,6 +265,100 @@
+ 0, 0, 0
+ };
+
++#ifdef NX_TRANS_SOCKET
++
++/*
++ * Replace the standard Select with a version giving NX a
++ * chance to check its own descriptors. This doesn't cover
++ * the cases where the system is using poll or when system-
++ * specific defines override the Select definition (OS/2).
++ */
++
++int _XSelect(int maxfds, fd_set *readfds, fd_set *writefds,
++ fd_set *exceptfds, struct timeval *timeout)
++{
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_XSelect: Called with [%d][%p][%p][%p][%p].\n",
++ maxfds, (void *) readfds, (void *) writefds, (void *) exceptfds,
++ (void *) timeout);
++#endif
++
++ if (NXTransRunning(NX_FD_ANY))
++ {
++ fd_set t_readfds, t_writefds;
++ struct timeval t_timeout;
++
++ int n, r, e;
++
++#ifdef NX_TRANS_TEST
++
++ if (exceptfds != NULL)
++ {
++ fprintf(stderr, "_XSelect: WARNING! Can't handle exception fds in select.\n");
++ }
++
++#endif
++
++ if (readfds == NULL)
++ {
++ FD_ZERO(&t_readfds);
++
++ readfds = &t_readfds;
++ }
++
++ if (writefds == NULL)
++ {
++ FD_ZERO(&t_writefds);
++
++ writefds = &t_writefds;
++ }
++
++ if (timeout == NULL)
++ {
++ t_timeout.tv_sec = 10;
++ t_timeout.tv_usec = 0;
++
++ timeout = &t_timeout;
++ }
++
++ n = maxfds;
++
++ /*
++ * If the transport is gone avoid
++ * sleeping until the timeout.
++ */
++
++ if (NXTransPrepare(&n, readfds, writefds, timeout) != 0)
++ {
++ NXTransSelect(&r, &e, &n, readfds, writefds, timeout);
++
++ NXTransExecute(&r, &e, &n, readfds, writefds, timeout);
++
++ errno = e;
++
++ return r;
++ }
++ else
++ {
++ return 0;
++ }
++ }
++ else
++ {
++ return select(maxfds, readfds, writefds, exceptfds, timeout);
++ }
++}
++
++#else /* #ifdef NX_TRANS_SOCKET */
++
++int _XSelect(int maxfds, fd_set *readfds, fd_set *writefds,
++ fd_set *exceptfds, struct timeval *timeout)
++{
++ return select(maxfds, readfds, writefds, exceptfds, timeout);
++}
++
++#endif /* #ifdef NX_TRANS_SOCKET */
++
+ /*
+ * This is an OS dependent routine which:
+ * 1) returns as soon as the connection can be written on....
+@@ -242,6 +382,18 @@
+ #endif
+ int nfound;
+
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE)
++ int congestion;
++#endif
++
++#ifdef NX_TRANS_SOCKET
++
++ if (_XGetIOError(dpy)) {
++ return;
++ }
++
++#endif
++
+ #ifdef USE_POLL
+ filedes.fd = dpy->fd;
+ filedes.events = 0;
+@@ -276,6 +428,8 @@
+ (!dpy->lock->reply_awaiters ||
+ dpy->lock->reply_awaiters->cv == cv)))
+ #endif
++
++#ifndef NX_TRANS_SOCKET
+ #ifdef USE_POLL
+ filedes.events = POLLIN;
+ filedes.events |= POLLOUT;
+@@ -283,17 +437,109 @@
+ FD_SET(dpy->fd, &r_mask);
+ FD_SET(dpy->fd, &w_mask);
+ #endif
++#endif /* #ifndef NX_TRANS_SOCKET */
+
+ do {
++#ifdef NX_TRANS_SOCKET
++ /*
++ * Give a chance to the registered client to perform
++ * any needed operation before entering the select.
++ */
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_XWaitForWritable: WAIT! Waiting for the display to become writable.\n");
++#endif
++ NXTransFlush(dpy->fd);
++
++ if (_NXDisplayBlockFunction != NULL) {
++ (*_NXDisplayBlockFunction)(dpy, NXBlockWrite);
++ }
++
++ /*
++ * Need to set again the descriptors as we could have
++ * run multiple selects before having the possibility
++ * to read or write to the X connection.
++ */
++
++#ifdef USE_POLL
++ filedes.events = POLLIN;
++ filedes.events |= POLLOUT;
++#else
++ FD_SET(dpy->fd, &r_mask);
++ FD_SET(dpy->fd, &w_mask);
++#endif
++#endif /* #ifdef NX_TRANS_SOCKET */
++
+ UnlockDisplay(dpy);
+ #ifdef USE_POLL
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "_XWaitForWritable: Calling poll().\n");
++#endif
+ nfound = poll (&filedes, 1, -1);
+ #else
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "_XWaitForWritable: Calling select() after [%ld] ms.\n",
++ NXTransTime());
++#endif
++#ifdef NX_TRANS_SOCKET
++ /*
++ * Give a chance to the callback to detect
++ * the failure of the display even if we
++ * miss the interrupt inside the select.
++ */
++
++ if (_NXDisplayErrorFunction != NULL) {
++ retry.tv_sec = 5;
++ retry.tv_usec = 0;
++ nfound = Select (dpy->fd + 1, &r_mask, &w_mask, NULL, &retry);
++ } else {
++ nfound = Select (dpy->fd + 1, &r_mask, &w_mask, NULL, NULL);
++ }
++#else
+ nfound = Select (dpy->fd + 1, &r_mask, &w_mask, NULL, NULL);
+ #endif
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "_XWaitForWritable: Out of select() with [%d] after [%ld] ms.\n",
++ nfound, NXTransTime());
++
++ if (FD_ISSET(dpy->fd, &r_mask))
++ {
++ BytesReadable_t pend;
++
++ _X11TransBytesReadable(dpy->trans_conn, &pend);
++
++ fprintf(stderr, "_XWaitForWritable: Descriptor [%d] is ready with [%ld] bytes to read.\n",
++ dpy->fd, pend);
++ }
++
++ if (FD_ISSET(dpy->fd, &w_mask))
++ {
++ fprintf(stderr, "_XWaitForWritable: Descriptor [%d] has become writable.\n\n",
++ dpy->fd);
++ }
++#endif
++#endif
+ InternalLockDisplay(dpy, cv != NULL);
+- if (nfound < 0 && !ECHECK(EINTR))
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE)
++ if (_NXDisplayCongestionFunction != NULL &&
++ _X11TransSocketCongestionChange(dpy->trans_conn, &congestion) == 1) {
++ (*_NXDisplayCongestionFunction)(dpy, congestion);
++ }
++#endif
++
++#ifdef NX_TRANS_SOCKET
++ if (nfound <= 0) {
++ if ((nfound == -1 && !ECHECK(EINTR)) ||
++ (_NXDisplayErrorFunction != NULL &&
++ (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) {
++ _XIOError(dpy);
++ return;
++ }
++ }
++#else
++ if (nfound < 0 && !ECHECK(EINTR))
+ _XIOError(dpy);
++#endif
+ } while (nfound <= 0);
+
+ if (
+@@ -311,7 +557,15 @@
+
+ /* find out how much data can be read */
+ if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0)
++#ifdef NX_TRANS_SOCKET
++ {
++ _XIOError(dpy);
++
++ return;
++ }
++#else
+ _XIOError(dpy);
++#endif
+ len = pend;
+
+ /* must read at least one xEvent; if none is pending, then
+@@ -464,6 +718,15 @@
+ int highest_fd = fd;
+ #endif
+
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE)
++ int congestion;
++#endif
++#ifdef NX_TRANS_SOCKET
++ if (_XGetIOError(dpy)) {
++ return -1;
++ }
++#endif
++
+ #ifdef USE_POLL
+ if (dpy->im_fd_length + 1 > POLLFD_CACHE_SIZE
+ && !(dpy->flags & XlibDisplayProcConni)) {
+@@ -495,16 +758,68 @@
+ #endif
+ UnlockDisplay(dpy);
+ #ifdef USE_POLL
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "_XWaitForReadable: Calling poll().\n");
++#endif
+ result = poll(filedes,
+ (dpy->flags & XlibDisplayProcConni) ? 1 : 1+dpy->im_fd_length,
+ -1);
+ #else
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "_XWaitForReadable: Calling select().\n");
++#endif
++#ifdef NX_TRANS_SOCKET
++ /*
++ * Give a chance to the registered application
++ * to perform any needed operation.
++ */
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_XWaitForReadable: WAIT! Waiting for the display to become readable.\n");
++#endif
++ NXTransFlush(dpy->fd);
++
++ if (_NXDisplayBlockFunction != NULL) {
++ (*_NXDisplayBlockFunction)(dpy, NXBlockRead);
++ }
++
++ if (_NXDisplayErrorFunction != NULL) {
++ retry.tv_sec = 5;
++ retry.tv_usec = 0;
++ result = Select(highest_fd + 1, &r_mask, NULL, NULL, &retry);
++ } else {
++ result = Select(highest_fd + 1, &r_mask, NULL, NULL, NULL);
++ }
++#else
+ result = Select(highest_fd + 1, &r_mask, NULL, NULL, NULL);
+ #endif
++#endif
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "_XWaitForReadable: Out of select with result [%d] and errno [%d].\n",
++ result, (result < 0 ? errno : 0));
++#endif
+ InternalLockDisplay(dpy, dpy->flags & XlibDisplayReply);
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE)
++ if (_NXDisplayCongestionFunction != NULL &&
++ _X11TransSocketCongestionChange(dpy->trans_conn, &congestion) == 1) {
++ (*_NXDisplayCongestionFunction)(dpy, congestion);
++ }
++#endif
++#ifdef NX_TRANS_SOCKET
++ if (result <= 0) {
++ if ((result == -1 && !ECHECK(EINTR)) ||
++ (_NXDisplayErrorFunction != NULL &&
++ (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) {
++ _XIOError(dpy);
++ return -1;
++ }
++ continue;
++ }
++#else
+ if (result == -1 && !ECHECK(EINTR)) _XIOError(dpy);
+ if (result <= 0)
+ continue;
++#endif
+ #ifdef USE_POLL
+ if (filedes[0].revents & (POLLIN|POLLHUP|POLLERR))
+ #else
+@@ -562,6 +877,19 @@
+ xGetInputFocusReply rep;
+ register xReq *req;
+
++#ifdef NX_TRANS_SOCKET
++#ifdef NX_TRANS_DEBUG
++ fprintf(stderr, "_XSeqSyncFunction: Going to synchronize the display.\n");
++#endif
++ if (dpy->flags & XlibDisplayIOError)
++ {
++#ifdef NX_TRANS_DEBUG
++ fprintf(stderr, "_XSeqSyncFunction: Returning 0 with I/O error detected.\n");
++#endif
++ return 0;
++ }
++#endif
++
+ LockDisplay(dpy);
+ if ((dpy->request - dpy->last_request_read) >= (BUFSIZE / SIZEOF(xReq))) {
+ GetEmptyReq(GetInputFocus, req);
+@@ -611,7 +939,14 @@
+ register int write_stat;
+ register char *bufindex;
+ _XExtension *ext;
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE)
++ int congestion;
++#endif
+
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "_XFlushInt: Entering flush with [%d] bytes to write.\n",
++ (dpy->bufptr - dpy->buffer));
++#endif
+ /* This fix resets the bufptr to the front of the buffer so
+ * additional appends to the bufptr will not corrupt memory. Since
+ * the server is down, these appends are no-op's anyway but
+@@ -619,13 +954,23 @@
+ */
+ if (dpy->flags & XlibDisplayIOError)
+ {
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "_XFlushInt: Returning with I/O error detected.\n");
++#endif
+ dpy->bufptr = dpy->buffer;
+ dpy->last_req = (char *)&_dummy_request;
+ return;
+ }
+
+ #ifdef XTHREADS
++#ifdef NX_TRANS_SOCKET
++ while (dpy->flags & XlibDisplayWriting) {
++ if (_XGetIOError(dpy)) {
++ return;
++ }
++#else
+ while (dpy->flags & XlibDisplayWriting) {
++#endif
+ if (dpy->lock) {
+ ConditionWait(dpy, dpy->lock->writers);
+ } else {
+@@ -653,6 +998,17 @@
+ write_stat = _X11TransWrite(dpy->trans_conn,
+ bufindex, (int) todo);
+ if (write_stat >= 0) {
++#ifdef NX_TRANS_SOCKET
++ if (_NXDisplayWriteFunction != NULL) {
++ (*_NXDisplayWriteFunction)(dpy, write_stat);
++ }
++#ifdef NX_TRANS_CHANGE
++ if (_NXDisplayCongestionFunction != NULL &&
++ _X11TransSocketCongestionChange(dpy->trans_conn, &congestion) == 1) {
++ (*_NXDisplayCongestionFunction)(dpy, congestion);
++ }
++#endif
++#endif
+ size -= write_stat;
+ todo = size;
+ bufindex += write_stat;
+@@ -682,11 +1038,25 @@
+ );
+ }
+ #endif
++#ifdef NX_TRANS_SOCKET
++ } else if (!ECHECK(EINTR) ||
++ (_NXDisplayErrorFunction != NULL &&
++ (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) {
++ _XIOError(dpy);
++ return;
++ }
++#else
+ } else if (!ECHECK(EINTR)) {
+ /* Write failed! */
+ /* errno set by write system call. */
+ _XIOError(dpy);
+ }
++#endif
++#ifdef NX_TRANS_SOCKET
++ if (_XGetIOError(dpy)) {
++ return;
++ }
++#endif
+ }
+ dpy->last_req = (char *)&_dummy_request;
+ if ((dpy->request - dpy->last_request_read) >= SEQLIMIT &&
+@@ -727,6 +1097,12 @@
+ if (dpy->qlen)
+ return(dpy->qlen);
+ }
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ if (dpy->flags & XlibDisplayIOError) {
++ fprintf(stderr, "_XEventsQueued: Returning [%d] after display failure.\n",
++ dpy->qlen);
++ }
++#endif
+ if (dpy->flags & XlibDisplayIOError) return(dpy->qlen);
+
+ #ifdef XTHREADS
+@@ -767,8 +1143,19 @@
+ }
+ #endif /* XTHREADS*/
+
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "_XEventsQueued: Checking bytes readable.\n");
++#endif
+ if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0)
++#ifdef NX_TRANS_SOCKET
++ {
++ _XIOError(dpy);
++
++ return (dpy->qlen);
++ }
++#else
+ _XIOError(dpy);
++#endif
+ #ifdef XCONN_CHECK_FREQ
+ /* This is a crock, required because FIONREAD or equivalent is
+ * not guaranteed to detect a broken connection.
+@@ -785,10 +1172,16 @@
+
+ dpy->conn_checker = 0;
+ #ifdef USE_POLL
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "_XEventsQueued: Calling poll().\n");
++#endif
+ filedes.fd = dpy->fd;
+ filedes.events = POLLIN;
+ if ((result = poll(&filedes, 1, 0)))
+ #else
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "_XEventsQueued: Calling select().\n");
++#endif
+ FD_ZERO(&r_mask);
+ FD_SET(dpy->fd, &r_mask);
+ if ((result = Select(dpy->fd + 1, &r_mask, NULL, NULL, &zero_time)))
+@@ -797,13 +1190,32 @@
+ if (result > 0)
+ {
+ if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0)
++#ifdef NX_TRANS_SOCKET
++ {
++ _XIOError(dpy);
++
++ return (dpy->qlen);
++ }
++#else
+ _XIOError(dpy);
++#endif
+ /* we should not get zero, if we do, force a read */
+ if (!pend)
+ pend = SIZEOF(xReply);
+ }
++#ifdef NX_TRANS_SOCKET
++ if (result <= 0) {
++ if ((result == -1 && !ECHECK(EINTR)) ||
++ (_NXDisplayErrorFunction != NULL &&
++ (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) {
++ _XIOError(dpy);
++ return (dpy->qlen);
++ }
++ }
++#else
+ else if (result < 0 && !ECHECK(EINTR))
+ _XIOError(dpy);
++#endif
+ }
+ }
+ #endif /* XCONN_CHECK_FREQ */
+@@ -815,6 +1227,10 @@
+ {
+ UnlockNextEventReader(dpy);
+ }
++
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "_XEventsQueued: Returning [%d].\n", dpy->qlen);
++#endif
+ return(dpy->qlen);
+ }
+ /* Force a read if there is not enough data. Otherwise,
+@@ -847,6 +1263,11 @@
+
+ (void) _XRead (dpy, read_buf, (long) len);
+
++#ifdef NX_TRANS_SOCKET
++ if (_XGetIOError(dpy)) {
++ return(dpy->qlen);
++ }
++#endif
+ #ifdef XTHREADS
+ /* what did we actually read: reply or event? */
+ if (dpy->lock && dpy->lock->reply_awaiters) {
+@@ -945,7 +1366,15 @@
+ #endif /* XTHREADS */
+ /* find out how much data can be read */
+ if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0)
++#ifdef NX_TRANS_SOCKET
++ {
++ _XIOError(dpy);
++
++ return;
++ }
++#else
+ _XIOError(dpy);
++#endif
+ len = pend;
+
+ /* must read at least one xEvent; if none is pending, then
+@@ -995,6 +1424,15 @@
+ dpy->flags |= XlibDisplayReadEvents;
+ i = _XRead (dpy, read_buf, (long) len);
+ dpy->flags &= ~XlibDisplayReadEvents;
++#ifdef NX_TRANS_SOCKET
++ if (dpy->flags & XlibDisplayIOError)
++ {
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "_XReadEvents: Returning with I/O error detected.\n");
++#endif
++ return;
++ }
++#endif
+ if (i == -2) {
+ /* special flag from _XRead to say that internal connection has
+ done XPutBackEvent. Which we can use so we're done. */
+@@ -1065,12 +1503,33 @@
+ #ifdef XTHREADS
+ int original_size = size;
+ #endif
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE)
++ int congestion;
++#endif
+
+ if ((dpy->flags & XlibDisplayIOError) || size == 0)
+ return 0;
+ ESET(0);
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE)
++ while (1) {
++ /*
++ * Need to check the congestion state
++ * after the read so split the statement
++ * in multiple blocks.
++ */
++
++ bytes_read = _X11TransRead(dpy->trans_conn, data, (int)size);
++ if (_NXDisplayCongestionFunction != NULL &&
++ _X11TransSocketCongestionChange(dpy->trans_conn, &congestion) == 1) {
++ (*_NXDisplayCongestionFunction)(dpy, congestion);
++ }
++ if (bytes_read == size) {
++ break;
++ }
++#else
+ while ((bytes_read = _X11TransRead(dpy->trans_conn, data, (int)size))
+ != size) {
++#endif
+
+ if (bytes_read > 0) {
+ size -= bytes_read;
+@@ -1090,14 +1549,34 @@
+ else if (bytes_read == 0) {
+ /* Read failed because of end of file! */
+ ESET(EPIPE);
++#ifdef NX_TRANS_SOCKET
++ _XIOError(dpy);
++
++ return -1;
++#else
+ _XIOError(dpy);
++#endif
+ }
+
+ else /* bytes_read is less than 0; presumably -1 */ {
+ /* If it's a system call interrupt, it's not an error. */
++#ifdef NX_TRANS_SOCKET
++ if (!ECHECK(EINTR) ||
++ (_NXDisplayErrorFunction != NULL &&
++ (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) {
++ _XIOError(dpy);
++ return -1;
++ }
++#else
+ if (!ECHECK(EINTR))
+ _XIOError(dpy);
++#endif
+ }
++#ifdef NX_TRANS_SOCKET
++ if (_XGetIOError(dpy)) {
++ return -1;
++ }
++#endif
+ }
+ #ifdef XTHREADS
+ if (dpy->lock && dpy->lock->reply_bytes_left > 0)
+@@ -1268,6 +1747,9 @@
+ #ifdef XTHREADS
+ int original_size;
+ #endif
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE)
++ int congestion;
++#endif
+
+ if ((dpy->flags & XlibDisplayIOError) || size == 0) return;
+ iov[0].iov_len = (int)size;
+@@ -1285,7 +1767,19 @@
+ original_size = size;
+ #endif
+ ESET(0);
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE)
++ while (1) {
++ bytes_read = _X11TransReadv (dpy->trans_conn, iov, 2);
++ if (_NXDisplayCongestionFunction != NULL &&
++ _X11TransSocketCongestionChange(dpy->trans_conn, &congestion) == 1) {
++ (*_NXDisplayCongestionFunction)(dpy, congestion);
++ }
++ if (bytes_read == size) {
++ break;
++ }
++#else
+ while ((bytes_read = _X11TransReadv (dpy->trans_conn, iov, 2)) != size) {
++#endif
+
+ if (bytes_read > 0) {
+ size -= bytes_read;
+@@ -1313,14 +1807,34 @@
+ else if (bytes_read == 0) {
+ /* Read failed because of end of file! */
+ ESET(EPIPE);
++#ifdef NX_TRANS_SOCKET
++ _XIOError(dpy);
++
++ return;
++#else
+ _XIOError(dpy);
++#endif
+ }
+
+ else /* bytes_read is less than 0; presumably -1 */ {
+ /* If it's a system call interrupt, it's not an error. */
++#ifdef NX_TRANS_SOCKET
++ if (!ECHECK(EINTR) ||
++ (_NXDisplayErrorFunction != NULL &&
++ (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) {
++ _XIOError(dpy);
++ return;
++ }
++#else
+ if (!ECHECK(EINTR))
+ _XIOError(dpy);
++#endif
+ }
++#ifdef NX_TRANS_SOCKET
++ if (_XGetIOError(dpy)) {
++ return;
++ }
++#endif
+ }
+ #ifdef XTHREADS
+ if (dpy->lock && dpy->lock->reply_bytes_left > 0)
+@@ -1351,8 +1865,31 @@
+
+ long skip, dbufsize, padsize, total, todo;
+ _XExtension *ext;
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE)
++ int congestion;
++#endif
++
++#ifdef NX_TRANS_SOCKET
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "_XSend: Sending data with [%d] bytes to write.\n",
++ (dpy->bufptr - dpy->buffer));
++#endif
++ if (!size || (dpy->flags & XlibDisplayIOError))
++ {
++ if (dpy->flags & XlibDisplayIOError)
++ {
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "_XSend: Returning with I/O error detected.\n");
++#endif
++ dpy->bufptr = dpy->buffer;
++ dpy->last_req = (char *)&_dummy_request;
++ }
+
++ return;
++ }
++#else
+ if (!size || (dpy->flags & XlibDisplayIOError)) return;
++#endif
+ dbufsize = dpy->bufptr - dpy->buffer;
+ #ifdef XTHREADS
+ dpy->flags |= XlibDisplayWriting;
+@@ -1418,6 +1955,17 @@
+
+ ESET(0);
+ if ((len = _X11TransWritev(dpy->trans_conn, iov, i)) >= 0) {
++#ifdef NX_TRANS_SOCKET
++ if (_NXDisplayWriteFunction != NULL) {
++ (*_NXDisplayWriteFunction)(dpy, len);
++ }
++#ifdef NX_TRANS_CHANGE
++ if (_NXDisplayCongestionFunction != NULL &&
++ _X11TransSocketCongestionChange(dpy->trans_conn, &congestion) == 1) {
++ (*_NXDisplayCongestionFunction)(dpy, congestion);
++ }
++#endif
++#endif
+ skip += len;
+ total -= len;
+ todo = total;
+@@ -1447,9 +1995,23 @@
+ );
+ }
+ #endif
++#ifdef NX_TRANS_SOCKET
++ } else if (!ECHECK(EINTR) ||
++ (_NXDisplayErrorFunction != NULL &&
++ (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) {
++ _XIOError(dpy);
++ return;
++ }
++#else
+ } else if (!ECHECK(EINTR)) {
+ _XIOError(dpy);
+ }
++#endif
++#ifdef NX_TRANS_SOCKET
++ if (_XGetIOError(dpy)) {
++ return;
++ }
++#endif
+ }
+ dpy->last_req = (char *) & _dummy_request;
+ if ((dpy->request - dpy->last_request_read) >= SEQLIMIT &&
+@@ -1640,10 +2202,31 @@
+ if (newseq < lastseq) {
+ newseq += 0x10000;
+ if (newseq > dpy->request) {
++
++#ifdef NX_TRANS_SOCKET
++
++ if (_NXLostSequenceFunction != NULL)
++ {
++ (*_NXLostSequenceFunction)(dpy, newseq, dpy->request,
++ (unsigned int) rep->type);
++ }
++ else
++ {
++ (void) fprintf (stderr,
++ "Xlib: sequence lost (0x%lx > 0x%lx) in reply type 0x%x!\n",
++ newseq, dpy->request,
++ (unsigned int) rep->type);
++ }
++
++#else /* #ifdef NX_TRANS_SOCKET */
++
+ (void) fprintf (stderr,
+ "Xlib: sequence lost (0x%lx > 0x%lx) in reply type 0x%x!\n",
+ newseq, dpy->request,
+ (unsigned int) rep->type);
++
++#endif /* #ifdef NX_TRANS_SOCKET */
++
+ newseq -= 0x10000;
+ }
+ }
+@@ -1671,9 +2254,22 @@
+ #ifdef XTHREADS
+ struct _XCVList *cvl;
+ #endif
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "_XReply: Going to wait for an X reply.\n");
++#endif
+
++#ifdef NX_TRANS_SOCKET
++ if (dpy->flags & XlibDisplayIOError)
++ {
++#ifdef NX_TRANS_DEBUG
++ fprintf(stderr, "_XReply: Returning 0 with I/O error detected.\n");
++#endif
++ return 0;
++ }
++#else
+ if (dpy->flags & XlibDisplayIOError)
+ return 0;
++#endif
+
+ #ifdef XTHREADS
+ /* create our condition variable and append to list */
+@@ -1689,6 +2285,9 @@
+ XThread_Self(), cvl);
+ #endif
+
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "_XReply: Going to flush the display buffer.\n");
++#endif
+ _XFlushInt(dpy, cvl ? cvl->cv : NULL);
+ /* if it is not our turn to read a reply off the wire,
+ * wait til we're at head of list. if there is an event waiter,
+@@ -1704,6 +2303,20 @@
+ _XFlush(dpy);
+ #endif
+
++#ifdef NX_TRANS_SOCKET
++ /*
++ * We are going to block waiting for the remote
++ * X server. Be sure that the proxy has flushed
++ * all the data.
++ */
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_XReply: Requesting a flush of the NX transport.\n");
++#endif
++
++ NXTransFlush(dpy->fd);
++#endif
++
+ for (;;) {
+ #ifdef XTHREADS
+ /* Did another thread's _XReadEvents get our reply by accident? */
+@@ -1767,6 +2380,12 @@
+ ((long) rep->generic.length) << 2);
+ dpy->flags &= ~XlibDisplayReply;
+ UnlockNextReplyReader(dpy);
++#ifdef NX_TRANS_SOCKET
++ /*
++ * The original code has provision
++ * for returning already.
++ */
++#endif
+ _XIOError (dpy);
+ return (0);
+
+@@ -1830,6 +2449,12 @@
+ #endif
+ break;
+ }
++#ifdef NX_TRANS_SOCKET
++ if (_XGetIOError(dpy)) {
++ UnlockNextReplyReader(dpy);
++ return 0;
++ }
++#endif
+ }
+ }
+
+@@ -1849,6 +2474,14 @@
+ (void) _XSetLastRequestRead(dpy, &rep->generic);
+ len = SIZEOF(xReply) + (rep->generic.length << 2);
+ if (len < SIZEOF(xReply)) {
++#ifdef NX_TRANS_SOCKET
++
++ /*
++ * The original code has provision
++ * for returning already.
++ */
++
++#endif
+ _XIOError (dpy);
+ buf += *lenp;
+ *lenp = 0;
+@@ -1876,6 +2509,14 @@
+ }
+ if (len < SIZEOF(xReply))
+ {
++#ifdef NX_TRANS_SOCKET
++
++ /*
++ * The original code has provision
++ * for returning already.
++ */
++
++#endif
+ _XIOError (dpy);
+ buf += *lenp;
+ *lenp = 0;
+@@ -1944,6 +2585,10 @@
+ struct _XConnWatchInfo *watchers;
+ XPointer *wd;
+
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "_XRegisterInternalConnection: Got called.\n");
++#endif
++
+ new_conni = (struct _XConnectionInfo*)Xmalloc(sizeof(struct _XConnectionInfo));
+ if (!new_conni)
+ return 0;
+@@ -1991,6 +2636,10 @@
+ struct _XConnWatchInfo *watch;
+ XPointer *wd;
+
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "_XUnregisterInternalConnection: Got called.\n");
++#endif
++
+ for (prev = &dpy->im_fd_info; (info_list = *prev);
+ prev = &info_list->next) {
+ if (info_list->fd == fd) {
+@@ -2030,6 +2679,10 @@
+ struct _XConnectionInfo *info_list;
+ int *fd_list;
+
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "XInternalConnectionNumbers: Got called.\n");
++#endif
++
+ LockDisplay(dpy);
+ count = 0;
+ for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next)
+@@ -2088,6 +2741,10 @@
+ {
+ struct _XConnectionInfo *info_list;
+
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "XProcessInternalConnection: Got called.\n");
++#endif
++
+ LockDisplay(dpy);
+ for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
+ if (info_list->fd == fd) {
+@@ -2116,6 +2773,10 @@
+ struct _XConnectionInfo *info_list;
+ XPointer *wd_array;
+
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "XAddConnectionWatch: Got called.\n");
++#endif
++
+ LockDisplay(dpy);
+
+ /* allocate new watch data */
+@@ -2172,6 +2833,10 @@
+ struct _XConnectionInfo *conni;
+ int counter = 0;
+
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "XRemoveConnectionWatch: Got called.\n");
++#endif
++
+ LockDisplay(dpy);
+ for (watch=dpy->conn_watchers; watch; watch=watch->next) {
+ if (watch->fn == callback && watch->client_data == client_data) {
+@@ -2209,6 +2874,10 @@
+ #define SCRATCHSIZE 2048
+ char buf[SCRATCHSIZE];
+
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
++ fprintf(stderr, "_XEatData: Going to eat [%ld] bytes of data from descriptor [%d].\n",
++ n, dpy->fd);
++#endif
+ while (n > 0) {
+ register long bytes_read = (n > SCRATCHSIZE) ? SCRATCHSIZE : n;
+ (void) _XRead (dpy, buf, bytes_read);
+@@ -2237,7 +2906,13 @@
+ (_XQEvent *) Xmalloc((unsigned)sizeof(_XQEvent))) == NULL) {
+ /* Malloc call failed! */
+ ESET(ENOMEM);
++#ifdef NX_TRANS_SOCKET
++ _XIOError(dpy);
++
++ return;
++#else
+ _XIOError(dpy);
++#endif
+ }
+ qelt->next = NULL;
+ /* go call through display to find proper event reformatter */
+@@ -2710,7 +3385,29 @@
+ QLength(dpy));
+
+ }
+- exit(1);
++#ifdef NX_TRANS_SOCKET
++ if (_NXHandleDisplayError == 1)
++ {
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_XDefaultIOError: Going to return from the error handler.\n");
++#endif
++ return 0;
++ }
++ else
++ {
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_XDefaultIOError: Going to exit from the program.\n");
++#endif
++#ifdef NX_TRANS_EXIT
++ NXTransExit(1);
++#else
++ exit(1);
++#endif
++ }
++#else
++ exit(1);
++#endif /* #ifdef NX_TRANS_SOCKET */
++
+ return(0); /* dummy - function should never return */
+ }
+
+@@ -2911,7 +3608,48 @@
+ (*_XIOErrorFunction)(dpy);
+ else
+ _XDefaultIOError(dpy);
++#ifdef NX_TRANS_SOCKET
++ /*
++ * Check if we are supposed to return in the case
++ * of a display failure. The client which originated
++ * the X operation will have to check the value of
++ * the XlibDisplayIOError flag and handle appropria-
++ * tely the display disconnection.
++ */
++
++ if (_NXHandleDisplayError == 0)
++ {
++#ifdef NX_TRANS_EXIT
++ NXTransExit(1);
++#else
++ exit(1);
++#endif
++ }
++
++ /*
++ * We are going to return. Reset the display
++ * buffers. Further writes will be discarded.
++ */
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_XIOError: Resetting the display buffer.\n");
++#endif
++
++ dpy->bufptr = dpy->buffer;
++ dpy->last_req = (char *) &_dummy_request;
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_XIOError: Resetting the display flags.\n");
++#endif
++
++ dpy->flags &= ~XlibDisplayProcConni;
++ dpy->flags &= ~XlibDisplayPrivSync;
++ dpy->flags &= ~XlibDisplayReadEvents;
++ dpy->flags &= ~XlibDisplayWriting;
++ dpy->flags &= ~XlibDisplayReply;
++#else
+ exit (1);
++#endif
+ return 0;
+ }
+
diff --git a/doc/nx-X11_vs_XOrg69_patches/Xlibint.h.NX.patch b/doc/nx-X11_vs_XOrg69_patches/Xlibint.h.NX.patch
new file mode 100644
index 000000000..a23172ed9
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/Xlibint.h.NX.patch
@@ -0,0 +1,59 @@
+--- ./nx-X11/lib/X11/Xlibint.h.X.original 2015-02-13 14:03:44.624443872 +0100
++++ ./nx-X11/lib/X11/Xlibint.h 2015-02-10 19:13:12.888720189 +0100
+@@ -27,6 +27,24 @@
+ from The Open Group.
+
+ */
++
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NX-X11, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /* $XFree86: xc/lib/X11/Xlibint.h,v 3.27 2003/05/27 22:26:26 tsi Exp $ */
+
+ #ifndef _XLIBINT_H_
+@@ -44,6 +62,15 @@
+ #include <X11/Xproto.h> /* to declare xEvent */
+ #include <X11/XlibConf.h> /* for configured options like XTHREADS */
+
++#ifdef NX_TRANS_SOCKET
++
++#include "NXvars.h"
++
++#define _XGetIOError(dpy) \
++ (dpy -> flags & XlibDisplayIOError)
++
++#endif
++
+ #ifdef WIN32
+ #define _XFlush _XFlushIt
+ #endif
+@@ -348,9 +375,15 @@
+ #define LOCKED 1
+ #define UNLOCKED 0
+
++#ifdef NX_TRANS_SOCKET
++#ifndef BUFSIZE /* Output buffer size is configurable */
++#define BUFSIZE 8192 /* but this is still used for reading. */
++#endif
++#else
+ #ifndef BUFSIZE
+ #define BUFSIZE 2048 /* X output buffer size. */
+ #endif
++#endif
+ #ifndef PTSPERBATCH
+ #define PTSPERBATCH 1024 /* point batching */
+ #endif
diff --git a/doc/nx-X11_vs_XOrg69_patches/Xpoll.h.in.NX.patch b/doc/nx-X11_vs_XOrg69_patches/Xpoll.h.in.NX.patch
new file mode 100644
index 000000000..b869d589d
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/Xpoll.h.in.NX.patch
@@ -0,0 +1,67 @@
+--- ./nx-X11/include/Xpoll.h.in.X.original 2015-02-13 14:03:44.612444107 +0100
++++ ./nx-X11/include/Xpoll.h.in 2015-02-10 19:13:14.464661220 +0100
+@@ -51,6 +51,23 @@
+
+ /* $XFree86: xc/include/Xpoll.h,v 3.8 2001/01/17 17:53:11 dawes Exp $ */
+
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NX-X11, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ #ifndef _XPOLL_H_
+ #define _XPOLL_H_
+
+@@ -120,6 +137,31 @@
+ } fd_set;
+ #endif
+
++/*
++ * Replace the standard Select with a version giving NX a
++ * chance to check its own descriptors. This doesn't cover
++ * the cases where the system is using poll or when system-
++ * specific defines override the Select definition (OS/2).
++ * See XlibInt.c for _XSelect().
++ */
++
++#ifdef NX_TRANS_SOCKET
++
++extern int _XSelect(int maxfds, fd_set *readfds, fd_set *writefds,
++ fd_set *exceptfds, struct timeval *timeout);
++
++#ifndef hpux /* and perhaps old BSD ??? */
++# define Select(n,r,w,e,t) _XSelect(n,(fd_set*)r,(fd_set*)w,(fd_set*)e,(struct timeval*)t)
++#else
++# ifndef _XPG4_EXTENDED /* HPUX 9.x and earlier */
++# define Select(n,r,w,e,t) _XSelect(n,(int*)r,(int*)w,(int*)e,(struct timeval*)t)
++# else
++# define Select(n,r,w,e,t) _XSelect(n,(fd_set*)r,(fd_set*)w,(fd_set*)e,(struct timeval*)t)
++# endif
++#endif
++
++#else /* #ifdef NX_TRANS_SOCKET */
++
+ #ifndef hpux /* and perhaps old BSD ??? */
+ # define Select(n,r,w,e,t) select(n,(fd_set*)r,(fd_set*)w,(fd_set*)e,(struct timeval*)t)
+ #else
+@@ -130,6 +172,8 @@
+ # endif
+ #endif
+
++#endif /* #ifdef NX_TRANS_SOCKET */
++
+ #define __X_FDS_BITS @USE_FDS_BITS@
+
+ #ifndef __FDS_BITS
diff --git a/doc/nx-X11_vs_XOrg69_patches/Xrender.h.NX.patch b/doc/nx-X11_vs_XOrg69_patches/Xrender.h.NX.patch
new file mode 100644
index 000000000..8bda13795
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/Xrender.h.NX.patch
@@ -0,0 +1,39 @@
+--- ./nx-X11/lib/Xrender/Xrender.h.X.original 2015-02-13 14:03:44.652443320 +0100
++++ ./nx-X11/lib/Xrender/Xrender.h 2015-02-10 19:13:12.596731149 +0100
+@@ -25,6 +25,8 @@
+ #ifndef _XRENDER_H_
+ #define _XRENDER_H_
+
++#define NX_CLEANUP
++
+ #include <X11/extensions/render.h>
+
+ #include <X11/Xlib.h>
+@@ -32,6 +34,10 @@
+ #include <X11/Xosdefs.h>
+ #include <X11/Xutil.h>
+
++#ifdef NX_CLEANUP
++#include "renderproto.h"
++#endif
++
+ typedef struct {
+ short red;
+ short redMask;
+@@ -296,6 +302,16 @@
+ void
+ XRenderFreeGlyphSet (Display *dpy, GlyphSet glyphset);
+
++#ifdef NX_CLEANUP
++
++void XRenderCleanGlyphs (xGlyphInfo *gi,
++ int nglyphs,
++ CARD8 *images,
++ int depth,
++ Display *dpy);
++
++#endif /* #ifdef NX_CLEANUP */
++
+ void
+ XRenderAddGlyphs (Display *dpy,
+ GlyphSet glyphset,
diff --git a/doc/nx-X11_vs_XOrg69_patches/Xtranssock.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/Xtranssock.c.NX.patch
new file mode 100644
index 000000000..fc81419d7
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/Xtranssock.c.NX.patch
@@ -0,0 +1,1133 @@
+--- ./nx-X11/lib/xtrans/Xtranssock.c.X.original 2015-02-13 14:03:44.672442927 +0100
++++ ./nx-X11/lib/xtrans/Xtranssock.c 2015-02-13 14:03:44.672442927 +0100
+@@ -53,6 +53,35 @@
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NX-X11, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
++#ifdef NX_TRANS_SOCKET
++
++#ifdef NX_TRANS_DEBUG
++#define XTRANSDEBUG 5
++#endif
++
++#ifndef PF_LOCAL
++#define PF_LOCAL PF_UNIX
++#endif
++
++#endif
++
+ #include <ctype.h>
+ #ifdef XTHREADS
+ #include <X11/Xthreads.h>
+@@ -294,6 +323,560 @@
+ static int haveIPv6 = 1;
+ #endif
+
++#ifndef X11_t
++
++/*
++ * No NX changes if this is not
++ * compiled as a X11 transport.
++ */
++
++#undef NX_TRANS_SOCKET
++
++#endif
++
++#ifdef NX_TRANS_SOCKET
++
++#ifdef TRANS_CLIENT
++
++#include "NX.h"
++
++typedef struct
++{
++ XtransConnInfo info;
++ int local;
++ int remote;
++ int congestion;
++
++} _NXProxyConnInfo;
++
++#define NX_PROXY_CONN_LIMIT 256
++
++static _NXProxyConnInfo *_NXProxyConnInfoTab[NX_PROXY_CONN_LIMIT];
++
++#endif /* #ifdef TRANS_CLIENT */
++
++/*
++ * Override the UNIX_DIR and UNIX_PATH settings and
++ * make them configurable, based on the NX_TEMP or
++ * the TEMP environment.
++ *
++ * We must be careful as the same defines are used
++ * for different directories, based on the subsystem
++ * that is compiling this, while we want to override
++ * only the '/tmp/.X11-unix' and '/tmp/.X11-unix/X'
++ * settings.
++ */
++
++static char _NXUnixDir[1024];
++static char _NXUnixPath[1024];
++
++static char *_NXGetUnixDir(char *dir)
++{
++ const char *tempDir;
++
++ PRMSG (3, "_NXGetUnixDir(%s)\n", dir, 0, 0);
++
++ if (strcmp(dir, UNIX_DIR) != 0)
++ {
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_NXGetUnixDir: Returning other Unix directory [%s].\n", dir);
++#endif
++ return dir;
++ }
++
++ /*
++ * Check the environment only once.
++ */
++
++ if (*_NXUnixDir != '\0')
++ {
++ return _NXUnixDir;
++ }
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_NXGetUnixDir: Trying with the NX_TEMP environment.\n");
++#endif
++
++ tempDir = getenv("NX_TEMP");
++
++ if (tempDir == NULL || *tempDir == '\0')
++ {
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_NXGetUnixDir: Trying with the TEMP environment.\n");
++#endif
++
++ tempDir = getenv("TEMP");
++ }
++
++ if (tempDir != NULL && *tempDir != '\0')
++ {
++ if (strlen(tempDir) + strlen("/.X11-unix") + 1 > 1024)
++ {
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_NXGetUnixDir: WARNING! Maximum length of X11 Unix directory exceeded.\n");
++#endif
++ goto _NXGetUnixDirError;
++ }
++
++ strcpy(_NXUnixDir, tempDir);
++ strcat(_NXUnixDir, "/.X11-unix");
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_NXGetUnixDir: Using X11 Unix directory [%s].\n", _NXUnixDir);
++#endif
++
++ return _NXUnixDir;
++ }
++
++_NXGetUnixDirError:
++
++ strcpy(_NXUnixDir, dir);
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_NXGetUnixDir: Returning default X11 Unix directory [%s].\n", _NXUnixDir);
++#endif
++
++ return _NXUnixDir;
++}
++
++static char *_NXGetUnixPath(char *path)
++{
++ const char *unixDir;
++
++ PRMSG (3, "_NXGetUnixPath(%s)\n", path, 0, 0);
++
++ if (strcmp(path, UNIX_PATH) != 0)
++ {
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_NXGetUnixPath: Returning other X11 Unix path [%s].\n", path);
++#endif
++ return path;
++ }
++
++ /*
++ * Check the environment only once.
++ */
++
++ if (*_NXUnixPath != '\0')
++ {
++ return _NXUnixPath;
++ }
++
++ unixDir = _NXGetUnixDir(UNIX_DIR);
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_NXGetUnixPath: Got X11 Unix directory [%s].\n", unixDir);
++#endif
++
++ if (strlen(unixDir) + strlen("/X") + 1 > 1024)
++ {
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_NXGetUnixPath: WARNING! Maximum length of X11 Unix path exceeded.\n");
++#endif
++
++ goto _NXGetUnixPathError;
++ }
++
++ strcpy(_NXUnixPath, unixDir);
++ strcat(_NXUnixPath, "/X");
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_NXGetUnixPath: Returning X11 Unix path [%s].\n", _NXUnixPath);
++#endif
++
++ return _NXUnixPath;
++
++_NXGetUnixPathError:
++
++ strcpy(_NXUnixPath, path);
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_NXGetUnixPath: Returning default X11 Unix path [%s].\n", _NXUnixPath);
++#endif
++
++ return _NXUnixPath;
++}
++
++#ifdef hpux
++
++static char *_NXGetOldUnixPath(char *path)
++{
++ PRMSG (3, "_NXGetOldUnixPath(%s)\n", path, 0, 0);
++
++ if (strcmp(path, OLD_UNIX_PATH) == 0)
++ {
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_NXGetOldUnixPath: Returning X11 Unix path [%s].\n",
++ _NXGetUnixPath(path));
++#endif
++
++ return _NXGetUnixPath(path);
++ }
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_NXGetOldUnixPath: Returning other old X11 Unix path [%s].\n", path);
++#endif
++
++ return path;
++}
++
++#endif /* #ifdef hpux */
++
++/*
++ * Forcibly close any connection attempt on the
++ * listening socket. Need this to avoid loopback
++ * connections to the agent server.
++ */
++
++#ifdef TRANS_SERVER
++
++void TRANS(SocketRejectConnection) (XtransConnInfo ciptr)
++{
++ size_t sa_l = sizeof(struct sockaddr);
++ struct sockaddr sa;
++ fd_set fs;
++ struct timeval t;
++ int f;
++
++ PRMSG (3, "SocketRejectConnection(%x)\n", ciptr, 0, 0);
++
++ FD_ZERO(&fs);
++ FD_SET(ciptr -> fd, &fs);
++
++ t.tv_sec = 0;
++ t.tv_usec = 0;
++
++ /*
++ * Check if there is an awaiting connection.
++ */
++
++ if (select(ciptr -> fd + 1, &fs, NULL, NULL, &t) == 1)
++ {
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "SocketRejectConnection: Accepting connection attempt on fd [%d].\n",
++ ciptr -> fd);
++#endif
++ /*
++ * If there is one, close it.
++ */
++
++ if ((f = accept(ciptr -> fd, &sa, &sa_l)) >= 0)
++ {
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "SocketRejectConnection: Closing connection attempt on fd [%d].\n",
++ ciptr -> fd);
++#endif
++ close(f);
++ }
++ }
++}
++
++#endif /* #ifdef TRANS_SERVER */
++
++#ifdef TRANS_CLIENT
++
++void *TRANS(SocketProxyConnInfo) (XtransConnInfo ciptr)
++{
++ if (_NXProxyConnInfoTab[ciptr->fd] != NULL)
++ {
++ return ciptr->priv;
++ }
++
++ return NULL;
++}
++
++static XtransConnInfo TRANS(SocketCreateConnInfo) ()
++{
++ XtransConnInfo ciptr;
++
++ int fds[2];
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "SocketCreateConnInfo: Going to create the NX connection info.\n");
++#endif
++
++ if ((ciptr = (XtransConnInfo) xcalloc (1, sizeof(struct _XtransConnInfo))) == NULL)
++ {
++ PRMSG (1, "SocketCreateConnInfo: malloc failed\n", 0, 0, 0);
++ return NULL;
++ }
++
++ /*
++ * Create a pair of sockets. We'll communicate with
++ * the NX proxy by reading and writing to our end.
++ */
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "SocketCreateConnInfo: Going to create the NX socketpair.\n");
++#endif
++
++ if (socketpair(PF_LOCAL, SOCK_STREAM, 0, fds) < 0)
++ {
++ PRMSG (1, "SocketCreateConnInfo: socketpair() failed.\n", 0, 0, 0);
++ xfree ((char *) ciptr);
++ return NULL;
++ }
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "SocketCreateConnInfo: X socket end is [%d] NX proxy end is [%d].\n",
++ fds[0], fds[1]);
++#endif
++
++ /*
++ * Save in _NXProxyConnInfoTab the local and remote end of
++ * the socketpair. The remote end will be used by the proxy.
++ * When the memory-to-memory transport is activated, the
++ * agent and the proxy don't read or write to the real des-
++ * criptors but the communication takes place by reading
++ * and writing to the proxy's buffers.
++ */
++
++ ciptr->fd = fds[0];
++
++ if (ciptr->fd >= NX_PROXY_CONN_LIMIT)
++ {
++ PRMSG (1, "SocketCreateConnInfo: No space for a new _NXProxyConnInfo for [%d].\n",
++ ciptr->fd, 0, 0);
++ xfree ((char *) ciptr);
++ return NULL;
++ }
++ else if (_NXProxyConnInfoTab[ciptr->fd] != NULL)
++ {
++ PRMSG (1, "SocketCreateConnInfo: _NXProxyConnInfo for [%d] is not NULL. Exiting.\n",
++ ciptr->fd, 0, 0);
++ exit(1);
++ }
++
++ _NXProxyConnInfoTab[ciptr->fd] = (_NXProxyConnInfo *) xcalloc(1, sizeof(_NXProxyConnInfo));
++
++ if (_NXProxyConnInfoTab[ciptr->fd] == NULL)
++ {
++ PRMSG (1, "SocketCreateConnInfo: Alloc of _NXProxyConnInfo failed.\n", 0, 0, 0);
++ xfree ((char *) ciptr);
++ return NULL;
++ }
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "SocketCreateConnInfo: Allocated new _NXProxyConnInfo for [%d].\n",
++ ciptr->fd);
++#endif
++
++ _NXProxyConnInfoTab[ciptr->fd]->info = ciptr;
++ _NXProxyConnInfoTab[ciptr->fd]->local = fds[0];
++ _NXProxyConnInfoTab[ciptr->fd]->remote = fds[1];
++ _NXProxyConnInfoTab[ciptr->fd]->congestion = 0;
++
++ ciptr->priv = (char *) _NXProxyConnInfoTab[ciptr->fd];
++
++ return ciptr;
++}
++
++static int TRANS(SocketConnectConnInfo) (XtransConnInfo ciptr, char *host, char *port)
++{
++ int fds[2];
++ char display[1024];
++
++ _NXProxyConnInfo *proxy_conn;
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "SocketConnectConnInfo: Going to connect NX fd [%d] to host [%s] port [%s].\n",
++ ciptr->fd, host, port);
++#endif
++
++ /*
++ * We should have already created the socket pair.
++ */
++
++ proxy_conn = (_NXProxyConnInfo *) ciptr->priv;
++
++ if (proxy_conn == NULL)
++ {
++ PRMSG (1, "SocketConnectConnInfo: Pointer to _NXProxyConnInfo is NULL. Exiting.\n", 0, 0, 0);
++
++ exit(1);
++ }
++ else if (_NXProxyConnInfoTab[ciptr->fd] != (_NXProxyConnInfo *) ciptr->priv)
++ {
++ PRMSG (1, "SocketConnectConnInfo: Can't find _NXProxyConnInfo in table. Exiting.\n",
++ 0, 0, 0);
++
++ exit(1);
++ }
++
++ if (strlen(host) + strlen(port) + 1 >= 1023)
++ {
++ PRMSG (1, "SocketConnectConnInfo: Length of NX display string '%s:%s' would exceed %d characters.\n",
++ host, port, 1023);
++
++ return TRANS_CONNECT_FAILED;
++ }
++
++ sprintf(display, "%s:%s", host, port);
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "SocketConnectConnInfo: Setting close-on-exec flag on local NX descriptor [%d].\n",
++ proxy_conn -> local);
++#endif
++
++#ifdef F_SETFD
++#ifdef FD_CLOEXEC
++ if (fcntl(proxy_conn -> local, F_SETFD, FD_CLOEXEC) != 0)
++#else
++ if (fcntl(proxy_conn -> local, F_SETFD, 1) != 0)
++#endif
++#endif
++ {
++ PRMSG (1, "SocketConnectConnInfo: Cannot set close-on-exec on local NX descriptor [%d].\n",
++ proxy_conn -> local, 0, 0);
++
++ return TRANS_CONNECT_FAILED;
++ }
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "SocketConnectConnInfo: Creating the NX transport with display [%s].\n",
++ display);
++#endif
++
++ if (NXTransCreate(NX_FD_ANY, NX_MODE_CLIENT, display) < 0)
++ {
++ PRMSG (1, "SocketConnectConnInfo: Cannot create the NX transport.\n",
++ 0, 0, 0);
++
++ return TRANS_CONNECT_FAILED;
++ }
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "SocketConnectConnInfo: Starting the NX agent with descriptor [%d].\n",
++ proxy_conn -> remote);
++#endif
++
++ fds[0] = proxy_conn -> local;
++ fds[1] = proxy_conn -> remote;
++
++ NXTransAgent(fds);
++
++ return 0;
++}
++
++static void TRANS(SocketCloseConnInfo) (XtransConnInfo ciptr)
++{
++ _NXProxyConnInfo *proxy_conn;
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "SocketCloseConnInfo: Going to close the NX fd [%d].\n", ciptr->fd);
++#endif
++
++ proxy_conn = (_NXProxyConnInfo *) ciptr->priv;
++
++ if (proxy_conn == NULL)
++ {
++ PRMSG (1, "SocketCloseConnInfo: Pointer to _NXProxyConnInfo is NULL. Exiting.\n", 0, 0, 0);
++
++ exit(1);
++ }
++ else if (ciptr->fd >= NX_PROXY_CONN_LIMIT ||
++ _NXProxyConnInfoTab[ciptr->fd] != (_NXProxyConnInfo *) ciptr->priv)
++ {
++ PRMSG (1, "SocketCloseConnInfo: Can't find _NXProxyConnInfo in table. Exiting.\n",
++ 0, 0, 0);
++ exit(1);
++ }
++ else if (_NXProxyConnInfoTab[ciptr->fd] -> info != ciptr ||
++ _NXProxyConnInfoTab[ciptr->fd] -> local != ciptr->fd)
++ {
++ PRMSG (1, "SocketCloseConnInfo: Invalid _NXProxyConnInfo structure for [%d]. Exiting.\n",
++ ciptr->fd, 0, 0);
++ exit(1);
++ }
++ else if (proxy_conn->local < 0 || proxy_conn->remote < 0)
++ {
++ PRMSG (1, "SocketCloseConnInfo: Invalid socket pair in NX connection for [%d]. Exiting.\n",
++ ciptr->fd, 0, 0);
++ exit(1);
++ }
++
++ NXTransClose(ciptr->fd);
++
++ /*
++ * Get rid of the _NXProxyConnInfo structure.
++ */
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "SocketCloseConnInfo: Freeing _NXProxyConnInfo structure for [%d].\n",
++ ciptr->fd);
++#endif
++
++ xfree((char *) _NXProxyConnInfoTab[ciptr->fd]);
++
++ _NXProxyConnInfoTab[ciptr->fd] = NULL;
++
++ ciptr->priv = NULL;
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "SocketCloseConnInfo: Should now close the local descriptor [%d].\n",
++ ciptr->fd);
++#endif
++}
++
++#endif /* #ifdef TRANS_CLIENT */
++
++#if defined(TRANS_CLIENT) && defined(NX_TRANS_CHANGE)
++
++/*
++ * Check the congestion state of the NX transport
++ * and return 1 if there has been a change. This
++ * can be extended by adding a few counters track-
++ * ing the bandwidth usage of the X11 connection.
++ */
++
++int TRANS(SocketCongestionChange) (XtransConnInfo ciptr, int *state)
++{
++ int congestion;
++
++ _NXProxyConnInfo *proxy_conn;
++
++ PRMSG (3, "SocketCongestionChange(%x)\n", ciptr, 0, 0);
++
++ proxy_conn = (_NXProxyConnInfo *) ciptr->priv;
++
++ if (proxy_conn == NULL)
++ {
++#ifdef NX_TRANS_DEBUG
++ fprintf(stderr, "SocketCongestionChange: Descriptor [%d] doesn't appear to be a NX connection.\n",
++ ciptr->fd);
++#endif
++ return 0;
++ }
++
++#ifdef NX_TRANS_DEBUG
++ fprintf(stderr, "SocketCongestionChange: Checking congestion on fd [%d] with old state [%d].\n",
++ ciptr->fd, proxy_conn->congestion);
++#endif
++
++ congestion = NXTransCongestion(ciptr->fd);
++
++ if (congestion != proxy_conn->congestion)
++ {
++ proxy_conn->congestion = congestion;
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "SocketCongestionChange: Change detected on fd [%d] with new state [%d].\n",
++ ciptr->fd, proxy_conn->congestion);
++#endif
++ return 1;
++ }
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "SocketCongestionChange: No change on fd [%d] with current state [%d].\n",
++ ciptr->fd, congestion);
++#endif
++ return 0;
++}
++
++#endif /* #if defined(TRANS_CLIENT) && defined(NX_TRANS_CHANGE) */
++
++#endif /* #ifdef NX_TRANS_SOCKET */
++
+ /*
+ * These are some utility function used by the real interface function below.
+ */
+@@ -562,6 +1145,29 @@
+ SocketInitOnce();
+
+ while ((i = TRANS(SocketSelectFamily) (i, transname)) >= 0) {
++
++#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
++
++ if ((!strcmp(protocol, "local") || !strcmp(protocol, "nx")) &&
++ (!strcasecmp(host, "nx") || !strncasecmp(host, "nx,", 3)))
++ {
++ ciptr = TRANS(SocketCreateConnInfo) ();
++
++ if (ciptr == NULL)
++ {
++ PRMSG (1, "SocketOpenCOTSClient: Unable to create the NX connection info for %s.\n",
++ transname, 0, 0);
++
++ return NULL;
++ }
++
++ ciptr->index = i;
++
++ return ciptr;
++ }
++
++#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
++
+ if ((ciptr = TRANS(SocketOpen) (
+ i, Sockettrans2devtab[i].devcotsname)) != NULL)
+ break;
+@@ -576,6 +1182,12 @@
+ return NULL;
+ }
+
++#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
++
++ ciptr->priv = NULL;
++
++#endif
++
+ /* Save the index for later use */
+
+ ciptr->index = i;
+@@ -677,6 +1289,29 @@
+ SocketInitOnce();
+
+ while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
++
++#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
++
++ if ((!strcmp(protocol, "local") || !strcmp(protocol, "nx")) &&
++ (!strcasecmp(host, "nx") || !strncasecmp(host, "nx,", 3)))
++ {
++ ciptr = TRANS(SocketCreateConnInfo) ();
++
++ if (ciptr == NULL)
++ {
++ PRMSG (1, "SocketOpenCLTSClient: Unable to create the NX connection info for %s.\n",
++ thistrans->TransName, 0, 0);
++
++ return NULL;
++ }
++
++ ciptr->index = i;
++
++ return ciptr;
++ }
++
++#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
++
+ if ((ciptr = TRANS(SocketOpen) (
+ i, Sockettrans2devtab[i].devcotsname)) != NULL)
+ break;
+@@ -691,6 +1326,12 @@
+ return NULL;
+ }
+
++#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
++
++ ciptr->priv = NULL;
++
++#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
++
+ /* Save the index for later use */
+
+ ciptr->index = i;
+@@ -826,6 +1467,11 @@
+ {
+ PRMSG (2,"SocketSetOption(%d,%d,%d)\n", ciptr->fd, option, arg);
+
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "SocketSetOption: WARNING! Not setting option [%d] with value [%d] on descriptor [%d].\n",
++ option, arg, ciptr -> fd);
++#endif
++
+ return -1;
+ }
+
+@@ -875,6 +1521,11 @@
+ else
+ retry = 0;
+
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
++ fprintf(stderr, "SocketCreateListener: Creating listener for ciptr at [%p] on path [%s].\n",
++ (void *) ciptr, ((struct sockaddr_un *) sockname)->sun_family == AF_UNIX ?
++ ((struct sockaddr_un *) sockname)->sun_path : "TCP");
++#endif
+ while (bind (fd, (struct sockaddr *) sockname, namelen) < 0)
+ {
+ if (errno == EADDRINUSE) {
+@@ -926,6 +1577,11 @@
+
+ ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS);
+
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
++ fprintf(stderr, "SocketCreateListener: Set flags to [%d] for ciptr [%p].\n",
++ ciptr->flags, (void *) ciptr);
++#endif
++
+ return 0;
+ }
+
+@@ -1084,9 +1740,15 @@
+ #else
+ mode = 0777;
+ #endif
++#ifdef NX_TRANS_SOCKET
++ if (trans_mkdir(_NXGetUnixDir(UNIX_DIR), mode) == -1) {
++ PRMSG (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n",
++ _NXGetUnixDir(UNIX_DIR), errno, 0);
++#else
+ if (trans_mkdir(UNIX_DIR, mode) == -1) {
+ PRMSG (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n",
+ UNIX_DIR, errno, 0);
++#endif
+ (void) umask (oldUmask);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+@@ -1095,12 +1757,20 @@
+ sockname.sun_family = AF_UNIX;
+
+ if (port && *port) {
++#ifdef NX_TRANS_SOCKET
++ if (set_sun_path(port, _NXGetUnixPath(UNIX_PATH), sockname.sun_path) != 0) {
++#else
+ if (set_sun_path(port, UNIX_PATH, sockname.sun_path) != 0) {
++#endif
+ PRMSG (1, "SocketUNIXCreateListener: path too long\n", 0, 0, 0);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+ } else {
++#ifdef NX_TRANS_SOCKET
++ sprintf (sockname.sun_path, "%s%ld", _NXGetUnixPath(UNIX_PATH), (long)getpid());
++#else
+ sprintf (sockname.sun_path, "%s%ld", UNIX_PATH, (long)getpid());
++#endif
+ }
+
+ #if (defined(BSD44SOCKETS) || defined(__UNIXWARE__)) && !defined(Lynx)
+@@ -1110,6 +1780,10 @@
+ namelen = strlen(sockname.sun_path) + sizeof(sockname.sun_family);
+ #endif
+
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
++ fprintf(stderr, "SocketUNIXCreateListener: Unlinking path [%s] for ciptr at [%p].\n",
++ sockname.sun_path, (void *) ciptr);
++#endif
+ unlink (sockname.sun_path);
+
+ if ((status = TRANS(SocketCreateListener) (ciptr,
+@@ -1181,9 +1855,15 @@
+ #else
+ mode = 0777;
+ #endif
++#ifdef NX_TRANS_SOCKET
++ if (trans_mkdir(_NXGetUnixDir(UNIX_DIR), mode) == -1) {
++ PRMSG (1, "SocketUNIXResetListener: mkdir(%s) failed, errno = %d\n",
++ _NXGetUnixDir(UNIX_DIR), errno, 0);
++#else
+ if (trans_mkdir(UNIX_DIR, mode) == -1) {
+ PRMSG (1, "SocketUNIXResetListener: mkdir(%s) failed, errno = %d\n",
+ UNIX_DIR, errno, 0);
++#endif
+ (void) umask (oldUmask);
+ return TRANS_RESET_FAILURE;
+ }
+@@ -1962,7 +2642,12 @@
+ * we know for sure it will fail.
+ */
+
++#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
++ if (strcmp(host, "unix") != 0 && strcasecmp(host, "nx") != 0 &&
++ strncasecmp(host, "nx,", 3) != 0 && !UnixHostReallyLocal (host))
++#else
+ if (strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host))
++#endif
+ {
+ PRMSG (1,
+ "SocketUNIXConnect: Cannot connect to non-local host %s\n",
+@@ -1988,7 +2673,11 @@
+
+ sockname.sun_family = AF_UNIX;
+
++#ifdef NX_TRANS_SOCKET
++ if (set_sun_path(port, _NXGetUnixPath(UNIX_PATH), sockname.sun_path) != 0) {
++#else
+ if (set_sun_path(port, UNIX_PATH, sockname.sun_path) != 0) {
++#endif
+ PRMSG (1, "SocketUNIXConnect: path too long\n", 0, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+@@ -2006,7 +2695,11 @@
+ * This is gross, but it was in Xlib
+ */
+ old_sockname.sun_family = AF_UNIX;
++#ifdef NX_TRANS_SOCKET
++ if (set_sun_path(port, _NXGetOldUnixPath(OLD_UNIX_PATH), old_sockname.sun_path) != 0) {
++#else
+ if (set_sun_path(port, OLD_UNIX_PATH, old_sockname.sun_path) != 0) {
++#endif
+ PRMSG (1, "SocketUNIXConnect: path too long\n", 0, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+@@ -2014,6 +2707,19 @@
+ sizeof (old_sockname.sun_family);
+ #endif
+
++#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
++
++ if (ciptr->priv != NULL)
++ {
++ if (TRANS(SocketConnectConnInfo) (ciptr, host, port) != 0)
++ {
++ return TRANS_CONNECT_FAILED;
++ }
++
++ goto SocketUNIXConnectPost;
++ }
++
++#endif
+
+ /*
+ * Do the connect()
+@@ -2065,6 +2771,12 @@
+ }
+ }
+
++#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
++
++SocketUNIXConnectPost:
++
++#endif
++
+ /*
+ * Get the socket name and the peer name from the connect socket,
+ * since this is unix domain.
+@@ -2099,6 +2811,58 @@
+ {
+ PRMSG (2,"SocketBytesReadable(%p,%d,%p)\n",
+ ciptr, ciptr->fd, pend);
++
++#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
++
++ if (ciptr->priv)
++ {
++ if (NXTransRunning(ciptr->fd) == 0)
++ {
++ /*
++ * Force the application to shut down the
++ * socket if the NX transport is gone. We
++ * may probably save this additional call.
++ */
++
++#ifdef NX_TRANS_DEBUG
++ fprintf(stderr, "SocketBytesReadable: NX transport not running for descriptor [%d].\n",
++ ciptr->fd);
++#endif
++ ESET(EPIPE);
++
++ return -1;
++ }
++ else
++ {
++ /*
++ * Emulate BytesReadable. Some X applications may use the system
++ * select() in their main loop, instead of the _XSelect() that is
++ * replaced by NX. Still these applications use _XEventsQueued to
++ * poll events from the X connection, and _XEventsQueued uses the
++ * NX _XSelect(), so it is generally possible to let the client
++ * yield the control to NX and let it handle the I/O on the proxy
++ * descriptors even if the application is not explicitly designed
++ * to work as a NX agent.
++ */
++
++#ifdef NX_TRANS_DEBUG
++
++ int result;
++
++ result = NXTransReadable(ciptr->fd, (int *) pend);
++
++ fprintf(stderr, "SocketBytesReadable: Descriptor [%d] result [%d] readable [%ld].\n",
++ ciptr->fd, result, *pend);
++
++ return result;
++#else
++ return NXTransReadable(ciptr->fd, (int *) pend);
++#endif
++ }
++ }
++
++#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
++
+ #if defined(QNX4)
+ *pend = 0L; /* FIONREAD only returns a short. Zero out upper bits */
+ #endif
+@@ -2128,6 +2892,41 @@
+ {
+ PRMSG (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, buf, size);
+
++#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
++
++ /*
++ * If we have a valid priv pointer then this
++ * is an internal connection to the proxy.
++ * In this case we should emulate the read.
++ */
++
++ if (ciptr->priv)
++ {
++ int result;
++
++ result = NXTransRead(ciptr->fd, buf, size);
++
++#ifdef NX_TRANS_DEBUG
++ if (result < 0 && EGET() == EAGAIN)
++ {
++ fprintf(stderr, "SocketRead: Read from descriptor [%d] would block.\n",
++ ciptr->fd);
++ }
++ else
++ {
++ fprintf(stderr, "SocketRead: Read [%d] bytes from descriptor [%d].\n",
++ result, ciptr->fd);
++ }
++#endif
++ return result;
++ }
++ else
++ {
++ return read (ciptr->fd, buf, size);
++ }
++
++#else /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
++
+ #if defined(WIN32) || defined(__UNIXOS2__)
+ {
+ int ret = recv ((SOCKET)ciptr->fd, buf, size, 0);
+@@ -2139,6 +2938,8 @@
+ #else
+ return read (ciptr->fd, buf, size);
+ #endif /* WIN32 */
++
++#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+ }
+
+
+@@ -2148,6 +2949,41 @@
+ {
+ PRMSG (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, buf, size);
+
++#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
++
++ /*
++ * If we have a valid priv pointer then this
++ * is an internal connection to the proxy.
++ * In this case we should emulate the write.
++ */
++
++ if (ciptr->priv)
++ {
++ int result;
++
++ result = NXTransWrite(ciptr->fd, buf, size);
++
++#ifdef NX_TRANS_DEBUG
++ if (result < 0 && EGET() == EAGAIN)
++ {
++ fprintf(stderr, "SocketWrite: Write on descriptor [%d] would block.\n",
++ ciptr->fd);
++ }
++ else
++ {
++ fprintf(stderr, "SocketWrite: Written [%d] bytes on descriptor [%d].\n",
++ result, ciptr->fd);
++ }
++#endif
++ return result;
++ }
++ else
++ {
++ return write (ciptr->fd, buf, size);
++ }
++
++#else /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
++
+ #if defined(WIN32) || defined(__UNIXOS2__)
+ {
+ int ret = send ((SOCKET)ciptr->fd, buf, size, 0);
+@@ -2159,6 +2995,8 @@
+ #else
+ return write (ciptr->fd, buf, size);
+ #endif /* WIN32 */
++
++#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+ }
+
+
+@@ -2168,7 +3006,28 @@
+ {
+ PRMSG (2,"SocketReadv(%d,%p,%d)\n", ciptr->fd, buf, size);
+
++#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
++
++ /*
++ * If we have a valid priv pointer then this
++ * is an internal connection to the proxy.
++ * In this case we should emulate the readv.
++ */
++
++ if (ciptr->priv)
++ {
++ return NXTransReadVector(ciptr->fd, buf, size);
++ }
++ else
++ {
++ return READV (ciptr, buf, size);
++ }
++
++#else /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
++
+ return READV (ciptr, buf, size);
++
++#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+ }
+
+
+@@ -2178,7 +3037,28 @@
+ {
+ PRMSG (2,"SocketWritev(%d,%p,%d)\n", ciptr->fd, buf, size);
+
++#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
++
++ /*
++ * If we have a valid priv pointer then this
++ * is an internal connection to the proxy.
++ * In this case we should emulate the writev.
++ */
++
++ if (ciptr->priv)
++ {
++ return NXTransWriteVector(ciptr->fd, buf, size);
++ }
++ else
++ {
++ return WRITEV (ciptr, buf, size);
++ }
++
++#else /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
++
+ return WRITEV (ciptr, buf, size);
++
++#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+ }
+
+
+@@ -2234,17 +3114,41 @@
+ struct sockaddr_un *sockname = (struct sockaddr_un *) ciptr->addr;
+ int ret;
+
+- PRMSG (2,"SocketUNIXClose(%p,%d)\n", ciptr, ciptr->fd, 0);
++ PRMSG (2,"SocketUNIXClose(%x,%d)\n", ciptr, ciptr->fd, 0);
++
++#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
++
++ if (ciptr->priv)
++ {
++ TRANS(SocketCloseConnInfo) (ciptr);
++ }
++
++#endif
+
+ ret = close(ciptr->fd);
+
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
++ fprintf(stderr, "SocketUNIXClose: Flags are [%d] for ciptr at [%p] check is [%d].\n",
++ ciptr->flags, (void *) ciptr, (ciptr->flags && sockname
++ && sockname->sun_family == AF_UNIX && sockname->sun_path[0]));
++#endif
++
+ if (ciptr->flags
+ && sockname
+ && sockname->sun_family == AF_UNIX
+ && sockname->sun_path[0])
+ {
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
++ if (!(ciptr->flags & TRANS_NOUNLINK))
++ {
++ fprintf(stderr, "SocketUNIXClose: Unlinking path [%s] for ciptr at [%p].\n",
++ sockname->sun_path, (void *) ciptr);
++ unlink (sockname->sun_path);
++ }
++#else
+ if (!(ciptr->flags & TRANS_NOUNLINK))
+ unlink (sockname->sun_path);
++#endif
+ }
+
+ return ret;
+@@ -2263,6 +3167,15 @@
+ PRMSG (2,"SocketUNIXCloseForCloning(%p,%d)\n",
+ ciptr, ciptr->fd, 0);
+
++#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
++
++ if (ciptr->priv)
++ {
++ TRANS(SocketCloseConnInfo) (ciptr);
++ }
++
++#endif
++
+ ret = close(ciptr->fd);
+
+ return ret;
diff --git a/doc/nx-X11_vs_XOrg69_patches/auth.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/auth.c.NX.patch
new file mode 100644
index 000000000..d7549c487
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/auth.c.NX.patch
@@ -0,0 +1,271 @@
+--- ./nx-X11/programs/Xserver/os/auth.c.X.original 2015-02-13 14:03:44.788440645 +0100
++++ ./nx-X11/programs/Xserver/os/auth.c 2015-02-10 19:13:13.452699065 +0100
+@@ -28,6 +28,23 @@
+ */
+ /* $XFree86: auth.c,v 1.13 2003/04/27 21:31:08 herrb Exp $ */
+
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NX-X11, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /*
+ * authorization hooks for the server
+ * Author: Keith Packard, MIT X Consortium
+@@ -129,7 +146,24 @@
+ void
+ InitAuthorization (char *file_name)
+ {
++#ifdef __sun
++ char * envBuffer;
++#endif
+ authorization_file = file_name;
++#ifdef NX_TRANS_AUTH
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "InitAuthorization: Going to propagate auth file '%s' to the environment.\n",
++ authorization_file);
++#endif
++#ifdef __sun
++ envBuffer = malloc(15+strlen(authorization_file));
++ sprintf(envBuffer,"NX_XAUTHORITY=%s",authorization_file);
++ putenv(envBuffer);
++#else
++ setenv("NX_XAUTHORITY", authorization_file, 1);
++#endif
++#endif
++
+ }
+
+ static int
+@@ -144,6 +178,68 @@
+ if (!authorization_file)
+ return 0;
+
++#ifdef NX_TRANS_AUTH
++
++ /*
++ * We think that the way LoadAuthorization() is working is wrong.
++ * It doesn't reset the list of stored authorizations before reading
++ * the new cookies. Our take is that if a new auth file is to be
++ * read, the only cookies that are to be accepted are those that are
++ * in the new file, not those in the file -plus- those that have
++ * been in the file in the past. Furthermore, if the list can't be
++ * read or it is empty, it should assume that it ignores which co-
++ * okies are valid and thus it should disable any access. Your mile-
++ * age can vary. A less draconian approach could be to leave the old
++ * cookies if the file can't be read and remove them only if the
++ * file is empty.
++ *
++ * Adding the cookies without removing the old values for the same
++ * protocol has an important implication. If an user shares the co-
++ * okie with somebody and later wants to revoke the access to the
++ * display, changing the cookie will not work. This is especially
++ * important with NX. For security reasons, after reconnecting the
++ * session to a different display, it is advisable to generate a
++ * new set of cookies, but doing that it is useless with the current
++ * code, as the old cookies are going to be still accepted. On the
++ * same topic, consider that once an user has got access to the X
++ * server, he/she can freely enable host authentication from any
++ * host, so the safe behaviour should be to reset the host based
++ * authenthication at least at reconnection, and keep as valid only
++ * the cookies that are actually in the file. This behaviour would
++ * surely break many applications, among them a SSH connection run
++ * inside a NX session, as ssh -X reads the cookie for the display
++ * only at session startup and does not read the cookies again
++ * when the auth file is changed.
++ *
++ * Another bug (or feature, depending on how you want to consider
++ * it) is that if the authority file contains entries for different
++ * displays (as it is the norm when the authority file is the default
++ * .Xauthority in the user's home), the server will match -any- of
++ * the cookies, even cookies that are not for its own display. This
++ * means that you have be careful when passing an authority file to
++ * nxagent or Xnest and maybe keep separate files for letting nxagent
++ * find the cookie to be used to connect to the remote display and
++ * for letting it find what cookies to accept. If the file is the
++ * same, clients will be able to connect to nxagent with both the
++ * cookies.
++ */
++
++#ifdef NX_TRANS_AUTH_RESET
++
++ #ifdef NX_TRANS_TEST
++ fprintf(stderr, "LoadAuthorization: Resetting authorization info.\n");
++ #endif
++
++ for (i = 0; i < NUM_AUTHORIZATION; i++) {
++ if (protocols[i].Reset) {
++ (*protocols[i].Reset) ();
++ }
++ }
++
++#endif
++
++#endif /* #ifdef NX_TRANS_AUTH */
++
+ f = Fopen (authorization_file, "r");
+ if (!f)
+ return -1;
+@@ -154,6 +250,14 @@
+ memcmp (protocols[i].name, auth->name, (int) auth->name_length) == 0 &&
+ protocols[i].Add)
+ {
++#ifdef NX_TRANS_AUTH
++
++ #ifdef NX_TRANS_TEST
++ fprintf(stderr, "LoadAuthorization: Adding new record from file [%s].\n",
++ authorization_file);
++ #endif
++
++#endif
+ ++count;
+ (*protocols[i].Add) (auth->data_length, auth->data,
+ FakeClientID(0));
+@@ -162,7 +266,46 @@
+ XauDisposeAuth (auth);
+ }
+
++#ifdef NX_TRANS_AUTH
++
++ if (count == 0)
++ {
++ fprintf(stderr, "Warning: No authorization record could be read from file '%s'.\n",
++ authorization_file);
++
++ fprintf(stderr, "Warning: Please, create a valid authorization cookie using the command\n"
++ "Warning: 'xauth -f %s add <display> MIT-MAGIC-COOKIE-1 <cookie>'.\n",
++ authorization_file);
++ }
++
++#endif
++
++#ifdef NX_TRANS_AUTH
++ if (Fclose (f) != 0)
++ {
++ /*
++ * If the Fclose() fails, for example because of a signal,
++ * it's advisable to return the number of protocols read,
++ * if any, or otherwise the server would believe that no
++ * cookie is valid and eventually fall back to host based
++ * authentication. Note anyway that the new code in Check-
++ * Authorization() doesn't care the return value and gives
++ * a chance to the function to check the file at the next
++ * connection.
++ */
++
++ if (count > 0)
++ {
++ return count;
++ }
++ else
++ {
++ return -1;
++ }
++ }
++#else
+ Fclose (f);
++#endif
+ return count;
+ }
+
+@@ -194,7 +337,10 @@
+ int i;
+ struct stat buf;
+ static time_t lastmod = 0;
++
++ #ifndef NX_TRANS_AUTH
+ static Bool loaded = FALSE;
++ #endif
+
+ if (!authorization_file || stat(authorization_file, &buf))
+ {
+@@ -225,7 +371,67 @@
+ * entries for this server), and reloading it later fails, don't
+ * change anything. (loadauth == -1 && loaded)
+ */
+-
++
++#ifdef NX_TRANS_AUTH
++
++ /*
++ * The implementation of CheckAuthorization() was changed. The way
++ * the auth file was handled previously was questionable and could
++ * open the way to a vast array of security problems. There might be
++ * ways for an attacker to prevent the server from reading the file
++ * and it was enough for the server to fail reading the file once
++ * (because of a not blocked signal, for example) to leave the dis-
++ * play open to all the users running a session on the same terminal
++ * server.
++ *
++ * In NX we want to have only two cases: either we have to check an
++ * authorization file or we don't. In the first case we need to do our
++ * best to read the file at any new client access and never fall back
++ * to host based authentication. Falling back to local host access has
++ * no way back, as it will always take precedence over the auth cookie
++ * (unless the user explicitly disables, one by one, all the rules
++ * allowing local access, if and only if he/she becomes aware of the
++ * problem). In the second case we assume that user doesn't care secu-
++ * rity and so allow unrestricted access from the local machine.
++ */
++
++ #ifdef NX_TRANS_TEST
++ fprintf(stderr, "CheckAuthorization: Going to set authorization with loadauth [%d].\n",
++ loadauth);
++ #endif
++
++ if (authorization_file)
++ {
++ #ifdef NX_TRANS_TEST
++ fprintf(stderr, "CheckAuthorization: Disabling local host access.\n");
++ #endif
++
++ DisableLocalHost();
++ }
++ else
++ {
++ /*
++ * Enable host-based authentication only if
++ * the authorization file was not specified
++ * either on the command line or in the env-
++ * ironment.
++ */
++
++ #ifdef NX_TRANS_TEST
++ fprintf(stderr, "CheckAuthorization: Enabling local host access.\n");
++ #endif
++
++ EnableLocalHost();
++ }
++
++ /*
++ * Avoid the 'unused variable' warning.
++ */
++
++ loadauth = loadauth;
++
++#else /* #ifdef NX_TRANS_AUTH */
++
+ if (loadauth > 0)
+ {
+ DisableLocalHost(); /* got at least one */
+@@ -233,6 +439,8 @@
+ }
+ else if (loadauth == 0 || !loaded)
+ EnableLocalHost ();
++
++#endif /* #ifdef NX_TRANS_AUTH */
+ }
+ if (name_length) {
+ for (i = 0; i < NUM_AUTHORIZATION; i++) {
diff --git a/doc/nx-X11_vs_XOrg69_patches/charproc.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/charproc.c.NX.patch
new file mode 100644
index 000000000..ecd0f67bb
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/charproc.c.NX.patch
@@ -0,0 +1,40 @@
+--- ./nx-X11/programs/xterm/charproc.c.X.original 2015-02-13 14:03:44.800440409 +0100
++++ ./nx-X11/programs/xterm/charproc.c 2015-02-13 14:03:44.796440488 +0100
+@@ -82,6 +82,23 @@
+ * SOFTWARE.
+ */
+
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NX-X11, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /* charproc.c */
+
+ #include <version.h>
+@@ -3177,6 +3194,13 @@
+ }
+ if (need_cleanup)
+ Cleanup(0);
++
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
++ fprintf(stderr, "xterm::in_put: Select called with [%d][%p][%p][%p][%p].\n",
++ max_plus1, (void *) &select_mask, (void *) &write_mask, (void *) 0,
++ (void *) (time_select ? &select_timeout : 0));
++#endif
++
+ i = Select(max_plus1, &select_mask, &write_mask, 0,
+ (time_select ? &select_timeout : 0));
+ if (i < 0) {
diff --git a/doc/nx-X11_vs_XOrg69_patches/cmsProp.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/cmsProp.c.NX.patch
new file mode 100644
index 000000000..c929125f7
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/cmsProp.c.NX.patch
@@ -0,0 +1,14 @@
+--- ./nx-X11/lib/X11/cmsProp.c.X.original 2015-02-13 14:03:44.624443872 +0100
++++ ./nx-X11/lib/X11/cmsProp.c 2015-02-10 19:13:12.948717938 +0100
+@@ -121,7 +121,11 @@
+ char *prop_ret;
+ int format_ret;
+ long len = 6516;
++ #ifdef NXAGENT_SERVER
++ unsigned long nitems_ret, after_ret = 0;
++ #else
+ unsigned long nitems_ret, after_ret;
++ #endif
+ Atom atom_ret;
+
+ while (XGetWindowProperty (pDpy, w, property, 0, len, False,
diff --git a/doc/nx-X11_vs_XOrg69_patches/connection.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/connection.c.NX.patch
new file mode 100644
index 000000000..f25c0160e
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/connection.c.NX.patch
@@ -0,0 +1,48 @@
+--- ./nx-X11/programs/Xserver/os/connection.c.X.original 2015-02-13 14:03:44.788440645 +0100
++++ ./nx-X11/programs/Xserver/os/connection.c 2015-02-10 19:13:13.452699065 +0100
+@@ -486,6 +486,45 @@
+ #endif
+ }
+
++#ifdef NX_TRANS_SOCKET
++
++/*
++ * The following block is now defined also
++ * under Cygwin to support this environment.
++ */
++
++#ifndef __DARWIN__
++
++/*
++ * This is defined in Xtranssock.c and must
++ * be called explicitly as it doesn't share
++ * a pointer in the transport function table.
++ */
++
++extern void _XSERVTransSocketRejectConnection(XtransConnInfo);
++
++void
++RejectWellKnownSockets ()
++{
++ int i;
++
++ for (i = 0; i < ListenTransCount; i++)
++ {
++ _XSERVTransSocketRejectConnection(ListenTransConns[i]);
++ }
++}
++
++#endif /* #ifndef __DARWIN__ */
++
++#else /* #ifdef NX_TRANS_SOCKET */
++
++void
++RejectWellKnownSockets ()
++{
++}
++
++#endif /* #ifdef NX_TRANS_SOCKET */
++
+ void
+ ResetWellKnownSockets (void)
+ {
diff --git a/doc/nx-X11_vs_XOrg69_patches/context.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/context.c.NX.patch
new file mode 100644
index 000000000..92dedfc0a
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/context.c.NX.patch
@@ -0,0 +1,103 @@
+--- ./nx-X11/extras/Mesa/src/mesa/main/context.c.X.original 2015-02-13 14:03:44.464447019 +0100
++++ ./nx-X11/extras/Mesa/src/mesa/main/context.c 2015-02-10 19:13:14.800648672 +0100
+@@ -131,6 +131,10 @@
+ #endif
+ #include "shaderobjects.h"
+
++#ifdef NXAGENT_SERVER
++#include "WSDrawBuffer.h"
++#endif
++
+ #ifdef USE_SPARC_ASM
+ #include "sparc/sparc.h"
+ #endif
+@@ -143,6 +147,47 @@
+ int MESA_DEBUG_FLAGS = 0;
+ #endif
+
++#ifdef NXAGENT_SERVER
++extern WSDrawBufferPtr pWSDrawBuffer;
++
++int IsWSDrawBuffer(GLframebuffer *mesa_buffer)
++{
++ WSDrawBufferPtr p = pWSDrawBuffer;
++
++ while (p != NULL) {
++ if (p -> DrawBuffer == mesa_buffer) {
++ return 1;
++ }
++ p = p -> next;
++ }
++ return 0;
++}
++
++void FreeWSDrawBuffer(GLframebuffer *mesa_buffer)
++{
++ WSDrawBufferPtr p = pWSDrawBuffer;
++ WSDrawBufferPtr pOld = NULL;
++
++ if (p == NULL)
++ return;
++
++ if (p -> DrawBuffer == mesa_buffer) {
++ pWSDrawBuffer = p -> next;
++ free(p);
++ return;
++ }
++
++ while (p -> next != NULL) {
++ if (p -> next -> DrawBuffer == mesa_buffer) {
++ pOld = p -> next;
++ p -> next = p -> next -> next;
++ free(pOld);
++ return;
++ }
++ p = p -> next;
++ }
++}
++#endif
+
+ /* ubyte -> float conversion */
+ GLfloat _mesa_ubyte_to_float_color_tab[256];
+@@ -1520,6 +1565,10 @@
+ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
+ GLframebuffer *readBuffer )
+ {
++ #ifdef NXAGENT_SERVER
++ int flag;
++ #endif
++
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(newCtx, "_mesa_make_current()\n");
+
+@@ -1558,11 +1607,30 @@
+ ASSERT(readBuffer->Name == 0);
+ newCtx->WinSysDrawBuffer = drawBuffer;
+ newCtx->WinSysReadBuffer = readBuffer;
++
++#ifdef NXAGENT_SERVER
++ flag = 0;
++ if (newCtx->DrawBuffer) {
++ if (!IsWSDrawBuffer(newCtx->DrawBuffer)) {
++ if (newCtx->DrawBuffer->Name == 0) {
++ flag = 1;
++ }
++ FreeWSDrawBuffer(newCtx->DrawBuffer);
++ }
++ else flag = 1;
++ }
++
++ if (!newCtx->DrawBuffer || flag) {
++ newCtx->DrawBuffer = drawBuffer;
++ newCtx->ReadBuffer = readBuffer;
++ }
++#else
+ /* don't replace user-buffer bindings with window system buffer */
+ if (!newCtx->DrawBuffer || newCtx->DrawBuffer->Name == 0) {
+ newCtx->DrawBuffer = drawBuffer;
+ newCtx->ReadBuffer = readBuffer;
+ }
++#endif
+
+ newCtx->NewState |= _NEW_BUFFERS;
+
diff --git a/doc/nx-X11_vs_XOrg69_patches/cross.def.NX.patch b/doc/nx-X11_vs_XOrg69_patches/cross.def.NX.patch
new file mode 100644
index 000000000..907c5c850
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/cross.def.NX.patch
@@ -0,0 +1,33 @@
+--- ./nx-X11/config/cf/cross.def.X.original 2015-02-13 14:03:44.396448342 +0100
++++ ./nx-X11/config/cf/cross.def 2015-02-10 19:13:13.392701311 +0100
+@@ -16,16 +16,16 @@
+ #define StandardDefines -Dlinux -D__arm__ -D_POSIX_SOURCE \
+ -D_BSD_SOURCE -D_GNU_SOURCE -DX_LOCALE
+ #undef CcCmd
+-#define StdIncDir /skiff/local/arm-linux/include
++#define StdIncDir /opt/Embedix/tools/arm-linux/include
+ #define PreIncDir
+ #undef PostIncDir
+-#define PostIncDir /skiff/local/lib/gcc-lib/arm-linux/2.95.2/include
+-#define CcCmd /skiff/local/bin/arm-linux-gcc
++#define PostIncDir /opt/Embedix/tools/lib/gcc-lib/arm-linux/2.95.2/include
++#define CcCmd /opt/Embedix/tools/bin/arm-linux-gcc
+ #undef CplusplusCmd
+ #define HasCplusplus YES
+-#define CplusplusCmd /skiff/local/bin/arm-linux-g++
++#define CplusplusCmd /opt/Embedix/tools/bin/arm-linux-g++
+ #define DoRanlibCmd YES
+-#define RanlibCmd /skiff/local/bin/arm-linux-ranlib
++#define RanlibCmd /opt/Embedix/tools/bin/arm-linux-ranlib
+ #undef ExtraLoadFlags
+ #define ExtraLoadFlags
+ #define FbNoPixelAddrCode
+@@ -33,7 +33,7 @@
+ #define TermcapLibrary -ltermcap
+
+ #undef LdPostLib
+-#define LdPostLib -L/skiff/local/arm-linux/lib
++#define LdPostLib -L/opt/Embedix/tools/arm-linux/lib
+
+ #undef ExtensionOSDefines
+ #define ExtensionOSDefines
diff --git a/doc/nx-X11_vs_XOrg69_patches/cursor.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/cursor.c.NX.patch
new file mode 100644
index 000000000..faf242160
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/cursor.c.NX.patch
@@ -0,0 +1,12 @@
+--- ./nx-X11/programs/Xserver/xfixes/cursor.c.X.original 2015-02-13 14:03:44.792440567 +0100
++++ ./nx-X11/programs/Xserver/xfixes/cursor.c 2015-02-10 19:13:13.508696968 +0100
+@@ -96,7 +96,8 @@
+ CursorCurrent = pCursor;
+ for (e = cursorEvents; e; e = e->next)
+ {
+- if (e->eventMask & XFixesDisplayCursorNotifyMask)
++ if ((e->eventMask & XFixesDisplayCursorNotifyMask) &&
++ !e->pClient->clientGone)
+ {
+ xXFixesCursorNotifyEvent ev;
+ ev.type = XFixesEventBase + XFixesCursorNotify;
diff --git a/doc/nx-X11_vs_XOrg69_patches/ddxKillSrv.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/ddxKillSrv.c.NX.patch
new file mode 100644
index 000000000..a6acd7c04
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/ddxKillSrv.c.NX.patch
@@ -0,0 +1,21 @@
+--- ./nx-X11/programs/Xserver/xkb/ddxKillSrv.c.X.original 2015-02-13 14:03:44.792440567 +0100
++++ ./nx-X11/programs/Xserver/xkb/ddxKillSrv.c 2015-02-10 19:13:13.736688433 +0100
+@@ -52,10 +52,18 @@
+ int
+ XkbDDXTerminateServer(DeviceIntPtr dev,KeyCode key,XkbAction *act)
+ {
++#ifdef NXAGENT_SERVER
++
++ return 0;
++
++#else
++
+ #ifdef XF86DDXACTIONS
+ xf86ProcessActionEvent(ACTION_TERMINATE, NULL);
+ #else
+ GiveUp(1);
+ #endif
+ return 0;
++
++#endif /* NXAGENT_SERVER */
+ }
diff --git a/doc/nx-X11_vs_XOrg69_patches/ddxLoad.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/ddxLoad.c.NX.patch
new file mode 100644
index 000000000..3c2eda498
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/ddxLoad.c.NX.patch
@@ -0,0 +1,443 @@
+--- ./nx-X11/programs/Xserver/xkb/ddxLoad.c.X.original 2015-02-13 14:03:44.792440567 +0100
++++ ./nx-X11/programs/Xserver/xkb/ddxLoad.c 2015-02-13 14:03:44.792440567 +0100
+@@ -34,6 +34,7 @@
+ #include <xkb-config.h>
+ #endif
+
++#include <errno.h>
+ #include <stdio.h>
+ #include <ctype.h>
+ #define NEED_EVENTS 1
+@@ -175,6 +176,310 @@
+ # endif
+ #endif
+
++#ifdef NXAGENT_SERVER
++
++#define NX_XKB_BASE_DIRECTORY "/usr/lib/X11/xkb"
++#define NX_XKB_ALTERNATE_BASE_DIRECTORY "/usr/share/X11/xkb"
++#define NX_KEYMAP_DIR_FILE "keymap.dir"
++#define NX_ALT_XKBCOMP_PATH "/usr/bin"
++
++static char _NXXkbBasePath[PATH_MAX];
++static char _NXXkbCompPath[PATH_MAX];
++
++static int NXVerifyXkbBaseDirectory(const char *dirPath)
++{
++ int size;
++ char *keymapDirFilePath;
++ struct stat keymapDirFileStat;
++
++ /*
++ * If keymap.dir file
++ * is not present into
++ * Xkb Base Directory,
++ * we suppose that the
++ * path is not valid.
++ */
++
++ size = strlen(dirPath) + strlen("/") +
++ strlen(NX_KEYMAP_DIR_FILE) + 1;
++
++ if ((keymapDirFilePath = malloc((size + 1) * sizeof(char))) == NULL)
++ {
++ FatalError("NXVerifyXkbBaseDirectory: malloc failed.\n");
++ }
++
++ strcpy(keymapDirFilePath, dirPath);
++ strcat(keymapDirFilePath, "/");
++ strcat(keymapDirFilePath, NX_KEYMAP_DIR_FILE);
++
++ #ifdef TEST
++ fprintf(stderr, "NXVerifyXkbBaseDirectory: Looking for [%s] file.\n",
++ keymapDirFilePath);
++ #endif
++
++ if (stat(keymapDirFilePath, &keymapDirFileStat) != 0)
++ {
++
++ #ifdef TEST
++ fprintf(stderr, "NXVerifyXkbBaseDirectory: Can't find the keymap.dir file [%s].\n",
++ keymapDirFilePath);
++ #endif
++
++ free(keymapDirFilePath);
++
++ return 0;
++ }
++
++ #ifdef TEST
++ fprintf(stderr, "NXVerifyXkbBaseDirectory: Xkb Base Directory [%s] is valid.\n",
++ dirPath);
++ #endif
++
++ free(keymapDirFilePath);
++
++ return 1;
++}
++
++/*
++ * This function returns the directory
++ * containing the configuration files.
++ * This directory is referred by Xkb-
++ * BaseDirectory variable (generally
++ * it contains the hardcoded path at
++ * compile time). If the directory
++ * does not exist, the function will
++ * try a set of well known directories.
++ */
++
++char *_NXGetXkbBasePath(const char *path)
++{
++ /*
++ * Check the xkb base directory only once.
++ */
++
++ if (*_NXXkbBasePath != '\0')
++ {
++ return _NXXkbBasePath;
++ }
++
++ if (NXVerifyXkbBaseDirectory(XkbBaseDirectory) == 1)
++ {
++ if (strlen(XkbBaseDirectory) + 1 > PATH_MAX)
++ {
++ #ifdef TEST
++ fprintf(stderr, "_NXGetXkbBasePath: WARNING! Maximum length of xkb base path exceeded.\n");
++ #endif
++
++ goto _NXGetXkbBasePathError;
++ }
++
++ strcpy(_NXXkbBasePath, XkbBaseDirectory);
++
++ #ifdef TEST
++ fprintf(stderr, "_NXGetXkbBasePath: Using NX xkb base directory path [%s].\n",
++ _NXXkbBasePath);
++ #endif
++
++ return _NXXkbBasePath;
++ }
++
++ if (NXVerifyXkbBaseDirectory(NX_XKB_BASE_DIRECTORY) == 1)
++ {
++ if (strlen(NX_XKB_BASE_DIRECTORY) + 1 > PATH_MAX)
++ {
++ #ifdef TEST
++ fprintf(stderr, "_NXGetXkbBasePath: WARNING! Maximum length of xkb base path exceeded.\n");
++ #endif
++
++ goto _NXGetXkbBasePathError;
++ }
++
++ strcpy(_NXXkbBasePath, NX_XKB_BASE_DIRECTORY);
++
++ #ifdef TEST
++ fprintf(stderr, "_NXGetXkbBasePath: Using NX xkb base directory path [%s].\n",
++ _NXXkbBasePath);
++ #endif
++
++ return _NXXkbBasePath;
++ }
++
++ if (NXVerifyXkbBaseDirectory(NX_XKB_ALTERNATE_BASE_DIRECTORY) == 1)
++ {
++ if (strlen(NX_XKB_ALTERNATE_BASE_DIRECTORY) + 1 > PATH_MAX)
++ {
++ #ifdef TEST
++ fprintf(stderr, "_NXGetXkbBasePath: WARNING! Maximum length of xkb base path exceeded.\n");
++ #endif
++
++ goto _NXGetXkbBasePathError;
++ }
++
++ strcpy(_NXXkbBasePath, NX_XKB_ALTERNATE_BASE_DIRECTORY);
++
++ #ifdef TEST
++ fprintf(stderr, "_NXGetXkbBasePath: Using NX xkb base directory path [%s].\n",
++ _NXXkbBasePath);
++ #endif
++
++ return _NXXkbBasePath;
++ }
++
++_NXGetXkbBasePathError:
++
++ if (strlen(path) + 1 > PATH_MAX)
++ {
++ #ifdef TEST
++ fprintf(stderr, "_NXGetXkbBasePath: WARNING! Maximum length of xkb base path exceeded.\n");
++ #endif
++ }
++
++ strcpy(_NXXkbBasePath, path);
++
++ #ifdef TEST
++ fprintf(stderr, "_NXGetXkbBasePath: Using default xkb base path [%s].\n",
++ _NXXkbBasePath);
++ #endif
++
++ return _NXXkbBasePath;
++}
++
++static int NXVerifyXkbCompPath(char *path)
++{
++ char *xkbCompPath;
++ int xkbCompPathSize;
++ struct stat xkbCompPathStat;
++
++ if (path == NULL)
++ {
++ return 0;
++ }
++
++ xkbCompPathSize = strlen(path) + strlen("/") +
++ strlen("xkbcomp") + 1;
++
++ if ((xkbCompPath = malloc((xkbCompPathSize + 1) * sizeof(char))) == NULL)
++ {
++ FatalError("NXVerifyXkbCompPath: WARNING! malloc failed.\n");
++
++ return 0;
++ }
++
++ strcpy(xkbCompPath, path);
++ strcat(xkbCompPath, "/");
++ strcat(xkbCompPath, "xkbcomp");
++
++ if (stat(xkbCompPath, &xkbCompPathStat) != 0)
++ {
++ #ifdef NX_TRANS_TEST
++ fprintf(stderr, "NXVerifyXkbCompPath: WARNING! Failed to stat xkbcomp path [%s].\n",
++ xkbCompPath);
++ #endif
++
++ free(xkbCompPath);
++
++ return 0;
++ }
++
++ free(xkbCompPath);
++
++ return 1;
++}
++
++/*
++ * This function returns the directory
++ * containing the xkbcomp executable.
++ * The function will first try to locate
++ * the executable in the hardcoded path
++ * (the same path as the "base" xkb one)
++ * and, if the xkbcomp file couldn't be
++ * found, the function will not include
++ * an explicit path and will rely on the
++ * PATH environment to list the directory.
++ */
++
++char *_NXGetXkbCompPath(const char *path)
++{
++
++ char * xkbCompPath;
++
++ /*
++ * Check the xkbcomp executable
++ * directory only once.
++ */
++
++ if (*_NXXkbCompPath != '\0')
++ {
++ return _NXXkbCompPath;
++ }
++
++ xkbCompPath = _NXGetXkbBasePath(path);
++
++ if (NXVerifyXkbCompPath(xkbCompPath) == 1)
++ {
++ if (strlen(xkbCompPath) + 1 > PATH_MAX)
++ {
++ #ifdef TEST
++ fprintf(stderr, "_NXGetXkbCompPath: WARNING! Maximum length of xkbcomp path exceeded.\n");
++ #endif
++
++ goto _NXGetXkbCompPathError;
++ }
++
++ strcpy(_NXXkbCompPath, xkbCompPath);
++
++ #ifdef TEST
++ fprintf(stderr, "_NXGetXkbCompPath: Using xkbcomp path [%s].\n",
++ _NXXkbCompPath);
++ #endif
++
++ return _NXXkbCompPath;
++ }
++
++ xkbCompPath = NX_ALT_XKBCOMP_PATH;
++
++ if (NXVerifyXkbCompPath(xkbCompPath) == 1)
++ {
++ if (strlen(xkbCompPath) + 1 > PATH_MAX)
++ {
++ #ifdef TEST
++ fprintf(stderr, "_NXGetXkbCompPath: WARNING! Maximum length of xkbcomp path exceeded.\n");
++ #endif
++
++ goto _NXGetXkbCompPathError;
++ }
++
++ strcpy(_NXXkbCompPath, xkbCompPath);
++
++ #ifdef TEST
++ fprintf(stderr, "_NXGetXkbCompPath: Using NX xkbcomp path [%s].\n",
++ _NXXkbCompPath);
++ #endif
++
++ return _NXXkbCompPath;
++ }
++
++_NXGetXkbCompPathError:
++
++ if (strlen(path) + 1 > PATH_MAX)
++ {
++ #ifdef TEST
++ fprintf(stderr, "_NXGetXkbCompPath: WARNING! Maximum length of xkbcomp path exceeded.\n");
++ #endif
++ }
++
++ strcpy(_NXXkbCompPath, path);
++
++ #ifdef TEST
++ fprintf(stderr, "_NXGetXkbCompPath: Using default xkbcomp path [%s].\n",
++ _NXXkbCompPath);
++ #endif
++
++ return _NXXkbCompPath;
++}
++
++#endif
++
+ static void
+ OutputDirectory(
+ char* outdir,
+@@ -240,14 +545,36 @@
+ XkbEnsureSafeMapName(outFile);
+ OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir));
+
++#ifdef NXAGENT_SERVER
++
++ if (_NXGetXkbCompPath(XkbBaseDirectory) != NULL)
++ {
++
++#else
++
+ if (XkbBaseDirectory!=NULL) {
++
++#endif
++
+ #ifndef __UNIXOS2__
++
++#ifdef NXAGENT_SERVER
++ char *xkbbasedir = _NXGetXkbBasePath(XkbBaseDirectory);
++ char *xkbbindir = _NXGetXkbCompPath(XkbBinDirectory);
++#else
+ char *xkbbasedir = XkbBaseDirectory;
+ char *xkbbindir = XkbBinDirectory;
++#endif
++
+ #else
+ /* relocate the basedir and replace the slashes with backslashes */
++#ifdef NXAGENT_SERVER
++ char *xkbbasedir = (char*)__XOS2RedirRoot(_NXGetXkbBasePath(XkbBaseDirectory));
++ char *xkbbindir = (char*)__XOS2RedirRoot(_NXGetXkbCompPath(XkbBinDirectory));
++#else
+ char *xkbbasedir = (char*)__XOS2RedirRoot(XkbBaseDirectory);
+ char *xkbbindir = (char*)__XOS2RedirRoot(XkbBinDirectory);
++#endif
+ int i;
+
+ for (i=0; i<strlen(xkbbasedir); i++)
+@@ -332,7 +659,13 @@
+ strcat(tmpname, "\\xkb_XXXXXX");
+ (void) mktemp(tmpname);
+ #endif
++
++#ifdef NXAGENT_SERVER
++ if (_NXGetXkbCompPath(XkbBaseDirectory)!=NULL) {
++#else
+ if (XkbBaseDirectory!=NULL) {
++#endif
++
+ #ifndef WIN32
+ char *xkmfile = "-";
+ #else
+@@ -341,12 +674,22 @@
+ char *xkmfile = tmpname;
+ #endif
+ #ifndef __UNIXOS2__
++#ifdef NXAGENT_SERVER
++ char *xkbbasedir = _NXGetXkbBasePath(XkbBaseDirectory);
++ char *xkbbindir = _NXGetXkbCompPath(XkbBinDirectory);
++#else
+ char *xkbbasedir = XkbBaseDirectory;
+ char *xkbbindir = XkbBinDirectory;
++#endif
+ #else
+ int i;
++#ifdef NXAGENT_SERVER
++ char *xkbbasedir = (char*)__XOS2RedirRoot(_NXGetXkbBasePath(XkbBaseDirectory));
++ char *xkbbindir = (char*)__XOS2RedirRoot(_NXGetXkbCompPath(XkbBinDirectory));
++#else
+ char *xkbbasedir = (char*)__XOS2RedirRoot(XkbBaseDirectory);
+ char *xkbbindir = (char*)__XOS2RedirRoot(XkbBinDirectory);
++#endif
+ for (i=0; i<strlen(xkbbasedir); i++)
+ if (xkbbasedir[i]=='/') xkbbasedir[i]='\\';
+ for (i=0; i<strlen(xkbbindir); i++)
+@@ -375,6 +718,15 @@
+ xkm_output_dir,keymap);
+ }
+
++ #ifdef TEST
++ if (buf != NULL)
++ fprintf(stderr, "XkbDDXCompileKeymapByNames: "
++ "Executing command [%s].\n", buf);
++ else
++ fprintf(stderr, "XkbDDXCompileKeymapByNames: "
++ "Callin Popen() with null command.\n");
++ #endif
++
+ #ifndef WIN32
+ out= Popen(buf,"w");
+ #else
+@@ -390,7 +742,15 @@
+ #endif
+ XkbWriteXKBKeymapForNames(out,names,NULL,xkb,want,need);
+ #ifndef WIN32
++#ifdef __sun
++ if (Pclose(out) != 0)
++ {
++ ErrorF("Warning: Spurious failure reported in Pclose() runnning 'xkbcomp'.\n");
++ }
++ if (1)
++#else
+ if (Pclose(out)==0)
++#endif
+ #else
+ if (fclose(out)==0 && System(buf) >= 0)
+ #endif
+@@ -415,9 +775,15 @@
+ {
+ int i;
+ char name[PATH_MAX];
++#ifdef NXAGENT_SERVER
++ if (_NXGetXkbCompPath(XkbBaseDirectory)!=NULL)
++ sprintf(name,"%s/%s%s.xkm", _NXGetXkbCompPath(XkbBaseDirectory)
++ ,xkm_output_dir, keymap);
++#else
+ if (XkbBaseDirectory!=NULL)
+ sprintf(name,"%s/%s%s.xkm", XkbBaseDirectory
+ ,xkm_output_dir, keymap);
++#endif
+ else
+ sprintf(name,"%s%s.xkm", xkm_output_dir, keymap);
+ for (i = 0; i < 10; i++) {
diff --git a/doc/nx-X11_vs_XOrg69_patches/dixfonts.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/dixfonts.c.NX.patch
new file mode 100644
index 000000000..1f0cbd4fd
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/dixfonts.c.NX.patch
@@ -0,0 +1,86 @@
+--- ./nx-X11/programs/Xserver/dix/dixfonts.c.X.original 2015-02-13 14:03:44.704442298 +0100
++++ ./nx-X11/programs/Xserver/dix/dixfonts.c 2015-02-13 14:03:44.704442298 +0100
+@@ -72,6 +72,63 @@
+ #include <stdio.h>
+ #endif
+
++#ifdef NX_TRANS_SOCKET
++
++char _NXFontPath[1024];
++
++/*
++ * Override the default font path and make
++ * it configurable at run time, based on
++ * the NX_FONT environment.
++ */
++
++static const char *_NXGetFontPath(const char *path)
++{
++ const char *fontEnv;
++
++ /*
++ * Check the environment only once.
++ */
++
++ if (*_NXFontPath != '\0')
++ {
++ return _NXFontPath;
++ }
++
++ fontEnv = getenv("NX_FONT");
++
++ if (fontEnv != NULL && *fontEnv != '\0')
++ {
++ if (strlen(fontEnv) + 1 > 1024)
++ {
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_NXGetFontPath: WARNING! Maximum length of font path exceeded.\n");
++#endif
++ goto _NXGetFontPathError;
++ }
++
++ strcpy(_NXFontPath, fontEnv);
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_NXGetFontPath: Using NX font path [%s].\n", _NXFontPath);
++#endif
++
++ return _NXFontPath;
++ }
++
++_NXGetFontPathError:
++
++ strcpy(_NXFontPath, path);
++
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "_NXGetFontPath: Using default font path [%s].\n", _NXFontPath);
++#endif
++
++ return _NXFontPath;
++}
++
++#endif
++
+ #ifdef PANORAMIX
+ #include "panoramiX.h"
+ #endif
+@@ -1817,11 +1874,19 @@
+ bad;
+
+ /* get enough for string, plus values -- use up commas */
++#ifdef NX_TRANS_SOCKET
++ len = strlen(_NXGetFontPath(path)) + 1;
++#else
+ len = strlen(path) + 1;
++#endif
+ nump = cp = newpath = (unsigned char *) ALLOCATE_LOCAL(len);
+ if (!newpath)
+ return BadAlloc;
++#ifdef NX_TRANS_SOCKET
++ pp = (unsigned char *) _NXGetFontPath(path);
++#else
+ pp = (unsigned char *) path;
++#endif
+ cp++;
+ while (*pp) {
+ if (*pp == ',') {
diff --git a/doc/nx-X11_vs_XOrg69_patches/dixstruct.h.NX.patch b/doc/nx-X11_vs_XOrg69_patches/dixstruct.h.NX.patch
new file mode 100644
index 000000000..f4bffa980
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/dixstruct.h.NX.patch
@@ -0,0 +1,12 @@
+--- ./nx-X11/programs/Xserver/include/dixstruct.h.X.original 2015-02-13 14:03:44.780440803 +0100
++++ ./nx-X11/programs/Xserver/include/dixstruct.h 2015-02-10 19:13:14.300667345 +0100
+@@ -170,6 +170,9 @@
+ extern Bool SmartScheduleIdle;
+ extern Bool SmartScheduleTimerStopped;
+ extern Bool SmartScheduleStartTimer(void);
++#ifdef NXAGENT_SERVER
++extern Bool SmartScheduleStopTimer(void);
++#endif
+ #define SMART_MAX_PRIORITY (20)
+ #define SMART_MIN_PRIORITY (-20)
+
diff --git a/doc/nx-X11_vs_XOrg69_patches/encparse.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/encparse.c.NX.patch
new file mode 100644
index 000000000..116badc07
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/encparse.c.NX.patch
@@ -0,0 +1,22 @@
+--- ./nx-X11/lib/font/fontfile/encparse.c.X.original 2015-02-13 14:03:44.668443005 +0100
++++ ./nx-X11/lib/font/fontfile/encparse.c 2015-02-10 19:13:12.336740907 +0100
+@@ -867,8 +867,10 @@
+ if(!strcasecmp(encoding_name, charset)) {
+ /* Found it */
+ if(file_name[0] != '/') {
+- if(strlen(dir) + strlen(file_name) >= MAXFONTFILENAMELEN)
++ if(strlen(dir) + strlen(file_name) >= MAXFONTFILENAMELEN) {
++ fclose(file);
+ return NULL;
++ }
+ strcpy(buf, dir);
+ strcat(buf, file_name);
+ } else {
+@@ -877,6 +879,7 @@
+
+ f = FontFileOpen(buf);
+ if(f == NULL) {
++ fclose(file);
+ return NULL;
+ }
+ encoding = parseEncodingFile(f, 0);
diff --git a/doc/nx-X11_vs_XOrg69_patches/fbtrap.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/fbtrap.c.NX.patch
new file mode 100644
index 000000000..343526131
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/fbtrap.c.NX.patch
@@ -0,0 +1,12 @@
+--- ./nx-X11/programs/Xserver/fb/fbtrap.c.X.original 2015-02-13 14:03:44.704442298 +0100
++++ ./nx-X11/programs/Xserver/fb/fbtrap.c 2015-02-10 19:13:14.156672722 +0100
+@@ -115,6 +115,9 @@
+ RenderEdge l, r;
+ xFixed t, b;
+
++ if (!xTrapezoidValid (trap))
++ return;
++
+ fbGetDrawable (pPicture->pDrawable, buf, stride, bpp, pxoff, pyoff);
+
+ width = pPicture->pDrawable->width;
diff --git a/doc/nx-X11_vs_XOrg69_patches/glcontextmodes.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/glcontextmodes.c.NX.patch
new file mode 100644
index 000000000..47db91cca
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/glcontextmodes.c.NX.patch
@@ -0,0 +1,10 @@
+--- ./nx-X11/extras/Mesa/src/mesa/drivers/dri/common/glcontextmodes.c.X.original 2015-02-13 14:03:44.416447966 +0100
++++ ./nx-X11/extras/Mesa/src/mesa/drivers/dri/common/glcontextmodes.c 2015-02-10 19:13:14.992641502 +0100
+@@ -44,6 +44,7 @@
+ # include "GL/glxint.h"
+
+ # ifdef XFree86Server
++void *memset( void * ptr, int val, size_t size);
+ # include "GL/glx_ansic.h"
+ extern void * __glXMalloc( size_t size );
+ extern void __glXFree( void * ptr );
diff --git a/doc/nx-X11_vs_XOrg69_patches/host.def.NX.patch b/doc/nx-X11_vs_XOrg69_patches/host.def.NX.patch
new file mode 100644
index 000000000..f3454e760
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/host.def.NX.patch
@@ -0,0 +1,1023 @@
+--- ./nx-X11/config/cf/host.def.X.original 2015-02-13 14:03:44.400448260 +0100
++++ ./nx-X11/config/cf/host.def 2015-02-13 14:03:44.400448260 +0100
+@@ -0,0 +1,1020 @@
++XCOMM $XFree86: xc/config/cf/xf86site.def,v 3.186 2003/06/25 18:06:22 eich Exp $
++/******************************************************************************/
++/*
++ * This file is to provide a quick method for most people to change the
++ * behaviour of their Xorg installation without having to fully
++ * understand the workings of site.def and all the various '.cf' files.
++ *
++ * In the vast majority of cases, it should not be necessary to use this
++ * file at all or change it in any way.
++ *
++ * This file is divided into two sections. The first contains settings
++ * that end-users might reasonably change. The second contains settings
++ * that developers might want to change.
++ *
++ * IMPORTANT NOTE: In all cases changing the defaults may cause problems
++ * and/or unexpected side-effects. If you don't understand what a setting
++ * does, then it's best to not change it. If you make changes and have
++ * problems, verify that those problems are also present when using an
++ * empty host.def file and unchanged version of this file before reporting
++ * them.
++ *
++ * A good way to use this file is to copy it to host.def, and make the
++ * changes there. That way, future patches to this file won't fail.
++ * The host.def file will never be patched.
++ *
++ * The distributed version of this file MUST contain no uncommented
++ * definitions. Default definitions belong in xorg.cf, or <vendor>.cf
++ * files.
++ */
++/******************************************************************************/
++
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NX-X11, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
++#if !defined(NXZaurusXServer) && !defined(NXiPAQXServer) && !defined(DarwinArchitecture)
++
++#if defined(SunArchitecture)
++#define ProjectRoot /usr/openwin
++#endif
++
++/*
++ * Enable use the Cygwin IPC libraries to get MIT-SHM support.
++ */
++#if defined(cygwinArchitecture)
++#define UseCygIPC YES
++#endif
++
++/*
++ * If you have build-specific modifications in your host.def file, but
++ * want an empty host.def file installed when doing 'make install',
++ * uncomment the following
++ *
++#define InstallEmptyHostDef
++ */
++
++/*
++ * Which servers to build. There is only Xorg server.
++ * It can be disabled by the following.
++ *
++#define XorgServer NO
++ */
++#define XorgServer NO
++
++/*
++ * To disable building the Xnest server, uncomment this.
++ *
++#define XnestServer NO
++ */
++#define XnestServer NO
++
++/*
++ * To disable building Xvfb, uncomment this.
++ *
++#define XVirtualFramebufferServer NO
++ */
++#define XVirtualFramebufferServer NO
++
++/*
++ * To enable building Xdmx, uncomment this.
++ *
++#define XdmxServer YES
++ */
++#define XdmxServer NO
++
++/*
++ * To disable building Xprt, uncomment this.
++ *
++#define XprtServer NO
++ */
++#define XprtServer NO
++
++/*
++ * Xprint is needed by Xprt. You can disable it if
++ * you are not going to build Xprt.
++ *
++#define BuildXprint NO
++ */
++#define BuildXprint NO
++
++/*
++ * Building libraries with NX enhancements is disabled
++ * by default. You should enable this in your host.def.
++ *
++#define NXLibraries YES
++ */
++#define NXLibraries YES
++
++/*
++ * Building the NX agent nested server is disabled
++ * by default. Enable this in your host.def.
++ *
++#define NXAgentServer YES
++ */
++#define NXAgentServer YES
++
++/*
++ * Assume the new build tree.
++ *
++#define NXUpgradeAgentServer NO
++ */
++#define NXUpgradeAgentServer YES
++
++#ifdef NXAgentServer
++#define BuildRenderLibrary YES
++#define SharedLibFreetype2 YES
++#define NormalLibFreetype2 YES
++#define FontLibSharedFreeType NO
++#endif
++
++/*
++ * Define this symbol to build the NX enhanced MS Windows
++ * X server for Cygnus environment.
++ *
++#define NXWinServer YES
++ */
++#if defined(cygwinArchitecture)
++#define NXWinServer NO
++#define XWinServer NO
++#endif
++
++/*
++ * Set the default server (ie the one that gets the sym-link to "X")
++ *
++#define ServerToInstall Xorg
++ */
++
++/*
++ * Force build of X libraries if any nested server is to be built.
++ *
++#define BuildLibraries YES
++ *
++ * If you just want libraries for NXAgentServer, this should be
++ * enough (never tested, although).
++ *
++#define BuildLibrariesForXServers YES
++ */
++#if XnestServer || NXAgentServer
++#define BuildLibraries YES
++#endif
++
++#define BuildDamageLibrary YES
++
++#define BuildXfixesLibrary YES
++
++#define BuildCompositeLibrary YES
++
++#define BuildRandRLibrary YES
++
++#define BuildDocs NO
++
++#define BuildComposite YES
++
++/*
++ * If you only run the X server under xdm the X servers don't need to be
++ * installed SetUID, and you may comment out the lines below. If you run
++ * the servers by hand (with xinit or startx), then they do need to be
++ * installed SetUID on most platforms.
++ *
++ * Consult your system administrator before making the X server setuid.
++ *
++#define InstallXserverSetUID NO
++ */
++
++
++/*
++ * Server configuration parameters. The defaults are shown here:
++ */
++
++/*
++ * Which drivers to build. When building a static server, each of these
++ * will be included in it. When building the loadable server each of these
++ * modules will be built.
++ *
++#define XF86CardDrivers mga glint nv tga s3virge sis rendition \
++ neomagic i740 tdfx savage \
++ cirrus vmware tseng trident chips apm \
++ GlideDriver fbdev i128 \
++ ati DevelDrivers ark cyrix \
++ siliconmotion \
++ vesa vga XF86OSCardDrivers XF86ExtraCardDrivers
++ */
++
++/*
++ * To add third party drivers to the standard driver list, set the
++ * following.
++ *
++#define XF86ExtraCardDrivers extradriver1 extradriver2 ...
++ */
++
++/*
++ * Select the XInput devices you want by uncommenting this.
++ *
++#define XInputDrivers mouse keyboard acecad calcomp citron \
++ digitaledge dmc dynapro elographics \
++ microtouch mutouch penmount spaceorb summa \
++ wacom void magictouch aiptek
++ */
++
++/* To enable building of development DRI drivers (insecure, or not
++ * useful on the chosen architecture, uncomment this define.
++#define BuildDevelDRIDrivers YES
++ */
++
++/*
++ * To use the deprecated, old keyboard driver, uncomment this. But
++ * even better, make the new keyboard driver (hw/xfree86/input/keyboard)
++ * work for your architechture. The old driver will be removed in the
++ * next release.
++ *
++#define UseDeprecatedKeyboardDriver YES
++ */
++
++/*
++ * There are three parameters that determine where and how the Matrox HAL
++ * library is used:
++ *
++ * HaveMatroxHal -- You have the HALlib.a binary library installed
++ * in xfree86/drivers/mga/HALlib, and you want it to
++ * be used.
++ * Default: NO
++ *
++ * BuildMatroxHal -- You have the source for the HALlib library (installed
++ * in xfree86/drivers/mga/hallib), and want to build and
++ * use it.
++ * Default: NO
++ *
++ * UseMatroxHal -- You want to build support for loading/using the HAL
++ * library into the mga driver. For module server builds
++ * you don't need to have the HALlib library to do this.
++ * but you want to build support for loading it and using
++ * it into the mga driver module.
++ * Default: YES for loadable server build
++ * (HaveMatroxHal || BuildMatroxHal) for static
++ */
++
++/*
++ * To disable use of the Matrox HAL library, uncomment this:
++ *
++#define UseMatroxHal NO
++ */
++
++/*
++ * If you have the HALlib.a binary installed in xfree86/drivers/mga/HALlib,
++ * uncomment this:
++ *
++#define HaveMatroxHal YES
++ */
++
++/*
++ * If you have the HALlib source code installed in xfree86/drivers/mga/hallib,
++ * uncomment this:
++#define BuildMatroxHal YES
++ */
++
++/*
++ * To disable building the font server, uncomment this.
++ *
++#define BuildFontServer NO
++ */
++#define BuildFontServer NO
++
++/*
++ * Speedo fonts have been disabled by default in this release.
++ * To re-enable support for Speedo fonts, uncomment this.
++ *
++#define BuildSpeedo YES
++ */
++
++/*
++ * To disable support for CID fonts, uncomment this.
++ *
++#define BuildCID NO
++ */
++
++/*
++ * To disable support for TrueType fonts, uncomment these.
++ *
++#define BuildFreeType NO
++ */
++
++/*
++ * To set non-default build options for the underlying FreeType libraries,
++ * add them here and uncomment.
++ *
++#define Freetype2BuildDefines -DFREETYPE_BUILD_DEFINES
++ */
++
++/*
++ * To build the FreeType libraries with the TrueType byte code interpreter
++ * enabled, uncomment this. Note that there are patent issues related to the
++ * TrueType byte code interpreter, and we only recommend you enabling this
++ * if you are sure that there are no legal impediments to you doing so. See
++ * <http://www.freetype.org/patents.html> for further information.
++ *
++#define Freetype2BuildDefines -DTT_CONFIG_OPTION_BYTECODE_INTERPRETER
++ */
++
++/*
++ * Do you want to Build Fonts (Usually you only want to build and install
++ * fonts once, if this is a first time install you will want to build the
++ * fonts)
++ *
++#define BuildFonts NO
++ */
++#define BuildFonts NO
++
++/*
++ * To not build/install the 75dpi fonts, uncomment the following
++ *
++#define Build75DpiFonts NO
++ */
++
++/*
++ * To not build/install the 100dpi fonts, uncomment the following
++ *
++#define Build100DpiFonts NO
++ */
++
++/*
++ * To build/install the Speedo fonts, uncomment the following
++ * (see setting above about Speedo support as well)
++ *
++#define BuildSpeedoFonts YES
++ */
++
++/*
++ * To not build/install the Type1 fonts, uncomment the following
++ *
++#define BuildType1Fonts NO
++ */
++
++/*
++ * To not build/install the CID fonts, uncomment the following
++ *
++#define BuildCIDFonts NO
++ */
++
++/*
++ * To not build/install the True Type fonts, uncomment the following
++ *
++#define BuildTrueTypeFonts NO
++ */
++
++/*
++ * To not build/install the Cyrillic fonts, uncomment the following
++ *
++#define BuildCyrillicFonts NO
++ */
++
++/*
++ * To not install the local font directory, uncomment the following
++ *
++#define MakeLocalFontDir NO
++ */
++
++/*
++ * Include True Type Fonts to default font path. It is safe to do
++ * this by default as NX intaller carries only misc and TTF in the
++ * basic set of fonts installed under Windows.
++ *
++#define DefaultFontPath $(FONTDIR)/misc/,$(FONTDIR)/Speedo/,$(FONTDIR)/Type1/,$(FONTDIR)/75dpi/,$(FONTDIR)/100dpi/
++ */
++
++#if defined(LinuxArchitecture) || defined(SunArchitecture) || defined(FreeBSDArchitecture)
++#define DefaultFontPath $(FONTDIR)/misc/,$(FONTDIR)/Speedo/,$(FONTDIR)/Type1/,$(FONTDIR)/75dpi/,$(FONTDIR)/100dpi/,$(FONTDIR)/TTF/
++#endif /* #if defined(LinuxArchitecture) || defined(SunArchitecture) */
++
++#if defined(cygwinArchitecture)
++#define DefaultFontPath /mnt/NX/fonts/base/,/mnt/NX/fonts/misc/,/mnt/NX/fonts/Speedo/,/mnt/NX/fonts/Type1/,/mnt/NX/fonts/75dpi/,/mnt/NX/fonts/100dpi/,/mnt/NX/fonts/TTF/
++#define DefaultRGBDatabase /mnt/NX/fonts/rgb
++#endif /* #if defined(cygwinArchitecture) */
++
++/*
++ * To build only the servers with a cut-down source tree, uncomment
++ * this.
++ *
++#define BuildServersOnly YES
++ */
++#define BuildServersOnly YES
++
++/*
++ * By default, the sample config files for xinit, xdm and xfs are installed
++ * only when there is no pre-existing version installed. Uncommenting the
++ * following lines will force the sample versions to be installed even if
++ * it means over-writing existing versions.
++ *
++#define InstallXinitConfig YES
++#define InstallXdmConfig YES
++#define InstallFSConfig YES
++ */
++
++/*
++ * By default the application defaults files are always installed.
++ * Uncommenting the the following will prevent exising application
++ * defaults files from being over-written.
++ *
++#define InstallAppDefFiles NO
++ */
++
++/*
++ * Undefine the following if you don't want to have config files and
++ * app-defaults installed in a separate directory (i.e. /etc/X11).
++ *
++#define UseSeparateConfDir NO
++ */
++
++/*
++ * To enable building the glide driver, you need to define
++ * HasGlide2 to YES and set the Glide2IncDir variable.
++ * HasGlide2 is per default NO.
++ *
++#define HasGlide2 YES
++ */
++
++/*
++ * Set the path to your Glide include files.
++ *
++#define Glide2IncDir /usr/include/glide
++ */
++
++/*
++ * Have glide 3?
++ *
++#define HasGlide3 YES
++ */
++
++/*
++ * Set the path to your Glide 3 include files.
++ *
++#define Glide3IncDir /usr/include/glide3
++ */
++
++
++
++/*
++ * Unless you're a developer you shouldn't need to change anything
++ * beyond this point.
++ */
++
++/*
++ * If you want to enable some developer settings, like more verbose
++ * compiler warnings, uncomment this.
++ *
++#define XFree86Devel YES
++*/
++
++/*
++ * If using GCC 2.x on a system where it isn't the default, uncomment
++ * the following
++ *
++ */
++#if defined(SunArchitecture)
++#define HasGcc2 YES
++#define HasGcc YES
++#endif
++
++/*
++ * The default optimisation flags for GCC 2.x. -fno-strength-reduce is
++ * here to work around a bug in -O2 for GCC 2.x on i386 platforms.
++ * If you are using a version that doesn't have this bug, you can
++ * uncomment the following line, and remove '-fno-strength-reduce'
++ * If you are building binaries for a 486, it may be beneficial to add
++ * -m486
++ *
++#define DefaultGcc2i386Opt -O2 -fno-strength-reduce
++ */
++
++#if defined (LinuxArchitecture)
++#define DefaultGcc2i386Opt -g -O3
++#endif
++
++/*
++ * Enable all the optimizations on AMD64.
++ */
++
++#define DefaultGcc2AMD64Opt -g -O3 GccAliasingArgs
++
++/*
++ * This allows the GCC warning flags to be set. The default is shown here.
++ *
++#define GccWarningOptions -Wall -Wpointer-arith -Wstrict-prototypes \
++ -Wmissing-prototypes -Wmissing-declarations \
++ -Wredundant-decls -Wnested-externs
++ */
++
++/*
++ * Sun Compiler stuff..
++ *
++#define HasSunC YES
++#define HasSunCplusplus YES
++#define CplusplusCompilerMajorVersion 5
++#define CplusplusCompilerMinorVersion 0
++#define CCompilerMajorVersion 5
++#define CCompilerMinorVersion 0
++ */
++
++/*
++ * Optimized Sun Compiler Build.
++ *
++#define DefaultCDebugFlags -xO4 -xtarget=pentium_pro
++#define OptimizedCDebugFlags -xO4 -xtarget=pentium_pro
++ */
++
++/*
++ * Debuggable Sun Compiler Build.
++ * Note: This builds _EVERYTHING_ as debuggable
++ *
++#define DefaultCDebugFlags -g -xs
++#define OptimizedCDebugFlags -g -xs
++ */
++
++/*
++ * For Linux, this should match the Binutils version you have. This example
++ * is for 2.6.0.7. See linux.cf for the default setting.
++ *
++ * This should automatically get set correctly by imake.
++ *
++#define LinuxBinUtilsMajorVersion 26
++ */
++
++/*
++ * For Linux, these should match the libc version you have. This example
++ * is for libc.5.4.x. See linux.cf for the default setting.
++ *
++ * This should automatically get set correctly by imake.
++ *
++#define LinuxCLibMajorVersion 5
++#define LinuxClibMinorVersion 4
++ */
++
++/*
++ * If you want to use the GNU malloc library, uncomment this
++ *
++#define UseGnuMalloc YES
++ */
++
++/*
++ * Set this to whatever is required to access the GNU malloc library.
++ * The default is '-lgmalloc' unless is specified in the OS's .cf file.
++ *
++#define GnuMallocLibrary -L/usr/local/lib -lgmalloc
++ */
++
++/*
++ * To enable the internal Xserver malloc, uncomment this
++ *
++#define UseInternalMalloc YES
++ */
++
++/*
++ * Some Linux releases don't have a libtermcap. In this case you may need
++ * to uncomment the following
++ *
++#define TermcapLibrary -lncurses
++ */
++
++/*
++ * Build a server that dynamically loads the modules by setting
++ * this to YES. This defaults to YES on most platforms. A static server
++ * can be built by setting this to NO.
++ *
++#define DoLoadableServer NO
++ */
++
++/*
++ * This release defaults to building dlopen() style modules instead of the
++ * previously standard loader modules.
++ *
++ * Uncomment the following to return to the XFree86 custom loader modules.
++ *
++#define MakeDllModules NO
++ */
++
++/*
++ * Build XAA. This can be disabled with:
++ *
++#define XF86XAA NO
++ */
++
++/*
++ * Build vgahw. This can be disabled with:
++ *
++#define XF86VgaHw NO
++ */
++
++/*
++ * Build xf1bpp. This can be disabled with:
++ *
++#define XF1Bpp NO
++ */
++
++/*
++ * Build xf4bpp. This can be disabled with:
++ *
++#define XF4Bpp NO
++ */
++
++
++/*
++ * BSD Console driver support (for FreeBSD and NetBSD).
++ *
++ * By default, support is included for pccons and pcvt for NetBSD, and
++ * pccons, syscons and pcvt for FreeBSD.
++ *
++ * To change the list of supported drivers, set the following parameter.
++ * Possible values are -DPCCONS_SUPPORT, -DSYSCONS_SUPPORT, -DPCVT_SUPPORT.
++ * The following example includes support for syscons and pcvt only.
++ *
++#define XFree86ConsoleDefines -DSYSCONS_SUPPORT -DPCVT_SUPPORT
++ */
++
++/*
++ * To link the X server with a dynamic version of the Xfont library,
++ * uncomment this.
++ *
++#define XserverStaticFontLib NO
++ */
++
++/*
++ * To enable binary compatibility with previous versions of the font
++ * encoding support, uncomment this.
++ *
++#define FontencCompatibility YES
++ */
++
++/*
++ * To disable building XInput support, uncomment this
++ *
++#define BuildXInputExt NO
++ */
++#if defined(SunArchitecture)
++#define BuildXInputExt YES
++#endif
++
++/*
++ * Uncomment this for joystick support.
++ *
++ * Note: Joystick support is broken, so don't enable this.
++ *
++#define JoystickSupport YES
++ */
++
++/*
++ * To disable the ScreenSaver Extension, uncomment this line.
++ *
++#define BuildScreenSaverExt NO
++ */
++#define BuildScreenSaverExt NO
++
++/*
++ * If you don't want to build Xinerama support, uncomment this.
++ *
++#define BuildXinerama NO
++ */
++#define BuildXinerama NO
++
++/*
++ * If you don't want to build support for the GLX extension, uncomment this.
++ *
++#define BuildGlxExt NO
++ */
++#define BuildGlxExt YES
++
++/*
++ * Taken from xorg.cf.
++ */
++
++#if defined(SparcArchitecture) \
++ || defined (Sparc64Architecture) \
++ || defined(ia64Architecture) \
++ || defined(s390xArchitecture) \
++ || defined(AMD64Architecture)
++#define GlxExtraDefines -D__GLX_ALIGN64
++#endif
++
++/*
++ * If you want to build the xf86rush extension, uncomment this line.
++ * This isn't recommended.
++ *
++#define BuildXF86RushExt YES
++ */
++#define BuildXF86RushExt NO
++
++/*
++ * If you want to build the client library for the xf86rush extension,
++ * uncomment this line. This isn't recommended.
++ *
++#define BuildXF86RushLibrary NO
++ */
++#define BuildXF86RushLibrary NO
++
++/*
++ * We should never need LBX in a NX enabled environment...
++ *
++#define BuildLBX NO
++ */
++#define BuildLBX NO
++
++#define BuildXKB YES
++#define BuildXKBlib YES
++
++#define SharedLibXau NO
++
++/*
++ * If you are running NetBSD 0.9C or later, and have the aperture driver
++ * installed, uncomment this.
++ *
++#define HasNetBSDApertureDriver YES
++ */
++
++/*
++ * If you are running SVR3 and have the mmap driver installed (for linear
++ * framebuffer access) uncomment this.
++ *
++#define HasSVR3mmapDrv YES
++ */
++
++/*
++ * If you are using an SVR3 (like ISC 4.x) which supports long file names,
++ * you can uncomment this to have manual pages installed under their
++ * full names
++ *
++#define ExpandManNames YES
++ */
++
++/*
++ * For a POSIXized build on Interactive uncomment this
++ * Could be used with gcc 'till Version 2.6.3
++ * Should be used with gcc 2.7.2.
++ *
++#define UsePosix YES
++ */
++
++/*
++ * If you don't want XDMAUTH support (if you don't have Wraphelp.c),
++ * comment this out.
++ *
++ */
++#if defined(LinuxArchitecture)
++#define HasXdmAuth YES
++#endif /* #if defined(LinuxArchitecture) */
++
++/*
++ * If you have Linux DECnet support, and want to build XFree86 with support
++ * for connections over DECnet, uncomment this.
++ *
++#define HasDECnet YES
++ */
++
++/*
++ * To build static and shared libraries with debugging information, uncomment
++ * this. Assumes you have Gcc2.
++ * (If you don't have Gcc2, you can use the DebugLib{X11,Xt,Xaw,...} variables
++ * to build debugging versions of the libraries separately.)
++ *
++#define DebuggableLibraries YES
++*/
++#if defined(LinuxArchitecture)
++#define DebuggableLibraries YES
++#endif /* #if defined(LinuxArchitecture) */
++/*
++ * To forceably build static libraries in addition to shared libraries,
++ * uncomment this.
++ *
++#define ForceNormalLib YES
++ */
++
++/*
++ * Uncomment this if your default tools (eg, gcc, ld, as, etc) are
++ * not the Linux ELF versions.
++ *
++#define LinuxElfDefault NO
++ */
++
++/*
++ * To use ELF format shared libraries for supported OSs, uncomment this.
++ *
++ * For Linux the default setting of this is the same as the setting of
++ * LinuxElfDefault.
++ *
++ * For FreeBSD this should automatically be set correctly by imake. Only
++ * change it here if you need to override the automatic setting.
++ *
++#define UseElfFormat YES
++ */
++
++/*
++ * For FreeBSD/ELF (FreeBSD 3.0) it is possible to also build and install
++ * a.out compatibility libraries. To enable that, uncomment this.
++ *
++#define BuildAoutLibraries YES
++ */
++
++/*
++ * If you have trouble with make bombing out in Xlib, try uncommenting this.
++ * You will not get dependencies as a result, but better than nothing.
++ *
++#define MakeHashTableBug YES
++ */
++
++/*
++ * If you do not want your man pages compress under SVR3 systems that
++ * support it, uncomment this.
++ *
++#define CompressManPages NO
++ */
++
++/*
++ * If you have sgmlfmt (the XFree86 doctools package) and want to build
++ * formatted docs from the SGML source, uncomment this.
++ *
++#define HasSgmlFmt YES
++ */
++
++/*
++ * To disable building some document formats, uncomment some of these.
++ *
++#define BuildLinuxDocText NO
++#define BuildLinuxDocHtml NO
++#define BuildLinuxDocPS NO
++ */
++
++/*
++ * To install Japanese versions of the documentation uncomment this.
++ * Note: The Japanese documentation consists of a subset of the
++ * XFree86 3.1 docs.
++ *
++#define InstallJapaneseDocs YES
++ */
++
++/*
++ * To build/install X specs docs, uncomment the following.
++ * The SpecsDocDirs setting here is recommended because it covers
++ * the docs that XFree86 has changed or added.
++ *
++#define BuildSpecsDocs YES
++#define SpecsDocDirs CTEXT GL ICCCM X11 Xext Xmu Xv XvMC i18n
++ */
++
++/*
++ * To build all specs docs, not just those listed in SpecsDocDirs, uncomment
++ * the following.
++ *
++#define BuildAllSpecsDocs YES
++ */
++
++/*
++ * If your system doesn't support vm86() mode and you have
++ * libx86emu set library path here
++ *
++#define X86EMU_LIBPATH /usr/local/lib
++ */
++
++/*
++ * Most platforms default to using an already installed FreeType 2 library.
++ * To use the one included in this release instead, uncomment the following.
++ *
++#define HasFreetype2 NO
++ */
++#define HasFreetype2 NO
++
++/*
++ * To use a FreeType library already installed outside the default search
++ * paths, uncomment the following and set the path as needed.
++ *
++#define HasFreetype2 YES
++#define Freetype2Dir /usr/local
++ */
++
++
++/*
++ * Most platforms default to using an already installed Fontconfig library.
++ * To use the one included in this release instead, uncomment the following.
++ *
++#define HasFontconfig NO
++ */
++#define HasFontconfig NO
++
++/*
++ * To use a Fontconfig library already installed outside the default search
++ * paths, uncomment the following and set the path as needed.
++#define HasFontconfig YES
++#define FontconfigDir /usr/local
++ */
++
++
++/*
++ * Most platforms default to using an already installed Expat library.
++ * To use the one included in this release instead, uncomment the following.
++ *
++#define HasExpat NO
++ */
++#define HasExpat NO
++
++/*
++ * To use a Expat library already installed outside the default search
++ * paths, uncomment the following and set the path as needed.
++#define HasExpat YES
++#define ExpatDir /usr/local
++ */
++
++
++/*
++ * Most platforms default to using an already installed PNG library.
++ * To use the one included in this release instead, uncomment the following.
++ *
++#define HasLibpng NO
++ */
++
++/*
++ * To use a PNG library already installed outside the default search
++ * paths, uncomment the following and set the path as needed.
++#define HasLibpng YES
++#define LibpngDir /usr/local
++ */
++
++
++/*
++ * Most platforms default to using an already installed xterm program.
++ * To use the one included in this release instead, uncomment the following.
++ *
++#define BuildXterm YES
++ */
++
++#define SharedLibXau NO
++
++#define SharedLibXdmcp NO
++
++#define BuildXaw7 YES
++
++#else /* #if !defined(NXZaurusXServer) && !defined(NXiPAQXServer) && !defined(DarwinArchitecture) */
++
++#if defined(DarwinArchitecture) && !defined(NXZaurusXServer) && !defined(NXiPAQXServer)
++#define NXDarwinServer NO
++#define BuildServersOnly YES
++#define DefaultFontPath /usr/NX/share/fonts/misc/,/usr/NX/share/fonts/TTF/
++#define DefaultRGBDatabase /usr/NX/share/rgb
++#define XprtServer NO
++#define BuildXprint NO
++#define XnestServer NO
++#define XVirtualFramebufferServer NO
++#define BuildFontServer NO
++#define BuildFreeType NO
++#define BuildXTrueType NO
++#define FontLibSharedFreeType NO
++#endif
++
++#if !defined(NXZaurusXServer) && defined(NXiPAQXServer)
++#define KDriveXServer YES
++#define XiPAQH3500Server YES
++#define BuildServersOnly YES
++#define NXEmbeddedXServer YES
++#define KdriveServerExtraDefines -DITSY -DMAXSCREENS=1
++#define TinyXServer YES
++#define CrossCompiling YES
++#define TouchScreen YES
++#define ItsyCompilerBug YES
++#undef BuildRandR
++#define BuildRandR YES
++#define BuildXInputLib YES
++#define BuildXTrueType YES
++#define ServerXdmcpDefines
++#define XipaqServer YES
++#endif
++
++#if !defined(NXiPAQXServer) && defined(NXZaurusXServer)
++#define KDriveXServer YES
++#define XiPAQH3500Server YES
++#define BuildServersOnly YES
++#define ZaurusXServer YES
++#define NXEmbeddedXServer YES
++#define KdriveServerExtraDefines -DITSY -DMAXSCREENS=1
++#define TinyXServer YES
++#define CrossCompiling YES
++#define TouchScreen YES
++#define ItsyCompilerBug YES
++#undef BuildRandR
++#define BuildRandR YES
++#define BuildXInputLib YES
++#define BuildXTrueType YES
++#define ServerXdmcpDefines
++#define XipaqServer YES
++#define XfbdevServer YES
++#endif
++
++#endif /* #if !defined(NXZaurusXServer) && !defined(NXiPAQXServer) && !defined(DarwinArchitecture) */
diff --git a/doc/nx-X11_vs_XOrg69_patches/iPAQH3600.cf.NX.patch b/doc/nx-X11_vs_XOrg69_patches/iPAQH3600.cf.NX.patch
new file mode 100644
index 000000000..ab93486c4
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/iPAQH3600.cf.NX.patch
@@ -0,0 +1,112 @@
+--- ./nx-X11/config/cf/iPAQH3600.cf.X.original 2015-02-13 14:03:44.400448260 +0100
++++ ./nx-X11/config/cf/iPAQH3600.cf 2015-02-13 14:03:44.400448260 +0100
+@@ -0,0 +1,109 @@
++/* $XFree86: xc/config/cf/iPAQH3600.cf,v 1.2 2000/10/10 14:05:48 tsi Exp $ */
++/*
++ * This configuration file contains additional configuration needed
++ * to cross compile X for the Compaq iPAQ H3600 PocketPC.
++ * To use this, add the following to host.def:
++ #define KDriveXServer YES
++ #define XiPAQH3500Server YES
++ */
++
++#define CrossCompiling YES
++
++#undef i386Architecture
++#define Arm32Architecture
++
++#undef OptimizedCDebugFlags
++#define OptimizedCDebugFlags -O2
++#define ServerCDebugFlags -O2
++#undef StandardDefines
++#define StandardDefines -Dlinux -D__arm__ -D_POSIX_SOURCE \
++ -D_BSD_SOURCE -D_GNU_SOURCE -DX_LOCALE
++#undef CcCmd
++#define StdIncDir /opt/Embedix/tools/arm-linux/include
++#define PreIncDir
++#undef PostIncDir
++#define PostIncDir /opt/Embedix/tools/lib/gcc-lib/arm-linux/2.95.2/include
++#define CcCmd /opt/Embedix/tools/bin/arm-linux-gcc
++#define DoRanlibCmd YES
++#define RanlibCmd /opt/Embedix/tools/bin/arm-linux-ranlib
++#undef ExtraLoadFlags
++#define ExtraLoadFlags
++#define FbNoPixelAddrCode
++#undef TermcapLibrary
++#define TermcapLibrary -ltermcap
++
++#undef LdPostLib
++#define LdPostLib -L/opt/Embedix/tools/arm-linux/lib
++
++#undef XfbdevServer
++#define XfbdevServer YES
++#undef BuildXprint
++#define BuildLBX NO
++#define BuildFonts NO
++#define BuildAppgroup NO
++#define BuildRECORD NO
++#define BuildDBE NO
++#define BuildXCSecurity NO
++#define ItsyCompilerBug YES
++#define FontServerAccess NO
++#define ServerXdmcpDefines /**/
++
++#undef ExtensionOSDefines
++#define ExtensionOSDefines
++
++#define ProjectRoot /usr/X11R6
++
++#define GzipFontCompression YES
++
++#define KdriveServerExtraDefines -DITSY -DMAXSCREENS=1
++
++#define HostLinkRule(target, flags, src, libs) cc -I$(BUILDINCDIR) -o target src
++
++/* ComplexHostProgramTarget - Compile a program such that we can run
++ * it on this host, i.e., don't use the default cross compiler.
++ */
++#ifndef ComplexHostProgramTarget
++#define ComplexHostProgramTarget(program) @@\
++ CC=cc @@\
++ STD_INCLUDES= @@\
++ CFLAGS=$(TOP_INCLUDES) $(INCLUDES) $(BOOTSTRAPCFLAGS) @@\
++EXTRA_LOAD_FLAGS= @@\
++ PROGRAM = program @@\
++ @@\
++AllTarget(program) @@\
++ @@\
++program: $(OBJS) $(DEPLIBS) @@\
++ RemoveTargetProgram($@) @@\
++ HostLinkRule($@,$(_NOOP_),$(OBJS),$(DEPLIBS) $(LOCAL_LIBRARIES)) @@\
++ @@\
++DependTarget() @@\
++ @@\
++LintTarget() @@\
++ @@\
++clean:: @@\
++ RemoveFile(ProgramTargetName(program))
++#endif /* ComplexHostProgramTarget */
++
++#ifndef SimpleHostProgramTarget
++#define SimpleHostProgramTarget(program) @@\
++ SRCS = program.c @@\
++ @@\
++ CC=cc @@\
++ STD_INCLUDES= @@\
++ CFLAGS=$(TOP_INCLUDES) $(INCLUDES) $(BOOTSTRAPCFLAGS) @@\
++EXTRA_LOAD_FLAGS= @@\
++ PROGRAM = program @@\
++ @@\
++AllTarget(program) @@\
++ @@\
++program: program.o $(DEPLIBS) @@\
++ RemoveTargetProgram($@) @@\
++ HostLinkRule($@,$(_NOOP_),program.o,$(DEPLIBS) $(LOCAL_LIBRARIES)) @@\
++ @@\
++DependTarget() @@\
++ @@\
++LintTarget() @@\
++ @@\
++clean:: @@\
++ RemoveFile(ProgramTargetName(program))
++#endif /* SimpleHostProgramTarget */
diff --git a/doc/nx-X11_vs_XOrg69_patches/log.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/log.c.NX.patch
new file mode 100644
index 000000000..44407e05a
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/log.c.NX.patch
@@ -0,0 +1,136 @@
+--- ./nx-X11/programs/Xserver/os/log.c.X.original 2015-02-13 14:03:44.788440645 +0100
++++ ./nx-X11/programs/Xserver/os/log.c 2015-02-13 14:03:44.788440645 +0100
+@@ -78,6 +78,23 @@
+
+ /* $XFree86: xc/programs/Xserver/os/log.c,v 1.6 2003/11/07 13:45:27 tsi Exp $ */
+
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NX-X11, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ #ifdef HAVE_DIX_CONFIG_H
+ #include <dix-config.h>
+ #endif
+@@ -98,9 +115,17 @@
+ #define getpid(x) _getpid(x)
+ #endif
+
++#ifdef NX_TRANS_SOCKET
++
++#include "NX.h"
++
++#endif
+
+ #ifdef DDXOSVERRORF
+ void (*OsVendorVErrorFProc)(const char *, va_list args) = NULL;
++#ifdef NX_TRANS_EXIT
++int OsVendorVErrorFFatal = 0;
++#endif
+ #endif
+
+ static FILE *logFile = NULL;
+@@ -265,6 +290,32 @@
+ */
+ if (verb < 0 || logFileVerbosity >= verb || logVerbosity >= verb) {
+ vsnprintf(tmpBuffer, sizeof(tmpBuffer), f, args);
++#ifdef NX_TRANS_EXIT
++ /*
++ * Beautify the message. Make the
++ * first letter uppercase.
++ */
++
++ *tmpBuffer = toupper(*tmpBuffer);
++
++ /*
++ * Remove the trailing newline.
++ */
++
++ if (strlen(tmpBuffer) > 0 &&
++ *(tmpBuffer + strlen(tmpBuffer) - 1) == '\n') {
++ *(tmpBuffer + strlen(tmpBuffer) - 1) = '\0';
++ }
++
++ /*
++ * Remove the trailing full-stop.
++ */
++
++ if (strlen(tmpBuffer) > 0 &&
++ *(tmpBuffer + strlen(tmpBuffer) - 1) == '.') {
++ *(tmpBuffer + strlen(tmpBuffer) - 1) = '\0';
++ }
++#endif /* #ifdef NX_TRANS_EXIT */
+ len = strlen(tmpBuffer);
+ }
+ if ((verb < 0 || logVerbosity >= verb) && len > 0)
+@@ -404,12 +455,22 @@
+ void
+ AbortServer(void)
+ {
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
++ fprintf(stderr, "AbortServer: Going to abort the current server.\n");
++#endif
+ OsCleanup(TRUE);
+ AbortDDX();
+ fflush(stderr);
+ if (CoreDump)
+ abort();
++#ifdef NX_TRANS_EXIT
++#ifdef NX_TRANS_TEST
++ fprintf(stderr, "AbortServer: Going to clean up NX resources and exit.\n");
++#endif
++ NXTransExit(1);
++#else /* #ifdef NX_TRANS_EXIT */
+ exit (1);
++#endif
+ }
+
+ #ifndef AUDIT_PREFIX
+@@ -533,6 +594,27 @@
+ va_list args;
+ static Bool beenhere = FALSE;
+
++#ifdef NX_TRANS_EXIT
++ if (beenhere) {
++ fprintf(stderr, "Error: Aborting session with fatal error function reentered.\n");
++ }
++ else {
++ /*
++ * Tell to the log function that this
++ * is a fatal error.
++ */
++
++ OsVendorVErrorFFatal = 1;
++
++ fprintf(stderr, "Error: Aborting session with '");
++
++ va_start(args, f);
++ VErrorF(f, args);
++ va_end(args);
++
++ fprintf(stderr, "'.\n");
++ }
++#else /* #ifdef NX_TRANS_EXIT */
+ if (beenhere)
+ ErrorF("\nFatalError re-entered, aborting\n");
+ else
+@@ -542,6 +624,7 @@
+ VErrorF(f, args);
+ va_end(args);
+ ErrorF("\n");
++#endif /* #ifdef NX_TRANS_EXIT */
+ #ifdef DDXOSFATALERROR
+ if (!beenhere)
+ OsVendorFatalError();
diff --git a/doc/nx-X11_vs_XOrg69_patches/main.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/main.c.NX.patch
new file mode 100644
index 000000000..2ee26838e
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/main.c.NX.patch
@@ -0,0 +1,42 @@
+--- ./nx-X11/programs/xterm/main.c.X.original 2015-02-13 14:03:44.804440330 +0100
++++ ./nx-X11/programs/xterm/main.c 2015-02-13 14:03:44.804440330 +0100
+@@ -91,8 +91,39 @@
+
+ ******************************************************************/
+
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NX-X11, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ /* $XFree86: xc/programs/xterm/main.c,v 3.199 2005/11/13 23:10:36 dickey Exp $ */
+
++#ifdef NX_TRANS_EXIT
++
++/*
++ * Redefine the libc exit() function to be
++ * sure we get rid of proxy and detect any
++ * abnormal termination.
++ */
++
++extern void NXTransExit(int code) __attribute__((noreturn));
++
++#define exit(code) NXTransExit(code)
++
++#endif /* #ifdef NX_TRANS_EXIT */
++
+ /* main.c */
+
+ #define RES_OFFSET(field) XtOffsetOf(XTERM_RESOURCE, field)
diff --git a/doc/nx-X11_vs_XOrg69_patches/oscolor.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/oscolor.c.NX.patch
new file mode 100644
index 000000000..88acc878a
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/oscolor.c.NX.patch
@@ -0,0 +1,214 @@
+--- ./nx-X11/programs/Xserver/os/oscolor.c.X.original 2015-02-13 14:03:44.788440645 +0100
++++ ./nx-X11/programs/Xserver/os/oscolor.c 2015-02-13 14:03:44.788440645 +0100
+@@ -47,6 +47,17 @@
+ ******************************************************************/
+ /* $Xorg: oscolor.c,v 1.4 2001/02/09 02:05:23 xorgcvs Exp $ */
+
++#ifdef NX_TRANS_SOCKET
++
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <unistd.h>
++
++static char* nxAltRgbPaths[] = {"/usr/NX/share/rgb", "/usr/share/X11/rgb", "/etc/X11/rgb"};
++static char _NXRgbPath[1024];
++
++#endif
++
+ #ifdef HAVE_DIX_CONFIG_H
+ #include <dix-config.h>
+ #endif
+@@ -174,6 +185,154 @@
+
+ static dbEntryPtr hashTab[HASHSIZE];
+
++#ifdef NX_TRANS_SOCKET
++
++static int NXVerifyRgbPath(char *path)
++{
++ int size;
++ char *rgbPath;
++ struct stat rgbFileStat;
++
++ /*
++ * Check if rgb file is present.
++ */
++
++ size = strlen(path) + strlen(".txt") + 1;
++
++ rgbPath = (char *) ALLOCATE_LOCAL(size + 1);
++
++ strcpy(rgbPath, path);
++
++ #ifdef NX_TRANS_TEST
++ fprintf(stderr, "NXVerifyRgbPath: Looking for [%s] file.\n",
++ rgbPath);
++ #endif
++
++ if (stat(rgbPath, &rgbFileStat) != 0)
++ {
++
++ #ifdef NX_TRANS_TEST
++ fprintf(stderr, "NXVerifyRgbPath: Can't find the rgb file [%s].\n",
++ rgbPath);
++ #endif
++
++ strcat(rgbPath, ".txt");
++
++ #ifdef NX_TRANS_TEST
++ fprintf(stderr, "NXVerifyRgbPath: Looking for [%s] file.\n",
++ rgbPath);
++ #endif
++
++ if (stat(rgbPath, &rgbFileStat) != 0)
++ {
++
++ #ifdef NX_TRANS_TEST
++ fprintf(stderr, "NXVerifyRgbPath: Can't find the rgb file [%s].\n",
++ rgbPath);
++ #endif
++
++ DEALLOCATE_LOCAL(rgbPath);
++
++ return 0;
++ }
++ }
++
++ #ifdef NX_TRANS_TEST
++ fprintf(stderr, "NXVerifyRgbPath: rgb path [%s] is valid.\n",
++ path);
++ #endif
++
++ DEALLOCATE_LOCAL(rgbPath);
++
++ return 1;
++}
++
++static const char *_NXGetRgbPath(const char *path)
++{
++ const char *systemEnv;
++ char rgbPath[1024];
++ int numAltRgbPaths;
++ int i;
++
++ /*
++ * Check the environment only once.
++ */
++
++ if (*_NXRgbPath != '\0')
++ {
++ return _NXRgbPath;
++ }
++
++ systemEnv = getenv("NX_SYSTEM");
++
++ if (systemEnv != NULL && *systemEnv != '\0')
++ {
++ if (strlen(systemEnv) + strlen("/share/rgb") + 1 > 1024)
++ {
++
++ #ifdef NX_TRANS_TEST
++ fprintf(stderr, "_NXGetRgbPath: WARNING! Maximum length of rgb file path exceeded.\n");
++ #endif
++
++ goto _NXGetRgbPathError;
++ }
++
++ strcpy(rgbPath, systemEnv);
++ strcat(rgbPath, "/share/rgb");
++
++ if (NXVerifyRgbPath(rgbPath) == 1)
++ {
++ strcpy(_NXRgbPath, systemEnv);
++ strcat(_NXRgbPath, "/share/rgb");
++
++ #ifdef NX_TRANS_TEST
++ fprintf(stderr, "_NXGetRgbPath: Using rgb file path [%s].\n",
++ _NXRgbPath);
++ #endif
++
++ return _NXRgbPath;
++ }
++ }
++
++ numAltRgbPaths = sizeof(nxAltRgbPaths) / sizeof(*nxAltRgbPaths);
++
++ for (i = 0; i < numAltRgbPaths; i++)
++ {
++ if (NXVerifyRgbPath(nxAltRgbPaths[i]) == 1)
++ {
++ if (strlen(nxAltRgbPaths[i]) + 1 > 1024)
++ {
++ #ifdef NX_TRANS_TEST
++ fprintf(stderr, "_NXGetRgbPath: WARNING! Maximum length of rgb file path exceeded.\n");
++ #endif
++
++ goto _NXGetRgbPathError;
++ }
++
++ strcpy(_NXRgbPath, nxAltRgbPaths[i]);
++
++ #ifdef NX_TRANS_TEST
++ fprintf(stderr, "_NXGetRgbPath: Using rgb file path [%s].\n",
++ _NXRgbPath);
++ #endif
++
++ return _NXRgbPath;
++ }
++ }
++
++_NXGetRgbPathError:
++
++ strcpy(_NXRgbPath, path);
++
++ #ifdef NX_TRANS_TEST
++ fprintf(stderr, "_NXGetRgbPath: Using default rgb file path [%s].\n",
++ _NXRgbPath);
++ #endif
++
++ return _NXRgbPath;
++}
++
++#endif
+
+ static dbEntryPtr
+ lookup(char *name, int len, Bool create)
+@@ -229,9 +388,26 @@
+ if (!was_here)
+ {
+ #ifndef __UNIXOS2__
++#ifdef NX_TRANS_SOCKET
++ /*
++ * Add the trailing '.txt' if a
++ * 'rgb' file is not found.
++ */
++
++ struct stat statbuf;
++
++ path = (char*)ALLOCATE_LOCAL(strlen(_NXGetRgbPath(rgbPath)) + 5);
++ strcpy(path, _NXGetRgbPath(rgbPath));
++
++ if (stat(path, &statbuf) != 0)
++ {
++ strcat(path, ".txt");
++ }
++#else
+ path = (char*)ALLOCATE_LOCAL(strlen(rgbPath) +5);
+ strcpy(path, rgbPath);
+ strcat(path, ".txt");
++#endif
+ #else
+ char *tmp = (char*)__XOS2RedirRoot(rgbPath);
+ path = (char*)ALLOCATE_LOCAL(strlen(tmp) +5);
+@@ -240,7 +416,11 @@
+ #endif
+ if (!(rgb = fopen(path, "r")))
+ {
++#ifdef NX_TRANS_SOCKET
++ ErrorF( "Couldn't open RGB_DB '%s'\n", _NXGetRgbPath(rgbPath));
++#else
+ ErrorF( "Couldn't open RGB_DB '%s'\n", rgbPath );
++#endif
+ DEALLOCATE_LOCAL(path);
+ return FALSE;
+ }
diff --git a/doc/nx-X11_vs_XOrg69_patches/panoramiXproto.h.NX.patch b/doc/nx-X11_vs_XOrg69_patches/panoramiXproto.h.NX.patch
new file mode 100644
index 000000000..3424f2e4a
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/panoramiXproto.h.NX.patch
@@ -0,0 +1,195 @@
+--- ./nx-X11/programs/Xserver/randr/panoramiXproto.h.X.original 2015-02-13 14:03:44.792440567 +0100
++++ ./nx-X11/programs/Xserver/randr/panoramiXproto.h 2015-02-10 19:13:13.612693075 +0100
+@@ -0,0 +1,192 @@
++/* $Xorg: panoramiXproto.h,v 1.4 2000/08/18 04:05:45 coskrey Exp $ */
++/*****************************************************************
++Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
++Permission is hereby granted, free of charge, to any person obtaining a copy
++of this software and associated documentation files (the "Software"), to deal
++in the Software without restriction, including without limitation the rights
++to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
++copies of the Software.
++
++The above copyright notice and this permission notice shall be included in
++all copies or substantial portions of the Software.
++
++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
++BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
++WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
++IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
++
++Except as contained in this notice, the name of Digital Equipment Corporation
++shall not be used in advertising or otherwise to promote the sale, use or other
++dealings in this Software without prior written authorization from Digital
++Equipment Corporation.
++******************************************************************/
++/* $XFree86: xc/include/extensions/panoramiXproto.h,v 3.5 2000/03/01 01:04:21 dawes Exp $ */
++
++/* THIS IS NOT AN X PROJECT TEAM SPECIFICATION */
++
++#ifndef _PANORAMIXPROTO_H_
++#define _PANORAMIXPROTO_H_
++
++#define PANORAMIX_PROTOCOL_NAME "XINERAMA"
++
++#define X_PanoramiXQueryVersion 0
++#define X_PanoramiXGetState 1
++#define X_PanoramiXGetScreenCount 2
++#define X_PanoramiXGetScreenSize 3
++
++#define X_XineramaIsActive 4
++#define X_XineramaQueryScreens 5
++
++typedef struct _PanoramiXQueryVersion {
++ CARD8 reqType; /* always PanoramiXReqCode */
++ CARD8 panoramiXReqType; /* always X_PanoramiXQueryVersion */
++ CARD16 length B16;
++ CARD8 clientMajor;
++ CARD8 clientMinor;
++ CARD16 unused B16;
++} xPanoramiXQueryVersionReq;
++
++#define sz_xPanoramiXQueryVersionReq 8
++
++typedef struct {
++ CARD8 type; /* must be X_Reply */
++ CARD8 pad1; /* unused */
++ CARD16 sequenceNumber B16; /* last sequence number */
++ CARD32 length B32; /* 0 */
++ CARD16 majorVersion B16;
++ CARD16 minorVersion B16;
++ CARD32 pad2 B32; /* unused */
++ CARD32 pad3 B32; /* unused */
++ CARD32 pad4 B32; /* unused */
++ CARD32 pad5 B32; /* unused */
++ CARD32 pad6 B32; /* unused */
++} xPanoramiXQueryVersionReply;
++
++#define sz_xPanoramiXQueryVersionReply 32
++
++
++typedef struct _PanoramiXGetState {
++ CARD8 reqType; /* always PanoramiXReqCode */
++ CARD8 panoramiXReqType; /* always X_PanoramiXGetState */
++ CARD16 length B16;
++ CARD32 window B32;
++} xPanoramiXGetStateReq;
++#define sz_xPanoramiXGetStateReq 8
++
++typedef struct {
++ BYTE type;
++ BYTE state;
++ CARD16 sequenceNumber B16;
++ CARD32 length B32;
++ CARD32 window B32;
++ CARD32 pad1 B32; /* unused */
++ CARD32 pad2 B32; /* unused */
++ CARD32 pad3 B32; /* unused */
++ CARD32 pad4 B32; /* unused */
++ CARD32 pad5 B32; /* unused */
++} xPanoramiXGetStateReply;
++
++#define sz_panoramiXGetStateReply 32
++
++typedef struct _PanoramiXGetScreenCount {
++ CARD8 reqType; /* always PanoramiXReqCode */
++ CARD8 panoramiXReqType; /* always X_PanoramiXGetScreenCount */
++ CARD16 length B16;
++ CARD32 window B32;
++} xPanoramiXGetScreenCountReq;
++#define sz_xPanoramiXGetScreenCountReq 8
++
++typedef struct {
++ BYTE type;
++ BYTE ScreenCount;
++ CARD16 sequenceNumber B16;
++ CARD32 length B32;
++ CARD32 window B32;
++ CARD32 pad1 B32; /* unused */
++ CARD32 pad2 B32; /* unused */
++ CARD32 pad3 B32; /* unused */
++ CARD32 pad4 B32; /* unused */
++ CARD32 pad5 B32; /* unused */
++} xPanoramiXGetScreenCountReply;
++#define sz_panoramiXGetScreenCountReply 32
++
++typedef struct _PanoramiXGetScreenSize {
++ CARD8 reqType; /* always PanoramiXReqCode */
++ CARD8 panoramiXReqType; /* always X_PanoramiXGetState */
++ CARD16 length B16;
++ CARD32 window B32;
++ CARD32 screen B32;
++} xPanoramiXGetScreenSizeReq;
++#define sz_xPanoramiXGetScreenSizeReq 12
++
++typedef struct {
++ BYTE type;
++ CARD8 pad1;
++ CARD16 sequenceNumber B16;
++ CARD32 length B32;
++ CARD32 width B32;
++ CARD32 height B32;
++ CARD32 window B32;
++ CARD32 screen B32;
++ CARD32 pad2 B32; /* unused */
++ CARD32 pad3 B32; /* unused */
++} xPanoramiXGetScreenSizeReply;
++#define sz_panoramiXGetScreenSizeReply 32
++
++/************ Alternate protocol ******************/
++
++typedef struct {
++ CARD8 reqType;
++ CARD8 panoramiXReqType;
++ CARD16 length B16;
++} xXineramaIsActiveReq;
++#define sz_xXineramaIsActiveReq 4
++
++typedef struct {
++ BYTE type;
++ CARD8 pad1;
++ CARD16 sequenceNumber B16;
++ CARD32 length B32;
++ CARD32 state B32;
++ CARD32 pad2 B32;
++ CARD32 pad3 B32;
++ CARD32 pad4 B32;
++ CARD32 pad5 B32;
++ CARD32 pad6 B32;
++} xXineramaIsActiveReply;
++#define sz_XineramaIsActiveReply 32
++
++
++typedef struct {
++ CARD8 reqType;
++ CARD8 panoramiXReqType;
++ CARD16 length B16;
++} xXineramaQueryScreensReq;
++#define sz_xXineramaQueryScreensReq 4
++
++typedef struct {
++ BYTE type;
++ CARD8 pad1;
++ CARD16 sequenceNumber B16;
++ CARD32 length B32;
++ CARD32 number B32;
++ CARD32 pad2 B32;
++ CARD32 pad3 B32;
++ CARD32 pad4 B32;
++ CARD32 pad5 B32;
++ CARD32 pad6 B32;
++} xXineramaQueryScreensReply;
++#define sz_XineramaQueryScreensReply 32
++
++typedef struct {
++ INT16 x_org B16;
++ INT16 y_org B16;
++ CARD16 width B16;
++ CARD16 height B16;
++} xXineramaScreenInfo;
++#define sz_XineramaScreenInfo 8
++
++#endif
diff --git a/doc/nx-X11_vs_XOrg69_patches/pixmap.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/pixmap.c.NX.patch
new file mode 100644
index 000000000..77b32d21c
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/pixmap.c.NX.patch
@@ -0,0 +1,18 @@
+--- ./nx-X11/programs/Xserver/dix/pixmap.c.X.original 2015-02-13 14:03:44.704442298 +0100
++++ ./nx-X11/programs/Xserver/dix/pixmap.c 2015-02-10 19:13:13.696689930 +0100
+@@ -121,7 +121,14 @@
+ if (pScreen->totalPixmapSize > ((size_t)-1) - pixDataSize)
+ return NullPixmap;
+
+- pPixmap = (PixmapPtr)xalloc(pScreen->totalPixmapSize + pixDataSize);
++ /*
++ * FIXME: Allocate 4 bytes at the end of each pixmap. This
++ * is a quick workaround intended to fix a problem reported
++ * by Valgrind due to fbBlt() writing just after the end of
++ * the pixmap buffer. This may be a RENDER bug.
++ */
++
++ pPixmap = (PixmapPtr)xalloc(pScreen->totalPixmapSize + pixDataSize + 4);
+ if (!pPixmap)
+ return NullPixmap;
+ ppriv = (DevUnion *)(pPixmap + 1);
diff --git a/doc/nx-X11_vs_XOrg69_patches/randr.NX.patch b/doc/nx-X11_vs_XOrg69_patches/randr.NX.patch
new file mode 100644
index 000000000..6462b1176
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/randr.NX.patch
@@ -0,0 +1,2704 @@
+diff -u ./nx-X11/programs/Xserver/randr.X.original/Imakefile ./nx-X11/programs/Xserver/randr/Imakefile
+--- ./nx-X11/programs/Xserver/randr.X.original/Imakefile 2015-02-13 14:03:44.792440567 +0100
++++ ./nx-X11/programs/Xserver/randr/Imakefile 2015-02-10 19:13:13.636692176 +0100
+@@ -1,15 +1,33 @@
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NX-X11, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
+ XCOMM $XFree86: xc/programs/Xserver/randr/Imakefile,v 1.1 2001/05/23 03:29:44 keithp Exp $
+ #include <Server.tmpl>
+
+- SRCS = randr.c mirandr.c
++ SRCS = mirandr.c randr.c rrcrtc.c rrdispatch.c rrinfo.c rrmode.c rroutput.c rrpointer.c rrproperty.c rrscreen.c rrsdispatch.c rrxinerama.c
+
+- OBJS = randr.o mirandr.o
++ OBJS = mirandr.o randr.o rrcrtc.o rrdispatch.o rrinfo.o rrmode.o rroutput.o rrpointer.o rrproperty.o rrscreen.o rrsdispatch.o rrxinerama.o
+
+ INCLUDES = -I../include -I../mi -I../../../include/fonts \
+ -I../fb -I../hw/kdrive -I$(EXTINCSRC) -I$(XINCLUDESRC) \
+ -I$(FONTINCSRC) -I../render
+ LINTLIBS = ../dix/llib-ldix.ln ../os/llib-los.ln
+
++ DEFINES = -DNXAGENT_SERVER
++
+ NormalLibraryTarget(randr,$(OBJS))
+ NormalLibraryObjectRule()
+ LintLibraryTarget(randr,$(SRCS))
+Only in ./nx-X11/programs/Xserver/randr: Imakefile.NX.original
+Only in ./nx-X11/programs/Xserver/randr: Imakefile.X.original
+Only in ./nx-X11/programs/Xserver/randr: Makefile.am
+Only in ./nx-X11/programs/Xserver/randr: Makefile.in
+diff -u ./nx-X11/programs/Xserver/randr.X.original/mirandr.c ./nx-X11/programs/Xserver/randr/mirandr.c
+--- ./nx-X11/programs/Xserver/randr.X.original/mirandr.c 2015-02-13 14:03:44.792440567 +0100
++++ ./nx-X11/programs/Xserver/randr/mirandr.c 2015-02-10 19:13:13.616692925 +0100
+@@ -1,76 +1,42 @@
+ /*
+- * $XFree86: xc/programs/Xserver/randr/mirandr.c,v 1.5 2001/06/04 09:45:40 keithp Exp $
+- *
+- * Copyright © 2000, Compaq Computer Corporation,
+- * Copyright © 2002, Hewlett Packard, Inc.
++ * Copyright © 2000 Compaq Computer Corporation
++ * Copyright © 2002 Hewlett-Packard Company
++ * Copyright © 2006 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+- * the above copyright notice appear in all copies and that both that
+- * copyright notice and this permission notice appear in supporting
+- * documentation, and that the name of Compaq or HP not be used in advertising
+- * or publicity pertaining to distribution of the software without specific,
+- * written prior permission. HP makes no representations about the
+- * suitability of this software for any purpose. It is provided "as is"
+- * without express or implied warranty.
++ * the above copyright notice appear in all copies and that both that copyright
++ * notice and this permission notice appear in supporting documentation, and
++ * that the name of the copyright holders not be used in advertising or
++ * publicity pertaining to distribution of the software without specific,
++ * written prior permission. The copyright holders make no representations
++ * about the suitability of this software for any purpose. It is provided "as
++ * is" without express or implied warranty.
+ *
+- * HP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL HP
+- * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
++ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
++ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
++ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
++ * OF THIS SOFTWARE.
+ *
+- * Author: Jim Gettys, HP Labs, Hewlett-Packard, Inc.
++ * Author: Jim Gettys, Hewlett-Packard Company, Inc.
++ * Keith Packard, Intel Corporation
+ */
+
+-
+ #ifdef HAVE_DIX_CONFIG_H
+ #include <dix-config.h>
+ #endif
+
+ #include "scrnintstr.h"
+ #include "mi.h"
+-#include <X11/extensions/randr.h>
+ #include "randrstr.h"
+ #include <stdio.h>
+
+-/*
+- * This function assumes that only a single depth can be
+- * displayed at a time, but that all visuals of that depth
+- * can be displayed simultaneously. It further assumes that
+- * only a single size is available. Hardware providing
+- * additional capabilties should use different code.
+- * XXX what to do here....
+- */
+-
+ Bool
+ miRRGetInfo (ScreenPtr pScreen, Rotation *rotations)
+ {
+- int i;
+- Bool setConfig = FALSE;
+-
+- *rotations = RR_Rotate_0;
+- for (i = 0; i < pScreen->numDepths; i++)
+- {
+- if (pScreen->allowedDepths[i].numVids)
+- {
+- RRScreenSizePtr pSize;
+-
+- pSize = RRRegisterSize (pScreen,
+- pScreen->width,
+- pScreen->height,
+- pScreen->mmWidth,
+- pScreen->mmHeight);
+- if (!pSize)
+- return FALSE;
+- if (!setConfig)
+- {
+- RRSetCurrentConfig (pScreen, RR_Rotate_0, 0, pSize);
+- setConfig = TRUE;
+- }
+- }
+- }
+ return TRUE;
+ }
+
+@@ -79,24 +45,110 @@
+ * different here
+ */
+ Bool
+-miRRSetConfig (ScreenPtr pScreen,
+- Rotation rotation,
+- int rate,
+- RRScreenSizePtr pSize)
++miRRCrtcSet (ScreenPtr pScreen,
++ RRCrtcPtr crtc,
++ RRModePtr mode,
++ int x,
++ int y,
++ Rotation rotation,
++ int numOutput,
++ RROutputPtr *outputs)
+ {
+ return TRUE;
+ }
+
++static Bool
++miRRCrtcSetGamma (ScreenPtr pScreen,
++ RRCrtcPtr crtc)
++{
++ return TRUE;
++}
++
++Bool
++miRROutputSetProperty (ScreenPtr pScreen,
++ RROutputPtr output,
++ Atom property,
++ RRPropertyValuePtr value)
++{
++ return TRUE;
++}
++
++Bool
++miRROutputValidateMode (ScreenPtr pScreen,
++ RROutputPtr output,
++ RRModePtr mode)
++{
++ return FALSE;
++}
++
++void
++miRRModeDestroy (ScreenPtr pScreen,
++ RRModePtr mode)
++{
++}
++
++/*
++ * This function assumes that only a single depth can be
++ * displayed at a time, but that all visuals of that depth
++ * can be displayed simultaneously. It further assumes that
++ * only a single size is available. Hardware providing
++ * additional capabilties should use different code.
++ * XXX what to do here....
++ */
+
+ Bool
+ miRandRInit (ScreenPtr pScreen)
+ {
+- rrScrPrivPtr rp;
++ rrScrPrivPtr pScrPriv;
++#if RANDR_12_INTERFACE
++ RRModePtr mode;
++ RRCrtcPtr crtc;
++ RROutputPtr output;
++ xRRModeInfo modeInfo;
++ char name[64];
++#endif
+
+ if (!RRScreenInit (pScreen))
+ return FALSE;
+- rp = rrGetScrPriv(pScreen);
+- rp->rrGetInfo = miRRGetInfo;
+- rp->rrSetConfig = miRRSetConfig;
++ pScrPriv = rrGetScrPriv(pScreen);
++ pScrPriv->rrGetInfo = miRRGetInfo;
++#if RANDR_12_INTERFACE
++ pScrPriv->rrCrtcSet = miRRCrtcSet;
++ pScrPriv->rrCrtcSetGamma = miRRCrtcSetGamma;
++ pScrPriv->rrOutputSetProperty = miRROutputSetProperty;
++ pScrPriv->rrOutputValidateMode = miRROutputValidateMode;
++ pScrPriv->rrModeDestroy = miRRModeDestroy;
++
++ RRScreenSetSizeRange (pScreen,
++ pScreen->width, pScreen->height,
++ pScreen->width, pScreen->height);
++
++ sprintf (name, "%dx%d", pScreen->width, pScreen->height);
++ memset (&modeInfo, '\0', sizeof (modeInfo));
++ modeInfo.width = pScreen->width;
++ modeInfo.height = pScreen->height;
++ modeInfo.nameLength = strlen (name);
++
++ mode = RRModeGet (&modeInfo, name);
++ if (!mode)
++ return FALSE;
++
++ crtc = RRCrtcCreate (pScreen, NULL);
++ if (!crtc)
++ return FALSE;
++
++ output = RROutputCreate (pScreen, "screen", 6, NULL);
++ if (!output)
++ return FALSE;
++ if (!RROutputSetClones (output, NULL, 0))
++ return FALSE;
++ if (!RROutputSetModes (output, &mode, 1, 0))
++ return FALSE;
++ if (!RROutputSetCrtcs (output, &crtc, 1))
++ return FALSE;
++ if (!RROutputSetConnection (output, RR_Connected))
++ return FALSE;
++ RRCrtcNotify (crtc, mode, 0, 0, RR_Rotate_0, 1, &output);
++#endif
+ return TRUE;
+ }
+Only in ./nx-X11/programs/Xserver/randr: panoramiXproto.h
+Only in ./nx-X11/programs/Xserver/randr: panoramiXproto.h.NX.original
+Only in ./nx-X11/programs/Xserver/randr: panoramiXproto.h.X.original
+diff -u ./nx-X11/programs/Xserver/randr.X.original/randr.c ./nx-X11/programs/Xserver/randr/randr.c
+--- ./nx-X11/programs/Xserver/randr.X.original/randr.c 2015-02-13 14:03:44.792440567 +0100
++++ ./nx-X11/programs/Xserver/randr/randr.c 2015-02-10 19:13:13.616692925 +0100
+@@ -1,29 +1,46 @@
+ /*
+- * $XFree86: xc/programs/Xserver/randr/randr.c,v 1.21tsi Exp $
+- *
+- * Copyright © 2000, Compaq Computer Corporation,
+- * Copyright © 2002, Hewlett Packard, Inc.
++ * Copyright © 2000 Compaq Computer Corporation
++ * Copyright © 2002 Hewlett-Packard Company
++ * Copyright © 2006 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+- * the above copyright notice appear in all copies and that both that
+- * copyright notice and this permission notice appear in supporting
+- * documentation, and that the name of Compaq or HP not be used in advertising
+- * or publicity pertaining to distribution of the software without specific,
+- * written prior permission. HP makes no representations about the
+- * suitability of this software for any purpose. It is provided "as is"
+- * without express or implied warranty.
++ * the above copyright notice appear in all copies and that both that copyright
++ * notice and this permission notice appear in supporting documentation, and
++ * that the name of the copyright holders not be used in advertising or
++ * publicity pertaining to distribution of the software without specific,
++ * written prior permission. The copyright holders make no representations
++ * about the suitability of this software for any purpose. It is provided "as
++ * is" without express or implied warranty.
+ *
+- * HP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL HP
+- * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
++ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
++ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
++ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
++ * OF THIS SOFTWARE.
+ *
+- * Author: Jim Gettys, HP Labs, Hewlett-Packard, Inc.
++ * Author: Jim Gettys, Hewlett-Packard Company, Inc.
++ * Keith Packard, Intel Corporation
+ */
+
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NX-X11, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
+
+ #define NEED_REPLIES
+ #define NEED_EVENTS
+@@ -31,28 +48,7 @@
+ #include <dix-config.h>
+ #endif
+
+-#include <X11/X.h>
+-#include <X11/Xproto.h>
+-#include "misc.h"
+-#include "os.h"
+-#include "dixstruct.h"
+-#include "resource.h"
+-#include "scrnintstr.h"
+-#include "windowstr.h"
+-#include "pixmapstr.h"
+-#include "extnsionst.h"
+-#include "servermd.h"
+-#include <X11/extensions/randr.h>
+-#include <X11/extensions/randrproto.h>
+ #include "randrstr.h"
+-#ifdef RENDER
+-#include <X11/extensions/render.h> /* we share subpixel order information */
+-#include "picturestr.h"
+-#endif
+-#include <X11/Xfuncproto.h>
+-#ifdef EXTMODULE
+-#include "xf86_ansic.h"
+-#endif
+
+ /* From render.h */
+ #ifndef SubPixelUnknown
+@@ -60,13 +56,7 @@
+ #endif
+
+ #define RR_VALIDATE
+-int RRGeneration;
+-int RRNScreens;
+-
+-static int ProcRRQueryVersion (ClientPtr pClient);
+-static int ProcRRDispatch (ClientPtr pClient);
+-static int SProcRRDispatch (ClientPtr pClient);
+-static int SProcRRQueryVersion (ClientPtr pClient);
++static int RRNScreens;
+
+ #define wrap(priv,real,mem,func) {\
+ priv->mem = real->mem; \
+@@ -77,56 +67,20 @@
+ real->mem = priv->mem; \
+ }
+
+-#if 0
+-static CARD8 RRReqCode;
+-static int RRErrBase;
+-#endif
+-static int RREventBase;
+-static RESTYPE ClientType, EventType; /* resource types for event masks */
+-static int RRClientPrivateIndex;
+-
+-typedef struct _RRTimes {
+- TimeStamp setTime;
+- TimeStamp configTime;
+-} RRTimesRec, *RRTimesPtr;
+-
+-typedef struct _RRClient {
+- int major_version;
+- int minor_version;
+-/* RRTimesRec times[0]; */
+-} RRClientRec, *RRClientPtr;
+-
+-/*
+- * each window has a list of clients requesting
+- * RRNotify events. Each client has a resource
+- * for each window it selects RRNotify input for,
+- * this resource is used to delete the RRNotifyRec
+- * entry from the per-window queue.
+- */
+-
+-typedef struct _RREvent *RREventPtr;
+-
+-typedef struct _RREvent {
+- RREventPtr next;
+- ClientPtr client;
+- WindowPtr window;
+- XID clientResource;
+- int mask;
+-} RREventRec;
++static int ProcRRDispatch (ClientPtr pClient);
++static int SProcRRDispatch (ClientPtr pClient);
+
++int RREventBase;
++int RRErrorBase;
++RESTYPE RRClientType, RREventType; /* resource types for event masks */
++
++#ifndef NXAGENT_SERVER
++DevPrivateKey RRClientPrivateKey = &RRClientPrivateKey;
++DevPrivateKey rrPrivKey = &rrPrivKey;
++#else
++int RRClientPrivateIndex;
+ int rrPrivIndex = -1;
+-
+-#define GetRRClient(pClient) ((RRClientPtr) (pClient)->devPrivates[RRClientPrivateIndex].ptr)
+-#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient)
+-
+-static Bool
+-RRClientKnowsRates (ClientPtr pClient)
+-{
+- rrClientPriv(pClient);
+-
+- return (pRRClient->major_version > 1 ||
+- (pRRClient->major_version == 1 && pRRClient->minor_version >= 1));
+-}
++#endif
+
+ static void
+ RRClientCallback (CallbackListPtr *list,
+@@ -163,10 +117,14 @@
+ RRCloseScreen (int i, ScreenPtr pScreen)
+ {
+ rrScrPriv(pScreen);
++ int j;
+
+ unwrap (pScrPriv, pScreen, CloseScreen);
+- if (pScrPriv->pSizes)
+- xfree (pScrPriv->pSizes);
++ for (j = pScrPriv->numCrtcs - 1; j >= 0; j--)
++ RRCrtcDestroy (pScrPriv->crtcs[j]);
++ for (j = pScrPriv->numOutputs - 1; j >= 0; j--)
++ RROutputDestroy (pScrPriv->outputs[j]);
++
+ xfree (pScrPriv);
+ RRNScreens -= 1; /* ok, one fewer screen with RandR running */
+ return (*pScreen->CloseScreen) (i, pScreen);
+@@ -191,18 +149,105 @@
+ cpswaps(from->subpixelOrder, to->subpixelOrder);
+ }
+
+-Bool RRScreenInit(ScreenPtr pScreen)
++static void
++SRRCrtcChangeNotifyEvent(xRRCrtcChangeNotifyEvent *from,
++ xRRCrtcChangeNotifyEvent *to)
+ {
+- rrScrPrivPtr pScrPriv;
++ to->type = from->type;
++ to->subCode = from->subCode;
++ cpswaps(from->sequenceNumber, to->sequenceNumber);
++ cpswapl(from->timestamp, to->timestamp);
++ cpswapl(from->window, to->window);
++ cpswapl(from->crtc, to->crtc);
++ cpswapl(from->mode, to->mode);
++ cpswapl(from->window, to->window);
++ cpswaps(from->rotation, to->rotation);
++ cpswaps(from->x, to->x);
++ cpswaps(from->y, to->y);
++ cpswaps(from->width, to->width);
++ cpswaps(from->height, to->height);
++}
++
++static void
++SRROutputChangeNotifyEvent(xRROutputChangeNotifyEvent *from,
++ xRROutputChangeNotifyEvent *to)
++{
++ to->type = from->type;
++ to->subCode = from->subCode;
++ cpswaps(from->sequenceNumber, to->sequenceNumber);
++ cpswapl(from->timestamp, to->timestamp);
++ cpswapl(from->configTimestamp, to->configTimestamp);
++ cpswapl(from->window, to->window);
++ cpswapl(from->output, to->output);
++ cpswapl(from->crtc, to->crtc);
++ cpswapl(from->mode, to->mode);
++ cpswaps(from->rotation, to->rotation);
++}
+
++static void
++SRROutputPropertyNotifyEvent(xRROutputPropertyNotifyEvent *from,
++ xRROutputPropertyNotifyEvent *to)
++{
++ to->type = from->type;
++ to->subCode = from->subCode;
++ cpswaps(from->sequenceNumber, to->sequenceNumber);
++ cpswapl(from->window, to->window);
++ cpswapl(from->output, to->output);
++ cpswapl(from->atom, to->atom);
++ cpswapl(from->timestamp, to->timestamp);
++}
++
++static void
++SRRNotifyEvent (xEvent *from,
++ xEvent *to)
++{
++ switch (from->u.u.detail) {
++ case RRNotify_CrtcChange:
++ SRRCrtcChangeNotifyEvent ((xRRCrtcChangeNotifyEvent *) from,
++ (xRRCrtcChangeNotifyEvent *) to);
++ break;
++ case RRNotify_OutputChange:
++ SRROutputChangeNotifyEvent ((xRROutputChangeNotifyEvent *) from,
++ (xRROutputChangeNotifyEvent *) to);
++ break;
++ case RRNotify_OutputProperty:
++ SRROutputPropertyNotifyEvent ((xRROutputPropertyNotifyEvent *) from,
++ (xRROutputPropertyNotifyEvent *) to);
++ break;
++ default:
++ break;
++ }
++}
++
++static int RRGeneration;
++
++Bool RRInit (void)
++{
+ if (RRGeneration != serverGeneration)
+ {
++ #ifdef NXAGENT_SERVER
+ if ((rrPrivIndex = AllocateScreenPrivateIndex()) < 0)
+ return FALSE;
++ #endif
++ if (!RRModeInit ())
++ return FALSE;
++ if (!RRCrtcInit ())
++ return FALSE;
++ if (!RROutputInit ())
++ return FALSE;
+ RRGeneration = serverGeneration;
+ }
++ return TRUE;
++}
++
++Bool RRScreenInit(ScreenPtr pScreen)
++{
++ rrScrPrivPtr pScrPriv;
++
++ if (!RRInit ())
++ return FALSE;
+
+- pScrPriv = (rrScrPrivPtr) xalloc (sizeof (rrScrPrivRec));
++ pScrPriv = (rrScrPrivPtr) xcalloc (1, sizeof (rrScrPrivRec));
+ if (!pScrPriv)
+ return FALSE;
+
+@@ -211,8 +256,31 @@
+ /*
+ * Calling function best set these function vectors
+ */
+- pScrPriv->rrSetConfig = 0;
+ pScrPriv->rrGetInfo = 0;
++ pScrPriv->maxWidth = pScrPriv->minWidth = pScreen->width;
++ pScrPriv->maxHeight = pScrPriv->minHeight = pScreen->height;
++
++ pScrPriv->width = pScreen->width;
++ pScrPriv->height = pScreen->height;
++ pScrPriv->mmWidth = pScreen->mmWidth;
++ pScrPriv->mmHeight = pScreen->mmHeight;
++#if RANDR_12_INTERFACE
++ pScrPriv->rrScreenSetSize = NULL;
++ pScrPriv->rrCrtcSet = NULL;
++ pScrPriv->rrCrtcSetGamma = NULL;
++#endif
++#if RANDR_10_INTERFACE
++ pScrPriv->rrSetConfig = 0;
++ pScrPriv->rotations = RR_Rotate_0;
++ pScrPriv->reqWidth = pScreen->width;
++ pScrPriv->reqHeight = pScreen->height;
++ pScrPriv->nSizes = 0;
++ pScrPriv->pSizes = NULL;
++ pScrPriv->rotation = RR_Rotate_0;
++ pScrPriv->rate = 0;
++ pScrPriv->size = 0;
++#endif
++
+ /*
+ * This value doesn't really matter -- any client must call
+ * GetScreenInfo before reading it which will automatically update
+@@ -223,14 +291,10 @@
+
+ wrap (pScrPriv, pScreen, CloseScreen, RRCloseScreen);
+
+- pScrPriv->rotations = RR_Rotate_0;
+-
+- pScrPriv->nSizes = 0;
+- pScrPriv->nSizesInUse = 0;
+- pScrPriv->pSizes = 0;
+-
+- pScrPriv->rotation = RR_Rotate_0;
+- pScrPriv->size = -1;
++ pScrPriv->numOutputs = 0;
++ pScrPriv->outputs = NULL;
++ pScrPriv->numCrtcs = 0;
++ pScrPriv->crtcs = NULL;
+
+ RRNScreens += 1; /* keep count of screens that implement randr */
+ return TRUE;
+@@ -246,7 +310,7 @@
+
+ pRREvent = (RREventPtr) data;
+ pWin = pRREvent->window;
+- pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, EventType);
++ pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, RREventType);
+ if (pHead) {
+ pPrev = 0;
+ for (pCur = *pHead; pCur && pCur != pRREvent; pCur=pCur->next)
+@@ -272,7 +336,7 @@
+ pHead = (RREventPtr *) data;
+ for (pCur = *pHead; pCur; pCur = pNext) {
+ pNext = pCur->next;
+- FreeResource (pCur->clientResource, ClientType);
++ FreeResource (pCur->clientResource, RRClientType);
+ xfree ((pointer) pCur);
+ }
+ xfree ((pointer) pHead);
+@@ -286,1034 +350,172 @@
+
+ if (RRNScreens == 0) return;
+
++ #ifndef NXAGENT_SERVER
++ if (!dixRequestPrivate(RRClientPrivateKey,
++ sizeof (RRClientRec) +
++ screenInfo.numScreens * sizeof (RRTimesRec)))
++ return;
++ #else
+ RRClientPrivateIndex = AllocateClientPrivateIndex ();
+ if (!AllocateClientPrivate (RRClientPrivateIndex,
+ sizeof (RRClientRec) +
+ screenInfo.numScreens * sizeof (RRTimesRec)))
+ return;
++ #endif
+ if (!AddCallback (&ClientStateCallback, RRClientCallback, 0))
+ return;
+
+- ClientType = CreateNewResourceType(RRFreeClient);
+- if (!ClientType)
++ RRClientType = CreateNewResourceType(RRFreeClient);
++ if (!RRClientType)
+ return;
+- EventType = CreateNewResourceType(RRFreeEvents);
+- if (!EventType)
++ RREventType = CreateNewResourceType(RRFreeEvents);
++ if (!RREventType)
+ return;
+ extEntry = AddExtension (RANDR_NAME, RRNumberEvents, RRNumberErrors,
+ ProcRRDispatch, SProcRRDispatch,
+ RRResetProc, StandardMinorOpcode);
+ if (!extEntry)
+ return;
+-#if 0
+- RRReqCode = (CARD8) extEntry->base;
+- RRErrBase = extEntry->errorBase;
+-#endif
++ RRErrorBase = extEntry->errorBase;
+ RREventBase = extEntry->eventBase;
+ EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr)
+- SRRScreenChangeNotifyEvent;
+-
+- return;
++ SRRScreenChangeNotifyEvent;
++ EventSwapVector[RREventBase + RRNotify] = (EventSwapPtr)
++ SRRNotifyEvent;
++#ifdef PANORAMIX
++ RRXineramaExtensionInit();
++#endif
+ }
+-
++
+ static int
+ TellChanged (WindowPtr pWin, pointer value)
+ {
+ RREventPtr *pHead, pRREvent;
+ ClientPtr client;
+- xRRScreenChangeNotifyEvent se;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ rrScrPriv(pScreen);
+- RRScreenSizePtr pSize;
+- WindowPtr pRoot = WindowTable[pScreen->myNum];
++ int i;
+
+- pHead = (RREventPtr *) LookupIDByType (pWin->drawable.id, EventType);
++ pHead = (RREventPtr *) LookupIDByType (pWin->drawable.id, RREventType);
+ if (!pHead)
+ return WT_WALKCHILDREN;
+
+- se.type = RRScreenChangeNotify + RREventBase;
+- se.rotation = (CARD8) pScrPriv->rotation;
+- se.timestamp = pScrPriv->lastSetTime.milliseconds;
+- se.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
+- se.root = pRoot->drawable.id;
+- se.window = pWin->drawable.id;
+-#ifdef RENDER
+- se.subpixelOrder = PictureGetSubpixelOrder (pScreen);
+-#else
+- se.subpixelOrder = SubPixelUnknown;
+-#endif
+- if (pScrPriv->size >= 0)
+- {
+- pSize = &pScrPriv->pSizes[pScrPriv->size];
+- se.sizeID = pSize->id;
+- se.widthInPixels = pSize->width;
+- se.heightInPixels = pSize->height;
+- se.widthInMillimeters = pSize->mmWidth;
+- se.heightInMillimeters = pSize->mmHeight;
+- }
+- else
+- {
+- /*
+- * This "shouldn't happen", but a broken DDX can
+- * forget to set the current configuration on GetInfo
+- */
+- se.sizeID = 0xffff;
+- se.widthInPixels = 0;
+- se.heightInPixels = 0;
+- se.widthInMillimeters = 0;
+- se.heightInMillimeters = 0;
+- }
+ for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
+ {
+ client = pRREvent->client;
+ if (client == serverClient || client->clientGone)
+ continue;
+- se.sequenceNumber = client->sequence;
+- if(pRREvent->mask & RRScreenChangeNotifyMask)
+- WriteEventsToClient (client, 1, (xEvent *) &se);
+- }
+- return WT_WALKCHILDREN;
+-}
+
+-static Bool
+-RRGetInfo (ScreenPtr pScreen)
+-{
+- rrScrPriv (pScreen);
+- int i, j, k, l;
+- Bool changed;
+- Rotation rotations;
+- RRScreenSizePtr pSize;
+- RRScreenRatePtr pRate;
+-
+- for (i = 0; i < pScrPriv->nSizes; i++)
+- {
+- pSize = &pScrPriv->pSizes[i];
+- pSize->oldReferenced = pSize->referenced;
+- pSize->referenced = FALSE;
+- for (k = 0; k < pSize->nRates; k++)
++ if (pRREvent->mask & RRScreenChangeNotifyMask)
++ RRDeliverScreenEvent (client, pWin, pScreen);
++
++ if (pRREvent->mask & RRCrtcChangeNotifyMask)
+ {
+- pRate = &pSize->pRates[k];
+- pRate->oldReferenced = pRate->referenced;
+- pRate->referenced = FALSE;
+- }
+- }
+- if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations))
+- return FALSE;
+-
+- changed = FALSE;
+-
+- /*
+- * Check whether anything changed and simultaneously generate
+- * the protocol id values for the objects
+- */
+- if (rotations != pScrPriv->rotations)
+- {
+- pScrPriv->rotations = rotations;
+- changed = TRUE;
+- }
+-
+- j = 0;
+- for (i = 0; i < pScrPriv->nSizes; i++)
+- {
+- pSize = &pScrPriv->pSizes[i];
+- if (pSize->oldReferenced != pSize->referenced)
+- changed = TRUE;
+- if (pSize->referenced)
+- pSize->id = j++;
+- l = 0;
+- for (k = 0; k < pSize->nRates; k++)
+- {
+- pRate = &pSize->pRates[k];
+- if (pRate->oldReferenced != pRate->referenced)
+- changed = TRUE;
+- if (pRate->referenced)
+- l++;
+- }
+- pSize->nRatesInUse = l;
+- }
+- pScrPriv->nSizesInUse = j;
+- if (changed)
+- {
+- UpdateCurrentTime ();
+- pScrPriv->lastConfigTime = currentTime;
+- WalkTree (pScreen, TellChanged, (pointer) pScreen);
+- }
+- return TRUE;
+-}
+-
+-static void
+-RRSendConfigNotify (ScreenPtr pScreen)
+-{
+- WindowPtr pWin = WindowTable[pScreen->myNum];
+- xEvent event;
+-
+- event.u.u.type = ConfigureNotify;
+- event.u.configureNotify.window = pWin->drawable.id;
+- event.u.configureNotify.aboveSibling = None;
+- event.u.configureNotify.x = 0;
+- event.u.configureNotify.y = 0;
+-
+- /* XXX xinerama stuff ? */
+-
+- event.u.configureNotify.width = pWin->drawable.width;
+- event.u.configureNotify.height = pWin->drawable.height;
+- event.u.configureNotify.borderWidth = wBorderWidth (pWin);
+- event.u.configureNotify.override = pWin->overrideRedirect;
+- DeliverEvents(pWin, &event, 1, NullWindow);
+-}
+-
+-static int
+-ProcRRQueryVersion (ClientPtr client)
+-{
+- xRRQueryVersionReply rep;
+- register int n;
+- REQUEST(xRRQueryVersionReq);
+- rrClientPriv(client);
+-
+- REQUEST_SIZE_MATCH(xRRQueryVersionReq);
+- pRRClient->major_version = stuff->majorVersion;
+- pRRClient->minor_version = stuff->minorVersion;
+- rep.type = X_Reply;
+- rep.length = 0;
+- rep.sequenceNumber = client->sequence;
+- rep.majorVersion = RANDR_MAJOR;
+- rep.minorVersion = RANDR_MINOR;
+- if (client->swapped) {
+- swaps(&rep.sequenceNumber, n);
+- swapl(&rep.length, n);
+- swapl(&rep.majorVersion, n);
+- swapl(&rep.minorVersion, n);
+- }
+- WriteToClient(client, sizeof(xRRQueryVersionReply), (char *)&rep);
+- return (client->noClientException);
+-}
+-
+-
+-extern char *ConnectionInfo;
+-
+-static int padlength[4] = {0, 3, 2, 1};
+-
+-static void
+-RREditConnectionInfo (ScreenPtr pScreen)
+-{
+- xConnSetup *connSetup;
+- char *vendor;
+- xPixmapFormat *formats;
+- xWindowRoot *root;
+- xDepth *depth;
+- xVisualType *visual;
+- int screen = 0;
+- int d;
+-
+- connSetup = (xConnSetup *) ConnectionInfo;
+- vendor = (char *) connSetup + sizeof (xConnSetup);
+- formats = (xPixmapFormat *) ((char *) vendor +
+- connSetup->nbytesVendor +
+- padlength[connSetup->nbytesVendor & 3]);
+- root = (xWindowRoot *) ((char *) formats +
+- sizeof (xPixmapFormat) * screenInfo.numPixmapFormats);
+- while (screen != pScreen->myNum)
+- {
+- depth = (xDepth *) ((char *) root +
+- sizeof (xWindowRoot));
+- for (d = 0; d < root->nDepths; d++)
+- {
+- visual = (xVisualType *) ((char *) depth +
+- sizeof (xDepth));
+- depth = (xDepth *) ((char *) visual +
+- depth->nVisuals * sizeof (xVisualType));
+- }
+- root = (xWindowRoot *) ((char *) depth);
+- screen++;
+- }
+- root->pixWidth = pScreen->width;
+- root->pixHeight = pScreen->height;
+- root->mmWidth = pScreen->mmWidth;
+- root->mmHeight = pScreen->mmHeight;
+-}
+-
+-static int
+-ProcRRGetScreenInfo (ClientPtr client)
+-{
+- REQUEST(xRRGetScreenInfoReq);
+- xRRGetScreenInfoReply rep;
+- WindowPtr pWin;
+- int n;
+- ScreenPtr pScreen;
+- rrScrPrivPtr pScrPriv;
+- CARD8 *extra;
+- unsigned long extraLen;
+-
+- REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
+- pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
+- SecurityReadAccess);
+-
+- if (!pWin)
+- return BadWindow;
+-
+- pScreen = pWin->drawable.pScreen;
+- pScrPriv = rrGetScrPriv(pScreen);
+- rep.pad = 0;
+- if (!pScrPriv)
+- {
+- rep.type = X_Reply;
+- rep.setOfRotations = RR_Rotate_0;;
+- rep.sequenceNumber = client->sequence;
+- rep.length = 0;
+- rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
+- rep.timestamp = currentTime.milliseconds;
+- rep.configTimestamp = currentTime.milliseconds;
+- rep.nSizes = 0;
+- rep.sizeID = 0;
+- rep.rotation = RR_Rotate_0;
+- rep.rate = 0;
+- rep.nrateEnts = 0;
+- extra = 0;
+- extraLen = 0;
+- }
+- else
+- {
+- int i, j;
+- xScreenSizes *size;
+- CARD16 *rates;
+- CARD8 *data8;
+- Bool has_rate = RRClientKnowsRates (client);
+-
+- RRGetInfo (pScreen);
+-
+- rep.type = X_Reply;
+- rep.setOfRotations = pScrPriv->rotations;
+- rep.sequenceNumber = client->sequence;
+- rep.length = 0;
+- rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
+- rep.timestamp = pScrPriv->lastSetTime.milliseconds;
+- rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
+- rep.rotation = pScrPriv->rotation;
+- rep.nSizes = pScrPriv->nSizesInUse;
+- rep.rate = pScrPriv->rate;
+- rep.nrateEnts = 0;
+- if (has_rate)
+- {
+- for (i = 0; i < pScrPriv->nSizes; i++)
++ for (i = 0; i < pScrPriv->numCrtcs; i++)
+ {
+- RRScreenSizePtr pSize = &pScrPriv->pSizes[i];
+- if (pSize->referenced)
+- {
+- rep.nrateEnts += (1 + pSize->nRatesInUse);
+- }
++ RRCrtcPtr crtc = pScrPriv->crtcs[i];
++ if (crtc->changed)
++ RRDeliverCrtcEvent (client, pWin, crtc);
+ }
+ }
+-
+- if (pScrPriv->size >= 0)
+- rep.sizeID = pScrPriv->pSizes[pScrPriv->size].id;
+- else
+- return BadImplementation;
+-
+- extraLen = (rep.nSizes * sizeof (xScreenSizes) +
+- rep.nrateEnts * sizeof (CARD16));
+-
+- extra = (CARD8 *) xalloc (extraLen);
+- if (!extra)
+- return BadAlloc;
+- /*
+- * First comes the size information
+- */
+- size = (xScreenSizes *) extra;
+- rates = (CARD16 *) (size + rep.nSizes);
+- for (i = 0; i < pScrPriv->nSizes; i++)
++
++ if (pRREvent->mask & RROutputChangeNotifyMask)
+ {
+- RRScreenSizePtr pSize = &pScrPriv->pSizes[i];
+- if (pSize->referenced)
++ for (i = 0; i < pScrPriv->numOutputs; i++)
+ {
+- size->widthInPixels = pSize->width;
+- size->heightInPixels = pSize->height;
+- size->widthInMillimeters = pSize->mmWidth;
+- size->heightInMillimeters = pSize->mmHeight;
+- if (client->swapped)
+- {
+- swaps (&size->widthInPixels, n);
+- swaps (&size->heightInPixels, n);
+- swaps (&size->widthInMillimeters, n);
+- swaps (&size->heightInMillimeters, n);
+- }
+- size++;
+- if (has_rate)
+- {
+- *rates = pSize->nRatesInUse;
+- if (client->swapped)
+- {
+- swaps (rates, n);
+- }
+- rates++;
+- for (j = 0; j < pSize->nRates; j++)
+- {
+- RRScreenRatePtr pRate = &pSize->pRates[j];
+- if (pRate->referenced)
+- {
+- *rates = pRate->rate;
+- if (client->swapped)
+- {
+- swaps (rates, n);
+- }
+- rates++;
+- }
+- }
+- }
++ RROutputPtr output = pScrPriv->outputs[i];
++ if (output->changed)
++ RRDeliverOutputEvent (client, pWin, output);
+ }
+ }
+- data8 = (CARD8 *) rates;
+-
+- if (data8 - (CARD8 *) extra != extraLen)
+- FatalError ("RRGetScreenInfo bad extra len %ld != %ld\n",
+- (unsigned long)(data8 - (CARD8 *) extra), extraLen);
+- rep.length = (extraLen + 3) >> 2;
+- }
+- if (client->swapped) {
+- swaps(&rep.sequenceNumber, n);
+- swapl(&rep.length, n);
+- swapl(&rep.timestamp, n);
+- swaps(&rep.rotation, n);
+- swaps(&rep.nSizes, n);
+- swaps(&rep.sizeID, n);
+- swaps(&rep.rate, n);
+- swaps(&rep.nrateEnts, n);
+- }
+- WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *)&rep);
+- if (extraLen)
+- {
+- WriteToClient (client, extraLen, (char *) extra);
+- xfree (extra);
+ }
+- return (client->noClientException);
++ return WT_WALKCHILDREN;
+ }
+
+-static int
+-ProcRRSetScreenConfig (ClientPtr client)
++/*
++ * Something changed; send events and adjust pointer position
++ */
++void
++RRTellChanged (ScreenPtr pScreen)
+ {
+- REQUEST(xRRSetScreenConfigReq);
+- xRRSetScreenConfigReply rep;
+- DrawablePtr pDraw;
+- int n;
+- ScreenPtr pScreen;
+- rrScrPrivPtr pScrPriv;
+- TimeStamp configTime;
+- TimeStamp time;
+- RRScreenSizePtr pSize;
+- int i;
+- Rotation rotation;
+- int rate;
+- short oldWidth, oldHeight;
+- Bool has_rate;
+-
+- UpdateCurrentTime ();
+-
+- if (RRClientKnowsRates (client))
+- {
+- REQUEST_SIZE_MATCH (xRRSetScreenConfigReq);
+- has_rate = TRUE;
+- }
+- else
+- {
+- REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq);
+- has_rate = FALSE;
+- }
+-
+- SECURITY_VERIFY_DRAWABLE(pDraw, stuff->drawable, client,
+- SecurityWriteAccess);
+-
+- pScreen = pDraw->pScreen;
+-
+- pScrPriv = rrGetScrPriv(pScreen);
+-
+- time = ClientTimeToServerTime(stuff->timestamp);
+- configTime = ClientTimeToServerTime(stuff->configTimestamp);
+-
+- oldWidth = pScreen->width;
+- oldHeight = pScreen->height;
+-
+- if (!pScrPriv)
+- {
+- time = currentTime;
+- rep.status = RRSetConfigFailed;
+- goto sendReply;
+- }
+- if (!RRGetInfo (pScreen))
+- return BadAlloc;
+-
+- /*
+- * if the client's config timestamp is not the same as the last config
+- * timestamp, then the config information isn't up-to-date and
+- * can't even be validated
+- */
+- if (CompareTimeStamps (configTime, pScrPriv->lastConfigTime) != 0)
+- {
+- rep.status = RRSetConfigInvalidConfigTime;
+- goto sendReply;
+- }
+-
+- /*
+- * Search for the requested size
+- */
+- pSize = 0;
+- for (i = 0; i < pScrPriv->nSizes; i++)
+- {
+- pSize = &pScrPriv->pSizes[i];
+- if (pSize->referenced && pSize->id == stuff->sizeID)
+- {
+- break;
+- }
+- }
+- if (i == pScrPriv->nSizes)
+- {
+- /*
+- * Invalid size ID
+- */
+- client->errorValue = stuff->sizeID;
+- return BadValue;
+- }
++ rrScrPriv (pScreen);
++ int i;
+
+- /*
+- * Validate requested rotation
+- */
+- rotation = (Rotation) stuff->rotation;
+-
+- /* test the rotation bits only! */
+- switch (rotation & 0xf) {
+- case RR_Rotate_0:
+- case RR_Rotate_90:
+- case RR_Rotate_180:
+- case RR_Rotate_270:
+- break;
+- default:
+- /*
+- * Invalid rotation
+- */
+- client->errorValue = stuff->rotation;
+- return BadValue;
+- }
+-
+- if ((~pScrPriv->rotations) & rotation)
++ if (pScrPriv->changed)
+ {
+- /*
+- * requested rotation or reflection not supported by screen
+- */
+- client->errorValue = stuff->rotation;
+- return BadMatch;
+- }
+-
+- /*
+- * Validate requested refresh
+- */
+- if (has_rate)
+- rate = (int) stuff->rate;
+- else
+- rate = 0;
+-
+- if (rate)
+- {
+- for (i = 0; i < pSize->nRates; i++)
++ UpdateCurrentTime ();
++ if (pScrPriv->configChanged)
+ {
+- RRScreenRatePtr pRate = &pSize->pRates[i];
+- if (pRate->referenced && pRate->rate == rate)
+- break;
++ pScrPriv->lastConfigTime = currentTime;
++ pScrPriv->configChanged = FALSE;
+ }
+- if (i == pSize->nRates)
+- {
+- /*
+- * Invalid rate
+- */
+- client->errorValue = rate;
+- return BadValue;
++ pScrPriv->changed = FALSE;
++ WalkTree (pScreen, TellChanged, (pointer) pScreen);
++ for (i = 0; i < pScrPriv->numOutputs; i++)
++ pScrPriv->outputs[i]->changed = FALSE;
++ for (i = 0; i < pScrPriv->numCrtcs; i++)
++ pScrPriv->crtcs[i]->changed = FALSE;
++ if (pScrPriv->layoutChanged)
++ {
++ pScrPriv->layoutChanged = FALSE;
++ RRPointerScreenConfigured (pScreen);
++ RRSendConfigNotify (pScreen);
+ }
+ }
+-
+- /*
+- * Make sure the requested set-time is not older than
+- * the last set-time
+- */
+- if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0)
+- {
+- rep.status = RRSetConfigInvalidTime;
+- goto sendReply;
+- }
+-
+- /*
+- * call out to ddx routine to effect the change
+- */
+- if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate,
+- pSize))
+- {
+- /*
+- * unknown DDX failure, report to client
+- */
+- rep.status = RRSetConfigFailed;
+- goto sendReply;
+- }
+-
+- /*
+- * set current extension configuration pointers
+- */
+- RRSetCurrentConfig (pScreen, rotation, rate, pSize);
+-
+- /*
+- * Deliver ScreenChangeNotify events whenever
+- * the configuration is updated
+- */
+- WalkTree (pScreen, TellChanged, (pointer) pScreen);
+-
+- /*
+- * Deliver ConfigureNotify events when root changes
+- * pixel size
+- */
+- if (oldWidth != pScreen->width || oldHeight != pScreen->height)
+- RRSendConfigNotify (pScreen);
+- RREditConnectionInfo (pScreen);
+-
+- /*
+- * Fix pointer bounds and location
+- */
+- ScreenRestructured (pScreen);
+- pScrPriv->lastSetTime = time;
+-
+- /*
+- * Report Success
+- */
+- rep.status = RRSetConfigSuccess;
+-
+-sendReply:
+-
+- rep.type = X_Reply;
+- /* rep.status has already been filled in */
+- rep.length = 0;
+- rep.sequenceNumber = client->sequence;
+-
+- rep.newTimestamp = pScrPriv->lastSetTime.milliseconds;
+- rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds;
+- rep.root = WindowTable[pDraw->pScreen->myNum]->drawable.id;
+-
+- if (client->swapped)
+- {
+- swaps(&rep.sequenceNumber, n);
+- swapl(&rep.length, n);
+- swapl(&rep.newTimestamp, n);
+- swapl(&rep.newConfigTimestamp, n);
+- swapl(&rep.root, n);
+- }
+- WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *)&rep);
+-
+- return (client->noClientException);
+ }
+
+-int
+-RRSetScreenConfig (ScreenPtr pScreen,
+- Rotation rotation,
+- int rate,
+- RRScreenSizePtr pSize)
++/*
++ * Return the first output which is connected to an active CRTC
++ * Used in emulating 1.0 behaviour
++ */
++RROutputPtr
++RRFirstOutput (ScreenPtr pScreen)
+ {
+- rrScrPrivPtr pScrPriv;
+- int i;
+- short oldWidth, oldHeight;
+-
+- pScrPriv = rrGetScrPriv(pScreen);
+-
+- oldWidth = pScreen->width;
+- oldHeight = pScreen->height;
+-
+- if (!RRGetInfo (pScreen))
+- return BadAlloc;
++ rrScrPriv(pScreen);
++ RROutputPtr output;
++ int i, j;
+
+- /*
+- * Validate requested rotation
+- */
+-
+- /* test the rotation bits only! */
+- switch (rotation & 0xf) {
+- case RR_Rotate_0:
+- case RR_Rotate_90:
+- case RR_Rotate_180:
+- case RR_Rotate_270:
+- break;
+- default:
+- /*
+- * Invalid rotation
+- */
+- return BadValue;
+- }
+-
+- if ((~pScrPriv->rotations) & rotation)
+- {
+- /*
+- * requested rotation or reflection not supported by screen
+- */
+- return BadMatch;
+- }
+-
+- /*
+- * Validate requested refresh
+- */
+- if (rate)
++ for (i = 0; i < pScrPriv->numCrtcs; i++)
+ {
+- for (i = 0; i < pSize->nRates; i++)
+- {
+- RRScreenRatePtr pRate = &pSize->pRates[i];
+- if (pRate->referenced && pRate->rate == rate)
+- break;
+- }
+- if (i == pSize->nRates)
++ RRCrtcPtr crtc = pScrPriv->crtcs[i];
++ for (j = 0; j < pScrPriv->numOutputs; j++)
+ {
+- /*
+- * Invalid rate
+- */
+- return BadValue;
++ output = pScrPriv->outputs[j];
++ if (output->crtc == crtc)
++ return output;
+ }
+ }
+-
+- /*
+- * call out to ddx routine to effect the change
+- */
+- if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate,
+- pSize))
+- {
+- /*
+- * unknown DDX failure, report to client
+- */
+- return BadImplementation;
+- }
+-
+- /*
+- * set current extension configuration pointers
+- */
+- RRSetCurrentConfig (pScreen, rotation, rate, pSize);
+-
+- /*
+- * Deliver ScreenChangeNotify events whenever
+- * the configuration is updated
+- */
+- WalkTree (pScreen, TellChanged, (pointer) pScreen);
+-
+- /*
+- * Deliver ConfigureNotify events when root changes
+- * pixel size
+- */
+- if (oldWidth != pScreen->width || oldHeight != pScreen->height)
+- RRSendConfigNotify (pScreen);
+- RREditConnectionInfo (pScreen);
+-
+- /*
+- * Fix pointer bounds and location
+- */
+- ScreenRestructured (pScreen);
+-
+- return Success;
++ return NULL;
+ }
+
+-static int
+-ProcRRSelectInput (ClientPtr client)
++CARD16
++RRVerticalRefresh (xRRModeInfo *mode)
+ {
+- REQUEST(xRRSelectInputReq);
+- rrClientPriv(client);
+- RRTimesPtr pTimes;
+- WindowPtr pWin;
+- RREventPtr pRREvent, pNewRREvent, *pHead;
+- XID clientResource;
+-
+- REQUEST_SIZE_MATCH(xRRSelectInputReq);
+- pWin = SecurityLookupWindow (stuff->window, client, SecurityWriteAccess);
+- if (!pWin)
+- return BadWindow;
+- pHead = (RREventPtr *)SecurityLookupIDByType(client,
+- pWin->drawable.id, EventType,
+- SecurityWriteAccess);
+-
+- if (stuff->enable & (RRScreenChangeNotifyMask))
+- {
+- ScreenPtr pScreen = pWin->drawable.pScreen;
+- rrScrPriv (pScreen);
+-
+- if (pHead)
+- {
+- /* check for existing entry. */
+- for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
+- if (pRREvent->client == client)
+- return Success;
+- }
+-
+- /* build the entry */
+- pNewRREvent = (RREventPtr) xalloc (sizeof (RREventRec));
+- if (!pNewRREvent)
+- return BadAlloc;
+- pNewRREvent->next = 0;
+- pNewRREvent->client = client;
+- pNewRREvent->window = pWin;
+- pNewRREvent->mask = stuff->enable;
+- /*
+- * add a resource that will be deleted when
+- * the client goes away
+- */
+- clientResource = FakeClientID (client->index);
+- pNewRREvent->clientResource = clientResource;
+- if (!AddResource (clientResource, ClientType, (pointer)pNewRREvent))
+- return BadAlloc;
+- /*
+- * create a resource to contain a pointer to the list
+- * of clients selecting input. This must be indirect as
+- * the list may be arbitrarily rearranged which cannot be
+- * done through the resource database.
+- */
+- if (!pHead)
+- {
+- pHead = (RREventPtr *) xalloc (sizeof (RREventPtr));
+- if (!pHead ||
+- !AddResource (pWin->drawable.id, EventType, (pointer)pHead))
+- {
+- FreeResource (clientResource, RT_NONE);
+- return BadAlloc;
+- }
+- *pHead = 0;
+- }
+- pNewRREvent->next = *pHead;
+- *pHead = pNewRREvent;
+- /*
+- * Now see if the client needs an event
+- */
+- if (pScrPriv)
+- {
+- pTimes = &((RRTimesPtr) (pRRClient + 1))[pScreen->myNum];
+- if (CompareTimeStamps (pTimes->setTime,
+- pScrPriv->lastSetTime) != 0 ||
+- CompareTimeStamps (pTimes->configTime,
+- pScrPriv->lastConfigTime) != 0)
+- {
+- TellChanged (pWin, (pointer) pScreen);
+- }
+- }
+- }
+- else if (stuff->enable == xFalse)
+- {
+- /* delete the interest */
+- if (pHead) {
+- pNewRREvent = 0;
+- for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
+- if (pRREvent->client == client)
+- break;
+- pNewRREvent = pRREvent;
+- }
+- if (pRREvent) {
+- FreeResource (pRREvent->clientResource, ClientType);
+- if (pNewRREvent)
+- pNewRREvent->next = pRREvent->next;
+- else
+- *pHead = pRREvent->next;
+- xfree (pRREvent);
+- }
+- }
+- }
+- else
+- {
+- client->errorValue = stuff->enable;
+- return BadValue;
+- }
+- return Success;
++ CARD32 refresh;
++ CARD32 dots = mode->hTotal * mode->vTotal;
++ if (!dots)
++ return 0;
++ refresh = (mode->dotClock + dots/2) / dots;
++ if (refresh > 0xffff)
++ refresh = 0xffff;
++ return (CARD16) refresh;
+ }
+
+-
+ static int
+ ProcRRDispatch (ClientPtr client)
+ {
+ REQUEST(xReq);
+- switch (stuff->data)
+- {
+- case X_RRQueryVersion:
+- return ProcRRQueryVersion(client);
+- case X_RRSetScreenConfig:
+- return ProcRRSetScreenConfig(client);
+- case X_RRSelectInput:
+- return ProcRRSelectInput(client);
+- case X_RRGetScreenInfo:
+- return ProcRRGetScreenInfo(client);
+- default:
++ if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data])
+ return BadRequest;
+- }
+-}
+-
+-static int
+-SProcRRQueryVersion (ClientPtr client)
+-{
+- register int n;
+- REQUEST(xRRQueryVersionReq);
+-
+- swaps(&stuff->length, n);
+- swapl(&stuff->majorVersion, n);
+- swapl(&stuff->minorVersion, n);
+- return ProcRRQueryVersion(client);
+-}
+-
+-static int
+-SProcRRGetScreenInfo (ClientPtr client)
+-{
+- register int n;
+- REQUEST(xRRGetScreenInfoReq);
+-
+- swaps(&stuff->length, n);
+- swapl(&stuff->window, n);
+- return ProcRRGetScreenInfo(client);
+-}
+-
+-static int
+-SProcRRSetScreenConfig (ClientPtr client)
+-{
+- register int n;
+- REQUEST(xRRSetScreenConfigReq);
+-
+- if (RRClientKnowsRates (client))
+- {
+- REQUEST_SIZE_MATCH (xRRSetScreenConfigReq);
+- swaps (&stuff->rate, n);
+- }
+- else
+- {
+- REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq);
+- }
+-
+- swaps(&stuff->length, n);
+- swapl(&stuff->drawable, n);
+- swapl(&stuff->timestamp, n);
+- swaps(&stuff->sizeID, n);
+- swaps(&stuff->rotation, n);
+- return ProcRRSetScreenConfig(client);
+-}
+-
+-static int
+-SProcRRSelectInput (ClientPtr client)
+-{
+- register int n;
+- REQUEST(xRRSelectInputReq);
+-
+- swaps(&stuff->length, n);
+- swapl(&stuff->window, n);
+- return ProcRRSelectInput(client);
++ return (*ProcRandrVector[stuff->data]) (client);
+ }
+
+-
+ static int
+ SProcRRDispatch (ClientPtr client)
+ {
+ REQUEST(xReq);
+- switch (stuff->data)
+- {
+- case X_RRQueryVersion:
+- return SProcRRQueryVersion(client);
+- case X_RRSetScreenConfig:
+- return SProcRRSetScreenConfig(client);
+- case X_RRSelectInput:
+- return SProcRRSelectInput(client);
+- case X_RRGetScreenInfo:
+- return SProcRRGetScreenInfo(client);
+- default:
++ if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data])
+ return BadRequest;
+- }
+-}
+-
+-
+-static Bool
+-RRScreenSizeMatches (RRScreenSizePtr a,
+- RRScreenSizePtr b)
+-{
+- if (a->width != b->width)
+- return FALSE;
+- if (a->height != b->height)
+- return FALSE;
+- if (a->mmWidth != b->mmWidth)
+- return FALSE;
+- if (a->mmHeight != b->mmHeight)
+- return FALSE;
+- return TRUE;
+-}
+-
+-RRScreenSizePtr
+-RRRegisterSize (ScreenPtr pScreen,
+- short width,
+- short height,
+- short mmWidth,
+- short mmHeight)
+-{
+- rrScrPriv (pScreen);
+- int i;
+- RRScreenSize tmp;
+- RRScreenSizePtr pNew;
+-
+- if (!pScrPriv)
+- return 0;
+-
+- tmp.width = width;
+- tmp.height= height;
+- tmp.mmWidth = mmWidth;
+- tmp.mmHeight = mmHeight;
+- tmp.pRates = 0;
+- tmp.nRates = 0;
+- tmp.nRatesInUse = 0;
+- tmp.referenced = TRUE;
+- tmp.oldReferenced = FALSE;
+- for (i = 0; i < pScrPriv->nSizes; i++)
+- if (RRScreenSizeMatches (&tmp, &pScrPriv->pSizes[i]))
+- {
+- pScrPriv->pSizes[i].referenced = TRUE;
+- return &pScrPriv->pSizes[i];
+- }
+- pNew = xrealloc (pScrPriv->pSizes,
+- (pScrPriv->nSizes + 1) * sizeof (RRScreenSize));
+- if (!pNew)
+- return 0;
+- pNew[pScrPriv->nSizes++] = tmp;
+- pScrPriv->pSizes = pNew;
+- return &pNew[pScrPriv->nSizes-1];
+-}
+-
+-Bool RRRegisterRate (ScreenPtr pScreen,
+- RRScreenSizePtr pSize,
+- int rate)
+-{
+- rrScrPriv(pScreen);
+- int i;
+- RRScreenRatePtr pNew, pRate;
+-
+- if (!pScrPriv)
+- return FALSE;
+-
+- for (i = 0; i < pSize->nRates; i++)
+- {
+- pRate = &pSize->pRates[i];
+- if (pRate->rate == rate)
+- {
+- pRate->referenced = TRUE;
+- return TRUE;
+- }
+- }
+-
+- pNew = xrealloc (pSize->pRates,
+- (pSize->nRates + 1) * sizeof (RRScreenRate));
+- if (!pNew)
+- return FALSE;
+- pRate = &pNew[pSize->nRates++];
+- pRate->rate = rate;
+- pRate->referenced = TRUE;
+- pRate->oldReferenced = FALSE;
+- pSize->pRates = pNew;
+- return TRUE;
++ return (*SProcRandrVector[stuff->data]) (client);
+ }
+
+-void
+-RRSetCurrentConfig (ScreenPtr pScreen,
+- Rotation rotation,
+- int rate,
+- RRScreenSizePtr pSize)
+-{
+- rrScrPriv (pScreen);
+-
+- if (!pScrPriv)
+- return;
+-
+- pScrPriv->rotation = rotation;
+- pScrPriv->size = pSize - pScrPriv->pSizes;
+- pScrPriv->rate = rate;
+-}
+Only in ./nx-X11/programs/Xserver/randr: randr.c.NX.original
+Only in ./nx-X11/programs/Xserver/randr: randr.c.X.original
+Only in ./nx-X11/programs/Xserver/randr: randr.h
+Only in ./nx-X11/programs/Xserver/randr: randr.h.NX.original
+Only in ./nx-X11/programs/Xserver/randr: randr.h.X.original
+Only in ./nx-X11/programs/Xserver/randr: randrproto.h
+Only in ./nx-X11/programs/Xserver/randr: randrproto.h.NX.original
+Only in ./nx-X11/programs/Xserver/randr: randrproto.h.X.original
+diff -u ./nx-X11/programs/Xserver/randr.X.original/randrstr.h ./nx-X11/programs/Xserver/randr/randrstr.h
+--- ./nx-X11/programs/Xserver/randr.X.original/randrstr.h 2015-02-13 14:03:44.792440567 +0100
++++ ./nx-X11/programs/Xserver/randr/randrstr.h 2015-02-10 19:13:13.636692176 +0100
+@@ -1,25 +1,28 @@
+ /*
+- * $XFree86: xc/programs/Xserver/randr/randrstr.h,v 1.5 2002/09/29 23:39:45 keithp Exp $
+- *
+ * Copyright © 2000 Compaq Computer Corporation
++ * Copyright © 2002 Hewlett-Packard Company
++ * Copyright © 2006 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+- * the above copyright notice appear in all copies and that both that
+- * copyright notice and this permission notice appear in supporting
+- * documentation, and that the name of Compaq not be used in
+- * advertising or publicity pertaining to distribution of the software without
+- * specific, written prior permission. Compaq makes no
+- * representations about the suitability of this software for any purpose. It
+- * is provided "as is" without express or implied warranty.
++ * the above copyright notice appear in all copies and that both that copyright
++ * notice and this permission notice appear in supporting documentation, and
++ * that the name of the copyright holders not be used in advertising or
++ * publicity pertaining to distribution of the software without specific,
++ * written prior permission. The copyright holders make no representations
++ * about the suitability of this software for any purpose. It is provided "as
++ * is" without express or implied warranty.
+ *
+- * COMPAQ DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+- * EVENT SHALL COMPAQ BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+- * PERFORMANCE OF THIS SOFTWARE.
++ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
++ * OF THIS SOFTWARE.
++ *
++ * Author: Jim Gettys, Hewlett-Packard Company, Inc.
++ * Keith Packard, Intel Corporation
+ */
+
+ #ifdef HAVE_DIX_CONFIG_H
+@@ -29,68 +32,456 @@
+ #ifndef _RANDRSTR_H_
+ #define _RANDRSTR_H_
+
++#include <X11/X.h>
++#include <X11/Xproto.h>
++#include "misc.h"
++#include "os.h"
++#include "dixstruct.h"
++#include "resource.h"
++#include "scrnintstr.h"
++#include "windowstr.h"
++#include "pixmapstr.h"
++#include "extnsionst.h"
++#include "servermd.h"
++#ifndef NXAGENT_SERVER
+ #include <X11/extensions/randr.h>
++#include <X11/extensions/randrproto.h>
++#else
++#include "randr.h"
++#include "randrproto.h"
++#endif
++#ifdef RENDER
++#include <X11/extensions/render.h> /* we share subpixel order information */
++#include "picturestr.h"
++#endif
++#include <X11/Xfuncproto.h>
++
++/* required for ABI compatibility for now */
++#define RANDR_10_INTERFACE 1
++#define RANDR_12_INTERFACE 1
++
++typedef XID RRMode;
++typedef XID RROutput;
++typedef XID RRCrtc;
++
++extern int RREventBase, RRErrorBase;
++
++extern int (*ProcRandrVector[RRNumberRequests])(ClientPtr);
++extern int (*SProcRandrVector[RRNumberRequests])(ClientPtr);
++
++/*
++ * Modeline for a monitor. Name follows directly after this struct
++ */
++
++#define RRModeName(pMode) ((char *) (pMode + 1))
++typedef struct _rrMode RRModeRec, *RRModePtr;
++typedef struct _rrPropertyValue RRPropertyValueRec, *RRPropertyValuePtr;
++typedef struct _rrProperty RRPropertyRec, *RRPropertyPtr;
++typedef struct _rrCrtc RRCrtcRec, *RRCrtcPtr;
++typedef struct _rrOutput RROutputRec, *RROutputPtr;
++
++struct _rrMode {
++ int refcnt;
++ xRRModeInfo mode;
++ char *name;
++ ScreenPtr userScreen;
++};
++
++struct _rrPropertyValue {
++ Atom type; /* ignored by server */
++ short format; /* format of data for swapping - 8,16,32 */
++ long size; /* size of data in (format/8) bytes */
++ pointer data; /* private to client */
++};
++
++struct _rrProperty {
++ RRPropertyPtr next;
++ ATOM propertyName;
++ Bool is_pending;
++ Bool range;
++ Bool immutable;
++ int num_valid;
++ INT32 *valid_values;
++ RRPropertyValueRec current, pending;
++};
++
++struct _rrCrtc {
++ RRCrtc id;
++ ScreenPtr pScreen;
++ RRModePtr mode;
++ int x, y;
++ Rotation rotation;
++ Rotation rotations;
++ Bool changed;
++ int numOutputs;
++ RROutputPtr *outputs;
++ int gammaSize;
++ CARD16 *gammaRed;
++ CARD16 *gammaBlue;
++ CARD16 *gammaGreen;
++ void *devPrivate;
++};
++
++struct _rrOutput {
++ RROutput id;
++ ScreenPtr pScreen;
++ char *name;
++ int nameLength;
++ CARD8 connection;
++ CARD8 subpixelOrder;
++ int mmWidth;
++ int mmHeight;
++ RRCrtcPtr crtc;
++ int numCrtcs;
++ RRCrtcPtr *crtcs;
++ int numClones;
++ RROutputPtr *clones;
++ int numModes;
++ int numPreferred;
++ RRModePtr *modes;
++ int numUserModes;
++ RRModePtr *userModes;
++ Bool changed;
++ RRPropertyPtr properties;
++ Bool pendingProperties;
++ void *devPrivate;
++};
++
++#if RANDR_12_INTERFACE
++typedef Bool (*RRScreenSetSizeProcPtr) (ScreenPtr pScreen,
++ CARD16 width,
++ CARD16 height,
++ CARD32 mmWidth,
++ CARD32 mmHeight);
++
++typedef Bool (*RRCrtcSetProcPtr) (ScreenPtr pScreen,
++ RRCrtcPtr crtc,
++ RRModePtr mode,
++ int x,
++ int y,
++ Rotation rotation,
++ int numOutputs,
++ RROutputPtr *outputs);
++
++typedef Bool (*RRCrtcSetGammaProcPtr) (ScreenPtr pScreen,
++ RRCrtcPtr crtc);
++
++typedef Bool (*RROutputSetPropertyProcPtr) (ScreenPtr pScreen,
++ RROutputPtr output,
++ Atom property,
++ RRPropertyValuePtr value);
++
++typedef Bool (*RROutputValidateModeProcPtr) (ScreenPtr pScreen,
++ RROutputPtr output,
++ RRModePtr mode);
++
++typedef void (*RRModeDestroyProcPtr) (ScreenPtr pScreen,
++ RRModePtr mode);
++
++#endif
++
++typedef Bool (*RRGetInfoProcPtr) (ScreenPtr pScreen, Rotation *rotations);
++typedef Bool (*RRCloseScreenProcPtr) ( int i, ScreenPtr pscreen);
+
+-typedef struct _rrScreenRate {
+- int rate;
+- Bool referenced;
+- Bool oldReferenced;
++/* These are for 1.0 compatibility */
++
++typedef struct _rrRefresh {
++ CARD16 rate;
++ RRModePtr mode;
+ } RRScreenRate, *RRScreenRatePtr;
+
+ typedef struct _rrScreenSize {
+ int id;
+ short width, height;
+ short mmWidth, mmHeight;
+- RRScreenRatePtr pRates;
+ int nRates;
+- int nRatesInUse;
+- Bool referenced;
+- Bool oldReferenced;
++ RRScreenRatePtr pRates;
+ } RRScreenSize, *RRScreenSizePtr;
+
++#ifdef RANDR_10_INTERFACE
++
+ typedef Bool (*RRSetConfigProcPtr) (ScreenPtr pScreen,
+ Rotation rotation,
+ int rate,
+ RRScreenSizePtr pSize);
+
+-typedef Bool (*RRGetInfoProcPtr) (ScreenPtr pScreen, Rotation *rotations);
+-typedef Bool (*RRCloseScreenProcPtr) ( int i, ScreenPtr pscreen);
++#endif
+
++
+ typedef struct _rrScrPriv {
++ /*
++ * 'public' part of the structure; DDXen fill this in
++ * as they initialize
++ */
++#if RANDR_10_INTERFACE
+ RRSetConfigProcPtr rrSetConfig;
++#endif
+ RRGetInfoProcPtr rrGetInfo;
++#if RANDR_12_INTERFACE
++ RRScreenSetSizeProcPtr rrScreenSetSize;
++ RRCrtcSetProcPtr rrCrtcSet;
++ RRCrtcSetGammaProcPtr rrCrtcSetGamma;
++ RROutputSetPropertyProcPtr rrOutputSetProperty;
++ RROutputValidateModeProcPtr rrOutputValidateMode;
++ RRModeDestroyProcPtr rrModeDestroy;
++#endif
+
++ /*
++ * Private part of the structure; not considered part of the ABI
++ */
+ TimeStamp lastSetTime; /* last changed by client */
+ TimeStamp lastConfigTime; /* possible configs changed */
+ RRCloseScreenProcPtr CloseScreen;
+
++ Bool changed; /* some config changed */
++ Bool configChanged; /* configuration changed */
++ Bool layoutChanged; /* screen layout changed */
++
++ CARD16 minWidth, minHeight;
++ CARD16 maxWidth, maxHeight;
++ CARD16 width, height; /* last known screen size */
++ CARD16 mmWidth, mmHeight; /* last known screen size */
++
++ int numOutputs;
++ RROutputPtr *outputs;
++
++ int numCrtcs;
++ RRCrtcPtr *crtcs;
++
++ /* Last known pointer position */
++ RRCrtcPtr pointerCrtc;
++
++#ifdef RANDR_10_INTERFACE
+ /*
+ * Configuration information
+ */
+ Rotation rotations;
++ CARD16 reqWidth, reqHeight;
+
+ int nSizes;
+- int nSizesInUse;
+ RRScreenSizePtr pSizes;
+-
+- /*
+- * Current state
+- */
++
+ Rotation rotation;
+- int size;
+ int rate;
++ int size;
++#endif
+ } rrScrPrivRec, *rrScrPrivPtr;
+
++#ifndef NXAGENT_SERVER
++extern DevPrivateKey rrPrivKey;
++#else
+ extern int rrPrivIndex;
++#endif
++
++#ifndef NXAGENT_SERVER
++
++#define rrGetScrPriv(pScr) ((rrScrPrivPtr)dixLookupPrivate(&(pScr)->devPrivates, rrPrivKey))
++#define rrScrPriv(pScr) rrScrPrivPtr pScrPriv = rrGetScrPriv(pScr)
++#define SetRRScreen(s,p) dixSetPrivate(&(s)->devPrivates, rrPrivKey, p)
++
++#else
+
+ #define rrGetScrPriv(pScr) ((rrScrPrivPtr) (pScr)->devPrivates[rrPrivIndex].ptr)
+ #define rrScrPriv(pScr) rrScrPrivPtr pScrPriv = rrGetScrPriv(pScr)
+ #define SetRRScreen(s,p) ((s)->devPrivates[rrPrivIndex].ptr = (pointer) (p))
+
++#endif
++
++/*
++ * each window has a list of clients requesting
++ * RRNotify events. Each client has a resource
++ * for each window it selects RRNotify input for,
++ * this resource is used to delete the RRNotifyRec
++ * entry from the per-window queue.
++ */
++
++typedef struct _RREvent *RREventPtr;
++
++typedef struct _RREvent {
++ RREventPtr next;
++ ClientPtr client;
++ WindowPtr window;
++ XID clientResource;
++ int mask;
++} RREventRec;
++
++typedef struct _RRTimes {
++ TimeStamp setTime;
++ TimeStamp configTime;
++} RRTimesRec, *RRTimesPtr;
++
++typedef struct _RRClient {
++ int major_version;
++ int minor_version;
++/* RRTimesRec times[0]; */
++} RRClientRec, *RRClientPtr;
++
++extern RESTYPE RRClientType, RREventType; /* resource types for event masks */
++#ifndef NXAGENT_SERVER
++extern DevPrivateKey RRClientPrivateKey;
++#else
++extern int RRClientPrivateIndex;
++#endif
++extern RESTYPE RRCrtcType, RRModeType, RROutputType;
++
++#define LookupOutput(client,id,a) ((RROutputPtr) \
++ (SecurityLookupIDByType (client, id, \
++ RROutputType, a)))
++#define LookupCrtc(client,id,a) ((RRCrtcPtr) \
++ (SecurityLookupIDByType (client, id, \
++ RRCrtcType, a)))
++#define LookupMode(client,id,a) ((RRModePtr) \
++ (SecurityLookupIDByType (client, id, \
++ RRModeType, a)))
++#ifndef NXAGENT_SERVER
++
++#define GetRRClient(pClient) ((RRClientPtr)dixLookupPrivate(&(pClient)->devPrivates, RRClientPrivateKey))
++#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient)
++
++#else
++
++#define GetRRClient(pClient) ((RRClientPtr) (pClient)->devPrivates[RRClientPrivateIndex].ptr)
++#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient)
++
++#define DixUnknownAccess SecurityUnknownAccess
++#define DixReadAccess SecurityReadAccess
++#define DixWriteAccess SecurityWriteAccess
++#define DixDestroyAccess SecurityDestroyAccess
++
++#endif
++
+ /* Initialize the extension */
+ void
+ RRExtensionInit (void);
+
++#ifdef RANDR_12_INTERFACE
++/*
++ * Set the range of sizes for the screen
++ */
++void
++RRScreenSetSizeRange (ScreenPtr pScreen,
++ CARD16 minWidth,
++ CARD16 minHeight,
++ CARD16 maxWidth,
++ CARD16 maxHeight);
++#endif
++
++/* rrscreen.c */
++/*
++ * Notify the extension that the screen size has been changed.
++ * The driver is responsible for calling this whenever it has changed
++ * the size of the screen
++ */
++void
++RRScreenSizeNotify (ScreenPtr pScreen);
++
++/*
++ * Request that the screen be resized
++ */
++Bool
++RRScreenSizeSet (ScreenPtr pScreen,
++ CARD16 width,
++ CARD16 height,
++ CARD32 mmWidth,
++ CARD32 mmHeight);
++
++/*
++ * Send ConfigureNotify event to root window when 'something' happens
++ */
++void
++RRSendConfigNotify (ScreenPtr pScreen);
++
++/*
++ * screen dispatch
++ */
++int
++ProcRRGetScreenSizeRange (ClientPtr client);
++
++int
++ProcRRSetScreenSize (ClientPtr client);
++
++int
++ProcRRGetScreenResources (ClientPtr client);
++
++int
++ProcRRSetScreenConfig (ClientPtr client);
++
++int
++ProcRRGetScreenInfo (ClientPtr client);
++
++/*
++ * Deliver a ScreenNotify event
++ */
++void
++RRDeliverScreenEvent (ClientPtr client, WindowPtr pWin, ScreenPtr pScreen);
++
++/* mirandr.c */
++Bool
++miRandRInit (ScreenPtr pScreen);
++
++Bool
++miRRGetInfo (ScreenPtr pScreen, Rotation *rotations);
++
++Bool
++miRRGetScreenInfo (ScreenPtr pScreen);
++
++Bool
++miRRCrtcSet (ScreenPtr pScreen,
++ RRCrtcPtr crtc,
++ RRModePtr mode,
++ int x,
++ int y,
++ Rotation rotation,
++ int numOutput,
++ RROutputPtr *outputs);
++
++Bool
++miRROutputSetProperty (ScreenPtr pScreen,
++ RROutputPtr output,
++ Atom property,
++ RRPropertyValuePtr value);
++
++Bool
++miRROutputValidateMode (ScreenPtr pScreen,
++ RROutputPtr output,
++ RRModePtr mode);
++
++void
++miRRModeDestroy (ScreenPtr pScreen,
++ RRModePtr mode);
++
++/* randr.c */
++/*
++ * Send all pending events
++ */
++void
++RRTellChanged (ScreenPtr pScreen);
++
++/*
++ * Poll the driver for changed information
++ */
++Bool
++RRGetInfo (ScreenPtr pScreen);
++
++Bool RRInit (void);
++
++Bool RRScreenInit(ScreenPtr pScreen);
++
++RROutputPtr
++RRFirstOutput (ScreenPtr pScreen);
++
++Rotation
++RRGetRotation (ScreenPtr pScreen);
++
++CARD16
++RRVerticalRefresh (xRRModeInfo *mode);
++
++#ifdef RANDR_10_INTERFACE
++/*
++ * This is the old interface, deprecated but left
++ * around for compatibility
++ */
++
+ /*
+ * Then, register the specific size with the screen
+ */
+@@ -116,7 +507,10 @@
+ int rate,
+ RRScreenSizePtr pSize);
+
+-Bool RRScreenInit(ScreenPtr pScreen);
++Bool RRScreenInit (ScreenPtr pScreen);
++
++Rotation
++RRGetRotation (ScreenPtr pScreen);
+
+ int
+ RRSetScreenConfig (ScreenPtr pScreen,
+@@ -124,19 +518,371 @@
+ int rate,
+ RRScreenSizePtr pSize);
+
++#endif
++
++/* rrcrtc.c */
++
++/*
++ * Notify the CRTC of some change; layoutChanged indicates that
++ * some position or size element changed
++ */
++void
++RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged);
++
++/*
++ * Create a CRTC
++ */
++RRCrtcPtr
++RRCrtcCreate (ScreenPtr pScreen, void *devPrivate);
++
++/*
++ * Set the allowed rotations on a CRTC
++ */
++void
++RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations);
++
++/*
++ * Notify the extension that the Crtc has been reconfigured,
++ * the driver calls this whenever it has updated the mode
++ */
++Bool
++RRCrtcNotify (RRCrtcPtr crtc,
++ RRModePtr mode,
++ int x,
++ int y,
++ Rotation rotation,
++ int numOutputs,
++ RROutputPtr *outputs);
++
++void
++RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc);
++
++/*
++ * Request that the Crtc be reconfigured
++ */
+ Bool
+-miRandRInit (ScreenPtr pScreen);
++RRCrtcSet (RRCrtcPtr crtc,
++ RRModePtr mode,
++ int x,
++ int y,
++ Rotation rotation,
++ int numOutput,
++ RROutputPtr *outputs);
++
++/*
++ * Request that the Crtc gamma be changed
++ */
+
+ Bool
+-miRRGetInfo (ScreenPtr pScreen, Rotation *rotations);
++RRCrtcGammaSet (RRCrtcPtr crtc,
++ CARD16 *red,
++ CARD16 *green,
++ CARD16 *blue);
++
++/*
++ * Notify the extension that the Crtc gamma has been changed
++ * The driver calls this whenever it has changed the gamma values
++ * in the RRCrtcRec
++ */
+
+ Bool
+-miRRSetConfig (ScreenPtr pScreen,
+- Rotation rotation,
+- int rate,
+- RRScreenSizePtr size);
++RRCrtcGammaNotify (RRCrtcPtr crtc);
++
++/*
++ * Set the size of the gamma table at server startup time
++ */
+
+ Bool
+-miRRGetScreenInfo (ScreenPtr pScreen);
++RRCrtcGammaSetSize (RRCrtcPtr crtc,
++ int size);
++
++/*
++ * Return the area of the frame buffer scanned out by the crtc,
++ * taking into account the current mode and rotation
++ */
++
++void
++RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height);
++
++/*
++ * Destroy a Crtc at shutdown
++ */
++void
++RRCrtcDestroy (RRCrtcPtr crtc);
++
++/*
++ * Initialize crtc type
++ */
++Bool
++RRCrtcInit (void);
++
++/*
++ * Crtc dispatch
++ */
++
++int
++ProcRRGetCrtcInfo (ClientPtr client);
++
++int
++ProcRRSetCrtcConfig (ClientPtr client);
++
++int
++ProcRRGetCrtcGammaSize (ClientPtr client);
++
++int
++ProcRRGetCrtcGamma (ClientPtr client);
++
++int
++ProcRRSetCrtcGamma (ClientPtr client);
++
++/* rrdispatch.c */
++Bool
++RRClientKnowsRates (ClientPtr pClient);
++
++/* rrmode.c */
++/*
++ * Find, and if necessary, create a mode
++ */
++
++RRModePtr
++RRModeGet (xRRModeInfo *modeInfo,
++ const char *name);
++
++void
++RRModePruneUnused (ScreenPtr pScreen);
++
++/*
++ * Destroy a mode.
++ */
++
++void
++RRModeDestroy (RRModePtr mode);
++
++/*
++ * Return a list of modes that are valid for some output in pScreen
++ */
++RRModePtr *
++RRModesForScreen (ScreenPtr pScreen, int *num_ret);
++
++/*
++ * Initialize mode type
++ */
++Bool
++RRModeInit (void);
++
++int
++ProcRRCreateMode (ClientPtr client);
++
++int
++ProcRRDestroyMode (ClientPtr client);
++
++int
++ProcRRAddOutputMode (ClientPtr client);
++
++int
++ProcRRDeleteOutputMode (ClientPtr client);
++
++/* rroutput.c */
++
++/*
++ * Notify the output of some change. configChanged indicates whether
++ * any external configuration (mode list, clones, connected status)
++ * has changed, or whether the change was strictly internal
++ * (which crtc is in use)
++ */
++void
++RROutputChanged (RROutputPtr output, Bool configChanged);
++
++/*
++ * Create an output
++ */
++
++RROutputPtr
++RROutputCreate (ScreenPtr pScreen,
++ const char *name,
++ int nameLength,
++ void *devPrivate);
++
++/*
++ * Notify extension that output parameters have been changed
++ */
++Bool
++RROutputSetClones (RROutputPtr output,
++ RROutputPtr *clones,
++ int numClones);
++
++Bool
++RROutputSetModes (RROutputPtr output,
++ RRModePtr *modes,
++ int numModes,
++ int numPreferred);
++
++int
++RROutputAddUserMode (RROutputPtr output,
++ RRModePtr mode);
++
++int
++RROutputDeleteUserMode (RROutputPtr output,
++ RRModePtr mode);
++
++Bool
++RROutputSetCrtcs (RROutputPtr output,
++ RRCrtcPtr *crtcs,
++ int numCrtcs);
++
++Bool
++RROutputSetConnection (RROutputPtr output,
++ CARD8 connection);
++
++Bool
++RROutputSetSubpixelOrder (RROutputPtr output,
++ int subpixelOrder);
++
++Bool
++RROutputSetPhysicalSize (RROutputPtr output,
++ int mmWidth,
++ int mmHeight);
++
++void
++RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output);
++
++void
++RROutputDestroy (RROutputPtr output);
++
++int
++ProcRRGetOutputInfo (ClientPtr client);
++
++/*
++ * Initialize output type
++ */
++Bool
++RROutputInit (void);
++
++/* rrpointer.c */
++void
++RRPointerMoved (ScreenPtr pScreen, int x, int y);
++
++void
++RRPointerScreenConfigured (ScreenPtr pScreen);
++
++/* rrproperty.c */
++
++void
++RRDeleteAllOutputProperties (RROutputPtr output);
++
++RRPropertyValuePtr
++RRGetOutputProperty (RROutputPtr output, Atom property, Bool pending);
++
++RRPropertyPtr
++RRQueryOutputProperty (RROutputPtr output, Atom property);
++
++void
++RRDeleteOutputProperty (RROutputPtr output, Atom property);
++
++Bool
++RRPostPendingProperties (RROutputPtr output);
++
++int
++RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
++ int format, int mode, unsigned long len,
++ pointer value, Bool sendevent, Bool pending);
++
++int
++RRConfigureOutputProperty (RROutputPtr output, Atom property,
++ Bool pending, Bool range, Bool immutable,
++ int num_values, INT32 *values);
++int
++ProcRRChangeOutputProperty (ClientPtr client);
++
++int
++ProcRRGetOutputProperty (ClientPtr client);
++
++int
++ProcRRListOutputProperties (ClientPtr client);
++
++int
++ProcRRQueryOutputProperty (ClientPtr client);
++
++int
++ProcRRConfigureOutputProperty (ClientPtr client);
++
++int
++ProcRRDeleteOutputProperty (ClientPtr client);
++
++/* rrxinerama.c */
++void
++RRXineramaExtensionInit(void);
+
+ #endif /* _RANDRSTR_H_ */
++
++/*
++
++randr extension implementation structure
++
++Query state:
++ ProcRRGetScreenInfo/ProcRRGetScreenResources
++ RRGetInfo
++
++ • Request configuration from driver, either 1.0 or 1.2 style
++ • These functions only record state changes, all
++ other actions are pended until RRTellChanged is called
++
++ ->rrGetInfo
++ 1.0:
++ RRRegisterSize
++ RRRegisterRate
++ RRSetCurrentConfig
++ 1.2:
++ RRScreenSetSizeRange
++ RROutputSetCrtcs
++ RRModeGet
++ RROutputSetModes
++ RROutputSetConnection
++ RROutputSetSubpixelOrder
++ RROutputSetClones
++ RRCrtcNotify
++
++ • Must delay scanning configuration until after ->rrGetInfo returns
++ because some drivers will call SetCurrentConfig in the middle
++ of the ->rrGetInfo operation.
++
++ 1.0:
++
++ • Scan old configuration, mirror to new structures
++
++ RRScanOldConfig
++ RRCrtcCreate
++ RROutputCreate
++ RROutputSetCrtcs
++ RROutputSetConnection
++ RROutputSetSubpixelOrder
++ RROldModeAdd • This adds modes one-at-a-time
++ RRModeGet
++ RRCrtcNotify
++
++ • send events, reset pointer if necessary
++
++ RRTellChanged
++ WalkTree (sending events)
++
++ • when layout has changed:
++ RRPointerScreenConfigured
++ RRSendConfigNotify
++
++Asynchronous state setting (1.2 only)
++ When setting state asynchronously, the driver invokes the
++ ->rrGetInfo function and then calls RRTellChanged to flush
++ the changes to the clients and reset pointer if necessary
++
++Set state
++
++ ProcRRSetScreenConfig
++ RRCrtcSet
++ 1.2:
++ ->rrCrtcSet
++ RRCrtcNotify
++ 1.0:
++ ->rrSetConfig
++ RRCrtcNotify
++ RRTellChanged
++ */
+Only in ./nx-X11/programs/Xserver/randr: registry.h
+Only in ./nx-X11/programs/Xserver/randr: registry.h.NX.original
+Only in ./nx-X11/programs/Xserver/randr: registry.h.X.original
+Only in ./nx-X11/programs/Xserver/randr: rrcrtc.c
+Only in ./nx-X11/programs/Xserver/randr: rrcrtc.c.NX.original
+Only in ./nx-X11/programs/Xserver/randr: rrcrtc.c.X.original
+Only in ./nx-X11/programs/Xserver/randr: rrdispatch.c
+Only in ./nx-X11/programs/Xserver/randr: rrdispatch.c.X.original
+Only in ./nx-X11/programs/Xserver/randr: rrinfo.c
+Only in ./nx-X11/programs/Xserver/randr: rrmode.c
+Only in ./nx-X11/programs/Xserver/randr: rrmode.c.NX.original
+Only in ./nx-X11/programs/Xserver/randr: rrmode.c.X.original
+Only in ./nx-X11/programs/Xserver/randr: rroutput.c
+Only in ./nx-X11/programs/Xserver/randr: rrpointer.c
+Only in ./nx-X11/programs/Xserver/randr: rrproperty.c
+Only in ./nx-X11/programs/Xserver/randr: rrscreen.c
+Only in ./nx-X11/programs/Xserver/randr: rrscreen.c.NX.original
+Only in ./nx-X11/programs/Xserver/randr: rrscreen.c.X.original
+Only in ./nx-X11/programs/Xserver/randr: rrsdispatch.c
+Only in ./nx-X11/programs/Xserver/randr: rrxinerama.c
+Only in ./nx-X11/programs/Xserver/randr: rrxinerama.c.NX.original
+Only in ./nx-X11/programs/Xserver/randr: rrxinerama.c.X.original
diff --git a/doc/nx-X11_vs_XOrg69_patches/randr.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/randr.c.NX.patch
new file mode 100644
index 000000000..d19f82022
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/randr.c.NX.patch
@@ -0,0 +1,72 @@
+--- ./nx-X11/programs/Xserver/randr/randr.c.X.original 2015-02-13 14:03:44.792440567 +0100
++++ ./nx-X11/programs/Xserver/randr/randr.c 2015-02-10 19:13:13.616692925 +0100
+@@ -25,6 +25,23 @@
+ * Keith Packard, Intel Corporation
+ */
+
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NX-X11, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ #define NEED_REPLIES
+ #define NEED_EVENTS
+ #ifdef HAVE_DIX_CONFIG_H
+@@ -56,9 +73,14 @@
+ int RREventBase;
+ int RRErrorBase;
+ RESTYPE RRClientType, RREventType; /* resource types for event masks */
+-DevPrivateKey RRClientPrivateKey = &RRClientPrivateKey;
+
++#ifndef NXAGENT_SERVER
++DevPrivateKey RRClientPrivateKey = &RRClientPrivateKey;
+ DevPrivateKey rrPrivKey = &rrPrivKey;
++#else
++int RRClientPrivateIndex;
++int rrPrivIndex = -1;
++#endif
+
+ static void
+ RRClientCallback (CallbackListPtr *list,
+@@ -203,6 +225,10 @@
+ {
+ if (RRGeneration != serverGeneration)
+ {
++ #ifdef NXAGENT_SERVER
++ if ((rrPrivIndex = AllocateScreenPrivateIndex()) < 0)
++ return FALSE;
++ #endif
+ if (!RRModeInit ())
+ return FALSE;
+ if (!RRCrtcInit ())
+@@ -324,10 +350,18 @@
+
+ if (RRNScreens == 0) return;
+
++ #ifndef NXAGENT_SERVER
+ if (!dixRequestPrivate(RRClientPrivateKey,
+ sizeof (RRClientRec) +
+ screenInfo.numScreens * sizeof (RRTimesRec)))
+ return;
++ #else
++ RRClientPrivateIndex = AllocateClientPrivateIndex ();
++ if (!AllocateClientPrivate (RRClientPrivateIndex,
++ sizeof (RRClientRec) +
++ screenInfo.numScreens * sizeof (RRTimesRec)))
++ return;
++ #endif
+ if (!AddCallback (&ClientStateCallback, RRClientCallback, 0))
+ return;
+
diff --git a/doc/nx-X11_vs_XOrg69_patches/randr.h.NX.patch b/doc/nx-X11_vs_XOrg69_patches/randr.h.NX.patch
new file mode 100644
index 000000000..a6f2d9c95
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/randr.h.NX.patch
@@ -0,0 +1,144 @@
+--- ./nx-X11/programs/Xserver/randr/randr.h.X.original 2015-02-13 14:03:44.792440567 +0100
++++ ./nx-X11/programs/Xserver/randr/randr.h 2015-02-10 19:13:13.628692476 +0100
+@@ -0,0 +1,141 @@
++/*
++ * Copyright © 2000 Compaq Computer Corporation
++ * Copyright © 2002 Hewlett Packard Company
++ * Copyright © 2006 Intel Corporation
++ *
++ * Permission to use, copy, modify, distribute, and sell this software and its
++ * documentation for any purpose is hereby granted without fee, provided that
++ * the above copyright notice appear in all copies and that both that copyright
++ * notice and this permission notice appear in supporting documentation, and
++ * that the name of the copyright holders not be used in advertising or
++ * publicity pertaining to distribution of the software without specific,
++ * written prior permission. The copyright holders make no representations
++ * about the suitability of this software for any purpose. It is provided "as
++ * is" without express or implied warranty.
++ *
++ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
++ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
++ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
++ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
++ * OF THIS SOFTWARE.
++ *
++ * Author: Jim Gettys, HP Labs, Hewlett-Packard, Inc.
++ * Keith Packard, Intel Corporation
++ */
++
++#ifndef _RANDR_H_
++#define _RANDR_H_
++
++typedef unsigned short Rotation;
++typedef unsigned short SizeID;
++typedef unsigned short SubpixelOrder;
++typedef unsigned short Connection;
++typedef unsigned short XRandrRotation;
++typedef unsigned short XRandrSizeID;
++typedef unsigned short XRandrSubpixelOrder;
++typedef unsigned long XRandrModeFlags;
++
++#define RANDR_NAME "RANDR"
++#define RANDR_MAJOR 1
++#define RANDR_MINOR 2
++
++#define RRNumberErrors 3
++#define RRNumberEvents 2
++#define RRNumberRequests 25
++
++#define X_RRQueryVersion 0
++/* we skip 1 to make old clients fail pretty immediately */
++#define X_RROldGetScreenInfo 1
++#define X_RR1_0SetScreenConfig 2
++/* V1.0 apps share the same set screen config request id */
++#define X_RRSetScreenConfig 2
++#define X_RROldScreenChangeSelectInput 3
++/* 3 used to be ScreenChangeSelectInput; deprecated */
++#define X_RRSelectInput 4
++#define X_RRGetScreenInfo 5
++
++/* V1.2 additions */
++#define X_RRGetScreenSizeRange 6
++#define X_RRSetScreenSize 7
++#define X_RRGetScreenResources 8
++#define X_RRGetOutputInfo 9
++#define X_RRListOutputProperties 10
++#define X_RRQueryOutputProperty 11
++#define X_RRConfigureOutputProperty 12
++#define X_RRChangeOutputProperty 13
++#define X_RRDeleteOutputProperty 14
++#define X_RRGetOutputProperty 15
++#define X_RRCreateMode 16
++#define X_RRDestroyMode 17
++#define X_RRAddOutputMode 18
++#define X_RRDeleteOutputMode 19
++#define X_RRGetCrtcInfo 20
++#define X_RRSetCrtcConfig 21
++#define X_RRGetCrtcGammaSize 22
++#define X_RRGetCrtcGamma 23
++#define X_RRSetCrtcGamma 24
++
++/* Event selection bits */
++#define RRScreenChangeNotifyMask (1L << 0)
++/* V1.2 additions */
++#define RRCrtcChangeNotifyMask (1L << 1)
++#define RROutputChangeNotifyMask (1L << 2)
++#define RROutputPropertyNotifyMask (1L << 3)
++
++/* Event codes */
++#define RRScreenChangeNotify 0
++/* V1.2 additions */
++#define RRNotify 1
++/* RRNotify Subcodes */
++#define RRNotify_CrtcChange 0
++#define RRNotify_OutputChange 1
++#define RRNotify_OutputProperty 2
++
++/* used in the rotation field; rotation and reflection in 0.1 proto. */
++#define RR_Rotate_0 1
++#define RR_Rotate_90 2
++#define RR_Rotate_180 4
++#define RR_Rotate_270 8
++
++/* new in 1.0 protocol, to allow reflection of screen */
++
++#define RR_Reflect_X 16
++#define RR_Reflect_Y 32
++
++#define RRSetConfigSuccess 0
++#define RRSetConfigInvalidConfigTime 1
++#define RRSetConfigInvalidTime 2
++#define RRSetConfigFailed 3
++
++/* new in 1.2 protocol */
++
++#define RR_HSyncPositive 0x00000001
++#define RR_HSyncNegative 0x00000002
++#define RR_VSyncPositive 0x00000004
++#define RR_VSyncNegative 0x00000008
++#define RR_Interlace 0x00000010
++#define RR_DoubleScan 0x00000020
++#define RR_CSync 0x00000040
++#define RR_CSyncPositive 0x00000080
++#define RR_CSyncNegative 0x00000100
++#define RR_HSkewPresent 0x00000200
++#define RR_BCast 0x00000400
++#define RR_PixelMultiplex 0x00000800
++#define RR_DoubleClock 0x00001000
++#define RR_ClockDivideBy2 0x00002000
++
++#define RR_Connected 0
++#define RR_Disconnected 1
++#define RR_UnknownConnection 2
++
++#define BadRROutput 0
++#define BadRRCrtc 1
++#define BadRRMode 2
++
++/* Conventional RandR output properties */
++
++#define RR_PROPERTY_RANDR_EDID "RANDR_EDID"
++
++#endif /* _RANDR_H_ */
diff --git a/doc/nx-X11_vs_XOrg69_patches/randrproto.h.NX.patch b/doc/nx-X11_vs_XOrg69_patches/randrproto.h.NX.patch
new file mode 100644
index 000000000..5c4ed74eb
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/randrproto.h.NX.patch
@@ -0,0 +1,658 @@
+--- ./nx-X11/programs/Xserver/randr/randrproto.h.X.original 2015-02-13 14:03:44.792440567 +0100
++++ ./nx-X11/programs/Xserver/randr/randrproto.h 2015-02-10 19:13:13.632692326 +0100
+@@ -0,0 +1,655 @@
++/*
++ * Copyright © 2000 Compaq Computer Corporation
++ * Copyright © 2002 Hewlett-Packard Company
++ * Copyright © 2006 Intel Corporation
++ *
++ * Permission to use, copy, modify, distribute, and sell this software and its
++ * documentation for any purpose is hereby granted without fee, provided that
++ * the above copyright notice appear in all copies and that both that copyright
++ * notice and this permission notice appear in supporting documentation, and
++ * that the name of the copyright holders not be used in advertising or
++ * publicity pertaining to distribution of the software without specific,
++ * written prior permission. The copyright holders make no representations
++ * about the suitability of this software for any purpose. It is provided "as
++ * is" without express or implied warranty.
++ *
++ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
++ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
++ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
++ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
++ * OF THIS SOFTWARE.
++ *
++ * Author: Jim Gettys, Hewlett-Packard Company, Inc.
++ * Keith Packard, Intel Corporation
++ */
++
++/* note that RANDR 1.0 is incompatible with version 0.0, or 0.1 */
++/* V1.0 removes depth switching from the protocol */
++#ifndef _XRANDRP_H_
++#define _XRANDRP_H_
++
++/*#include <X11/extensions/randr.h>*/
++#include "randr.h"
++
++#define Window CARD32
++#define Drawable CARD32
++#define Font CARD32
++#define Pixmap CARD32
++#define Cursor CARD32
++#define Colormap CARD32
++#define GContext CARD32
++#define Atom CARD32
++#define Time CARD32
++#define KeyCode CARD8
++#define KeySym CARD32
++#define RROutput CARD32
++#define RRMode CARD32
++#define RRCrtc CARD32
++#define RRModeFlags CARD32
++
++#define Rotation CARD16
++#define SizeID CARD16
++#define SubpixelOrder CARD16
++
++/*
++ * data structures
++ */
++
++typedef struct {
++ CARD16 widthInPixels B16;
++ CARD16 heightInPixels B16;
++ CARD16 widthInMillimeters B16;
++ CARD16 heightInMillimeters B16;
++} xScreenSizes;
++#define sz_xScreenSizes 8
++
++/*
++ * requests and replies
++ */
++
++typedef struct {
++ CARD8 reqType;
++ CARD8 randrReqType;
++ CARD16 length B16;
++ CARD32 majorVersion B32;
++ CARD32 minorVersion B32;
++} xRRQueryVersionReq;
++#define sz_xRRQueryVersionReq 12
++
++typedef struct {
++ BYTE type; /* X_Reply */
++ BYTE pad1;
++ CARD16 sequenceNumber B16;
++ CARD32 length B32;
++ CARD32 majorVersion B32;
++ CARD32 minorVersion B32;
++ CARD32 pad2 B32;
++ CARD32 pad3 B32;
++ CARD32 pad4 B32;
++ CARD32 pad5 B32;
++} xRRQueryVersionReply;
++#define sz_xRRQueryVersionReply 32
++
++typedef struct {
++ CARD8 reqType;
++ CARD8 randrReqType;
++ CARD16 length B16;
++ Window window B32;
++} xRRGetScreenInfoReq;
++#define sz_xRRGetScreenInfoReq 8
++
++/*
++ * the xRRScreenInfoReply structure is followed by:
++ *
++ * the size information
++ */
++
++
++typedef struct {
++ BYTE type; /* X_Reply */
++ BYTE setOfRotations;
++ CARD16 sequenceNumber B16;
++ CARD32 length B32;
++ Window root B32;
++ Time timestamp B32;
++ Time configTimestamp B32;
++ CARD16 nSizes B16;
++ SizeID sizeID B16;
++ Rotation rotation B16;
++ CARD16 rate B16;
++ CARD16 nrateEnts B16;
++ CARD16 pad B16;
++} xRRGetScreenInfoReply;
++#define sz_xRRGetScreenInfoReply 32
++
++typedef struct {
++ CARD8 reqType;
++ CARD8 randrReqType;
++ CARD16 length B16;
++ Drawable drawable B32;
++ Time timestamp B32;
++ Time configTimestamp B32;
++ SizeID sizeID B16;
++ Rotation rotation B16;
++} xRR1_0SetScreenConfigReq;
++#define sz_xRR1_0SetScreenConfigReq 20
++
++typedef struct {
++ CARD8 reqType;
++ CARD8 randrReqType;
++ CARD16 length B16;
++ Drawable drawable B32;
++ Time timestamp B32;
++ Time configTimestamp B32;
++ SizeID sizeID B16;
++ Rotation rotation B16;
++ CARD16 rate B16;
++ CARD16 pad B16;
++} xRRSetScreenConfigReq;
++#define sz_xRRSetScreenConfigReq 24
++
++typedef struct {
++ BYTE type; /* X_Reply */
++ CARD8 status;
++ CARD16 sequenceNumber B16;
++ CARD32 length B32;
++ Time newTimestamp B32;
++ Time newConfigTimestamp B32;
++ Window root;
++ CARD16 subpixelOrder B16;
++ CARD16 pad4 B16;
++ CARD32 pad5 B32;
++ CARD32 pad6 B32;
++} xRRSetScreenConfigReply;
++#define sz_xRRSetScreenConfigReply 32
++
++typedef struct {
++ CARD8 reqType;
++ CARD8 randrReqType;
++ CARD16 length B16;
++ Window window B32;
++ CARD16 enable B16;
++ CARD16 pad2 B16;
++} xRRSelectInputReq;
++#define sz_xRRSelectInputReq 12
++
++/*
++ * Additions for version 1.2
++ */
++
++typedef struct _xRRModeInfo {
++ RRMode id B32;
++ CARD16 width B16;
++ CARD16 height B16;
++ CARD32 dotClock B32;
++ CARD16 hSyncStart B16;
++ CARD16 hSyncEnd B16;
++ CARD16 hTotal B16;
++ CARD16 hSkew B16;
++ CARD16 vSyncStart B16;
++ CARD16 vSyncEnd B16;
++ CARD16 vTotal B16;
++ CARD16 nameLength B16;
++ RRModeFlags modeFlags B32;
++} xRRModeInfo;
++#define sz_xRRModeInfo 32
++
++typedef struct {
++ CARD8 reqType;
++ CARD8 randrReqType;
++ CARD16 length B16;
++ Window window B32;
++} xRRGetScreenSizeRangeReq;
++#define sz_xRRGetScreenSizeRangeReq 8
++
++typedef struct {
++ BYTE type; /* X_Reply */
++ CARD8 pad;
++ CARD16 sequenceNumber B16;
++ CARD32 length B32;
++ CARD16 minWidth B16;
++ CARD16 minHeight B16;
++ CARD16 maxWidth B16;
++ CARD16 maxHeight B16;
++ CARD32 pad0 B32;
++ CARD32 pad1 B32;
++ CARD32 pad2 B32;
++ CARD32 pad3 B32;
++} xRRGetScreenSizeRangeReply;
++#define sz_xRRGetScreenSizeRangeReply 32
++
++typedef struct {
++ CARD8 reqType;
++ CARD8 randrReqType;
++ CARD16 length B16;
++ Window window B32;
++ CARD16 width B16;
++ CARD16 height B16;
++ CARD32 widthInMillimeters B32;
++ CARD32 heightInMillimeters B32;
++} xRRSetScreenSizeReq;
++#define sz_xRRSetScreenSizeReq 20
++
++typedef struct {
++ CARD8 reqType;
++ CARD8 randrReqType;
++ CARD16 length B16;
++ Window window B32;
++} xRRGetScreenResourcesReq;
++#define sz_xRRGetScreenResourcesReq 8
++
++typedef struct {
++ BYTE type;
++ CARD8 pad;
++ CARD16 sequenceNumber B16;
++ CARD32 length B32;
++ Time timestamp B32;
++ Time configTimestamp B32;
++ CARD16 nCrtcs B16;
++ CARD16 nOutputs B16;
++ CARD16 nModes B16;
++ CARD16 nbytesNames B16;
++ CARD32 pad1 B32;
++ CARD32 pad2 B32;
++} xRRGetScreenResourcesReply;
++#define sz_xRRGetScreenResourcesReply 32
++
++typedef struct {
++ CARD8 reqType;
++ CARD8 randrReqType;
++ CARD16 length B16;
++ RROutput output B32;
++ Time configTimestamp B32;
++} xRRGetOutputInfoReq;
++#define sz_xRRGetOutputInfoReq 12
++
++typedef struct {
++ BYTE type;
++ CARD8 status;
++ CARD16 sequenceNumber B16;
++ CARD32 length B32;
++ Time timestamp B32;
++ RRCrtc crtc B32;
++ CARD32 mmWidth B32;
++ CARD32 mmHeight B32;
++ CARD8 connection;
++ CARD8 subpixelOrder;
++ CARD16 nCrtcs B16;
++ CARD16 nModes B16;
++ CARD16 nPreferred B16;
++ CARD16 nClones B16;
++ CARD16 nameLength B16;
++} xRRGetOutputInfoReply;
++#define sz_xRRGetOutputInfoReply 36
++
++typedef struct {
++ CARD8 reqType;
++ CARD8 randrReqType;
++ CARD16 length B16;
++ RROutput output B32;
++} xRRListOutputPropertiesReq;
++#define sz_xRRListOutputPropertiesReq 8
++
++typedef struct {
++ BYTE type;
++ CARD8 pad0;
++ CARD16 sequenceNumber B16;
++ CARD32 length B32;
++ CARD16 nAtoms B16;
++ CARD16 pad1 B16;
++ CARD32 pad2 B32;
++ CARD32 pad3 B32;
++ CARD32 pad4 B32;
++ CARD32 pad5 B32;
++ CARD32 pad6 B32;
++} xRRListOutputPropertiesReply;
++#define sz_xRRListOutputPropertiesReply 32
++
++typedef struct {
++ CARD8 reqType;
++ CARD8 randrReqType;
++ CARD16 length B16;
++ RROutput output B32;
++ Atom property B32;
++} xRRQueryOutputPropertyReq;
++#define sz_xRRQueryOutputPropertyReq 12
++
++typedef struct {
++ BYTE type;
++ BYTE pad0;
++ CARD16 sequenceNumber B16;
++ CARD32 length B32;
++ BOOL pending;
++ BOOL range;
++ BOOL immutable;
++ BYTE pad1;
++ CARD32 pad2 B32;
++ CARD32 pad3 B32;
++ CARD32 pad4 B32;
++ CARD32 pad5 B32;
++ CARD32 pad6 B32;
++} xRRQueryOutputPropertyReply;
++#define sz_xRRQueryOutputPropertyReply 32
++
++typedef struct {
++ CARD8 reqType;
++ CARD8 randrReqType;
++ CARD16 length B16;
++ RROutput output B32;
++ Atom property B32;
++ BOOL pending;
++ BOOL range;
++ CARD16 pad B16;
++} xRRConfigureOutputPropertyReq;
++#define sz_xRRConfigureOutputPropertyReq 16
++
++typedef struct {
++ CARD8 reqType;
++ CARD8 randrReqType;
++ CARD16 length B16;
++ RROutput output B32;
++ Atom property B32;
++ Atom type B32;
++ CARD8 format;
++ CARD8 mode;
++ CARD16 pad;
++ CARD32 nUnits B32;
++} xRRChangeOutputPropertyReq;
++#define sz_xRRChangeOutputPropertyReq 24
++
++typedef struct {
++ CARD8 reqType;
++ CARD8 randrReqType;
++ CARD16 length B16;
++ RROutput output B32;
++ Atom property B32;
++} xRRDeleteOutputPropertyReq;
++#define sz_xRRDeleteOutputPropertyReq 12
++
++typedef struct {
++ CARD8 reqType;
++ CARD8 randrReqType;
++ CARD16 length B16;
++ RROutput output B32;
++ Atom property B32;
++ Atom type B32;
++ CARD32 longOffset B32;
++ CARD32 longLength B32;
++#ifdef __cplusplus
++ BOOL _delete;
++#else
++ BOOL delete;
++#endif
++ BOOL pending;
++ CARD16 pad1 B16;
++} xRRGetOutputPropertyReq;
++#define sz_xRRGetOutputPropertyReq 28
++
++typedef struct {
++ BYTE type;
++ CARD8 format;
++ CARD16 sequenceNumber B16;
++ CARD32 length B32;
++ Atom propertyType B32;
++ CARD32 bytesAfter B32;
++ CARD32 nItems B32;
++ CARD32 pad1 B32;
++ CARD32 pad2 B32;
++ CARD32 pad3 B32;
++} xRRGetOutputPropertyReply;
++#define sz_xRRGetOutputPropertyReply 32
++
++typedef struct {
++ CARD8 reqType;
++ CARD8 randrReqType;
++ CARD16 length B16;
++ Window window B32;
++ xRRModeInfo modeInfo;
++} xRRCreateModeReq;
++#define sz_xRRCreateModeReq 40
++
++typedef struct {
++ BYTE type;
++ CARD8 pad0;
++ CARD16 sequenceNumber B16;
++ CARD32 length B32;
++ RRMode mode B32;
++ CARD32 pad1 B32;
++ CARD32 pad2 B32;
++ CARD32 pad3 B32;
++ CARD32 pad4 B32;
++ CARD32 pad5 B32;
++} xRRCreateModeReply;
++#define sz_xRRCreateModeReply 32
++
++typedef struct {
++ CARD8 reqType;
++ CARD8 randrReqType;
++ CARD16 length B16;
++ RRMode mode B32;
++} xRRDestroyModeReq;
++#define sz_xRRDestroyModeReq 8
++
++typedef struct {
++ CARD8 reqType;
++ CARD8 randrReqType;
++ CARD16 length B16;
++ RROutput output B32;
++ RRMode mode B32;
++} xRRAddOutputModeReq;
++#define sz_xRRAddOutputModeReq 12
++
++typedef struct {
++ CARD8 reqType;
++ CARD8 randrReqType;
++ CARD16 length B16;
++ RROutput output B32;
++ RRMode mode B32;
++} xRRDeleteOutputModeReq;
++#define sz_xRRDeleteOutputModeReq 12
++
++typedef struct {
++ CARD8 reqType;
++ CARD8 randrReqType;
++ CARD16 length B16;
++ RRCrtc crtc B32;
++ Time configTimestamp B32;
++} xRRGetCrtcInfoReq;
++#define sz_xRRGetCrtcInfoReq 12
++
++typedef struct {
++ BYTE type;
++ CARD8 status;
++ CARD16 sequenceNumber B16;
++ CARD32 length B32;
++ Time timestamp B32;
++ INT16 x B16;
++ INT16 y B16;
++ CARD16 width B16;
++ CARD16 height B16;
++ RRMode mode B32;
++ Rotation rotation B16;
++ Rotation rotations B16;
++ CARD16 nOutput B16;
++ CARD16 nPossibleOutput B16;
++} xRRGetCrtcInfoReply;
++#define sz_xRRGetCrtcInfoReply 32
++
++typedef struct {
++ CARD8 reqType;
++ CARD8 randrReqType;
++ CARD16 length B16;
++ RRCrtc crtc B32;
++ Time timestamp B32;
++ Time configTimestamp B32;
++ INT16 x B16;
++ INT16 y B16;
++ RRMode mode B32;
++ Rotation rotation B16;
++ CARD16 pad B16;
++} xRRSetCrtcConfigReq;
++#define sz_xRRSetCrtcConfigReq 28
++
++typedef struct {
++ BYTE type;
++ CARD8 status;
++ CARD16 sequenceNumber B16;
++ CARD32 length B32;
++ Time newTimestamp B32;
++ CARD32 pad1 B32;
++ CARD32 pad2 B16;
++ CARD32 pad3 B32;
++ CARD32 pad4 B32;
++ CARD32 pad5 B32;
++} xRRSetCrtcConfigReply;
++#define sz_xRRSetCrtcConfigReply 32
++
++typedef struct {
++ CARD8 reqType;
++ CARD8 randrReqType;
++ CARD16 length B16;
++ RRCrtc crtc B32;
++} xRRGetCrtcGammaSizeReq;
++#define sz_xRRGetCrtcGammaSizeReq 8
++
++typedef struct {
++ BYTE type;
++ CARD8 status;
++ CARD16 sequenceNumber B16;
++ CARD32 length B32;
++ CARD16 size B16;
++ CARD16 pad1 B16;
++ CARD32 pad2 B32;
++ CARD32 pad3 B32;
++ CARD32 pad4 B32;
++ CARD32 pad5 B32;
++ CARD32 pad6 B32;
++} xRRGetCrtcGammaSizeReply;
++#define sz_xRRGetCrtcGammaSizeReply 32
++
++typedef struct {
++ CARD8 reqType;
++ CARD8 randrReqType;
++ CARD16 length B16;
++ RRCrtc crtc B32;
++} xRRGetCrtcGammaReq;
++#define sz_xRRGetCrtcGammaReq 8
++
++typedef struct {
++ BYTE type;
++ CARD8 status;
++ CARD16 sequenceNumber B16;
++ CARD32 length B32;
++ CARD16 size B16;
++ CARD16 pad1 B16;
++ CARD32 pad2 B32;
++ CARD32 pad3 B32;
++ CARD32 pad4 B32;
++ CARD32 pad5 B32;
++ CARD32 pad6 B32;
++} xRRGetCrtcGammaReply;
++#define sz_xRRGetCrtcGammaReply 32
++
++typedef struct {
++ CARD8 reqType;
++ CARD8 randrReqType;
++ CARD16 length B16;
++ RRCrtc crtc B32;
++ CARD16 size B16;
++ CARD16 pad1 B16;
++} xRRSetCrtcGammaReq;
++#define sz_xRRSetCrtcGammaReq 12
++
++/*
++ * event
++ */
++typedef struct {
++ CARD8 type; /* always evBase + ScreenChangeNotify */
++ CARD8 rotation; /* new rotation */
++ CARD16 sequenceNumber B16;
++ Time timestamp B32; /* time screen was changed */
++ Time configTimestamp B32; /* time config data was changed */
++ Window root B32; /* root window */
++ Window window B32; /* window requesting notification */
++ SizeID sizeID B16; /* new size ID */
++ CARD16 subpixelOrder B16; /* subpixel order */
++ CARD16 widthInPixels B16; /* new size */
++ CARD16 heightInPixels B16;
++ CARD16 widthInMillimeters B16;
++ CARD16 heightInMillimeters B16;
++} xRRScreenChangeNotifyEvent;
++#define sz_xRRScreenChangeNotifyEvent 32
++
++typedef struct {
++ CARD8 type; /* always evBase + RRNotify */
++ CARD8 subCode; /* RRNotify_CrtcChange */
++ CARD16 sequenceNumber B16;
++ Time timestamp B32; /* time crtc was changed */
++ Window window B32; /* window requesting notification */
++ RRCrtc crtc B32; /* affected CRTC */
++ RRMode mode B32; /* current mode */
++ CARD16 rotation B16; /* rotation and reflection */
++ CARD16 pad1 B16; /* unused */
++ INT16 x B16; /* new location */
++ INT16 y B16;
++ CARD16 width B16; /* new size */
++ CARD16 height B16;
++} xRRCrtcChangeNotifyEvent;
++#define sz_xRRCrtcChangeNotifyEvent 32
++
++typedef struct {
++ CARD8 type; /* always evBase + RRNotify */
++ CARD8 subCode; /* RRNotify_OutputChange */
++ CARD16 sequenceNumber B16;
++ Time timestamp B32; /* time crtc was changed */
++ Time configTimestamp B32; /* time crtc was changed */
++ Window window B32; /* window requesting notification */
++ RROutput output B32; /* affected output */
++ RRCrtc crtc B32; /* current crtc */
++ RRMode mode B32; /* current mode */
++ CARD16 rotation B16; /* rotation and reflection */
++ CARD8 connection; /* connection status */
++ CARD8 subpixelOrder; /* subpixel order */
++} xRROutputChangeNotifyEvent;
++#define sz_xRROutputChangeNotifyEvent 32
++
++typedef struct {
++ CARD8 type; /* always evBase + RRNotify */
++ CARD8 subCode; /* RRNotify_OutputProperty */
++ CARD16 sequenceNumber B16;
++ Window window B32; /* window requesting notification */
++ RROutput output B32; /* affected output */
++ Atom atom B32; /* property name */
++ Time timestamp B32; /* time crtc was changed */
++ CARD8 state; /* NewValue or Deleted */
++ CARD8 pad1;
++ CARD16 pad2 B16;
++ CARD32 pad3 B32;
++ CARD32 pad4 B32;
++} xRROutputPropertyNotifyEvent;
++#define sz_xRROutputPropertyNotifyEvent 32
++
++#undef RRModeFlags
++#undef RRCrtc
++#undef RRMode
++#undef RROutput
++#undef RRMode
++#undef RRCrtc
++#undef Drawable
++#undef Window
++#undef Font
++#undef Pixmap
++#undef Cursor
++#undef Colormap
++#undef GContext
++#undef Atom
++#undef Time
++#undef KeyCode
++#undef KeySym
++#undef Rotation
++#undef SizeID
++#undef SubpixelOrder
++
++#endif /* _XRANDRP_H_ */
diff --git a/doc/nx-X11_vs_XOrg69_patches/registry.h.NX.patch b/doc/nx-X11_vs_XOrg69_patches/registry.h.NX.patch
new file mode 100644
index 000000000..601bc0a98
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/registry.h.NX.patch
@@ -0,0 +1,67 @@
+--- ./nx-X11/programs/Xserver/randr/registry.h.X.original 2015-02-13 14:03:44.792440567 +0100
++++ ./nx-X11/programs/Xserver/randr/registry.h 2015-02-10 19:13:13.616692925 +0100
+@@ -0,0 +1,64 @@
++/***********************************************************
++
++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
++AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
++
++******************************************************************/
++
++#ifndef DIX_REGISTRY_H
++#define DIX_REGISTRY_H
++
++/*
++ * Result returned from any unsuccessful lookup
++ */
++#define XREGISTRY_UNKNOWN "<unknown>"
++
++#ifdef XREGISTRY
++
++#include "resource.h"
++#include "extnsionst.h"
++
++/* Internal string registry - for auditing, debugging, security, etc. */
++
++/*
++ * Registration functions. The name string is not copied, so it must
++ * not be a stack variable.
++ */
++void RegisterResourceName(RESTYPE type, char *name);
++void RegisterExtensionNames(ExtensionEntry *ext);
++
++/*
++ * Lookup functions. The returned string must not be modified or freed.
++ */
++const char *LookupMajorName(int major);
++const char *LookupRequestName(int major, int minor);
++const char *LookupEventName(int event);
++const char *LookupErrorName(int error);
++const char *LookupResourceName(RESTYPE rtype);
++
++/*
++ * Setup and teardown
++ */
++void dixResetRegistry(void);
++
++#else /* XREGISTRY */
++
++/* Define calls away when the registry is not being built. */
++
++#define RegisterResourceName(a, b) { ; }
++#define RegisterExtensionNames(a) { ; }
++
++#define LookupMajorName(a) XREGISTRY_UNKNOWN
++#define LookupRequestName(a, b) XREGISTRY_UNKNOWN
++#define LookupEventName(a) XREGISTRY_UNKNOWN
++#define LookupErrorName(a) XREGISTRY_UNKNOWN
++#define LookupResourceName(a) XREGISTRY_UNKNOWN
++
++#define dixResetRegistry() { ; }
++
++#endif /* XREGISTRY */
++#endif /* DIX_REGISTRY_H */
diff --git a/doc/nx-X11_vs_XOrg69_patches/render2.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/render2.c.NX.patch
new file mode 100644
index 000000000..16fa7adcc
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/render2.c.NX.patch
@@ -0,0 +1,11 @@
+--- ./nx-X11/programs/Xserver/GL/glx/render2.c.X.original 2015-02-13 14:03:44.680442769 +0100
++++ ./nx-X11/programs/Xserver/GL/glx/render2.c 2015-02-10 19:13:14.416663013 +0100
+@@ -43,7 +43,7 @@
+ #include "unpack.h"
+ #include "g_disptab.h"
+ #include "g_disptab_EXT.h"
+-
++#include "indirect_size.h"
+
+ void __glXDisp_Map1f(GLbyte *pc)
+ {
diff --git a/doc/nx-X11_vs_XOrg69_patches/render2swap.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/render2swap.c.NX.patch
new file mode 100644
index 000000000..1ae924df0
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/render2swap.c.NX.patch
@@ -0,0 +1,11 @@
+--- ./nx-X11/programs/Xserver/GL/glx/render2swap.c.X.original 2015-02-13 14:03:44.680442769 +0100
++++ ./nx-X11/programs/Xserver/GL/glx/render2swap.c 2015-02-10 19:13:14.376664506 +0100
+@@ -43,7 +43,7 @@
+ #include "unpack.h"
+ #include "g_disptab.h"
+ #include "g_disptab_EXT.h"
+-
++#include "indirect_size.h"
+
+ void __glXDispSwap_Map1f(GLbyte *pc)
+ {
diff --git a/doc/nx-X11_vs_XOrg69_patches/renderedge.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/renderedge.c.NX.patch
new file mode 100644
index 000000000..3f1514250
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/renderedge.c.NX.patch
@@ -0,0 +1,10 @@
+--- ./nx-X11/programs/Xserver/render/renderedge.c.X.original 2015-02-13 14:03:44.792440567 +0100
++++ ./nx-X11/programs/Xserver/render/renderedge.c 2015-02-10 19:13:13.592693823 +0100
+@@ -143,6 +143,7 @@
+ dx = x_bot - x_top;
+ dy = y_bot - y_top;
+ e->dy = dy;
++ e->dx = 0;
+ if (dy)
+ {
+ if (dx >= 0)
diff --git a/doc/nx-X11_vs_XOrg69_patches/rrcrtc.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/rrcrtc.c.NX.patch
new file mode 100644
index 000000000..6cb8359b7
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/rrcrtc.c.NX.patch
@@ -0,0 +1,48 @@
+--- ./nx-X11/programs/Xserver/randr/rrcrtc.c.X.original 2015-02-13 14:03:44.792440567 +0100
++++ ./nx-X11/programs/Xserver/randr/rrcrtc.c 2015-02-10 19:13:13.624692625 +0100
+@@ -20,6 +20,23 @@
+ * OF THIS SOFTWARE.
+ */
+
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NX-X11, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ #include "randrstr.h"
+ #include "swaprep.h"
+ #include "registry.h"
+@@ -836,6 +853,9 @@
+ rep.status = RRSetConfigFailed;
+ goto sendReply;
+ }
++ #ifdef NXAGENT_SERVER /* Bug 21987 */
++ pScrPriv->lastSetTime = time;
++ #endif
+ rep.status = RRSetConfigSuccess;
+
+ sendReply:
+@@ -846,7 +866,11 @@
+ /* rep.status has already been filled in */
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
++ #ifndef NXAGENT_SERVER /* Bug 21987 */
+ rep.newTimestamp = pScrPriv->lastConfigTime.milliseconds;
++ #else
++ rep.newTimestamp = pScrPriv->lastSetTime.milliseconds;
++ #endif
+
+ if (client->swapped)
+ {
diff --git a/doc/nx-X11_vs_XOrg69_patches/rrdispatch.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/rrdispatch.c.NX.patch
new file mode 100644
index 000000000..8a4cc1387
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/rrdispatch.c.NX.patch
@@ -0,0 +1,15 @@
+--- ./nx-X11/programs/Xserver/randr/rrdispatch.c.X.original 2015-02-13 14:03:44.792440567 +0100
++++ ./nx-X11/programs/Xserver/randr/rrdispatch.c 2015-02-10 19:13:13.632692326 +0100
+@@ -76,7 +76,12 @@
+ int rc;
+
+ REQUEST_SIZE_MATCH(xRRSelectInputReq);
++ #ifndef NXAGENT_SERVER
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
++ #else
++ pWin = SecurityLookupWindow(stuff->window, client, SecurityWriteAccess);
++ rc = pWin ? Success : BadWindow;
++ #endif
+ if (rc != Success)
+ return rc;
+ pHead = (RREventPtr *)SecurityLookupIDByType(client,
diff --git a/doc/nx-X11_vs_XOrg69_patches/rrmode.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/rrmode.c.NX.patch
new file mode 100644
index 000000000..ddbe739b6
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/rrmode.c.NX.patch
@@ -0,0 +1,39 @@
+--- ./nx-X11/programs/Xserver/randr/rrmode.c.X.original 2015-02-13 14:03:44.792440567 +0100
++++ ./nx-X11/programs/Xserver/randr/rrmode.c 2015-02-10 19:13:13.612693075 +0100
+@@ -20,6 +20,23 @@
+ * OF THIS SOFTWARE.
+ */
+
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NX-X11, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ #include "randrstr.h"
+ #include "registry.h"
+
+@@ -288,7 +305,12 @@
+ RRModePtr mode;
+
+ REQUEST_AT_LEAST_SIZE (xRRCreateModeReq);
++ #ifndef NXAGENT_SERVER
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
++ #else
++ pWin = SecurityLookupWindow(stuff->window, client, SecurityReadAccess);
++ rc = pWin ? Success : BadWindow;
++ #endif
+ if (rc != Success)
+ return rc;
+
diff --git a/doc/nx-X11_vs_XOrg69_patches/rrscreen.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/rrscreen.c.NX.patch
new file mode 100644
index 000000000..c5c3d4757
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/rrscreen.c.NX.patch
@@ -0,0 +1,107 @@
+--- ./nx-X11/programs/Xserver/randr/rrscreen.c.X.original 2015-02-13 14:03:44.792440567 +0100
++++ ./nx-X11/programs/Xserver/randr/rrscreen.c 2015-02-10 19:13:13.632692326 +0100
+@@ -20,6 +20,23 @@
+ * OF THIS SOFTWARE.
+ */
+
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NX-X11, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ #include "randrstr.h"
+
+ extern char *ConnectionInfo;
+@@ -212,7 +229,12 @@
+ int rc;
+
+ REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
++ #ifndef NXAGENT_SERVER
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
++ #else
++ pWin = SecurityLookupWindow(stuff->window, client, SecurityReadAccess);
++ rc = pWin ? Success : BadWindow;
++ #endif
+ if (rc != Success)
+ return rc;
+
+@@ -263,7 +285,12 @@
+ int i, rc;
+
+ REQUEST_SIZE_MATCH(xRRSetScreenSizeReq);
++ #ifndef NXAGENT_SERVER
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
++ #else
++ pWin = SecurityLookupWindow(stuff->window, client, SecurityReadAccess);
++ rc = pWin ? Success : BadWindow;
++ #endif
+ if (rc != Success)
+ return rc;
+
+@@ -333,7 +360,12 @@
+ CARD8 *names;
+
+ REQUEST_SIZE_MATCH(xRRGetScreenResourcesReq);
++ #ifndef NXAGENT_SERVER
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
++ #else
++ pWin = SecurityLookupWindow(stuff->window, client, SecurityReadAccess);
++ rc = pWin ? Success : BadWindow;
++ #endif
+ if (rc != Success)
+ return rc;
+
+@@ -582,7 +614,12 @@
+ RROutputPtr output;
+
+ REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
++ #ifndef NXAGENT_SERVER
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
++ #else
++ pWin = SecurityLookupWindow(stuff->window, client, SecurityReadAccess);
++ rc = pWin ? Success : BadWindow;
++ #endif
+ if (rc != Success)
+ return rc;
+
+@@ -756,7 +793,12 @@
+ has_rate = FALSE;
+ }
+
++ #ifndef NXAGENT_SERVER
+ rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixWriteAccess);
++ #else
++ pDraw = SecurityLookupDrawable(stuff->drawable, client, SecurityWriteAccess);
++ rc = pDraw ? Success : BadDrawable;
++ #endif
+ if (rc != Success)
+ return rc;
+
+@@ -921,8 +963,15 @@
+
+ if (!RRCrtcSet (crtc, mode, 0, 0, stuff->rotation, 1, &output))
+ rep.status = RRSetConfigFailed;
++ #ifndef NXAGENT_SERVER /* Bug 21987 */
+ else
+ rep.status = RRSetConfigSuccess;
++ #else
++ else {
++ rep.status = RRSetConfigSuccess;
++ pScrPriv->lastSetTime = time;
++ }
++ #endif
+
+ /*
+ * XXX Configure other crtcs to mirror as much as possible
diff --git a/doc/nx-X11_vs_XOrg69_patches/rrxinerama.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/rrxinerama.c.NX.patch
new file mode 100644
index 000000000..f95d6325a
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/rrxinerama.c.NX.patch
@@ -0,0 +1,72 @@
+--- ./nx-X11/programs/Xserver/randr/rrxinerama.c.X.original 2015-02-13 14:03:44.792440567 +0100
++++ ./nx-X11/programs/Xserver/randr/rrxinerama.c 2015-02-10 19:13:13.620692775 +0100
+@@ -68,9 +68,30 @@
+ * David Thomas <davtom@dream.org.uk>.
+ */
+
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NX-X11, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ #include "randrstr.h"
+ #include "swaprep.h"
++#ifndef NXAGENT_SERVER
+ #include <X11/extensions/panoramiXproto.h>
++#else
++#include "panoramiXproto.h"
++#endif
+
+ #define RR_XINERAMA_MAJOR_VERSION 1
+ #define RR_XINERAMA_MINOR_VERSION 1
+@@ -122,7 +143,12 @@
+ Bool active = FALSE;
+
+ REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
++ #ifndef NXAGENT_SERVER
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
++ #else
++ pWin = SecurityLookupWindow(stuff->window, client, SecurityReadAccess);
++ rc = pWin ? Success : BadWindow;
++ #endif
+ if(rc != Success)
+ return rc;
+
+@@ -185,7 +211,12 @@
+ register int n, rc;
+
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
++ #ifndef NXAGENT_SERVER
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
++ #else
++ pWin = SecurityLookupWindow(stuff->window, client, SecurityReadAccess);
++ rc = pWin ? Success : BadWindow;
++ #endif
+ if (rc != Success)
+ return rc;
+
+@@ -213,7 +244,12 @@
+ register int n, rc;
+
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
++ #ifndef NXAGENT_SERVER
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
++ #else
++ pWin = SecurityLookupWindow(stuff->window, client, SecurityReadAccess);
++ rc = pWin ? Success : BadWindow;
++ #endif
+ if (rc != Success)
+ return rc;
+
diff --git a/doc/nx-X11_vs_XOrg69_patches/security.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/security.c.NX.patch
new file mode 100644
index 000000000..bb461afcd
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/security.c.NX.patch
@@ -0,0 +1,315 @@
+--- ./nx-X11/programs/Xserver/Xext/security.c.X.original 2015-02-13 14:03:44.684442691 +0100
++++ ./nx-X11/programs/Xserver/Xext/security.c 2015-02-13 14:03:44.684442691 +0100
+@@ -27,6 +27,23 @@
+ */
+ /* $XFree86: xc/programs/Xserver/Xext/security.c,v 1.16tsi Exp $ */
+
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NX-X11, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ #ifdef HAVE_DIX_CONFIG_H
+ #include <dix-config.h>
+ #endif
+@@ -54,14 +71,49 @@
+ #include <stdio.h> /* for file reading operations */
+ #include <X11/Xatom.h> /* for XA_STRING */
+
++#ifdef NXAGENT_SERVER
++
++#include <unistd.h>
++#include <string.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++
++#endif
++
+ #ifndef DEFAULTPOLICYFILE
+ # define DEFAULTPOLICYFILE NULL
+ #endif
++
++#ifdef NXAGENT_SERVER
++
++#define NX_ALTERNATIVEPOLICYFILE "/usr/lib/xserver/SecurityPolicy"
++
++#endif
++
+ #if defined(WIN32) || defined(__CYGWIN__)
+ #include <X11/Xos.h>
+ #undef index
+ #endif
+
++/*
++ * Set here the required NX log level.
++ */
++
++#ifdef NXAGENT_SERVER
++
++#define PANIC
++#define WARNING
++#undef TEST
++#undef DEBUG
++
++#endif
++
++#ifdef NXAGENT_SERVER
++
++static char _NXPolicyFilePath[1024];
++
++#endif
++
+ #include "modinit.h"
+
+ static int SecurityErrorBase; /* first Security error number */
+@@ -87,6 +139,115 @@
+ ClientPtr /*client*/
+ );
+
++#ifdef NXAGENT_SERVER
++
++/*
++ * This function returns the SecurityPolicy
++ * file full path. This path is referred by
++ * SecurityPolicyFile variable (generally it
++ * contains the hardcoded path at compile time).
++ * If the path does not exist, the function will
++ * try a set of well known paths.
++ */
++
++const char *_NXGetPolicyFilePath(const char *path)
++{
++
++ struct stat SecurityPolicyStat;
++
++ /*
++ * Check the policy file path only once.
++ */
++
++ if (*_NXPolicyFilePath != '\0')
++ {
++ return _NXPolicyFilePath;
++ }
++
++ if (stat(path, &SecurityPolicyStat) == 0)
++ {
++ if (strlen(path) + 1 > 1024)
++ {
++ #ifdef WARNING
++ fprintf(stderr, "_NXGetPolicyFilePath: WARNING! Maximum length of SecurityPolicy file path exceeded.\n");
++ #endif
++
++ goto _NXGetPolicyFilePathError;
++ }
++
++ strcpy(_NXPolicyFilePath, path);
++
++ #ifdef TEST
++ fprintf(stderr, "_NXGetPolicyFilePath: Using SecurityPolicy file path [%s].\n",
++ _NXPolicyFilePath);
++ #endif
++
++ return _NXPolicyFilePath;
++ }
++
++ if (stat(DEFAULTPOLICYFILE, &SecurityPolicyStat) == 0)
++ {
++ if (strlen(DEFAULTPOLICYFILE) + 1 > 1024)
++ {
++ #ifdef WARNING
++ fprintf(stderr, "_NXGetPolicyFilePath: WARNING! Maximum length of SecurityPolicy file path exceeded.\n");
++ #endif
++
++ goto _NXGetPolicyFilePathError;
++ }
++
++ strcpy(_NXPolicyFilePath, DEFAULTPOLICYFILE);
++
++ #ifdef TEST
++ fprintf(stderr, "_NXGetPolicyFilePath: Using SecurityPolicy file path [%s].\n",
++ _NXPolicyFilePath);
++ #endif
++
++ return _NXPolicyFilePath;
++ }
++
++ if (stat(NX_ALTERNATIVEPOLICYFILE, &SecurityPolicyStat) == 0)
++ {
++ if (strlen(NX_ALTERNATIVEPOLICYFILE) + 1 > 1024)
++ {
++ #ifdef WARNING
++ fprintf(stderr, "_NXGetPolicyFilePath: WARNING! Maximum length of SecurityPolicy file path exceeded.\n");
++ #endif
++
++ goto _NXGetPolicyFilePathError;
++ }
++
++ strcpy(_NXPolicyFilePath, NX_ALTERNATIVEPOLICYFILE);
++
++ #ifdef TEST
++ fprintf(stderr, "_NXGetPolicyFilePath: Using SecurityPolicy file path [%s].\n",
++ _NXPolicyFilePath);
++ #endif
++
++ return _NXPolicyFilePath;
++ }
++
++_NXGetPolicyFilePathError:
++
++ if (strlen(path) + 1 > 1024)
++ {
++ #ifdef WARNING
++ fprintf(stderr, "_NXGetPolicyFilePath: WARNING! Maximum length of SecurityPolicy file exceeded.\n");
++ #endif
++ }
++
++ strcpy(_NXPolicyFilePath, path);
++
++ #ifdef TEST
++ fprintf(stderr, "_NXGetPolicyFilePath: Using default SecurityPolicy file path [%s].\n",
++ _NXPolicyFilePath);
++ #endif
++
++ return _NXPolicyFilePath;
++}
++
++#endif
++
+ /* SecurityAudit
+ *
+ * Arguments:
+@@ -1647,18 +1808,60 @@
+
+ SecurityMaxPropertyName = 0;
+
++#ifdef NXAGENT_SERVER
++
++ if (!_NXGetPolicyFilePath(SecurityPolicyFile))
++ {
++ return;
++ }
++
++#else
++
+ if (!SecurityPolicyFile)
+ return;
+
++#endif
++
+ #ifndef __UNIXOS2__
++
++#ifdef NXAGENT_SERVER
++
++ f = Fopen(_NXGetPolicyFilePath(SecurityPolicyFile), "r");
++
++#else
++
+ f = Fopen(SecurityPolicyFile, "r");
++
++#endif
++
++#else
++
++#ifdef NXAGENT_SERVER
++
++ f = Fopen((char*)__XOS2RedirRoot( _NXGetPolicyFilePath(SecurityPolicyFile)), "r");
++
+ #else
++
+ f = Fopen((char*)__XOS2RedirRoot(SecurityPolicyFile), "r");
+-#endif
++
++#endif
++
++#endif
++
+ if (!f)
+ {
++#ifdef NXAGENT_SERVER
++
++ ErrorF("error opening security policy file %s\n",
++ _NXGetPolicyFilePath(SecurityPolicyFile));
++
++#else
++
+ ErrorF("error opening security policy file %s\n",
+ SecurityPolicyFile);
++
++#endif
++
+ return;
+ }
+
+@@ -1678,8 +1881,19 @@
+ char *v = SecurityParseString(&p);
+ if (strcmp(v, SECURITY_POLICY_FILE_VERSION) != 0)
+ {
++
++#ifdef NXAGENT_SERVER
++
++ ErrorF("%s: invalid security policy file version, ignoring file\n",
++ _NXGetPolicyFilePath(SecurityPolicyFile));
++
++#else
++
+ ErrorF("%s: invalid security policy file version, ignoring file\n",
+ SecurityPolicyFile);
++
++#endif
++
+ break;
+ }
+ validLine = TRUE;
+@@ -1706,9 +1920,22 @@
+ }
+ }
+
++#ifdef NXAGENT_SERVER
++
++ if (!validLine)
++ {
++ ErrorF("Line %d of %s invalid, ignoring\n",
++ lineNumber, _NXGetPolicyFilePath(SecurityPolicyFile));
++ }
++
++#else
++
+ if (!validLine)
+ ErrorF("Line %d of %s invalid, ignoring\n",
+ lineNumber, SecurityPolicyFile);
++
++#endif
++
+ } /* end while more input */
+
+ #ifdef PROPDEBUG
+@@ -1799,7 +2026,17 @@
+ {
+ struct stat buf;
+ static time_t lastmod = 0;
++
++#ifdef NXAGENT_SERVER
++
++ int ret = stat(_NXGetPolicyFilePath(SecurityPolicyFile), &buf);
++
++#else
++
+ int ret = stat(SecurityPolicyFile , &buf);
++
++#endif
++
+ if ( (ret == 0) && (buf.st_mtime > lastmod) )
+ {
+ ErrorF("reloading property rules\n");
diff --git a/doc/nx-X11_vs_XOrg69_patches/select.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/select.c.NX.patch
new file mode 100644
index 000000000..9876bf465
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/select.c.NX.patch
@@ -0,0 +1,13 @@
+--- ./nx-X11/programs/Xserver/xfixes/select.c.X.original 2015-02-13 14:03:44.792440567 +0100
++++ ./nx-X11/programs/Xserver/xfixes/select.c 2015-02-10 19:13:13.504697118 +0100
+@@ -78,7 +78,9 @@
+ }
+ for (e = selectionEvents; e; e = e->next)
+ {
+- if (e->selection == selection->selection && (e->eventMask & eventMask))
++ if (e->selection == selection->selection &&
++ (e->eventMask & eventMask) &&
++ !e->pClient->clientGone)
+ {
+ xXFixesSelectionNotifyEvent ev;
+
diff --git a/doc/nx-X11_vs_XOrg69_patches/sun.cf.NX.patch b/doc/nx-X11_vs_XOrg69_patches/sun.cf.NX.patch
new file mode 100644
index 000000000..444c142be
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/sun.cf.NX.patch
@@ -0,0 +1,50 @@
+--- ./nx-X11/config/cf/sun.cf.X.original 2015-02-13 14:03:44.400448260 +0100
++++ ./nx-X11/config/cf/sun.cf 2015-02-13 14:03:44.400448260 +0100
+@@ -299,7 +299,12 @@
+
+ #if OSMajorVersion == 4
+ # if OSMinorVersion == 1
++/*
++ * Currently the NX transport only works with select().
++ *
+ # define HasPoll YES
++ */
++# define HasPoll NO
+ # endif
+ # if OSMinorVersion > 1 || (OSMinorVersion == 1 && OSTeenyVersion > 1)
+ /* You ALSO need this if you have Sun ld patch 100170-06 or later to 4.1.1 */
+@@ -359,10 +364,12 @@
+ # endif
+ #endif
+
+-#define ServerOSDefines XFree86ServerOSDefines IncludeCG2HeaderDefine
++#define ServerOSDefines XFree86ServerOSDefines IncludeCG2HeaderDefine \
++ -DPIXPRIV
+ #define ServerExtraDefines AllocateLocalDefines XFree86ServerDefines \
+ CompilerServerExtraDefines \
+- OSServerExtraDefines ArchServerExtraDefines
++ OSServerExtraDefines ArchServerExtraDefines \
++ -DPIXPRIV
+
+ #ifndef HasPerl
+ /* Solaris 8 comes with perl. Earlier versions don't. */
+@@ -384,7 +391,8 @@
+ #endif
+
+ #if OSMajorVersion > 4
+-# define ConnectionFlags -DTCPCONN -DUNIXCONN -DLOCALCONN
++/* #define ConnectionFlags -DTCPCONN -DUNIXCONN -DLOCALCONN */
++#define ConnectionFlags -DUNIXCONN -DTCPCONN
+ # if HasSunC
+ # ifdef DefaultSunProCCompilerDir
+ # ifndef CcCmd
+@@ -452,7 +460,8 @@
+ # endif
+ # define ToolkitStringsABIOptions -intelabi SolarisABIFlag
+ # else
+-# define StandardDefines -Dsun -Dsparc -DSVR4 -D__EXTENSIONS__ LargefileDefines
++# define StandardDefines -Dsun -Dsparc -DSVR4 -D__EXTENSIONS__ LargefileDefines \
++ -DPIXPRIV
+ # define ToolkitStringsABIOptions -sparcabi SolarisABIFlag
+ # endif
+ # define ExtraLibraries -lsocket -lnsl
diff --git a/doc/nx-X11_vs_XOrg69_patches/sunLib.tmpl.NX.patch b/doc/nx-X11_vs_XOrg69_patches/sunLib.tmpl.NX.patch
new file mode 100644
index 000000000..17f858440
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/sunLib.tmpl.NX.patch
@@ -0,0 +1,122 @@
+--- ./nx-X11/config/cf/sunLib.tmpl.X.original 2015-02-13 14:03:44.400448260 +0100
++++ ./nx-X11/config/cf/sunLib.tmpl 2015-02-13 14:03:44.400448260 +0100
+@@ -45,119 +45,6 @@
+
+ #else /* else it's Solaris */
+
+-/* Solaris uses single digit library versions, and versions of libraries
+- * defined in SVID specs should match the versions specified there.
+- */
+-
+-#ifndef SharedX11Rev
+-# define SharedX11Rev 4
+-#endif
+-#ifndef SharedOldXRev
+-# define SharedOldXRev 6
+-#endif
+-#ifndef SharedXextRev
+-# define SharedXextRev 0
+-#endif
+-#ifndef SharedXauRev
+-# define SharedXauRev 6
+-#endif
+-#ifndef SharedXdmcpRev
+-# define SharedXdmcpRev 6
+-#endif
+-#ifndef SharedXmuRev
+-# define SharedXmuRev 4
+-#endif
+-#ifndef SharedXmuuRev
+-# define SharedXmuuRev 1
+-#endif
+-#ifndef SharedXpRev
+-# define SharedXpRev 1
+-#endif
+-#ifndef SharedXpmRev
+-# define SharedXpmRev 4
+-#endif
+-#ifndef SharedXtRev
+-# define SharedXtRev 4
+-#endif
+-#ifndef SharedXaw6Rev
+-# define SharedXaw6Rev 5
+-#endif
+-#ifndef SharedXiRev
+-# define SharedXiRev 5
+-#endif
+-#ifndef SharedXtstRev
+-# define SharedXtstRev 1
+-#endif
+-#ifndef SharedFSRev
+-# define SharedFSRev 5
+-#endif
+-#ifndef SharedICERev
+-# define SharedICERev 6
+-#endif
+-#ifndef SharedSMRev
+-# define SharedSMRev 6
+-#endif
+-#ifndef SharedXcursor
+-# define SharedXcursorRev 1
+-#endif
+-#ifndef SharedXdamageRev
+-# define SharedXdamageRev 1
+-#endif
+-#ifndef SharedXevieRev
+-# define SharedXevieRev 1
+-#endif
+-#ifndef SharedXfixesRev
+-# define SharedXfixesRev 1
+-#endif
+-#ifndef SharedXftRev
+-# define SharedXftRev 2
+-#endif
+-#ifndef SharedXineramaRev
+-# define SharedXineramaRev 1
+-#endif
+-#ifndef SharedXrenderRev
+-# define SharedXrenderRev 1
+-#endif
+-#ifndef SharedXResRev
+-# define SharedXResRev 1
+-#endif
+-#ifndef SharedXvRev
+-# define SharedXvRev 1
+-#endif
+-#ifndef SharedXvMCRev
+-# define SharedXvMCRev 1
+-#endif
+-#ifndef SharedXrandrRev
+-# define SharedXrandrRev 2
+-#endif
+-#ifndef SharedXssRev
+-# define SharedXssRev 1
+-#endif
+-#ifndef SharedFontconfigRev
+-# define SharedFontconfigRev 1
+-#endif
+-#ifndef SharedGlxRev
+-# define SharedGlxRev 1
+-#endif
+-#ifndef SharedGluRev
+-# define SharedGluRev 1
+-#endif
+-#ifndef SharedGLwRev
+-# define SharedGLwRev 1
+-#endif
+-#ifndef SharedOSMesaRev
+-# define SharedOSMesaRev 4
+-#endif
+-#ifndef SharedxkbfileRev
+-# define SharedxkbfileRev 5
+-#endif
+-#ifndef SharedXxf86miscRev
+-# define SharedXxf86miscRev 1
+-#endif
+-#ifndef SharedXxf86vmRev
+-# define SharedXxf86vmRev 1
+-#endif
+-
+ # if ThreadedX
+ # if OSMinorVersion > 3
+ # define SharedThreadReqs /**/
diff --git a/doc/nx-X11_vs_XOrg69_patches/svr4.cf.NX.patch b/doc/nx-X11_vs_XOrg69_patches/svr4.cf.NX.patch
new file mode 100644
index 000000000..487c295fc
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/svr4.cf.NX.patch
@@ -0,0 +1,24 @@
+--- ./nx-X11/config/cf/svr4.cf.X.original 2015-02-13 14:03:44.400448260 +0100
++++ ./nx-X11/config/cf/svr4.cf 2015-02-13 14:03:44.400448260 +0100
+@@ -51,7 +51,12 @@
+ #ifndef HasLdRunPath
+ #define HasLdRunPath YES
+ #endif
++/*
++ * Currently the NX transport only works with select().
++ *
+ #define HasPoll YES
++ */
++#define HasPoll NO
+ #ifndef SVR4Architecture
+ #define SVR4Architecture
+ #endif
+@@ -278,7 +283,7 @@
+ # define XFree86ServerDefines /* */
+ #endif
+ #ifndef XFree86ServerOSDefines
+-# define XFree86ServerOSDefines -DDDXOSINIT
++# define XFree86ServerOSDefines -DDDXOSINIT -DDDXOSFATALERROR -DDDXOSVERRORF
+ #endif
+
+ #if HasGcc2ForCplusplus
diff --git a/doc/nx-X11_vs_XOrg69_patches/utils.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/utils.c.NX.patch
new file mode 100644
index 000000000..5e18abfdb
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/utils.c.NX.patch
@@ -0,0 +1,250 @@
+--- ./nx-X11/programs/Xserver/os/utils.c.X.original 2015-02-13 14:03:44.792440567 +0100
++++ ./nx-X11/programs/Xserver/os/utils.c 2015-02-13 14:03:44.788440645 +0100
+@@ -52,6 +52,23 @@
+ */
+ /* $XFree86: xc/programs/Xserver/os/utils.c,v 3.96 2004/01/07 04:16:37 dawes Exp $ */
+
++/**************************************************************************/
++/* */
++/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
++/* */
++/* NX-X11, NX protocol compression and NX extensions to this software */
++/* are copyright of NoMachine. Redistribution and use of the present */
++/* software is allowed according to terms specified in the file LICENSE */
++/* which comes in the source distribution. */
++/* */
++/* Check http://www.nomachine.com/licensing.html for applicability. */
++/* */
++/* NX and NoMachine are trademarks of Medialogic S.p.A. */
++/* */
++/* All rights reserved. */
++/* */
++/**************************************************************************/
++
+ #ifdef HAVE_DIX_CONFIG_H
+ #include <dix-config.h>
+ #endif
+@@ -246,6 +263,20 @@
+
+ #include <errno.h>
+
++#ifdef NX_TRANS_SOCKET
++
++#include "NX.h"
++#include "NXvars.h"
++
++#endif
++
++#ifdef NX_TRANS_EXIT
++
++void (*OsVendorStartRedirectErrorFProc)() = NULL;
++void (*OsVendorEndRedirectErrorFProc)() = NULL;
++
++#endif
++
+ Bool CoreDump;
+
+ #ifdef PANORAMIX
+@@ -543,6 +574,10 @@
+ {
+ int olderrno = errno;
+
++#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
++ fprintf(stderr, "GiveUp: Called with signal [%d].\n", sig);
++#endif
++
+ dispatchException |= DE_TERMINATE;
+ isItTimeToYield = TRUE;
+ #if defined(SYSV) && defined(X_NOT_POSIX)
+@@ -1548,12 +1583,21 @@
+ #define SMART_SCHEDULE_TIMER ITIMER_REAL
+ #endif
+
++#ifdef NX_TRANS_SOCKET
++void
++SmartScheduleStopTimer (void)
++#else
+ static void
+ SmartScheduleStopTimer (void)
++#endif
+ {
+ #ifdef SMART_SCHEDULE_POSSIBLE
+ struct itimerval timer;
+-
++
++ #ifdef NX_TRANS_TEST
++ fprintf(stderr, "SmartScheduleStopTimer: Stopping timer.\n");
++ #endif
++
+ timer.it_interval.tv_sec = 0;
+ timer.it_interval.tv_usec = 0;
+ timer.it_value.tv_sec = 0;
+@@ -1568,7 +1612,21 @@
+ {
+ #ifdef SMART_SCHEDULE_POSSIBLE
+ struct itimerval timer;
+-
++
++ #ifdef NX_TRANS_SOCKET
++
++ if (SmartScheduleDisable)
++ {
++ return FALSE;
++ }
++
++ #endif
++
++ #ifdef NX_TRANS_TEST
++ fprintf(stderr, "SmartScheduleStartTimer: Starting timer with [%ld] ms.\n",
++ SmartScheduleInterval);
++ #endif
++
+ SmartScheduleTimerStopped = FALSE;
+ timer.it_interval.tv_sec = 0;
+ timer.it_interval.tv_usec = SmartScheduleInterval * 1000;
+@@ -1586,6 +1644,12 @@
+ int olderrno = errno;
+
+ SmartScheduleTime += SmartScheduleInterval;
++
++ #ifdef NX_TRANS_TEST
++ fprintf(stderr, "SmartScheduleTimer: Got timer with time [%ld] ms.\n",
++ SmartScheduleTime);
++ #endif
++
+ if (SmartScheduleIdle)
+ {
+ SmartScheduleStopTimer ();
+@@ -1603,6 +1667,10 @@
+ if (SmartScheduleDisable)
+ return TRUE;
+
++ #ifdef NX_TRANS_TEST
++ fprintf(stderr, "SmartScheduleInit: Initializing the smart scheduler.\n");
++ #endif
++
+ bzero ((char *) &act, sizeof(struct sigaction));
+
+ /* Set up the timer signal function */
+@@ -1714,6 +1782,11 @@
+ ErrorF("System: `%s'\n", command);
+ #endif
+
++#ifdef NX_TRANS_EXIT
++ if (OsVendorStartRedirectErrorFProc != NULL) {
++ OsVendorStartRedirectErrorFProc();
++ }
++#endif
+ switch (pid = fork()) {
+ case -1: /* error */
+ p = -1;
+@@ -1730,6 +1803,11 @@
+ } while (p == -1 && errno == EINTR);
+
+ }
++#ifdef NX_TRANS_EXIT
++ if (OsVendorEndRedirectErrorFProc != NULL) {
++ OsVendorEndRedirectErrorFProc();
++ }
++#endif
+
+ #ifdef SIGCHLD
+ signal(SIGCHLD, csig);
+@@ -1765,11 +1843,23 @@
+ return NULL;
+ }
+
++#ifdef NX_TRANS_EXIT
++ if (OsVendorStartRedirectErrorFProc != NULL) {
++ OsVendorStartRedirectErrorFProc();
++ }
++ OsBlockSignals ();
++#endif
+ switch (pid = fork()) {
+ case -1: /* error */
+ close(pdes[0]);
+ close(pdes[1]);
+ xfree(cur);
++#ifdef NX_TRANS_EXIT
++ if (OsVendorEndRedirectErrorFProc != NULL) {
++ OsVendorEndRedirectErrorFProc();
++ }
++ OsReleaseSignals ();
++#endif
+ return NULL;
+ case 0: /* child */
+ if (setgid(getgid()) == -1)
+@@ -1791,12 +1881,61 @@
+ }
+ close(pdes[1]);
+ }
++
++ #ifdef NX_TRANS_SOCKET
++
++ /*
++ * Check if the child process should not
++ * use the parent's libraries.
++ */
++
++ if (_NXUnsetLibraryPath)
++ {
++ #ifndef __sun
++
++ unsetenv ("LD_LIBRARY_PATH");
++
++ #else
++
++ extern char **environ;
++
++ char **ep = environ;
++
++ ep = environ;
++
++ while (*ep)
++ {
++ if (!strncmp("LD_LIBRARY_PATH=", *ep, strlen("LD_LIBRARY_PATH=")))
++ {
++ break;
++ }
++
++ *ep++;
++ }
++
++ while (*ep)
++ {
++ *ep = *(ep + 1);
++ ep++;
++ }
++
++ #endif
++ }
++
++ #endif
++
++ #ifdef NX_TRANS_EXIT
++ OsReleaseSignals ();
++ #endif
++
+ execl("/bin/sh", "sh", "-c", command, (char *)NULL);
+ _exit(127);
+ }
+
++#ifndef NX_TRANS_EXIT
+ /* Avoid EINTR during stdio calls */
+ OsBlockSignals ();
++#endif
+
+ /* parent */
+ if (*type == 'r') {
+@@ -1945,6 +2084,11 @@
+ /* allow EINTR again */
+ OsReleaseSignals ();
+
++#ifdef NX_TRANS_EXIT
++ if (OsVendorEndRedirectErrorFProc != NULL) {
++ OsVendorEndRedirectErrorFProc();
++ }
++#endif
+ return pid == -1 ? -1 : pstat;
+ }
+
diff --git a/doc/nx-X11_vs_XOrg69_patches/xdmcp.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/xdmcp.c.NX.patch
new file mode 100644
index 000000000..47e231453
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/xdmcp.c.NX.patch
@@ -0,0 +1,59 @@
+--- ./nx-X11/programs/Xserver/os/xdmcp.c.X.original 2015-02-13 14:03:44.792440567 +0100
++++ ./nx-X11/programs/Xserver/os/xdmcp.c 2015-02-10 19:13:13.472698316 +0100
+@@ -59,6 +59,13 @@
+ #include <netdir.h>
+ #endif
+
++#ifndef NX_TRANS_SOCKET
++
++#define NX_TRANS_SOCKET
++#define NX_TRANS_TEST
++
++#endif
++
+ #ifdef XDMCP
+ #undef REQUEST
+
+@@ -71,6 +78,15 @@
+ #define X_INCLUDE_NETDB_H
+ #include <X11/Xos_r.h>
+
++#ifdef NX_TRANS_SOCKET
++
++xdmcp_states XdmcpState;
++
++int XdmcpStartTime;
++int XdmcpTimeOutRtx;
++
++#endif
++
+ extern char *defaultDisplayClass;
+
+ static int xdmcpSocket, sessionSocket;
+@@ -590,6 +606,12 @@
+ void
+ XdmcpInit(void)
+ {
++#ifdef NX_TRANS_SOCKET
++
++ XdmcpStartTime = GetTimeInMillis();
++
++#endif
++
+ state = XDM_INIT_STATE;
+ #ifdef HASXDMAUTH
+ if (xdmAuthCookie)
+@@ -699,6 +721,13 @@
+ fd_set* LastSelectMask = (fd_set*)pReadmask;
+ fd_set devicesReadable;
+
++#ifdef NX_TRANS_SOCKET
++
++ XdmcpState = state;
++ XdmcpTimeOutRtx = timeOutRtx;
++
++#endif
++
+ if (state == XDM_OFF)
+ return;
+ if (i > 0)
diff --git a/doc/nx-X11_vs_XOrg69_patches/xf86glx.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/xf86glx.c.NX.patch
new file mode 100644
index 000000000..eaa3a1624
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/xf86glx.c.NX.patch
@@ -0,0 +1,70 @@
+--- ./nx-X11/programs/Xserver/GL/mesa/X/xf86glx.c.X.original 2015-02-13 14:03:44.680442769 +0100
++++ ./nx-X11/programs/Xserver/GL/mesa/X/xf86glx.c 2015-02-10 19:13:14.340665851 +0100
+@@ -71,6 +71,10 @@
+
+ #include "glcontextmodes.h"
+
++#ifdef NXAGENT_SERVER
++#include "../main/WSDrawBuffer.h"
++#endif
++
+ /*
+ * This structure is statically allocated in the __glXScreens[]
+ * structure. This struct is not used anywhere other than in
+@@ -95,6 +99,36 @@
+ NULL /* WrappedPositionWindow is overwritten */
+ };
+
++#ifdef NXAGENT_SERVER
++WSDrawBufferPtr pWSDrawBuffer = NULL;
++
++void AddWSDrawBuffer(GLframebuffer *mesa_buffer)
++{
++ WSDrawBufferPtr prevWSDB;
++ WSDrawBufferPtr newWSDB;
++ WSDrawBufferPtr p;
++
++ prevWSDB = NULL;
++ newWSDB = NULL;
++ p = pWSDrawBuffer;
++ while (p != NULL) {
++ prevWSDB = p;
++ if (prevWSDB -> DrawBuffer == mesa_buffer) {
++ return;
++ }
++ p = p -> next;
++ }
++ newWSDB = malloc(sizeof(WSDrawBufferRec));
++ newWSDB -> DrawBuffer = mesa_buffer;
++ newWSDB -> next = NULL;
++
++ if (pWSDrawBuffer == NULL)
++ pWSDrawBuffer = newWSDB;
++ else
++ prevWSDB -> next = newWSDB;
++}
++#endif
++
+ void *__glXglDDXScreenInfo(void) {
+ return &__glDDXScreenInfo;
+ }
+@@ -748,6 +782,10 @@
+ __MESA_buffer buf = (__MESA_buffer)glPriv->private;
+ __GLXdrawablePrivate *glxPriv = (__GLXdrawablePrivate *)glPriv->other;
+
++#ifdef NXAGENT_SERVER
++ AddWSDrawBuffer(& (buf -> xm_buf -> mesa_buffer) );
++#endif
++
+ /* Destroy Mesa's buffers */
+ if (buf->xm_buf)
+ XMesaDestroyBuffer(buf->xm_buf);
+@@ -757,7 +795,7 @@
+ glPriv->frontBuffer.resize = buf->fbresize;
+
+ __glXFree(glPriv->private);
+- glPriv->private = NULL;
++ glPriv->private = NULL;
+ }
+
+ __GLinterface *__MESA_createContext(__GLimports *imports,
diff --git a/doc/nx-X11_vs_XOrg69_patches/xkbDflts.h.NX.patch b/doc/nx-X11_vs_XOrg69_patches/xkbDflts.h.NX.patch
new file mode 100644
index 000000000..41ef7091e
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/xkbDflts.h.NX.patch
@@ -0,0 +1,24 @@
+--- ./nx-X11/programs/Xserver/xkb/xkbDflts.h.X.original 2015-02-13 14:03:44.792440567 +0100
++++ ./nx-X11/programs/Xserver/xkb/xkbDflts.h 2015-02-10 19:13:13.736688433 +0100
+@@ -417,10 +417,21 @@
+ XkbSI_AnyOfOrNone, 0xff,
+ 255,
+ { XkbSA_LockControls, { 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00 } } },
++
++#ifndef NX_TRANS_SOCKET
++
++ /*
++ * Make sure that the server can't be killed
++ * by pressing this key-sequence.
++ */
++
+ { XK_Terminate_Server, 0x0000,
+ XkbSI_AnyOfOrNone, 0xff,
+ 255,
+ { XkbSA_Terminate, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
++
++#endif
++
+ { XK_ISO_Group_Latch, 0x0000,
+ XkbSI_LevelOneOnly|XkbSI_AnyOfOrNone, 0xff,
+ 3,
diff --git a/doc/nx-X11_vs_XOrg69_patches/xprintf.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/xprintf.c.NX.patch
new file mode 100644
index 000000000..fa0796dc9
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/xprintf.c.NX.patch
@@ -0,0 +1,75 @@
+--- ./nx-X11/programs/Xserver/os/xprintf.c.X.original 2015-02-13 14:03:44.792440567 +0100
++++ ./nx-X11/programs/Xserver/os/xprintf.c 2015-02-10 19:13:13.480698017 +0100
+@@ -43,6 +43,63 @@
+ # endif
+ #endif
+
++#ifdef NX_TRANS_SOCKET
++
++#define PANIC
++#define WARNING
++#undef TEST
++#undef DEBUG
++
++#define START_SIZE 256
++#define END_SIZE 2048
++
++char *
++Xvprintf(const char *format, va_list va)
++{
++ char *ret;
++ char *newret;
++ int size;
++ int r;
++
++ size = 0;
++
++ for (;;)
++ {
++ if (size == 0)
++ {
++ ret = (char *)malloc(START_SIZE);
++ if (ret == NULL)
++ return NULL;
++ size = START_SIZE;
++ }
++ else if (size < END_SIZE &&
++ (newret = (char *) realloc(ret, 2 * size)) != NULL)
++ {
++ ret = newret;
++ size = 2 * size;
++ }
++ else
++ {
++ free(ret);
++ return NULL;
++ }
++
++ r = vsnprintf(ret, size, format, va);
++
++ if (r == -1 || r == size || r > size || r == size - 1)
++ {
++ continue;
++ }
++ else
++ {
++ ret[r] = 0;
++ return ret;
++ }
++ }
++}
++
++#else
++
+ char *
+ Xvprintf(const char *format, va_list va)
+ {
+@@ -63,6 +120,8 @@
+ return ret;
+ }
+
++#endif
++
+ char *Xprintf(const char *format, ...)
+ {
+ char *ret;